diff --git a/.circleci/config.yml b/.circleci/config.yml index f22bff0f71b..dd8ad9417b2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -656,6 +656,12 @@ workflows: - build suite: itest-deals target: "./itests/deals_test.go" + - test: + name: test-itest-decode_params + requires: + - build + suite: itest-decode_params + target: "./itests/decode_params_test.go" - test: name: test-itest-dup_mpool_messages requires: @@ -680,6 +686,18 @@ workflows: - build suite: itest-eth_block_hash target: "./itests/eth_block_hash_test.go" + - test: + name: test-itest-eth_config + requires: + - build + suite: itest-eth_config + target: "./itests/eth_config_test.go" + - test: + name: test-itest-eth_conformance + requires: + - build + suite: itest-eth_conformance + target: "./itests/eth_conformance_test.go" - test: name: test-itest-eth_deploy requires: diff --git a/api/api_full.go b/api/api_full.go index 00d1017cbb3..f3ab9e82bda 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -16,6 +16,7 @@ import ( datatransfer "github.com/filecoin-project/go-data-transfer" "github.com/filecoin-project/go-fil-markets/retrievalmarket" "github.com/filecoin-project/go-fil-markets/storagemarket" + "github.com/filecoin-project/go-jsonrpc" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/builtin/v8/paych" @@ -831,11 +832,14 @@ type FullNode interface { // - logs: notify new event logs that match a criteria // params contains additional parameters used with the log event type // The client will receive a stream of EthSubscriptionResponse values until EthUnsubscribe is called. - EthSubscribe(ctx context.Context, eventType string, params *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) //perm:write + EthSubscribe(ctx context.Context, params jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) //perm:write // Unsubscribe from a websocket subscription EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error) //perm:write + // Returns the client version + Web3ClientVersion(ctx context.Context) (string, error) //perm:read + // CreateBackup creates node backup onder the specified file name. The // method requires that the lotus daemon is running with the // LOTUS_BACKUP_BASE_PATH environment variable set to some path, and that @@ -846,6 +850,12 @@ type FullNode interface { RaftLeader(ctx context.Context) (peer.ID, error) //perm:read } +// reverse interface to the client, called after EthSubscribe +type EthSubscriber interface { + // note: the parameter is ethtypes.EthSubscriptionResponse serialized as json object + EthSubscription(ctx context.Context, r jsonrpc.RawParams) error // rpc_method:eth_subscription notify:true +} + type StorageAsk struct { Response *storagemarket.StorageAsk diff --git a/api/api_gateway.go b/api/api_gateway.go index 38ddb667006..60f52aa7dec 100644 --- a/api/api_gateway.go +++ b/api/api_gateway.go @@ -7,6 +7,7 @@ import ( blocks "github.com/ipfs/go-libipfs/blocks" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-jsonrpc" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/builtin/v9/miner" "github.com/filecoin-project/go-state-types/dline" @@ -78,6 +79,8 @@ type Gateway interface { EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error) EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (ethtypes.EthBlock, error) EthGetTransactionByHash(ctx context.Context, txHash *ethtypes.EthHash) (*ethtypes.EthTx, error) + EthGetTransactionHashByCid(ctx context.Context, cid cid.Cid) (*ethtypes.EthHash, error) + 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) @@ -102,6 +105,7 @@ type Gateway interface { EthNewBlockFilter(ctx context.Context) (ethtypes.EthFilterID, error) EthNewPendingTransactionFilter(ctx context.Context) (ethtypes.EthFilterID, error) EthUninstallFilter(ctx context.Context, id ethtypes.EthFilterID) (bool, error) - EthSubscribe(ctx context.Context, eventType string, params *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) + EthSubscribe(ctx context.Context, params jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error) + Web3ClientVersion(ctx context.Context) (string, error) } diff --git a/api/client/client.go b/api/client/client.go index 32583097e64..8b159c5b1c9 100644 --- a/api/client/client.go +++ b/api/client/client.go @@ -35,10 +35,10 @@ func NewFullNodeRPCV0(ctx context.Context, addr string, requestHeader http.Heade } // NewFullNodeRPCV1 creates a new http jsonrpc client. -func NewFullNodeRPCV1(ctx context.Context, addr string, requestHeader http.Header) (api.FullNode, jsonrpc.ClientCloser, error) { +func NewFullNodeRPCV1(ctx context.Context, addr string, requestHeader http.Header, opts ...jsonrpc.Option) (api.FullNode, jsonrpc.ClientCloser, error) { var res v1api.FullNodeStruct closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin", - api.GetInternalStructs(&res), requestHeader, jsonrpc.WithErrors(api.RPCErrors)) + api.GetInternalStructs(&res), requestHeader, append([]jsonrpc.Option{jsonrpc.WithErrors(api.RPCErrors)}, opts...)...) return &res, closer, err } diff --git a/api/eth_aliases.go b/api/eth_aliases.go index cf69bfff70f..ccf0317d951 100644 --- a/api/eth_aliases.go +++ b/api/eth_aliases.go @@ -41,4 +41,6 @@ func CreateEthRPCAliases(as apitypes.Aliaser) { as.AliasMethod("net_version", "Filecoin.NetVersion") as.AliasMethod("net_listening", "Filecoin.NetListening") + + as.AliasMethod("web3_clientVersion", "Filecoin.Web3ClientVersion") } diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index 43e2c55dfd8..799802c3cef 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -23,6 +23,7 @@ import ( bitfield "github.com/filecoin-project/go-bitfield" datatransfer "github.com/filecoin-project/go-data-transfer" retrievalmarket "github.com/filecoin-project/go-fil-markets/retrievalmarket" + jsonrpc "github.com/filecoin-project/go-jsonrpc" auth "github.com/filecoin-project/go-jsonrpc/auth" abi "github.com/filecoin-project/go-state-types/abi" big "github.com/filecoin-project/go-state-types/big" @@ -1388,18 +1389,18 @@ func (mr *MockFullNodeMockRecorder) EthSendRawTransaction(arg0, arg1 interface{} } // EthSubscribe mocks base method. -func (m *MockFullNode) EthSubscribe(arg0 context.Context, arg1 string, arg2 *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) { +func (m *MockFullNode) EthSubscribe(arg0 context.Context, arg1 jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "EthSubscribe", arg0, arg1, arg2) - ret0, _ := ret[0].(<-chan ethtypes.EthSubscriptionResponse) + ret := m.ctrl.Call(m, "EthSubscribe", arg0, arg1) + ret0, _ := ret[0].(ethtypes.EthSubscriptionID) ret1, _ := ret[1].(error) return ret0, ret1 } // EthSubscribe indicates an expected call of EthSubscribe. -func (mr *MockFullNodeMockRecorder) EthSubscribe(arg0, arg1, arg2 interface{}) *gomock.Call { +func (mr *MockFullNodeMockRecorder) EthSubscribe(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthSubscribe", reflect.TypeOf((*MockFullNode)(nil).EthSubscribe), arg0, arg1, arg2) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthSubscribe", reflect.TypeOf((*MockFullNode)(nil).EthSubscribe), arg0, arg1) } // EthUninstallFilter mocks base method. @@ -4096,3 +4097,18 @@ func (mr *MockFullNodeMockRecorder) WalletVerify(arg0, arg1, arg2, arg3 interfac mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WalletVerify", reflect.TypeOf((*MockFullNode)(nil).WalletVerify), arg0, arg1, arg2, arg3) } + +// Web3ClientVersion mocks base method. +func (m *MockFullNode) Web3ClientVersion(arg0 context.Context) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Web3ClientVersion", arg0) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Web3ClientVersion indicates an expected call of Web3ClientVersion. +func (mr *MockFullNodeMockRecorder) Web3ClientVersion(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Web3ClientVersion", reflect.TypeOf((*MockFullNode)(nil).Web3ClientVersion), arg0) +} diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 6a0a204e0f0..1198cc2ffa3 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -22,6 +22,7 @@ import ( "github.com/filecoin-project/go-fil-markets/piecestore" "github.com/filecoin-project/go-fil-markets/retrievalmarket" "github.com/filecoin-project/go-fil-markets/storagemarket" + "github.com/filecoin-project/go-jsonrpc" "github.com/filecoin-project/go-jsonrpc/auth" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/builtin/v8/paych" @@ -49,42 +50,46 @@ import ( var ErrNotSupported = xerrors.New("method not supported") type ChainIOStruct struct { - Internal struct { - ChainHasObj func(p0 context.Context, p1 cid.Cid) (bool, error) `` + Internal ChainIOMethods +} - ChainPutObj func(p0 context.Context, p1 blocks.Block) error `` +type ChainIOMethods struct { + ChainHasObj func(p0 context.Context, p1 cid.Cid) (bool, error) `` - ChainReadObj func(p0 context.Context, p1 cid.Cid) ([]byte, error) `` - } + ChainPutObj func(p0 context.Context, p1 blocks.Block) error `` + + ChainReadObj func(p0 context.Context, p1 cid.Cid) ([]byte, error) `` } type ChainIOStub struct { } type CommonStruct struct { - Internal struct { - AuthNew func(p0 context.Context, p1 []auth.Permission) ([]byte, error) `perm:"admin"` + Internal CommonMethods +} - AuthVerify func(p0 context.Context, p1 string) ([]auth.Permission, error) `perm:"read"` +type CommonMethods struct { + AuthNew func(p0 context.Context, p1 []auth.Permission) ([]byte, error) `perm:"admin"` - Closing func(p0 context.Context) (<-chan struct{}, error) `perm:"read"` + AuthVerify func(p0 context.Context, p1 string) ([]auth.Permission, error) `perm:"read"` - Discover func(p0 context.Context) (apitypes.OpenRPCDocument, error) `perm:"read"` + Closing func(p0 context.Context) (<-chan struct{}, error) `perm:"read"` - LogAlerts func(p0 context.Context) ([]alerting.Alert, error) `perm:"admin"` + Discover func(p0 context.Context) (apitypes.OpenRPCDocument, error) `perm:"read"` - LogList func(p0 context.Context) ([]string, error) `perm:"write"` + LogAlerts func(p0 context.Context) ([]alerting.Alert, error) `perm:"admin"` - LogSetLevel func(p0 context.Context, p1 string, p2 string) error `perm:"write"` + LogList func(p0 context.Context) ([]string, error) `perm:"write"` - Session func(p0 context.Context) (uuid.UUID, error) `perm:"read"` + LogSetLevel func(p0 context.Context, p1 string, p2 string) error `perm:"write"` - Shutdown func(p0 context.Context) error `perm:"admin"` + Session func(p0 context.Context) (uuid.UUID, error) `perm:"read"` - StartTime func(p0 context.Context) (time.Time, error) `perm:"read"` + Shutdown func(p0 context.Context) error `perm:"admin"` - Version func(p0 context.Context) (APIVersion, error) `perm:"read"` - } + StartTime func(p0 context.Context) (time.Time, error) `perm:"read"` + + Version func(p0 context.Context) (APIVersion, error) `perm:"read"` } type CommonStub struct { @@ -95,8 +100,10 @@ type CommonNetStruct struct { NetStruct - Internal struct { - } + Internal CommonNetMethods +} + +type CommonNetMethods struct { } type CommonNetStub struct { @@ -105,484 +112,499 @@ type CommonNetStub struct { NetStub } +type EthSubscriberStruct struct { + Internal EthSubscriberMethods +} + +type EthSubscriberMethods struct { + EthSubscription func(p0 context.Context, p1 jsonrpc.RawParams) error `notify:"true"rpc_method:"eth_subscription"` +} + +type EthSubscriberStub struct { +} + type FullNodeStruct struct { CommonStruct NetStruct - Internal struct { - ChainBlockstoreInfo func(p0 context.Context) (map[string]interface{}, error) `perm:"read"` + Internal FullNodeMethods +} + +type FullNodeMethods struct { + ChainBlockstoreInfo func(p0 context.Context) (map[string]interface{}, error) `perm:"read"` - ChainCheckBlockstore func(p0 context.Context) error `perm:"admin"` + ChainCheckBlockstore func(p0 context.Context) error `perm:"admin"` - ChainDeleteObj func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` + ChainDeleteObj func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` - ChainExport func(p0 context.Context, p1 abi.ChainEpoch, p2 bool, p3 types.TipSetKey) (<-chan []byte, error) `perm:"read"` + ChainExport func(p0 context.Context, p1 abi.ChainEpoch, p2 bool, p3 types.TipSetKey) (<-chan []byte, error) `perm:"read"` - ChainGetBlock func(p0 context.Context, p1 cid.Cid) (*types.BlockHeader, error) `perm:"read"` + ChainGetBlock func(p0 context.Context, p1 cid.Cid) (*types.BlockHeader, error) `perm:"read"` - ChainGetBlockMessages func(p0 context.Context, p1 cid.Cid) (*BlockMessages, error) `perm:"read"` + ChainGetBlockMessages func(p0 context.Context, p1 cid.Cid) (*BlockMessages, error) `perm:"read"` - ChainGetEvents func(p0 context.Context, p1 cid.Cid) ([]types.Event, error) `perm:"read"` + ChainGetEvents func(p0 context.Context, p1 cid.Cid) ([]types.Event, error) `perm:"read"` - ChainGetGenesis func(p0 context.Context) (*types.TipSet, error) `perm:"read"` + ChainGetGenesis func(p0 context.Context) (*types.TipSet, error) `perm:"read"` - ChainGetMessage func(p0 context.Context, p1 cid.Cid) (*types.Message, error) `perm:"read"` + ChainGetMessage func(p0 context.Context, p1 cid.Cid) (*types.Message, error) `perm:"read"` - ChainGetMessagesInTipset func(p0 context.Context, p1 types.TipSetKey) ([]Message, error) `perm:"read"` + ChainGetMessagesInTipset func(p0 context.Context, p1 types.TipSetKey) ([]Message, error) `perm:"read"` - ChainGetNode func(p0 context.Context, p1 string) (*IpldObject, error) `perm:"read"` + ChainGetNode func(p0 context.Context, p1 string) (*IpldObject, error) `perm:"read"` - ChainGetParentMessages func(p0 context.Context, p1 cid.Cid) ([]Message, error) `perm:"read"` + ChainGetParentMessages func(p0 context.Context, p1 cid.Cid) ([]Message, error) `perm:"read"` - ChainGetParentReceipts func(p0 context.Context, p1 cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"` + ChainGetParentReceipts func(p0 context.Context, p1 cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"` - ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*HeadChange, error) `perm:"read"` + ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*HeadChange, error) `perm:"read"` - ChainGetTipSet func(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) `perm:"read"` + ChainGetTipSet func(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) `perm:"read"` - ChainGetTipSetAfterHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `perm:"read"` + ChainGetTipSetAfterHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `perm:"read"` - ChainGetTipSetByHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `perm:"read"` + ChainGetTipSetByHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `perm:"read"` - ChainHasObj func(p0 context.Context, p1 cid.Cid) (bool, error) `perm:"read"` + ChainHasObj func(p0 context.Context, p1 cid.Cid) (bool, error) `perm:"read"` - ChainHead func(p0 context.Context) (*types.TipSet, error) `perm:"read"` + ChainHead func(p0 context.Context) (*types.TipSet, error) `perm:"read"` - ChainNotify func(p0 context.Context) (<-chan []*HeadChange, error) `perm:"read"` + ChainNotify func(p0 context.Context) (<-chan []*HeadChange, error) `perm:"read"` - ChainPrune func(p0 context.Context, p1 PruneOpts) error `perm:"admin"` + ChainPrune func(p0 context.Context, p1 PruneOpts) error `perm:"admin"` - ChainPutObj func(p0 context.Context, p1 blocks.Block) error `perm:"admin"` + ChainPutObj func(p0 context.Context, p1 blocks.Block) error `perm:"admin"` - ChainReadObj func(p0 context.Context, p1 cid.Cid) ([]byte, error) `perm:"read"` + ChainReadObj func(p0 context.Context, p1 cid.Cid) ([]byte, error) `perm:"read"` - ChainSetHead func(p0 context.Context, p1 types.TipSetKey) error `perm:"admin"` + ChainSetHead func(p0 context.Context, p1 types.TipSetKey) error `perm:"admin"` - ChainStatObj func(p0 context.Context, p1 cid.Cid, p2 cid.Cid) (ObjStat, error) `perm:"read"` + ChainStatObj func(p0 context.Context, p1 cid.Cid, p2 cid.Cid) (ObjStat, error) `perm:"read"` - ChainTipSetWeight func(p0 context.Context, p1 types.TipSetKey) (types.BigInt, error) `perm:"read"` + ChainTipSetWeight func(p0 context.Context, p1 types.TipSetKey) (types.BigInt, error) `perm:"read"` - ClientCalcCommP func(p0 context.Context, p1 string) (*CommPRet, error) `perm:"write"` + ClientCalcCommP func(p0 context.Context, p1 string) (*CommPRet, error) `perm:"write"` - ClientCancelDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` + ClientCancelDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` - ClientCancelRetrievalDeal func(p0 context.Context, p1 retrievalmarket.DealID) error `perm:"write"` + ClientCancelRetrievalDeal func(p0 context.Context, p1 retrievalmarket.DealID) error `perm:"write"` - ClientDataTransferUpdates func(p0 context.Context) (<-chan DataTransferChannel, error) `perm:"write"` + ClientDataTransferUpdates func(p0 context.Context) (<-chan DataTransferChannel, error) `perm:"write"` - ClientDealPieceCID func(p0 context.Context, p1 cid.Cid) (DataCIDSize, error) `perm:"read"` + ClientDealPieceCID func(p0 context.Context, p1 cid.Cid) (DataCIDSize, error) `perm:"read"` - ClientDealSize func(p0 context.Context, p1 cid.Cid) (DataSize, error) `perm:"read"` + ClientDealSize func(p0 context.Context, p1 cid.Cid) (DataSize, error) `perm:"read"` - ClientExport func(p0 context.Context, p1 ExportRef, p2 FileRef) error `perm:"admin"` + ClientExport func(p0 context.Context, p1 ExportRef, p2 FileRef) error `perm:"admin"` - ClientFindData func(p0 context.Context, p1 cid.Cid, p2 *cid.Cid) ([]QueryOffer, error) `perm:"read"` + ClientFindData func(p0 context.Context, p1 cid.Cid, p2 *cid.Cid) ([]QueryOffer, error) `perm:"read"` - ClientGenCar func(p0 context.Context, p1 FileRef, p2 string) error `perm:"write"` + ClientGenCar func(p0 context.Context, p1 FileRef, p2 string) error `perm:"write"` - ClientGetDealInfo func(p0 context.Context, p1 cid.Cid) (*DealInfo, error) `perm:"read"` + ClientGetDealInfo func(p0 context.Context, p1 cid.Cid) (*DealInfo, error) `perm:"read"` - ClientGetDealStatus func(p0 context.Context, p1 uint64) (string, error) `perm:"read"` + ClientGetDealStatus func(p0 context.Context, p1 uint64) (string, error) `perm:"read"` - ClientGetDealUpdates func(p0 context.Context) (<-chan DealInfo, error) `perm:"write"` + ClientGetDealUpdates func(p0 context.Context) (<-chan DealInfo, error) `perm:"write"` - ClientGetRetrievalUpdates func(p0 context.Context) (<-chan RetrievalInfo, error) `perm:"write"` + ClientGetRetrievalUpdates func(p0 context.Context) (<-chan RetrievalInfo, error) `perm:"write"` - ClientHasLocal func(p0 context.Context, p1 cid.Cid) (bool, error) `perm:"write"` + ClientHasLocal func(p0 context.Context, p1 cid.Cid) (bool, error) `perm:"write"` - ClientImport func(p0 context.Context, p1 FileRef) (*ImportRes, error) `perm:"admin"` + ClientImport func(p0 context.Context, p1 FileRef) (*ImportRes, error) `perm:"admin"` - ClientListDataTransfers func(p0 context.Context) ([]DataTransferChannel, error) `perm:"write"` + ClientListDataTransfers func(p0 context.Context) ([]DataTransferChannel, error) `perm:"write"` - ClientListDeals func(p0 context.Context) ([]DealInfo, error) `perm:"write"` + ClientListDeals func(p0 context.Context) ([]DealInfo, error) `perm:"write"` - ClientListImports func(p0 context.Context) ([]Import, error) `perm:"write"` + ClientListImports func(p0 context.Context) ([]Import, error) `perm:"write"` - ClientListRetrievals func(p0 context.Context) ([]RetrievalInfo, error) `perm:"write"` + ClientListRetrievals func(p0 context.Context) ([]RetrievalInfo, error) `perm:"write"` - ClientMinerQueryOffer func(p0 context.Context, p1 address.Address, p2 cid.Cid, p3 *cid.Cid) (QueryOffer, error) `perm:"read"` + ClientMinerQueryOffer func(p0 context.Context, p1 address.Address, p2 cid.Cid, p3 *cid.Cid) (QueryOffer, error) `perm:"read"` - ClientQueryAsk func(p0 context.Context, p1 peer.ID, p2 address.Address) (*StorageAsk, error) `perm:"read"` + ClientQueryAsk func(p0 context.Context, p1 peer.ID, p2 address.Address) (*StorageAsk, error) `perm:"read"` - ClientRemoveImport func(p0 context.Context, p1 imports.ID) error `perm:"admin"` + ClientRemoveImport func(p0 context.Context, p1 imports.ID) error `perm:"admin"` - ClientRestartDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` + ClientRestartDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` - ClientRetrieve func(p0 context.Context, p1 RetrievalOrder) (*RestrievalRes, error) `perm:"admin"` + ClientRetrieve func(p0 context.Context, p1 RetrievalOrder) (*RestrievalRes, error) `perm:"admin"` - ClientRetrieveTryRestartInsufficientFunds func(p0 context.Context, p1 address.Address) error `perm:"write"` + ClientRetrieveTryRestartInsufficientFunds func(p0 context.Context, p1 address.Address) error `perm:"write"` - ClientRetrieveWait func(p0 context.Context, p1 retrievalmarket.DealID) error `perm:"admin"` + ClientRetrieveWait func(p0 context.Context, p1 retrievalmarket.DealID) error `perm:"admin"` - ClientStartDeal func(p0 context.Context, p1 *StartDealParams) (*cid.Cid, error) `perm:"admin"` + ClientStartDeal func(p0 context.Context, p1 *StartDealParams) (*cid.Cid, error) `perm:"admin"` - ClientStatelessDeal func(p0 context.Context, p1 *StartDealParams) (*cid.Cid, error) `perm:"write"` + ClientStatelessDeal func(p0 context.Context, p1 *StartDealParams) (*cid.Cid, error) `perm:"write"` - CreateBackup func(p0 context.Context, p1 string) error `perm:"admin"` + CreateBackup func(p0 context.Context, p1 string) error `perm:"admin"` - EthAccounts func(p0 context.Context) ([]ethtypes.EthAddress, error) `perm:"read"` + EthAccounts func(p0 context.Context) ([]ethtypes.EthAddress, error) `perm:"read"` - EthBlockNumber func(p0 context.Context) (ethtypes.EthUint64, error) `perm:"read"` + EthBlockNumber func(p0 context.Context) (ethtypes.EthUint64, error) `perm:"read"` - EthCall func(p0 context.Context, p1 ethtypes.EthCall, p2 string) (ethtypes.EthBytes, error) `perm:"read"` + EthCall func(p0 context.Context, p1 ethtypes.EthCall, p2 string) (ethtypes.EthBytes, error) `perm:"read"` - EthChainId func(p0 context.Context) (ethtypes.EthUint64, error) `perm:"read"` + EthChainId func(p0 context.Context) (ethtypes.EthUint64, error) `perm:"read"` - EthEstimateGas func(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) `perm:"read"` + EthEstimateGas func(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) `perm:"read"` - EthFeeHistory func(p0 context.Context, p1 ethtypes.EthUint64, p2 string, p3 []float64) (ethtypes.EthFeeHistory, error) `perm:"read"` + EthFeeHistory func(p0 context.Context, p1 ethtypes.EthUint64, p2 string, p3 []float64) (ethtypes.EthFeeHistory, error) `perm:"read"` - EthGasPrice func(p0 context.Context) (ethtypes.EthBigInt, error) `perm:"read"` + EthGasPrice func(p0 context.Context) (ethtypes.EthBigInt, error) `perm:"read"` - EthGetBalance func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBigInt, error) `perm:"read"` + EthGetBalance func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBigInt, error) `perm:"read"` - EthGetBlockByHash func(p0 context.Context, p1 ethtypes.EthHash, p2 bool) (ethtypes.EthBlock, error) `perm:"read"` + EthGetBlockByHash func(p0 context.Context, p1 ethtypes.EthHash, p2 bool) (ethtypes.EthBlock, error) `perm:"read"` - EthGetBlockByNumber func(p0 context.Context, p1 string, p2 bool) (ethtypes.EthBlock, error) `perm:"read"` + EthGetBlockByNumber func(p0 context.Context, p1 string, p2 bool) (ethtypes.EthBlock, error) `perm:"read"` - EthGetBlockTransactionCountByHash func(p0 context.Context, p1 ethtypes.EthHash) (ethtypes.EthUint64, error) `perm:"read"` + EthGetBlockTransactionCountByHash func(p0 context.Context, p1 ethtypes.EthHash) (ethtypes.EthUint64, error) `perm:"read"` - EthGetBlockTransactionCountByNumber func(p0 context.Context, p1 ethtypes.EthUint64) (ethtypes.EthUint64, error) `perm:"read"` + EthGetBlockTransactionCountByNumber func(p0 context.Context, p1 ethtypes.EthUint64) (ethtypes.EthUint64, error) `perm:"read"` - EthGetCode func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBytes, error) `perm:"read"` + EthGetCode func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBytes, error) `perm:"read"` - EthGetFilterChanges func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) `perm:"write"` + EthGetFilterChanges func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) `perm:"write"` - EthGetFilterLogs func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) `perm:"write"` + EthGetFilterLogs func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) `perm:"write"` - EthGetLogs func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) `perm:"read"` + EthGetLogs func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) `perm:"read"` - EthGetMessageCidByTransactionHash func(p0 context.Context, p1 *ethtypes.EthHash) (*cid.Cid, error) `perm:"read"` + EthGetMessageCidByTransactionHash func(p0 context.Context, p1 *ethtypes.EthHash) (*cid.Cid, error) `perm:"read"` - EthGetStorageAt func(p0 context.Context, p1 ethtypes.EthAddress, p2 ethtypes.EthBytes, p3 string) (ethtypes.EthBytes, error) `perm:"read"` + EthGetStorageAt func(p0 context.Context, p1 ethtypes.EthAddress, p2 ethtypes.EthBytes, p3 string) (ethtypes.EthBytes, error) `perm:"read"` - EthGetTransactionByBlockHashAndIndex func(p0 context.Context, p1 ethtypes.EthHash, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) `perm:"read"` + EthGetTransactionByBlockHashAndIndex func(p0 context.Context, p1 ethtypes.EthHash, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) `perm:"read"` - EthGetTransactionByBlockNumberAndIndex func(p0 context.Context, p1 ethtypes.EthUint64, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) `perm:"read"` + EthGetTransactionByBlockNumberAndIndex func(p0 context.Context, p1 ethtypes.EthUint64, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) `perm:"read"` - EthGetTransactionByHash func(p0 context.Context, p1 *ethtypes.EthHash) (*ethtypes.EthTx, error) `perm:"read"` + EthGetTransactionByHash func(p0 context.Context, p1 *ethtypes.EthHash) (*ethtypes.EthTx, error) `perm:"read"` - EthGetTransactionCount func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthUint64, error) `perm:"read"` + EthGetTransactionCount func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthUint64, error) `perm:"read"` - EthGetTransactionHashByCid func(p0 context.Context, p1 cid.Cid) (*ethtypes.EthHash, error) `perm:"read"` + EthGetTransactionHashByCid func(p0 context.Context, p1 cid.Cid) (*ethtypes.EthHash, error) `perm:"read"` - EthGetTransactionReceipt func(p0 context.Context, p1 ethtypes.EthHash) (*EthTxReceipt, error) `perm:"read"` + EthGetTransactionReceipt func(p0 context.Context, p1 ethtypes.EthHash) (*EthTxReceipt, error) `perm:"read"` - EthMaxPriorityFeePerGas func(p0 context.Context) (ethtypes.EthBigInt, error) `perm:"read"` + EthMaxPriorityFeePerGas func(p0 context.Context) (ethtypes.EthBigInt, error) `perm:"read"` - EthNewBlockFilter func(p0 context.Context) (ethtypes.EthFilterID, error) `perm:"write"` + EthNewBlockFilter func(p0 context.Context) (ethtypes.EthFilterID, error) `perm:"write"` - EthNewFilter func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) `perm:"write"` + EthNewFilter func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) `perm:"write"` - EthNewPendingTransactionFilter func(p0 context.Context) (ethtypes.EthFilterID, error) `perm:"write"` + EthNewPendingTransactionFilter func(p0 context.Context) (ethtypes.EthFilterID, error) `perm:"write"` - EthProtocolVersion func(p0 context.Context) (ethtypes.EthUint64, error) `perm:"read"` + EthProtocolVersion func(p0 context.Context) (ethtypes.EthUint64, error) `perm:"read"` - EthSendRawTransaction func(p0 context.Context, p1 ethtypes.EthBytes) (ethtypes.EthHash, error) `perm:"read"` + EthSendRawTransaction func(p0 context.Context, p1 ethtypes.EthBytes) (ethtypes.EthHash, error) `perm:"read"` - EthSubscribe func(p0 context.Context, p1 string, p2 *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) `perm:"write"` + EthSubscribe func(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) `perm:"write"` - EthUninstallFilter func(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) `perm:"write"` + EthUninstallFilter func(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) `perm:"write"` - EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) `perm:"write"` + EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) `perm:"write"` - GasEstimateFeeCap func(p0 context.Context, p1 *types.Message, p2 int64, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` + GasEstimateFeeCap func(p0 context.Context, p1 *types.Message, p2 int64, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` - GasEstimateGasLimit func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (int64, error) `perm:"read"` + GasEstimateGasLimit func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (int64, error) `perm:"read"` - GasEstimateGasPremium func(p0 context.Context, p1 uint64, p2 address.Address, p3 int64, p4 types.TipSetKey) (types.BigInt, error) `perm:"read"` + GasEstimateGasPremium func(p0 context.Context, p1 uint64, p2 address.Address, p3 int64, p4 types.TipSetKey) (types.BigInt, error) `perm:"read"` - GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) `perm:"read"` + GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) `perm:"read"` - MarketAddBalance func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` + MarketAddBalance func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` - MarketGetReserved func(p0 context.Context, p1 address.Address) (types.BigInt, error) `perm:"sign"` + MarketGetReserved func(p0 context.Context, p1 address.Address) (types.BigInt, error) `perm:"sign"` - MarketReleaseFunds func(p0 context.Context, p1 address.Address, p2 types.BigInt) error `perm:"sign"` + MarketReleaseFunds func(p0 context.Context, p1 address.Address, p2 types.BigInt) error `perm:"sign"` - MarketReserveFunds func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` + MarketReserveFunds func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` - MarketWithdraw func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` + MarketWithdraw func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` - MinerCreateBlock func(p0 context.Context, p1 *BlockTemplate) (*types.BlockMsg, error) `perm:"write"` + MinerCreateBlock func(p0 context.Context, p1 *BlockTemplate) (*types.BlockMsg, error) `perm:"write"` - MinerGetBaseInfo func(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*MiningBaseInfo, error) `perm:"read"` + MinerGetBaseInfo func(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*MiningBaseInfo, error) `perm:"read"` - MpoolBatchPush func(p0 context.Context, p1 []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"` + MpoolBatchPush func(p0 context.Context, p1 []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"` - MpoolBatchPushMessage func(p0 context.Context, p1 []*types.Message, p2 *MessageSendSpec) ([]*types.SignedMessage, error) `perm:"sign"` + MpoolBatchPushMessage func(p0 context.Context, p1 []*types.Message, p2 *MessageSendSpec) ([]*types.SignedMessage, error) `perm:"sign"` - MpoolBatchPushUntrusted func(p0 context.Context, p1 []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"` + MpoolBatchPushUntrusted func(p0 context.Context, p1 []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"` - MpoolCheckMessages func(p0 context.Context, p1 []*MessagePrototype) ([][]MessageCheckStatus, error) `perm:"read"` + MpoolCheckMessages func(p0 context.Context, p1 []*MessagePrototype) ([][]MessageCheckStatus, error) `perm:"read"` - MpoolCheckPendingMessages func(p0 context.Context, p1 address.Address) ([][]MessageCheckStatus, error) `perm:"read"` + MpoolCheckPendingMessages func(p0 context.Context, p1 address.Address) ([][]MessageCheckStatus, error) `perm:"read"` - MpoolCheckReplaceMessages func(p0 context.Context, p1 []*types.Message) ([][]MessageCheckStatus, error) `perm:"read"` + MpoolCheckReplaceMessages func(p0 context.Context, p1 []*types.Message) ([][]MessageCheckStatus, error) `perm:"read"` - MpoolClear func(p0 context.Context, p1 bool) error `perm:"write"` + MpoolClear func(p0 context.Context, p1 bool) error `perm:"write"` - MpoolGetConfig func(p0 context.Context) (*types.MpoolConfig, error) `perm:"read"` + MpoolGetConfig func(p0 context.Context) (*types.MpoolConfig, error) `perm:"read"` - MpoolGetNonce func(p0 context.Context, p1 address.Address) (uint64, error) `perm:"read"` + MpoolGetNonce func(p0 context.Context, p1 address.Address) (uint64, error) `perm:"read"` - MpoolPending func(p0 context.Context, p1 types.TipSetKey) ([]*types.SignedMessage, error) `perm:"read"` + MpoolPending func(p0 context.Context, p1 types.TipSetKey) ([]*types.SignedMessage, error) `perm:"read"` - MpoolPush func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `perm:"write"` + MpoolPush func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `perm:"write"` - MpoolPushMessage func(p0 context.Context, p1 *types.Message, p2 *MessageSendSpec) (*types.SignedMessage, error) `perm:"sign"` + MpoolPushMessage func(p0 context.Context, p1 *types.Message, p2 *MessageSendSpec) (*types.SignedMessage, error) `perm:"sign"` - MpoolPushUntrusted func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `perm:"write"` + MpoolPushUntrusted func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `perm:"write"` - MpoolSelect func(p0 context.Context, p1 types.TipSetKey, p2 float64) ([]*types.SignedMessage, error) `perm:"read"` + MpoolSelect func(p0 context.Context, p1 types.TipSetKey, p2 float64) ([]*types.SignedMessage, error) `perm:"read"` - MpoolSetConfig func(p0 context.Context, p1 *types.MpoolConfig) error `perm:"admin"` + MpoolSetConfig func(p0 context.Context, p1 *types.MpoolConfig) error `perm:"admin"` - MpoolSub func(p0 context.Context) (<-chan MpoolUpdate, error) `perm:"read"` + MpoolSub func(p0 context.Context) (<-chan MpoolUpdate, error) `perm:"read"` - MsigAddApprove func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 bool) (*MessagePrototype, error) `perm:"sign"` + MsigAddApprove func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 bool) (*MessagePrototype, error) `perm:"sign"` - MsigAddCancel func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 bool) (*MessagePrototype, error) `perm:"sign"` + MsigAddCancel func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 bool) (*MessagePrototype, error) `perm:"sign"` - MsigAddPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (*MessagePrototype, error) `perm:"sign"` + MsigAddPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (*MessagePrototype, error) `perm:"sign"` - MsigApprove func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address) (*MessagePrototype, error) `perm:"sign"` + MsigApprove func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address) (*MessagePrototype, error) `perm:"sign"` - MsigApproveTxnHash func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 address.Address, p5 types.BigInt, p6 address.Address, p7 uint64, p8 []byte) (*MessagePrototype, error) `perm:"sign"` + MsigApproveTxnHash func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 address.Address, p5 types.BigInt, p6 address.Address, p7 uint64, p8 []byte) (*MessagePrototype, error) `perm:"sign"` - MsigCancel func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address) (*MessagePrototype, error) `perm:"sign"` + MsigCancel func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address) (*MessagePrototype, error) `perm:"sign"` - MsigCancelTxnHash func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 types.BigInt, p5 address.Address, p6 uint64, p7 []byte) (*MessagePrototype, error) `perm:"sign"` + MsigCancelTxnHash func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 types.BigInt, p5 address.Address, p6 uint64, p7 []byte) (*MessagePrototype, error) `perm:"sign"` - MsigCreate func(p0 context.Context, p1 uint64, p2 []address.Address, p3 abi.ChainEpoch, p4 types.BigInt, p5 address.Address, p6 types.BigInt) (*MessagePrototype, error) `perm:"sign"` + MsigCreate func(p0 context.Context, p1 uint64, p2 []address.Address, p3 abi.ChainEpoch, p4 types.BigInt, p5 address.Address, p6 types.BigInt) (*MessagePrototype, error) `perm:"sign"` - MsigGetAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `perm:"read"` + MsigGetAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `perm:"read"` - MsigGetPending func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*MsigTransaction, error) `perm:"read"` + MsigGetPending func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*MsigTransaction, error) `perm:"read"` - MsigGetVested func(p0 context.Context, p1 address.Address, p2 types.TipSetKey, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` + MsigGetVested func(p0 context.Context, p1 address.Address, p2 types.TipSetKey, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` - MsigGetVestingSchedule func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MsigVesting, error) `perm:"read"` + MsigGetVestingSchedule func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MsigVesting, error) `perm:"read"` - MsigPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 address.Address, p5 uint64, p6 []byte) (*MessagePrototype, error) `perm:"sign"` + MsigPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 address.Address, p5 uint64, p6 []byte) (*MessagePrototype, error) `perm:"sign"` - MsigRemoveSigner func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (*MessagePrototype, error) `perm:"sign"` + MsigRemoveSigner func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (*MessagePrototype, error) `perm:"sign"` - MsigSwapApprove func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 address.Address) (*MessagePrototype, error) `perm:"sign"` + MsigSwapApprove func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 address.Address) (*MessagePrototype, error) `perm:"sign"` - MsigSwapCancel func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address) (*MessagePrototype, error) `perm:"sign"` + MsigSwapCancel func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address) (*MessagePrototype, error) `perm:"sign"` - MsigSwapPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 address.Address) (*MessagePrototype, error) `perm:"sign"` + MsigSwapPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 address.Address) (*MessagePrototype, error) `perm:"sign"` - NetListening func(p0 context.Context) (bool, error) `perm:"read"` + NetListening func(p0 context.Context) (bool, error) `perm:"read"` - NetVersion func(p0 context.Context) (string, error) `perm:"read"` + NetVersion func(p0 context.Context) (string, error) `perm:"read"` - NodeStatus func(p0 context.Context, p1 bool) (NodeStatus, error) `perm:"read"` + NodeStatus func(p0 context.Context, p1 bool) (NodeStatus, error) `perm:"read"` - PaychAllocateLane func(p0 context.Context, p1 address.Address) (uint64, error) `perm:"sign"` + PaychAllocateLane func(p0 context.Context, p1 address.Address) (uint64, error) `perm:"sign"` - PaychAvailableFunds func(p0 context.Context, p1 address.Address) (*ChannelAvailableFunds, error) `perm:"sign"` + PaychAvailableFunds func(p0 context.Context, p1 address.Address) (*ChannelAvailableFunds, error) `perm:"sign"` - PaychAvailableFundsByFromTo func(p0 context.Context, p1 address.Address, p2 address.Address) (*ChannelAvailableFunds, error) `perm:"sign"` + PaychAvailableFundsByFromTo func(p0 context.Context, p1 address.Address, p2 address.Address) (*ChannelAvailableFunds, error) `perm:"sign"` - PaychCollect func(p0 context.Context, p1 address.Address) (cid.Cid, error) `perm:"sign"` + PaychCollect func(p0 context.Context, p1 address.Address) (cid.Cid, error) `perm:"sign"` - PaychFund func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (*ChannelInfo, error) `perm:"sign"` + PaychFund func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (*ChannelInfo, error) `perm:"sign"` - PaychGet func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 PaychGetOpts) (*ChannelInfo, error) `perm:"sign"` + PaychGet func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 PaychGetOpts) (*ChannelInfo, error) `perm:"sign"` - PaychGetWaitReady func(p0 context.Context, p1 cid.Cid) (address.Address, error) `perm:"sign"` + PaychGetWaitReady func(p0 context.Context, p1 cid.Cid) (address.Address, error) `perm:"sign"` - PaychList func(p0 context.Context) ([]address.Address, error) `perm:"read"` + PaychList func(p0 context.Context) ([]address.Address, error) `perm:"read"` - PaychNewPayment func(p0 context.Context, p1 address.Address, p2 address.Address, p3 []VoucherSpec) (*PaymentInfo, error) `perm:"sign"` + PaychNewPayment func(p0 context.Context, p1 address.Address, p2 address.Address, p3 []VoucherSpec) (*PaymentInfo, error) `perm:"sign"` - PaychSettle func(p0 context.Context, p1 address.Address) (cid.Cid, error) `perm:"sign"` + PaychSettle func(p0 context.Context, p1 address.Address) (cid.Cid, error) `perm:"sign"` - PaychStatus func(p0 context.Context, p1 address.Address) (*PaychStatus, error) `perm:"read"` + PaychStatus func(p0 context.Context, p1 address.Address) (*PaychStatus, error) `perm:"read"` - PaychVoucherAdd func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 types.BigInt) (types.BigInt, error) `perm:"write"` + PaychVoucherAdd func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 types.BigInt) (types.BigInt, error) `perm:"write"` - PaychVoucherCheckSpendable func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 []byte) (bool, error) `perm:"read"` + PaychVoucherCheckSpendable func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 []byte) (bool, error) `perm:"read"` - PaychVoucherCheckValid func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher) error `perm:"read"` + PaychVoucherCheckValid func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher) error `perm:"read"` - PaychVoucherCreate func(p0 context.Context, p1 address.Address, p2 types.BigInt, p3 uint64) (*VoucherCreateResult, error) `perm:"sign"` + PaychVoucherCreate func(p0 context.Context, p1 address.Address, p2 types.BigInt, p3 uint64) (*VoucherCreateResult, error) `perm:"sign"` - PaychVoucherList func(p0 context.Context, p1 address.Address) ([]*paych.SignedVoucher, error) `perm:"write"` + PaychVoucherList func(p0 context.Context, p1 address.Address) ([]*paych.SignedVoucher, error) `perm:"write"` - PaychVoucherSubmit func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 []byte) (cid.Cid, error) `perm:"sign"` + PaychVoucherSubmit func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 []byte) (cid.Cid, error) `perm:"sign"` - RaftLeader func(p0 context.Context) (peer.ID, error) `perm:"read"` + RaftLeader func(p0 context.Context) (peer.ID, error) `perm:"read"` - RaftState func(p0 context.Context) (*RaftStateData, error) `perm:"read"` + RaftState func(p0 context.Context) (*RaftStateData, error) `perm:"read"` - StateAccountKey func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` + StateAccountKey func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` - StateActorCodeCIDs func(p0 context.Context, p1 abinetwork.Version) (map[string]cid.Cid, error) `perm:"read"` + StateActorCodeCIDs func(p0 context.Context, p1 abinetwork.Version) (map[string]cid.Cid, error) `perm:"read"` - StateActorManifestCID func(p0 context.Context, p1 abinetwork.Version) (cid.Cid, error) `perm:"read"` + StateActorManifestCID func(p0 context.Context, p1 abinetwork.Version) (cid.Cid, error) `perm:"read"` - StateAllMinerFaults func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) ([]*Fault, error) `perm:"read"` + StateAllMinerFaults func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) ([]*Fault, error) `perm:"read"` - StateCall func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (*InvocResult, error) `perm:"read"` + StateCall func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (*InvocResult, error) `perm:"read"` - StateChangedActors func(p0 context.Context, p1 cid.Cid, p2 cid.Cid) (map[string]types.Actor, error) `perm:"read"` + StateChangedActors func(p0 context.Context, p1 cid.Cid, p2 cid.Cid) (map[string]types.Actor, error) `perm:"read"` - StateCirculatingSupply func(p0 context.Context, p1 types.TipSetKey) (abi.TokenAmount, error) `perm:"read"` + StateCirculatingSupply func(p0 context.Context, p1 types.TipSetKey) (abi.TokenAmount, error) `perm:"read"` - StateCompute func(p0 context.Context, p1 abi.ChainEpoch, p2 []*types.Message, p3 types.TipSetKey) (*ComputeStateOutput, error) `perm:"read"` + StateCompute func(p0 context.Context, p1 abi.ChainEpoch, p2 []*types.Message, p3 types.TipSetKey) (*ComputeStateOutput, error) `perm:"read"` - StateComputeDataCID func(p0 context.Context, p1 address.Address, p2 abi.RegisteredSealProof, p3 []abi.DealID, p4 types.TipSetKey) (cid.Cid, error) `perm:"read"` + StateComputeDataCID func(p0 context.Context, p1 address.Address, p2 abi.RegisteredSealProof, p3 []abi.DealID, p4 types.TipSetKey) (cid.Cid, error) `perm:"read"` - StateDealProviderCollateralBounds func(p0 context.Context, p1 abi.PaddedPieceSize, p2 bool, p3 types.TipSetKey) (DealCollateralBounds, error) `perm:"read"` + StateDealProviderCollateralBounds func(p0 context.Context, p1 abi.PaddedPieceSize, p2 bool, p3 types.TipSetKey) (DealCollateralBounds, error) `perm:"read"` - StateDecodeParams func(p0 context.Context, p1 address.Address, p2 abi.MethodNum, p3 []byte, p4 types.TipSetKey) (interface{}, error) `perm:"read"` + StateDecodeParams func(p0 context.Context, p1 address.Address, p2 abi.MethodNum, p3 []byte, p4 types.TipSetKey) (interface{}, error) `perm:"read"` - StateEncodeParams func(p0 context.Context, p1 cid.Cid, p2 abi.MethodNum, p3 json.RawMessage) ([]byte, error) `perm:"read"` + StateEncodeParams func(p0 context.Context, p1 cid.Cid, p2 abi.MethodNum, p3 json.RawMessage) ([]byte, error) `perm:"read"` - StateGetActor func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*types.Actor, error) `perm:"read"` + StateGetActor func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*types.Actor, error) `perm:"read"` - StateGetAllocation func(p0 context.Context, p1 address.Address, p2 verifregtypes.AllocationId, p3 types.TipSetKey) (*verifregtypes.Allocation, error) `perm:"read"` + StateGetAllocation func(p0 context.Context, p1 address.Address, p2 verifregtypes.AllocationId, p3 types.TipSetKey) (*verifregtypes.Allocation, error) `perm:"read"` - StateGetAllocationForPendingDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*verifregtypes.Allocation, error) `perm:"read"` + StateGetAllocationForPendingDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*verifregtypes.Allocation, error) `perm:"read"` - StateGetAllocations func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (map[verifregtypes.AllocationId]verifregtypes.Allocation, error) `perm:"read"` + StateGetAllocations func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (map[verifregtypes.AllocationId]verifregtypes.Allocation, error) `perm:"read"` - StateGetBeaconEntry func(p0 context.Context, p1 abi.ChainEpoch) (*types.BeaconEntry, error) `perm:"read"` + StateGetBeaconEntry func(p0 context.Context, p1 abi.ChainEpoch) (*types.BeaconEntry, error) `perm:"read"` - StateGetClaim func(p0 context.Context, p1 address.Address, p2 verifregtypes.ClaimId, p3 types.TipSetKey) (*verifregtypes.Claim, error) `perm:"read"` + StateGetClaim func(p0 context.Context, p1 address.Address, p2 verifregtypes.ClaimId, p3 types.TipSetKey) (*verifregtypes.Claim, error) `perm:"read"` - StateGetClaims func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (map[verifregtypes.ClaimId]verifregtypes.Claim, error) `perm:"read"` + StateGetClaims func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (map[verifregtypes.ClaimId]verifregtypes.Claim, error) `perm:"read"` - StateGetNetworkParams func(p0 context.Context) (*NetworkParams, error) `perm:"read"` + StateGetNetworkParams func(p0 context.Context) (*NetworkParams, error) `perm:"read"` - StateGetRandomnessFromBeacon func(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) `perm:"read"` + StateGetRandomnessFromBeacon func(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) `perm:"read"` - StateGetRandomnessFromTickets func(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) `perm:"read"` + StateGetRandomnessFromTickets func(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) `perm:"read"` - StateListActors func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `perm:"read"` + StateListActors func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `perm:"read"` - StateListMessages func(p0 context.Context, p1 *MessageMatch, p2 types.TipSetKey, p3 abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"` + StateListMessages func(p0 context.Context, p1 *MessageMatch, p2 types.TipSetKey, p3 abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"` - StateListMiners func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `perm:"read"` + StateListMiners func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `perm:"read"` - StateLookupID func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` + StateLookupID func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` - StateLookupRobustAddress func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` + StateLookupRobustAddress func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` - StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MarketBalance, error) `perm:"read"` + StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MarketBalance, error) `perm:"read"` - StateMarketDeals func(p0 context.Context, p1 types.TipSetKey) (map[string]*MarketDeal, error) `perm:"read"` + StateMarketDeals func(p0 context.Context, p1 types.TipSetKey) (map[string]*MarketDeal, error) `perm:"read"` - StateMarketParticipants func(p0 context.Context, p1 types.TipSetKey) (map[string]MarketBalance, error) `perm:"read"` + StateMarketParticipants func(p0 context.Context, p1 types.TipSetKey) (map[string]MarketBalance, error) `perm:"read"` - StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*MarketDeal, error) `perm:"read"` + StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*MarketDeal, error) `perm:"read"` - StateMinerActiveSectors func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*miner.SectorOnChainInfo, error) `perm:"read"` + StateMinerActiveSectors func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*miner.SectorOnChainInfo, error) `perm:"read"` - StateMinerAllocated func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*bitfield.BitField, error) `perm:"read"` + StateMinerAllocated func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*bitfield.BitField, error) `perm:"read"` - StateMinerAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `perm:"read"` + StateMinerAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `perm:"read"` - StateMinerDeadlines func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]Deadline, error) `perm:"read"` + StateMinerDeadlines func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]Deadline, error) `perm:"read"` - StateMinerFaults func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (bitfield.BitField, error) `perm:"read"` + StateMinerFaults func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (bitfield.BitField, error) `perm:"read"` - StateMinerInfo func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MinerInfo, error) `perm:"read"` + StateMinerInfo func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MinerInfo, error) `perm:"read"` - StateMinerInitialPledgeCollateral func(p0 context.Context, p1 address.Address, p2 miner.SectorPreCommitInfo, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` + StateMinerInitialPledgeCollateral func(p0 context.Context, p1 address.Address, p2 miner.SectorPreCommitInfo, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` - StateMinerPartitions func(p0 context.Context, p1 address.Address, p2 uint64, p3 types.TipSetKey) ([]Partition, error) `perm:"read"` + StateMinerPartitions func(p0 context.Context, p1 address.Address, p2 uint64, p3 types.TipSetKey) ([]Partition, error) `perm:"read"` - StateMinerPower func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*MinerPower, error) `perm:"read"` + StateMinerPower func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*MinerPower, error) `perm:"read"` - StateMinerPreCommitDepositForPower func(p0 context.Context, p1 address.Address, p2 miner.SectorPreCommitInfo, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` + StateMinerPreCommitDepositForPower func(p0 context.Context, p1 address.Address, p2 miner.SectorPreCommitInfo, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` - StateMinerProvingDeadline func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*dline.Info, error) `perm:"read"` + StateMinerProvingDeadline func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*dline.Info, error) `perm:"read"` - StateMinerRecoveries func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (bitfield.BitField, error) `perm:"read"` + StateMinerRecoveries func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (bitfield.BitField, error) `perm:"read"` - StateMinerSectorAllocated func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (bool, error) `perm:"read"` + StateMinerSectorAllocated func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (bool, error) `perm:"read"` - StateMinerSectorCount func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MinerSectors, error) `perm:"read"` + StateMinerSectorCount func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MinerSectors, error) `perm:"read"` - StateMinerSectors func(p0 context.Context, p1 address.Address, p2 *bitfield.BitField, p3 types.TipSetKey) ([]*miner.SectorOnChainInfo, error) `perm:"read"` + StateMinerSectors func(p0 context.Context, p1 address.Address, p2 *bitfield.BitField, p3 types.TipSetKey) ([]*miner.SectorOnChainInfo, error) `perm:"read"` - StateNetworkName func(p0 context.Context) (dtypes.NetworkName, error) `perm:"read"` + StateNetworkName func(p0 context.Context) (dtypes.NetworkName, error) `perm:"read"` - StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (apitypes.NetworkVersion, error) `perm:"read"` + StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (apitypes.NetworkVersion, error) `perm:"read"` - StateReadState func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*ActorState, error) `perm:"read"` + StateReadState func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*ActorState, error) `perm:"read"` - StateReplay func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*InvocResult, error) `perm:"read"` + StateReplay func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*InvocResult, error) `perm:"read"` - StateSearchMsg func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `perm:"read"` + StateSearchMsg func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `perm:"read"` - StateSectorExpiration func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*lminer.SectorExpiration, error) `perm:"read"` + StateSectorExpiration func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*lminer.SectorExpiration, error) `perm:"read"` - StateSectorGetInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorOnChainInfo, error) `perm:"read"` + StateSectorGetInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorOnChainInfo, error) `perm:"read"` - StateSectorPartition func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*lminer.SectorLocation, error) `perm:"read"` + StateSectorPartition func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*lminer.SectorLocation, error) `perm:"read"` - StateSectorPreCommitInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorPreCommitOnChainInfo, error) `perm:"read"` + StateSectorPreCommitInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorPreCommitOnChainInfo, error) `perm:"read"` - StateVMCirculatingSupplyInternal func(p0 context.Context, p1 types.TipSetKey) (CirculatingSupply, error) `perm:"read"` + StateVMCirculatingSupplyInternal func(p0 context.Context, p1 types.TipSetKey) (CirculatingSupply, error) `perm:"read"` - StateVerifiedClientStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` + StateVerifiedClientStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` - StateVerifiedRegistryRootKey func(p0 context.Context, p1 types.TipSetKey) (address.Address, error) `perm:"read"` + StateVerifiedRegistryRootKey func(p0 context.Context, p1 types.TipSetKey) (address.Address, error) `perm:"read"` - StateVerifierStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` + StateVerifierStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` - StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `perm:"read"` + StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `perm:"read"` - SyncCheckBad func(p0 context.Context, p1 cid.Cid) (string, error) `perm:"read"` + SyncCheckBad func(p0 context.Context, p1 cid.Cid) (string, error) `perm:"read"` - SyncCheckpoint func(p0 context.Context, p1 types.TipSetKey) error `perm:"admin"` + SyncCheckpoint func(p0 context.Context, p1 types.TipSetKey) error `perm:"admin"` - SyncIncomingBlocks func(p0 context.Context) (<-chan *types.BlockHeader, error) `perm:"read"` + SyncIncomingBlocks func(p0 context.Context) (<-chan *types.BlockHeader, error) `perm:"read"` - SyncMarkBad func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` + SyncMarkBad func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` - SyncState func(p0 context.Context) (*SyncState, error) `perm:"read"` + SyncState func(p0 context.Context) (*SyncState, error) `perm:"read"` - SyncSubmitBlock func(p0 context.Context, p1 *types.BlockMsg) error `perm:"write"` + SyncSubmitBlock func(p0 context.Context, p1 *types.BlockMsg) error `perm:"write"` - SyncUnmarkAllBad func(p0 context.Context) error `perm:"admin"` + SyncUnmarkAllBad func(p0 context.Context) error `perm:"admin"` - SyncUnmarkBad func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` + SyncUnmarkBad func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` - SyncValidateTipset func(p0 context.Context, p1 types.TipSetKey) (bool, error) `perm:"read"` + SyncValidateTipset func(p0 context.Context, p1 types.TipSetKey) (bool, error) `perm:"read"` - WalletBalance func(p0 context.Context, p1 address.Address) (types.BigInt, error) `perm:"read"` + WalletBalance func(p0 context.Context, p1 address.Address) (types.BigInt, error) `perm:"read"` - WalletDefaultAddress func(p0 context.Context) (address.Address, error) `perm:"write"` + WalletDefaultAddress func(p0 context.Context) (address.Address, error) `perm:"write"` - WalletDelete func(p0 context.Context, p1 address.Address) error `perm:"admin"` + WalletDelete func(p0 context.Context, p1 address.Address) error `perm:"admin"` - WalletExport func(p0 context.Context, p1 address.Address) (*types.KeyInfo, error) `perm:"admin"` + WalletExport func(p0 context.Context, p1 address.Address) (*types.KeyInfo, error) `perm:"admin"` - WalletHas func(p0 context.Context, p1 address.Address) (bool, error) `perm:"write"` + WalletHas func(p0 context.Context, p1 address.Address) (bool, error) `perm:"write"` - WalletImport func(p0 context.Context, p1 *types.KeyInfo) (address.Address, error) `perm:"admin"` + WalletImport func(p0 context.Context, p1 *types.KeyInfo) (address.Address, error) `perm:"admin"` - WalletList func(p0 context.Context) ([]address.Address, error) `perm:"write"` + WalletList func(p0 context.Context) ([]address.Address, error) `perm:"write"` - WalletNew func(p0 context.Context, p1 types.KeyType) (address.Address, error) `perm:"write"` + WalletNew func(p0 context.Context, p1 types.KeyType) (address.Address, error) `perm:"write"` - WalletSetDefault func(p0 context.Context, p1 address.Address) error `perm:"write"` + WalletSetDefault func(p0 context.Context, p1 address.Address) error `perm:"write"` - WalletSign func(p0 context.Context, p1 address.Address, p2 []byte) (*crypto.Signature, error) `perm:"sign"` + WalletSign func(p0 context.Context, p1 address.Address, p2 []byte) (*crypto.Signature, error) `perm:"sign"` - WalletSignMessage func(p0 context.Context, p1 address.Address, p2 *types.Message) (*types.SignedMessage, error) `perm:"sign"` + WalletSignMessage func(p0 context.Context, p1 address.Address, p2 *types.Message) (*types.SignedMessage, error) `perm:"sign"` - WalletValidateAddress func(p0 context.Context, p1 string) (address.Address, error) `perm:"read"` + WalletValidateAddress func(p0 context.Context, p1 string) (address.Address, error) `perm:"read"` - WalletVerify func(p0 context.Context, p1 address.Address, p2 []byte, p3 *crypto.Signature) (bool, error) `perm:"read"` - } + WalletVerify func(p0 context.Context, p1 address.Address, p2 []byte, p3 *crypto.Signature) (bool, error) `perm:"read"` + + Web3ClientVersion func(p0 context.Context) (string, error) `perm:"read"` } type FullNodeStub struct { @@ -592,215 +614,227 @@ type FullNodeStub struct { } type GatewayStruct struct { - Internal struct { - ChainGetBlockMessages func(p0 context.Context, p1 cid.Cid) (*BlockMessages, error) `` + Internal GatewayMethods +} - ChainGetGenesis func(p0 context.Context) (*types.TipSet, error) `` +type GatewayMethods struct { + ChainGetBlockMessages func(p0 context.Context, p1 cid.Cid) (*BlockMessages, error) `` - ChainGetMessage func(p0 context.Context, p1 cid.Cid) (*types.Message, error) `` + ChainGetGenesis func(p0 context.Context) (*types.TipSet, error) `` - ChainGetParentMessages func(p0 context.Context, p1 cid.Cid) ([]Message, error) `` + ChainGetMessage func(p0 context.Context, p1 cid.Cid) (*types.Message, error) `` - ChainGetParentReceipts func(p0 context.Context, p1 cid.Cid) ([]*types.MessageReceipt, error) `` + ChainGetParentMessages func(p0 context.Context, p1 cid.Cid) ([]Message, error) `` - ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*HeadChange, error) `` + ChainGetParentReceipts func(p0 context.Context, p1 cid.Cid) ([]*types.MessageReceipt, error) `` - ChainGetTipSet func(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) `` + ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*HeadChange, error) `` - ChainGetTipSetAfterHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `` + ChainGetTipSet func(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) `` - ChainGetTipSetByHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `` + ChainGetTipSetAfterHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `` - ChainHasObj func(p0 context.Context, p1 cid.Cid) (bool, error) `` + ChainGetTipSetByHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `` - ChainHead func(p0 context.Context) (*types.TipSet, error) `` + ChainHasObj func(p0 context.Context, p1 cid.Cid) (bool, error) `` - ChainNotify func(p0 context.Context) (<-chan []*HeadChange, error) `` + ChainHead func(p0 context.Context) (*types.TipSet, error) `` - ChainPutObj func(p0 context.Context, p1 blocks.Block) error `` + ChainNotify func(p0 context.Context) (<-chan []*HeadChange, error) `` - ChainReadObj func(p0 context.Context, p1 cid.Cid) ([]byte, error) `` + ChainPutObj func(p0 context.Context, p1 blocks.Block) error `` - Discover func(p0 context.Context) (apitypes.OpenRPCDocument, error) `` + ChainReadObj func(p0 context.Context, p1 cid.Cid) ([]byte, error) `` - EthAccounts func(p0 context.Context) ([]ethtypes.EthAddress, error) `` + Discover func(p0 context.Context) (apitypes.OpenRPCDocument, error) `` - EthBlockNumber func(p0 context.Context) (ethtypes.EthUint64, error) `` + EthAccounts func(p0 context.Context) ([]ethtypes.EthAddress, error) `` - EthCall func(p0 context.Context, p1 ethtypes.EthCall, p2 string) (ethtypes.EthBytes, error) `` + EthBlockNumber func(p0 context.Context) (ethtypes.EthUint64, error) `` - EthChainId func(p0 context.Context) (ethtypes.EthUint64, error) `` + EthCall func(p0 context.Context, p1 ethtypes.EthCall, p2 string) (ethtypes.EthBytes, error) `` - EthEstimateGas func(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) `` + EthChainId func(p0 context.Context) (ethtypes.EthUint64, error) `` - EthFeeHistory func(p0 context.Context, p1 ethtypes.EthUint64, p2 string, p3 []float64) (ethtypes.EthFeeHistory, error) `` + EthEstimateGas func(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) `` - EthGasPrice func(p0 context.Context) (ethtypes.EthBigInt, error) `` + EthFeeHistory func(p0 context.Context, p1 ethtypes.EthUint64, p2 string, p3 []float64) (ethtypes.EthFeeHistory, error) `` - EthGetBalance func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBigInt, error) `` + EthGasPrice func(p0 context.Context) (ethtypes.EthBigInt, error) `` - EthGetBlockByHash func(p0 context.Context, p1 ethtypes.EthHash, p2 bool) (ethtypes.EthBlock, error) `` + EthGetBalance func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBigInt, error) `` - EthGetBlockByNumber func(p0 context.Context, p1 string, p2 bool) (ethtypes.EthBlock, error) `` + EthGetBlockByHash func(p0 context.Context, p1 ethtypes.EthHash, p2 bool) (ethtypes.EthBlock, error) `` - EthGetBlockTransactionCountByHash func(p0 context.Context, p1 ethtypes.EthHash) (ethtypes.EthUint64, error) `` + EthGetBlockByNumber func(p0 context.Context, p1 string, p2 bool) (ethtypes.EthBlock, error) `` - EthGetBlockTransactionCountByNumber func(p0 context.Context, p1 ethtypes.EthUint64) (ethtypes.EthUint64, error) `` + EthGetBlockTransactionCountByHash func(p0 context.Context, p1 ethtypes.EthHash) (ethtypes.EthUint64, error) `` - EthGetCode func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBytes, error) `` + EthGetBlockTransactionCountByNumber func(p0 context.Context, p1 ethtypes.EthUint64) (ethtypes.EthUint64, error) `` - EthGetFilterChanges func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) `` + EthGetCode func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBytes, error) `` - EthGetFilterLogs func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) `` + EthGetFilterChanges func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) `` - EthGetLogs func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) `` + EthGetFilterLogs func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) `` - EthGetStorageAt func(p0 context.Context, p1 ethtypes.EthAddress, p2 ethtypes.EthBytes, p3 string) (ethtypes.EthBytes, error) `` + EthGetLogs func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) `` - EthGetTransactionByBlockHashAndIndex func(p0 context.Context, p1 ethtypes.EthHash, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) `` + EthGetMessageCidByTransactionHash func(p0 context.Context, p1 *ethtypes.EthHash) (*cid.Cid, error) `` - EthGetTransactionByBlockNumberAndIndex func(p0 context.Context, p1 ethtypes.EthUint64, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) `` + EthGetStorageAt func(p0 context.Context, p1 ethtypes.EthAddress, p2 ethtypes.EthBytes, p3 string) (ethtypes.EthBytes, error) `` - EthGetTransactionByHash func(p0 context.Context, p1 *ethtypes.EthHash) (*ethtypes.EthTx, error) `` + EthGetTransactionByBlockHashAndIndex func(p0 context.Context, p1 ethtypes.EthHash, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) `` - EthGetTransactionCount func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthUint64, error) `` + EthGetTransactionByBlockNumberAndIndex func(p0 context.Context, p1 ethtypes.EthUint64, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) `` - EthGetTransactionReceipt func(p0 context.Context, p1 ethtypes.EthHash) (*EthTxReceipt, error) `` + EthGetTransactionByHash func(p0 context.Context, p1 *ethtypes.EthHash) (*ethtypes.EthTx, error) `` - EthMaxPriorityFeePerGas func(p0 context.Context) (ethtypes.EthBigInt, error) `` + EthGetTransactionCount func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthUint64, error) `` - EthNewBlockFilter func(p0 context.Context) (ethtypes.EthFilterID, error) `` + EthGetTransactionHashByCid func(p0 context.Context, p1 cid.Cid) (*ethtypes.EthHash, error) `` - EthNewFilter func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) `` + EthGetTransactionReceipt func(p0 context.Context, p1 ethtypes.EthHash) (*EthTxReceipt, error) `` - EthNewPendingTransactionFilter func(p0 context.Context) (ethtypes.EthFilterID, error) `` + EthMaxPriorityFeePerGas func(p0 context.Context) (ethtypes.EthBigInt, error) `` - EthProtocolVersion func(p0 context.Context) (ethtypes.EthUint64, error) `` + EthNewBlockFilter func(p0 context.Context) (ethtypes.EthFilterID, error) `` - EthSendRawTransaction func(p0 context.Context, p1 ethtypes.EthBytes) (ethtypes.EthHash, error) `` + EthNewFilter func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) `` - EthSubscribe func(p0 context.Context, p1 string, p2 *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) `` + EthNewPendingTransactionFilter func(p0 context.Context) (ethtypes.EthFilterID, error) `` - EthUninstallFilter func(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) `` + EthProtocolVersion func(p0 context.Context) (ethtypes.EthUint64, error) `` - EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) `` + EthSendRawTransaction func(p0 context.Context, p1 ethtypes.EthBytes) (ethtypes.EthHash, error) `` - GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) `` + EthSubscribe func(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) `` - MpoolPush func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `` + EthUninstallFilter func(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) `` - MsigGetAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `` + EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) `` - MsigGetPending func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*MsigTransaction, error) `` + GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) `` - MsigGetVested func(p0 context.Context, p1 address.Address, p2 types.TipSetKey, p3 types.TipSetKey) (types.BigInt, error) `` + MpoolPush func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `` - MsigGetVestingSchedule func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MsigVesting, error) `` + MsigGetAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `` - NetListening func(p0 context.Context) (bool, error) `` + MsigGetPending func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*MsigTransaction, error) `` - NetVersion func(p0 context.Context) (string, error) `` + MsigGetVested func(p0 context.Context, p1 address.Address, p2 types.TipSetKey, p3 types.TipSetKey) (types.BigInt, error) `` - StateAccountKey func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `` + MsigGetVestingSchedule func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MsigVesting, error) `` - StateDealProviderCollateralBounds func(p0 context.Context, p1 abi.PaddedPieceSize, p2 bool, p3 types.TipSetKey) (DealCollateralBounds, error) `` + NetListening func(p0 context.Context) (bool, error) `` - StateGetActor func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*types.Actor, error) `` + NetVersion func(p0 context.Context) (string, error) `` - StateListMiners func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `` + StateAccountKey func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `` - StateLookupID func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `` + StateDealProviderCollateralBounds func(p0 context.Context, p1 abi.PaddedPieceSize, p2 bool, p3 types.TipSetKey) (DealCollateralBounds, error) `` - StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MarketBalance, error) `` + StateGetActor func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*types.Actor, error) `` - StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*MarketDeal, error) `` + StateListMiners func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `` - StateMinerInfo func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MinerInfo, error) `` + StateLookupID func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `` - StateMinerPower func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*MinerPower, error) `` + StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MarketBalance, error) `` - StateMinerProvingDeadline func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*dline.Info, error) `` + StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*MarketDeal, error) `` - StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (apitypes.NetworkVersion, error) `` + StateMinerInfo func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MinerInfo, error) `` - StateReadState func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*ActorState, error) `perm:"read"` + StateMinerPower func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*MinerPower, error) `` - StateSearchMsg func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `` + StateMinerProvingDeadline func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*dline.Info, error) `` - StateSectorGetInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorOnChainInfo, error) `` + StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (apitypes.NetworkVersion, error) `` - StateVerifiedClientStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `` + StateReadState func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*ActorState, error) `perm:"read"` - StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `` + StateSearchMsg func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `` - Version func(p0 context.Context) (APIVersion, error) `` + StateSectorGetInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorOnChainInfo, error) `` - WalletBalance func(p0 context.Context, p1 address.Address) (types.BigInt, error) `` - } + StateVerifiedClientStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `` + + StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `` + + Version func(p0 context.Context) (APIVersion, error) `` + + WalletBalance func(p0 context.Context, p1 address.Address) (types.BigInt, error) `` + + Web3ClientVersion func(p0 context.Context) (string, error) `` } type GatewayStub struct { } type NetStruct struct { - Internal struct { - ID func(p0 context.Context) (peer.ID, error) `perm:"read"` + Internal NetMethods +} - NetAddrsListen func(p0 context.Context) (peer.AddrInfo, error) `perm:"read"` +type NetMethods struct { + ID func(p0 context.Context) (peer.ID, error) `perm:"read"` - NetAgentVersion func(p0 context.Context, p1 peer.ID) (string, error) `perm:"read"` + NetAddrsListen func(p0 context.Context) (peer.AddrInfo, error) `perm:"read"` - NetAutoNatStatus func(p0 context.Context) (NatInfo, error) `perm:"read"` + NetAgentVersion func(p0 context.Context, p1 peer.ID) (string, error) `perm:"read"` - NetBandwidthStats func(p0 context.Context) (metrics.Stats, error) `perm:"read"` + NetAutoNatStatus func(p0 context.Context) (NatInfo, error) `perm:"read"` - NetBandwidthStatsByPeer func(p0 context.Context) (map[string]metrics.Stats, error) `perm:"read"` + NetBandwidthStats func(p0 context.Context) (metrics.Stats, error) `perm:"read"` - NetBandwidthStatsByProtocol func(p0 context.Context) (map[protocol.ID]metrics.Stats, error) `perm:"read"` + NetBandwidthStatsByPeer func(p0 context.Context) (map[string]metrics.Stats, error) `perm:"read"` - NetBlockAdd func(p0 context.Context, p1 NetBlockList) error `perm:"admin"` + NetBandwidthStatsByProtocol func(p0 context.Context) (map[protocol.ID]metrics.Stats, error) `perm:"read"` - NetBlockList func(p0 context.Context) (NetBlockList, error) `perm:"read"` + NetBlockAdd func(p0 context.Context, p1 NetBlockList) error `perm:"admin"` - NetBlockRemove func(p0 context.Context, p1 NetBlockList) error `perm:"admin"` + NetBlockList func(p0 context.Context) (NetBlockList, error) `perm:"read"` - NetConnect func(p0 context.Context, p1 peer.AddrInfo) error `perm:"write"` + NetBlockRemove func(p0 context.Context, p1 NetBlockList) error `perm:"admin"` - NetConnectedness func(p0 context.Context, p1 peer.ID) (network.Connectedness, error) `perm:"read"` + NetConnect func(p0 context.Context, p1 peer.AddrInfo) error `perm:"write"` - NetDisconnect func(p0 context.Context, p1 peer.ID) error `perm:"write"` + NetConnectedness func(p0 context.Context, p1 peer.ID) (network.Connectedness, error) `perm:"read"` - NetFindPeer func(p0 context.Context, p1 peer.ID) (peer.AddrInfo, error) `perm:"read"` + NetDisconnect func(p0 context.Context, p1 peer.ID) error `perm:"write"` - NetLimit func(p0 context.Context, p1 string) (NetLimit, error) `perm:"read"` + NetFindPeer func(p0 context.Context, p1 peer.ID) (peer.AddrInfo, error) `perm:"read"` - NetPeerInfo func(p0 context.Context, p1 peer.ID) (*ExtendedPeerInfo, error) `perm:"read"` + NetLimit func(p0 context.Context, p1 string) (NetLimit, error) `perm:"read"` - NetPeers func(p0 context.Context) ([]peer.AddrInfo, error) `perm:"read"` + NetPeerInfo func(p0 context.Context, p1 peer.ID) (*ExtendedPeerInfo, error) `perm:"read"` - NetPing func(p0 context.Context, p1 peer.ID) (time.Duration, error) `perm:"read"` + NetPeers func(p0 context.Context) ([]peer.AddrInfo, error) `perm:"read"` - NetProtectAdd func(p0 context.Context, p1 []peer.ID) error `perm:"admin"` + NetPing func(p0 context.Context, p1 peer.ID) (time.Duration, error) `perm:"read"` - NetProtectList func(p0 context.Context) ([]peer.ID, error) `perm:"read"` + NetProtectAdd func(p0 context.Context, p1 []peer.ID) error `perm:"admin"` - NetProtectRemove func(p0 context.Context, p1 []peer.ID) error `perm:"admin"` + NetProtectList func(p0 context.Context) ([]peer.ID, error) `perm:"read"` - NetPubsubScores func(p0 context.Context) ([]PubsubScore, error) `perm:"read"` + NetProtectRemove func(p0 context.Context, p1 []peer.ID) error `perm:"admin"` - NetSetLimit func(p0 context.Context, p1 string, p2 NetLimit) error `perm:"admin"` + NetPubsubScores func(p0 context.Context) ([]PubsubScore, error) `perm:"read"` - NetStat func(p0 context.Context, p1 string) (NetStat, error) `perm:"read"` - } + NetSetLimit func(p0 context.Context, p1 string, p2 NetLimit) error `perm:"admin"` + + NetStat func(p0 context.Context, p1 string) (NetStat, error) `perm:"read"` } type NetStub struct { } type SignableStruct struct { - Internal struct { - Sign func(p0 context.Context, p1 SignFunc) error `` - } + Internal SignableMethods +} + +type SignableMethods struct { + Sign func(p0 context.Context, p1 SignFunc) error `` } type SignableStub struct { @@ -811,271 +845,273 @@ type StorageMinerStruct struct { NetStruct - Internal struct { - ActorAddress func(p0 context.Context) (address.Address, error) `perm:"read"` + Internal StorageMinerMethods +} - ActorAddressConfig func(p0 context.Context) (AddressConfig, error) `perm:"read"` +type StorageMinerMethods struct { + ActorAddress func(p0 context.Context) (address.Address, error) `perm:"read"` - ActorSectorSize func(p0 context.Context, p1 address.Address) (abi.SectorSize, error) `perm:"read"` + ActorAddressConfig func(p0 context.Context) (AddressConfig, error) `perm:"read"` - ActorWithdrawBalance func(p0 context.Context, p1 abi.TokenAmount) (cid.Cid, error) `perm:"admin"` + ActorSectorSize func(p0 context.Context, p1 address.Address) (abi.SectorSize, error) `perm:"read"` - BeneficiaryWithdrawBalance func(p0 context.Context, p1 abi.TokenAmount) (cid.Cid, error) `perm:"admin"` + ActorWithdrawBalance func(p0 context.Context, p1 abi.TokenAmount) (cid.Cid, error) `perm:"admin"` - CheckProvable func(p0 context.Context, p1 abi.RegisteredPoStProof, p2 []storiface.SectorRef) (map[abi.SectorNumber]string, error) `perm:"admin"` + BeneficiaryWithdrawBalance func(p0 context.Context, p1 abi.TokenAmount) (cid.Cid, error) `perm:"admin"` - ComputeDataCid func(p0 context.Context, p1 abi.UnpaddedPieceSize, p2 storiface.Data) (abi.PieceInfo, error) `perm:"admin"` + CheckProvable func(p0 context.Context, p1 abi.RegisteredPoStProof, p2 []storiface.SectorRef) (map[abi.SectorNumber]string, error) `perm:"admin"` - ComputeProof func(p0 context.Context, p1 []builtinactors.ExtendedSectorInfo, p2 abi.PoStRandomness, p3 abi.ChainEpoch, p4 abinetwork.Version) ([]builtinactors.PoStProof, error) `perm:"read"` + ComputeDataCid func(p0 context.Context, p1 abi.UnpaddedPieceSize, p2 storiface.Data) (abi.PieceInfo, error) `perm:"admin"` - ComputeWindowPoSt func(p0 context.Context, p1 uint64, p2 types.TipSetKey) ([]miner.SubmitWindowedPoStParams, error) `perm:"admin"` + ComputeProof func(p0 context.Context, p1 []builtinactors.ExtendedSectorInfo, p2 abi.PoStRandomness, p3 abi.ChainEpoch, p4 abinetwork.Version) ([]builtinactors.PoStProof, error) `perm:"read"` - CreateBackup func(p0 context.Context, p1 string) error `perm:"admin"` + ComputeWindowPoSt func(p0 context.Context, p1 uint64, p2 types.TipSetKey) ([]miner.SubmitWindowedPoStParams, error) `perm:"admin"` - DagstoreGC func(p0 context.Context) ([]DagstoreShardResult, error) `perm:"admin"` + CreateBackup func(p0 context.Context, p1 string) error `perm:"admin"` - DagstoreInitializeAll func(p0 context.Context, p1 DagstoreInitializeAllParams) (<-chan DagstoreInitializeAllEvent, error) `perm:"write"` + DagstoreGC func(p0 context.Context) ([]DagstoreShardResult, error) `perm:"admin"` - DagstoreInitializeShard func(p0 context.Context, p1 string) error `perm:"write"` + DagstoreInitializeAll func(p0 context.Context, p1 DagstoreInitializeAllParams) (<-chan DagstoreInitializeAllEvent, error) `perm:"write"` - DagstoreListShards func(p0 context.Context) ([]DagstoreShardInfo, error) `perm:"read"` + DagstoreInitializeShard func(p0 context.Context, p1 string) error `perm:"write"` - DagstoreLookupPieces func(p0 context.Context, p1 cid.Cid) ([]DagstoreShardInfo, error) `perm:"admin"` + DagstoreListShards func(p0 context.Context) ([]DagstoreShardInfo, error) `perm:"read"` - DagstoreRecoverShard func(p0 context.Context, p1 string) error `perm:"write"` + DagstoreLookupPieces func(p0 context.Context, p1 cid.Cid) ([]DagstoreShardInfo, error) `perm:"admin"` - DagstoreRegisterShard func(p0 context.Context, p1 string) error `perm:"admin"` + DagstoreRecoverShard func(p0 context.Context, p1 string) error `perm:"write"` - DealsConsiderOfflineRetrievalDeals func(p0 context.Context) (bool, error) `perm:"admin"` + DagstoreRegisterShard func(p0 context.Context, p1 string) error `perm:"admin"` - DealsConsiderOfflineStorageDeals func(p0 context.Context) (bool, error) `perm:"admin"` + DealsConsiderOfflineRetrievalDeals func(p0 context.Context) (bool, error) `perm:"admin"` - DealsConsiderOnlineRetrievalDeals func(p0 context.Context) (bool, error) `perm:"admin"` + DealsConsiderOfflineStorageDeals func(p0 context.Context) (bool, error) `perm:"admin"` - DealsConsiderOnlineStorageDeals func(p0 context.Context) (bool, error) `perm:"admin"` + DealsConsiderOnlineRetrievalDeals func(p0 context.Context) (bool, error) `perm:"admin"` - DealsConsiderUnverifiedStorageDeals func(p0 context.Context) (bool, error) `perm:"admin"` + DealsConsiderOnlineStorageDeals func(p0 context.Context) (bool, error) `perm:"admin"` - DealsConsiderVerifiedStorageDeals func(p0 context.Context) (bool, error) `perm:"admin"` + DealsConsiderUnverifiedStorageDeals func(p0 context.Context) (bool, error) `perm:"admin"` - DealsImportData func(p0 context.Context, p1 cid.Cid, p2 string) error `perm:"admin"` + DealsConsiderVerifiedStorageDeals func(p0 context.Context) (bool, error) `perm:"admin"` - DealsList func(p0 context.Context) ([]*MarketDeal, error) `perm:"admin"` + DealsImportData func(p0 context.Context, p1 cid.Cid, p2 string) error `perm:"admin"` - DealsPieceCidBlocklist func(p0 context.Context) ([]cid.Cid, error) `perm:"admin"` + DealsList func(p0 context.Context) ([]*MarketDeal, error) `perm:"admin"` - DealsSetConsiderOfflineRetrievalDeals func(p0 context.Context, p1 bool) error `perm:"admin"` + DealsPieceCidBlocklist func(p0 context.Context) ([]cid.Cid, error) `perm:"admin"` - DealsSetConsiderOfflineStorageDeals func(p0 context.Context, p1 bool) error `perm:"admin"` + DealsSetConsiderOfflineRetrievalDeals func(p0 context.Context, p1 bool) error `perm:"admin"` - DealsSetConsiderOnlineRetrievalDeals func(p0 context.Context, p1 bool) error `perm:"admin"` + DealsSetConsiderOfflineStorageDeals func(p0 context.Context, p1 bool) error `perm:"admin"` - DealsSetConsiderOnlineStorageDeals func(p0 context.Context, p1 bool) error `perm:"admin"` + DealsSetConsiderOnlineRetrievalDeals func(p0 context.Context, p1 bool) error `perm:"admin"` - DealsSetConsiderUnverifiedStorageDeals func(p0 context.Context, p1 bool) error `perm:"admin"` + DealsSetConsiderOnlineStorageDeals func(p0 context.Context, p1 bool) error `perm:"admin"` - DealsSetConsiderVerifiedStorageDeals func(p0 context.Context, p1 bool) error `perm:"admin"` + DealsSetConsiderUnverifiedStorageDeals func(p0 context.Context, p1 bool) error `perm:"admin"` - DealsSetPieceCidBlocklist func(p0 context.Context, p1 []cid.Cid) error `perm:"admin"` + DealsSetConsiderVerifiedStorageDeals func(p0 context.Context, p1 bool) error `perm:"admin"` - IndexerAnnounceAllDeals func(p0 context.Context) error `perm:"admin"` + DealsSetPieceCidBlocklist func(p0 context.Context, p1 []cid.Cid) error `perm:"admin"` - IndexerAnnounceDeal func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` + IndexerAnnounceAllDeals func(p0 context.Context) error `perm:"admin"` - MarketCancelDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` + IndexerAnnounceDeal func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` - MarketDataTransferDiagnostics func(p0 context.Context, p1 peer.ID) (*TransferDiagnostics, error) `perm:"write"` + MarketCancelDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` - MarketDataTransferUpdates func(p0 context.Context) (<-chan DataTransferChannel, error) `perm:"write"` + MarketDataTransferDiagnostics func(p0 context.Context, p1 peer.ID) (*TransferDiagnostics, error) `perm:"write"` - MarketGetAsk func(p0 context.Context) (*storagemarket.SignedStorageAsk, error) `perm:"read"` + MarketDataTransferUpdates func(p0 context.Context) (<-chan DataTransferChannel, error) `perm:"write"` - MarketGetDealUpdates func(p0 context.Context) (<-chan storagemarket.MinerDeal, error) `perm:"read"` + MarketGetAsk func(p0 context.Context) (*storagemarket.SignedStorageAsk, error) `perm:"read"` - MarketGetRetrievalAsk func(p0 context.Context) (*retrievalmarket.Ask, error) `perm:"read"` + MarketGetDealUpdates func(p0 context.Context) (<-chan storagemarket.MinerDeal, error) `perm:"read"` - MarketImportDealData func(p0 context.Context, p1 cid.Cid, p2 string) error `perm:"write"` + MarketGetRetrievalAsk func(p0 context.Context) (*retrievalmarket.Ask, error) `perm:"read"` - MarketListDataTransfers func(p0 context.Context) ([]DataTransferChannel, error) `perm:"write"` + MarketImportDealData func(p0 context.Context, p1 cid.Cid, p2 string) error `perm:"write"` - MarketListDeals func(p0 context.Context) ([]*MarketDeal, error) `perm:"read"` + MarketListDataTransfers func(p0 context.Context) ([]DataTransferChannel, error) `perm:"write"` - MarketListIncompleteDeals func(p0 context.Context) ([]storagemarket.MinerDeal, error) `perm:"read"` + MarketListDeals func(p0 context.Context) ([]*MarketDeal, error) `perm:"read"` - MarketListRetrievalDeals func(p0 context.Context) ([]retrievalmarket.ProviderDealState, error) `perm:"read"` + MarketListIncompleteDeals func(p0 context.Context) ([]storagemarket.MinerDeal, error) `perm:"read"` - MarketPendingDeals func(p0 context.Context) (PendingDealInfo, error) `perm:"write"` + MarketListRetrievalDeals func(p0 context.Context) ([]retrievalmarket.ProviderDealState, error) `perm:"read"` - MarketPublishPendingDeals func(p0 context.Context) error `perm:"admin"` + MarketPendingDeals func(p0 context.Context) (PendingDealInfo, error) `perm:"write"` - MarketRestartDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` + MarketPublishPendingDeals func(p0 context.Context) error `perm:"admin"` - MarketRetryPublishDeal func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` + MarketRestartDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` - MarketSetAsk func(p0 context.Context, p1 types.BigInt, p2 types.BigInt, p3 abi.ChainEpoch, p4 abi.PaddedPieceSize, p5 abi.PaddedPieceSize) error `perm:"admin"` + MarketRetryPublishDeal func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` - MarketSetRetrievalAsk func(p0 context.Context, p1 *retrievalmarket.Ask) error `perm:"admin"` + MarketSetAsk func(p0 context.Context, p1 types.BigInt, p2 types.BigInt, p3 abi.ChainEpoch, p4 abi.PaddedPieceSize, p5 abi.PaddedPieceSize) error `perm:"admin"` - MiningBase func(p0 context.Context) (*types.TipSet, error) `perm:"read"` + MarketSetRetrievalAsk func(p0 context.Context, p1 *retrievalmarket.Ask) error `perm:"admin"` - PiecesGetCIDInfo func(p0 context.Context, p1 cid.Cid) (*piecestore.CIDInfo, error) `perm:"read"` + MiningBase func(p0 context.Context) (*types.TipSet, error) `perm:"read"` - PiecesGetPieceInfo func(p0 context.Context, p1 cid.Cid) (*piecestore.PieceInfo, error) `perm:"read"` + PiecesGetCIDInfo func(p0 context.Context, p1 cid.Cid) (*piecestore.CIDInfo, error) `perm:"read"` - PiecesListCidInfos func(p0 context.Context) ([]cid.Cid, error) `perm:"read"` + PiecesGetPieceInfo func(p0 context.Context, p1 cid.Cid) (*piecestore.PieceInfo, error) `perm:"read"` - PiecesListPieces func(p0 context.Context) ([]cid.Cid, error) `perm:"read"` + PiecesListCidInfos func(p0 context.Context) ([]cid.Cid, error) `perm:"read"` - PledgeSector func(p0 context.Context) (abi.SectorID, error) `perm:"write"` + PiecesListPieces func(p0 context.Context) ([]cid.Cid, error) `perm:"read"` - RecoverFault func(p0 context.Context, p1 []abi.SectorNumber) ([]cid.Cid, error) `perm:"admin"` + PledgeSector func(p0 context.Context) (abi.SectorID, error) `perm:"write"` - ReturnAddPiece func(p0 context.Context, p1 storiface.CallID, p2 abi.PieceInfo, p3 *storiface.CallError) error `perm:"admin"` + RecoverFault func(p0 context.Context, p1 []abi.SectorNumber) ([]cid.Cid, error) `perm:"admin"` - ReturnDataCid func(p0 context.Context, p1 storiface.CallID, p2 abi.PieceInfo, p3 *storiface.CallError) error `perm:"admin"` + ReturnAddPiece func(p0 context.Context, p1 storiface.CallID, p2 abi.PieceInfo, p3 *storiface.CallError) error `perm:"admin"` - ReturnDownloadSector func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` + ReturnDataCid func(p0 context.Context, p1 storiface.CallID, p2 abi.PieceInfo, p3 *storiface.CallError) error `perm:"admin"` - ReturnFetch func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` + ReturnDownloadSector func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` - ReturnFinalizeReplicaUpdate func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` + ReturnFetch func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` - ReturnFinalizeSector func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` + ReturnFinalizeReplicaUpdate func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` - ReturnGenerateSectorKeyFromData func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` + ReturnFinalizeSector func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` - ReturnMoveStorage func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` + ReturnGenerateSectorKeyFromData func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` - ReturnProveReplicaUpdate1 func(p0 context.Context, p1 storiface.CallID, p2 storiface.ReplicaVanillaProofs, p3 *storiface.CallError) error `perm:"admin"` + ReturnMoveStorage func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` - ReturnProveReplicaUpdate2 func(p0 context.Context, p1 storiface.CallID, p2 storiface.ReplicaUpdateProof, p3 *storiface.CallError) error `perm:"admin"` + ReturnProveReplicaUpdate1 func(p0 context.Context, p1 storiface.CallID, p2 storiface.ReplicaVanillaProofs, p3 *storiface.CallError) error `perm:"admin"` - ReturnReadPiece func(p0 context.Context, p1 storiface.CallID, p2 bool, p3 *storiface.CallError) error `perm:"admin"` + ReturnProveReplicaUpdate2 func(p0 context.Context, p1 storiface.CallID, p2 storiface.ReplicaUpdateProof, p3 *storiface.CallError) error `perm:"admin"` - ReturnReleaseUnsealed func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` + ReturnReadPiece func(p0 context.Context, p1 storiface.CallID, p2 bool, p3 *storiface.CallError) error `perm:"admin"` - ReturnReplicaUpdate func(p0 context.Context, p1 storiface.CallID, p2 storiface.ReplicaUpdateOut, p3 *storiface.CallError) error `perm:"admin"` + ReturnReleaseUnsealed func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` - ReturnSealCommit1 func(p0 context.Context, p1 storiface.CallID, p2 storiface.Commit1Out, p3 *storiface.CallError) error `perm:"admin"` + ReturnReplicaUpdate func(p0 context.Context, p1 storiface.CallID, p2 storiface.ReplicaUpdateOut, p3 *storiface.CallError) error `perm:"admin"` - ReturnSealCommit2 func(p0 context.Context, p1 storiface.CallID, p2 storiface.Proof, p3 *storiface.CallError) error `perm:"admin"` + ReturnSealCommit1 func(p0 context.Context, p1 storiface.CallID, p2 storiface.Commit1Out, p3 *storiface.CallError) error `perm:"admin"` - ReturnSealPreCommit1 func(p0 context.Context, p1 storiface.CallID, p2 storiface.PreCommit1Out, p3 *storiface.CallError) error `perm:"admin"` + ReturnSealCommit2 func(p0 context.Context, p1 storiface.CallID, p2 storiface.Proof, p3 *storiface.CallError) error `perm:"admin"` - ReturnSealPreCommit2 func(p0 context.Context, p1 storiface.CallID, p2 storiface.SectorCids, p3 *storiface.CallError) error `perm:"admin"` + ReturnSealPreCommit1 func(p0 context.Context, p1 storiface.CallID, p2 storiface.PreCommit1Out, p3 *storiface.CallError) error `perm:"admin"` - ReturnUnsealPiece func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` + ReturnSealPreCommit2 func(p0 context.Context, p1 storiface.CallID, p2 storiface.SectorCids, p3 *storiface.CallError) error `perm:"admin"` - RuntimeSubsystems func(p0 context.Context) (MinerSubsystems, error) `perm:"read"` + ReturnUnsealPiece func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` - SealingAbort func(p0 context.Context, p1 storiface.CallID) error `perm:"admin"` + RuntimeSubsystems func(p0 context.Context) (MinerSubsystems, error) `perm:"read"` - SealingRemoveRequest func(p0 context.Context, p1 uuid.UUID) error `perm:"admin"` + SealingAbort func(p0 context.Context, p1 storiface.CallID) error `perm:"admin"` - SealingSchedDiag func(p0 context.Context, p1 bool) (interface{}, error) `perm:"admin"` + SealingRemoveRequest func(p0 context.Context, p1 uuid.UUID) error `perm:"admin"` - SectorAbortUpgrade func(p0 context.Context, p1 abi.SectorNumber) error `perm:"admin"` + SealingSchedDiag func(p0 context.Context, p1 bool) (interface{}, error) `perm:"admin"` - SectorAddPieceToAny func(p0 context.Context, p1 abi.UnpaddedPieceSize, p2 storiface.Data, p3 PieceDealInfo) (SectorOffset, error) `perm:"admin"` + SectorAbortUpgrade func(p0 context.Context, p1 abi.SectorNumber) error `perm:"admin"` - SectorCommitFlush func(p0 context.Context) ([]sealiface.CommitBatchRes, error) `perm:"admin"` + SectorAddPieceToAny func(p0 context.Context, p1 abi.UnpaddedPieceSize, p2 storiface.Data, p3 PieceDealInfo) (SectorOffset, error) `perm:"admin"` - SectorCommitPending func(p0 context.Context) ([]abi.SectorID, error) `perm:"admin"` + SectorCommitFlush func(p0 context.Context) ([]sealiface.CommitBatchRes, error) `perm:"admin"` - SectorGetExpectedSealDuration func(p0 context.Context) (time.Duration, error) `perm:"read"` + SectorCommitPending func(p0 context.Context) ([]abi.SectorID, error) `perm:"admin"` - SectorGetSealDelay func(p0 context.Context) (time.Duration, error) `perm:"read"` + SectorGetExpectedSealDuration func(p0 context.Context) (time.Duration, error) `perm:"read"` - SectorMarkForUpgrade func(p0 context.Context, p1 abi.SectorNumber, p2 bool) error `perm:"admin"` + SectorGetSealDelay func(p0 context.Context) (time.Duration, error) `perm:"read"` - SectorMatchPendingPiecesToOpenSectors func(p0 context.Context) error `perm:"admin"` + SectorMarkForUpgrade func(p0 context.Context, p1 abi.SectorNumber, p2 bool) error `perm:"admin"` - SectorNumAssignerMeta func(p0 context.Context) (NumAssignerMeta, error) `perm:"read"` + SectorMatchPendingPiecesToOpenSectors func(p0 context.Context) error `perm:"admin"` - SectorNumFree func(p0 context.Context, p1 string) error `perm:"admin"` + SectorNumAssignerMeta func(p0 context.Context) (NumAssignerMeta, error) `perm:"read"` - SectorNumReservations func(p0 context.Context) (map[string]bitfield.BitField, error) `perm:"read"` + SectorNumFree func(p0 context.Context, p1 string) error `perm:"admin"` - SectorNumReserve func(p0 context.Context, p1 string, p2 bitfield.BitField, p3 bool) error `perm:"admin"` + SectorNumReservations func(p0 context.Context) (map[string]bitfield.BitField, error) `perm:"read"` - SectorNumReserveCount func(p0 context.Context, p1 string, p2 uint64) (bitfield.BitField, error) `perm:"admin"` + SectorNumReserve func(p0 context.Context, p1 string, p2 bitfield.BitField, p3 bool) error `perm:"admin"` - SectorPreCommitFlush func(p0 context.Context) ([]sealiface.PreCommitBatchRes, error) `perm:"admin"` + SectorNumReserveCount func(p0 context.Context, p1 string, p2 uint64) (bitfield.BitField, error) `perm:"admin"` - SectorPreCommitPending func(p0 context.Context) ([]abi.SectorID, error) `perm:"admin"` + SectorPreCommitFlush func(p0 context.Context) ([]sealiface.PreCommitBatchRes, error) `perm:"admin"` - SectorReceive func(p0 context.Context, p1 RemoteSectorMeta) error `perm:"admin"` + SectorPreCommitPending func(p0 context.Context) ([]abi.SectorID, error) `perm:"admin"` - SectorRemove func(p0 context.Context, p1 abi.SectorNumber) error `perm:"admin"` + SectorReceive func(p0 context.Context, p1 RemoteSectorMeta) error `perm:"admin"` - SectorSetExpectedSealDuration func(p0 context.Context, p1 time.Duration) error `perm:"write"` + SectorRemove func(p0 context.Context, p1 abi.SectorNumber) error `perm:"admin"` - SectorSetSealDelay func(p0 context.Context, p1 time.Duration) error `perm:"write"` + SectorSetExpectedSealDuration func(p0 context.Context, p1 time.Duration) error `perm:"write"` - SectorStartSealing func(p0 context.Context, p1 abi.SectorNumber) error `perm:"write"` + SectorSetSealDelay func(p0 context.Context, p1 time.Duration) error `perm:"write"` - SectorTerminate func(p0 context.Context, p1 abi.SectorNumber) error `perm:"admin"` + SectorStartSealing func(p0 context.Context, p1 abi.SectorNumber) error `perm:"write"` - SectorTerminateFlush func(p0 context.Context) (*cid.Cid, error) `perm:"admin"` + SectorTerminate func(p0 context.Context, p1 abi.SectorNumber) error `perm:"admin"` - SectorTerminatePending func(p0 context.Context) ([]abi.SectorID, error) `perm:"admin"` + SectorTerminateFlush func(p0 context.Context) (*cid.Cid, error) `perm:"admin"` - SectorsList func(p0 context.Context) ([]abi.SectorNumber, error) `perm:"read"` + SectorTerminatePending func(p0 context.Context) ([]abi.SectorID, error) `perm:"admin"` - SectorsListInStates func(p0 context.Context, p1 []SectorState) ([]abi.SectorNumber, error) `perm:"read"` + SectorsList func(p0 context.Context) ([]abi.SectorNumber, error) `perm:"read"` - SectorsRefs func(p0 context.Context) (map[string][]SealedRef, error) `perm:"read"` + SectorsListInStates func(p0 context.Context, p1 []SectorState) ([]abi.SectorNumber, error) `perm:"read"` - SectorsStatus func(p0 context.Context, p1 abi.SectorNumber, p2 bool) (SectorInfo, error) `perm:"read"` + SectorsRefs func(p0 context.Context) (map[string][]SealedRef, error) `perm:"read"` - SectorsSummary func(p0 context.Context) (map[SectorState]int, error) `perm:"read"` + SectorsStatus func(p0 context.Context, p1 abi.SectorNumber, p2 bool) (SectorInfo, error) `perm:"read"` - SectorsUnsealPiece func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.UnpaddedByteIndex, p3 abi.UnpaddedPieceSize, p4 abi.SealRandomness, p5 *cid.Cid) error `perm:"admin"` + SectorsSummary func(p0 context.Context) (map[SectorState]int, error) `perm:"read"` - SectorsUpdate func(p0 context.Context, p1 abi.SectorNumber, p2 SectorState) error `perm:"admin"` + SectorsUnsealPiece func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.UnpaddedByteIndex, p3 abi.UnpaddedPieceSize, p4 abi.SealRandomness, p5 *cid.Cid) error `perm:"admin"` - StorageAddLocal func(p0 context.Context, p1 string) error `perm:"admin"` + SectorsUpdate func(p0 context.Context, p1 abi.SectorNumber, p2 SectorState) error `perm:"admin"` - StorageAttach func(p0 context.Context, p1 storiface.StorageInfo, p2 fsutil.FsStat) error `perm:"admin"` + StorageAddLocal func(p0 context.Context, p1 string) error `perm:"admin"` - StorageAuthVerify func(p0 context.Context, p1 string) ([]auth.Permission, error) `perm:"read"` + StorageAttach func(p0 context.Context, p1 storiface.StorageInfo, p2 fsutil.FsStat) error `perm:"admin"` - StorageBestAlloc func(p0 context.Context, p1 storiface.SectorFileType, p2 abi.SectorSize, p3 storiface.PathType) ([]storiface.StorageInfo, error) `perm:"admin"` + StorageAuthVerify func(p0 context.Context, p1 string) ([]auth.Permission, error) `perm:"read"` - StorageDeclareSector func(p0 context.Context, p1 storiface.ID, p2 abi.SectorID, p3 storiface.SectorFileType, p4 bool) error `perm:"admin"` + StorageBestAlloc func(p0 context.Context, p1 storiface.SectorFileType, p2 abi.SectorSize, p3 storiface.PathType) ([]storiface.StorageInfo, error) `perm:"admin"` - StorageDetach func(p0 context.Context, p1 storiface.ID, p2 string) error `perm:"admin"` + StorageDeclareSector func(p0 context.Context, p1 storiface.ID, p2 abi.SectorID, p3 storiface.SectorFileType, p4 bool) error `perm:"admin"` - StorageDetachLocal func(p0 context.Context, p1 string) error `perm:"admin"` + StorageDetach func(p0 context.Context, p1 storiface.ID, p2 string) error `perm:"admin"` - StorageDropSector func(p0 context.Context, p1 storiface.ID, p2 abi.SectorID, p3 storiface.SectorFileType) error `perm:"admin"` + StorageDetachLocal func(p0 context.Context, p1 string) error `perm:"admin"` - StorageFindSector func(p0 context.Context, p1 abi.SectorID, p2 storiface.SectorFileType, p3 abi.SectorSize, p4 bool) ([]storiface.SectorStorageInfo, error) `perm:"admin"` + StorageDropSector func(p0 context.Context, p1 storiface.ID, p2 abi.SectorID, p3 storiface.SectorFileType) error `perm:"admin"` - StorageGetLocks func(p0 context.Context) (storiface.SectorLocks, error) `perm:"admin"` + StorageFindSector func(p0 context.Context, p1 abi.SectorID, p2 storiface.SectorFileType, p3 abi.SectorSize, p4 bool) ([]storiface.SectorStorageInfo, error) `perm:"admin"` - StorageInfo func(p0 context.Context, p1 storiface.ID) (storiface.StorageInfo, error) `perm:"admin"` + StorageGetLocks func(p0 context.Context) (storiface.SectorLocks, error) `perm:"admin"` - StorageList func(p0 context.Context) (map[storiface.ID][]storiface.Decl, error) `perm:"admin"` + StorageInfo func(p0 context.Context, p1 storiface.ID) (storiface.StorageInfo, error) `perm:"admin"` - StorageLocal func(p0 context.Context) (map[storiface.ID]string, error) `perm:"admin"` + StorageList func(p0 context.Context) (map[storiface.ID][]storiface.Decl, error) `perm:"admin"` - StorageLock func(p0 context.Context, p1 abi.SectorID, p2 storiface.SectorFileType, p3 storiface.SectorFileType) error `perm:"admin"` + StorageLocal func(p0 context.Context) (map[storiface.ID]string, error) `perm:"admin"` - StorageRedeclareLocal func(p0 context.Context, p1 *storiface.ID, p2 bool) error `perm:"admin"` + StorageLock func(p0 context.Context, p1 abi.SectorID, p2 storiface.SectorFileType, p3 storiface.SectorFileType) error `perm:"admin"` - StorageReportHealth func(p0 context.Context, p1 storiface.ID, p2 storiface.HealthReport) error `perm:"admin"` + StorageRedeclareLocal func(p0 context.Context, p1 *storiface.ID, p2 bool) error `perm:"admin"` - StorageStat func(p0 context.Context, p1 storiface.ID) (fsutil.FsStat, error) `perm:"admin"` + StorageReportHealth func(p0 context.Context, p1 storiface.ID, p2 storiface.HealthReport) error `perm:"admin"` - StorageTryLock func(p0 context.Context, p1 abi.SectorID, p2 storiface.SectorFileType, p3 storiface.SectorFileType) (bool, error) `perm:"admin"` + StorageStat func(p0 context.Context, p1 storiface.ID) (fsutil.FsStat, error) `perm:"admin"` - WorkerConnect func(p0 context.Context, p1 string) error `perm:"admin"` + StorageTryLock func(p0 context.Context, p1 abi.SectorID, p2 storiface.SectorFileType, p3 storiface.SectorFileType) (bool, error) `perm:"admin"` - WorkerJobs func(p0 context.Context) (map[uuid.UUID][]storiface.WorkerJob, error) `perm:"admin"` + WorkerConnect func(p0 context.Context, p1 string) error `perm:"admin"` - WorkerStats func(p0 context.Context) (map[uuid.UUID]storiface.WorkerStats, error) `perm:"admin"` - } + WorkerJobs func(p0 context.Context) (map[uuid.UUID][]storiface.WorkerJob, error) `perm:"admin"` + + WorkerStats func(p0 context.Context) (map[uuid.UUID]storiface.WorkerStats, error) `perm:"admin"` } type StorageMinerStub struct { @@ -1085,102 +1121,106 @@ type StorageMinerStub struct { } type WalletStruct struct { - Internal struct { - WalletDelete func(p0 context.Context, p1 address.Address) error `perm:"admin"` + Internal WalletMethods +} - WalletExport func(p0 context.Context, p1 address.Address) (*types.KeyInfo, error) `perm:"admin"` +type WalletMethods struct { + WalletDelete func(p0 context.Context, p1 address.Address) error `perm:"admin"` - WalletHas func(p0 context.Context, p1 address.Address) (bool, error) `perm:"admin"` + WalletExport func(p0 context.Context, p1 address.Address) (*types.KeyInfo, error) `perm:"admin"` - WalletImport func(p0 context.Context, p1 *types.KeyInfo) (address.Address, error) `perm:"admin"` + WalletHas func(p0 context.Context, p1 address.Address) (bool, error) `perm:"admin"` - WalletList func(p0 context.Context) ([]address.Address, error) `perm:"admin"` + WalletImport func(p0 context.Context, p1 *types.KeyInfo) (address.Address, error) `perm:"admin"` - WalletNew func(p0 context.Context, p1 types.KeyType) (address.Address, error) `perm:"admin"` + WalletList func(p0 context.Context) ([]address.Address, error) `perm:"admin"` - WalletSign func(p0 context.Context, p1 address.Address, p2 []byte, p3 MsgMeta) (*crypto.Signature, error) `perm:"admin"` - } + WalletNew func(p0 context.Context, p1 types.KeyType) (address.Address, error) `perm:"admin"` + + WalletSign func(p0 context.Context, p1 address.Address, p2 []byte, p3 MsgMeta) (*crypto.Signature, error) `perm:"admin"` } type WalletStub struct { } type WorkerStruct struct { - Internal struct { - AddPiece func(p0 context.Context, p1 storiface.SectorRef, p2 []abi.UnpaddedPieceSize, p3 abi.UnpaddedPieceSize, p4 storiface.Data) (storiface.CallID, error) `perm:"admin"` + Internal WorkerMethods +} - DataCid func(p0 context.Context, p1 abi.UnpaddedPieceSize, p2 storiface.Data) (storiface.CallID, error) `perm:"admin"` +type WorkerMethods struct { + AddPiece func(p0 context.Context, p1 storiface.SectorRef, p2 []abi.UnpaddedPieceSize, p3 abi.UnpaddedPieceSize, p4 storiface.Data) (storiface.CallID, error) `perm:"admin"` - DownloadSectorData func(p0 context.Context, p1 storiface.SectorRef, p2 bool, p3 map[storiface.SectorFileType]storiface.SectorLocation) (storiface.CallID, error) `perm:"admin"` + DataCid func(p0 context.Context, p1 abi.UnpaddedPieceSize, p2 storiface.Data) (storiface.CallID, error) `perm:"admin"` - Enabled func(p0 context.Context) (bool, error) `perm:"admin"` + DownloadSectorData func(p0 context.Context, p1 storiface.SectorRef, p2 bool, p3 map[storiface.SectorFileType]storiface.SectorLocation) (storiface.CallID, error) `perm:"admin"` - Fetch func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.SectorFileType, p3 storiface.PathType, p4 storiface.AcquireMode) (storiface.CallID, error) `perm:"admin"` + Enabled func(p0 context.Context) (bool, error) `perm:"admin"` - FinalizeReplicaUpdate func(p0 context.Context, p1 storiface.SectorRef) (storiface.CallID, error) `perm:"admin"` + Fetch func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.SectorFileType, p3 storiface.PathType, p4 storiface.AcquireMode) (storiface.CallID, error) `perm:"admin"` - FinalizeSector func(p0 context.Context, p1 storiface.SectorRef) (storiface.CallID, error) `perm:"admin"` + FinalizeReplicaUpdate func(p0 context.Context, p1 storiface.SectorRef) (storiface.CallID, error) `perm:"admin"` - GenerateSectorKeyFromData func(p0 context.Context, p1 storiface.SectorRef, p2 cid.Cid) (storiface.CallID, error) `perm:"admin"` + FinalizeSector func(p0 context.Context, p1 storiface.SectorRef) (storiface.CallID, error) `perm:"admin"` - GenerateWindowPoSt func(p0 context.Context, p1 abi.RegisteredPoStProof, p2 abi.ActorID, p3 []storiface.PostSectorChallenge, p4 int, p5 abi.PoStRandomness) (storiface.WindowPoStResult, error) `perm:"admin"` + GenerateSectorKeyFromData func(p0 context.Context, p1 storiface.SectorRef, p2 cid.Cid) (storiface.CallID, error) `perm:"admin"` - GenerateWinningPoSt func(p0 context.Context, p1 abi.RegisteredPoStProof, p2 abi.ActorID, p3 []storiface.PostSectorChallenge, p4 abi.PoStRandomness) ([]proof.PoStProof, error) `perm:"admin"` + GenerateWindowPoSt func(p0 context.Context, p1 abi.RegisteredPoStProof, p2 abi.ActorID, p3 []storiface.PostSectorChallenge, p4 int, p5 abi.PoStRandomness) (storiface.WindowPoStResult, error) `perm:"admin"` - Info func(p0 context.Context) (storiface.WorkerInfo, error) `perm:"admin"` + GenerateWinningPoSt func(p0 context.Context, p1 abi.RegisteredPoStProof, p2 abi.ActorID, p3 []storiface.PostSectorChallenge, p4 abi.PoStRandomness) ([]proof.PoStProof, error) `perm:"admin"` - MoveStorage func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.SectorFileType) (storiface.CallID, error) `perm:"admin"` + Info func(p0 context.Context) (storiface.WorkerInfo, error) `perm:"admin"` - Paths func(p0 context.Context) ([]storiface.StoragePath, error) `perm:"admin"` + MoveStorage func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.SectorFileType) (storiface.CallID, error) `perm:"admin"` - ProcessSession func(p0 context.Context) (uuid.UUID, error) `perm:"admin"` + Paths func(p0 context.Context) ([]storiface.StoragePath, error) `perm:"admin"` - ProveReplicaUpdate1 func(p0 context.Context, p1 storiface.SectorRef, p2 cid.Cid, p3 cid.Cid, p4 cid.Cid) (storiface.CallID, error) `perm:"admin"` + ProcessSession func(p0 context.Context) (uuid.UUID, error) `perm:"admin"` - ProveReplicaUpdate2 func(p0 context.Context, p1 storiface.SectorRef, p2 cid.Cid, p3 cid.Cid, p4 cid.Cid, p5 storiface.ReplicaVanillaProofs) (storiface.CallID, error) `perm:"admin"` + ProveReplicaUpdate1 func(p0 context.Context, p1 storiface.SectorRef, p2 cid.Cid, p3 cid.Cid, p4 cid.Cid) (storiface.CallID, error) `perm:"admin"` - ReleaseUnsealed func(p0 context.Context, p1 storiface.SectorRef, p2 []storiface.Range) (storiface.CallID, error) `perm:"admin"` + ProveReplicaUpdate2 func(p0 context.Context, p1 storiface.SectorRef, p2 cid.Cid, p3 cid.Cid, p4 cid.Cid, p5 storiface.ReplicaVanillaProofs) (storiface.CallID, error) `perm:"admin"` - Remove func(p0 context.Context, p1 abi.SectorID) error `perm:"admin"` + ReleaseUnsealed func(p0 context.Context, p1 storiface.SectorRef, p2 []storiface.Range) (storiface.CallID, error) `perm:"admin"` - ReplicaUpdate func(p0 context.Context, p1 storiface.SectorRef, p2 []abi.PieceInfo) (storiface.CallID, error) `perm:"admin"` + Remove func(p0 context.Context, p1 abi.SectorID) error `perm:"admin"` - SealCommit1 func(p0 context.Context, p1 storiface.SectorRef, p2 abi.SealRandomness, p3 abi.InteractiveSealRandomness, p4 []abi.PieceInfo, p5 storiface.SectorCids) (storiface.CallID, error) `perm:"admin"` + ReplicaUpdate func(p0 context.Context, p1 storiface.SectorRef, p2 []abi.PieceInfo) (storiface.CallID, error) `perm:"admin"` - SealCommit2 func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.Commit1Out) (storiface.CallID, error) `perm:"admin"` + SealCommit1 func(p0 context.Context, p1 storiface.SectorRef, p2 abi.SealRandomness, p3 abi.InteractiveSealRandomness, p4 []abi.PieceInfo, p5 storiface.SectorCids) (storiface.CallID, error) `perm:"admin"` - SealPreCommit1 func(p0 context.Context, p1 storiface.SectorRef, p2 abi.SealRandomness, p3 []abi.PieceInfo) (storiface.CallID, error) `perm:"admin"` + SealCommit2 func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.Commit1Out) (storiface.CallID, error) `perm:"admin"` - SealPreCommit2 func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.PreCommit1Out) (storiface.CallID, error) `perm:"admin"` + SealPreCommit1 func(p0 context.Context, p1 storiface.SectorRef, p2 abi.SealRandomness, p3 []abi.PieceInfo) (storiface.CallID, error) `perm:"admin"` - Session func(p0 context.Context) (uuid.UUID, error) `perm:"admin"` + SealPreCommit2 func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.PreCommit1Out) (storiface.CallID, error) `perm:"admin"` - SetEnabled func(p0 context.Context, p1 bool) error `perm:"admin"` + Session func(p0 context.Context) (uuid.UUID, error) `perm:"admin"` - Shutdown func(p0 context.Context) error `perm:"admin"` + SetEnabled func(p0 context.Context, p1 bool) error `perm:"admin"` - StorageAddLocal func(p0 context.Context, p1 string) error `perm:"admin"` + Shutdown func(p0 context.Context) error `perm:"admin"` - StorageDetachAll func(p0 context.Context) error `perm:"admin"` + StorageAddLocal func(p0 context.Context, p1 string) error `perm:"admin"` - StorageDetachLocal func(p0 context.Context, p1 string) error `perm:"admin"` + StorageDetachAll func(p0 context.Context) error `perm:"admin"` - StorageLocal func(p0 context.Context) (map[storiface.ID]string, error) `perm:"admin"` + StorageDetachLocal func(p0 context.Context, p1 string) error `perm:"admin"` - StorageRedeclareLocal func(p0 context.Context, p1 *storiface.ID, p2 bool) error `perm:"admin"` + StorageLocal func(p0 context.Context) (map[storiface.ID]string, error) `perm:"admin"` - TaskDisable func(p0 context.Context, p1 sealtasks.TaskType) error `perm:"admin"` + StorageRedeclareLocal func(p0 context.Context, p1 *storiface.ID, p2 bool) error `perm:"admin"` - TaskEnable func(p0 context.Context, p1 sealtasks.TaskType) error `perm:"admin"` + TaskDisable func(p0 context.Context, p1 sealtasks.TaskType) error `perm:"admin"` - TaskTypes func(p0 context.Context) (map[sealtasks.TaskType]struct{}, error) `perm:"admin"` + TaskEnable func(p0 context.Context, p1 sealtasks.TaskType) error `perm:"admin"` - UnsealPiece func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.UnpaddedByteIndex, p3 abi.UnpaddedPieceSize, p4 abi.SealRandomness, p5 cid.Cid) (storiface.CallID, error) `perm:"admin"` + TaskTypes func(p0 context.Context) (map[sealtasks.TaskType]struct{}, error) `perm:"admin"` - Version func(p0 context.Context) (Version, error) `perm:"admin"` + UnsealPiece func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.UnpaddedByteIndex, p3 abi.UnpaddedPieceSize, p4 abi.SealRandomness, p5 cid.Cid) (storiface.CallID, error) `perm:"admin"` - WaitQuiet func(p0 context.Context) error `perm:"admin"` - } + Version func(p0 context.Context) (Version, error) `perm:"admin"` + + WaitQuiet func(p0 context.Context) error `perm:"admin"` } type WorkerStub struct { @@ -1340,6 +1380,17 @@ func (s *CommonStub) Version(p0 context.Context) (APIVersion, error) { return *new(APIVersion), ErrNotSupported } +func (s *EthSubscriberStruct) EthSubscription(p0 context.Context, p1 jsonrpc.RawParams) error { + if s.Internal.EthSubscription == nil { + return ErrNotSupported + } + return s.Internal.EthSubscription(p0, p1) +} + +func (s *EthSubscriberStub) EthSubscription(p0 context.Context, p1 jsonrpc.RawParams) error { + return ErrNotSupported +} + func (s *FullNodeStruct) ChainBlockstoreInfo(p0 context.Context) (map[string]interface{}, error) { if s.Internal.ChainBlockstoreInfo == nil { return *new(map[string]interface{}), ErrNotSupported @@ -2275,15 +2326,15 @@ func (s *FullNodeStub) EthSendRawTransaction(p0 context.Context, p1 ethtypes.Eth return *new(ethtypes.EthHash), ErrNotSupported } -func (s *FullNodeStruct) EthSubscribe(p0 context.Context, p1 string, p2 *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) { +func (s *FullNodeStruct) EthSubscribe(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) { if s.Internal.EthSubscribe == nil { - return nil, ErrNotSupported + return *new(ethtypes.EthSubscriptionID), ErrNotSupported } - return s.Internal.EthSubscribe(p0, p1, p2) + return s.Internal.EthSubscribe(p0, p1) } -func (s *FullNodeStub) EthSubscribe(p0 context.Context, p1 string, p2 *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) { - return nil, ErrNotSupported +func (s *FullNodeStub) EthSubscribe(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) { + return *new(ethtypes.EthSubscriptionID), ErrNotSupported } func (s *FullNodeStruct) EthUninstallFilter(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) { @@ -3936,6 +3987,17 @@ func (s *FullNodeStub) WalletVerify(p0 context.Context, p1 address.Address, p2 [ return false, ErrNotSupported } +func (s *FullNodeStruct) Web3ClientVersion(p0 context.Context) (string, error) { + if s.Internal.Web3ClientVersion == nil { + return "", ErrNotSupported + } + return s.Internal.Web3ClientVersion(p0) +} + +func (s *FullNodeStub) Web3ClientVersion(p0 context.Context) (string, error) { + return "", ErrNotSupported +} + func (s *GatewayStruct) ChainGetBlockMessages(p0 context.Context, p1 cid.Cid) (*BlockMessages, error) { if s.Internal.ChainGetBlockMessages == nil { return nil, ErrNotSupported @@ -4277,6 +4339,17 @@ func (s *GatewayStub) EthGetLogs(p0 context.Context, p1 *ethtypes.EthFilterSpec) return nil, ErrNotSupported } +func (s *GatewayStruct) EthGetMessageCidByTransactionHash(p0 context.Context, p1 *ethtypes.EthHash) (*cid.Cid, error) { + if s.Internal.EthGetMessageCidByTransactionHash == nil { + return nil, ErrNotSupported + } + return s.Internal.EthGetMessageCidByTransactionHash(p0, p1) +} + +func (s *GatewayStub) EthGetMessageCidByTransactionHash(p0 context.Context, p1 *ethtypes.EthHash) (*cid.Cid, error) { + return nil, ErrNotSupported +} + func (s *GatewayStruct) EthGetStorageAt(p0 context.Context, p1 ethtypes.EthAddress, p2 ethtypes.EthBytes, p3 string) (ethtypes.EthBytes, error) { if s.Internal.EthGetStorageAt == nil { return *new(ethtypes.EthBytes), ErrNotSupported @@ -4332,6 +4405,17 @@ func (s *GatewayStub) EthGetTransactionCount(p0 context.Context, p1 ethtypes.Eth return *new(ethtypes.EthUint64), ErrNotSupported } +func (s *GatewayStruct) EthGetTransactionHashByCid(p0 context.Context, p1 cid.Cid) (*ethtypes.EthHash, error) { + if s.Internal.EthGetTransactionHashByCid == nil { + return nil, ErrNotSupported + } + return s.Internal.EthGetTransactionHashByCid(p0, p1) +} + +func (s *GatewayStub) EthGetTransactionHashByCid(p0 context.Context, p1 cid.Cid) (*ethtypes.EthHash, error) { + return nil, ErrNotSupported +} + func (s *GatewayStruct) EthGetTransactionReceipt(p0 context.Context, p1 ethtypes.EthHash) (*EthTxReceipt, error) { if s.Internal.EthGetTransactionReceipt == nil { return nil, ErrNotSupported @@ -4409,15 +4493,15 @@ func (s *GatewayStub) EthSendRawTransaction(p0 context.Context, p1 ethtypes.EthB return *new(ethtypes.EthHash), ErrNotSupported } -func (s *GatewayStruct) EthSubscribe(p0 context.Context, p1 string, p2 *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) { +func (s *GatewayStruct) EthSubscribe(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) { if s.Internal.EthSubscribe == nil { - return nil, ErrNotSupported + return *new(ethtypes.EthSubscriptionID), ErrNotSupported } - return s.Internal.EthSubscribe(p0, p1, p2) + return s.Internal.EthSubscribe(p0, p1) } -func (s *GatewayStub) EthSubscribe(p0 context.Context, p1 string, p2 *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) { - return nil, ErrNotSupported +func (s *GatewayStub) EthSubscribe(p0 context.Context, p1 jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) { + return *new(ethtypes.EthSubscriptionID), ErrNotSupported } func (s *GatewayStruct) EthUninstallFilter(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) { @@ -4728,6 +4812,17 @@ func (s *GatewayStub) WalletBalance(p0 context.Context, p1 address.Address) (typ return *new(types.BigInt), ErrNotSupported } +func (s *GatewayStruct) Web3ClientVersion(p0 context.Context) (string, error) { + if s.Internal.Web3ClientVersion == nil { + return "", ErrNotSupported + } + return s.Internal.Web3ClientVersion(p0) +} + +func (s *GatewayStub) Web3ClientVersion(p0 context.Context) (string, error) { + return "", ErrNotSupported +} + func (s *NetStruct) ID(p0 context.Context) (peer.ID, error) { if s.Internal.ID == nil { return *new(peer.ID), ErrNotSupported @@ -6942,6 +7037,7 @@ func (s *WorkerStub) WaitQuiet(p0 context.Context) error { var _ ChainIO = new(ChainIOStruct) var _ Common = new(CommonStruct) var _ CommonNet = new(CommonNetStruct) +var _ EthSubscriber = new(EthSubscriberStruct) var _ FullNode = new(FullNodeStruct) var _ Gateway = new(GatewayStruct) var _ Net = new(NetStruct) diff --git a/api/v0api/proxy_gen.go b/api/v0api/proxy_gen.go index de912140f3e..5fa0d949c6f 100644 --- a/api/v0api/proxy_gen.go +++ b/api/v0api/proxy_gen.go @@ -39,383 +39,385 @@ type FullNodeStruct struct { NetStruct - Internal struct { - BeaconGetEntry func(p0 context.Context, p1 abi.ChainEpoch) (*types.BeaconEntry, error) `perm:"read"` + Internal FullNodeMethods +} - ChainDeleteObj func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` +type FullNodeMethods struct { + BeaconGetEntry func(p0 context.Context, p1 abi.ChainEpoch) (*types.BeaconEntry, error) `perm:"read"` - ChainExport func(p0 context.Context, p1 abi.ChainEpoch, p2 bool, p3 types.TipSetKey) (<-chan []byte, error) `perm:"read"` + ChainDeleteObj func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` - ChainGetBlock func(p0 context.Context, p1 cid.Cid) (*types.BlockHeader, error) `perm:"read"` + ChainExport func(p0 context.Context, p1 abi.ChainEpoch, p2 bool, p3 types.TipSetKey) (<-chan []byte, error) `perm:"read"` - ChainGetBlockMessages func(p0 context.Context, p1 cid.Cid) (*api.BlockMessages, error) `perm:"read"` + ChainGetBlock func(p0 context.Context, p1 cid.Cid) (*types.BlockHeader, error) `perm:"read"` - ChainGetGenesis func(p0 context.Context) (*types.TipSet, error) `perm:"read"` + ChainGetBlockMessages func(p0 context.Context, p1 cid.Cid) (*api.BlockMessages, error) `perm:"read"` - ChainGetMessage func(p0 context.Context, p1 cid.Cid) (*types.Message, error) `perm:"read"` + ChainGetGenesis func(p0 context.Context) (*types.TipSet, error) `perm:"read"` - ChainGetMessagesInTipset func(p0 context.Context, p1 types.TipSetKey) ([]api.Message, error) `perm:"read"` + ChainGetMessage func(p0 context.Context, p1 cid.Cid) (*types.Message, error) `perm:"read"` - ChainGetNode func(p0 context.Context, p1 string) (*api.IpldObject, error) `perm:"read"` + ChainGetMessagesInTipset func(p0 context.Context, p1 types.TipSetKey) ([]api.Message, error) `perm:"read"` - ChainGetParentMessages func(p0 context.Context, p1 cid.Cid) ([]api.Message, error) `perm:"read"` + ChainGetNode func(p0 context.Context, p1 string) (*api.IpldObject, error) `perm:"read"` - ChainGetParentReceipts func(p0 context.Context, p1 cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"` + ChainGetParentMessages func(p0 context.Context, p1 cid.Cid) ([]api.Message, error) `perm:"read"` - ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*api.HeadChange, error) `perm:"read"` + ChainGetParentReceipts func(p0 context.Context, p1 cid.Cid) ([]*types.MessageReceipt, error) `perm:"read"` - ChainGetRandomnessFromBeacon func(p0 context.Context, p1 types.TipSetKey, p2 crypto.DomainSeparationTag, p3 abi.ChainEpoch, p4 []byte) (abi.Randomness, error) `perm:"read"` + ChainGetPath func(p0 context.Context, p1 types.TipSetKey, p2 types.TipSetKey) ([]*api.HeadChange, error) `perm:"read"` - ChainGetRandomnessFromTickets func(p0 context.Context, p1 types.TipSetKey, p2 crypto.DomainSeparationTag, p3 abi.ChainEpoch, p4 []byte) (abi.Randomness, error) `perm:"read"` + ChainGetRandomnessFromBeacon func(p0 context.Context, p1 types.TipSetKey, p2 crypto.DomainSeparationTag, p3 abi.ChainEpoch, p4 []byte) (abi.Randomness, error) `perm:"read"` - ChainGetTipSet func(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) `perm:"read"` + ChainGetRandomnessFromTickets func(p0 context.Context, p1 types.TipSetKey, p2 crypto.DomainSeparationTag, p3 abi.ChainEpoch, p4 []byte) (abi.Randomness, error) `perm:"read"` - ChainGetTipSetByHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `perm:"read"` + ChainGetTipSet func(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) `perm:"read"` - ChainHasObj func(p0 context.Context, p1 cid.Cid) (bool, error) `perm:"read"` + ChainGetTipSetByHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `perm:"read"` - ChainHead func(p0 context.Context) (*types.TipSet, error) `perm:"read"` + ChainHasObj func(p0 context.Context, p1 cid.Cid) (bool, error) `perm:"read"` - ChainNotify func(p0 context.Context) (<-chan []*api.HeadChange, error) `perm:"read"` + ChainHead func(p0 context.Context) (*types.TipSet, error) `perm:"read"` - ChainPutObj func(p0 context.Context, p1 blocks.Block) error `` + ChainNotify func(p0 context.Context) (<-chan []*api.HeadChange, error) `perm:"read"` - ChainReadObj func(p0 context.Context, p1 cid.Cid) ([]byte, error) `perm:"read"` + ChainPutObj func(p0 context.Context, p1 blocks.Block) error `` - ChainSetHead func(p0 context.Context, p1 types.TipSetKey) error `perm:"admin"` + ChainReadObj func(p0 context.Context, p1 cid.Cid) ([]byte, error) `perm:"read"` - ChainStatObj func(p0 context.Context, p1 cid.Cid, p2 cid.Cid) (api.ObjStat, error) `perm:"read"` + ChainSetHead func(p0 context.Context, p1 types.TipSetKey) error `perm:"admin"` - ChainTipSetWeight func(p0 context.Context, p1 types.TipSetKey) (types.BigInt, error) `perm:"read"` + ChainStatObj func(p0 context.Context, p1 cid.Cid, p2 cid.Cid) (api.ObjStat, error) `perm:"read"` - ClientCalcCommP func(p0 context.Context, p1 string) (*api.CommPRet, error) `perm:"write"` + ChainTipSetWeight func(p0 context.Context, p1 types.TipSetKey) (types.BigInt, error) `perm:"read"` - ClientCancelDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` + ClientCalcCommP func(p0 context.Context, p1 string) (*api.CommPRet, error) `perm:"write"` - ClientCancelRetrievalDeal func(p0 context.Context, p1 retrievalmarket.DealID) error `perm:"write"` + ClientCancelDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` - ClientDataTransferUpdates func(p0 context.Context) (<-chan api.DataTransferChannel, error) `perm:"write"` + ClientCancelRetrievalDeal func(p0 context.Context, p1 retrievalmarket.DealID) error `perm:"write"` - ClientDealPieceCID func(p0 context.Context, p1 cid.Cid) (api.DataCIDSize, error) `perm:"read"` + ClientDataTransferUpdates func(p0 context.Context) (<-chan api.DataTransferChannel, error) `perm:"write"` - ClientDealSize func(p0 context.Context, p1 cid.Cid) (api.DataSize, error) `perm:"read"` + ClientDealPieceCID func(p0 context.Context, p1 cid.Cid) (api.DataCIDSize, error) `perm:"read"` - ClientFindData func(p0 context.Context, p1 cid.Cid, p2 *cid.Cid) ([]api.QueryOffer, error) `perm:"read"` + ClientDealSize func(p0 context.Context, p1 cid.Cid) (api.DataSize, error) `perm:"read"` - ClientGenCar func(p0 context.Context, p1 api.FileRef, p2 string) error `perm:"write"` + ClientFindData func(p0 context.Context, p1 cid.Cid, p2 *cid.Cid) ([]api.QueryOffer, error) `perm:"read"` - ClientGetDealInfo func(p0 context.Context, p1 cid.Cid) (*api.DealInfo, error) `perm:"read"` + ClientGenCar func(p0 context.Context, p1 api.FileRef, p2 string) error `perm:"write"` - ClientGetDealStatus func(p0 context.Context, p1 uint64) (string, error) `perm:"read"` + ClientGetDealInfo func(p0 context.Context, p1 cid.Cid) (*api.DealInfo, error) `perm:"read"` - ClientGetDealUpdates func(p0 context.Context) (<-chan api.DealInfo, error) `perm:"write"` + ClientGetDealStatus func(p0 context.Context, p1 uint64) (string, error) `perm:"read"` - ClientGetRetrievalUpdates func(p0 context.Context) (<-chan api.RetrievalInfo, error) `perm:"write"` + ClientGetDealUpdates func(p0 context.Context) (<-chan api.DealInfo, error) `perm:"write"` - ClientHasLocal func(p0 context.Context, p1 cid.Cid) (bool, error) `perm:"write"` + ClientGetRetrievalUpdates func(p0 context.Context) (<-chan api.RetrievalInfo, error) `perm:"write"` - ClientImport func(p0 context.Context, p1 api.FileRef) (*api.ImportRes, error) `perm:"admin"` + ClientHasLocal func(p0 context.Context, p1 cid.Cid) (bool, error) `perm:"write"` - ClientListDataTransfers func(p0 context.Context) ([]api.DataTransferChannel, error) `perm:"write"` + ClientImport func(p0 context.Context, p1 api.FileRef) (*api.ImportRes, error) `perm:"admin"` - ClientListDeals func(p0 context.Context) ([]api.DealInfo, error) `perm:"write"` + ClientListDataTransfers func(p0 context.Context) ([]api.DataTransferChannel, error) `perm:"write"` - ClientListImports func(p0 context.Context) ([]api.Import, error) `perm:"write"` + ClientListDeals func(p0 context.Context) ([]api.DealInfo, error) `perm:"write"` - ClientListRetrievals func(p0 context.Context) ([]api.RetrievalInfo, error) `perm:"write"` + ClientListImports func(p0 context.Context) ([]api.Import, error) `perm:"write"` - ClientMinerQueryOffer func(p0 context.Context, p1 address.Address, p2 cid.Cid, p3 *cid.Cid) (api.QueryOffer, error) `perm:"read"` + ClientListRetrievals func(p0 context.Context) ([]api.RetrievalInfo, error) `perm:"write"` - ClientQueryAsk func(p0 context.Context, p1 peer.ID, p2 address.Address) (*storagemarket.StorageAsk, error) `perm:"read"` + ClientMinerQueryOffer func(p0 context.Context, p1 address.Address, p2 cid.Cid, p3 *cid.Cid) (api.QueryOffer, error) `perm:"read"` - ClientRemoveImport func(p0 context.Context, p1 imports.ID) error `perm:"admin"` + ClientQueryAsk func(p0 context.Context, p1 peer.ID, p2 address.Address) (*storagemarket.StorageAsk, error) `perm:"read"` - ClientRestartDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` + ClientRemoveImport func(p0 context.Context, p1 imports.ID) error `perm:"admin"` - ClientRetrieve func(p0 context.Context, p1 RetrievalOrder, p2 *api.FileRef) error `perm:"admin"` + ClientRestartDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` - ClientRetrieveTryRestartInsufficientFunds func(p0 context.Context, p1 address.Address) error `perm:"write"` + ClientRetrieve func(p0 context.Context, p1 RetrievalOrder, p2 *api.FileRef) error `perm:"admin"` - ClientRetrieveWithEvents func(p0 context.Context, p1 RetrievalOrder, p2 *api.FileRef) (<-chan marketevents.RetrievalEvent, error) `perm:"admin"` + ClientRetrieveTryRestartInsufficientFunds func(p0 context.Context, p1 address.Address) error `perm:"write"` - ClientStartDeal func(p0 context.Context, p1 *api.StartDealParams) (*cid.Cid, error) `perm:"admin"` + ClientRetrieveWithEvents func(p0 context.Context, p1 RetrievalOrder, p2 *api.FileRef) (<-chan marketevents.RetrievalEvent, error) `perm:"admin"` - ClientStatelessDeal func(p0 context.Context, p1 *api.StartDealParams) (*cid.Cid, error) `perm:"write"` + ClientStartDeal func(p0 context.Context, p1 *api.StartDealParams) (*cid.Cid, error) `perm:"admin"` - CreateBackup func(p0 context.Context, p1 string) error `perm:"admin"` + ClientStatelessDeal func(p0 context.Context, p1 *api.StartDealParams) (*cid.Cid, error) `perm:"write"` - GasEstimateFeeCap func(p0 context.Context, p1 *types.Message, p2 int64, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` + CreateBackup func(p0 context.Context, p1 string) error `perm:"admin"` - GasEstimateGasLimit func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (int64, error) `perm:"read"` + GasEstimateFeeCap func(p0 context.Context, p1 *types.Message, p2 int64, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` - GasEstimateGasPremium func(p0 context.Context, p1 uint64, p2 address.Address, p3 int64, p4 types.TipSetKey) (types.BigInt, error) `perm:"read"` + GasEstimateGasLimit func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (int64, error) `perm:"read"` - GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *api.MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) `perm:"read"` + GasEstimateGasPremium func(p0 context.Context, p1 uint64, p2 address.Address, p3 int64, p4 types.TipSetKey) (types.BigInt, error) `perm:"read"` - MarketAddBalance func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` + GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *api.MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) `perm:"read"` - MarketGetReserved func(p0 context.Context, p1 address.Address) (types.BigInt, error) `perm:"sign"` + MarketAddBalance func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` - MarketReleaseFunds func(p0 context.Context, p1 address.Address, p2 types.BigInt) error `perm:"sign"` + MarketGetReserved func(p0 context.Context, p1 address.Address) (types.BigInt, error) `perm:"sign"` - MarketReserveFunds func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` + MarketReleaseFunds func(p0 context.Context, p1 address.Address, p2 types.BigInt) error `perm:"sign"` - MarketWithdraw func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` + MarketReserveFunds func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` - MinerCreateBlock func(p0 context.Context, p1 *api.BlockTemplate) (*types.BlockMsg, error) `perm:"write"` + MarketWithdraw func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"` - MinerGetBaseInfo func(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*api.MiningBaseInfo, error) `perm:"read"` + MinerCreateBlock func(p0 context.Context, p1 *api.BlockTemplate) (*types.BlockMsg, error) `perm:"write"` - MpoolBatchPush func(p0 context.Context, p1 []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"` + MinerGetBaseInfo func(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*api.MiningBaseInfo, error) `perm:"read"` - MpoolBatchPushMessage func(p0 context.Context, p1 []*types.Message, p2 *api.MessageSendSpec) ([]*types.SignedMessage, error) `perm:"sign"` + MpoolBatchPush func(p0 context.Context, p1 []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"` - MpoolBatchPushUntrusted func(p0 context.Context, p1 []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"` + MpoolBatchPushMessage func(p0 context.Context, p1 []*types.Message, p2 *api.MessageSendSpec) ([]*types.SignedMessage, error) `perm:"sign"` - MpoolClear func(p0 context.Context, p1 bool) error `perm:"write"` + MpoolBatchPushUntrusted func(p0 context.Context, p1 []*types.SignedMessage) ([]cid.Cid, error) `perm:"write"` - MpoolGetConfig func(p0 context.Context) (*types.MpoolConfig, error) `perm:"read"` + MpoolClear func(p0 context.Context, p1 bool) error `perm:"write"` - MpoolGetNonce func(p0 context.Context, p1 address.Address) (uint64, error) `perm:"read"` + MpoolGetConfig func(p0 context.Context) (*types.MpoolConfig, error) `perm:"read"` - MpoolPending func(p0 context.Context, p1 types.TipSetKey) ([]*types.SignedMessage, error) `perm:"read"` + MpoolGetNonce func(p0 context.Context, p1 address.Address) (uint64, error) `perm:"read"` - MpoolPush func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `perm:"write"` + MpoolPending func(p0 context.Context, p1 types.TipSetKey) ([]*types.SignedMessage, error) `perm:"read"` - MpoolPushMessage func(p0 context.Context, p1 *types.Message, p2 *api.MessageSendSpec) (*types.SignedMessage, error) `perm:"sign"` + MpoolPush func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `perm:"write"` - MpoolPushUntrusted func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `perm:"write"` + MpoolPushMessage func(p0 context.Context, p1 *types.Message, p2 *api.MessageSendSpec) (*types.SignedMessage, error) `perm:"sign"` - MpoolSelect func(p0 context.Context, p1 types.TipSetKey, p2 float64) ([]*types.SignedMessage, error) `perm:"read"` + MpoolPushUntrusted func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `perm:"write"` - MpoolSetConfig func(p0 context.Context, p1 *types.MpoolConfig) error `perm:"admin"` + MpoolSelect func(p0 context.Context, p1 types.TipSetKey, p2 float64) ([]*types.SignedMessage, error) `perm:"read"` - MpoolSub func(p0 context.Context) (<-chan api.MpoolUpdate, error) `perm:"read"` + MpoolSetConfig func(p0 context.Context, p1 *types.MpoolConfig) error `perm:"admin"` - MsigAddApprove func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 bool) (cid.Cid, error) `perm:"sign"` + MpoolSub func(p0 context.Context) (<-chan api.MpoolUpdate, error) `perm:"read"` - MsigAddCancel func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 bool) (cid.Cid, error) `perm:"sign"` + MsigAddApprove func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 bool) (cid.Cid, error) `perm:"sign"` - MsigAddPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (cid.Cid, error) `perm:"sign"` + MsigAddCancel func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 bool) (cid.Cid, error) `perm:"sign"` - MsigApprove func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address) (cid.Cid, error) `perm:"sign"` + MsigAddPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (cid.Cid, error) `perm:"sign"` - MsigApproveTxnHash func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 address.Address, p5 types.BigInt, p6 address.Address, p7 uint64, p8 []byte) (cid.Cid, error) `perm:"sign"` + MsigApprove func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address) (cid.Cid, error) `perm:"sign"` - MsigCancel func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 types.BigInt, p5 address.Address, p6 uint64, p7 []byte) (cid.Cid, error) `perm:"sign"` + MsigApproveTxnHash func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 address.Address, p5 types.BigInt, p6 address.Address, p7 uint64, p8 []byte) (cid.Cid, error) `perm:"sign"` - MsigCreate func(p0 context.Context, p1 uint64, p2 []address.Address, p3 abi.ChainEpoch, p4 types.BigInt, p5 address.Address, p6 types.BigInt) (cid.Cid, error) `perm:"sign"` + MsigCancel func(p0 context.Context, p1 address.Address, p2 uint64, p3 address.Address, p4 types.BigInt, p5 address.Address, p6 uint64, p7 []byte) (cid.Cid, error) `perm:"sign"` - MsigGetAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `perm:"read"` + MsigCreate func(p0 context.Context, p1 uint64, p2 []address.Address, p3 abi.ChainEpoch, p4 types.BigInt, p5 address.Address, p6 types.BigInt) (cid.Cid, error) `perm:"sign"` - MsigGetPending func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*api.MsigTransaction, error) `perm:"read"` + MsigGetAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `perm:"read"` - MsigGetVested func(p0 context.Context, p1 address.Address, p2 types.TipSetKey, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` + MsigGetPending func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*api.MsigTransaction, error) `perm:"read"` - MsigGetVestingSchedule func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MsigVesting, error) `perm:"read"` + MsigGetVested func(p0 context.Context, p1 address.Address, p2 types.TipSetKey, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` - MsigPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 address.Address, p5 uint64, p6 []byte) (cid.Cid, error) `perm:"sign"` + MsigGetVestingSchedule func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MsigVesting, error) `perm:"read"` - MsigRemoveSigner func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (cid.Cid, error) `perm:"sign"` + MsigPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt, p4 address.Address, p5 uint64, p6 []byte) (cid.Cid, error) `perm:"sign"` - MsigSwapApprove func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 address.Address) (cid.Cid, error) `perm:"sign"` + MsigRemoveSigner func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 bool) (cid.Cid, error) `perm:"sign"` - MsigSwapCancel func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address) (cid.Cid, error) `perm:"sign"` + MsigSwapApprove func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address, p6 address.Address) (cid.Cid, error) `perm:"sign"` - MsigSwapPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 address.Address) (cid.Cid, error) `perm:"sign"` + MsigSwapCancel func(p0 context.Context, p1 address.Address, p2 address.Address, p3 uint64, p4 address.Address, p5 address.Address) (cid.Cid, error) `perm:"sign"` - PaychAllocateLane func(p0 context.Context, p1 address.Address) (uint64, error) `perm:"sign"` + MsigSwapPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 address.Address) (cid.Cid, error) `perm:"sign"` - PaychAvailableFunds func(p0 context.Context, p1 address.Address) (*api.ChannelAvailableFunds, error) `perm:"sign"` + PaychAllocateLane func(p0 context.Context, p1 address.Address) (uint64, error) `perm:"sign"` - PaychAvailableFundsByFromTo func(p0 context.Context, p1 address.Address, p2 address.Address) (*api.ChannelAvailableFunds, error) `perm:"sign"` + PaychAvailableFunds func(p0 context.Context, p1 address.Address) (*api.ChannelAvailableFunds, error) `perm:"sign"` - PaychCollect func(p0 context.Context, p1 address.Address) (cid.Cid, error) `perm:"sign"` + PaychAvailableFundsByFromTo func(p0 context.Context, p1 address.Address, p2 address.Address) (*api.ChannelAvailableFunds, error) `perm:"sign"` - PaychGet func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (*api.ChannelInfo, error) `perm:"sign"` + PaychCollect func(p0 context.Context, p1 address.Address) (cid.Cid, error) `perm:"sign"` - PaychGetWaitReady func(p0 context.Context, p1 cid.Cid) (address.Address, error) `perm:"sign"` + PaychGet func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (*api.ChannelInfo, error) `perm:"sign"` - PaychList func(p0 context.Context) ([]address.Address, error) `perm:"read"` + PaychGetWaitReady func(p0 context.Context, p1 cid.Cid) (address.Address, error) `perm:"sign"` - PaychNewPayment func(p0 context.Context, p1 address.Address, p2 address.Address, p3 []api.VoucherSpec) (*api.PaymentInfo, error) `perm:"sign"` + PaychList func(p0 context.Context) ([]address.Address, error) `perm:"read"` - PaychSettle func(p0 context.Context, p1 address.Address) (cid.Cid, error) `perm:"sign"` + PaychNewPayment func(p0 context.Context, p1 address.Address, p2 address.Address, p3 []api.VoucherSpec) (*api.PaymentInfo, error) `perm:"sign"` - PaychStatus func(p0 context.Context, p1 address.Address) (*api.PaychStatus, error) `perm:"read"` + PaychSettle func(p0 context.Context, p1 address.Address) (cid.Cid, error) `perm:"sign"` - PaychVoucherAdd func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 types.BigInt) (types.BigInt, error) `perm:"write"` + PaychStatus func(p0 context.Context, p1 address.Address) (*api.PaychStatus, error) `perm:"read"` - PaychVoucherCheckSpendable func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 []byte) (bool, error) `perm:"read"` + PaychVoucherAdd func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 types.BigInt) (types.BigInt, error) `perm:"write"` - PaychVoucherCheckValid func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher) error `perm:"read"` + PaychVoucherCheckSpendable func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 []byte) (bool, error) `perm:"read"` - PaychVoucherCreate func(p0 context.Context, p1 address.Address, p2 types.BigInt, p3 uint64) (*api.VoucherCreateResult, error) `perm:"sign"` + PaychVoucherCheckValid func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher) error `perm:"read"` - PaychVoucherList func(p0 context.Context, p1 address.Address) ([]*paych.SignedVoucher, error) `perm:"write"` + PaychVoucherCreate func(p0 context.Context, p1 address.Address, p2 types.BigInt, p3 uint64) (*api.VoucherCreateResult, error) `perm:"sign"` - PaychVoucherSubmit func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 []byte) (cid.Cid, error) `perm:"sign"` + PaychVoucherList func(p0 context.Context, p1 address.Address) ([]*paych.SignedVoucher, error) `perm:"write"` - StateAccountKey func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` + PaychVoucherSubmit func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 []byte) (cid.Cid, error) `perm:"sign"` - StateActorCodeCIDs func(p0 context.Context, p1 abinetwork.Version) (map[string]cid.Cid, error) `perm:"read"` + StateAccountKey func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` - StateActorManifestCID func(p0 context.Context, p1 abinetwork.Version) (cid.Cid, error) `perm:"read"` + StateActorCodeCIDs func(p0 context.Context, p1 abinetwork.Version) (map[string]cid.Cid, error) `perm:"read"` - StateAllMinerFaults func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) ([]*api.Fault, error) `perm:"read"` + StateActorManifestCID func(p0 context.Context, p1 abinetwork.Version) (cid.Cid, error) `perm:"read"` - StateCall func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (*api.InvocResult, error) `perm:"read"` + StateAllMinerFaults func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) ([]*api.Fault, error) `perm:"read"` - StateChangedActors func(p0 context.Context, p1 cid.Cid, p2 cid.Cid) (map[string]types.Actor, error) `perm:"read"` + StateCall func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (*api.InvocResult, error) `perm:"read"` - StateCirculatingSupply func(p0 context.Context, p1 types.TipSetKey) (abi.TokenAmount, error) `perm:"read"` + StateChangedActors func(p0 context.Context, p1 cid.Cid, p2 cid.Cid) (map[string]types.Actor, error) `perm:"read"` - StateCompute func(p0 context.Context, p1 abi.ChainEpoch, p2 []*types.Message, p3 types.TipSetKey) (*api.ComputeStateOutput, error) `perm:"read"` + StateCirculatingSupply func(p0 context.Context, p1 types.TipSetKey) (abi.TokenAmount, error) `perm:"read"` - StateDealProviderCollateralBounds func(p0 context.Context, p1 abi.PaddedPieceSize, p2 bool, p3 types.TipSetKey) (api.DealCollateralBounds, error) `perm:"read"` + StateCompute func(p0 context.Context, p1 abi.ChainEpoch, p2 []*types.Message, p3 types.TipSetKey) (*api.ComputeStateOutput, error) `perm:"read"` - StateDecodeParams func(p0 context.Context, p1 address.Address, p2 abi.MethodNum, p3 []byte, p4 types.TipSetKey) (interface{}, error) `perm:"read"` + StateDealProviderCollateralBounds func(p0 context.Context, p1 abi.PaddedPieceSize, p2 bool, p3 types.TipSetKey) (api.DealCollateralBounds, error) `perm:"read"` - StateGetActor func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*types.Actor, error) `perm:"read"` + StateDecodeParams func(p0 context.Context, p1 address.Address, p2 abi.MethodNum, p3 []byte, p4 types.TipSetKey) (interface{}, error) `perm:"read"` - StateGetAllocation func(p0 context.Context, p1 address.Address, p2 verifregtypes.AllocationId, p3 types.TipSetKey) (*verifregtypes.Allocation, error) `perm:"read"` + StateGetActor func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*types.Actor, error) `perm:"read"` - StateGetAllocationForPendingDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*verifregtypes.Allocation, error) `perm:"read"` + StateGetAllocation func(p0 context.Context, p1 address.Address, p2 verifregtypes.AllocationId, p3 types.TipSetKey) (*verifregtypes.Allocation, error) `perm:"read"` - StateGetAllocations func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (map[verifregtypes.AllocationId]verifregtypes.Allocation, error) `perm:"read"` + StateGetAllocationForPendingDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*verifregtypes.Allocation, error) `perm:"read"` - StateGetClaim func(p0 context.Context, p1 address.Address, p2 verifregtypes.ClaimId, p3 types.TipSetKey) (*verifregtypes.Claim, error) `perm:"read"` + StateGetAllocations func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (map[verifregtypes.AllocationId]verifregtypes.Allocation, error) `perm:"read"` - StateGetClaims func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (map[verifregtypes.ClaimId]verifregtypes.Claim, error) `perm:"read"` + StateGetClaim func(p0 context.Context, p1 address.Address, p2 verifregtypes.ClaimId, p3 types.TipSetKey) (*verifregtypes.Claim, error) `perm:"read"` - StateGetNetworkParams func(p0 context.Context) (*api.NetworkParams, error) `perm:"read"` + StateGetClaims func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (map[verifregtypes.ClaimId]verifregtypes.Claim, error) `perm:"read"` - StateGetRandomnessFromBeacon func(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) `perm:"read"` + StateGetNetworkParams func(p0 context.Context) (*api.NetworkParams, error) `perm:"read"` - StateGetRandomnessFromTickets func(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) `perm:"read"` + StateGetRandomnessFromBeacon func(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) `perm:"read"` - StateGetReceipt func(p0 context.Context, p1 cid.Cid, p2 types.TipSetKey) (*types.MessageReceipt, error) `perm:"read"` + StateGetRandomnessFromTickets func(p0 context.Context, p1 crypto.DomainSeparationTag, p2 abi.ChainEpoch, p3 []byte, p4 types.TipSetKey) (abi.Randomness, error) `perm:"read"` - StateListActors func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `perm:"read"` + StateGetReceipt func(p0 context.Context, p1 cid.Cid, p2 types.TipSetKey) (*types.MessageReceipt, error) `perm:"read"` - StateListMessages func(p0 context.Context, p1 *api.MessageMatch, p2 types.TipSetKey, p3 abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"` + StateListActors func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `perm:"read"` - StateListMiners func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `perm:"read"` + StateListMessages func(p0 context.Context, p1 *api.MessageMatch, p2 types.TipSetKey, p3 abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"` - StateLookupID func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` + StateListMiners func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `perm:"read"` - StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MarketBalance, error) `perm:"read"` + StateLookupID func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` - StateMarketDeals func(p0 context.Context, p1 types.TipSetKey) (map[string]*api.MarketDeal, error) `perm:"read"` + StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MarketBalance, error) `perm:"read"` - StateMarketParticipants func(p0 context.Context, p1 types.TipSetKey) (map[string]api.MarketBalance, error) `perm:"read"` + StateMarketDeals func(p0 context.Context, p1 types.TipSetKey) (map[string]*api.MarketDeal, error) `perm:"read"` - StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*api.MarketDeal, error) `perm:"read"` + StateMarketParticipants func(p0 context.Context, p1 types.TipSetKey) (map[string]api.MarketBalance, error) `perm:"read"` - StateMinerActiveSectors func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*miner.SectorOnChainInfo, error) `perm:"read"` + StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*api.MarketDeal, error) `perm:"read"` - StateMinerAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `perm:"read"` + StateMinerActiveSectors func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*miner.SectorOnChainInfo, error) `perm:"read"` - StateMinerDeadlines func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]api.Deadline, error) `perm:"read"` + StateMinerAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `perm:"read"` - StateMinerFaults func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (bitfield.BitField, error) `perm:"read"` + StateMinerDeadlines func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]api.Deadline, error) `perm:"read"` - StateMinerInfo func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MinerInfo, error) `perm:"read"` + StateMinerFaults func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (bitfield.BitField, error) `perm:"read"` - StateMinerInitialPledgeCollateral func(p0 context.Context, p1 address.Address, p2 miner.SectorPreCommitInfo, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` + StateMinerInfo func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MinerInfo, error) `perm:"read"` - StateMinerPartitions func(p0 context.Context, p1 address.Address, p2 uint64, p3 types.TipSetKey) ([]api.Partition, error) `perm:"read"` + StateMinerInitialPledgeCollateral func(p0 context.Context, p1 address.Address, p2 miner.SectorPreCommitInfo, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` - StateMinerPower func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*api.MinerPower, error) `perm:"read"` + StateMinerPartitions func(p0 context.Context, p1 address.Address, p2 uint64, p3 types.TipSetKey) ([]api.Partition, error) `perm:"read"` - StateMinerPreCommitDepositForPower func(p0 context.Context, p1 address.Address, p2 miner.SectorPreCommitInfo, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` + StateMinerPower func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*api.MinerPower, error) `perm:"read"` - StateMinerProvingDeadline func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*dline.Info, error) `perm:"read"` + StateMinerPreCommitDepositForPower func(p0 context.Context, p1 address.Address, p2 miner.SectorPreCommitInfo, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"` - StateMinerRecoveries func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (bitfield.BitField, error) `perm:"read"` + StateMinerProvingDeadline func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*dline.Info, error) `perm:"read"` - StateMinerSectorAllocated func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (bool, error) `perm:"read"` + StateMinerRecoveries func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (bitfield.BitField, error) `perm:"read"` - StateMinerSectorCount func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MinerSectors, error) `perm:"read"` + StateMinerSectorAllocated func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (bool, error) `perm:"read"` - StateMinerSectors func(p0 context.Context, p1 address.Address, p2 *bitfield.BitField, p3 types.TipSetKey) ([]*miner.SectorOnChainInfo, error) `perm:"read"` + StateMinerSectorCount func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MinerSectors, error) `perm:"read"` - StateNetworkName func(p0 context.Context) (dtypes.NetworkName, error) `perm:"read"` + StateMinerSectors func(p0 context.Context, p1 address.Address, p2 *bitfield.BitField, p3 types.TipSetKey) ([]*miner.SectorOnChainInfo, error) `perm:"read"` - StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (apitypes.NetworkVersion, error) `perm:"read"` + StateNetworkName func(p0 context.Context) (dtypes.NetworkName, error) `perm:"read"` - StateReadState func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*api.ActorState, error) `perm:"read"` + StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (apitypes.NetworkVersion, error) `perm:"read"` - StateReplay func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*api.InvocResult, error) `perm:"read"` + StateReadState func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*api.ActorState, error) `perm:"read"` - StateSearchMsg func(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) `perm:"read"` + StateReplay func(p0 context.Context, p1 types.TipSetKey, p2 cid.Cid) (*api.InvocResult, error) `perm:"read"` - StateSearchMsgLimited func(p0 context.Context, p1 cid.Cid, p2 abi.ChainEpoch) (*api.MsgLookup, error) `perm:"read"` + StateSearchMsg func(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) `perm:"read"` - StateSectorExpiration func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*lminer.SectorExpiration, error) `perm:"read"` + StateSearchMsgLimited func(p0 context.Context, p1 cid.Cid, p2 abi.ChainEpoch) (*api.MsgLookup, error) `perm:"read"` - StateSectorGetInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorOnChainInfo, error) `perm:"read"` + StateSectorExpiration func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*lminer.SectorExpiration, error) `perm:"read"` - StateSectorPartition func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*lminer.SectorLocation, error) `perm:"read"` + StateSectorGetInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorOnChainInfo, error) `perm:"read"` - StateSectorPreCommitInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) `perm:"read"` + StateSectorPartition func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*lminer.SectorLocation, error) `perm:"read"` - StateVMCirculatingSupplyInternal func(p0 context.Context, p1 types.TipSetKey) (api.CirculatingSupply, error) `perm:"read"` + StateSectorPreCommitInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (miner.SectorPreCommitOnChainInfo, error) `perm:"read"` - StateVerifiedClientStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` + StateVMCirculatingSupplyInternal func(p0 context.Context, p1 types.TipSetKey) (api.CirculatingSupply, error) `perm:"read"` - StateVerifiedRegistryRootKey func(p0 context.Context, p1 types.TipSetKey) (address.Address, error) `perm:"read"` + StateVerifiedClientStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` - StateVerifierStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` + StateVerifiedRegistryRootKey func(p0 context.Context, p1 types.TipSetKey) (address.Address, error) `perm:"read"` - StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64) (*api.MsgLookup, error) `perm:"read"` + StateVerifierStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` - StateWaitMsgLimited func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch) (*api.MsgLookup, error) `perm:"read"` + StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64) (*api.MsgLookup, error) `perm:"read"` - SyncCheckBad func(p0 context.Context, p1 cid.Cid) (string, error) `perm:"read"` + StateWaitMsgLimited func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch) (*api.MsgLookup, error) `perm:"read"` - SyncCheckpoint func(p0 context.Context, p1 types.TipSetKey) error `perm:"admin"` + SyncCheckBad func(p0 context.Context, p1 cid.Cid) (string, error) `perm:"read"` - SyncIncomingBlocks func(p0 context.Context) (<-chan *types.BlockHeader, error) `perm:"read"` + SyncCheckpoint func(p0 context.Context, p1 types.TipSetKey) error `perm:"admin"` - SyncMarkBad func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` + SyncIncomingBlocks func(p0 context.Context) (<-chan *types.BlockHeader, error) `perm:"read"` - SyncState func(p0 context.Context) (*api.SyncState, error) `perm:"read"` + SyncMarkBad func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` - SyncSubmitBlock func(p0 context.Context, p1 *types.BlockMsg) error `perm:"write"` + SyncState func(p0 context.Context) (*api.SyncState, error) `perm:"read"` - SyncUnmarkAllBad func(p0 context.Context) error `perm:"admin"` + SyncSubmitBlock func(p0 context.Context, p1 *types.BlockMsg) error `perm:"write"` - SyncUnmarkBad func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` + SyncUnmarkAllBad func(p0 context.Context) error `perm:"admin"` - SyncValidateTipset func(p0 context.Context, p1 types.TipSetKey) (bool, error) `perm:"read"` + SyncUnmarkBad func(p0 context.Context, p1 cid.Cid) error `perm:"admin"` - WalletBalance func(p0 context.Context, p1 address.Address) (types.BigInt, error) `perm:"read"` + SyncValidateTipset func(p0 context.Context, p1 types.TipSetKey) (bool, error) `perm:"read"` - WalletDefaultAddress func(p0 context.Context) (address.Address, error) `perm:"write"` + WalletBalance func(p0 context.Context, p1 address.Address) (types.BigInt, error) `perm:"read"` - WalletDelete func(p0 context.Context, p1 address.Address) error `perm:"admin"` + WalletDefaultAddress func(p0 context.Context) (address.Address, error) `perm:"write"` - WalletExport func(p0 context.Context, p1 address.Address) (*types.KeyInfo, error) `perm:"admin"` + WalletDelete func(p0 context.Context, p1 address.Address) error `perm:"admin"` - WalletHas func(p0 context.Context, p1 address.Address) (bool, error) `perm:"write"` + WalletExport func(p0 context.Context, p1 address.Address) (*types.KeyInfo, error) `perm:"admin"` - WalletImport func(p0 context.Context, p1 *types.KeyInfo) (address.Address, error) `perm:"admin"` + WalletHas func(p0 context.Context, p1 address.Address) (bool, error) `perm:"write"` - WalletList func(p0 context.Context) ([]address.Address, error) `perm:"write"` + WalletImport func(p0 context.Context, p1 *types.KeyInfo) (address.Address, error) `perm:"admin"` - WalletNew func(p0 context.Context, p1 types.KeyType) (address.Address, error) `perm:"write"` + WalletList func(p0 context.Context) ([]address.Address, error) `perm:"write"` - WalletSetDefault func(p0 context.Context, p1 address.Address) error `perm:"write"` + WalletNew func(p0 context.Context, p1 types.KeyType) (address.Address, error) `perm:"write"` - WalletSign func(p0 context.Context, p1 address.Address, p2 []byte) (*crypto.Signature, error) `perm:"sign"` + WalletSetDefault func(p0 context.Context, p1 address.Address) error `perm:"write"` - WalletSignMessage func(p0 context.Context, p1 address.Address, p2 *types.Message) (*types.SignedMessage, error) `perm:"sign"` + WalletSign func(p0 context.Context, p1 address.Address, p2 []byte) (*crypto.Signature, error) `perm:"sign"` - WalletValidateAddress func(p0 context.Context, p1 string) (address.Address, error) `perm:"read"` + WalletSignMessage func(p0 context.Context, p1 address.Address, p2 *types.Message) (*types.SignedMessage, error) `perm:"sign"` - WalletVerify func(p0 context.Context, p1 address.Address, p2 []byte, p3 *crypto.Signature) (bool, error) `perm:"read"` - } + WalletValidateAddress func(p0 context.Context, p1 string) (address.Address, error) `perm:"read"` + + WalletVerify func(p0 context.Context, p1 address.Address, p2 []byte, p3 *crypto.Signature) (bool, error) `perm:"read"` } type FullNodeStub struct { @@ -425,71 +427,73 @@ type FullNodeStub struct { } type GatewayStruct struct { - Internal struct { - ChainGetBlockMessages func(p0 context.Context, p1 cid.Cid) (*api.BlockMessages, error) `` + Internal GatewayMethods +} - ChainGetMessage func(p0 context.Context, p1 cid.Cid) (*types.Message, error) `` +type GatewayMethods struct { + ChainGetBlockMessages func(p0 context.Context, p1 cid.Cid) (*api.BlockMessages, error) `` - ChainGetTipSet func(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) `` + ChainGetMessage func(p0 context.Context, p1 cid.Cid) (*types.Message, error) `` - ChainGetTipSetByHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `` + ChainGetTipSet func(p0 context.Context, p1 types.TipSetKey) (*types.TipSet, error) `` - ChainHasObj func(p0 context.Context, p1 cid.Cid) (bool, error) `` + ChainGetTipSetByHeight func(p0 context.Context, p1 abi.ChainEpoch, p2 types.TipSetKey) (*types.TipSet, error) `` - ChainHead func(p0 context.Context) (*types.TipSet, error) `` + ChainHasObj func(p0 context.Context, p1 cid.Cid) (bool, error) `` - ChainNotify func(p0 context.Context) (<-chan []*api.HeadChange, error) `` + ChainHead func(p0 context.Context) (*types.TipSet, error) `` - ChainPutObj func(p0 context.Context, p1 blocks.Block) error `` + ChainNotify func(p0 context.Context) (<-chan []*api.HeadChange, error) `` - ChainReadObj func(p0 context.Context, p1 cid.Cid) ([]byte, error) `` + ChainPutObj func(p0 context.Context, p1 blocks.Block) error `` - GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *api.MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) `` + ChainReadObj func(p0 context.Context, p1 cid.Cid) ([]byte, error) `` - MpoolPush func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `` + GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *api.MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) `` - MsigGetAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `` + MpoolPush func(p0 context.Context, p1 *types.SignedMessage) (cid.Cid, error) `` - MsigGetPending func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*api.MsigTransaction, error) `` + MsigGetAvailableBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (types.BigInt, error) `` - MsigGetVested func(p0 context.Context, p1 address.Address, p2 types.TipSetKey, p3 types.TipSetKey) (types.BigInt, error) `` + MsigGetPending func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]*api.MsigTransaction, error) `` - StateAccountKey func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `` + MsigGetVested func(p0 context.Context, p1 address.Address, p2 types.TipSetKey, p3 types.TipSetKey) (types.BigInt, error) `` - StateDealProviderCollateralBounds func(p0 context.Context, p1 abi.PaddedPieceSize, p2 bool, p3 types.TipSetKey) (api.DealCollateralBounds, error) `` + StateAccountKey func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `` - StateGetActor func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*types.Actor, error) `` + StateDealProviderCollateralBounds func(p0 context.Context, p1 abi.PaddedPieceSize, p2 bool, p3 types.TipSetKey) (api.DealCollateralBounds, error) `` - StateGetReceipt func(p0 context.Context, p1 cid.Cid, p2 types.TipSetKey) (*types.MessageReceipt, error) `` + StateGetActor func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*types.Actor, error) `` - StateListMiners func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `` + StateGetReceipt func(p0 context.Context, p1 cid.Cid, p2 types.TipSetKey) (*types.MessageReceipt, error) `` - StateLookupID func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `` + StateListMiners func(p0 context.Context, p1 types.TipSetKey) ([]address.Address, error) `` - StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MarketBalance, error) `` + StateLookupID func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `` - StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*api.MarketDeal, error) `` + StateMarketBalance func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MarketBalance, error) `` - StateMinerInfo func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MinerInfo, error) `` + StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*api.MarketDeal, error) `` - StateMinerPower func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*api.MinerPower, error) `` + StateMinerInfo func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (api.MinerInfo, error) `` - StateMinerProvingDeadline func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*dline.Info, error) `` + StateMinerPower func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*api.MinerPower, error) `` - StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (abinetwork.Version, error) `` + StateMinerProvingDeadline func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*dline.Info, error) `` - StateSearchMsg func(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) `` + StateNetworkVersion func(p0 context.Context, p1 types.TipSetKey) (abinetwork.Version, error) `` - StateSectorGetInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorOnChainInfo, error) `` + StateSearchMsg func(p0 context.Context, p1 cid.Cid) (*api.MsgLookup, error) `` - StateVerifiedClientStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `` + StateSectorGetInfo func(p0 context.Context, p1 address.Address, p2 abi.SectorNumber, p3 types.TipSetKey) (*miner.SectorOnChainInfo, error) `` - StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64) (*api.MsgLookup, error) `` + StateVerifiedClientStatus func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*abi.StoragePower, error) `` - Version func(p0 context.Context) (api.APIVersion, error) `` + StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64) (*api.MsgLookup, error) `` - WalletBalance func(p0 context.Context, p1 address.Address) (types.BigInt, error) `` - } + Version func(p0 context.Context) (api.APIVersion, error) `` + + WalletBalance func(p0 context.Context, p1 address.Address) (types.BigInt, error) `` } type GatewayStub struct { diff --git a/build/actors/v10.tar.zst b/build/actors/v10.tar.zst index b0c9e5ce86e..d3a8e0a1e6d 100644 Binary files a/build/actors/v10.tar.zst and b/build/actors/v10.tar.zst differ diff --git a/build/builtin_actors_gen.go b/build/builtin_actors_gen.go index 38d4c49ed77..1f13ac6ed86 100644 --- a/build/builtin_actors_gen.go +++ b/build/builtin_actors_gen.go @@ -53,24 +53,24 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet }, { Network: "butterflynet", Version: 10, - ManifestCid: MustParseCid("bafy2bzaced2wq4k4i2deknam6ehbynaoo37bhysud7eze7su3ftlaggwwjuje"), + ManifestCid: MustParseCid("bafy2bzacedsgi3wpyd46hbktrleolnlepzsm6k466fcrxuc7keht4guokgxiy"), Actors: map[string]cid.Cid{ - "account": MustParseCid("bafk2bzacebd5zetyjtragjwrv2nqktct6u2pmsi4eifbanovxohx3a7lszjxi"), - "cron": MustParseCid("bafk2bzacecrszortqkc7har77ssgajglymv6ftrqvmdko5h2yqqh5k2qospl2"), - "datacap": MustParseCid("bafk2bzacecapjnxnyw4talwqv5ajbtbkzmzqiosztj5cb3sortyp73ndjl76e"), - "eam": MustParseCid("bafk2bzacebsvtqzp7g7vpufbyqrwwcpuo2yu3y7kenm7auidyiwzcv6jdw724"), - "ethaccount": MustParseCid("bafk2bzacedl4pmkfxkzoqajs6im3ranmopozsmxjcxsnk3kwvd3vv7mfwwrf4"), - "evm": MustParseCid("bafk2bzacedx5wdyaihi22pwqqqtfxmuwh5acem46mzaep3znmhh5bsuqmxogq"), - "init": MustParseCid("bafk2bzacecbxp66q3ytjkg37nyv4rmzezbfaigvx4i5yhvqbm5gg4amjeaias"), - "multisig": MustParseCid("bafk2bzacecjltag3mn75dsnmrmopjow27buxqhabissowayqlmavrcfetqswc"), - "paymentchannel": MustParseCid("bafk2bzacednzxg263eqbl2imwz3uhujov63tjkffieyl4hl3dhrgxyhwep6hc"), - "placeholder": MustParseCid("bafk2bzaceaamp2a35vpfml4skap4dffklzae2urcm34mtwwce2lvhaons3a5y"), - "reward": MustParseCid("bafk2bzacectp23cxsbbdrr3uggnw7f263qll5wkkfzqhn5yq37ae2ehdjdzri"), - "storagemarket": MustParseCid("bafk2bzacea45ko3ezkpeujsniovncwnizc4wsxd7kyckskhs7gvzwthzb2mqe"), - "storageminer": MustParseCid("bafk2bzaced74qthwrl3gahcf7o3vrdrodbcqhlplh6fykbgy5sd2iyouhq44c"), - "storagepower": MustParseCid("bafk2bzaceduksv6wqthr5fgp7mx5prv6gzul2oozf3svrjbuggc4bgokdxgfy"), - "system": MustParseCid("bafk2bzacebe6j2ius6clbbr7dypsg54jzmn5xablzunph7ebedw6yhwla4cj2"), - "verifiedregistry": MustParseCid("bafk2bzacebu4joy25gneu2qv3qfm3ktakzalndjrbhekeqrqk3zhotv6nyy2g"), + "account": MustParseCid("bafk2bzacebz7dm3vcuqtzzcf5jwvcubz6ecqk52t5rsd36fyzka2iosy4l4ro"), + "cron": MustParseCid("bafk2bzacea6qtj2wkbe2wq5vxc2knlnj3vdvk4bkjp36xtazgzhnegd2uaj7m"), + "datacap": MustParseCid("bafk2bzacedwxkx3jz7qwv5iwozadz7t5hhw5dtlgdxuwqxdp6oqguas7nakjk"), + "eam": MustParseCid("bafk2bzacedoegh4idwvhjqahfnbqq6aqzgccgjwumudx6ihfut36ng57or7fi"), + "ethaccount": MustParseCid("bafk2bzacebn6l3x7d2i6lv72osbgcl4a37imexh5ou5kvbmj56taetwcyyhgq"), + "evm": MustParseCid("bafk2bzaced5gaxg5mz3hho473aszx5brgjriicqgrcbqctnyyn2e6vcxv3ule"), + "init": MustParseCid("bafk2bzacecbo6ggprh7sz3oy6uu5raykwngqmnjdsiijdrgp4glet3mb65ywo"), + "multisig": MustParseCid("bafk2bzacecmu3bhbg4rh5sqbagjlvrpb6ip5k3pngq22a33ok44yuhk75zenq"), + "paymentchannel": MustParseCid("bafk2bzacebth7fqe5xts6hbm7m6n733qcu6b6atd7ur6l7jhddferjgpxdy4s"), + "placeholder": MustParseCid("bafk2bzacedfvut2myeleyq67fljcrw4kkmn5pb5dpyozovj7jpoez5irnc3ro"), + "reward": MustParseCid("bafk2bzaceds7hy7v77k2jsbkfob7b2qor6v5s2oancfxhkuuzwqqg6kxk27xe"), + "storagemarket": MustParseCid("bafk2bzacebqi6ylwfmack3hfzw6eej7r6gwlbxzo33tdkfkpof7wg7h54pjtw"), + "storageminer": MustParseCid("bafk2bzacedsxpkqqiycn5tjydycnlqer4544mpqvtwfamwyq6hwz7yjqd3iry"), + "storagepower": MustParseCid("bafk2bzacedssirrse7ufxti6capgf2qufb6y3oatv2fnnnh7xrgp47x3hfox4"), + "system": MustParseCid("bafk2bzacea2lod7lxod72voxyik5btpzmpvduddr4hwshcsyyy257izh6kut4"), + "verifiedregistry": MustParseCid("bafk2bzacebss7ol4ay6nkg7r3c2355aqpku4yvqipyh3sgdrxkhsrssrsaaig"), }, }, { Network: "calibrationnet", @@ -110,24 +110,24 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet }, { Network: "calibrationnet", Version: 10, - ManifestCid: MustParseCid("bafy2bzacearpwvmcqlailxyq2d2wtzmtudxqhvfot77tbdqotek5qiq5hyhzg"), + ManifestCid: MustParseCid("bafy2bzacec4ilfymf3sorrfxp67ruwbax3a4mbqzic63vy2xlfh3ulky3bxvs"), Actors: map[string]cid.Cid{ - "account": MustParseCid("bafk2bzacea7zmrdz2rjbzlbmrmx3ko6pm3cbyqxxgogiqldsccbqffuok7m6s"), - "cron": MustParseCid("bafk2bzacec7bxugi7ouh75nglycy7qwdq7e2hnku3w6yafq4fwdwvvq2mtrl2"), - "datacap": MustParseCid("bafk2bzacedii4stmlo3ccdff7eevcolmgnuxy5ftkzbzwtkqa4iinlfzq4mei"), - "eam": MustParseCid("bafk2bzacedykxiyewqijj5nksr7qi6o4wu5yz4rezb747ntql4rpidyfdpes4"), - "ethaccount": MustParseCid("bafk2bzacecgbcbh3uk7olcfdqo44no5nxxayeqnycdznrlekqigbifor2revm"), - "evm": MustParseCid("bafk2bzaceau5n66rabegik55kymni6uyk7n7jb5eymfywybs543yifpl7du2m"), - "init": MustParseCid("bafk2bzacea7lxnvgxupwwgoxlmwtrca75w73qabe324wnwx43qranbgf5zdqo"), - "multisig": MustParseCid("bafk2bzacear5eu5gpbjlroqkmsgpqerzc4aemp2uqcaeq7s2h4ur4ucgpzesg"), - "paymentchannel": MustParseCid("bafk2bzacecwxuruxawcru7xfcx3rmt4hmhlfh4hi6jvfumerazz6jpvfmxxcw"), - "placeholder": MustParseCid("bafk2bzaceaamp2a35vpfml4skap4dffklzae2urcm34mtwwce2lvhaons3a5y"), - "reward": MustParseCid("bafk2bzacebk4syfvyk7kbxelk7ajo4vuxcc24k5ry52mvi3qtadlucy2vqlay"), - "storagemarket": MustParseCid("bafk2bzaced2rfzwup3jlwovblx2y7q64w6mshbtn2nmampi4zfd3b4oplkp5c"), - "storageminer": MustParseCid("bafk2bzacecden66gfmmgylmr47myn4murqmbt3ycyxqayn54yzhcsda32rp3m"), - "storagepower": MustParseCid("bafk2bzacebxvco3shuhdnzjmmme3olbffdgpab7j3onfncksi762k3agjhzaa"), - "system": MustParseCid("bafk2bzacednnhpk5kno67bkomiohweglryqvgnqz4cbks6eomidai677fat5w"), - "verifiedregistry": MustParseCid("bafk2bzaceawecz24xbz7robn7ck7k2mprkewvup6q346whbfiybcrvy63qcsa"), + "account": MustParseCid("bafk2bzacecupizfd6xbts7blvn3ozouy3f2gtehwl7qohjks54nsomtzs3aki"), + "cron": MustParseCid("bafk2bzacedry7eqweymdnybq5jm5slizm67v4ffhv7zqiw2jwevr7ijv25gjc"), + "datacap": MustParseCid("bafk2bzacebq6vigteuwchk7si6y45ogrfu2zpxjbo4a54btnbhp3rc3ifghx6"), + "eam": MustParseCid("bafk2bzacebounosssmuaz35xpyuupvijbcwqyaumbeztqmigbihfw2ysbnx4w"), + "ethaccount": MustParseCid("bafk2bzacebi2ymbi5wo2o3rp2x6cqo55vroixngmpbdcs7el4rq4hvacyzsqy"), + "evm": MustParseCid("bafk2bzaceapklwjzdzkmnfprn5wsjdzjnueuw2ke4kixq46gnbwjncns4dleu"), + "init": MustParseCid("bafk2bzaced7u4zpkxh5ecjo2emwsrk3vnickhmkxy22garqf766nbxcewymy6"), + "multisig": MustParseCid("bafk2bzacedlunqzd3mxslb7zej5fsti2jxredfhtcqqxepng67t4zfiv6lwlc"), + "paymentchannel": MustParseCid("bafk2bzacea4z2yi33rfiiutkmqko33fslikmeqgypkiam5cqpeylyp3oup552"), + "placeholder": MustParseCid("bafk2bzacedfvut2myeleyq67fljcrw4kkmn5pb5dpyozovj7jpoez5irnc3ro"), + "reward": MustParseCid("bafk2bzacea4dnvun5vwzunhgepejrknukx2di2kmo3x4akz6rollq5icsrl3m"), + "storagemarket": MustParseCid("bafk2bzaceafoon3fsl756rbrih4upar3ayi6746gaj756bk56thncpotl4coa"), + "storageminer": MustParseCid("bafk2bzacea3dj37h74ue2jtief3bj2shxagigygcm2h6purgp42mr6swwfdiw"), + "storagepower": MustParseCid("bafk2bzacebmodckd4tustgfmeilcfi3ovd4wzxz2hnd6vyhkq7hgiojiy3cc6"), + "system": MustParseCid("bafk2bzacebpqirxha42noejsk5miv5kip44eay6lm63pxt26xhlwdmn7tnqaq"), + "verifiedregistry": MustParseCid("bafk2bzaceczf7qrddwt5kh3gvro25wpls346tanffeatk7nsczjnwb7jtd454"), }, }, { Network: "caterpillarnet", @@ -176,24 +176,24 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet }, { Network: "caterpillarnet", Version: 10, - ManifestCid: MustParseCid("bafy2bzacebxr4uvnf5g3373shjzbaca6pf4th6nnfubytjfbrlxcpvbjw4ane"), + ManifestCid: MustParseCid("bafy2bzacec36gpvghhgjwa5ya3ocxg33pct2vddegeixgkpqsc6eiyajdjkii"), Actors: map[string]cid.Cid{ - "account": MustParseCid("bafk2bzacedfms6w3ghqtljpgsfuiqa6ztjx7kcuin6myjezj6rypj3zjbqms6"), - "cron": MustParseCid("bafk2bzaceaganmlpozvy4jywigs46pfrtdmhjjey6uyhpurplqbasojsislba"), - "datacap": MustParseCid("bafk2bzacebafqqe3wv5ytkfwmqzbmchgem66pw6yq6rl7w6vlhqsbkxnisswq"), - "eam": MustParseCid("bafk2bzacedwk5eqczflcsuisqsyeomgkpg54olojjq2ieb2ozu5s45wfwluti"), - "ethaccount": MustParseCid("bafk2bzaceburkmtd63nmzxpux5rcxsbqr6x5didl2ce7al32g4tqrvo4pjz2i"), - "evm": MustParseCid("bafk2bzacedbroioygjnbjtc7ykcjjs4wfbwnaa6gkzubi7c5enifoqqqu66s6"), - "init": MustParseCid("bafk2bzaced23r54kwuebl7t6mdantbby5qpfduxwxfryeliof2enyqzhokix6"), - "multisig": MustParseCid("bafk2bzacebcn3rib6j6jvclys7dkf62hco45ssgamczkrtzt6xyewd6gt3mtu"), - "paymentchannel": MustParseCid("bafk2bzacecvas4leo44pqdguj22nnwqoqdgwajzrpm5d6ltkehc37ni6p6doq"), - "placeholder": MustParseCid("bafk2bzaceaamp2a35vpfml4skap4dffklzae2urcm34mtwwce2lvhaons3a5y"), - "reward": MustParseCid("bafk2bzacebiizh4ohvv6p4uxjusoygex4wxcgvudqmdl2fsh6ft6s2zt4tz6q"), - "storagemarket": MustParseCid("bafk2bzacedhkidshm7w2sqlw7izvaieyhkvmyhfsem6t6qfnkh7dnwqe56po2"), - "storageminer": MustParseCid("bafk2bzacedcmsibwfwhkp3sabmbyjmhqibyhjf3wwst7u5bkb2k6xpun3xevg"), - "storagepower": MustParseCid("bafk2bzacecrgnpypxnxzgglhlitaallfee3dl4ejy3y63knl7llnwba4ycf7i"), - "system": MustParseCid("bafk2bzacecl7gizbe52xj6sfm5glubkhrdblmzuwlid6lxrwr5zhcmv4dl2ew"), - "verifiedregistry": MustParseCid("bafk2bzacebzndvdqtdck2y35smcxezldgh6nm6rbkj3g3fmiknsgg2uah235y"), + "account": MustParseCid("bafk2bzacebcl3xlk7i6t5tau2rfgxft5pu6qzvjqxo6zs5guerz3xarxztyv6"), + "cron": MustParseCid("bafk2bzacebhoqjvaxtzj3k4tz7c4vtt4or4u3h3jhwxlh3t4l6by2ota3s7by"), + "datacap": MustParseCid("bafk2bzaceb7ttn3d43yb7l5ok5rjgr7325jb6ds4air7mivgoyzp5p4gwgrq4"), + "eam": MustParseCid("bafk2bzacebobuasaev75fge6xg6bekrdvnyox4h7iluupt4wqq2n4expha2oe"), + "ethaccount": MustParseCid("bafk2bzaceaghtv45mm6qx3yrxwy7zz7x7mqj4n4lzw4hx7zxzlij6dcxxuv4c"), + "evm": MustParseCid("bafk2bzacecu7xpnpw27jquvnpfv4rseaal477ml4ouxy37eo7wymgfzkexllg"), + "init": MustParseCid("bafk2bzacea2rnkho4nliqvisiqgtqx66c4xneagpgj52tyqa64grxadggylbk"), + "multisig": MustParseCid("bafk2bzacebak6spthfa23cyqjmpgkgku4gg4egdn2zc6vkikbh5ongadzakma"), + "paymentchannel": MustParseCid("bafk2bzaceb3tib72pwze2rov72ldwlfv3otes3tejgnfpbrzahwb5xi7slhqm"), + "placeholder": MustParseCid("bafk2bzacedfvut2myeleyq67fljcrw4kkmn5pb5dpyozovj7jpoez5irnc3ro"), + "reward": MustParseCid("bafk2bzaceak3n3orgdraub4bqiy3paio77hu4laaqv4vf7wmwv4ybl5ahgi5o"), + "storagemarket": MustParseCid("bafk2bzacearo7sog7yqbrwyws5o3lbsdsjf2cp5vsoxc4u3s5atgjtwzzh65s"), + "storageminer": MustParseCid("bafk2bzacecrzmjrbqjwknnkybdexspb6gfu4q6dvtaeguxl26yuytsjc3w7ws"), + "storagepower": MustParseCid("bafk2bzaceavlmlu4mt2u7xwnnzf6vwdmh2yo76aauujwlgsbfhafjgxb4zgtg"), + "system": MustParseCid("bafk2bzacec35rgzpiaa4n3r5bzgssk33bhfgozjvgunbwax32dooqqokfe6ag"), + "verifiedregistry": MustParseCid("bafk2bzacebjfkrzihgzlb2jecgm5seoqwf5e656zc22vjoyclioru6vdy2bnm"), }, }, { Network: "devnet", @@ -233,24 +233,24 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet }, { Network: "devnet", Version: 10, - ManifestCid: MustParseCid("bafy2bzacebixrjysarwxdadewlllfp4rwfoejxstwdutghghei54uvuuxlsbq"), + ManifestCid: MustParseCid("bafy2bzacebemt6rdgtsj5vhv2iimbdvm5g4xllgl7nugxvuuthsedncmfakww"), Actors: map[string]cid.Cid{ - "account": MustParseCid("bafk2bzacebb5txxkfexeaxa2th3rckxsxchzyss3ijgqbicf265h7rre2rvhm"), - "cron": MustParseCid("bafk2bzacecotn4gwluhamoqwnzgbg7ogehv26o5xnhjzltnzfv6utrlyanzek"), - "datacap": MustParseCid("bafk2bzacea4hket2srrtbewkf3tip6ellwpxdfbrzt5u47y57i2k6iojqqgba"), - "eam": MustParseCid("bafk2bzacecxm2gr6tevzzan6oqp6aiqydjm5b7eo34mlzo5jdm7mnlbbueikq"), - "ethaccount": MustParseCid("bafk2bzacedh4y3zvtgft3i6ift4rpptgr2dx67pvenowvq7yaspuf25gqgcdc"), - "evm": MustParseCid("bafk2bzacec26myls7vg6anr5yjbb2r75dryhdzwlwnrhjcyuhahlaoxdrua6i"), - "init": MustParseCid("bafk2bzacedof2ckc6w2qboxzxv4w67njcug4ut4cq3nnlrfybzsvlgnp4kt24"), - "multisig": MustParseCid("bafk2bzacec4eqajjqhl53tnkbs7glu7njlbtlditi7lxhvw33ezmxk6jae46y"), - "paymentchannel": MustParseCid("bafk2bzacec6nvdprqja7dy3qp5islebbbh2ifiyg2p7arbe6pocjhfe6xwkfy"), - "placeholder": MustParseCid("bafk2bzaceaamp2a35vpfml4skap4dffklzae2urcm34mtwwce2lvhaons3a5y"), - "reward": MustParseCid("bafk2bzacecqaoqksjotl4wwsqt2wf6kqv6s372afi3r5on4bqj3u3a44px2rm"), - "storagemarket": MustParseCid("bafk2bzaceb7yefqlzyoxkgoug5k4kizy63izrg5udartw5l4d6j53xjwdxbg4"), - "storageminer": MustParseCid("bafk2bzaceagmuxcgdj65yuvtfrcup5viwkhhhlzslpdd4j6v6qxmhxtcssc6u"), - "storagepower": MustParseCid("bafk2bzacedt2qu6ykj3bjsfhchg2gxvc6asfb7c4tmranl76n4ojut5d6sgqm"), - "system": MustParseCid("bafk2bzacebp4ysxqv4cy633pgdxjlbwkwqkokc2fgez77y73abpt5hkthczn6"), - "verifiedregistry": MustParseCid("bafk2bzaceb7odugx7meltvt2gra4vogn2g6avbgysivvdccldylusjcfsnfhy"), + "account": MustParseCid("bafk2bzaceajmds6zbz235lbjjhv3mxc6x3kqudjkxedh5xqvlemh3f6xslz76"), + "cron": MustParseCid("bafk2bzaceabbv5ej2yd3n7txl3s4pahknb4in5dok57hzwfheqnk6k67zegbk"), + "datacap": MustParseCid("bafk2bzaceayzgq7qpuc5pr4lrh6k3xnvmirlmutffplmgur4pvcaynpxlkph6"), + "eam": MustParseCid("bafk2bzacecrand7mp7q3jm3u5dpqm4o24ki3pk3uzcw4zonjcowq4rxwptsis"), + "ethaccount": MustParseCid("bafk2bzacecpwfxpvqiyiisbfw45v5ottcstxu2vifji3xswxt3jzk4vcrs4g4"), + "evm": MustParseCid("bafk2bzaceajrtntc5urxkwbzdu3khi2eqvarnfx6vh7luqt33gn6z4a4kjkj6"), + "init": MustParseCid("bafk2bzaced6npj5zrjb3lxhgtsq4st66dvde56nftbvchmpid3rcazfvnqkpk"), + "multisig": MustParseCid("bafk2bzacealhbd4slci4o76dpdurkkk3q5busopediwfh7uis4hfh7tzghzni"), + "paymentchannel": MustParseCid("bafk2bzacebvpkvrihus53sdyutsjsbpfefe5gd2amfb6zkztdfp6g2m4ubqrk"), + "placeholder": MustParseCid("bafk2bzacedfvut2myeleyq67fljcrw4kkmn5pb5dpyozovj7jpoez5irnc3ro"), + "reward": MustParseCid("bafk2bzaceaftaidppnno2dzhpxl5vyti5mcmdhvheieanwvptgacuj5ozzloe"), + "storagemarket": MustParseCid("bafk2bzacea75td2k2cdwc2o4kotdods2thomhcoqg5rf62ty6gkuxojknziae"), + "storageminer": MustParseCid("bafk2bzaceapj5q7egywl3zovwcm4hpbvr4vjtoshj57ncqg3srzseweyclvug"), + "storagepower": MustParseCid("bafk2bzacebbraebsoin6hhmr4na56st4gyg7yd7p2ry2igegnvws7deq32hec"), + "system": MustParseCid("bafk2bzacedtw3mq5zyxxbnybnjegqyrz3ufiboeoipyzynlk6zgyumvl3267g"), + "verifiedregistry": MustParseCid("bafk2bzacecaqciqoky2z7win5rkzd3gkgpa3345adjyiidmg4swmw5celeb3a"), }, }, { Network: "hyperspace", @@ -296,28 +296,6 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet "system": MustParseCid("bafk2bzacedo2hfopt6gy52goj7fot5qwzhtnysmgo7h25crq4clpugkerjabk"), "verifiedregistry": MustParseCid("bafk2bzacea7rfkjrixaidksnmjehglmavyt56nyeu3sfxu2e3dcpf62oab6tw"), }, -}, { - Network: "hyperspace", - Version: 10, - ManifestCid: MustParseCid("bafy2bzaced6hc7ujjmypg6mkrxdmf32oh2udhmhpmwkqyxusdkxoi2uoodyxg"), - Actors: map[string]cid.Cid{ - "account": MustParseCid("bafk2bzacecim7uybic2qprbkjhowg7qkniv4zywj5h5g4u4ss72urco2akzuo"), - "cron": MustParseCid("bafk2bzaceahgq64awp4f7li3hdgimc4upqvdvltpmeywckvens33umcxt424a"), - "datacap": MustParseCid("bafk2bzacebkxn52ttooaslkwncijk3bgd3tm2zw7vijdhwvg2cxnxbrzmmq5e"), - "eam": MustParseCid("bafk2bzaceaftiqwpx6dcjfqxyq7pazn2p55diukf32pz74755vj7pgg5joexw"), - "ethaccount": MustParseCid("bafk2bzacealn5enbxyxbfs7gbsjbyma2zk3bcr7okvflxhpr753d4eh6ixooa"), - "evm": MustParseCid("bafk2bzacea6etsvrqejjl7uej5dxlswja5gxzqyggsjjvg27timvtiedf7nsg"), - "init": MustParseCid("bafk2bzacec55gyyaqjrw7zughywocgwcjvv6k5fijjpjw4xgckuqz6pjtff5a"), - "multisig": MustParseCid("bafk2bzaceblozbdzybdivvjdiid4jwm2jc6x5a66sunh2vvwsqba6wzqmr7i6"), - "paymentchannel": MustParseCid("bafk2bzacealcyke5a6n24efs6qe4iikynpk2twqssyugy7jcyf6p6shgw2iwa"), - "placeholder": MustParseCid("bafk2bzaceaamp2a35vpfml4skap4dffklzae2urcm34mtwwce2lvhaons3a5y"), - "reward": MustParseCid("bafk2bzacebafzaqhwsm3nmsfwcd6ngvx6ev6zlcpyfljqh4kb77vok6opban6"), - "storagemarket": MustParseCid("bafk2bzacecrjfg4p7fxznsdkoobs4po2ve3ywixrirrk6netgxh63qqaefamg"), - "storageminer": MustParseCid("bafk2bzaceb3ctd4atxwhdkmlg4i63zxo5aopknlj7l5kaiqr22xpcmico6vg4"), - "storagepower": MustParseCid("bafk2bzacecvcix3ugopvby2vah5wwiu5cqjedwzwkanmr34kdoc4f3o6p7nsq"), - "system": MustParseCid("bafk2bzacedo2hfopt6gy52goj7fot5qwzhtnysmgo7h25crq4clpugkerjabk"), - "verifiedregistry": MustParseCid("bafk2bzacea7rfkjrixaidksnmjehglmavyt56nyeu3sfxu2e3dcpf62oab6tw"), - }, }, { Network: "mainnet", Version: 8, @@ -356,24 +334,24 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet }, { Network: "mainnet", Version: 10, - ManifestCid: MustParseCid("bafy2bzacea5vylkbby7rb42fknkk4g4byhj7hkqlxp4z4urydi3vlpwsgllik"), + ManifestCid: MustParseCid("bafy2bzacec2ggeabyyl2cjaqmcpnyvjirrrm6bfc7d73q4pekm27hybzdqs3q"), Actors: map[string]cid.Cid{ - "account": MustParseCid("bafk2bzacedsn6i2flkpk6sb4iuejo7gfl5n6fhsdawggtbsihlrrjtvs7oepu"), - "cron": MustParseCid("bafk2bzacecw4guere7ba2canyi2622lw52b5qbn7iubckcp5cwlmx2kw7qqwy"), - "datacap": MustParseCid("bafk2bzaceat2ncckd2jjjqcovd3ib4sylwff7jk7rlk6gr5d2gmrrc7isrmu2"), - "eam": MustParseCid("bafk2bzacebbpu5smjrjqpkrvvlhcpk23yvlovlndqmwzhfz5kuuph54tdw732"), - "ethaccount": MustParseCid("bafk2bzacedmwzkbytxfn7exmxxosomvix4mpyxrmupeqw45aofqmdq5q7mgqe"), - "evm": MustParseCid("bafk2bzacechkf43lmddynxmc35hvz5kwr3fdxrbg6fxbcvysfsihgiopbrb7o"), - "init": MustParseCid("bafk2bzacec6276d7ls3hhuqibqorn3yp45mv7hroczf3bgb6jkhmbb2zqt3bw"), - "multisig": MustParseCid("bafk2bzaceahggxrnjj3w3cgtko54srssqyhcs4x6y55ytego6jf2owg5piw3y"), - "paymentchannel": MustParseCid("bafk2bzaceaobaqjamso57bkjv3n4ilv7lfropgrncnnej666w3tegmr4cfgve"), - "placeholder": MustParseCid("bafk2bzaceaamp2a35vpfml4skap4dffklzae2urcm34mtwwce2lvhaons3a5y"), - "reward": MustParseCid("bafk2bzacecqet4s7abe4owznq2wtdefe2z2w5isbde2gj7u3hwgf54di4r7hy"), - "storagemarket": MustParseCid("bafk2bzacebgk2q2ktrqauzop6ha4pcq5gpf6g24hprxnp6wdmlzf724e5sx7i"), - "storageminer": MustParseCid("bafk2bzacecqrm4tlmzci7vilmcchr4lq2e6yyrlhy6ofbuecjna2phmbq4h2a"), - "storagepower": MustParseCid("bafk2bzaceco674a5e5lpv5leui65bljxzgyc2ypdquaow55iuckmq5rvsghr6"), - "system": MustParseCid("bafk2bzacedlt3zcsbw2vucbydptbcfudw5y5pkhhxe26m7pjod6rkxkuzn52w"), - "verifiedregistry": MustParseCid("bafk2bzacea2eehyf7h3m6ydh46piu2gtr4fawpqzh3brtmybgi2tyxf5nwj6m"), + "account": MustParseCid("bafk2bzacebdlwwnd57vd2444wrfe5amtf2f6htqj3hdh4fxblywdbynrurhgy"), + "cron": MustParseCid("bafk2bzacecxmaxh272zhgmayfg7btvq5lshv2cd7njkarlbbikba4otiaboyg"), + "datacap": MustParseCid("bafk2bzaceb64wicovvrjzaotvs64hmdtvolw4l6qanwp5tk56okzqbfttxck2"), + "eam": MustParseCid("bafk2bzacedxs56zywfumzcv7i5fwluku2qevg54cuiuwi5d3pavf3rilfu33g"), + "ethaccount": MustParseCid("bafk2bzacecepsmgsucfebvbwf5vebm7j6zeqaz3ub52warxqobqeymh5vdjik"), + "evm": MustParseCid("bafk2bzacecf6arqbso67nmrhcsjvyradrbbv7hs2noand27fyr4nfilms4znu"), + "init": MustParseCid("bafk2bzaceat2xcem5lko5ot4mmrowtm6ehx5klw7c4ss4vxma55tyfvvxwlge"), + "multisig": MustParseCid("bafk2bzacebz43omxi5vtkidhsxroqtgkpxtftdj6poew3744fayfftgdebe4y"), + "paymentchannel": MustParseCid("bafk2bzaceds4ob3ev2ie2vorhfomddd44otqfau4d4eogfofjjbjjx2h27nh2"), + "placeholder": MustParseCid("bafk2bzacedfvut2myeleyq67fljcrw4kkmn5pb5dpyozovj7jpoez5irnc3ro"), + "reward": MustParseCid("bafk2bzaced7xvqx7n6426lls4ao54exn63pv73m7makxf7ygb575roqxhjuuw"), + "storagemarket": MustParseCid("bafk2bzaceb5piewkvdj4ee6b4qzhimixjzee5z3hsuwdjksncpvef7sgaw6rw"), + "storageminer": MustParseCid("bafk2bzaceacukfushmnsqtdvtdyx2in6o2el7jq46qo7iaxgwytel4oz5srv4"), + "storagepower": MustParseCid("bafk2bzacedi6z45jcms5guns4qxi6rs2e2prc6mpnhkr4klljrra3ayfburss"), + "system": MustParseCid("bafk2bzacedy7ssu2hez3nu7bi4j6ucojty4sfaublxlxhfd3tkgzyrm5sdxbq"), + "verifiedregistry": MustParseCid("bafk2bzacecjgudirfyzyroq3xhf2bldl636w7prexcvo7v3xqdijzcom4rgry"), }, }, { Network: "testing", @@ -413,24 +391,24 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet }, { Network: "testing", Version: 10, - ManifestCid: MustParseCid("bafy2bzacea7tbn4p232ecrjvlp2uvpci5pexqjqq2vpv4t5ihktpja2zsj3ek"), + ManifestCid: MustParseCid("bafy2bzacedhivj4zbumou6d3242p3ecqhlqfcjfskdv46uzjchlj3ve23xyoa"), Actors: map[string]cid.Cid{ - "account": MustParseCid("bafk2bzaceds3iy5qjgr3stoywxt4uxvhybca23q7d2kxhitedgudrkhxaxa6o"), - "cron": MustParseCid("bafk2bzacebxp4whb4ocqxnbvqlz3kckarabtyvhjbhqvrdwhejuffwactyiss"), - "datacap": MustParseCid("bafk2bzacedepm3zas6vqryruwiz7d3axkneo7v66q65gf2dlpfd53pjlycrg4"), - "eam": MustParseCid("bafk2bzacea2uascrtv6xnsqlxyf3tcf4onpgrs7frh55p6dnrdeum2uup7wx4"), - "ethaccount": MustParseCid("bafk2bzacecbhz4ipg773lsovgpjysm6fxl2i7y2wuxadqnt4s4vm3nd2qodb4"), - "evm": MustParseCid("bafk2bzaceabwn4i62od3i4qkuj5zx4vn5w5cbcl53tqnszk6kl43bfl55hl6c"), - "init": MustParseCid("bafk2bzacebqym5i5eciyyyzsimu73z6bkffpm5hzjpx3gwcm64pm2fh7okrja"), - "multisig": MustParseCid("bafk2bzacecmlyngek7qvj5ezaaitadrycapup3mbty4ijlzun6g23tcoysxle"), - "paymentchannel": MustParseCid("bafk2bzacedspin4hxpgnxkjen3hsxpcc52oc5q4ypukl4qq6vaytcgmmi7hl4"), - "placeholder": MustParseCid("bafk2bzaceaamp2a35vpfml4skap4dffklzae2urcm34mtwwce2lvhaons3a5y"), - "reward": MustParseCid("bafk2bzacecmumnnqkqnoa23hhsfgwccwvmksr2q65tznbves6x2a6fhwvtm7a"), - "storagemarket": MustParseCid("bafk2bzacea2re4nxba7mtlrwdxabu2i3l2fwbuw2veb4p7qbvrsaocgablqvi"), - "storageminer": MustParseCid("bafk2bzacecixm7d7d5ltsp6mubzw5s3fv335cjuwwy7oqovujn3xlyk6twivs"), - "storagepower": MustParseCid("bafk2bzaced5lqpftacjsflcgfwlm32gzckpi3ndj3kd3prtqqi2lfj3uhl2je"), - "system": MustParseCid("bafk2bzaceaafqf7lwaiqx5po6b3l4dfg4xsr5qhfk3bjgoi7qke2mfy3shla4"), - "verifiedregistry": MustParseCid("bafk2bzacec2ouguts4z335vetmdeifpk5fkqthcmrwshk7yxbw2uohddfu5lo"), + "account": MustParseCid("bafk2bzacea3vbptmow72euwh2meu2sgwxrxjxg53qba6xxrknltr6j7bgnlhg"), + "cron": MustParseCid("bafk2bzaceclbrnwfgolv5icdknexv3oi3ujzpt5stqabiyshwhtvnijacysjg"), + "datacap": MustParseCid("bafk2bzacebt2gym3ot447unemieakxfep3u2m2zxiqlssbacu3ifsyhtulz4m"), + "eam": MustParseCid("bafk2bzacedmnvhfvt7qc5w3mfr54ikrpwox54ddkxkxp5qka24xudj4vkggjs"), + "ethaccount": MustParseCid("bafk2bzacebnh3oadihryhwgo73ooesgk3x2eg4g5gorps463iirilm5ur4q7w"), + "evm": MustParseCid("bafk2bzacecw2i5bsjymtdblvxh5xte3htff4przqaek673cw5z7ommaptdmqq"), + "init": MustParseCid("bafk2bzacebo6n4pwpwayjsc7cbrmmjy6l6om3wzx5jdldni4wl47a4x4jeazo"), + "multisig": MustParseCid("bafk2bzacecl4mc5esjwfcoirhdeqhms4qquafam4ut424hj2mo3gqzb47n2rs"), + "paymentchannel": MustParseCid("bafk2bzacedsmvdirjuywbg5xz7r5u2pxew7ye4kpy2toksv5nba7dzkcsmu3i"), + "placeholder": MustParseCid("bafk2bzacedfvut2myeleyq67fljcrw4kkmn5pb5dpyozovj7jpoez5irnc3ro"), + "reward": MustParseCid("bafk2bzaceakq4np44ltnscgff7h3a6s6ao2d43vwx66tce5r57r2amw42pl5i"), + "storagemarket": MustParseCid("bafk2bzacebskzlyhvhrdheslyrez3p4sccr5t42xnqophnvj775roskwzoic4"), + "storageminer": MustParseCid("bafk2bzacecx2fs3ra4ydxvwq6oh73esqy2xjqhwsnfrdl5ctbg26zem77zy3u"), + "storagepower": MustParseCid("bafk2bzacedwfnzestwv7ylleeuk3fhp6jewc4ygw3fgodsciww7gw5ilt4ony"), + "system": MustParseCid("bafk2bzaceaql3e6266ixcbwcdmwuhod4tahhawlvhfkq4qzp7hnmkkybdf7zi"), + "verifiedregistry": MustParseCid("bafk2bzacecibid6xpyu64kaxk2mspouajnenxlh4jkny7d6l5ht3hxg67l32u"), }, }, { Network: "testing-fake-proofs", @@ -470,23 +448,23 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet }, { Network: "testing-fake-proofs", Version: 10, - ManifestCid: MustParseCid("bafy2bzacecyqfyzmw72234rvbk6vzq2omnmt3cbfezkq2h3ewnn33w42b2s62"), + ManifestCid: MustParseCid("bafy2bzaceav36pezxhapk6vlgohdp6jiydk44o6xowltjnyhu3nrhpfcby5zs"), Actors: map[string]cid.Cid{ - "account": MustParseCid("bafk2bzaceds3iy5qjgr3stoywxt4uxvhybca23q7d2kxhitedgudrkhxaxa6o"), - "cron": MustParseCid("bafk2bzacebxp4whb4ocqxnbvqlz3kckarabtyvhjbhqvrdwhejuffwactyiss"), - "datacap": MustParseCid("bafk2bzacedepm3zas6vqryruwiz7d3axkneo7v66q65gf2dlpfd53pjlycrg4"), - "eam": MustParseCid("bafk2bzacea2uascrtv6xnsqlxyf3tcf4onpgrs7frh55p6dnrdeum2uup7wx4"), - "ethaccount": MustParseCid("bafk2bzacecbhz4ipg773lsovgpjysm6fxl2i7y2wuxadqnt4s4vm3nd2qodb4"), - "evm": MustParseCid("bafk2bzaceabwn4i62od3i4qkuj5zx4vn5w5cbcl53tqnszk6kl43bfl55hl6c"), - "init": MustParseCid("bafk2bzacebqym5i5eciyyyzsimu73z6bkffpm5hzjpx3gwcm64pm2fh7okrja"), - "multisig": MustParseCid("bafk2bzacecmlyngek7qvj5ezaaitadrycapup3mbty4ijlzun6g23tcoysxle"), - "paymentchannel": MustParseCid("bafk2bzacedspin4hxpgnxkjen3hsxpcc52oc5q4ypukl4qq6vaytcgmmi7hl4"), - "placeholder": MustParseCid("bafk2bzaceaamp2a35vpfml4skap4dffklzae2urcm34mtwwce2lvhaons3a5y"), - "reward": MustParseCid("bafk2bzacecmumnnqkqnoa23hhsfgwccwvmksr2q65tznbves6x2a6fhwvtm7a"), - "storagemarket": MustParseCid("bafk2bzacea2re4nxba7mtlrwdxabu2i3l2fwbuw2veb4p7qbvrsaocgablqvi"), - "storageminer": MustParseCid("bafk2bzacedz4mmupganqbwe6mz4636zepooh5ipxb36tybsrf6ynewrfdihl6"), - "storagepower": MustParseCid("bafk2bzacedcqv6k2fszpfb7zpw6q6c6fe2u7g2zefabcntp46xgv3owosgymy"), - "system": MustParseCid("bafk2bzaceaafqf7lwaiqx5po6b3l4dfg4xsr5qhfk3bjgoi7qke2mfy3shla4"), - "verifiedregistry": MustParseCid("bafk2bzacec2ouguts4z335vetmdeifpk5fkqthcmrwshk7yxbw2uohddfu5lo"), + "account": MustParseCid("bafk2bzacea3vbptmow72euwh2meu2sgwxrxjxg53qba6xxrknltr6j7bgnlhg"), + "cron": MustParseCid("bafk2bzaceclbrnwfgolv5icdknexv3oi3ujzpt5stqabiyshwhtvnijacysjg"), + "datacap": MustParseCid("bafk2bzacebt2gym3ot447unemieakxfep3u2m2zxiqlssbacu3ifsyhtulz4m"), + "eam": MustParseCid("bafk2bzacedmnvhfvt7qc5w3mfr54ikrpwox54ddkxkxp5qka24xudj4vkggjs"), + "ethaccount": MustParseCid("bafk2bzacebnh3oadihryhwgo73ooesgk3x2eg4g5gorps463iirilm5ur4q7w"), + "evm": MustParseCid("bafk2bzacecw2i5bsjymtdblvxh5xte3htff4przqaek673cw5z7ommaptdmqq"), + "init": MustParseCid("bafk2bzacebo6n4pwpwayjsc7cbrmmjy6l6om3wzx5jdldni4wl47a4x4jeazo"), + "multisig": MustParseCid("bafk2bzacecl4mc5esjwfcoirhdeqhms4qquafam4ut424hj2mo3gqzb47n2rs"), + "paymentchannel": MustParseCid("bafk2bzacedsmvdirjuywbg5xz7r5u2pxew7ye4kpy2toksv5nba7dzkcsmu3i"), + "placeholder": MustParseCid("bafk2bzacedfvut2myeleyq67fljcrw4kkmn5pb5dpyozovj7jpoez5irnc3ro"), + "reward": MustParseCid("bafk2bzaceakq4np44ltnscgff7h3a6s6ao2d43vwx66tce5r57r2amw42pl5i"), + "storagemarket": MustParseCid("bafk2bzacebskzlyhvhrdheslyrez3p4sccr5t42xnqophnvj775roskwzoic4"), + "storageminer": MustParseCid("bafk2bzacebp3rj6d4g2ppngw2xp7okzqx6oapfk6xi54n3aqenadqvptlk45g"), + "storagepower": MustParseCid("bafk2bzacedhwtksxb6orm63doxx2bgcy6fpy5li5prjb3twsxdh75anjbmdug"), + "system": MustParseCid("bafk2bzaceaql3e6266ixcbwcdmwuhod4tahhawlvhfkq4qzp7hnmkkybdf7zi"), + "verifiedregistry": MustParseCid("bafk2bzacecibid6xpyu64kaxk2mspouajnenxlh4jkny7d6l5ht3hxg67l32u"), }, }} diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index d7a354461cd..1fa47bab592 100644 Binary files a/build/openrpc/full.json.gz and b/build/openrpc/full.json.gz differ diff --git a/build/openrpc/gateway.json.gz b/build/openrpc/gateway.json.gz index 74a9f322175..f10a433e32c 100644 Binary files a/build/openrpc/gateway.json.gz and b/build/openrpc/gateway.json.gz differ diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index d3750150c33..be2151d62ba 100644 Binary files a/build/openrpc/miner.json.gz and b/build/openrpc/miner.json.gz differ diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index e84f7f5d103..d8130e9e124 100644 Binary files a/build/openrpc/worker.json.gz and b/build/openrpc/worker.json.gz differ diff --git a/build/params_2k.go b/build/params_2k.go index 081007dd191..962b2f9ba45 100644 --- a/build/params_2k.go +++ b/build/params_2k.go @@ -23,7 +23,7 @@ var NetworkBundle = "devnet" var BundleOverrides map[actorstypes.Version]string var ActorDebugging = true -const GenesisNetworkVersion = network.Version18 +const GenesisNetworkVersion = network.Version17 var UpgradeBreezeHeight = abi.ChainEpoch(-1) @@ -59,7 +59,7 @@ var UpgradeSkyrHeight = abi.ChainEpoch(-19) var UpgradeSharkHeight = abi.ChainEpoch(-20) -var UpgradeHyggeHeight = abi.ChainEpoch(-21) +var UpgradeHyggeHeight = abi.ChainEpoch(30) var DrandSchedule = map[abi.ChainEpoch]DrandEnum{ 0: DrandMainnet, diff --git a/chain/actors/builtin/builtin.go b/chain/actors/builtin/builtin.go index 116ed35d071..414a11e72e2 100644 --- a/chain/actors/builtin/builtin.go +++ b/chain/actors/builtin/builtin.go @@ -26,6 +26,7 @@ import ( var SystemActorAddr = builtin.SystemActorAddr var BurntFundsActorAddr = builtin.BurntFundsActorAddr var CronActorAddr = builtin.CronActorAddr +var EthereumAddressManagerActorAddr = builtin.EthereumAddressManagerActorAddr var SaftAddress = makeAddress("t0122") var ReserveAddress = makeAddress("t090") var RootVerifierAddress = makeAddress("t080") diff --git a/chain/actors/builtin/builtin.go.template b/chain/actors/builtin/builtin.go.template index 977217b1a0a..3b737c47e29 100644 --- a/chain/actors/builtin/builtin.go.template +++ b/chain/actors/builtin/builtin.go.template @@ -26,6 +26,7 @@ import ( var SystemActorAddr = builtin.SystemActorAddr var BurntFundsActorAddr = builtin.BurntFundsActorAddr var CronActorAddr = builtin.CronActorAddr +var EthereumAddressManagerActorAddr = builtin.EthereumAddressManagerActorAddr var SaftAddress = makeAddress("t0122") var ReserveAddress = makeAddress("t090") var RootVerifierAddress = makeAddress("t080") diff --git a/chain/consensus/compute_state.go b/chain/consensus/compute_state.go index d3d9e382dc8..dd038634149 100644 --- a/chain/consensus/compute_state.go +++ b/chain/consensus/compute_state.go @@ -5,11 +5,13 @@ import ( "sync/atomic" "github.com/ipfs/go-cid" + cbor "github.com/ipfs/go-ipld-cbor" cbg "github.com/whyrusleeping/cbor-gen" "go.opencensus.io/stats" "go.opencensus.io/trace" "golang.org/x/xerrors" + amt4 "github.com/filecoin-project/go-amt-ipld/v4" "github.com/filecoin-project/go-state-types/abi" actorstypes "github.com/filecoin-project/go-state-types/actors" "github.com/filecoin-project/go-state-types/big" @@ -105,6 +107,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, LookbackState: stmgr.LookbackStateGetterForTipset(sm, ts), TipSetGetter: stmgr.TipSetGetterForTipset(sm.ChainStore(), ts), Tracing: vmTracing, + ReturnEvents: sm.ChainStore().IsStoringEvents(), } return sm.VMConstructor()(ctx, vmopt) @@ -174,8 +177,13 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, return cid.Undef, cid.Undef, xerrors.Errorf("making vm: %w", err) } - var receipts []cbg.CBORMarshaler - processedMsgs := make(map[cid.Cid]struct{}) + var ( + receipts []*types.MessageReceipt + storingEvents = sm.ChainStore().IsStoringEvents() + events [][]types.Event + processedMsgs = make(map[cid.Cid]struct{}) + ) + for _, b := range bms { penalty := types.NewInt(0) gasReward := big.Zero() @@ -194,6 +202,11 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, gasReward = big.Add(gasReward, r.GasCosts.MinerTip) penalty = big.Add(penalty, r.GasCosts.MinerPenalty) + if storingEvents { + // Appends nil when no events are returned to preserve positional alignment. + events = append(events, r.Events) + } + if em != nil { if err := em.MessageApplied(ctx, ts, cm.Cid(), m, r, false); err != nil { return cid.Undef, cid.Undef, err @@ -235,6 +248,23 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, return cid.Undef, cid.Undef, xerrors.Errorf("failed to build receipts amt: %w", err) } + // Slice will be empty if not storing events. + for i, evs := range events { + if len(evs) == 0 { + continue + } + switch root, err := t.StoreEventsAMT(ctx, sm.ChainStore(), evs); { + case err != nil: + return cid.Undef, cid.Undef, xerrors.Errorf("failed to store events amt: %w", err) + case i >= len(receipts): + return cid.Undef, cid.Undef, xerrors.Errorf("assertion failed: receipt and events array lengths inconsistent") + case receipts[i].EventsRoot == nil: + return cid.Undef, cid.Undef, xerrors.Errorf("assertion failed: VM returned events with no events root") + case root != *receipts[i].EventsRoot: + return cid.Undef, cid.Undef, xerrors.Errorf("assertion failed: returned events AMT root does not match derived") + } + } + st, err := vmi.Flush(ctx) if err != nil { return cid.Undef, cid.Undef, xerrors.Errorf("vm flush failed: %w", err) @@ -293,4 +323,13 @@ func (t *TipSetExecutor) ExecuteTipSet(ctx context.Context, return t.ApplyBlocks(ctx, sm, parentEpoch, pstate, fbmsgs, blks[0].Height, r, em, vmTracing, baseFee, ts) } +func (t *TipSetExecutor) StoreEventsAMT(ctx context.Context, cs *store.ChainStore, events []types.Event) (cid.Cid, error) { + cst := cbor.NewCborStore(cs.ChainBlockstore()) + objs := make([]cbg.CBORMarshaler, len(events)) + for i := 0; i < len(events); i++ { + objs[i] = &events[i] + } + return amt4.FromArray(ctx, cst, objs, amt4.UseTreeBitWidth(types.EventAMTBitwidth)) +} + var _ stmgr.Executor = &TipSetExecutor{} diff --git a/chain/consensus/signatures.go b/chain/consensus/signatures.go index d89ae833716..cb0e229a85b 100644 --- a/chain/consensus/signatures.go +++ b/chain/consensus/signatures.go @@ -22,7 +22,7 @@ func AuthenticateMessage(msg *types.SignedMessage, signer address.Address) error typ := msg.Signature.Type switch typ { case crypto.SigTypeDelegated: - txArgs, err := ethtypes.EthTxArgsFromMessage(&msg.Message) + txArgs, err := ethtypes.EthTxArgsFromUnsignedEthMessage(&msg.Message) if err != nil { return xerrors.Errorf("failed to reconstruct eth transaction: %w", err) } diff --git a/chain/ethhashlookup/eth_transaction_hash_lookup.go b/chain/ethhashlookup/eth_transaction_hash_lookup.go index 85cb84db12d..d936809128b 100644 --- a/chain/ethhashlookup/eth_transaction_hash_lookup.go +++ b/chain/ethhashlookup/eth_transaction_hash_lookup.go @@ -67,34 +67,28 @@ func (ei *EthTxHashLookup) UpsertHash(txHash ethtypes.EthHash, c cid.Cid) error } func (ei *EthTxHashLookup) GetCidFromHash(txHash ethtypes.EthHash) (cid.Cid, error) { - q, err := ei.db.Query("SELECT cid FROM eth_tx_hashes WHERE hash = :hash;", sql.Named("hash", txHash.String())) - if err != nil { - return cid.Undef, err - } + row := ei.db.QueryRow("SELECT cid FROM eth_tx_hashes WHERE hash = :hash;", sql.Named("hash", txHash.String())) var c string - if !q.Next() { - return cid.Undef, ErrNotFound - } - err = q.Scan(&c) + err := row.Scan(&c) if err != nil { + if err == sql.ErrNoRows { + return cid.Undef, ErrNotFound + } return cid.Undef, err } return cid.Decode(c) } func (ei *EthTxHashLookup) GetHashFromCid(c cid.Cid) (ethtypes.EthHash, error) { - q, err := ei.db.Query("SELECT hash FROM eth_tx_hashes WHERE cid = :cid;", sql.Named("cid", c.String())) - if err != nil { - return ethtypes.EmptyEthHash, err - } + row := ei.db.QueryRow("SELECT hash FROM eth_tx_hashes WHERE cid = :cid;", sql.Named("cid", c.String())) var hashString string - if !q.Next() { - return ethtypes.EmptyEthHash, ErrNotFound - } - err = q.Scan(&hashString) + err := row.Scan(&c) if err != nil { + if err == sql.ErrNoRows { + return ethtypes.EmptyEthHash, ErrNotFound + } return ethtypes.EmptyEthHash, err } return ethtypes.ParseEthHash(hashString) diff --git a/chain/events/filter/event.go b/chain/events/filter/event.go index 7d59ad8bd5f..dfb61f111d6 100644 --- a/chain/events/filter/event.go +++ b/chain/events/filter/event.go @@ -20,7 +20,12 @@ import ( "github.com/filecoin-project/lotus/chain/types" ) -const indexed uint8 = 0x01 +func isIndexedValue(b uint8) bool { + // currently we mark the full entry as indexed if either the key + // or the value are indexed; in the future we will need finer-grained + // management of indices + return b&(types.EventFlagIndexedKey|types.EventFlagIndexedValue) > 0 +} type EventFilter struct { id types.FilterID @@ -100,18 +105,18 @@ func (f *EventFilter) CollectEvents(ctx context.Context, te *TipSetEvents, rever continue } - decodedEntries := make([]types.EventEntry, len(ev.Entries)) + entries := make([]types.EventEntry, len(ev.Entries)) for i, entry := range ev.Entries { - decodedEntries[i] = types.EventEntry{ + entries[i] = types.EventEntry{ Flags: entry.Flags, Key: entry.Key, - Value: decodeLogBytes(entry.Value), + Value: entry.Value, } } // event matches filter, so record it cev := &CollectedEvent{ - Entries: decodedEntries, + Entries: entries, EmitterAddr: addr, EventIdx: evIdx, Reverted: revert, @@ -209,7 +214,7 @@ func (f *EventFilter) matchKeys(ees []types.EventEntry) bool { matched := map[string]bool{} for _, ee := range ees { // Skip an entry that is not indexable - if ee.Flags&indexed != indexed { + if !isIndexedValue(ee.Flags) { continue } @@ -221,7 +226,7 @@ func (f *EventFilter) matchKeys(ees []types.EventEntry) bool { } wantlist, ok := f.keys[keyname] - if !ok { + if !ok || len(wantlist) == 0 { continue } diff --git a/chain/events/filter/index.go b/chain/events/filter/index.go index 1920a91fe07..1b69dfd102b 100644 --- a/chain/events/filter/index.go +++ b/chain/events/filter/index.go @@ -1,7 +1,6 @@ package filter import ( - "bytes" "context" "database/sql" "errors" @@ -11,7 +10,6 @@ import ( "github.com/ipfs/go-cid" _ "github.com/mattn/go-sqlite3" - cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" @@ -153,13 +151,6 @@ func (ei *EventIndex) CollectEvents(ctx context.Context, te *TipSetEvents, rever return xerrors.Errorf("prepare insert entry: %w", err) } - isIndexedValue := func(b uint8) bool { - // currently we mark the full entry as indexed if either the key - // or the value are indexed; in the future we will need finer-grained - // management of indices - return b&(types.EventFlagIndexedKey|types.EventFlagIndexedValue) > 0 - } - for msgIdx, em := range ems { for evIdx, ev := range em.Events() { addr, found := addressLookups[ev.Emitter] @@ -198,13 +189,12 @@ func (ei *EventIndex) CollectEvents(ctx context.Context, te *TipSetEvents, rever } for _, entry := range ev.Entries { - value := decodeLogBytes(entry.Value) _, err := stmtEntry.Exec( lastID, // event_id isIndexedValue(entry.Flags), // indexed []byte{entry.Flags}, // flags entry.Key, // key - value, // value + entry.Value, // value ) if err != nil { return xerrors.Errorf("exec insert entry: %w", err) @@ -220,21 +210,6 @@ func (ei *EventIndex) CollectEvents(ctx context.Context, te *TipSetEvents, rever return nil } -// decodeLogBytes decodes a CBOR-serialized array into its original form. -// -// This function swallows errors and returns the original array if it failed -// to decode. -func decodeLogBytes(orig []byte) []byte { - if len(orig) == 0 { - return orig - } - decoded, err := cbg.ReadByteArray(bytes.NewReader(orig), uint64(len(orig))) - if err != nil { - return orig - } - return decoded -} - // PrefillFilter fills a filter's collection of events from the historic index func (ei *EventIndex) PrefillFilter(ctx context.Context, f *EventFilter) error { clauses := []string{} diff --git a/chain/messagesigner/messagesigner.go b/chain/messagesigner/messagesigner.go index 6a622dd5755..84dd6d0aa05 100644 --- a/chain/messagesigner/messagesigner.go +++ b/chain/messagesigner/messagesigner.go @@ -202,7 +202,7 @@ func (ms *MessageSigner) dstoreKey(addr address.Address) datastore.Key { func SigningBytes(msg *types.Message, sigType crypto.SigType) ([]byte, error) { if sigType == crypto.SigTypeDelegated { - txArgs, err := ethtypes.EthTxArgsFromMessage(msg) + txArgs, err := ethtypes.EthTxArgsFromUnsignedEthMessage(msg) if err != nil { return nil, xerrors.Errorf("failed to reconstruct eth transaction: %w", err) } diff --git a/chain/stmgr/supply.go b/chain/stmgr/supply.go index 89708097e25..a48ff36c7f9 100644 --- a/chain/stmgr/supply.go +++ b/chain/stmgr/supply.go @@ -403,7 +403,8 @@ func (sm *StateManager) GetCirculatingSupply(ctx context.Context, height abi.Cha a == builtin.CronActorAddr || a == builtin.BurntFundsActorAddr || a == builtin.SaftAddress || - a == builtin.ReserveAddress: + a == builtin.ReserveAddress || + a == builtin.EthereumAddressManagerActorAddr: unCirc = big.Add(unCirc, actor.Balance) @@ -421,7 +422,12 @@ func (sm *StateManager) GetCirculatingSupply(ctx context.Context, height abi.Cha circ = big.Add(circ, big.Sub(actor.Balance, lb)) unCirc = big.Add(unCirc, lb) - case builtin.IsAccountActor(actor.Code) || builtin.IsPaymentChannelActor(actor.Code): + case builtin.IsAccountActor(actor.Code) || + builtin.IsPaymentChannelActor(actor.Code) || + builtin.IsEthAccountActor(actor.Code) || + builtin.IsEvmActor(actor.Code) || + builtin.IsPlaceholderActor(actor.Code): + circ = big.Add(circ, actor.Balance) case builtin.IsStorageMinerActor(actor.Code): diff --git a/chain/store/store.go b/chain/store/store.go index 0299a1fb9d7..754e3a12347 100644 --- a/chain/store/store.go +++ b/chain/store/store.go @@ -126,6 +126,8 @@ type ChainStore struct { evtTypes [1]journal.EventType journal journal.Journal + storeEvents bool + cancelFn context.CancelFunc wg sync.WaitGroup } @@ -680,7 +682,7 @@ func FlushValidationCache(ctx context.Context, ds dstore.Batching) error { // If this is addressed (blockcache goes into its own sub-namespace) then // strings.HasPrefix(...) below can be skipped // - //Prefix: blockValidationCacheKeyPrefix.String() + // Prefix: blockValidationCacheKeyPrefix.String() KeysOnly: true, }) if err != nil { @@ -1202,6 +1204,16 @@ func (cs *ChainStore) Weight(ctx context.Context, hts *types.TipSet) (types.BigI return cs.weight(ctx, cs.StateBlockstore(), hts) } +// StoreEvents marks this ChainStore as storing events. +func (cs *ChainStore) StoreEvents(store bool) { + cs.storeEvents = store +} + +// IsStoringEvents indicates if this ChainStore is storing events. +func (cs *ChainStore) IsStoringEvents() bool { + return cs.storeEvents +} + // true if ts1 wins according to the filecoin tie-break rule func breakWeightTie(ts1, ts2 *types.TipSet) bool { s := len(ts1.Blocks()) diff --git a/chain/types/ethtypes/eth_transactions.go b/chain/types/ethtypes/eth_transactions.go index 18b92223488..9f9df238167 100644 --- a/chain/types/ethtypes/eth_transactions.go +++ b/chain/types/ethtypes/eth_transactions.go @@ -56,7 +56,44 @@ type EthTxArgs struct { S big.Int `json:"s"` } -func EthTxArgsFromMessage(msg *types.Message) (EthTxArgs, error) { +// EthTxFromSignedEthMessage does NOT populate: +// - BlockHash +// - BlockNumber +// - TransactionIndex +// - From +// - Hash +func EthTxFromSignedEthMessage(smsg *types.SignedMessage) (EthTx, error) { + if smsg.Signature.Type != typescrypto.SigTypeDelegated { + return EthTx{}, xerrors.Errorf("signature is not delegated type, is type: %d", smsg.Signature.Type) + } + + txArgs, err := EthTxArgsFromUnsignedEthMessage(&smsg.Message) + if err != nil { + return EthTx{}, xerrors.Errorf("failed to convert the unsigned message: %w", err) + } + + r, s, v, err := RecoverSignature(smsg.Signature) + if err != nil { + return EthTx{}, xerrors.Errorf("failed to recover signature: %w", err) + } + + return EthTx{ + Nonce: EthUint64(txArgs.Nonce), + ChainID: EthUint64(txArgs.ChainID), + To: txArgs.To, + Value: EthBigInt(txArgs.Value), + Type: Eip1559TxType, + Gas: EthUint64(txArgs.GasLimit), + MaxFeePerGas: EthBigInt(txArgs.MaxFeePerGas), + MaxPriorityFeePerGas: EthBigInt(txArgs.MaxPriorityFeePerGas), + V: v, + R: r, + S: s, + Input: txArgs.Input, + }, nil +} + +func EthTxArgsFromUnsignedEthMessage(msg *types.Message) (EthTxArgs, error) { var ( to *EthAddress params []byte diff --git a/chain/types/ethtypes/eth_types.go b/chain/types/ethtypes/eth_types.go index 235cc7c7921..d003e5ed287 100644 --- a/chain/types/ethtypes/eth_types.go +++ b/chain/types/ethtypes/eth_types.go @@ -22,13 +22,14 @@ import ( builtintypes "github.com/filecoin-project/go-state-types/builtin" "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/lib/must" ) var ( - EthTopic1 = "topic1" - EthTopic2 = "topic2" - EthTopic3 = "topic3" - EthTopic4 = "topic4" + EthTopic1 = "t1" + EthTopic2 = "t2" + EthTopic3 = "t3" + EthTopic4 = "t4" ) var ErrInvalidAddress = errors.New("invalid Filecoin Eth address") @@ -144,7 +145,7 @@ type EthBlock struct { GasLimit EthUint64 `json:"gasLimit"` GasUsed EthUint64 `json:"gasUsed"` Timestamp EthUint64 `json:"timestamp"` - Extradata []byte `json:"extraData"` + Extradata EthBytes `json:"extraData"` MixHash EthHash `json:"mixHash"` Nonce EthNonce `json:"nonce"` BaseFeePerGas EthBigInt `json:"baseFeePerGas"` @@ -155,17 +156,19 @@ type EthBlock struct { } var ( - EmptyEthBloom = [256]byte{} - EmptyEthHash = EthHash{} - EmptyEthInt = EthUint64(0) - EmptyEthNonce = [8]byte{0, 0, 0, 0, 0, 0, 0, 0} + EmptyEthBloom = [256]byte{} + EmptyEthHash = EthHash{} + EmptyUncleHash = must.One(ParseEthHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")) // Keccak-256 of an RLP of an empty array + EmptyRootHash = must.One(ParseEthHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")) // Keccak-256 hash of the RLP of null + EmptyEthInt = EthUint64(0) + EmptyEthNonce = [8]byte{0, 0, 0, 0, 0, 0, 0, 0} ) -func NewEthBlock() EthBlock { - return EthBlock{ - Sha3Uncles: EmptyEthHash, +func NewEthBlock(hasTransactions bool) EthBlock { + b := EthBlock{ + Sha3Uncles: EmptyUncleHash, // Sha3Uncles set to a hardcoded value which is used by some clients to determine if has no uncles. StateRoot: EmptyEthHash, - TransactionsRoot: EmptyEthHash, + TransactionsRoot: EmptyRootHash, // TransactionsRoot set to a hardcoded value which is used by some clients to determine if has no transactions. ReceiptsRoot: EmptyEthHash, Difficulty: EmptyEthInt, LogsBloom: EmptyEthBloom[:], @@ -176,6 +179,11 @@ func NewEthBlock() EthBlock { Uncles: []EthHash{}, Transactions: []interface{}{}, } + if hasTransactions { + b.TransactionsRoot = EmptyEthHash + } + + return b } type EthCall struct { @@ -363,6 +371,18 @@ func (h *EthHash) UnmarshalJSON(b []byte) error { return nil } +func (h EthHash) String() string { + return "0x" + hex.EncodeToString(h[:]) +} + +// Should ONLY be used for blocks and Filecoin messages. Eth transactions expect a different hashing scheme. +func (h EthHash) ToCid() cid.Cid { + // err is always nil + mh, _ := multihash.EncodeName(h[:], "blake2b-256") + + return cid.NewCidV1(cid.DagCBOR, mh) +} + func decodeHexString(s string, expectedLen int) ([]byte, error) { s = handleHexStringPrefix(s) if len(s) != expectedLen*2 { @@ -420,20 +440,8 @@ func EthHashFromTxBytes(b []byte) EthHash { return ethHash } -func (h EthHash) String() string { - return "0x" + hex.EncodeToString(h[:]) -} - -// Should ONLY be used for blocks and Filecoin messages. Eth transactions expect a different hashing scheme. -func (h EthHash) ToCid() cid.Cid { - // err is always nil - mh, _ := multihash.EncodeName(h[:], "blake2b-256") - - return cid.NewCidV1(cid.DagCBOR, mh) -} - type EthFeeHistory struct { - OldestBlock uint64 `json:"oldestBlock"` + OldestBlock EthUint64 `json:"oldestBlock"` BaseFeePerGas []EthBigInt `json:"baseFeePerGas"` GasUsedRatio []float64 `json:"gasUsedRatio"` Reward *[][]EthBigInt `json:"reward,omitempty"` @@ -441,9 +449,33 @@ type EthFeeHistory struct { type EthFilterID EthHash +func (h EthFilterID) MarshalJSON() ([]byte, error) { + return (EthHash)(h).MarshalJSON() +} + +func (h *EthFilterID) UnmarshalJSON(b []byte) error { + return (*EthHash)(h).UnmarshalJSON(b) +} + +func (h EthFilterID) String() string { + return (EthHash)(h).String() +} + // An opaque identifier generated by the Lotus node to refer to an active subscription. type EthSubscriptionID EthHash +func (h EthSubscriptionID) MarshalJSON() ([]byte, error) { + return (EthHash)(h).MarshalJSON() +} + +func (h *EthSubscriptionID) UnmarshalJSON(b []byte) error { + return (*EthHash)(h).UnmarshalJSON(b) +} + +func (h EthSubscriptionID) String() string { + return (EthHash)(h).String() +} + type EthFilterSpec struct { // Interpreted as an epoch or one of "latest" for last mined block, "earliest" for first, // "pending" for not yet committed messages. @@ -595,10 +627,53 @@ type EthLog struct { BlockNumber EthUint64 `json:"blockNumber"` } +// EthSubscribeParams handles raw jsonrpc params for eth_subscribe +type EthSubscribeParams struct { + EventType string + Params *EthSubscriptionParams +} + +func (e *EthSubscribeParams) UnmarshalJSON(b []byte) error { + var params []json.RawMessage + err := json.Unmarshal(b, ¶ms) + if err != nil { + return err + } + switch len(params) { + case 2: + err = json.Unmarshal(params[1], &e.Params) + if err != nil { + return err + } + fallthrough + case 1: + err = json.Unmarshal(params[0], &e.EventType) + if err != nil { + return err + } + default: + return xerrors.Errorf("expected 1 or 2 params, got %d", len(params)) + } + return nil +} + +func (e EthSubscribeParams) MarshalJSON() ([]byte, error) { + if e.Params != nil { + return json.Marshal([]interface{}{e.EventType, e.Params}) + } + return json.Marshal([]interface{}{e.EventType}) +} + type EthSubscriptionParams struct { // List of topics to be matched. // Optional, default: empty list Topics EthTopicSpec `json:"topics,omitempty"` + + // Actor address or a list of addresses from which event logs should originate. + // Optional, default nil. + // The JSON decoding must treat a string as equivalent to an array with one value, for example + // "0x8888f1f195afa192cfee86069858" must be decoded as [ "0x8888f1f195afa192cfee86069858" ] + Address EthAddressList `json:"address"` } type EthSubscriptionResponse struct { diff --git a/chain/types/ethtypes/eth_types_test.go b/chain/types/ethtypes/eth_types_test.go index 89c38ba29f8..e42d2bdc328 100644 --- a/chain/types/ethtypes/eth_types_test.go +++ b/chain/types/ethtypes/eth_types_test.go @@ -93,6 +93,48 @@ func TestEthHash(t *testing.T) { h1, err := EthHashFromCid(c) require.Nil(t, err) require.Equal(t, h, h1) + + jm, err := json.Marshal(h) + require.NoError(t, err) + require.Equal(t, hash, string(jm)) + } +} + +func TestEthFilterID(t *testing.T) { + testcases := []string{ + `"0x013dbb9442ca9667baccc6230fcd5c1c4b2d4d2870f4bd20681d4d47cfd15184"`, + `"0xab8653edf9f51785664a643b47605a7ba3d917b5339a0724e7642c114d0e4738"`, + } + + for _, hash := range testcases { + var h EthFilterID + err := h.UnmarshalJSON([]byte(hash)) + + require.Nil(t, err) + require.Equal(t, h.String(), strings.Replace(hash, `"`, "", -1)) + + jm, err := json.Marshal(h) + require.NoError(t, err) + require.Equal(t, hash, string(jm)) + } +} + +func TestEthSubscriptionID(t *testing.T) { + testcases := []string{ + `"0x013dbb9442ca9667baccc6230fcd5c1c4b2d4d2870f4bd20681d4d47cfd15184"`, + `"0xab8653edf9f51785664a643b47605a7ba3d917b5339a0724e7642c114d0e4738"`, + } + + for _, hash := range testcases { + var h EthSubscriptionID + err := h.UnmarshalJSON([]byte(hash)) + + require.Nil(t, err) + require.Equal(t, h.String(), strings.Replace(hash, `"`, "", -1)) + + jm, err := json.Marshal(h) + require.NoError(t, err) + require.Equal(t, hash, string(jm)) } } diff --git a/chain/types/event.go b/chain/types/event.go index 00c25ca4cb6..20c6fd85256 100644 --- a/chain/types/event.go +++ b/chain/types/event.go @@ -1,9 +1,20 @@ package types import ( + "bytes" + "fmt" + + cbg "github.com/whyrusleeping/cbor-gen" + "github.com/filecoin-project/go-state-types/abi" ) +// EventEntry flags defined in fvm_shared +const ( + EventFlagIndexedKey = 0b00000001 + EventFlagIndexedValue = 0b00000010 +) + type Event struct { // The ID of the actor that emitted this event. Emitter abi.ActorID @@ -25,8 +36,23 @@ type EventEntry struct { type FilterID [32]byte // compatible with EthHash -// EventEntry flags defined in fvm_shared -const ( - EventFlagIndexedKey = 0b00000001 - EventFlagIndexedValue = 0b00000010 -) +// DecodeEvents decodes a CBOR list of CBOR-encoded events. +func DecodeEvents(input []byte) ([]Event, error) { + r := bytes.NewReader(input) + typ, len, err := cbg.NewCborReader(r).ReadHeader() + if err != nil { + return nil, fmt.Errorf("failed to read events: %w", err) + } + if typ != cbg.MajArray { + return nil, fmt.Errorf("expected a CBOR list, was major type %d", typ) + } + events := make([]Event, 0, len) + for i := 0; i < int(len); i++ { + var evt Event + if err := evt.UnmarshalCBOR(r); err != nil { + return nil, fmt.Errorf("failed to parse event: %w", err) + } + events = append(events, evt) + } + return events, nil +} diff --git a/chain/vm/fvm.go b/chain/vm/fvm.go index a81bc10d679..8e78e58d9df 100644 --- a/chain/vm/fvm.go +++ b/chain/vm/fvm.go @@ -287,6 +287,9 @@ func (x *FvmExtern) workerKeyAtLookback(ctx context.Context, minerId address.Add type FVM struct { fvm *ffi.FVM nv network.Version + + // returnEvents specifies whether to parse and return events when applying messages. + returnEvents bool } func defaultFVMOpts(ctx context.Context, opts *VMOpts) (*ffi.FVMOpts, error) { @@ -335,10 +338,13 @@ func NewFVM(ctx context.Context, opts *VMOpts) (*FVM, error) { return nil, xerrors.Errorf("failed to create FVM: %w", err) } - return &FVM{ - fvm: fvm, - nv: opts.NetworkVersion, - }, nil + ret := &FVM{ + fvm: fvm, + nv: opts.NetworkVersion, + returnEvents: opts.ReturnEvents, + } + + return ret, nil } func NewDebugFVM(ctx context.Context, opts *VMOpts) (*FVM, error) { @@ -438,10 +444,13 @@ func NewDebugFVM(ctx context.Context, opts *VMOpts) (*FVM, error) { return nil, err } - return &FVM{ - fvm: fvm, - nv: opts.NetworkVersion, - }, nil + ret := &FVM{ + fvm: fvm, + nv: opts.NetworkVersion, + returnEvents: opts.ReturnEvents, + } + + return ret, nil } func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, error) { @@ -493,7 +502,7 @@ func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet et.Error = aerr.Error() } - return &ApplyRet{ + applyRet := &ApplyRet{ MessageReceipt: receipt, GasCosts: &GasOutputs{ BaseFeeBurn: ret.BaseFeeBurn, @@ -507,7 +516,16 @@ func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet ActorErr: aerr, ExecutionTrace: et, Duration: duration, - }, nil + } + + if vm.returnEvents && len(ret.EventsBytes) > 0 { + applyRet.Events, err = types.DecodeEvents(ret.EventsBytes) + if err != nil { + return nil, fmt.Errorf("failed to decode events returned by the FVM: %w", err) + } + } + + return applyRet, nil } func (vm *FVM) ApplyImplicitMessage(ctx context.Context, cmsg *types.Message) (*ApplyRet, error) { @@ -565,6 +583,13 @@ func (vm *FVM) ApplyImplicitMessage(ctx context.Context, cmsg *types.Message) (* Duration: duration, } + if vm.returnEvents && len(ret.EventsBytes) > 0 { + applyRet.Events, err = types.DecodeEvents(ret.EventsBytes) + if err != nil { + return nil, fmt.Errorf("failed to decode events returned by the FVM: %w", err) + } + } + if ret.ExitCode != 0 { return applyRet, fmt.Errorf("implicit message failed with exit code: %d and error: %w", ret.ExitCode, applyRet.ActorErr) } diff --git a/chain/vm/invoker.go b/chain/vm/invoker.go index 47bd2e326e0..2dd1f37e6cb 100644 --- a/chain/vm/invoker.go +++ b/chain/vm/invoker.go @@ -291,7 +291,10 @@ func DumpActorState(i *ActorRegistry, act *types.Actor, b []byte) (interface{}, um := actInfo.vmActor.State() if um == nil { - // TODO::FVM @arajasek I would like to assert that we have the empty object here + if act.Code != EmptyObjectCid { + return nil, xerrors.Errorf("actor with code %s should only have empty object (%s) as its Head, instead has %s", act.Code, EmptyObjectCid, act.Head) + } + return nil, nil } if err := um.UnmarshalCBOR(bytes.NewReader(b)); err != nil { diff --git a/chain/vm/vm.go b/chain/vm/vm.go index 5ba6938e579..f09864c2ddc 100644 --- a/chain/vm/vm.go +++ b/chain/vm/vm.go @@ -236,6 +236,8 @@ type VMOpts struct { LookbackState LookbackStateGetter TipSetGetter TipSetGetter Tracing bool + // ReturnEvents decodes and returns emitted events. + ReturnEvents bool } func NewLegacyVM(ctx context.Context, opts *VMOpts) (*LegacyVM, error) { @@ -282,6 +284,7 @@ type ApplyRet struct { ExecutionTrace types.ExecutionTrace Duration time.Duration GasCosts *GasOutputs + Events []types.Event } func (vm *LegacyVM) send(ctx context.Context, msg *types.Message, parent *Runtime, diff --git a/cli/state.go b/cli/state.go index 9441077b1c6..93ede1f5a15 100644 --- a/cli/state.go +++ b/cli/state.go @@ -1360,7 +1360,7 @@ func ComputeStateHTMLTempl(w io.Writer, ts *types.TipSet, o *api.ComputeStateOut "GetMethod": getMethod, "ToFil": toFil, "JsonParams": JsonParams, - "JsonReturn": jsonReturn, + "JsonReturn": JsonReturn, "IsSlow": isSlow, "IsVerySlow": isVerySlow, "IntExit": func(i exitcode.ExitCode) int64 { return int64(i) }, @@ -1446,7 +1446,7 @@ func JsonParams(code cid.Cid, method abi.MethodNum, params []byte) (string, erro return string(b), err } -func jsonReturn(code cid.Cid, method abi.MethodNum, ret []byte) (string, error) { +func JsonReturn(code cid.Cid, method abi.MethodNum, ret []byte) (string, error) { methodMeta, found := consensus.NewActorRegistry().Methods[code][method] // TODO: use remote if !found { return "", fmt.Errorf("method %d not found on actor %s", method, code) @@ -1555,7 +1555,7 @@ func printReceiptReturn(ctx context.Context, api v0api.FullNode, m *types.Messag return err } - jret, err := jsonReturn(act.Code, m.Method, r.Return) + jret, err := JsonReturn(act.Code, m.Method, r.Return) if err != nil { return err } @@ -1695,7 +1695,7 @@ var StateCallCmd = &cli.Command{ return xerrors.Errorf("getting actor: %w", err) } - retStr, err := jsonReturn(act.Code, abi.MethodNum(method), ret.MsgRct.Return) + retStr, err := JsonReturn(act.Code, abi.MethodNum(method), ret.MsgRct.Return) if err != nil { return xerrors.Errorf("decoding return: %w", err) } diff --git a/cli/util/api.go b/cli/util/api.go index b35974c6932..1d6928c3fa2 100644 --- a/cli/util/api.go +++ b/cli/util/api.go @@ -319,11 +319,33 @@ func GetFullNodeAPIV1Single(ctx *cli.Context) (v1api.FullNode, jsonrpc.ClientClo return v1API, closer, nil } -func GetFullNodeAPIV1(ctx *cli.Context) (v1api.FullNode, jsonrpc.ClientCloser, error) { +type GetFullNodeOptions struct { + ethSubHandler api.EthSubscriber +} + +type GetFullNodeOption func(*GetFullNodeOptions) + +func FullNodeWithEthSubscribtionHandler(sh api.EthSubscriber) GetFullNodeOption { + return func(opts *GetFullNodeOptions) { + opts.ethSubHandler = sh + } +} + +func GetFullNodeAPIV1(ctx *cli.Context, opts ...GetFullNodeOption) (v1api.FullNode, jsonrpc.ClientCloser, error) { if tn, ok := ctx.App.Metadata["testnode-full"]; ok { return tn.(v1api.FullNode), func() {}, nil } + var options GetFullNodeOptions + for _, opt := range opts { + opt(&options) + } + + var rpcOpts []jsonrpc.Option + if options.ethSubHandler != nil { + rpcOpts = append(rpcOpts, jsonrpc.WithClientHandler("Filecoin", options.ethSubHandler), jsonrpc.WithClientHandlerAlias("eth_subscription", "Filecoin.EthSubscription")) + } + heads, err := GetRawAPIMulti(ctx, repo.FullNode, "v1") if err != nil { return nil, nil, err @@ -337,7 +359,7 @@ func GetFullNodeAPIV1(ctx *cli.Context) (v1api.FullNode, jsonrpc.ClientCloser, e var closers []jsonrpc.ClientCloser for _, head := range heads { - v1api, closer, err := client.NewFullNodeRPCV1(ctx.Context, head.addr, head.header) + v1api, closer, err := client.NewFullNodeRPCV1(ctx.Context, head.addr, head.header, rpcOpts...) if err != nil { log.Warnf("Not able to establish connection to node with addr: ", head.addr) continue diff --git a/cmd/lotus-gateway/main.go b/cmd/lotus-gateway/main.go index 89b2152ddb5..2023551ef80 100644 --- a/cmd/lotus-gateway/main.go +++ b/cmd/lotus-gateway/main.go @@ -162,7 +162,9 @@ var runCmd = &cli.Command{ log.Fatalf("Cannot register the view: %v", err) } - api, closer, err := lcli.GetFullNodeAPIV1(cctx) + subHnd := gateway.NewEthSubHandler() + + api, closer, err := lcli.GetFullNodeAPIV1(cctx, cliutil.FullNodeWithEthSubscribtionHandler(subHnd)) if err != nil { return err } @@ -195,7 +197,7 @@ var runCmd = &cli.Command{ return xerrors.Errorf("failed to convert endpoint address to multiaddr: %w", err) } - gwapi := gateway.NewNode(api, lookbackCap, waitLookback, rateLimit, rateLimitTimeout) + gwapi := gateway.NewNode(api, subHnd, lookbackCap, waitLookback, rateLimit, rateLimitTimeout) h, err := gateway.Handler(gwapi, api, perConnRateLimit, connPerMinute, serverOptions...) if err != nil { return xerrors.Errorf("failed to set up gateway HTTP handler") diff --git a/cmd/lotus-shed/eth.go b/cmd/lotus-shed/eth.go new file mode 100644 index 00000000000..1ebe2fb59aa --- /dev/null +++ b/cmd/lotus-shed/eth.go @@ -0,0 +1,72 @@ +package main + +import ( + "fmt" + "reflect" + + "github.com/urfave/cli/v2" + + "github.com/filecoin-project/go-state-types/abi" + + "github.com/filecoin-project/lotus/chain/types" + lcli "github.com/filecoin-project/lotus/cli" +) + +var ethCmd = &cli.Command{ + Name: "eth", + Description: "Ethereum compatibility related commands", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "repo", + Value: "~/.lotus", + }, + }, + Subcommands: []*cli.Command{ + checkTipsetsCmd, + }, +} + +var checkTipsetsCmd = &cli.Command{ + Name: "check-tipsets", + Description: "Check that eth_getBlockByNumber and eth_getBlockByHash consistently return tipsets", + Action: func(cctx *cli.Context) error { + api, closer, err := lcli.GetFullNodeAPIV1(cctx) + if err != nil { + return err + } + + defer closer() + ctx := lcli.ReqContext(cctx) + + head, err := api.ChainHead(ctx) + if err != nil { + return err + } + + height := head.Height() + fmt.Println("Current height:", height) + for i := int64(height); i > 0; i-- { + if _, err := api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(i), types.EmptyTSK); err != nil { + fmt.Printf("[FAIL] failed to get tipset @%d from Lotus: %s\n", i, err) + continue + } + hex := fmt.Sprintf("0x%x", i) + ethBlockA, err := api.EthGetBlockByNumber(ctx, hex, false) + if err != nil { + fmt.Printf("[FAIL] failed to get tipset @%d via eth_getBlockByNumber: %s\n", i, err) + continue + } + ethBlockB, err := api.EthGetBlockByHash(ctx, ethBlockA.Hash, false) + if err != nil { + fmt.Printf("[FAIL] failed to get tipset @%d via eth_getBlockByHash: %s\n", i, err) + continue + } + if equal := reflect.DeepEqual(ethBlockA, ethBlockB); equal { + fmt.Printf("[OK] blocks received via eth_getBlockByNumber and eth_getBlockByHash for tipset @%d are identical\n", i) + } else { + fmt.Printf("[FAIL] blocks received via eth_getBlockByNumber and eth_getBlockByHash for tipset @%d are NOT identical\n", i) + } + } + return nil + }, +} diff --git a/cmd/lotus-shed/main.go b/cmd/lotus-shed/main.go index a8ced92f834..19072dd7191 100644 --- a/cmd/lotus-shed/main.go +++ b/cmd/lotus-shed/main.go @@ -51,6 +51,7 @@ func main() { minerCmd, mpoolStatsCmd, exportChainCmd, + ethCmd, exportCarCmd, consensusCmd, syncCmd, diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index 2c853754b15..5ec10834797 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -291,6 +291,8 @@ * [WalletSignMessage](#WalletSignMessage) * [WalletValidateAddress](#WalletValidateAddress) * [WalletVerify](#WalletVerify) +* [Web3](#Web3) + * [Web3ClientVersion](#Web3ClientVersion) ## @@ -2340,7 +2342,7 @@ Inputs: Response: ```json { - "oldestBlock": 42, + "oldestBlock": "0x5", "baseFeePerGas": [ "0x0" ], @@ -2405,7 +2407,7 @@ Response: "gasLimit": "0x5", "gasUsed": "0x5", "timestamp": "0x5", - "extraData": "Ynl0ZSBhcnJheQ==", + "extraData": "0x07", "mixHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e", "nonce": "0x0707070707070707", "baseFeePerGas": "0x0", @@ -2449,7 +2451,7 @@ Response: "gasLimit": "0x5", "gasUsed": "0x5", "timestamp": "0x5", - "extraData": "Ynl0ZSBhcnJheQ==", + "extraData": "0x07", "mixHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e", "nonce": "0x0707070707070707", "baseFeePerGas": "0x0", @@ -2518,40 +2520,7 @@ Perms: write Inputs: ```json [ - [ - 55, - 105, - 12, - 254, - 198, - 193, - 191, - 76, - 59, - 146, - 136, - 199, - 165, - 215, - 131, - 233, - 135, - 49, - 233, - 11, - 10, - 76, - 23, - 124, - 42, - 55, - 76, - 122, - 148, - 39, - 53, - 94 - ] + "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e" ] ``` @@ -2572,40 +2541,7 @@ Perms: write Inputs: ```json [ - [ - 55, - 105, - 12, - 254, - 198, - 193, - 191, - 76, - 59, - 146, - 136, - 199, - 165, - 215, - 131, - 233, - 135, - 49, - 233, - 11, - 10, - 76, - 23, - 124, - 42, - 55, - 76, - 122, - 148, - 39, - 53, - 94 - ] + "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e" ] ``` @@ -2879,43 +2815,7 @@ Perms: write Inputs: `null` -Response: -```json -[ - 55, - 105, - 12, - 254, - 198, - 193, - 191, - 76, - 59, - 146, - 136, - 199, - 165, - 215, - 131, - 233, - 135, - 49, - 233, - 11, - 10, - 76, - 23, - 124, - 42, - 55, - 76, - 122, - 148, - 39, - 53, - 94 -] -``` +Response: `"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"` ### EthNewFilter Installs a persistent filter based on given filter spec. @@ -2936,43 +2836,7 @@ Inputs: ] ``` -Response: -```json -[ - 55, - 105, - 12, - 254, - 198, - 193, - 191, - 76, - 59, - 146, - 136, - 199, - 165, - 215, - 131, - 233, - 135, - 49, - 233, - 11, - 10, - 76, - 23, - 124, - 42, - 55, - 76, - 122, - 148, - 39, - 53, - 94 -] -``` +Response: `"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"` ### EthNewPendingTransactionFilter Installs a persistent filter to notify when new messages arrive in the message pool. @@ -2982,43 +2846,7 @@ Perms: write Inputs: `null` -Response: -```json -[ - 55, - 105, - 12, - 254, - 198, - 193, - 191, - 76, - 59, - 146, - 136, - 199, - 165, - 215, - 131, - 233, - 135, - 49, - 233, - 11, - 10, - 76, - 23, - 124, - 42, - 55, - 76, - 122, - 148, - 39, - 53, - 94 -] -``` +Response: `"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"` ### EthProtocolVersion @@ -3058,57 +2886,11 @@ Perms: write Inputs: ```json [ - "string value", - { - "topics": [ - [ - "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e" - ] - ] - } + "Bw==" ] ``` -Response: -```json -{ - "subscription": [ - 55, - 105, - 12, - 254, - 198, - 193, - 191, - 76, - 59, - 146, - 136, - 199, - 165, - 215, - 131, - 233, - 135, - 49, - 233, - 11, - 10, - 76, - 23, - 124, - 42, - 55, - 76, - 122, - 148, - 39, - 53, - 94 - ], - "result": {} -} -``` +Response: `"0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e"` ### EthUninstallFilter Uninstalls a filter with given id. @@ -3119,40 +2901,7 @@ Perms: write Inputs: ```json [ - [ - 55, - 105, - 12, - 254, - 198, - 193, - 191, - 76, - 59, - 146, - 136, - 199, - 165, - 215, - 131, - 233, - 135, - 49, - 233, - 11, - 10, - 76, - 23, - 124, - 42, - 55, - 76, - 122, - 148, - 39, - 53, - 94 - ] + "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e" ] ``` @@ -3167,40 +2916,7 @@ Perms: write Inputs: ```json [ - [ - 55, - 105, - 12, - 254, - 198, - 193, - 191, - 76, - 59, - 146, - 136, - 199, - 165, - 215, - 131, - 233, - 135, - 49, - 233, - 11, - 10, - 76, - 23, - 124, - 42, - 55, - 76, - 122, - 148, - 39, - 53, - 94 - ] + "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e" ] ``` @@ -9207,3 +8923,16 @@ Inputs: Response: `true` +## Web3 + + +### Web3ClientVersion +Returns the client version + + +Perms: read + +Inputs: `null` + +Response: `"string value"` + diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index 86eac2161f4..0c792ee1d1f 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit 86eac2161f442945bffee3fbfe7d094c20b48dd3 +Subproject commit 0c792ee1d1f062377033d7d37442d18f765be467 diff --git a/gateway/eth_sub.go b/gateway/eth_sub.go new file mode 100644 index 00000000000..76d9139835c --- /dev/null +++ b/gateway/eth_sub.go @@ -0,0 +1,71 @@ +package gateway + +import ( + "context" + "sync" + + "github.com/filecoin-project/go-jsonrpc" + + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/types/ethtypes" +) + +type EthSubHandler struct { + queued map[ethtypes.EthSubscriptionID][]ethtypes.EthSubscriptionResponse + sinks map[ethtypes.EthSubscriptionID]func(context.Context, *ethtypes.EthSubscriptionResponse) error + + lk sync.Mutex +} + +func NewEthSubHandler() *EthSubHandler { + return &EthSubHandler{ + queued: make(map[ethtypes.EthSubscriptionID][]ethtypes.EthSubscriptionResponse), + sinks: make(map[ethtypes.EthSubscriptionID]func(context.Context, *ethtypes.EthSubscriptionResponse) error), + } +} + +func (e *EthSubHandler) AddSub(ctx context.Context, id ethtypes.EthSubscriptionID, sink func(context.Context, *ethtypes.EthSubscriptionResponse) error) error { + e.lk.Lock() + defer e.lk.Unlock() + + for _, p := range e.queued[id] { + p := p // copy + if err := sink(ctx, &p); err != nil { + return err + } + } + delete(e.queued, id) + e.sinks[id] = sink + return nil +} + +func (e *EthSubHandler) RemoveSub(id ethtypes.EthSubscriptionID) { + e.lk.Lock() + defer e.lk.Unlock() + + delete(e.sinks, id) + delete(e.queued, id) +} + +func (e *EthSubHandler) EthSubscription(ctx context.Context, r jsonrpc.RawParams) error { + p, err := jsonrpc.DecodeParams[ethtypes.EthSubscriptionResponse](r) + if err != nil { + return err + } + + e.lk.Lock() + + sink := e.sinks[p.SubscriptionID] + + if sink == nil { + e.queued[p.SubscriptionID] = append(e.queued[p.SubscriptionID], p) + e.lk.Unlock() + return nil + } + + e.lk.Unlock() + + return sink(ctx, &p) // todo track errors and auto-unsubscribe on rpc conn close? +} + +var _ api.EthSubscriber = (*EthSubHandler)(nil) diff --git a/gateway/handler.go b/gateway/handler.go index e9bee6d5281..54ab2467f91 100644 --- a/gateway/handler.go +++ b/gateway/handler.go @@ -27,14 +27,14 @@ const perConnLimiterKey perConnLimiterKeyType = "limiter" type filterTrackerKeyType string -const filterTrackerKey filterTrackerKeyType = "filterTracker" +const statefulCallTrackerKey filterTrackerKeyType = "statefulCallTracker" // Handler returns a gateway http.Handler, to be mounted as-is on the server. func Handler(gwapi lapi.Gateway, api lapi.FullNode, rateLimit int64, connPerMinute int64, opts ...jsonrpc.ServerOption) (http.Handler, error) { m := mux.NewRouter() serveRpc := func(path string, hnd interface{}) { - rpcServer := jsonrpc.NewServer(append(opts, jsonrpc.WithServerErrors(lapi.RPCErrors))...) + rpcServer := jsonrpc.NewServer(append(opts, jsonrpc.WithReverseClient[lapi.EthSubscriberMethods]("Filecoin"), jsonrpc.WithServerErrors(lapi.RPCErrors))...) rpcServer.Register("Filecoin", hnd) rpcServer.AliasMethod("rpc.discover", "Filecoin.Discover") @@ -90,7 +90,7 @@ func (h RateLimiterHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { r = r.WithContext(context.WithValue(r.Context(), perConnLimiterKey, h.limiter)) // also add a filter tracker to the context - r = r.WithContext(context.WithValue(r.Context(), filterTrackerKey, newFilterTracker())) + r = r.WithContext(context.WithValue(r.Context(), statefulCallTrackerKey, newStatefulCallTracker())) h.handler.ServeHTTP(w, r) } diff --git a/gateway/node.go b/gateway/node.go index bfe0c7c0b61..29f9579f773 100644 --- a/gateway/node.go +++ b/gateway/node.go @@ -12,6 +12,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-bitfield" + "github.com/filecoin-project/go-jsonrpc" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/dline" "github.com/filecoin-project/go-state-types/network" @@ -93,6 +94,8 @@ type TargetAPI interface { EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error) EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (ethtypes.EthBlock, error) EthGetTransactionByHash(ctx context.Context, txHash *ethtypes.EthHash) (*ethtypes.EthTx, error) + EthGetTransactionHashByCid(ctx context.Context, cid cid.Cid) (*ethtypes.EthHash, error) + 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) (*api.EthTxReceipt, error) EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash ethtypes.EthHash, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error) @@ -117,14 +120,16 @@ type TargetAPI interface { EthNewBlockFilter(ctx context.Context) (ethtypes.EthFilterID, error) EthNewPendingTransactionFilter(ctx context.Context) (ethtypes.EthFilterID, error) EthUninstallFilter(ctx context.Context, id ethtypes.EthFilterID) (bool, error) - EthSubscribe(ctx context.Context, eventType string, params *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) + EthSubscribe(ctx context.Context, params jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error) + Web3ClientVersion(ctx context.Context) (string, error) } var _ TargetAPI = *new(api.FullNode) // gateway depends on latest type Node struct { target TargetAPI + subHnd *EthSubHandler lookbackCap time.Duration stateWaitLookbackLimit abi.ChainEpoch rateLimiter *rate.Limiter @@ -141,7 +146,7 @@ var ( ) // NewNode creates a new gateway node. -func NewNode(api TargetAPI, lookbackCap time.Duration, stateWaitLookbackLimit abi.ChainEpoch, rateLimit int64, rateLimitTimeout time.Duration) *Node { +func NewNode(api TargetAPI, sHnd *EthSubHandler, lookbackCap time.Duration, stateWaitLookbackLimit abi.ChainEpoch, rateLimit int64, rateLimitTimeout time.Duration) *Node { var limit rate.Limit if rateLimit == 0 { limit = rate.Inf @@ -150,6 +155,7 @@ func NewNode(api TargetAPI, lookbackCap time.Duration, stateWaitLookbackLimit ab } return &Node{ target: api, + subHnd: sHnd, lookbackCap: lookbackCap, stateWaitLookbackLimit: stateWaitLookbackLimit, rateLimiter: rate.NewLimiter(limit, stateRateLimitTokens), diff --git a/gateway/node_test.go b/gateway/node_test.go index 805767dc627..aa33e8bfb20 100644 --- a/gateway/node_test.go +++ b/gateway/node_test.go @@ -89,7 +89,7 @@ func TestGatewayAPIChainGetTipSetByHeight(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { mock := &mockGatewayDepsAPI{} - a := NewNode(mock, DefaultLookbackCap, DefaultStateWaitLookbackLimit, 0, time.Minute) + a := NewNode(mock, nil, DefaultLookbackCap, DefaultStateWaitLookbackLimit, 0, time.Minute) // Create tipsets from genesis up to tskh and return the highest ts := mock.createTipSets(tt.args.tskh, tt.args.genesisTS) @@ -245,7 +245,7 @@ func TestGatewayVersion(t *testing.T) { //stm: @GATEWAY_NODE_GET_VERSION_001 ctx := context.Background() mock := &mockGatewayDepsAPI{} - a := NewNode(mock, DefaultLookbackCap, DefaultStateWaitLookbackLimit, 0, time.Minute) + a := NewNode(mock, nil, DefaultLookbackCap, DefaultStateWaitLookbackLimit, 0, time.Minute) v, err := a.Version(ctx) require.NoError(t, err) @@ -256,7 +256,7 @@ func TestGatewayLimitTokensAvailable(t *testing.T) { ctx := context.Background() mock := &mockGatewayDepsAPI{} tokens := 3 - a := NewNode(mock, DefaultLookbackCap, DefaultStateWaitLookbackLimit, int64(tokens), time.Minute) + a := NewNode(mock, nil, DefaultLookbackCap, DefaultStateWaitLookbackLimit, int64(tokens), time.Minute) require.NoError(t, a.limit(ctx, tokens), "requests should not be limited when there are enough tokens available") } @@ -264,7 +264,7 @@ func TestGatewayLimitTokensNotAvailable(t *testing.T) { ctx := context.Background() mock := &mockGatewayDepsAPI{} tokens := 3 - a := NewNode(mock, DefaultLookbackCap, DefaultStateWaitLookbackLimit, int64(1), time.Millisecond) + a := NewNode(mock, nil, DefaultLookbackCap, DefaultStateWaitLookbackLimit, int64(1), time.Millisecond) var err error // try to be rate limited for i := 0; i <= 1000; i++ { diff --git a/gateway/proxy_eth.go b/gateway/proxy_eth.go index fcad213d9ab..40b68f5002b 100644 --- a/gateway/proxy_eth.go +++ b/gateway/proxy_eth.go @@ -3,12 +3,15 @@ package gateway import ( "bytes" "context" + "encoding/json" "fmt" "sync" "time" + "github.com/ipfs/go-cid" "golang.org/x/xerrors" + "github.com/filecoin-project/go-jsonrpc" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" @@ -17,6 +20,14 @@ import ( "github.com/filecoin-project/lotus/chain/types/ethtypes" ) +func (gw *Node) Web3ClientVersion(ctx context.Context) (string, error) { + if err := gw.limit(ctx, stateRateLimitTokens); err != nil { + return "", err + } + + return gw.target.Web3ClientVersion(ctx) +} + func (gw *Node) EthAccounts(ctx context.Context) ([]ethtypes.EthAddress, error) { // gateway provides public API, so it can't hold user accounts return []ethtypes.EthAddress{}, nil @@ -141,6 +152,22 @@ func (gw *Node) EthGetTransactionByHash(ctx context.Context, txHash *ethtypes.Et return gw.target.EthGetTransactionByHash(ctx, txHash) } +func (gw *Node) EthGetTransactionHashByCid(ctx context.Context, cid cid.Cid) (*ethtypes.EthHash, error) { + if err := gw.limit(ctx, stateRateLimitTokens); err != nil { + return nil, err + } + + return gw.target.EthGetTransactionHashByCid(ctx, cid) +} + +func (gw *Node) EthGetMessageCidByTransactionHash(ctx context.Context, txHash *ethtypes.EthHash) (*cid.Cid, error) { + if err := gw.limit(ctx, stateRateLimitTokens); err != nil { + return nil, err + } + + return gw.target.EthGetMessageCidByTransactionHash(ctx, txHash) +} + func (gw *Node) EthGetTransactionCount(ctx context.Context, sender ethtypes.EthAddress, blkOpt string) (ethtypes.EthUint64, error) { if err := gw.limit(ctx, stateRateLimitTokens); err != nil { return 0, err @@ -352,7 +379,7 @@ func (gw *Node) EthGetFilterChanges(ctx context.Context, id ethtypes.EthFilterID return nil, err } - ft := filterTrackerFromContext(ctx) + ft := statefulCallFromContext(ctx) ft.lk.Lock() _, ok := ft.userFilters[id] ft.lk.Unlock() @@ -369,7 +396,7 @@ func (gw *Node) EthGetFilterLogs(ctx context.Context, id ethtypes.EthFilterID) ( return nil, err } - ft := filterTrackerFromContext(ctx) + ft := statefulCallFromContext(ctx) ft.lk.Lock() _, ok := ft.userFilters[id] ft.lk.Unlock() @@ -417,7 +444,7 @@ func (gw *Node) EthUninstallFilter(ctx context.Context, id ethtypes.EthFilterID) } // check if the filter belongs to this connection - ft := filterTrackerFromContext(ctx) + ft := statefulCallFromContext(ctx) ft.lk.Lock() defer ft.lk.Unlock() @@ -434,18 +461,88 @@ func (gw *Node) EthUninstallFilter(ctx context.Context, id ethtypes.EthFilterID) return ok, nil } -func (gw *Node) EthSubscribe(ctx context.Context, eventType string, params *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) { - return nil, xerrors.Errorf("not implemented") +func (gw *Node) EthSubscribe(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) { + // validate params + _, err := jsonrpc.DecodeParams[ethtypes.EthSubscribeParams](p) + if err != nil { + return ethtypes.EthSubscriptionID{}, xerrors.Errorf("decoding params: %w", err) + } + + if err := gw.limit(ctx, stateRateLimitTokens); err != nil { + return ethtypes.EthSubscriptionID{}, err + } + + if gw.subHnd == nil { + return ethtypes.EthSubscriptionID{}, xerrors.New("subscription support not enabled") + } + + ethCb, ok := jsonrpc.ExtractReverseClient[api.EthSubscriberMethods](ctx) + if !ok { + return ethtypes.EthSubscriptionID{}, xerrors.Errorf("connection doesn't support callbacks") + } + + ft := statefulCallFromContext(ctx) + ft.lk.Lock() + defer ft.lk.Unlock() + + if len(ft.userSubscriptions) >= EthMaxFiltersPerConn { + return ethtypes.EthSubscriptionID{}, fmt.Errorf("too many subscriptions") + } + + sub, err := gw.target.EthSubscribe(ctx, p) + if err != nil { + return ethtypes.EthSubscriptionID{}, err + } + + err = gw.subHnd.AddSub(ctx, sub, func(ctx context.Context, response *ethtypes.EthSubscriptionResponse) error { + outParam, err := json.Marshal(response) + if err != nil { + return err + } + + return ethCb.EthSubscription(ctx, outParam) + }) + if err != nil { + return ethtypes.EthSubscriptionID{}, err + } + + ft.userSubscriptions[sub] = time.Now() + + return sub, err } func (gw *Node) EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error) { - return false, xerrors.Errorf("not implemented") + if err := gw.limit(ctx, stateRateLimitTokens); err != nil { + return false, err + } + + // check if the filter belongs to this connection + ft := statefulCallFromContext(ctx) + ft.lk.Lock() + defer ft.lk.Unlock() + + if _, ok := ft.userSubscriptions[id]; !ok { + return false, nil + } + + ok, err := gw.target.EthUnsubscribe(ctx, id) + if err != nil { + return false, err + } + + delete(ft.userSubscriptions, id) + + if gw.subHnd != nil { + gw.subHnd.RemoveSub(id) + } + + return ok, nil } var EthMaxFiltersPerConn = 16 // todo make this configurable func addUserFilterLimited(ctx context.Context, cb func() (ethtypes.EthFilterID, error)) (ethtypes.EthFilterID, error) { - ft := filterTrackerFromContext(ctx) + ft := statefulCallFromContext(ctx) ft.lk.Lock() defer ft.lk.Unlock() @@ -463,19 +560,21 @@ func addUserFilterLimited(ctx context.Context, cb func() (ethtypes.EthFilterID, return id, nil } -func filterTrackerFromContext(ctx context.Context) *filterTracker { - return ctx.Value(filterTrackerKey).(*filterTracker) +func statefulCallFromContext(ctx context.Context) *statefulCallTracker { + return ctx.Value(statefulCallTrackerKey).(*statefulCallTracker) } -type filterTracker struct { +type statefulCallTracker struct { lk sync.Mutex - userFilters map[ethtypes.EthFilterID]time.Time + userFilters map[ethtypes.EthFilterID]time.Time + userSubscriptions map[ethtypes.EthSubscriptionID]time.Time } // called per request (ws connection) -func newFilterTracker() *filterTracker { - return &filterTracker{ - userFilters: make(map[ethtypes.EthFilterID]time.Time), +func newStatefulCallTracker() *statefulCallTracker { + return &statefulCallTracker{ + userFilters: make(map[ethtypes.EthFilterID]time.Time), + userSubscriptions: make(map[ethtypes.EthSubscriptionID]time.Time), } } diff --git a/gen/api/proxygen.go b/gen/api/proxygen.go index f756c0d0c18..75fbc668c90 100644 --- a/gen/api/proxygen.go +++ b/gen/api/proxygen.go @@ -259,7 +259,7 @@ func generate(path, pkg, outpkg, outfile string) error { if len(tf) != 2 { continue } - if tf[0] != "perm" { // todo: allow more tag types + if tf[0] != "perm" && tf[0] != "rpc_method" && tf[0] != "notify" { // todo: allow more tag types continue } info.Methods[mname].Tags[tf[0]] = tf @@ -302,12 +302,14 @@ type {{.Num}}Struct struct { {{range .Include}} {{.}}Struct {{end}} - Internal struct { + Internal {{.Num}}Methods +} + +type {{.Num}}Methods struct { {{range .Methods}} {{.Num}} func({{.NamedParams}}) ({{.Results}}) `+"`"+`{{range .Tags}}{{index . 0}}:"{{index . 1}}"{{end}}`+"`"+` {{end}} } -} type {{.Num}}Stub struct { {{range .Include}} diff --git a/go.mod b/go.mod index dbd2459c7bf..1387b33c9fe 100644 --- a/go.mod +++ b/go.mod @@ -40,11 +40,11 @@ require ( github.com/filecoin-project/go-fil-commcid v0.1.0 github.com/filecoin-project/go-fil-commp-hashhash v0.1.0 github.com/filecoin-project/go-fil-markets v1.26.0 - github.com/filecoin-project/go-jsonrpc v0.1.9 + github.com/filecoin-project/go-jsonrpc v0.2.1 github.com/filecoin-project/go-legs v0.4.4 github.com/filecoin-project/go-padreader v0.0.1 github.com/filecoin-project/go-paramfetch v0.0.4 - github.com/filecoin-project/go-state-types v0.10.0-alpha-10 + github.com/filecoin-project/go-state-types v0.10.0-alpha-11 github.com/filecoin-project/go-statemachine v1.0.2 github.com/filecoin-project/go-statestore v0.2.0 github.com/filecoin-project/go-storedcounter v0.1.0 @@ -61,10 +61,12 @@ require ( github.com/gbrlsnchs/jwt/v3 v3.0.1 github.com/gdamore/tcell/v2 v2.2.0 github.com/go-kit/kit v0.12.0 + github.com/go-openapi/spec v0.19.11 github.com/golang/mock v1.6.0 github.com/google/uuid v1.3.0 github.com/gorilla/mux v1.8.0 github.com/gorilla/websocket v1.5.0 + github.com/gregdhill/go-openrpc v0.0.0-20220114144539-ae6f44720487 github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e github.com/hashicorp/go-multierror v1.1.1 @@ -144,6 +146,7 @@ require ( github.com/whyrusleeping/cbor-gen v0.0.0-20221021053955-c138aae13722 github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4 github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 + github.com/xeipuuv/gojsonschema v1.2.0 github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 go.opencensus.io v0.23.0 go.opentelemetry.io/otel v1.11.1 @@ -211,7 +214,6 @@ require ( github.com/go-ole/go-ole v1.2.5 // indirect github.com/go-openapi/jsonpointer v0.19.3 // indirect github.com/go-openapi/jsonreference v0.19.4 // indirect - github.com/go-openapi/spec v0.19.11 // indirect github.com/go-openapi/swag v0.19.11 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect @@ -324,6 +326,8 @@ require ( github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/zondax/hid v0.9.1 // indirect github.com/zondax/ledger-go v0.12.1 // indirect diff --git a/go.sum b/go.sum index bf049f3a0e9..7a15ec7034d 100644 --- a/go.sum +++ b/go.sum @@ -340,8 +340,8 @@ github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0/go.mod h1:7aWZdaQ1b16BVoQUYR+ github.com/filecoin-project/go-hamt-ipld/v3 v3.0.1/go.mod h1:gXpNmr3oQx8l3o7qkGyDjJjYSRX7hp/FGOStdqrWyDI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0 h1:rVVNq0x6RGQIzCo1iiJlGFm9AGIZzeifggxtKMU7zmI= github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0/go.mod h1:bxmzgT8tmeVQA1/gvBwFmYdT8SOFUwB3ovSUfG1Ux0g= -github.com/filecoin-project/go-jsonrpc v0.1.9 h1:HRWLxo7HAWzI3xZGeFG4LZJoYpms+Q+8kwmMTLnyS3A= -github.com/filecoin-project/go-jsonrpc v0.1.9/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4= +github.com/filecoin-project/go-jsonrpc v0.2.1 h1:xfxkfIAO300sPiV59DnxnCb4sdTtWYlRz/TsP+ByT2E= +github.com/filecoin-project/go-jsonrpc v0.2.1/go.mod h1:jBSvPTl8V1N7gSTuCR4bis8wnQnIjHbRPpROol6iQKM= github.com/filecoin-project/go-legs v0.4.4 h1:mpMmAOOnamaz0CV9rgeKhEWA8j9kMC+f+UGCGrxKaZo= github.com/filecoin-project/go-legs v0.4.4/go.mod h1:JQ3hA6xpJdbR8euZ2rO0jkxaMxeidXf0LDnVuqPAe9s= github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= @@ -356,8 +356,8 @@ github.com/filecoin-project/go-state-types v0.1.0/go.mod h1:ezYnPf0bNkTsDibL/psS github.com/filecoin-project/go-state-types v0.1.6/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q= github.com/filecoin-project/go-state-types v0.1.8/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q= github.com/filecoin-project/go-state-types v0.1.10/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q= -github.com/filecoin-project/go-state-types v0.10.0-alpha-10 h1:QUpSayVFUADlrtzCh7SDNlbuaNSlYPBR46Nt7WpFl9I= -github.com/filecoin-project/go-state-types v0.10.0-alpha-10/go.mod h1:FPgQE05BFwZxKw/vCuIaIrzfJKo4RPQQMMPGd43dAFI= +github.com/filecoin-project/go-state-types v0.10.0-alpha-11 h1:lfrbmLXaC3vQk1gQCUwtTuY1U2ANrgDsJ7+VapBjRCo= +github.com/filecoin-project/go-state-types v0.10.0-alpha-11/go.mod h1:aLIas+W8BWAfpLWEPUOGMPBdhcVwoCG4pIQSQk26024= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= github.com/filecoin-project/go-statemachine v1.0.2 h1:421SSWBk8GIoCoWYYTE/d+qCWccgmRH0uXotXRDjUbc= github.com/filecoin-project/go-statemachine v1.0.2/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54= @@ -447,6 +447,7 @@ github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwoh github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= github.com/go-openapi/jsonreference v0.19.4 h1:3Vw+rh13uq2JFNxgnMTGE1rnoieU9FmyE1gvnyylsYg= github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= +github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= github.com/go-openapi/spec v0.19.7/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= github.com/go-openapi/spec v0.19.11 h1:ogU5q8dtp3MMPn59a9VRrPKVxvJHEs5P7yNMR5sNnis= github.com/go-openapi/spec v0.19.11/go.mod h1:vqK/dIdLGCosfvYsQV3WfC7N3TiZSnGY2RZKoFK7X28= @@ -460,6 +461,10 @@ github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/logger v1.0.0/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs= +github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q= +github.com/gobuffalo/packr/v2 v2.6.0/go.mod h1:sgEE1xNZ6G0FNN5xn9pevVu4nywaxHvgup67xisti08= github.com/godbus/dbus v0.0.0-20190402143921-271e53dc4968/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -582,6 +587,8 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gregdhill/go-openrpc v0.0.0-20220114144539-ae6f44720487 h1:NyaWOSkqFK1d9o+HLfnMIGzrHuUUPeBNIZyi5Zoe/lY= +github.com/gregdhill/go-openrpc v0.0.0-20220114144539-ae6f44720487/go.mod h1:a1eRkbhd3DYpRH2lnuUsVG+QMTI+v0hGnsis8C9hMrA= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= @@ -661,6 +668,7 @@ github.com/icza/backscanner v0.0.0-20210726202459-ac2ffc679f94 h1:9tcYMdi+7Rb1y0 github.com/icza/backscanner v0.0.0-20210726202459-ac2ffc679f94/go.mod h1:GYeBD1CF7AqnKZK+UCytLcY3G+UKo0ByXX/3xfdNyqQ= github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6 h1:8UsGZ2rr2ksmEru6lToqnXgA8Mz1DP11X4zSJ159C3k= github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6/go.mod h1:xQig96I1VNBDIWGCdTt54nHt6EeI639SmHycLYL7FkA= +github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab h1:HqW4xhhynfjrtEiiSGcQUd6vrK23iMam1FO8rI7mwig= @@ -823,7 +831,6 @@ github.com/ipfs/go-log/v2 v2.0.1/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBW github.com/ipfs/go-log/v2 v2.0.2/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= github.com/ipfs/go-log/v2 v2.0.3/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= -github.com/ipfs/go-log/v2 v2.0.8/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= github.com/ipfs/go-log/v2 v2.1.1/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= github.com/ipfs/go-log/v2 v2.1.2-0.20200626104915-0016c0b4b3e4/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= github.com/ipfs/go-log/v2 v2.1.2/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= @@ -927,6 +934,7 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8l6qbCUTSiRLG/iKnW3K3/QfPPuSsBt4= github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.1.1-0.20190114141812-62fb9bc030d1/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= @@ -955,6 +963,7 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kabukky/httpscerts v0.0.0-20150320125433-617593d7dcb3/go.mod h1:BYpt4ufZiIGv2nXn4gMxnfKV306n3mWXgNu/d2TqdTU= github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= +github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= github.com/kilic/bls12-381 v0.0.0-20200607163746-32e1441c8a9f/go.mod h1:XXfR6YFCRSrkEXbNlIyDsgXVNJWVUV30m/ebkVy9n6s= @@ -980,6 +989,7 @@ github.com/klauspost/cpuid/v2 v2.1.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8t github.com/koalacxr/quantile v0.0.1 h1:wAW+SQ286Erny9wOjVww96t8ws+x5Zj6AKHDULUK+o0= github.com/koalacxr/quantile v0.0.1/go.mod h1:bGN/mCZLZ4lrSDHRQ6Lglj9chowGux8sGUIND+DQeD0= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= @@ -994,6 +1004,7 @@ github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= @@ -1697,6 +1708,7 @@ github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= @@ -1783,6 +1795,7 @@ github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3 github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -1801,6 +1814,8 @@ github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpP github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= +github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g= github.com/tidwall/gjson v1.6.0 h1:9VEQWz6LLMUsUl6PueE49ir4Ka6CzLymOAZDxpFsTDc= github.com/tidwall/gjson v1.6.0/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls= @@ -1886,6 +1901,12 @@ github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go. github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow= github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1:m2aV4LZI4Aez7dP5PMyVKEHhUyEJ/RjmPEDOpDvudHg= github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xorcare/golden v0.6.0/go.mod h1:7T39/ZMvaSEZlBPoYfVFmsBLmUl3uz9IuzWj/U6FtvQ= github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 h1:oWgZJmC1DorFZDpfMfWg7xk29yEOZiXmo/wZl+utTI8= @@ -2010,6 +2031,7 @@ golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -2197,12 +2219,14 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190524122548-abf6ff778158/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190524152521-dbbf3f1254d4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2314,6 +2338,7 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= diff --git a/itests/contracts/AutoSelfDestruct.hex b/itests/contracts/AutoSelfDestruct.hex new file mode 100644 index 00000000000..f5128bf3039 --- /dev/null +++ b/itests/contracts/AutoSelfDestruct.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b5061001f61002460201b60201c565b61003d565b3373ffffffffffffffffffffffffffffffffffffffff16ff5b60848061004b6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806383197ef014602d575b600080fd5b60336035565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea26469706673582212208d48a69a112633756d84552847610df29b02ac89dd39e4e295066e99a45e809664736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/AutoSelfDestruct.sol b/itests/contracts/AutoSelfDestruct.sol new file mode 100644 index 00000000000..bdb165f5d13 --- /dev/null +++ b/itests/contracts/AutoSelfDestruct.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; + +contract AutoSelfDestruct { + constructor() { + destroy(); + } + function destroy() public { + selfdestruct(payable(msg.sender)); + } +} diff --git a/itests/contracts/Constructor.hex b/itests/contracts/Constructor.hex new file mode 100644 index 00000000000..e46d5bcd1f2 --- /dev/null +++ b/itests/contracts/Constructor.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b506103ca806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c806358f5ebb614610030575b600080fd5b61004a60048036038101906100459190610123565b610060565b6040516100579190610191565b60405180910390f35b60008082604051610070906100db565b61007a91906101bb565b604051809103906000f080158015610096573d6000803e3d6000fd5b5090507f3a5c468996b00310e3e82919e3af9cce21d49c40c39a2627a9f946e1a54d886232846040516100ca9291906101d6565b60405180910390a180915050919050565b6101958061020083390190565b600080fd5b6000819050919050565b610100816100ed565b811461010b57600080fd5b50565b60008135905061011d816100f7565b92915050565b600060208284031215610139576101386100e8565b5b60006101478482850161010e565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061017b82610150565b9050919050565b61018b81610170565b82525050565b60006020820190506101a66000830184610182565b92915050565b6101b5816100ed565b82525050565b60006020820190506101d060008301846101ac565b92915050565b60006040820190506101eb6000830185610182565b6101f860208301846101ac565b939250505056fe608060405234801561001057600080fd5b506040516101953803806101958339818101604052810190610032919061007a565b80600081905550506100a7565b600080fd5b6000819050919050565b61005781610044565b811461006257600080fd5b50565b6000815190506100748161004e565b92915050565b6000602082840312156100905761008f61003f565b5b600061009e84828501610065565b91505092915050565b60e0806100b56000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80638381f58a146037578063eeb4e367146051575b600080fd5b603d606b565b604051604891906091565b60405180910390f35b60576071565b604051606291906091565b60405180910390f35b60005481565b60008054905090565b6000819050919050565b608b81607a565b82525050565b600060208201905060a460008301846084565b9291505056fea2646970667358221220451c388f24a935fc5f5eef536207cbd982254ac8521d49937bb10e5079e3924164736f6c63430008110033a264697066735822122027da159d84a9bdcd5aff5755c4602f7099db638f7a95d715c76454c99511146f64736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/Constructor.sol b/itests/contracts/Constructor.sol new file mode 100644 index 00000000000..a85d13269f3 --- /dev/null +++ b/itests/contracts/Constructor.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.2; + + +contract Test_contract { + uint256 public number; + + constructor(uint256 _number) { + number = _number; + } + + function get_number() public view returns (uint256) { + return number; + } +} + +contract App { + + event NewTest(address sender, uint256 number); + + function new_Test(uint256 number) + public + returns (address) + { + address mynew = address(new Test_contract({_number: number})); + emit NewTest(tx.origin, number); + return mynew; + } +} diff --git a/itests/contracts/DelegatecallStorage.hex b/itests/contracts/DelegatecallStorage.hex index 7ce9ef210d3..966e9e906fe 100644 --- a/itests/contracts/DelegatecallStorage.hex +++ b/itests/contracts/DelegatecallStorage.hex @@ -1 +1 @@ -608060405234801561001057600080fd5b50610477806100206000396000f3fe6080604052600436106100345760003560e01c806361bc221a146100395780638ada066e14610064578063d1e0f3081461008f575b600080fd5b34801561004557600080fd5b5061004e6100bf565b60405161005b919061022c565b60405180910390f35b34801561007057600080fd5b506100796100c5565b604051610086919061022c565b60405180910390f35b6100a960048036038101906100a491906102d6565b6100ce565b6040516100b6919061022c565b60405180910390f35b60005481565b60008054905090565b6000808373ffffffffffffffffffffffffffffffffffffffff16836040516024016100f9919061022c565b6040516020818303038152906040527f6466414b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516101839190610387565b600060405180830381855af49150503d80600081146101be576040519150601f19603f3d011682016040523d82523d6000602084013e6101c3565b606091505b5050905080610207576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101fe90610421565b60405180910390fd5b60005491505092915050565b6000819050919050565b61022681610213565b82525050565b6000602082019050610241600083018461021d565b92915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102778261024c565b9050919050565b6102878161026c565b811461029257600080fd5b50565b6000813590506102a48161027e565b92915050565b6102b381610213565b81146102be57600080fd5b50565b6000813590506102d0816102aa565b92915050565b600080604083850312156102ed576102ec610247565b5b60006102fb85828601610295565b925050602061030c858286016102c1565b9150509250929050565b600081519050919050565b600081905092915050565b60005b8381101561034a57808201518184015260208101905061032f565b60008484015250505050565b600061036182610316565b61036b8185610321565b935061037b81856020860161032c565b80840191505092915050565b60006103938284610356565b915081905092915050565b600082825260208201905092915050565b7f4572726f72206d6573736167653a2044656c656761746563616c6c206661696c60008201527f6564000000000000000000000000000000000000000000000000000000000000602082015250565b600061040b60228361039e565b9150610416826103af565b604082019050919050565b6000602082019050818103600083015261043a816103fe565b905091905056fea26469706673582212203663909b8221e9b87047be99420c00339af1430c085260df209b909ed8e0f05164736f6c63430008110033 \ No newline at end of file +608060405234801561001057600080fd5b5061087e806100206000396000f3fe6080604052600436106100555760003560e01c80630712ede21461005a57806361bc221a1461008a5780637da3c3ab146100b55780638ada066e146100cc578063bed56f47146100f7578063d1e0f30814610127575b600080fd5b610074600480360381019061006f919061060f565b610157565b604051610081919061065e565b60405180910390f35b34801561009657600080fd5b5061009f610298565b6040516100ac919061065e565b60405180910390f35b3480156100c157600080fd5b506100ca61029e565b005b3480156100d857600080fd5b506100e16102e1565b6040516100ee919061065e565b60405180910390f35b610111600480360381019061010c919061060f565b6102ea565b60405161011e919061065e565b60405180910390f35b610141600480360381019061013c919061060f565b610431565b60405161014e919061065e565b60405180910390f35b6000808373ffffffffffffffffffffffffffffffffffffffff1683604051602401610182919061065e565b6040516020818303038152906040527f6466414b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161020c91906106ea565b600060405180830381855af49150503d8060008114610247576040519150601f19603f3d011682016040523d82523d6000602084013e61024c565b606091505b505090506000610291576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102889061075e565b60405180910390fd5b5092915050565b60005481565b60006102df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d69061075e565b60405180910390fd5b565b60008054905090565b6000808373ffffffffffffffffffffffffffffffffffffffff16848460405160240161031792919061078d565b6040516020818303038152906040527fbed56f47000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516103a191906106ea565b600060405180830381855af49150503d80600081146103dc576040519150601f19603f3d011682016040523d82523d6000602084013e6103e1565b606091505b5050905080610425576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161041c90610828565b60405180910390fd5b60005491505092915050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160240161045c919061065e565b6040516020818303038152906040527f6466414b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516104e691906106ea565b600060405180830381855af49150503d8060008114610521576040519150601f19603f3d011682016040523d82523d6000602084013e610526565b606091505b505090508061056a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161056190610828565b60405180910390fd5b60005491505092915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006105a68261057b565b9050919050565b6105b68161059b565b81146105c157600080fd5b50565b6000813590506105d3816105ad565b92915050565b6000819050919050565b6105ec816105d9565b81146105f757600080fd5b50565b600081359050610609816105e3565b92915050565b6000806040838503121561062657610625610576565b5b6000610634858286016105c4565b9250506020610645858286016105fa565b9150509250929050565b610658816105d9565b82525050565b6000602082019050610673600083018461064f565b92915050565b600081519050919050565b600081905092915050565b60005b838110156106ad578082015181840152602081019050610692565b60008484015250505050565b60006106c482610679565b6106ce8185610684565b93506106de81856020860161068f565b80840191505092915050565b60006106f682846106b9565b915081905092915050565b600082825260208201905092915050565b7f696e74656e74696f6e616c6c79207468726f77696e67206572726f7200000000600082015250565b6000610748601c83610701565b915061075382610712565b602082019050919050565b600060208201905081810360008301526107778161073b565b9050919050565b6107878161059b565b82525050565b60006040820190506107a2600083018561077e565b6107af602083018461064f565b9392505050565b7f4572726f72206d6573736167653a2044656c656761746563616c6c206661696c60008201527f6564000000000000000000000000000000000000000000000000000000000000602082015250565b6000610812602283610701565b915061081d826107b6565b604082019050919050565b6000602082019050818103600083015261084181610805565b905091905056fea2646970667358221220b2a3ae7e2a9ffc78e3e2a7aadb2885435c5e51aa9d3f07372a0dffb6238aa1db64736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/DelegatecallStorage.sol b/itests/contracts/DelegatecallStorage.sol index 434cd934e3e..15e672082a6 100644 --- a/itests/contracts/DelegatecallStorage.sol +++ b/itests/contracts/DelegatecallStorage.sol @@ -5,13 +5,29 @@ contract DelegatecallStorage { uint public counter; function getCounter() public view returns (uint){ - return counter; + return counter; } function setVars(address _contract, uint _counter) public payable returns (uint){ + (bool success, ) = _contract.delegatecall( + abi.encodeWithSignature("setVars(uint256)", _counter) + ); + require(success, 'Error message: Delegatecall failed'); + return counter; + } + function setVarsSelf(address _contract, uint _counter) public payable returns (uint){ + (bool success, ) = _contract.delegatecall( + abi.encodeWithSignature("setVarsSelf(address,uint256)", _contract, _counter) + ); + require(success, 'Error message: Delegatecall failed'); + return counter; + } + function setVarsRevert(address _contract, uint _counter) public payable returns (uint){ (bool success, ) = _contract.delegatecall( abi.encodeWithSignature("setVars(uint256)", _counter) ); - require(success, 'Error message: Delegatecall failed'); - return counter; + require(false,"intentionally throwing error"); + } + function revert() public{ + require(false,"intentionally throwing error"); } } diff --git a/itests/contracts/EventMatrix.hex b/itests/contracts/EventMatrix.hex index 2b3ad91ada9..be831e397c9 100644 --- a/itests/contracts/EventMatrix.hex +++ b/itests/contracts/EventMatrix.hex @@ -1 +1 @@ -608060405234801561001057600080fd5b506105eb806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c8063c755553811610071578063c755553814610198578063cbfc3b58146101c6578063cc6f8faf14610212578063cd5b6c3d14610254578063e2a614731461028c578063fb62b28b146102d8576100a9565b80630919b8be146100ae5780636199074d146100e657806366eef3461461012857806375091b1f14610132578063a63ae81a1461016a575b600080fd5b6100e4600480360360408110156100c457600080fd5b81019080803590602001909291908035906020019092919050505061031a565b005b610126600480360360608110156100fc57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919050505061035d565b005b610130610391565b005b6101686004803603604081101561014857600080fd5b8101908080359060200190929190803590602001909291905050506103bf565b005b6101966004803603602081101561018057600080fd5b81019080803590602001909291905050506103fb565b005b6101c4600480360360208110156101ae57600080fd5b8101908080359060200190929190505050610435565b005b610210600480360360808110156101dc57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919080359060200190929190505050610465565b005b6102526004803603606081101561022857600080fd5b810190808035906020019092919080359060200190929190803590602001909291905050506104ba565b005b61028a6004803603604081101561026a57600080fd5b8101908080359060200190929190803590602001909291905050506104f8565b005b6102d6600480360360808110156102a257600080fd5b810190808035906020019092919080359060200190929190803590602001909291908035906020019092919050505061052a565b005b610318600480360360608110156102ee57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919050505061056a565b005b7f5469c6b769315f5668523937f05ca07d4cc87849432bc5f5907f1d90fa73b9f98282604051808381526020018281526020019250505060405180910390a15050565b8082847fb89dabcdb7ff41f1794c0da92f65ece6c19b6b0caeac5407b2a721efe27c080460405160405180910390a4505050565b7fc3f6f1c76bd4e74ee5782052b0b4f8bd5c50b86c3c5a2f52638e03066e50a91b60405160405180910390a1565b817f6709824ebe5f6e620ca3f4b02a3428e8ce2dc97c550816eaeeb3a342b214bd85826040518082815260200191505060405180910390a25050565b7fc804e53d6048af1b3e6a352e246d5f3864fea9d635ace499e023a58c383b3a88816040518082815260200191505060405180910390a150565b807f44a227a31429ab5eb00daf6611c6422f10571619f2267e0e149e9ebe6d2a5d0560405160405180910390a250565b7f28d45631a87b2a52a9625f8520fa37ff8c4d926cdf17042e241985da5cb7b850848484846040518085815260200184815260200183815260200182815260200194505050505060405180910390a150505050565b81837fcd5fe5fbc1d27b90036997224cea7aa565e3779622867265081f636b3a5ccb08836040518082815260200191505060405180910390a3505050565b80827f232f09cef3babc26e58d1cc1346c0a8bc626ffe600c9605b5d747783eda484a760405160405180910390a35050565b8183857f812e73dbcf7e267f27ecb1383bfc902a6650b41b6e7d03ac265108c369673d95846040518082815260200191505060405180910390a450505050565b7fd4d143faaf60340ad98e1f2c96fc26f5695834c21b5200edad339ee7e9a372cc83838360405180848152602001838152602001828152602001935050505060405180910390a150505056fea265627a7a72315820954561fde80ab925299e0a9f3356b01f64fb1976dd335ac2ebd9367441e29f0564736f6c63430005110032 +608060405234801561001057600080fd5b506106af806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c8063c755553811610071578063c755553814610128578063cbfc3b5814610144578063cc6f8faf14610160578063cd5b6c3d1461017c578063e2a6147314610198578063fb62b28b146101b4576100a9565b80630919b8be146100ae5780636199074d146100ca57806366eef346146100e657806375091b1f146100f0578063a63ae81a1461010c575b600080fd5b6100c860048036038101906100c39190610483565b6101d0565b005b6100e460048036038101906100df91906104c3565b61020d565b005b6100ee610241565b005b61010a60048036038101906101059190610483565b61026f565b005b61012660048036038101906101219190610516565b6102ab565b005b610142600480360381019061013d9190610516565b6102e5565b005b61015e60048036038101906101599190610543565b610315565b005b61017a600480360381019061017591906104c3565b610358565b005b61019660048036038101906101919190610483565b610396565b005b6101b260048036038101906101ad9190610543565b6103c8565b005b6101ce60048036038101906101c991906104c3565b610408565b005b7f5469c6b769315f5668523937f05ca07d4cc87849432bc5f5907f1d90fa73b9f982826040516102019291906105b9565b60405180910390a15050565b8082847fb89dabcdb7ff41f1794c0da92f65ece6c19b6b0caeac5407b2a721efe27c080460405160405180910390a4505050565b7fc3f6f1c76bd4e74ee5782052b0b4f8bd5c50b86c3c5a2f52638e03066e50a91b60405160405180910390a1565b817f6709824ebe5f6e620ca3f4b02a3428e8ce2dc97c550816eaeeb3a342b214bd858260405161029f91906105e2565b60405180910390a25050565b7fc804e53d6048af1b3e6a352e246d5f3864fea9d635ace499e023a58c383b3a88816040516102da91906105e2565b60405180910390a150565b807f44a227a31429ab5eb00daf6611c6422f10571619f2267e0e149e9ebe6d2a5d0560405160405180910390a250565b7f28d45631a87b2a52a9625f8520fa37ff8c4d926cdf17042e241985da5cb7b8508484848460405161034a94939291906105fd565b60405180910390a150505050565b81837fcd5fe5fbc1d27b90036997224cea7aa565e3779622867265081f636b3a5ccb088360405161038991906105e2565b60405180910390a3505050565b80827f232f09cef3babc26e58d1cc1346c0a8bc626ffe600c9605b5d747783eda484a760405160405180910390a35050565b8183857f812e73dbcf7e267f27ecb1383bfc902a6650b41b6e7d03ac265108c369673d95846040516103fa91906105e2565b60405180910390a450505050565b7fd4d143faaf60340ad98e1f2c96fc26f5695834c21b5200edad339ee7e9a372cc83838360405161043b93929190610642565b60405180910390a1505050565b600080fd5b6000819050919050565b6104608161044d565b811461046b57600080fd5b50565b60008135905061047d81610457565b92915050565b6000806040838503121561049a57610499610448565b5b60006104a88582860161046e565b92505060206104b98582860161046e565b9150509250929050565b6000806000606084860312156104dc576104db610448565b5b60006104ea8682870161046e565b93505060206104fb8682870161046e565b925050604061050c8682870161046e565b9150509250925092565b60006020828403121561052c5761052b610448565b5b600061053a8482850161046e565b91505092915050565b6000806000806080858703121561055d5761055c610448565b5b600061056b8782880161046e565b945050602061057c8782880161046e565b935050604061058d8782880161046e565b925050606061059e8782880161046e565b91505092959194509250565b6105b38161044d565b82525050565b60006040820190506105ce60008301856105aa565b6105db60208301846105aa565b9392505050565b60006020820190506105f760008301846105aa565b92915050565b600060808201905061061260008301876105aa565b61061f60208301866105aa565b61062c60408301856105aa565b61063960608301846105aa565b95945050505050565b600060608201905061065760008301866105aa565b61066460208301856105aa565b61067160408301846105aa565b94935050505056fea26469706673582212201b2f4de851da592b926eb2cd07ccfbbd02270fde6dee2459ba942e5dcf5685d364736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/EventMatrix.sol b/itests/contracts/EventMatrix.sol index bd008e27bbd..f1d63c69e60 100644 --- a/itests/contracts/EventMatrix.sol +++ b/itests/contracts/EventMatrix.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.5.0; +// SPDX-License-Identifier: MIT +pragma solidity >=0.5.0; contract EventMatrix { event EventZeroData(); diff --git a/itests/contracts/ExternalRecursiveCallSimple.hex b/itests/contracts/ExternalRecursiveCallSimple.hex new file mode 100644 index 00000000000..03d79fe2d05 --- /dev/null +++ b/itests/contracts/ExternalRecursiveCallSimple.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b506101ee806100206000396000f3fe60806040526004361061001e5760003560e01c8063c38e07dd14610023575b600080fd5b61003d600480360381019061003891906100fe565b61003f565b005b60008111156100c0573073ffffffffffffffffffffffffffffffffffffffff1663c38e07dd600183610071919061015a565b6040518263ffffffff1660e01b815260040161008d919061019d565b600060405180830381600087803b1580156100a757600080fd5b505af11580156100bb573d6000803e3d6000fd5b505050505b50565b600080fd5b6000819050919050565b6100db816100c8565b81146100e657600080fd5b50565b6000813590506100f8816100d2565b92915050565b600060208284031215610114576101136100c3565b5b6000610122848285016100e9565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610165826100c8565b9150610170836100c8565b92508282039050818111156101885761018761012b565b5b92915050565b610197816100c8565b82525050565b60006020820190506101b2600083018461018e565b9291505056fea264697066735822122033d012e17f5d7a62bb724021b5c4e0d109aeb28d1cd5b5c0a0b1b801c0b5032164736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/ExternalRecursiveCallSimple.sol b/itests/contracts/ExternalRecursiveCallSimple.sol new file mode 100644 index 00000000000..97a27811be8 --- /dev/null +++ b/itests/contracts/ExternalRecursiveCallSimple.sol @@ -0,0 +1,13 @@ + +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +contract StackRecCallExp { + function exec1(uint256 r) public payable { + if(r > 0) { + StackRecCallExp(address(this)).exec1(r-1); + } + + return; + } +} diff --git a/itests/contracts/GasLimitSend.hex b/itests/contracts/GasLimitSend.hex new file mode 100644 index 00000000000..ac4927d3862 --- /dev/null +++ b/itests/contracts/GasLimitSend.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b5061027c806100206000396000f3fe6080604052600436106100385760003560e01c80630bc07a88146100435780633da767881461005a578063f0ba84401461008557610039565b5b6100416100c2565b005b34801561004f57600080fd5b506100586100c2565b005b34801561006657600080fd5b5061006f61010d565b60405161007c9190610156565b60405180910390f35b34801561009157600080fd5b506100ac60048036038101906100a791906101a2565b610119565b6040516100b99190610156565b60405180910390f35b60005b606481101561010a5760008190806001815401808255809150506001900390600052602060002001600090919091909150558080610102906101fe565b9150506100c5565b50565b60008080549050905090565b6000818154811061012957600080fd5b906000526020600020016000915090505481565b6000819050919050565b6101508161013d565b82525050565b600060208201905061016b6000830184610147565b92915050565b600080fd5b61017f8161013d565b811461018a57600080fd5b50565b60008135905061019c81610176565b92915050565b6000602082840312156101b8576101b7610171565b5b60006101c68482850161018d565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006102098261013d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361023b5761023a6101cf565b5b60018201905091905056fea2646970667358221220c56d78e0c60a01681eee1b76c95e7b214d16a512c944e31cfee71eb727c1e44064736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/GasLimitSend.sol b/itests/contracts/GasLimitSend.sol new file mode 100644 index 00000000000..b5a91e14d2e --- /dev/null +++ b/itests/contracts/GasLimitSend.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +contract GasLimitTest { + address payable receiver; + constructor(){ + address mynew = address(new GasLimitTestReceiver()); + receiver = payable(mynew); + } + function send() public payable{ + receiver.transfer(msg.value); + } + function expensiveTest() public{ + GasLimitTestReceiver(receiver).expensive(); + } + function getDataLength() public returns (uint256) { + return GasLimitTestReceiver(receiver).getDataLength(); + } +} + +contract GasLimitTestReceiver { + uint256[] public data; + fallback() external payable { + expensive(); + } + function expensive() public{ + for (uint256 i = 0; i < 100; i++) { + data.push(i); + } + } + function getDataLength() public view returns (uint256) { + return data.length; + } +} diff --git a/itests/contracts/GasSendTest.hex b/itests/contracts/GasSendTest.hex new file mode 100644 index 00000000000..b41be3463cf --- /dev/null +++ b/itests/contracts/GasSendTest.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b5060b68061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80630c55699c14602d575b600080fd5b60336047565b604051603e91906067565b60405180910390f35b60006007905090565b6000819050919050565b6061816050565b82525050565b6000602082019050607a6000830184605a565b9291505056fea2646970667358221220c0f2da1b01178b54afba1ddf14f30307a03cdb66f61b4e1dc342079561db009064736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/GasSendTest.sol b/itests/contracts/GasSendTest.sol new file mode 100644 index 00000000000..b422bda26ca --- /dev/null +++ b/itests/contracts/GasSendTest.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +contract GasLimitTestReceiver { + function x() public returns (uint256){ + return 7; + } +} + diff --git a/itests/contracts/NotPayable.hex b/itests/contracts/NotPayable.hex new file mode 100644 index 00000000000..c08070029dc --- /dev/null +++ b/itests/contracts/NotPayable.hex @@ -0,0 +1 @@ +6080604052348015600f57600080fd5b50604780601d6000396000f3fe6080604052348015600f57600080fd5b00fea26469706673582212200cd38951eddebe3692dc8921afb65a04fbe64e10d5e261806330156459bf227264736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/NotPayable.sol b/itests/contracts/NotPayable.sol new file mode 100644 index 00000000000..9b9a06e082e --- /dev/null +++ b/itests/contracts/NotPayable.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; + +//sending eth should fall because fallback is not payable +contract NotPayable { + fallback() external {} +} diff --git a/itests/contracts/RecCall.hex b/itests/contracts/RecCall.hex new file mode 100644 index 00000000000..b8de20213ca --- /dev/null +++ b/itests/contracts/RecCall.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b5061025b806100206000396000f3fe60806040526004361061001e5760003560e01c8063cb7786d714610023575b600080fd5b61003d60048036038101906100389190610129565b61003f565b005b600083036100d15760008111156100cc573073ffffffffffffffffffffffffffffffffffffffff1663cb7786d7838460018561007b91906101ab565b6040518463ffffffff1660e01b8152600401610099939291906101ee565b600060405180830381600087803b1580156100b357600080fd5b505af11580156100c7573d6000803e3d6000fd5b505050505b6100e9565b6100e86001846100e191906101ab565b838361003f565b5b505050565b600080fd5b6000819050919050565b610106816100f3565b811461011157600080fd5b50565b600081359050610123816100fd565b92915050565b600080600060608486031215610142576101416100ee565b5b600061015086828701610114565b935050602061016186828701610114565b925050604061017286828701610114565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006101b6826100f3565b91506101c1836100f3565b92508282039050818111156101d9576101d861017c565b5b92915050565b6101e8816100f3565b82525050565b600060608201905061020360008301866101df565b61021060208301856101df565b61021d60408301846101df565b94935050505056fea26469706673582212209a21ff59c642e2970917c07bf498271c2a6df8e3929677952c0c2d8031db15cc64736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/RecCall.sol b/itests/contracts/RecCall.sol new file mode 100644 index 00000000000..f89611f0ee4 --- /dev/null +++ b/itests/contracts/RecCall.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +contract StackRecCall { + function exec1(uint256 n, uint256 m, uint256 r) public payable { + if(n == 0) { + if(r > 0) { + StackRecCall(address(this)).exec1(m, m, r-1); + } + + return; + } + + exec1(n-1, m, r); + } +} diff --git a/itests/contracts/Recursive.hex b/itests/contracts/Recursive.hex new file mode 100644 index 00000000000..b211aafd990 --- /dev/null +++ b/itests/contracts/Recursive.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b506102d9806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063032cec451461005c57806372536f3c1461007a57806399fdb86e14610098578063d2aac3ea146100b6578063ec49254c146100d4575b600080fd5b610064610104565b60405161007191906101c7565b60405180910390f35b610082610115565b60405161008f91906101c7565b60405180910390f35b6100a0610126565b6040516100ad91906101c7565b60405180910390f35b6100be610137565b6040516100cb91906101c7565b60405180910390f35b6100ee60048036038101906100e99190610213565b610148565b6040516100fb91906101c7565b60405180910390f35b60006101106001610148565b905090565b6000610121600a610148565b905090565b60006101326002610148565b905090565b60006101436000610148565b905090565b6000808211156101a5577f3110e0ccd510fcbb471c933ad12161c459e8735b5bde2eea61a659c2e2f0a3cc8260405161018191906101c7565b60405180910390a161019e600183610199919061026f565b610148565b90506101a9565b8190505b919050565b6000819050919050565b6101c1816101ae565b82525050565b60006020820190506101dc60008301846101b8565b92915050565b600080fd5b6101f0816101ae565b81146101fb57600080fd5b50565b60008135905061020d816101e7565b92915050565b600060208284031215610229576102286101e2565b5b6000610237848285016101fe565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061027a826101ae565b9150610285836101ae565b925082820390508181111561029d5761029c610240565b5b9291505056fea26469706673582212206178e15eb87e2f766b94ec09a6a860878c93d72a31de225e1684da1755f917c764736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/Recursive.sol b/itests/contracts/Recursive.sol new file mode 100644 index 00000000000..aa8fe62b0ab --- /dev/null +++ b/itests/contracts/Recursive.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +contract Recursive { + event RecursiveCallEvent(uint256 count); + + function recursive10() public returns (uint256){ + return recursiveCall(10); + } + function recursive2() public returns (uint256){ + return recursiveCall(2); + } + function recursive1() public returns (uint256){ + return recursiveCall(1); + } + function recursive0() public returns (uint256){ + return recursiveCall(0); + } + function recursiveCall(uint256 count) public returns (uint256) { + if (count > 0) { + emit RecursiveCallEvent(count); + return recursiveCall(count-1); + } + return count; + } +} diff --git a/itests/contracts/RecursiveDelegeatecall.hex b/itests/contracts/RecursiveDelegeatecall.hex new file mode 100644 index 00000000000..d8337c258bc --- /dev/null +++ b/itests/contracts/RecursiveDelegeatecall.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b50610459806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80633af3f24f1461003b578063ec49254c14610059575b600080fd5b610043610089565b6040516100509190610221565b60405180910390f35b610073600480360381019061006e919061026d565b61008f565b6040516100809190610221565b60405180910390f35b60005481565b60007faab69767807d0ab32f0099452739da31b76ecd3e8694bb49898829c8bf9d063582306040516100c29291906102db565b60405180910390a160016000808282546100dc9190610333565b9250508190555060018211156101ff576001826100f99190610367565b91506000803073ffffffffffffffffffffffffffffffffffffffff16846040516024016101269190610221565b6040516020818303038152906040527fec49254c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516101b0919061040c565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b50915091508392505050610203565b8190505b919050565b6000819050919050565b61021b81610208565b82525050565b60006020820190506102366000830184610212565b92915050565b600080fd5b61024a81610208565b811461025557600080fd5b50565b60008135905061026781610241565b92915050565b6000602082840312156102835761028261023c565b5b600061029184828501610258565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102c58261029a565b9050919050565b6102d5816102ba565b82525050565b60006040820190506102f06000830185610212565b6102fd60208301846102cc565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061033e82610208565b915061034983610208565b925082820190508082111561036157610360610304565b5b92915050565b600061037282610208565b915061037d83610208565b925082820390508181111561039557610394610304565b5b92915050565b600081519050919050565b600081905092915050565b60005b838110156103cf5780820151818401526020810190506103b4565b60008484015250505050565b60006103e68261039b565b6103f081856103a6565b93506104008185602086016103b1565b80840191505092915050565b600061041882846103db565b91508190509291505056fea2646970667358221220e70fbbfaccd3fbb084623d6d06895fba1abc5fefc181215b56ab1e43db79c7fb64736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/RecursiveDelegeatecall.sol b/itests/contracts/RecursiveDelegeatecall.sol new file mode 100644 index 00000000000..cd1b693c0ad --- /dev/null +++ b/itests/contracts/RecursiveDelegeatecall.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; + +contract RecursiveDelegatecall { + event RecursiveCallEvent(uint256 count, address self); + uint256 public totalCalls; + + function recursiveCall(uint256 count) public returns (uint256) { + emit RecursiveCallEvent(count, address(this)); + totalCalls += 1; + if (count > 1) { + count -= 1; + (bool success, bytes memory returnedData) = address(this) + .delegatecall( + abi.encodeWithSignature("recursiveCall(uint256)", count) + ); + return count; + } + return count; + } +} diff --git a/itests/contracts/SelfDestruct.hex b/itests/contracts/SelfDestruct.hex new file mode 100644 index 00000000000..c2f91b80342 --- /dev/null +++ b/itests/contracts/SelfDestruct.hex @@ -0,0 +1 @@ +6080604052348015600f57600080fd5b5060848061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806383197ef014602d575b600080fd5b60336035565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea2646970667358221220d4aa109d42268586e7ce4f0fafb0ebbd04c412c6c7e8c387b009a08ecdff864264736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/SelfDestruct.sol b/itests/contracts/SelfDestruct.sol new file mode 100644 index 00000000000..6c4ff91884b --- /dev/null +++ b/itests/contracts/SelfDestruct.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; + +contract SelfDestruct { + function destroy() public { + selfdestruct(payable(msg.sender)); + } +} diff --git a/itests/contracts/StackFunc.hex b/itests/contracts/StackFunc.hex new file mode 100644 index 00000000000..1a3d1202e2d --- /dev/null +++ b/itests/contracts/StackFunc.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b50610162806100206000396000f3fe60806040526004361061001e5760003560e01c8063c38e07dd14610023575b600080fd5b61003d6004803603810190610038919061009c565b61003f565b005b600081031561005e5761005d60018261005891906100f8565b61003f565b5b50565b600080fd5b6000819050919050565b61007981610066565b811461008457600080fd5b50565b60008135905061009681610070565b92915050565b6000602082840312156100b2576100b1610061565b5b60006100c084828501610087565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061010382610066565b915061010e83610066565b9250828203905081811115610126576101256100c9565b5b9291505056fea2646970667358221220ee8f18bfd33b1e0156cfe68e9071dd32960b370c7e63ec53c62dd48e28cb5d3b64736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/StackFunc.sol b/itests/contracts/StackFunc.sol new file mode 100644 index 00000000000..7084901c638 --- /dev/null +++ b/itests/contracts/StackFunc.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +contract StackSelf { + function exec1(uint256 n) public payable { + if(n == 0) { + return; + } + + exec1(n-1); + } +} \ No newline at end of file diff --git a/itests/contracts/TestApp.hex b/itests/contracts/TestApp.hex new file mode 100644 index 00000000000..bf18300711d --- /dev/null +++ b/itests/contracts/TestApp.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b50612e80806100206000396000f3fe60806040523480156200001157600080fd5b5060043610620000a05760003560e01c8063883a8410116200006f578063883a84101462000181578063c483289114620001bb578063d65c239c14620001dd578063dc33b0041462000213578063eae185c4146200024b57620000a0565b806308eaae9614620000a5578063120f83c414620000db5780632db0de8514620001115780637f823290146200014b575b600080fd5b620000c36004803603810190620000bd919062001a74565b62000281565b604051620000d2919062001b1f565b60405180910390f35b620000f96004803603810190620000f3919062001b6d565b620005b4565b60405162000108919062001bb0565b60405180910390f35b6200012f600480360381019062000129919062001bcd565b62000600565b6040516200014295949392919062001c88565b60405180910390f35b62000169600480360381019062000163919062001cec565b620006d3565b60405162000178919062001f0c565b60405180910390f35b6200019f600480360381019062000199919062001f30565b62000d53565b604051620001b295949392919062001c88565b60405180910390f35b620001c562000e68565b604051620001d4919062001bb0565b60405180910390f35b620001fb6004803603810190620001f5919062001f77565b62000e72565b6040516200020a919062001f0c565b60405180910390f35b6200023160048036038101906200022b919062001b6d565b6200127e565b604051620002429392919062001fdb565b60405180910390f35b62000269600480360381019062000263919062001f77565b620012d5565b60405162000278919062001f0c565b60405180910390f35b600080838360405162000294906200176c565b620002a192919062002018565b604051809103906000f080158015620002be573d6000803e3d6000fd5b509050600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff16620003f4576200032181620016ba565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548160ff0219169083151502179055506040820151816001019080519060200190620003e59291906200177a565b50606082015181600201559050505b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002016000828254620004ec91906200207b565b925050819055506000819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060018060008282546200056a91906200207b565b925050819055507f1e91349225b89f401c5f81de959b2a1cbc472147eeefbf4e367a6b7d2dfcd3bc32604051620005a2919062001b1f565b60405180910390a18091505092915050565b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201549050919050565b6000806000606060008086815481106200061f576200061e620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663909747956040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000695573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190620006c0919062002191565b9450945094509450945091939590929450565b606060008367ffffffffffffffff811115620006f457620006f3620018f2565b5b6040519080825280602002602001820160405280156200073157816020015b6200071d62001809565b815260200190600190039081620007135790505b50905060008390505b8481101562000d4757600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010184826200079391906200207b565b81548110620007a757620007a6620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16828583620007e1919062002238565b81518110620007f557620007f4620020b6565b5b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010184826200088391906200207b565b81548110620008975762000896620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632212dbc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200090d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000933919062002273565b82858362000942919062002238565b81518110620009565762000955620020b6565b5b60200260200101516020018181525050600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018482620009b691906200207b565b81548110620009ca57620009c9620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a8d509ff6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000a40573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000a669190620022a5565b82858362000a75919062002238565b8151811062000a895762000a88620020b6565b5b60200260200101516040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101848262000b1791906200207b565b8154811062000b2b5762000b2a620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630cb1851a6040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000ba1573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019062000bcc9190620022d7565b82858362000bdb919062002238565b8151811062000bef5762000bee620020b6565b5b602002602001015160600181905250600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101848262000c4e91906200207b565b8154811062000c625762000c61620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663eeb4e3676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000cd8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000cfe919062002273565b82858362000d0d919062002238565b8151811062000d215762000d20620020b6565b5b60200260200101516080018181525050808062000d3e9062002328565b9150506200073a565b50809150509392505050565b600080600060606000600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101868154811062000db35762000db2620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663909747956040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000e29573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019062000e54919062002191565b945094509450945094509295509295909350565b6000600154905090565b606060008367ffffffffffffffff81111562000e935762000e92620018f2565b5b60405190808252806020026020018201604052801562000ed057816020015b62000ebc62001809565b81526020019060019003908162000eb25790505b50905060008390505b848110156200127357600080858362000ef391906200207b565b8154811062000f075762000f06620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508083868462000f44919062002238565b8151811062000f585762000f57620020b6565b5b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff16632212dbc36040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000fe2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001008919062002273565b83868462001017919062002238565b815181106200102b576200102a620020b6565b5b602002602001015160200181815250508073ffffffffffffffffffffffffffffffffffffffff1663a8d509ff6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562001087573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620010ad9190620022a5565b838684620010bc919062002238565b81518110620010d057620010cf620020b6565b5b60200260200101516040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff16630cb1851a6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156200115a573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190620011859190620022d7565b83868462001194919062002238565b81518110620011a857620011a7620020b6565b5b6020026020010151606001819052508073ffffffffffffffffffffffffffffffffffffffff1663eeb4e3676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562001203573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001229919062002273565b83868462001238919062002238565b815181106200124c576200124b620020b6565b5b602002602001015160800181815250505080806200126a9062002328565b91505062000ed9565b508091505092915050565b60026020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060000160149054906101000a900460ff16908060020154905083565b606060008367ffffffffffffffff811115620012f657620012f5620018f2565b5b6040519080825280602002602001820160405280156200133357816020015b6200131f62001809565b815260200190600190039081620013155790505b50905060005b84811015620016af576000806001868460015462001358919062002238565b62001364919062002238565b62001370919062002238565b81548110620013845762001383620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905080838381518110620013c857620013c7620020b6565b5b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff16632212dbc36040518163ffffffff1660e01b8152600401602060405180830381865afa15801562001452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001478919062002273565b8383815181106200148e576200148d620020b6565b5b602002602001015160200181815250508073ffffffffffffffffffffffffffffffffffffffff1663a8d509ff6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620014ea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620015109190620022a5565b838381518110620015265762001525620020b6565b5b60200260200101516040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff16630cb1851a6040518163ffffffff1660e01b8152600401600060405180830381865afa158015620015b0573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190620015db9190620022d7565b838381518110620015f157620015f0620020b6565b5b6020026020010151606001819052508073ffffffffffffffffffffffffffffffffffffffff1663eeb4e3676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200164c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001672919062002273565b838381518110620016885762001687620020b6565b5b60200260200101516080018181525050508080620016a69062002328565b91505062001339565b508091505092915050565b620016c462001864565b60606003839080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180608001604052808473ffffffffffffffffffffffffffffffffffffffff1681526020016001151581526020018281526020016000815250915050919050565b610ad5806200237683390190565b828054828255906000526020600020908101928215620017f6579160200282015b82811115620017f55782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550916020019190600101906200179b565b5b509050620018059190620018a4565b5090565b6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160608152602001600081525090565b6040518060800160405280600073ffffffffffffffffffffffffffffffffffffffff16815260200160001515815260200160608152602001600081525090565b5b80821115620018bf576000816000905550600101620018a5565b5090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200192c82620018e1565b810181811067ffffffffffffffff821117156200194e576200194d620018f2565b5b80604052505050565b600062001963620018c3565b905062001971828262001921565b919050565b600067ffffffffffffffff821115620019945762001993620018f2565b5b6200199f82620018e1565b9050602081019050919050565b82818337600083830152505050565b6000620019d2620019cc8462001976565b62001957565b905082815260208101848484011115620019f157620019f0620018dc565b5b620019fe848285620019ac565b509392505050565b600082601f83011262001a1e5762001a1d620018d7565b5b813562001a30848260208601620019bb565b91505092915050565b6000819050919050565b62001a4e8162001a39565b811462001a5a57600080fd5b50565b60008135905062001a6e8162001a43565b92915050565b6000806040838503121562001a8e5762001a8d620018cd565b5b600083013567ffffffffffffffff81111562001aaf5762001aae620018d2565b5b62001abd8582860162001a06565b925050602062001ad08582860162001a5d565b9150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600062001b078262001ada565b9050919050565b62001b198162001afa565b82525050565b600060208201905062001b36600083018462001b0e565b92915050565b62001b478162001afa565b811462001b5357600080fd5b50565b60008135905062001b678162001b3c565b92915050565b60006020828403121562001b865762001b85620018cd565b5b600062001b968482850162001b56565b91505092915050565b62001baa8162001a39565b82525050565b600060208201905062001bc7600083018462001b9f565b92915050565b60006020828403121562001be65762001be5620018cd565b5b600062001bf68482850162001a5d565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101562001c3b57808201518184015260208101905062001c1e565b60008484015250505050565b600062001c548262001bff565b62001c60818562001c0a565b935062001c7281856020860162001c1b565b62001c7d81620018e1565b840191505092915050565b600060a08201905062001c9f600083018862001b0e565b62001cae602083018762001b9f565b62001cbd604083018662001b0e565b818103606083015262001cd1818562001c47565b905062001ce2608083018462001b9f565b9695505050505050565b60008060006060848603121562001d085762001d07620018cd565b5b600062001d188682870162001b56565b935050602062001d2b8682870162001a5d565b925050604062001d3e8682870162001a5d565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b62001d7f8162001afa565b82525050565b62001d908162001a39565b82525050565b600082825260208201905092915050565b600062001db48262001bff565b62001dc0818562001d96565b935062001dd281856020860162001c1b565b62001ddd81620018e1565b840191505092915050565b600060a08301600083015162001e02600086018262001d74565b50602083015162001e17602086018262001d85565b50604083015162001e2c604086018262001d74565b506060830151848203606086015262001e46828262001da7565b915050608083015162001e5d608086018262001d85565b508091505092915050565b600062001e76838362001de8565b905092915050565b6000602082019050919050565b600062001e988262001d48565b62001ea4818562001d53565b93508360208202850162001eb88562001d64565b8060005b8581101562001efa578484038952815162001ed8858262001e68565b945062001ee58362001e7e565b925060208a0199505060018101905062001ebc565b50829750879550505050505092915050565b6000602082019050818103600083015262001f28818462001e8b565b905092915050565b6000806040838503121562001f4a5762001f49620018cd565b5b600062001f5a8582860162001b56565b925050602062001f6d8582860162001a5d565b9150509250929050565b6000806040838503121562001f915762001f90620018cd565b5b600062001fa18582860162001a5d565b925050602062001fb48582860162001a5d565b9150509250929050565b60008115159050919050565b62001fd58162001fbe565b82525050565b600060608201905062001ff2600083018662001b0e565b62002001602083018562001fca565b62002010604083018462001b9f565b949350505050565b6000604082019050818103600083015262002034818562001c47565b905062002045602083018462001b9f565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000620020888262001a39565b9150620020958362001a39565b9250828201905080821115620020b057620020af6200204c565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081519050620020f68162001b3c565b92915050565b6000815190506200210d8162001a43565b92915050565b60006200212a620021248462001976565b62001957565b905082815260208101848484011115620021495762002148620018dc565b5b6200215684828562001c1b565b509392505050565b600082601f830112620021765762002175620018d7565b5b81516200218884826020860162002113565b91505092915050565b600080600080600060a08688031215620021b057620021af620018cd565b5b6000620021c088828901620020e5565b9550506020620021d388828901620020fc565b9450506040620021e688828901620020e5565b935050606086015167ffffffffffffffff8111156200220a5762002209620018d2565b5b62002218888289016200215e565b92505060806200222b88828901620020fc565b9150509295509295909350565b6000620022458262001a39565b9150620022528362001a39565b92508282039050818111156200226d576200226c6200204c565b5b92915050565b6000602082840312156200228c576200228b620018cd565b5b60006200229c84828501620020fc565b91505092915050565b600060208284031215620022be57620022bd620018cd565b5b6000620022ce84828501620020e5565b91505092915050565b600060208284031215620022f057620022ef620018cd565b5b600082015167ffffffffffffffff811115620023115762002310620018d2565b5b6200231f848285016200215e565b91505092915050565b6000620023358262001a39565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036200236a57620023696200204c565b5b60018201905091905056fe60806040523480156200001157600080fd5b5060405162000ad538038062000ad583398181016040528101906200003791906200026e565b32600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555042600081905550816002908162000090919062000515565b50806003819055505050620005fc565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200010982620000be565b810181811067ffffffffffffffff821117156200012b576200012a620000cf565b5b80604052505050565b600062000140620000a0565b90506200014e8282620000fe565b919050565b600067ffffffffffffffff821115620001715762000170620000cf565b5b6200017c82620000be565b9050602081019050919050565b60005b83811015620001a95780820151818401526020810190506200018c565b60008484015250505050565b6000620001cc620001c68462000153565b62000134565b905082815260208101848484011115620001eb57620001ea620000b9565b5b620001f884828562000189565b509392505050565b600082601f830112620002185762000217620000b4565b5b81516200022a848260208601620001b5565b91505092915050565b6000819050919050565b620002488162000233565b81146200025457600080fd5b50565b60008151905062000268816200023d565b92915050565b60008060408385031215620002885762000287620000aa565b5b600083015167ffffffffffffffff811115620002a957620002a8620000af565b5b620002b78582860162000200565b9250506020620002ca8582860162000257565b9150509250929050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200032757607f821691505b6020821081036200033d576200033c620002df565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620003a77fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000368565b620003b3868362000368565b95508019841693508086168417925050509392505050565b6000819050919050565b6000620003f6620003f0620003ea8462000233565b620003cb565b62000233565b9050919050565b6000819050919050565b6200041283620003d5565b6200042a6200042182620003fd565b84845462000375565b825550505050565b600090565b6200044162000432565b6200044e81848462000407565b505050565b5b8181101562000476576200046a60008262000437565b60018101905062000454565b5050565b601f821115620004c5576200048f8162000343565b6200049a8462000358565b81016020851015620004aa578190505b620004c2620004b98562000358565b83018262000453565b50505b505050565b600082821c905092915050565b6000620004ea60001984600802620004ca565b1980831691505092915050565b6000620005058383620004d7565b9150826002028217905092915050565b6200052082620002d4565b67ffffffffffffffff8111156200053c576200053b620000cf565b5b6200054882546200030e565b620005558282856200047a565b600060209050601f8311600181146200058d576000841562000578578287015190505b620005848582620004f7565b865550620005f4565b601f1984166200059d8662000343565b60005b82811015620005c757848901518255600182019150602085019450602081019050620005a0565b86831015620005e75784890151620005e3601f891682620004d7565b8355505b6001600288020188555050505b505050505050565b6104c9806200060c6000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80630cb1851a1461005c5780632212dbc31461007a5780639097479514610098578063a8d509ff146100ba578063eeb4e367146100d8575b600080fd5b6100646100f6565b6040516100719190610327565b60405180910390f35b610082610188565b60405161008f9190610362565b60405180910390f35b6100a0610191565b6040516100b19594939291906103be565b60405180910390f35b6100c2610263565b6040516100cf9190610418565b60405180910390f35b6100e061028d565b6040516100ed9190610362565b60405180910390f35b60606002805461010590610462565b80601f016020809104026020016040519081016040528092919081815260200182805461013190610462565b801561017e5780601f106101535761010080835404028352916020019161017e565b820191906000526020600020905b81548152906001019060200180831161016157829003601f168201915b5050505050905090565b60008054905090565b60008060006060600030600054600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660026003548180546101d290610462565b80601f01602080910402602001604051908101604052809291908181526020018280546101fe90610462565b801561024b5780601f106102205761010080835404028352916020019161024b565b820191906000526020600020905b81548152906001019060200180831161022e57829003601f168201915b50505050509150945094509450945094509091929394565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600354905090565b600081519050919050565b600082825260208201905092915050565b60005b838110156102d15780820151818401526020810190506102b6565b60008484015250505050565b6000601f19601f8301169050919050565b60006102f982610297565b61030381856102a2565b93506103138185602086016102b3565b61031c816102dd565b840191505092915050565b6000602082019050818103600083015261034181846102ee565b905092915050565b6000819050919050565b61035c81610349565b82525050565b60006020820190506103776000830184610353565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006103a88261037d565b9050919050565b6103b88161039d565b82525050565b600060a0820190506103d360008301886103af565b6103e06020830187610353565b6103ed60408301866103af565b81810360608301526103ff81856102ee565b905061040e6080830184610353565b9695505050505050565b600060208201905061042d60008301846103af565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061047a57607f821691505b60208210810361048d5761048c610433565b5b5091905056fea264697066735822122096ba86e2c854094a9f7774cf59534923c219cc0ab6e812963e86557d6743467c64736f6c63430008110033a2646970667358221220b58cd7b4415159e845caf380c6ffa231afa779fa9b6af3b83d7b80ca521527a464736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/TestApp.sol b/itests/contracts/TestApp.sol new file mode 100644 index 00000000000..072eb7a6157 --- /dev/null +++ b/itests/contracts/TestApp.sol @@ -0,0 +1,211 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.2; +pragma experimental ABIEncoderV2; + +contract Test_contract { + uint256 timestamp; + address sender; + string text; + uint256 number; + + constructor(string memory _text, uint256 _number) { + sender = tx.origin; + timestamp = block.timestamp; + text = _text; + number = _number; + } + + function getall() + public + view + returns ( + address, + uint256, + address, + string memory, + uint256 + ) + { + return (address(this), timestamp, sender, text, number); + } + + function get_timestamp() public view returns (uint256) { + return timestamp; + } + + function get_sender() public view returns (address) { + return sender; + } + + function get_text() public view returns (string memory) { + return text; + } + + function get_number() public view returns (uint256) { + return number; + } +} + +contract App { + address[] Test_list; + uint256 Test_list_length; + + function get_Test_list_length() public view returns (uint256) { + return Test_list_length; + } + + struct Test_getter { + address _address; + uint256 timestamp; + address sender; + string text; + uint256 number; + } + + function get_Test_N(uint256 index) + public + view + returns ( + address, + uint256, + address, + string memory, + uint256 + ) + { + return Test_contract(Test_list[index]).getall(); + } + + function get_first_Test_N(uint256 count, uint256 offset) + public + view + returns (Test_getter[] memory) + { + Test_getter[] memory getters = new Test_getter[](count); + for (uint256 i = offset; i < count; i++) { + Test_contract myTest = Test_contract(Test_list[i + offset]); + getters[i - offset]._address = address(myTest); + getters[i - offset].timestamp = myTest.get_timestamp(); + getters[i - offset].sender = myTest.get_sender(); + getters[i - offset].text = myTest.get_text(); + getters[i - offset].number = myTest.get_number(); + } + return getters; + } + + function get_last_Test_N(uint256 count, uint256 offset) + public + view + returns (Test_getter[] memory) + { + Test_getter[] memory getters = new Test_getter[](count); + for (uint256 i = 0; i < count; i++) { + Test_contract myTest = + Test_contract(Test_list[Test_list_length - i - offset - 1]); + getters[i]._address = address(myTest); + + getters[i].timestamp = myTest.get_timestamp(); + getters[i].sender = myTest.get_sender(); + getters[i].text = myTest.get_text(); + getters[i].number = myTest.get_number(); + } + return getters; + } + + function get_Test_user_length(address user) public view returns (uint256) { + return user_map[user].Test_list_length; + } + + function get_Test_user_N(address user, uint256 index) + public + view + returns ( + address, + uint256, + address, + string memory, + uint256 + ) + { + return Test_contract(user_map[user].Test_list[index]).getall(); + } + + function get_last_Test_user_N( + address user, + uint256 count, + uint256 offset + ) public view returns (Test_getter[] memory) { + Test_getter[] memory getters = new Test_getter[](count); + + for (uint256 i = offset; i < count; i++) { + getters[i - offset]._address = user_map[user].Test_list[i + offset]; + getters[i - offset].timestamp = Test_contract( + user_map[user].Test_list[i + offset] + ) + .get_timestamp(); + getters[i - offset].sender = Test_contract( + user_map[user].Test_list[i + offset] + ) + .get_sender(); + getters[i - offset].text = Test_contract( + user_map[user].Test_list[i + offset] + ) + .get_text(); + getters[i - offset].number = Test_contract( + user_map[user].Test_list[i + offset] + ) + .get_number(); + } + return getters; + } + + struct UserInfo { + address owner; + bool exists; + address[] Test_list; + uint256 Test_list_length; + } + mapping(address => UserInfo) public user_map; + address[] UserInfoList; + uint256 UserInfoListLength; + + event NewTest(address sender); + + function new_Test(string memory text, uint256 number) + public + returns (address) + { + address mynew = + address(new Test_contract({_text: text, _number: number})); + + if (!user_map[tx.origin].exists) { + user_map[tx.origin] = create_user_on_new_Test(mynew); + } + user_map[tx.origin].Test_list.push(mynew); + + user_map[tx.origin].Test_list_length += 1; + + Test_list.push(mynew); + Test_list_length += 1; + + emit NewTest(tx.origin); + + return mynew; + } + + function create_user_on_new_Test(address addr) + private + returns (UserInfo memory) + { + address[] memory Test_list_; + + UserInfoList.push(addr); + return + UserInfo({ + exists: true, + owner: addr, + Test_list: Test_list_, + Test_list_length: 0 + }); + } +} diff --git a/itests/contracts/ValueSender.hex b/itests/contracts/ValueSender.hex new file mode 100644 index 00000000000..ed69dacdbd3 --- /dev/null +++ b/itests/contracts/ValueSender.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b506106dc806100206000396000f3fe60806040526004361061002d5760003560e01c8063dbdc275d14610072578063fd75295a1461009d5761006d565b3661006d577f34fb9cb8f63eaccc6c0beefc202db703e529c3bf9ce83f485b398af7fd679308333460405161006392919061020f565b60405180910390a1005b600080fd5b34801561007e57600080fd5b506100876100b9565b6040516100949190610238565b60405180910390f35b6100b760048036038101906100b29190610296565b610125565b005b6000806040516100c8906101a8565b604051809103906000f0801580156100e4573d6000803e3d6000fd5b5090507f8db3b20eed31d927a4f613b5c11765212e129cf726d025649650665569ea683b816040516101169190610238565b60405180910390a18091505090565b7f34fb9cb8f63eaccc6c0beefc202db703e529c3bf9ce83f485b398af7fd6793088134604051610156929190610322565b60405180910390a18073ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501580156101a4573d6000803e3d6000fd5b5050565b61035b8061034c83390190565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101e0826101b5565b9050919050565b6101f0816101d5565b82525050565b6000819050919050565b610209816101f6565b82525050565b600060408201905061022460008301856101e7565b6102316020830184610200565b9392505050565b600060208201905061024d60008301846101e7565b92915050565b600080fd5b6000610263826101b5565b9050919050565b61027381610258565b811461027e57600080fd5b50565b6000813590506102908161026a565b92915050565b6000602082840312156102ac576102ab610253565b5b60006102ba84828501610281565b91505092915050565b6000819050919050565b60006102e86102e36102de846101b5565b6102c3565b6101b5565b9050919050565b60006102fa826102cd565b9050919050565b600061030c826102ef565b9050919050565b61031c81610301565b82525050565b60006040820190506103376000830185610313565b6103446020830184610200565b939250505056fe608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102fb806100606000396000f3fe60806040526004361061002d5760003560e01c806337cb6570146100725780639cb8a26a1461007c5761006d565b3661006d577fe1494f56a1ccfd8c7361f2ca5b8fd2b1a2fe11773821ac29534f09f4a0637d603334604051610063929190610214565b60405180910390a1005b600080fd5b61007a610093565b005b34801561008857600080fd5b50610091610155565b005b7f76cff203b0794a9e9013657ecb172f2d6e8de5941fd11a6bfbc0fb6014a5f07960008054906101000a900473ffffffffffffffffffffffffffffffffffffffff16476040516100e492919061029c565b60405180910390a160008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f19350505050158015610152573d6000803e3d6000fd5b50565b7f1cbd47e7b0f55dc1a45ba8ebada53eaa1712b3e3e86f49a12c008ff22334569060405160405180910390a160008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101e5826101ba565b9050919050565b6101f5816101da565b82525050565b6000819050919050565b61020e816101fb565b82525050565b600060408201905061022960008301856101ec565b6102366020830184610205565b9392505050565b6000819050919050565b600061026261025d610258846101ba565b61023d565b6101ba565b9050919050565b600061027482610247565b9050919050565b600061028682610269565b9050919050565b6102968161027b565b82525050565b60006040820190506102b1600083018561028d565b6102be6020830184610205565b939250505056fea2646970667358221220bdf21908b1c91973a8440fe81130e0077cf83c8f8e9a053d8a0c3063391aa40764736f6c63430008110033a26469706673582212202e514fe078dfcf4f1142a088c57cfa71ada74d72ee0cc4a46b7e1141cdbaeeed64736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/ValueSender.sol b/itests/contracts/ValueSender.sol new file mode 100644 index 00000000000..1be682b25f8 --- /dev/null +++ b/itests/contracts/ValueSender.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; + +contract A { + event LogCreateB(address _bAddress); + event LogSendEthA(address _bAddress, uint _value); + event LogReceiveEthA(address _bAddress, uint _value); + + // Function to create a new instance of contract B and return its address + function createB() public returns (address) { + address bAddress = address(new B()); + emit LogCreateB(bAddress); + return bAddress; + } + + // Payable method to accept eth and an address for B and send the eth to B + function sendEthToB(address payable _bAddress) public payable { + emit LogSendEthA(_bAddress, msg.value); + _bAddress.transfer(msg.value); + } + + // Payable function to accept the eth + receive() external payable { + emit LogSendEthA(msg.sender, msg.value); + } +} + +contract B { + event LogSelfDestruct(); + event LogSendEthToA(address _to, uint _value); + event LogReceiveEth(address from, uint value); + address payable creator; + + constructor(){ + creator = payable(msg.sender); + } + + // Payable function to accept the eth + receive() external payable { + emit LogReceiveEth(msg.sender, msg.value); + } + + // Method to send ether to contract A + function sendEthToA() public payable { + emit LogSendEthToA(creator,address(this).balance); + creator.transfer(address(this).balance); + } + + // Self destruct method to send eth to its creator + function selfDestruct() public { + emit LogSelfDestruct(); + selfdestruct(creator); + } +} diff --git a/itests/contracts/compile.sh b/itests/contracts/compile.sh index 1163ad9a676..4395fdb535d 100755 --- a/itests/contracts/compile.sh +++ b/itests/contracts/compile.sh @@ -1,6 +1,19 @@ +set -eu +set -o pipefail + #use the solc compiler https://docs.soliditylang.org/en/v0.8.17/installing-solidity.html # to compile all of the .sol files to their corresponding evm binary files stored as .hex # solc outputs to stdout a format that we just want to grab the last line of and then remove the trailing newline on that line -find -type f -name \*.sol -print0 | - xargs -0 -I{} bash -c 'solc --bin {} |tail -n1 | tr -d "\n" > $(echo {} | sed -e s/.sol$/.hex/)' +find . -name \*.sol -print0 | + xargs -0 -I{} bash -euc -o pipefail 'solc --bin {} |tail -n1 | tr -d "\n" > $(echo {} | sed -e s/.sol$/.hex/)' + + + +#for these contracts we have 2 contracts in the same solidity file +#this command grabs the correct bytecode for us +for filename in Constructor TestApp ValueSender ; do + echo $filename + solc --bin $filename.sol | tail -n5|head -n1 | tr -d "\n" > $filename.hex +done + diff --git a/itests/decode_params_test.go b/itests/decode_params_test.go new file mode 100644 index 00000000000..6a4a8c681ed --- /dev/null +++ b/itests/decode_params_test.go @@ -0,0 +1,124 @@ +// stm: #integration +package itests + +import ( + "bytes" + "encoding/json" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + actorstypes "github.com/filecoin-project/go-state-types/actors" + "github.com/filecoin-project/go-state-types/builtin" + "github.com/filecoin-project/go-state-types/builtin/v10/eam" + "github.com/filecoin-project/go-state-types/cbor" + "github.com/filecoin-project/go-state-types/manifest" + + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/actors" + "github.com/filecoin-project/lotus/cli" +) + +type marshalable interface { + cbor.Marshaler + cbor.Unmarshaler +} + +type testCase struct { + ActorKey string + MethodNum abi.MethodNum + retVal marshalable +} + +// Used './lotus state replay --show-trace ' to get params/return to decode. +func TestDecodeParams(t *testing.T) { + testCborBytes := abi.CborBytes([]byte{1, 2, 3}) + + testCases := []testCase{ + { + ActorKey: manifest.EvmKey, + MethodNum: builtin.MethodsEVM.InvokeContract, + retVal: &testCborBytes, + }, + { + ActorKey: manifest.EamKey, + MethodNum: builtin.MethodsEAM.CreateExternal, + retVal: &testCborBytes, + }, + } + + for _, _tc := range testCases { + tc := _tc + t.Run(tc.ActorKey+" "+tc.MethodNum.String(), func(t *testing.T) { + av, err := actorstypes.VersionForNetwork(build.TestNetworkVersion) + require.NoError(t, err) + actorCodeCid, found := actors.GetActorCodeID(av, tc.ActorKey) + require.True(t, found) + + buf := bytes.NewBuffer(nil) + if err := tc.retVal.MarshalCBOR(buf); err != nil { + t.Fatal(err) + } + + paramString, err := cli.JsonParams(actorCodeCid, tc.MethodNum, buf.Bytes()) + require.NoError(t, err) + + jsonParams, err := json.MarshalIndent(tc.retVal, "", " ") + require.NoError(t, err) + require.Equal(t, string(jsonParams), paramString) + }) + } +} + +func TestDecodeReturn(t *testing.T) { + testCborBytes := abi.CborBytes([]byte{1, 2, 3}) + + robustAddr, err := address.NewIDAddress(12345) + require.NoError(t, err) + + //ethAddr, err := ethtypes.ParseEthAddress("d4c5fb16488Aa48081296299d54b0c648C9333dA") + //require.NoError(t, err) + + testReturn := eam.CreateExternalReturn{ + ActorID: 12345, + RobustAddress: &robustAddr, + EthAddress: [20]byte{}, + } + + testCases := []testCase{ + { + ActorKey: manifest.EvmKey, + MethodNum: builtin.MethodsEVM.InvokeContract, + retVal: &testCborBytes, + }, + { + ActorKey: manifest.EamKey, + MethodNum: builtin.MethodsEAM.CreateExternal, + retVal: &testReturn, + }, + } + + for _, _tc := range testCases { + tc := _tc + t.Run(tc.ActorKey+" "+tc.MethodNum.String(), func(t *testing.T) { + av, err := actorstypes.VersionForNetwork(build.TestNetworkVersion) + require.NoError(t, err) + actorCodeCid, found := actors.GetActorCodeID(av, tc.ActorKey) + require.True(t, found) + + buf := bytes.NewBuffer(nil) + if err := tc.retVal.MarshalCBOR(buf); err != nil { + t.Fatal(err) + } + + returnString, err := cli.JsonReturn(actorCodeCid, tc.MethodNum, buf.Bytes()) + require.NoError(t, err) + + jsonReturn, err := json.MarshalIndent(tc.retVal, "", " ") + require.NoError(t, err) + require.Equal(t, string(jsonReturn), returnString) + }) + } +} diff --git a/itests/eth_account_abstraction_test.go b/itests/eth_account_abstraction_test.go index 692e4646f41..e6d9723bf40 100644 --- a/itests/eth_account_abstraction_test.go +++ b/itests/eth_account_abstraction_test.go @@ -11,6 +11,8 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" + builtin2 "github.com/filecoin-project/go-state-types/builtin" + "github.com/filecoin-project/go-state-types/builtin/v10/eam" "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/lotus/api" @@ -70,7 +72,7 @@ func TestEthAccountAbstraction(t *testing.T) { msgFromPlaceholder, err = client.GasEstimateMessageGas(ctx, msgFromPlaceholder, nil, types.EmptyTSK) require.NoError(t, err) - txArgs, err := ethtypes.EthTxArgsFromMessage(msgFromPlaceholder) + txArgs, err := ethtypes.EthTxArgsFromUnsignedEthMessage(msgFromPlaceholder) require.NoError(t, err) digest, err := txArgs.ToRlpUnsignedMsg() @@ -106,7 +108,7 @@ func TestEthAccountAbstraction(t *testing.T) { msgFromPlaceholder, err = client.GasEstimateMessageGas(ctx, msgFromPlaceholder, nil, types.EmptyTSK) require.NoError(t, err) - txArgs, err = ethtypes.EthTxArgsFromMessage(msgFromPlaceholder) + txArgs, err = ethtypes.EthTxArgsFromUnsignedEthMessage(msgFromPlaceholder) require.NoError(t, err) digest, err = txArgs.ToRlpUnsignedMsg() @@ -178,7 +180,7 @@ func TestEthAccountAbstractionFailure(t *testing.T) { require.NoError(t, err) msgFromPlaceholder.Value = abi.TokenAmount(types.MustParseFIL("1000")) - txArgs, err := ethtypes.EthTxArgsFromMessage(msgFromPlaceholder) + txArgs, err := ethtypes.EthTxArgsFromUnsignedEthMessage(msgFromPlaceholder) require.NoError(t, err) digest, err := txArgs.ToRlpUnsignedMsg() @@ -216,7 +218,7 @@ func TestEthAccountAbstractionFailure(t *testing.T) { msgFromPlaceholder, err = client.GasEstimateMessageGas(ctx, msgFromPlaceholder, nil, types.EmptyTSK) require.NoError(t, err) - txArgs, err = ethtypes.EthTxArgsFromMessage(msgFromPlaceholder) + txArgs, err = ethtypes.EthTxArgsFromUnsignedEthMessage(msgFromPlaceholder) require.NoError(t, err) digest, err = txArgs.ToRlpUnsignedMsg() @@ -313,3 +315,51 @@ func TestEthAccountAbstractionFailsFromEvmActor(t *testing.T) { require.Error(t, err, "expected gas estimation to fail") require.Contains(t, err.Error(), "SysErrSenderInvalid") } + +func TestEthAccountManagerPermissions(t *testing.T) { + kit.QuietMiningLogs() + + client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC()) + ens.InterconnectAll().BeginMining(10 * time.Millisecond) + + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + // setup f1/f3/f4 accounts + + wsp, err := client.WalletNew(ctx, types.KTSecp256k1) + require.NoError(t, err) + + wbl, err := client.WalletNew(ctx, types.KTBLS) + require.NoError(t, err) + + wdl, err := client.WalletNew(ctx, types.KTDelegated) + require.NoError(t, err) + + def := client.DefaultKey.Address + + // send some funds + client.ExpectSend(ctx, def, wsp, types.FromFil(10), "") + client.ExpectSend(ctx, def, wbl, types.FromFil(10), "") + client.ExpectSend(ctx, def, wdl, types.FromFil(10), "") + require.NoError(t, err) + + // make sure that EAM only allows CreateExternal to be called by accounts + client.ExpectSend(ctx, wsp, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "not one of supported (18)", client.MakeSendCall(builtin2.MethodsEAM.Create, &eam.CreateParams{Nonce: 0})) + client.ExpectSend(ctx, wbl, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "not one of supported (18)", client.MakeSendCall(builtin2.MethodsEAM.Create, &eam.CreateParams{Nonce: 0})) + client.ExpectSend(ctx, wdl, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "not one of supported (18)", client.MakeSendCall(builtin2.MethodsEAM.Create, &eam.CreateParams{Nonce: 0})) + + client.ExpectSend(ctx, wsp, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "not one of supported (18)", client.MakeSendCall(builtin2.MethodsEAM.Create2, &eam.Create2Params{})) + client.ExpectSend(ctx, wbl, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "not one of supported (18)", client.MakeSendCall(builtin2.MethodsEAM.Create2, &eam.Create2Params{})) + client.ExpectSend(ctx, wdl, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "not one of supported (18)", client.MakeSendCall(builtin2.MethodsEAM.Create2, &eam.Create2Params{})) + + contractHex, err := os.ReadFile("contracts/SimpleCoin.hex") + require.NoError(t, err) + contract, err := hex.DecodeString(string(contractHex)) + require.NoError(t, err) + contractParams := abi.CborBytes(contract) + + client.ExpectSend(ctx, wsp, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "", client.MakeSendCall(builtin2.MethodsEAM.CreateExternal, &contractParams)) + client.ExpectSend(ctx, wbl, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "", client.MakeSendCall(builtin2.MethodsEAM.CreateExternal, &contractParams)) + client.ExpectSend(ctx, wdl, builtin2.EthereumAddressManagerActorAddr, big.Zero(), "", client.MakeSendCall(builtin2.MethodsEAM.CreateExternal, &contractParams)) +} diff --git a/itests/eth_config_test.go b/itests/eth_config_test.go new file mode 100644 index 00000000000..8b74d011aa2 --- /dev/null +++ b/itests/eth_config_test.go @@ -0,0 +1,62 @@ +// stm: #integration +package itests + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/lotus/chain/types/ethtypes" + "github.com/filecoin-project/lotus/itests/kit" + "github.com/filecoin-project/lotus/node/impl/full" +) + +func TestEthFilterAPIDisabledViaConfig(t *testing.T) { + ctx := context.Background() + + kit.QuietMiningLogs() + + // pass kit.DisableEthRPC() so RealTimeFilterAPI will not be enabled + client, _, _ := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC(), kit.DisableEthRPC()) + + _, err := client.EthNewPendingTransactionFilter(ctx) + require.NotNil(t, err) + require.Equal(t, err.Error(), full.ErrModuleDisabled.Error()) + + _, err = client.EthGetLogs(ctx, ðtypes.EthFilterSpec{}) + require.NotNil(t, err) + require.Equal(t, err.Error(), full.ErrModuleDisabled.Error()) + + _, err = client.EthGetFilterChanges(ctx, ethtypes.EthFilterID{}) + require.NotNil(t, err) + require.Equal(t, err.Error(), full.ErrModuleDisabled.Error()) + + _, err = client.EthGetFilterLogs(ctx, ethtypes.EthFilterID{}) + require.NotNil(t, err) + require.Equal(t, err.Error(), full.ErrModuleDisabled.Error()) + + _, err = client.EthNewFilter(ctx, ðtypes.EthFilterSpec{}) + require.NotNil(t, err) + require.Equal(t, err.Error(), full.ErrModuleDisabled.Error()) + + _, err = client.EthNewBlockFilter(ctx) + require.NotNil(t, err) + require.Equal(t, err.Error(), full.ErrModuleDisabled.Error()) + + _, err = client.EthNewPendingTransactionFilter(ctx) + require.NotNil(t, err) + require.Equal(t, err.Error(), full.ErrModuleDisabled.Error()) + + _, err = client.EthUninstallFilter(ctx, ethtypes.EthFilterID{}) + require.NotNil(t, err) + require.Equal(t, err.Error(), full.ErrModuleDisabled.Error()) + + _, err = client.EthSubscribe(ctx, []byte("{}")) + require.NotNil(t, err) + require.Equal(t, err.Error(), full.ErrModuleDisabled.Error()) + + _, err = client.EthUnsubscribe(ctx, ethtypes.EthSubscriptionID{}) + require.NotNil(t, err) + require.Equal(t, err.Error(), full.ErrModuleDisabled.Error()) +} diff --git a/itests/eth_conformance_test.go b/itests/eth_conformance_test.go new file mode 100644 index 00000000000..b11366465c5 --- /dev/null +++ b/itests/eth_conformance_test.go @@ -0,0 +1,520 @@ +package itests + +import ( + "bytes" + "context" + "encoding/binary" + "encoding/hex" + "encoding/json" + "os" + "strings" + "testing" + "time" + + "github.com/go-openapi/spec" + "github.com/gregdhill/go-openrpc/parse" + orpctypes "github.com/gregdhill/go-openrpc/types" + manet "github.com/multiformats/go-multiaddr/net" + "github.com/stretchr/testify/require" + "github.com/xeipuuv/gojsonschema" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-jsonrpc" + "github.com/filecoin-project/go-state-types/big" + + "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" + "github.com/filecoin-project/lotus/itests/kit" +) + +// TODO generate this using reflection. It's the same as the EthAPI except every return value is a json.RawMessage +type ethAPIRaw struct { + EthAccounts func(context.Context) (json.RawMessage, error) + EthBlockNumber func(context.Context) (json.RawMessage, error) + EthCall func(context.Context, ethtypes.EthCall, string) (json.RawMessage, error) + EthChainId func(context.Context) (json.RawMessage, error) + EthEstimateGas func(context.Context, ethtypes.EthCall) (json.RawMessage, error) + EthFeeHistory func(context.Context, ethtypes.EthUint64, string, []float64) (json.RawMessage, error) + EthGasPrice func(context.Context) (json.RawMessage, error) + EthGetBalance func(context.Context, ethtypes.EthAddress, string) (json.RawMessage, error) + EthGetBlockByHash func(context.Context, ethtypes.EthHash, bool) (json.RawMessage, error) + EthGetBlockByNumber func(context.Context, string, bool) (json.RawMessage, error) + EthGetBlockTransactionCountByHash func(context.Context, ethtypes.EthHash) (json.RawMessage, error) + EthGetBlockTransactionCountByNumber func(context.Context, ethtypes.EthUint64) (json.RawMessage, error) + EthGetCode func(context.Context, ethtypes.EthAddress, string) (json.RawMessage, error) + EthGetFilterChanges func(context.Context, ethtypes.EthFilterID) (json.RawMessage, error) + EthGetFilterLogs func(context.Context, ethtypes.EthFilterID) (json.RawMessage, error) + EthGetLogs func(context.Context, *ethtypes.EthFilterSpec) (json.RawMessage, error) + EthGetStorageAt func(context.Context, ethtypes.EthAddress, ethtypes.EthBytes, string) (json.RawMessage, error) + EthGetTransactionByBlockHashAndIndex func(context.Context, ethtypes.EthHash, ethtypes.EthUint64) (json.RawMessage, error) + EthGetTransactionByBlockNumberAndIndex func(context.Context, ethtypes.EthUint64, ethtypes.EthUint64) (json.RawMessage, error) + EthGetTransactionByHash func(context.Context, *ethtypes.EthHash) (json.RawMessage, error) + EthGetTransactionCount func(context.Context, ethtypes.EthAddress, string) (json.RawMessage, error) + EthGetTransactionReceipt func(context.Context, ethtypes.EthHash) (json.RawMessage, error) + EthMaxPriorityFeePerGas func(context.Context) (json.RawMessage, error) + EthNewBlockFilter func(context.Context) (json.RawMessage, error) + EthNewFilter func(context.Context, *ethtypes.EthFilterSpec) (json.RawMessage, error) + EthNewPendingTransactionFilter func(context.Context) (json.RawMessage, error) + EthSendRawTransaction func(context.Context, ethtypes.EthBytes) (json.RawMessage, error) + EthSubscribe func(context.Context, string, *ethtypes.EthSubscriptionParams) (json.RawMessage, error) + EthUninstallFilter func(context.Context, ethtypes.EthFilterID) (json.RawMessage, error) + EthUnsubscribe func(context.Context, ethtypes.EthSubscriptionID) (json.RawMessage, error) +} + +func TestEthOpenRPCConformance(t *testing.T) { + kit.QuietAllLogsExcept("events", "messagepool") + + // specs/eth_openrpc.json is built from https://github.com/ethereum/execution-apis + specJSON, err := os.ReadFile("specs/eth_openrpc.json") + require.NoError(t, err) + + specParsed := orpctypes.NewOpenRPCSpec1() + err = json.Unmarshal(specJSON, specParsed) + require.NoError(t, err) + parse.GetTypes(specParsed, specParsed.Objects) + + schemas := make(map[string]spec.Schema) + for _, method := range specParsed.Methods { + if method.Result != nil { + schemas[method.Name] = method.Result.Schema + } + } + + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC(), kit.WithEthRPC()) + ens.InterconnectAll().BeginMining(10 * time.Millisecond) + + contractHex, err := os.ReadFile("contracts/EventMatrix.hex") + require.NoError(t, err) + + // strip any trailing newlines from the file + contractHex = bytes.TrimRight(contractHex, "\n") + + contractBin, err := hex.DecodeString(string(contractHex)) + require.NoError(t, err) + + senderKey, senderEthAddr, senderFilAddr := client.EVM().NewAccount() + _, receiverEthAddr, _ := client.EVM().NewAccount() + kit.SendFunds(ctx, t, client, senderFilAddr, types.FromFil(1000)) + + deployerAddr, err := client.EVM().WalletDefaultAddress(ctx) + require.NoError(t, err) + + pendingTransactionFilterID, err := client.EthNewPendingTransactionFilter(ctx) + require.NoError(t, err) + + blockFilterID, err := client.EthNewBlockFilter(ctx) + require.NoError(t, err) + + filterAllLogs := kit.NewEthFilterBuilder().FromBlockEpoch(0).Filter() + + logFilterID, err := client.EthNewFilter(ctx, filterAllLogs) + require.NoError(t, err) + + uninstallableFilterID, err := client.EthNewFilter(ctx, filterAllLogs) + require.NoError(t, err) + + rawSignedEthTx := createRawSignedEthTx(ctx, t, client, senderEthAddr, receiverEthAddr, senderKey, contractBin) + + result := client.EVM().DeployContract(ctx, deployerAddr, contractBin) + contractAddr, err := address.NewIDAddress(result.ActorID) + require.NoError(t, err) + + contractEthAddr := ethtypes.EthAddress(result.EthAddress) + + messageWithEvents, blockHashWithMessage, blockNumberWithMessage := waitForMessageWithEvents(ctx, t, client, deployerAddr, contractAddr) + + // create a json-rpc client that returns raw json responses + var ethapi ethAPIRaw + + netAddr, err := manet.ToNetAddr(client.ListenAddr) + require.NoError(t, err) + rpcAddr := "ws://" + netAddr.String() + "/rpc/v1" + + closer, err := jsonrpc.NewClient(ctx, rpcAddr, "Filecoin", ðapi, nil) + require.NoError(t, err) + defer closer() + + const skipUntilIssue10106 = "Skipped until EthTx is updated, see https://github.com/filecoin-project/lotus/issues/10106" + + testCases := []struct { + method string + variant string // suffix applied to the test name to distinguish different variants of a method call + call func(*ethAPIRaw) (json.RawMessage, error) + skipReason string + }{ + // Alphabetical order + + { + method: "eth_accounts", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthAccounts(context.Background()) + }, + }, + + { + method: "eth_blockNumber", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthBlockNumber(context.Background()) + }, + }, + + { + method: "eth_call", + variant: "latest", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthCall(context.Background(), ethtypes.EthCall{ + From: &senderEthAddr, + Data: contractBin, + }, "latest") + }, + }, + + { + method: "eth_chainId", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthChainId(context.Background()) + }, + }, + + { + method: "eth_estimateGas", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthEstimateGas(context.Background(), ethtypes.EthCall{ + From: &senderEthAddr, + Data: contractBin, + }) + }, + }, + + { + method: "eth_feeHistory", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthFeeHistory(context.Background(), ethtypes.EthUint64(2), "", nil) + }, + }, + + { + method: "eth_gasPrice", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGasPrice(context.Background()) + }, + }, + + { + method: "eth_getBalance", + variant: "blocknumber", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetBalance(context.Background(), contractEthAddr, "0x0") + }, + }, + + { + method: "eth_getBlockByHash", + variant: "txhashes", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetBlockByHash(context.Background(), blockHashWithMessage, false) + }, + }, + + { + method: "eth_getBlockByHash", + variant: "txfull", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetBlockByHash(context.Background(), blockHashWithMessage, true) + }, + skipReason: skipUntilIssue10106, + }, + + { + method: "eth_getBlockByNumber", + variant: "earliest", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetBlockByNumber(context.Background(), "earliest", true) + }, + skipReason: skipUntilIssue10106, + }, + + { + method: "eth_getBlockByNumber", + variant: "pending", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetBlockByNumber(context.Background(), "pending", true) + }, + skipReason: skipUntilIssue10106, + }, + + { + method: "eth_getBlockByNumber", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetBlockByNumber(context.Background(), blockNumberWithMessage.Hex(), true) + }, + skipReason: skipUntilIssue10106, + }, + + { + method: "eth_getBlockTransactionCountByHash", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetBlockTransactionCountByHash(context.Background(), blockHashWithMessage) + }, + }, + + { + method: "eth_getBlockTransactionCountByNumber", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetBlockTransactionCountByNumber(context.Background(), blockNumberWithMessage) + }, + }, + + { + method: "eth_getCode", + variant: "blocknumber", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetCode(context.Background(), contractEthAddr, blockNumberWithMessage.Hex()) + }, + }, + + { + method: "eth_getFilterChanges", + variant: "pendingtransaction", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return a.EthGetFilterChanges(ctx, pendingTransactionFilterID) + }, + }, + + { + method: "eth_getFilterChanges", + variant: "block", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return a.EthGetFilterChanges(ctx, blockFilterID) + }, + }, + + { + method: "eth_getFilterChanges", + variant: "logs", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return a.EthGetFilterChanges(ctx, logFilterID) + }, + }, + + { + method: "eth_getFilterLogs", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return a.EthGetFilterLogs(ctx, logFilterID) + }, + }, + + { + method: "eth_getLogs", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetLogs(context.Background(), filterAllLogs) + }, + }, + + { + method: "eth_getStorageAt", + variant: "blocknumber", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetStorageAt(context.Background(), contractEthAddr, ethtypes.EthBytes{0}, "0x0") + }, + }, + + { + method: "eth_getTransactionByBlockHashAndIndex", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetTransactionByBlockHashAndIndex(context.Background(), blockHashWithMessage, ethtypes.EthUint64(0)) + }, + skipReason: skipUntilIssue10106, + }, + + { + method: "eth_getTransactionByBlockNumberAndIndex", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetTransactionByBlockNumberAndIndex(context.Background(), blockNumberWithMessage, ethtypes.EthUint64(0)) + }, + skipReason: skipUntilIssue10106, + }, + + { + method: "eth_getTransactionByHash", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetTransactionByHash(context.Background(), &messageWithEvents) + }, + skipReason: skipUntilIssue10106, + }, + + { + method: "eth_getTransactionCount", + variant: "blocknumber", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetTransactionCount(context.Background(), senderEthAddr, blockNumberWithMessage.Hex()) + }, + }, + + { + method: "eth_getTransactionReceipt", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthGetTransactionReceipt(context.Background(), messageWithEvents) + }, + }, + + { + method: "eth_maxPriorityFeePerGas", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthMaxPriorityFeePerGas(context.Background()) + }, + }, + + { + method: "eth_newBlockFilter", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthNewBlockFilter(context.Background()) + }, + }, + + { + method: "eth_newFilter", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthNewFilter(context.Background(), filterAllLogs) + }, + }, + + { + method: "eth_newPendingTransactionFilter", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthNewPendingTransactionFilter(context.Background()) + }, + }, + + { + method: "eth_sendRawTransaction", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return ethapi.EthSendRawTransaction(context.Background(), rawSignedEthTx) + }, + }, + { + method: "eth_uninstallFilter", + call: func(a *ethAPIRaw) (json.RawMessage, error) { + return a.EthUninstallFilter(ctx, uninstallableFilterID) + }, + }, + } + + for _, tc := range testCases { + tc := tc + name := tc.method + if tc.variant != "" { + name += "_" + tc.variant + } + t.Run(name, func(t *testing.T) { + if tc.skipReason != "" { + t.Skipf(tc.skipReason) + } + + schema, ok := schemas[tc.method] + require.True(t, ok, "method not found in openrpc spec") + + resp, err := tc.call(ðapi) + require.NoError(t, err) + + respJson, err := json.Marshal(resp) + require.NoError(t, err) + + loader := gojsonschema.NewGoLoader(schema) + resploader := gojsonschema.NewBytesLoader(respJson) + result, err := gojsonschema.Validate(loader, resploader) + require.NoError(t, err) + + if !result.Valid() { + if len(result.Errors()) == 1 && strings.Contains(result.Errors()[0].String(), "Must validate one and only one schema (oneOf)") { + // Ignore this error, since it seems the openrpc spec can't handle it + // New transaction and block filters have the same schema: an array of 32 byte hashes + return + } + + niceRespJson, err := json.MarshalIndent(resp, "", " ") + if err == nil { + t.Logf("response was %s", niceRespJson) + } + + schemaJson, err := json.MarshalIndent(schema, "", " ") + if err == nil { + t.Logf("schema was %s", schemaJson) + } + + // check against https://www.jsonschemavalidator.net/ + + for _, desc := range result.Errors() { + t.Logf("- %s\n", desc) + } + + t.Errorf("response did not validate") + } + }) + } +} + +func createRawSignedEthTx(ctx context.Context, t *testing.T, client *kit.TestFullNode, senderEthAddr ethtypes.EthAddress, receiverEthAddr ethtypes.EthAddress, senderKey *key.Key, contractBin []byte) []byte { + gaslimit, err := client.EthEstimateGas(ctx, ethtypes.EthCall{ + From: &senderEthAddr, + Data: contractBin, + }) + require.NoError(t, err) + + maxPriorityFeePerGas, err := client.EthMaxPriorityFeePerGas(ctx) + require.NoError(t, err) + + tx := ethtypes.EthTxArgs{ + ChainID: build.Eip155ChainId, + Value: big.NewInt(100), + Nonce: 0, + To: &receiverEthAddr, + MaxFeePerGas: types.NanoFil, + MaxPriorityFeePerGas: big.Int(maxPriorityFeePerGas), + GasLimit: int(gaslimit), + V: big.Zero(), + R: big.Zero(), + S: big.Zero(), + } + + client.EVM().SignTransaction(&tx, senderKey.PrivateKey) + signed, err := tx.ToRlpSignedMsg() + require.NoError(t, err) + return signed +} + +func waitForMessageWithEvents(ctx context.Context, t *testing.T, client *kit.TestFullNode, sender address.Address, target address.Address) (ethtypes.EthHash, ethtypes.EthHash, ethtypes.EthUint64) { + vals := []uint64{44, 27, 19, 12} + inputData := []byte{} + for _, v := range vals { + buf := make([]byte, 32) + binary.BigEndian.PutUint64(buf[24:], v) + inputData = append(inputData, buf...) + } + + // send a message that exercises event logs + ret, err := client.EVM().InvokeSolidity(ctx, sender, target, kit.EventMatrixContract.Fn["logEventThreeIndexedWithData"], inputData) + require.NoError(t, err) + require.True(t, ret.Receipt.ExitCode.IsSuccess(), "contract execution failed") + + msgHash, err := client.EthGetTransactionHashByCid(ctx, ret.Message) + require.NoError(t, err) + require.NotNil(t, msgHash) + + ts, err := client.ChainGetTipSet(ctx, ret.TipSet) + require.NoError(t, err) + + blockNumber := ethtypes.EthUint64(ts.Height()) + + tsCid, err := ts.Key().Cid() + require.NoError(t, err) + + blockHash, err := ethtypes.EthHashFromCid(tsCid) + require.NoError(t, err) + return *msgHash, blockHash, blockNumber +} diff --git a/itests/eth_filter_test.go b/itests/eth_filter_test.go index aba61f9349f..cdaf599ba8c 100644 --- a/itests/eth_filter_test.go +++ b/itests/eth_filter_test.go @@ -1,4 +1,3 @@ -// stm: #integration package itests import ( @@ -18,10 +17,10 @@ import ( "github.com/ipfs/go-cid" "github.com/stretchr/testify/require" cbg "github.com/whyrusleeping/cbor-gen" - "golang.org/x/crypto/sha3" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-jsonrpc" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" @@ -30,55 +29,9 @@ import ( "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types/ethtypes" "github.com/filecoin-project/lotus/itests/kit" + res "github.com/filecoin-project/lotus/lib/result" ) -// SolidityContractDef holds information about one of the test contracts -type SolidityContractDef struct { - Filename string // filename of the hex of the contract, e.g. contracts/EventMatrix.hex - Fn map[string][]byte // mapping of function names to 32-bit selector - Ev map[string][]byte // mapping of event names to 256-bit signature hashes -} - -var EventMatrixContract = SolidityContractDef{ - Filename: "contracts/EventMatrix.hex", - Fn: map[string][]byte{ - "logEventZeroData": ethFunctionHash("logEventZeroData()"), - "logEventOneData": ethFunctionHash("logEventOneData(uint256)"), - "logEventTwoData": ethFunctionHash("logEventTwoData(uint256,uint256)"), - "logEventThreeData": ethFunctionHash("logEventThreeData(uint256,uint256,uint256)"), - "logEventFourData": ethFunctionHash("logEventFourData(uint256,uint256,uint256,uint256)"), - "logEventOneIndexed": ethFunctionHash("logEventOneIndexed(uint256)"), - "logEventTwoIndexed": ethFunctionHash("logEventTwoIndexed(uint256,uint256)"), - "logEventThreeIndexed": ethFunctionHash("logEventThreeIndexed(uint256,uint256,uint256)"), - "logEventOneIndexedWithData": ethFunctionHash("logEventOneIndexedWithData(uint256,uint256)"), - "logEventTwoIndexedWithData": ethFunctionHash("logEventTwoIndexedWithData(uint256,uint256,uint256)"), - "logEventThreeIndexedWithData": ethFunctionHash("logEventThreeIndexedWithData(uint256,uint256,uint256,uint256)"), - }, - Ev: map[string][]byte{ - "EventZeroData": ethTopicHash("EventZeroData()"), - "EventOneData": ethTopicHash("EventOneData(uint256)"), - "EventTwoData": ethTopicHash("EventTwoData(uint256,uint256)"), - "EventThreeData": ethTopicHash("EventThreeData(uint256,uint256,uint256)"), - "EventFourData": ethTopicHash("EventFourData(uint256,uint256,uint256,uint256)"), - "EventOneIndexed": ethTopicHash("EventOneIndexed(uint256)"), - "EventTwoIndexed": ethTopicHash("EventTwoIndexed(uint256,uint256)"), - "EventThreeIndexed": ethTopicHash("EventThreeIndexed(uint256,uint256,uint256)"), - "EventOneIndexedWithData": ethTopicHash("EventOneIndexedWithData(uint256,uint256)"), - "EventTwoIndexedWithData": ethTopicHash("EventTwoIndexedWithData(uint256,uint256,uint256)"), - "EventThreeIndexedWithData": ethTopicHash("EventThreeIndexedWithData(uint256,uint256,uint256,uint256)"), - }, -} - -var EventsContract = SolidityContractDef{ - Filename: "contracts/events.bin", - Fn: map[string][]byte{ - "log_zero_data": {0x00, 0x00, 0x00, 0x00}, - "log_zero_nodata": {0x00, 0x00, 0x00, 0x01}, - "log_four_data": {0x00, 0x00, 0x00, 0x02}, - }, - Ev: map[string][]byte{}, -} - func TestEthNewPendingTransactionFilter(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() @@ -287,7 +240,7 @@ func TestEthNewBlockFilter(t *testing.T) { } } -func TestEthNewFilterCatchAll(t *testing.T) { +func TestEthNewFilterDefaultSpec(t *testing.T) { require := require.New(t) kit.QuietAllLogsExcept("events", "messagepool") @@ -367,7 +320,7 @@ func TestEthNewFilterCatchAll(t *testing.T) { AssertEthLogs(t, elogs, expected, received) } -func TestEthGetLogsAll(t *testing.T) { +func TestEthGetLogsBasic(t *testing.T) { require := require.New(t) kit.QuietAllLogsExcept("events", "messagepool") @@ -383,7 +336,7 @@ func TestEthGetLogsAll(t *testing.T) { ethContractAddr, received := invokeLogFourData(t, client, invocations) // Build filter spec - spec := newEthFilterBuilder(). + spec := kit.NewEthFilterBuilder(). FromBlockEpoch(0). Topic1OneOf(paddedEthHash([]byte{0x11, 0x11})). Filter() @@ -410,45 +363,7 @@ func TestEthGetLogsAll(t *testing.T) { AssertEthLogs(t, elogs, expected, received) } -func TestEthGetLogsByTopic(t *testing.T) { - require := require.New(t) - - kit.QuietAllLogsExcept("events", "messagepool") - - blockTime := 100 * time.Millisecond - - client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC()) - ens.InterconnectAll().BeginMining(blockTime) - - invocations := 1 - ethContractAddr, received := invokeLogFourData(t, client, invocations) - - // find log by known topic1 - var spec ethtypes.EthFilterSpec - err := json.Unmarshal([]byte(`{"fromBlock":"0x0","topics":["0x0000000000000000000000000000000000000000000000000000000000001111"]}`), &spec) - require.NoError(err) - - res, err := client.EthGetLogs(context.Background(), &spec) - require.NoError(err) - - expected := []ExpectedEthLog{ - { - Address: ethContractAddr, - Topics: []ethtypes.EthBytes{ - paddedEthBytes([]byte{0x11, 0x11}), - paddedEthBytes([]byte{0x22, 0x22}), - paddedEthBytes([]byte{0x33, 0x33}), - paddedEthBytes([]byte{0x44, 0x44}), - }, - Data: paddedEthBytes([]byte{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}), - }, - } - elogs, err := parseEthLogsFromFilterResult(res) - require.NoError(err) - AssertEthLogs(t, elogs, expected, received) -} - -func TestEthSubscribeLogs(t *testing.T) { +func TestEthSubscribeLogsNoTopicSpec(t *testing.T) { require := require.New(t) kit.QuietAllLogsExcept("events", "messagepool") @@ -477,15 +392,15 @@ func TestEthSubscribeLogs(t *testing.T) { t.Logf("actor ID address is %s", idAddr) // install filter - respCh, err := client.EthSubscribe(ctx, "logs", nil) + subId, err := client.EthSubscribe(ctx, res.Wrap[jsonrpc.RawParams](json.Marshal(ethtypes.EthSubscribeParams{EventType: "logs"})).Assert(require.NoError)) require.NoError(err) - subResponses := []ethtypes.EthSubscriptionResponse{} - go func() { - for resp := range respCh { - subResponses = append(subResponses, resp) - } - }() + var subResponses []ethtypes.EthSubscriptionResponse + err = client.EthSubRouter.AddSub(ctx, subId, func(ctx context.Context, resp *ethtypes.EthSubscriptionResponse) error { + subResponses = append(subResponses, *resp) + return nil + }) + require.NoError(err) const iterations = 10 ethContractAddr, messages := invokeLogFourData(t, client, iterations) @@ -522,544 +437,188 @@ func TestEthGetLogs(t *testing.T) { defer cancel() // Set up the test fixture with a standard list of invocations - contract1, contract2, messages := invokeEventMatrix(ctx, t, client) + contract1, contract2, invocations := prepareEventMatrixInvocations(ctx, t, client) + testCases := getCombinationFilterTestCases(contract1, contract2, "0x0") - testCases := []struct { - name string - spec *ethtypes.EthFilterSpec - expected []ExpectedEthLog - }{ - { - name: "find all EventZeroData events", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventZeroData"])).Filter(), + messages := invokeAndWaitUntilAllOnChain(t, client, invocations) - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventZeroData"], - }, - Data: nil, - }, - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventZeroData"], - }, - Data: nil, - }, - }, - }, - { - name: "find all EventOneData events", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventOneData"])).Filter(), + for _, tc := range testCases { + tc := tc // appease the lint despot + t.Run(tc.name, func(t *testing.T) { + res, err := client.EthGetLogs(ctx, tc.spec) + require.NoError(err) - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneData"], - }, - Data: packUint64Values(23), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneData"], - }, - Data: packUint64Values(44), - }, - }, - }, - { - name: "find all EventTwoData events", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventTwoData"])).Filter(), + elogs, err := parseEthLogsFromFilterResult(res) + require.NoError(err) + AssertEthLogs(t, elogs, tc.expected, messages) + }) + } +} - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoData"], - }, - Data: packUint64Values(555, 666), - }, - }, - }, - { - name: "find all EventThreeData events", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventThreeData"])).Filter(), +func TestEthGetFilterChanges(t *testing.T) { + require := require.New(t) + kit.QuietAllLogsExcept("events", "messagepool") - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventThreeData"], - }, - Data: packUint64Values(1, 2, 3), - }, - }, - }, - { - name: "find all EventOneIndexed events", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventOneIndexed"])).Filter(), + blockTime := 100 * time.Millisecond - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexed"], - paddedUint64(44), - }, - Data: nil, - }, - }, - }, - { - name: "find all EventTwoIndexed events", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventTwoIndexed"])).Filter(), + client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC()) + ens.InterconnectAll().BeginMining(blockTime) - expected: []ExpectedEthLog{ - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexed"], - paddedUint64(44), - paddedUint64(19), - }, - Data: nil, - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexed"], - paddedUint64(40), - paddedUint64(20), - }, - Data: nil, - }, - }, - }, - { - name: "find all EventThreeIndexed events", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventThreeIndexed"])).Filter(), + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() - expected: []ExpectedEthLog{ - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventThreeIndexed"], - paddedUint64(44), - paddedUint64(27), - paddedUint64(19), - }, - Data: nil, - }, - }, - }, - { - name: "find all EventOneIndexedWithData events", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventOneIndexedWithData"])).Filter(), + // Set up the test fixture with a standard list of invocations + contract1, contract2, invocations := prepareEventMatrixInvocations(ctx, t, client) - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(44), - }, - Data: paddedUint64(19), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(46), - }, - Data: paddedUint64(12), - }, - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(50), - }, - Data: paddedUint64(9), - }, - }, - }, - { - name: "find all EventTwoIndexedWithData events", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventTwoIndexedWithData"])).Filter(), + // Get the test cases + testCases := getCombinationFilterTestCases(contract1, contract2, "latest") - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], - paddedUint64(44), - paddedUint64(27), - }, - Data: paddedUint64(19), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], - paddedUint64(46), - paddedUint64(27), - }, - Data: paddedUint64(19), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], - paddedUint64(46), - paddedUint64(14), - }, - Data: paddedUint64(19), - }, - }, - }, - { - name: "find all EventThreeIndexedWithData events", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventThreeIndexedWithData"])).Filter(), + testFilters := map[string]ethtypes.EthFilterID{} + // Create all the filters + for _, tc := range testCases { + filterID, err := client.EthNewFilter(ctx, tc.spec) + require.NoError(err) + testFilters[tc.name] = filterID + } - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventThreeIndexedWithData"], - paddedUint64(44), - paddedUint64(27), - paddedUint64(19), - }, - Data: paddedUint64(12), - }, - }, - }, + // Perform all the invocations + messages := invokeAndWaitUntilAllOnChain(t, client, invocations) - { - name: "find all events from contract2", - spec: newEthFilterBuilder().FromBlockEpoch(0).AddressOneOf(contract2).Filter(), + for _, tc := range testCases { + tc := tc // appease the lint despot + t.Run(tc.name, func(t *testing.T) { + filterID, ok := testFilters[tc.name] + require.True(ok) - expected: []ExpectedEthLog{ - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventZeroData"], - }, - Data: nil, - }, - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventThreeIndexed"], - paddedUint64(44), - paddedUint64(27), - paddedUint64(19), - }, - Data: nil, - }, - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexed"], - paddedUint64(44), - paddedUint64(19), - }, - Data: nil, - }, - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(50), - }, - Data: paddedUint64(9), - }, - }, - }, + // Look for events that the filter has accumulated + res, err := client.EthGetFilterChanges(ctx, filterID) + require.NoError(err) - { - name: "find all events with topic2 of 44", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic2OneOf(paddedEthHash(paddedUint64(44))).Filter(), + elogs, err := parseEthLogsFromFilterResult(res) + require.NoError(err) + AssertEthLogs(t, elogs, tc.expected, messages) + }) + } +} - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexed"], - paddedUint64(44), - }, - Data: nil, - }, - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexed"], - paddedUint64(44), - paddedUint64(19), - }, - Data: nil, - }, - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventThreeIndexed"], - paddedUint64(44), - paddedUint64(27), - paddedUint64(19), - }, - Data: nil, - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(44), - }, - Data: paddedUint64(19), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], - paddedUint64(44), - paddedUint64(27), - }, - Data: paddedUint64(19), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventThreeIndexedWithData"], - paddedUint64(44), - paddedUint64(27), - paddedUint64(19), - }, - Data: paddedUint64(12), - }, - }, - }, +func TestEthSubscribeLogs(t *testing.T) { + require := require.New(t) + kit.QuietAllLogsExcept("events", "messagepool") - { - name: "find all events with topic2 of 44 from contract2", - spec: newEthFilterBuilder().FromBlockEpoch(0).AddressOneOf(contract2).Topic2OneOf(paddedEthHash(paddedUint64(44))).Filter(), + blockTime := 100 * time.Millisecond - expected: []ExpectedEthLog{ - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventThreeIndexed"], - paddedUint64(44), - paddedUint64(27), - paddedUint64(19), - }, - Data: nil, - }, - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexed"], - paddedUint64(44), - paddedUint64(19), - }, - Data: nil, - }, - }, - }, + client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC()) + ens.InterconnectAll().BeginMining(blockTime) - { - name: "find all EventOneIndexedWithData events from contract1 or contract2", - spec: newEthFilterBuilder(). - FromBlockEpoch(0). - AddressOneOf(contract1, contract2). - Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventOneIndexedWithData"])). - Filter(), + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(44), - }, - Data: paddedUint64(19), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(46), - }, - Data: paddedUint64(12), - }, - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(50), - }, - Data: paddedUint64(9), - }, - }, - }, + // Set up the test fixture with a standard list of invocations + contract1, contract2, invocations := prepareEventMatrixInvocations(ctx, t, client) - { - name: "find all events with topic2 of 46", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic2OneOf(paddedEthHash(paddedUint64(46))).Filter(), + // Get the test cases + testCases := getTopicFilterTestCases(contract1, contract2, "latest") - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(46), - }, - Data: paddedUint64(12), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], - paddedUint64(46), - paddedUint64(27), - }, - Data: paddedUint64(19), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], - paddedUint64(46), - paddedUint64(14), - }, - Data: paddedUint64(19), - }, - }, - }, - { - name: "find all events with topic2 of 50", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic2OneOf(paddedEthHash(paddedUint64(50))).Filter(), + testResponses := map[string]chan ethtypes.EthSubscriptionResponse{} - expected: []ExpectedEthLog{ - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(50), - }, - Data: paddedUint64(9), - }, + // Create all the filters + for _, tc := range testCases { + // subscribe to topics in filter + subParam, err := json.Marshal(ethtypes.EthSubscribeParams{ + EventType: "logs", + Params: ðtypes.EthSubscriptionParams{ + Topics: tc.spec.Topics, + Address: tc.spec.Address, }, - }, - { - name: "find all events with topic2 of 46 or 50", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic2OneOf(paddedEthHash(paddedUint64(46)), paddedEthHash(paddedUint64(50))).Filter(), + }) + require.NoError(err) - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(46), - }, - Data: paddedUint64(12), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], - paddedUint64(46), - paddedUint64(27), - }, - Data: paddedUint64(19), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], - paddedUint64(46), - paddedUint64(14), - }, - Data: paddedUint64(19), - }, - { - Address: contract2, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexedWithData"], - paddedUint64(50), - }, - Data: paddedUint64(9), - }, - }, - }, + subId, err := client.EthSubscribe(ctx, subParam) + require.NoError(err) - { - name: "find all events with topic1 of EventTwoIndexedWithData and topic3 of 27", - spec: newEthFilterBuilder(). - FromBlockEpoch(0). - Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventTwoIndexedWithData"])). - Topic3OneOf(paddedEthHash(paddedUint64(27))). - Filter(), + responseCh := make(chan ethtypes.EthSubscriptionResponse, len(invocations)) + testResponses[tc.name] = responseCh - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], - paddedUint64(44), - paddedUint64(27), - }, - Data: paddedUint64(19), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], - paddedUint64(46), - paddedUint64(27), - }, - Data: paddedUint64(19), - }, - }, - }, + err = client.EthSubRouter.AddSub(ctx, subId, func(ctx context.Context, resp *ethtypes.EthSubscriptionResponse) error { + responseCh <- *resp + return nil + }) + require.NoError(err) + } - { - name: "find all events with topic1 of EventTwoIndexedWithData or EventOneIndexed and topic2 of 44", - spec: newEthFilterBuilder(). - FromBlockEpoch(0). - Topic1OneOf(paddedEthHash(EventMatrixContract.Ev["EventTwoIndexedWithData"]), paddedEthHash(EventMatrixContract.Ev["EventOneIndexed"])). - Topic2OneOf(paddedEthHash(paddedUint64(44))). - Filter(), + // Perform all the invocations + messages := invokeAndWaitUntilAllOnChain(t, client, invocations) - expected: []ExpectedEthLog{ - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], - paddedUint64(44), - paddedUint64(27), - }, - Data: paddedUint64(19), - }, - { - Address: contract1, - Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventOneIndexed"], - paddedUint64(44), - }, - Data: nil, - }, - }, - }, + // wait a little for subscriptions to gather results + time.Sleep(blockTime * 6) + + for _, tc := range testCases { + tc := tc // appease the lint despot + t.Run(tc.name, func(t *testing.T) { + responseCh, ok := testResponses[tc.name] + require.True(ok) + + // don't expect any more responses + close(responseCh) + + var elogs []*ethtypes.EthLog + for resp := range responseCh { + rlist, ok := resp.Result.([]interface{}) + require.True(ok, "expected subscription result to be []interface{}, but was %T", resp.Result) + + for _, rentry := range rlist { + rmap, ok := rentry.(map[string]interface{}) + require.True(ok, "expected subscription result entry to be map[string]interface{}, but was %T", resp.Result) + + elog, err := ParseEthLog(rmap) + require.NoError(err) + + elogs = append(elogs, elog) + } + + } + AssertEthLogs(t, elogs, tc.expected, messages) + }) + } +} + +func TestEthGetFilterLogs(t *testing.T) { + require := require.New(t) + kit.QuietAllLogsExcept("events", "messagepool") + + 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() + + // Set up the test fixture with a standard list of invocations + contract1, contract2, invocations := prepareEventMatrixInvocations(ctx, t, client) + + // Get the test cases + testCases := getCombinationFilterTestCases(contract1, contract2, "latest") + + testFilters := map[string]ethtypes.EthFilterID{} + // Create all the filters + for _, tc := range testCases { + filterID, err := client.EthNewFilter(ctx, tc.spec) + require.NoError(err) + testFilters[tc.name] = filterID } + // Perform all the invocations + messages := invokeAndWaitUntilAllOnChain(t, client, invocations) + for _, tc := range testCases { tc := tc // appease the lint despot t.Run(tc.name, func(t *testing.T) { - res, err := client.EthGetLogs(ctx, tc.spec) + filterID, ok := testFilters[tc.name] + require.True(ok) + + // Look for events that the filter has accumulated + res, err := client.EthGetFilterLogs(ctx, filterID) require.NoError(err) elogs, err := parseEthLogsFromFilterResult(res) @@ -1090,8 +649,8 @@ func TestEthGetLogsWithBlockRanges(t *testing.T) { // Select events for partitioning for _, m := range messages { - if bytes.Equal(m.invocation.Selector, EventMatrixContract.Fn["logEventTwoIndexedWithData"]) { - addr := getContractEthAddress(ctx, t, client, m.invocation.Target) + if bytes.Equal(m.invocation.Selector, kit.EventMatrixContract.Fn["logEventTwoIndexedWithData"]) { + addr := getEthAddress(ctx, t, client, m.invocation.Target) args := unpackUint64Values(m.invocation.Data) require.Equal(3, len(args), "logEventTwoIndexedWithData should have 3 arguments") @@ -1099,7 +658,7 @@ func TestEthGetLogsWithBlockRanges(t *testing.T) { expectedByHeight[m.ts.Height()] = append(expectedByHeight[m.ts.Height()], ExpectedEthLog{ Address: addr, Topics: []ethtypes.EthBytes{ - EventMatrixContract.Ev["EventTwoIndexedWithData"], + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], paddedUint64(args[0]), paddedUint64(args[1]), }, @@ -1164,7 +723,7 @@ func TestEthGetLogsWithBlockRanges(t *testing.T) { require.True(len(partition3.expected) > 0, "partition should have events") // these are the topics we selected for partitioning earlier - topics := []ethtypes.EthHash{paddedEthHash(EventMatrixContract.Ev["EventTwoIndexedWithData"])} + topics := []ethtypes.EthHash{paddedEthHash(kit.EventMatrixContract.Ev["EventTwoIndexedWithData"])} union := func(lists ...[]ExpectedEthLog) []ExpectedEthLog { ret := []ExpectedEthLog{} @@ -1181,91 +740,91 @@ func TestEthGetLogsWithBlockRanges(t *testing.T) { }{ { name: "find all events from genesis", - spec: newEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(0).Topic1OneOf(topics...).Filter(), expected: union(partition1.expected, partition2.expected, partition3.expected), }, { name: "find all from start of partition1", - spec: newEthFilterBuilder().FromBlockEpoch(partition1.start).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(partition1.start).Topic1OneOf(topics...).Filter(), expected: union(partition1.expected, partition2.expected, partition3.expected), }, { name: "find all from start of partition2", - spec: newEthFilterBuilder().FromBlockEpoch(partition2.start).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(partition2.start).Topic1OneOf(topics...).Filter(), expected: union(partition2.expected, partition3.expected), }, { name: "find all from start of partition3", - spec: newEthFilterBuilder().FromBlockEpoch(partition3.start).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(partition3.start).Topic1OneOf(topics...).Filter(), expected: union(partition3.expected), }, { name: "find none after end of partition3", - spec: newEthFilterBuilder().FromBlockEpoch(partition3.end + 1).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(partition3.end + 1).Topic1OneOf(topics...).Filter(), expected: nil, }, { name: "find all events from genesis to end of partition1", - spec: newEthFilterBuilder().FromBlockEpoch(0).ToBlockEpoch(partition1.end).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(0).ToBlockEpoch(partition1.end).Topic1OneOf(topics...).Filter(), expected: union(partition1.expected), }, { name: "find all events from genesis to end of partition2", - spec: newEthFilterBuilder().FromBlockEpoch(0).ToBlockEpoch(partition2.end).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(0).ToBlockEpoch(partition2.end).Topic1OneOf(topics...).Filter(), expected: union(partition1.expected, partition2.expected), }, { name: "find all events from genesis to end of partition3", - spec: newEthFilterBuilder().FromBlockEpoch(0).ToBlockEpoch(partition3.end).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(0).ToBlockEpoch(partition3.end).Topic1OneOf(topics...).Filter(), expected: union(partition1.expected, partition2.expected, partition3.expected), }, { name: "find none from genesis to start of partition1", - spec: newEthFilterBuilder().FromBlockEpoch(0).ToBlockEpoch(partition1.start - 1).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(0).ToBlockEpoch(partition1.start - 1).Topic1OneOf(topics...).Filter(), expected: nil, }, { name: "find all events in partition1", - spec: newEthFilterBuilder().FromBlockEpoch(partition1.start).ToBlockEpoch(partition1.end).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(partition1.start).ToBlockEpoch(partition1.end).Topic1OneOf(topics...).Filter(), expected: union(partition1.expected), }, { name: "find all events in partition2", - spec: newEthFilterBuilder().FromBlockEpoch(partition2.start).ToBlockEpoch(partition2.end).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(partition2.start).ToBlockEpoch(partition2.end).Topic1OneOf(topics...).Filter(), expected: union(partition2.expected), }, { name: "find all events in partition3", - spec: newEthFilterBuilder().FromBlockEpoch(partition3.start).ToBlockEpoch(partition3.end).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(partition3.start).ToBlockEpoch(partition3.end).Topic1OneOf(topics...).Filter(), expected: union(partition3.expected), }, { name: "find all events from earliest to end of partition1", - spec: newEthFilterBuilder().FromBlock("earliest").ToBlockEpoch(partition1.end).Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlock("earliest").ToBlockEpoch(partition1.end).Topic1OneOf(topics...).Filter(), expected: union(partition1.expected), }, { name: "find all events from start of partition3 to latest", - spec: newEthFilterBuilder().FromBlockEpoch(partition3.start).ToBlock("latest").Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlockEpoch(partition3.start).ToBlock("latest").Topic1OneOf(topics...).Filter(), expected: union(partition3.expected), }, { name: "find all events from earliest to latest", - spec: newEthFilterBuilder().FromBlock("earliest").ToBlock("latest").Topic1OneOf(topics...).Filter(), + spec: kit.NewEthFilterBuilder().FromBlock("earliest").ToBlock("latest").Topic1OneOf(topics...).Filter(), expected: union(partition1.expected, partition2.expected, partition3.expected), }, } @@ -1283,6 +842,108 @@ func TestEthGetLogsWithBlockRanges(t *testing.T) { } } +func TestEthNewFilterMergesHistoricWithRealtime(t *testing.T) { + require := require.New(t) + + kit.QuietAllLogsExcept("events", "messagepool") + + 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() + + sender, contract := client.EVM().DeployContractFromFilename(ctx, kit.EventMatrixContract.Filename) + + // generate some events before the creation of the filter + preInvocations := []Invocation{ + { + Sender: sender, + Target: contract, + Selector: kit.EventMatrixContract.Fn["logEventOneData"], + Data: packUint64Values(1), + }, + { + Sender: sender, + Target: contract, + Selector: kit.EventMatrixContract.Fn["logEventOneIndexed"], + Data: packUint64Values(2), + }, + } + + messages := invokeAndWaitUntilAllOnChain(t, client, preInvocations) + + // now install filter + spec := kit.NewEthFilterBuilder().FromBlock("earliest").Filter() + + filterID, err := client.EthNewFilter(ctx, spec) + require.NoError(err) + + // generate some events after the creation of the filter + postInvocations := []Invocation{ + { + Sender: sender, + Target: contract, + Selector: kit.EventMatrixContract.Fn["logEventOneData"], + Data: packUint64Values(3), + }, + { + Sender: sender, + Target: contract, + Selector: kit.EventMatrixContract.Fn["logEventOneIndexed"], + Data: packUint64Values(4), + }, + } + + postMessages := invokeAndWaitUntilAllOnChain(t, client, postInvocations) + for k, v := range postMessages { + messages[k] = v + } + + // collect filter results + res, err := client.EthGetFilterChanges(ctx, filterID) + require.NoError(err) + + ethContractAddr := getEthAddress(ctx, t, client, contract) + + // expect to see 2 messages from before the filter was installed and 2 after + expected := []ExpectedEthLog{ + { + Address: ethContractAddr, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneData"], + }, + Data: paddedUint64(1), + }, + { + Address: ethContractAddr, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexed"], + paddedUint64(2), + }, + }, + { + Address: ethContractAddr, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneData"], + }, + Data: paddedUint64(3), + }, + { + Address: ethContractAddr, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexed"], + paddedUint64(4), + }, + }, + } + + elogs, err := parseEthLogsFromFilterResult(res) + require.NoError(err) + AssertEthLogs(t, elogs, expected, messages) +} + // ------------------------------------------------------------------------------- // end of tests // ------------------------------------------------------------------------------- @@ -1295,7 +956,7 @@ type msgInTipset struct { reverted bool } -func getContractEthAddress(ctx context.Context, t *testing.T, client *kit.TestFullNode, addr address.Address) ethtypes.EthAddress { +func getEthAddress(ctx context.Context, t *testing.T, client *kit.TestFullNode, addr address.Address) ethtypes.EthAddress { head, err := client.ChainHead(ctx) require.NoError(t, err) @@ -1392,7 +1053,8 @@ func invokeAndWaitUntilAllOnChain(t *testing.T, client *kit.TestFullNode, invoca } } } - ret := client.EVM().InvokeSolidity(ctx, inv.Sender, inv.Target, inv.Selector, inv.Data) + ret, err := client.EVM().InvokeSolidity(ctx, inv.Sender, inv.Target, inv.Selector, inv.Data) + require.NoError(err) require.True(ret.Receipt.ExitCode.IsSuccess(), "contract execution failed") invocationMap[ret.Message] = inv @@ -1432,28 +1094,28 @@ func invokeLogFourData(t *testing.T, client *kit.TestFullNode, iterations int) ( ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() - fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, EventsContract.Filename) + fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, kit.EventsContract.Filename) invocations := make([]Invocation, iterations) for i := range invocations { invocations[i] = Invocation{ Sender: fromAddr, Target: idAddr, - Selector: EventsContract.Fn["log_four_data"], + Selector: kit.EventsContract.Fn["log_four_data"], Data: nil, } } messages := invokeAndWaitUntilAllOnChain(t, client, invocations) - ethAddr := getContractEthAddress(ctx, t, client, idAddr) + ethAddr := getEthAddress(ctx, t, client, idAddr) return ethAddr, messages } -func invokeEventMatrix(ctx context.Context, t *testing.T, client *kit.TestFullNode) (ethtypes.EthAddress, ethtypes.EthAddress, map[ethtypes.EthHash]msgInTipset) { - sender1, contract1 := client.EVM().DeployContractFromFilename(ctx, EventMatrixContract.Filename) - sender2, contract2 := client.EVM().DeployContractFromFilename(ctx, EventMatrixContract.Filename) +func prepareEventMatrixInvocations(ctx context.Context, t *testing.T, client *kit.TestFullNode) (ethtypes.EthAddress, ethtypes.EthAddress, []Invocation) { + sender1, contract1 := client.EVM().DeployContractFromFilename(ctx, kit.EventMatrixContract.Filename) + sender2, contract2 := client.EVM().DeployContractFromFilename(ctx, kit.EventMatrixContract.Filename) invocations := []Invocation{ // log EventZeroData() @@ -1461,189 +1123,743 @@ func invokeEventMatrix(ctx context.Context, t *testing.T, client *kit.TestFullNo { Sender: sender1, Target: contract1, - Selector: EventMatrixContract.Fn["logEventZeroData"], + Selector: kit.EventMatrixContract.Fn["logEventZeroData"], + Data: nil, + }, + + // log EventOneData(23) + // topic1: hash(EventOneData) + // data: 23 + { + Sender: sender1, + Target: contract1, + Selector: kit.EventMatrixContract.Fn["logEventOneData"], + Data: packUint64Values(23), + }, + + // log EventOneIndexed(44) + // topic1: hash(EventOneIndexed) + // topic2: 44 + { + Sender: sender1, + Target: contract1, + Selector: kit.EventMatrixContract.Fn["logEventOneIndexed"], + Data: packUint64Values(44), + }, + + // log EventTwoIndexed(44,19) from contract2 + // topic1: hash(EventTwoIndexed) + // topic2: 44 + // topic3: 19 + { + Sender: sender2, + Target: contract2, + Selector: kit.EventMatrixContract.Fn["logEventTwoIndexed"], + Data: packUint64Values(44, 19), + }, + + // log EventOneData(44) + // topic1: hash(EventOneData) + // data: 44 + { + Sender: sender1, + Target: contract1, + Selector: kit.EventMatrixContract.Fn["logEventOneData"], + Data: packUint64Values(44), + }, + + // log EventTwoData(555,666) + // topic1: hash(EventTwoData) + // data: 555,666 + { + Sender: sender1, + Target: contract1, + Selector: kit.EventMatrixContract.Fn["logEventTwoData"], + Data: packUint64Values(555, 666), + }, + + // log EventZeroData() from contract2 + // topic1: hash(EventZeroData) + { + Sender: sender2, + Target: contract2, + Selector: kit.EventMatrixContract.Fn["logEventZeroData"], Data: nil, }, - // log EventOneData(23) - // topic1: hash(EventOneData) - // data: 23 + // log EventThreeData(1,2,3) + // topic1: hash(EventTwoData) + // data: 1,2,3 + { + Sender: sender1, + Target: contract1, + Selector: kit.EventMatrixContract.Fn["logEventThreeData"], + Data: packUint64Values(1, 2, 3), + }, + + // log EventThreeIndexed(44,27,19) from contract2 + // topic1: hash(EventThreeIndexed) + // topic2: 44 + // topic3: 27 + // topic4: 19 + { + Sender: sender1, + Target: contract2, + Selector: kit.EventMatrixContract.Fn["logEventThreeIndexed"], + Data: packUint64Values(44, 27, 19), + }, + + // log EventOneIndexedWithData(44,19) + // topic1: hash(EventOneIndexedWithData) + // topic2: 44 + // data: 19 + { + Sender: sender1, + Target: contract1, + Selector: kit.EventMatrixContract.Fn["logEventOneIndexedWithData"], + Data: packUint64Values(44, 19), + }, + + // log EventOneIndexedWithData(46,12) + // topic1: hash(EventOneIndexedWithData) + // topic2: 46 + // data: 12 + { + Sender: sender1, + Target: contract1, + Selector: kit.EventMatrixContract.Fn["logEventOneIndexedWithData"], + Data: packUint64Values(46, 12), + }, + + // log EventTwoIndexedWithData(44,27,19) + // topic1: hash(EventTwoIndexedWithData) + // topic2: 44 + // topic3: 27 + // data: 19 + { + Sender: sender1, + Target: contract1, + Selector: kit.EventMatrixContract.Fn["logEventTwoIndexedWithData"], + Data: packUint64Values(44, 27, 19), + }, + + // log EventThreeIndexedWithData(44,27,19,12) + // topic1: hash(EventThreeIndexedWithData) + // topic2: 44 + // topic3: 27 + // topic4: 19 + // data: 12 + { + Sender: sender1, + Target: contract1, + Selector: kit.EventMatrixContract.Fn["logEventThreeIndexedWithData"], + Data: packUint64Values(44, 27, 19, 12), + }, + + // log EventOneIndexedWithData(50,9) + // topic1: hash(EventOneIndexedWithData) + // topic2: 50 + // data: 9 + { + Sender: sender2, + Target: contract2, + Selector: kit.EventMatrixContract.Fn["logEventOneIndexedWithData"], + Data: packUint64Values(50, 9), + }, + + // log EventTwoIndexedWithData(46,27,19) + // topic1: hash(EventTwoIndexedWithData) + // topic2: 46 + // topic3: 27 + // data: 19 + { + Sender: sender1, + Target: contract1, + Selector: kit.EventMatrixContract.Fn["logEventTwoIndexedWithData"], + Data: packUint64Values(46, 27, 19), + }, + + // log EventTwoIndexedWithData(46,14,19) + // topic1: hash(EventTwoIndexedWithData) + // topic2: 46 + // topic3: 14 + // data: 19 + { + Sender: sender1, + Target: contract1, + Selector: kit.EventMatrixContract.Fn["logEventTwoIndexedWithData"], + Data: packUint64Values(46, 14, 19), + }, + // log EventTwoIndexed(44,19) from contract1 + // topic1: hash(EventTwoIndexed) + // topic2: 44 + // topic3: 19 + { + Sender: sender1, + Target: contract1, + Selector: kit.EventMatrixContract.Fn["logEventTwoIndexed"], + Data: packUint64Values(40, 20), + }, + } + + ethAddr1 := getEthAddress(ctx, t, client, contract1) + ethAddr2 := getEthAddress(ctx, t, client, contract2) + + return ethAddr1, ethAddr2, invocations +} + +func invokeEventMatrix(ctx context.Context, t *testing.T, client *kit.TestFullNode) (ethtypes.EthAddress, ethtypes.EthAddress, map[ethtypes.EthHash]msgInTipset) { + ethAddr1, ethAddr2, invocations := prepareEventMatrixInvocations(ctx, t, client) + messages := invokeAndWaitUntilAllOnChain(t, client, invocations) + return ethAddr1, ethAddr2, messages +} + +type filterTestCase struct { + name string + spec *ethtypes.EthFilterSpec + expected []ExpectedEthLog +} + +// getTopicFilterTestCases returns filter test cases that only include topic criteria +func getTopicFilterTestCases(contract1, contract2 ethtypes.EthAddress, fromBlock string) []filterTestCase { + return []filterTestCase{ + { + name: "find all EventZeroData events", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventZeroData"])).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventZeroData"], + }, + Data: nil, + }, + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventZeroData"], + }, + Data: nil, + }, + }, + }, + { + name: "find all EventOneData events", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventOneData"])).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneData"], + }, + Data: packUint64Values(23), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneData"], + }, + Data: packUint64Values(44), + }, + }, + }, + { + name: "find all EventTwoData events", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventTwoData"])).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoData"], + }, + Data: packUint64Values(555, 666), + }, + }, + }, + { + name: "find all EventThreeData events", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventThreeData"])).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventThreeData"], + }, + Data: packUint64Values(1, 2, 3), + }, + }, + }, + { + name: "find all EventOneIndexed events", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventOneIndexed"])).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexed"], + paddedUint64(44), + }, + Data: nil, + }, + }, + }, + { + name: "find all EventTwoIndexed events", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventTwoIndexed"])).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexed"], + paddedUint64(44), + paddedUint64(19), + }, + Data: nil, + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexed"], + paddedUint64(40), + paddedUint64(20), + }, + Data: nil, + }, + }, + }, + { + name: "find all EventThreeIndexed events", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventThreeIndexed"])).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventThreeIndexed"], + paddedUint64(44), + paddedUint64(27), + paddedUint64(19), + }, + Data: nil, + }, + }, + }, { - Sender: sender1, - Target: contract1, - Selector: EventMatrixContract.Fn["logEventOneData"], - Data: packUint64Values(23), + name: "find all EventOneIndexedWithData events", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventOneIndexedWithData"])).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(44), + }, + Data: paddedUint64(19), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(46), + }, + Data: paddedUint64(12), + }, + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(50), + }, + Data: paddedUint64(9), + }, + }, }, + { + name: "find all EventTwoIndexedWithData events", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventTwoIndexedWithData"])).Filter(), - // log EventOneIndexed(44) - // topic1: hash(EventOneIndexed) - // topic2: 44 + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], + paddedUint64(44), + paddedUint64(27), + }, + Data: paddedUint64(19), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], + paddedUint64(46), + paddedUint64(27), + }, + Data: paddedUint64(19), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], + paddedUint64(46), + paddedUint64(14), + }, + Data: paddedUint64(19), + }, + }, + }, { - Sender: sender1, - Target: contract1, - Selector: EventMatrixContract.Fn["logEventOneIndexed"], - Data: packUint64Values(44), + name: "find all EventThreeIndexedWithData events", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventThreeIndexedWithData"])).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventThreeIndexedWithData"], + paddedUint64(44), + paddedUint64(27), + paddedUint64(19), + }, + Data: paddedUint64(12), + }, + }, }, - // log EventTwoIndexed(44,19) from contract2 - // topic1: hash(EventTwoIndexed) - // topic2: 44 - // topic3: 19 { - Sender: sender2, - Target: contract2, - Selector: EventMatrixContract.Fn["logEventTwoIndexed"], - Data: packUint64Values(44, 19), - }, + name: "find all events with topic2 of 44", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic2OneOf(paddedEthHash(paddedUint64(44))).Filter(), - // log EventOneData(44) - // topic1: hash(EventOneData) - // data: 44 + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexed"], + paddedUint64(44), + }, + Data: nil, + }, + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexed"], + paddedUint64(44), + paddedUint64(19), + }, + Data: nil, + }, + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventThreeIndexed"], + paddedUint64(44), + paddedUint64(27), + paddedUint64(19), + }, + Data: nil, + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(44), + }, + Data: paddedUint64(19), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], + paddedUint64(44), + paddedUint64(27), + }, + Data: paddedUint64(19), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventThreeIndexedWithData"], + paddedUint64(44), + paddedUint64(27), + paddedUint64(19), + }, + Data: paddedUint64(12), + }, + }, + }, { - Sender: sender1, - Target: contract1, - Selector: EventMatrixContract.Fn["logEventOneData"], - Data: packUint64Values(44), + name: "find all events with topic2 of 46", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic2OneOf(paddedEthHash(paddedUint64(46))).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(46), + }, + Data: paddedUint64(12), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], + paddedUint64(46), + paddedUint64(27), + }, + Data: paddedUint64(19), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], + paddedUint64(46), + paddedUint64(14), + }, + Data: paddedUint64(19), + }, + }, }, + { + name: "find all events with topic2 of 50", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic2OneOf(paddedEthHash(paddedUint64(50))).Filter(), - // log EventTwoData(555,666) - // topic1: hash(EventTwoData) - // data: 555,666 + expected: []ExpectedEthLog{ + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(50), + }, + Data: paddedUint64(9), + }, + }, + }, { - Sender: sender1, - Target: contract1, - Selector: EventMatrixContract.Fn["logEventTwoData"], - Data: packUint64Values(555, 666), + name: "find all events with topic2 of 46 or 50", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).Topic2OneOf(paddedEthHash(paddedUint64(46)), paddedEthHash(paddedUint64(50))).Filter(), + + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(46), + }, + Data: paddedUint64(12), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], + paddedUint64(46), + paddedUint64(27), + }, + Data: paddedUint64(19), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], + paddedUint64(46), + paddedUint64(14), + }, + Data: paddedUint64(19), + }, + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(50), + }, + Data: paddedUint64(9), + }, + }, }, - // log EventZeroData() from contract2 - // topic1: hash(EventZeroData) { - Sender: sender2, - Target: contract2, - Selector: EventMatrixContract.Fn["logEventZeroData"], - Data: nil, - }, + name: "find all events with topic1 of EventTwoIndexedWithData and topic3 of 27", + spec: kit.NewEthFilterBuilder(). + FromBlockEpoch(0). + Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventTwoIndexedWithData"])). + Topic3OneOf(paddedEthHash(paddedUint64(27))). + Filter(), - // log EventThreeData(1,2,3) - // topic1: hash(EventTwoData) - // data: 1,2,3 - { - Sender: sender1, - Target: contract1, - Selector: EventMatrixContract.Fn["logEventThreeData"], - Data: packUint64Values(1, 2, 3), + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], + paddedUint64(44), + paddedUint64(27), + }, + Data: paddedUint64(19), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], + paddedUint64(46), + paddedUint64(27), + }, + Data: paddedUint64(19), + }, + }, }, - // log EventThreeIndexed(44,27,19) from contract2 - // topic1: hash(EventThreeIndexed) - // topic2: 44 - // topic3: 27 - // topic4: 19 { - Sender: sender1, - Target: contract2, - Selector: EventMatrixContract.Fn["logEventThreeIndexed"], - Data: packUint64Values(44, 27, 19), - }, + name: "find all events with topic1 of EventTwoIndexedWithData or EventOneIndexed and topic2 of 44", + spec: kit.NewEthFilterBuilder(). + FromBlockEpoch(0). + Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventTwoIndexedWithData"]), paddedEthHash(kit.EventMatrixContract.Ev["EventOneIndexed"])). + Topic2OneOf(paddedEthHash(paddedUint64(44))). + Filter(), - // log EventOneIndexedWithData(44,19) - // topic1: hash(EventOneIndexedWithData) - // topic2: 44 - // data: 19 - { - Sender: sender1, - Target: contract1, - Selector: EventMatrixContract.Fn["logEventOneIndexedWithData"], - Data: packUint64Values(44, 19), + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexedWithData"], + paddedUint64(44), + paddedUint64(27), + }, + Data: paddedUint64(19), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexed"], + paddedUint64(44), + }, + Data: nil, + }, + }, }, + } +} - // log EventOneIndexedWithData(46,12) - // topic1: hash(EventOneIndexedWithData) - // topic2: 46 - // data: 12 +// getAddressFilterTestCases returns filter test cases include address criteria +func getAddressFilterTestCases(contract1, contract2 ethtypes.EthAddress, fromBlock string) []filterTestCase { + return []filterTestCase{ { - Sender: sender1, - Target: contract1, - Selector: EventMatrixContract.Fn["logEventOneIndexedWithData"], - Data: packUint64Values(46, 12), - }, + name: "find all events from contract2", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).AddressOneOf(contract2).Filter(), - // log EventTwoIndexedWithData(44,27,19) - // topic1: hash(EventTwoIndexedWithData) - // topic2: 44 - // topic3: 27 - // data: 19 - { - Sender: sender1, - Target: contract1, - Selector: EventMatrixContract.Fn["logEventTwoIndexedWithData"], - Data: packUint64Values(44, 27, 19), + expected: []ExpectedEthLog{ + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventZeroData"], + }, + Data: nil, + }, + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventThreeIndexed"], + paddedUint64(44), + paddedUint64(27), + paddedUint64(19), + }, + Data: nil, + }, + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexed"], + paddedUint64(44), + paddedUint64(19), + }, + Data: nil, + }, + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(50), + }, + Data: paddedUint64(9), + }, + }, }, - // log EventThreeIndexedWithData(44,27,19,12) - // topic1: hash(EventThreeIndexedWithData) - // topic2: 44 - // topic3: 27 - // topic4: 19 - // data: 12 { - Sender: sender1, - Target: contract1, - Selector: EventMatrixContract.Fn["logEventThreeIndexedWithData"], - Data: packUint64Values(44, 27, 19, 12), - }, + name: "find all events with topic2 of 44 from contract2", + spec: kit.NewEthFilterBuilder().FromBlock(fromBlock).AddressOneOf(contract2).Topic2OneOf(paddedEthHash(paddedUint64(44))).Filter(), - // log EventOneIndexedWithData(50,9) - // topic1: hash(EventOneIndexedWithData) - // topic2: 50 - // data: 9 - { - Sender: sender2, - Target: contract2, - Selector: EventMatrixContract.Fn["logEventOneIndexedWithData"], - Data: packUint64Values(50, 9), + expected: []ExpectedEthLog{ + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventThreeIndexed"], + paddedUint64(44), + paddedUint64(27), + paddedUint64(19), + }, + Data: nil, + }, + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventTwoIndexed"], + paddedUint64(44), + paddedUint64(19), + }, + Data: nil, + }, + }, }, - // log EventTwoIndexedWithData(46,27,19) - // topic1: hash(EventTwoIndexedWithData) - // topic2: 46 - // topic3: 27 - // data: 19 { - Sender: sender1, - Target: contract1, - Selector: EventMatrixContract.Fn["logEventTwoIndexedWithData"], - Data: packUint64Values(46, 27, 19), - }, + name: "find all EventOneIndexedWithData events from contract1 or contract2", + spec: kit.NewEthFilterBuilder(). + FromBlockEpoch(0). + AddressOneOf(contract1, contract2). + Topic1OneOf(paddedEthHash(kit.EventMatrixContract.Ev["EventOneIndexedWithData"])). + Filter(), - // log EventTwoIndexedWithData(46,14,19) - // topic1: hash(EventTwoIndexedWithData) - // topic2: 46 - // topic3: 14 - // data: 19 - { - Sender: sender1, - Target: contract1, - Selector: EventMatrixContract.Fn["logEventTwoIndexedWithData"], - Data: packUint64Values(46, 14, 19), - }, - // log EventTwoIndexed(44,19) from contract1 - // topic1: hash(EventTwoIndexed) - // topic2: 44 - // topic3: 19 - { - Sender: sender1, - Target: contract1, - Selector: EventMatrixContract.Fn["logEventTwoIndexed"], - Data: packUint64Values(40, 20), + expected: []ExpectedEthLog{ + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(44), + }, + Data: paddedUint64(19), + }, + { + Address: contract1, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(46), + }, + Data: paddedUint64(12), + }, + { + Address: contract2, + Topics: []ethtypes.EthBytes{ + kit.EventMatrixContract.Ev["EventOneIndexedWithData"], + paddedUint64(50), + }, + Data: paddedUint64(9), + }, + }, }, } +} - messages := invokeAndWaitUntilAllOnChain(t, client, invocations) - ethAddr1 := getContractEthAddress(ctx, t, client, contract1) - ethAddr2 := getContractEthAddress(ctx, t, client, contract2) - return ethAddr1, ethAddr2, messages +func getCombinationFilterTestCases(contract1, contract2 ethtypes.EthAddress, fromBlock string) []filterTestCase { + topicCases := getTopicFilterTestCases(contract1, contract2, fromBlock) + addressCases := getAddressFilterTestCases(contract1, contract2, fromBlock) + + return append(topicCases, addressCases...) } type ExpectedEthLog struct { @@ -1659,7 +1875,8 @@ type ExpectedEthLog struct { func AssertEthLogs(t *testing.T, actual []*ethtypes.EthLog, expected []ExpectedEthLog, messages map[ethtypes.EthHash]msgInTipset) { require := require.New(t) - // require.Equal(len(expected), len(actual), "number of results equal to expected") + + t.Logf("got %d ethlogs, wanted %d", len(actual), len(expected)) formatTopics := func(topics []ethtypes.EthBytes) string { ss := make([]string, len(topics)) @@ -1673,7 +1890,7 @@ func AssertEthLogs(t *testing.T, actual []*ethtypes.EthLog, expected []ExpectedE for _, elog := range actual { msg, exists := messages[elog.TransactionHash] - require.True(exists, "message seen on chain") + require.True(exists, "message not seen on chain") tsCid, err := msg.ts.Key().Cid() require.NoError(err) @@ -1929,18 +2146,6 @@ func paddedEthHash(orig []byte) ethtypes.EthHash { return ret } -func ethTopicHash(sig string) []byte { - hasher := sha3.NewLegacyKeccak256() - hasher.Write([]byte(sig)) - return hasher.Sum(nil) -} - -func ethFunctionHash(sig string) []byte { - hasher := sha3.NewLegacyKeccak256() - hasher.Write([]byte(sig)) - return hasher.Sum(nil)[:4] -} - func packUint64Values(vals ...uint64) []byte { ret := []byte{} for _, v := range vals { @@ -1963,78 +2168,6 @@ func unpackUint64Values(data []byte) []uint64 { return vals } -func newEthFilterBuilder() *ethFilterBuilder { return ðFilterBuilder{} } - -type ethFilterBuilder struct { - filter ethtypes.EthFilterSpec -} - -func (e *ethFilterBuilder) Filter() *ethtypes.EthFilterSpec { return &e.filter } - -func (e *ethFilterBuilder) FromBlock(v string) *ethFilterBuilder { - e.filter.FromBlock = &v - return e -} - -func (e *ethFilterBuilder) FromBlockEpoch(v abi.ChainEpoch) *ethFilterBuilder { - s := ethtypes.EthUint64(v).Hex() - e.filter.FromBlock = &s - return e -} - -func (e *ethFilterBuilder) ToBlock(v string) *ethFilterBuilder { - e.filter.ToBlock = &v - return e -} - -func (e *ethFilterBuilder) ToBlockEpoch(v abi.ChainEpoch) *ethFilterBuilder { - s := ethtypes.EthUint64(v).Hex() - e.filter.ToBlock = &s - return e -} - -func (e *ethFilterBuilder) BlockHash(h ethtypes.EthHash) *ethFilterBuilder { - e.filter.BlockHash = &h - return e -} - -func (e *ethFilterBuilder) AddressOneOf(as ...ethtypes.EthAddress) *ethFilterBuilder { - e.filter.Address = as - return e -} - -func (e *ethFilterBuilder) Topic1OneOf(hs ...ethtypes.EthHash) *ethFilterBuilder { - if len(e.filter.Topics) == 0 { - e.filter.Topics = make(ethtypes.EthTopicSpec, 1) - } - e.filter.Topics[0] = hs - return e -} - -func (e *ethFilterBuilder) Topic2OneOf(hs ...ethtypes.EthHash) *ethFilterBuilder { - for len(e.filter.Topics) < 2 { - e.filter.Topics = append(e.filter.Topics, nil) - } - e.filter.Topics[1] = hs - return e -} - -func (e *ethFilterBuilder) Topic3OneOf(hs ...ethtypes.EthHash) *ethFilterBuilder { - for len(e.filter.Topics) < 3 { - e.filter.Topics = append(e.filter.Topics, nil) - } - e.filter.Topics[2] = hs - return e -} - -func (e *ethFilterBuilder) Topic4OneOf(hs ...ethtypes.EthHash) *ethFilterBuilder { - for len(e.filter.Topics) < 4 { - e.filter.Topics = append(e.filter.Topics, nil) - } - e.filter.Topics[3] = hs - return e -} - func decodeLogBytes(orig []byte) []byte { if len(orig) == 0 { return orig diff --git a/itests/eth_transactions_test.go b/itests/eth_transactions_test.go index 0c8f1baa5e0..9afeb7bd5f9 100644 --- a/itests/eth_transactions_test.go +++ b/itests/eth_transactions_test.go @@ -83,6 +83,23 @@ func TestValueTransferValidSignature(t *testing.T) { // Success. require.EqualValues(t, ethtypes.EthUint64(0x1), receipt.Status) + + ethTx, err := client.EthGetTransactionByHash(ctx, &hash) + require.Nil(t, err) + require.EqualValues(t, ethAddr, ethTx.From) + require.EqualValues(t, ethAddr2, *ethTx.To) + require.EqualValues(t, tx.ChainID, ethTx.ChainID) + require.EqualValues(t, tx.Nonce, ethTx.Nonce) + require.EqualValues(t, hash, ethTx.Hash) + require.EqualValues(t, tx.Value, ethTx.Value) + require.EqualValues(t, 2, ethTx.Type) + require.EqualValues(t, ethtypes.EthBytes{}, ethTx.Input) + require.EqualValues(t, tx.GasLimit, ethTx.Gas) + require.EqualValues(t, tx.MaxFeePerGas, ethTx.MaxFeePerGas) + require.EqualValues(t, tx.MaxPriorityFeePerGas, ethTx.MaxPriorityFeePerGas) + require.EqualValues(t, tx.V, ethTx.V) + require.EqualValues(t, tx.R, ethTx.R) + require.EqualValues(t, tx.S, ethTx.S) } func TestLegacyTransaction(t *testing.T) { @@ -100,11 +117,9 @@ func TestLegacyTransaction(t *testing.T) { require.NoError(t, err) _, err = client.EVM().EthSendRawTransaction(ctx, txBytes) require.ErrorContains(t, err, "legacy transaction is not supported") - } func TestContractDeploymentValidSignature(t *testing.T) { - blockTime := 100 * time.Millisecond client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC()) @@ -253,7 +268,6 @@ func TestContractInvocation(t *testing.T) { // Success. require.EqualValues(t, ethtypes.EthUint64(0x1), receipt.Status) - } func deployContractTx(ctx context.Context, client *kit.TestFullNode, ethAddr ethtypes.EthAddress, contract []byte) (*ethtypes.EthTxArgs, error) { diff --git a/itests/fevm_address_test.go b/itests/fevm_address_test.go index a23e9686004..9eaac464773 100644 --- a/itests/fevm_address_test.go +++ b/itests/fevm_address_test.go @@ -6,7 +6,6 @@ import ( "encoding/hex" "os" "testing" - "time" "github.com/stretchr/testify/require" "golang.org/x/crypto/sha3" @@ -44,14 +43,43 @@ func effectiveEthAddressForCreate(t *testing.T, sender address.Address) ethtypes panic("unreachable") } -func TestAddressCreationBeforeDeploy(t *testing.T) { - kit.QuietMiningLogs() +func createAndDeploy(ctx context.Context, t *testing.T, client *kit.TestFullNode, fromAddr address.Address, contract []byte) *api.MsgLookup { + // Create and deploy evm actor + + method := builtintypes.MethodsEAM.CreateExternal + contractParams := abi.CborBytes(contract) + params, actorsErr := actors.SerializeParams(&contractParams) + require.NoError(t, actorsErr) + + createMsg := &types.Message{ + To: builtintypes.EthereumAddressManagerActorAddr, + From: fromAddr, + Value: big.Zero(), + Method: method, + Params: params, + } + smsg, err := client.MpoolPushMessage(ctx, createMsg, nil) + require.NoError(t, err) + + wait, err := client.StateWaitMsg(ctx, smsg.Cid(), 0, 0, false) + require.NoError(t, err) + require.Equal(t, exitcode.Ok, wait.Receipt.ExitCode) + return wait +} + +func getEthAddressTX(ctx context.Context, t *testing.T, client *kit.TestFullNode, wait *api.MsgLookup, ethAddr ethtypes.EthAddress) ethtypes.EthAddress { + // Check if eth address returned from CreateExternal is the same as eth address predicted at the start + var createExternalReturn eam.CreateExternalReturn + err := createExternalReturn.UnmarshalCBOR(bytes.NewReader(wait.Receipt.Return)) + require.NoError(t, err) - blockTime := 100 * time.Millisecond - client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC()) - ens.InterconnectAll().BeginMining(blockTime) + createdEthAddr, err := ethtypes.CastEthAddress(createExternalReturn.EthAddress[:]) + require.NoError(t, err) + return createdEthAddr +} - ctx, cancel := context.WithTimeout(context.Background(), time.Minute) +func TestAddressCreationBeforeDeploy(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) defer cancel() // install contract @@ -72,22 +100,11 @@ func TestAddressCreationBeforeDeploy(t *testing.T) { contractFilAddr, err := ethAddr.ToFilecoinAddress() require.NoError(t, err) - // Send contract address some funds - + //transfer half the wallet balance bal, err := client.WalletBalance(ctx, client.DefaultKey.Address) require.NoError(t, err) sendAmount := big.Div(bal, big.NewInt(2)) - - sendMsg := &types.Message{ - From: fromAddr, - To: contractFilAddr, - Value: sendAmount, - } - signedMsg, err := client.MpoolPushMessage(ctx, sendMsg, nil) - require.NoError(t, err) - mLookup, err := client.StateWaitMsg(ctx, signedMsg.Cid(), 3, api.LookbackNoLimit, true) - require.NoError(t, err) - require.Equal(t, exitcode.Ok, mLookup.Receipt.ExitCode) + client.EVM().TransferValueOrFail(ctx, fromAddr, contractFilAddr, sendAmount) // Check if actor at new address is a placeholder actor actor, err := client.StateGetActor(ctx, contractFilAddr, types.EmptyTSK) @@ -95,40 +112,69 @@ func TestAddressCreationBeforeDeploy(t *testing.T) { require.True(t, builtin.IsPlaceholderActor(actor.Code)) // Create and deploy evm actor + wait := createAndDeploy(ctx, t, client, fromAddr, contract) - method := builtintypes.MethodsEAM.CreateExternal - contractParams := abi.CborBytes(contract) - params, err := actors.SerializeParams(&contractParams) + // Check if eth address returned from CreateExternal is the same as eth address predicted at the start + createdEthAddr := getEthAddressTX(ctx, t, client, wait, ethAddr) + require.Equal(t, ethAddr, createdEthAddr) + + // Check if newly deployed actor still has funds + actorPostCreate, err := client.StateGetActor(ctx, contractFilAddr, types.EmptyTSK) require.NoError(t, err) + require.Equal(t, actorPostCreate.Balance, sendAmount) + require.True(t, builtin.IsEvmActor(actorPostCreate.Code)) - createMsg := &types.Message{ - To: builtintypes.EthereumAddressManagerActorAddr, - From: fromAddr, - Value: big.Zero(), - Method: method, - Params: params, - } - smsg, err := client.MpoolPushMessage(ctx, createMsg, nil) +} + +func TestDeployAddressMultipleTimes(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + // install contract + contractHex, err := os.ReadFile("contracts/SimpleCoin.hex") require.NoError(t, err) - wait, err := client.StateWaitMsg(ctx, smsg.Cid(), 0, 0, false) + contract, err := hex.DecodeString(string(contractHex)) require.NoError(t, err) - require.Equal(t, exitcode.Ok, wait.Receipt.ExitCode) - // Check if eth address returned from CreateExternal is the same as eth address predicted at the start - var createExternalReturn eam.CreateExternalReturn - err = createExternalReturn.UnmarshalCBOR(bytes.NewReader(wait.Receipt.Return)) + fromAddr, err := client.WalletDefaultAddress(ctx) require.NoError(t, err) - createdEthAddr, err := ethtypes.CastEthAddress(createExternalReturn.EthAddress[:]) + // We hash the f1/f3 address into the EVM's address space when deploying contracts from + // accounts. + effectiveEvmAddress := effectiveEthAddressForCreate(t, fromAddr) + ethAddr := client.EVM().ComputeContractAddress(effectiveEvmAddress, 1) + + contractFilAddr, err := ethAddr.ToFilecoinAddress() + require.NoError(t, err) + + // Send contract address small funds to init + sendAmount := big.NewInt(2) + client.EVM().TransferValueOrFail(ctx, fromAddr, contractFilAddr, sendAmount) + + // Check if actor at new address is a placeholder actor + actor, err := client.StateGetActor(ctx, contractFilAddr, types.EmptyTSK) require.NoError(t, err) + require.True(t, builtin.IsPlaceholderActor(actor.Code)) + + // Create and deploy evm actor + wait := createAndDeploy(ctx, t, client, fromAddr, contract) + + // Check if eth address returned from CreateExternal is the same as eth address predicted at the start + createdEthAddr := getEthAddressTX(ctx, t, client, wait, ethAddr) require.Equal(t, ethAddr, createdEthAddr) // Check if newly deployed actor still has funds actorPostCreate, err := client.StateGetActor(ctx, contractFilAddr, types.EmptyTSK) require.NoError(t, err) - require.Equal(t, actorPostCreate.Balance, sendAmount) require.True(t, builtin.IsEvmActor(actorPostCreate.Code)) + // Create and deploy evm actor + wait = createAndDeploy(ctx, t, client, fromAddr, contract) + + // Check that this time eth address returned from CreateExternal is not the same as eth address predicted at the start + createdEthAddr = getEthAddressTX(ctx, t, client, wait, ethAddr) + require.NotEqual(t, ethAddr, createdEthAddr) + } diff --git a/itests/fevm_events_test.go b/itests/fevm_events_test.go index 079a7a699b4..458ac3470ab 100644 --- a/itests/fevm_events_test.go +++ b/itests/fevm_events_test.go @@ -64,20 +64,23 @@ func TestFEVMEvents(t *testing.T) { require.Empty(res.Results) // log a zero topic event with data - ret := client.EVM().InvokeSolidity(ctx, fromAddr, idAddr, []byte{0x00, 0x00, 0x00, 0x00}, nil) + ret, err := client.EVM().InvokeSolidity(ctx, fromAddr, idAddr, []byte{0x00, 0x00, 0x00, 0x00}, nil) + require.NoError(err) require.True(ret.Receipt.ExitCode.IsSuccess(), "contract execution failed") require.NotNil(ret.Receipt.EventsRoot) fmt.Println(ret) fmt.Printf("Events:\n %+v\n", client.EVM().LoadEvents(ctx, *ret.Receipt.EventsRoot)) // log a zero topic event with no data - ret = client.EVM().InvokeSolidity(ctx, fromAddr, idAddr, []byte{0x00, 0x00, 0x00, 0x01}, nil) + ret, err = client.EVM().InvokeSolidity(ctx, fromAddr, idAddr, []byte{0x00, 0x00, 0x00, 0x01}, nil) + require.NoError(err) require.True(ret.Receipt.ExitCode.IsSuccess(), "contract execution failed") fmt.Println(ret) fmt.Printf("Events:\n %+v\n", client.EVM().LoadEvents(ctx, *ret.Receipt.EventsRoot)) // log a four topic event with data - ret = client.EVM().InvokeSolidity(ctx, fromAddr, idAddr, []byte{0x00, 0x00, 0x00, 0x02}, nil) + ret, err = client.EVM().InvokeSolidity(ctx, fromAddr, idAddr, []byte{0x00, 0x00, 0x00, 0x02}, nil) + require.NoError(err) require.True(ret.Receipt.ExitCode.IsSuccess(), "contract execution failed") fmt.Println(ret) fmt.Printf("Events:\n %+v\n", client.EVM().LoadEvents(ctx, *ret.Receipt.EventsRoot)) diff --git a/itests/fevm_test.go b/itests/fevm_test.go index e05b0e2ccb1..68a653ca0ba 100644 --- a/itests/fevm_test.go +++ b/itests/fevm_test.go @@ -1,17 +1,22 @@ package itests import ( + "bytes" "context" + "encoding/binary" "encoding/hex" + "fmt" "testing" - "time" "github.com/stretchr/testify/require" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/big" builtintypes "github.com/filecoin-project/go-state-types/builtin" + "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/go-state-types/manifest" + "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/itests/kit" @@ -36,19 +41,141 @@ func inputDataFromFrom(ctx context.Context, t *testing.T, client *kit.TestFullNo return inputData } -func setupFEVMTest(t *testing.T) (context.Context, context.CancelFunc, *kit.TestFullNode) { - kit.QuietMiningLogs() - 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) - return ctx, cancel, client +func decodeOutputToUint64(output []byte) (uint64, error) { + var result uint64 + buf := bytes.NewReader(output[len(output)-8:]) + err := binary.Read(buf, binary.BigEndian, &result) + return result, err +} +func buildInputFromuint64(number uint64) []byte { + // Convert the number to a binary uint64 array + binaryNumber := make([]byte, 8) + binary.BigEndian.PutUint64(binaryNumber, number) + return inputDataFromArray(binaryNumber) +} + +// recursive delegate calls that fail due to gas limits are currently getting to 229 iterations +// before running out of gas +func recursiveDelegatecallFail(ctx context.Context, t *testing.T, client *kit.TestFullNode, filename string, count uint64) { + expectedIterationsBeforeFailing := int(228) + fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, filename) + t.Log("recursion count - ", count) + inputData := buildInputFromuint64(count) + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "recursiveCall(uint256)", inputData) + + require.NoError(t, err) + + result, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "totalCalls()", []byte{}) + require.NoError(t, err) + + resultUint, err := decodeOutputToUint64(result) + require.NoError(t, err) + + require.NotEqual(t, int(resultUint), int(count)) + require.Equal(t, expectedIterationsBeforeFailing, int(resultUint)) +} +func recursiveDelegatecallSuccess(ctx context.Context, t *testing.T, client *kit.TestFullNode, filename string, count uint64) { + t.Log("Count - ", count) + + fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, filename) + inputData := buildInputFromuint64(count) + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "recursiveCall(uint256)", inputData) + require.NoError(t, err) + + result, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "totalCalls()", []byte{}) + require.NoError(t, err) + + resultUint, err := decodeOutputToUint64(result) + require.NoError(t, err) + + require.Equal(t, int(count), int(resultUint)) +} + +// TestFEVMRecursive does a basic fevm contract installation and invocation +func TestFEVMRecursive(t *testing.T) { + callCounts := []uint64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 230, 330} + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + filename := "contracts/Recursive.hex" + fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, filename) + + // Successful calls + for _, callCount := range callCounts { + callCount := callCount // linter unhappy unless callCount is local to loop + t.Run(fmt.Sprintf("TestFEVMRecursive%d", callCount), func(t *testing.T) { + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "recursiveCall(uint256)", buildInputFromuint64(callCount)) + require.NoError(t, err) + }) + } + +} + +func TestFEVMRecursiveFail(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + filename := "contracts/Recursive.hex" + fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, filename) + + // Unsuccessful calls + failCallCounts := []uint64{340, 400, 600, 850, 1000} + for _, failCallCount := range failCallCounts { + failCallCount := failCallCount // linter unhappy unless callCount is local to loop + t.Run(fmt.Sprintf("TestFEVMRecursiveFail%d", failCallCount), func(t *testing.T) { + _, wait, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "recursiveCall(uint256)", buildInputFromuint64(failCallCount)) + require.Error(t, err) + require.Equal(t, exitcode.ExitCode(37), wait.Receipt.ExitCode) + }) + } +} + +func TestFEVMRecursive1(t *testing.T) { + callCount := 1 + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + filename := "contracts/Recursive.hex" + fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, filename) + _, ret, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "recursive1()", []byte{}) + require.NoError(t, err) + events := client.EVM().LoadEvents(ctx, *ret.Receipt.EventsRoot) + require.Equal(t, callCount, len(events)) +} +func TestFEVMRecursive2(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + filename := "contracts/Recursive.hex" + fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, filename) + _, ret, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "recursive2()", []byte{}) + require.NoError(t, err) + events := client.EVM().LoadEvents(ctx, *ret.Receipt.EventsRoot) + require.Equal(t, 2, len(events)) +} + +// TestFEVMRecursiveDelegatecallCount tests the maximum delegatecall recursion depth. It currently +// succeeds succeeds up to 237 times. +func TestFEVMRecursiveDelegatecallCount(t *testing.T) { + + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + highestSuccessCount := uint64(237) + + filename := "contracts/RecursiveDelegeatecall.hex" + recursiveDelegatecallSuccess(ctx, t, client, filename, uint64(1)) + recursiveDelegatecallSuccess(ctx, t, client, filename, uint64(2)) + recursiveDelegatecallSuccess(ctx, t, client, filename, uint64(10)) + recursiveDelegatecallSuccess(ctx, t, client, filename, uint64(100)) + recursiveDelegatecallSuccess(ctx, t, client, filename, highestSuccessCount) + + recursiveDelegatecallFail(ctx, t, client, filename, highestSuccessCount+1) + recursiveDelegatecallFail(ctx, t, client, filename, uint64(1000)) + recursiveDelegatecallFail(ctx, t, client, filename, uint64(10000000)) + } // TestFEVMBasic does a basic fevm contract installation and invocation func TestFEVMBasic(t *testing.T) { - ctx, cancel, client := setupFEVMTest(t) + ctx, cancel, client := kit.SetupFEVMTest(t) defer cancel() filename := "contracts/SimpleCoin.hex" @@ -58,7 +185,8 @@ func TestFEVMBasic(t *testing.T) { // invoke the contract with owner { inputData := inputDataFromFrom(ctx, t, client, fromAddr) - result := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "getBalance(address)", inputData) + result, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "getBalance(address)", inputData) + require.NoError(t, err) expectedResult, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000002710") require.NoError(t, err) @@ -68,8 +196,9 @@ func TestFEVMBasic(t *testing.T) { // invoke the contract with non owner { inputData := inputDataFromFrom(ctx, t, client, fromAddr) - inputData[31]++ // change the pub address to one that has 0 balance by incrementing the last byte of the address - result := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "getBalance(address)", inputData) + inputData[31]++ // change the pub address to one that has 0 balance by modifying the last byte of the address + result, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "getBalance(address)", inputData) + require.NoError(t, err) expectedResult, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000000") require.NoError(t, err) @@ -79,7 +208,7 @@ func TestFEVMBasic(t *testing.T) { // TestFEVMETH0 tests that the ETH0 actor is in genesis func TestFEVMETH0(t *testing.T) { - ctx, cancel, client := setupFEVMTest(t) + ctx, cancel, client := kit.SetupFEVMTest(t) defer cancel() eth0id, err := address.NewIDAddress(1001) @@ -98,7 +227,7 @@ func TestFEVMETH0(t *testing.T) { // TestFEVMDelegateCall deploys two contracts and makes a delegate call transaction func TestFEVMDelegateCall(t *testing.T) { - ctx, cancel, client := setupFEVMTest(t) + ctx, cancel, client := kit.SetupFEVMTest(t) defer cancel() //install contract Actor @@ -111,31 +240,467 @@ func TestFEVMDelegateCall(t *testing.T) { //call Contract Storage which makes a delegatecall to contract Actor //this contract call sets the "counter" variable to 7, from default value 0 - inputDataContract := inputDataFromFrom(ctx, t, client, actorAddr) inputDataValue := inputDataFromArray([]byte{7}) inputData := append(inputDataContract, inputDataValue...) //verify that the returned value of the call to setvars is 7 - result := client.EVM().InvokeContractByFuncName(ctx, fromAddr, storageAddr, "setVars(address,uint256)", inputData) + result, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, storageAddr, "setVars(address,uint256)", inputData) + require.NoError(t, err) expectedResult, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000007") require.NoError(t, err) require.Equal(t, result, expectedResult) - //test the value is 7 via calling the getter - result = client.EVM().InvokeContractByFuncName(ctx, fromAddr, storageAddr, "getCounter()", []byte{}) + //test the value is 7 a second way by calling the getter + result, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, storageAddr, "getCounter()", []byte{}) + require.NoError(t, err) require.Equal(t, result, expectedResult) //test the value is 0 via calling the getter on the Actor contract - result = client.EVM().InvokeContractByFuncName(ctx, fromAddr, actorAddr, "getCounter()", []byte{}) + result, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, actorAddr, "getCounter()", []byte{}) + require.NoError(t, err) expectedResultActor, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000000") require.NoError(t, err) require.Equal(t, result, expectedResultActor) } +// TestFEVMDelegateCallRevert makes a delegatecall action and then calls revert. +// the state should not have changed because of the revert +func TestFEVMDelegateCallRevert(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameActor := "contracts/DelegatecallActor.hex" + fromAddr, actorAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + //install contract Storage + filenameStorage := "contracts/DelegatecallStorage.hex" + fromAddrStorage, storageAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + require.Equal(t, fromAddr, fromAddrStorage) + + //call Contract Storage which makes a delegatecall to contract Actor + //this contract call sets the "counter" variable to 7, from default value 0 + + inputDataContract := inputDataFromFrom(ctx, t, client, actorAddr) + inputDataValue := inputDataFromArray([]byte{7}) + inputData := append(inputDataContract, inputDataValue...) + + //verify that the returned value of the call to setvars is 7 + _, wait, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, storageAddr, "setVarsRevert(address,uint256)", inputData) + require.Error(t, err) + require.Equal(t, exitcode.ExitCode(33), wait.Receipt.ExitCode) + + //test the value is 0 via calling the getter and was not set to 7 + expectedResult, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + result, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, storageAddr, "getCounter()", []byte{}) + require.NoError(t, err) + require.Equal(t, result, expectedResult) + + //test the value is 0 via calling the getter on the Actor contract + result, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, actorAddr, "getCounter()", []byte{}) + require.NoError(t, err) + require.Equal(t, result, expectedResult) +} + +// TestFEVMSimpleRevert makes a call that is a simple revert +func TestFEVMSimpleRevert(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameStorage := "contracts/DelegatecallStorage.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + + //call revert + _, wait, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "revert()", []byte{}) + + require.Equal(t, wait.Receipt.ExitCode, exitcode.ExitCode(33)) + require.Error(t, err) +} + +// TestFEVMSelfDestruct creates a contract that just has a self destruct feature and calls it +func TestFEVMSelfDestruct(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameStorage := "contracts/SelfDestruct.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + + //call destroy + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "destroy()", []byte{}) + require.NoError(t, err) + + //call destroy a second time and also no error + _, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "destroy()", []byte{}) + require.NoError(t, err) +} + +// TestFEVMTestApp deploys a fairly complex app contract and confirms it works as expected +func TestFEVMTestApp(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameStorage := "contracts/TestApp.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + + inputData, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000066162636465660000000000000000000000000000000000000000000000000000") // sending string "abcdef" and int 7 - constructed using remix + require.NoError(t, err) + _, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "new_Test(string,uint256)", inputData) + require.NoError(t, err) + + inputData, err = hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + + _, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "get_Test_N(uint256)", inputData) + require.NoError(t, err) + +} + +// TestFEVMTestApp creates a contract that just has a self destruct feature and calls it +func TestFEVMTestConstructor(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameStorage := "contracts/Constructor.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + + //input = uint256{7}. set value and confirm tx success + inputData, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000007") + require.NoError(t, err) + _, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "new_Test(uint256)", inputData) + require.NoError(t, err) + +} + +// TestFEVMAutoSelfDestruct creates a contract that just has a self destruct feature and calls it +func TestFEVMAutoSelfDestruct(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameStorage := "contracts/AutoSelfDestruct.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + + //call destroy + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "destroy()", []byte{}) + require.NoError(t, err) +} + +// TestFEVMTestApp creates a contract that just has a self destruct feature and calls it +func TestFEVMTestSendToContract(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + bal, err := client.WalletBalance(ctx, client.DefaultKey.Address) + require.NoError(t, err) + + //install contract TestApp + filenameStorage := "contracts/SelfDestruct.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + + //transfer half balance to contract + + sendAmount := big.Div(bal, big.NewInt(2)) + client.EVM().TransferValueOrFail(ctx, fromAddr, contractAddr, sendAmount) + + //call self destruct which should return balance + _, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "destroy()", []byte{}) + require.NoError(t, err) + + finalBalanceMinimum := types.FromFil(uint64(99_999_999)) // 100 million FIL - 1 FIL for gas upper bounds + finalBal, err := client.WalletBalance(ctx, client.DefaultKey.Address) + require.NoError(t, err) + require.Equal(t, true, finalBal.GreaterThan(finalBalanceMinimum)) +} + +// creates a contract that would fail when tx are sent to it +// on eth but on fevm it succeeds +// example failing on testnet https://goerli.etherscan.io/address/0x2ff1525e060169dbf97b9461758c8f701f107cd2 +func TestFEVMTestNotPayable(t *testing.T) { + + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + fromAddr := client.DefaultKey.Address + t.Log("from - ", fromAddr) + + //create contract A + filenameStorage := "contracts/NotPayable.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + sendAmount := big.NewInt(10_000_000) + + client.EVM().TransferValueOrFail(ctx, fromAddr, contractAddr, sendAmount) + +} + +// tx to non function succeeds +func TestFEVMSendCall(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract + filenameActor := "contracts/GasSendTest.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "x()", []byte{}) + require.NoError(t, err) +} + +// creates a contract that would fail when tx are sent to it +// on eth but on fevm it succeeds +// example on goerli of tx failing https://goerli.etherscan.io/address/0xec037bdc9a79420985a53a49fdae3ccf8989909b +func TestFEVMSendGasLimit(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract + filenameActor := "contracts/GasLimitSend.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + + //send $ to contract + //transfer 1 attoFIL to contract + sendAmount := big.MustFromString("1") + + client.EVM().TransferValueOrFail(ctx, fromAddr, contractAddr, sendAmount) + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "getDataLength()", []byte{}) + require.NoError(t, err) + +} + +// TestFEVMDelegateCall deploys the two contracts in TestFEVMDelegateCall but instead of A calling B, A calls A which should cause A to cause A in an infinite loop and should give a reasonable error +func TestFEVMDelegateCallRecursiveFail(t *testing.T) { + //TODO change the gas limit of this invocation and confirm that the number of errors is + // different + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameActor := "contracts/DelegatecallStorage.hex" + fromAddr, actorAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + + //any data will do for this test that fails + inputDataContract := inputDataFromFrom(ctx, t, client, actorAddr) + inputDataValue := inputDataFromArray([]byte{7}) + inputData := append(inputDataContract, inputDataValue...) + + //verify that we run out of gas then revert. + _, wait, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, actorAddr, "setVarsSelf(address,uint256)", inputData) + require.Error(t, err) + require.Equal(t, exitcode.ExitCode(33), wait.Receipt.ExitCode) + + //assert no fatal errors but still there are errors:: + errorAny := "fatal error" + require.NotContains(t, err.Error(), errorAny) +} + +// TestFEVMTestSendValueThroughContracts creates A and B contract and exchanges value +// and self destructs and accounts for value sent +func TestFEVMTestSendValueThroughContractsAndDestroy(t *testing.T) { + + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + fromAddr := client.DefaultKey.Address + t.Log("from - ", fromAddr) + + //create contract A + filenameStorage := "contracts/ValueSender.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + + //create contract B + ret, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "createB()", []byte{}) + require.NoError(t, err) + + ethAddr, err := ethtypes.CastEthAddress(ret[12:]) + require.NoError(t, err) + contractBAddress, err := ethAddr.ToFilecoinAddress() + require.NoError(t, err) + t.Log("contractBAddress - ", contractBAddress) + + //self destruct contract B + _, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractBAddress, "selfDestruct()", []byte{}) + require.NoError(t, err) + +} + func TestEVMRpcDisable(t *testing.T) { client, _, _ := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC(), kit.DisableEthRPC()) _, err := client.EthBlockNumber(context.Background()) require.ErrorContains(t, err, "module disabled, enable with Fevm.EnableEthRPC") } + +// TestFEVMRecursiveFuncCall deploys a contract and makes a recursive function calls +func TestFEVMRecursiveFuncCall(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameActor := "contracts/StackFunc.hex" + fromAddr, actorAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + + testN := func(n int, ex exitcode.ExitCode) func(t *testing.T) { + return func(t *testing.T) { + inputData := make([]byte, 32) + binary.BigEndian.PutUint64(inputData[24:], uint64(n)) + client.EVM().InvokeContractByFuncNameExpectExit(ctx, fromAddr, actorAddr, "exec1(uint256)", inputData, ex) + } + } + + t.Run("n=0", testN(0, exitcode.Ok)) + t.Run("n=1", testN(1, exitcode.Ok)) + t.Run("n=20", testN(20, exitcode.Ok)) + t.Run("n=200", testN(200, exitcode.Ok)) + t.Run("n=507", testN(507, exitcode.Ok)) + t.Run("n=508", testN(508, exitcode.ExitCode(37))) // 37 means stack overflow +} + +// TestFEVMRecursiveActorCall deploys a contract and makes a recursive actor calls +func TestFEVMRecursiveActorCall(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameActor := "contracts/RecCall.hex" + fromAddr, actorAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + + testN := func(n, r int, ex exitcode.ExitCode) func(t *testing.T) { + return func(t *testing.T) { + inputData := make([]byte, 32*3) + binary.BigEndian.PutUint64(inputData[24:], uint64(n)) + binary.BigEndian.PutUint64(inputData[32+24:], uint64(n)) + binary.BigEndian.PutUint64(inputData[32+32+24:], uint64(r)) + + client.EVM().InvokeContractByFuncNameExpectExit(ctx, fromAddr, actorAddr, "exec1(uint256,uint256,uint256)", inputData, ex) + } + } + + t.Run("n=0,r=1", testN(0, 1, exitcode.Ok)) + t.Run("n=1,r=1", testN(1, 1, exitcode.Ok)) + t.Run("n=20,r=1", testN(20, 1, exitcode.Ok)) + t.Run("n=200,r=1", testN(200, 1, exitcode.Ok)) + t.Run("n=251,r=1", testN(251, 1, exitcode.Ok)) + + t.Run("n=252,r=1-fails", testN(252, 1, exitcode.ExitCode(37))) // 37 means stack overflow + + t.Run("n=0,r=10", testN(0, 10, exitcode.Ok)) + t.Run("n=1,r=10", testN(1, 10, exitcode.Ok)) + t.Run("n=20,r=10", testN(20, 10, exitcode.Ok)) + t.Run("n=200,r=10", testN(200, 10, exitcode.Ok)) + t.Run("n=251,r=10", testN(251, 10, exitcode.Ok)) + + t.Run("n=252,r=10-fails", testN(252, 10, exitcode.ExitCode(37))) + + t.Run("n=0,r=32", testN(0, 32, exitcode.Ok)) + t.Run("n=1,r=32", testN(1, 32, exitcode.Ok)) + t.Run("n=20,r=32", testN(20, 32, exitcode.Ok)) + t.Run("n=200,r=32", testN(200, 32, exitcode.Ok)) + t.Run("n=251,r=32", testN(251, 32, exitcode.Ok)) + + t.Run("n=0,r=254", testN(0, 254, exitcode.Ok)) + t.Run("n=251,r=166", testN(251, 166, exitcode.Ok)) + + t.Run("n=0,r=256-fails", testN(0, 256, exitcode.ExitCode(33))) // 33 means transaction reverted + t.Run("n=251,r=167-fails", testN(251, 167, exitcode.ExitCode(33))) +} + +// TestFEVMRecursiveActorCallEstimate +func TestFEVMRecursiveActorCallEstimate(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameActor := "contracts/ExternalRecursiveCallSimple.hex" + _, actorAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + + contractAddr, err := ethtypes.EthAddressFromFilecoinAddress(actorAddr) + require.NoError(t, err) + + // create a new Ethereum account + key, ethAddr, ethFilAddr := client.EVM().NewAccount() + kit.SendFunds(ctx, t, client, ethFilAddr, types.FromFil(1000)) + + makeParams := func(r int) []byte { + funcSignature := "exec1(uint256)" + entryPoint := kit.CalcFuncSignature(funcSignature) + + inputData := make([]byte, 32) + binary.BigEndian.PutUint64(inputData[24:], uint64(r)) + + params := append(entryPoint, inputData...) + + return params + } + + testN := func(r int) func(t *testing.T) { + return func(t *testing.T) { + t.Logf("running with %d recursive calls", r) + + params := makeParams(r) + gaslimit, err := client.EthEstimateGas(ctx, ethtypes.EthCall{ + From: ðAddr, + To: &contractAddr, + Data: params, + }) + require.NoError(t, err) + require.LessOrEqual(t, int64(gaslimit), build.BlockGasLimit) + + t.Logf("EthEstimateGas GasLimit=%d", gaslimit) + + maxPriorityFeePerGas, err := client.EthMaxPriorityFeePerGas(ctx) + require.NoError(t, err) + + nonce, err := client.MpoolGetNonce(ctx, ethFilAddr) + require.NoError(t, err) + + tx := ðtypes.EthTxArgs{ + ChainID: build.Eip155ChainId, + To: &contractAddr, + Value: big.Zero(), + Nonce: int(nonce), + MaxFeePerGas: types.NanoFil, + MaxPriorityFeePerGas: big.Int(maxPriorityFeePerGas), + GasLimit: int(gaslimit), + Input: params, + V: big.Zero(), + R: big.Zero(), + S: big.Zero(), + } + + client.EVM().SignTransaction(tx, key.PrivateKey) + hash := client.EVM().SubmitTransaction(ctx, tx) + + smsg, err := tx.ToSignedMessage() + require.NoError(t, err) + + _, err = client.StateWaitMsg(ctx, smsg.Cid(), 0, 0, false) + require.NoError(t, err) + + receipt, err := client.EthGetTransactionReceipt(ctx, hash) + require.NoError(t, err) + require.NotNil(t, receipt) + + t.Logf("Receipt GasUsed=%d", receipt.GasUsed) + t.Logf("Ratio %0.2f", float64(receipt.GasUsed)/float64(gaslimit)) + t.Logf("Overestimate %0.2f", ((float64(gaslimit)/float64(receipt.GasUsed))-1)*100) + + require.EqualValues(t, ethtypes.EthUint64(1), receipt.Status) + } + } + + t.Run("n=1", testN(1)) + t.Run("n=2", testN(2)) + t.Run("n=3", testN(3)) + t.Run("n=4", testN(4)) + t.Run("n=5", testN(5)) + t.Run("n=10", testN(10)) + t.Run("n=20", testN(20)) + t.Run("n=30", testN(30)) + t.Run("n=40", testN(40)) + t.Run("n=50", testN(50)) + t.Run("n=100", testN(100)) +} diff --git a/itests/gateway_test.go b/itests/gateway_test.go index b9c861bf303..d20b3bd1a09 100644 --- a/itests/gateway_test.go +++ b/itests/gateway_test.go @@ -290,7 +290,7 @@ func startNodes( ens.InterconnectAll().BeginMining(blocktime) // Create a gateway server in front of the full node - gwapi := gateway.NewNode(full, lookbackCap, stateWaitLookbackLimit, 0, time.Minute) + gwapi := gateway.NewNode(full, nil, lookbackCap, stateWaitLookbackLimit, 0, time.Minute) handler, err := gateway.Handler(gwapi, full, 0, 0) require.NoError(t, err) diff --git a/itests/kit/ensemble.go b/itests/kit/ensemble.go index 8b92202dc38..6d4ca1c129d 100644 --- a/itests/kit/ensemble.go +++ b/itests/kit/ensemble.go @@ -47,6 +47,7 @@ import ( "github.com/filecoin-project/lotus/chain/wallet/key" "github.com/filecoin-project/lotus/cmd/lotus-seed/seed" "github.com/filecoin-project/lotus/cmd/lotus-worker/sealworker" + "github.com/filecoin-project/lotus/gateway" "github.com/filecoin-project/lotus/genesis" "github.com/filecoin-project/lotus/markets/idxprov" "github.com/filecoin-project/lotus/markets/idxprov/idxprov_test" @@ -210,7 +211,7 @@ func (n *Ensemble) FullNode(full *TestFullNode, opts ...NodeOpt) *Ensemble { n.genesis.accounts = append(n.genesis.accounts, genacc) } - *full = TestFullNode{t: n.t, options: options, DefaultKey: key} + *full = TestFullNode{t: n.t, options: options, DefaultKey: key, EthSubRouter: gateway.NewEthSubHandler()} n.inactive.fullnodes = append(n.inactive.fullnodes, full) return n diff --git a/itests/kit/evm.go b/itests/kit/evm.go index 46aaf52dbe9..eac8f02343b 100644 --- a/itests/kit/evm.go +++ b/itests/kit/evm.go @@ -5,10 +5,14 @@ import ( "context" "encoding/binary" "encoding/hex" + "errors" "fmt" "os" + "testing" + "time" "github.com/ipfs/go-cid" + logging "github.com/ipfs/go-log/v2" "github.com/multiformats/go-varint" "github.com/stretchr/testify/require" cbg "github.com/whyrusleeping/cbor-gen" @@ -21,8 +25,10 @@ import ( builtintypes "github.com/filecoin-project/go-state-types/builtin" "github.com/filecoin-project/go-state-types/builtin/v10/eam" "github.com/filecoin-project/go-state-types/crypto" + "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types/ethtypes" @@ -38,16 +44,9 @@ func (f *TestFullNode) EVM() *EVM { } func (e *EVM) DeployContract(ctx context.Context, sender address.Address, bytecode []byte) eam.CreateReturn { + var err error require := require.New(e.t) - nonce, err := e.MpoolGetNonce(ctx, sender) - if err != nil { - nonce = 0 // assume a zero nonce on error (e.g. sender doesn't exist). - } - - var salt [32]byte - binary.BigEndian.PutUint64(salt[:], nonce) - method := builtintypes.MethodsEAM.CreateExternal initcode := abi.CborBytes(bytecode) params, err := actors.SerializeParams(&initcode) @@ -99,32 +98,41 @@ func (e *EVM) DeployContractFromFilename(ctx context.Context, binFilename string return fromAddr, idAddr } -func (e *EVM) InvokeSolidity(ctx context.Context, sender address.Address, target address.Address, selector []byte, inputData []byte) *api.MsgLookup { - require := require.New(e.t) - +func (e *EVM) InvokeSolidity(ctx context.Context, sender address.Address, target address.Address, selector []byte, inputData []byte) (*api.MsgLookup, error) { params := append(selector, inputData...) var buffer bytes.Buffer err := cbg.WriteByteArray(&buffer, params) - require.NoError(err) + if err != nil { + return nil, err + } params = buffer.Bytes() msg := &types.Message{ - To: target, - From: sender, - Value: big.Zero(), - Method: builtintypes.MethodsEVM.InvokeContract, - Params: params, + To: target, + From: sender, + Value: big.Zero(), + Method: builtintypes.MethodsEVM.InvokeContract, + GasLimit: build.BlockGasLimit, // note: we hardcode block gas limit due to slightly broken gas estimation - https://github.com/filecoin-project/lotus/issues/10041 + Params: params, } e.t.Log("sending invoke message") smsg, err := e.MpoolPushMessage(ctx, msg, nil) - require.NoError(err) + if err != nil { + return nil, err + } e.t.Log("waiting for message to execute") wait, err := e.StateWaitMsg(ctx, smsg.Cid(), 0, 0, false) - require.NoError(err) - - return wait + if err != nil { + return nil, err + } + if !wait.Receipt.ExitCode.IsSuccess() { + result, err := e.StateReplay(ctx, types.EmptyTSK, wait.Message) + require.NoError(e.t, err) + e.t.Log(result.Error) + } + return wait, nil } // LoadEvents loads all events in an event AMT. @@ -234,13 +242,28 @@ func (e *EVM) ComputeContractAddress(deployer ethtypes.EthAddress, nonce uint64) return *(*ethtypes.EthAddress)(hasher.Sum(nil)[12:]) } -func (e *EVM) InvokeContractByFuncName(ctx context.Context, fromAddr address.Address, idAddr address.Address, funcSignature string, inputData []byte) []byte { +func (e *EVM) InvokeContractByFuncName(ctx context.Context, fromAddr address.Address, idAddr address.Address, funcSignature string, inputData []byte) ([]byte, *api.MsgLookup, error) { entryPoint := CalcFuncSignature(funcSignature) - wait := e.InvokeSolidity(ctx, fromAddr, idAddr, entryPoint, inputData) - require.True(e.t, wait.Receipt.ExitCode.IsSuccess(), "contract execution failed") + wait, err := e.InvokeSolidity(ctx, fromAddr, idAddr, entryPoint, inputData) + if err != nil { + return nil, wait, err + } + if !wait.Receipt.ExitCode.IsSuccess() { + result, err := e.StateReplay(ctx, types.EmptyTSK, wait.Message) + require.NoError(e.t, err) + return nil, wait, errors.New(result.Error) + } result, err := cbg.ReadByteArray(bytes.NewBuffer(wait.Receipt.Return), uint64(len(wait.Receipt.Return))) - require.NoError(e.t, err) - return result + if err != nil { + return nil, wait, err + } + return result, wait, nil +} + +func (e *EVM) InvokeContractByFuncNameExpectExit(ctx context.Context, fromAddr address.Address, idAddr address.Address, funcSignature string, inputData []byte, exit exitcode.ExitCode) { + entryPoint := CalcFuncSignature(funcSignature) + wait, _ := e.InvokeSolidity(ctx, fromAddr, idAddr, entryPoint, inputData) + require.Equal(e.t, exit, wait.Receipt.ExitCode) } // function signatures are the first 4 bytes of the hash of the function name and types @@ -301,3 +324,114 @@ func removeLeadingZeros(data []byte) []byte { } return data[firstNonZeroIndex:] } + +func SetupFEVMTest(t *testing.T) (context.Context, context.CancelFunc, *TestFullNode) { + // make all logs extra quiet for fevm tests + lvl, err := logging.LevelFromString("error") + if err != nil { + panic(err) + } + logging.SetAllLoggers(lvl) + + blockTime := 100 * time.Millisecond + client, _, ens := EnsembleMinimal(t, MockProofs(), ThroughRPC()) + ens.InterconnectAll().BeginMining(blockTime) + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + + // require that the initial balance is 100 million FIL in setup + // this way other tests can count on this initial wallet balance + fromAddr := client.DefaultKey.Address + bal, err := client.WalletBalance(ctx, fromAddr) + require.NoError(t, err) + originalBalance := types.FromFil(uint64(100_000_000)) // 100 million FIL + require.Equal(t, originalBalance, bal) + + return ctx, cancel, client +} + +func (e *EVM) TransferValueOrFail(ctx context.Context, fromAddr address.Address, toAddr address.Address, sendAmount big.Int) { + sendMsg := &types.Message{ + From: fromAddr, + To: toAddr, + Value: sendAmount, + } + signedMsg, err := e.MpoolPushMessage(ctx, sendMsg, nil) + require.NoError(e.t, err) + mLookup, err := e.StateWaitMsg(ctx, signedMsg.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(e.t, err) + require.Equal(e.t, exitcode.Ok, mLookup.Receipt.ExitCode) +} + +func NewEthFilterBuilder() *EthFilterBuilder { + return &EthFilterBuilder{} +} + +type EthFilterBuilder struct { + filter ethtypes.EthFilterSpec +} + +func (e *EthFilterBuilder) Filter() *ethtypes.EthFilterSpec { return &e.filter } + +func (e *EthFilterBuilder) FromBlock(v string) *EthFilterBuilder { + e.filter.FromBlock = &v + return e +} + +func (e *EthFilterBuilder) FromBlockEpoch(v abi.ChainEpoch) *EthFilterBuilder { + s := ethtypes.EthUint64(v).Hex() + e.filter.FromBlock = &s + return e +} + +func (e *EthFilterBuilder) ToBlock(v string) *EthFilterBuilder { + e.filter.ToBlock = &v + return e +} + +func (e *EthFilterBuilder) ToBlockEpoch(v abi.ChainEpoch) *EthFilterBuilder { + s := ethtypes.EthUint64(v).Hex() + e.filter.ToBlock = &s + return e +} + +func (e *EthFilterBuilder) BlockHash(h ethtypes.EthHash) *EthFilterBuilder { + e.filter.BlockHash = &h + return e +} + +func (e *EthFilterBuilder) AddressOneOf(as ...ethtypes.EthAddress) *EthFilterBuilder { + e.filter.Address = as + return e +} + +func (e *EthFilterBuilder) Topic1OneOf(hs ...ethtypes.EthHash) *EthFilterBuilder { + if len(e.filter.Topics) == 0 { + e.filter.Topics = make(ethtypes.EthTopicSpec, 1) + } + e.filter.Topics[0] = hs + return e +} + +func (e *EthFilterBuilder) Topic2OneOf(hs ...ethtypes.EthHash) *EthFilterBuilder { + for len(e.filter.Topics) < 2 { + e.filter.Topics = append(e.filter.Topics, nil) + } + e.filter.Topics[1] = hs + return e +} + +func (e *EthFilterBuilder) Topic3OneOf(hs ...ethtypes.EthHash) *EthFilterBuilder { + for len(e.filter.Topics) < 3 { + e.filter.Topics = append(e.filter.Topics, nil) + } + e.filter.Topics[2] = hs + return e +} + +func (e *EthFilterBuilder) Topic4OneOf(hs ...ethtypes.EthHash) *EthFilterBuilder { + for len(e.filter.Topics) < 4 { + e.filter.Topics = append(e.filter.Topics, nil) + } + e.filter.Topics[3] = hs + return e +} diff --git a/itests/kit/node_full.go b/itests/kit/node_full.go index 4546f5a0301..3e80ed68869 100644 --- a/itests/kit/node_full.go +++ b/itests/kit/node_full.go @@ -1,6 +1,7 @@ package kit import ( + "bytes" "context" "fmt" "testing" @@ -10,15 +11,18 @@ import ( "github.com/libp2p/go-libp2p/core/peer" "github.com/multiformats/go-multiaddr" "github.com/stretchr/testify/require" + cbg "github.com/whyrusleeping/cbor-gen" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api/v1api" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/wallet/key" cliutil "github.com/filecoin-project/lotus/cli/util" + "github.com/filecoin-project/lotus/gateway" "github.com/filecoin-project/lotus/node" ) @@ -43,6 +47,10 @@ type TestFullNode struct { Stop node.StopFunc + // gateway handler makes it convenient to register callbalks per topic, so we + // also use it for tests + EthSubRouter *gateway.EthSubHandler + options nodeOpts } @@ -124,6 +132,50 @@ func (f *TestFullNode) AssignPrivKey(pkey *Libp2p) { f.Pkey = pkey } +type SendCall struct { + Method abi.MethodNum + Params []byte +} + +func (f *TestFullNode) MakeSendCall(m abi.MethodNum, params cbg.CBORMarshaler) SendCall { + var b bytes.Buffer + err := params.MarshalCBOR(&b) + require.NoError(f.t, err) + return SendCall{ + Method: m, + Params: b.Bytes(), + } +} + +func (f *TestFullNode) ExpectSend(ctx context.Context, from, to address.Address, value types.BigInt, errContains string, sc ...SendCall) *types.SignedMessage { + msg := &types.Message{From: from, To: to, Value: value} + + if len(sc) == 1 { + msg.Method = sc[0].Method + msg.Params = sc[0].Params + } + + _, err := f.GasEstimateMessageGas(ctx, msg, nil, types.EmptyTSK) + if errContains != "" { + require.ErrorContains(f.t, err, errContains) + return nil + } + require.NoError(f.t, err) + + if errContains == "" { + m, err := f.MpoolPushMessage(ctx, msg, nil) + require.NoError(f.t, err) + + r, err := f.StateWaitMsg(ctx, m.Cid(), 1, api.LookbackNoLimit, true) + require.NoError(f.t, err) + + require.Equal(f.t, exitcode.Ok, r.Receipt.ExitCode) + return m + } + + return nil +} + // ChainPredicate encapsulates a chain condition. type ChainPredicate func(set *types.TipSet) bool diff --git a/itests/kit/rpc.go b/itests/kit/rpc.go index f8c2c6e53bc..5d40ac3e96e 100644 --- a/itests/kit/rpc.go +++ b/itests/kit/rpc.go @@ -13,6 +13,8 @@ import ( manet "github.com/multiformats/go-multiaddr/net" "github.com/stretchr/testify/require" + "github.com/filecoin-project/go-jsonrpc" + "github.com/filecoin-project/lotus/api/client" "github.com/filecoin-project/lotus/cmd/lotus-worker/sealworker" "github.com/filecoin-project/lotus/node" @@ -52,7 +54,12 @@ func fullRpc(t *testing.T, f *TestFullNode) (*TestFullNode, Closer) { fmt.Printf("FULLNODE RPC ENV FOR CLI DEBUGGING `export FULLNODE_API_INFO=%s`\n", "ws://"+srv.Listener.Addr().String()) sendItestdNotif("FULLNODE_API_INFO", t.Name(), "ws://"+srv.Listener.Addr().String()) - cl, stop, err := client.NewFullNodeRPCV1(context.Background(), "ws://"+srv.Listener.Addr().String()+"/rpc/v1", nil) + rpcOpts := []jsonrpc.Option{ + jsonrpc.WithClientHandler("Filecoin", f.EthSubRouter), + jsonrpc.WithClientHandlerAlias("eth_subscription", "Filecoin.EthSubscription"), + } + + cl, stop, err := client.NewFullNodeRPCV1(context.Background(), "ws://"+srv.Listener.Addr().String()+"/rpc/v1", nil, rpcOpts...) require.NoError(t, err) f.ListenAddr, f.ListenURL, f.FullNode = maddr, srv.URL, cl diff --git a/itests/kit/solidity.go b/itests/kit/solidity.go new file mode 100644 index 00000000000..ea9d452f465 --- /dev/null +++ b/itests/kit/solidity.go @@ -0,0 +1,64 @@ +package kit + +import ( + "golang.org/x/crypto/sha3" +) + +func EthTopicHash(sig string) []byte { + hasher := sha3.NewLegacyKeccak256() + hasher.Write([]byte(sig)) + return hasher.Sum(nil) +} + +func EthFunctionHash(sig string) []byte { + hasher := sha3.NewLegacyKeccak256() + hasher.Write([]byte(sig)) + return hasher.Sum(nil)[:4] +} + +// SolidityContractDef holds information about one of the test contracts +type SolidityContractDef struct { + Filename string // filename of the hex of the contract, e.g. contracts/EventMatrix.hex + Fn map[string][]byte // mapping of function names to 32-bit selector + Ev map[string][]byte // mapping of event names to 256-bit signature hashes +} + +var EventMatrixContract = SolidityContractDef{ + Filename: "contracts/EventMatrix.hex", + Fn: map[string][]byte{ + "logEventZeroData": EthFunctionHash("logEventZeroData()"), + "logEventOneData": EthFunctionHash("logEventOneData(uint256)"), + "logEventTwoData": EthFunctionHash("logEventTwoData(uint256,uint256)"), + "logEventThreeData": EthFunctionHash("logEventThreeData(uint256,uint256,uint256)"), + "logEventFourData": EthFunctionHash("logEventFourData(uint256,uint256,uint256,uint256)"), + "logEventOneIndexed": EthFunctionHash("logEventOneIndexed(uint256)"), + "logEventTwoIndexed": EthFunctionHash("logEventTwoIndexed(uint256,uint256)"), + "logEventThreeIndexed": EthFunctionHash("logEventThreeIndexed(uint256,uint256,uint256)"), + "logEventOneIndexedWithData": EthFunctionHash("logEventOneIndexedWithData(uint256,uint256)"), + "logEventTwoIndexedWithData": EthFunctionHash("logEventTwoIndexedWithData(uint256,uint256,uint256)"), + "logEventThreeIndexedWithData": EthFunctionHash("logEventThreeIndexedWithData(uint256,uint256,uint256,uint256)"), + }, + Ev: map[string][]byte{ + "EventZeroData": EthTopicHash("EventZeroData()"), + "EventOneData": EthTopicHash("EventOneData(uint256)"), + "EventTwoData": EthTopicHash("EventTwoData(uint256,uint256)"), + "EventThreeData": EthTopicHash("EventThreeData(uint256,uint256,uint256)"), + "EventFourData": EthTopicHash("EventFourData(uint256,uint256,uint256,uint256)"), + "EventOneIndexed": EthTopicHash("EventOneIndexed(uint256)"), + "EventTwoIndexed": EthTopicHash("EventTwoIndexed(uint256,uint256)"), + "EventThreeIndexed": EthTopicHash("EventThreeIndexed(uint256,uint256,uint256)"), + "EventOneIndexedWithData": EthTopicHash("EventOneIndexedWithData(uint256,uint256)"), + "EventTwoIndexedWithData": EthTopicHash("EventTwoIndexedWithData(uint256,uint256,uint256)"), + "EventThreeIndexedWithData": EthTopicHash("EventThreeIndexedWithData(uint256,uint256,uint256,uint256)"), + }, +} + +var EventsContract = SolidityContractDef{ + Filename: "contracts/events.bin", + Fn: map[string][]byte{ + "log_zero_data": {0x00, 0x00, 0x00, 0x00}, + "log_zero_nodata": {0x00, 0x00, 0x00, 0x01}, + "log_four_data": {0x00, 0x00, 0x00, 0x02}, + }, + Ev: map[string][]byte{}, +} diff --git a/itests/specs/eth_openrpc.json b/itests/specs/eth_openrpc.json new file mode 100644 index 00000000000..ed13614e991 --- /dev/null +++ b/itests/specs/eth_openrpc.json @@ -0,0 +1,4392 @@ +{ + "openrpc": "1.2.4", + "info": { + "title": "Ethereum JSON-RPC Specification", + "description": "A specification of the standard interface for Ethereum clients.", + "license": { + "name": "CC0-1.0", + "url": "https://creativecommons.org/publicdomain/zero/1.0/legalcode" + }, + "version": "0.0.0" + }, + "methods": [ + { + "name": "eth_getBlockByHash", + "summary": "Returns information about a block by hash.", + "params": [ + { + "name": "Block hash", + "required": true, + "schema": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "name": "Hydrated transactions", + "required": true, + "schema": { + "title": "hydrated", + "type": "boolean" + } + } + ], + "result": { + "name": "Block information", + "schema": { + "title": "Block object", + "type": "object", + "required": [ + "parentHash", + "sha3Uncles", + "miner", + "stateRoot", + "transactionsRoot", + "receiptsRoot", + "logsBloom", + "number", + "gasLimit", + "gasUsed", + "timestamp", + "extraData", + "mixHash", + "nonce", + "size", + "transactions", + "uncles" + ], + "properties": { + "parentHash": { + "title": "Parent block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "sha3Uncles": { + "title": "Ommers hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "miner": { + "title": "Coinbase", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "stateRoot": { + "title": "State root", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "transactionsRoot": { + "title": "Transactions root", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "receiptsRoot": { + "title": "Receipts root", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "logsBloom": { + "title": "Bloom filter", + "type": "string", + "pattern": "^0x[0-9a-f]{512}$" + }, + "difficulty": { + "title": "Difficulty", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "number": { + "title": "Number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "gasLimit": { + "title": "Gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "gasUsed": { + "title": "Gas used", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "timestamp": { + "title": "Timestamp", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "extraData": { + "title": "Extra data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "mixHash": { + "title": "Mix hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "nonce": { + "title": "Nonce", + "type": "string", + "pattern": "^0x[0-9a-f]{16}$" + }, + "totalDifficulty": { + "title": "Total difficult", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "baseFeePerGas": { + "title": "Base fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "size": { + "title": "Block size", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "transactions": { + "anyOf": [ + { + "title": "Transaction hashes", + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "title": "Full transactions", + "type": "array", + "items": { + "oneOf": [ + { + "title": "Signed 1559 Transaction", + "type": "object", + "required": [ + "accessList", + "chainId", + "gas", + "input", + "maxFeePerGas", + "maxPriorityFeePerGas", + "nonce", + "r", + "s", + "type", + "value", + "yParity" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "maxPriorityFeePerGas": { + "title": "max priority fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Maximum fee per gas the sender is willing to pay to miners in wei" + }, + "maxFeePerGas": { + "title": "max fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "yParity": { + "title": "yParity", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The parity (0 for even, 1 for odd) of the y-value of the secp256k1 signature." + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "title": "Signed 2930 Transaction", + "type": "object", + "required": [ + "accessList", + "chainId", + "gas", + "gasPrice", + "input", + "nonce", + "r", + "s", + "type", + "value", + "yParity" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "yParity": { + "title": "yParity", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The parity (0 for even, 1 for odd) of the y-value of the secp256k1 signature." + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "title": "Signed Legacy Transaction", + "type": "object", + "required": [ + "gas", + "gasPrice", + "input", + "nonce", + "r", + "s", + "type", + "v", + "value" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "v": { + "title": "v", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + } + ] + } + } + ] + }, + "uncles": { + "title": "Uncles", + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + } + }, + { + "name": "eth_getBlockByNumber", + "summary": "Returns information about a block by number.", + "params": [ + { + "name": "Block", + "required": true, + "schema": { + "title": "Block number or tag", + "oneOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + } + ] + } + }, + { + "name": "Hydrated transactions", + "required": true, + "schema": { + "title": "hydrated", + "type": "boolean" + } + } + ], + "result": { + "name": "Block information", + "schema": { + "title": "Block object", + "type": "object", + "required": [ + "parentHash", + "sha3Uncles", + "miner", + "stateRoot", + "transactionsRoot", + "receiptsRoot", + "logsBloom", + "number", + "gasLimit", + "gasUsed", + "timestamp", + "extraData", + "mixHash", + "nonce", + "size", + "transactions", + "uncles" + ], + "properties": { + "parentHash": { + "title": "Parent block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "sha3Uncles": { + "title": "Ommers hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "miner": { + "title": "Coinbase", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "stateRoot": { + "title": "State root", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "transactionsRoot": { + "title": "Transactions root", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "receiptsRoot": { + "title": "Receipts root", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "logsBloom": { + "title": "Bloom filter", + "type": "string", + "pattern": "^0x[0-9a-f]{512}$" + }, + "difficulty": { + "title": "Difficulty", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "number": { + "title": "Number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "gasLimit": { + "title": "Gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "gasUsed": { + "title": "Gas used", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "timestamp": { + "title": "Timestamp", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "extraData": { + "title": "Extra data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "mixHash": { + "title": "Mix hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "nonce": { + "title": "Nonce", + "type": "string", + "pattern": "^0x[0-9a-f]{16}$" + }, + "totalDifficulty": { + "title": "Total difficult", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "baseFeePerGas": { + "title": "Base fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "size": { + "title": "Block size", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "transactions": { + "anyOf": [ + { + "title": "Transaction hashes", + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "title": "Full transactions", + "type": "array", + "items": { + "oneOf": [ + { + "title": "Signed 1559 Transaction", + "type": "object", + "required": [ + "accessList", + "chainId", + "gas", + "input", + "maxFeePerGas", + "maxPriorityFeePerGas", + "nonce", + "r", + "s", + "type", + "value", + "yParity" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "maxPriorityFeePerGas": { + "title": "max priority fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Maximum fee per gas the sender is willing to pay to miners in wei" + }, + "maxFeePerGas": { + "title": "max fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "yParity": { + "title": "yParity", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The parity (0 for even, 1 for odd) of the y-value of the secp256k1 signature." + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "title": "Signed 2930 Transaction", + "type": "object", + "required": [ + "accessList", + "chainId", + "gas", + "gasPrice", + "input", + "nonce", + "r", + "s", + "type", + "value", + "yParity" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "yParity": { + "title": "yParity", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The parity (0 for even, 1 for odd) of the y-value of the secp256k1 signature." + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "title": "Signed Legacy Transaction", + "type": "object", + "required": [ + "gas", + "gasPrice", + "input", + "nonce", + "r", + "s", + "type", + "v", + "value" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "v": { + "title": "v", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + } + ] + } + } + ] + }, + "uncles": { + "title": "Uncles", + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + } + }, + { + "name": "eth_getBlockTransactionCountByHash", + "summary": "Returns the number of transactions in a block from a block matching the given block hash.", + "params": [ + { + "name": "Block hash", + "schema": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + ], + "result": { + "name": "Transaction count", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_getBlockTransactionCountByNumber", + "summary": "Returns the number of transactions in a block matching the given block number.", + "params": [ + { + "name": "Block", + "schema": { + "title": "Block number or tag", + "oneOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + } + ] + } + } + ], + "result": { + "name": "Transaction count", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_getUncleCountByBlockHash", + "summary": "Returns the number of uncles in a block from a block matching the given block hash.", + "params": [ + { + "name": "Block hash", + "schema": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + ], + "result": { + "name": "Uncle count", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_getUncleCountByBlockNumber", + "summary": "Returns the number of transactions in a block matching the given block number.", + "params": [ + { + "name": "Block", + "schema": { + "title": "Block number or tag", + "oneOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + } + ] + } + } + ], + "result": { + "name": "Uncle count", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_chainId", + "summary": "Returns the chain ID of the current network.", + "params": [], + "result": { + "name": "Chain ID", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_syncing", + "summary": "Returns an object with data about the sync status or false.", + "params": [], + "result": { + "name": "Syncing status", + "schema": { + "title": "Syncing status", + "oneOf": [ + { + "title": "Syncing progress", + "type": "object", + "properties": { + "startingBlock": { + "title": "Starting block", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "currentBlock": { + "title": "Current block", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "highestBlock": { + "title": "Highest block", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "title": "Not syncing", + "description": "Should always return false if not syncing.", + "type": "boolean" + } + ] + } + } + }, + { + "name": "eth_coinbase", + "summary": "Returns the client coinbase address.", + "params": [], + "result": { + "name": "Coinbase address", + "schema": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + } + } + }, + { + "name": "eth_accounts", + "summary": "Returns a list of addresses owned by client.", + "params": [], + "result": { + "name": "Accounts", + "schema": { + "title": "Accounts", + "type": "array", + "items": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + } + } + } + }, + { + "name": "eth_blockNumber", + "summary": "Returns the number of most recent block.", + "params": [], + "result": { + "name": "Block number", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_call", + "summary": "Executes a new message call immediately without creating a transaction on the block chain.", + "params": [ + { + "name": "Transaction", + "required": true, + "schema": { + "type": "object", + "title": "Transaction object generic to all types", + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "from": { + "title": "from address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "maxPriorityFeePerGas": { + "title": "max priority fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Maximum fee per gas the sender is willing to pay to miners in wei" + }, + "maxFeePerGas": { + "title": "max fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + } + } + } + }, + { + "name": "Block", + "required": false, + "schema": { + "title": "Block number, tag, or block hash", + "anyOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + }, + { + "title": "Block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + ] + } + } + ], + "result": { + "name": "Return data", + "schema": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + }, + { + "name": "eth_estimateGas", + "summary": "Generates and returns an estimate of how much gas is necessary to allow the transaction to complete.", + "params": [ + { + "name": "Transaction", + "required": true, + "schema": { + "type": "object", + "title": "Transaction object generic to all types", + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "from": { + "title": "from address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "maxPriorityFeePerGas": { + "title": "max priority fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Maximum fee per gas the sender is willing to pay to miners in wei" + }, + "maxFeePerGas": { + "title": "max fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + } + } + } + }, + { + "name": "Block", + "required": false, + "schema": { + "title": "Block number or tag", + "oneOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + } + ] + } + } + ], + "result": { + "name": "Gas used", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_createAccessList", + "summary": "Generates an access list for a transaction.", + "params": [ + { + "name": "Transaction", + "required": true, + "schema": { + "type": "object", + "title": "Transaction object generic to all types", + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "from": { + "title": "from address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "maxPriorityFeePerGas": { + "title": "max priority fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Maximum fee per gas the sender is willing to pay to miners in wei" + }, + "maxFeePerGas": { + "title": "max fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + } + } + } + }, + { + "name": "Block", + "required": false, + "schema": { + "title": "Block number or tag", + "oneOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + } + ] + } + } + ], + "result": { + "name": "Gas used", + "schema": { + "title": "Access list result", + "type": "object", + "properties": { + "accessList": { + "title": "accessList", + "type": "array", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "error": { + "title": "error", + "type": "string" + }, + "gasUsed": { + "title": "Gas used", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + } + } + }, + { + "name": "eth_gasPrice", + "summary": "Returns the current price per gas in wei.", + "params": [], + "result": { + "name": "Gas price", + "schema": { + "title": "Gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_maxPriorityFeePerGas", + "summary": "Returns the current maxPriorityFeePerGas per gas in wei.", + "params": [], + "result": { + "name": "Max priority fee per gas", + "schema": { + "title": "Max priority fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_feeHistory", + "summary": "Transaction fee history", + "description": "Returns transaction base fee per gas and effective priority fee per gas for the requested/supported block range.", + "params": [ + { + "name": "blockCount", + "description": "Requested range of blocks. Clients will return less than the requested range if not all blocks are available.", + "required": true, + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + }, + { + "name": "newestBlock", + "description": "Highest block of the requested range.", + "required": true, + "schema": { + "title": "Block number or tag", + "oneOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + } + ] + } + }, + { + "name": "rewardPercentiles", + "description": "A monotonically increasing list of percentile values. For each block in the requested range, the transactions will be sorted in ascending order by effective tip per gas and the coresponding effective tip for the percentile will be determined, accounting for gas consumed.", + "required": true, + "schema": { + "title": "rewardPercentiles", + "type": "array", + "items": { + "title": "rewardPercentile", + "description": "Floating point value between 0 and 100.", + "type": "number" + } + } + } + ], + "result": { + "name": "feeHistoryResult", + "description": "Fee history for the returned block range. This can be a subsection of the requested range if not all blocks are available.", + "schema": { + "title": "feeHistoryResults", + "description": "Fee history results.", + "type": "object", + "required": [ + "oldestBlock", + "baseFeePerGas", + "gasUsedRatio" + ], + "properties": { + "oldestBlock": { + "title": "oldestBlock", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Lowest number block of returned range." + }, + "baseFeePerGas": { + "title": "baseFeePerGasArray", + "description": "An array of block base fees per gas. This includes the next block after the newest of the returned range, because this value can be derived from the newest block. Zeroes are returned for pre-EIP-1559 blocks.", + "type": "array", + "items": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + }, + "reward": { + "title": "rewardArray", + "description": "A two-dimensional array of effective priority fees per gas at the requested block percentiles.", + "type": "array", + "items": { + "title": "rewardPercentile", + "description": "An array of effective priority fee per gas data points from a single block. All zeroes are returned if the block is empty.", + "type": "array", + "items": { + "title": "rewardPercentile", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "A given percentile sample of effective priority fees per gas from a single block in ascending order, weighted by gas used. Zeroes are returned if the block is empty." + } + } + } + } + } + } + }, + { + "name": "eth_newFilter", + "summary": "Creates a filter object, based on filter options, to notify when the state changes (logs).", + "params": [ + { + "name": "Filter", + "schema": { + "title": "filter", + "type": "object", + "properties": { + "fromBlock": { + "title": "from block", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "toBlock": { + "title": "to block", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "address": { + "title": "Address(es)", + "oneOf": [ + { + "title": "Address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + { + "title": "Addresses", + "type": "array", + "items": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + } + } + ] + }, + "topics": { + "title": "Topics", + "type": "array", + "items": { + "title": "Filter Topic List Entry", + "oneOf": [ + { + "title": "Any Topic Match", + "type": "null" + }, + { + "title": "Single Topic Match", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + { + "title": "Multiple Topic Match", + "type": "array", + "items": { + "title": "32 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + ] + } + } + } + } + } + ], + "result": { + "name": "Filter Identifier", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_newBlockFilter", + "summary": "Creates a filter in the node, to notify when a new block arrives.", + "params": [], + "result": { + "name": "Filter Identifier", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_newPendingTransactionFilter", + "summary": "Creates a filter in the node, to notify when new pending transactions arrive.", + "params": [], + "result": { + "name": "Filter Identifier", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_uninstallFilter", + "summary": "Uninstalls a filter with given id.", + "params": [ + { + "name": "Filter Identifier", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + ], + "result": { + "name": "Success", + "schema": { + "type": "boolean" + } + } + }, + { + "name": "eth_getFilterChanges", + "summary": "Polling method for a filter, which returns an array of logs which occurred since last poll.", + "params": [ + { + "name": "Filter Identifier", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + ], + "result": { + "name": "Log objects", + "schema": { + "title": "Filter results", + "oneOf": [ + { + "title": "new block hashes", + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "title": "new transaction hashes", + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "title": "new logs", + "type": "array", + "items": { + "title": "log", + "type": "object", + "required": [ + "transactionHash" + ], + "properties": { + "removed": { + "title": "removed", + "type": "boolean" + }, + "logIndex": { + "title": "log index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "transactionIndex": { + "title": "transaction index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "transactionHash": { + "title": "transaction hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockHash": { + "title": "block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockNumber": { + "title": "block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "address": { + "title": "address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "data": { + "title": "data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "topics": { + "title": "topics", + "type": "array", + "items": { + "title": "32 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + } + ] + } + } + }, + { + "name": "eth_getFilterLogs", + "summary": "Returns an array of all logs matching filter with given id.", + "params": [ + { + "name": "Filter Identifier", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + ], + "result": { + "name": "Log objects", + "schema": { + "title": "Filter results", + "oneOf": [ + { + "title": "new block hashes", + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "title": "new transaction hashes", + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "title": "new logs", + "type": "array", + "items": { + "title": "log", + "type": "object", + "required": [ + "transactionHash" + ], + "properties": { + "removed": { + "title": "removed", + "type": "boolean" + }, + "logIndex": { + "title": "log index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "transactionIndex": { + "title": "transaction index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "transactionHash": { + "title": "transaction hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockHash": { + "title": "block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockNumber": { + "title": "block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "address": { + "title": "address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "data": { + "title": "data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "topics": { + "title": "topics", + "type": "array", + "items": { + "title": "32 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + } + ] + } + } + }, + { + "name": "eth_getLogs", + "summary": "Returns an array of all logs matching filter with given id.", + "params": [ + { + "name": "Filter", + "schema": { + "title": "filter", + "type": "object", + "properties": { + "fromBlock": { + "title": "from block", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "toBlock": { + "title": "to block", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "address": { + "title": "Address(es)", + "oneOf": [ + { + "title": "Address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + { + "title": "Addresses", + "type": "array", + "items": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + } + } + ] + }, + "topics": { + "title": "Topics", + "type": "array", + "items": { + "title": "Filter Topic List Entry", + "oneOf": [ + { + "title": "Any Topic Match", + "type": "null" + }, + { + "title": "Single Topic Match", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + { + "title": "Multiple Topic Match", + "type": "array", + "items": { + "title": "32 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + ] + } + } + } + } + } + ], + "result": { + "name": "Log objects", + "schema": { + "title": "Filter results", + "oneOf": [ + { + "title": "new block hashes", + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "title": "new transaction hashes", + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "title": "new logs", + "type": "array", + "items": { + "title": "log", + "type": "object", + "required": [ + "transactionHash" + ], + "properties": { + "removed": { + "title": "removed", + "type": "boolean" + }, + "logIndex": { + "title": "log index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "transactionIndex": { + "title": "transaction index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "transactionHash": { + "title": "transaction hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockHash": { + "title": "block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockNumber": { + "title": "block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "address": { + "title": "address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "data": { + "title": "data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "topics": { + "title": "topics", + "type": "array", + "items": { + "title": "32 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + } + ] + } + } + }, + { + "name": "eth_mining", + "summary": "Returns whether the client is actively mining new blocks.", + "params": [], + "result": { + "name": "Mining status", + "schema": { + "title": "miningStatus", + "type": "boolean" + } + } + }, + { + "name": "eth_hashrate", + "summary": "Returns the number of hashes per second that the node is mining with.", + "params": [], + "result": { + "name": "Mining status", + "schema": { + "title": "Hashrate", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_getWork", + "summary": "Returns the hash of the current block, the seedHash, and the boundary condition to be met (“target”).", + "params": [], + "result": { + "name": "Current work", + "schema": { + "type": "array", + "items": [ + { + "title": "Proof-of-work hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + { + "title": "seed hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + { + "title": "difficulty", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + ] + } + } + }, + { + "name": "eth_submitWork", + "summary": "Used for submitting a proof-of-work solution.", + "params": [ + { + "name": "nonce", + "required": true, + "schema": { + "title": "8 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{16}$" + } + }, + { + "name": "hash", + "required": true, + "schema": { + "title": "32 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "name": "digest", + "required": true, + "schema": { + "title": "32 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + ], + "result": { + "name": "Success", + "schema": { + "type": "boolean" + } + } + }, + { + "name": "eth_submitHashrate", + "summary": "Used for submitting mining hashrate.", + "params": [ + { + "name": "Hashrate", + "required": true, + "schema": { + "title": "32 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "name": "ID", + "required": true, + "schema": { + "title": "32 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + ], + "result": { + "name": "Success", + "schema": { + "type": "boolean" + } + } + }, + { + "name": "eth_sign", + "summary": "Returns an EIP-191 signature over the provided data.", + "params": [ + { + "name": "Address", + "required": true, + "schema": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + } + }, + { + "name": "Message", + "required": true, + "schema": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + ], + "result": { + "name": "Signature", + "schema": { + "title": "65 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{65}$" + } + } + }, + { + "name": "eth_signTransaction", + "summary": "Returns an RLP encoded transaction signed by the specified account.", + "params": [ + { + "name": "Transaction", + "required": true, + "schema": { + "type": "object", + "title": "Transaction object generic to all types", + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "from": { + "title": "from address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "maxPriorityFeePerGas": { + "title": "max priority fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Maximum fee per gas the sender is willing to pay to miners in wei" + }, + "maxFeePerGas": { + "title": "max fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + } + } + } + } + ], + "result": { + "name": "Encoded transaction", + "schema": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + }, + { + "name": "eth_getBalance", + "summary": "Returns the balance of the account of given address.", + "params": [ + { + "name": "Address", + "required": true, + "schema": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + } + }, + { + "name": "Block", + "required": false, + "schema": { + "title": "Block number, tag, or block hash", + "anyOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + }, + { + "title": "Block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + ] + } + } + ], + "result": { + "name": "Balance", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_getStorageAt", + "summary": "Returns the value from a storage position at a given address.", + "params": [ + { + "name": "Address", + "required": true, + "schema": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + } + }, + { + "name": "Storage slot", + "required": true, + "schema": { + "title": "hex encoded 256 bit unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]{0,31})|0$" + } + }, + { + "name": "Block", + "required": false, + "schema": { + "title": "Block number, tag, or block hash", + "anyOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + }, + { + "title": "Block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + ] + } + } + ], + "result": { + "name": "Value", + "schema": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + }, + { + "name": "eth_getTransactionCount", + "summary": "Returns the number of transactions sent from an address.", + "params": [ + { + "name": "Address", + "required": true, + "schema": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + } + }, + { + "name": "Block", + "required": false, + "schema": { + "title": "Block number, tag, or block hash", + "anyOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + }, + { + "title": "Block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + ] + } + } + ], + "result": { + "name": "Transaction count", + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "name": "eth_getCode", + "summary": "Returns code at a given address.", + "params": [ + { + "name": "Address", + "required": true, + "schema": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + } + }, + { + "name": "Block", + "required": false, + "schema": { + "title": "Block number, tag, or block hash", + "anyOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + }, + { + "title": "Block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + ] + } + } + ], + "result": { + "name": "Bytecode", + "schema": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + }, + { + "name": "eth_getProof", + "summary": "Returns the merkle proof for a given account and optionally some storage keys.", + "params": [ + { + "name": "Address", + "required": true, + "schema": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + } + }, + { + "name": "StorageKeys", + "required": true, + "schema": { + "title": "Storage keys", + "type": "array", + "items": { + "title": "32 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{0,64}$" + } + } + }, + { + "name": "Block", + "required": true, + "schema": { + "title": "Block number, tag, or block hash", + "anyOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + }, + { + "title": "Block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + ] + } + } + ], + "result": { + "name": "Account", + "schema": { + "title": "Account proof", + "type": "object", + "required": [ + "address", + "accountProof", + "balance", + "codeHash", + "nonce", + "storageHash", + "storageProof" + ], + "properties": { + "address": { + "title": "address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "accountProof": { + "title": "accountProof", + "type": "array", + "items": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + }, + "balance": { + "title": "balance", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]{0,31})|0$" + }, + "codeHash": { + "title": "codeHash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]{0,15})|0$" + }, + "storageHash": { + "title": "storageHash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "storageProof": { + "title": "Storage proofs", + "type": "array", + "items": { + "title": "Storage proof", + "type": "object", + "required": [ + "key", + "value", + "proof" + ], + "properties": { + "key": { + "title": "key", + "type": "string", + "pattern": "^0x[0-9a-f]{0,64}$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]{0,31})|0$" + }, + "proof": { + "title": "proof", + "type": "array", + "items": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + } + } + } + } + } + } + }, + { + "name": "eth_sendTransaction", + "summary": "Signs and submits a transaction.", + "params": [ + { + "name": "Transaction", + "required": true, + "schema": { + "type": "object", + "title": "Transaction object generic to all types", + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "from": { + "title": "from address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "maxPriorityFeePerGas": { + "title": "max priority fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Maximum fee per gas the sender is willing to pay to miners in wei" + }, + "maxFeePerGas": { + "title": "max fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + } + } + } + } + ], + "result": { + "name": "Transaction hash", + "schema": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + }, + { + "name": "eth_sendRawTransaction", + "summary": "Submits a raw transaction.", + "params": [ + { + "name": "Transaction", + "required": true, + "schema": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + ], + "result": { + "name": "Transaction hash", + "schema": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + }, + { + "name": "eth_getTransactionByHash", + "summary": "Returns the information about a transaction requested by transaction hash.", + "params": [ + { + "name": "Transaction hash", + "required": true, + "schema": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + ], + "result": { + "name": "Transaction information", + "schema": { + "type": "object", + "title": "Transaction information", + "required": [ + "blockHash", + "blockNumber", + "from", + "hash", + "transactionIndex" + ], + "oneOf": [ + { + "title": "Signed 1559 Transaction", + "type": "object", + "required": [ + "accessList", + "chainId", + "gas", + "input", + "maxFeePerGas", + "maxPriorityFeePerGas", + "nonce", + "r", + "s", + "type", + "value", + "yParity" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "maxPriorityFeePerGas": { + "title": "max priority fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Maximum fee per gas the sender is willing to pay to miners in wei" + }, + "maxFeePerGas": { + "title": "max fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "yParity": { + "title": "yParity", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The parity (0 for even, 1 for odd) of the y-value of the secp256k1 signature." + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "title": "Signed 2930 Transaction", + "type": "object", + "required": [ + "accessList", + "chainId", + "gas", + "gasPrice", + "input", + "nonce", + "r", + "s", + "type", + "value", + "yParity" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "yParity": { + "title": "yParity", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The parity (0 for even, 1 for odd) of the y-value of the secp256k1 signature." + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "title": "Signed Legacy Transaction", + "type": "object", + "required": [ + "gas", + "gasPrice", + "input", + "nonce", + "r", + "s", + "type", + "v", + "value" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "v": { + "title": "v", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + } + ], + "properties": { + "blockHash": { + "title": "block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockNumber": { + "title": "block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "from": { + "title": "from address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "hash": { + "title": "transaction hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "transactionIndex": { + "title": "transaction index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + } + } + }, + { + "name": "eth_getTransactionByBlockHashAndIndex", + "summary": "Returns information about a transaction by block hash and transaction index position.", + "params": [ + { + "name": "Block hash", + "required": true, + "schema": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + }, + { + "name": "Transaction index", + "required": true, + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + ], + "result": { + "name": "Transaction information", + "schema": { + "type": "object", + "title": "Transaction information", + "required": [ + "blockHash", + "blockNumber", + "from", + "hash", + "transactionIndex" + ], + "oneOf": [ + { + "title": "Signed 1559 Transaction", + "type": "object", + "required": [ + "accessList", + "chainId", + "gas", + "input", + "maxFeePerGas", + "maxPriorityFeePerGas", + "nonce", + "r", + "s", + "type", + "value", + "yParity" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "maxPriorityFeePerGas": { + "title": "max priority fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Maximum fee per gas the sender is willing to pay to miners in wei" + }, + "maxFeePerGas": { + "title": "max fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "yParity": { + "title": "yParity", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The parity (0 for even, 1 for odd) of the y-value of the secp256k1 signature." + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "title": "Signed 2930 Transaction", + "type": "object", + "required": [ + "accessList", + "chainId", + "gas", + "gasPrice", + "input", + "nonce", + "r", + "s", + "type", + "value", + "yParity" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "yParity": { + "title": "yParity", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The parity (0 for even, 1 for odd) of the y-value of the secp256k1 signature." + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "title": "Signed Legacy Transaction", + "type": "object", + "required": [ + "gas", + "gasPrice", + "input", + "nonce", + "r", + "s", + "type", + "v", + "value" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "v": { + "title": "v", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + } + ], + "properties": { + "blockHash": { + "title": "block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockNumber": { + "title": "block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "from": { + "title": "from address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "hash": { + "title": "transaction hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "transactionIndex": { + "title": "transaction index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + } + } + }, + { + "name": "eth_getTransactionByBlockNumberAndIndex", + "summary": "Returns information about a transaction by block number and transaction index position.", + "params": [ + { + "name": "Block", + "required": true, + "schema": { + "title": "Block number or tag", + "oneOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + } + ] + } + }, + { + "name": "Transaction index", + "required": true, + "schema": { + "title": "hex encoded unsigned integer", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + ], + "result": { + "name": "Transaction information", + "schema": { + "type": "object", + "title": "Transaction information", + "required": [ + "blockHash", + "blockNumber", + "from", + "hash", + "transactionIndex" + ], + "oneOf": [ + { + "title": "Signed 1559 Transaction", + "type": "object", + "required": [ + "accessList", + "chainId", + "gas", + "input", + "maxFeePerGas", + "maxPriorityFeePerGas", + "nonce", + "r", + "s", + "type", + "value", + "yParity" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "maxPriorityFeePerGas": { + "title": "max priority fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Maximum fee per gas the sender is willing to pay to miners in wei" + }, + "maxFeePerGas": { + "title": "max fee per gas", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "yParity": { + "title": "yParity", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The parity (0 for even, 1 for odd) of the y-value of the secp256k1 signature." + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "title": "Signed 2930 Transaction", + "type": "object", + "required": [ + "accessList", + "chainId", + "gas", + "gasPrice", + "input", + "nonce", + "r", + "s", + "type", + "value", + "yParity" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "accessList": { + "title": "accessList", + "type": "array", + "description": "EIP-2930 access list", + "items": { + "title": "Access list entry", + "type": "object", + "properties": { + "address": { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "storageKeys": { + "type": "array", + "items": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "yParity": { + "title": "yParity", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The parity (0 for even, 1 for odd) of the y-value of the secp256k1 signature." + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + }, + { + "title": "Signed Legacy Transaction", + "type": "object", + "required": [ + "gas", + "gasPrice", + "input", + "nonce", + "r", + "s", + "type", + "v", + "value" + ], + "properties": { + "type": { + "title": "type", + "type": "string", + "pattern": "^0x([0-9,a-f,A-F]?){1,2}$" + }, + "nonce": { + "title": "nonce", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "to": { + "title": "to address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "gas": { + "title": "gas limit", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "value": { + "title": "value", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "input": { + "title": "input data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "gasPrice": { + "title": "gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The gas price willing to be paid by the sender in wei" + }, + "chainId": { + "title": "chainId", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Chain ID that this transaction is valid on." + }, + "v": { + "title": "v", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "r": { + "title": "r", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "s": { + "title": "s", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + } + ], + "properties": { + "blockHash": { + "title": "block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockNumber": { + "title": "block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "from": { + "title": "from address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "hash": { + "title": "transaction hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "transactionIndex": { + "title": "transaction index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + } + } + } + } + }, + { + "name": "eth_getTransactionReceipt", + "summary": "Returns the receipt of a transaction by transaction hash.", + "params": [ + { + "name": "Transaction hash", + "schema": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + ], + "result": { + "name": "Receipt Information", + "schema": { + "type": "object", + "title": "Receipt info", + "required": [ + "blockHash", + "blockNumber", + "from", + "cumulativeGasUsed", + "gasUsed", + "logs", + "logsBloom", + "transactionHash", + "transactionIndex", + "effectiveGasPrice" + ], + "properties": { + "transactionHash": { + "title": "transaction hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "transactionIndex": { + "title": "transaction index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "blockHash": { + "title": "block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockNumber": { + "title": "block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "from": { + "title": "from", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "to": { + "title": "to", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$", + "description": "Address of the receiver or null in a contract creation transaction." + }, + "cumulativeGasUsed": { + "title": "cumulative gas used", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The sum of gas used by this transaction and all preceding transactions in the same block." + }, + "gasUsed": { + "title": "gas used", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The amount of gas used for this specific transaction alone." + }, + "contractAddress": { + "title": "contract address", + "description": "The contract address created, if the transaction was a contract creation, otherwise null.", + "oneOf": [ + { + "title": "hex encoded address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + { + "name": null, + "type": "null" + } + ] + }, + "logs": { + "title": "logs", + "type": "array", + "items": { + "title": "log", + "type": "object", + "required": [ + "transactionHash" + ], + "properties": { + "removed": { + "title": "removed", + "type": "boolean" + }, + "logIndex": { + "title": "log index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "transactionIndex": { + "title": "transaction index", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "transactionHash": { + "title": "transaction hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockHash": { + "title": "block hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "blockNumber": { + "title": "block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + "address": { + "title": "address", + "type": "string", + "pattern": "^0x[0-9,a-f,A-F]{40}$" + }, + "data": { + "title": "data", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "topics": { + "title": "topics", + "type": "array", + "items": { + "title": "32 hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + } + } + }, + "logsBloom": { + "title": "logs bloom", + "type": "string", + "pattern": "^0x[0-9a-f]{512}$" + }, + "root": { + "title": "state root", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$", + "description": "The post-transaction state root. Only specified for transactions included before the Byzantium upgrade." + }, + "status": { + "title": "status", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "Either 1 (success) or 0 (failure). Only specified for transactions included after the Byzantium upgrade." + }, + "effectiveGasPrice": { + "title": "effective gas price", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$", + "description": "The actual value per gas deducted from the senders account. Before EIP-1559, this is equal to the transaction's gas price. After, it is equal to baseFeePerGas + min(maxFeePerGas - baseFeePerGas, maxPriorityFeePerGas)." + } + } + } + } + }, + { + "name": "debug_getRawHeader", + "summary": "Returns an RLP-encoded header.", + "params": [ + { + "name": "Block", + "required": true, + "schema": { + "title": "Block number or tag", + "oneOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + } + ] + } + } + ], + "result": { + "name": "Header RLP", + "schema": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + }, + { + "name": "debug_getRawBlock", + "summary": "Returns an RLP-encoded block.", + "params": [ + { + "name": "Block", + "required": true, + "schema": { + "title": "Block number or tag", + "oneOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + } + ] + } + } + ], + "result": { + "name": "Block RLP", + "schema": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + }, + { + "name": "debug_getRawTransaction", + "summary": "Returns an array of EIP-2718 binary-encoded transactions.", + "params": [ + { + "name": "Transaction hash", + "required": true, + "schema": { + "title": "32 byte hex value", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + } + } + ], + "result": { + "name": "EIP-2718 binary-encoded transaction", + "schema": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + }, + { + "name": "debug_getRawReceipts", + "summary": "Returns an array of EIP-2718 binary-encoded receipts.", + "params": [ + { + "name": "Block", + "required": true, + "schema": { + "title": "Block number or tag", + "oneOf": [ + { + "title": "Block number", + "type": "string", + "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$" + }, + { + "title": "Block tag", + "type": "string", + "enum": [ + "earliest", + "finalized", + "safe", + "latest", + "pending" + ], + "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error" + } + ] + } + } + ], + "result": { + "name": "Receipts", + "schema": { + "title": "Receipt array", + "type": "array", + "items": { + "title": "hex encoded bytes", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + } + }, + { + "name": "debug_getBadBlocks", + "summary": "Returns an array of recent bad blocks that the client has seen on the network.", + "params": [], + "result": { + "name": "Blocks", + "schema": { + "title": "Bad block array", + "type": "array", + "items": { + "title": "Bad block", + "type": "object", + "required": [ + "block", + "hash", + "rlp" + ], + "properties": { + "block": { + "title": "Block", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + }, + "hash": { + "title": "Hash", + "type": "string", + "pattern": "^0x[0-9a-f]{64}$" + }, + "rlp": { + "title": "RLP", + "type": "string", + "pattern": "^0x[0-9a-f]*$" + } + } + } + } + } + } + ], + "components": {} +} diff --git a/lib/must/must.go b/lib/must/must.go new file mode 100644 index 00000000000..e072b4e04dc --- /dev/null +++ b/lib/must/must.go @@ -0,0 +1,9 @@ +package must + +func One[R any](r R, err error) R { + if err != nil { + panic(err) + } + + return r +} diff --git a/lib/result/result.go b/lib/result/result.go index bec839d7ad6..56a9ffab713 100644 --- a/lib/result/result.go +++ b/lib/result/result.go @@ -30,6 +30,12 @@ func Wrap[T any](value T, err error) Result[T] { } } -func (r *Result[T]) Unwrap() (T, error) { +func (r Result[T]) Unwrap() (T, error) { return r.Value, r.Error } + +func (r Result[T]) Assert(noErrFn func(err error, msgAndArgs ...interface{})) T { + noErrFn(r.Error) + + return r.Value +} diff --git a/node/builder.go b/node/builder.go index 1e4ea0400f2..76c93cbc6c0 100644 --- a/node/builder.go +++ b/node/builder.go @@ -127,6 +127,8 @@ const ( SetApiEndpointKey + StoreEventsKey + _nInvokes // keep this last ) diff --git a/node/builder_chain.go b/node/builder_chain.go index 07b082cd27c..d334d782e3f 100644 --- a/node/builder_chain.go +++ b/node/builder_chain.go @@ -219,6 +219,11 @@ func ConfigFullNode(c interface{}) Option { Override(SetupFallbackBlockstoresKey, modules.InitFallbackBlockstores), ), + // If the Eth JSON-RPC is enabled, enable storing events at the ChainStore. + // This is the case even if real-time and historic filtering are disabled, + // as it enables us to serve logs in eth_getTransactionReceipt. + If(cfg.Fevm.EnableEthRPC, Override(StoreEventsKey, modules.EnableStoringEvents)), + Override(new(dtypes.ClientImportMgr), modules.ClientImportMgr), Override(new(dtypes.ClientBlockstore), modules.ClientBlockstore), @@ -258,11 +263,18 @@ func ConfigFullNode(c interface{}) Option { // Actor event filtering support Override(new(events.EventAPI), From(new(modules.EventAPI))), - // in lite-mode Eth event api is provided by gateway - ApplyIf(isFullNode, Override(new(full.EthEventAPI), modules.EthEventAPI(cfg.Fevm))), - If(cfg.Fevm.EnableEthRPC, Override(new(full.EthModuleAPI), modules.EthModuleAPI(cfg.Fevm))), - If(!cfg.Fevm.EnableEthRPC, Override(new(full.EthModuleAPI), &full.EthModuleDummy{})), + // in lite-mode Eth api is provided by gateway + ApplyIf(isFullNode, + If(cfg.Fevm.EnableEthRPC, + Override(new(full.EthModuleAPI), modules.EthModuleAPI(cfg.Fevm)), + Override(new(full.EthEventAPI), modules.EthEventAPI(cfg.Fevm)), + ), + If(!cfg.Fevm.EnableEthRPC, + Override(new(full.EthModuleAPI), &full.EthModuleDummy{}), + Override(new(full.EthEventAPI), &full.EthModuleDummy{}), + ), + ), ) } diff --git a/node/impl/full/dummy.go b/node/impl/full/dummy.go index aa1450212aa..c1c6ea9759c 100644 --- a/node/impl/full/dummy.go +++ b/node/impl/full/dummy.go @@ -6,6 +6,8 @@ import ( "github.com/ipfs/go-cid" + "github.com/filecoin-project/go-jsonrpc" + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types/ethtypes" ) @@ -118,4 +120,45 @@ func (e *EthModuleDummy) EthSendRawTransaction(ctx context.Context, rawTx ethtyp return ethtypes.EthHash{}, ErrModuleDisabled } +func (e *EthModuleDummy) Web3ClientVersion(ctx context.Context) (string, error) { + return "", ErrModuleDisabled +} + +func (e *EthModuleDummy) EthGetLogs(ctx context.Context, filter *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) { + return ðtypes.EthFilterResult{}, ErrModuleDisabled +} + +func (e *EthModuleDummy) EthGetFilterChanges(ctx context.Context, id ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) { + return ðtypes.EthFilterResult{}, ErrModuleDisabled +} + +func (e *EthModuleDummy) EthGetFilterLogs(ctx context.Context, id ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) { + return ðtypes.EthFilterResult{}, ErrModuleDisabled +} + +func (e *EthModuleDummy) EthNewFilter(ctx context.Context, filter *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) { + return ethtypes.EthFilterID{}, ErrModuleDisabled +} + +func (e *EthModuleDummy) EthNewBlockFilter(ctx context.Context) (ethtypes.EthFilterID, error) { + return ethtypes.EthFilterID{}, ErrModuleDisabled +} + +func (e *EthModuleDummy) EthNewPendingTransactionFilter(ctx context.Context) (ethtypes.EthFilterID, error) { + return ethtypes.EthFilterID{}, ErrModuleDisabled +} + +func (e *EthModuleDummy) EthUninstallFilter(ctx context.Context, id ethtypes.EthFilterID) (bool, error) { + return false, ErrModuleDisabled +} + +func (e *EthModuleDummy) EthSubscribe(ctx context.Context, params jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) { + return ethtypes.EthSubscriptionID{}, ErrModuleDisabled +} + +func (e *EthModuleDummy) EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error) { + return false, ErrModuleDisabled +} + var _ EthModuleAPI = &EthModuleDummy{} +var _ EthEventAPI = &EthModuleDummy{} diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index 7eb992a2258..6d144b9ae89 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -3,6 +3,7 @@ package full import ( "bytes" "context" + "encoding/json" "errors" "fmt" "strconv" @@ -16,12 +17,14 @@ import ( "golang.org/x/xerrors" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-jsonrpc" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" builtintypes "github.com/filecoin-project/go-state-types/builtin" "github.com/filecoin-project/go-state-types/builtin/v10/eam" "github.com/filecoin-project/go-state-types/builtin/v10/evm" "github.com/filecoin-project/go-state-types/crypto" + "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" @@ -64,6 +67,7 @@ type EthModuleAPI interface { EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam string) (ethtypes.EthBytes, error) EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt, error) EthSendRawTransaction(ctx context.Context, rawTx ethtypes.EthBytes) (ethtypes.EthHash, error) + Web3ClientVersion(ctx context.Context) (string, error) } type EthEventAPI interface { @@ -74,13 +78,15 @@ type EthEventAPI interface { EthNewBlockFilter(ctx context.Context) (ethtypes.EthFilterID, error) EthNewPendingTransactionFilter(ctx context.Context) (ethtypes.EthFilterID, error) EthUninstallFilter(ctx context.Context, id ethtypes.EthFilterID) (bool, error) - EthSubscribe(ctx context.Context, eventType string, params *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) + EthSubscribe(ctx context.Context, params jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error) } var ( _ EthModuleAPI = *new(api.FullNode) _ EthEventAPI = *new(api.FullNode) + + _ EthModuleAPI = *new(api.Gateway) ) // EthModule provides the default implementation of the standard Ethereum JSON-RPC API. @@ -131,6 +137,7 @@ type EthEvent struct { FilterStore filter.FilterStore SubManager *EthSubscriptionManager MaxFilterHeightRange abi.ChainEpoch + SubscribtionCtx context.Context } var _ EthEventAPI = (*EthEvent)(nil) @@ -211,7 +218,7 @@ func (a *EthModule) EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthH if err != nil { return ethtypes.EthBlock{}, xerrors.Errorf("error loading tipset %s: %w", ts, err) } - return newEthBlockFromFilecoinTipSet(ctx, ts, fullTxInfo, a.Chain, a.ChainAPI, a.StateAPI) + return newEthBlockFromFilecoinTipSet(ctx, ts, fullTxInfo, a.Chain, a.StateAPI) } func (a *EthModule) parseBlkParam(ctx context.Context, blkParam string) (tipset *types.TipSet, err error) { @@ -248,7 +255,7 @@ func (a *EthModule) EthGetBlockByNumber(ctx context.Context, blkParam string, fu if err != nil { return ethtypes.EthBlock{}, err } - return newEthBlockFromFilecoinTipSet(ctx, ts, fullTxInfo, a.Chain, a.ChainAPI, a.StateAPI) + return newEthBlockFromFilecoinTipSet(ctx, ts, fullTxInfo, a.Chain, a.StateAPI) } func (a *EthModule) EthGetTransactionByHash(ctx context.Context, txHash *ethtypes.EthHash) (*ethtypes.EthTx, error) { @@ -269,8 +276,8 @@ func (a *EthModule) EthGetTransactionByHash(ctx context.Context, txHash *ethtype // first, try to get the cid from mined transactions msgLookup, err := a.StateAPI.StateSearchMsg(ctx, types.EmptyTSK, c, api.LookbackNoLimit, true) - if err == nil { - tx, err := newEthTxFromFilecoinMessageLookup(ctx, msgLookup, -1, a.Chain, a.StateAPI) + if err == nil && msgLookup != nil { + tx, err := newEthTxFromMessageLookup(ctx, msgLookup, -1, a.Chain, a.StateAPI) if err == nil { return &tx, nil } @@ -286,7 +293,7 @@ func (a *EthModule) EthGetTransactionByHash(ctx context.Context, txHash *ethtype for _, p := range pending { if p.Cid() == c { - tx, err := NewEthTxFromFilecoinMessage(ctx, p, a.StateAPI) + tx, err := newEthTxFromSignedMessage(ctx, p, a.StateAPI) if err != nil { return nil, fmt.Errorf("could not convert Filecoin message into tx: %s", err) } @@ -335,7 +342,7 @@ func (a *EthModule) EthGetMessageCidByTransactionHash(ctx context.Context, txHas } func (a *EthModule) EthGetTransactionHashByCid(ctx context.Context, cid cid.Cid) (*ethtypes.EthHash, error) { - hash, err := EthTxHashFromFilecoinMessageCid(ctx, cid, a.StateAPI) + hash, err := EthTxHashFromMessageCid(ctx, cid, a.StateAPI) if hash == ethtypes.EmptyEthHash { // not found return nil, nil @@ -378,7 +385,7 @@ func (a *EthModule) EthGetTransactionReceipt(ctx context.Context, txHash ethtype return nil, nil } - tx, err := newEthTxFromFilecoinMessageLookup(ctx, msgLookup, -1, a.Chain, a.StateAPI) + tx, err := newEthTxFromMessageLookup(ctx, msgLookup, -1, a.Chain, a.StateAPI) if err != nil { return nil, nil } @@ -440,6 +447,11 @@ func (a *EthModule) EthGetCode(ctx context.Context, ethAddr ethtypes.EthAddress, return nil, xerrors.Errorf("cannot parse block param: %s", blkParam) } + // StateManager.Call will panic if there is no parent + if ts.Height() == 0 { + return nil, xerrors.Errorf("block param must not specify genesis block") + } + // Try calling until we find a height with no migration. var res *api.InvocResult for { @@ -500,18 +512,8 @@ func (a *EthModule) EthGetStorageAt(ctx context.Context, ethAddr ethtypes.EthAdd return nil, fmt.Errorf("failed to construct system sender address: %w", err) } - // TODO super duper hack (raulk). The EVM runtime actor uses the U256 parameter type in - // GetStorageAtParams, which serializes as a hex-encoded string. It should serialize - // as bytes. We didn't get to fix in time for Iron, so for now we just pass - // through the hex-encoded value passed through the Eth JSON-RPC API, by remarshalling it. - // We don't fix this at origin (builtin-actors) because we are not updating the bundle - // for Iron. - tmp, err := position.MarshalJSON() - if err != nil { - panic(err) - } params, err := actors.SerializeParams(&evm.GetStorageAtParams{ - StorageKey: tmp[1 : len(tmp)-1], // TODO strip the JSON-encoding quotes -- yuck + StorageKey: position, }) if err != nil { return nil, fmt.Errorf("failed to serialize parameters: %w", err) @@ -614,7 +616,7 @@ func (a *EthModule) EthFeeHistory(ctx context.Context, blkCount ethtypes.EthUint for ts.Height() >= abi.ChainEpoch(oldestBlkHeight) { // Unfortunately we need to rebuild the full message view so we can // totalize gas used in the tipset. - block, err := newEthBlockFromFilecoinTipSet(ctx, ts, false, a.Chain, a.ChainAPI, a.StateAPI) + block, err := newEthBlockFromFilecoinTipSet(ctx, ts, false, a.Chain, a.StateAPI) if err != nil { return ethtypes.EthFeeHistory{}, fmt.Errorf("cannot create eth block: %v", err) } @@ -640,7 +642,7 @@ func (a *EthModule) EthFeeHistory(ctx context.Context, blkCount ethtypes.EthUint } return ethtypes.EthFeeHistory{ - OldestBlock: oldestBlkHeight, + OldestBlock: ethtypes.EthUint64(oldestBlkHeight), BaseFeePerGas: baseFeeArray, GasUsedRatio: gasUsedRatioArray, }, nil @@ -699,13 +701,6 @@ func (a *EthModule) EthSendRawTransaction(ctx context.Context, rawTx ethtypes.Et return ethtypes.EmptyEthHash, err } - _, err = a.StateAPI.StateGetActor(ctx, smsg.Message.To, types.EmptyTSK) - if err != nil { - // if actor does not exist on chain yet, set the method to 0 because - // placeholders only implement method 0 - smsg.Message.Method = builtinactors.MethodSend - } - _, err = a.MpoolAPI.MpoolPush(ctx, smsg) if err != nil { return ethtypes.EmptyEthHash, err @@ -714,6 +709,10 @@ func (a *EthModule) EthSendRawTransaction(ctx context.Context, rawTx ethtypes.Et return ethtypes.EthHashFromTxBytes(rawTx), nil } +func (a *EthModule) Web3ClientVersion(ctx context.Context) (string, error) { + return build.UserVersion(), nil +} + func (a *EthModule) ethCallToFilecoinMessage(ctx context.Context, tx ethtypes.EthCall) (*types.Message, error) { var from address.Address if tx.From == nil || *tx.From == (ethtypes.EthAddress{}) { @@ -816,19 +815,145 @@ func (a *EthModule) EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (et // gas estimation actually run. msg.GasLimit = 0 - msg, err = a.GasAPI.GasEstimateMessageGas(ctx, msg, nil, types.EmptyTSK) + ts := a.Chain.GetHeaviestTipSet() + msg, err = a.GasAPI.GasEstimateMessageGas(ctx, msg, nil, ts.Key()) if err != nil { - return ethtypes.EthUint64(0), err + return ethtypes.EthUint64(0), xerrors.Errorf("failed to estimate gas: %w", err) + } + + expectedGas, err := ethGasSearch(ctx, a.Chain, a.Stmgr, a.Mpool, msg, ts) + if err != nil { + log.Errorw("expected gas", "err", err) + } + + return ethtypes.EthUint64(expectedGas), nil +} + +// gasSearch does an exponential search to find a gas value to execute the +// message with. It first finds a high gas limit that allows the message to execute +// by doubling the previous gas limit until it succeeds then does a binary +// search till it gets within a range of 1% +func gasSearch( + ctx context.Context, + smgr *stmgr.StateManager, + msgIn *types.Message, + priorMsgs []types.ChainMsg, + ts *types.TipSet, +) (int64, error) { + msg := *msgIn + + high := msg.GasLimit + low := msg.GasLimit + + canSucceed := func(limit int64) (bool, error) { + msg.GasLimit = limit + + res, err := smgr.CallWithGas(ctx, &msg, priorMsgs, ts) + if err != nil { + return false, xerrors.Errorf("CallWithGas failed: %w", err) + } + + if res.MsgRct.ExitCode.IsSuccess() { + return true, nil + } + + return false, nil + } + + for { + ok, err := canSucceed(high) + if err != nil { + return -1, xerrors.Errorf("searching for high gas limit failed: %w", err) + } + if ok { + break + } + + low = high + high = high * 2 + + if high > build.BlockGasLimit { + high = build.BlockGasLimit + break + } + } + + checkThreshold := high / 100 + for (high - low) > checkThreshold { + median := (low + high) / 2 + ok, err := canSucceed(median) + if err != nil { + return -1, xerrors.Errorf("searching for optimal gas limit failed: %w", err) + } + + if ok { + high = median + } else { + low = median + } + + checkThreshold = median / 100 + } + + return high, nil +} + +func traceContainsExitCode(et types.ExecutionTrace, ex exitcode.ExitCode) bool { + if et.MsgRct.ExitCode == ex { + return true } - return ethtypes.EthUint64(msg.GasLimit), nil + for _, et := range et.Subcalls { + if traceContainsExitCode(et, ex) { + return true + } + } + + return false +} + +// ethGasSearch executes a message for gas estimation using the previously estimated gas. +// If the message fails due to an out of gas error then a gas search is performed. +// See gasSearch. +func ethGasSearch( + ctx context.Context, + cstore *store.ChainStore, + smgr *stmgr.StateManager, + mpool *messagepool.MessagePool, + msgIn *types.Message, + ts *types.TipSet, +) (int64, error) { + msg := *msgIn + currTs := ts + + res, priorMsgs, ts, err := gasEstimateCallWithGas(ctx, cstore, smgr, mpool, &msg, currTs) + if err != nil { + return -1, xerrors.Errorf("gas estimation failed: %w", err) + } + + if res.MsgRct.ExitCode.IsSuccess() { + return msg.GasLimit, nil + } + + if traceContainsExitCode(res.ExecutionTrace, exitcode.SysErrOutOfGas) { + ret, err := gasSearch(ctx, smgr, &msg, priorMsgs, ts) + if err != nil { + return -1, xerrors.Errorf("gas estimation search failed: %w", err) + } + + ret = int64(float64(ret) * mpool.GetConfig().GasLimitOverestimation) + return ret, nil + } + + return -1, xerrors.Errorf("message execution failed: exit %s, reason: %s", res.MsgRct.ExitCode, res.Error) } func (a *EthModule) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam string) (ethtypes.EthBytes, error) { msg, err := a.ethCallToFilecoinMessage(ctx, tx) if err != nil { - return nil, err + return nil, xerrors.Errorf("failed to convert ethcall to filecoin message: %w", err) } + ts, err := a.parseBlkParam(ctx, blkParam) if err != nil { return nil, xerrors.Errorf("cannot parse block param: %s", blkParam) @@ -836,11 +961,16 @@ func (a *EthModule) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam s invokeResult, err := a.applyMessage(ctx, msg, ts.Key()) if err != nil { - return nil, err + return nil, xerrors.Errorf("failed to apply message: %w", err) } - if len(invokeResult.MsgRct.Return) > 0 { + + if msg.To == builtintypes.EthereumAddressManagerActorAddr { + // As far as I can tell, the Eth API always returns empty on contract deployment + return ethtypes.EthBytes{}, nil + } else if len(invokeResult.MsgRct.Return) > 0 { return cbg.ReadByteArray(bytes.NewReader(invokeResult.MsgRct.Return), uint64(len(invokeResult.MsgRct.Return))) } + return ethtypes.EthBytes{}, nil } @@ -980,17 +1110,9 @@ func (e *EthEvent) installEthFilterSpec(ctx context.Context, filterSpec *ethtype addresses = append(addresses, a) } - for idx, vals := range filterSpec.Topics { - if len(vals) == 0 { - continue - } - // Ethereum topics are emitted using `LOG{0..4}` opcodes resulting in topics1..4 - key := fmt.Sprintf("topic%d", idx+1) - for _, v := range vals { - buf := make([]byte, len(v[:])) - copy(buf, v[:]) - keys[key] = append(keys[key], buf) - } + keys, err := parseEthTopics(filterSpec.Topics) + if err != nil { + return nil, err } return e.EventFilterManager.Install(ctx, minHeight, maxHeight, tipsetCid, addresses, keys) @@ -1015,7 +1137,6 @@ func (e *EthEvent) EthNewFilter(ctx context.Context, filterSpec *ethtypes.EthFil return ethtypes.EthFilterID{}, err } - return ethtypes.EthFilterID(f.ID()), nil } @@ -1114,54 +1235,71 @@ const ( EthSubscribeEventTypeLogs = "logs" ) -func (e *EthEvent) EthSubscribe(ctx context.Context, eventType string, params *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) { +func (e *EthEvent) EthSubscribe(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) { + params, err := jsonrpc.DecodeParams[ethtypes.EthSubscribeParams](p) + if err != nil { + return ethtypes.EthSubscriptionID{}, xerrors.Errorf("decoding params: %w", err) + } + if e.SubManager == nil { - return nil, api.ErrNotSupported + return ethtypes.EthSubscriptionID{}, api.ErrNotSupported } - // Note that go-jsonrpc will set the method field of the response to "xrpc.ch.val" but the ethereum api expects the name of the - // method to be "eth_subscription". This probably doesn't matter in practice. - sub, err := e.SubManager.StartSubscription(ctx) + ethCb, ok := jsonrpc.ExtractReverseClient[api.EthSubscriberMethods](ctx) + if !ok { + return ethtypes.EthSubscriptionID{}, xerrors.Errorf("connection doesn't support callbacks") + } + + sub, err := e.SubManager.StartSubscription(e.SubscribtionCtx, ethCb.EthSubscription) if err != nil { - return nil, err + return ethtypes.EthSubscriptionID{}, err } - switch eventType { + switch params.EventType { case EthSubscribeEventTypeHeads: f, err := e.TipSetFilterManager.Install(ctx) if err != nil { // clean up any previous filters added and stop the sub _, _ = e.EthUnsubscribe(ctx, sub.id) - return nil, err + return ethtypes.EthSubscriptionID{}, err } sub.addFilter(ctx, f) case EthSubscribeEventTypeLogs: keys := map[string][][]byte{} - if params != nil { - for idx, vals := range params.Topics { - // Ethereum topics are emitted using `LOG{0..4}` opcodes resulting in topics1..4 - key := fmt.Sprintf("topic%d", idx+1) - keyvals := make([][]byte, len(vals)) - for i, v := range vals { - keyvals[i] = v[:] + if params.Params != nil { + var err error + keys, err = parseEthTopics(params.Params.Topics) + if err != nil { + // clean up any previous filters added and stop the sub + _, _ = e.EthUnsubscribe(ctx, sub.id) + return ethtypes.EthSubscriptionID{}, err + } + } + + var addresses []address.Address + if params.Params != nil { + for _, ea := range params.Params.Address { + a, err := ea.ToFilecoinAddress() + if err != nil { + return ethtypes.EthSubscriptionID{}, xerrors.Errorf("invalid address %x", ea) } - keys[key] = keyvals + addresses = append(addresses, a) } } - f, err := e.EventFilterManager.Install(ctx, -1, -1, cid.Undef, []address.Address{}, keys) + f, err := e.EventFilterManager.Install(ctx, -1, -1, cid.Undef, addresses, keys) if err != nil { // clean up any previous filters added and stop the sub _, _ = e.EthUnsubscribe(ctx, sub.id) - return nil, err + return ethtypes.EthSubscriptionID{}, err } sub.addFilter(ctx, f) default: - return nil, xerrors.Errorf("unsupported event type: %s", eventType) + return ethtypes.EthSubscriptionID{}, xerrors.Errorf("unsupported event type: %s", params.EventType) } - return sub.out, nil + return sub.id, nil } func (e *EthEvent) EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error) { @@ -1233,7 +1371,10 @@ func ethFilterResultFromEvents(evs []*filter.CollectedEvent, sa StateAPI) (*etht var err error for _, entry := range ev.Entries { - value := ethtypes.EthBytes(leftpad32(entry.Value)) // value has already been cbor-decoded but see https://github.com/filecoin-project/ref-fvm/issues/1345 + value, err := cborDecodeTopicValue(entry.Value) + if err != nil { + return nil, err + } if entry.Key == ethtypes.EthTopic1 || entry.Key == ethtypes.EthTopic2 || entry.Key == ethtypes.EthTopic3 || entry.Key == ethtypes.EthTopic4 { log.Topics = append(log.Topics, value) } else { @@ -1246,7 +1387,7 @@ func ethFilterResultFromEvents(evs []*filter.CollectedEvent, sa StateAPI) (*etht return nil, err } - log.TransactionHash, err = EthTxHashFromFilecoinMessageCid(context.TODO(), ev.MsgCid, sa) + log.TransactionHash, err = EthTxHashFromMessageCid(context.TODO(), ev.MsgCid, sa) if err != nil { return nil, err } @@ -1288,7 +1429,7 @@ func ethFilterResultFromMessages(cs []*types.SignedMessage, sa StateAPI) (*ethty res := ðtypes.EthFilterResult{} for _, c := range cs { - hash, err := EthTxHashFromSignedFilecoinMessage(context.TODO(), c, sa) + hash, err := EthTxHashFromSignedMessage(context.TODO(), c, sa) if err != nil { return nil, err } @@ -1307,7 +1448,7 @@ type EthSubscriptionManager struct { subs map[ethtypes.EthSubscriptionID]*ethSubscription } -func (e *EthSubscriptionManager) StartSubscription(ctx context.Context) (*ethSubscription, error) { // nolint +func (e *EthSubscriptionManager) StartSubscription(ctx context.Context, out ethSubscriptionCallback) (*ethSubscription, error) { // nolint rawid, err := uuid.NewRandom() if err != nil { return nil, xerrors.Errorf("new uuid: %w", err) @@ -1323,7 +1464,7 @@ func (e *EthSubscriptionManager) StartSubscription(ctx context.Context) (*ethSub ChainAPI: e.ChainAPI, id: id, in: make(chan interface{}, 200), - out: make(chan ethtypes.EthSubscriptionResponse, 20), + out: out, quit: quit, } @@ -1353,13 +1494,15 @@ func (e *EthSubscriptionManager) StopSubscription(ctx context.Context, id ethtyp return sub.filters, nil } +type ethSubscriptionCallback func(context.Context, jsonrpc.RawParams) error + type ethSubscription struct { Chain *store.ChainStore StateAPI StateAPI ChainAPI ChainAPI id ethtypes.EthSubscriptionID in chan interface{} - out chan ethtypes.EthSubscriptionResponse + out ethSubscriptionCallback mu sync.Mutex filters []filter.Filter @@ -1389,7 +1532,7 @@ func (e *ethSubscription) start(ctx context.Context) { case *filter.CollectedEvent: resp.Result, err = ethFilterResultFromEvents([]*filter.CollectedEvent{vt}, e.StateAPI) case *types.TipSet: - eb, err := newEthBlockFromFilecoinTipSet(ctx, vt, true, e.Chain, e.ChainAPI, e.StateAPI) + eb, err := newEthBlockFromFilecoinTipSet(ctx, vt, true, e.Chain, e.StateAPI) if err != nil { break } @@ -1403,10 +1546,15 @@ func (e *ethSubscription) start(ctx context.Context) { continue } - select { - case e.out <- resp: - default: - // Skip if client is not reading responses + outParam, err := json.Marshal(resp) + if err != nil { + log.Warnw("marshaling subscription response", "sub", e.id, "error", err) + continue + } + + if err := e.out(ctx, outParam); err != nil { + log.Warnw("sending subscription response", "sub", e.id, "error", err) + continue } } } @@ -1418,12 +1566,11 @@ func (e *ethSubscription) stop() { if e.quit != nil { e.quit() - close(e.out) e.quit = nil } } -func newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTxInfo bool, cs *store.ChainStore, ca ChainAPI, sa StateAPI) (ethtypes.EthBlock, error) { +func newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTxInfo bool, cs *store.ChainStore, sa StateAPI) (ethtypes.EthBlock, error) { parent, err := cs.LoadTipSet(ctx, ts.Parents()) if err != nil { return ethtypes.EthBlock{}, err @@ -1451,7 +1598,7 @@ func newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTx return ethtypes.EthBlock{}, xerrors.Errorf("error loading messages for tipset: %v: %w", ts, err) } - block := ethtypes.NewEthBlock() + block := ethtypes.NewEthBlock(len(msgs) > 0) // this seems to be a very expensive way to get gasUsed of the block. may need to find an efficient way to do it gasUsed := int64(0) @@ -1462,7 +1609,7 @@ func newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTx } gasUsed += msgLookup.Receipt.GasUsed - tx, err := newEthTxFromFilecoinMessageLookup(ctx, msgLookup, txIdx, cs, sa) + tx, err := newEthTxFromMessageLookup(ctx, msgLookup, txIdx, cs, sa) if err != nil { return ethtypes.EthBlock{}, nil } @@ -1522,11 +1669,11 @@ func lookupEthAddress(ctx context.Context, addr address.Address, sa StateAPI) (e return ethtypes.EthAddressFromFilecoinAddress(idAddr) } -func EthTxHashFromFilecoinMessageCid(ctx context.Context, c cid.Cid, sa StateAPI) (ethtypes.EthHash, error) { +func EthTxHashFromMessageCid(ctx context.Context, c cid.Cid, sa StateAPI) (ethtypes.EthHash, error) { smsg, err := sa.Chain.GetSignedMessage(ctx, c) if err == nil { // This is an Eth Tx, Secp message, Or BLS message in the mpool - return EthTxHashFromSignedFilecoinMessage(ctx, smsg, sa) + return EthTxHashFromSignedMessage(ctx, smsg, sa) } _, err = sa.Chain.GetMessage(ctx, c) @@ -1538,109 +1685,85 @@ func EthTxHashFromFilecoinMessageCid(ctx context.Context, c cid.Cid, sa StateAPI return ethtypes.EmptyEthHash, nil } -func EthTxHashFromSignedFilecoinMessage(ctx context.Context, smsg *types.SignedMessage, sa StateAPI) (ethtypes.EthHash, error) { +func EthTxHashFromSignedMessage(ctx context.Context, smsg *types.SignedMessage, sa StateAPI) (ethtypes.EthHash, error) { if smsg.Signature.Type == crypto.SigTypeDelegated { - ethTx, err := NewEthTxFromFilecoinMessage(ctx, smsg, sa) + ethTx, err := newEthTxFromSignedMessage(ctx, smsg, sa) if err != nil { return ethtypes.EmptyEthHash, err } return ethTx.Hash, nil + } else if smsg.Signature.Type == crypto.SigTypeSecp256k1 { + return ethtypes.EthHashFromCid(smsg.Cid()) + } else { // BLS message + return ethtypes.EthHashFromCid(smsg.Message.Cid()) } - - return ethtypes.EthHashFromCid(smsg.Cid()) } -func NewEthTxFromFilecoinMessage(ctx context.Context, smsg *types.SignedMessage, sa StateAPI) (ethtypes.EthTx, error) { - // Ignore errors here so we can still parse non-eth messages - fromEthAddr, _ := lookupEthAddress(ctx, smsg.Message.From, sa) - toEthAddr, _ := lookupEthAddress(ctx, smsg.Message.To, sa) - - toAddr := &toEthAddr - input := smsg.Message.Params +func newEthTxFromSignedMessage(ctx context.Context, smsg *types.SignedMessage, sa StateAPI) (ethtypes.EthTx, error) { + var tx ethtypes.EthTx var err error - // Check to see if we need to decode as contract deployment. - // We don't need to resolve the to address, because there's only one form (an ID). - if smsg.Message.To == builtintypes.EthereumAddressManagerActorAddr { - switch smsg.Message.Method { - case builtintypes.MethodsEAM.Create: - toAddr = nil - var params eam.CreateParams - err = params.UnmarshalCBOR(bytes.NewReader(smsg.Message.Params)) - input = params.Initcode - case builtintypes.MethodsEAM.Create2: - toAddr = nil - var params eam.Create2Params - err = params.UnmarshalCBOR(bytes.NewReader(smsg.Message.Params)) - input = params.Initcode - case builtintypes.MethodsEAM.CreateExternal: - toAddr = nil - var params abi.CborBytes - err = params.UnmarshalCBOR(bytes.NewReader(smsg.Message.Params)) - input = []byte(params) - } - if err != nil { - return ethtypes.EthTx{}, err - } - } - // Otherwise, try to decode as a cbor byte array. - // TODO: Actually check if this is an ethereum call. This code will work for demo purposes, but is not correct. - if toAddr != nil { - if decodedParams, err := cbg.ReadByteArray(bytes.NewReader(smsg.Message.Params), uint64(len(smsg.Message.Params))); err == nil { - input = decodedParams - } - } - - r, s, v, err := ethtypes.RecoverSignature(smsg.Signature) - if err != nil { - // we don't want to return error if the message is not an Eth tx - r, s, v = ethtypes.EthBigIntZero, ethtypes.EthBigIntZero, ethtypes.EthBigIntZero - } - - tx := ethtypes.EthTx{ - Nonce: ethtypes.EthUint64(smsg.Message.Nonce), - ChainID: ethtypes.EthUint64(build.Eip155ChainId), - From: fromEthAddr, - To: toAddr, - Value: ethtypes.EthBigInt(smsg.Message.Value), - Type: ethtypes.EthUint64(2), - Input: input, - Gas: ethtypes.EthUint64(smsg.Message.GasLimit), - MaxFeePerGas: ethtypes.EthBigInt(smsg.Message.GasFeeCap), - MaxPriorityFeePerGas: ethtypes.EthBigInt(smsg.Message.GasPremium), - V: v, - R: r, - S: s, - } // This is an eth tx if smsg.Signature.Type == crypto.SigTypeDelegated { + tx, err = ethtypes.EthTxFromSignedEthMessage(smsg) + if err != nil { + return ethtypes.EthTx{}, xerrors.Errorf("failed to convert from signed message: %w", err) + } + tx.Hash, err = tx.TxHash() if err != nil { - return tx, err + return ethtypes.EthTx{}, xerrors.Errorf("failed to calculate hash for ethTx: %w", err) } - } else if smsg.Signature.Type == crypto.SigTypeUnknown { // BLS Filecoin message - tx.Hash, err = ethtypes.EthHashFromCid(smsg.Message.Cid()) + + fromAddr, err := lookupEthAddress(ctx, smsg.Message.From, sa) if err != nil { - return tx, err + return ethtypes.EthTx{}, xerrors.Errorf("failed to resolve Ethereum address: %w", err) } - } else { // Secp Filecoin Message + + tx.From = fromAddr + } else if smsg.Signature.Type == crypto.SigTypeSecp256k1 { // Secp Filecoin Message + tx = ethTxFromNativeMessage(ctx, smsg.VMMessage(), sa) tx.Hash, err = ethtypes.EthHashFromCid(smsg.Cid()) if err != nil { return tx, err } + } else { // BLS Filecoin message + tx = ethTxFromNativeMessage(ctx, smsg.VMMessage(), sa) + tx.Hash, err = ethtypes.EthHashFromCid(smsg.Message.Cid()) + if err != nil { + return tx, err + } } return tx, nil } -// newEthTxFromFilecoinMessageLookup creates an ethereum transaction from filecoin message lookup. If a negative txIdx is passed -// into the function, it looksup the transaction index of the message in the tipset, otherwise it uses the txIdx passed into the -// function -func newEthTxFromFilecoinMessageLookup(ctx context.Context, msgLookup *api.MsgLookup, txIdx int, cs *store.ChainStore, sa StateAPI) (ethtypes.EthTx, error) { - if msgLookup == nil { - return ethtypes.EthTx{}, fmt.Errorf("msg does not exist") +// ethTxFromNativeMessage does NOT populate: +// - BlockHash +// - BlockNumber +// - TransactionIndex +// - Hash +func ethTxFromNativeMessage(ctx context.Context, msg *types.Message, sa StateAPI) ethtypes.EthTx { + // We don't care if we error here, conversion is best effort for non-eth transactions + from, _ := lookupEthAddress(ctx, msg.From, sa) + to, _ := lookupEthAddress(ctx, msg.To, sa) + return ethtypes.EthTx{ + To: &to, + From: from, + Nonce: ethtypes.EthUint64(msg.Nonce), + ChainID: ethtypes.EthUint64(build.Eip155ChainId), + Value: ethtypes.EthBigInt(msg.Value), + Type: ethtypes.Eip1559TxType, + Gas: ethtypes.EthUint64(msg.GasLimit), + MaxFeePerGas: ethtypes.EthBigInt(msg.GasFeeCap), + MaxPriorityFeePerGas: ethtypes.EthBigInt(msg.GasPremium), } +} +// newEthTxFromMessageLookup creates an ethereum transaction from filecoin message lookup. If a negative txIdx is passed +// into the function, it looks up the transaction index of the message in the tipset, otherwise it uses the txIdx passed into the +// function +func newEthTxFromMessageLookup(ctx context.Context, msgLookup *api.MsgLookup, txIdx int, cs *store.ChainStore, sa StateAPI) (ethtypes.EthTx, error) { ts, err := cs.LoadTipSet(ctx, msgLookup.TipSet) if err != nil { return ethtypes.EthTx{}, err @@ -1689,13 +1812,13 @@ func newEthTxFromFilecoinMessageLookup(ctx context.Context, msgLookup *api.MsgLo smsg = &types.SignedMessage{ Message: *msg, Signature: crypto.Signature{ - Type: crypto.SigTypeUnknown, + Type: crypto.SigTypeBLS, Data: nil, }, } } - tx, err := NewEthTxFromFilecoinMessage(ctx, smsg, sa) + tx, err := newEthTxFromSignedMessage(ctx, smsg, sa) if err != nil { return ethtypes.EthTx{}, err } @@ -1741,9 +1864,24 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook LogsBloom: ethtypes.EmptyEthBloom[:], } + if lookup.Receipt.ExitCode.IsSuccess() { + receipt.Status = 1 + } + if lookup.Receipt.ExitCode.IsError() { + receipt.Status = 0 + } + + receipt.GasUsed = ethtypes.EthUint64(lookup.Receipt.GasUsed) + + // TODO: handle CumulativeGasUsed + receipt.CumulativeGasUsed = ethtypes.EmptyEthInt + + effectiveGasPrice := big.Div(replay.GasCost.TotalCost, big.NewInt(lookup.Receipt.GasUsed)) + receipt.EffectiveGasPrice = ethtypes.EthBigInt(effectiveGasPrice) + if receipt.To == nil && lookup.Receipt.ExitCode.IsSuccess() { // Create and Create2 return the same things. - var ret eam.CreateReturn + var ret eam.CreateExternalReturn if err := ret.UnmarshalCBOR(bytes.NewReader(lookup.Receipt.Return)); err != nil { return api.EthTxReceipt{}, xerrors.Errorf("failed to parse contract creation result: %w", err) } @@ -1751,13 +1889,6 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook receipt.ContractAddress = &addr } - if lookup.Receipt.ExitCode.IsSuccess() { - receipt.Status = 1 - } - if lookup.Receipt.ExitCode.IsError() { - receipt.Status = 0 - } - if len(events) > 0 { // TODO return a dummy non-zero bloom to signal that there are logs // need to figure out how worth it is to populate with a real bloom @@ -1776,7 +1907,10 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook } for _, entry := range evt.Entries { - value := ethtypes.EthBytes(leftpad32(entry.Value)) // value has already been cbor-decoded but see https://github.com/filecoin-project/ref-fvm/issues/1345 + value, err := cborDecodeTopicValue(entry.Value) + if err != nil { + return api.EthTxReceipt{}, xerrors.Errorf("failed to decode event log value: %w", err) + } if entry.Key == ethtypes.EthTopic1 || entry.Key == ethtypes.EthTopic2 || entry.Key == ethtypes.EthTopic3 || entry.Key == ethtypes.EthTopic4 { l.Topics = append(l.Topics, value) } else { @@ -1798,14 +1932,6 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook } } - receipt.GasUsed = ethtypes.EthUint64(lookup.Receipt.GasUsed) - - // TODO: handle CumulativeGasUsed - receipt.CumulativeGasUsed = ethtypes.EmptyEthInt - - effectiveGasPrice := big.Div(replay.GasCost.TotalCost, big.NewInt(lookup.Receipt.GasUsed)) - receipt.EffectiveGasPrice = ethtypes.EthBigInt(effectiveGasPrice) - return receipt, nil } @@ -1821,7 +1947,7 @@ func (m *EthTxHashManager) Apply(ctx context.Context, from, to *types.TipSet) er continue } - hash, err := EthTxHashFromSignedFilecoinMessage(ctx, smsg, m.StateAPI) + hash, err := EthTxHashFromSignedMessage(ctx, smsg, m.StateAPI) if err != nil { return err } @@ -1858,7 +1984,7 @@ func WaitForMpoolUpdates(ctx context.Context, ch <-chan api.MpoolUpdate, manager continue } - ethTx, err := NewEthTxFromFilecoinMessage(ctx, u.Message, manager.StateAPI) + ethTx, err := newEthTxFromSignedMessage(ctx, u.Message, manager.StateAPI) if err != nil { log.Errorf("error converting filecoin message to eth tx: %s", err) } @@ -1887,10 +2013,6 @@ func EthTxHashGC(ctx context.Context, retentionDays int, manager *EthTxHashManag } } -// TODO we could also emit full EVM words from the EVM runtime, but not doing so -// makes the contract slightly cheaper (and saves storage bytes), at the expense -// of having to left pad in the API, which is a pretty acceptable tradeoff at -// face value. There may be other protocol implications to consider. func leftpad32(orig []byte) []byte { needed := 32 - len(orig) if needed <= 0 { @@ -1900,3 +2022,51 @@ func leftpad32(orig []byte) []byte { copy(ret[needed:], orig) return ret } + +func trimLeadingZeros(b []byte) []byte { + for i := range b { + if b[i] != 0 { + return b[i:] + } + } + return []byte{} +} + +func cborEncodeTopicValue(orig []byte) ([]byte, error) { + var buf bytes.Buffer + err := cbg.WriteByteArray(&buf, trimLeadingZeros(orig)) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func cborDecodeTopicValue(orig []byte) ([]byte, error) { + if len(orig) == 0 { + return orig, nil + } + decoded, err := cbg.ReadByteArray(bytes.NewReader(orig), uint64(len(orig))) + if err != nil { + return nil, err + } + return leftpad32(decoded), nil +} + +func parseEthTopics(topics ethtypes.EthTopicSpec) (map[string][][]byte, error) { + keys := map[string][][]byte{} + for idx, vals := range topics { + if len(vals) == 0 { + continue + } + // Ethereum topics are emitted using `LOG{0..4}` opcodes resulting in topics1..4 + key := fmt.Sprintf("t%d", idx+1) + for _, v := range vals { + encodedVal, err := cborEncodeTopicValue(v[:]) + if err != nil { + return nil, xerrors.Errorf("failed to encode topic value") + } + keys[key] = append(keys[key], encodedVal) + } + } + return keys, nil +} diff --git a/node/impl/full/gas.go b/node/impl/full/gas.go index 435e2c65b55..c0e328bc94e 100644 --- a/node/impl/full/gas.go +++ b/node/impl/full/gas.go @@ -248,22 +248,23 @@ func (m *GasModule) GasEstimateGasLimit(ctx context.Context, msgIn *types.Messag } return gasEstimateGasLimit(ctx, m.Chain, m.Stmgr, m.Mpool, msgIn, ts) } -func gasEstimateGasLimit( + +// gasEstimateCallWithGas invokes a message "msgIn" on the earliest available tipset with pending +// messages in the message pool. The function returns the result of the message invocation, the +// pending messages, the tipset used for the invocation, and an error if occurred. +// The returned information can be used to make subsequent calls to CallWithGas with the same parameters. +func gasEstimateCallWithGas( ctx context.Context, cstore *store.ChainStore, smgr *stmgr.StateManager, mpool *messagepool.MessagePool, msgIn *types.Message, currTs *types.TipSet, -) (int64, error) { +) (*api.InvocResult, []types.ChainMsg, *types.TipSet, error) { msg := *msgIn - msg.GasLimit = build.BlockGasLimit - msg.GasFeeCap = big.Zero() - msg.GasPremium = big.Zero() - fromA, err := smgr.ResolveToDeterministicAddress(ctx, msgIn.From, currTs) if err != nil { - return -1, xerrors.Errorf("getting key address: %w", err) + return nil, []types.ChainMsg{}, nil, xerrors.Errorf("getting key address: %w", err) } pending, ts := mpool.PendingFor(ctx, fromA) @@ -284,12 +285,34 @@ func gasEstimateGasLimit( } ts, err = cstore.GetTipSetFromKey(ctx, ts.Parents()) if err != nil { - return -1, xerrors.Errorf("getting parent tipset: %w", err) + return nil, []types.ChainMsg{}, nil, xerrors.Errorf("getting parent tipset: %w", err) } } if err != nil { - return -1, xerrors.Errorf("CallWithGas failed: %w", err) + return nil, []types.ChainMsg{}, nil, xerrors.Errorf("CallWithGas failed: %w", err) } + + return res, priorMsgs, ts, nil +} + +func gasEstimateGasLimit( + ctx context.Context, + cstore *store.ChainStore, + smgr *stmgr.StateManager, + mpool *messagepool.MessagePool, + msgIn *types.Message, + currTs *types.TipSet, +) (int64, error) { + msg := *msgIn + msg.GasLimit = build.BlockGasLimit + msg.GasFeeCap = big.Zero() + msg.GasPremium = big.Zero() + + res, _, ts, err := gasEstimateCallWithGas(ctx, cstore, smgr, mpool, &msg, currTs) + if err != nil { + return -1, xerrors.Errorf("gas estimation failed: %w", err) + } + if res.MsgRct.ExitCode == exitcode.SysErrOutOfGas { return -1, &api.ErrOutOfGas{} } @@ -300,6 +323,8 @@ func gasEstimateGasLimit( ret := res.MsgRct.GasUsed + log.Infow("GasEstimateMessageGas CallWithGas Result", "GasUsed", ret, "ExitCode", res.MsgRct.ExitCode) + transitionalMulti := 1.0 // Overestimate gas around the upgrade if ts.Height() <= build.UpgradeSkyrHeight && (build.UpgradeSkyrHeight-ts.Height() <= 20) { diff --git a/node/modules/actorevent.go b/node/modules/actorevent.go index eb5afb8e659..55a79a59a97 100644 --- a/node/modules/actorevent.go +++ b/node/modules/actorevent.go @@ -40,6 +40,7 @@ func EthEventAPI(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRepo ee := &full.EthEvent{ Chain: cs, MaxFilterHeightRange: abi.ChainEpoch(cfg.Events.MaxFilterHeightRange), + SubscribtionCtx: ctx, } if !cfg.EnableEthRPC || cfg.Events.DisableRealTimeFilterAPI { diff --git a/node/modules/chain.go b/node/modules/chain.go index 2be840266b7..f304ab135c6 100644 --- a/node/modules/chain.go +++ b/node/modules/chain.go @@ -181,3 +181,7 @@ func NewSlashFilter(ds dtypes.MetadataDS) *slashfilter.SlashFilter { func UpgradeSchedule() stmgr.UpgradeSchedule { return filcns.DefaultUpgradeSchedule() } + +func EnableStoringEvents(cs *store.ChainStore) { + cs.StoreEvents(true) +} diff --git a/node/rpc.go b/node/rpc.go index 1dab2a61f24..cacd33526c8 100644 --- a/node/rpc.go +++ b/node/rpc.go @@ -75,7 +75,7 @@ func FullNodeHandler(a v1api.FullNode, permissioned bool, opts ...jsonrpc.Server m := mux.NewRouter() serveRpc := func(path string, hnd interface{}) { - rpcServer := jsonrpc.NewServer(append(opts, jsonrpc.WithServerErrors(api.RPCErrors))...) + rpcServer := jsonrpc.NewServer(append(opts, jsonrpc.WithReverseClient[api.EthSubscriberMethods]("Filecoin"), jsonrpc.WithServerErrors(api.RPCErrors))...) rpcServer.Register("Filecoin", hnd) rpcServer.AliasMethod("rpc.discover", "Filecoin.Discover")