NV18: Filecoin EVM runtime + Actor Events + EthAccount + EAM + f4 addressing (#9998)
Co-authored-by: Steven Allen <steven@stebalien.com> Co-authored-by: Raul Kripalani <raulk@users.noreply.github.com> Co-authored-by: Kevin Li <ychiaoli18@users.noreply.github.com> Co-authored-by: vyzo <vyzo@hackzen.org> Co-authored-by: Ian Davis <nospam@iandavis.com> Co-authored-by: Aayush Rajasekaran <arajasek94@gmail.com> Co-authored-by: Jiaying Wang <42981373+jennijuju@users.noreply.github.com> Co-authored-by: Jennifer Wang <jiayingw703@gmail.com> Co-authored-by: Geoff Stuart <geoff.vball@gmail.com> Co-authored-by: Shrenuj Bansal <shrenuj.bansal@protocol.ai> Co-authored-by: Shrenuj Bansal <108157875+shrenujbansal@users.noreply.github.com> Co-authored-by: Geoff Stuart <geoffrey.stuart@protocol.ai> Co-authored-by: Aayush Rajasekaran <aayushrajasekaran@Aayushs-MacBook-Pro.local> Co-authored-by: ZenGround0 <5515260+ZenGround0@users.noreply.github.com> Co-authored-by: zenground0 <ZenGround0@users.noreply.github.com>
This commit is contained in:
co-authored by
Steven Allen
Raul Kripalani
Kevin Li
vyzo
Ian Davis
Aayush Rajasekaran
Jiaying Wang
Jennifer Wang
Geoff Stuart
Shrenuj Bansal
Shrenuj Bansal
Geoff Stuart
Aayush Rajasekaran
ZenGround0
zenground0
parent
048ccc71bb
commit
cdf3812e40
@@ -720,6 +720,46 @@ workflows:
|
||||
suite: itest-dup_mpool_messages
|
||||
target: "./itests/dup_mpool_messages_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-eth_account_abstraction
|
||||
suite: itest-eth_account_abstraction
|
||||
target: "./itests/eth_account_abstraction_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-eth_balance
|
||||
suite: itest-eth_balance
|
||||
target: "./itests/eth_balance_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-eth_deploy
|
||||
suite: itest-eth_deploy
|
||||
target: "./itests/eth_deploy_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-eth_filter
|
||||
suite: itest-eth_filter
|
||||
target: "./itests/eth_filter_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-eth_transactions
|
||||
suite: itest-eth_transactions
|
||||
target: "./itests/eth_transactions_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-fevm_address
|
||||
suite: itest-fevm_address
|
||||
target: "./itests/fevm_address_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-fevm_events
|
||||
suite: itest-fevm_events
|
||||
target: "./itests/fevm_events_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-fevm
|
||||
suite: itest-fevm
|
||||
target: "./itests/fevm_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-gas_estimation
|
||||
suite: itest-gas_estimation
|
||||
@@ -755,6 +795,11 @@ workflows:
|
||||
suite: itest-migration_nv17
|
||||
target: "./itests/migration_nv17_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-migration_nv18
|
||||
suite: itest-migration_nv18
|
||||
target: "./itests/migration_nv18_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-mpool_msg_uuid
|
||||
suite: itest-mpool_msg_uuid
|
||||
|
||||
@@ -84,6 +84,12 @@ butterflynet: build-devnets
|
||||
interopnet: GOFLAGS+=-tags=interopnet
|
||||
interopnet: build-devnets
|
||||
|
||||
wallabynet: GOFLAGS+=-tags=wallabynet
|
||||
wallabynet: build-devnets
|
||||
|
||||
hyperspacenet: GOFLAGS+=-tags=hyperspacenet
|
||||
hyperspacenet: build-devnets
|
||||
|
||||
lotus: $(BUILD_DEPS)
|
||||
rm -f lotus
|
||||
$(GOCC) build $(GOFLAGS) -o lotus ./cmd/lotus
|
||||
|
||||
+101
-8
@@ -31,6 +31,7 @@ import (
|
||||
lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
"github.com/filecoin-project/lotus/node/repo/imports"
|
||||
)
|
||||
@@ -151,7 +152,7 @@ type FullNode interface {
|
||||
|
||||
// ChainGetPath returns a set of revert/apply operations needed to get from
|
||||
// one tipset to another, for example:
|
||||
//```
|
||||
// ```
|
||||
// to
|
||||
// ^
|
||||
// from tAA
|
||||
@@ -160,7 +161,7 @@ type FullNode interface {
|
||||
// ^---*--^
|
||||
// ^
|
||||
// tRR
|
||||
//```
|
||||
// ```
|
||||
// Would return `[revert(tBA), apply(tAB), apply(tAA)]`
|
||||
ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*HeadChange, error) //perm:read
|
||||
|
||||
@@ -182,6 +183,9 @@ type FullNode interface {
|
||||
// ChainBlockstoreInfo returns some basic information about the blockstore
|
||||
ChainBlockstoreInfo(context.Context) (map[string]interface{}, error) //perm:read
|
||||
|
||||
// ChainGetEvents returns the events under an event AMT root CID.
|
||||
ChainGetEvents(context.Context, cid.Cid) ([]types.Event, error) //perm:read
|
||||
|
||||
// GasEstimateFeeCap estimates gas fee cap
|
||||
GasEstimateFeeCap(context.Context, *types.Message, int64, types.TipSetKey) (types.BigInt, error) //perm:read
|
||||
|
||||
@@ -388,12 +392,12 @@ type FullNode interface {
|
||||
ClientCancelRetrievalDeal(ctx context.Context, dealid retrievalmarket.DealID) error //perm:write
|
||||
|
||||
// ClientUnimport removes references to the specified file from filestore
|
||||
//ClientUnimport(path string)
|
||||
// ClientUnimport(path string)
|
||||
|
||||
// ClientListImports lists imported files and their root CIDs
|
||||
ClientListImports(ctx context.Context) ([]Import, error) //perm:write
|
||||
|
||||
//ClientListAsks() []Ask
|
||||
// ClientListAsks() []Ask
|
||||
|
||||
// MethodGroup: State
|
||||
// The State methods are used to query, inspect, and interact with chain state.
|
||||
@@ -640,14 +644,14 @@ type FullNode interface {
|
||||
// It takes the following params: <multisig address>, <start epoch>, <end epoch>
|
||||
MsigGetVested(context.Context, address.Address, types.TipSetKey, types.TipSetKey) (types.BigInt, error) //perm:read
|
||||
|
||||
//MsigGetPending returns pending transactions for the given multisig
|
||||
//wallet. Once pending transactions are fully approved, they will no longer
|
||||
//appear here.
|
||||
// MsigGetPending returns pending transactions for the given multisig
|
||||
// wallet. Once pending transactions are fully approved, they will no longer
|
||||
// appear here.
|
||||
MsigGetPending(context.Context, address.Address, types.TipSetKey) ([]*MsigTransaction, error) //perm:read
|
||||
|
||||
// MsigCreate creates a multisig wallet
|
||||
// It takes the following params: <required number of senders>, <approving addresses>, <unlock duration>
|
||||
//<initial balance>, <sender address of the create msg>, <gas price>
|
||||
// <initial balance>, <sender address of the create msg>, <gas price>
|
||||
MsigCreate(context.Context, uint64, []address.Address, abi.ChainEpoch, types.BigInt, address.Address, types.BigInt) (*MessagePrototype, error) //perm:sign
|
||||
|
||||
// MsigPropose proposes a multisig message
|
||||
@@ -759,6 +763,77 @@ type FullNode interface {
|
||||
|
||||
NodeStatus(ctx context.Context, inclChainStatus bool) (NodeStatus, error) //perm:read
|
||||
|
||||
// MethodGroup: Eth
|
||||
// These methods are used for Ethereum-compatible JSON-RPC calls
|
||||
//
|
||||
// EthAccounts will always return [] since we don't expect Lotus to manage private keys
|
||||
EthAccounts(ctx context.Context) ([]ethtypes.EthAddress, error) //perm:read
|
||||
// EthBlockNumber returns the height of the latest (heaviest) TipSet
|
||||
EthBlockNumber(ctx context.Context) (ethtypes.EthUint64, error) //perm:read
|
||||
// EthGetBlockTransactionCountByNumber returns the number of messages in the TipSet
|
||||
EthGetBlockTransactionCountByNumber(ctx context.Context, blkNum ethtypes.EthUint64) (ethtypes.EthUint64, error) //perm:read
|
||||
// EthGetBlockTransactionCountByHash returns the number of messages in the TipSet
|
||||
EthGetBlockTransactionCountByHash(ctx context.Context, blkHash ethtypes.EthHash) (ethtypes.EthUint64, error) //perm:read
|
||||
|
||||
EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error) //perm:read
|
||||
EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (ethtypes.EthBlock, error) //perm:read
|
||||
EthGetTransactionByHash(ctx context.Context, txHash *ethtypes.EthHash) (*ethtypes.EthTx, error) //perm:read
|
||||
EthGetTransactionCount(ctx context.Context, sender ethtypes.EthAddress, blkOpt string) (ethtypes.EthUint64, error) //perm:read
|
||||
EthGetTransactionReceipt(ctx context.Context, txHash ethtypes.EthHash) (*EthTxReceipt, error) //perm:read
|
||||
EthGetTransactionByBlockHashAndIndex(ctx context.Context, blkHash ethtypes.EthHash, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error) //perm:read
|
||||
EthGetTransactionByBlockNumberAndIndex(ctx context.Context, blkNum ethtypes.EthUint64, txIndex ethtypes.EthUint64) (ethtypes.EthTx, error) //perm:read
|
||||
|
||||
EthGetCode(ctx context.Context, address ethtypes.EthAddress, blkOpt string) (ethtypes.EthBytes, error) //perm:read
|
||||
EthGetStorageAt(ctx context.Context, address ethtypes.EthAddress, position ethtypes.EthBytes, blkParam string) (ethtypes.EthBytes, error) //perm:read
|
||||
EthGetBalance(ctx context.Context, address ethtypes.EthAddress, blkParam string) (ethtypes.EthBigInt, error) //perm:read
|
||||
EthChainId(ctx context.Context) (ethtypes.EthUint64, error) //perm:read
|
||||
NetVersion(ctx context.Context) (string, error) //perm:read
|
||||
NetListening(ctx context.Context) (bool, error) //perm:read
|
||||
EthProtocolVersion(ctx context.Context) (ethtypes.EthUint64, error) //perm:read
|
||||
EthGasPrice(ctx context.Context) (ethtypes.EthBigInt, error) //perm:read
|
||||
EthFeeHistory(ctx context.Context, blkCount ethtypes.EthUint64, newestBlk string, rewardPercentiles []float64) (ethtypes.EthFeeHistory, error) //perm:read
|
||||
|
||||
EthMaxPriorityFeePerGas(ctx context.Context) (ethtypes.EthBigInt, error) //perm:read
|
||||
EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (ethtypes.EthUint64, error) //perm:read
|
||||
EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam string) (ethtypes.EthBytes, error) //perm:read
|
||||
|
||||
EthSendRawTransaction(ctx context.Context, rawTx ethtypes.EthBytes) (ethtypes.EthHash, error) //perm:read
|
||||
|
||||
// Returns event logs matching given filter spec.
|
||||
EthGetLogs(ctx context.Context, filter *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) //perm:read
|
||||
|
||||
// Polling method for a filter, returns event logs which occurred since last poll.
|
||||
// (requires write perm since timestamp of last filter execution will be written)
|
||||
EthGetFilterChanges(ctx context.Context, id ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) //perm:write
|
||||
|
||||
// Returns event logs matching filter with given id.
|
||||
// (requires write perm since timestamp of last filter execution will be written)
|
||||
EthGetFilterLogs(ctx context.Context, id ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) //perm:write
|
||||
|
||||
// Installs a persistent filter based on given filter spec.
|
||||
EthNewFilter(ctx context.Context, filter *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) //perm:write
|
||||
|
||||
// Installs a persistent filter to notify when a new block arrives.
|
||||
EthNewBlockFilter(ctx context.Context) (ethtypes.EthFilterID, error) //perm:write
|
||||
|
||||
// Installs a persistent filter to notify when new messages arrive in the message pool.
|
||||
EthNewPendingTransactionFilter(ctx context.Context) (ethtypes.EthFilterID, error) //perm:write
|
||||
|
||||
// Uninstalls a filter with given id.
|
||||
EthUninstallFilter(ctx context.Context, id ethtypes.EthFilterID) (bool, error) //perm:write
|
||||
|
||||
// Subscribe to different event types using websockets
|
||||
// eventTypes is one or more of:
|
||||
// - newHeads: notify when new blocks arrive.
|
||||
// - pendingTransactions: notify when new messages arrive in the message pool.
|
||||
// - 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
|
||||
|
||||
// Unsubscribe from a websocket subscription
|
||||
EthUnsubscribe(ctx context.Context, id ethtypes.EthSubscriptionID) (bool, error) //perm:write
|
||||
|
||||
// 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
|
||||
@@ -1252,3 +1327,21 @@ type PruneOpts struct {
|
||||
MovingGC bool
|
||||
RetainState int64
|
||||
}
|
||||
|
||||
type EthTxReceipt struct {
|
||||
TransactionHash ethtypes.EthHash `json:"transactionHash"`
|
||||
TransactionIndex ethtypes.EthUint64 `json:"transactionIndex"`
|
||||
BlockHash ethtypes.EthHash `json:"blockHash"`
|
||||
BlockNumber ethtypes.EthUint64 `json:"blockNumber"`
|
||||
From ethtypes.EthAddress `json:"from"`
|
||||
To *ethtypes.EthAddress `json:"to"`
|
||||
StateRoot ethtypes.EthHash `json:"root"`
|
||||
Status ethtypes.EthUint64 `json:"status"`
|
||||
ContractAddress *ethtypes.EthAddress `json:"contractAddress"`
|
||||
CumulativeGasUsed ethtypes.EthUint64 `json:"cumulativeGasUsed"`
|
||||
GasUsed ethtypes.EthUint64 `json:"gasUsed"`
|
||||
EffectiveGasPrice ethtypes.EthBigInt `json:"effectiveGasPrice"`
|
||||
LogsBloom ethtypes.EthBytes `json:"logsBloom"`
|
||||
Logs []ethtypes.EthLog `json:"logs"`
|
||||
Type ethtypes.EthUint64 `json:"type"`
|
||||
}
|
||||
|
||||
+4
-4
@@ -22,7 +22,7 @@ import (
|
||||
"github.com/filecoin-project/go-state-types/builtin/v9/miner"
|
||||
abinetwork "github.com/filecoin-project/go-state-types/network"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
||||
builtinactors "github.com/filecoin-project/lotus/chain/actors/builtin"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/storage/pipeline/sealiface"
|
||||
"github.com/filecoin-project/lotus/storage/sealer/fsutil"
|
||||
@@ -152,7 +152,7 @@ type StorageMiner interface {
|
||||
WorkerStats(context.Context) (map[uuid.UUID]storiface.WorkerStats, error) //perm:admin
|
||||
WorkerJobs(context.Context) (map[uuid.UUID][]storiface.WorkerJob, error) //perm:admin
|
||||
|
||||
//storiface.WorkerReturn
|
||||
// storiface.WorkerReturn
|
||||
ReturnDataCid(ctx context.Context, callID storiface.CallID, pi abi.PieceInfo, err *storiface.CallError) error //perm:admin retry:true
|
||||
ReturnAddPiece(ctx context.Context, callID storiface.CallID, pi abi.PieceInfo, err *storiface.CallError) error //perm:admin retry:true
|
||||
ReturnSealPreCommit1(ctx context.Context, callID storiface.CallID, p1o storiface.PreCommit1Out, err *storiface.CallError) error //perm:admin retry:true
|
||||
@@ -175,7 +175,7 @@ type StorageMiner interface {
|
||||
// SealingSchedDiag dumps internal sealing scheduler state
|
||||
SealingSchedDiag(ctx context.Context, doSched bool) (interface{}, error) //perm:admin
|
||||
SealingAbort(ctx context.Context, call storiface.CallID) error //perm:admin
|
||||
//SealingSchedRemove removes a request from sealing pipeline
|
||||
// SealingSchedRemove removes a request from sealing pipeline
|
||||
SealingRemoveRequest(ctx context.Context, schedId uuid.UUID) error //perm:admin
|
||||
|
||||
// paths.SectorIndex
|
||||
@@ -322,7 +322,7 @@ type StorageMiner interface {
|
||||
|
||||
CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storiface.SectorRef) (map[abi.SectorNumber]string, error) //perm:admin
|
||||
|
||||
ComputeProof(ctx context.Context, ssi []builtin.ExtendedSectorInfo, rand abi.PoStRandomness, poStEpoch abi.ChainEpoch, nv abinetwork.Version) ([]builtin.PoStProof, error) //perm:read
|
||||
ComputeProof(ctx context.Context, ssi []builtinactors.ExtendedSectorInfo, rand abi.PoStRandomness, poStEpoch abi.ChainEpoch, nv abinetwork.Version) ([]builtinactors.PoStProof, error) //perm:read
|
||||
|
||||
// RecoverFault can be used to declare recoveries manually. It sends messages
|
||||
// to the miner actor with details of recovered sectors and returns the CID of messages. It honors the
|
||||
|
||||
+38
-4
@@ -41,6 +41,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/api/v0api"
|
||||
"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/node/modules/dtypes"
|
||||
"github.com/filecoin-project/lotus/node/repo/imports"
|
||||
sealing "github.com/filecoin-project/lotus/storage/pipeline"
|
||||
@@ -68,6 +69,7 @@ func init() {
|
||||
}
|
||||
|
||||
ExampleValues[reflect.TypeOf(c)] = c
|
||||
ExampleValues[reflect.TypeOf(&c)] = &c
|
||||
|
||||
c2, err := cid.Decode("bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve")
|
||||
if err != nil {
|
||||
@@ -298,7 +300,8 @@ func init() {
|
||||
"title": "Lotus RPC API",
|
||||
"version": "1.2.1/generated=2020-11-22T08:22:42-06:00",
|
||||
},
|
||||
"methods": []interface{}{}},
|
||||
"methods": []interface{}{},
|
||||
},
|
||||
)
|
||||
|
||||
addExample(api.CheckStatusCode(0))
|
||||
@@ -335,7 +338,8 @@ func init() {
|
||||
NumConnsInbound: 3,
|
||||
NumConnsOutbound: 4,
|
||||
NumFD: 5,
|
||||
}})
|
||||
},
|
||||
})
|
||||
addExample(api.NetLimit{
|
||||
Memory: 123,
|
||||
StreamsInbound: 1,
|
||||
@@ -346,6 +350,7 @@ func init() {
|
||||
Conns: 4,
|
||||
FD: 5,
|
||||
})
|
||||
|
||||
addExample(map[string]bitfield.BitField{
|
||||
"": bitfield.NewFromSet([]uint64{5, 6, 7, 10}),
|
||||
})
|
||||
@@ -365,11 +370,40 @@ func init() {
|
||||
Headers: nil,
|
||||
},
|
||||
})
|
||||
|
||||
ethint := ethtypes.EthUint64(5)
|
||||
addExample(ethint)
|
||||
addExample(ðint)
|
||||
|
||||
ethaddr, _ := ethtypes.ParseEthAddress("0x5CbEeCF99d3fDB3f25E309Cc264f240bb0664031")
|
||||
addExample(ethaddr)
|
||||
addExample(ðaddr)
|
||||
|
||||
ethhash, _ := ethtypes.EthHashFromCid(c)
|
||||
addExample(ethhash)
|
||||
addExample(ðhash)
|
||||
|
||||
ethFeeHistoryReward := [][]ethtypes.EthBigInt{}
|
||||
addExample(ðFeeHistoryReward)
|
||||
|
||||
addExample(&uuid.UUID{})
|
||||
|
||||
filterid := ethtypes.EthFilterID(ethhash)
|
||||
addExample(filterid)
|
||||
addExample(&filterid)
|
||||
|
||||
subid := ethtypes.EthSubscriptionID(ethhash)
|
||||
addExample(subid)
|
||||
addExample(&subid)
|
||||
|
||||
pstring := func(s string) *string { return &s }
|
||||
addExample(ðtypes.EthFilterSpec{
|
||||
FromBlock: pstring("2301220"),
|
||||
Address: []ethtypes.EthAddress{ethaddr},
|
||||
})
|
||||
}
|
||||
|
||||
func GetAPIType(name, pkg string) (i interface{}, t reflect.Type, permStruct []reflect.Type) {
|
||||
|
||||
switch pkg {
|
||||
case "api": // latest
|
||||
switch name {
|
||||
@@ -439,7 +473,7 @@ func ExampleValue(method string, t, parent reflect.Type) interface{} {
|
||||
case reflect.Ptr:
|
||||
if t.Elem().Kind() == reflect.Struct {
|
||||
es := exampleStruct(method, t.Elem(), t)
|
||||
//ExampleValues[t] = es
|
||||
ExampleValues[t] = es
|
||||
return es
|
||||
}
|
||||
case reflect.Interface:
|
||||
|
||||
@@ -37,6 +37,7 @@ import (
|
||||
apitypes "github.com/filecoin-project/lotus/api/types"
|
||||
miner0 "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||
types "github.com/filecoin-project/lotus/chain/types"
|
||||
ethtypes "github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
alerting "github.com/filecoin-project/lotus/journal/alerting"
|
||||
dtypes "github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
imports "github.com/filecoin-project/lotus/node/repo/imports"
|
||||
@@ -183,6 +184,21 @@ func (mr *MockFullNodeMockRecorder) ChainGetBlockMessages(arg0, arg1 interface{}
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainGetBlockMessages", reflect.TypeOf((*MockFullNode)(nil).ChainGetBlockMessages), arg0, arg1)
|
||||
}
|
||||
|
||||
// ChainGetEvents mocks base method.
|
||||
func (m *MockFullNode) ChainGetEvents(arg0 context.Context, arg1 cid.Cid) ([]types.Event, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ChainGetEvents", arg0, arg1)
|
||||
ret0, _ := ret[0].([]types.Event)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// ChainGetEvents indicates an expected call of ChainGetEvents.
|
||||
func (mr *MockFullNodeMockRecorder) ChainGetEvents(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChainGetEvents", reflect.TypeOf((*MockFullNode)(nil).ChainGetEvents), arg0, arg1)
|
||||
}
|
||||
|
||||
// ChainGetGenesis mocks base method.
|
||||
func (m *MockFullNode) ChainGetGenesis(arg0 context.Context) (*types.TipSet, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -921,6 +937,471 @@ func (mr *MockFullNodeMockRecorder) Discover(arg0 interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Discover", reflect.TypeOf((*MockFullNode)(nil).Discover), arg0)
|
||||
}
|
||||
|
||||
// EthAccounts mocks base method.
|
||||
func (m *MockFullNode) EthAccounts(arg0 context.Context) ([]ethtypes.EthAddress, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthAccounts", arg0)
|
||||
ret0, _ := ret[0].([]ethtypes.EthAddress)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthAccounts indicates an expected call of EthAccounts.
|
||||
func (mr *MockFullNodeMockRecorder) EthAccounts(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthAccounts", reflect.TypeOf((*MockFullNode)(nil).EthAccounts), arg0)
|
||||
}
|
||||
|
||||
// EthBlockNumber mocks base method.
|
||||
func (m *MockFullNode) EthBlockNumber(arg0 context.Context) (ethtypes.EthUint64, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthBlockNumber", arg0)
|
||||
ret0, _ := ret[0].(ethtypes.EthUint64)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthBlockNumber indicates an expected call of EthBlockNumber.
|
||||
func (mr *MockFullNodeMockRecorder) EthBlockNumber(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthBlockNumber", reflect.TypeOf((*MockFullNode)(nil).EthBlockNumber), arg0)
|
||||
}
|
||||
|
||||
// EthCall mocks base method.
|
||||
func (m *MockFullNode) EthCall(arg0 context.Context, arg1 ethtypes.EthCall, arg2 string) (ethtypes.EthBytes, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthCall", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(ethtypes.EthBytes)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthCall indicates an expected call of EthCall.
|
||||
func (mr *MockFullNodeMockRecorder) EthCall(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthCall", reflect.TypeOf((*MockFullNode)(nil).EthCall), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// EthChainId mocks base method.
|
||||
func (m *MockFullNode) EthChainId(arg0 context.Context) (ethtypes.EthUint64, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthChainId", arg0)
|
||||
ret0, _ := ret[0].(ethtypes.EthUint64)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthChainId indicates an expected call of EthChainId.
|
||||
func (mr *MockFullNodeMockRecorder) EthChainId(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthChainId", reflect.TypeOf((*MockFullNode)(nil).EthChainId), arg0)
|
||||
}
|
||||
|
||||
// EthEstimateGas mocks base method.
|
||||
func (m *MockFullNode) EthEstimateGas(arg0 context.Context, arg1 ethtypes.EthCall) (ethtypes.EthUint64, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthEstimateGas", arg0, arg1)
|
||||
ret0, _ := ret[0].(ethtypes.EthUint64)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthEstimateGas indicates an expected call of EthEstimateGas.
|
||||
func (mr *MockFullNodeMockRecorder) EthEstimateGas(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthEstimateGas", reflect.TypeOf((*MockFullNode)(nil).EthEstimateGas), arg0, arg1)
|
||||
}
|
||||
|
||||
// EthFeeHistory mocks base method.
|
||||
func (m *MockFullNode) EthFeeHistory(arg0 context.Context, arg1 ethtypes.EthUint64, arg2 string, arg3 []float64) (ethtypes.EthFeeHistory, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthFeeHistory", arg0, arg1, arg2, arg3)
|
||||
ret0, _ := ret[0].(ethtypes.EthFeeHistory)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthFeeHistory indicates an expected call of EthFeeHistory.
|
||||
func (mr *MockFullNodeMockRecorder) EthFeeHistory(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthFeeHistory", reflect.TypeOf((*MockFullNode)(nil).EthFeeHistory), arg0, arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
// EthGasPrice mocks base method.
|
||||
func (m *MockFullNode) EthGasPrice(arg0 context.Context) (ethtypes.EthBigInt, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthGasPrice", arg0)
|
||||
ret0, _ := ret[0].(ethtypes.EthBigInt)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthGasPrice indicates an expected call of EthGasPrice.
|
||||
func (mr *MockFullNodeMockRecorder) EthGasPrice(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthGasPrice", reflect.TypeOf((*MockFullNode)(nil).EthGasPrice), arg0)
|
||||
}
|
||||
|
||||
// EthGetBalance mocks base method.
|
||||
func (m *MockFullNode) EthGetBalance(arg0 context.Context, arg1 ethtypes.EthAddress, arg2 string) (ethtypes.EthBigInt, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthGetBalance", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(ethtypes.EthBigInt)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthGetBalance indicates an expected call of EthGetBalance.
|
||||
func (mr *MockFullNodeMockRecorder) EthGetBalance(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthGetBalance", reflect.TypeOf((*MockFullNode)(nil).EthGetBalance), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// EthGetBlockByHash mocks base method.
|
||||
func (m *MockFullNode) EthGetBlockByHash(arg0 context.Context, arg1 ethtypes.EthHash, arg2 bool) (ethtypes.EthBlock, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthGetBlockByHash", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(ethtypes.EthBlock)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthGetBlockByHash indicates an expected call of EthGetBlockByHash.
|
||||
func (mr *MockFullNodeMockRecorder) EthGetBlockByHash(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthGetBlockByHash", reflect.TypeOf((*MockFullNode)(nil).EthGetBlockByHash), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// EthGetBlockByNumber mocks base method.
|
||||
func (m *MockFullNode) EthGetBlockByNumber(arg0 context.Context, arg1 string, arg2 bool) (ethtypes.EthBlock, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthGetBlockByNumber", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(ethtypes.EthBlock)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthGetBlockByNumber indicates an expected call of EthGetBlockByNumber.
|
||||
func (mr *MockFullNodeMockRecorder) EthGetBlockByNumber(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthGetBlockByNumber", reflect.TypeOf((*MockFullNode)(nil).EthGetBlockByNumber), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// EthGetBlockTransactionCountByHash mocks base method.
|
||||
func (m *MockFullNode) EthGetBlockTransactionCountByHash(arg0 context.Context, arg1 ethtypes.EthHash) (ethtypes.EthUint64, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthGetBlockTransactionCountByHash", arg0, arg1)
|
||||
ret0, _ := ret[0].(ethtypes.EthUint64)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthGetBlockTransactionCountByHash indicates an expected call of EthGetBlockTransactionCountByHash.
|
||||
func (mr *MockFullNodeMockRecorder) EthGetBlockTransactionCountByHash(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthGetBlockTransactionCountByHash", reflect.TypeOf((*MockFullNode)(nil).EthGetBlockTransactionCountByHash), arg0, arg1)
|
||||
}
|
||||
|
||||
// EthGetBlockTransactionCountByNumber mocks base method.
|
||||
func (m *MockFullNode) EthGetBlockTransactionCountByNumber(arg0 context.Context, arg1 ethtypes.EthUint64) (ethtypes.EthUint64, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthGetBlockTransactionCountByNumber", arg0, arg1)
|
||||
ret0, _ := ret[0].(ethtypes.EthUint64)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthGetBlockTransactionCountByNumber indicates an expected call of EthGetBlockTransactionCountByNumber.
|
||||
func (mr *MockFullNodeMockRecorder) EthGetBlockTransactionCountByNumber(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthGetBlockTransactionCountByNumber", reflect.TypeOf((*MockFullNode)(nil).EthGetBlockTransactionCountByNumber), arg0, arg1)
|
||||
}
|
||||
|
||||
// EthGetCode mocks base method.
|
||||
func (m *MockFullNode) EthGetCode(arg0 context.Context, arg1 ethtypes.EthAddress, arg2 string) (ethtypes.EthBytes, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthGetCode", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(ethtypes.EthBytes)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthGetCode indicates an expected call of EthGetCode.
|
||||
func (mr *MockFullNodeMockRecorder) EthGetCode(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthGetCode", reflect.TypeOf((*MockFullNode)(nil).EthGetCode), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// EthGetFilterChanges mocks base method.
|
||||
func (m *MockFullNode) EthGetFilterChanges(arg0 context.Context, arg1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthGetFilterChanges", arg0, arg1)
|
||||
ret0, _ := ret[0].(*ethtypes.EthFilterResult)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthGetFilterChanges indicates an expected call of EthGetFilterChanges.
|
||||
func (mr *MockFullNodeMockRecorder) EthGetFilterChanges(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthGetFilterChanges", reflect.TypeOf((*MockFullNode)(nil).EthGetFilterChanges), arg0, arg1)
|
||||
}
|
||||
|
||||
// EthGetFilterLogs mocks base method.
|
||||
func (m *MockFullNode) EthGetFilterLogs(arg0 context.Context, arg1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthGetFilterLogs", arg0, arg1)
|
||||
ret0, _ := ret[0].(*ethtypes.EthFilterResult)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthGetFilterLogs indicates an expected call of EthGetFilterLogs.
|
||||
func (mr *MockFullNodeMockRecorder) EthGetFilterLogs(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthGetFilterLogs", reflect.TypeOf((*MockFullNode)(nil).EthGetFilterLogs), arg0, arg1)
|
||||
}
|
||||
|
||||
// EthGetLogs mocks base method.
|
||||
func (m *MockFullNode) EthGetLogs(arg0 context.Context, arg1 *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthGetLogs", arg0, arg1)
|
||||
ret0, _ := ret[0].(*ethtypes.EthFilterResult)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthGetLogs indicates an expected call of EthGetLogs.
|
||||
func (mr *MockFullNodeMockRecorder) EthGetLogs(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthGetLogs", reflect.TypeOf((*MockFullNode)(nil).EthGetLogs), arg0, arg1)
|
||||
}
|
||||
|
||||
// EthGetStorageAt mocks base method.
|
||||
func (m *MockFullNode) EthGetStorageAt(arg0 context.Context, arg1 ethtypes.EthAddress, arg2 ethtypes.EthBytes, arg3 string) (ethtypes.EthBytes, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthGetStorageAt", arg0, arg1, arg2, arg3)
|
||||
ret0, _ := ret[0].(ethtypes.EthBytes)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthGetStorageAt indicates an expected call of EthGetStorageAt.
|
||||
func (mr *MockFullNodeMockRecorder) EthGetStorageAt(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthGetStorageAt", reflect.TypeOf((*MockFullNode)(nil).EthGetStorageAt), arg0, arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
// EthGetTransactionByBlockHashAndIndex mocks base method.
|
||||
func (m *MockFullNode) EthGetTransactionByBlockHashAndIndex(arg0 context.Context, arg1 ethtypes.EthHash, arg2 ethtypes.EthUint64) (ethtypes.EthTx, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthGetTransactionByBlockHashAndIndex", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(ethtypes.EthTx)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthGetTransactionByBlockHashAndIndex indicates an expected call of EthGetTransactionByBlockHashAndIndex.
|
||||
func (mr *MockFullNodeMockRecorder) EthGetTransactionByBlockHashAndIndex(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthGetTransactionByBlockHashAndIndex", reflect.TypeOf((*MockFullNode)(nil).EthGetTransactionByBlockHashAndIndex), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// EthGetTransactionByBlockNumberAndIndex mocks base method.
|
||||
func (m *MockFullNode) EthGetTransactionByBlockNumberAndIndex(arg0 context.Context, arg1, arg2 ethtypes.EthUint64) (ethtypes.EthTx, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthGetTransactionByBlockNumberAndIndex", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(ethtypes.EthTx)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthGetTransactionByBlockNumberAndIndex indicates an expected call of EthGetTransactionByBlockNumberAndIndex.
|
||||
func (mr *MockFullNodeMockRecorder) EthGetTransactionByBlockNumberAndIndex(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthGetTransactionByBlockNumberAndIndex", reflect.TypeOf((*MockFullNode)(nil).EthGetTransactionByBlockNumberAndIndex), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// EthGetTransactionByHash mocks base method.
|
||||
func (m *MockFullNode) EthGetTransactionByHash(arg0 context.Context, arg1 *ethtypes.EthHash) (*ethtypes.EthTx, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthGetTransactionByHash", arg0, arg1)
|
||||
ret0, _ := ret[0].(*ethtypes.EthTx)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthGetTransactionByHash indicates an expected call of EthGetTransactionByHash.
|
||||
func (mr *MockFullNodeMockRecorder) EthGetTransactionByHash(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthGetTransactionByHash", reflect.TypeOf((*MockFullNode)(nil).EthGetTransactionByHash), arg0, arg1)
|
||||
}
|
||||
|
||||
// EthGetTransactionCount mocks base method.
|
||||
func (m *MockFullNode) EthGetTransactionCount(arg0 context.Context, arg1 ethtypes.EthAddress, arg2 string) (ethtypes.EthUint64, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthGetTransactionCount", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(ethtypes.EthUint64)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthGetTransactionCount indicates an expected call of EthGetTransactionCount.
|
||||
func (mr *MockFullNodeMockRecorder) EthGetTransactionCount(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthGetTransactionCount", reflect.TypeOf((*MockFullNode)(nil).EthGetTransactionCount), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// EthGetTransactionReceipt mocks base method.
|
||||
func (m *MockFullNode) EthGetTransactionReceipt(arg0 context.Context, arg1 ethtypes.EthHash) (*api.EthTxReceipt, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthGetTransactionReceipt", arg0, arg1)
|
||||
ret0, _ := ret[0].(*api.EthTxReceipt)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthGetTransactionReceipt indicates an expected call of EthGetTransactionReceipt.
|
||||
func (mr *MockFullNodeMockRecorder) EthGetTransactionReceipt(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthGetTransactionReceipt", reflect.TypeOf((*MockFullNode)(nil).EthGetTransactionReceipt), arg0, arg1)
|
||||
}
|
||||
|
||||
// EthMaxPriorityFeePerGas mocks base method.
|
||||
func (m *MockFullNode) EthMaxPriorityFeePerGas(arg0 context.Context) (ethtypes.EthBigInt, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthMaxPriorityFeePerGas", arg0)
|
||||
ret0, _ := ret[0].(ethtypes.EthBigInt)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthMaxPriorityFeePerGas indicates an expected call of EthMaxPriorityFeePerGas.
|
||||
func (mr *MockFullNodeMockRecorder) EthMaxPriorityFeePerGas(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthMaxPriorityFeePerGas", reflect.TypeOf((*MockFullNode)(nil).EthMaxPriorityFeePerGas), arg0)
|
||||
}
|
||||
|
||||
// EthNewBlockFilter mocks base method.
|
||||
func (m *MockFullNode) EthNewBlockFilter(arg0 context.Context) (ethtypes.EthFilterID, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthNewBlockFilter", arg0)
|
||||
ret0, _ := ret[0].(ethtypes.EthFilterID)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthNewBlockFilter indicates an expected call of EthNewBlockFilter.
|
||||
func (mr *MockFullNodeMockRecorder) EthNewBlockFilter(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthNewBlockFilter", reflect.TypeOf((*MockFullNode)(nil).EthNewBlockFilter), arg0)
|
||||
}
|
||||
|
||||
// EthNewFilter mocks base method.
|
||||
func (m *MockFullNode) EthNewFilter(arg0 context.Context, arg1 *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthNewFilter", arg0, arg1)
|
||||
ret0, _ := ret[0].(ethtypes.EthFilterID)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthNewFilter indicates an expected call of EthNewFilter.
|
||||
func (mr *MockFullNodeMockRecorder) EthNewFilter(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthNewFilter", reflect.TypeOf((*MockFullNode)(nil).EthNewFilter), arg0, arg1)
|
||||
}
|
||||
|
||||
// EthNewPendingTransactionFilter mocks base method.
|
||||
func (m *MockFullNode) EthNewPendingTransactionFilter(arg0 context.Context) (ethtypes.EthFilterID, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthNewPendingTransactionFilter", arg0)
|
||||
ret0, _ := ret[0].(ethtypes.EthFilterID)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthNewPendingTransactionFilter indicates an expected call of EthNewPendingTransactionFilter.
|
||||
func (mr *MockFullNodeMockRecorder) EthNewPendingTransactionFilter(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthNewPendingTransactionFilter", reflect.TypeOf((*MockFullNode)(nil).EthNewPendingTransactionFilter), arg0)
|
||||
}
|
||||
|
||||
// EthProtocolVersion mocks base method.
|
||||
func (m *MockFullNode) EthProtocolVersion(arg0 context.Context) (ethtypes.EthUint64, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthProtocolVersion", arg0)
|
||||
ret0, _ := ret[0].(ethtypes.EthUint64)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthProtocolVersion indicates an expected call of EthProtocolVersion.
|
||||
func (mr *MockFullNodeMockRecorder) EthProtocolVersion(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthProtocolVersion", reflect.TypeOf((*MockFullNode)(nil).EthProtocolVersion), arg0)
|
||||
}
|
||||
|
||||
// EthSendRawTransaction mocks base method.
|
||||
func (m *MockFullNode) EthSendRawTransaction(arg0 context.Context, arg1 ethtypes.EthBytes) (ethtypes.EthHash, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthSendRawTransaction", arg0, arg1)
|
||||
ret0, _ := ret[0].(ethtypes.EthHash)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthSendRawTransaction indicates an expected call of EthSendRawTransaction.
|
||||
func (mr *MockFullNodeMockRecorder) EthSendRawTransaction(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthSendRawTransaction", reflect.TypeOf((*MockFullNode)(nil).EthSendRawTransaction), arg0, arg1)
|
||||
}
|
||||
|
||||
// EthSubscribe mocks base method.
|
||||
func (m *MockFullNode) EthSubscribe(arg0 context.Context, arg1 string, arg2 *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthSubscribe", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(<-chan ethtypes.EthSubscriptionResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthSubscribe indicates an expected call of EthSubscribe.
|
||||
func (mr *MockFullNodeMockRecorder) EthSubscribe(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthSubscribe", reflect.TypeOf((*MockFullNode)(nil).EthSubscribe), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// EthUninstallFilter mocks base method.
|
||||
func (m *MockFullNode) EthUninstallFilter(arg0 context.Context, arg1 ethtypes.EthFilterID) (bool, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthUninstallFilter", arg0, arg1)
|
||||
ret0, _ := ret[0].(bool)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthUninstallFilter indicates an expected call of EthUninstallFilter.
|
||||
func (mr *MockFullNodeMockRecorder) EthUninstallFilter(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthUninstallFilter", reflect.TypeOf((*MockFullNode)(nil).EthUninstallFilter), arg0, arg1)
|
||||
}
|
||||
|
||||
// EthUnsubscribe mocks base method.
|
||||
func (m *MockFullNode) EthUnsubscribe(arg0 context.Context, arg1 ethtypes.EthSubscriptionID) (bool, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "EthUnsubscribe", arg0, arg1)
|
||||
ret0, _ := ret[0].(bool)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// EthUnsubscribe indicates an expected call of EthUnsubscribe.
|
||||
func (mr *MockFullNodeMockRecorder) EthUnsubscribe(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthUnsubscribe", reflect.TypeOf((*MockFullNode)(nil).EthUnsubscribe), arg0, arg1)
|
||||
}
|
||||
|
||||
// GasEstimateFeeCap mocks base method.
|
||||
func (m *MockFullNode) GasEstimateFeeCap(arg0 context.Context, arg1 *types.Message, arg2 int64, arg3 types.TipSetKey) (big.Int, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -1843,6 +2324,21 @@ func (mr *MockFullNodeMockRecorder) NetLimit(arg0, arg1 interface{}) *gomock.Cal
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetLimit", reflect.TypeOf((*MockFullNode)(nil).NetLimit), arg0, arg1)
|
||||
}
|
||||
|
||||
// NetListening mocks base method.
|
||||
func (m *MockFullNode) NetListening(arg0 context.Context) (bool, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "NetListening", arg0)
|
||||
ret0, _ := ret[0].(bool)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// NetListening indicates an expected call of NetListening.
|
||||
func (mr *MockFullNodeMockRecorder) NetListening(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetListening", reflect.TypeOf((*MockFullNode)(nil).NetListening), arg0)
|
||||
}
|
||||
|
||||
// NetPeerInfo mocks base method.
|
||||
func (m *MockFullNode) NetPeerInfo(arg0 context.Context, arg1 peer.ID) (*api.ExtendedPeerInfo, error) {
|
||||
m.ctrl.T.Helper()
|
||||
@@ -1975,6 +2471,21 @@ func (mr *MockFullNodeMockRecorder) NetStat(arg0, arg1 interface{}) *gomock.Call
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetStat", reflect.TypeOf((*MockFullNode)(nil).NetStat), arg0, arg1)
|
||||
}
|
||||
|
||||
// NetVersion mocks base method.
|
||||
func (m *MockFullNode) NetVersion(arg0 context.Context) (string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "NetVersion", arg0)
|
||||
ret0, _ := ret[0].(string)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// NetVersion indicates an expected call of NetVersion.
|
||||
func (mr *MockFullNodeMockRecorder) NetVersion(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NetVersion", reflect.TypeOf((*MockFullNode)(nil).NetVersion), arg0)
|
||||
}
|
||||
|
||||
// NodeStatus mocks base method.
|
||||
func (m *MockFullNode) NodeStatus(arg0 context.Context, arg1 bool) (api.NodeStatus, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
||||
+449
-6
@@ -33,9 +33,10 @@ import (
|
||||
"github.com/filecoin-project/go-state-types/proof"
|
||||
|
||||
apitypes "github.com/filecoin-project/lotus/api/types"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
||||
builtinactors "github.com/filecoin-project/lotus/chain/actors/builtin"
|
||||
lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
"github.com/filecoin-project/lotus/journal/alerting"
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
"github.com/filecoin-project/lotus/node/repo/imports"
|
||||
@@ -122,6 +123,8 @@ type FullNodeStruct struct {
|
||||
|
||||
ChainGetBlockMessages func(p0 context.Context, p1 cid.Cid) (*BlockMessages, error) `perm:"read"`
|
||||
|
||||
ChainGetEvents func(p0 context.Context, p1 cid.Cid) ([]types.Event, error) `perm:"read"`
|
||||
|
||||
ChainGetGenesis func(p0 context.Context) (*types.TipSet, error) `perm:"read"`
|
||||
|
||||
ChainGetMessage func(p0 context.Context, p1 cid.Cid) (*types.Message, error) `perm:"read"`
|
||||
@@ -218,6 +221,68 @@ type FullNodeStruct struct {
|
||||
|
||||
CreateBackup func(p0 context.Context, p1 string) error `perm:"admin"`
|
||||
|
||||
EthAccounts func(p0 context.Context) ([]ethtypes.EthAddress, error) `perm:"read"`
|
||||
|
||||
EthBlockNumber func(p0 context.Context) (ethtypes.EthUint64, error) `perm:"read"`
|
||||
|
||||
EthCall func(p0 context.Context, p1 ethtypes.EthCall, p2 string) (ethtypes.EthBytes, error) `perm:"read"`
|
||||
|
||||
EthChainId func(p0 context.Context) (ethtypes.EthUint64, error) `perm:"read"`
|
||||
|
||||
EthEstimateGas func(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) `perm:"read"`
|
||||
|
||||
EthFeeHistory func(p0 context.Context, p1 ethtypes.EthUint64, p2 string, p3 []float64) (ethtypes.EthFeeHistory, error) `perm:"read"`
|
||||
|
||||
EthGasPrice func(p0 context.Context) (ethtypes.EthBigInt, error) `perm:"read"`
|
||||
|
||||
EthGetBalance func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBigInt, error) `perm:"read"`
|
||||
|
||||
EthGetBlockByHash func(p0 context.Context, p1 ethtypes.EthHash, p2 bool) (ethtypes.EthBlock, error) `perm:"read"`
|
||||
|
||||
EthGetBlockByNumber func(p0 context.Context, p1 string, p2 bool) (ethtypes.EthBlock, error) `perm:"read"`
|
||||
|
||||
EthGetBlockTransactionCountByHash func(p0 context.Context, p1 ethtypes.EthHash) (ethtypes.EthUint64, error) `perm:"read"`
|
||||
|
||||
EthGetBlockTransactionCountByNumber func(p0 context.Context, p1 ethtypes.EthUint64) (ethtypes.EthUint64, error) `perm:"read"`
|
||||
|
||||
EthGetCode func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBytes, error) `perm:"read"`
|
||||
|
||||
EthGetFilterChanges func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) `perm:"write"`
|
||||
|
||||
EthGetFilterLogs func(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) `perm:"write"`
|
||||
|
||||
EthGetLogs func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) `perm:"read"`
|
||||
|
||||
EthGetStorageAt func(p0 context.Context, p1 ethtypes.EthAddress, p2 ethtypes.EthBytes, p3 string) (ethtypes.EthBytes, error) `perm:"read"`
|
||||
|
||||
EthGetTransactionByBlockHashAndIndex func(p0 context.Context, p1 ethtypes.EthHash, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) `perm:"read"`
|
||||
|
||||
EthGetTransactionByBlockNumberAndIndex func(p0 context.Context, p1 ethtypes.EthUint64, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) `perm:"read"`
|
||||
|
||||
EthGetTransactionByHash func(p0 context.Context, p1 *ethtypes.EthHash) (*ethtypes.EthTx, error) `perm:"read"`
|
||||
|
||||
EthGetTransactionCount func(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthUint64, error) `perm:"read"`
|
||||
|
||||
EthGetTransactionReceipt func(p0 context.Context, p1 ethtypes.EthHash) (*EthTxReceipt, error) `perm:"read"`
|
||||
|
||||
EthMaxPriorityFeePerGas func(p0 context.Context) (ethtypes.EthBigInt, error) `perm:"read"`
|
||||
|
||||
EthNewBlockFilter func(p0 context.Context) (ethtypes.EthFilterID, error) `perm:"write"`
|
||||
|
||||
EthNewFilter func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) `perm:"write"`
|
||||
|
||||
EthNewPendingTransactionFilter func(p0 context.Context) (ethtypes.EthFilterID, error) `perm:"write"`
|
||||
|
||||
EthProtocolVersion func(p0 context.Context) (ethtypes.EthUint64, error) `perm:"read"`
|
||||
|
||||
EthSendRawTransaction func(p0 context.Context, p1 ethtypes.EthBytes) (ethtypes.EthHash, error) `perm:"read"`
|
||||
|
||||
EthSubscribe func(p0 context.Context, p1 string, p2 *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) `perm:"write"`
|
||||
|
||||
EthUninstallFilter func(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) `perm:"write"`
|
||||
|
||||
EthUnsubscribe func(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) `perm:"write"`
|
||||
|
||||
GasEstimateFeeCap func(p0 context.Context, p1 *types.Message, p2 int64, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"`
|
||||
|
||||
GasEstimateGasLimit func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (int64, error) `perm:"read"`
|
||||
@@ -306,6 +371,10 @@ type FullNodeStruct struct {
|
||||
|
||||
MsigSwapPropose func(p0 context.Context, p1 address.Address, p2 address.Address, p3 address.Address, p4 address.Address) (*MessagePrototype, error) `perm:"sign"`
|
||||
|
||||
NetListening func(p0 context.Context) (bool, error) `perm:"read"`
|
||||
|
||||
NetVersion func(p0 context.Context) (string, error) `perm:"read"`
|
||||
|
||||
NodeStatus func(p0 context.Context, p1 bool) (NodeStatus, error) `perm:"read"`
|
||||
|
||||
PaychAllocateLane func(p0 context.Context, p1 address.Address) (uint64, error) `perm:"sign"`
|
||||
@@ -687,7 +756,7 @@ type StorageMinerStruct struct {
|
||||
|
||||
ComputeDataCid func(p0 context.Context, p1 abi.UnpaddedPieceSize, p2 storiface.Data) (abi.PieceInfo, error) `perm:"admin"`
|
||||
|
||||
ComputeProof func(p0 context.Context, p1 []builtin.ExtendedSectorInfo, p2 abi.PoStRandomness, p3 abi.ChainEpoch, p4 abinetwork.Version) ([]builtin.PoStProof, error) `perm:"read"`
|
||||
ComputeProof func(p0 context.Context, p1 []builtinactors.ExtendedSectorInfo, p2 abi.PoStRandomness, p3 abi.ChainEpoch, p4 abinetwork.Version) ([]builtinactors.PoStProof, error) `perm:"read"`
|
||||
|
||||
ComputeWindowPoSt func(p0 context.Context, p1 uint64, p2 types.TipSetKey) ([]miner.SubmitWindowedPoStParams, error) `perm:"admin"`
|
||||
|
||||
@@ -1267,6 +1336,17 @@ func (s *FullNodeStub) ChainGetBlockMessages(p0 context.Context, p1 cid.Cid) (*B
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) ChainGetEvents(p0 context.Context, p1 cid.Cid) ([]types.Event, error) {
|
||||
if s.Internal.ChainGetEvents == nil {
|
||||
return *new([]types.Event), ErrNotSupported
|
||||
}
|
||||
return s.Internal.ChainGetEvents(p0, p1)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) ChainGetEvents(p0 context.Context, p1 cid.Cid) ([]types.Event, error) {
|
||||
return *new([]types.Event), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) ChainGetGenesis(p0 context.Context) (*types.TipSet, error) {
|
||||
if s.Internal.ChainGetGenesis == nil {
|
||||
return nil, ErrNotSupported
|
||||
@@ -1795,6 +1875,347 @@ func (s *FullNodeStub) CreateBackup(p0 context.Context, p1 string) error {
|
||||
return ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthAccounts(p0 context.Context) ([]ethtypes.EthAddress, error) {
|
||||
if s.Internal.EthAccounts == nil {
|
||||
return *new([]ethtypes.EthAddress), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthAccounts(p0)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthAccounts(p0 context.Context) ([]ethtypes.EthAddress, error) {
|
||||
return *new([]ethtypes.EthAddress), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthBlockNumber(p0 context.Context) (ethtypes.EthUint64, error) {
|
||||
if s.Internal.EthBlockNumber == nil {
|
||||
return *new(ethtypes.EthUint64), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthBlockNumber(p0)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthBlockNumber(p0 context.Context) (ethtypes.EthUint64, error) {
|
||||
return *new(ethtypes.EthUint64), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthCall(p0 context.Context, p1 ethtypes.EthCall, p2 string) (ethtypes.EthBytes, error) {
|
||||
if s.Internal.EthCall == nil {
|
||||
return *new(ethtypes.EthBytes), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthCall(p0, p1, p2)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthCall(p0 context.Context, p1 ethtypes.EthCall, p2 string) (ethtypes.EthBytes, error) {
|
||||
return *new(ethtypes.EthBytes), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthChainId(p0 context.Context) (ethtypes.EthUint64, error) {
|
||||
if s.Internal.EthChainId == nil {
|
||||
return *new(ethtypes.EthUint64), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthChainId(p0)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthChainId(p0 context.Context) (ethtypes.EthUint64, error) {
|
||||
return *new(ethtypes.EthUint64), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthEstimateGas(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) {
|
||||
if s.Internal.EthEstimateGas == nil {
|
||||
return *new(ethtypes.EthUint64), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthEstimateGas(p0, p1)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthEstimateGas(p0 context.Context, p1 ethtypes.EthCall) (ethtypes.EthUint64, error) {
|
||||
return *new(ethtypes.EthUint64), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthFeeHistory(p0 context.Context, p1 ethtypes.EthUint64, p2 string, p3 []float64) (ethtypes.EthFeeHistory, error) {
|
||||
if s.Internal.EthFeeHistory == nil {
|
||||
return *new(ethtypes.EthFeeHistory), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthFeeHistory(p0, p1, p2, p3)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthFeeHistory(p0 context.Context, p1 ethtypes.EthUint64, p2 string, p3 []float64) (ethtypes.EthFeeHistory, error) {
|
||||
return *new(ethtypes.EthFeeHistory), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthGasPrice(p0 context.Context) (ethtypes.EthBigInt, error) {
|
||||
if s.Internal.EthGasPrice == nil {
|
||||
return *new(ethtypes.EthBigInt), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthGasPrice(p0)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthGasPrice(p0 context.Context) (ethtypes.EthBigInt, error) {
|
||||
return *new(ethtypes.EthBigInt), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthGetBalance(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBigInt, error) {
|
||||
if s.Internal.EthGetBalance == nil {
|
||||
return *new(ethtypes.EthBigInt), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthGetBalance(p0, p1, p2)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthGetBalance(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBigInt, error) {
|
||||
return *new(ethtypes.EthBigInt), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthGetBlockByHash(p0 context.Context, p1 ethtypes.EthHash, p2 bool) (ethtypes.EthBlock, error) {
|
||||
if s.Internal.EthGetBlockByHash == nil {
|
||||
return *new(ethtypes.EthBlock), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthGetBlockByHash(p0, p1, p2)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthGetBlockByHash(p0 context.Context, p1 ethtypes.EthHash, p2 bool) (ethtypes.EthBlock, error) {
|
||||
return *new(ethtypes.EthBlock), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthGetBlockByNumber(p0 context.Context, p1 string, p2 bool) (ethtypes.EthBlock, error) {
|
||||
if s.Internal.EthGetBlockByNumber == nil {
|
||||
return *new(ethtypes.EthBlock), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthGetBlockByNumber(p0, p1, p2)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthGetBlockByNumber(p0 context.Context, p1 string, p2 bool) (ethtypes.EthBlock, error) {
|
||||
return *new(ethtypes.EthBlock), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthGetBlockTransactionCountByHash(p0 context.Context, p1 ethtypes.EthHash) (ethtypes.EthUint64, error) {
|
||||
if s.Internal.EthGetBlockTransactionCountByHash == nil {
|
||||
return *new(ethtypes.EthUint64), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthGetBlockTransactionCountByHash(p0, p1)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthGetBlockTransactionCountByHash(p0 context.Context, p1 ethtypes.EthHash) (ethtypes.EthUint64, error) {
|
||||
return *new(ethtypes.EthUint64), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthGetBlockTransactionCountByNumber(p0 context.Context, p1 ethtypes.EthUint64) (ethtypes.EthUint64, error) {
|
||||
if s.Internal.EthGetBlockTransactionCountByNumber == nil {
|
||||
return *new(ethtypes.EthUint64), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthGetBlockTransactionCountByNumber(p0, p1)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthGetBlockTransactionCountByNumber(p0 context.Context, p1 ethtypes.EthUint64) (ethtypes.EthUint64, error) {
|
||||
return *new(ethtypes.EthUint64), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthGetCode(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBytes, error) {
|
||||
if s.Internal.EthGetCode == nil {
|
||||
return *new(ethtypes.EthBytes), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthGetCode(p0, p1, p2)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthGetCode(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthBytes, error) {
|
||||
return *new(ethtypes.EthBytes), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthGetFilterChanges(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) {
|
||||
if s.Internal.EthGetFilterChanges == nil {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthGetFilterChanges(p0, p1)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthGetFilterChanges(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthGetFilterLogs(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) {
|
||||
if s.Internal.EthGetFilterLogs == nil {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthGetFilterLogs(p0, p1)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthGetFilterLogs(p0 context.Context, p1 ethtypes.EthFilterID) (*ethtypes.EthFilterResult, error) {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthGetLogs(p0 context.Context, p1 *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) {
|
||||
if s.Internal.EthGetLogs == nil {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthGetLogs(p0, p1)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthGetLogs(p0 context.Context, p1 *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthGetStorageAt(p0 context.Context, p1 ethtypes.EthAddress, p2 ethtypes.EthBytes, p3 string) (ethtypes.EthBytes, error) {
|
||||
if s.Internal.EthGetStorageAt == nil {
|
||||
return *new(ethtypes.EthBytes), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthGetStorageAt(p0, p1, p2, p3)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthGetStorageAt(p0 context.Context, p1 ethtypes.EthAddress, p2 ethtypes.EthBytes, p3 string) (ethtypes.EthBytes, error) {
|
||||
return *new(ethtypes.EthBytes), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthGetTransactionByBlockHashAndIndex(p0 context.Context, p1 ethtypes.EthHash, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) {
|
||||
if s.Internal.EthGetTransactionByBlockHashAndIndex == nil {
|
||||
return *new(ethtypes.EthTx), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthGetTransactionByBlockHashAndIndex(p0, p1, p2)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthGetTransactionByBlockHashAndIndex(p0 context.Context, p1 ethtypes.EthHash, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) {
|
||||
return *new(ethtypes.EthTx), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthGetTransactionByBlockNumberAndIndex(p0 context.Context, p1 ethtypes.EthUint64, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) {
|
||||
if s.Internal.EthGetTransactionByBlockNumberAndIndex == nil {
|
||||
return *new(ethtypes.EthTx), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthGetTransactionByBlockNumberAndIndex(p0, p1, p2)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthGetTransactionByBlockNumberAndIndex(p0 context.Context, p1 ethtypes.EthUint64, p2 ethtypes.EthUint64) (ethtypes.EthTx, error) {
|
||||
return *new(ethtypes.EthTx), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthGetTransactionByHash(p0 context.Context, p1 *ethtypes.EthHash) (*ethtypes.EthTx, error) {
|
||||
if s.Internal.EthGetTransactionByHash == nil {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthGetTransactionByHash(p0, p1)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthGetTransactionByHash(p0 context.Context, p1 *ethtypes.EthHash) (*ethtypes.EthTx, error) {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthGetTransactionCount(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthUint64, error) {
|
||||
if s.Internal.EthGetTransactionCount == nil {
|
||||
return *new(ethtypes.EthUint64), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthGetTransactionCount(p0, p1, p2)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthGetTransactionCount(p0 context.Context, p1 ethtypes.EthAddress, p2 string) (ethtypes.EthUint64, error) {
|
||||
return *new(ethtypes.EthUint64), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthGetTransactionReceipt(p0 context.Context, p1 ethtypes.EthHash) (*EthTxReceipt, error) {
|
||||
if s.Internal.EthGetTransactionReceipt == nil {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthGetTransactionReceipt(p0, p1)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthGetTransactionReceipt(p0 context.Context, p1 ethtypes.EthHash) (*EthTxReceipt, error) {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthMaxPriorityFeePerGas(p0 context.Context) (ethtypes.EthBigInt, error) {
|
||||
if s.Internal.EthMaxPriorityFeePerGas == nil {
|
||||
return *new(ethtypes.EthBigInt), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthMaxPriorityFeePerGas(p0)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthMaxPriorityFeePerGas(p0 context.Context) (ethtypes.EthBigInt, error) {
|
||||
return *new(ethtypes.EthBigInt), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthNewBlockFilter(p0 context.Context) (ethtypes.EthFilterID, error) {
|
||||
if s.Internal.EthNewBlockFilter == nil {
|
||||
return *new(ethtypes.EthFilterID), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthNewBlockFilter(p0)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthNewBlockFilter(p0 context.Context) (ethtypes.EthFilterID, error) {
|
||||
return *new(ethtypes.EthFilterID), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthNewFilter(p0 context.Context, p1 *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) {
|
||||
if s.Internal.EthNewFilter == nil {
|
||||
return *new(ethtypes.EthFilterID), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthNewFilter(p0, p1)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthNewFilter(p0 context.Context, p1 *ethtypes.EthFilterSpec) (ethtypes.EthFilterID, error) {
|
||||
return *new(ethtypes.EthFilterID), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthNewPendingTransactionFilter(p0 context.Context) (ethtypes.EthFilterID, error) {
|
||||
if s.Internal.EthNewPendingTransactionFilter == nil {
|
||||
return *new(ethtypes.EthFilterID), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthNewPendingTransactionFilter(p0)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthNewPendingTransactionFilter(p0 context.Context) (ethtypes.EthFilterID, error) {
|
||||
return *new(ethtypes.EthFilterID), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthProtocolVersion(p0 context.Context) (ethtypes.EthUint64, error) {
|
||||
if s.Internal.EthProtocolVersion == nil {
|
||||
return *new(ethtypes.EthUint64), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthProtocolVersion(p0)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthProtocolVersion(p0 context.Context) (ethtypes.EthUint64, error) {
|
||||
return *new(ethtypes.EthUint64), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthSendRawTransaction(p0 context.Context, p1 ethtypes.EthBytes) (ethtypes.EthHash, error) {
|
||||
if s.Internal.EthSendRawTransaction == nil {
|
||||
return *new(ethtypes.EthHash), ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthSendRawTransaction(p0, p1)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthSendRawTransaction(p0 context.Context, p1 ethtypes.EthBytes) (ethtypes.EthHash, error) {
|
||||
return *new(ethtypes.EthHash), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthSubscribe(p0 context.Context, p1 string, p2 *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) {
|
||||
if s.Internal.EthSubscribe == nil {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthSubscribe(p0, p1, p2)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthSubscribe(p0 context.Context, p1 string, p2 *ethtypes.EthSubscriptionParams) (<-chan ethtypes.EthSubscriptionResponse, error) {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthUninstallFilter(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) {
|
||||
if s.Internal.EthUninstallFilter == nil {
|
||||
return false, ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthUninstallFilter(p0, p1)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthUninstallFilter(p0 context.Context, p1 ethtypes.EthFilterID) (bool, error) {
|
||||
return false, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) EthUnsubscribe(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) {
|
||||
if s.Internal.EthUnsubscribe == nil {
|
||||
return false, ErrNotSupported
|
||||
}
|
||||
return s.Internal.EthUnsubscribe(p0, p1)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) EthUnsubscribe(p0 context.Context, p1 ethtypes.EthSubscriptionID) (bool, error) {
|
||||
return false, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) GasEstimateFeeCap(p0 context.Context, p1 *types.Message, p2 int64, p3 types.TipSetKey) (types.BigInt, error) {
|
||||
if s.Internal.GasEstimateFeeCap == nil {
|
||||
return *new(types.BigInt), ErrNotSupported
|
||||
@@ -2279,6 +2700,28 @@ func (s *FullNodeStub) MsigSwapPropose(p0 context.Context, p1 address.Address, p
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) NetListening(p0 context.Context) (bool, error) {
|
||||
if s.Internal.NetListening == nil {
|
||||
return false, ErrNotSupported
|
||||
}
|
||||
return s.Internal.NetListening(p0)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) NetListening(p0 context.Context) (bool, error) {
|
||||
return false, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) NetVersion(p0 context.Context) (string, error) {
|
||||
if s.Internal.NetVersion == nil {
|
||||
return "", ErrNotSupported
|
||||
}
|
||||
return s.Internal.NetVersion(p0)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) NetVersion(p0 context.Context) (string, error) {
|
||||
return "", ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) NodeStatus(p0 context.Context, p1 bool) (NodeStatus, error) {
|
||||
if s.Internal.NodeStatus == nil {
|
||||
return *new(NodeStatus), ErrNotSupported
|
||||
@@ -4182,15 +4625,15 @@ func (s *StorageMinerStub) ComputeDataCid(p0 context.Context, p1 abi.UnpaddedPie
|
||||
return *new(abi.PieceInfo), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *StorageMinerStruct) ComputeProof(p0 context.Context, p1 []builtin.ExtendedSectorInfo, p2 abi.PoStRandomness, p3 abi.ChainEpoch, p4 abinetwork.Version) ([]builtin.PoStProof, error) {
|
||||
func (s *StorageMinerStruct) ComputeProof(p0 context.Context, p1 []builtinactors.ExtendedSectorInfo, p2 abi.PoStRandomness, p3 abi.ChainEpoch, p4 abinetwork.Version) ([]builtinactors.PoStProof, error) {
|
||||
if s.Internal.ComputeProof == nil {
|
||||
return *new([]builtin.PoStProof), ErrNotSupported
|
||||
return *new([]builtinactors.PoStProof), ErrNotSupported
|
||||
}
|
||||
return s.Internal.ComputeProof(p0, p1, p2, p3, p4)
|
||||
}
|
||||
|
||||
func (s *StorageMinerStub) ComputeProof(p0 context.Context, p1 []builtin.ExtendedSectorInfo, p2 abi.PoStRandomness, p3 abi.ChainEpoch, p4 abinetwork.Version) ([]builtin.PoStProof, error) {
|
||||
return *new([]builtin.PoStProof), ErrNotSupported
|
||||
func (s *StorageMinerStub) ComputeProof(p0 context.Context, p1 []builtinactors.ExtendedSectorInfo, p2 abi.PoStRandomness, p3 abi.ChainEpoch, p4 abinetwork.Version) ([]builtinactors.PoStProof, error) {
|
||||
return *new([]builtinactors.PoStProof), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *StorageMinerStruct) ComputeWindowPoSt(p0 context.Context, p1 uint64, p2 types.TipSetKey) ([]miner.SubmitWindowedPoStParams, error) {
|
||||
|
||||
@@ -338,6 +338,7 @@ type ForkUpgradeParams struct {
|
||||
UpgradeOhSnapHeight abi.ChainEpoch
|
||||
UpgradeSkyrHeight abi.ChainEpoch
|
||||
UpgradeSharkHeight abi.ChainEpoch
|
||||
UpgradeHyggeHeight abi.ChainEpoch
|
||||
}
|
||||
|
||||
type NonceMapType map[address.Address]uint64
|
||||
|
||||
+8
-8
@@ -141,7 +141,7 @@ type FullNode interface {
|
||||
|
||||
// ChainGetPath returns a set of revert/apply operations needed to get from
|
||||
// one tipset to another, for example:
|
||||
//```
|
||||
// ```
|
||||
// to
|
||||
// ^
|
||||
// from tAA
|
||||
@@ -150,7 +150,7 @@ type FullNode interface {
|
||||
// ^---*--^
|
||||
// ^
|
||||
// tRR
|
||||
//```
|
||||
// ```
|
||||
// Would return `[revert(tBA), apply(tAB), apply(tAA)]`
|
||||
ChainGetPath(ctx context.Context, from types.TipSetKey, to types.TipSetKey) ([]*api.HeadChange, error) //perm:read
|
||||
|
||||
@@ -367,12 +367,12 @@ type FullNode interface {
|
||||
ClientCancelRetrievalDeal(ctx context.Context, dealid retrievalmarket.DealID) error //perm:write
|
||||
|
||||
// ClientUnimport removes references to the specified file from filestore
|
||||
//ClientUnimport(path string)
|
||||
// ClientUnimport(path string)
|
||||
|
||||
// ClientListImports lists imported files and their root CIDs
|
||||
ClientListImports(ctx context.Context) ([]api.Import, error) //perm:write
|
||||
|
||||
//ClientListAsks() []Ask
|
||||
// ClientListAsks() []Ask
|
||||
|
||||
// MethodGroup: State
|
||||
// The State methods are used to query, inspect, and interact with chain state.
|
||||
@@ -641,14 +641,14 @@ type FullNode interface {
|
||||
// It takes the following params: <multisig address>, <start epoch>, <end epoch>
|
||||
MsigGetVested(context.Context, address.Address, types.TipSetKey, types.TipSetKey) (types.BigInt, error) //perm:read
|
||||
|
||||
//MsigGetPending returns pending transactions for the given multisig
|
||||
//wallet. Once pending transactions are fully approved, they will no longer
|
||||
//appear here.
|
||||
// MsigGetPending returns pending transactions for the given multisig
|
||||
// wallet. Once pending transactions are fully approved, they will no longer
|
||||
// appear here.
|
||||
MsigGetPending(context.Context, address.Address, types.TipSetKey) ([]*api.MsigTransaction, error) //perm:read
|
||||
|
||||
// MsigCreate creates a multisig wallet
|
||||
// It takes the following params: <required number of senders>, <approving addresses>, <unlock duration>
|
||||
//<initial balance>, <sender address of the create msg>, <gas price>
|
||||
// <initial balance>, <sender address of the create msg>, <gas price>
|
||||
MsigCreate(context.Context, uint64, []address.Address, abi.ChainEpoch, types.BigInt, address.Address, types.BigInt) (cid.Cid, error) //perm:sign
|
||||
// MsigPropose proposes a multisig message
|
||||
// It takes the following params: <multisig address>, <recipient address>, <value to transfer>,
|
||||
|
||||
@@ -905,6 +905,10 @@ func (s *SplitStore) walkChain(ts *types.TipSet, inclState, inclMsgs abi.ChainEp
|
||||
walkCnt := new(int64)
|
||||
scanCnt := new(int64)
|
||||
|
||||
tsRef := func(blkCids []cid.Cid) (cid.Cid, error) {
|
||||
return types.NewTipSetKey(blkCids...).Cid()
|
||||
}
|
||||
|
||||
stopWalk := func(_ cid.Cid) error { return errStopWalk }
|
||||
|
||||
walkBlock := func(c cid.Cid) error {
|
||||
@@ -926,11 +930,19 @@ func (s *SplitStore) walkChain(ts *types.TipSet, inclState, inclMsgs abi.ChainEp
|
||||
err = s.view(c, func(data []byte) error {
|
||||
return hdr.UnmarshalCBOR(bytes.NewBuffer(data))
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return xerrors.Errorf("error unmarshaling block header (cid: %s): %w", c, err)
|
||||
}
|
||||
|
||||
// tipset CID references are retained
|
||||
pRef, err := tsRef(hdr.Parents)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("error computing cid reference to parent tipset")
|
||||
}
|
||||
if err := s.walkObjectIncomplete(pRef, visitor, fHot, stopWalk); err != nil {
|
||||
return xerrors.Errorf("error walking parent tipset cid reference")
|
||||
}
|
||||
|
||||
// message are retained if within the inclMsgs boundary
|
||||
if hdr.Height >= inclMsgs && hdr.Height > 0 {
|
||||
if inclMsgs < inclState {
|
||||
@@ -981,6 +993,15 @@ func (s *SplitStore) walkChain(ts *types.TipSet, inclState, inclMsgs abi.ChainEp
|
||||
return nil
|
||||
}
|
||||
|
||||
// retain ref to chain head
|
||||
hRef, err := tsRef(ts.Cids())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("error computing cid reference to parent tipset")
|
||||
}
|
||||
if err := s.walkObjectIncomplete(hRef, visitor, fHot, stopWalk); err != nil {
|
||||
return xerrors.Errorf("error walking parent tipset cid reference")
|
||||
}
|
||||
|
||||
for len(toWalk) > 0 {
|
||||
// walking can take a while, so check this with every opportunity
|
||||
if err := s.checkClosing(); err != nil {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
NETWORKS=(devnet mainnet caterpillarnet butterflynet testing testing-fake-proofs calibrationnet)
|
||||
NETWORKS=(devnet mainnet caterpillarnet butterflynet testing testing-fake-proofs calibrationnet hyperspace)
|
||||
|
||||
set -e
|
||||
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,4 @@
|
||||
/dns4/de0.bootstrap.wallaby.network/tcp/1337/p2p/12D3KooWHAvUVk5XuxSwi2dNLWbTDDRSGeHxMuWdQ3SQpRuNHbLz
|
||||
/dns4/de1.bootstrap.wallaby.network/tcp/1337/p2p/12D3KooWBRqtxhJCtiLmCwKgAQozJtdGinEDdJGoS5oHw7vCjMGc
|
||||
/dns4/ca0.bootstrap.wallaby.network/tcp/1337/p2p/12D3KooWCApBpUk7EX9pmEfyky1gKC6N2KJ74S1AwFfvnkDqw3pK
|
||||
/dns4/sg0.bootstrap.wallaby.network/tcp/1337/p2p/12D3KooWLnYqr4hRoNHBJQVXsFGkDoKuoVfw5R2ASw1bHzrWU5Px
|
||||
+141
-112
@@ -44,23 +44,24 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
|
||||
}, {
|
||||
Network: "butterflynet",
|
||||
Version: 10,
|
||||
ManifestCid: MustParseCid("bafy2bzaceciz4ytt5gnn6gc4epez7v6xeg6efkgbvwfxkoa34o2gj3hp5f7zc"),
|
||||
ManifestCid: MustParseCid("bafy2bzaceav7txndea2xt6kvaosokp42vyjkhtplbb67tpkov3jbsvbwplnz4"),
|
||||
Actors: map[string]cid.Cid{
|
||||
"account": MustParseCid("bafk2bzacedavorwsriewoddjlaganjpsk3o7zfts2wyid3clv5xnctacg37j2"),
|
||||
"cron": MustParseCid("bafk2bzacebtauucwaewxuzgxfpjtmn6xt3kya4om4ugyprlkhhkde76h7fkqg"),
|
||||
"datacap": MustParseCid("bafk2bzacebzdjapqwasq6woxkgq2nm2nre3v7cl2754xwiuo2cfhvsceq4cba"),
|
||||
"eam": MustParseCid("bafk2bzacecmr4zdbpfnemvgo446qby7x4y4v5cbfespt3f6ousv2hxnflyrlk"),
|
||||
"embryo": MustParseCid("bafk2bzacebj2mj5zlcs3yjlgpbznzistfjkdlwaoncjziliqrxqavvz4dcvnk"),
|
||||
"evm": MustParseCid("bafk2bzacebuewexvig54cuvsvwn4k4zr36tm2q5fel4ezq4v7363n2lmn362k"),
|
||||
"init": MustParseCid("bafk2bzacebww5gsctsk5hack2alkt4kh55bmpb4ywzbyyhoaskryymjj3snj6"),
|
||||
"multisig": MustParseCid("bafk2bzacec5k4wxvou34pyjd5kcsrbsfnlk4k753kkscg3ron2r7tsxollfsq"),
|
||||
"paymentchannel": MustParseCid("bafk2bzacebzdeaxglaqpmegalakmxr6secjd24mu5llo4ctoy7pvom5upyuvs"),
|
||||
"reward": MustParseCid("bafk2bzaceb4hyabxnyrrsno5erqqwk5ynnjibblzfcaq3aotlz3ek4uu6dyla"),
|
||||
"storagemarket": MustParseCid("bafk2bzacedpocbf2lg2x2jg6arw2argnwmvo2hyjqvpkrgfu4khz5mtlzxz2o"),
|
||||
"storageminer": MustParseCid("bafk2bzaceacrumah7jdfc62bmvemob4lsh5yiohwodest2cgxakgnn24cenlk"),
|
||||
"storagepower": MustParseCid("bafk2bzaceaxz6n5nywermfptnz6dc53vqsa42lic4rf66l4irm3mqfj4ak5ps"),
|
||||
"system": MustParseCid("bafk2bzaceb4w5bblgyu25ylytpmfrixjsk2ra6emd44j4mv42xfxbwnqloyzi"),
|
||||
"verifiedregistry": MustParseCid("bafk2bzacedbz2koeb6teewobcjdpgfv7qdae7utgoka6wzlkf6gronnis2nn2"),
|
||||
"account": MustParseCid("bafk2bzacec34ox7drngorgal3ujxat2a2dlsh7eissgiisrv2uubuub2avbe2"),
|
||||
"cron": MustParseCid("bafk2bzaceb77n6gkytpkn2wguemnpfqfaynv7u6ci4j247leg2w3dhcoxa5ns"),
|
||||
"datacap": MustParseCid("bafk2bzacebj2ztqmlb7mmkggaqf66sv7gao5722vzmpnngiuncu4efpsjyhy4"),
|
||||
"eam": MustParseCid("bafk2bzacecvl6xpmldfk5oyehqhmuasp7cbx3kh3y425curdy65hlmhovc4oi"),
|
||||
"ethaccount": MustParseCid("bafk2bzacec2wy3fknb63r5zili7qojvt4f3rvstweqvnjne5adarx3lskgz5m"),
|
||||
"evm": MustParseCid("bafk2bzacebtoqzucrh7kvtxpo4ruzisey67z6t3z5cbff4c36du3dlm3aj4l6"),
|
||||
"init": MustParseCid("bafk2bzacebvc5t5u3opeyx4rxbeinshjsghjhttdbsyqifb4ikzpa2ic5mkhu"),
|
||||
"multisig": MustParseCid("bafk2bzaceckmb2bcw2m5o4hifhodrq2j6ow5nhouj5wpqsxpzntgveft3hplu"),
|
||||
"paymentchannel": MustParseCid("bafk2bzacebsvkpbavcdjguev4dxfnjx5j5bqzeeyk3petwbkmfptoej5bqlqc"),
|
||||
"placeholder": MustParseCid("bafk2bzacedv773z6clfjh7wxvlqd6ki7bncztt73org7apnnt2acjigrjdg4a"),
|
||||
"reward": MustParseCid("bafk2bzacea3rkyhzmugj6ap3uv5m5jnhxt64y2775vo6vemdi5aafzxty3nmq"),
|
||||
"storagemarket": MustParseCid("bafk2bzacebfacbnuauxhq63f5jbchoi2xwc5ljrxnwgj2xulkx4yzfu6i4lhg"),
|
||||
"storageminer": MustParseCid("bafk2bzaceal4ct6gwlzl3owu6d4iiudf4ioxth5gn6cvm37enl465px2bhznk"),
|
||||
"storagepower": MustParseCid("bafk2bzaceb5pdkt55d7wxjgmhvzvnlkuw5r6eamypgqm5kem5tz3sxddwtizw"),
|
||||
"system": MustParseCid("bafk2bzacecuu2y5b6r4jrj64w5yuh3klnoevrcnbdxozmtagdcyfve7oe27ri"),
|
||||
"verifiedregistry": MustParseCid("bafk2bzacediez3q42tjeit7hbsglv33ltfeamoa43lftwsxh2nyov5ijhuihm"),
|
||||
},
|
||||
}, {
|
||||
Network: "calibrationnet",
|
||||
@@ -100,23 +101,24 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
|
||||
}, {
|
||||
Network: "calibrationnet",
|
||||
Version: 10,
|
||||
ManifestCid: MustParseCid("bafy2bzaced7wbd43lvgc55xb37mkoo4ppev6ig4jj4j7dtswtjfjq4u5qmpck"),
|
||||
ManifestCid: MustParseCid("bafy2bzacebb4qaymahytofcakf3vcyuv4tnu4zsgxp4iikc6kkmfagtaierro"),
|
||||
Actors: map[string]cid.Cid{
|
||||
"account": MustParseCid("bafk2bzacecq4owv5begvryvpsy4atfb2jnf7g7o4hxovtdb5a4jfkzacownli"),
|
||||
"cron": MustParseCid("bafk2bzaced4uz5w5h5wksx4end27lphd4qc4kh7q336uyt46lba5ddynwftya"),
|
||||
"datacap": MustParseCid("bafk2bzacedoc7y4s5n3p2zo4bcmafcrellkakn2e3uyf5wb3mtbuqhvwqn2l4"),
|
||||
"eam": MustParseCid("bafk2bzacealpqjgz5qmucm3v6z6hn36igx7zijixhqrxwoj3g4bdgvyml3adi"),
|
||||
"embryo": MustParseCid("bafk2bzacebj2mj5zlcs3yjlgpbznzistfjkdlwaoncjziliqrxqavvz4dcvnk"),
|
||||
"evm": MustParseCid("bafk2bzacedmlmyy2efbt4qk5ighawiychklhzc6pzyiwvpijwvxoq3xyxlgxw"),
|
||||
"init": MustParseCid("bafk2bzaceaqcfmfylwdemq5bdcelydpf6iqfct4p7b2zwtmqyhuxn522yvic2"),
|
||||
"multisig": MustParseCid("bafk2bzacebuh55hkbkobmmoaoduruss5nsh6e2gtqtdbqsmw6e7k5vg6heyrm"),
|
||||
"paymentchannel": MustParseCid("bafk2bzacedcpzw7prdoxnaclcvmtwr6yf54zi4bzzwe5w3xknh72ji6p3qfc6"),
|
||||
"reward": MustParseCid("bafk2bzaced74ym6j424zzbr6millasfcyl3r4zm5fnauasrwn3ti6fdarbkym"),
|
||||
"storagemarket": MustParseCid("bafk2bzacec7delr2q42yj4wu3daa5xjz4zezeivphtx3xwyvpgwpdnfoevhh2"),
|
||||
"storageminer": MustParseCid("bafk2bzaced7isnew5lhu237pdtwaqmbv65qqvfmmnve2c5yfobtfqw2fptuvc"),
|
||||
"storagepower": MustParseCid("bafk2bzacebe5frk6gcgzcvzkxavhhbs3id3iyacybn7y7gxwzgl5t6zawzswg"),
|
||||
"system": MustParseCid("bafk2bzacectivaezqijucle5s2f7xeui5uxig7bnk7fe4vsvz3xu7agjtb2ge"),
|
||||
"verifiedregistry": MustParseCid("bafk2bzaceczgwckte4exultjxyzgzoo6m6r5coyphnlappi4clethhhybslxc"),
|
||||
"account": MustParseCid("bafk2bzaceakcix46r7hh4wjhzaksnha6f5elbg62ld6dklz6ttkhisnppmoe2"),
|
||||
"cron": MustParseCid("bafk2bzaceb5ezi5dlgxjmxffecrmgiajwseiblgivho5qnfejivuqxfclooma"),
|
||||
"datacap": MustParseCid("bafk2bzaceag4j2myqvwevm3mdtvmqoeguwtjheyezodjcpq5ugibjx6gtz65u"),
|
||||
"eam": MustParseCid("bafk2bzacedwnuqthwpl3si5gs27xnxq7bcr5ucg3vg4utltfhnytaqzwlk33g"),
|
||||
"ethaccount": MustParseCid("bafk2bzacechx3zdc4yw7ehtelecwsp6hb2iguefusfccqxfmdinjjoa64ado4"),
|
||||
"evm": MustParseCid("bafk2bzaceaqtomr2odeyjabgkwnwfgm54b44cpshpkssn7nq35umzogkqqbee"),
|
||||
"init": MustParseCid("bafk2bzacebtqjmdudvfl5cq6yqswortlc46cjpz36qj5igzfglu55kppuovyw"),
|
||||
"multisig": MustParseCid("bafk2bzaceb2hlrmljz26gecv7zj5ymeleiuebf6mnvc7vng3qbcxvxagrlc22"),
|
||||
"paymentchannel": MustParseCid("bafk2bzacecbn4m6evxxoalujyt4wnas3hdttffzjee5qjp62w7dsjdoeuhzka"),
|
||||
"placeholder": MustParseCid("bafk2bzacedv773z6clfjh7wxvlqd6ki7bncztt73org7apnnt2acjigrjdg4a"),
|
||||
"reward": MustParseCid("bafk2bzaceds2kn4fn27nwlxx2raawldkytlro6i2qeh6rdtmme6ybd4otpwqq"),
|
||||
"storagemarket": MustParseCid("bafk2bzacec35rrhgiqqrwqjtuhoseg7e4g67sqaa74b2x2p7f37ylfulc672i"),
|
||||
"storageminer": MustParseCid("bafk2bzaceaiwkboswmk4kmzctnzd5txf2axdvladlf6x5as7ey7avxa5dgfd4"),
|
||||
"storagepower": MustParseCid("bafk2bzaceb2nlgx5aw2psgiedc7oqefs6mttwcloczsbucxtit55zzpbgr4fc"),
|
||||
"system": MustParseCid("bafk2bzacecki2gyvfguathvwva4ilovedftfuxvk3rhuw4y2t4aawkm2e5ttq"),
|
||||
"verifiedregistry": MustParseCid("bafk2bzacebvicauwopayihp5jjegtma26nuhubauya73tkhpdfs27xwjutn4w"),
|
||||
},
|
||||
}, {
|
||||
Network: "caterpillarnet",
|
||||
@@ -156,23 +158,24 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
|
||||
}, {
|
||||
Network: "caterpillarnet",
|
||||
Version: 10,
|
||||
ManifestCid: MustParseCid("bafy2bzacea5csj2os7h76a6yvf6shgpwkysawijxemk5uvvzejxrwjo6ir4yg"),
|
||||
ManifestCid: MustParseCid("bafy2bzacedktxutlehqmx2uryphph6dln4wbgy6yfsj7un36b2u7l7a32n3km"),
|
||||
Actors: map[string]cid.Cid{
|
||||
"account": MustParseCid("bafk2bzacea7tpruyxdgyz4xa7curiphwdw4abmspft3ee24puruazdcl3tq5c"),
|
||||
"cron": MustParseCid("bafk2bzacebc6kkj7kzsicm5baszjgd37b4b3kijsffqmmkhhjlyd7zhkwfcqm"),
|
||||
"datacap": MustParseCid("bafk2bzaceddcmwl6po2jd3tfkkgv4zvub7i47gsx33pkqdspqhgvhe4npc4as"),
|
||||
"eam": MustParseCid("bafk2bzaceccsvcww2rmqnh4plkq6oapqaeqbhydrtup54z4dwunolz5tpgtb4"),
|
||||
"embryo": MustParseCid("bafk2bzacebj2mj5zlcs3yjlgpbznzistfjkdlwaoncjziliqrxqavvz4dcvnk"),
|
||||
"evm": MustParseCid("bafk2bzacea5sig3zpxfkqppoj3t344cvuhzvkx6ge2isgdzc34rfpng2ogdje"),
|
||||
"init": MustParseCid("bafk2bzacedtby353aho7itoyoj7w6moydmigjm3sgy6djgnfxqehlpae4vcc2"),
|
||||
"multisig": MustParseCid("bafk2bzacedyguvwz5zfveqoqicn3j6lkdzipf247nhvdi6dvmahulr7nzgox6"),
|
||||
"paymentchannel": MustParseCid("bafk2bzaceavaatmmnsz3v3ksopcbu6jx4iq7u7nnmqbclsiabsfkfu3zfpmka"),
|
||||
"reward": MustParseCid("bafk2bzacecrphs4avteik4yejsqwkpy5bcqramdhnzykbfq3uu2qalj2p26ti"),
|
||||
"storagemarket": MustParseCid("bafk2bzaceajby2jb5m3fenzarum374zxdzuyrpkspfljwovu7c3hvyceqd5sa"),
|
||||
"storageminer": MustParseCid("bafk2bzacebqtn7jdvk756ighri5ajro6gjepnef3c6rxupbbgkth62zytiy5s"),
|
||||
"storagepower": MustParseCid("bafk2bzacedwlo32brlalpovfkkk7qwo3ou2kpgv2bf7fioy5srn7uejmn7n46"),
|
||||
"system": MustParseCid("bafk2bzacebbt63h26x5vw5fdo2pmdb4q65u3t6lilkugvmjar6zfsc7ethxsi"),
|
||||
"verifiedregistry": MustParseCid("bafk2bzacecr5kbyypdxnxlepzk5sji2k72t454vto5ok4owfcuwfpeyivjtu4"),
|
||||
"account": MustParseCid("bafk2bzaceaoina2vmmq24ij5kqbgawjrlnxkmj6arzucoigabt25ch6cdvbyc"),
|
||||
"cron": MustParseCid("bafk2bzaceancnphwoym4pmzatrzfxo3bac72gk4bjgaqxedrigfrua62an3n2"),
|
||||
"datacap": MustParseCid("bafk2bzaceaoebtmqyqvyv7oq7ehdkhl6fxjamz5fjdje7axslxsc7rhqchcdm"),
|
||||
"eam": MustParseCid("bafk2bzaceazfxudfagmhdmwx46sjeyqoba3quy7cllqv2nuksh3ikc6gw63yg"),
|
||||
"ethaccount": MustParseCid("bafk2bzaceblsm6aaymb2ua64eqbe32uyxdoyqzger5recw6k4p43yeu2oyigi"),
|
||||
"evm": MustParseCid("bafk2bzacea7jveqmq5u6ijabkbuujtgqzmy3p5zl5x45frnygio3hqqnabbso"),
|
||||
"init": MustParseCid("bafk2bzacecdewh4goftyp2cmuq3zpkyjinv6faysksjgqxtbk2j5dljv75rgq"),
|
||||
"multisig": MustParseCid("bafk2bzacecpscu24o2fwlspi64k3fiaufeh3nnrv6wgumvaeco2jduhposcf4"),
|
||||
"paymentchannel": MustParseCid("bafk2bzacedxc3fy436wlebsusgwcwqf6lzo7yv5iugy75z5hwrdt33pq2rhho"),
|
||||
"placeholder": MustParseCid("bafk2bzacedv773z6clfjh7wxvlqd6ki7bncztt73org7apnnt2acjigrjdg4a"),
|
||||
"reward": MustParseCid("bafk2bzacebzvjtzzuo6ijkbx2yx3ly6vlrgw37fymasdwcdymlxc26znib2og"),
|
||||
"storagemarket": MustParseCid("bafk2bzaceabdr5l4qluc4rgxjxo4xnoyc5e6slp7s3fojhnv4ng3swu7qv556"),
|
||||
"storageminer": MustParseCid("bafk2bzaceclwbgfqr7wqepi6xkpoqz2bl6p22mlbmsgs4zarxki2cub5rspxy"),
|
||||
"storagepower": MustParseCid("bafk2bzacean3trpjoxvwztrmbw7lx6osapicxzclyz2cgou4upq432norjnaq"),
|
||||
"system": MustParseCid("bafk2bzacedeexlnmp677eauba76trar47p2zddbspiodri5aof6ccasyicxxo"),
|
||||
"verifiedregistry": MustParseCid("bafk2bzaceayctmu2avbckz4scuep3ocxsw5r3eqxz7wu27volaxnvfvoxjhbq"),
|
||||
},
|
||||
}, {
|
||||
Network: "devnet",
|
||||
@@ -212,23 +215,46 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
|
||||
}, {
|
||||
Network: "devnet",
|
||||
Version: 10,
|
||||
ManifestCid: MustParseCid("bafy2bzacea73thrlpfejrswlcu5uhe7rcgdewvmrcwoef6jzngsba3i4v5ibi"),
|
||||
ManifestCid: MustParseCid("bafy2bzacea2wblucgi2tztgk52fap2wsjddrrobito5zdklqdhpdwhmyr7lbk"),
|
||||
Actors: map[string]cid.Cid{
|
||||
"account": MustParseCid("bafk2bzaceau2o55aripm7kqrbzzog72zcduv5psnxzpohx5rdkykepc4z7aag"),
|
||||
"cron": MustParseCid("bafk2bzacec5qc5xluwikf4lolfa4oe356iwep25tiezbxfdyg5jib54rhlh6q"),
|
||||
"datacap": MustParseCid("bafk2bzacebo47u6q3xou5exsecjpa4rpfqjfm7vyhz4qlr3nk7p46trsk4occ"),
|
||||
"eam": MustParseCid("bafk2bzacea6yeptevserd7ayf4ahokor4sdpizpxpbqwkuvvhzdkon672shsm"),
|
||||
"embryo": MustParseCid("bafk2bzacebj2mj5zlcs3yjlgpbznzistfjkdlwaoncjziliqrxqavvz4dcvnk"),
|
||||
"evm": MustParseCid("bafk2bzacebi46zgjili4luu3nqy6mno5k4skvo4cvs7genhkdfaukhtw7xirw"),
|
||||
"init": MustParseCid("bafk2bzacedvf2bij6jovem2dfzkz347yvmydxj7vlgaiagosz5t3c5jyy43zu"),
|
||||
"multisig": MustParseCid("bafk2bzacecukolwx6y5pcajnxg2aawiubgxo5zyj24a23zg5t4qu3k4qbofh4"),
|
||||
"paymentchannel": MustParseCid("bafk2bzacecwyih7nodrwsw5vyl5zk7fapklje76jpowqjr6x6br2bm55smqqy"),
|
||||
"reward": MustParseCid("bafk2bzacea6vfrcprxg2i4l5qnigf4c6pyvnjxpzfqr4pmph3elif7sfidrei"),
|
||||
"storagemarket": MustParseCid("bafk2bzaceahradb3od4ahs46x6yriwvm36iabgtohhoiolubsumto5eravzbu"),
|
||||
"storageminer": MustParseCid("bafk2bzacedekivqgvqapbepvzn6jte3xyymyg5yjuwy42xvboa6rcqnzgo74u"),
|
||||
"storagepower": MustParseCid("bafk2bzacedkmiosllqqqarmr53twspyswdvsm7givwczgo3qqsxzpad4hzjma"),
|
||||
"system": MustParseCid("bafk2bzaceagdymtxb4lxqqjgmnphbgdtdgveuuqaouswpzagj4bpbon3ptop4"),
|
||||
"verifiedregistry": MustParseCid("bafk2bzacec556wsqldm22k2abshvvnsrawlm3bbqkwzht6ubcj76m2jsy3azi"),
|
||||
"account": MustParseCid("bafk2bzacealrkumvvuyeefrnedyh2ilgozgrdp5canubuakp723pczjdcogvw"),
|
||||
"cron": MustParseCid("bafk2bzacedcfqpqgwj4tgtccliqzwnjbxiceyc3lzylnf6owu54etiv3udjxi"),
|
||||
"datacap": MustParseCid("bafk2bzacear73heimtdso2qnw77gx6lzqmnr5f5etlggwevut5di6d7nzaoqu"),
|
||||
"eam": MustParseCid("bafk2bzacecff4dgsqjcele3zejp77weofbqkef57r2tcy4alkx7e7n3kbkmyy"),
|
||||
"ethaccount": MustParseCid("bafk2bzacec75pm3q66lsex2mqpm7fax7h6bfbkpwodf4o5gzgnrc2cdifbvfw"),
|
||||
"evm": MustParseCid("bafk2bzaceacbkauvu7ia3euoz5jfdrkw5s7mk4ga5byf3oqndxeaxyxhgnk4m"),
|
||||
"init": MustParseCid("bafk2bzacebtc7p3fq4d7m76jphagzpav2kfxfok7d56wrkek4zqyfqvtpihwm"),
|
||||
"multisig": MustParseCid("bafk2bzaceci3czx4l42u22iozsgg6zkls5wdtrztekmzy4qnybg4qlv4b3qli"),
|
||||
"paymentchannel": MustParseCid("bafk2bzacea54hgf2czdhlxvn66pyoon5cw3fwdlwx4kp4fwftv2tat4r4nnqg"),
|
||||
"placeholder": MustParseCid("bafk2bzacedv773z6clfjh7wxvlqd6ki7bncztt73org7apnnt2acjigrjdg4a"),
|
||||
"reward": MustParseCid("bafk2bzacebd7ia2qfpxob2enuazpy3yc2wpach5rq2qbm7uwgknyzqqruefmm"),
|
||||
"storagemarket": MustParseCid("bafk2bzaceam7ns7axlv3sghrwdo7kriw2hrlblim2pingllnvatqu2xfjfhgs"),
|
||||
"storageminer": MustParseCid("bafk2bzacecbfmgzg5unc3ia7yme75psji2j6uhalt5jco6niu6wcn3pdufavy"),
|
||||
"storagepower": MustParseCid("bafk2bzacedxzvoqa3a4lzajoke75q2ujhmazm4inb7robfikgtywr4sp6mgcy"),
|
||||
"system": MustParseCid("bafk2bzaceb5wpgomztoaxfv2hhgb5xtbmq4t53wev6mg4yonax5glbi4dtcoe"),
|
||||
"verifiedregistry": MustParseCid("bafk2bzacedf2f53g4cuvt6efwlga2sbovuy3tzcc2rhjh5eaa5f2ivri25ehc"),
|
||||
},
|
||||
}, {
|
||||
Network: "hyperspace",
|
||||
Version: 10,
|
||||
ManifestCid: MustParseCid("bafy2bzacearfqpg6omcyjot2zc5yynkb4bsfkykqacmwaiwiodvhlin4j4xta"),
|
||||
Actors: map[string]cid.Cid{
|
||||
"account": MustParseCid("bafk2bzacec63ehicn6roe4hwtktiqjdpn7buw4vewix2fshvk7ruk6bg54bga"),
|
||||
"cron": MustParseCid("bafk2bzacedgz5736vxapicnbdrk5yrbgwbjizhr5hjglxwkb6sonqpoyaid4u"),
|
||||
"datacap": MustParseCid("bafk2bzacedmuhap3ephpwcvyqxry54irmw5zaz74abhmnjlwrf6ioihrzcqgu"),
|
||||
"eam": MustParseCid("bafk2bzacedx5iw3jyrdfkvgqcas244e6hqotli72uinwiy74ae7s4imax6agc"),
|
||||
"ethaccount": MustParseCid("bafk2bzacectie3kbxquentwvrlcwoqzfisfcqfgngzgyndhjgclmg7cyf6zwa"),
|
||||
"evm": MustParseCid("bafk2bzacedtbvq77pb4vd7rx2inklizjeipt7myb7tim5hms2vzzmuareekrw"),
|
||||
"init": MustParseCid("bafk2bzacebcmb4nwbhambosg2xcfhifkqnaoxsotfwekmxeq7phgqgxzzxnts"),
|
||||
"multisig": MustParseCid("bafk2bzacedw73tmdl7stykyycxmhsb3iom7notxmx24b2647g3vwmrg2brgqu"),
|
||||
"paymentchannel": MustParseCid("bafk2bzaced5frgcp6bszhis5kxtm6uko5jlgbuzyczqsj7uavovkayrbizg4s"),
|
||||
"placeholder": MustParseCid("bafk2bzacedv773z6clfjh7wxvlqd6ki7bncztt73org7apnnt2acjigrjdg4a"),
|
||||
"reward": MustParseCid("bafk2bzaceddc5c45lnbo7i3uknk5zi3qbq6k4rocfoq3n7x3qerehyevjl7ja"),
|
||||
"storagemarket": MustParseCid("bafk2bzaceafqt55lykve6ex5bw65ueuec6bjcwfmq6vbhwbgjmpt4cztldzle"),
|
||||
"storageminer": MustParseCid("bafk2bzacebongyek6ijaqzup6fe2kplq24dr3dtvweu5fmfjl236rjhyqv3gs"),
|
||||
"storagepower": MustParseCid("bafk2bzaceapgnms6ldjpewmniaqawu5sflssycjbwydqvilja66y5wm4lulwq"),
|
||||
"system": MustParseCid("bafk2bzaceaki4yktxjcaxuj4be4q2ybrjiqcqq7orgzqgmidcavn3dzxyo7ds"),
|
||||
"verifiedregistry": MustParseCid("bafk2bzacedrd4uxho6tpksyullgb6lofudlwntjwt7sqrtdgzjoj6eu7onwnc"),
|
||||
},
|
||||
}, {
|
||||
Network: "mainnet",
|
||||
@@ -268,23 +294,24 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
|
||||
}, {
|
||||
Network: "mainnet",
|
||||
Version: 10,
|
||||
ManifestCid: MustParseCid("bafy2bzaceduyggnyqhlr346hfw32tbobzrvhzhill33zhe7jw64pmwjci2xoc"),
|
||||
ManifestCid: MustParseCid("bafy2bzacedjq47v3yxxptl3vvtpin4optnhoe7ynxjncuhpak2ifdvff2mrfy"),
|
||||
Actors: map[string]cid.Cid{
|
||||
"account": MustParseCid("bafk2bzacedmr3wxl7qmhquageorrt3aavbzqfpm7eymxidakwuhaobu7dseqs"),
|
||||
"cron": MustParseCid("bafk2bzaceblekxapm5nnqnxmw3mk27236iyutvbhhpsc3fyde7zi7guccn7cc"),
|
||||
"datacap": MustParseCid("bafk2bzacedu4jevyvqsilq7bq4uhegbkm75muwebc5ifqpfaojwhexf2j4i6a"),
|
||||
"eam": MustParseCid("bafk2bzacedc7224twbolvdq6iwc7ybdpah2ywe3ueo33jv67ecimndinle374"),
|
||||
"embryo": MustParseCid("bafk2bzacebj2mj5zlcs3yjlgpbznzistfjkdlwaoncjziliqrxqavvz4dcvnk"),
|
||||
"evm": MustParseCid("bafk2bzaceaggldo6wmkvp5innv4pnjv4xnpedspzofvma3dhu7vk45hh5djoq"),
|
||||
"init": MustParseCid("bafk2bzacedutlaebaczkdi4vqvt3xim24u3whleqk2r4lufjd5jnmxcosea6q"),
|
||||
"multisig": MustParseCid("bafk2bzaceatiqxjwtugpzus3s52zoggnrftxqn7kiw3obvjgkjvtd6zr3636q"),
|
||||
"paymentchannel": MustParseCid("bafk2bzacebyviac6i43gtsvmjfg6mzcp6rwgz44axidc7m432btbmvt7i2m2g"),
|
||||
"reward": MustParseCid("bafk2bzacecbcnlvk2izojpfoaksitqenhzaofn6ynxx5pegl4y45wjlouexdi"),
|
||||
"storagemarket": MustParseCid("bafk2bzacebobteeoz2jycplgtydfyltzughegz2sopn6pzy2udjfvuo77joyk"),
|
||||
"storageminer": MustParseCid("bafk2bzacecwcypas3y6u4rya7qolfwmou437xgrjxh7mnnim7bo3nhk4dscxw"),
|
||||
"storagepower": MustParseCid("bafk2bzacec62kids6rcrdmdeqhwiz3s5rs35s5gn25ilwemgmm6jqnr2rnaaq"),
|
||||
"system": MustParseCid("bafk2bzacecj3c4bjbs2xfttn7zqle7yocqh47u2s7hwuxrsn7fi5h74tcyxoc"),
|
||||
"verifiedregistry": MustParseCid("bafk2bzacedgf7zbnlste5ukzueduemkimiit64scz7lvebztufx5jxtx6gkz2"),
|
||||
"account": MustParseCid("bafk2bzaceb7wftmnoa5zbeu6jsrzvqpjfd7kudhueve6duwxcflcaqeagqg6g"),
|
||||
"cron": MustParseCid("bafk2bzacean2xecc6kfbrueglsujjqswz5nvjstmtvdq2zc5vk4cbh6gvgxcq"),
|
||||
"datacap": MustParseCid("bafk2bzacear4esja4asfsdeqto6o5cjn5dbgxmzvu2uel36tzdp2s26fkte4y"),
|
||||
"eam": MustParseCid("bafk2bzacectduzxzk23xffgohmsmq4gisl4etaguq2xe6h52y7aiaaibmi2pg"),
|
||||
"ethaccount": MustParseCid("bafk2bzacecqoxzy2p3i46ncuvw6wzlesaw5iobqpp7nmjtkbxyiwblg4frzmg"),
|
||||
"evm": MustParseCid("bafk2bzacecgz6klga2lwjp3d3iyzkzm4td5aefeaymmn3rmixgg7a4vwoewcu"),
|
||||
"init": MustParseCid("bafk2bzacebzrlucqk23kkjv26srpzjgztx7qjm23suqbyzu2qdto5jbpifm7y"),
|
||||
"multisig": MustParseCid("bafk2bzacedls4tgmkfkasgcsfrtnkjoi6yoze5yq4cafqzbjvbty5gfeut4n4"),
|
||||
"paymentchannel": MustParseCid("bafk2bzaceazuokt65n3hqjgmwmgoi6gpcvete2b46nlecnynjkgrzp4wnl4ii"),
|
||||
"placeholder": MustParseCid("bafk2bzacedv773z6clfjh7wxvlqd6ki7bncztt73org7apnnt2acjigrjdg4a"),
|
||||
"reward": MustParseCid("bafk2bzacecqjpnbxravwqb7liwxowb5bdml4x2qboo5vqxk7slprq3eo4ujp2"),
|
||||
"storagemarket": MustParseCid("bafk2bzacecuedinzm256nup2pbsdrnxerfk33hqxhakupb3c26fwk576ehgiw"),
|
||||
"storageminer": MustParseCid("bafk2bzaceb4c7iqlmk4lgnkccpdvzdv6kbwqz2leyluuehh2ino2m6e5cd7d6"),
|
||||
"storagepower": MustParseCid("bafk2bzacedkwcuzvlx43nbwdwms5smerdaeja45rh7d646k4nc4s5toyryuxi"),
|
||||
"system": MustParseCid("bafk2bzacedexhpixywvxk37jyp3sehcqmomyq4kpxu3wjhrehawyjhv6grav2"),
|
||||
"verifiedregistry": MustParseCid("bafk2bzacebsnm343frbrfted3vbia4to7iiav4qm3tvpkcbsgkd5fynop3q7s"),
|
||||
},
|
||||
}, {
|
||||
Network: "testing",
|
||||
@@ -324,23 +351,24 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
|
||||
}, {
|
||||
Network: "testing",
|
||||
Version: 10,
|
||||
ManifestCid: MustParseCid("bafy2bzacearlgbespxi2zdrybtp2rrbwscmtbyou5qa2egbdvcz6v2yjjqvjo"),
|
||||
ManifestCid: MustParseCid("bafy2bzacececfnvx4hay5b6yhtkxdqgkauupeqpwnlgainug6blp2isihwtww"),
|
||||
Actors: map[string]cid.Cid{
|
||||
"account": MustParseCid("bafk2bzaceba6me5ipkcijuhyypnzjydhv3ebi2ctailar7mtzlk4vk3rbxfee"),
|
||||
"cron": MustParseCid("bafk2bzacea6k2mai2xnakygqvbigivfrvv5q7d34qrzjv2crkqtwbjxnxmkbe"),
|
||||
"datacap": MustParseCid("bafk2bzaceah4oxcgck6bcfkzctm2klpvmltyidq7uxnlkcap6ypi3lnkcvrqk"),
|
||||
"eam": MustParseCid("bafk2bzacedjtkvocrnkrot2oztsfrxtpwl32wwbmbkrjfbbm4xipwzrhhxn5c"),
|
||||
"embryo": MustParseCid("bafk2bzacebj2mj5zlcs3yjlgpbznzistfjkdlwaoncjziliqrxqavvz4dcvnk"),
|
||||
"evm": MustParseCid("bafk2bzaced6vhabkr2ojpjzsybrq5yvksjzpjk6yei6fwobkwwydlj5f473pw"),
|
||||
"init": MustParseCid("bafk2bzaceaib3o5e7wop7kwjirgpferqarmngrgjkur2yhdnwplctidpxsgme"),
|
||||
"multisig": MustParseCid("bafk2bzaced4z3awacxumq6yr33a3adu2legb7colahgvqpmigs3fvvjxs3byc"),
|
||||
"paymentchannel": MustParseCid("bafk2bzaceb6mfi24mpzt7qlkratj2tdtqo7aia67zcztuslrxcjaycz6fnai6"),
|
||||
"reward": MustParseCid("bafk2bzacebngh5kwtem4ncarpjtxhs4rwyoficttkgxlsjtiz5ucdi4p3czoc"),
|
||||
"storagemarket": MustParseCid("bafk2bzacecnsibyil62jfq2gbkoe6c2epehfcrxzjmqjnwz7kxab2hkbu3lks"),
|
||||
"storageminer": MustParseCid("bafk2bzacedzw4vkrt3sdkhagpvn62pknyyjkcrzewncvtvae5qgwe6ulzx4a4"),
|
||||
"storagepower": MustParseCid("bafk2bzacedxgadibot6nzvripqt3z5shvjsoscupinejnsvswq4cbeskblwyy"),
|
||||
"system": MustParseCid("bafk2bzacedm24avrmp5o5odhpad43qeglooflygwh4ah7qnzbij2h4c3v6cge"),
|
||||
"verifiedregistry": MustParseCid("bafk2bzaceapq3j6ww3ofytwq3pz3obumaqsyg3wrm6tksdh7op23a72co3rya"),
|
||||
"account": MustParseCid("bafk2bzaceb56iceglbwg3s2skdjj5vhak7j6srlaxvd7v6hzvxpccwsrvfaxi"),
|
||||
"cron": MustParseCid("bafk2bzacearjb3buxy4jwhcn4jeqbof3dinsh52zyj74djkfghmjdoxbsvjkq"),
|
||||
"datacap": MustParseCid("bafk2bzacec2dghsnwhyhquwkbsfcct53pgglxzgmw7j66y3keniklbiq4q7ti"),
|
||||
"eam": MustParseCid("bafk2bzacedojoymbgz275lzvtlpaf2thoydz7fb274mhvadbpk2thbgpye72s"),
|
||||
"ethaccount": MustParseCid("bafk2bzaceddhvqqkwc4p7exdgv2bwefkk3lnq2rw6chvar7hdeowahtjdmznw"),
|
||||
"evm": MustParseCid("bafk2bzacecgzk3ompisq5n7oualijioce6nhsm6zwil7p5p57nojuyrdckti2"),
|
||||
"init": MustParseCid("bafk2bzaceacdto7l5qp65ukclc3qqlfpv3tdio7u5lxufg2uc3hrx5hpqt2x2"),
|
||||
"multisig": MustParseCid("bafk2bzacebw6ujt54gyhxvo5jmimg3z54crmfzbbcr677ljqmmb2ejh6srlsm"),
|
||||
"paymentchannel": MustParseCid("bafk2bzacebfht4drwm5aagcx4kvuiwclldd6rnosce42474u4asnurjqyxhna"),
|
||||
"placeholder": MustParseCid("bafk2bzacedv773z6clfjh7wxvlqd6ki7bncztt73org7apnnt2acjigrjdg4a"),
|
||||
"reward": MustParseCid("bafk2bzacedqmiebckz7xqs7f7gcj67wzzpko2q3jhom6rwtopogv7iz5bnwlu"),
|
||||
"storagemarket": MustParseCid("bafk2bzaceam3n2xjbvkyyifw7jvkc4z4lxvblnbmx4ruzr5lpesgmpuhbmb2w"),
|
||||
"storageminer": MustParseCid("bafk2bzacebcbyuzniiqksk47v7zyfc56noblbsmlqblv3n6s7l5un3heigdwk"),
|
||||
"storagepower": MustParseCid("bafk2bzacechzbqmunxv6o2zgp4uicswapmgexc3uejco2n2r7cirbijrbgewc"),
|
||||
"system": MustParseCid("bafk2bzaceb6obdybgoyjvdfxvxg5uxhrpnoixtbof663dllo2eelcuvsfycew"),
|
||||
"verifiedregistry": MustParseCid("bafk2bzacedlogwaofqaqou4pckoatwei2ulbz3ucjmbsm3lfwuw3tr7g5opjc"),
|
||||
},
|
||||
}, {
|
||||
Network: "testing-fake-proofs",
|
||||
@@ -380,22 +408,23 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
|
||||
}, {
|
||||
Network: "testing-fake-proofs",
|
||||
Version: 10,
|
||||
ManifestCid: MustParseCid("bafy2bzacea4irr2oxhclwt4mvtrevbzb7mbqddcebjz7bkqjq6eoflpfhencc"),
|
||||
ManifestCid: MustParseCid("bafy2bzacec4yawvg2rbdvzlez4lyf4e7ysjfjdrg5mpclvvwxt7texyeeletg"),
|
||||
Actors: map[string]cid.Cid{
|
||||
"account": MustParseCid("bafk2bzaceba6me5ipkcijuhyypnzjydhv3ebi2ctailar7mtzlk4vk3rbxfee"),
|
||||
"cron": MustParseCid("bafk2bzacea6k2mai2xnakygqvbigivfrvv5q7d34qrzjv2crkqtwbjxnxmkbe"),
|
||||
"datacap": MustParseCid("bafk2bzaceah4oxcgck6bcfkzctm2klpvmltyidq7uxnlkcap6ypi3lnkcvrqk"),
|
||||
"eam": MustParseCid("bafk2bzacedjtkvocrnkrot2oztsfrxtpwl32wwbmbkrjfbbm4xipwzrhhxn5c"),
|
||||
"embryo": MustParseCid("bafk2bzacebj2mj5zlcs3yjlgpbznzistfjkdlwaoncjziliqrxqavvz4dcvnk"),
|
||||
"evm": MustParseCid("bafk2bzaced6vhabkr2ojpjzsybrq5yvksjzpjk6yei6fwobkwwydlj5f473pw"),
|
||||
"init": MustParseCid("bafk2bzaceaib3o5e7wop7kwjirgpferqarmngrgjkur2yhdnwplctidpxsgme"),
|
||||
"multisig": MustParseCid("bafk2bzaced4z3awacxumq6yr33a3adu2legb7colahgvqpmigs3fvvjxs3byc"),
|
||||
"paymentchannel": MustParseCid("bafk2bzaceb6mfi24mpzt7qlkratj2tdtqo7aia67zcztuslrxcjaycz6fnai6"),
|
||||
"reward": MustParseCid("bafk2bzacebngh5kwtem4ncarpjtxhs4rwyoficttkgxlsjtiz5ucdi4p3czoc"),
|
||||
"storagemarket": MustParseCid("bafk2bzacecnsibyil62jfq2gbkoe6c2epehfcrxzjmqjnwz7kxab2hkbu3lks"),
|
||||
"storageminer": MustParseCid("bafk2bzaceb4grddnw54gczgcdak5a2gqvwed66mhibbug6qu4jy35bf45jltg"),
|
||||
"storagepower": MustParseCid("bafk2bzacedp2dnbk4bg3hhaeztre4q3jv7eqs267rlafszpggb2njjn3x5eru"),
|
||||
"system": MustParseCid("bafk2bzacedm24avrmp5o5odhpad43qeglooflygwh4ah7qnzbij2h4c3v6cge"),
|
||||
"verifiedregistry": MustParseCid("bafk2bzaceapq3j6ww3ofytwq3pz3obumaqsyg3wrm6tksdh7op23a72co3rya"),
|
||||
"account": MustParseCid("bafk2bzaceb56iceglbwg3s2skdjj5vhak7j6srlaxvd7v6hzvxpccwsrvfaxi"),
|
||||
"cron": MustParseCid("bafk2bzacearjb3buxy4jwhcn4jeqbof3dinsh52zyj74djkfghmjdoxbsvjkq"),
|
||||
"datacap": MustParseCid("bafk2bzacec2dghsnwhyhquwkbsfcct53pgglxzgmw7j66y3keniklbiq4q7ti"),
|
||||
"eam": MustParseCid("bafk2bzacedojoymbgz275lzvtlpaf2thoydz7fb274mhvadbpk2thbgpye72s"),
|
||||
"ethaccount": MustParseCid("bafk2bzaceddhvqqkwc4p7exdgv2bwefkk3lnq2rw6chvar7hdeowahtjdmznw"),
|
||||
"evm": MustParseCid("bafk2bzacecgzk3ompisq5n7oualijioce6nhsm6zwil7p5p57nojuyrdckti2"),
|
||||
"init": MustParseCid("bafk2bzaceacdto7l5qp65ukclc3qqlfpv3tdio7u5lxufg2uc3hrx5hpqt2x2"),
|
||||
"multisig": MustParseCid("bafk2bzacebw6ujt54gyhxvo5jmimg3z54crmfzbbcr677ljqmmb2ejh6srlsm"),
|
||||
"paymentchannel": MustParseCid("bafk2bzacebfht4drwm5aagcx4kvuiwclldd6rnosce42474u4asnurjqyxhna"),
|
||||
"placeholder": MustParseCid("bafk2bzacedv773z6clfjh7wxvlqd6ki7bncztt73org7apnnt2acjigrjdg4a"),
|
||||
"reward": MustParseCid("bafk2bzacedqmiebckz7xqs7f7gcj67wzzpko2q3jhom6rwtopogv7iz5bnwlu"),
|
||||
"storagemarket": MustParseCid("bafk2bzaceam3n2xjbvkyyifw7jvkc4z4lxvblnbmx4ruzr5lpesgmpuhbmb2w"),
|
||||
"storageminer": MustParseCid("bafk2bzaceataoi4vlifq2roanrfjt2f2cql2dq4osjs5i3nt4v76462mtrcm2"),
|
||||
"storagepower": MustParseCid("bafk2bzacede4nq6cbym2z7p5vc2gwbxhnd34qxtd7sy4rmwula3kk6yhbqtve"),
|
||||
"system": MustParseCid("bafk2bzaceb6obdybgoyjvdfxvxg5uxhrpnoixtbof663dllo2eelcuvsfycew"),
|
||||
"verifiedregistry": MustParseCid("bafk2bzacedlogwaofqaqou4pckoatwei2ulbz3ucjmbsm3lfwuw3tr7g5opjc"),
|
||||
},
|
||||
}}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -21,6 +21,7 @@ const GenesisFile = ""
|
||||
|
||||
var NetworkBundle = "devnet"
|
||||
var BundleOverrides map[actorstypes.Version]string
|
||||
var ActorDebugging = true
|
||||
|
||||
const GenesisNetworkVersion = network.Version18
|
||||
|
||||
@@ -58,6 +59,8 @@ var UpgradeSkyrHeight = abi.ChainEpoch(-19)
|
||||
|
||||
var UpgradeSharkHeight = abi.ChainEpoch(-20)
|
||||
|
||||
var UpgradeHyggeHeight = abi.ChainEpoch(-21)
|
||||
|
||||
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||
0: DrandMainnet,
|
||||
}
|
||||
@@ -110,6 +113,7 @@ func init() {
|
||||
UpgradeOhSnapHeight = getUpgradeHeight("LOTUS_OHSNAP_HEIGHT", UpgradeOhSnapHeight)
|
||||
UpgradeSkyrHeight = getUpgradeHeight("LOTUS_SKYR_HEIGHT", UpgradeSkyrHeight)
|
||||
UpgradeSharkHeight = getUpgradeHeight("LOTUS_SHARK_HEIGHT", UpgradeSharkHeight)
|
||||
UpgradeHyggeHeight = getUpgradeHeight("LOTUS_HYGGE_HEIGHT", UpgradeHyggeHeight)
|
||||
|
||||
BuildType |= Build2k
|
||||
|
||||
@@ -130,4 +134,8 @@ const InteractivePoRepConfidence = 6
|
||||
|
||||
const BootstrapPeerThreshold = 1
|
||||
|
||||
// ChainId defines the chain ID used in the Ethereum JSON-RPC endpoint.
|
||||
// As per https://github.com/ethereum-lists/chains
|
||||
const Eip155ChainId = 31415926
|
||||
|
||||
var WhitelistedBlock = cid.Undef
|
||||
|
||||
@@ -23,6 +23,7 @@ const GenesisNetworkVersion = network.Version16
|
||||
|
||||
var NetworkBundle = "butterflynet"
|
||||
var BundleOverrides map[actorstypes.Version]string
|
||||
var ActorDebugging = false
|
||||
|
||||
const BootstrappersFile = "butterflynet.pi"
|
||||
const GenesisFile = "butterflynet.car"
|
||||
@@ -49,7 +50,8 @@ const UpgradeHyperdriveHeight = -16
|
||||
const UpgradeChocolateHeight = -17
|
||||
const UpgradeOhSnapHeight = -18
|
||||
const UpgradeSkyrHeight = -19
|
||||
const UpgradeSharkHeight = abi.ChainEpoch(600)
|
||||
const UpgradeSharkHeight = abi.ChainEpoch(-20)
|
||||
const UpgradeHyggeHeight = abi.ChainEpoch(600)
|
||||
|
||||
var SupportedProofTypes = []abi.RegisteredSealProof{
|
||||
abi.RegisteredSealProof_StackedDrg512MiBV1,
|
||||
@@ -80,4 +82,8 @@ const PropagationDelaySecs = uint64(6)
|
||||
// BootstrapPeerThreshold is the minimum number peers we need to track for a sync worker to start
|
||||
const BootstrapPeerThreshold = 2
|
||||
|
||||
// ChainId defines the chain ID used in the Ethereum JSON-RPC endpoint.
|
||||
// As per https://github.com/ethereum-lists/chains
|
||||
const Eip155ChainId = 3141592
|
||||
|
||||
var WhitelistedBlock = cid.Undef
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package build
|
||||
|
||||
import (
|
||||
"math"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
@@ -26,6 +27,7 @@ const GenesisNetworkVersion = network.Version0
|
||||
|
||||
var NetworkBundle = "calibrationnet"
|
||||
var BundleOverrides map[actorstypes.Version]string
|
||||
var ActorDebugging = false
|
||||
|
||||
const BootstrappersFile = "calibnet.pi"
|
||||
const GenesisFile = "calibnet.car"
|
||||
@@ -69,6 +71,8 @@ const UpgradeSkyrHeight = 510
|
||||
|
||||
const UpgradeSharkHeight = 16800 // 6 days after genesis
|
||||
|
||||
const UpgradeHyggeHeight = math.MaxInt64
|
||||
|
||||
var SupportedProofTypes = []abi.RegisteredSealProof{
|
||||
abi.RegisteredSealProof_StackedDrg32GiBV1,
|
||||
abi.RegisteredSealProof_StackedDrg64GiBV1,
|
||||
@@ -113,4 +117,8 @@ var PropagationDelaySecs = uint64(10)
|
||||
// BootstrapPeerThreshold is the minimum number peers we need to track for a sync worker to start
|
||||
const BootstrapPeerThreshold = 4
|
||||
|
||||
// ChainId defines the chain ID used in the Ethereum JSON-RPC endpoint.
|
||||
// As per https://github.com/ethereum-lists/chains
|
||||
const Eip155ChainId = 314159
|
||||
|
||||
var WhitelistedBlock = cid.Undef
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
//go:build hyperspace
|
||||
// +build hyperspace
|
||||
|
||||
package build
|
||||
|
||||
import (
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"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/network"
|
||||
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
)
|
||||
|
||||
var NetworkBundle = "hyperspace"
|
||||
var BundleOverrides map[actorstypes.Version]string
|
||||
var ActorDebugging = true
|
||||
|
||||
const BootstrappersFile = "hyperspace.pi"
|
||||
const GenesisFile = "hyperspace.car"
|
||||
|
||||
const GenesisNetworkVersion = network.Version18
|
||||
|
||||
var NetworkBundle = "hyperspacenet"
|
||||
var BundleOverrides map[actorstypes.Version]string
|
||||
var ActorDebugging = false
|
||||
|
||||
var UpgradeBreezeHeight = abi.ChainEpoch(-1)
|
||||
|
||||
const BreezeGasTampingDuration = 120
|
||||
|
||||
var UpgradeSmokeHeight = abi.ChainEpoch(-1)
|
||||
var UpgradeIgnitionHeight = abi.ChainEpoch(-2)
|
||||
var UpgradeRefuelHeight = abi.ChainEpoch(-3)
|
||||
var UpgradeTapeHeight = abi.ChainEpoch(-4)
|
||||
|
||||
var UpgradeAssemblyHeight = abi.ChainEpoch(-5)
|
||||
var UpgradeLiftoffHeight = abi.ChainEpoch(-6)
|
||||
|
||||
var UpgradeKumquatHeight = abi.ChainEpoch(-7)
|
||||
var UpgradeCalicoHeight = abi.ChainEpoch(-9)
|
||||
var UpgradePersianHeight = abi.ChainEpoch(-10)
|
||||
var UpgradeOrangeHeight = abi.ChainEpoch(-11)
|
||||
var UpgradeClausHeight = abi.ChainEpoch(-12)
|
||||
|
||||
var UpgradeTrustHeight = abi.ChainEpoch(-13)
|
||||
|
||||
var UpgradeNorwegianHeight = abi.ChainEpoch(-14)
|
||||
|
||||
var UpgradeTurboHeight = abi.ChainEpoch(-15)
|
||||
|
||||
var UpgradeHyperdriveHeight = abi.ChainEpoch(-16)
|
||||
var UpgradeChocolateHeight = abi.ChainEpoch(-17)
|
||||
var UpgradeOhSnapHeight = abi.ChainEpoch(-18)
|
||||
var UpgradeSkyrHeight = abi.ChainEpoch(-19)
|
||||
var UpgradeSharkHeight = abi.ChainEpoch(-20)
|
||||
var UpgradeHyggeHeight = abi.ChainEpoch(-21)
|
||||
|
||||
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||
0: DrandMainnet,
|
||||
}
|
||||
|
||||
var SupportedProofTypes = []abi.RegisteredSealProof{
|
||||
abi.RegisteredSealProof_StackedDrg512MiBV1,
|
||||
abi.RegisteredSealProof_StackedDrg32GiBV1,
|
||||
abi.RegisteredSealProof_StackedDrg64GiBV1,
|
||||
}
|
||||
var ConsensusMinerMinPower = abi.NewStoragePower(16 << 30)
|
||||
var MinVerifiedDealSize = abi.NewStoragePower(1 << 20)
|
||||
var PreCommitChallengeDelay = abi.ChainEpoch(10)
|
||||
|
||||
func init() {
|
||||
policy.SetSupportedProofTypes(SupportedProofTypes...)
|
||||
policy.SetConsensusMinerMinPower(ConsensusMinerMinPower)
|
||||
policy.SetMinVerifiedDealSize(MinVerifiedDealSize)
|
||||
policy.SetPreCommitChallengeDelay(PreCommitChallengeDelay)
|
||||
|
||||
BuildType = BuildHyperspacenet
|
||||
SetAddressNetwork(address.Testnet)
|
||||
Devnet = true
|
||||
|
||||
}
|
||||
|
||||
const BlockDelaySecs = uint64(builtin2.EpochDurationSeconds)
|
||||
|
||||
const PropagationDelaySecs = uint64(6)
|
||||
|
||||
// BootstrapPeerThreshold is the minimum number peers we need to track for a sync worker to start
|
||||
const BootstrapPeerThreshold = 2
|
||||
|
||||
// ChainId defines the chain ID used in the Ethereum JSON-RPC endpoint.
|
||||
// As per https://github.com/ethereum-lists/chains
|
||||
const Eip155ChainId = 3141
|
||||
|
||||
var WhitelistedBlock = cid.Undef
|
||||
+10
-1
@@ -20,6 +20,7 @@ import (
|
||||
|
||||
var NetworkBundle = "caterpillarnet"
|
||||
var BundleOverrides map[actorstypes.Version]string
|
||||
var ActorDebugging = false
|
||||
|
||||
const BootstrappersFile = "interopnet.pi"
|
||||
const GenesisFile = "interopnet.car"
|
||||
@@ -49,7 +50,9 @@ var UpgradeChocolateHeight = abi.ChainEpoch(-17)
|
||||
var UpgradeOhSnapHeight = abi.ChainEpoch(-18)
|
||||
var UpgradeSkyrHeight = abi.ChainEpoch(-19)
|
||||
|
||||
const UpgradeSharkHeight = abi.ChainEpoch(99999999999999)
|
||||
const UpgradeSharkHeight = abi.ChainEpoch(-20)
|
||||
|
||||
const UpgradeHyggeHeight = abi.ChainEpoch(99999999999999)
|
||||
|
||||
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||
0: DrandMainnet,
|
||||
@@ -104,6 +107,7 @@ func init() {
|
||||
UpgradeOhSnapHeight = getUpgradeHeight("LOTUS_OHSNAP_HEIGHT", UpgradeOhSnapHeight)
|
||||
UpgradeSkyrHeight = getUpgradeHeight("LOTUS_SKYR_HEIGHT", UpgradeSkyrHeight)
|
||||
UpgradeSharkHeight = getUpgradeHeight("LOTUS_SHARK_HEIGHT", UpgradeSharkHeight)
|
||||
UpgradeHyggeHeight = getUpgradeHeight("LOTUS_HYGGE_HEIGHT", UpgradeHyggeHeight)
|
||||
|
||||
BuildType |= BuildInteropnet
|
||||
SetAddressNetwork(address.Testnet)
|
||||
@@ -118,4 +122,9 @@ const PropagationDelaySecs = uint64(6)
|
||||
// BootstrapPeerThreshold is the minimum number peers we need to track for a sync worker to start
|
||||
const BootstrapPeerThreshold = 2
|
||||
|
||||
// ChainId defines the chain ID used in the Ethereum JSON-RPC endpoint.
|
||||
// As per https://github.com/ethereum-lists/chains
|
||||
// TODO same as butterfly for now, as we didn't submit an assignment for interopnet.
|
||||
const Eip155ChainId = 3141592
|
||||
|
||||
var WhitelistedBlock = cid.Undef
|
||||
|
||||
+16
-5
@@ -1,5 +1,5 @@
|
||||
//go:build !debug && !2k && !testground && !calibnet && !butterflynet && !interopnet
|
||||
// +build !debug,!2k,!testground,!calibnet,!butterflynet,!interopnet
|
||||
//go:build !debug && !2k && !testground && !calibnet && !butterflynet && !interopnet && !wallabynet && !hyperspacenet
|
||||
// +build !debug,!2k,!testground,!calibnet,!butterflynet,!interopnet,!wallabynet,!hyperspacenet
|
||||
|
||||
package build
|
||||
|
||||
@@ -25,6 +25,9 @@ var NetworkBundle = "mainnet"
|
||||
// NOTE: DO NOT change this unless you REALLY know what you're doing. This is consensus critical.
|
||||
var BundleOverrides map[actorstypes.Version]string
|
||||
|
||||
// NOTE: DO NOT change this unless you REALLY know what you're doing. This is consensus critical.
|
||||
const ActorDebugging = false
|
||||
|
||||
const GenesisNetworkVersion = network.Version0
|
||||
|
||||
const BootstrappersFile = "mainnet.pi"
|
||||
@@ -56,6 +59,7 @@ const UpgradePersianHeight = UpgradeCalicoHeight + (builtin2.EpochsInHour * 60)
|
||||
const UpgradeOrangeHeight = 336458
|
||||
|
||||
// 2020-12-22T02:00:00Z
|
||||
// var because of wdpost_test.go
|
||||
var UpgradeClausHeight = abi.ChainEpoch(343200)
|
||||
|
||||
// 2021-03-04T00:00:30Z
|
||||
@@ -80,7 +84,10 @@ const UpgradeOhSnapHeight = 1594680
|
||||
const UpgradeSkyrHeight = 1960320
|
||||
|
||||
// 2022-11-30T14:00:00Z
|
||||
var UpgradeSharkHeight = abi.ChainEpoch(2383680)
|
||||
const UpgradeSharkHeight = 2383680
|
||||
|
||||
// ??????????????
|
||||
var UpgradeHyggeHeight = abi.ChainEpoch(math.MaxInt64)
|
||||
|
||||
var SupportedProofTypes = []abi.RegisteredSealProof{
|
||||
abi.RegisteredSealProof_StackedDrg32GiBV1,
|
||||
@@ -95,8 +102,8 @@ func init() {
|
||||
SetAddressNetwork(address.Mainnet)
|
||||
}
|
||||
|
||||
if os.Getenv("LOTUS_DISABLE_SHARK") == "1" {
|
||||
UpgradeSharkHeight = math.MaxInt64
|
||||
if os.Getenv("LOTUS_DISABLE_HYGGE") == "1" {
|
||||
UpgradeHyggeHeight = math.MaxInt64
|
||||
}
|
||||
|
||||
// NOTE: DO NOT change this unless you REALLY know what you're doing. This is not consensus critical, however,
|
||||
@@ -124,5 +131,9 @@ const BlockDelaySecs = uint64(builtin2.EpochDurationSeconds)
|
||||
// BootstrapPeerThreshold is the minimum number peers we need to track for a sync worker to start
|
||||
const BootstrapPeerThreshold = 4
|
||||
|
||||
// ChainId defines the chain ID used in the Ethereum JSON-RPC endpoint.
|
||||
// As per https://github.com/ethereum-lists/chains
|
||||
const Eip155ChainId = 314
|
||||
|
||||
// we skip checks on message validity in this block to sidestep the zero-bls signature
|
||||
var WhitelistedBlock = MustParseCid("bafy2bzaceapyg2uyzk7vueh3xccxkuwbz3nxewjyguoxvhx77malc2lzn2ybi")
|
||||
|
||||
@@ -108,6 +108,7 @@ var (
|
||||
UpgradeOhSnapHeight abi.ChainEpoch = -17
|
||||
UpgradeSkyrHeight abi.ChainEpoch = -18
|
||||
UpgradeSharkHeight abi.ChainEpoch = -19
|
||||
UpgradeHyggeHeight abi.ChainEpoch = -20
|
||||
|
||||
DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||
0: DrandMainnet,
|
||||
@@ -116,6 +117,7 @@ var (
|
||||
GenesisNetworkVersion = network.Version0
|
||||
NetworkBundle = "devnet"
|
||||
BundleOverrides map[actorstypes.Version]string
|
||||
ActorDebugging = true
|
||||
|
||||
NewestNetworkVersion = network.Version16
|
||||
ActorUpgradeNetworkVersion = network.Version16
|
||||
@@ -129,3 +131,7 @@ var (
|
||||
)
|
||||
|
||||
const BootstrapPeerThreshold = 1
|
||||
|
||||
// ChainId defines the chain ID used in the Ethereum JSON-RPC endpoint.
|
||||
// As per https://github.com/ethereum-lists/chains
|
||||
const Eip155ChainId = 31415926
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
//go:build wallabynet
|
||||
// +build wallabynet
|
||||
|
||||
package build
|
||||
|
||||
import (
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"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/network"
|
||||
builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
)
|
||||
|
||||
var NetworkBundle = "wallaby"
|
||||
var BundleOverrides map[actorstypes.Version]string
|
||||
var ActorDebugging = true
|
||||
|
||||
const BootstrappersFile = "wallabynet.pi"
|
||||
const GenesisFile = "wallabynet.car"
|
||||
|
||||
const GenesisNetworkVersion = network.Version18
|
||||
|
||||
var UpgradeBreezeHeight = abi.ChainEpoch(-1)
|
||||
|
||||
const BreezeGasTampingDuration = 120
|
||||
|
||||
var UpgradeSmokeHeight = abi.ChainEpoch(-1)
|
||||
var UpgradeIgnitionHeight = abi.ChainEpoch(-2)
|
||||
var UpgradeRefuelHeight = abi.ChainEpoch(-3)
|
||||
var UpgradeTapeHeight = abi.ChainEpoch(-4)
|
||||
|
||||
var UpgradeAssemblyHeight = abi.ChainEpoch(-5)
|
||||
var UpgradeLiftoffHeight = abi.ChainEpoch(-6)
|
||||
|
||||
var UpgradeKumquatHeight = abi.ChainEpoch(-7)
|
||||
var UpgradeCalicoHeight = abi.ChainEpoch(-9)
|
||||
var UpgradePersianHeight = abi.ChainEpoch(-10)
|
||||
var UpgradeOrangeHeight = abi.ChainEpoch(-11)
|
||||
var UpgradeClausHeight = abi.ChainEpoch(-12)
|
||||
|
||||
var UpgradeTrustHeight = abi.ChainEpoch(-13)
|
||||
|
||||
var UpgradeNorwegianHeight = abi.ChainEpoch(-14)
|
||||
|
||||
var UpgradeTurboHeight = abi.ChainEpoch(-15)
|
||||
|
||||
var UpgradeHyperdriveHeight = abi.ChainEpoch(-16)
|
||||
var UpgradeChocolateHeight = abi.ChainEpoch(-17)
|
||||
var UpgradeOhSnapHeight = abi.ChainEpoch(-18)
|
||||
var UpgradeSkyrHeight = abi.ChainEpoch(-19)
|
||||
var UpgradeSharkHeight = abi.ChainEpoch(-20)
|
||||
var UpgradeHyggeHeight = abi.ChainEpoch(-21)
|
||||
|
||||
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||
0: DrandMainnet,
|
||||
}
|
||||
|
||||
var SupportedProofTypes = []abi.RegisteredSealProof{
|
||||
abi.RegisteredSealProof_StackedDrg512MiBV1,
|
||||
abi.RegisteredSealProof_StackedDrg32GiBV1,
|
||||
abi.RegisteredSealProof_StackedDrg64GiBV1,
|
||||
}
|
||||
var ConsensusMinerMinPower = abi.NewStoragePower(16 << 30)
|
||||
var MinVerifiedDealSize = abi.NewStoragePower(1 << 20)
|
||||
var PreCommitChallengeDelay = abi.ChainEpoch(10)
|
||||
|
||||
func init() {
|
||||
policy.SetSupportedProofTypes(SupportedProofTypes...)
|
||||
policy.SetConsensusMinerMinPower(ConsensusMinerMinPower)
|
||||
policy.SetMinVerifiedDealSize(MinVerifiedDealSize)
|
||||
policy.SetPreCommitChallengeDelay(PreCommitChallengeDelay)
|
||||
|
||||
BuildType = BuildWallabynet
|
||||
SetAddressNetwork(address.Testnet)
|
||||
Devnet = true
|
||||
|
||||
}
|
||||
|
||||
const BlockDelaySecs = uint64(builtin2.EpochDurationSeconds)
|
||||
|
||||
const PropagationDelaySecs = uint64(6)
|
||||
|
||||
// BootstrapPeerThreshold is the minimum number peers we need to track for a sync worker to start
|
||||
const BootstrapPeerThreshold = 2
|
||||
|
||||
// ChainId defines the chain ID used in the Ethereum JSON-RPC endpoint.
|
||||
// As per https://github.com/ethereum-lists/chains
|
||||
const Eip155ChainId = 31415
|
||||
|
||||
var WhitelistedBlock = cid.Undef
|
||||
+13
-7
@@ -6,13 +6,15 @@ var CurrentCommit string
|
||||
var BuildType int
|
||||
|
||||
const (
|
||||
BuildDefault = 0
|
||||
BuildMainnet = 0x1
|
||||
Build2k = 0x2
|
||||
BuildDebug = 0x3
|
||||
BuildCalibnet = 0x4
|
||||
BuildInteropnet = 0x5
|
||||
BuildButterflynet = 0x7
|
||||
BuildDefault = 0
|
||||
BuildMainnet = 0x1
|
||||
Build2k = 0x2
|
||||
BuildDebug = 0x3
|
||||
BuildCalibnet = 0x4
|
||||
BuildInteropnet = 0x5
|
||||
BuildButterflynet = 0x7
|
||||
BuildWallabynet = 0x8
|
||||
BuildHyperspacenet = 0x9
|
||||
)
|
||||
|
||||
func BuildTypeString() string {
|
||||
@@ -31,6 +33,10 @@ func BuildTypeString() string {
|
||||
return "+interopnet"
|
||||
case BuildButterflynet:
|
||||
return "+butterflynet"
|
||||
case BuildWallabynet:
|
||||
return "+wallabynet"
|
||||
case BuildHyperspacenet:
|
||||
return "+hyperspacenet"
|
||||
default:
|
||||
return "+huh?"
|
||||
}
|
||||
|
||||
@@ -274,6 +274,33 @@ func IsPaymentChannelActor(c cid.Cid) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func IsPlaceholderActor(c cid.Cid) bool {
|
||||
name, _, ok := actors.GetActorMetaByCode(c)
|
||||
if ok {
|
||||
return name == manifest.PlaceholderKey
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func IsEvmActor(c cid.Cid) bool {
|
||||
name, _, ok := actors.GetActorMetaByCode(c)
|
||||
if ok {
|
||||
return name == manifest.EvmKey
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func IsEthAccountActor(c cid.Cid) bool {
|
||||
name, _, ok := actors.GetActorMetaByCode(c)
|
||||
if ok {
|
||||
return name == manifest.EthAccountKey
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func makeAddress(addr string) address.Address {
|
||||
ret, err := address.NewFromString(addr)
|
||||
if err != nil {
|
||||
|
||||
@@ -153,6 +153,33 @@ func IsPaymentChannelActor(c cid.Cid) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func IsPlaceholderActor(c cid.Cid) bool {
|
||||
name, _, ok := actors.GetActorMetaByCode(c)
|
||||
if ok {
|
||||
return name == manifest.PlaceholderKey
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func IsEvmActor(c cid.Cid) bool {
|
||||
name, _, ok := actors.GetActorMetaByCode(c)
|
||||
if ok {
|
||||
return name == manifest.EvmKey
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func IsEthAccountActor(c cid.Cid) bool {
|
||||
name, _, ok := actors.GetActorMetaByCode(c)
|
||||
if ok {
|
||||
return name == manifest.EthAccountKey
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func makeAddress(addr string) address.Address {
|
||||
ret, err := address.NewFromString(addr)
|
||||
if err != nil {
|
||||
|
||||
@@ -13,11 +13,15 @@ import (
|
||||
account10 "github.com/filecoin-project/go-state-types/builtin/v10/account"
|
||||
cron10 "github.com/filecoin-project/go-state-types/builtin/v10/cron"
|
||||
datacap10 "github.com/filecoin-project/go-state-types/builtin/v10/datacap"
|
||||
eam10 "github.com/filecoin-project/go-state-types/builtin/v10/eam"
|
||||
ethaccount10 "github.com/filecoin-project/go-state-types/builtin/v10/ethaccount"
|
||||
evm10 "github.com/filecoin-project/go-state-types/builtin/v10/evm"
|
||||
_init10 "github.com/filecoin-project/go-state-types/builtin/v10/init"
|
||||
market10 "github.com/filecoin-project/go-state-types/builtin/v10/market"
|
||||
miner10 "github.com/filecoin-project/go-state-types/builtin/v10/miner"
|
||||
multisig10 "github.com/filecoin-project/go-state-types/builtin/v10/multisig"
|
||||
paych10 "github.com/filecoin-project/go-state-types/builtin/v10/paych"
|
||||
placeholder10 "github.com/filecoin-project/go-state-types/builtin/v10/placeholder"
|
||||
power10 "github.com/filecoin-project/go-state-types/builtin/v10/power"
|
||||
reward10 "github.com/filecoin-project/go-state-types/builtin/v10/reward"
|
||||
system10 "github.com/filecoin-project/go-state-types/builtin/v10/system"
|
||||
@@ -265,6 +269,7 @@ func MakeRegistry(av actorstypes.Version) []RegistryEntry {
|
||||
methods: datacap9.Methods,
|
||||
state: new(datacap9.State),
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,6 +348,32 @@ func MakeRegistry(av actorstypes.Version) []RegistryEntry {
|
||||
methods: datacap10.Methods,
|
||||
state: new(datacap10.State),
|
||||
})
|
||||
|
||||
case manifest.EvmKey:
|
||||
registry = append(registry, RegistryEntry{
|
||||
code: codeID,
|
||||
methods: evm10.Methods,
|
||||
state: new(evm10.State),
|
||||
})
|
||||
case manifest.EamKey:
|
||||
registry = append(registry, RegistryEntry{
|
||||
code: codeID,
|
||||
methods: eam10.Methods,
|
||||
state: nil,
|
||||
})
|
||||
case manifest.PlaceholderKey:
|
||||
registry = append(registry, RegistryEntry{
|
||||
code: codeID,
|
||||
methods: placeholder10.Methods,
|
||||
state: nil,
|
||||
})
|
||||
case manifest.EthAccountKey:
|
||||
registry = append(registry, RegistryEntry{
|
||||
code: codeID,
|
||||
methods: ethaccount10.Methods,
|
||||
state: nil,
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,12 @@ import (
|
||||
{{if (ge . 9)}}
|
||||
datacap{{.}} "github.com/filecoin-project/go-state-types/builtin/v{{.}}/datacap"
|
||||
{{end}}
|
||||
{{if (ge . 10)}}
|
||||
evm{{.}} "github.com/filecoin-project/go-state-types/builtin/v{{.}}/evm"
|
||||
eam{{.}} "github.com/filecoin-project/go-state-types/builtin/v{{.}}/eam"
|
||||
placeholder{{.}} "github.com/filecoin-project/go-state-types/builtin/v{{.}}/placeholder"
|
||||
ethaccount{{.}} "github.com/filecoin-project/go-state-types/builtin/v{{.}}/ethaccount"
|
||||
{{end}}
|
||||
{{end}}
|
||||
"github.com/filecoin-project/go-state-types/cbor"
|
||||
rtt "github.com/filecoin-project/go-state-types/rt"
|
||||
@@ -174,6 +180,32 @@ func MakeRegistry(av actorstypes.Version) []RegistryEntry {
|
||||
methods: datacap{{.}}.Methods,
|
||||
state: new(datacap{{.}}.State),
|
||||
}){{end}}
|
||||
{{if (ge . 10)}}
|
||||
case manifest.EvmKey:
|
||||
registry = append(registry, RegistryEntry{
|
||||
code: codeID,
|
||||
methods: evm{{.}}.Methods,
|
||||
state: new(evm{{.}}.State),
|
||||
})
|
||||
case manifest.EamKey:
|
||||
registry = append(registry, RegistryEntry{
|
||||
code: codeID,
|
||||
methods: eam{{.}}.Methods,
|
||||
state: nil,
|
||||
})
|
||||
case manifest.PlaceholderKey:
|
||||
registry = append(registry, RegistryEntry{
|
||||
code: codeID,
|
||||
methods: placeholder{{.}}.Methods,
|
||||
state: nil,
|
||||
})
|
||||
case manifest.EthAccountKey:
|
||||
registry = append(registry, RegistryEntry{
|
||||
code: codeID,
|
||||
methods: ethaccount{{.}}.Methods,
|
||||
state: nil,
|
||||
})
|
||||
{{end}}
|
||||
}
|
||||
}
|
||||
{{end}}
|
||||
|
||||
@@ -93,6 +93,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context,
|
||||
vmopt := &vm.VMOpts{
|
||||
StateBase: base,
|
||||
Epoch: e,
|
||||
Timestamp: ts.MinTimestamp(),
|
||||
Rand: r,
|
||||
Bstore: sm.ChainStore().StateBlockstore(),
|
||||
Actors: NewActorRegistry(),
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||
"github.com/multiformats/go-varint"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"go.opencensus.io/stats"
|
||||
"go.opencensus.io/trace"
|
||||
@@ -21,6 +22,7 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
builtintypes "github.com/filecoin-project/go-state-types/builtin"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
blockadt "github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||
@@ -433,6 +435,39 @@ func (filec *FilecoinEC) VerifyWinningPoStProof(ctx context.Context, nv network.
|
||||
return nil
|
||||
}
|
||||
|
||||
func IsValidForSending(nv network.Version, act *types.Actor) bool {
|
||||
// Before nv18 (Hygge), we only supported built-in account actors as senders.
|
||||
//
|
||||
// Note: this gate is probably superfluous, since:
|
||||
// 1. Placeholder actors cannot be created before nv18.
|
||||
// 2. EthAccount actors cannot be created before nv18.
|
||||
// 3. Delegated addresses cannot be created before nv18.
|
||||
//
|
||||
// But it's a safeguard.
|
||||
//
|
||||
// Note 2: ad-hoc checks for network versions like this across the codebase
|
||||
// will be problematic with networks with diverging version lineages
|
||||
// (e.g. Hyperspace). We need to revisit this strategy entirely.
|
||||
if nv < network.Version18 {
|
||||
return builtin.IsAccountActor(act.Code)
|
||||
}
|
||||
|
||||
// After nv18, we also support other kinds of senders.
|
||||
if builtin.IsAccountActor(act.Code) || builtin.IsEthAccountActor(act.Code) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Allow placeholder actors with a delegated address and nonce 0 to send a message.
|
||||
// These will be converted to an EthAccount actor on first send.
|
||||
if !builtin.IsPlaceholderActor(act.Code) || act.Nonce != 0 || act.Address == nil || act.Address.Protocol() != address.Delegated {
|
||||
return false
|
||||
}
|
||||
|
||||
// Only allow such actors to send if their delegated address is in the EAM's namespace.
|
||||
id, _, err := varint.FromUvarint(act.Address.Payload())
|
||||
return err == nil && id == builtintypes.EthereumAddressManagerActorID
|
||||
}
|
||||
|
||||
// TODO: We should extract this somewhere else and make the message pool and miner use the same logic
|
||||
func (filec *FilecoinEC) checkBlockMessages(ctx context.Context, b *types.FullBlock, baseTs *types.TipSet) error {
|
||||
{
|
||||
@@ -505,7 +540,7 @@ func (filec *FilecoinEC) checkBlockMessages(ctx context.Context, b *types.FullBl
|
||||
return xerrors.Errorf("failed to get actor: %w", err)
|
||||
}
|
||||
|
||||
if !builtin.IsAccountActor(act.Code) {
|
||||
if !IsValidForSending(nv, act) {
|
||||
return xerrors.New("Sender must be an account actor")
|
||||
}
|
||||
nonces[sender] = act.Nonce
|
||||
@@ -542,25 +577,23 @@ func (filec *FilecoinEC) checkBlockMessages(ctx context.Context, b *types.FullBl
|
||||
|
||||
smArr := blockadt.MakeEmptyArray(tmpstore)
|
||||
for i, m := range b.SecpkMessages {
|
||||
if filec.sm.GetNetworkVersion(ctx, b.Header.Height) >= network.Version14 {
|
||||
if m.Signature.Type != crypto.SigTypeSecp256k1 {
|
||||
return xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err)
|
||||
}
|
||||
if nv >= network.Version14 && !chain.IsValidSecpkSigType(nv, m.Signature.Type) {
|
||||
return xerrors.Errorf("block had invalid signed message at index %d: %w", i, err)
|
||||
}
|
||||
|
||||
if err := checkMsg(m); err != nil {
|
||||
return xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err)
|
||||
}
|
||||
|
||||
// `From` being an account actor is only validated inside the `vm.ResolveToKeyAddr` call
|
||||
// in `StateManager.ResolveToKeyAddress` here (and not in `checkMsg`).
|
||||
kaddr, err := filec.sm.ResolveToKeyAddress(ctx, m.Message.From, baseTs)
|
||||
// `From` being an account actor is only validated inside the `vm.ResolveToDeterministicAddr` call
|
||||
// in `StateManager.ResolveToDeterministicAddress` here (and not in `checkMsg`).
|
||||
kaddr, err := filec.sm.ResolveToDeterministicAddress(ctx, m.Message.From, baseTs)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to resolve key addr: %w", err)
|
||||
}
|
||||
|
||||
if err := sigs.Verify(&m.Signature, kaddr, m.Message.Cid().Bytes()); err != nil {
|
||||
return xerrors.Errorf("secpk message %s has invalid signature: %w", m.Cid(), err)
|
||||
if err := chain.AuthenticateMessage(m, kaddr); err != nil {
|
||||
return xerrors.Errorf("failed to validate signature: %w", err)
|
||||
}
|
||||
|
||||
c, err := store.PutMessage(ctx, tmpbs, m)
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain"
|
||||
"github.com/filecoin-project/lotus/chain/consensus"
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
@@ -54,6 +55,7 @@ func (filec *FilecoinEC) CreateBlock(ctx context.Context, w api.Wallet, bt *api.
|
||||
|
||||
var blsMsgCids, secpkMsgCids []cid.Cid
|
||||
var blsSigs []crypto.Signature
|
||||
nv := filec.sm.GetNetworkVersion(ctx, bt.Epoch)
|
||||
for _, msg := range bt.Messages {
|
||||
if msg.Signature.Type == crypto.SigTypeBLS {
|
||||
blsSigs = append(blsSigs, msg.Signature)
|
||||
@@ -65,7 +67,7 @@ func (filec *FilecoinEC) CreateBlock(ctx context.Context, w api.Wallet, bt *api.
|
||||
}
|
||||
|
||||
blsMsgCids = append(blsMsgCids, c)
|
||||
} else if msg.Signature.Type == crypto.SigTypeSecp256k1 {
|
||||
} else if chain.IsValidSecpkSigType(nv, msg.Signature.Type) {
|
||||
c, err := filec.sm.ChainStore().PutMessage(ctx, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -18,8 +18,10 @@ import (
|
||||
"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"
|
||||
nv18 "github.com/filecoin-project/go-state-types/builtin/v10/migration"
|
||||
nv17 "github.com/filecoin-project/go-state-types/builtin/v9/migration"
|
||||
"github.com/filecoin-project/go-state-types/manifest"
|
||||
"github.com/filecoin-project/go-state-types/migration"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
"github.com/filecoin-project/go-state-types/rt"
|
||||
gstStore "github.com/filecoin-project/go-state-types/store"
|
||||
@@ -232,8 +234,18 @@ func DefaultUpgradeSchedule() stmgr.UpgradeSchedule {
|
||||
StopWithin: 5,
|
||||
}},
|
||||
Expensive: true,
|
||||
}, {
|
||||
Height: build.UpgradeHyggeHeight,
|
||||
Network: network.Version18,
|
||||
Migration: UpgradeActorsV10,
|
||||
PreMigrations: []stmgr.PreMigration{{
|
||||
PreMigration: PreUpgradeActorsV10,
|
||||
StartWithin: 180,
|
||||
DontStartWithin: 60,
|
||||
StopWithin: 5,
|
||||
}},
|
||||
Expensive: true,
|
||||
},
|
||||
// TODO v10 upgrade
|
||||
}
|
||||
|
||||
for _, u := range updates {
|
||||
@@ -1580,11 +1592,110 @@ func upgradeActorsV9Common(
|
||||
|
||||
func UpgradeActorsV10(ctx context.Context, sm *stmgr.StateManager, cache stmgr.MigrationCache, cb stmgr.ExecMonitor,
|
||||
root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet) (cid.Cid, error) {
|
||||
// Use all the CPUs except 3.
|
||||
workerCount := MigrationMaxWorkerCount - 3
|
||||
if workerCount <= 0 {
|
||||
workerCount = 1
|
||||
}
|
||||
|
||||
// TODO migration
|
||||
// - the init actor state to include the (empty) installed actors field
|
||||
// - state tree migration to v5
|
||||
return cid.Undef, fmt.Errorf("IMPLEMENTME: v10 migration")
|
||||
config := migration.Config{
|
||||
MaxWorkers: uint(workerCount),
|
||||
JobQueueSize: 1000,
|
||||
ResultQueueSize: 100,
|
||||
ProgressLogPeriod: 10 * time.Second,
|
||||
}
|
||||
|
||||
newRoot, err := upgradeActorsV10Common(ctx, sm, cache, root, epoch, ts, config)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("migrating actors v10 state: %w", err)
|
||||
}
|
||||
|
||||
return newRoot, nil
|
||||
}
|
||||
|
||||
func PreUpgradeActorsV10(ctx context.Context, sm *stmgr.StateManager, cache stmgr.MigrationCache, root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet) error {
|
||||
// Use half the CPUs for pre-migration, but leave at least 3.
|
||||
workerCount := MigrationMaxWorkerCount
|
||||
if workerCount <= 4 {
|
||||
workerCount = 1
|
||||
} else {
|
||||
workerCount /= 2
|
||||
}
|
||||
|
||||
lbts, lbRoot, err := stmgr.GetLookbackTipSetForRound(ctx, sm, ts, epoch)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("error getting lookback ts for premigration: %w", err)
|
||||
}
|
||||
|
||||
config := migration.Config{
|
||||
MaxWorkers: uint(workerCount),
|
||||
ProgressLogPeriod: time.Minute * 5,
|
||||
}
|
||||
|
||||
_, err = upgradeActorsV10Common(ctx, sm, cache, lbRoot, epoch, lbts, config)
|
||||
return err
|
||||
}
|
||||
|
||||
func upgradeActorsV10Common(
|
||||
ctx context.Context, sm *stmgr.StateManager, cache stmgr.MigrationCache,
|
||||
root cid.Cid, epoch abi.ChainEpoch, ts *types.TipSet,
|
||||
config migration.Config,
|
||||
) (cid.Cid, error) {
|
||||
buf := blockstore.NewTieredBstore(sm.ChainStore().StateBlockstore(), blockstore.NewMemorySync())
|
||||
store := store.ActorStore(ctx, buf)
|
||||
|
||||
// ensure that the manifest is loaded in the blockstore
|
||||
if err := bundle.LoadBundles(ctx, sm.ChainStore().StateBlockstore(), actorstypes.Version10); err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to load manifest bundle: %w", err)
|
||||
}
|
||||
|
||||
// Load the state root.
|
||||
var stateRoot types.StateRoot
|
||||
if err := store.Get(ctx, root, &stateRoot); err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to decode state root: %w", err)
|
||||
}
|
||||
|
||||
if stateRoot.Version != types.StateTreeVersion4 {
|
||||
return cid.Undef, xerrors.Errorf(
|
||||
"expected state root version 4 for actors v9 upgrade, got %d",
|
||||
stateRoot.Version,
|
||||
)
|
||||
}
|
||||
|
||||
manifest, ok := actors.GetManifest(actorstypes.Version10)
|
||||
if !ok {
|
||||
return cid.Undef, xerrors.Errorf("no manifest CID for v9 upgrade")
|
||||
}
|
||||
|
||||
// Perform the migration
|
||||
newHamtRoot, err := nv18.MigrateStateTree(ctx, store, manifest, stateRoot.Actors, epoch, config,
|
||||
migrationLogger{}, cache)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("upgrading to actors v10: %w", err)
|
||||
}
|
||||
|
||||
// Persist the result.
|
||||
newRoot, err := store.Put(ctx, &types.StateRoot{
|
||||
Version: types.StateTreeVersion5,
|
||||
Actors: newHamtRoot,
|
||||
Info: stateRoot.Info,
|
||||
})
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("failed to persist new state root: %w", err)
|
||||
}
|
||||
|
||||
// Persist the new tree.
|
||||
|
||||
{
|
||||
from := buf
|
||||
to := buf.Read()
|
||||
|
||||
if err := vm.Copy(ctx, from, to, newRoot); err != nil {
|
||||
return cid.Undef, xerrors.Errorf("copying migrated tree: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return newRoot, nil
|
||||
}
|
||||
|
||||
// Example upgrade function if upgrade requires only code changes
|
||||
|
||||
@@ -0,0 +1,474 @@
|
||||
package filter
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"math"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
amt4 "github.com/filecoin-project/go-amt-ipld/v4"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
blockadt "github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||
|
||||
cstore "github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
const indexed uint8 = 0x01
|
||||
|
||||
type EventFilter struct {
|
||||
id types.FilterID
|
||||
minHeight abi.ChainEpoch // minimum epoch to apply filter or -1 if no minimum
|
||||
maxHeight abi.ChainEpoch // maximum epoch to apply filter or -1 if no maximum
|
||||
tipsetCid cid.Cid
|
||||
addresses []address.Address // list of f4 actor addresses that are extpected to emit the event
|
||||
keys map[string][][]byte // map of key names to a list of alternate values that may match
|
||||
maxResults int // maximum number of results to collect, 0 is unlimited
|
||||
|
||||
mu sync.Mutex
|
||||
collected []*CollectedEvent
|
||||
lastTaken time.Time
|
||||
ch chan<- interface{}
|
||||
}
|
||||
|
||||
var _ Filter = (*EventFilter)(nil)
|
||||
|
||||
type CollectedEvent struct {
|
||||
Entries []types.EventEntry
|
||||
EmitterAddr address.Address // f4 address of emitter
|
||||
EventIdx int // index of the event within the list of emitted events
|
||||
Reverted bool
|
||||
Height abi.ChainEpoch
|
||||
TipSetKey types.TipSetKey // tipset that contained the message
|
||||
MsgIdx int // index of the message in the tipset
|
||||
MsgCid cid.Cid // cid of message that produced event
|
||||
}
|
||||
|
||||
func (f *EventFilter) ID() types.FilterID {
|
||||
return f.id
|
||||
}
|
||||
|
||||
func (f *EventFilter) SetSubChannel(ch chan<- interface{}) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
f.ch = ch
|
||||
f.collected = nil
|
||||
}
|
||||
|
||||
func (f *EventFilter) ClearSubChannel() {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
f.ch = nil
|
||||
}
|
||||
|
||||
func (f *EventFilter) CollectEvents(ctx context.Context, te *TipSetEvents, revert bool, resolver func(ctx context.Context, emitter abi.ActorID, ts *types.TipSet) (address.Address, bool)) error {
|
||||
if !f.matchTipset(te) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// cache of lookups between actor id and f4 address
|
||||
addressLookups := make(map[abi.ActorID]address.Address)
|
||||
|
||||
ems, err := te.messages(ctx)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("load executed messages: %w", err)
|
||||
}
|
||||
for msgIdx, em := range ems {
|
||||
for evIdx, ev := range em.Events() {
|
||||
// lookup address corresponding to the actor id
|
||||
addr, found := addressLookups[ev.Emitter]
|
||||
if !found {
|
||||
var ok bool
|
||||
addr, ok = resolver(ctx, ev.Emitter, te.rctTs)
|
||||
if !ok {
|
||||
// not an address we will be able to match against
|
||||
continue
|
||||
}
|
||||
addressLookups[ev.Emitter] = addr
|
||||
}
|
||||
|
||||
if !f.matchAddress(addr) {
|
||||
continue
|
||||
}
|
||||
if !f.matchKeys(ev.Entries) {
|
||||
continue
|
||||
}
|
||||
|
||||
// event matches filter, so record it
|
||||
cev := &CollectedEvent{
|
||||
Entries: ev.Entries,
|
||||
EmitterAddr: addr,
|
||||
EventIdx: evIdx,
|
||||
Reverted: revert,
|
||||
Height: te.msgTs.Height(),
|
||||
TipSetKey: te.msgTs.Key(),
|
||||
MsgCid: em.Message().Cid(),
|
||||
MsgIdx: msgIdx,
|
||||
}
|
||||
|
||||
f.mu.Lock()
|
||||
// if we have a subscription channel then push event to it
|
||||
if f.ch != nil {
|
||||
f.ch <- cev
|
||||
f.mu.Unlock()
|
||||
continue
|
||||
}
|
||||
|
||||
if f.maxResults > 0 && len(f.collected) == f.maxResults {
|
||||
copy(f.collected, f.collected[1:])
|
||||
f.collected = f.collected[:len(f.collected)-1]
|
||||
}
|
||||
f.collected = append(f.collected, cev)
|
||||
f.mu.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *EventFilter) setCollectedEvents(ces []*CollectedEvent) {
|
||||
f.mu.Lock()
|
||||
f.collected = ces
|
||||
f.mu.Unlock()
|
||||
}
|
||||
|
||||
func (f *EventFilter) TakeCollectedEvents(ctx context.Context) []*CollectedEvent {
|
||||
f.mu.Lock()
|
||||
collected := f.collected
|
||||
f.collected = nil
|
||||
f.lastTaken = time.Now().UTC()
|
||||
f.mu.Unlock()
|
||||
|
||||
return collected
|
||||
}
|
||||
|
||||
func (f *EventFilter) LastTaken() time.Time {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
return f.lastTaken
|
||||
}
|
||||
|
||||
// matchTipset reports whether this filter matches the given tipset
|
||||
func (f *EventFilter) matchTipset(te *TipSetEvents) bool {
|
||||
if f.tipsetCid != cid.Undef {
|
||||
tsCid, err := te.Cid()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return f.tipsetCid.Equals(tsCid)
|
||||
}
|
||||
|
||||
if f.minHeight >= 0 && f.minHeight > te.Height() {
|
||||
return false
|
||||
}
|
||||
if f.maxHeight >= 0 && f.maxHeight < te.Height() {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (f *EventFilter) matchAddress(o address.Address) bool {
|
||||
if len(f.addresses) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
// Assume short lists of addresses
|
||||
// TODO: binary search for longer lists or restrict list length
|
||||
for _, a := range f.addresses {
|
||||
if a == o {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (f *EventFilter) matchKeys(ees []types.EventEntry) bool {
|
||||
if len(f.keys) == 0 {
|
||||
return true
|
||||
}
|
||||
// TODO: optimize this naive algorithm
|
||||
// tracked in https://github.com/filecoin-project/lotus/issues/9987
|
||||
|
||||
// Note keys names may be repeated so we may have multiple opportunities to match
|
||||
|
||||
matched := map[string]bool{}
|
||||
for _, ee := range ees {
|
||||
// Skip an entry that is not indexable
|
||||
if ee.Flags&indexed != indexed {
|
||||
continue
|
||||
}
|
||||
|
||||
keyname := ee.Key
|
||||
|
||||
// skip if we have already matched this key
|
||||
if matched[keyname] {
|
||||
continue
|
||||
}
|
||||
|
||||
wantlist, ok := f.keys[keyname]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, w := range wantlist {
|
||||
if bytes.Equal(w, ee.Value) {
|
||||
matched[keyname] = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(matched) == len(f.keys) {
|
||||
// all keys have been matched
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
type TipSetEvents struct {
|
||||
rctTs *types.TipSet // rctTs is the tipset containing the receipts of executed messages
|
||||
msgTs *types.TipSet // msgTs is the tipset containing the messages that have been executed
|
||||
|
||||
load func(ctx context.Context, msgTs, rctTs *types.TipSet) ([]executedMessage, error)
|
||||
|
||||
once sync.Once // for lazy population of ems
|
||||
ems []executedMessage
|
||||
err error
|
||||
}
|
||||
|
||||
func (te *TipSetEvents) Height() abi.ChainEpoch {
|
||||
return te.msgTs.Height()
|
||||
}
|
||||
|
||||
func (te *TipSetEvents) Cid() (cid.Cid, error) {
|
||||
return te.msgTs.Key().Cid()
|
||||
}
|
||||
|
||||
func (te *TipSetEvents) messages(ctx context.Context) ([]executedMessage, error) {
|
||||
te.once.Do(func() {
|
||||
// populate executed message list
|
||||
ems, err := te.load(ctx, te.msgTs, te.rctTs)
|
||||
if err != nil {
|
||||
te.err = err
|
||||
return
|
||||
}
|
||||
te.ems = ems
|
||||
})
|
||||
return te.ems, te.err
|
||||
}
|
||||
|
||||
type executedMessage struct {
|
||||
msg *types.Message
|
||||
rct *types.MessageReceipt
|
||||
// events extracted from receipt
|
||||
evs []*types.Event
|
||||
}
|
||||
|
||||
func (e *executedMessage) Message() *types.Message {
|
||||
return e.msg
|
||||
}
|
||||
|
||||
func (e *executedMessage) Receipt() *types.MessageReceipt {
|
||||
return e.rct
|
||||
}
|
||||
|
||||
func (e *executedMessage) Events() []*types.Event {
|
||||
return e.evs
|
||||
}
|
||||
|
||||
type EventFilterManager struct {
|
||||
ChainStore *cstore.ChainStore
|
||||
AddressResolver func(ctx context.Context, emitter abi.ActorID, ts *types.TipSet) (address.Address, bool)
|
||||
MaxFilterResults int
|
||||
EventIndex *EventIndex
|
||||
|
||||
mu sync.Mutex // guards mutations to filters
|
||||
filters map[types.FilterID]*EventFilter
|
||||
currentHeight abi.ChainEpoch
|
||||
}
|
||||
|
||||
func (m *EventFilterManager) Apply(ctx context.Context, from, to *types.TipSet) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.currentHeight = to.Height()
|
||||
|
||||
if len(m.filters) == 0 && m.EventIndex == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
tse := &TipSetEvents{
|
||||
msgTs: from,
|
||||
rctTs: to,
|
||||
load: m.loadExecutedMessages,
|
||||
}
|
||||
|
||||
if m.EventIndex != nil {
|
||||
if err := m.EventIndex.CollectEvents(ctx, tse, false, m.AddressResolver); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: could run this loop in parallel with errgroup if there are many filters
|
||||
for _, f := range m.filters {
|
||||
if err := f.CollectEvents(ctx, tse, false, m.AddressResolver); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *EventFilterManager) Revert(ctx context.Context, from, to *types.TipSet) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.currentHeight = to.Height()
|
||||
|
||||
if len(m.filters) == 0 && m.EventIndex == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
tse := &TipSetEvents{
|
||||
msgTs: to,
|
||||
rctTs: from,
|
||||
load: m.loadExecutedMessages,
|
||||
}
|
||||
|
||||
if m.EventIndex != nil {
|
||||
if err := m.EventIndex.CollectEvents(ctx, tse, true, m.AddressResolver); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: could run this loop in parallel with errgroup if there are many filters
|
||||
for _, f := range m.filters {
|
||||
if err := f.CollectEvents(ctx, tse, true, m.AddressResolver); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *EventFilterManager) Install(ctx context.Context, minHeight, maxHeight abi.ChainEpoch, tipsetCid cid.Cid, addresses []address.Address, keys map[string][][]byte) (*EventFilter, error) {
|
||||
m.mu.Lock()
|
||||
currentHeight := m.currentHeight
|
||||
m.mu.Unlock()
|
||||
|
||||
if m.EventIndex == nil && minHeight != -1 && minHeight < currentHeight {
|
||||
return nil, xerrors.Errorf("historic event index disabled")
|
||||
}
|
||||
|
||||
id, err := newFilterID()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("new filter id: %w", err)
|
||||
}
|
||||
|
||||
f := &EventFilter{
|
||||
id: id,
|
||||
minHeight: minHeight,
|
||||
maxHeight: maxHeight,
|
||||
tipsetCid: tipsetCid,
|
||||
addresses: addresses,
|
||||
keys: keys,
|
||||
maxResults: m.MaxFilterResults,
|
||||
}
|
||||
|
||||
if m.EventIndex != nil && minHeight != -1 && minHeight < currentHeight {
|
||||
// Filter needs historic events
|
||||
if err := m.EventIndex.PrefillFilter(ctx, f); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
m.mu.Lock()
|
||||
if m.filters == nil {
|
||||
m.filters = make(map[types.FilterID]*EventFilter)
|
||||
}
|
||||
m.filters[id] = f
|
||||
m.mu.Unlock()
|
||||
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (m *EventFilterManager) Remove(ctx context.Context, id types.FilterID) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if _, found := m.filters[id]; !found {
|
||||
return ErrFilterNotFound
|
||||
}
|
||||
delete(m.filters, id)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *EventFilterManager) loadExecutedMessages(ctx context.Context, msgTs, rctTs *types.TipSet) ([]executedMessage, error) {
|
||||
msgs, err := m.ChainStore.MessagesForTipset(ctx, msgTs)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("read messages: %w", err)
|
||||
}
|
||||
|
||||
st := m.ChainStore.ActorStore(ctx)
|
||||
|
||||
arr, err := blockadt.AsArray(st, rctTs.Blocks()[0].ParentMessageReceipts)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("load receipts amt: %w", err)
|
||||
}
|
||||
|
||||
if uint64(len(msgs)) != arr.Length() {
|
||||
return nil, xerrors.Errorf("mismatching message and receipt counts (%d msgs, %d rcts)", len(msgs), arr.Length())
|
||||
}
|
||||
|
||||
ems := make([]executedMessage, len(msgs))
|
||||
|
||||
for i := 0; i < len(msgs); i++ {
|
||||
ems[i].msg = msgs[i].VMMessage()
|
||||
|
||||
var rct types.MessageReceipt
|
||||
found, err := arr.Get(uint64(i), &rct)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("load receipt: %w", err)
|
||||
}
|
||||
if !found {
|
||||
return nil, xerrors.Errorf("receipt %d not found", i)
|
||||
}
|
||||
ems[i].rct = &rct
|
||||
|
||||
if rct.EventsRoot == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
evtArr, err := amt4.LoadAMT(ctx, st, *rct.EventsRoot, amt4.UseTreeBitWidth(types.EventAMTBitwidth))
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("load events amt: %w", err)
|
||||
}
|
||||
|
||||
ems[i].evs = make([]*types.Event, evtArr.Len())
|
||||
var evt types.Event
|
||||
err = evtArr.ForEach(ctx, func(u uint64, deferred *cbg.Deferred) error {
|
||||
if u > math.MaxInt {
|
||||
return xerrors.Errorf("too many events")
|
||||
}
|
||||
if err := evt.UnmarshalCBOR(bytes.NewReader(deferred.Raw)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cpy := evt
|
||||
ems[i].evs[int(u)] = &cpy //nolint:scopelint
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("read events: %w", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ems, nil
|
||||
}
|
||||
@@ -0,0 +1,431 @@
|
||||
package filter
|
||||
|
||||
import (
|
||||
"context"
|
||||
pseudo "math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
mh "github.com/multiformats/go-multihash"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
builtintypes "github.com/filecoin-project/go-state-types/builtin"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/filecoin-project/go-state-types/exitcode"
|
||||
blockadt "github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||
|
||||
"github.com/filecoin-project/lotus/blockstore"
|
||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
func TestEventFilterCollectEvents(t *testing.T) {
|
||||
rng := pseudo.New(pseudo.NewSource(299792458))
|
||||
a1 := randomF4Addr(t, rng)
|
||||
a2 := randomF4Addr(t, rng)
|
||||
|
||||
a1ID := abi.ActorID(1)
|
||||
a2ID := abi.ActorID(2)
|
||||
|
||||
addrMap := addressMap{}
|
||||
addrMap.add(a1ID, a1)
|
||||
addrMap.add(a2ID, a2)
|
||||
|
||||
ev1 := fakeEvent(
|
||||
a1ID,
|
||||
[]kv{
|
||||
{k: "type", v: []byte("approval")},
|
||||
{k: "signer", v: []byte("addr1")},
|
||||
},
|
||||
[]kv{
|
||||
{k: "amount", v: []byte("2988181")},
|
||||
},
|
||||
)
|
||||
|
||||
st := newStore()
|
||||
events := []*types.Event{ev1}
|
||||
em := executedMessage{
|
||||
msg: fakeMessage(randomF4Addr(t, rng), randomF4Addr(t, rng)),
|
||||
rct: fakeReceipt(t, rng, st, events),
|
||||
evs: events,
|
||||
}
|
||||
|
||||
events14000 := buildTipSetEvents(t, rng, 14000, em)
|
||||
cid14000, err := events14000.msgTs.Key().Cid()
|
||||
require.NoError(t, err, "tipset cid")
|
||||
|
||||
noCollectedEvents := []*CollectedEvent{}
|
||||
oneCollectedEvent := []*CollectedEvent{
|
||||
{
|
||||
Entries: ev1.Entries,
|
||||
EmitterAddr: a1,
|
||||
EventIdx: 0,
|
||||
Reverted: false,
|
||||
Height: 14000,
|
||||
TipSetKey: events14000.msgTs.Key(),
|
||||
MsgIdx: 0,
|
||||
MsgCid: em.msg.Cid(),
|
||||
},
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
filter *EventFilter
|
||||
te *TipSetEvents
|
||||
want []*CollectedEvent
|
||||
}{
|
||||
{
|
||||
name: "nomatch tipset min height",
|
||||
filter: &EventFilter{
|
||||
minHeight: 14001,
|
||||
maxHeight: -1,
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "nomatch tipset max height",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: 13999,
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "match tipset min height",
|
||||
filter: &EventFilter{
|
||||
minHeight: 14000,
|
||||
maxHeight: -1,
|
||||
},
|
||||
te: events14000,
|
||||
want: oneCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "match tipset cid",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
tipsetCid: cid14000,
|
||||
},
|
||||
te: events14000,
|
||||
want: oneCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "nomatch address",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
addresses: []address.Address{a2},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "match address",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
addresses: []address.Address{a1},
|
||||
},
|
||||
te: events14000,
|
||||
want: oneCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "match one entry",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("approval"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: oneCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "match one entry with alternate values",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("cancel"),
|
||||
[]byte("propose"),
|
||||
[]byte("approval"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: oneCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "nomatch one entry by missing value",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("cancel"),
|
||||
[]byte("propose"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "nomatch one entry by missing key",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"method": {
|
||||
[]byte("approval"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "match one entry with multiple keys",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("approval"),
|
||||
},
|
||||
"signer": {
|
||||
[]byte("addr1"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: oneCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "nomatch one entry with one mismatching key",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("approval"),
|
||||
},
|
||||
"approver": {
|
||||
[]byte("addr1"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "nomatch one entry with one mismatching value",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("approval"),
|
||||
},
|
||||
"signer": {
|
||||
[]byte("addr2"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "nomatch one entry with one unindexed key",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"amount": {
|
||||
[]byte("2988181"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc // appease lint
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if err := tc.filter.CollectEvents(context.Background(), tc.te, false, addrMap.ResolveAddress); err != nil {
|
||||
require.NoError(t, err, "collect events")
|
||||
}
|
||||
|
||||
coll := tc.filter.TakeCollectedEvents(context.Background())
|
||||
require.ElementsMatch(t, coll, tc.want)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type kv struct {
|
||||
k string
|
||||
v []byte
|
||||
}
|
||||
|
||||
func fakeEvent(emitter abi.ActorID, indexed []kv, unindexed []kv) *types.Event {
|
||||
ev := &types.Event{
|
||||
Emitter: emitter,
|
||||
}
|
||||
|
||||
for _, in := range indexed {
|
||||
ev.Entries = append(ev.Entries, types.EventEntry{
|
||||
Flags: 0x01,
|
||||
Key: in.k,
|
||||
Value: in.v,
|
||||
})
|
||||
}
|
||||
|
||||
for _, in := range unindexed {
|
||||
ev.Entries = append(ev.Entries, types.EventEntry{
|
||||
Flags: 0x00,
|
||||
Key: in.k,
|
||||
Value: in.v,
|
||||
})
|
||||
}
|
||||
|
||||
return ev
|
||||
}
|
||||
|
||||
func randomF4Addr(tb testing.TB, rng *pseudo.Rand) address.Address {
|
||||
tb.Helper()
|
||||
addr, err := address.NewDelegatedAddress(builtintypes.EthereumAddressManagerActorID, randomBytes(32, rng))
|
||||
require.NoError(tb, err)
|
||||
|
||||
return addr
|
||||
}
|
||||
|
||||
func randomIDAddr(tb testing.TB, rng *pseudo.Rand) address.Address {
|
||||
tb.Helper()
|
||||
addr, err := address.NewIDAddress(uint64(rng.Int63()))
|
||||
require.NoError(tb, err)
|
||||
return addr
|
||||
}
|
||||
|
||||
func randomCid(tb testing.TB, rng *pseudo.Rand) cid.Cid {
|
||||
tb.Helper()
|
||||
cb := cid.V1Builder{Codec: cid.Raw, MhType: mh.IDENTITY}
|
||||
c, err := cb.Sum(randomBytes(10, rng))
|
||||
require.NoError(tb, err)
|
||||
return c
|
||||
}
|
||||
|
||||
func randomBytes(n int, rng *pseudo.Rand) []byte {
|
||||
buf := make([]byte, n)
|
||||
rng.Read(buf)
|
||||
return buf
|
||||
}
|
||||
|
||||
func fakeMessage(to, from address.Address) *types.Message {
|
||||
return &types.Message{
|
||||
To: to,
|
||||
From: from,
|
||||
Nonce: 197,
|
||||
Method: 1,
|
||||
Params: []byte("some random bytes"),
|
||||
GasLimit: 126723,
|
||||
GasPremium: types.NewInt(4),
|
||||
GasFeeCap: types.NewInt(120),
|
||||
}
|
||||
}
|
||||
|
||||
func fakeReceipt(tb testing.TB, rng *pseudo.Rand, st adt.Store, events []*types.Event) *types.MessageReceipt {
|
||||
arr := blockadt.MakeEmptyArray(st)
|
||||
for _, ev := range events {
|
||||
err := arr.AppendContinuous(ev)
|
||||
require.NoError(tb, err, "append event")
|
||||
}
|
||||
eventsRoot, err := arr.Root()
|
||||
require.NoError(tb, err, "flush events amt")
|
||||
|
||||
rec := types.NewMessageReceiptV1(exitcode.Ok, randomBytes(32, rng), rng.Int63(), &eventsRoot)
|
||||
return &rec
|
||||
}
|
||||
|
||||
func fakeTipSet(tb testing.TB, rng *pseudo.Rand, h abi.ChainEpoch, parents []cid.Cid) *types.TipSet {
|
||||
tb.Helper()
|
||||
ts, err := types.NewTipSet([]*types.BlockHeader{
|
||||
{
|
||||
Height: h,
|
||||
Miner: randomIDAddr(tb, rng),
|
||||
|
||||
Parents: parents,
|
||||
|
||||
Ticket: &types.Ticket{VRFProof: []byte{byte(h % 2)}},
|
||||
|
||||
ParentStateRoot: randomCid(tb, rng),
|
||||
Messages: randomCid(tb, rng),
|
||||
ParentMessageReceipts: randomCid(tb, rng),
|
||||
|
||||
BlockSig: &crypto.Signature{Type: crypto.SigTypeBLS},
|
||||
BLSAggregate: &crypto.Signature{Type: crypto.SigTypeBLS},
|
||||
},
|
||||
{
|
||||
Height: h,
|
||||
Miner: randomIDAddr(tb, rng),
|
||||
|
||||
Parents: parents,
|
||||
|
||||
Ticket: &types.Ticket{VRFProof: []byte{byte((h + 1) % 2)}},
|
||||
|
||||
ParentStateRoot: randomCid(tb, rng),
|
||||
Messages: randomCid(tb, rng),
|
||||
ParentMessageReceipts: randomCid(tb, rng),
|
||||
|
||||
BlockSig: &crypto.Signature{Type: crypto.SigTypeBLS},
|
||||
BLSAggregate: &crypto.Signature{Type: crypto.SigTypeBLS},
|
||||
},
|
||||
})
|
||||
|
||||
require.NoError(tb, err)
|
||||
|
||||
return ts
|
||||
}
|
||||
|
||||
func newStore() adt.Store {
|
||||
ctx := context.Background()
|
||||
bs := blockstore.NewMemorySync()
|
||||
store := cbor.NewCborStore(bs)
|
||||
return adt.WrapStore(ctx, store)
|
||||
}
|
||||
|
||||
func buildTipSetEvents(tb testing.TB, rng *pseudo.Rand, h abi.ChainEpoch, em executedMessage) *TipSetEvents {
|
||||
tb.Helper()
|
||||
|
||||
msgTs := fakeTipSet(tb, rng, h, []cid.Cid{})
|
||||
rctTs := fakeTipSet(tb, rng, h+1, msgTs.Cids())
|
||||
|
||||
return &TipSetEvents{
|
||||
msgTs: msgTs,
|
||||
rctTs: rctTs,
|
||||
load: func(ctx context.Context, msgTs, rctTs *types.TipSet) ([]executedMessage, error) {
|
||||
return []executedMessage{em}, nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type addressMap map[abi.ActorID]address.Address
|
||||
|
||||
func (a addressMap) add(actorID abi.ActorID, addr address.Address) {
|
||||
a[actorID] = addr
|
||||
}
|
||||
|
||||
func (a addressMap) ResolveAddress(ctx context.Context, emitter abi.ActorID, ts *types.TipSet) (address.Address, bool) {
|
||||
ra, ok := a[emitter]
|
||||
return ra, ok
|
||||
}
|
||||
@@ -0,0 +1,434 @@
|
||||
package filter
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"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"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
var pragmas = []string{
|
||||
"PRAGMA synchronous = normal",
|
||||
"PRAGMA temp_store = memory",
|
||||
"PRAGMA mmap_size = 30000000000",
|
||||
"PRAGMA page_size = 32768",
|
||||
"PRAGMA auto_vacuum = NONE",
|
||||
"PRAGMA automatic_index = OFF",
|
||||
"PRAGMA journal_mode = WAL",
|
||||
"PRAGMA read_uncommitted = ON",
|
||||
}
|
||||
|
||||
var ddls = []string{
|
||||
`CREATE TABLE IF NOT EXISTS event (
|
||||
id INTEGER PRIMARY KEY,
|
||||
height INTEGER NOT NULL,
|
||||
tipset_key BLOB NOT NULL,
|
||||
tipset_key_cid BLOB NOT NULL,
|
||||
emitter_addr BLOB NOT NULL,
|
||||
event_index INTEGER NOT NULL,
|
||||
message_cid BLOB NOT NULL,
|
||||
message_index INTEGER NOT NULL,
|
||||
reverted INTEGER NOT NULL
|
||||
)`,
|
||||
|
||||
`CREATE TABLE IF NOT EXISTS event_entry (
|
||||
event_id INTEGER,
|
||||
indexed INTEGER NOT NULL,
|
||||
flags BLOB NOT NULL,
|
||||
key TEXT NOT NULL,
|
||||
value BLOB NOT NULL
|
||||
)`,
|
||||
|
||||
// metadata containing version of schema
|
||||
`CREATE TABLE IF NOT EXISTS _meta (
|
||||
version UINT64 NOT NULL UNIQUE
|
||||
)`,
|
||||
|
||||
// version 1.
|
||||
`INSERT OR IGNORE INTO _meta (version) VALUES (1)`,
|
||||
}
|
||||
|
||||
const schemaVersion = 1
|
||||
|
||||
const (
|
||||
insertEvent = `INSERT OR IGNORE INTO event
|
||||
(height, tipset_key, tipset_key_cid, emitter_addr, event_index, message_cid, message_index, reverted)
|
||||
VALUES(?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
|
||||
insertEntry = `INSERT OR IGNORE INTO event_entry
|
||||
(event_id, indexed, flags, key, value)
|
||||
VALUES(?, ?, ?, ?, ?)`
|
||||
)
|
||||
|
||||
type EventIndex struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func NewEventIndex(path string) (*EventIndex, error) {
|
||||
db, err := sql.Open("sqlite3", path+"?mode=rwc")
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("open sqlite3 database: %w", err)
|
||||
}
|
||||
|
||||
for _, pragma := range pragmas {
|
||||
if _, err := db.Exec(pragma); err != nil {
|
||||
_ = db.Close()
|
||||
return nil, xerrors.Errorf("exec pragma %q: %w", pragma, err)
|
||||
}
|
||||
}
|
||||
|
||||
q, err := db.Query("SELECT name FROM sqlite_master WHERE type='table' AND name='_meta';")
|
||||
if err == sql.ErrNoRows || !q.Next() {
|
||||
// empty database, create the schema
|
||||
for _, ddl := range ddls {
|
||||
if _, err := db.Exec(ddl); err != nil {
|
||||
_ = db.Close()
|
||||
return nil, xerrors.Errorf("exec ddl %q: %w", ddl, err)
|
||||
}
|
||||
}
|
||||
} else if err != nil {
|
||||
_ = db.Close()
|
||||
return nil, xerrors.Errorf("looking for _meta table: %w", err)
|
||||
} else {
|
||||
// Ensure we don't open a database from a different schema version
|
||||
|
||||
row := db.QueryRow("SELECT max(version) FROM _meta")
|
||||
var version int
|
||||
err := row.Scan(&version)
|
||||
if err != nil {
|
||||
_ = db.Close()
|
||||
return nil, xerrors.Errorf("invalid database version: no version found")
|
||||
}
|
||||
if version != schemaVersion {
|
||||
_ = db.Close()
|
||||
return nil, xerrors.Errorf("invalid database version: got %d, expected %d", version, schemaVersion)
|
||||
}
|
||||
}
|
||||
|
||||
return &EventIndex{
|
||||
db: db,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (ei *EventIndex) Close() error {
|
||||
if ei.db == nil {
|
||||
return nil
|
||||
}
|
||||
return ei.db.Close()
|
||||
}
|
||||
|
||||
func (ei *EventIndex) CollectEvents(ctx context.Context, te *TipSetEvents, revert bool, resolver func(ctx context.Context, emitter abi.ActorID, ts *types.TipSet) (address.Address, bool)) error {
|
||||
// cache of lookups between actor id and f4 address
|
||||
|
||||
addressLookups := make(map[abi.ActorID]address.Address)
|
||||
|
||||
ems, err := te.messages(ctx)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("load executed messages: %w", err)
|
||||
}
|
||||
|
||||
tx, err := ei.db.Begin()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("begin transaction: %w", err)
|
||||
}
|
||||
stmtEvent, err := tx.Prepare(insertEvent)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("prepare insert event: %w", err)
|
||||
}
|
||||
stmtEntry, err := tx.Prepare(insertEntry)
|
||||
if err != nil {
|
||||
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]
|
||||
if !found {
|
||||
var ok bool
|
||||
addr, ok = resolver(ctx, ev.Emitter, te.rctTs)
|
||||
if !ok {
|
||||
// not an address we will be able to match against
|
||||
continue
|
||||
}
|
||||
addressLookups[ev.Emitter] = addr
|
||||
}
|
||||
|
||||
tsKeyCid, err := te.msgTs.Key().Cid()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("tipset key cid: %w", err)
|
||||
}
|
||||
|
||||
res, err := stmtEvent.Exec(
|
||||
te.msgTs.Height(), // height
|
||||
te.msgTs.Key().Bytes(), // tipset_key
|
||||
tsKeyCid.Bytes(), // tipset_key_cid
|
||||
addr.Bytes(), // emitter_addr
|
||||
evIdx, // event_index
|
||||
em.Message().Cid().Bytes(), // message_cid
|
||||
msgIdx, // message_index
|
||||
revert, // reverted
|
||||
)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("exec insert event: %w", err)
|
||||
}
|
||||
|
||||
lastID, err := res.LastInsertId()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("get last row id: %w", err)
|
||||
}
|
||||
|
||||
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
|
||||
)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("exec insert entry: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
return xerrors.Errorf("commit transaction: %w", err)
|
||||
}
|
||||
|
||||
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 orig == nil {
|
||||
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{}
|
||||
values := []any{}
|
||||
joins := []string{}
|
||||
|
||||
if f.tipsetCid != cid.Undef {
|
||||
clauses = append(clauses, "event.tipset_key_cid=?")
|
||||
values = append(values, f.tipsetCid.Bytes())
|
||||
} else {
|
||||
if f.minHeight >= 0 {
|
||||
clauses = append(clauses, "event.height>=?")
|
||||
values = append(values, f.minHeight)
|
||||
}
|
||||
if f.maxHeight >= 0 {
|
||||
clauses = append(clauses, "event.height<=?")
|
||||
values = append(values, f.maxHeight)
|
||||
}
|
||||
}
|
||||
|
||||
if len(f.addresses) > 0 {
|
||||
subclauses := []string{}
|
||||
for _, addr := range f.addresses {
|
||||
subclauses = append(subclauses, "emitter_addr=?")
|
||||
values = append(values, addr.Bytes())
|
||||
}
|
||||
clauses = append(clauses, "("+strings.Join(subclauses, " OR ")+")")
|
||||
}
|
||||
|
||||
if len(f.keys) > 0 {
|
||||
join := 0
|
||||
for key, vals := range f.keys {
|
||||
if len(vals) > 0 {
|
||||
join++
|
||||
joinAlias := fmt.Sprintf("ee%d", join)
|
||||
joins = append(joins, fmt.Sprintf("event_entry %s on event.id=%[1]s.event_id", joinAlias))
|
||||
clauses = append(clauses, fmt.Sprintf("%s.indexed=1 AND %[1]s.key=?", joinAlias))
|
||||
values = append(values, key)
|
||||
subclauses := []string{}
|
||||
for _, val := range vals {
|
||||
subclauses = append(subclauses, fmt.Sprintf("%s.value=?", joinAlias))
|
||||
values = append(values, trimLeadingZeros(val))
|
||||
}
|
||||
clauses = append(clauses, "("+strings.Join(subclauses, " OR ")+")")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s := `SELECT
|
||||
event.id,
|
||||
event.height,
|
||||
event.tipset_key,
|
||||
event.tipset_key_cid,
|
||||
event.emitter_addr,
|
||||
event.event_index,
|
||||
event.message_cid,
|
||||
event.message_index,
|
||||
event.reverted,
|
||||
event_entry.flags,
|
||||
event_entry.key,
|
||||
event_entry.value
|
||||
FROM event JOIN event_entry ON event.id=event_entry.event_id`
|
||||
|
||||
if len(joins) > 0 {
|
||||
s = s + ", " + strings.Join(joins, ", ")
|
||||
}
|
||||
|
||||
if len(clauses) > 0 {
|
||||
s = s + " WHERE " + strings.Join(clauses, " AND ")
|
||||
}
|
||||
|
||||
s += " ORDER BY event.height DESC"
|
||||
|
||||
stmt, err := ei.db.Prepare(s)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("prepare prefill query: %w", err)
|
||||
}
|
||||
|
||||
q, err := stmt.QueryContext(ctx, values...)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil
|
||||
}
|
||||
return xerrors.Errorf("exec prefill query: %w", err)
|
||||
}
|
||||
|
||||
var ces []*CollectedEvent
|
||||
var currentID int64 = -1
|
||||
var ce *CollectedEvent
|
||||
|
||||
for q.Next() {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
var row struct {
|
||||
id int64
|
||||
height uint64
|
||||
tipsetKey []byte
|
||||
tipsetKeyCid []byte
|
||||
emitterAddr []byte
|
||||
eventIndex int
|
||||
messageCid []byte
|
||||
messageIndex int
|
||||
reverted bool
|
||||
flags []byte
|
||||
key string
|
||||
value []byte
|
||||
}
|
||||
|
||||
if err := q.Scan(
|
||||
&row.id,
|
||||
&row.height,
|
||||
&row.tipsetKey,
|
||||
&row.tipsetKeyCid,
|
||||
&row.emitterAddr,
|
||||
&row.eventIndex,
|
||||
&row.messageCid,
|
||||
&row.messageIndex,
|
||||
&row.reverted,
|
||||
&row.flags,
|
||||
&row.key,
|
||||
&row.value,
|
||||
); err != nil {
|
||||
return xerrors.Errorf("read prefill row: %w", err)
|
||||
}
|
||||
|
||||
if row.id != currentID {
|
||||
if ce != nil {
|
||||
ces = append(ces, ce)
|
||||
ce = nil
|
||||
// Unfortunately we can't easily incorporate the max results limit into the query due to the
|
||||
// unpredictable number of rows caused by joins
|
||||
// Break here to stop collecting rows
|
||||
if f.maxResults > 0 && len(ces) >= f.maxResults {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
currentID = row.id
|
||||
ce = &CollectedEvent{
|
||||
EventIdx: row.eventIndex,
|
||||
Reverted: row.reverted,
|
||||
Height: abi.ChainEpoch(row.height),
|
||||
MsgIdx: row.messageIndex,
|
||||
}
|
||||
|
||||
ce.EmitterAddr, err = address.NewFromBytes(row.emitterAddr)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("parse emitter addr: %w", err)
|
||||
}
|
||||
|
||||
ce.TipSetKey, err = types.TipSetKeyFromBytes(row.tipsetKey)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("parse tipsetkey: %w", err)
|
||||
}
|
||||
|
||||
ce.MsgCid, err = cid.Cast(row.messageCid)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("parse message cid: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
ce.Entries = append(ce.Entries, types.EventEntry{
|
||||
Flags: row.flags[0],
|
||||
Key: row.key,
|
||||
Value: row.value,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
if ce != nil {
|
||||
ces = append(ces, ce)
|
||||
}
|
||||
|
||||
if len(ces) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// collected event list is in inverted order since we selected only the most recent events
|
||||
// sort it into height order
|
||||
sort.Slice(ces, func(i, j int) bool { return ces[i].Height < ces[j].Height })
|
||||
f.setCollectedEvents(ces)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func trimLeadingZeros(b []byte) []byte {
|
||||
for i := range b {
|
||||
if b[i] != 0 {
|
||||
return b[i:]
|
||||
}
|
||||
}
|
||||
return []byte{}
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
package filter
|
||||
|
||||
import (
|
||||
"context"
|
||||
pseudo "math/rand"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
func TestEventIndexPrefillFilter(t *testing.T) {
|
||||
rng := pseudo.New(pseudo.NewSource(299792458))
|
||||
a1 := randomF4Addr(t, rng)
|
||||
a2 := randomF4Addr(t, rng)
|
||||
|
||||
a1ID := abi.ActorID(1)
|
||||
a2ID := abi.ActorID(2)
|
||||
|
||||
addrMap := addressMap{}
|
||||
addrMap.add(a1ID, a1)
|
||||
addrMap.add(a2ID, a2)
|
||||
|
||||
ev1 := fakeEvent(
|
||||
a1ID,
|
||||
[]kv{
|
||||
{k: "type", v: []byte("approval")},
|
||||
{k: "signer", v: []byte("addr1")},
|
||||
},
|
||||
[]kv{
|
||||
{k: "amount", v: []byte("2988181")},
|
||||
},
|
||||
)
|
||||
|
||||
st := newStore()
|
||||
events := []*types.Event{ev1}
|
||||
em := executedMessage{
|
||||
msg: fakeMessage(randomF4Addr(t, rng), randomF4Addr(t, rng)),
|
||||
rct: fakeReceipt(t, rng, st, events),
|
||||
evs: events,
|
||||
}
|
||||
|
||||
events14000 := buildTipSetEvents(t, rng, 14000, em)
|
||||
cid14000, err := events14000.msgTs.Key().Cid()
|
||||
require.NoError(t, err, "tipset cid")
|
||||
|
||||
noCollectedEvents := []*CollectedEvent{}
|
||||
oneCollectedEvent := []*CollectedEvent{
|
||||
{
|
||||
Entries: ev1.Entries,
|
||||
EmitterAddr: a1,
|
||||
EventIdx: 0,
|
||||
Reverted: false,
|
||||
Height: 14000,
|
||||
TipSetKey: events14000.msgTs.Key(),
|
||||
MsgIdx: 0,
|
||||
MsgCid: em.msg.Cid(),
|
||||
},
|
||||
}
|
||||
|
||||
workDir, err := os.MkdirTemp("", "lotusevents")
|
||||
require.NoError(t, err, "create temporary work directory")
|
||||
|
||||
defer func() {
|
||||
_ = os.RemoveAll(workDir)
|
||||
}()
|
||||
t.Logf("using work dir %q", workDir)
|
||||
|
||||
dbPath := filepath.Join(workDir, "actorevents.db")
|
||||
|
||||
ei, err := NewEventIndex(dbPath)
|
||||
require.NoError(t, err, "create event index")
|
||||
if err := ei.CollectEvents(context.Background(), events14000, false, addrMap.ResolveAddress); err != nil {
|
||||
require.NoError(t, err, "collect events")
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
filter *EventFilter
|
||||
te *TipSetEvents
|
||||
want []*CollectedEvent
|
||||
}{
|
||||
{
|
||||
name: "nomatch tipset min height",
|
||||
filter: &EventFilter{
|
||||
minHeight: 14001,
|
||||
maxHeight: -1,
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "nomatch tipset max height",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: 13999,
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "match tipset min height",
|
||||
filter: &EventFilter{
|
||||
minHeight: 14000,
|
||||
maxHeight: -1,
|
||||
},
|
||||
te: events14000,
|
||||
want: oneCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "match tipset cid",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
tipsetCid: cid14000,
|
||||
},
|
||||
te: events14000,
|
||||
want: oneCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "nomatch address",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
addresses: []address.Address{a2},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "match address",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
addresses: []address.Address{a1},
|
||||
},
|
||||
te: events14000,
|
||||
want: oneCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "match one entry",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("approval"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: oneCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "match one entry with alternate values",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("cancel"),
|
||||
[]byte("propose"),
|
||||
[]byte("approval"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: oneCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "nomatch one entry by missing value",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("cancel"),
|
||||
[]byte("propose"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "nomatch one entry by missing key",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"method": {
|
||||
[]byte("approval"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "match one entry with multiple keys",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("approval"),
|
||||
},
|
||||
"signer": {
|
||||
[]byte("addr1"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: oneCollectedEvent,
|
||||
},
|
||||
{
|
||||
name: "nomatch one entry with one mismatching key",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("approval"),
|
||||
},
|
||||
"approver": {
|
||||
[]byte("addr1"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "nomatch one entry with one mismatching value",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"type": {
|
||||
[]byte("approval"),
|
||||
},
|
||||
"signer": {
|
||||
[]byte("addr2"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
{
|
||||
name: "nomatch one entry with one unindexed key",
|
||||
filter: &EventFilter{
|
||||
minHeight: -1,
|
||||
maxHeight: -1,
|
||||
keys: map[string][][]byte{
|
||||
"amount": {
|
||||
[]byte("2988181"),
|
||||
},
|
||||
},
|
||||
},
|
||||
te: events14000,
|
||||
want: noCollectedEvents,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc // appease lint
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if err := ei.PrefillFilter(context.Background(), tc.filter); err != nil {
|
||||
require.NoError(t, err, "prefill filter events")
|
||||
}
|
||||
|
||||
coll := tc.filter.TakeCollectedEvents(context.Background())
|
||||
require.ElementsMatch(t, coll, tc.want)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package filter
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
type MemPoolFilter struct {
|
||||
id types.FilterID
|
||||
maxResults int // maximum number of results to collect, 0 is unlimited
|
||||
ch chan<- interface{}
|
||||
|
||||
mu sync.Mutex
|
||||
collected []cid.Cid
|
||||
lastTaken time.Time
|
||||
}
|
||||
|
||||
var _ Filter = (*MemPoolFilter)(nil)
|
||||
|
||||
func (f *MemPoolFilter) ID() types.FilterID {
|
||||
return f.id
|
||||
}
|
||||
|
||||
func (f *MemPoolFilter) SetSubChannel(ch chan<- interface{}) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
f.ch = ch
|
||||
f.collected = nil
|
||||
}
|
||||
|
||||
func (f *MemPoolFilter) ClearSubChannel() {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
f.ch = nil
|
||||
}
|
||||
|
||||
func (f *MemPoolFilter) CollectMessage(ctx context.Context, msg *types.SignedMessage) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
|
||||
// if we have a subscription channel then push message to it
|
||||
if f.ch != nil {
|
||||
f.ch <- msg
|
||||
return
|
||||
}
|
||||
|
||||
if f.maxResults > 0 && len(f.collected) == f.maxResults {
|
||||
copy(f.collected, f.collected[1:])
|
||||
f.collected = f.collected[:len(f.collected)-1]
|
||||
}
|
||||
f.collected = append(f.collected, msg.Cid())
|
||||
}
|
||||
|
||||
func (f *MemPoolFilter) TakeCollectedMessages(context.Context) []cid.Cid {
|
||||
f.mu.Lock()
|
||||
collected := f.collected
|
||||
f.collected = nil
|
||||
f.lastTaken = time.Now().UTC()
|
||||
f.mu.Unlock()
|
||||
|
||||
return collected
|
||||
}
|
||||
|
||||
func (f *MemPoolFilter) LastTaken() time.Time {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
return f.lastTaken
|
||||
}
|
||||
|
||||
type MemPoolFilterManager struct {
|
||||
MaxFilterResults int
|
||||
|
||||
mu sync.Mutex // guards mutations to filters
|
||||
filters map[types.FilterID]*MemPoolFilter
|
||||
}
|
||||
|
||||
func (m *MemPoolFilterManager) WaitForMpoolUpdates(ctx context.Context, ch <-chan api.MpoolUpdate) {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case u := <-ch:
|
||||
m.processUpdate(ctx, u)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MemPoolFilterManager) processUpdate(ctx context.Context, u api.MpoolUpdate) {
|
||||
// only process added messages
|
||||
if u.Type == api.MpoolRemove {
|
||||
return
|
||||
}
|
||||
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
if len(m.filters) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: could run this loop in parallel with errgroup if we expect large numbers of filters
|
||||
for _, f := range m.filters {
|
||||
f.CollectMessage(ctx, u.Message)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MemPoolFilterManager) Install(ctx context.Context) (*MemPoolFilter, error) {
|
||||
id, err := newFilterID()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("new filter id: %w", err)
|
||||
}
|
||||
|
||||
f := &MemPoolFilter{
|
||||
id: id,
|
||||
maxResults: m.MaxFilterResults,
|
||||
}
|
||||
|
||||
m.mu.Lock()
|
||||
if m.filters == nil {
|
||||
m.filters = make(map[types.FilterID]*MemPoolFilter)
|
||||
}
|
||||
m.filters[id] = f
|
||||
m.mu.Unlock()
|
||||
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (m *MemPoolFilterManager) Remove(ctx context.Context, id types.FilterID) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if _, found := m.filters[id]; !found {
|
||||
return ErrFilterNotFound
|
||||
}
|
||||
delete(m.filters, id)
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package filter
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
type Filter interface {
|
||||
ID() types.FilterID
|
||||
LastTaken() time.Time
|
||||
SetSubChannel(chan<- interface{})
|
||||
ClearSubChannel()
|
||||
}
|
||||
|
||||
type FilterStore interface {
|
||||
Add(context.Context, Filter) error
|
||||
Get(context.Context, types.FilterID) (Filter, error)
|
||||
Remove(context.Context, types.FilterID) error
|
||||
NotTakenSince(when time.Time) []Filter // returns a list of filters that have not had their collected results taken
|
||||
}
|
||||
|
||||
var (
|
||||
ErrFilterAlreadyRegistered = errors.New("filter already registered")
|
||||
ErrFilterNotFound = errors.New("filter not found")
|
||||
ErrMaximumNumberOfFilters = errors.New("maximum number of filters registered")
|
||||
)
|
||||
|
||||
func newFilterID() (types.FilterID, error) {
|
||||
rawid, err := uuid.NewRandom()
|
||||
if err != nil {
|
||||
return types.FilterID{}, xerrors.Errorf("new uuid: %w", err)
|
||||
}
|
||||
id := types.FilterID{}
|
||||
copy(id[:], rawid[:]) // uuid is 16 bytes, the last 16 bytes are zeroed
|
||||
return id, nil
|
||||
}
|
||||
|
||||
type memFilterStore struct {
|
||||
max int
|
||||
mu sync.Mutex
|
||||
filters map[types.FilterID]Filter
|
||||
}
|
||||
|
||||
var _ FilterStore = (*memFilterStore)(nil)
|
||||
|
||||
func NewMemFilterStore(maxFilters int) FilterStore {
|
||||
return &memFilterStore{
|
||||
max: maxFilters,
|
||||
filters: make(map[types.FilterID]Filter),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *memFilterStore) Add(_ context.Context, f Filter) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
if len(m.filters) >= m.max {
|
||||
return ErrMaximumNumberOfFilters
|
||||
}
|
||||
|
||||
if _, exists := m.filters[f.ID()]; exists {
|
||||
return ErrFilterAlreadyRegistered
|
||||
}
|
||||
m.filters[f.ID()] = f
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *memFilterStore) Get(_ context.Context, id types.FilterID) (Filter, error) {
|
||||
m.mu.Lock()
|
||||
f, found := m.filters[id]
|
||||
m.mu.Unlock()
|
||||
if !found {
|
||||
return nil, ErrFilterNotFound
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (m *memFilterStore) Remove(_ context.Context, id types.FilterID) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
if _, exists := m.filters[id]; !exists {
|
||||
return ErrFilterNotFound
|
||||
}
|
||||
delete(m.filters, id)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *memFilterStore) NotTakenSince(when time.Time) []Filter {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
var res []Filter
|
||||
for _, f := range m.filters {
|
||||
if f.LastTaken().Before(when) {
|
||||
res = append(res, f)
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package filter
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
type TipSetFilter struct {
|
||||
id types.FilterID
|
||||
maxResults int // maximum number of results to collect, 0 is unlimited
|
||||
ch chan<- interface{}
|
||||
|
||||
mu sync.Mutex
|
||||
collected []types.TipSetKey
|
||||
lastTaken time.Time
|
||||
}
|
||||
|
||||
var _ Filter = (*TipSetFilter)(nil)
|
||||
|
||||
func (f *TipSetFilter) ID() types.FilterID {
|
||||
return f.id
|
||||
}
|
||||
|
||||
func (f *TipSetFilter) SetSubChannel(ch chan<- interface{}) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
f.ch = ch
|
||||
f.collected = nil
|
||||
}
|
||||
|
||||
func (f *TipSetFilter) ClearSubChannel() {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
f.ch = nil
|
||||
}
|
||||
|
||||
func (f *TipSetFilter) CollectTipSet(ctx context.Context, ts *types.TipSet) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
|
||||
// if we have a subscription channel then push tipset to it
|
||||
if f.ch != nil {
|
||||
f.ch <- ts
|
||||
return
|
||||
}
|
||||
|
||||
if f.maxResults > 0 && len(f.collected) == f.maxResults {
|
||||
copy(f.collected, f.collected[1:])
|
||||
f.collected = f.collected[:len(f.collected)-1]
|
||||
}
|
||||
f.collected = append(f.collected, ts.Key())
|
||||
}
|
||||
|
||||
func (f *TipSetFilter) TakeCollectedTipSets(context.Context) []types.TipSetKey {
|
||||
f.mu.Lock()
|
||||
collected := f.collected
|
||||
f.collected = nil
|
||||
f.lastTaken = time.Now().UTC()
|
||||
f.mu.Unlock()
|
||||
|
||||
return collected
|
||||
}
|
||||
|
||||
func (f *TipSetFilter) LastTaken() time.Time {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
return f.lastTaken
|
||||
}
|
||||
|
||||
type TipSetFilterManager struct {
|
||||
MaxFilterResults int
|
||||
|
||||
mu sync.Mutex // guards mutations to filters
|
||||
filters map[types.FilterID]*TipSetFilter
|
||||
}
|
||||
|
||||
func (m *TipSetFilterManager) Apply(ctx context.Context, from, to *types.TipSet) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if len(m.filters) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: could run this loop in parallel with errgroup
|
||||
for _, f := range m.filters {
|
||||
f.CollectTipSet(ctx, to)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *TipSetFilterManager) Revert(ctx context.Context, from, to *types.TipSet) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *TipSetFilterManager) Install(ctx context.Context) (*TipSetFilter, error) {
|
||||
id, err := newFilterID()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("new filter id: %w", err)
|
||||
}
|
||||
|
||||
f := &TipSetFilter{
|
||||
id: id,
|
||||
maxResults: m.MaxFilterResults,
|
||||
}
|
||||
|
||||
m.mu.Lock()
|
||||
if m.filters == nil {
|
||||
m.filters = make(map[types.FilterID]*TipSetFilter)
|
||||
}
|
||||
m.filters[id] = f
|
||||
m.mu.Unlock()
|
||||
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (m *TipSetFilterManager) Remove(ctx context.Context, id types.FilterID) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if _, found := m.filters[id]; !found {
|
||||
return ErrFilterNotFound
|
||||
}
|
||||
delete(m.filters, id)
|
||||
return nil
|
||||
}
|
||||
@@ -468,10 +468,6 @@ func (cg *ChainGen) NextTipSetFromMinersWithMessagesAndNulls(base *types.TipSet,
|
||||
return nil, xerrors.Errorf("making a block for next tipset failed: %w", err)
|
||||
}
|
||||
|
||||
if err := cg.cs.PersistBlockHeaders(context.TODO(), fblk.Header); err != nil {
|
||||
return nil, xerrors.Errorf("chainstore AddBlock: %w", err)
|
||||
}
|
||||
|
||||
blks = append(blks, fblk)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,12 +123,7 @@ Genesis: {
|
||||
|
||||
func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template genesis.Template) (*state.StateTree, map[address.Address]address.Address, error) {
|
||||
// Create empty state tree
|
||||
|
||||
cst := cbor.NewCborStore(bs)
|
||||
_, err := cst.Put(context.TODO(), []struct{}{})
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("putting empty object: %w", err)
|
||||
}
|
||||
|
||||
sv, err := state.VersionForNetwork(template.NetworkVersion)
|
||||
if err != nil {
|
||||
@@ -238,15 +233,12 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
|
||||
|
||||
// Create accounts
|
||||
for _, info := range template.Accounts {
|
||||
|
||||
switch info.Type {
|
||||
case genesis.TAccount:
|
||||
if err := CreateAccountActor(ctx, cst, state, info, keyIDs, av); err != nil {
|
||||
return nil, nil, xerrors.Errorf("failed to create account actor: %w", err)
|
||||
}
|
||||
|
||||
case genesis.TMultisig:
|
||||
|
||||
ida, err := address.NewIDAddress(uint64(idStart))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@@ -566,6 +558,11 @@ func MakeGenesisBlock(ctx context.Context, j journal.Journal, bs bstore.Blocksto
|
||||
return nil, xerrors.Errorf("make initial state tree failed: %w", err)
|
||||
}
|
||||
|
||||
// Set up the Ethereum Address Manager
|
||||
if err = SetupEAM(ctx, st, template.NetworkVersion); err != nil {
|
||||
return nil, xerrors.Errorf("failed to setup EAM: %w", err)
|
||||
}
|
||||
|
||||
stateroot, err := st.Flush(ctx)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("flush state tree failed: %w", err)
|
||||
@@ -580,11 +577,27 @@ func MakeGenesisBlock(ctx context.Context, j journal.Journal, bs bstore.Blocksto
|
||||
return nil, xerrors.Errorf("failed to verify presealed data: %w", err)
|
||||
}
|
||||
|
||||
// setup Storage Miners
|
||||
stateroot, err = SetupStorageMiners(ctx, cs, sys, stateroot, template.Miners, template.NetworkVersion)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("setup miners failed: %w", err)
|
||||
}
|
||||
|
||||
st, err = state.LoadStateTree(st.Store, stateroot)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to load updated state tree: %w", err)
|
||||
}
|
||||
|
||||
// Set up Eth null addresses.
|
||||
if _, err := SetupEthNullAddresses(ctx, st, template.NetworkVersion); err != nil {
|
||||
return nil, xerrors.Errorf("failed to set up Eth null addresses: %w", err)
|
||||
}
|
||||
|
||||
stateroot, err = st.Flush(ctx)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to flush state tree: %w", err)
|
||||
}
|
||||
|
||||
store := adt.WrapStore(ctx, cbor.NewCborStore(bs))
|
||||
emptyroot, err := adt0.MakeEmptyArray(store).Root()
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
package genesis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/go-state-types/builtin"
|
||||
"github.com/filecoin-project/go-state-types/manifest"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
|
||||
"github.com/filecoin-project/lotus/chain/state"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
)
|
||||
|
||||
// EthNullAddresses are the Ethereum addresses we want to create zero-balanced EthAccounts in.
|
||||
// We may want to add null addresses for precompiles going forward.
|
||||
var EthNullAddresses = []string{
|
||||
"0x0000000000000000000000000000000000000000",
|
||||
}
|
||||
|
||||
func SetupEAM(_ context.Context, nst *state.StateTree, nv network.Version) error {
|
||||
av, err := actorstypes.VersionForNetwork(nv)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get actors version for network version %d: %w", nv, err)
|
||||
}
|
||||
|
||||
if av < actorstypes.Version10 {
|
||||
// Not defined before version 10; migration has to create.
|
||||
return nil
|
||||
}
|
||||
|
||||
codecid, ok := actors.GetActorCodeID(av, manifest.EamKey)
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to get CodeCID for EAM during genesis")
|
||||
}
|
||||
|
||||
header := &types.Actor{
|
||||
Code: codecid,
|
||||
Head: vm.EmptyObjectCid,
|
||||
Balance: big.Zero(),
|
||||
Address: &builtin.EthereumAddressManagerActorAddr, // so that it can create ETH0
|
||||
}
|
||||
return nst.SetActor(builtin.EthereumAddressManagerActorAddr, header)
|
||||
}
|
||||
|
||||
// MakeEthNullAddressActor creates a null address actor at the specified Ethereum address.
|
||||
func MakeEthNullAddressActor(av actorstypes.Version, addr address.Address) (*types.Actor, error) {
|
||||
actcid, ok := actors.GetActorCodeID(av, manifest.EthAccountKey)
|
||||
if !ok {
|
||||
return nil, xerrors.Errorf("failed to get EthAccount actor code ID for actors version %d", av)
|
||||
}
|
||||
|
||||
act := &types.Actor{
|
||||
Code: actcid,
|
||||
Head: vm.EmptyObjectCid,
|
||||
Nonce: 0,
|
||||
Balance: big.Zero(),
|
||||
Address: &addr,
|
||||
}
|
||||
|
||||
return act, nil
|
||||
}
|
||||
|
||||
func SetupEthNullAddresses(ctx context.Context, st *state.StateTree, nv network.Version) ([]address.Address, error) {
|
||||
av, err := actorstypes.VersionForNetwork(nv)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to resolve actors version for network version %d: %w", av, err)
|
||||
}
|
||||
|
||||
if av < actorstypes.Version10 {
|
||||
// Not defined before version 10.
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var ethAddresses []ethtypes.EthAddress
|
||||
for _, addr := range EthNullAddresses {
|
||||
a, err := ethtypes.ParseEthAddress(addr)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to represent the 0x0 as an EthAddress: %w", err)
|
||||
}
|
||||
ethAddresses = append(ethAddresses, a)
|
||||
}
|
||||
|
||||
initAct, err := st.GetActor(builtin.InitActorAddr)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to load init actor: %w", err)
|
||||
}
|
||||
|
||||
initState, err := init_.Load(adt.WrapStore(ctx, st.Store), initAct)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to load init actor state: %w", err)
|
||||
}
|
||||
|
||||
var ret []address.Address
|
||||
for _, ethAddr := range ethAddresses {
|
||||
// Place an EthAccount at the 0x0 Eth Null Address.
|
||||
f4Addr, err := ethAddr.ToFilecoinAddress()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to compute Filecoin address for Eth addr 0x0: %w", err)
|
||||
}
|
||||
|
||||
idAddr, err := initState.MapAddressToNewID(f4Addr)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to map addr in init actor: %w", err)
|
||||
}
|
||||
|
||||
actState, err := MakeEthNullAddressActor(av, f4Addr)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to create EthAccount actor for null address: %w", err)
|
||||
}
|
||||
|
||||
if err := st.SetActor(idAddr, actState); err != nil {
|
||||
return nil, xerrors.Errorf("failed to set Eth Null Address EthAccount actor state: %w", err)
|
||||
}
|
||||
|
||||
ret = append(ret, idAddr)
|
||||
}
|
||||
|
||||
initAct.Head, err = st.Store.Put(ctx, initState)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to add init actor state to store: %w", err)
|
||||
}
|
||||
|
||||
if err := st.SetActor(builtin.InitActorAddr, initAct); err != nil {
|
||||
return nil, xerrors.Errorf("failed to set updated state for init actor: %w", err)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
@@ -33,12 +33,13 @@ import (
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain"
|
||||
"github.com/filecoin-project/lotus/chain/consensus/filcns"
|
||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
"github.com/filecoin-project/lotus/journal"
|
||||
"github.com/filecoin-project/lotus/lib/sigs"
|
||||
"github.com/filecoin-project/lotus/metrics"
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
)
|
||||
@@ -282,7 +283,7 @@ func (ms *msgSet) add(m *types.SignedMessage, mp *MessagePool, strict, untrusted
|
||||
}
|
||||
|
||||
ms.requiredFunds.Sub(ms.requiredFunds, exms.Message.RequiredFunds().Int)
|
||||
//ms.requiredFunds.Sub(ms.requiredFunds, exms.Message.Value.Int)
|
||||
// ms.requiredFunds.Sub(ms.requiredFunds, exms.Message.Value.Int)
|
||||
}
|
||||
|
||||
if !has && strict && len(ms.msgs) >= maxActorPendingMessages {
|
||||
@@ -298,7 +299,7 @@ func (ms *msgSet) add(m *types.SignedMessage, mp *MessagePool, strict, untrusted
|
||||
ms.nextNonce = nextNonce
|
||||
ms.msgs[m.Message.Nonce] = m
|
||||
ms.requiredFunds.Add(ms.requiredFunds, m.Message.RequiredFunds().Int)
|
||||
//ms.requiredFunds.Add(ms.requiredFunds, m.Message.Value.Int)
|
||||
// ms.requiredFunds.Add(ms.requiredFunds, m.Message.Value.Int)
|
||||
|
||||
return !has, nil
|
||||
}
|
||||
@@ -318,7 +319,7 @@ func (ms *msgSet) rm(nonce uint64, applied bool) {
|
||||
}
|
||||
|
||||
ms.requiredFunds.Sub(ms.requiredFunds, m.Message.RequiredFunds().Int)
|
||||
//ms.requiredFunds.Sub(ms.requiredFunds, m.Message.Value.Int)
|
||||
// ms.requiredFunds.Sub(ms.requiredFunds, m.Message.Value.Int)
|
||||
delete(ms.msgs, nonce)
|
||||
|
||||
// adjust next nonce
|
||||
@@ -344,7 +345,7 @@ func (ms *msgSet) getRequiredFunds(nonce uint64) types.BigInt {
|
||||
m, has := ms.msgs[nonce]
|
||||
if has {
|
||||
requiredFunds.Sub(requiredFunds, m.Message.RequiredFunds().Int)
|
||||
//requiredFunds.Sub(requiredFunds, m.Message.Value.Int)
|
||||
// requiredFunds.Sub(requiredFunds, m.Message.Value.Int)
|
||||
}
|
||||
|
||||
return types.BigInt{Int: requiredFunds}
|
||||
@@ -476,7 +477,7 @@ func (mp *MessagePool) resolveToKey(ctx context.Context, addr address.Address) (
|
||||
}
|
||||
|
||||
// resolve the address
|
||||
ka, err := mp.api.StateAccountKeyAtFinality(ctx, addr, mp.curTs)
|
||||
ka, err := mp.api.StateDeterministicAddressAtFinality(ctx, addr, mp.curTs)
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
@@ -772,11 +773,9 @@ func sigCacheKey(m *types.SignedMessage) (string, error) {
|
||||
if len(m.Signature.Data) != ffi.SignatureBytes {
|
||||
return "", fmt.Errorf("bls signature incorrectly sized")
|
||||
}
|
||||
|
||||
hashCache := blake2b.Sum256(append(m.Cid().Bytes(), m.Signature.Data...))
|
||||
|
||||
return string(hashCache[:]), nil
|
||||
case crypto.SigTypeSecp256k1:
|
||||
case crypto.SigTypeSecp256k1, crypto.SigTypeDelegated:
|
||||
return string(m.Cid().Bytes()), nil
|
||||
default:
|
||||
return "", xerrors.Errorf("unrecognized signature type: %d", m.Signature.Type)
|
||||
@@ -795,8 +794,8 @@ func (mp *MessagePool) VerifyMsgSig(m *types.SignedMessage) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := sigs.Verify(&m.Signature, m.Message.From, m.Message.Cid().Bytes()); err != nil {
|
||||
return err
|
||||
if err := chain.AuthenticateMessage(m, m.Message.From); err != nil {
|
||||
return xerrors.Errorf("failed to validate signature: %w", err)
|
||||
}
|
||||
|
||||
mp.sigValCache.Add(sck, struct{}{})
|
||||
@@ -816,7 +815,7 @@ func (mp *MessagePool) checkBalance(ctx context.Context, m *types.SignedMessage,
|
||||
}
|
||||
|
||||
// add Value for soft failure check
|
||||
//requiredFunds = types.BigAdd(requiredFunds, m.Message.Value)
|
||||
// requiredFunds = types.BigAdd(requiredFunds, m.Message.Value)
|
||||
|
||||
mset, ok, err := mp.getPendingMset(ctx, m.Message.From)
|
||||
if err != nil {
|
||||
@@ -853,18 +852,32 @@ func (mp *MessagePool) addTs(ctx context.Context, m *types.SignedMessage, curTs
|
||||
mp.lk.Lock()
|
||||
defer mp.lk.Unlock()
|
||||
|
||||
senderAct, err := mp.api.GetActorAfter(m.Message.From, curTs)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("failed to get sender actor: %w", err)
|
||||
}
|
||||
|
||||
// This message can only be included in the _next_ epoch and beyond, hence the +1.
|
||||
epoch := curTs.Height() + 1
|
||||
nv := mp.api.StateNetworkVersion(ctx, epoch)
|
||||
|
||||
// TODO: I'm not thrilled about depending on filcns here, but I prefer this to duplicating logic
|
||||
if !filcns.IsValidForSending(nv, senderAct) {
|
||||
return false, xerrors.Errorf("sender actor %s is not a valid top-level sender", m.Message.From)
|
||||
}
|
||||
|
||||
publish, err := mp.verifyMsgBeforeAdd(ctx, m, curTs, local)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return false, xerrors.Errorf("verify msg failed: %w", err)
|
||||
}
|
||||
|
||||
if err := mp.checkBalance(ctx, m, curTs); err != nil {
|
||||
return false, err
|
||||
return false, xerrors.Errorf("failed to check balance: %w", err)
|
||||
}
|
||||
|
||||
err = mp.addLocked(ctx, m, !local, untrusted)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return false, xerrors.Errorf("failed to add locked: %w", err)
|
||||
}
|
||||
|
||||
if local {
|
||||
|
||||
@@ -155,14 +155,14 @@ func (tma *testMpoolAPI) GetActorAfter(addr address.Address, ts *types.TipSet) (
|
||||
}
|
||||
|
||||
return &types.Actor{
|
||||
Code: builtin2.StorageMarketActorCodeID,
|
||||
Code: builtin2.AccountActorCodeID,
|
||||
Nonce: nonce,
|
||||
Balance: balance,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (tma *testMpoolAPI) StateAccountKeyAtFinality(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
|
||||
if addr.Protocol() != address.BLS && addr.Protocol() != address.SECP256K1 {
|
||||
func (tma *testMpoolAPI) StateDeterministicAddressAtFinality(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
|
||||
if addr.Protocol() != address.BLS && addr.Protocol() != address.SECP256K1 && addr.Protocol() != address.Delegated {
|
||||
return address.Undef, fmt.Errorf("given address was not a key addr")
|
||||
}
|
||||
return addr, nil
|
||||
@@ -214,7 +214,7 @@ func (tma *testMpoolAPI) ChainComputeBaseFee(ctx context.Context, ts *types.TipS
|
||||
|
||||
func assertNonce(t *testing.T, mp *MessagePool, addr address.Address, val uint64) {
|
||||
t.Helper()
|
||||
//stm: @CHAIN_MEMPOOL_GET_NONCE_001
|
||||
// stm: @CHAIN_MEMPOOL_GET_NONCE_001
|
||||
n, err := mp.GetNonce(context.TODO(), addr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -233,7 +233,7 @@ func mustAdd(t *testing.T, mp *MessagePool, msg *types.SignedMessage) {
|
||||
}
|
||||
|
||||
func TestMessagePool(t *testing.T) {
|
||||
//stm: @CHAIN_MEMPOOL_GET_NONCE_001
|
||||
// stm: @CHAIN_MEMPOOL_GET_NONCE_001
|
||||
|
||||
tma := newTestMpoolAPI()
|
||||
|
||||
@@ -336,7 +336,7 @@ func TestCheckMessageBig(t *testing.T) {
|
||||
Message: *msg,
|
||||
Signature: *sig,
|
||||
}
|
||||
//stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
// stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
err = mp.Add(context.TODO(), sm)
|
||||
assert.ErrorIs(t, err, ErrMessageTooBig)
|
||||
}
|
||||
@@ -378,10 +378,10 @@ func TestMessagePoolMessagesInEachBlock(t *testing.T) {
|
||||
tma.applyBlock(t, a)
|
||||
tsa := mock.TipSet(a)
|
||||
|
||||
//stm: @CHAIN_MEMPOOL_PENDING_001
|
||||
// stm: @CHAIN_MEMPOOL_PENDING_001
|
||||
_, _ = mp.Pending(context.TODO())
|
||||
|
||||
//stm: @CHAIN_MEMPOOL_SELECT_001
|
||||
// stm: @CHAIN_MEMPOOL_SELECT_001
|
||||
selm, _ := mp.SelectMessages(context.Background(), tsa, 1)
|
||||
if len(selm) == 0 {
|
||||
t.Fatal("should have returned the rest of the messages")
|
||||
@@ -442,7 +442,7 @@ func TestRevertMessages(t *testing.T) {
|
||||
|
||||
assertNonce(t, mp, sender, 4)
|
||||
|
||||
//stm: @CHAIN_MEMPOOL_PENDING_001
|
||||
// stm: @CHAIN_MEMPOOL_PENDING_001
|
||||
p, _ := mp.Pending(context.TODO())
|
||||
fmt.Printf("%+v\n", p)
|
||||
if len(p) != 3 {
|
||||
@@ -501,7 +501,7 @@ func TestPruningSimple(t *testing.T) {
|
||||
|
||||
mp.Prune()
|
||||
|
||||
//stm: @CHAIN_MEMPOOL_PENDING_001
|
||||
// stm: @CHAIN_MEMPOOL_PENDING_001
|
||||
msgs, _ := mp.Pending(context.TODO())
|
||||
if len(msgs) != 5 {
|
||||
t.Fatal("expected only 5 messages in pool, got: ", len(msgs))
|
||||
@@ -544,7 +544,7 @@ func TestLoadLocal(t *testing.T) {
|
||||
msgs := make(map[cid.Cid]struct{})
|
||||
for i := 0; i < 10; i++ {
|
||||
m := makeTestMessage(w1, a1, a2, uint64(i), gasLimit, uint64(i+1))
|
||||
//stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
// stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
cid, err := mp.Push(context.TODO(), m, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -561,7 +561,7 @@ func TestLoadLocal(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
//stm: @CHAIN_MEMPOOL_PENDING_001
|
||||
// stm: @CHAIN_MEMPOOL_PENDING_001
|
||||
pmsgs, _ := mp.Pending(context.TODO())
|
||||
if len(msgs) != len(pmsgs) {
|
||||
t.Fatalf("expected %d messages, but got %d", len(msgs), len(pmsgs))
|
||||
@@ -617,7 +617,7 @@ func TestClearAll(t *testing.T) {
|
||||
gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin2.StorageMarketActorCodeID, M: 2}]
|
||||
for i := 0; i < 10; i++ {
|
||||
m := makeTestMessage(w1, a1, a2, uint64(i), gasLimit, uint64(i+1))
|
||||
//stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
// stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
_, err := mp.Push(context.TODO(), m, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -629,10 +629,10 @@ func TestClearAll(t *testing.T) {
|
||||
mustAdd(t, mp, m)
|
||||
}
|
||||
|
||||
//stm: @CHAIN_MEMPOOL_CLEAR_001
|
||||
// stm: @CHAIN_MEMPOOL_CLEAR_001
|
||||
mp.Clear(context.Background(), true)
|
||||
|
||||
//stm: @CHAIN_MEMPOOL_PENDING_001
|
||||
// stm: @CHAIN_MEMPOOL_PENDING_001
|
||||
pending, _ := mp.Pending(context.TODO())
|
||||
if len(pending) > 0 {
|
||||
t.Fatalf("cleared the mpool, but got %d pending messages", len(pending))
|
||||
@@ -675,7 +675,7 @@ func TestClearNonLocal(t *testing.T) {
|
||||
gasLimit := gasguess.Costs[gasguess.CostKey{Code: builtin2.StorageMarketActorCodeID, M: 2}]
|
||||
for i := 0; i < 10; i++ {
|
||||
m := makeTestMessage(w1, a1, a2, uint64(i), gasLimit, uint64(i+1))
|
||||
//stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
// stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
_, err := mp.Push(context.TODO(), m, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -687,10 +687,10 @@ func TestClearNonLocal(t *testing.T) {
|
||||
mustAdd(t, mp, m)
|
||||
}
|
||||
|
||||
//stm: @CHAIN_MEMPOOL_CLEAR_001
|
||||
// stm: @CHAIN_MEMPOOL_CLEAR_001
|
||||
mp.Clear(context.Background(), false)
|
||||
|
||||
//stm: @CHAIN_MEMPOOL_PENDING_001
|
||||
// stm: @CHAIN_MEMPOOL_PENDING_001
|
||||
pending, _ := mp.Pending(context.TODO())
|
||||
if len(pending) != 10 {
|
||||
t.Fatalf("expected 10 pending messages, but got %d instead", len(pending))
|
||||
@@ -748,7 +748,7 @@ func TestUpdates(t *testing.T) {
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
m := makeTestMessage(w1, a1, a2, uint64(i), gasLimit, uint64(i+1))
|
||||
//stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
// stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
_, err := mp.Push(context.TODO(), m, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -772,7 +772,7 @@ func TestUpdates(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMessageBelowMinGasFee(t *testing.T) {
|
||||
//stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
// stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
tma := newTestMpoolAPI()
|
||||
|
||||
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
|
||||
@@ -818,7 +818,7 @@ func TestMessageBelowMinGasFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMessageValueTooHigh(t *testing.T) {
|
||||
//stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
// stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
tma := newTestMpoolAPI()
|
||||
|
||||
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
|
||||
@@ -866,7 +866,7 @@ func TestMessageValueTooHigh(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMessageSignatureInvalid(t *testing.T) {
|
||||
//stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
// stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
tma := newTestMpoolAPI()
|
||||
|
||||
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
|
||||
@@ -911,7 +911,7 @@ func TestMessageSignatureInvalid(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAddMessageTwice(t *testing.T) {
|
||||
//stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
// stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
tma := newTestMpoolAPI()
|
||||
|
||||
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
|
||||
@@ -957,7 +957,7 @@ func TestAddMessageTwice(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAddMessageTwiceNonceGap(t *testing.T) {
|
||||
//stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
// stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
tma := newTestMpoolAPI()
|
||||
|
||||
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
|
||||
@@ -1011,7 +1011,7 @@ func TestAddMessageTwiceCidDiff(t *testing.T) {
|
||||
// Create message with different data, so CID is different
|
||||
sm2 := makeTestMessage(w, from, to, 0, 50_000_001, minimumBaseFee.Uint64())
|
||||
|
||||
//stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
// stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
// then try to add message again
|
||||
err = mp.Add(context.TODO(), sm2)
|
||||
// assert.Contains(t, err.Error(), "replace by fee has too low GasPremium")
|
||||
@@ -1020,7 +1020,7 @@ func TestAddMessageTwiceCidDiff(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAddMessageTwiceCidDiffReplaced(t *testing.T) {
|
||||
//stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
// stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
tma := newTestMpoolAPI()
|
||||
|
||||
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
|
||||
@@ -1049,7 +1049,7 @@ func TestAddMessageTwiceCidDiffReplaced(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRemoveMessage(t *testing.T) {
|
||||
//stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
// stm: @CHAIN_MEMPOOL_PUSH_001
|
||||
tma := newTestMpoolAPI()
|
||||
|
||||
w, err := wallet.NewWallet(wallet.NewMemKeyStore())
|
||||
@@ -1071,11 +1071,11 @@ func TestRemoveMessage(t *testing.T) {
|
||||
sm := makeTestMessage(w, from, to, 0, 50_000_000, minimumBaseFee.Uint64())
|
||||
mustAdd(t, mp, sm)
|
||||
|
||||
//stm: @CHAIN_MEMPOOL_REMOVE_001
|
||||
// stm: @CHAIN_MEMPOOL_REMOVE_001
|
||||
// remove message for sender
|
||||
mp.Remove(context.TODO(), from, sm.Message.Nonce, true)
|
||||
|
||||
//stm: @CHAIN_MEMPOOL_PENDING_FOR_001
|
||||
// stm: @CHAIN_MEMPOOL_PENDING_FOR_001
|
||||
// check messages in pool: should be none present
|
||||
msgs := mp.pendingFor(context.TODO(), from)
|
||||
assert.Len(t, msgs, 0)
|
||||
|
||||
@@ -28,7 +28,7 @@ type Provider interface {
|
||||
PutMessage(ctx context.Context, m types.ChainMsg) (cid.Cid, error)
|
||||
PubSubPublish(string, []byte) error
|
||||
GetActorAfter(address.Address, *types.TipSet) (*types.Actor, error)
|
||||
StateAccountKeyAtFinality(context.Context, address.Address, *types.TipSet) (address.Address, error)
|
||||
StateDeterministicAddressAtFinality(context.Context, address.Address, *types.TipSet) (address.Address, error)
|
||||
StateNetworkVersion(context.Context, abi.ChainEpoch) network.Version
|
||||
MessagesForBlock(context.Context, *types.BlockHeader) ([]*types.Message, []*types.SignedMessage, error)
|
||||
MessagesForTipset(context.Context, *types.TipSet) ([]types.ChainMsg, error)
|
||||
@@ -74,7 +74,7 @@ func (mpp *mpoolProvider) PutMessage(ctx context.Context, m types.ChainMsg) (cid
|
||||
}
|
||||
|
||||
func (mpp *mpoolProvider) PubSubPublish(k string, v []byte) error {
|
||||
return mpp.ps.Publish(k, v) //nolint
|
||||
return mpp.ps.Publish(k, v) // nolint
|
||||
}
|
||||
|
||||
func (mpp *mpoolProvider) GetActorAfter(addr address.Address, ts *types.TipSet) (*types.Actor, error) {
|
||||
@@ -102,8 +102,8 @@ func (mpp *mpoolProvider) GetActorAfter(addr address.Address, ts *types.TipSet)
|
||||
return st.GetActor(addr)
|
||||
}
|
||||
|
||||
func (mpp *mpoolProvider) StateAccountKeyAtFinality(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
|
||||
return mpp.sm.ResolveToKeyAddressAtFinality(ctx, addr, ts)
|
||||
func (mpp *mpoolProvider) StateDeterministicAddressAtFinality(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
|
||||
return mpp.sm.ResolveToDeterministicAddressAtFinality(ctx, addr, ts)
|
||||
}
|
||||
|
||||
func (mpp *mpoolProvider) StateNetworkVersion(ctx context.Context, height abi.ChainEpoch) network.Version {
|
||||
|
||||
@@ -97,7 +97,7 @@ func (sm *selectedMessages) tryToAdd(mc *msgChain) bool {
|
||||
sm.msgs = append(sm.msgs, mc.msgs...)
|
||||
sm.blsLimit -= l
|
||||
sm.gasLimit -= mc.gasLimit
|
||||
} else if mc.sigType == crypto.SigTypeSecp256k1 {
|
||||
} else if mc.sigType == crypto.SigTypeSecp256k1 || mc.sigType == crypto.SigTypeDelegated {
|
||||
if sm.secpLimit < l {
|
||||
return false
|
||||
}
|
||||
@@ -123,7 +123,7 @@ func (sm *selectedMessages) tryToAddWithDeps(mc *msgChain, mp *MessagePool, base
|
||||
|
||||
if mc.sigType == crypto.SigTypeBLS {
|
||||
smMsgLimit = sm.blsLimit
|
||||
} else if mc.sigType == crypto.SigTypeSecp256k1 {
|
||||
} else if mc.sigType == crypto.SigTypeSecp256k1 || mc.sigType == crypto.SigTypeDelegated {
|
||||
smMsgLimit = sm.secpLimit
|
||||
} else {
|
||||
return false
|
||||
@@ -174,7 +174,7 @@ func (sm *selectedMessages) tryToAddWithDeps(mc *msgChain, mp *MessagePool, base
|
||||
|
||||
if mc.sigType == crypto.SigTypeBLS {
|
||||
sm.blsLimit -= chainMsgLimit
|
||||
} else if mc.sigType == crypto.SigTypeSecp256k1 {
|
||||
} else if mc.sigType == crypto.SigTypeSecp256k1 || mc.sigType == crypto.SigTypeDelegated {
|
||||
sm.secpLimit -= chainMsgLimit
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ func (sm *selectedMessages) trimChain(mc *msgChain, mp *MessagePool, baseFee typ
|
||||
if msgLimit > sm.blsLimit {
|
||||
msgLimit = sm.blsLimit
|
||||
}
|
||||
} else if mc.sigType == crypto.SigTypeSecp256k1 {
|
||||
} else if mc.sigType == crypto.SigTypeSecp256k1 || mc.sigType == crypto.SigTypeDelegated {
|
||||
if msgLimit > sm.secpLimit {
|
||||
msgLimit = sm.secpLimit
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/types/mock"
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/delegated"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
"github.com/filecoin-project/lotus/lib/sigs"
|
||||
)
|
||||
|
||||
// AuthenticateMessage authenticates the message by verifying that the supplied
|
||||
// SignedMessage was signed by the indicated Address, computing the correct
|
||||
// signature payload depending on the signature type. The supplied Address type
|
||||
// must be recognized by the registered verifier for the signature type.
|
||||
func AuthenticateMessage(msg *types.SignedMessage, signer address.Address) error {
|
||||
var digest []byte
|
||||
|
||||
typ := msg.Signature.Type
|
||||
switch typ {
|
||||
case crypto.SigTypeDelegated:
|
||||
txArgs, err := ethtypes.NewEthTxArgsFromMessage(&msg.Message)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to reconstruct eth transaction: %w", err)
|
||||
}
|
||||
msg, err := txArgs.ToRlpUnsignedMsg()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to repack eth rlp message: %w", err)
|
||||
}
|
||||
digest = msg
|
||||
default:
|
||||
digest = msg.Message.Cid().Bytes()
|
||||
}
|
||||
|
||||
if err := sigs.Verify(&msg.Signature, signer, digest); err != nil {
|
||||
return xerrors.Errorf("message %s has invalid signature (type %d): %w", msg.Cid(), typ, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsValidSecpkSigType checks that a signature type is valid for the network
|
||||
// version, for a "secpk" message.
|
||||
func IsValidSecpkSigType(nv network.Version, typ crypto.SigType) bool {
|
||||
switch {
|
||||
case nv < network.Version18:
|
||||
return typ == crypto.SigTypeSecp256k1
|
||||
default:
|
||||
return typ == crypto.SigTypeSecp256k1 || typ == crypto.SigTypeDelegated
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ func GetMinerWorkerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr
|
||||
return address.Undef, xerrors.Errorf("failed to load actor info: %w", err)
|
||||
}
|
||||
|
||||
return vm.ResolveToKeyAddr(state, sm.cs.ActorStore(ctx), info.Worker)
|
||||
return vm.ResolveToDeterministicAddr(state, sm.cs.ActorStore(ctx), info.Worker)
|
||||
}
|
||||
|
||||
func GetPower(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (power.Claim, power.Claim, bool, error) {
|
||||
@@ -381,7 +381,7 @@ func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcs beacon.Schedule
|
||||
return nil, err
|
||||
}
|
||||
|
||||
worker, err := sm.ResolveToKeyAddress(ctx, info.Worker, ts)
|
||||
worker, err := sm.ResolveToDeterministicAddress(ctx, info.Worker, ts)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("resolving worker address: %w", err)
|
||||
}
|
||||
|
||||
+20
-1
@@ -143,6 +143,7 @@ func (sm *StateManager) callInternal(ctx context.Context, msg *types.Message, pr
|
||||
vmopt := &vm.VMOpts{
|
||||
StateBase: stateCid,
|
||||
Epoch: vmHeight,
|
||||
Timestamp: ts.MinTimestamp(),
|
||||
Rand: rand.NewStateRand(sm.cs, ts.Cids(), sm.beacon, nvGetter),
|
||||
Bstore: buffStore,
|
||||
Actors: sm.tsExec.NewActorRegistry(),
|
||||
@@ -199,7 +200,7 @@ func (sm *StateManager) callInternal(ctx context.Context, msg *types.Message, pr
|
||||
var ret *vm.ApplyRet
|
||||
var gasInfo api.MsgGasCost
|
||||
if checkGas {
|
||||
fromKey, err := sm.ResolveToKeyAddress(ctx, msg.From, ts)
|
||||
fromKey, err := sm.ResolveToDeterministicAddress(ctx, msg.From, ts)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("could not resolve key: %w", err)
|
||||
}
|
||||
@@ -217,6 +218,24 @@ func (sm *StateManager) callInternal(ctx context.Context, msg *types.Message, pr
|
||||
Data: make([]byte, 65),
|
||||
},
|
||||
}
|
||||
case address.Delegated:
|
||||
msgApply = &types.SignedMessage{
|
||||
Message: *msg,
|
||||
Signature: crypto.Signature{
|
||||
Type: crypto.SigTypeDelegated,
|
||||
Data: make([]byte, 65),
|
||||
},
|
||||
}
|
||||
default:
|
||||
// XXX: Hack to make sending from f099 (and others) "just work".
|
||||
// REMOVE ME.
|
||||
msgApply = &types.SignedMessage{
|
||||
Message: *msg,
|
||||
Signature: crypto.Signature{
|
||||
Type: crypto.SigTypeSecp256k1,
|
||||
Data: make([]byte, 65),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
ret, err = vmi.ApplyMessage(ctx, msgApply)
|
||||
|
||||
@@ -48,7 +48,7 @@ func (s *RPCStateManager) LookupID(ctx context.Context, addr address.Address, ts
|
||||
return s.gapi.StateLookupID(ctx, addr, ts.Key())
|
||||
}
|
||||
|
||||
func (s *RPCStateManager) ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
|
||||
func (s *RPCStateManager) ResolveToDeterministicAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
|
||||
return s.gapi.StateAccountKey(ctx, addr, ts.Key())
|
||||
}
|
||||
|
||||
|
||||
+11
-11
@@ -42,7 +42,7 @@ type StateManagerAPI interface {
|
||||
GetPaychState(ctx context.Context, addr address.Address, ts *types.TipSet) (*types.Actor, paych.State, error)
|
||||
LoadActorTsk(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*types.Actor, error)
|
||||
LookupID(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error)
|
||||
ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error)
|
||||
ResolveToDeterministicAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error)
|
||||
}
|
||||
|
||||
type versionSpec struct {
|
||||
@@ -207,11 +207,11 @@ func (sm *StateManager) Beacon() beacon.Schedule {
|
||||
return sm.beacon
|
||||
}
|
||||
|
||||
// ResolveToKeyAddress is similar to `vm.ResolveToKeyAddr` but does not allow `Actor` type of addresses.
|
||||
// ResolveToDeterministicAddress is similar to `vm.ResolveToDeterministicAddr` but does not allow `Actor` type of addresses.
|
||||
// Uses the `TipSet` `ts` to generate the VM state.
|
||||
func (sm *StateManager) ResolveToKeyAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
|
||||
func (sm *StateManager) ResolveToDeterministicAddress(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
|
||||
switch addr.Protocol() {
|
||||
case address.BLS, address.SECP256K1:
|
||||
case address.BLS, address.SECP256K1, address.Delegated:
|
||||
return addr, nil
|
||||
case address.Actor:
|
||||
return address.Undef, xerrors.New("cannot resolve actor address to key address")
|
||||
@@ -230,7 +230,7 @@ func (sm *StateManager) ResolveToKeyAddress(ctx context.Context, addr address.Ad
|
||||
return address.Undef, xerrors.Errorf("failed to load parent state tree at tipset %s: %w", ts.Parents(), err)
|
||||
}
|
||||
|
||||
resolved, err := vm.ResolveToKeyAddr(tree, cst, addr)
|
||||
resolved, err := vm.ResolveToDeterministicAddr(tree, cst, addr)
|
||||
if err == nil {
|
||||
return resolved, nil
|
||||
}
|
||||
@@ -246,14 +246,14 @@ func (sm *StateManager) ResolveToKeyAddress(ctx context.Context, addr address.Ad
|
||||
return address.Undef, xerrors.Errorf("failed to load state tree at tipset %s: %w", ts, err)
|
||||
}
|
||||
|
||||
return vm.ResolveToKeyAddr(tree, cst, addr)
|
||||
return vm.ResolveToDeterministicAddr(tree, cst, addr)
|
||||
}
|
||||
|
||||
// ResolveToKeyAddressAtFinality is similar to stmgr.ResolveToKeyAddress but fails if the ID address being resolved isn't reorg-stable yet.
|
||||
// ResolveToDeterministicAddressAtFinality is similar to stmgr.ResolveToDeterministicAddress but fails if the ID address being resolved isn't reorg-stable yet.
|
||||
// It should not be used for consensus-critical subsystems.
|
||||
func (sm *StateManager) ResolveToKeyAddressAtFinality(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
|
||||
func (sm *StateManager) ResolveToDeterministicAddressAtFinality(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
|
||||
switch addr.Protocol() {
|
||||
case address.BLS, address.SECP256K1:
|
||||
case address.BLS, address.SECP256K1, address.Delegated:
|
||||
return addr, nil
|
||||
case address.Actor:
|
||||
return address.Undef, xerrors.New("cannot resolve actor address to key address")
|
||||
@@ -287,7 +287,7 @@ func (sm *StateManager) ResolveToKeyAddressAtFinality(ctx context.Context, addr
|
||||
}
|
||||
}
|
||||
|
||||
resolved, err := vm.ResolveToKeyAddr(tree, cst, addr)
|
||||
resolved, err := vm.ResolveToDeterministicAddr(tree, cst, addr)
|
||||
if err == nil {
|
||||
return resolved, nil
|
||||
}
|
||||
@@ -296,7 +296,7 @@ func (sm *StateManager) ResolveToKeyAddressAtFinality(ctx context.Context, addr
|
||||
}
|
||||
|
||||
func (sm *StateManager) GetBlsPublicKey(ctx context.Context, addr address.Address, ts *types.TipSet) (pubk []byte, err error) {
|
||||
kaddr, err := sm.ResolveToKeyAddress(ctx, addr, ts)
|
||||
kaddr, err := sm.ResolveToDeterministicAddress(ctx, addr, ts)
|
||||
if err != nil {
|
||||
return pubk, xerrors.Errorf("failed to resolve address to key address: %w", err)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package stmgr
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
@@ -27,6 +28,8 @@ import (
|
||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
)
|
||||
|
||||
var ErrMetadataNotFound = errors.New("actor metadata not found")
|
||||
|
||||
func GetReturnType(ctx context.Context, sm *StateManager, to address.Address, method abi.MethodNum, ts *types.TipSet) (cbg.CBORUnmarshaler, error) {
|
||||
act, err := sm.LoadActor(ctx, to, ts)
|
||||
if err != nil {
|
||||
@@ -35,7 +38,7 @@ func GetReturnType(ctx context.Context, sm *StateManager, to address.Address, me
|
||||
|
||||
m, found := sm.tsExec.NewActorRegistry().Methods[act.Code][method]
|
||||
if !found {
|
||||
return nil, fmt.Errorf("unknown method %d for actor %s", method, act.Code)
|
||||
return nil, fmt.Errorf("unknown method %d for actor %s: %w", method, act.Code, ErrMetadataNotFound)
|
||||
}
|
||||
|
||||
return reflect.New(m.Ret.Elem()).Interface().(cbg.CBORUnmarshaler), nil
|
||||
@@ -44,7 +47,7 @@ func GetReturnType(ctx context.Context, sm *StateManager, to address.Address, me
|
||||
func GetParamType(ar *vm.ActorRegistry, actCode cid.Cid, method abi.MethodNum) (cbg.CBORUnmarshaler, error) {
|
||||
m, found := ar.Methods[actCode][method]
|
||||
if !found {
|
||||
return nil, fmt.Errorf("unknown method %d for actor %s", method, actCode)
|
||||
return nil, fmt.Errorf("unknown method %d for actor %s: %w", method, actCode, ErrMetadataNotFound)
|
||||
}
|
||||
return reflect.New(m.Params.Elem()).Interface().(cbg.CBORUnmarshaler), nil
|
||||
}
|
||||
@@ -87,6 +90,7 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch,
|
||||
vmopt := &vm.VMOpts{
|
||||
StateBase: base,
|
||||
Epoch: height,
|
||||
Timestamp: ts.MinTimestamp(),
|
||||
Rand: r,
|
||||
Bstore: sm.cs.StateBlockstore(),
|
||||
Actors: sm.tsExec.NewActorRegistry(),
|
||||
|
||||
+40
-23
@@ -1,6 +1,7 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
@@ -375,10 +376,8 @@ func (cs *ChainStore) SetGenesis(ctx context.Context, b *types.BlockHeader) erro
|
||||
}
|
||||
|
||||
func (cs *ChainStore) PutTipSet(ctx context.Context, ts *types.TipSet) error {
|
||||
for _, b := range ts.Blocks() {
|
||||
if err := cs.PersistBlockHeaders(ctx, b); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := cs.PersistTipset(ctx, ts); err != nil {
|
||||
return xerrors.Errorf("failed to persist tipset: %w", err)
|
||||
}
|
||||
|
||||
expanded, err := cs.expandTipset(ctx, ts.Blocks()[0])
|
||||
@@ -646,7 +645,7 @@ func (cs *ChainStore) takeHeaviestTipSet(ctx context.Context, ts *types.TipSet)
|
||||
|
||||
if err := cs.writeHead(ctx, ts); err != nil {
|
||||
log.Errorf("failed to write chain head: %s", err)
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -958,7 +957,24 @@ func (cs *ChainStore) AddToTipSetTracker(ctx context.Context, b *types.BlockHead
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cs *ChainStore) PersistBlockHeaders(ctx context.Context, b ...*types.BlockHeader) error {
|
||||
func (cs *ChainStore) PersistTipset(ctx context.Context, ts *types.TipSet) error {
|
||||
if err := cs.persistBlockHeaders(ctx, ts.Blocks()...); err != nil {
|
||||
return xerrors.Errorf("failed to persist block headers: %w", err)
|
||||
}
|
||||
|
||||
tsBlk, err := ts.Key().ToStorageBlock()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to get tipset key block: %w", err)
|
||||
}
|
||||
|
||||
if err = cs.chainLocalBlockstore.Put(ctx, tsBlk); err != nil {
|
||||
return xerrors.Errorf("failed to put tipset key block: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cs *ChainStore) persistBlockHeaders(ctx context.Context, b ...*types.BlockHeader) error {
|
||||
sbs := make([]block.Block, len(b))
|
||||
|
||||
for i, header := range b {
|
||||
@@ -1026,23 +1042,6 @@ func (cs *ChainStore) expandTipset(ctx context.Context, b *types.BlockHeader) (*
|
||||
return types.NewTipSet(all)
|
||||
}
|
||||
|
||||
func (cs *ChainStore) AddBlock(ctx context.Context, b *types.BlockHeader) error {
|
||||
if err := cs.PersistBlockHeaders(ctx, b); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ts, err := cs.expandTipset(ctx, b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := cs.MaybeTakeHeavierTipSet(ctx, ts); err != nil {
|
||||
return xerrors.Errorf("MaybeTakeHeavierTipSet failed: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cs *ChainStore) GetGenesis(ctx context.Context) (*types.BlockHeader, error) {
|
||||
data, err := cs.metadataDs.Get(ctx, dstore.NewKey("0"))
|
||||
if err != nil {
|
||||
@@ -1165,6 +1164,24 @@ func (cs *ChainStore) GetTipsetByHeight(ctx context.Context, h abi.ChainEpoch, t
|
||||
return cs.LoadTipSet(ctx, lbts.Parents())
|
||||
}
|
||||
|
||||
func (cs *ChainStore) GetTipSetByCid(ctx context.Context, c cid.Cid) (*types.TipSet, error) {
|
||||
blk, err := cs.chainBlockstore.Get(ctx, c)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("cannot find tipset with cid %s: %w", c, err)
|
||||
}
|
||||
|
||||
tsk := new(types.TipSetKey)
|
||||
if err := tsk.UnmarshalCBOR(bytes.NewReader(blk.RawData())); err != nil {
|
||||
return nil, xerrors.Errorf("cannot unmarshal block into tipset key: %w", err)
|
||||
}
|
||||
|
||||
ts, err := cs.GetTipSetFromKey(ctx, *tsk)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("cannot get tipset from key: %w", err)
|
||||
}
|
||||
return ts, nil
|
||||
}
|
||||
|
||||
func (cs *ChainStore) Weight(ctx context.Context, hts *types.TipSet) (types.BigInt, error) { // todo remove
|
||||
return cs.weight(ctx, cs.StateBlockstore(), hts)
|
||||
}
|
||||
|
||||
+7
-10
@@ -228,7 +228,7 @@ func (syncer *Syncer) InformNewHead(from peer.ID, fts *store.FullTipSet) bool {
|
||||
|
||||
// TODO: IMPORTANT(GARBAGE) this needs to be put in the 'temporary' side of
|
||||
// the blockstore
|
||||
if err := syncer.store.PersistBlockHeaders(ctx, fts.TipSet().Blocks()...); err != nil {
|
||||
if err := syncer.store.PersistTipset(ctx, fts.TipSet()); err != nil {
|
||||
log.Warn("failed to persist incoming block header: ", err)
|
||||
return false
|
||||
}
|
||||
@@ -1145,7 +1145,7 @@ func persistMessages(ctx context.Context, bs bstore.Blockstore, bst *exchange.Co
|
||||
}
|
||||
}
|
||||
for _, m := range bst.Secpk {
|
||||
if m.Signature.Type != crypto.SigTypeSecp256k1 {
|
||||
if m.Signature.Type != crypto.SigTypeSecp256k1 && m.Signature.Type != crypto.SigTypeDelegated {
|
||||
return xerrors.Errorf("unknown signature type on message %s: %q", m.Cid(), m.Signature.Type)
|
||||
}
|
||||
//log.Infof("putting secp256k1 message: %s", m.Cid())
|
||||
@@ -1198,16 +1198,13 @@ func (syncer *Syncer) collectChain(ctx context.Context, ts *types.TipSet, hts *t
|
||||
|
||||
ss.SetStage(api.StagePersistHeaders)
|
||||
|
||||
toPersist := make([]*types.BlockHeader, 0, len(headers)*int(build.BlocksPerEpoch))
|
||||
for _, ts := range headers {
|
||||
toPersist = append(toPersist, ts.Blocks()...)
|
||||
if err := syncer.store.PersistTipset(ctx, ts); err != nil {
|
||||
err = xerrors.Errorf("failed to persist synced tipset to the chainstore: %w", err)
|
||||
ss.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := syncer.store.PersistBlockHeaders(ctx, toPersist...); err != nil {
|
||||
err = xerrors.Errorf("failed to persist synced blocks to the chainstore: %w", err)
|
||||
ss.Error(err)
|
||||
return err
|
||||
}
|
||||
toPersist = nil
|
||||
|
||||
ss.SetStage(api.StageMessages)
|
||||
|
||||
|
||||
+5
-5
@@ -306,13 +306,13 @@ func (tu *syncTestUtil) addSourceNode(gen int) {
|
||||
require.NoError(tu.t, err)
|
||||
tu.t.Cleanup(func() { _ = stop(context.Background()) })
|
||||
|
||||
lastTs := blocks[len(blocks)-1].Blocks
|
||||
for _, lastB := range lastTs {
|
||||
cs := out.(*impl.FullNodeAPI).ChainAPI.Chain
|
||||
lastTs := blocks[len(blocks)-1]
|
||||
cs := out.(*impl.FullNodeAPI).ChainAPI.Chain
|
||||
for _, lastB := range lastTs.Blocks {
|
||||
require.NoError(tu.t, cs.AddToTipSetTracker(context.Background(), lastB.Header))
|
||||
err = cs.AddBlock(tu.ctx, lastB.Header)
|
||||
require.NoError(tu.t, err)
|
||||
}
|
||||
err = cs.PutTipSet(tu.ctx, lastTs.TipSet())
|
||||
require.NoError(tu.t, err)
|
||||
|
||||
tu.genesis = genesis
|
||||
tu.blocks = blocks
|
||||
|
||||
@@ -26,7 +26,7 @@ type ActorV5 struct {
|
||||
Head cid.Cid
|
||||
Nonce uint64
|
||||
Balance BigInt
|
||||
// Predictable Address
|
||||
// Deterministic Address.
|
||||
Address *address.Address
|
||||
}
|
||||
|
||||
|
||||
+221
-149
@@ -15,7 +15,6 @@ import (
|
||||
address "github.com/filecoin-project/go-address"
|
||||
abi "github.com/filecoin-project/go-state-types/abi"
|
||||
crypto "github.com/filecoin-project/go-state-types/crypto"
|
||||
exitcode "github.com/filecoin-project/go-state-types/exitcode"
|
||||
proof "github.com/filecoin-project/go-state-types/proof"
|
||||
)
|
||||
|
||||
@@ -1289,154 +1288,6 @@ func (t *ActorV5) UnmarshalCBOR(r io.Reader) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
var lengthBufMessageReceipt = []byte{131}
|
||||
|
||||
func (t *MessageReceipt) MarshalCBOR(w io.Writer) error {
|
||||
if t == nil {
|
||||
_, err := w.Write(cbg.CborNull)
|
||||
return err
|
||||
}
|
||||
|
||||
cw := cbg.NewCborWriter(w)
|
||||
|
||||
if _, err := cw.Write(lengthBufMessageReceipt); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.ExitCode (exitcode.ExitCode) (int64)
|
||||
if t.ExitCode >= 0 {
|
||||
if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.ExitCode)); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.ExitCode-1)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// t.Return ([]uint8) (slice)
|
||||
if len(t.Return) > cbg.ByteArrayMaxLen {
|
||||
return xerrors.Errorf("Byte array in field t.Return was too long")
|
||||
}
|
||||
|
||||
if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(t.Return))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := cw.Write(t.Return[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.GasUsed (int64) (int64)
|
||||
if t.GasUsed >= 0 {
|
||||
if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.GasUsed)); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.GasUsed-1)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *MessageReceipt) UnmarshalCBOR(r io.Reader) (err error) {
|
||||
*t = MessageReceipt{}
|
||||
|
||||
cr := cbg.NewCborReader(r)
|
||||
|
||||
maj, extra, err := cr.ReadHeader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err == io.EOF {
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
}()
|
||||
|
||||
if maj != cbg.MajArray {
|
||||
return fmt.Errorf("cbor input should be of type array")
|
||||
}
|
||||
|
||||
if extra != 3 {
|
||||
return fmt.Errorf("cbor input had wrong number of fields")
|
||||
}
|
||||
|
||||
// t.ExitCode (exitcode.ExitCode) (int64)
|
||||
{
|
||||
maj, extra, err := cr.ReadHeader()
|
||||
var extraI int64
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch maj {
|
||||
case cbg.MajUnsignedInt:
|
||||
extraI = int64(extra)
|
||||
if extraI < 0 {
|
||||
return fmt.Errorf("int64 positive overflow")
|
||||
}
|
||||
case cbg.MajNegativeInt:
|
||||
extraI = int64(extra)
|
||||
if extraI < 0 {
|
||||
return fmt.Errorf("int64 negative oveflow")
|
||||
}
|
||||
extraI = -1 - extraI
|
||||
default:
|
||||
return fmt.Errorf("wrong type for int64 field: %d", maj)
|
||||
}
|
||||
|
||||
t.ExitCode = exitcode.ExitCode(extraI)
|
||||
}
|
||||
// t.Return ([]uint8) (slice)
|
||||
|
||||
maj, extra, err = cr.ReadHeader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if extra > cbg.ByteArrayMaxLen {
|
||||
return fmt.Errorf("t.Return: byte array too large (%d)", extra)
|
||||
}
|
||||
if maj != cbg.MajByteString {
|
||||
return fmt.Errorf("expected byte array")
|
||||
}
|
||||
|
||||
if extra > 0 {
|
||||
t.Return = make([]uint8, extra)
|
||||
}
|
||||
|
||||
if _, err := io.ReadFull(cr, t.Return[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
// t.GasUsed (int64) (int64)
|
||||
{
|
||||
maj, extra, err := cr.ReadHeader()
|
||||
var extraI int64
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch maj {
|
||||
case cbg.MajUnsignedInt:
|
||||
extraI = int64(extra)
|
||||
if extraI < 0 {
|
||||
return fmt.Errorf("int64 positive overflow")
|
||||
}
|
||||
case cbg.MajNegativeInt:
|
||||
extraI = int64(extra)
|
||||
if extraI < 0 {
|
||||
return fmt.Errorf("int64 negative oveflow")
|
||||
}
|
||||
extraI = -1 - extraI
|
||||
default:
|
||||
return fmt.Errorf("wrong type for int64 field: %d", maj)
|
||||
}
|
||||
|
||||
t.GasUsed = int64(extraI)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var lengthBufBlockMsg = []byte{131}
|
||||
|
||||
func (t *BlockMsg) MarshalCBOR(w io.Writer) error {
|
||||
@@ -1986,3 +1837,224 @@ func (t *StateInfo0) UnmarshalCBOR(r io.Reader) (err error) {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var lengthBufEvent = []byte{130}
|
||||
|
||||
func (t *Event) MarshalCBOR(w io.Writer) error {
|
||||
if t == nil {
|
||||
_, err := w.Write(cbg.CborNull)
|
||||
return err
|
||||
}
|
||||
|
||||
cw := cbg.NewCborWriter(w)
|
||||
|
||||
if _, err := cw.Write(lengthBufEvent); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.Emitter (abi.ActorID) (uint64)
|
||||
|
||||
if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.Emitter)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.Entries ([]types.EventEntry) (slice)
|
||||
if len(t.Entries) > cbg.MaxLength {
|
||||
return xerrors.Errorf("Slice value in field t.Entries was too long")
|
||||
}
|
||||
|
||||
if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.Entries))); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, v := range t.Entries {
|
||||
if err := v.MarshalCBOR(cw); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Event) UnmarshalCBOR(r io.Reader) (err error) {
|
||||
*t = Event{}
|
||||
|
||||
cr := cbg.NewCborReader(r)
|
||||
|
||||
maj, extra, err := cr.ReadHeader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err == io.EOF {
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
}()
|
||||
|
||||
if maj != cbg.MajArray {
|
||||
return fmt.Errorf("cbor input should be of type array")
|
||||
}
|
||||
|
||||
if extra != 2 {
|
||||
return fmt.Errorf("cbor input had wrong number of fields")
|
||||
}
|
||||
|
||||
// t.Emitter (abi.ActorID) (uint64)
|
||||
|
||||
{
|
||||
|
||||
maj, extra, err = cr.ReadHeader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if maj != cbg.MajUnsignedInt {
|
||||
return fmt.Errorf("wrong type for uint64 field")
|
||||
}
|
||||
t.Emitter = abi.ActorID(extra)
|
||||
|
||||
}
|
||||
// t.Entries ([]types.EventEntry) (slice)
|
||||
|
||||
maj, extra, err = cr.ReadHeader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if extra > cbg.MaxLength {
|
||||
return fmt.Errorf("t.Entries: array too large (%d)", extra)
|
||||
}
|
||||
|
||||
if maj != cbg.MajArray {
|
||||
return fmt.Errorf("expected cbor array")
|
||||
}
|
||||
|
||||
if extra > 0 {
|
||||
t.Entries = make([]EventEntry, extra)
|
||||
}
|
||||
|
||||
for i := 0; i < int(extra); i++ {
|
||||
|
||||
var v EventEntry
|
||||
if err := v.UnmarshalCBOR(cr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.Entries[i] = v
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var lengthBufEventEntry = []byte{131}
|
||||
|
||||
func (t *EventEntry) MarshalCBOR(w io.Writer) error {
|
||||
if t == nil {
|
||||
_, err := w.Write(cbg.CborNull)
|
||||
return err
|
||||
}
|
||||
|
||||
cw := cbg.NewCborWriter(w)
|
||||
|
||||
if _, err := cw.Write(lengthBufEventEntry); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.Flags (uint8) (uint8)
|
||||
if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.Flags)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.Key (string) (string)
|
||||
if len(t.Key) > cbg.MaxLength {
|
||||
return xerrors.Errorf("Value in field t.Key was too long")
|
||||
}
|
||||
|
||||
if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Key))); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := io.WriteString(w, string(t.Key)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.Value ([]uint8) (slice)
|
||||
if len(t.Value) > cbg.ByteArrayMaxLen {
|
||||
return xerrors.Errorf("Byte array in field t.Value was too long")
|
||||
}
|
||||
|
||||
if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(t.Value))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := cw.Write(t.Value[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *EventEntry) UnmarshalCBOR(r io.Reader) (err error) {
|
||||
*t = EventEntry{}
|
||||
|
||||
cr := cbg.NewCborReader(r)
|
||||
|
||||
maj, extra, err := cr.ReadHeader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err == io.EOF {
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
}()
|
||||
|
||||
if maj != cbg.MajArray {
|
||||
return fmt.Errorf("cbor input should be of type array")
|
||||
}
|
||||
|
||||
if extra != 3 {
|
||||
return fmt.Errorf("cbor input had wrong number of fields")
|
||||
}
|
||||
|
||||
// t.Flags (uint8) (uint8)
|
||||
|
||||
maj, extra, err = cr.ReadHeader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if maj != cbg.MajUnsignedInt {
|
||||
return fmt.Errorf("wrong type for uint8 field")
|
||||
}
|
||||
if extra > math.MaxUint8 {
|
||||
return fmt.Errorf("integer in input was too large for uint8 field")
|
||||
}
|
||||
t.Flags = uint8(extra)
|
||||
// t.Key (string) (string)
|
||||
|
||||
{
|
||||
sval, err := cbg.ReadString(cr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.Key = string(sval)
|
||||
}
|
||||
// t.Value ([]uint8) (slice)
|
||||
|
||||
maj, extra, err = cr.ReadHeader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if extra > cbg.ByteArrayMaxLen {
|
||||
return fmt.Errorf("t.Value: byte array too large (%d)", extra)
|
||||
}
|
||||
if maj != cbg.MajByteString {
|
||||
return fmt.Errorf("expected byte array")
|
||||
}
|
||||
|
||||
if extra > 0 {
|
||||
t.Value = make([]uint8, extra)
|
||||
}
|
||||
|
||||
if _, err := io.ReadFull(cr, t.Value[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,595 @@
|
||||
package ethtypes
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
mathbig "math/big"
|
||||
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/crypto/sha3"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
gocrypto "github.com/filecoin-project/go-crypto"
|
||||
"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"
|
||||
typescrypto "github.com/filecoin-project/go-state-types/crypto"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
const Eip1559TxType = 2
|
||||
|
||||
type EthTx struct {
|
||||
ChainID EthUint64 `json:"chainId"`
|
||||
Nonce EthUint64 `json:"nonce"`
|
||||
Hash EthHash `json:"hash"`
|
||||
BlockHash *EthHash `json:"blockHash"`
|
||||
BlockNumber *EthUint64 `json:"blockNumber"`
|
||||
TransactionIndex *EthUint64 `json:"transactionIndex"`
|
||||
From EthAddress `json:"from"`
|
||||
To *EthAddress `json:"to"`
|
||||
Value EthBigInt `json:"value"`
|
||||
Type EthUint64 `json:"type"`
|
||||
Input EthBytes `json:"input"`
|
||||
Gas EthUint64 `json:"gas"`
|
||||
MaxFeePerGas EthBigInt `json:"maxFeePerGas"`
|
||||
MaxPriorityFeePerGas EthBigInt `json:"maxPriorityFeePerGas"`
|
||||
V EthBigInt `json:"v"`
|
||||
R EthBigInt `json:"r"`
|
||||
S EthBigInt `json:"s"`
|
||||
}
|
||||
|
||||
type EthTxArgs struct {
|
||||
ChainID int `json:"chainId"`
|
||||
Nonce int `json:"nonce"`
|
||||
To *EthAddress `json:"to"`
|
||||
Value big.Int `json:"value"`
|
||||
MaxFeePerGas big.Int `json:"maxFeePerGas"`
|
||||
MaxPriorityFeePerGas big.Int `json:"maxPriorityFeePerGas"`
|
||||
GasLimit int `json:"gasLimit"`
|
||||
Input []byte `json:"input"`
|
||||
V big.Int `json:"v"`
|
||||
R big.Int `json:"r"`
|
||||
S big.Int `json:"s"`
|
||||
}
|
||||
|
||||
func NewEthTxArgsFromMessage(msg *types.Message) (EthTxArgs, error) {
|
||||
var (
|
||||
to *EthAddress
|
||||
decodedParams []byte
|
||||
paramsReader = bytes.NewReader(msg.Params)
|
||||
)
|
||||
|
||||
if msg.To == builtintypes.EthereumAddressManagerActorAddr {
|
||||
switch msg.Method {
|
||||
case builtintypes.MethodsEAM.Create:
|
||||
var create eam.CreateParams
|
||||
if err := create.UnmarshalCBOR(paramsReader); err != nil {
|
||||
return EthTxArgs{}, err
|
||||
}
|
||||
decodedParams = create.Initcode
|
||||
case builtintypes.MethodsEAM.Create2:
|
||||
var create2 eam.Create2Params
|
||||
if err := create2.UnmarshalCBOR(paramsReader); err != nil {
|
||||
return EthTxArgs{}, err
|
||||
}
|
||||
decodedParams = create2.Initcode
|
||||
default:
|
||||
return EthTxArgs{}, fmt.Errorf("unsupported EAM method")
|
||||
}
|
||||
} else {
|
||||
addr, err := EthAddressFromFilecoinAddress(msg.To)
|
||||
if err != nil {
|
||||
return EthTxArgs{}, err
|
||||
}
|
||||
to = &addr
|
||||
|
||||
if len(msg.Params) > 0 {
|
||||
params, err := cbg.ReadByteArray(paramsReader, uint64(len(msg.Params)))
|
||||
if err != nil {
|
||||
return EthTxArgs{}, err
|
||||
}
|
||||
decodedParams = params
|
||||
}
|
||||
}
|
||||
|
||||
return EthTxArgs{
|
||||
ChainID: build.Eip155ChainId,
|
||||
Nonce: int(msg.Nonce),
|
||||
To: to,
|
||||
Value: msg.Value,
|
||||
Input: decodedParams,
|
||||
MaxFeePerGas: msg.GasFeeCap,
|
||||
MaxPriorityFeePerGas: msg.GasPremium,
|
||||
GasLimit: int(msg.GasLimit),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (tx *EthTxArgs) ToSignedMessage() (*types.SignedMessage, error) {
|
||||
from, err := tx.Sender()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var to address.Address
|
||||
var params []byte
|
||||
|
||||
if len(tx.To) == 0 && len(tx.Input) == 0 {
|
||||
return nil, fmt.Errorf("to and input cannot both be empty")
|
||||
}
|
||||
|
||||
var method abi.MethodNum
|
||||
if tx.To == nil {
|
||||
// TODO unify with applyEvmMsg
|
||||
|
||||
// this is a contract creation
|
||||
to = builtintypes.EthereumAddressManagerActorAddr
|
||||
|
||||
params2, err := actors.SerializeParams(&eam.CreateParams{
|
||||
Initcode: tx.Input,
|
||||
Nonce: uint64(tx.Nonce),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to serialize Create params: %w", err)
|
||||
}
|
||||
params = params2
|
||||
method = builtintypes.MethodsEAM.Create
|
||||
} else {
|
||||
addr, err := tx.To.ToFilecoinAddress()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
to = addr
|
||||
|
||||
if len(tx.Input) > 0 {
|
||||
var buf bytes.Buffer
|
||||
if err := cbg.WriteByteArray(&buf, tx.Input); err != nil {
|
||||
return nil, fmt.Errorf("failed to encode tx input into a cbor byte-string")
|
||||
}
|
||||
params = buf.Bytes()
|
||||
method = builtintypes.MethodsEVM.InvokeContract
|
||||
} else {
|
||||
method = builtintypes.MethodSend
|
||||
}
|
||||
}
|
||||
|
||||
msg := &types.Message{
|
||||
Nonce: uint64(tx.Nonce),
|
||||
From: from,
|
||||
To: to,
|
||||
Value: tx.Value,
|
||||
Method: method,
|
||||
Params: params,
|
||||
GasLimit: int64(tx.GasLimit),
|
||||
GasFeeCap: tx.MaxFeePerGas,
|
||||
GasPremium: tx.MaxPriorityFeePerGas,
|
||||
}
|
||||
|
||||
sig, err := tx.Signature()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
signedMsg := types.SignedMessage{
|
||||
Message: *msg,
|
||||
Signature: *sig,
|
||||
}
|
||||
return &signedMsg, nil
|
||||
|
||||
}
|
||||
|
||||
func (tx *EthTxArgs) HashedOriginalRlpMsg() ([]byte, error) {
|
||||
msg, err := tx.ToRlpUnsignedMsg()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hasher := sha3.NewLegacyKeccak256()
|
||||
hasher.Write(msg)
|
||||
hash := hasher.Sum(nil)
|
||||
return hash, nil
|
||||
}
|
||||
|
||||
func (tx *EthTxArgs) ToRlpUnsignedMsg() ([]byte, error) {
|
||||
packed, err := tx.packTxFields()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
encoded, err := EncodeRLP(packed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append([]byte{0x02}, encoded...), nil
|
||||
}
|
||||
|
||||
func (tx *EthTxArgs) ToRlpSignedMsg() ([]byte, error) {
|
||||
packed1, err := tx.packTxFields()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
packed2, err := tx.packSigFields()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
encoded, err := EncodeRLP(append(packed1, packed2...))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append([]byte{0x02}, encoded...), nil
|
||||
}
|
||||
|
||||
func (tx *EthTxArgs) packTxFields() ([]interface{}, error) {
|
||||
chainId, err := formatInt(tx.ChainID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nonce, err := formatInt(tx.Nonce)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
maxPriorityFeePerGas, err := formatBigInt(tx.MaxPriorityFeePerGas)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
maxFeePerGas, err := formatBigInt(tx.MaxFeePerGas)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gasLimit, err := formatInt(tx.GasLimit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
value, err := formatBigInt(tx.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := []interface{}{
|
||||
chainId,
|
||||
nonce,
|
||||
maxPriorityFeePerGas,
|
||||
maxFeePerGas,
|
||||
gasLimit,
|
||||
formatEthAddr(tx.To),
|
||||
value,
|
||||
tx.Input,
|
||||
[]interface{}{}, // access list
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (tx *EthTxArgs) packSigFields() ([]interface{}, error) {
|
||||
r, err := formatBigInt(tx.R)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s, err := formatBigInt(tx.S)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v, err := formatBigInt(tx.V)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := []interface{}{v, r, s}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (tx *EthTxArgs) Signature() (*typescrypto.Signature, error) {
|
||||
r := tx.R.Int.Bytes()
|
||||
s := tx.S.Int.Bytes()
|
||||
v := tx.V.Int.Bytes()
|
||||
|
||||
sig := append([]byte{}, padLeadingZeros(r, 32)...)
|
||||
sig = append(sig, padLeadingZeros(s, 32)...)
|
||||
if len(v) == 0 {
|
||||
sig = append(sig, 0)
|
||||
} else {
|
||||
sig = append(sig, v[0])
|
||||
}
|
||||
|
||||
if len(sig) != 65 {
|
||||
return nil, fmt.Errorf("signature is not 65 bytes")
|
||||
}
|
||||
return &typescrypto.Signature{
|
||||
Type: typescrypto.SigTypeDelegated, Data: sig,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (tx *EthTxArgs) Sender() (address.Address, error) {
|
||||
msg, err := tx.ToRlpUnsignedMsg()
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
hasher := sha3.NewLegacyKeccak256()
|
||||
hasher.Write(msg)
|
||||
hash := hasher.Sum(nil)
|
||||
|
||||
sig, err := tx.Signature()
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
pubk, err := gocrypto.EcRecover(hash, sig.Data)
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
ethAddr, err := EthAddressFromPubKey(pubk)
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
ea, err := CastEthAddress(ethAddr)
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
return ea.ToFilecoinAddress()
|
||||
}
|
||||
|
||||
func RecoverSignature(sig typescrypto.Signature) (r, s, v EthBigInt, err error) {
|
||||
if sig.Type != typescrypto.SigTypeDelegated {
|
||||
return EthBigIntZero, EthBigIntZero, EthBigIntZero, fmt.Errorf("RecoverSignature only supports Delegated signature")
|
||||
}
|
||||
|
||||
if len(sig.Data) != 65 {
|
||||
return EthBigIntZero, EthBigIntZero, EthBigIntZero, fmt.Errorf("signature should be 65 bytes long, but got %d bytes", len(sig.Data))
|
||||
}
|
||||
|
||||
r_, err := parseBigInt(sig.Data[0:32])
|
||||
if err != nil {
|
||||
return EthBigIntZero, EthBigIntZero, EthBigIntZero, fmt.Errorf("cannot parse r into EthBigInt")
|
||||
}
|
||||
|
||||
s_, err := parseBigInt(sig.Data[32:64])
|
||||
if err != nil {
|
||||
return EthBigIntZero, EthBigIntZero, EthBigIntZero, fmt.Errorf("cannot parse s into EthBigInt")
|
||||
}
|
||||
|
||||
v_, err := parseBigInt([]byte{sig.Data[64]})
|
||||
if err != nil {
|
||||
return EthBigIntZero, EthBigIntZero, EthBigIntZero, fmt.Errorf("cannot parse v into EthBigInt")
|
||||
}
|
||||
|
||||
return EthBigInt(r_), EthBigInt(s_), EthBigInt(v_), nil
|
||||
}
|
||||
|
||||
func parseEip1559Tx(data []byte) (*EthTxArgs, error) {
|
||||
if data[0] != 2 {
|
||||
return nil, fmt.Errorf("not an EIP-1559 transaction: first byte is not 2")
|
||||
}
|
||||
|
||||
d, err := DecodeRLP(data[1:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
decoded, ok := d.([]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("not an EIP-1559 transaction: decoded data is not a list")
|
||||
}
|
||||
|
||||
if len(decoded) != 12 {
|
||||
return nil, fmt.Errorf("not an EIP-1559 transaction: should have 12 elements in the rlp list")
|
||||
}
|
||||
|
||||
chainId, err := parseInt(decoded[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nonce, err := parseInt(decoded[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
maxPriorityFeePerGas, err := parseBigInt(decoded[2])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
maxFeePerGas, err := parseBigInt(decoded[3])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gasLimit, err := parseInt(decoded[4])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
to, err := parseEthAddr(decoded[5])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
value, err := parseBigInt(decoded[6])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
input, err := parseBytes(decoded[7])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
accessList, ok := decoded[8].([]interface{})
|
||||
if !ok || (ok && len(accessList) != 0) {
|
||||
return nil, fmt.Errorf("access list should be an empty list")
|
||||
}
|
||||
|
||||
r, err := parseBigInt(decoded[10])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s, err := parseBigInt(decoded[11])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v, err := parseBigInt(decoded[9])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// EIP-1559 and EIP-2930 transactions only support 0 or 1 for v
|
||||
// Legacy and EIP-155 transactions support other values
|
||||
// https://github.com/ethers-io/ethers.js/blob/56fabe987bb8c1e4891fdf1e5d3fe8a4c0471751/packages/transactions/src.ts/index.ts#L333
|
||||
if !v.Equals(big.NewInt(0)) && !v.Equals(big.NewInt(1)) {
|
||||
return nil, fmt.Errorf("EIP-1559 transactions only support 0 or 1 for v")
|
||||
}
|
||||
|
||||
args := EthTxArgs{
|
||||
ChainID: chainId,
|
||||
Nonce: nonce,
|
||||
To: to,
|
||||
MaxPriorityFeePerGas: maxPriorityFeePerGas,
|
||||
MaxFeePerGas: maxFeePerGas,
|
||||
GasLimit: gasLimit,
|
||||
Value: value,
|
||||
Input: input,
|
||||
V: v,
|
||||
R: r,
|
||||
S: s,
|
||||
}
|
||||
return &args, nil
|
||||
}
|
||||
|
||||
func ParseEthTxArgs(data []byte) (*EthTxArgs, error) {
|
||||
if len(data) == 0 {
|
||||
return nil, fmt.Errorf("empty data")
|
||||
}
|
||||
|
||||
if data[0] > 0x7f {
|
||||
// legacy transaction
|
||||
return nil, fmt.Errorf("legacy transaction is not supported")
|
||||
}
|
||||
|
||||
if data[0] == 1 {
|
||||
// EIP-2930
|
||||
return nil, fmt.Errorf("EIP-2930 transaction is not supported")
|
||||
}
|
||||
|
||||
if data[0] == Eip1559TxType {
|
||||
// EIP-1559
|
||||
return parseEip1559Tx(data)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("unsupported transaction type")
|
||||
}
|
||||
|
||||
func padLeadingZeros(data []byte, length int) []byte {
|
||||
if len(data) >= length {
|
||||
return data
|
||||
}
|
||||
zeros := make([]byte, length-len(data))
|
||||
return append(zeros, data...)
|
||||
}
|
||||
|
||||
func removeLeadingZeros(data []byte) []byte {
|
||||
firstNonZeroIndex := len(data)
|
||||
for i, b := range data {
|
||||
if b > 0 {
|
||||
firstNonZeroIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
return data[firstNonZeroIndex:]
|
||||
}
|
||||
|
||||
func formatInt(val int) ([]byte, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
err := binary.Write(buf, binary.BigEndian, int64(val))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return removeLeadingZeros(buf.Bytes()), nil
|
||||
}
|
||||
|
||||
func formatEthAddr(addr *EthAddress) []byte {
|
||||
if addr == nil {
|
||||
return nil
|
||||
}
|
||||
return addr[:]
|
||||
}
|
||||
|
||||
func formatBigInt(val big.Int) ([]byte, error) {
|
||||
b, err := val.Bytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return removeLeadingZeros(b), nil
|
||||
}
|
||||
|
||||
func parseInt(v interface{}) (int, error) {
|
||||
data, ok := v.([]byte)
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("cannot parse interface to int: input is not a byte array")
|
||||
}
|
||||
if len(data) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
if len(data) > 8 {
|
||||
return 0, fmt.Errorf("cannot parse interface to int: length is more than 8 bytes")
|
||||
}
|
||||
var value int64
|
||||
r := bytes.NewReader(append(make([]byte, 8-len(data)), data...))
|
||||
if err := binary.Read(r, binary.BigEndian, &value); err != nil {
|
||||
return 0, fmt.Errorf("cannot parse interface to EthUint64: %w", err)
|
||||
}
|
||||
return int(value), nil
|
||||
}
|
||||
|
||||
func parseBigInt(v interface{}) (big.Int, error) {
|
||||
data, ok := v.([]byte)
|
||||
if !ok {
|
||||
return big.Zero(), fmt.Errorf("cannot parse interface to big.Int: input is not a byte array")
|
||||
}
|
||||
if len(data) == 0 {
|
||||
return big.Zero(), nil
|
||||
}
|
||||
var b mathbig.Int
|
||||
b.SetBytes(data)
|
||||
return big.NewFromGo(&b), nil
|
||||
}
|
||||
|
||||
func parseBytes(v interface{}) ([]byte, error) {
|
||||
val, ok := v.([]byte)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("cannot parse interface into bytes: input is not a byte array")
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
func parseEthAddr(v interface{}) (*EthAddress, error) {
|
||||
b, err := parseBytes(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(b) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
addr, err := CastEthAddress(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &addr, nil
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,600 @@
|
||||
package ethtypes
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
mathbig "math/big"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/multiformats/go-multihash"
|
||||
"github.com/multiformats/go-varint"
|
||||
"golang.org/x/crypto/sha3"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"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/lotus/build"
|
||||
)
|
||||
|
||||
var (
|
||||
EthTopic1 = "topic1"
|
||||
EthTopic2 = "topic2"
|
||||
EthTopic3 = "topic3"
|
||||
EthTopic4 = "topic4"
|
||||
)
|
||||
|
||||
var ErrInvalidAddress = errors.New("invalid Filecoin Eth address")
|
||||
|
||||
type EthUint64 uint64
|
||||
|
||||
func (e EthUint64) MarshalJSON() ([]byte, error) {
|
||||
if e == 0 {
|
||||
return json.Marshal("0x0")
|
||||
}
|
||||
return json.Marshal(fmt.Sprintf("0x%x", e))
|
||||
}
|
||||
|
||||
func (e *EthUint64) UnmarshalJSON(b []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(b, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
parsedInt, err := strconv.ParseUint(strings.Replace(s, "0x", "", -1), 16, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eint := EthUint64(parsedInt)
|
||||
*e = eint
|
||||
return nil
|
||||
}
|
||||
|
||||
func EthUint64FromHex(s string) (EthUint64, error) {
|
||||
parsedInt, err := strconv.ParseUint(strings.Replace(s, "0x", "", -1), 16, 64)
|
||||
if err != nil {
|
||||
return EthUint64(0), err
|
||||
}
|
||||
return EthUint64(parsedInt), nil
|
||||
}
|
||||
|
||||
// EthBigInt represents a large integer whose zero value serializes to "0x0".
|
||||
type EthBigInt big.Int
|
||||
|
||||
var EthBigIntZero = EthBigInt{Int: big.Zero().Int}
|
||||
|
||||
func (e EthBigInt) MarshalJSON() ([]byte, error) {
|
||||
if e.Int == nil || e.Int.BitLen() == 0 {
|
||||
return json.Marshal("0x0")
|
||||
}
|
||||
return json.Marshal(fmt.Sprintf("0x%x", e.Int))
|
||||
}
|
||||
|
||||
func (e *EthBigInt) UnmarshalJSON(b []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(b, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
replaced := strings.Replace(s, "0x", "", -1)
|
||||
if len(replaced)%2 == 1 {
|
||||
replaced = "0" + replaced
|
||||
}
|
||||
|
||||
i := new(mathbig.Int)
|
||||
i.SetString(replaced, 16)
|
||||
|
||||
*e = EthBigInt(big.NewFromGo(i))
|
||||
return nil
|
||||
}
|
||||
|
||||
// EthBytes represent arbitrary bytes. A nil or empty slice serializes to "0x".
|
||||
type EthBytes []byte
|
||||
|
||||
func (e EthBytes) MarshalJSON() ([]byte, error) {
|
||||
if len(e) == 0 {
|
||||
return json.Marshal("0x")
|
||||
}
|
||||
s := hex.EncodeToString(e)
|
||||
return json.Marshal("0x" + s)
|
||||
}
|
||||
|
||||
func (e *EthBytes) UnmarshalJSON(b []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(b, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s = strings.Replace(s, "0x", "", -1)
|
||||
if len(s)%2 == 1 {
|
||||
s = "0" + s
|
||||
}
|
||||
|
||||
decoded, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*e = decoded
|
||||
return nil
|
||||
}
|
||||
|
||||
type EthBlock struct {
|
||||
Hash EthHash `json:"hash"`
|
||||
ParentHash EthHash `json:"parentHash"`
|
||||
Sha3Uncles EthHash `json:"sha3Uncles"`
|
||||
Miner EthAddress `json:"miner"`
|
||||
StateRoot EthHash `json:"stateRoot"`
|
||||
TransactionsRoot EthHash `json:"transactionsRoot"`
|
||||
ReceiptsRoot EthHash `json:"receiptsRoot"`
|
||||
LogsBloom EthBytes `json:"logsBloom"`
|
||||
Difficulty EthUint64 `json:"difficulty"`
|
||||
TotalDifficulty EthUint64 `json:"totalDifficulty"`
|
||||
Number EthUint64 `json:"number"`
|
||||
GasLimit EthUint64 `json:"gasLimit"`
|
||||
GasUsed EthUint64 `json:"gasUsed"`
|
||||
Timestamp EthUint64 `json:"timestamp"`
|
||||
Extradata []byte `json:"extraData"`
|
||||
MixHash EthHash `json:"mixHash"`
|
||||
Nonce EthNonce `json:"nonce"`
|
||||
BaseFeePerGas EthBigInt `json:"baseFeePerGas"`
|
||||
Size EthUint64 `json:"size"`
|
||||
// can be []EthTx or []string depending on query params
|
||||
Transactions []interface{} `json:"transactions"`
|
||||
Uncles []EthHash `json:"uncles"`
|
||||
}
|
||||
|
||||
var (
|
||||
EmptyEthBloom = [256]byte{}
|
||||
EmptyEthHash = EthHash{}
|
||||
EmptyEthInt = EthUint64(0)
|
||||
EmptyEthNonce = [8]byte{0, 0, 0, 0, 0, 0, 0, 0}
|
||||
)
|
||||
|
||||
func NewEthBlock() EthBlock {
|
||||
return EthBlock{
|
||||
Sha3Uncles: EmptyEthHash,
|
||||
StateRoot: EmptyEthHash,
|
||||
TransactionsRoot: EmptyEthHash,
|
||||
ReceiptsRoot: EmptyEthHash,
|
||||
Difficulty: EmptyEthInt,
|
||||
LogsBloom: EmptyEthBloom[:],
|
||||
Extradata: []byte{},
|
||||
MixHash: EmptyEthHash,
|
||||
Nonce: EmptyEthNonce,
|
||||
GasLimit: EthUint64(build.BlockGasLimit), // TODO we map Ethereum blocks to Filecoin tipsets; this is inconsistent.
|
||||
Uncles: []EthHash{},
|
||||
Transactions: []interface{}{},
|
||||
}
|
||||
}
|
||||
|
||||
type EthCall struct {
|
||||
From *EthAddress `json:"from"`
|
||||
To *EthAddress `json:"to"`
|
||||
Gas EthUint64 `json:"gas"`
|
||||
GasPrice EthBigInt `json:"gasPrice"`
|
||||
Value EthBigInt `json:"value"`
|
||||
Data EthBytes `json:"data"`
|
||||
}
|
||||
|
||||
func (c *EthCall) UnmarshalJSON(b []byte) error {
|
||||
type TempEthCall EthCall
|
||||
var params TempEthCall
|
||||
|
||||
if err := json.Unmarshal(b, ¶ms); err != nil {
|
||||
return err
|
||||
}
|
||||
*c = EthCall(params)
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
EthAddressLength = 20
|
||||
EthHashLength = 32
|
||||
)
|
||||
|
||||
type EthNonce [8]byte
|
||||
|
||||
func (n EthNonce) String() string {
|
||||
return "0x" + hex.EncodeToString(n[:])
|
||||
}
|
||||
|
||||
func (n EthNonce) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(n.String())
|
||||
}
|
||||
|
||||
func (n *EthNonce) UnmarshalJSON(b []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(b, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s = strings.Replace(s, "0x", "", -1)
|
||||
if len(s)%2 == 1 {
|
||||
s = "0" + s
|
||||
}
|
||||
|
||||
decoded, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
copy(n[:], decoded[:8])
|
||||
return nil
|
||||
}
|
||||
|
||||
type EthAddress [EthAddressLength]byte
|
||||
|
||||
// EthAddressFromPubKey returns the Ethereum address corresponding to an
|
||||
// uncompressed secp256k1 public key.
|
||||
func EthAddressFromPubKey(pubk []byte) ([]byte, error) {
|
||||
// if we get an uncompressed public key (that's what we get from the library,
|
||||
// but putting this check here for defensiveness), strip the prefix
|
||||
const pubKeyLen = 65
|
||||
if len(pubk) != pubKeyLen {
|
||||
return nil, fmt.Errorf("public key should have %d in length, but got %d", pubKeyLen, len(pubk))
|
||||
}
|
||||
if pubk[0] != 0x04 {
|
||||
return nil, fmt.Errorf("expected first byte of secp256k1 to be 0x04 (uncompressed)")
|
||||
}
|
||||
pubk = pubk[1:]
|
||||
|
||||
// Calculate the Ethereum address based on the keccak hash of the pubkey.
|
||||
hasher := sha3.NewLegacyKeccak256()
|
||||
hasher.Write(pubk)
|
||||
ethAddr := hasher.Sum(nil)[12:]
|
||||
return ethAddr, nil
|
||||
}
|
||||
|
||||
func EthAddressFromFilecoinAddress(addr address.Address) (EthAddress, error) {
|
||||
switch addr.Protocol() {
|
||||
case address.ID:
|
||||
id, err := address.IDFromAddress(addr)
|
||||
if err != nil {
|
||||
return EthAddress{}, err
|
||||
}
|
||||
var ethaddr EthAddress
|
||||
ethaddr[0] = 0xff
|
||||
binary.BigEndian.PutUint64(ethaddr[12:], id)
|
||||
return ethaddr, nil
|
||||
case address.Delegated:
|
||||
payload := addr.Payload()
|
||||
namespace, n, err := varint.FromUvarint(payload)
|
||||
if err != nil {
|
||||
return EthAddress{}, xerrors.Errorf("invalid delegated address namespace in: %s", addr)
|
||||
}
|
||||
payload = payload[n:]
|
||||
if namespace == builtintypes.EthereumAddressManagerActorID {
|
||||
return CastEthAddress(payload)
|
||||
}
|
||||
}
|
||||
return EthAddress{}, ErrInvalidAddress
|
||||
}
|
||||
|
||||
// ParseEthAddress parses an Ethereum address from a hex string.
|
||||
func ParseEthAddress(s string) (EthAddress, error) {
|
||||
b, err := decodeHexString(s, EthAddressLength)
|
||||
if err != nil {
|
||||
return EthAddress{}, err
|
||||
}
|
||||
var h EthAddress
|
||||
copy(h[EthAddressLength-len(b):], b)
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// CastEthAddress interprets bytes as an EthAddress, performing some basic checks.
|
||||
func CastEthAddress(b []byte) (EthAddress, error) {
|
||||
var a EthAddress
|
||||
if len(b) != EthAddressLength {
|
||||
return EthAddress{}, xerrors.Errorf("cannot parse bytes into an EthAddress: incorrect input length")
|
||||
}
|
||||
copy(a[:], b[:])
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func (ea EthAddress) String() string {
|
||||
return "0x" + hex.EncodeToString(ea[:])
|
||||
}
|
||||
|
||||
func (ea EthAddress) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(ea.String())
|
||||
}
|
||||
|
||||
func (ea *EthAddress) UnmarshalJSON(b []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(b, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
addr, err := ParseEthAddress(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
copy(ea[:], addr[:])
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ea EthAddress) IsMaskedID() bool {
|
||||
idmask := [12]byte{0xff}
|
||||
return bytes.Equal(ea[:12], idmask[:])
|
||||
}
|
||||
|
||||
func (ea EthAddress) ToFilecoinAddress() (address.Address, error) {
|
||||
if ea.IsMaskedID() {
|
||||
// This is a masked ID address.
|
||||
id := binary.BigEndian.Uint64(ea[12:])
|
||||
return address.NewIDAddress(id)
|
||||
}
|
||||
|
||||
// Otherwise, translate the address into an address controlled by the
|
||||
// Ethereum Address Manager.
|
||||
addr, err := address.NewDelegatedAddress(builtintypes.EthereumAddressManagerActorID, ea[:])
|
||||
if err != nil {
|
||||
return address.Undef, fmt.Errorf("failed to translate supplied address (%s) into a "+
|
||||
"Filecoin f4 address: %w", hex.EncodeToString(ea[:]), err)
|
||||
}
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
type EthHash [EthHashLength]byte
|
||||
|
||||
func (h EthHash) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(h.String())
|
||||
}
|
||||
|
||||
func (h *EthHash) UnmarshalJSON(b []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(b, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
hash, err := ParseEthHash(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
copy(h[:], hash[:])
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeHexString(s string, expectedLen int) ([]byte, error) {
|
||||
// Strip the leading 0x or 0X prefix since hex.DecodeString does not support it.
|
||||
if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") {
|
||||
s = s[2:]
|
||||
}
|
||||
// Sometimes clients will omit a leading zero in a byte; pad so we can decode correctly.
|
||||
if len(s)%2 == 1 {
|
||||
s = "0" + s
|
||||
}
|
||||
if len(s) != expectedLen*2 {
|
||||
return nil, xerrors.Errorf("expected hex string length sans prefix %d, got %d", expectedLen*2, len(s))
|
||||
}
|
||||
b, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("cannot parse hex value: %w", err)
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func EthHashFromCid(c cid.Cid) (EthHash, error) {
|
||||
return ParseEthHash(c.Hash().HexString()[8:])
|
||||
}
|
||||
|
||||
func ParseEthHash(s string) (EthHash, error) {
|
||||
b, err := decodeHexString(s, EthHashLength)
|
||||
if err != nil {
|
||||
return EthHash{}, err
|
||||
}
|
||||
var h EthHash
|
||||
copy(h[EthHashLength-len(b):], b)
|
||||
return h, nil
|
||||
}
|
||||
|
||||
func (h EthHash) String() string {
|
||||
return "0x" + hex.EncodeToString(h[:])
|
||||
}
|
||||
|
||||
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"`
|
||||
BaseFeePerGas []EthBigInt `json:"baseFeePerGas"`
|
||||
GasUsedRatio []float64 `json:"gasUsedRatio"`
|
||||
Reward *[][]EthBigInt `json:"reward,omitempty"`
|
||||
}
|
||||
|
||||
type EthFilterID EthHash
|
||||
|
||||
// An opaque identifier generated by the Lotus node to refer to an active subscription.
|
||||
type EthSubscriptionID EthHash
|
||||
|
||||
type EthFilterSpec struct {
|
||||
// Interpreted as an epoch or one of "latest" for last mined block, "earliest" for first,
|
||||
// "pending" for not yet committed messages.
|
||||
// Optional, default: "latest".
|
||||
FromBlock *string `json:"fromBlock,omitempty"`
|
||||
|
||||
// Interpreted as an epoch or one of "latest" for last mined block, "earliest" for first,
|
||||
// "pending" for not yet committed messages.
|
||||
// Optional, default: "latest".
|
||||
ToBlock *string `json:"toBlock,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"`
|
||||
|
||||
// List of topics to be matched.
|
||||
// Optional, default: empty list
|
||||
Topics EthTopicSpec `json:"topics"`
|
||||
|
||||
// Restricts event logs returned to those emitted from messages contained in this tipset.
|
||||
// If BlockHash is present in in the filter criteria, then neither FromBlock nor ToBlock are allowed.
|
||||
// Added in EIP-234
|
||||
BlockHash *EthHash `json:"blockHash,omitempty"`
|
||||
}
|
||||
|
||||
// EthAddressSpec represents a list of addresses.
|
||||
// The JSON decoding must treat a string as equivalent to an array with one value, for example
|
||||
// "0x8888f1f195afa192cfee86069858" must be decoded as [ "0x8888f1f195afa192cfee86069858" ]
|
||||
type EthAddressList []EthAddress
|
||||
|
||||
func (e *EthAddressList) UnmarshalJSON(b []byte) error {
|
||||
if bytes.Equal(b, []byte{'n', 'u', 'l', 'l'}) {
|
||||
return nil
|
||||
}
|
||||
if len(b) > 0 && b[0] == '[' {
|
||||
var addrs []EthAddress
|
||||
err := json.Unmarshal(b, &addrs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*e = addrs
|
||||
return nil
|
||||
}
|
||||
var addr EthAddress
|
||||
err := json.Unmarshal(b, &addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*e = []EthAddress{addr}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TopicSpec represents a specification for matching by topic. An empty spec means all topics
|
||||
// will be matched. Otherwise topics are matched conjunctively in the first dimension of the
|
||||
// slice and disjunctively in the second dimension. Topics are matched in order.
|
||||
// An event log with topics [A, B] will be matched by the following topic specs:
|
||||
// [] "all"
|
||||
// [[A]] "A in first position (and anything after)"
|
||||
// [nil, [B] ] "anything in first position AND B in second position (and anything after)"
|
||||
// [[A], [B]] "A in first position AND B in second position (and anything after)"
|
||||
// [[A, B], [A, B]] "(A OR B) in first position AND (A OR B) in second position (and anything after)"
|
||||
//
|
||||
// The JSON decoding must treat string values as equivalent to arrays with one value, for example
|
||||
// { "A", [ "B", "C" ] } must be decoded as [ [ A ], [ B, C ] ]
|
||||
type EthTopicSpec []EthHashList
|
||||
|
||||
// EthHashList represents a list of EthHashes.
|
||||
// The JSON decoding treats string values as equivalent to arrays with one value.
|
||||
type EthHashList []EthHash
|
||||
|
||||
func (e *EthHashList) UnmarshalJSON(b []byte) error {
|
||||
if bytes.Equal(b, []byte{'n', 'u', 'l', 'l'}) {
|
||||
return nil
|
||||
}
|
||||
if len(b) > 0 && b[0] == '[' {
|
||||
var hashes []EthHash
|
||||
err := json.Unmarshal(b, &hashes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*e = hashes
|
||||
return nil
|
||||
}
|
||||
var hash EthHash
|
||||
err := json.Unmarshal(b, &hash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*e = []EthHash{hash}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FilterResult represents the response from executing a filter: a list of block hashes, a list of transaction hashes
|
||||
// or a list of logs
|
||||
// This is a union type. Only one field will be populated.
|
||||
// The JSON encoding must produce an array of the populated field.
|
||||
type EthFilterResult struct {
|
||||
Results []interface{}
|
||||
}
|
||||
|
||||
func (h EthFilterResult) MarshalJSON() ([]byte, error) {
|
||||
if h.Results != nil {
|
||||
return json.Marshal(h.Results)
|
||||
}
|
||||
return []byte{'[', ']'}, nil
|
||||
}
|
||||
|
||||
func (h *EthFilterResult) UnmarshalJSON(b []byte) error {
|
||||
if bytes.Equal(b, []byte{'n', 'u', 'l', 'l'}) {
|
||||
return nil
|
||||
}
|
||||
err := json.Unmarshal(b, &h.Results)
|
||||
return err
|
||||
}
|
||||
|
||||
// EthLog represents the results of an event filter execution.
|
||||
type EthLog struct {
|
||||
// Address is the address of the actor that produced the event log.
|
||||
Address EthAddress `json:"address"`
|
||||
|
||||
// Data is the value of the event log, excluding topics
|
||||
Data EthBytes `json:"data"`
|
||||
|
||||
// List of topics associated with the event log.
|
||||
Topics []EthBytes `json:"topics"`
|
||||
|
||||
// Following fields are derived from the transaction containing the log
|
||||
|
||||
// Indicates whether the log was removed due to a chain reorganization.
|
||||
Removed bool `json:"removed"`
|
||||
|
||||
// LogIndex is the index of the event log in the sequence of events produced by the message execution.
|
||||
// (this is the index in the events AMT on the message receipt)
|
||||
LogIndex EthUint64 `json:"logIndex"`
|
||||
|
||||
// TransactionIndex is the index in the tipset of the transaction that produced the event log.
|
||||
// The index corresponds to the sequence of messages produced by ChainGetParentMessages
|
||||
TransactionIndex EthUint64 `json:"transactionIndex"`
|
||||
|
||||
// TransactionHash is the cid of the message that produced the event log.
|
||||
TransactionHash EthHash `json:"transactionHash"`
|
||||
|
||||
// BlockHash is the hash of the tipset containing the message that produced the log.
|
||||
BlockHash EthHash `json:"blockHash"`
|
||||
|
||||
// BlockNumber is the epoch of the tipset containing the message.
|
||||
BlockNumber EthUint64 `json:"blockNumber"`
|
||||
}
|
||||
|
||||
type EthSubscriptionParams struct {
|
||||
// List of topics to be matched.
|
||||
// Optional, default: empty list
|
||||
Topics EthTopicSpec `json:"topics,omitempty"`
|
||||
}
|
||||
|
||||
type EthSubscriptionResponse struct {
|
||||
// The persistent identifier for the subscription which can be used to unsubscribe.
|
||||
SubscriptionID EthSubscriptionID `json:"subscription"`
|
||||
|
||||
// The object matching the subscription. This may be a Block (tipset), a Transaction (message) or an EthLog
|
||||
Result interface{} `json:"result"`
|
||||
}
|
||||
|
||||
func GetContractEthAddressFromCode(sender EthAddress, salt [32]byte, initcode []byte) (EthAddress, error) {
|
||||
hasher := sha3.NewLegacyKeccak256()
|
||||
hasher.Write(initcode)
|
||||
inithash := hasher.Sum(nil)
|
||||
|
||||
hasher.Reset()
|
||||
hasher.Write([]byte{0xff})
|
||||
hasher.Write(sender[:])
|
||||
hasher.Write(salt[:])
|
||||
hasher.Write(inithash)
|
||||
|
||||
ethAddr, err := CastEthAddress(hasher.Sum(nil)[12:])
|
||||
if err != nil {
|
||||
return [20]byte{}, err
|
||||
}
|
||||
|
||||
return ethAddr, nil
|
||||
}
|
||||
@@ -0,0 +1,384 @@
|
||||
package ethtypes
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
)
|
||||
|
||||
type TestCase struct {
|
||||
Input interface{}
|
||||
Output interface{}
|
||||
}
|
||||
|
||||
func TestEthIntMarshalJSON(t *testing.T) {
|
||||
// https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding
|
||||
testcases := []TestCase{
|
||||
{EthUint64(0), []byte("\"0x0\"")},
|
||||
{EthUint64(65), []byte("\"0x41\"")},
|
||||
{EthUint64(1024), []byte("\"0x400\"")},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
j, err := tc.Input.(EthUint64).MarshalJSON()
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, j, tc.Output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEthIntUnmarshalJSON(t *testing.T) {
|
||||
testcases := []TestCase{
|
||||
{[]byte("\"0x0\""), EthUint64(0)},
|
||||
{[]byte("\"0x41\""), EthUint64(65)},
|
||||
{[]byte("\"0x400\""), EthUint64(1024)},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
var i EthUint64
|
||||
err := i.UnmarshalJSON(tc.Input.([]byte))
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, i, tc.Output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEthBigIntMarshalJSON(t *testing.T) {
|
||||
testcases := []TestCase{
|
||||
{EthBigInt(big.NewInt(0)), []byte("\"0x0\"")},
|
||||
{EthBigInt(big.NewInt(65)), []byte("\"0x41\"")},
|
||||
{EthBigInt(big.NewInt(1024)), []byte("\"0x400\"")},
|
||||
{EthBigInt(big.Int{}), []byte("\"0x0\"")},
|
||||
}
|
||||
for _, tc := range testcases {
|
||||
j, err := tc.Input.(EthBigInt).MarshalJSON()
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, j, tc.Output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEthBigIntUnmarshalJSON(t *testing.T) {
|
||||
testcases := []TestCase{
|
||||
{[]byte("\"0x0\""), EthBigInt(big.MustFromString("0"))},
|
||||
{[]byte("\"0x41\""), EthBigInt(big.MustFromString("65"))},
|
||||
{[]byte("\"0x400\""), EthBigInt(big.MustFromString("1024"))},
|
||||
{[]byte("\"0xff1000000000000000000000000\""), EthBigInt(big.MustFromString("323330131220712761719252861321216"))},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
var i EthBigInt
|
||||
err := i.UnmarshalJSON(tc.Input.([]byte))
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, i, tc.Output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEthHash(t *testing.T) {
|
||||
testcases := []string{
|
||||
`"0x013dbb9442ca9667baccc6230fcd5c1c4b2d4d2870f4bd20681d4d47cfd15184"`,
|
||||
`"0xab8653edf9f51785664a643b47605a7ba3d917b5339a0724e7642c114d0e4738"`,
|
||||
}
|
||||
|
||||
for _, hash := range testcases {
|
||||
var h EthHash
|
||||
err := h.UnmarshalJSON([]byte(hash))
|
||||
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, h.String(), strings.Replace(hash, `"`, "", -1))
|
||||
|
||||
c := h.ToCid()
|
||||
h1, err := EthHashFromCid(c)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, h, h1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEthAddr(t *testing.T) {
|
||||
testcases := []string{
|
||||
strings.ToLower(`"0xd4c5fb16488Aa48081296299d54b0c648C9333dA"`),
|
||||
strings.ToLower(`"0x2C2EC67e3e1FeA8e4A39601cB3A3Cd44f5fa830d"`),
|
||||
strings.ToLower(`"0x01184F793982104363F9a8a5845743f452dE0586"`),
|
||||
}
|
||||
|
||||
for _, addr := range testcases {
|
||||
var a EthAddress
|
||||
err := a.UnmarshalJSON([]byte(addr))
|
||||
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, a.String(), strings.Replace(addr, `"`, "", -1))
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseEthAddr(t *testing.T) {
|
||||
testcases := []uint64{
|
||||
1, 2, 3, 100, 101,
|
||||
}
|
||||
for _, id := range testcases {
|
||||
addr, err := address.NewIDAddress(id)
|
||||
require.Nil(t, err)
|
||||
|
||||
eaddr, err := EthAddressFromFilecoinAddress(addr)
|
||||
require.Nil(t, err)
|
||||
|
||||
faddr, err := eaddr.ToFilecoinAddress()
|
||||
require.Nil(t, err)
|
||||
|
||||
require.Equal(t, addr, faddr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalEthCall(t *testing.T) {
|
||||
data := `{"from":"0x4D6D86b31a112a05A473c4aE84afaF873f632325","to":"0xFe01CC39f5Ae8553D6914DBb9dC27D219fa22D7f","gas":"0x5","gasPrice":"0x6","value":"0x123","data":""}`
|
||||
|
||||
var c EthCall
|
||||
err := c.UnmarshalJSON([]byte(data))
|
||||
require.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestUnmarshalEthBytes(t *testing.T) {
|
||||
testcases := []string{
|
||||
`"0x00"`,
|
||||
strings.ToLower(`"0xd4c5fb16488Aa48081296299d54b0c648C9333dA"`),
|
||||
strings.ToLower(`"0x2C2EC67e3e1FeA8e4A39601cB3A3Cd44f5fa830d"`),
|
||||
strings.ToLower(`"0x01184F793982104363F9a8a5845743f452dE0586"`),
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
var s EthBytes
|
||||
err := s.UnmarshalJSON([]byte(tc))
|
||||
require.Nil(t, err)
|
||||
|
||||
data, err := s.MarshalJSON()
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, string(data), tc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEthFilterResultMarshalJSON(t *testing.T) {
|
||||
hash1, err := ParseEthHash("013dbb9442ca9667baccc6230fcd5c1c4b2d4d2870f4bd20681d4d47cfd15184")
|
||||
require.NoError(t, err, "eth hash")
|
||||
|
||||
hash2, err := ParseEthHash("ab8653edf9f51785664a643b47605a7ba3d917b5339a0724e7642c114d0e4738")
|
||||
require.NoError(t, err, "eth hash")
|
||||
|
||||
addr, err := ParseEthAddress("d4c5fb16488Aa48081296299d54b0c648C9333dA")
|
||||
require.NoError(t, err, "eth address")
|
||||
|
||||
log := EthLog{
|
||||
Removed: true,
|
||||
LogIndex: 5,
|
||||
TransactionIndex: 45,
|
||||
TransactionHash: hash1,
|
||||
BlockHash: hash2,
|
||||
BlockNumber: 53,
|
||||
Topics: []EthBytes{hash1[:]},
|
||||
Data: EthBytes(hash1[:]),
|
||||
Address: addr,
|
||||
}
|
||||
logjson, err := json.Marshal(log)
|
||||
require.NoError(t, err, "log json")
|
||||
|
||||
testcases := []struct {
|
||||
res EthFilterResult
|
||||
want string
|
||||
}{
|
||||
{
|
||||
res: EthFilterResult{},
|
||||
want: "[]",
|
||||
},
|
||||
|
||||
{
|
||||
res: EthFilterResult{
|
||||
Results: []any{hash1, hash2},
|
||||
},
|
||||
want: `["0x013dbb9442ca9667baccc6230fcd5c1c4b2d4d2870f4bd20681d4d47cfd15184","0xab8653edf9f51785664a643b47605a7ba3d917b5339a0724e7642c114d0e4738"]`,
|
||||
},
|
||||
|
||||
{
|
||||
res: EthFilterResult{
|
||||
Results: []any{hash1, hash2},
|
||||
},
|
||||
want: `["0x013dbb9442ca9667baccc6230fcd5c1c4b2d4d2870f4bd20681d4d47cfd15184","0xab8653edf9f51785664a643b47605a7ba3d917b5339a0724e7642c114d0e4738"]`,
|
||||
},
|
||||
|
||||
{
|
||||
res: EthFilterResult{
|
||||
Results: []any{log},
|
||||
},
|
||||
want: `[` + string(logjson) + `]`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
tc := tc
|
||||
t.Run("", func(t *testing.T) {
|
||||
data, err := json.Marshal(tc.res)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.want, string(data))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEthFilterSpecUnmarshalJSON(t *testing.T) {
|
||||
hash1, err := ParseEthHash("013dbb9442ca9667baccc6230fcd5c1c4b2d4d2870f4bd20681d4d47cfd15184")
|
||||
require.NoError(t, err, "eth hash")
|
||||
|
||||
hash2, err := ParseEthHash("ab8653edf9f51785664a643b47605a7ba3d917b5339a0724e7642c114d0e4738")
|
||||
require.NoError(t, err, "eth hash")
|
||||
|
||||
addr, err := ParseEthAddress("d4c5fb16488Aa48081296299d54b0c648C9333dA")
|
||||
require.NoError(t, err, "eth address")
|
||||
|
||||
pstring := func(s string) *string { return &s }
|
||||
phash := func(h EthHash) *EthHash { return &h }
|
||||
|
||||
testcases := []struct {
|
||||
input string
|
||||
want EthFilterSpec
|
||||
}{
|
||||
{
|
||||
input: `{"fromBlock":"latest"}`,
|
||||
want: EthFilterSpec{FromBlock: pstring("latest")},
|
||||
},
|
||||
{
|
||||
input: `{"toBlock":"pending"}`,
|
||||
want: EthFilterSpec{ToBlock: pstring("pending")},
|
||||
},
|
||||
{
|
||||
input: `{"address":["0xd4c5fb16488Aa48081296299d54b0c648C9333dA"]}`,
|
||||
want: EthFilterSpec{Address: EthAddressList{addr}},
|
||||
},
|
||||
{
|
||||
input: `{"address":"0xd4c5fb16488Aa48081296299d54b0c648C9333dA"}`,
|
||||
want: EthFilterSpec{Address: EthAddressList{addr}},
|
||||
},
|
||||
{
|
||||
input: `{"blockHash":"0x013dbb9442ca9667baccc6230fcd5c1c4b2d4d2870f4bd20681d4d47cfd15184"}`,
|
||||
want: EthFilterSpec{BlockHash: phash(hash1)},
|
||||
},
|
||||
{
|
||||
input: `{"topics":["0x013dbb9442ca9667baccc6230fcd5c1c4b2d4d2870f4bd20681d4d47cfd15184"]}`,
|
||||
want: EthFilterSpec{
|
||||
Topics: EthTopicSpec{
|
||||
{hash1},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: `{"topics":["0x013dbb9442ca9667baccc6230fcd5c1c4b2d4d2870f4bd20681d4d47cfd15184","0xab8653edf9f51785664a643b47605a7ba3d917b5339a0724e7642c114d0e4738"]}`,
|
||||
want: EthFilterSpec{
|
||||
Topics: EthTopicSpec{
|
||||
{hash1},
|
||||
{hash2},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: `{"topics":[null, ["0x013dbb9442ca9667baccc6230fcd5c1c4b2d4d2870f4bd20681d4d47cfd15184","0xab8653edf9f51785664a643b47605a7ba3d917b5339a0724e7642c114d0e4738"]]}`,
|
||||
want: EthFilterSpec{
|
||||
Topics: EthTopicSpec{
|
||||
nil,
|
||||
{hash1, hash2},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: `{"topics":[null, "0x013dbb9442ca9667baccc6230fcd5c1c4b2d4d2870f4bd20681d4d47cfd15184"]}`,
|
||||
want: EthFilterSpec{
|
||||
Topics: EthTopicSpec{
|
||||
nil,
|
||||
{hash1},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
var got EthFilterSpec
|
||||
err := json.Unmarshal([]byte(tc.input), &got)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEthAddressListUnmarshalJSON(t *testing.T) {
|
||||
addr1, err := ParseEthAddress("d4c5fb16488Aa48081296299d54b0c648C9333dA")
|
||||
require.NoError(t, err, "eth address")
|
||||
|
||||
addr2, err := ParseEthAddress("abbbfb16488Aa48081296299d54b0c648C9333dA")
|
||||
require.NoError(t, err, "eth address")
|
||||
|
||||
testcases := []struct {
|
||||
input string
|
||||
want EthAddressList
|
||||
}{
|
||||
{
|
||||
input: `["0xd4c5fb16488Aa48081296299d54b0c648C9333dA"]`,
|
||||
want: EthAddressList{addr1},
|
||||
},
|
||||
{
|
||||
input: `["0xd4c5fb16488Aa48081296299d54b0c648C9333dA","abbbfb16488Aa48081296299d54b0c648C9333dA"]`,
|
||||
want: EthAddressList{addr1, addr2},
|
||||
},
|
||||
{
|
||||
input: `"0xd4c5fb16488Aa48081296299d54b0c648C9333dA"`,
|
||||
want: EthAddressList{addr1},
|
||||
},
|
||||
{
|
||||
input: `[]`,
|
||||
want: EthAddressList{},
|
||||
},
|
||||
{
|
||||
input: `null`,
|
||||
want: EthAddressList(nil),
|
||||
},
|
||||
}
|
||||
for _, tc := range testcases {
|
||||
tc := tc
|
||||
t.Run("", func(t *testing.T) {
|
||||
var got EthAddressList
|
||||
err := json.Unmarshal([]byte(tc.input), &got)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEthHashListUnmarshalJSON(t *testing.T) {
|
||||
hash1, err := ParseEthHash("013dbb9442ca9667baccc6230fcd5c1c4b2d4d2870f4bd20681d4d47cfd15184")
|
||||
require.NoError(t, err, "eth hash")
|
||||
|
||||
hash2, err := ParseEthHash("ab8653edf9f51785664a643b47605a7ba3d917b5339a0724e7642c114d0e4738")
|
||||
require.NoError(t, err, "eth hash")
|
||||
|
||||
testcases := []struct {
|
||||
input string
|
||||
want *EthHashList
|
||||
}{
|
||||
{
|
||||
input: `["0x013dbb9442ca9667baccc6230fcd5c1c4b2d4d2870f4bd20681d4d47cfd15184"]`,
|
||||
want: &EthHashList{hash1},
|
||||
},
|
||||
{
|
||||
input: `["0x013dbb9442ca9667baccc6230fcd5c1c4b2d4d2870f4bd20681d4d47cfd15184","0xab8653edf9f51785664a643b47605a7ba3d917b5339a0724e7642c114d0e4738"]`,
|
||||
want: &EthHashList{hash1, hash2},
|
||||
},
|
||||
{
|
||||
input: `"0x013dbb9442ca9667baccc6230fcd5c1c4b2d4d2870f4bd20681d4d47cfd15184"`,
|
||||
want: &EthHashList{hash1},
|
||||
},
|
||||
{
|
||||
input: `null`,
|
||||
want: nil,
|
||||
},
|
||||
}
|
||||
for _, tc := range testcases {
|
||||
var got *EthHashList
|
||||
err := json.Unmarshal([]byte(tc.input), &got)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.want, got)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
package ethtypes
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
// maxListElements restricts the amount of RLP list elements we'll read.
|
||||
// The ETH API only ever reads EIP-1559 transactions, which are bounded by
|
||||
// 12 elements exactly, so we play it safe and set exactly that limit here.
|
||||
const maxListElements = 12
|
||||
|
||||
func EncodeRLP(val interface{}) ([]byte, error) {
|
||||
return encodeRLP(val)
|
||||
}
|
||||
|
||||
func encodeRLPListItems(list []interface{}) (result []byte, err error) {
|
||||
res := []byte{}
|
||||
for _, elem := range list {
|
||||
encoded, err := encodeRLP(elem)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res = append(res, encoded...)
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func encodeLength(length int) (lenInBytes []byte, err error) {
|
||||
if length == 0 {
|
||||
return nil, fmt.Errorf("cannot encode length: length should be larger than 0")
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
err = binary.Write(buf, binary.BigEndian, int64(length))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
firstNonZeroIndex := len(buf.Bytes()) - 1
|
||||
for i, b := range buf.Bytes() {
|
||||
if b != 0 {
|
||||
firstNonZeroIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
res := buf.Bytes()[firstNonZeroIndex:]
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func encodeRLP(val interface{}) ([]byte, error) {
|
||||
switch data := val.(type) {
|
||||
case []byte:
|
||||
if len(data) == 1 && data[0] <= 0x7f {
|
||||
return data, nil
|
||||
} else if len(data) <= 55 {
|
||||
prefix := byte(0x80 + len(data))
|
||||
return append([]byte{prefix}, data...), nil
|
||||
} else {
|
||||
lenInBytes, err := encodeLength(len(data))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
prefix := byte(0xb7 + len(lenInBytes))
|
||||
return append(
|
||||
[]byte{prefix},
|
||||
append(lenInBytes, data...)...,
|
||||
), nil
|
||||
}
|
||||
case []interface{}:
|
||||
encodedList, err := encodeRLPListItems(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(encodedList) <= 55 {
|
||||
prefix := byte(0xc0 + len(encodedList))
|
||||
return append(
|
||||
[]byte{prefix},
|
||||
encodedList...,
|
||||
), nil
|
||||
}
|
||||
lenInBytes, err := encodeLength(len(encodedList))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
prefix := byte(0xf7 + len(lenInBytes))
|
||||
return append(
|
||||
[]byte{prefix},
|
||||
append(lenInBytes, encodedList...)...,
|
||||
), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("input data should either be a list or a byte array")
|
||||
}
|
||||
}
|
||||
|
||||
func DecodeRLP(data []byte) (interface{}, error) {
|
||||
res, consumed, err := decodeRLP(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if consumed != len(data) {
|
||||
return nil, xerrors.Errorf("invalid rlp data: length %d, consumed %d", len(data), consumed)
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func decodeRLP(data []byte) (res interface{}, consumed int, err error) {
|
||||
if len(data) == 0 {
|
||||
return data, 0, xerrors.Errorf("invalid rlp data: data cannot be empty")
|
||||
}
|
||||
if data[0] >= 0xf8 {
|
||||
listLenInBytes := int(data[0]) - 0xf7
|
||||
listLen, err := decodeLength(data[1:], listLenInBytes)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if 1+listLenInBytes+listLen > len(data) {
|
||||
return nil, 0, xerrors.Errorf("invalid rlp data: out of bound while parsing list")
|
||||
}
|
||||
result, err := decodeListElems(data[1+listLenInBytes:], listLen)
|
||||
return result, 1 + listLenInBytes + listLen, err
|
||||
} else if data[0] >= 0xc0 {
|
||||
length := int(data[0]) - 0xc0
|
||||
result, err := decodeListElems(data[1:], length)
|
||||
return result, 1 + length, err
|
||||
} else if data[0] >= 0xb8 {
|
||||
strLenInBytes := int(data[0]) - 0xb7
|
||||
strLen, err := decodeLength(data[1:], strLenInBytes)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
totalLen := 1 + strLenInBytes + strLen
|
||||
if totalLen > len(data) {
|
||||
return nil, 0, xerrors.Errorf("invalid rlp data: out of bound while parsing string")
|
||||
}
|
||||
return data[1+strLenInBytes : totalLen], totalLen, nil
|
||||
} else if data[0] >= 0x80 {
|
||||
length := int(data[0]) - 0x80
|
||||
if 1+length > len(data) {
|
||||
return nil, 0, xerrors.Errorf("invalid rlp data: out of bound while parsing string")
|
||||
}
|
||||
return data[1 : 1+length], 1 + length, nil
|
||||
}
|
||||
return []byte{data[0]}, 1, nil
|
||||
}
|
||||
|
||||
func decodeLength(data []byte, lenInBytes int) (length int, err error) {
|
||||
if lenInBytes > len(data) || lenInBytes > 8 {
|
||||
return 0, xerrors.Errorf("invalid rlp data: out of bound while parsing list length")
|
||||
}
|
||||
var decodedLength int64
|
||||
r := bytes.NewReader(append(make([]byte, 8-lenInBytes), data[:lenInBytes]...))
|
||||
if err := binary.Read(r, binary.BigEndian, &decodedLength); err != nil {
|
||||
return 0, xerrors.Errorf("invalid rlp data: cannot parse string length: %w", err)
|
||||
}
|
||||
if lenInBytes+int(decodedLength) > len(data) {
|
||||
return 0, xerrors.Errorf("invalid rlp data: out of bound while parsing list")
|
||||
}
|
||||
return int(decodedLength), nil
|
||||
}
|
||||
|
||||
func decodeListElems(data []byte, length int) (res []interface{}, err error) {
|
||||
totalConsumed := 0
|
||||
result := []interface{}{}
|
||||
|
||||
for i := 0; totalConsumed < length && i < maxListElements; i++ {
|
||||
elem, consumed, err := decodeRLP(data[totalConsumed:])
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("invalid rlp data: cannot decode list element: %w", err)
|
||||
}
|
||||
totalConsumed += consumed
|
||||
result = append(result, elem)
|
||||
}
|
||||
if totalConsumed != length {
|
||||
return nil, xerrors.Errorf("invalid rlp data: incorrect list length")
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
package ethtypes
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
)
|
||||
|
||||
func TestEncode(t *testing.T) {
|
||||
testcases := []TestCase{
|
||||
{[]byte(""), mustDecodeHex("0x80")},
|
||||
{mustDecodeHex("0x01"), mustDecodeHex("0x01")},
|
||||
{mustDecodeHex("0xaa"), mustDecodeHex("0x81aa")},
|
||||
{mustDecodeHex("0x0402"), mustDecodeHex("0x820402")},
|
||||
{
|
||||
[]interface{}{},
|
||||
mustDecodeHex("0xc0"),
|
||||
},
|
||||
{
|
||||
mustDecodeHex("0xabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"),
|
||||
mustDecodeHex("0xb83cabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"),
|
||||
},
|
||||
{
|
||||
mustDecodeHex("0xabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"),
|
||||
mustDecodeHex("0xb8aaabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"),
|
||||
},
|
||||
{
|
||||
[]interface{}{
|
||||
mustDecodeHex("0xaaaa"),
|
||||
mustDecodeHex("0xbbbb"),
|
||||
mustDecodeHex("0xcccc"),
|
||||
mustDecodeHex("0xdddd"),
|
||||
},
|
||||
mustDecodeHex("0xcc82aaaa82bbbb82cccc82dddd"),
|
||||
},
|
||||
{
|
||||
[]interface{}{
|
||||
mustDecodeHex("0xaaaaaaaaaaaaaaaaaaaa"),
|
||||
mustDecodeHex("0xbbbbbbbbbbbbbbbbbbbb"),
|
||||
[]interface{}{
|
||||
mustDecodeHex("0xc1c1c1c1c1c1c1c1c1c1"),
|
||||
mustDecodeHex("0xc2c2c2c2c2c2c2c2c2c2"),
|
||||
mustDecodeHex("0xc3c3c3c3c3c3c3c3c3c3"),
|
||||
},
|
||||
mustDecodeHex("0xdddddddddddddddddddd"),
|
||||
mustDecodeHex("0xeeeeeeeeeeeeeeeeeeee"),
|
||||
mustDecodeHex("0xffffffffffffffffffff"),
|
||||
},
|
||||
mustDecodeHex("0xf8598aaaaaaaaaaaaaaaaaaaaa8abbbbbbbbbbbbbbbbbbbbe18ac1c1c1c1c1c1c1c1c1c18ac2c2c2c2c2c2c2c2c2c28ac3c3c3c3c3c3c3c3c3c38adddddddddddddddddddd8aeeeeeeeeeeeeeeeeeeee8affffffffffffffffffff"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
result, err := EncodeRLP(tc.Input)
|
||||
require.Nil(t, err)
|
||||
|
||||
require.Equal(t, tc.Output.([]byte), result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeString(t *testing.T) {
|
||||
testcases := []TestCase{
|
||||
{"0x00", "0x00"},
|
||||
{"0x80", "0x"},
|
||||
{"0x0f", "0x0f"},
|
||||
{"0x81aa", "0xaa"},
|
||||
{"0x820400", "0x0400"},
|
||||
{"0xb83cabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd",
|
||||
"0xabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
input, err := hex.DecodeString(strings.Replace(tc.Input.(string), "0x", "", -1))
|
||||
require.Nil(t, err)
|
||||
|
||||
output, err := hex.DecodeString(strings.Replace(tc.Output.(string), "0x", "", -1))
|
||||
require.Nil(t, err)
|
||||
|
||||
result, err := DecodeRLP(input)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, output, result.([]byte))
|
||||
}
|
||||
}
|
||||
|
||||
func mustDecodeHex(s string) []byte {
|
||||
d, err := hex.DecodeString(strings.Replace(s, "0x", "", -1))
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("err must be nil: %w", err))
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func TestDecodeList(t *testing.T) {
|
||||
testcases := []TestCase{
|
||||
{"0xc0", []interface{}{}},
|
||||
{"0xc100", []interface{}{[]byte{0}}},
|
||||
{"0xc3000102", []interface{}{[]byte{0}, []byte{1}, []byte{2}}},
|
||||
{"0xc4000181aa", []interface{}{[]byte{0}, []byte{1}, []byte{0xaa}}},
|
||||
{"0xc6000181aa81ff", []interface{}{[]byte{0}, []byte{1}, []byte{0xaa}, []byte{0xff}}},
|
||||
{"0xf8428aabcdabcdabcdabcdabcd8aabcdabcdabcdabcdabcd8aabcdabcdabcdabcdabcd8aabcdabcdabcdabcdabcd8aabcdabcdabcdabcdabcd8aabcdabcdabcdabcdabcd",
|
||||
[]interface{}{
|
||||
mustDecodeHex("0xabcdabcdabcdabcdabcd"),
|
||||
mustDecodeHex("0xabcdabcdabcdabcdabcd"),
|
||||
mustDecodeHex("0xabcdabcdabcdabcdabcd"),
|
||||
mustDecodeHex("0xabcdabcdabcdabcdabcd"),
|
||||
mustDecodeHex("0xabcdabcdabcdabcdabcd"),
|
||||
mustDecodeHex("0xabcdabcdabcdabcdabcd"),
|
||||
},
|
||||
},
|
||||
{"0xf1030185012a05f2008504a817c800825208942b87d1cb599bc2a606db9a0169fcec96af04ad3a880de0b6b3a764000080c0",
|
||||
[]interface{}{
|
||||
[]byte{3},
|
||||
[]byte{1},
|
||||
mustDecodeHex("0x012a05f200"),
|
||||
mustDecodeHex("0x04a817c800"),
|
||||
mustDecodeHex("0x5208"),
|
||||
mustDecodeHex("0x2b87d1CB599Bc2a606Db9A0169fcEc96Af04ad3a"),
|
||||
mustDecodeHex("0x0de0b6b3a7640000"),
|
||||
[]byte{},
|
||||
[]interface{}{},
|
||||
}},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
input, err := hex.DecodeString(strings.Replace(tc.Input.(string), "0x", "", -1))
|
||||
require.Nil(t, err)
|
||||
|
||||
result, err := DecodeRLP(input)
|
||||
require.Nil(t, err)
|
||||
|
||||
fmt.Println(result)
|
||||
r := result.([]interface{})
|
||||
require.Equal(t, len(tc.Output.([]interface{})), len(r))
|
||||
|
||||
for i, v := range r {
|
||||
require.Equal(t, tc.Output.([]interface{})[i], v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeEncodeTx(t *testing.T) {
|
||||
testcases := [][]byte{
|
||||
mustDecodeHex("0xdc82013a0185012a05f2008504a817c8008080872386f26fc1000000c0"),
|
||||
mustDecodeHex("0xf85f82013a0185012a05f2008504a817c8008080872386f26fc1000000c001a027fa36fb9623e4d71fcdd7f7dce71eb814c9560dcf3908c1719386e2efd122fba05fb4e4227174eeb0ba84747a4fb883c8d4e0fdb129c4b1f42e90282c41480234"),
|
||||
mustDecodeHex("0xf9061c82013a0185012a05f2008504a817c8008080872386f26fc10000b905bb608060405234801561001057600080fd5b506127106000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610556806100656000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80637bd703e81461004657806390b98a1114610076578063f8b2cb4f146100a6575b600080fd5b610060600480360381019061005b919061030a565b6100d6565b60405161006d9190610350565b60405180910390f35b610090600480360381019061008b9190610397565b6100f4565b60405161009d91906103f2565b60405180910390f35b6100c060048036038101906100bb919061030a565b61025f565b6040516100cd9190610350565b60405180910390f35b600060026100e38361025f565b6100ed919061043c565b9050919050565b6000816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156101455760009050610259565b816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546101939190610496565b92505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546101e891906104ca565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161024c9190610350565b60405180910390a3600190505b92915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102d7826102ac565b9050919050565b6102e7816102cc565b81146102f257600080fd5b50565b600081359050610304816102de565b92915050565b6000602082840312156103205761031f6102a7565b5b600061032e848285016102f5565b91505092915050565b6000819050919050565b61034a81610337565b82525050565b60006020820190506103656000830184610341565b92915050565b61037481610337565b811461037f57600080fd5b50565b6000813590506103918161036b565b92915050565b600080604083850312156103ae576103ad6102a7565b5b60006103bc858286016102f5565b92505060206103cd85828601610382565b9150509250929050565b60008115159050919050565b6103ec816103d7565b82525050565b600060208201905061040760008301846103e3565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061044782610337565b915061045283610337565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561048b5761048a61040d565b5b828202905092915050565b60006104a182610337565b91506104ac83610337565b9250828210156104bf576104be61040d565b5b828203905092915050565b60006104d582610337565b91506104e083610337565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156105155761051461040d565b5b82820190509291505056fea26469706673582212208e5b4b874c839967f88008ed2fa42d6c2d9c9b0ae05d1d2c61faa7d229c134e664736f6c634300080d0033c080a0c4e9477f57c6848b2f1ea73a14809c1f44529d20763c947f3ac8ffd3d1629d93a011485a215457579bb13ac7b53bb9d6804763ae6fe5ce8ddd41642cea55c9a09a"),
|
||||
mustDecodeHex("0xf9063082013a0185012a05f2008504a817c8008094025b594a4f1c4888cafcfaf2bb24ed95507749e0872386f26fc10000b905bb608060405234801561001057600080fd5b506127106000803273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610556806100656000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80637bd703e81461004657806390b98a1114610076578063f8b2cb4f146100a6575b600080fd5b610060600480360381019061005b919061030a565b6100d6565b60405161006d9190610350565b60405180910390f35b610090600480360381019061008b9190610397565b6100f4565b60405161009d91906103f2565b60405180910390f35b6100c060048036038101906100bb919061030a565b61025f565b6040516100cd9190610350565b60405180910390f35b600060026100e38361025f565b6100ed919061043c565b9050919050565b6000816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156101455760009050610259565b816000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546101939190610496565b92505081905550816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546101e891906104ca565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161024c9190610350565b60405180910390a3600190505b92915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102d7826102ac565b9050919050565b6102e7816102cc565b81146102f257600080fd5b50565b600081359050610304816102de565b92915050565b6000602082840312156103205761031f6102a7565b5b600061032e848285016102f5565b91505092915050565b6000819050919050565b61034a81610337565b82525050565b60006020820190506103656000830184610341565b92915050565b61037481610337565b811461037f57600080fd5b50565b6000813590506103918161036b565b92915050565b600080604083850312156103ae576103ad6102a7565b5b60006103bc858286016102f5565b92505060206103cd85828601610382565b9150509250929050565b60008115159050919050565b6103ec816103d7565b82525050565b600060208201905061040760008301846103e3565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061044782610337565b915061045283610337565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561048b5761048a61040d565b5b828202905092915050565b60006104a182610337565b91506104ac83610337565b9250828210156104bf576104be61040d565b5b828203905092915050565b60006104d582610337565b91506104e083610337565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156105155761051461040d565b5b82820190509291505056fea26469706673582212208e5b4b874c839967f88008ed2fa42d6c2d9c9b0ae05d1d2c61faa7d229c134e664736f6c634300080d0033c080a0fe38720928596f9e9dfbf891d00311638efce3713f03cdd67b212ecbbcf18f29a05993e656c0b35b8a580da6aff7c89b3d3e8b1c6f83a7ce09473c0699a8500b9c"),
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
decoded, err := DecodeRLP(tc)
|
||||
require.Nil(t, err)
|
||||
|
||||
encoded, err := EncodeRLP(decoded)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, tc, encoded)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeError(t *testing.T) {
|
||||
testcases := [][]byte{
|
||||
mustDecodeHex("0xdc82013a0185012a05f2008504a817c8008080872386f26fc1000000"),
|
||||
mustDecodeHex("0xdc013a01012a05f2008504a817c8008080872386f26fc1000000"),
|
||||
mustDecodeHex("0xdc82013a0185012a05f28504a817c08080872386f26fc1000000"),
|
||||
mustDecodeHex("0xdc82013a0185012a05f504a817c080872386ffc1000000"),
|
||||
mustDecodeHex("0x013a018505f2008504a817c8008080872386f26fc1000000"),
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
_, err := DecodeRLP(tc)
|
||||
require.NotNil(t, err, hex.EncodeToString(tc))
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecode1(t *testing.T) {
|
||||
b := mustDecodeHex("0x02f8758401df5e7680832c8411832c8411830767f89452963ef50e27e06d72d59fcb4f3c2a687be3cfef880de0b6b3a764000080c080a094b11866f453ad85a980e0e8a2fc98cbaeb4409618c7734a7e12ae2f66fd405da042dbfb1b37af102023830ceeee0e703ffba0b8b3afeb8fe59f405eca9ed61072")
|
||||
decoded, err := ParseEthTxArgs(b)
|
||||
require.NoError(t, err)
|
||||
|
||||
sender, err := decoded.Sender()
|
||||
require.NoError(t, err)
|
||||
|
||||
addr, err := address.NewFromString("f410fkkld55ioe7qg24wvt7fu6pbknb56ht7pt4zamxa")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, sender, addr)
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
)
|
||||
|
||||
type Event struct {
|
||||
// The ID of the actor that emitted this event.
|
||||
Emitter abi.ActorID
|
||||
|
||||
// Key values making up this event.
|
||||
Entries []EventEntry
|
||||
}
|
||||
|
||||
type EventEntry struct {
|
||||
// A bitmap conveying metadata or hints about this entry.
|
||||
Flags uint8
|
||||
|
||||
// The key of this event entry
|
||||
Key string
|
||||
|
||||
// Any DAG-CBOR encodeable type.
|
||||
Value []byte
|
||||
}
|
||||
|
||||
type FilterID [32]byte // compatible with EthHash
|
||||
|
||||
// EventEntry flags defined in fvm_shared
|
||||
const (
|
||||
EventFlagIndexedKey = 0b00000001
|
||||
EventFlagIndexedValue = 0b00000010
|
||||
)
|
||||
@@ -39,6 +39,8 @@ func (kt *KeyType) UnmarshalJSON(bb []byte) error {
|
||||
*kt = KTBLS
|
||||
case crypto.SigTypeSecp256k1:
|
||||
*kt = KTSecp256k1
|
||||
case crypto.SigTypeDelegated:
|
||||
*kt = KTDelegated
|
||||
default:
|
||||
return fmt.Errorf("unknown sigtype: %d", bst)
|
||||
}
|
||||
@@ -51,6 +53,7 @@ const (
|
||||
KTBLS KeyType = "bls"
|
||||
KTSecp256k1 KeyType = "secp256k1"
|
||||
KTSecp256k1Ledger KeyType = "secp256k1-ledger"
|
||||
KTDelegated KeyType = "delegated"
|
||||
)
|
||||
|
||||
// KeyInfo is used for storing keys in KeyStore
|
||||
|
||||
@@ -3,15 +3,59 @@ package types
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/exitcode"
|
||||
)
|
||||
|
||||
type MessageReceiptVersion byte
|
||||
|
||||
const (
|
||||
// MessageReceiptV0 refers to pre FIP-0049 receipts.
|
||||
MessageReceiptV0 MessageReceiptVersion = 0
|
||||
// MessageReceiptV1 refers to post FIP-0049 receipts.
|
||||
MessageReceiptV1 MessageReceiptVersion = 1
|
||||
)
|
||||
|
||||
const EventAMTBitwidth = 5
|
||||
|
||||
type MessageReceipt struct {
|
||||
ExitCode exitcode.ExitCode
|
||||
Return []byte
|
||||
GasUsed int64
|
||||
version MessageReceiptVersion
|
||||
|
||||
ExitCode exitcode.ExitCode
|
||||
Return []byte
|
||||
GasUsed int64
|
||||
EventsRoot *cid.Cid // Root of Event AMT with bitwidth = EventAMTBitwidth
|
||||
}
|
||||
|
||||
// NewMessageReceiptV0 creates a new pre FIP-0049 receipt with no capability to
|
||||
// convey events.
|
||||
func NewMessageReceiptV0(exitcode exitcode.ExitCode, ret []byte, gasUsed int64) MessageReceipt {
|
||||
return MessageReceipt{
|
||||
version: MessageReceiptV0,
|
||||
ExitCode: exitcode,
|
||||
Return: ret,
|
||||
GasUsed: gasUsed,
|
||||
}
|
||||
}
|
||||
|
||||
// NewMessageReceiptV1 creates a new pre FIP-0049 receipt with the ability to
|
||||
// convey events.
|
||||
func NewMessageReceiptV1(exitcode exitcode.ExitCode, ret []byte, gasUsed int64, eventsRoot *cid.Cid) MessageReceipt {
|
||||
return MessageReceipt{
|
||||
version: MessageReceiptV1,
|
||||
ExitCode: exitcode,
|
||||
Return: ret,
|
||||
GasUsed: gasUsed,
|
||||
EventsRoot: eventsRoot,
|
||||
}
|
||||
}
|
||||
|
||||
func (mr *MessageReceipt) Version() MessageReceiptVersion {
|
||||
return mr.version
|
||||
}
|
||||
|
||||
func (mr *MessageReceipt) Equals(o *MessageReceipt) bool {
|
||||
return mr.ExitCode == o.ExitCode && bytes.Equal(mr.Return, o.Return) && mr.GasUsed == o.GasUsed
|
||||
return mr.version == o.version && mr.ExitCode == o.ExitCode && bytes.Equal(mr.Return, o.Return) && mr.GasUsed == o.GasUsed &&
|
||||
(mr.EventsRoot == o.EventsRoot || (mr.EventsRoot != nil && o.EventsRoot != nil && *mr.EventsRoot == *o.EventsRoot))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,359 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/cbor"
|
||||
"github.com/filecoin-project/go-state-types/exitcode"
|
||||
)
|
||||
|
||||
// This file contains custom CBOR serde logic to deal with the new versioned
|
||||
// MessageReceipt resulting from the introduction of actor events (FIP-0049).
|
||||
|
||||
type messageReceiptV0 struct{ *MessageReceipt }
|
||||
|
||||
type messageReceiptV1 struct{ *MessageReceipt }
|
||||
|
||||
func (mr *MessageReceipt) MarshalCBOR(w io.Writer) error {
|
||||
if mr == nil {
|
||||
_, err := w.Write(cbg.CborNull)
|
||||
return err
|
||||
}
|
||||
|
||||
var m cbor.Marshaler
|
||||
switch mr.version {
|
||||
case MessageReceiptV0:
|
||||
m = &messageReceiptV0{mr}
|
||||
case MessageReceiptV1:
|
||||
m = &messageReceiptV1{mr}
|
||||
default:
|
||||
return xerrors.Errorf("invalid message receipt version: %d", mr.version)
|
||||
}
|
||||
|
||||
return m.MarshalCBOR(w)
|
||||
}
|
||||
|
||||
func (mr *MessageReceipt) UnmarshalCBOR(r io.Reader) (err error) {
|
||||
*mr = MessageReceipt{}
|
||||
|
||||
cr := cbg.NewCborReader(r)
|
||||
|
||||
maj, extra, err := cr.ReadHeader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err == io.EOF {
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
}()
|
||||
|
||||
if maj != cbg.MajArray {
|
||||
return fmt.Errorf("cbor input should be of type array")
|
||||
}
|
||||
|
||||
var u cbor.Unmarshaler
|
||||
switch extra {
|
||||
case 3:
|
||||
mr.version = MessageReceiptV0
|
||||
u = &messageReceiptV0{mr}
|
||||
case 4:
|
||||
mr.version = MessageReceiptV1
|
||||
u = &messageReceiptV1{mr}
|
||||
default:
|
||||
return fmt.Errorf("cbor input had wrong number of fields")
|
||||
}
|
||||
|
||||
// Ok to pass a CBOR reader since cbg.NewCborReader will return itself when
|
||||
// already a CBOR reader.
|
||||
return u.UnmarshalCBOR(cr)
|
||||
}
|
||||
|
||||
var lengthBufAMessageReceiptV0 = []byte{131}
|
||||
|
||||
func (t *messageReceiptV0) MarshalCBOR(w io.Writer) error {
|
||||
// eliding null check since nulls were already handled in the dispatcher
|
||||
|
||||
cw := cbg.NewCborWriter(w)
|
||||
|
||||
if _, err := cw.Write(lengthBufAMessageReceiptV0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.ExitCode (exitcode.ExitCode) (int64)
|
||||
if t.ExitCode >= 0 {
|
||||
if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.ExitCode)); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.ExitCode-1)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// t.Return ([]uint8) (slice)
|
||||
if len(t.Return) > cbg.ByteArrayMaxLen {
|
||||
return xerrors.Errorf("Byte array in field t.Return was too long")
|
||||
}
|
||||
|
||||
if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(t.Return))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := cw.Write(t.Return[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.GasUsed (int64) (int64)
|
||||
if t.GasUsed >= 0 {
|
||||
if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.GasUsed)); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.GasUsed-1)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *messageReceiptV0) UnmarshalCBOR(r io.Reader) (err error) {
|
||||
cr := cbg.NewCborReader(r)
|
||||
|
||||
// t.ExitCode (exitcode.ExitCode) (int64)
|
||||
{
|
||||
maj, extra, err := cr.ReadHeader()
|
||||
var extraI int64
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch maj {
|
||||
case cbg.MajUnsignedInt:
|
||||
extraI = int64(extra)
|
||||
if extraI < 0 {
|
||||
return fmt.Errorf("int64 positive overflow")
|
||||
}
|
||||
case cbg.MajNegativeInt:
|
||||
extraI = int64(extra)
|
||||
if extraI < 0 {
|
||||
return fmt.Errorf("int64 negative oveflow")
|
||||
}
|
||||
extraI = -1 - extraI
|
||||
default:
|
||||
return fmt.Errorf("wrong type for int64 field: %d", maj)
|
||||
}
|
||||
|
||||
t.ExitCode = exitcode.ExitCode(extraI)
|
||||
}
|
||||
// t.Return ([]uint8) (slice)
|
||||
|
||||
maj, extra, err := cr.ReadHeader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if extra > cbg.ByteArrayMaxLen {
|
||||
return fmt.Errorf("t.Return: byte array too large (%d)", extra)
|
||||
}
|
||||
if maj != cbg.MajByteString {
|
||||
return fmt.Errorf("expected byte array")
|
||||
}
|
||||
|
||||
if extra > 0 {
|
||||
t.Return = make([]uint8, extra)
|
||||
}
|
||||
|
||||
if _, err := io.ReadFull(cr, t.Return[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
// t.GasUsed (int64) (int64)
|
||||
{
|
||||
maj, extra, err := cr.ReadHeader()
|
||||
var extraI int64
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch maj {
|
||||
case cbg.MajUnsignedInt:
|
||||
extraI = int64(extra)
|
||||
if extraI < 0 {
|
||||
return fmt.Errorf("int64 positive overflow")
|
||||
}
|
||||
case cbg.MajNegativeInt:
|
||||
extraI = int64(extra)
|
||||
if extraI < 0 {
|
||||
return fmt.Errorf("int64 negative oveflow")
|
||||
}
|
||||
extraI = -1 - extraI
|
||||
default:
|
||||
return fmt.Errorf("wrong type for int64 field: %d", maj)
|
||||
}
|
||||
|
||||
t.GasUsed = extraI
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var lengthBufBMessageReceiptV1 = []byte{132}
|
||||
|
||||
func (t *messageReceiptV1) MarshalCBOR(w io.Writer) error {
|
||||
// eliding null check since nulls were already handled in the dispatcher
|
||||
|
||||
cw := cbg.NewCborWriter(w)
|
||||
|
||||
if _, err := cw.Write(lengthBufBMessageReceiptV1); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.ExitCode (exitcode.ExitCode) (int64)
|
||||
if t.ExitCode >= 0 {
|
||||
if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.ExitCode)); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.ExitCode-1)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// t.Return ([]uint8) (slice)
|
||||
if len(t.Return) > cbg.ByteArrayMaxLen {
|
||||
return xerrors.Errorf("Byte array in field t.Return was too long")
|
||||
}
|
||||
|
||||
if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(t.Return))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := cw.Write(t.Return[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// t.GasUsed (int64) (int64)
|
||||
if t.GasUsed >= 0 {
|
||||
if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(t.GasUsed)); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := cw.WriteMajorTypeHeader(cbg.MajNegativeInt, uint64(-t.GasUsed-1)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// t.EventsRoot (cid.Cid) (struct)
|
||||
|
||||
if t.EventsRoot == nil {
|
||||
if _, err := cw.Write(cbg.CborNull); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := cbg.WriteCid(cw, *t.EventsRoot); err != nil {
|
||||
return xerrors.Errorf("failed to write cid field t.EventsRoot: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *messageReceiptV1) UnmarshalCBOR(r io.Reader) (err error) {
|
||||
cr := cbg.NewCborReader(r)
|
||||
|
||||
// t.ExitCode (exitcode.ExitCode) (int64)
|
||||
{
|
||||
maj, extra, err := cr.ReadHeader()
|
||||
var extraI int64
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch maj {
|
||||
case cbg.MajUnsignedInt:
|
||||
extraI = int64(extra)
|
||||
if extraI < 0 {
|
||||
return fmt.Errorf("int64 positive overflow")
|
||||
}
|
||||
case cbg.MajNegativeInt:
|
||||
extraI = int64(extra)
|
||||
if extraI < 0 {
|
||||
return fmt.Errorf("int64 negative oveflow")
|
||||
}
|
||||
extraI = -1 - extraI
|
||||
default:
|
||||
return fmt.Errorf("wrong type for int64 field: %d", maj)
|
||||
}
|
||||
|
||||
t.ExitCode = exitcode.ExitCode(extraI)
|
||||
}
|
||||
// t.Return ([]uint8) (slice)
|
||||
|
||||
maj, extra, err := cr.ReadHeader()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if extra > cbg.ByteArrayMaxLen {
|
||||
return fmt.Errorf("t.Return: byte array too large (%d)", extra)
|
||||
}
|
||||
if maj != cbg.MajByteString {
|
||||
return fmt.Errorf("expected byte array")
|
||||
}
|
||||
|
||||
if extra > 0 {
|
||||
t.Return = make([]uint8, extra)
|
||||
}
|
||||
|
||||
if _, err := io.ReadFull(cr, t.Return[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
// t.GasUsed (int64) (int64)
|
||||
{
|
||||
maj, extra, err := cr.ReadHeader()
|
||||
var extraI int64
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch maj {
|
||||
case cbg.MajUnsignedInt:
|
||||
extraI = int64(extra)
|
||||
if extraI < 0 {
|
||||
return fmt.Errorf("int64 positive overflow")
|
||||
}
|
||||
case cbg.MajNegativeInt:
|
||||
extraI = int64(extra)
|
||||
if extraI < 0 {
|
||||
return fmt.Errorf("int64 negative oveflow")
|
||||
}
|
||||
extraI = -1 - extraI
|
||||
default:
|
||||
return fmt.Errorf("wrong type for int64 field: %d", maj)
|
||||
}
|
||||
|
||||
t.GasUsed = extraI
|
||||
}
|
||||
// t.EventsRoot (cid.Cid) (struct)
|
||||
|
||||
{
|
||||
|
||||
b, err := cr.ReadByte()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if b != cbg.CborNull[0] {
|
||||
if err := cr.UnreadByte(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c, err := cbg.ReadCid(cr)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to read cid field t.EventsRoot: %w", err)
|
||||
}
|
||||
|
||||
t.EventsRoot = &c
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMessageReceiptSerdeRoundrip(t *testing.T) {
|
||||
var (
|
||||
assert = assert.New(t)
|
||||
buf = new(bytes.Buffer)
|
||||
err error
|
||||
)
|
||||
|
||||
randomCid, err := cid.Decode("bafy2bzacecu7n7wbtogznrtuuvf73dsz7wasgyneqasksdblxupnyovmtwxxu")
|
||||
assert.NoError(err)
|
||||
|
||||
//
|
||||
// Version 0
|
||||
//
|
||||
mr := NewMessageReceiptV0(0, []byte{0x00, 0x01, 0x02, 0x04}, 42)
|
||||
|
||||
// marshal
|
||||
err = mr.MarshalCBOR(buf)
|
||||
assert.NoError(err)
|
||||
|
||||
t.Logf("version 0: %s\n", hex.EncodeToString(buf.Bytes()))
|
||||
|
||||
// unmarshal
|
||||
var mr2 MessageReceipt
|
||||
err = mr2.UnmarshalCBOR(buf)
|
||||
assert.NoError(err)
|
||||
assert.Equal(mr, mr2)
|
||||
|
||||
// version 0 with an events root -- should not serialize the events root!
|
||||
mr.EventsRoot = &randomCid
|
||||
|
||||
buf.Reset()
|
||||
|
||||
// marshal
|
||||
err = mr.MarshalCBOR(buf)
|
||||
assert.NoError(err)
|
||||
|
||||
t.Logf("version 0 (with root): %s\n", hex.EncodeToString(buf.Bytes()))
|
||||
|
||||
// unmarshal
|
||||
mr2 = MessageReceipt{}
|
||||
err = mr2.UnmarshalCBOR(buf)
|
||||
assert.NoError(err)
|
||||
assert.NotEqual(mr, mr2)
|
||||
assert.Nil(mr2.EventsRoot)
|
||||
|
||||
//
|
||||
// Version 1
|
||||
//
|
||||
buf.Reset()
|
||||
mr = NewMessageReceiptV1(0, []byte{0x00, 0x01, 0x02, 0x04}, 42, &randomCid)
|
||||
|
||||
// marshal
|
||||
err = mr.MarshalCBOR(buf)
|
||||
assert.NoError(err)
|
||||
|
||||
t.Logf("version 1: %s\n", hex.EncodeToString(buf.Bytes()))
|
||||
|
||||
// unmarshal
|
||||
mr2 = MessageReceipt{}
|
||||
err = mr2.UnmarshalCBOR(buf)
|
||||
assert.NoError(err)
|
||||
assert.Equal(mr, mr2)
|
||||
assert.NotNil(mr2.EventsRoot)
|
||||
}
|
||||
+17
-2
@@ -196,8 +196,23 @@ func (ts *TipSet) MinTicket() *Ticket {
|
||||
}
|
||||
|
||||
func (ts *TipSet) MinTimestamp() uint64 {
|
||||
minTs := ts.Blocks()[0].Timestamp
|
||||
for _, bh := range ts.Blocks()[1:] {
|
||||
if ts == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
blks := ts.Blocks()
|
||||
|
||||
// TODO::FVM @vyzo @magik Null rounds shouldn't ever be represented as
|
||||
// tipsets with no blocks; Null-round generally means that the tipset at
|
||||
// that epoch doesn't exist - and the next tipset that does exist links
|
||||
// straight to first epoch with blocks (@raulk agrees -- this is odd)
|
||||
if len(blks) == 0 {
|
||||
// null rounds make things crash -- it is threaded in every fvm instantiation
|
||||
return 0
|
||||
}
|
||||
|
||||
minTs := blks[0].Timestamp
|
||||
for _, bh := range blks[1:] {
|
||||
if bh.Timestamp < minTs {
|
||||
minTs = bh.Timestamp
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@ type StateTree interface {
|
||||
SetActor(addr address.Address, act *Actor) error
|
||||
// GetActor returns the actor from any type of `addr` provided.
|
||||
GetActor(addr address.Address) (*Actor, error)
|
||||
|
||||
Version() StateTreeVersion
|
||||
}
|
||||
|
||||
type storageWrapper struct {
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/vectors"
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/delegated"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
|
||||
)
|
||||
|
||||
|
||||
+20
-23
@@ -24,6 +24,7 @@ import (
|
||||
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
||||
"github.com/filecoin-project/go-state-types/exitcode"
|
||||
"github.com/filecoin-project/go-state-types/manifest"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
|
||||
"github.com/filecoin-project/lotus/blockstore"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
@@ -275,7 +276,7 @@ func (x *FvmExtern) workerKeyAtLookback(ctx context.Context, minerId address.Add
|
||||
return address.Undef, gasUsed, err
|
||||
}
|
||||
|
||||
raddr, err := ResolveToKeyAddr(stateTree, cstWithGas, info.Worker)
|
||||
raddr, err := ResolveToDeterministicAddr(stateTree, cstWithGas, info.Worker)
|
||||
if err != nil {
|
||||
return address.Undef, gasUsed, err
|
||||
}
|
||||
@@ -285,6 +286,7 @@ func (x *FvmExtern) workerKeyAtLookback(ctx context.Context, minerId address.Add
|
||||
|
||||
type FVM struct {
|
||||
fvm *ffi.FVM
|
||||
nv network.Version
|
||||
}
|
||||
|
||||
func defaultFVMOpts(ctx context.Context, opts *VMOpts) (*ffi.FVMOpts, error) {
|
||||
@@ -309,11 +311,14 @@ func defaultFVMOpts(ctx context.Context, opts *VMOpts) (*ffi.FVMOpts, error) {
|
||||
epoch: opts.Epoch,
|
||||
},
|
||||
Epoch: opts.Epoch,
|
||||
Timestamp: opts.Timestamp,
|
||||
ChainID: build.Eip155ChainId,
|
||||
BaseFee: opts.BaseFee,
|
||||
BaseCircSupply: circToReport,
|
||||
NetworkVersion: opts.NetworkVersion,
|
||||
StateBase: opts.StateBase,
|
||||
Tracing: opts.Tracing || EnableDetailedTracing,
|
||||
Debug: build.ActorDebugging,
|
||||
}, nil
|
||||
|
||||
}
|
||||
@@ -324,20 +329,6 @@ func NewFVM(ctx context.Context, opts *VMOpts) (*FVM, error) {
|
||||
return nil, xerrors.Errorf("creating fvm opts: %w", err)
|
||||
}
|
||||
|
||||
if os.Getenv("LOTUS_USE_FVM_CUSTOM_BUNDLE") == "1" {
|
||||
av, err := actorstypes.VersionForNetwork(opts.NetworkVersion)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("mapping network version to actors version: %w", err)
|
||||
}
|
||||
|
||||
c, ok := actors.GetManifest(av)
|
||||
if !ok {
|
||||
return nil, xerrors.Errorf("no manifest for custom bundle (actors version %d)", av)
|
||||
}
|
||||
|
||||
fvmOpts.Manifest = c
|
||||
}
|
||||
|
||||
fvm, err := ffi.CreateFVM(fvmOpts)
|
||||
|
||||
if err != nil {
|
||||
@@ -346,6 +337,7 @@ func NewFVM(ctx context.Context, opts *VMOpts) (*FVM, error) {
|
||||
|
||||
return &FVM{
|
||||
fvm: fvm,
|
||||
nv: opts.NetworkVersion,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -448,6 +440,7 @@ func NewDebugFVM(ctx context.Context, opts *VMOpts) (*FVM, error) {
|
||||
|
||||
return &FVM{
|
||||
fvm: fvm,
|
||||
nv: opts.NetworkVersion,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -466,10 +459,12 @@ func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet
|
||||
}
|
||||
|
||||
duration := time.Since(start)
|
||||
receipt := types.MessageReceipt{
|
||||
Return: ret.Return,
|
||||
ExitCode: exitcode.ExitCode(ret.ExitCode),
|
||||
GasUsed: ret.GasUsed,
|
||||
|
||||
var receipt types.MessageReceipt
|
||||
if vm.nv >= network.Version18 {
|
||||
receipt = types.NewMessageReceiptV1(exitcode.ExitCode(ret.ExitCode), ret.Return, ret.GasUsed, ret.EventsRoot)
|
||||
} else {
|
||||
receipt = types.NewMessageReceiptV0(exitcode.ExitCode(ret.ExitCode), ret.Return, ret.GasUsed)
|
||||
}
|
||||
|
||||
var aerr aerrors.ActorError
|
||||
@@ -530,10 +525,12 @@ func (vm *FVM) ApplyImplicitMessage(ctx context.Context, cmsg *types.Message) (*
|
||||
}
|
||||
|
||||
duration := time.Since(start)
|
||||
receipt := types.MessageReceipt{
|
||||
Return: ret.Return,
|
||||
ExitCode: exitcode.ExitCode(ret.ExitCode),
|
||||
GasUsed: ret.GasUsed,
|
||||
|
||||
var receipt types.MessageReceipt
|
||||
if vm.nv >= network.Version18 {
|
||||
receipt = types.NewMessageReceiptV1(exitcode.ExitCode(ret.ExitCode), ret.Return, ret.GasUsed, ret.EventsRoot)
|
||||
} else {
|
||||
receipt = types.NewMessageReceiptV0(exitcode.ExitCode(ret.ExitCode), ret.Return, ret.GasUsed)
|
||||
}
|
||||
|
||||
var aerr aerrors.ActorError
|
||||
|
||||
@@ -111,6 +111,7 @@ var Prices = map[abi.ChainEpoch]Pricelist{
|
||||
verifySignature: map[crypto.SigType]int64{
|
||||
crypto.SigTypeBLS: 16598605,
|
||||
crypto.SigTypeSecp256k1: 1637292,
|
||||
crypto.SigTypeDelegated: 1637292,
|
||||
},
|
||||
|
||||
hashingBase: 31355,
|
||||
|
||||
+4
-4
@@ -284,16 +284,16 @@ func DecodeParams(b []byte, out interface{}) error {
|
||||
}
|
||||
|
||||
func DumpActorState(i *ActorRegistry, act *types.Actor, b []byte) (interface{}, error) {
|
||||
if builtin.IsAccountActor(act.Code) { // Account code special case
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
actInfo, ok := i.actors[act.Code]
|
||||
if !ok {
|
||||
return nil, xerrors.Errorf("state type for actor %s not found", act.Code)
|
||||
}
|
||||
|
||||
um := actInfo.vmActor.State()
|
||||
if um == nil {
|
||||
// TODO::FVM @arajasek I would like to assert that we have the empty object here
|
||||
return nil, nil
|
||||
}
|
||||
if err := um.UnmarshalCBOR(bytes.NewReader(b)); err != nil {
|
||||
return nil, xerrors.Errorf("unmarshaling actor state: %w", err)
|
||||
}
|
||||
|
||||
+3
-3
@@ -168,8 +168,8 @@ func (rt *Runtime) shimCall(f func() interface{}) (rval []byte, aerr aerrors.Act
|
||||
aerr = ar
|
||||
return
|
||||
}
|
||||
//log.Desugar().WithOptions(zap.AddStacktrace(zapcore.ErrorLevel)).
|
||||
//Sugar().Errorf("spec actors failure: %s", r)
|
||||
// log.Desugar().WithOptions(zap.AddStacktrace(zapcore.ErrorLevel)).
|
||||
// Sugar().Errorf("spec actors failure: %s", r)
|
||||
log.Errorf("spec actors failure: %s", r)
|
||||
if rt.NetworkVersion() <= network.Version3 {
|
||||
aerr = aerrors.Newf(1, "spec actors failure: %s", r)
|
||||
@@ -249,7 +249,7 @@ func (rt *Runtime) GetRandomnessFromBeacon(personalization crypto.DomainSeparati
|
||||
|
||||
func (rt *Runtime) NewActorAddress() address.Address {
|
||||
var b bytes.Buffer
|
||||
oa, _ := ResolveToKeyAddr(rt.vm.cstate, rt.vm.cst, rt.origin)
|
||||
oa, _ := ResolveToDeterministicAddr(rt.vm.cstate, rt.vm.cst, rt.origin)
|
||||
if err := oa.MarshalCBOR(&b); err != nil { // todo: spec says cbor; why not just bytes?
|
||||
panic(aerrors.Fatalf("writing caller address into a buffer: %v", err))
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ func (ss *syscallShim) workerKeyAtLookback(height abi.ChainEpoch) (address.Addre
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
return ResolveToKeyAddr(ss.cstate, ss.cst, info.Worker)
|
||||
return ResolveToDeterministicAddr(ss.cstate, ss.cst, info.Worker)
|
||||
}
|
||||
|
||||
func (ss *syscallShim) VerifyPoSt(info proof7.WindowPoStVerifyInfo) error {
|
||||
@@ -270,8 +270,8 @@ func (ss *syscallShim) VerifyPoSt(info proof7.WindowPoStVerifyInfo) error {
|
||||
}
|
||||
|
||||
func (ss *syscallShim) VerifySeal(info proof7.SealVerifyInfo) error {
|
||||
//_, span := trace.StartSpan(ctx, "ValidatePoRep")
|
||||
//defer span.End()
|
||||
// _, span := trace.StartSpan(ctx, "ValidatePoRep")
|
||||
// defer span.End()
|
||||
|
||||
miner, err := address.NewIDAddress(uint64(info.Miner))
|
||||
if err != nil {
|
||||
@@ -284,7 +284,7 @@ func (ss *syscallShim) VerifySeal(info proof7.SealVerifyInfo) error {
|
||||
|
||||
log.Debugf("Verif r:%s; d:%s; m:%s; t:%x; s:%x; N:%d; p:%x", info.SealedCID, info.UnsealedCID, miner, ticket, seed, info.SectorID.Number, proof)
|
||||
|
||||
//func(ctx context.Context, maddr address.Address, ssize abi.SectorSize, commD, commR, ticket, proof, seed []byte, sectorID abi.SectorNumber)
|
||||
// func(ctx context.Context, maddr address.Address, ssize abi.SectorSize, commD, commR, ticket, proof, seed []byte, sectorID abi.SectorNumber)
|
||||
ok, err := ss.verifier.VerifySeal(info)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to validate PoRep: %w", err)
|
||||
@@ -325,7 +325,7 @@ func (ss *syscallShim) VerifyReplicaUpdate(update proof7.ReplicaUpdateInfo) erro
|
||||
func (ss *syscallShim) VerifySignature(sig crypto.Signature, addr address.Address, input []byte) error {
|
||||
// TODO: in genesis setup, we are currently faking signatures
|
||||
|
||||
kaddr, err := ResolveToKeyAddr(ss.cstate, ss.cst, addr)
|
||||
kaddr, err := ResolveToDeterministicAddr(ss.cstate, ss.cst, addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+14
-4
@@ -45,9 +45,11 @@ var (
|
||||
gasOnActorExec = newGasCharge("OnActorExec", 0, 0)
|
||||
)
|
||||
|
||||
// ResolveToKeyAddr returns the public key type of address (`BLS`/`SECP256K1`) of an account actor identified by `addr`.
|
||||
func ResolveToKeyAddr(state types.StateTree, cst cbor.IpldStore, addr address.Address) (address.Address, error) {
|
||||
if addr.Protocol() == address.BLS || addr.Protocol() == address.SECP256K1 {
|
||||
// ResolveToDeterministicAddr returns the public key type of address
|
||||
// (`BLS`/`SECP256K1`) of an actor identified by `addr`, or its
|
||||
// delegated address.
|
||||
func ResolveToDeterministicAddr(state types.StateTree, cst cbor.IpldStore, addr address.Address) (address.Address, error) {
|
||||
if addr.Protocol() == address.BLS || addr.Protocol() == address.SECP256K1 || addr.Protocol() == address.Delegated {
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
@@ -56,12 +58,19 @@ func ResolveToKeyAddr(state types.StateTree, cst cbor.IpldStore, addr address.Ad
|
||||
return address.Undef, xerrors.Errorf("failed to find actor: %s", addr)
|
||||
}
|
||||
|
||||
if state.Version() >= types.StateTreeVersion5 {
|
||||
if act.Address != nil {
|
||||
// If there _is_ an f4 address, return it as "key" address
|
||||
return *act.Address, nil
|
||||
}
|
||||
}
|
||||
|
||||
aast, err := account.Load(adt.WrapStore(context.TODO(), cst), act)
|
||||
if err != nil {
|
||||
return address.Undef, xerrors.Errorf("failed to get account actor state for %s: %w", addr, err)
|
||||
}
|
||||
|
||||
return aast.PubkeyAddress()
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -216,6 +225,7 @@ type LegacyVM struct {
|
||||
type VMOpts struct {
|
||||
StateBase cid.Cid
|
||||
Epoch abi.ChainEpoch
|
||||
Timestamp uint64
|
||||
Rand Rand
|
||||
Bstore blockstore.Blockstore
|
||||
Actors *ActorRegistry
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
"github.com/filecoin-project/lotus/lib/sigs"
|
||||
)
|
||||
|
||||
@@ -50,6 +51,22 @@ func NewKey(keyinfo types.KeyInfo) (*Key, error) {
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("converting Secp256k1 to address: %w", err)
|
||||
}
|
||||
case types.KTDelegated:
|
||||
// Transitory Delegated signature verification as per FIP-0055
|
||||
ethAddr, err := ethtypes.EthAddressFromPubKey(k.PublicKey)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to calculate Eth address from public key: %w", err)
|
||||
}
|
||||
|
||||
ea, err := ethtypes.CastEthAddress(ethAddr)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to create ethereum address from bytes: %w", err)
|
||||
}
|
||||
|
||||
k.Address, err = ea.ToFilecoinAddress()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("converting Delegated to address: %w", err)
|
||||
}
|
||||
case types.KTBLS:
|
||||
k.Address, err = address.NewBLSAddress(k.PublicKey)
|
||||
if err != nil {
|
||||
@@ -58,6 +75,7 @@ func NewKey(keyinfo types.KeyInfo) (*Key, error) {
|
||||
default:
|
||||
return nil, xerrors.Errorf("unsupported key type: %s", k.Type)
|
||||
}
|
||||
|
||||
return k, nil
|
||||
|
||||
}
|
||||
@@ -68,6 +86,8 @@ func ActSigType(typ types.KeyType) crypto.SigType {
|
||||
return crypto.SigTypeBLS
|
||||
case types.KTSecp256k1:
|
||||
return crypto.SigTypeSecp256k1
|
||||
case types.KTDelegated:
|
||||
return crypto.SigTypeDelegated
|
||||
default:
|
||||
return crypto.SigTypeUnknown
|
||||
}
|
||||
|
||||
@@ -16,7 +16,8 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/wallet/key"
|
||||
"github.com/filecoin-project/lotus/lib/sigs"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls" // enable bls signatures
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls" // enable bls signatures
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/delegated"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/secp" // enable secp signatures
|
||||
)
|
||||
|
||||
|
||||
+1
-1
@@ -149,7 +149,7 @@ var ChainGetBlock = &cli.Command{
|
||||
recpts, err := api.ChainGetParentReceipts(ctx, bcid)
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
//return xerrors.Errorf("failed to get receipts: %w", err)
|
||||
// return xerrors.Errorf("failed to get receipts: %w", err)
|
||||
}
|
||||
|
||||
cblock := struct {
|
||||
|
||||
@@ -81,6 +81,7 @@ var Commands = []*cli.Command{
|
||||
WithCategory("developer", LogCmd),
|
||||
WithCategory("developer", WaitApiCmd),
|
||||
WithCategory("developer", FetchParamCmd),
|
||||
WithCategory("developer", EvmCmd),
|
||||
WithCategory("network", NetCmd),
|
||||
WithCategory("network", SyncCmd),
|
||||
WithCategory("status", StatusCmd),
|
||||
|
||||
+503
@@ -0,0 +1,503 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
amt4 "github.com/filecoin-project/go-amt-ipld/v4"
|
||||
"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/lotus/api/v0api"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
)
|
||||
|
||||
var EvmCmd = &cli.Command{
|
||||
Name: "evm",
|
||||
Usage: "Commands related to the Filecoin EVM runtime",
|
||||
Subcommands: []*cli.Command{
|
||||
EvmDeployCmd,
|
||||
EvmInvokeCmd,
|
||||
EvmGetInfoCmd,
|
||||
EvmCallSimulateCmd,
|
||||
EvmGetContractAddress,
|
||||
},
|
||||
}
|
||||
|
||||
var EvmGetInfoCmd = &cli.Command{
|
||||
Name: "stat",
|
||||
Usage: "Print eth/filecoin addrs and code cid",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "filAddr",
|
||||
Usage: "Filecoin address",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "ethAddr",
|
||||
Usage: "Ethereum address",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
|
||||
filAddr := cctx.String("filAddr")
|
||||
ethAddr := cctx.String("ethAddr")
|
||||
|
||||
var faddr address.Address
|
||||
var eaddr ethtypes.EthAddress
|
||||
|
||||
api, closer, err := GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
if filAddr != "" {
|
||||
addr, err := address.NewFromString(filAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eaddr, faddr, err = ethAddrFromFilecoinAddress(ctx, addr, api)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if ethAddr != "" {
|
||||
eaddr, err = ethtypes.ParseEthAddress(ethAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
faddr, err = eaddr.ToFilecoinAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return xerrors.Errorf("Neither filAddr nor ethAddr specified")
|
||||
}
|
||||
|
||||
actor, err := api.StateGetActor(ctx, faddr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("Filecoin address: ", faddr)
|
||||
fmt.Println("Eth address: ", eaddr)
|
||||
fmt.Println("Code cid: ", actor.Code.String())
|
||||
|
||||
return nil
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
var EvmCallSimulateCmd = &cli.Command{
|
||||
Name: "call",
|
||||
Usage: "Simulate an eth contract call",
|
||||
ArgsUsage: "[from] [to] [params]",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
|
||||
if cctx.NArg() != 3 {
|
||||
return IncorrectNumArgs(cctx)
|
||||
}
|
||||
|
||||
fromEthAddr, err := ethtypes.ParseEthAddress(cctx.Args().Get(0))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
toEthAddr, err := ethtypes.ParseEthAddress(cctx.Args().Get(1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
params, err := hex.DecodeString(cctx.Args().Get(2))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
api, closer, err := GetFullNodeAPIV1(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
res, err := api.EthCall(ctx, ethtypes.EthCall{
|
||||
From: &fromEthAddr,
|
||||
To: &toEthAddr,
|
||||
Data: params,
|
||||
}, "")
|
||||
if err != nil {
|
||||
fmt.Println("Eth call fails, return val: ", res)
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("Result: ", res)
|
||||
|
||||
return nil
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
var EvmGetContractAddress = &cli.Command{
|
||||
Name: "contract-address",
|
||||
Usage: "Generate contract address from smart contract code",
|
||||
ArgsUsage: "[senderEthAddr] [salt] [contractHexPath]",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
|
||||
if cctx.NArg() != 3 {
|
||||
return IncorrectNumArgs(cctx)
|
||||
}
|
||||
|
||||
sender, err := ethtypes.ParseEthAddress(cctx.Args().Get(0))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
salt, err := hex.DecodeString(cctx.Args().Get(1))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("Could not decode salt: %w", err)
|
||||
}
|
||||
if len(salt) > 32 {
|
||||
return xerrors.Errorf("Len of salt bytes greater than 32")
|
||||
}
|
||||
var fsalt [32]byte
|
||||
copy(fsalt[:], salt[:])
|
||||
|
||||
contractBin := cctx.Args().Get(2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
contractHex, err := os.ReadFile(contractBin)
|
||||
if err != nil {
|
||||
|
||||
return err
|
||||
}
|
||||
contract, err := hex.DecodeString(string(contractHex))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("Could not decode contract file: %w", err)
|
||||
}
|
||||
|
||||
contractAddr, err := ethtypes.GetContractEthAddressFromCode(sender, fsalt, contract)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("Contract Eth address: ", contractAddr)
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var EvmDeployCmd = &cli.Command{
|
||||
Name: "deploy",
|
||||
Usage: "Deploy an EVM smart contract and return its address",
|
||||
ArgsUsage: "contract",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "from",
|
||||
Usage: "optionally specify the account to use for sending the creation message",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "hex",
|
||||
Usage: "use when input contract is in hex",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
afmt := NewAppFmt(cctx.App)
|
||||
|
||||
api, closer, err := GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
if argc := cctx.Args().Len(); argc != 1 {
|
||||
return xerrors.Errorf("must pass the contract init code")
|
||||
}
|
||||
|
||||
contract, err := os.ReadFile(cctx.Args().First())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to read contract: %w", err)
|
||||
}
|
||||
if cctx.Bool("hex") {
|
||||
contract, err = hex.DecodeString(string(contract))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to decode contract: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var fromAddr address.Address
|
||||
if from := cctx.String("from"); from == "" {
|
||||
fromAddr, err = api.WalletDefaultAddress(ctx)
|
||||
} else {
|
||||
fromAddr, err = address.NewFromString(from)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nonce, err := api.MpoolGetNonce(ctx, fromAddr)
|
||||
if err != nil {
|
||||
nonce = 0 // assume a zero nonce on error (e.g. sender doesn't exist).
|
||||
}
|
||||
|
||||
params, err := actors.SerializeParams(&eam.CreateParams{
|
||||
Initcode: contract,
|
||||
Nonce: nonce,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to serialize Create params: %w", err)
|
||||
}
|
||||
|
||||
msg := &types.Message{
|
||||
To: builtintypes.EthereumAddressManagerActorAddr,
|
||||
From: fromAddr,
|
||||
Value: big.Zero(),
|
||||
Method: builtintypes.MethodsEAM.Create,
|
||||
Params: params,
|
||||
}
|
||||
|
||||
// TODO: On Jan 11th, we decided to add an `EAM#create_external` method
|
||||
// that uses the nonce of the caller instead of taking a user-supplied nonce.
|
||||
// Track: https://github.com/filecoin-project/ref-fvm/issues/1255
|
||||
// When that's implemented, we should migrate the CLI to use that,
|
||||
// as `EAM#create` will be reserved for the EVM runtime actor.
|
||||
// TODO: this is very racy. It may assign a _different_ nonce than the expected one.
|
||||
afmt.Println("sending message...")
|
||||
smsg, err := api.MpoolPushMessage(ctx, msg, nil)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to push message: %w", err)
|
||||
}
|
||||
|
||||
afmt.Println("waiting for message to execute...")
|
||||
wait, err := api.StateWaitMsg(ctx, smsg.Cid(), 0)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("error waiting for message: %w", err)
|
||||
}
|
||||
|
||||
// check it executed successfully
|
||||
if wait.Receipt.ExitCode != 0 {
|
||||
return xerrors.Errorf("actor execution failed")
|
||||
}
|
||||
|
||||
var result eam.CreateReturn
|
||||
r := bytes.NewReader(wait.Receipt.Return)
|
||||
if err := result.UnmarshalCBOR(r); err != nil {
|
||||
return xerrors.Errorf("error unmarshaling return value: %w", err)
|
||||
}
|
||||
|
||||
addr, err := address.NewIDAddress(result.ActorID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
afmt.Printf("Actor ID: %d\n", result.ActorID)
|
||||
afmt.Printf("ID Address: %s\n", addr)
|
||||
afmt.Printf("Robust Address: %s\n", result.RobustAddress)
|
||||
afmt.Printf("Eth Address: %s\n", "0x"+hex.EncodeToString(result.EthAddress[:]))
|
||||
|
||||
ea, err := ethtypes.CastEthAddress(result.EthAddress[:])
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create ethereum address: %w", err)
|
||||
}
|
||||
|
||||
delegated, err := ea.ToFilecoinAddress()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to calculate f4 address: %w", err)
|
||||
}
|
||||
|
||||
afmt.Printf("f4 Address: %s\n", delegated)
|
||||
|
||||
if len(wait.Receipt.Return) > 0 {
|
||||
result := base64.StdEncoding.EncodeToString(wait.Receipt.Return)
|
||||
afmt.Printf("Return: %s\n", result)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var EvmInvokeCmd = &cli.Command{
|
||||
Name: "invoke",
|
||||
Usage: "Invoke an EVM smart contract using the specified CALLDATA",
|
||||
ArgsUsage: "address calldata",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "from",
|
||||
Usage: "optionally specify the account to use for sending the exec message",
|
||||
}, &cli.IntFlag{
|
||||
Name: "value",
|
||||
Usage: "optionally specify the value to be sent with the invokation message",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
afmt := NewAppFmt(cctx.App)
|
||||
|
||||
api, closer, err := GetFullNodeAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
if argc := cctx.Args().Len(); argc < 2 || argc > 3 {
|
||||
return xerrors.Errorf("must pass the address, entry point and (optionally) input data")
|
||||
}
|
||||
|
||||
addr, err := address.NewFromString(cctx.Args().Get(0))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to decode address: %w", err)
|
||||
}
|
||||
|
||||
var calldata []byte
|
||||
calldata, err = hex.DecodeString(cctx.Args().Get(2))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("decoding hex input data: %w", err)
|
||||
}
|
||||
|
||||
var buffer bytes.Buffer
|
||||
if err := cbg.WriteByteArray(&buffer, calldata); err != nil {
|
||||
return xerrors.Errorf("failed to encode evm params as cbor: %w", err)
|
||||
}
|
||||
calldata = buffer.Bytes()
|
||||
|
||||
var fromAddr address.Address
|
||||
if from := cctx.String("from"); from == "" {
|
||||
defaddr, err := api.WalletDefaultAddress(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fromAddr = defaddr
|
||||
} else {
|
||||
addr, err := address.NewFromString(from)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fromAddr = addr
|
||||
}
|
||||
|
||||
val := abi.NewTokenAmount(cctx.Int64("value"))
|
||||
msg := &types.Message{
|
||||
To: addr,
|
||||
From: fromAddr,
|
||||
Value: val,
|
||||
Method: abi.MethodNum(2),
|
||||
Params: calldata,
|
||||
}
|
||||
|
||||
afmt.Println("sending message...")
|
||||
smsg, err := api.MpoolPushMessage(ctx, msg, nil)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to push message: %w", err)
|
||||
}
|
||||
|
||||
afmt.Println("waiting for message to execute...")
|
||||
wait, err := api.StateWaitMsg(ctx, smsg.Cid(), 0)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("error waiting for message: %w", err)
|
||||
}
|
||||
|
||||
// check it executed successfully
|
||||
if wait.Receipt.ExitCode != 0 {
|
||||
return xerrors.Errorf("actor execution failed")
|
||||
}
|
||||
|
||||
afmt.Println("Gas used: ", wait.Receipt.GasUsed)
|
||||
result, err := cbg.ReadByteArray(bytes.NewBuffer(wait.Receipt.Return), uint64(len(wait.Receipt.Return)))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("evm result not correctly encoded: %w", err)
|
||||
}
|
||||
|
||||
if len(result) > 0 {
|
||||
afmt.Println(hex.EncodeToString(result))
|
||||
} else {
|
||||
afmt.Println("OK")
|
||||
}
|
||||
|
||||
if eventsRoot := wait.Receipt.EventsRoot; eventsRoot != nil {
|
||||
afmt.Println("Events emitted:")
|
||||
|
||||
s := &apiIpldStore{ctx, api}
|
||||
amt, err := amt4.LoadAMT(ctx, s, *eventsRoot, amt4.UseTreeBitWidth(types.EventAMTBitwidth))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var evt types.Event
|
||||
err = amt.ForEach(ctx, func(u uint64, deferred *cbg.Deferred) error {
|
||||
fmt.Printf("%x\n", deferred.Raw)
|
||||
if err := evt.UnmarshalCBOR(bytes.NewReader(deferred.Raw)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("\tEmitter ID: %s\n", evt.Emitter)
|
||||
for _, e := range evt.Entries {
|
||||
value, err := cbg.ReadByteArray(bytes.NewBuffer(e.Value), uint64(len(e.Value)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("\t\tKey: %s, Value: 0x%x, Flags: b%b\n", e.Key, value, e.Flags)
|
||||
}
|
||||
return nil
|
||||
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func ethAddrFromFilecoinAddress(ctx context.Context, addr address.Address, fnapi v0api.FullNode) (ethtypes.EthAddress, address.Address, error) {
|
||||
var faddr address.Address
|
||||
var err error
|
||||
|
||||
switch addr.Protocol() {
|
||||
case address.BLS, address.SECP256K1:
|
||||
faddr, err = fnapi.StateLookupID(ctx, addr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return ethtypes.EthAddress{}, addr, err
|
||||
}
|
||||
case address.Actor, address.ID:
|
||||
faddr, err = fnapi.StateLookupID(ctx, addr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return ethtypes.EthAddress{}, addr, err
|
||||
}
|
||||
fAct, err := fnapi.StateGetActor(ctx, faddr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return ethtypes.EthAddress{}, addr, err
|
||||
}
|
||||
if fAct.Address != nil && (*fAct.Address).Protocol() == address.Delegated {
|
||||
faddr = *fAct.Address
|
||||
}
|
||||
case address.Delegated:
|
||||
faddr = addr
|
||||
default:
|
||||
return ethtypes.EthAddress{}, addr, xerrors.Errorf("Filecoin address doesn't match known protocols")
|
||||
}
|
||||
|
||||
ethAddr, err := ethtypes.EthAddressFromFilecoinAddress(faddr)
|
||||
if err != nil {
|
||||
return ethtypes.EthAddress{}, addr, err
|
||||
}
|
||||
|
||||
return ethAddr, faddr, nil
|
||||
}
|
||||
@@ -776,6 +776,7 @@ var StateGetActorCmd = &cli.Command{
|
||||
fmt.Printf("Nonce:\t\t%d\n", a.Nonce)
|
||||
fmt.Printf("Code:\t\t%s (%s)\n", a.Code, strtype)
|
||||
fmt.Printf("Head:\t\t%s\n", a.Head)
|
||||
fmt.Printf("Delegated address:\t\t%s\n", a.Address)
|
||||
|
||||
return nil
|
||||
},
|
||||
|
||||
@@ -41,6 +41,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/delegated"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
|
||||
"github.com/filecoin-project/lotus/node/repo"
|
||||
"github.com/filecoin-project/lotus/storage/sealer/ffiwrapper"
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/delegated"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
|
||||
)
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/wallet"
|
||||
"github.com/filecoin-project/lotus/chain/wallet/key"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/delegated"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
|
||||
"github.com/filecoin-project/lotus/node/modules"
|
||||
"github.com/filecoin-project/lotus/node/modules/lp2p"
|
||||
|
||||
@@ -4,10 +4,10 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"github.com/urfave/cli/v2"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
"golang.org/x/xerrors"
|
||||
@@ -25,6 +25,8 @@ import (
|
||||
adt9 "github.com/filecoin-project/go-state-types/builtin/v9/util/adt"
|
||||
verifreg9 "github.com/filecoin-project/go-state-types/builtin/v9/verifreg"
|
||||
"github.com/filecoin-project/go-state-types/manifest"
|
||||
mutil "github.com/filecoin-project/go-state-types/migration"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
"github.com/filecoin-project/specs-actors/v7/actors/migration/nv15"
|
||||
|
||||
"github.com/filecoin-project/lotus/blockstore"
|
||||
@@ -47,9 +49,9 @@ import (
|
||||
)
|
||||
|
||||
var migrationsCmd = &cli.Command{
|
||||
Name: "migrate-nv17",
|
||||
Description: "Run the nv17 migration",
|
||||
ArgsUsage: "[block to look back from]",
|
||||
Name: "migrate-state",
|
||||
Description: "Run a network upgrade migration",
|
||||
ArgsUsage: "[new network version, block to look back from]",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "repo",
|
||||
@@ -65,16 +67,21 @@ var migrationsCmd = &cli.Command{
|
||||
Action: func(cctx *cli.Context) error {
|
||||
ctx := context.TODO()
|
||||
|
||||
err := logging.SetLogLevelRegex("badger*", "ERROR")
|
||||
if cctx.NArg() != 2 {
|
||||
return lcli.IncorrectNumArgs(cctx)
|
||||
}
|
||||
|
||||
nv, err := strconv.ParseUint(cctx.Args().Get(0), 10, 32)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse network version: %w", err)
|
||||
}
|
||||
|
||||
upgradeActorsFunc, preUpgradeActorsFunc, checkInvariantsFunc, err := getMigrationFuncsForNetwork(network.Version(nv))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cctx.NArg() != 1 {
|
||||
return lcli.IncorrectNumArgs(cctx)
|
||||
}
|
||||
|
||||
blkCid, err := cid.Decode(cctx.Args().First())
|
||||
blkCid, err := cid.Decode(cctx.Args().Get(1))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse input: %w", err)
|
||||
}
|
||||
@@ -129,7 +136,7 @@ var migrationsCmd = &cli.Command{
|
||||
|
||||
startTime := time.Now()
|
||||
|
||||
newCid2, err := filcns.UpgradeActorsV9(ctx, sm, nv15.NewMemMigrationCache(), nil, blk.ParentStateRoot, blk.Height-1, migrationTs)
|
||||
newCid2, err := upgradeActorsFunc(ctx, sm, nv15.NewMemMigrationCache(), nil, blk.ParentStateRoot, blk.Height-1, migrationTs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -142,7 +149,7 @@ var migrationsCmd = &cli.Command{
|
||||
fmt.Println("completed round actual (without cache), took ", uncachedMigrationTime)
|
||||
|
||||
if !cctx.IsSet("skip-pre-migration") {
|
||||
cache := nv15.NewMemMigrationCache()
|
||||
cache := mutil.NewMemMigrationCache()
|
||||
|
||||
ts1, err := cs.GetTipsetByHeight(ctx, blk.Height-240, migrationTs, false)
|
||||
if err != nil {
|
||||
@@ -151,7 +158,7 @@ var migrationsCmd = &cli.Command{
|
||||
|
||||
startTime = time.Now()
|
||||
|
||||
err = filcns.PreUpgradeActorsV9(ctx, sm, cache, ts1.ParentState(), ts1.Height()-1, ts1)
|
||||
err = preUpgradeActorsFunc(ctx, sm, cache, ts1.ParentState(), ts1.Height()-1, ts1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -165,7 +172,7 @@ var migrationsCmd = &cli.Command{
|
||||
|
||||
startTime = time.Now()
|
||||
|
||||
err = filcns.PreUpgradeActorsV9(ctx, sm, cache, ts2.ParentState(), ts2.Height()-1, ts2)
|
||||
err = preUpgradeActorsFunc(ctx, sm, cache, ts2.ParentState(), ts2.Height()-1, ts2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -174,7 +181,7 @@ var migrationsCmd = &cli.Command{
|
||||
|
||||
startTime = time.Now()
|
||||
|
||||
newCid1, err := filcns.UpgradeActorsV9(ctx, sm, cache, nil, blk.ParentStateRoot, blk.Height-1, migrationTs)
|
||||
newCid1, err := upgradeActorsFunc(ctx, sm, cache, nil, blk.ParentStateRoot, blk.Height-1, migrationTs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -191,7 +198,10 @@ var migrationsCmd = &cli.Command{
|
||||
}
|
||||
|
||||
if cctx.Bool("check-invariants") {
|
||||
err = checkMigrationInvariants(ctx, blk.ParentStateRoot, newCid2, bs, blk.Height-1)
|
||||
if checkInvariantsFunc == nil {
|
||||
return xerrors.Errorf("check invariants not implemented for nv%d", nv)
|
||||
}
|
||||
err = checkInvariantsFunc(ctx, blk.ParentStateRoot, newCid2, bs, blk.Height-1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -201,7 +211,22 @@ var migrationsCmd = &cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
func checkMigrationInvariants(ctx context.Context, v8StateRootCid cid.Cid, v9StateRootCid cid.Cid, bs blockstore.Blockstore, epoch abi.ChainEpoch) error {
|
||||
func getMigrationFuncsForNetwork(nv network.Version) (UpgradeActorsFunc, PreUpgradeActorsFunc, CheckInvariantsFunc, error) {
|
||||
switch nv {
|
||||
case network.Version17:
|
||||
return filcns.UpgradeActorsV9, filcns.PreUpgradeActorsV9, checkNv17Invariants, nil
|
||||
case network.Version18:
|
||||
return filcns.UpgradeActorsV10, filcns.PreUpgradeActorsV10, nil, nil
|
||||
default:
|
||||
return nil, nil, nil, xerrors.Errorf("migration not implemented for nv%d", nv)
|
||||
}
|
||||
}
|
||||
|
||||
type UpgradeActorsFunc = func(context.Context, *stmgr.StateManager, stmgr.MigrationCache, stmgr.ExecMonitor, cid.Cid, abi.ChainEpoch, *types.TipSet) (cid.Cid, error)
|
||||
type PreUpgradeActorsFunc = func(context.Context, *stmgr.StateManager, stmgr.MigrationCache, cid.Cid, abi.ChainEpoch, *types.TipSet) error
|
||||
type CheckInvariantsFunc = func(context.Context, cid.Cid, cid.Cid, blockstore.Blockstore, abi.ChainEpoch) error
|
||||
|
||||
func checkNv17Invariants(ctx context.Context, v8StateRootCid cid.Cid, v9StateRootCid cid.Cid, bs blockstore.Blockstore, epoch abi.ChainEpoch) error {
|
||||
actorStore := store.ActorStore(ctx, bs)
|
||||
startTime := time.Now()
|
||||
|
||||
|
||||
@@ -74,14 +74,17 @@ func (sim *Simulation) makeTipSet(ctx context.Context, messages []*types.Message
|
||||
Timestamp: uts,
|
||||
ElectionProof: &types.ElectionProof{WinCount: 1},
|
||||
}}
|
||||
err = sim.Node.Chainstore.PersistBlockHeaders(ctx, blks...)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to persist block headers: %w", err)
|
||||
}
|
||||
|
||||
newTipSet, err := types.NewTipSet(blks)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to create new tipset: %w", err)
|
||||
}
|
||||
|
||||
err = sim.Node.Chainstore.PersistTipset(ctx, newTipSet)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to persist block headers: %w", err)
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
_, _, err = sim.StateManager.TipSetState(ctx, newTipSet)
|
||||
if err != nil {
|
||||
|
||||
@@ -27,7 +27,8 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
"github.com/filecoin-project/lotus/conformance/chaos"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls" // enable bls signatures
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls" // enable bls signatures
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/delegated"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/secp" // enable secp signatures
|
||||
"github.com/filecoin-project/lotus/storage/sealer/ffiwrapper"
|
||||
)
|
||||
|
||||
@@ -464,7 +464,9 @@ Inputs:
|
||||
{
|
||||
"SealProof": 8,
|
||||
"SectorNumber": 9,
|
||||
"SectorKey": null,
|
||||
"SectorKey": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"SealedCID": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
@@ -1279,8 +1281,12 @@ Response:
|
||||
"ProposalCid": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"AddFundsCid": null,
|
||||
"PublishCid": null,
|
||||
"AddFundsCid": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"PublishCid": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"Miner": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
||||
"Client": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
||||
"State": 42,
|
||||
@@ -1295,7 +1301,9 @@ Response:
|
||||
"Root": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"PieceCid": null,
|
||||
"PieceCid": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"PieceSize": 1024,
|
||||
"RawBlockSize": 42
|
||||
},
|
||||
@@ -1457,8 +1465,12 @@ Response:
|
||||
"ProposalCid": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"AddFundsCid": null,
|
||||
"PublishCid": null,
|
||||
"AddFundsCid": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"PublishCid": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"Miner": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
||||
"Client": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
||||
"State": 42,
|
||||
@@ -1473,7 +1485,9 @@ Response:
|
||||
"Root": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"PieceCid": null,
|
||||
"PieceCid": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"PieceSize": 1024,
|
||||
"RawBlockSize": 42
|
||||
},
|
||||
@@ -1509,7 +1523,9 @@ Response:
|
||||
"Selector": {
|
||||
"Raw": "Ynl0ZSBhcnJheQ=="
|
||||
},
|
||||
"PieceCID": null,
|
||||
"PieceCID": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"PricePerByte": "0",
|
||||
"PaymentInterval": 42,
|
||||
"PaymentIntervalIncrease": 42,
|
||||
@@ -2908,7 +2924,9 @@ Inputs:
|
||||
1024,
|
||||
{},
|
||||
{
|
||||
"PublishCid": null,
|
||||
"PublishCid": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"DealID": 5432,
|
||||
"DealProposal": {
|
||||
"PieceCID": {
|
||||
@@ -2962,7 +2980,9 @@ Response:
|
||||
"FailedSectors": {
|
||||
"123": "can't acquire read lock"
|
||||
},
|
||||
"Msg": null,
|
||||
"Msg": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"Error": "string value"
|
||||
}
|
||||
]
|
||||
@@ -3156,7 +3176,9 @@ Response:
|
||||
123,
|
||||
124
|
||||
],
|
||||
"Msg": null,
|
||||
"Msg": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"Error": "string value"
|
||||
}
|
||||
]
|
||||
@@ -3204,7 +3226,9 @@ Inputs:
|
||||
}
|
||||
},
|
||||
"DealInfo": {
|
||||
"PublishCid": null,
|
||||
"PublishCid": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"DealID": 5432,
|
||||
"DealProposal": {
|
||||
"PieceCID": {
|
||||
@@ -3232,8 +3256,12 @@ Inputs:
|
||||
"TicketValue": "Bw==",
|
||||
"TicketEpoch": 10101,
|
||||
"PreCommit1Out": "Bw==",
|
||||
"CommD": null,
|
||||
"CommR": null,
|
||||
"CommD": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"CommR": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"PreCommitInfo": {
|
||||
"SealProof": 8,
|
||||
"SectorNumber": 9,
|
||||
@@ -3245,10 +3273,14 @@ Inputs:
|
||||
5432
|
||||
],
|
||||
"Expiration": 10101,
|
||||
"UnsealedCid": null
|
||||
"UnsealedCid": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
},
|
||||
"PreCommitDeposit": "0",
|
||||
"PreCommitMessage": null,
|
||||
"PreCommitMessage": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"PreCommitTipSet": [
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
@@ -3260,7 +3292,9 @@ Inputs:
|
||||
"SeedValue": "Bw==",
|
||||
"SeedEpoch": 10101,
|
||||
"CommitProof": "Ynl0ZSBhcnJheQ==",
|
||||
"CommitMessage": null,
|
||||
"CommitMessage": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"Log": [
|
||||
{
|
||||
"Kind": "string value",
|
||||
@@ -3396,7 +3430,12 @@ Perms: admin
|
||||
|
||||
Inputs: `null`
|
||||
|
||||
Response: `null`
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
```
|
||||
|
||||
### SectorTerminatePending
|
||||
SectorTerminatePending returns a list of pending sector terminations to be sent in the next batch message
|
||||
@@ -3497,8 +3536,12 @@ Response:
|
||||
{
|
||||
"SectorID": 9,
|
||||
"State": "Proving",
|
||||
"CommD": null,
|
||||
"CommR": null,
|
||||
"CommD": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"CommR": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"Proof": "Ynl0ZSBhcnJheQ==",
|
||||
"Deals": [
|
||||
5432
|
||||
@@ -3512,7 +3555,9 @@ Response:
|
||||
}
|
||||
},
|
||||
"DealInfo": {
|
||||
"PublishCid": null,
|
||||
"PublishCid": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"DealID": 5432,
|
||||
"DealProposal": {
|
||||
"PieceCID": {
|
||||
@@ -3545,11 +3590,17 @@ Response:
|
||||
"Value": "Bw==",
|
||||
"Epoch": 10101
|
||||
},
|
||||
"PreCommitMsg": null,
|
||||
"CommitMsg": null,
|
||||
"PreCommitMsg": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"CommitMsg": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"Retries": 42,
|
||||
"ToUpgrade": true,
|
||||
"ReplicaUpdateMessage": null,
|
||||
"ReplicaUpdateMessage": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"LastErr": "string value",
|
||||
"Log": [
|
||||
{
|
||||
@@ -3603,7 +3654,9 @@ Inputs:
|
||||
1040384,
|
||||
1024,
|
||||
"Bw==",
|
||||
null
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
@@ -754,7 +754,10 @@ Response:
|
||||
{
|
||||
"ExitCode": 0,
|
||||
"Return": "Ynl0ZSBhcnJheQ==",
|
||||
"GasUsed": 9
|
||||
"GasUsed": 9,
|
||||
"EventsRoot": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
@@ -1247,7 +1250,9 @@ Inputs:
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
null
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
@@ -1259,7 +1264,9 @@ Response:
|
||||
"Root": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"Piece": null,
|
||||
"Piece": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"Size": 42,
|
||||
"MinPrice": "0",
|
||||
"UnsealPrice": "0",
|
||||
@@ -1270,7 +1277,9 @@ Response:
|
||||
"MinerPeer": {
|
||||
"Address": "f01234",
|
||||
"ID": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
||||
"PieceCID": null
|
||||
"PieceCID": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1341,7 +1350,9 @@ Response:
|
||||
"Root": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"PieceCid": null,
|
||||
"PieceCid": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"PieceSize": 1024,
|
||||
"RawBlockSize": 42
|
||||
},
|
||||
@@ -1445,7 +1456,9 @@ Response:
|
||||
"Root": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"PieceCid": null,
|
||||
"PieceCid": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"PieceSize": 1024,
|
||||
"RawBlockSize": 42
|
||||
},
|
||||
@@ -1510,7 +1523,9 @@ Response:
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"ID": 5,
|
||||
"PieceCID": null,
|
||||
"PieceCID": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"PricePerByte": "0",
|
||||
"UnsealPrice": "0",
|
||||
"Status": 0,
|
||||
@@ -1683,7 +1698,9 @@ Response:
|
||||
"Root": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"PieceCid": null,
|
||||
"PieceCid": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"PieceSize": 1024,
|
||||
"RawBlockSize": 42
|
||||
},
|
||||
@@ -1748,7 +1765,9 @@ Response:
|
||||
{
|
||||
"Key": 50,
|
||||
"Err": "string value",
|
||||
"Root": null,
|
||||
"Root": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"Source": "string value",
|
||||
"FilePath": "string value",
|
||||
"CARPath": "string value"
|
||||
@@ -1773,7 +1792,9 @@ Response:
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"ID": 5,
|
||||
"PieceCID": null,
|
||||
"PieceCID": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"PricePerByte": "0",
|
||||
"UnsealPrice": "0",
|
||||
"Status": 0,
|
||||
@@ -1834,7 +1855,9 @@ Inputs:
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
null
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
@@ -1845,7 +1868,9 @@ Response:
|
||||
"Root": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"Piece": null,
|
||||
"Piece": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"Size": 42,
|
||||
"MinPrice": "0",
|
||||
"UnsealPrice": "0",
|
||||
@@ -1856,7 +1881,9 @@ Response:
|
||||
"MinerPeer": {
|
||||
"Address": "f01234",
|
||||
"ID": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
||||
"PieceCID": null
|
||||
"PieceCID": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -1933,7 +1960,9 @@ Inputs:
|
||||
"Root": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"Piece": null,
|
||||
"Piece": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"DatamodelPathSelector": "Links/21/Hash/Links/42/Hash",
|
||||
"Size": 42,
|
||||
"FromLocalCAR": "string value",
|
||||
@@ -1946,7 +1975,9 @@ Inputs:
|
||||
"MinerPeer": {
|
||||
"Address": "f01234",
|
||||
"ID": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
||||
"PieceCID": null
|
||||
"PieceCID": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1988,7 +2019,9 @@ Inputs:
|
||||
"Root": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"Piece": null,
|
||||
"Piece": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"DatamodelPathSelector": "Links/21/Hash/Links/42/Hash",
|
||||
"Size": 42,
|
||||
"FromLocalCAR": "string value",
|
||||
@@ -2001,7 +2034,9 @@ Inputs:
|
||||
"MinerPeer": {
|
||||
"Address": "f01234",
|
||||
"ID": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
||||
"PieceCID": null
|
||||
"PieceCID": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2037,7 +2072,9 @@ Inputs:
|
||||
"Root": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"PieceCid": null,
|
||||
"PieceCid": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"PieceSize": 1024,
|
||||
"RawBlockSize": 42
|
||||
},
|
||||
@@ -2053,7 +2090,12 @@ Inputs:
|
||||
]
|
||||
```
|
||||
|
||||
Response: `null`
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
```
|
||||
|
||||
### ClientStatelessDeal
|
||||
ClientStatelessDeal fire-and-forget-proposes an offline deal to a miner without subsequent tracking.
|
||||
@@ -2070,7 +2112,9 @@ Inputs:
|
||||
"Root": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"PieceCid": null,
|
||||
"PieceCid": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"PieceSize": 1024,
|
||||
"RawBlockSize": 42
|
||||
},
|
||||
@@ -2086,7 +2130,12 @@ Inputs:
|
||||
]
|
||||
```
|
||||
|
||||
Response: `null`
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
```
|
||||
|
||||
## Create
|
||||
|
||||
@@ -2613,7 +2662,9 @@ Response:
|
||||
{
|
||||
"SealProof": 8,
|
||||
"SectorNumber": 9,
|
||||
"SectorKey": null,
|
||||
"SectorKey": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"SealedCID": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
@@ -4156,7 +4207,9 @@ Response:
|
||||
"PendingAmt": "0",
|
||||
"NonReservedAmt": "0",
|
||||
"PendingAvailableAmt": "0",
|
||||
"PendingWaitSentinel": null,
|
||||
"PendingWaitSentinel": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"QueuedAmt": "0",
|
||||
"VoucherReedeemedAmt": "0"
|
||||
}
|
||||
@@ -4185,7 +4238,9 @@ Response:
|
||||
"PendingAmt": "0",
|
||||
"NonReservedAmt": "0",
|
||||
"PendingAvailableAmt": "0",
|
||||
"PendingWaitSentinel": null,
|
||||
"PendingWaitSentinel": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"QueuedAmt": "0",
|
||||
"VoucherReedeemedAmt": "0"
|
||||
}
|
||||
@@ -4792,7 +4847,10 @@ Response:
|
||||
"MsgRct": {
|
||||
"ExitCode": 0,
|
||||
"Return": "Ynl0ZSBhcnJheQ==",
|
||||
"GasUsed": 9
|
||||
"GasUsed": 9,
|
||||
"EventsRoot": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
},
|
||||
"GasCost": {
|
||||
"Message": {
|
||||
@@ -4825,7 +4883,10 @@ Response:
|
||||
"MsgRct": {
|
||||
"ExitCode": 0,
|
||||
"Return": "Ynl0ZSBhcnJheQ==",
|
||||
"GasUsed": 9
|
||||
"GasUsed": 9,
|
||||
"EventsRoot": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
},
|
||||
"Error": "string value",
|
||||
"Duration": 60000000000,
|
||||
@@ -4869,7 +4930,10 @@ Response:
|
||||
"MsgRct": {
|
||||
"ExitCode": 0,
|
||||
"Return": "Ynl0ZSBhcnJheQ==",
|
||||
"GasUsed": 9
|
||||
"GasUsed": 9,
|
||||
"EventsRoot": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
},
|
||||
"Error": "string value",
|
||||
"Duration": 60000000000,
|
||||
@@ -5059,7 +5123,10 @@ Response:
|
||||
"MsgRct": {
|
||||
"ExitCode": 0,
|
||||
"Return": "Ynl0ZSBhcnJheQ==",
|
||||
"GasUsed": 9
|
||||
"GasUsed": 9,
|
||||
"EventsRoot": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
},
|
||||
"GasCost": {
|
||||
"Message": {
|
||||
@@ -5092,7 +5159,10 @@ Response:
|
||||
"MsgRct": {
|
||||
"ExitCode": 0,
|
||||
"Return": "Ynl0ZSBhcnJheQ==",
|
||||
"GasUsed": 9
|
||||
"GasUsed": 9,
|
||||
"EventsRoot": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
},
|
||||
"Error": "string value",
|
||||
"Duration": 60000000000,
|
||||
@@ -5136,7 +5206,10 @@ Response:
|
||||
"MsgRct": {
|
||||
"ExitCode": 0,
|
||||
"Return": "Ynl0ZSBhcnJheQ==",
|
||||
"GasUsed": 9
|
||||
"GasUsed": 9,
|
||||
"EventsRoot": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
},
|
||||
"Error": "string value",
|
||||
"Duration": 60000000000,
|
||||
@@ -5460,7 +5533,8 @@ Response:
|
||||
"UpgradeChocolateHeight": 10101,
|
||||
"UpgradeOhSnapHeight": 10101,
|
||||
"UpgradeSkyrHeight": 10101,
|
||||
"UpgradeSharkHeight": 10101
|
||||
"UpgradeSharkHeight": 10101,
|
||||
"UpgradeHyggeHeight": 10101
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -5551,7 +5625,10 @@ Response:
|
||||
{
|
||||
"ExitCode": 0,
|
||||
"Return": "Ynl0ZSBhcnJheQ==",
|
||||
"GasUsed": 9
|
||||
"GasUsed": 9,
|
||||
"EventsRoot": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5864,7 +5941,9 @@ Response:
|
||||
"ExpectedStoragePledge": "0",
|
||||
"ReplacedSectorAge": 10101,
|
||||
"ReplacedDayReward": "0",
|
||||
"SectorKeyCID": null,
|
||||
"SectorKeyCID": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"SimpleQAPower": true
|
||||
}
|
||||
]
|
||||
@@ -6032,7 +6111,9 @@ Inputs:
|
||||
5432
|
||||
],
|
||||
"Expiration": 10101,
|
||||
"UnsealedCid": null
|
||||
"UnsealedCid": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
},
|
||||
[
|
||||
{
|
||||
@@ -6154,7 +6235,9 @@ Inputs:
|
||||
5432
|
||||
],
|
||||
"Expiration": 10101,
|
||||
"UnsealedCid": null
|
||||
"UnsealedCid": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
},
|
||||
[
|
||||
{
|
||||
@@ -6337,7 +6420,9 @@ Response:
|
||||
"ExpectedStoragePledge": "0",
|
||||
"ReplacedSectorAge": 10101,
|
||||
"ReplacedDayReward": "0",
|
||||
"SectorKeyCID": null,
|
||||
"SectorKeyCID": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"SimpleQAPower": true
|
||||
}
|
||||
]
|
||||
@@ -6470,7 +6555,10 @@ Response:
|
||||
"MsgRct": {
|
||||
"ExitCode": 0,
|
||||
"Return": "Ynl0ZSBhcnJheQ==",
|
||||
"GasUsed": 9
|
||||
"GasUsed": 9,
|
||||
"EventsRoot": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
},
|
||||
"GasCost": {
|
||||
"Message": {
|
||||
@@ -6503,7 +6591,10 @@ Response:
|
||||
"MsgRct": {
|
||||
"ExitCode": 0,
|
||||
"Return": "Ynl0ZSBhcnJheQ==",
|
||||
"GasUsed": 9
|
||||
"GasUsed": 9,
|
||||
"EventsRoot": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
},
|
||||
"Error": "string value",
|
||||
"Duration": 60000000000,
|
||||
@@ -6547,7 +6638,10 @@ Response:
|
||||
"MsgRct": {
|
||||
"ExitCode": 0,
|
||||
"Return": "Ynl0ZSBhcnJheQ==",
|
||||
"GasUsed": 9
|
||||
"GasUsed": 9,
|
||||
"EventsRoot": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
},
|
||||
"Error": "string value",
|
||||
"Duration": 60000000000,
|
||||
@@ -6618,7 +6712,10 @@ Response:
|
||||
"Receipt": {
|
||||
"ExitCode": 0,
|
||||
"Return": "Ynl0ZSBhcnJheQ==",
|
||||
"GasUsed": 9
|
||||
"GasUsed": 9,
|
||||
"EventsRoot": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
},
|
||||
"ReturnDec": {},
|
||||
"TipSet": [
|
||||
@@ -6672,7 +6769,10 @@ Response:
|
||||
"Receipt": {
|
||||
"ExitCode": 0,
|
||||
"Return": "Ynl0ZSBhcnJheQ==",
|
||||
"GasUsed": 9
|
||||
"GasUsed": 9,
|
||||
"EventsRoot": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
},
|
||||
"ReturnDec": {},
|
||||
"TipSet": [
|
||||
@@ -6761,7 +6861,9 @@ Response:
|
||||
"ExpectedStoragePledge": "0",
|
||||
"ReplacedSectorAge": 10101,
|
||||
"ReplacedDayReward": "0",
|
||||
"SectorKeyCID": null,
|
||||
"SectorKeyCID": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
"SimpleQAPower": true
|
||||
}
|
||||
```
|
||||
@@ -6832,7 +6934,9 @@ Response:
|
||||
5432
|
||||
],
|
||||
"Expiration": 10101,
|
||||
"UnsealedCid": null
|
||||
"UnsealedCid": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
},
|
||||
"PreCommitDeposit": "0",
|
||||
"PreCommitEpoch": 10101
|
||||
@@ -6984,7 +7088,10 @@ Response:
|
||||
"Receipt": {
|
||||
"ExitCode": 0,
|
||||
"Return": "Ynl0ZSBhcnJheQ==",
|
||||
"GasUsed": 9
|
||||
"GasUsed": 9,
|
||||
"EventsRoot": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
},
|
||||
"ReturnDec": {},
|
||||
"TipSet": [
|
||||
@@ -7041,7 +7148,10 @@ Response:
|
||||
"Receipt": {
|
||||
"ExitCode": 0,
|
||||
"Return": "Ynl0ZSBhcnJheQ==",
|
||||
"GasUsed": 9
|
||||
"GasUsed": 9,
|
||||
"EventsRoot": {
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
},
|
||||
"ReturnDec": {},
|
||||
"TipSet": [
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,7 @@ COMMANDS:
|
||||
log Manage logging
|
||||
wait-api Wait for lotus api to come online
|
||||
fetch-params Fetch proving parameters
|
||||
evm Commands related to the Filecoin EVM runtime
|
||||
NETWORK:
|
||||
net Manage P2P Network
|
||||
sync Inspect or interact with the chain syncer
|
||||
@@ -2539,6 +2540,95 @@ OPTIONS:
|
||||
|
||||
```
|
||||
|
||||
## lotus evm
|
||||
```
|
||||
NAME:
|
||||
lotus evm - Commands related to the Filecoin EVM runtime
|
||||
|
||||
USAGE:
|
||||
lotus evm command [command options] [arguments...]
|
||||
|
||||
COMMANDS:
|
||||
deploy Deploy an EVM smart contract and return its address
|
||||
invoke Invoke an EVM smart contract using the specified CALLDATA
|
||||
stat Print eth/filecoin addrs and code cid
|
||||
call Simulate an eth contract call
|
||||
contract-address Generate contract address from smart contract code
|
||||
help, h Shows a list of commands or help for one command
|
||||
|
||||
OPTIONS:
|
||||
--help, -h show help (default: false)
|
||||
|
||||
```
|
||||
|
||||
### lotus evm deploy
|
||||
```
|
||||
NAME:
|
||||
lotus evm deploy - Deploy an EVM smart contract and return its address
|
||||
|
||||
USAGE:
|
||||
lotus evm deploy [command options] contract
|
||||
|
||||
OPTIONS:
|
||||
--from value optionally specify the account to use for sending the creation message
|
||||
--hex use when input contract is in hex (default: false)
|
||||
|
||||
```
|
||||
|
||||
### lotus evm invoke
|
||||
```
|
||||
NAME:
|
||||
lotus evm invoke - Invoke an EVM smart contract using the specified CALLDATA
|
||||
|
||||
USAGE:
|
||||
lotus evm invoke [command options] address calldata
|
||||
|
||||
OPTIONS:
|
||||
--from value optionally specify the account to use for sending the exec message
|
||||
--value value optionally specify the value to be sent with the invokation message (default: 0)
|
||||
|
||||
```
|
||||
|
||||
### lotus evm stat
|
||||
```
|
||||
NAME:
|
||||
lotus evm stat - Print eth/filecoin addrs and code cid
|
||||
|
||||
USAGE:
|
||||
lotus evm stat [command options] [arguments...]
|
||||
|
||||
OPTIONS:
|
||||
--ethAddr value Ethereum address
|
||||
--filAddr value Filecoin address
|
||||
|
||||
```
|
||||
|
||||
### lotus evm call
|
||||
```
|
||||
NAME:
|
||||
lotus evm call - Simulate an eth contract call
|
||||
|
||||
USAGE:
|
||||
lotus evm call [command options] [from] [to] [params]
|
||||
|
||||
OPTIONS:
|
||||
--help, -h show help (default: false)
|
||||
|
||||
```
|
||||
|
||||
### lotus evm contract-address
|
||||
```
|
||||
NAME:
|
||||
lotus evm contract-address - Generate contract address from smart contract code
|
||||
|
||||
USAGE:
|
||||
lotus evm contract-address [command options] [senderEthAddr] [salt] [contractHexPath]
|
||||
|
||||
OPTIONS:
|
||||
--help, -h show help (default: false)
|
||||
|
||||
```
|
||||
|
||||
## lotus net
|
||||
```
|
||||
NAME:
|
||||
|
||||
@@ -293,3 +293,53 @@
|
||||
#Tracing = false
|
||||
|
||||
|
||||
[ActorEvent]
|
||||
# EnableRealTimeFilterAPI enables APIs that can create and query filters for actor events as they are emitted.
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_ACTOREVENT_ENABLEREALTIMEFILTERAPI
|
||||
#EnableRealTimeFilterAPI = false
|
||||
|
||||
# EnableHistoricFilterAPI enables APIs that can create and query filters for actor events that occurred in the past.
|
||||
# A queryable index of events will be maintained.
|
||||
#
|
||||
# type: bool
|
||||
# env var: LOTUS_ACTOREVENT_ENABLEHISTORICFILTERAPI
|
||||
#EnableHistoricFilterAPI = false
|
||||
|
||||
# FilterTTL specifies the time to live for actor event filters. Filters that haven't been accessed longer than
|
||||
# this time become eligible for automatic deletion.
|
||||
#
|
||||
# type: Duration
|
||||
# env var: LOTUS_ACTOREVENT_FILTERTTL
|
||||
#FilterTTL = "24h0m0s"
|
||||
|
||||
# MaxFilters specifies the maximum number of filters that may exist at any one time.
|
||||
#
|
||||
# type: int
|
||||
# env var: LOTUS_ACTOREVENT_MAXFILTERS
|
||||
#MaxFilters = 100
|
||||
|
||||
# MaxFilterResults specifies the maximum number of results that can be accumulated by an actor event filter.
|
||||
#
|
||||
# type: int
|
||||
# env var: LOTUS_ACTOREVENT_MAXFILTERRESULTS
|
||||
#MaxFilterResults = 10000
|
||||
|
||||
# MaxFilterHeightRange specifies the maximum range of heights that can be used in a filter (to avoid querying
|
||||
# the entire chain)
|
||||
#
|
||||
# type: uint64
|
||||
# env var: LOTUS_ACTOREVENT_MAXFILTERHEIGHTRANGE
|
||||
#MaxFilterHeightRange = 2880
|
||||
|
||||
# ActorEventDatabasePath is the full path to a sqlite database that will be used to index actor events to
|
||||
# support the historic filter APIs. If the database does not exist it will be created. The directory containing
|
||||
# the database must already exist and be writeable. If a relative path is provided here, sqlite treats it as
|
||||
# relative to the CWD (current working directory).
|
||||
#
|
||||
# type: string
|
||||
# env var: LOTUS_ACTOREVENT_ACTOREVENTDATABASEPATH
|
||||
#ActorEventDatabasePath = ""
|
||||
|
||||
|
||||
|
||||
Vendored
+1
-1
Submodule extern/filecoin-ffi updated: 02ebb2d616...c4adeb4532
@@ -25,6 +25,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/lib/sigs"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/delegated"
|
||||
_ "github.com/filecoin-project/lotus/lib/sigs/secp"
|
||||
"github.com/filecoin-project/lotus/metrics"
|
||||
"github.com/filecoin-project/lotus/node/impl/full"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user