Compare commits
4
Commits
dev
...
v1.20.3-rpc-p01
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f656c18615 | ||
|
|
5accb588e9 | ||
|
|
7d8b3053a2 | ||
|
|
d4dc28cec9 |
@@ -88,8 +88,6 @@ type Gateway interface {
|
||||
EthGetMessageCidByTransactionHash(ctx context.Context, txHash *ethtypes.EthHash) (*cid.Cid, error)
|
||||
EthGetTransactionCount(ctx context.Context, sender ethtypes.EthAddress, blkOpt string) (ethtypes.EthUint64, error)
|
||||
EthGetTransactionReceipt(ctx context.Context, txHash ethtypes.EthHash) (*EthTxReceipt, error)
|
||||
EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash ethtypes.EthHash, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error)
|
||||
EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum ethtypes.EthUint64, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error)
|
||||
EthGetCode(ctx context.Context, address ethtypes.EthAddress, blkOpt string) (ethtypes.EthBytes, error)
|
||||
EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error)
|
||||
EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error)
|
||||
|
||||
@@ -688,10 +688,6 @@ type GatewayMethods struct {
|
||||
|
||||
EthGetStorageAt func(p0 context.Context, p1 ethtypes.EthAddress, p2 ethtypes.EthBytes, p3 string) (ethtypes.EthBytes, error) ``
|
||||
|
||||
EthGetTransactionByBlockHashAndIndex func(p0 context.Context, p1 ethtypes.EthHash, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) ``
|
||||
|
||||
EthGetTransactionByBlockNumberAndIndex func(p0 context.Context, p1 ethtypes.EthUint64, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) ``
|
||||
|
||||
EthGetTransactionByHash func(p0 context.Context, p1 *ethtypes.EthHash) (*ethtypes.EthTx, error) ``
|
||||
|
||||
EthGetTransactionCount func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthUint64, error) ``
|
||||
@@ -4395,28 +4391,6 @@ func (s *GatewayStub) EthGetStorageAt(p0 context.Context, p1 ethtypes.EthAddress
|
||||
return *new(ethtypes.EthBytes), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) EthGetTransactionByBlockHashAndIndex(p0 context.Context, p1 ethtypes.EthHash, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) {
|
||||
if s.Internal.EthGetTransactionByBlockHashAndIndex == nil {
|
||||
return *new(ethtypes.EthTx), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthGetTransactionByBlockHashAndIndex(p0, p1, p2)
|
||||
}
|
||||
|
||||
func (s *GatewayStub) EthGetTransactionByBlockHashAndIndex(p0 context.Context, p1 ethtypes.EthHash, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) {
|
||||
return *new(ethtypes.EthTx), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) EthGetTransactionByBlockNumberAndIndex(p0 context.Context, p1 ethtypes.EthUint64, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) {
|
||||
if s.Internal.EthGetTransactionByBlockNumberAndIndex == nil {
|
||||
return *new(ethtypes.EthTx), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthGetTransactionByBlockNumberAndIndex(p0, p1, p2)
|
||||
}
|
||||
|
||||
func (s *GatewayStub) EthGetTransactionByBlockNumberAndIndex(p0 context.Context, p1 ethtypes.EthUint64, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) {
|
||||
return *new(ethtypes.EthTx), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) EthGetTransactionByHash(p0 context.Context, p1 *ethtypes.EthHash) (*ethtypes.EthTx, error) {
|
||||
if s.Internal.EthGetTransactionByHash == nil {
|
||||
return nil, ErrNotSupported
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -8,6 +8,7 @@ import (
|
||||
"go.opencensus.io/trace"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
@@ -52,6 +53,12 @@ func (sm *StateManager) TipSetState(ctx context.Context, ts *types.TipSet) (st c
|
||||
|
||||
sm.stlk.Unlock()
|
||||
|
||||
// First, try to find the tipset in the current chain. If found, we can avoid re-executing
|
||||
// it.
|
||||
if st, rec, found := tryLookupTipsetState(ctx, sm.cs, ts); found {
|
||||
return st, rec, nil
|
||||
}
|
||||
|
||||
st, rec, err = sm.tsExec.ExecuteTipSet(ctx, sm, ts, sm.tsExecMonitor, false)
|
||||
if err != nil {
|
||||
return cid.Undef, cid.Undef, err
|
||||
@@ -60,6 +67,51 @@ func (sm *StateManager) TipSetState(ctx context.Context, ts *types.TipSet) (st c
|
||||
return st, rec, nil
|
||||
}
|
||||
|
||||
// Try to lookup a state & receipt CID for a given tipset by walking the chain instead of executing
|
||||
// it. This will only successfully return the state/receipt CIDs if they're found in the state
|
||||
// store.
|
||||
//
|
||||
// NOTE: This _won't_ recursively walk the receipt/state trees. It assumes that having the root
|
||||
// implies having the rest of the tree. However, lotus generally makes that assumption anyways.
|
||||
func tryLookupTipsetState(ctx context.Context, cs *store.ChainStore, ts *types.TipSet) (cid.Cid, cid.Cid, bool) {
|
||||
nextTs, err := cs.GetTipsetByHeight(ctx, ts.Height()+1, nil, false)
|
||||
if err != nil {
|
||||
// Nothing to see here. The requested height may be beyond the current head.
|
||||
return cid.Undef, cid.Undef, false
|
||||
}
|
||||
|
||||
// Make sure we're on the correct fork.
|
||||
if nextTs.Parents() != ts.Key() {
|
||||
// Also nothing to see here. This just means that the requested tipset is on a
|
||||
// different fork.
|
||||
return cid.Undef, cid.Undef, false
|
||||
}
|
||||
|
||||
stateCid := nextTs.ParentState()
|
||||
receiptCid := nextTs.ParentMessageReceipts()
|
||||
|
||||
// Make sure we have the parent state.
|
||||
if hasState, err := cs.StateBlockstore().Has(ctx, stateCid); err != nil {
|
||||
log.Errorw("failed to lookup state-root in blockstore", "cid", stateCid, "error", err)
|
||||
return cid.Undef, cid.Undef, false
|
||||
} else if !hasState {
|
||||
// We have the chain but don't have the state. It looks like we need to try
|
||||
// executing?
|
||||
return cid.Undef, cid.Undef, false
|
||||
}
|
||||
|
||||
// Make sure we have the receipts.
|
||||
if hasReceipts, err := cs.ChainBlockstore().Has(ctx, receiptCid); err != nil {
|
||||
log.Errorw("failed to lookup receipts in blockstore", "cid", receiptCid, "error", err)
|
||||
return cid.Undef, cid.Undef, false
|
||||
} else if !hasReceipts {
|
||||
// If we don't have the receipts, re-execute and try again.
|
||||
return cid.Undef, cid.Undef, false
|
||||
}
|
||||
|
||||
return stateCid, receiptCid, true
|
||||
}
|
||||
|
||||
func (sm *StateManager) ExecutionTraceWithMonitor(ctx context.Context, ts *types.TipSet, em ExecMonitor) (cid.Cid, error) {
|
||||
st, _, err := sm.tsExec.ExecuteTipSet(ctx, sm, ts, em, true)
|
||||
return st, err
|
||||
|
||||
@@ -237,6 +237,26 @@ func (cs *ChainStore) ReadMsgMetaCids(ctx context.Context, mmc cid.Cid) ([]cid.C
|
||||
return blscids, secpkcids, nil
|
||||
}
|
||||
|
||||
func (cs *ChainStore) ReadReceipts(ctx context.Context, root cid.Cid) ([]types.MessageReceipt, error) {
|
||||
a, err := blockadt.AsArray(cs.ActorStore(ctx), root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
receipts := make([]types.MessageReceipt, 0, a.Length())
|
||||
var rcpt types.MessageReceipt
|
||||
if err := a.ForEach(&rcpt, func(i int64) error {
|
||||
if int64(len(receipts)) != i {
|
||||
return xerrors.Errorf("missing receipt %d", i)
|
||||
}
|
||||
receipts = append(receipts, rcpt)
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return receipts, nil
|
||||
}
|
||||
|
||||
func (cs *ChainStore) MessagesForBlock(ctx context.Context, b *types.BlockHeader) ([]*types.Message, []*types.SignedMessage, error) {
|
||||
blscids, secpkcids, err := cs.ReadMsgMetaCids(ctx, b.Messages)
|
||||
if err != nil {
|
||||
|
||||
@@ -44,14 +44,6 @@ type EthTx struct {
|
||||
S EthBigInt `json:"s"`
|
||||
}
|
||||
|
||||
func (tx *EthTx) Reward(blkBaseFee big.Int) EthBigInt {
|
||||
availablePriorityFee := big.Sub(big.Int(tx.MaxFeePerGas), blkBaseFee)
|
||||
if big.Cmp(big.Int(tx.MaxPriorityFeePerGas), availablePriorityFee) <= 0 {
|
||||
return tx.MaxPriorityFeePerGas
|
||||
}
|
||||
return EthBigInt(availablePriorityFee)
|
||||
}
|
||||
|
||||
type EthTxArgs struct {
|
||||
ChainID int `json:"chainId"`
|
||||
Nonce int `json:"nonce"`
|
||||
|
||||
@@ -215,4 +215,17 @@ func (m *Message) ValidForBlockInclusion(minGas int64, version network.Version)
|
||||
return nil
|
||||
}
|
||||
|
||||
// EffectiveGasPremium returns the effective gas premium claimable by the miner
|
||||
// given the supplied base fee.
|
||||
//
|
||||
// Filecoin clamps the gas premium at GasFeeCap - BaseFee, if lower than the
|
||||
// specified premium.
|
||||
func (m *Message) EffectiveGasPremium(baseFee abi.TokenAmount) abi.TokenAmount {
|
||||
available := big.Sub(m.GasFeeCap, baseFee)
|
||||
if big.Cmp(m.GasPremium, available) <= 0 {
|
||||
return m.GasPremium
|
||||
}
|
||||
return available
|
||||
}
|
||||
|
||||
const TestGasLimit = 100e6
|
||||
|
||||
@@ -234,6 +234,10 @@ func (ts *TipSet) MinTicketBlock() *BlockHeader {
|
||||
return min
|
||||
}
|
||||
|
||||
func (ts *TipSet) ParentMessageReceipts() cid.Cid {
|
||||
return ts.blks[0].ParentMessageReceipts
|
||||
}
|
||||
|
||||
func (ts *TipSet) ParentState() cid.Cid {
|
||||
return ts.blks[0].ParentStateRoot
|
||||
}
|
||||
|
||||
+8
-40
@@ -21,7 +21,7 @@ import (
|
||||
)
|
||||
|
||||
func (gw *Node) Web3ClientVersion(ctx context.Context) (string, error) {
|
||||
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
|
||||
if err := gw.limit(ctx, basicRateLimitTokens); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ func (gw *Node) EthAccounts(ctx context.Context) ([]ethtypes.EthAddress, error)
|
||||
}
|
||||
|
||||
func (gw *Node) EthBlockNumber(ctx context.Context) (ethtypes.EthUint64, error) {
|
||||
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
|
||||
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
@@ -109,11 +109,7 @@ func (gw *Node) checkBlkParam(ctx context.Context, blkParam string) error {
|
||||
}
|
||||
|
||||
func (gw *Node) EthGetBlockTransactionCountByHash(ctx context.Context, blkHash ethtypes.EthHash) (ethtypes.EthUint64, error) {
|
||||
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if err := gw.checkBlkHash(ctx, blkHash); err != nil {
|
||||
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
@@ -161,7 +157,7 @@ func (gw *Node) EthGetTransactionHashByCid(ctx context.Context, cid cid.Cid) (*e
|
||||
}
|
||||
|
||||
func (gw *Node) EthGetMessageCidByTransactionHash(ctx context.Context, txHash *ethtypes.EthHash) (*cid.Cid, error) {
|
||||
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
|
||||
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -188,34 +184,6 @@ func (gw *Node) EthGetTransactionReceipt(ctx context.Context, txHash ethtypes.Et
|
||||
return gw.target.EthGetTransactionReceipt(ctx, txHash)
|
||||
}
|
||||
|
||||
func (gw *Node) EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash ethtypes.EthHash, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error) {
|
||||
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
|
||||
return ethtypes.EthTx{}, err
|
||||
}
|
||||
|
||||
if err := gw.checkBlkHash(ctx, blkHash); err != nil {
|
||||
return ethtypes.EthTx{}, err
|
||||
}
|
||||
|
||||
return gw.target.EthGetTransactionByBlockHashAndIndex(ctx, blkHash, txIndex)
|
||||
}
|
||||
|
||||
func (gw *Node) EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum ethtypes.EthUint64, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error) {
|
||||
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
|
||||
return ethtypes.EthTx{}, err
|
||||
}
|
||||
|
||||
head, err := gw.target.ChainHead(ctx)
|
||||
if err != nil {
|
||||
return ethtypes.EthTx{}, err
|
||||
}
|
||||
if err := gw.checkTipsetHeight(head, abi.ChainEpoch(blkNum)); err != nil {
|
||||
return ethtypes.EthTx{}, err
|
||||
}
|
||||
|
||||
return gw.target.EthGetTransactionByBlockNumberAndIndex(ctx, blkNum, txIndex)
|
||||
}
|
||||
|
||||
func (gw *Node) EthGetCode(ctx context.Context, address ethtypes.EthAddress, blkOpt string) (ethtypes.EthBytes, error) {
|
||||
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
|
||||
return nil, err
|
||||
@@ -253,7 +221,7 @@ func (gw *Node) EthGetBalance(ctx context.Context, address ethtypes.EthAddress,
|
||||
}
|
||||
|
||||
func (gw *Node) EthChainId(ctx context.Context) (ethtypes.EthUint64, error) {
|
||||
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
|
||||
if err := gw.limit(ctx, basicRateLimitTokens); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
@@ -269,7 +237,7 @@ func (gw *Node) NetVersion(ctx context.Context) (string, error) {
|
||||
}
|
||||
|
||||
func (gw *Node) NetListening(ctx context.Context) (bool, error) {
|
||||
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
|
||||
if err := gw.limit(ctx, basicRateLimitTokens); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
@@ -285,7 +253,7 @@ func (gw *Node) EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, err
|
||||
}
|
||||
|
||||
func (gw *Node) EthGasPrice(ctx context.Context) (ethtypes.EthBigInt, error) {
|
||||
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
|
||||
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
|
||||
return ethtypes.EthBigInt(big.Zero()), err
|
||||
}
|
||||
|
||||
@@ -316,7 +284,7 @@ func (gw *Node) EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (ethtype
|
||||
}
|
||||
|
||||
func (gw *Node) EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt, error) {
|
||||
if err := gw.limit(ctx, stateRateLimitTokens); err != nil {
|
||||
if err := gw.limit(ctx, chainRateLimitTokens); err != nil {
|
||||
return ethtypes.EthBigInt(big.Zero()), err
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package itests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -9,6 +10,7 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-state-types/builtin"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
"github.com/filecoin-project/lotus/chain/wallet/key"
|
||||
@@ -109,3 +111,16 @@ func TestEthGetGenesis(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, ethBlk.Hash, genesisHash)
|
||||
}
|
||||
|
||||
func TestNetVersion(t *testing.T) {
|
||||
blockTime := 100 * time.Millisecond
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
|
||||
ens.InterconnectAll().BeginMining(blockTime)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
|
||||
version, err := client.NetVersion(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, strconv.Itoa(build.Eip155ChainId), version)
|
||||
}
|
||||
|
||||
@@ -49,9 +49,6 @@ func TestEthBlockHashesCorrect_MultiBlockTipset(t *testing.T) {
|
||||
// let the chain run a little bit longer to minimise the chance of reorgs
|
||||
n2.WaitTillChain(ctx, kit.HeightAtLeast(head.Height()+50))
|
||||
|
||||
head, err = n2.ChainHead(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
for i := 1; i <= int(head.Height()); i++ {
|
||||
hex := fmt.Sprintf("0x%x", i)
|
||||
|
||||
|
||||
@@ -236,14 +236,6 @@ func TestEthOpenRPCConformance(t *testing.T) {
|
||||
skipReason: "earliest block is not supported",
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_getBlockByNumber",
|
||||
variant: "pending",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthGetBlockByNumber(context.Background(), "pending", true)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_getBlockByNumber",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
|
||||
+4
-15
@@ -186,25 +186,14 @@ func (a *ChainAPI) ChainGetParentReceipts(ctx context.Context, bcid cid.Cid) ([]
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// TODO: need to get the number of messages better than this
|
||||
pts, err := a.Chain.LoadTipSet(ctx, types.NewTipSetKey(b.Parents...))
|
||||
receipts, err := a.Chain.ReadReceipts(ctx, b.ParentMessageReceipts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cm, err := a.Chain.MessagesForTipset(ctx, pts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var out []*types.MessageReceipt
|
||||
for i := 0; i < len(cm); i++ {
|
||||
r, err := a.Chain.GetParentReceipt(ctx, b, i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out = append(out, r)
|
||||
out := make([]*types.MessageReceipt, len(receipts))
|
||||
for i := range receipts {
|
||||
out[i] = &receipts[i]
|
||||
}
|
||||
|
||||
return out, nil
|
||||
|
||||
+87
-82
@@ -42,6 +42,8 @@ import (
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
)
|
||||
|
||||
var ErrUnsupported = errors.New("unsupported method")
|
||||
|
||||
type EthModuleAPI interface {
|
||||
EthBlockNumber(ctx context.Context) (ethtypes.EthUint64, error)
|
||||
EthAccounts(ctx context.Context) ([]ethtypes.EthAddress, error)
|
||||
@@ -54,8 +56,6 @@ type EthModuleAPI interface {
|
||||
EthGetTransactionHashByCid(ctx context.Context, cid cid.Cid) (*ethtypes.EthHash, error)
|
||||
EthGetTransactionCount(ctx context.Context, sender ethtypes.EthAddress, blkOpt string) (ethtypes.EthUint64, error)
|
||||
EthGetTransactionReceipt(ctx context.Context, txHash ethtypes.EthHash) (*api.EthTxReceipt, error)
|
||||
EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash ethtypes.EthHash, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error)
|
||||
EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum ethtypes.EthUint64, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error)
|
||||
EthGetCode(ctx context.Context, address ethtypes.EthAddress, blkOpt string) (ethtypes.EthBytes, error)
|
||||
EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error)
|
||||
EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error)
|
||||
@@ -234,14 +234,13 @@ func (a *EthModule) EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthH
|
||||
}
|
||||
|
||||
func (a *EthModule) parseBlkParam(ctx context.Context, blkParam string, strict bool) (tipset *types.TipSet, err error) {
|
||||
if blkParam == "earliest" {
|
||||
return nil, fmt.Errorf("block param \"earliest\" is not supported")
|
||||
switch blkParam {
|
||||
case "earliest", "pending":
|
||||
return nil, fmt.Errorf("block param %q is not supported", blkParam)
|
||||
}
|
||||
|
||||
head := a.Chain.GetHeaviestTipSet()
|
||||
switch blkParam {
|
||||
case "pending":
|
||||
return head, nil
|
||||
case "latest":
|
||||
parent, err := a.Chain.GetTipSetFromKey(ctx, head.Parents())
|
||||
if err != nil {
|
||||
@@ -343,13 +342,13 @@ func (a *EthModule) EthGetMessageCidByTransactionHash(ctx context.Context, txHas
|
||||
c = txHash.ToCid()
|
||||
}
|
||||
|
||||
_, err = a.StateAPI.Chain.GetSignedMessage(ctx, c)
|
||||
_, err = a.Chain.GetSignedMessage(ctx, c)
|
||||
if err == nil {
|
||||
// This is an Eth Tx, Secp message, Or BLS message in the mpool
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
_, err = a.StateAPI.Chain.GetMessage(ctx, c)
|
||||
_, err = a.Chain.GetMessage(ctx, c)
|
||||
if err == nil {
|
||||
// This is a BLS message
|
||||
return &c, nil
|
||||
@@ -449,12 +448,12 @@ func (a *EthModule) EthGetTransactionReceipt(ctx context.Context, txHash ethtype
|
||||
return &receipt, nil
|
||||
}
|
||||
|
||||
func (a *EthModule) EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash ethtypes.EthHash, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error) {
|
||||
return ethtypes.EthTx{}, nil
|
||||
func (a *EthAPI) EthGetTransactionByBlockHashAndIndex(context.Context, ethtypes.EthHash, ethtypes.EthUint64) (ethtypes.EthTx, error) {
|
||||
return ethtypes.EthTx{}, ErrUnsupported
|
||||
}
|
||||
|
||||
func (a *EthModule) EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum ethtypes.EthUint64, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error) {
|
||||
return ethtypes.EthTx{}, nil
|
||||
func (a *EthAPI) EthGetTransactionByBlockNumberAndIndex(context.Context, ethtypes.EthUint64, ethtypes.EthUint64) (ethtypes.EthTx, error) {
|
||||
return ethtypes.EthTx{}, ErrUnsupported
|
||||
}
|
||||
|
||||
// EthGetCode returns string value of the compiled bytecode
|
||||
@@ -689,49 +688,39 @@ func (a *EthModule) EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (eth
|
||||
return ethtypes.EthFeeHistory{}, fmt.Errorf("bad block parameter %s: %s", params.NewestBlkNum, err)
|
||||
}
|
||||
|
||||
oldestBlkHeight := uint64(1)
|
||||
var (
|
||||
basefee = ts.Blocks()[0].ParentBaseFee
|
||||
oldestBlkHeight = uint64(1)
|
||||
|
||||
// NOTE: baseFeePerGas should include the next block after the newest of the returned range,
|
||||
// because the next base fee can be inferred from the messages in the newest block.
|
||||
// However, this is NOT the case in Filecoin due to deferred execution, so the best
|
||||
// we can do is duplicate the last value.
|
||||
baseFeeArray := []ethtypes.EthBigInt{ethtypes.EthBigInt(ts.Blocks()[0].ParentBaseFee)}
|
||||
gasUsedRatioArray := []float64{}
|
||||
rewardsArray := make([][]ethtypes.EthBigInt, 0)
|
||||
// NOTE: baseFeePerGas should include the next block after the newest of the returned range,
|
||||
// because the next base fee can be inferred from the messages in the newest block.
|
||||
// However, this is NOT the case in Filecoin due to deferred execution, so the best
|
||||
// we can do is duplicate the last value.
|
||||
baseFeeArray = []ethtypes.EthBigInt{ethtypes.EthBigInt(basefee)}
|
||||
rewardsArray = make([][]ethtypes.EthBigInt, 0)
|
||||
gasUsedRatioArray = []float64{}
|
||||
blocksIncluded int
|
||||
)
|
||||
|
||||
blocksIncluded := 0
|
||||
for blocksIncluded < int(params.BlkCount) && ts.Height() > 0 {
|
||||
compOutput, err := a.StateCompute(ctx, ts.Height(), nil, ts.Key())
|
||||
msgs, rcpts, err := messagesAndReceipts(ctx, ts, a.Chain, a.StateAPI)
|
||||
if err != nil {
|
||||
return ethtypes.EthFeeHistory{}, xerrors.Errorf("cannot lookup the status of tipset: %v: %w", ts, err)
|
||||
return ethtypes.EthFeeHistory{}, xerrors.Errorf("failed to retrieve messages and receipts for height %d: %w", ts.Height(), err)
|
||||
}
|
||||
|
||||
txGasRewards := gasRewardSorter{}
|
||||
for _, msg := range compOutput.Trace {
|
||||
if msg.Msg.From == builtintypes.SystemActorAddr {
|
||||
continue
|
||||
}
|
||||
|
||||
smsgCid, err := getSignedMessage(ctx, a.Chain, msg.MsgCid)
|
||||
if err != nil {
|
||||
return ethtypes.EthFeeHistory{}, xerrors.Errorf("failed to get signed msg %s: %w", msg.MsgCid, err)
|
||||
}
|
||||
|
||||
tx, err := newEthTxFromSignedMessage(ctx, smsgCid, a.StateAPI)
|
||||
if err != nil {
|
||||
return ethtypes.EthFeeHistory{}, err
|
||||
}
|
||||
|
||||
for i, msg := range msgs {
|
||||
effectivePremium := msg.VMMessage().EffectiveGasPremium(basefee)
|
||||
txGasRewards = append(txGasRewards, gasRewardTuple{
|
||||
reward: tx.Reward(ts.Blocks()[0].ParentBaseFee),
|
||||
gas: uint64(msg.MsgRct.GasUsed),
|
||||
premium: effectivePremium,
|
||||
gasUsed: rcpts[i].GasUsed,
|
||||
})
|
||||
}
|
||||
|
||||
rewards, totalGasUsed := calculateRewardsAndGasUsed(rewardPercentiles, txGasRewards)
|
||||
|
||||
// arrays should be reversed at the end
|
||||
baseFeeArray = append(baseFeeArray, ethtypes.EthBigInt(ts.Blocks()[0].ParentBaseFee))
|
||||
baseFeeArray = append(baseFeeArray, ethtypes.EthBigInt(basefee))
|
||||
gasUsedRatioArray = append(gasUsedRatioArray, float64(totalGasUsed)/float64(build.BlockGasLimit))
|
||||
rewardsArray = append(rewardsArray, rewards)
|
||||
oldestBlkHeight = uint64(ts.Height())
|
||||
@@ -766,13 +755,8 @@ func (a *EthModule) EthFeeHistory(ctx context.Context, p jsonrpc.RawParams) (eth
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (a *EthModule) NetVersion(ctx context.Context) (string, error) {
|
||||
// Note that networkId is not encoded in hex
|
||||
nv, err := a.StateNetworkVersion(ctx, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strconv.FormatUint(uint64(nv), 10), nil
|
||||
func (a *EthModule) NetVersion(_ context.Context) (string, error) {
|
||||
return strconv.FormatInt(build.Eip155ChainId, 10), nil
|
||||
}
|
||||
|
||||
func (a *EthModule) NetListening(ctx context.Context) (bool, error) {
|
||||
@@ -1792,35 +1776,33 @@ func newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTx
|
||||
return ethtypes.EthBlock{}, err
|
||||
}
|
||||
|
||||
msgs, err := cs.MessagesForTipset(ctx, ts)
|
||||
msgs, rcpts, err := messagesAndReceipts(ctx, ts, cs, sa)
|
||||
if err != nil {
|
||||
return ethtypes.EthBlock{}, xerrors.Errorf("error loading messages for tipset: %v: %w", ts, err)
|
||||
return ethtypes.EthBlock{}, xerrors.Errorf("failed to retrieve messages and receipts: %w", err)
|
||||
}
|
||||
|
||||
block := ethtypes.NewEthBlock(len(msgs) > 0)
|
||||
|
||||
gasUsed := int64(0)
|
||||
compOutput, err := sa.StateCompute(ctx, ts.Height(), nil, ts.Key())
|
||||
if err != nil {
|
||||
return ethtypes.EthBlock{}, xerrors.Errorf("failed to compute state: %w", err)
|
||||
}
|
||||
|
||||
txIdx := 0
|
||||
for _, msg := range compOutput.Trace {
|
||||
// skip system messages like reward application and cron
|
||||
if msg.Msg.From == builtintypes.SystemActorAddr {
|
||||
continue
|
||||
for i, msg := range msgs {
|
||||
rcpt := rcpts[i]
|
||||
ti := ethtypes.EthUint64(i)
|
||||
gasUsed += rcpt.GasUsed
|
||||
var smsg *types.SignedMessage
|
||||
switch msg := msg.(type) {
|
||||
case *types.SignedMessage:
|
||||
smsg = msg
|
||||
case *types.Message:
|
||||
smsg = &types.SignedMessage{
|
||||
Message: *msg,
|
||||
Signature: crypto.Signature{
|
||||
Type: crypto.SigTypeBLS,
|
||||
},
|
||||
}
|
||||
default:
|
||||
return ethtypes.EthBlock{}, xerrors.Errorf("failed to get signed msg %s: %w", msg.Cid(), err)
|
||||
}
|
||||
|
||||
ti := ethtypes.EthUint64(txIdx)
|
||||
txIdx++
|
||||
|
||||
gasUsed += msg.MsgRct.GasUsed
|
||||
smsgCid, err := getSignedMessage(ctx, cs, msg.MsgCid)
|
||||
if err != nil {
|
||||
return ethtypes.EthBlock{}, xerrors.Errorf("failed to get signed msg %s: %w", msg.MsgCid, err)
|
||||
}
|
||||
tx, err := newEthTxFromSignedMessage(ctx, smsgCid, sa)
|
||||
tx, err := newEthTxFromSignedMessage(ctx, smsg, sa)
|
||||
if err != nil {
|
||||
return ethtypes.EthBlock{}, xerrors.Errorf("failed to convert msg to ethTx: %w", err)
|
||||
}
|
||||
@@ -1846,6 +1828,29 @@ func newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTx
|
||||
return block, nil
|
||||
}
|
||||
|
||||
func messagesAndReceipts(ctx context.Context, ts *types.TipSet, cs *store.ChainStore, sa StateAPI) ([]types.ChainMsg, []types.MessageReceipt, error) {
|
||||
msgs, err := cs.MessagesForTipset(ctx, ts)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("error loading messages for tipset: %v: %w", ts, err)
|
||||
}
|
||||
|
||||
_, rcptRoot, err := sa.StateManager.TipSetState(ctx, ts)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("failed to compute state: %w", err)
|
||||
}
|
||||
|
||||
rcpts, err := cs.ReadReceipts(ctx, rcptRoot)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("error loading receipts for tipset: %v: %w", ts, err)
|
||||
}
|
||||
|
||||
if len(msgs) != len(rcpts) {
|
||||
return nil, nil, xerrors.Errorf("receipts and message array lengths didn't match for tipset: %v: %w", ts, err)
|
||||
}
|
||||
|
||||
return msgs, rcpts, nil
|
||||
}
|
||||
|
||||
// lookupEthAddress makes its best effort at finding the Ethereum address for a
|
||||
// Filecoin address. It does the following:
|
||||
//
|
||||
@@ -2346,10 +2351,10 @@ func parseEthRevert(ret []byte) string {
|
||||
return ethtypes.EthBytes(cbytes).String()
|
||||
}
|
||||
|
||||
func calculateRewardsAndGasUsed(rewardPercentiles []float64, txGasRewards gasRewardSorter) ([]ethtypes.EthBigInt, uint64) {
|
||||
var totalGasUsed uint64
|
||||
func calculateRewardsAndGasUsed(rewardPercentiles []float64, txGasRewards gasRewardSorter) ([]ethtypes.EthBigInt, int64) {
|
||||
var gasUsedTotal int64
|
||||
for _, tx := range txGasRewards {
|
||||
totalGasUsed += tx.gas
|
||||
gasUsedTotal += tx.gasUsed
|
||||
}
|
||||
|
||||
rewards := make([]ethtypes.EthBigInt, len(rewardPercentiles))
|
||||
@@ -2358,23 +2363,23 @@ func calculateRewardsAndGasUsed(rewardPercentiles []float64, txGasRewards gasRew
|
||||
}
|
||||
|
||||
if len(txGasRewards) == 0 {
|
||||
return rewards, totalGasUsed
|
||||
return rewards, gasUsedTotal
|
||||
}
|
||||
|
||||
sort.Stable(txGasRewards)
|
||||
|
||||
var idx int
|
||||
var sum uint64
|
||||
var sum int64
|
||||
for i, percentile := range rewardPercentiles {
|
||||
threshold := uint64(float64(totalGasUsed) * percentile / 100)
|
||||
threshold := int64(float64(gasUsedTotal) * percentile / 100)
|
||||
for sum < threshold && idx < len(txGasRewards)-1 {
|
||||
sum += txGasRewards[idx].gas
|
||||
sum += txGasRewards[idx].gasUsed
|
||||
idx++
|
||||
}
|
||||
rewards[i] = txGasRewards[idx].reward
|
||||
rewards[i] = ethtypes.EthBigInt(txGasRewards[idx].premium)
|
||||
}
|
||||
|
||||
return rewards, totalGasUsed
|
||||
return rewards, gasUsedTotal
|
||||
}
|
||||
|
||||
func getSignedMessage(ctx context.Context, cs *store.ChainStore, msgCid cid.Cid) (*types.SignedMessage, error) {
|
||||
@@ -2397,8 +2402,8 @@ func getSignedMessage(ctx context.Context, cs *store.ChainStore, msgCid cid.Cid)
|
||||
}
|
||||
|
||||
type gasRewardTuple struct {
|
||||
gas uint64
|
||||
reward ethtypes.EthBigInt
|
||||
gasUsed int64
|
||||
premium abi.TokenAmount
|
||||
}
|
||||
|
||||
// sorted in ascending order
|
||||
@@ -2409,5 +2414,5 @@ func (g gasRewardSorter) Swap(i, j int) {
|
||||
g[i], g[j] = g[j], g[i]
|
||||
}
|
||||
func (g gasRewardSorter) Less(i, j int) bool {
|
||||
return g[i].reward.Int.Cmp(g[j].reward.Int) == -1
|
||||
return g[i].premium.Int.Cmp(g[j].premium.Int) == -1
|
||||
}
|
||||
|
||||
@@ -117,11 +117,8 @@ func TestReward(t *testing.T) {
|
||||
{maxFeePerGas: big.NewInt(50), maxPriorityFeePerGas: big.NewInt(200), answer: big.NewInt(-50)},
|
||||
}
|
||||
for _, tc := range testcases {
|
||||
tx := ethtypes.EthTx{
|
||||
MaxFeePerGas: ethtypes.EthBigInt(tc.maxFeePerGas),
|
||||
MaxPriorityFeePerGas: ethtypes.EthBigInt(tc.maxPriorityFeePerGas),
|
||||
}
|
||||
reward := tx.Reward(baseFee)
|
||||
msg := &types.Message{GasFeeCap: tc.maxFeePerGas, GasPremium: tc.maxPriorityFeePerGas}
|
||||
reward := msg.EffectiveGasPremium(baseFee)
|
||||
require.Equal(t, 0, reward.Int.Cmp(tc.answer.Int), reward, tc.answer)
|
||||
}
|
||||
}
|
||||
@@ -140,20 +137,20 @@ func TestRewardPercentiles(t *testing.T) {
|
||||
{
|
||||
percentiles: []float64{25, 50, 75, 100},
|
||||
txGasRewards: []gasRewardTuple{
|
||||
{gas: uint64(0), reward: ethtypes.EthBigInt(big.NewInt(300))},
|
||||
{gas: uint64(100), reward: ethtypes.EthBigInt(big.NewInt(200))},
|
||||
{gas: uint64(350), reward: ethtypes.EthBigInt(big.NewInt(100))},
|
||||
{gas: uint64(500), reward: ethtypes.EthBigInt(big.NewInt(600))},
|
||||
{gas: uint64(300), reward: ethtypes.EthBigInt(big.NewInt(700))},
|
||||
{gasUsed: int64(0), premium: big.NewInt(300)},
|
||||
{gasUsed: int64(100), premium: big.NewInt(200)},
|
||||
{gasUsed: int64(350), premium: big.NewInt(100)},
|
||||
{gasUsed: int64(500), premium: big.NewInt(600)},
|
||||
{gasUsed: int64(300), premium: big.NewInt(700)},
|
||||
},
|
||||
answer: []int64{200, 700, 700, 700},
|
||||
},
|
||||
}
|
||||
for _, tc := range testcases {
|
||||
rewards, totalGasUsed := calculateRewardsAndGasUsed(tc.percentiles, tc.txGasRewards)
|
||||
gasUsed := uint64(0)
|
||||
var gasUsed int64
|
||||
for _, tx := range tc.txGasRewards {
|
||||
gasUsed += tx.gas
|
||||
gasUsed += tx.gasUsed
|
||||
}
|
||||
ans := []ethtypes.EthBigInt{}
|
||||
for _, bi := range tc.answer {
|
||||
|
||||
Reference in New Issue
Block a user