Merge pull request #10184 from filecoin-project/asr/merge-release-into-master
chore: merge release/v1.20.0 into master
This commit is contained in:
commit
cb8e2836bb
@ -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:
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
1202
api/proxy_gen.go
1202
api/proxy_gen.go
File diff suppressed because it is too large
Load Diff
@ -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 {
|
||||
|
Binary file not shown.
@ -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"),
|
||||
},
|
||||
}}
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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,
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
|
@ -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{}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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{}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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):
|
||||
|
@ -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())
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
72
cmd/lotus-shed/eth.go
Normal file
72
cmd/lotus-shed/eth.go
Normal file
@ -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
|
||||
},
|
||||
}
|
@ -51,6 +51,7 @@ func main() {
|
||||
minerCmd,
|
||||
mpoolStatsCmd,
|
||||
exportChainCmd,
|
||||
ethCmd,
|
||||
exportCarCmd,
|
||||
consensusCmd,
|
||||
syncCmd,
|
||||
|
@ -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"`
|
||||
|
||||
|
2
extern/filecoin-ffi
vendored
2
extern/filecoin-ffi
vendored
@ -1 +1 @@
|
||||
Subproject commit 86eac2161f442945bffee3fbfe7d094c20b48dd3
|
||||
Subproject commit 0c792ee1d1f062377033d7d37442d18f765be467
|
71
gateway/eth_sub.go
Normal file
71
gateway/eth_sub.go
Normal file
@ -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)
|
@ -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)
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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++ {
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
@ -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}}
|
||||
|
10
go.mod
10
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
|
||||
|
35
go.sum
35
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=
|
||||
|
1
itests/contracts/AutoSelfDestruct.hex
Normal file
1
itests/contracts/AutoSelfDestruct.hex
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b5061001f61002460201b60201c565b61003d565b3373ffffffffffffffffffffffffffffffffffffffff16ff5b60848061004b6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806383197ef014602d575b600080fd5b60336035565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea26469706673582212208d48a69a112633756d84552847610df29b02ac89dd39e4e295066e99a45e809664736f6c63430008110033
|
11
itests/contracts/AutoSelfDestruct.sol
Normal file
11
itests/contracts/AutoSelfDestruct.sol
Normal file
@ -0,0 +1,11 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.8.17;
|
||||
|
||||
contract AutoSelfDestruct {
|
||||
constructor() {
|
||||
destroy();
|
||||
}
|
||||
function destroy() public {
|
||||
selfdestruct(payable(msg.sender));
|
||||
}
|
||||
}
|
1
itests/contracts/Constructor.hex
Normal file
1
itests/contracts/Constructor.hex
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b506103ca806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c806358f5ebb614610030575b600080fd5b61004a60048036038101906100459190610123565b610060565b6040516100579190610191565b60405180910390f35b60008082604051610070906100db565b61007a91906101bb565b604051809103906000f080158015610096573d6000803e3d6000fd5b5090507f3a5c468996b00310e3e82919e3af9cce21d49c40c39a2627a9f946e1a54d886232846040516100ca9291906101d6565b60405180910390a180915050919050565b6101958061020083390190565b600080fd5b6000819050919050565b610100816100ed565b811461010b57600080fd5b50565b60008135905061011d816100f7565b92915050565b600060208284031215610139576101386100e8565b5b60006101478482850161010e565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061017b82610150565b9050919050565b61018b81610170565b82525050565b60006020820190506101a66000830184610182565b92915050565b6101b5816100ed565b82525050565b60006020820190506101d060008301846101ac565b92915050565b60006040820190506101eb6000830185610182565b6101f860208301846101ac565b939250505056fe608060405234801561001057600080fd5b506040516101953803806101958339818101604052810190610032919061007a565b80600081905550506100a7565b600080fd5b6000819050919050565b61005781610044565b811461006257600080fd5b50565b6000815190506100748161004e565b92915050565b6000602082840312156100905761008f61003f565b5b600061009e84828501610065565b91505092915050565b60e0806100b56000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80638381f58a146037578063eeb4e367146051575b600080fd5b603d606b565b604051604891906091565b60405180910390f35b60576071565b604051606291906091565b60405180910390f35b60005481565b60008054905090565b6000819050919050565b608b81607a565b82525050565b600060208201905060a460008301846084565b9291505056fea2646970667358221220451c388f24a935fc5f5eef536207cbd982254ac8521d49937bb10e5079e3924164736f6c63430008110033a264697066735822122027da159d84a9bdcd5aff5755c4602f7099db638f7a95d715c76454c99511146f64736f6c63430008110033
|
29
itests/contracts/Constructor.sol
Normal file
29
itests/contracts/Constructor.sol
Normal file
@ -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;
|
||||
}
|
||||
}
|
@ -1 +1 @@
|
||||
608060405234801561001057600080fd5b50610477806100206000396000f3fe6080604052600436106100345760003560e01c806361bc221a146100395780638ada066e14610064578063d1e0f3081461008f575b600080fd5b34801561004557600080fd5b5061004e6100bf565b60405161005b919061022c565b60405180910390f35b34801561007057600080fd5b506100796100c5565b604051610086919061022c565b60405180910390f35b6100a960048036038101906100a491906102d6565b6100ce565b6040516100b6919061022c565b60405180910390f35b60005481565b60008054905090565b6000808373ffffffffffffffffffffffffffffffffffffffff16836040516024016100f9919061022c565b6040516020818303038152906040527f6466414b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516101839190610387565b600060405180830381855af49150503d80600081146101be576040519150601f19603f3d011682016040523d82523d6000602084013e6101c3565b606091505b5050905080610207576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101fe90610421565b60405180910390fd5b60005491505092915050565b6000819050919050565b61022681610213565b82525050565b6000602082019050610241600083018461021d565b92915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102778261024c565b9050919050565b6102878161026c565b811461029257600080fd5b50565b6000813590506102a48161027e565b92915050565b6102b381610213565b81146102be57600080fd5b50565b6000813590506102d0816102aa565b92915050565b600080604083850312156102ed576102ec610247565b5b60006102fb85828601610295565b925050602061030c858286016102c1565b9150509250929050565b600081519050919050565b600081905092915050565b60005b8381101561034a57808201518184015260208101905061032f565b60008484015250505050565b600061036182610316565b61036b8185610321565b935061037b81856020860161032c565b80840191505092915050565b60006103938284610356565b915081905092915050565b600082825260208201905092915050565b7f4572726f72206d6573736167653a2044656c656761746563616c6c206661696c60008201527f6564000000000000000000000000000000000000000000000000000000000000602082015250565b600061040b60228361039e565b9150610416826103af565b604082019050919050565b6000602082019050818103600083015261043a816103fe565b905091905056fea26469706673582212203663909b8221e9b87047be99420c00339af1430c085260df209b909ed8e0f05164736f6c63430008110033
|
||||
608060405234801561001057600080fd5b5061087e806100206000396000f3fe6080604052600436106100555760003560e01c80630712ede21461005a57806361bc221a1461008a5780637da3c3ab146100b55780638ada066e146100cc578063bed56f47146100f7578063d1e0f30814610127575b600080fd5b610074600480360381019061006f919061060f565b610157565b604051610081919061065e565b60405180910390f35b34801561009657600080fd5b5061009f610298565b6040516100ac919061065e565b60405180910390f35b3480156100c157600080fd5b506100ca61029e565b005b3480156100d857600080fd5b506100e16102e1565b6040516100ee919061065e565b60405180910390f35b610111600480360381019061010c919061060f565b6102ea565b60405161011e919061065e565b60405180910390f35b610141600480360381019061013c919061060f565b610431565b60405161014e919061065e565b60405180910390f35b6000808373ffffffffffffffffffffffffffffffffffffffff1683604051602401610182919061065e565b6040516020818303038152906040527f6466414b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161020c91906106ea565b600060405180830381855af49150503d8060008114610247576040519150601f19603f3d011682016040523d82523d6000602084013e61024c565b606091505b505090506000610291576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102889061075e565b60405180910390fd5b5092915050565b60005481565b60006102df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d69061075e565b60405180910390fd5b565b60008054905090565b6000808373ffffffffffffffffffffffffffffffffffffffff16848460405160240161031792919061078d565b6040516020818303038152906040527fbed56f47000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516103a191906106ea565b600060405180830381855af49150503d80600081146103dc576040519150601f19603f3d011682016040523d82523d6000602084013e6103e1565b606091505b5050905080610425576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161041c90610828565b60405180910390fd5b60005491505092915050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160240161045c919061065e565b6040516020818303038152906040527f6466414b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516104e691906106ea565b600060405180830381855af49150503d8060008114610521576040519150601f19603f3d011682016040523d82523d6000602084013e610526565b606091505b505090508061056a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161056190610828565b60405180910390fd5b60005491505092915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006105a68261057b565b9050919050565b6105b68161059b565b81146105c157600080fd5b50565b6000813590506105d3816105ad565b92915050565b6000819050919050565b6105ec816105d9565b81146105f757600080fd5b50565b600081359050610609816105e3565b92915050565b6000806040838503121561062657610625610576565b5b6000610634858286016105c4565b9250506020610645858286016105fa565b9150509250929050565b610658816105d9565b82525050565b6000602082019050610673600083018461064f565b92915050565b600081519050919050565b600081905092915050565b60005b838110156106ad578082015181840152602081019050610692565b60008484015250505050565b60006106c482610679565b6106ce8185610684565b93506106de81856020860161068f565b80840191505092915050565b60006106f682846106b9565b915081905092915050565b600082825260208201905092915050565b7f696e74656e74696f6e616c6c79207468726f77696e67206572726f7200000000600082015250565b6000610748601c83610701565b915061075382610712565b602082019050919050565b600060208201905081810360008301526107778161073b565b9050919050565b6107878161059b565b82525050565b60006040820190506107a2600083018561077e565b6107af602083018461064f565b9392505050565b7f4572726f72206d6573736167653a2044656c656761746563616c6c206661696c60008201527f6564000000000000000000000000000000000000000000000000000000000000602082015250565b6000610812602283610701565b915061081d826107b6565b604082019050919050565b6000602082019050818103600083015261084181610805565b905091905056fea2646970667358221220b2a3ae7e2a9ffc78e3e2a7aadb2885435c5e51aa9d3f07372a0dffb6238aa1db64736f6c63430008110033
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
608060405234801561001057600080fd5b506105eb806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c8063c755553811610071578063c755553814610198578063cbfc3b58146101c6578063cc6f8faf14610212578063cd5b6c3d14610254578063e2a614731461028c578063fb62b28b146102d8576100a9565b80630919b8be146100ae5780636199074d146100e657806366eef3461461012857806375091b1f14610132578063a63ae81a1461016a575b600080fd5b6100e4600480360360408110156100c457600080fd5b81019080803590602001909291908035906020019092919050505061031a565b005b610126600480360360608110156100fc57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919050505061035d565b005b610130610391565b005b6101686004803603604081101561014857600080fd5b8101908080359060200190929190803590602001909291905050506103bf565b005b6101966004803603602081101561018057600080fd5b81019080803590602001909291905050506103fb565b005b6101c4600480360360208110156101ae57600080fd5b8101908080359060200190929190505050610435565b005b610210600480360360808110156101dc57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919080359060200190929190505050610465565b005b6102526004803603606081101561022857600080fd5b810190808035906020019092919080359060200190929190803590602001909291905050506104ba565b005b61028a6004803603604081101561026a57600080fd5b8101908080359060200190929190803590602001909291905050506104f8565b005b6102d6600480360360808110156102a257600080fd5b810190808035906020019092919080359060200190929190803590602001909291908035906020019092919050505061052a565b005b610318600480360360608110156102ee57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919050505061056a565b005b7f5469c6b769315f5668523937f05ca07d4cc87849432bc5f5907f1d90fa73b9f98282604051808381526020018281526020019250505060405180910390a15050565b8082847fb89dabcdb7ff41f1794c0da92f65ece6c19b6b0caeac5407b2a721efe27c080460405160405180910390a4505050565b7fc3f6f1c76bd4e74ee5782052b0b4f8bd5c50b86c3c5a2f52638e03066e50a91b60405160405180910390a1565b817f6709824ebe5f6e620ca3f4b02a3428e8ce2dc97c550816eaeeb3a342b214bd85826040518082815260200191505060405180910390a25050565b7fc804e53d6048af1b3e6a352e246d5f3864fea9d635ace499e023a58c383b3a88816040518082815260200191505060405180910390a150565b807f44a227a31429ab5eb00daf6611c6422f10571619f2267e0e149e9ebe6d2a5d0560405160405180910390a250565b7f28d45631a87b2a52a9625f8520fa37ff8c4d926cdf17042e241985da5cb7b850848484846040518085815260200184815260200183815260200182815260200194505050505060405180910390a150505050565b81837fcd5fe5fbc1d27b90036997224cea7aa565e3779622867265081f636b3a5ccb08836040518082815260200191505060405180910390a3505050565b80827f232f09cef3babc26e58d1cc1346c0a8bc626ffe600c9605b5d747783eda484a760405160405180910390a35050565b8183857f812e73dbcf7e267f27ecb1383bfc902a6650b41b6e7d03ac265108c369673d95846040518082815260200191505060405180910390a450505050565b7fd4d143faaf60340ad98e1f2c96fc26f5695834c21b5200edad339ee7e9a372cc83838360405180848152602001838152602001828152602001935050505060405180910390a150505056fea265627a7a72315820954561fde80ab925299e0a9f3356b01f64fb1976dd335ac2ebd9367441e29f0564736f6c63430005110032
|
||||
608060405234801561001057600080fd5b506106af806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c8063c755553811610071578063c755553814610128578063cbfc3b5814610144578063cc6f8faf14610160578063cd5b6c3d1461017c578063e2a6147314610198578063fb62b28b146101b4576100a9565b80630919b8be146100ae5780636199074d146100ca57806366eef346146100e657806375091b1f146100f0578063a63ae81a1461010c575b600080fd5b6100c860048036038101906100c39190610483565b6101d0565b005b6100e460048036038101906100df91906104c3565b61020d565b005b6100ee610241565b005b61010a60048036038101906101059190610483565b61026f565b005b61012660048036038101906101219190610516565b6102ab565b005b610142600480360381019061013d9190610516565b6102e5565b005b61015e60048036038101906101599190610543565b610315565b005b61017a600480360381019061017591906104c3565b610358565b005b61019660048036038101906101919190610483565b610396565b005b6101b260048036038101906101ad9190610543565b6103c8565b005b6101ce60048036038101906101c991906104c3565b610408565b005b7f5469c6b769315f5668523937f05ca07d4cc87849432bc5f5907f1d90fa73b9f982826040516102019291906105b9565b60405180910390a15050565b8082847fb89dabcdb7ff41f1794c0da92f65ece6c19b6b0caeac5407b2a721efe27c080460405160405180910390a4505050565b7fc3f6f1c76bd4e74ee5782052b0b4f8bd5c50b86c3c5a2f52638e03066e50a91b60405160405180910390a1565b817f6709824ebe5f6e620ca3f4b02a3428e8ce2dc97c550816eaeeb3a342b214bd858260405161029f91906105e2565b60405180910390a25050565b7fc804e53d6048af1b3e6a352e246d5f3864fea9d635ace499e023a58c383b3a88816040516102da91906105e2565b60405180910390a150565b807f44a227a31429ab5eb00daf6611c6422f10571619f2267e0e149e9ebe6d2a5d0560405160405180910390a250565b7f28d45631a87b2a52a9625f8520fa37ff8c4d926cdf17042e241985da5cb7b8508484848460405161034a94939291906105fd565b60405180910390a150505050565b81837fcd5fe5fbc1d27b90036997224cea7aa565e3779622867265081f636b3a5ccb088360405161038991906105e2565b60405180910390a3505050565b80827f232f09cef3babc26e58d1cc1346c0a8bc626ffe600c9605b5d747783eda484a760405160405180910390a35050565b8183857f812e73dbcf7e267f27ecb1383bfc902a6650b41b6e7d03ac265108c369673d95846040516103fa91906105e2565b60405180910390a450505050565b7fd4d143faaf60340ad98e1f2c96fc26f5695834c21b5200edad339ee7e9a372cc83838360405161043b93929190610642565b60405180910390a1505050565b600080fd5b6000819050919050565b6104608161044d565b811461046b57600080fd5b50565b60008135905061047d81610457565b92915050565b6000806040838503121561049a57610499610448565b5b60006104a88582860161046e565b92505060206104b98582860161046e565b9150509250929050565b6000806000606084860312156104dc576104db610448565b5b60006104ea8682870161046e565b93505060206104fb8682870161046e565b925050604061050c8682870161046e565b9150509250925092565b60006020828403121561052c5761052b610448565b5b600061053a8482850161046e565b91505092915050565b6000806000806080858703121561055d5761055c610448565b5b600061056b8782880161046e565b945050602061057c8782880161046e565b935050604061058d8782880161046e565b925050606061059e8782880161046e565b91505092959194509250565b6105b38161044d565b82525050565b60006040820190506105ce60008301856105aa565b6105db60208301846105aa565b9392505050565b60006020820190506105f760008301846105aa565b92915050565b600060808201905061061260008301876105aa565b61061f60208301866105aa565b61062c60408301856105aa565b61063960608301846105aa565b95945050505050565b600060608201905061065760008301866105aa565b61066460208301856105aa565b61067160408301846105aa565b94935050505056fea26469706673582212201b2f4de851da592b926eb2cd07ccfbbd02270fde6dee2459ba942e5dcf5685d364736f6c63430008110033
|
@ -1,4 +1,5 @@
|
||||
pragma solidity ^0.5.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.5.0;
|
||||
|
||||
contract EventMatrix {
|
||||
event EventZeroData();
|
||||
|
1
itests/contracts/ExternalRecursiveCallSimple.hex
Normal file
1
itests/contracts/ExternalRecursiveCallSimple.hex
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b506101ee806100206000396000f3fe60806040526004361061001e5760003560e01c8063c38e07dd14610023575b600080fd5b61003d600480360381019061003891906100fe565b61003f565b005b60008111156100c0573073ffffffffffffffffffffffffffffffffffffffff1663c38e07dd600183610071919061015a565b6040518263ffffffff1660e01b815260040161008d919061019d565b600060405180830381600087803b1580156100a757600080fd5b505af11580156100bb573d6000803e3d6000fd5b505050505b50565b600080fd5b6000819050919050565b6100db816100c8565b81146100e657600080fd5b50565b6000813590506100f8816100d2565b92915050565b600060208284031215610114576101136100c3565b5b6000610122848285016100e9565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610165826100c8565b9150610170836100c8565b92508282039050818111156101885761018761012b565b5b92915050565b610197816100c8565b82525050565b60006020820190506101b2600083018461018e565b9291505056fea264697066735822122033d012e17f5d7a62bb724021b5c4e0d109aeb28d1cd5b5c0a0b1b801c0b5032164736f6c63430008110033
|
13
itests/contracts/ExternalRecursiveCallSimple.sol
Normal file
13
itests/contracts/ExternalRecursiveCallSimple.sol
Normal file
@ -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;
|
||||
}
|
||||
}
|
1
itests/contracts/GasLimitSend.hex
Normal file
1
itests/contracts/GasLimitSend.hex
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b5061027c806100206000396000f3fe6080604052600436106100385760003560e01c80630bc07a88146100435780633da767881461005a578063f0ba84401461008557610039565b5b6100416100c2565b005b34801561004f57600080fd5b506100586100c2565b005b34801561006657600080fd5b5061006f61010d565b60405161007c9190610156565b60405180910390f35b34801561009157600080fd5b506100ac60048036038101906100a791906101a2565b610119565b6040516100b99190610156565b60405180910390f35b60005b606481101561010a5760008190806001815401808255809150506001900390600052602060002001600090919091909150558080610102906101fe565b9150506100c5565b50565b60008080549050905090565b6000818154811061012957600080fd5b906000526020600020016000915090505481565b6000819050919050565b6101508161013d565b82525050565b600060208201905061016b6000830184610147565b92915050565b600080fd5b61017f8161013d565b811461018a57600080fd5b50565b60008135905061019c81610176565b92915050565b6000602082840312156101b8576101b7610171565b5b60006101c68482850161018d565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006102098261013d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361023b5761023a6101cf565b5b60018201905091905056fea2646970667358221220c56d78e0c60a01681eee1b76c95e7b214d16a512c944e31cfee71eb727c1e44064736f6c63430008110033
|
34
itests/contracts/GasLimitSend.sol
Normal file
34
itests/contracts/GasLimitSend.sol
Normal file
@ -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;
|
||||
}
|
||||
}
|
1
itests/contracts/GasSendTest.hex
Normal file
1
itests/contracts/GasSendTest.hex
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b5060b68061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80630c55699c14602d575b600080fd5b60336047565b604051603e91906067565b60405180910390f35b60006007905090565b6000819050919050565b6061816050565b82525050565b6000602082019050607a6000830184605a565b9291505056fea2646970667358221220c0f2da1b01178b54afba1ddf14f30307a03cdb66f61b4e1dc342079561db009064736f6c63430008110033
|
9
itests/contracts/GasSendTest.sol
Normal file
9
itests/contracts/GasSendTest.sol
Normal file
@ -0,0 +1,9 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.17;
|
||||
|
||||
contract GasLimitTestReceiver {
|
||||
function x() public returns (uint256){
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
|
1
itests/contracts/NotPayable.hex
Normal file
1
itests/contracts/NotPayable.hex
Normal file
@ -0,0 +1 @@
|
||||
6080604052348015600f57600080fd5b50604780601d6000396000f3fe6080604052348015600f57600080fd5b00fea26469706673582212200cd38951eddebe3692dc8921afb65a04fbe64e10d5e261806330156459bf227264736f6c63430008110033
|
7
itests/contracts/NotPayable.sol
Normal file
7
itests/contracts/NotPayable.sol
Normal file
@ -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 {}
|
||||
}
|
1
itests/contracts/RecCall.hex
Normal file
1
itests/contracts/RecCall.hex
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b5061025b806100206000396000f3fe60806040526004361061001e5760003560e01c8063cb7786d714610023575b600080fd5b61003d60048036038101906100389190610129565b61003f565b005b600083036100d15760008111156100cc573073ffffffffffffffffffffffffffffffffffffffff1663cb7786d7838460018561007b91906101ab565b6040518463ffffffff1660e01b8152600401610099939291906101ee565b600060405180830381600087803b1580156100b357600080fd5b505af11580156100c7573d6000803e3d6000fd5b505050505b6100e9565b6100e86001846100e191906101ab565b838361003f565b5b505050565b600080fd5b6000819050919050565b610106816100f3565b811461011157600080fd5b50565b600081359050610123816100fd565b92915050565b600080600060608486031215610142576101416100ee565b5b600061015086828701610114565b935050602061016186828701610114565b925050604061017286828701610114565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006101b6826100f3565b91506101c1836100f3565b92508282039050818111156101d9576101d861017c565b5b92915050565b6101e8816100f3565b82525050565b600060608201905061020360008301866101df565b61021060208301856101df565b61021d60408301846101df565b94935050505056fea26469706673582212209a21ff59c642e2970917c07bf498271c2a6df8e3929677952c0c2d8031db15cc64736f6c63430008110033
|
16
itests/contracts/RecCall.sol
Normal file
16
itests/contracts/RecCall.sol
Normal file
@ -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);
|
||||
}
|
||||
}
|
1
itests/contracts/Recursive.hex
Normal file
1
itests/contracts/Recursive.hex
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b506102d9806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063032cec451461005c57806372536f3c1461007a57806399fdb86e14610098578063d2aac3ea146100b6578063ec49254c146100d4575b600080fd5b610064610104565b60405161007191906101c7565b60405180910390f35b610082610115565b60405161008f91906101c7565b60405180910390f35b6100a0610126565b6040516100ad91906101c7565b60405180910390f35b6100be610137565b6040516100cb91906101c7565b60405180910390f35b6100ee60048036038101906100e99190610213565b610148565b6040516100fb91906101c7565b60405180910390f35b60006101106001610148565b905090565b6000610121600a610148565b905090565b60006101326002610148565b905090565b60006101436000610148565b905090565b6000808211156101a5577f3110e0ccd510fcbb471c933ad12161c459e8735b5bde2eea61a659c2e2f0a3cc8260405161018191906101c7565b60405180910390a161019e600183610199919061026f565b610148565b90506101a9565b8190505b919050565b6000819050919050565b6101c1816101ae565b82525050565b60006020820190506101dc60008301846101b8565b92915050565b600080fd5b6101f0816101ae565b81146101fb57600080fd5b50565b60008135905061020d816101e7565b92915050565b600060208284031215610229576102286101e2565b5b6000610237848285016101fe565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061027a826101ae565b9150610285836101ae565b925082820390508181111561029d5761029c610240565b5b9291505056fea26469706673582212206178e15eb87e2f766b94ec09a6a860878c93d72a31de225e1684da1755f917c764736f6c63430008110033
|
26
itests/contracts/Recursive.sol
Normal file
26
itests/contracts/Recursive.sol
Normal file
@ -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;
|
||||
}
|
||||
}
|
1
itests/contracts/RecursiveDelegeatecall.hex
Normal file
1
itests/contracts/RecursiveDelegeatecall.hex
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b50610459806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80633af3f24f1461003b578063ec49254c14610059575b600080fd5b610043610089565b6040516100509190610221565b60405180910390f35b610073600480360381019061006e919061026d565b61008f565b6040516100809190610221565b60405180910390f35b60005481565b60007faab69767807d0ab32f0099452739da31b76ecd3e8694bb49898829c8bf9d063582306040516100c29291906102db565b60405180910390a160016000808282546100dc9190610333565b9250508190555060018211156101ff576001826100f99190610367565b91506000803073ffffffffffffffffffffffffffffffffffffffff16846040516024016101269190610221565b6040516020818303038152906040527fec49254c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516101b0919061040c565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b50915091508392505050610203565b8190505b919050565b6000819050919050565b61021b81610208565b82525050565b60006020820190506102366000830184610212565b92915050565b600080fd5b61024a81610208565b811461025557600080fd5b50565b60008135905061026781610241565b92915050565b6000602082840312156102835761028261023c565b5b600061029184828501610258565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102c58261029a565b9050919050565b6102d5816102ba565b82525050565b60006040820190506102f06000830185610212565b6102fd60208301846102cc565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061033e82610208565b915061034983610208565b925082820190508082111561036157610360610304565b5b92915050565b600061037282610208565b915061037d83610208565b925082820390508181111561039557610394610304565b5b92915050565b600081519050919050565b600081905092915050565b60005b838110156103cf5780820151818401526020810190506103b4565b60008484015250505050565b60006103e68261039b565b6103f081856103a6565b93506104008185602086016103b1565b80840191505092915050565b600061041882846103db565b91508190509291505056fea2646970667358221220e70fbbfaccd3fbb084623d6d06895fba1abc5fefc181215b56ab1e43db79c7fb64736f6c63430008110033
|
21
itests/contracts/RecursiveDelegeatecall.sol
Normal file
21
itests/contracts/RecursiveDelegeatecall.sol
Normal file
@ -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;
|
||||
}
|
||||
}
|
1
itests/contracts/SelfDestruct.hex
Normal file
1
itests/contracts/SelfDestruct.hex
Normal file
@ -0,0 +1 @@
|
||||
6080604052348015600f57600080fd5b5060848061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806383197ef014602d575b600080fd5b60336035565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea2646970667358221220d4aa109d42268586e7ce4f0fafb0ebbd04c412c6c7e8c387b009a08ecdff864264736f6c63430008110033
|
8
itests/contracts/SelfDestruct.sol
Normal file
8
itests/contracts/SelfDestruct.sol
Normal file
@ -0,0 +1,8 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.8.17;
|
||||
|
||||
contract SelfDestruct {
|
||||
function destroy() public {
|
||||
selfdestruct(payable(msg.sender));
|
||||
}
|
||||
}
|
1
itests/contracts/StackFunc.hex
Normal file
1
itests/contracts/StackFunc.hex
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b50610162806100206000396000f3fe60806040526004361061001e5760003560e01c8063c38e07dd14610023575b600080fd5b61003d6004803603810190610038919061009c565b61003f565b005b600081031561005e5761005d60018261005891906100f8565b61003f565b5b50565b600080fd5b6000819050919050565b61007981610066565b811461008457600080fd5b50565b60008135905061009681610070565b92915050565b6000602082840312156100b2576100b1610061565b5b60006100c084828501610087565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061010382610066565b915061010e83610066565b9250828203905081811115610126576101256100c9565b5b9291505056fea2646970667358221220ee8f18bfd33b1e0156cfe68e9071dd32960b370c7e63ec53c62dd48e28cb5d3b64736f6c63430008110033
|
12
itests/contracts/StackFunc.sol
Normal file
12
itests/contracts/StackFunc.sol
Normal file
@ -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);
|
||||
}
|
||||
}
|
1
itests/contracts/TestApp.hex
Normal file
1
itests/contracts/TestApp.hex
Normal file
File diff suppressed because one or more lines are too long
211
itests/contracts/TestApp.sol
Normal file
211
itests/contracts/TestApp.sol
Normal file
@ -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
|
||||
});
|
||||
}
|
||||
}
|
1
itests/contracts/ValueSender.hex
Normal file
1
itests/contracts/ValueSender.hex
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b506106dc806100206000396000f3fe60806040526004361061002d5760003560e01c8063dbdc275d14610072578063fd75295a1461009d5761006d565b3661006d577f34fb9cb8f63eaccc6c0beefc202db703e529c3bf9ce83f485b398af7fd679308333460405161006392919061020f565b60405180910390a1005b600080fd5b34801561007e57600080fd5b506100876100b9565b6040516100949190610238565b60405180910390f35b6100b760048036038101906100b29190610296565b610125565b005b6000806040516100c8906101a8565b604051809103906000f0801580156100e4573d6000803e3d6000fd5b5090507f8db3b20eed31d927a4f613b5c11765212e129cf726d025649650665569ea683b816040516101169190610238565b60405180910390a18091505090565b7f34fb9cb8f63eaccc6c0beefc202db703e529c3bf9ce83f485b398af7fd6793088134604051610156929190610322565b60405180910390a18073ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501580156101a4573d6000803e3d6000fd5b5050565b61035b8061034c83390190565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101e0826101b5565b9050919050565b6101f0816101d5565b82525050565b6000819050919050565b610209816101f6565b82525050565b600060408201905061022460008301856101e7565b6102316020830184610200565b9392505050565b600060208201905061024d60008301846101e7565b92915050565b600080fd5b6000610263826101b5565b9050919050565b61027381610258565b811461027e57600080fd5b50565b6000813590506102908161026a565b92915050565b6000602082840312156102ac576102ab610253565b5b60006102ba84828501610281565b91505092915050565b6000819050919050565b60006102e86102e36102de846101b5565b6102c3565b6101b5565b9050919050565b60006102fa826102cd565b9050919050565b600061030c826102ef565b9050919050565b61031c81610301565b82525050565b60006040820190506103376000830185610313565b6103446020830184610200565b939250505056fe608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102fb806100606000396000f3fe60806040526004361061002d5760003560e01c806337cb6570146100725780639cb8a26a1461007c5761006d565b3661006d577fe1494f56a1ccfd8c7361f2ca5b8fd2b1a2fe11773821ac29534f09f4a0637d603334604051610063929190610214565b60405180910390a1005b600080fd5b61007a610093565b005b34801561008857600080fd5b50610091610155565b005b7f76cff203b0794a9e9013657ecb172f2d6e8de5941fd11a6bfbc0fb6014a5f07960008054906101000a900473ffffffffffffffffffffffffffffffffffffffff16476040516100e492919061029c565b60405180910390a160008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f19350505050158015610152573d6000803e3d6000fd5b50565b7f1cbd47e7b0f55dc1a45ba8ebada53eaa1712b3e3e86f49a12c008ff22334569060405160405180910390a160008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101e5826101ba565b9050919050565b6101f5816101da565b82525050565b6000819050919050565b61020e816101fb565b82525050565b600060408201905061022960008301856101ec565b6102366020830184610205565b9392505050565b6000819050919050565b600061026261025d610258846101ba565b61023d565b6101ba565b9050919050565b600061027482610247565b9050919050565b600061028682610269565b9050919050565b6102968161027b565b82525050565b60006040820190506102b1600083018561028d565b6102be6020830184610205565b939250505056fea2646970667358221220bdf21908b1c91973a8440fe81130e0077cf83c8f8e9a053d8a0c3063391aa40764736f6c63430008110033a26469706673582212202e514fe078dfcf4f1142a088c57cfa71ada74d72ee0cc4a46b7e1141cdbaeeed64736f6c63430008110033
|
54
itests/contracts/ValueSender.sol
Normal file
54
itests/contracts/ValueSender.sol
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
||||
|
||||
|
124
itests/decode_params_test.go
Normal file
124
itests/decode_params_test.go
Normal file
@ -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 <msg-cid>' 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)
|
||||
})
|
||||
}
|
||||
}
|
@ -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))
|
||||
}
|
||||
|
62
itests/eth_config_test.go
Normal file
62
itests/eth_config_test.go
Normal file
@ -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())
|
||||
}
|
520
itests/eth_conformance_test.go
Normal file
520
itests/eth_conformance_test.go
Normal file
@ -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
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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) {
|
||||
|
@ -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 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)
|
||||
|
||||
createdEthAddr, err := ethtypes.CastEthAddress(createExternalReturn.EthAddress[:])
|
||||
require.NoError(t, err)
|
||||
return createdEthAddr
|
||||
}
|
||||
|
||||
func TestAddressCreationBeforeDeploy(t *testing.T) {
|
||||
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)
|
||||
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
|
||||
|
||||
method := builtintypes.MethodsEAM.CreateExternal
|
||||
contractParams := abi.CborBytes(contract)
|
||||
params, err := actors.SerializeParams(&contractParams)
|
||||
require.NoError(t, err)
|
||||
|
||||
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)
|
||||
wait := createAndDeploy(ctx, t, client, fromAddr, contract)
|
||||
|
||||
// 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)
|
||||
|
||||
createdEthAddr, err := ethtypes.CastEthAddress(createExternalReturn.EthAddress[:])
|
||||
require.NoError(t, err)
|
||||
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))
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
contract, err := hex.DecodeString(string(contractHex))
|
||||
require.NoError(t, err)
|
||||
|
||||
fromAddr, err := client.WalletDefaultAddress(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
// 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)
|
||||
|
||||
}
|
||||
|
@ -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))
|
||||
|
@ -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,47 @@ 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
|
||||
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
|
||||
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 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, _, 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
|
||||
@ -117,20 +286,245 @@ func TestFEVMDelegateCall(t *testing.T) {
|
||||
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)
|
||||
expectedResult, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000007")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, result, expectedResult)
|
||||
_, 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 7 via calling the getter
|
||||
result = client.EVM().InvokeContractByFuncName(ctx, fromAddr, storageAddr, "getCounter()", []byte{})
|
||||
//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 = client.EVM().InvokeContractByFuncName(ctx, fromAddr, actorAddr, "getCounter()", []byte{})
|
||||
expectedResultActor, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000000")
|
||||
result, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, actorAddr, "getCounter()", []byte{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, result, expectedResultActor)
|
||||
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) {
|
||||
@ -139,3 +533,174 @@ func TestEVMRpcDisable(t *testing.T) {
|
||||
_, 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))
|
||||
}
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
64
itests/kit/solidity.go
Normal file
64
itests/kit/solidity.go
Normal file
@ -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{},
|
||||
}
|
4392
itests/specs/eth_openrpc.json
Normal file
4392
itests/specs/eth_openrpc.json
Normal file
File diff suppressed because it is too large
Load Diff
9
lib/must/must.go
Normal file
9
lib/must/must.go
Normal file
@ -0,0 +1,9 @@
|
||||
package must
|
||||
|
||||
func One[R any](r R, err error) R {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -127,6 +127,8 @@ const (
|
||||
|
||||
SetApiEndpointKey
|
||||
|
||||
StoreEventsKey
|
||||
|
||||
_nInvokes // keep this last
|
||||
)
|
||||
|
||||
|
@ -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{}),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -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{}
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
return ethtypes.EthUint64(msg.GasLimit), nil
|
||||
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
|
||||
}
|
||||
|
||||
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) {
|
||||
if e.SubManager == nil {
|
||||
return nil, 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)
|
||||
func (e *EthEvent) EthSubscribe(ctx context.Context, p jsonrpc.RawParams) (ethtypes.EthSubscriptionID, error) {
|
||||
params, err := jsonrpc.DecodeParams[ethtypes.EthSubscribeParams](p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return ethtypes.EthSubscriptionID{}, xerrors.Errorf("decoding params: %w", err)
|
||||
}
|
||||
|
||||
switch eventType {
|
||||
if e.SubManager == nil {
|
||||
return ethtypes.EthSubscriptionID{}, api.ErrNotSupported
|
||||
}
|
||||
|
||||
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 ethtypes.EthSubscriptionID{}, err
|
||||
}
|
||||
|
||||
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[:]
|
||||
}
|
||||
keys[key] = keyvals
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
f, err := e.EventFilterManager.Install(ctx, -1, -1, cid.Undef, []address.Address{}, keys)
|
||||
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)
|
||||
}
|
||||
addresses = append(addresses, a)
|
||||
}
|
||||
}
|
||||
|
||||
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,93 +1685,51 @@ 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 ethtypes.EthTx{}, xerrors.Errorf("failed to resolve Ethereum address: %w", err)
|
||||
}
|
||||
|
||||
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 { // Secp Filecoin Message
|
||||
tx.Hash, err = ethtypes.EthHashFromCid(smsg.Cid())
|
||||
} else { // BLS Filecoin message
|
||||
tx = ethTxFromNativeMessage(ctx, smsg.VMMessage(), sa)
|
||||
tx.Hash, err = ethtypes.EthHashFromCid(smsg.Message.Cid())
|
||||
if err != nil {
|
||||
return tx, err
|
||||
}
|
||||
@ -1633,14 +1738,32 @@ func NewEthTxFromFilecoinMessage(ctx context.Context, smsg *types.SignedMessage,
|
||||
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,16 +1864,6 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook
|
||||
LogsBloom: ethtypes.EmptyEthBloom[:],
|
||||
}
|
||||
|
||||
if receipt.To == nil && lookup.Receipt.ExitCode.IsSuccess() {
|
||||
// Create and Create2 return the same things.
|
||||
var ret eam.CreateReturn
|
||||
if err := ret.UnmarshalCBOR(bytes.NewReader(lookup.Receipt.Return)); err != nil {
|
||||
return api.EthTxReceipt{}, xerrors.Errorf("failed to parse contract creation result: %w", err)
|
||||
}
|
||||
addr := ethtypes.EthAddress(ret.EthAddress)
|
||||
receipt.ContractAddress = &addr
|
||||
}
|
||||
|
||||
if lookup.Receipt.ExitCode.IsSuccess() {
|
||||
receipt.Status = 1
|
||||
}
|
||||
@ -1758,6 +1871,24 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook
|
||||
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.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)
|
||||
}
|
||||
addr := ethtypes.EthAddress(ret.EthAddress)
|
||||
receipt.ContractAddress = &addr
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user