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:
parent
048ccc71bb
commit
cdf3812e40
@ -720,6 +720,46 @@ workflows:
|
|||||||
suite: itest-dup_mpool_messages
|
suite: itest-dup_mpool_messages
|
||||||
target: "./itests/dup_mpool_messages_test.go"
|
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:
|
- test:
|
||||||
name: test-itest-gas_estimation
|
name: test-itest-gas_estimation
|
||||||
suite: itest-gas_estimation
|
suite: itest-gas_estimation
|
||||||
@ -755,6 +795,11 @@ workflows:
|
|||||||
suite: itest-migration_nv17
|
suite: itest-migration_nv17
|
||||||
target: "./itests/migration_nv17_test.go"
|
target: "./itests/migration_nv17_test.go"
|
||||||
|
|
||||||
|
- test:
|
||||||
|
name: test-itest-migration_nv18
|
||||||
|
suite: itest-migration_nv18
|
||||||
|
target: "./itests/migration_nv18_test.go"
|
||||||
|
|
||||||
- test:
|
- test:
|
||||||
name: test-itest-mpool_msg_uuid
|
name: test-itest-mpool_msg_uuid
|
||||||
suite: itest-mpool_msg_uuid
|
suite: itest-mpool_msg_uuid
|
||||||
|
6
Makefile
6
Makefile
@ -84,6 +84,12 @@ butterflynet: build-devnets
|
|||||||
interopnet: GOFLAGS+=-tags=interopnet
|
interopnet: GOFLAGS+=-tags=interopnet
|
||||||
interopnet: build-devnets
|
interopnet: build-devnets
|
||||||
|
|
||||||
|
wallabynet: GOFLAGS+=-tags=wallabynet
|
||||||
|
wallabynet: build-devnets
|
||||||
|
|
||||||
|
hyperspacenet: GOFLAGS+=-tags=hyperspacenet
|
||||||
|
hyperspacenet: build-devnets
|
||||||
|
|
||||||
lotus: $(BUILD_DEPS)
|
lotus: $(BUILD_DEPS)
|
||||||
rm -f lotus
|
rm -f lotus
|
||||||
$(GOCC) build $(GOFLAGS) -o lotus ./cmd/lotus
|
$(GOCC) build $(GOFLAGS) -o lotus ./cmd/lotus
|
||||||
|
@ -31,6 +31,7 @@ import (
|
|||||||
lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
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/actors/builtin/power"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"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/modules/dtypes"
|
||||||
"github.com/filecoin-project/lotus/node/repo/imports"
|
"github.com/filecoin-project/lotus/node/repo/imports"
|
||||||
)
|
)
|
||||||
@ -182,6 +183,9 @@ type FullNode interface {
|
|||||||
// ChainBlockstoreInfo returns some basic information about the blockstore
|
// ChainBlockstoreInfo returns some basic information about the blockstore
|
||||||
ChainBlockstoreInfo(context.Context) (map[string]interface{}, error) //perm:read
|
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 estimates gas fee cap
|
||||||
GasEstimateFeeCap(context.Context, *types.Message, int64, types.TipSetKey) (types.BigInt, error) //perm:read
|
GasEstimateFeeCap(context.Context, *types.Message, int64, types.TipSetKey) (types.BigInt, error) //perm:read
|
||||||
|
|
||||||
@ -759,6 +763,77 @@ type FullNode interface {
|
|||||||
|
|
||||||
NodeStatus(ctx context.Context, inclChainStatus bool) (NodeStatus, error) //perm:read
|
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
|
// CreateBackup creates node backup onder the specified file name. The
|
||||||
// method requires that the lotus daemon is running with the
|
// method requires that the lotus daemon is running with the
|
||||||
// LOTUS_BACKUP_BASE_PATH environment variable set to some path, and that
|
// LOTUS_BACKUP_BASE_PATH environment variable set to some path, and that
|
||||||
@ -1252,3 +1327,21 @@ type PruneOpts struct {
|
|||||||
MovingGC bool
|
MovingGC bool
|
||||||
RetainState int64
|
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"`
|
||||||
|
}
|
||||||
|
@ -22,7 +22,7 @@ import (
|
|||||||
"github.com/filecoin-project/go-state-types/builtin/v9/miner"
|
"github.com/filecoin-project/go-state-types/builtin/v9/miner"
|
||||||
abinetwork "github.com/filecoin-project/go-state-types/network"
|
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/chain/types"
|
||||||
"github.com/filecoin-project/lotus/storage/pipeline/sealiface"
|
"github.com/filecoin-project/lotus/storage/pipeline/sealiface"
|
||||||
"github.com/filecoin-project/lotus/storage/sealer/fsutil"
|
"github.com/filecoin-project/lotus/storage/sealer/fsutil"
|
||||||
@ -322,7 +322,7 @@ type StorageMiner interface {
|
|||||||
|
|
||||||
CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storiface.SectorRef) (map[abi.SectorNumber]string, error) //perm:admin
|
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
|
// 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
|
// to the miner actor with details of recovered sectors and returns the CID of messages. It honors the
|
||||||
|
@ -41,6 +41,7 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/api/v0api"
|
"github.com/filecoin-project/lotus/api/v0api"
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"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/modules/dtypes"
|
||||||
"github.com/filecoin-project/lotus/node/repo/imports"
|
"github.com/filecoin-project/lotus/node/repo/imports"
|
||||||
sealing "github.com/filecoin-project/lotus/storage/pipeline"
|
sealing "github.com/filecoin-project/lotus/storage/pipeline"
|
||||||
@ -68,6 +69,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ExampleValues[reflect.TypeOf(c)] = c
|
ExampleValues[reflect.TypeOf(c)] = c
|
||||||
|
ExampleValues[reflect.TypeOf(&c)] = &c
|
||||||
|
|
||||||
c2, err := cid.Decode("bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve")
|
c2, err := cid.Decode("bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -298,7 +300,8 @@ func init() {
|
|||||||
"title": "Lotus RPC API",
|
"title": "Lotus RPC API",
|
||||||
"version": "1.2.1/generated=2020-11-22T08:22:42-06:00",
|
"version": "1.2.1/generated=2020-11-22T08:22:42-06:00",
|
||||||
},
|
},
|
||||||
"methods": []interface{}{}},
|
"methods": []interface{}{},
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
addExample(api.CheckStatusCode(0))
|
addExample(api.CheckStatusCode(0))
|
||||||
@ -335,7 +338,8 @@ func init() {
|
|||||||
NumConnsInbound: 3,
|
NumConnsInbound: 3,
|
||||||
NumConnsOutbound: 4,
|
NumConnsOutbound: 4,
|
||||||
NumFD: 5,
|
NumFD: 5,
|
||||||
}})
|
},
|
||||||
|
})
|
||||||
addExample(api.NetLimit{
|
addExample(api.NetLimit{
|
||||||
Memory: 123,
|
Memory: 123,
|
||||||
StreamsInbound: 1,
|
StreamsInbound: 1,
|
||||||
@ -346,6 +350,7 @@ func init() {
|
|||||||
Conns: 4,
|
Conns: 4,
|
||||||
FD: 5,
|
FD: 5,
|
||||||
})
|
})
|
||||||
|
|
||||||
addExample(map[string]bitfield.BitField{
|
addExample(map[string]bitfield.BitField{
|
||||||
"": bitfield.NewFromSet([]uint64{5, 6, 7, 10}),
|
"": bitfield.NewFromSet([]uint64{5, 6, 7, 10}),
|
||||||
})
|
})
|
||||||
@ -365,11 +370,40 @@ func init() {
|
|||||||
Headers: nil,
|
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{})
|
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) {
|
func GetAPIType(name, pkg string) (i interface{}, t reflect.Type, permStruct []reflect.Type) {
|
||||||
|
|
||||||
switch pkg {
|
switch pkg {
|
||||||
case "api": // latest
|
case "api": // latest
|
||||||
switch name {
|
switch name {
|
||||||
@ -439,7 +473,7 @@ func ExampleValue(method string, t, parent reflect.Type) interface{} {
|
|||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
if t.Elem().Kind() == reflect.Struct {
|
if t.Elem().Kind() == reflect.Struct {
|
||||||
es := exampleStruct(method, t.Elem(), t)
|
es := exampleStruct(method, t.Elem(), t)
|
||||||
//ExampleValues[t] = es
|
ExampleValues[t] = es
|
||||||
return es
|
return es
|
||||||
}
|
}
|
||||||
case reflect.Interface:
|
case reflect.Interface:
|
||||||
|
@ -37,6 +37,7 @@ import (
|
|||||||
apitypes "github.com/filecoin-project/lotus/api/types"
|
apitypes "github.com/filecoin-project/lotus/api/types"
|
||||||
miner0 "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
miner0 "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||||
types "github.com/filecoin-project/lotus/chain/types"
|
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"
|
alerting "github.com/filecoin-project/lotus/journal/alerting"
|
||||||
dtypes "github.com/filecoin-project/lotus/node/modules/dtypes"
|
dtypes "github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||||
imports "github.com/filecoin-project/lotus/node/repo/imports"
|
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)
|
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.
|
// ChainGetGenesis mocks base method.
|
||||||
func (m *MockFullNode) ChainGetGenesis(arg0 context.Context) (*types.TipSet, error) {
|
func (m *MockFullNode) ChainGetGenesis(arg0 context.Context) (*types.TipSet, error) {
|
||||||
m.ctrl.T.Helper()
|
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)
|
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.
|
// GasEstimateFeeCap mocks base method.
|
||||||
func (m *MockFullNode) GasEstimateFeeCap(arg0 context.Context, arg1 *types.Message, arg2 int64, arg3 types.TipSetKey) (big.Int, error) {
|
func (m *MockFullNode) GasEstimateFeeCap(arg0 context.Context, arg1 *types.Message, arg2 int64, arg3 types.TipSetKey) (big.Int, error) {
|
||||||
m.ctrl.T.Helper()
|
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)
|
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.
|
// NetPeerInfo mocks base method.
|
||||||
func (m *MockFullNode) NetPeerInfo(arg0 context.Context, arg1 peer.ID) (*api.ExtendedPeerInfo, error) {
|
func (m *MockFullNode) NetPeerInfo(arg0 context.Context, arg1 peer.ID) (*api.ExtendedPeerInfo, error) {
|
||||||
m.ctrl.T.Helper()
|
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)
|
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.
|
// NodeStatus mocks base method.
|
||||||
func (m *MockFullNode) NodeStatus(arg0 context.Context, arg1 bool) (api.NodeStatus, error) {
|
func (m *MockFullNode) NodeStatus(arg0 context.Context, arg1 bool) (api.NodeStatus, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
455
api/proxy_gen.go
455
api/proxy_gen.go
@ -33,9 +33,10 @@ import (
|
|||||||
"github.com/filecoin-project/go-state-types/proof"
|
"github.com/filecoin-project/go-state-types/proof"
|
||||||
|
|
||||||
apitypes "github.com/filecoin-project/lotus/api/types"
|
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"
|
lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"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/journal/alerting"
|
||||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||||
"github.com/filecoin-project/lotus/node/repo/imports"
|
"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"`
|
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"`
|
ChainGetGenesis func(p0 context.Context) (*types.TipSet, error) `perm:"read"`
|
||||||
|
|
||||||
ChainGetMessage func(p0 context.Context, p1 cid.Cid) (*types.Message, error) `perm:"read"`
|
ChainGetMessage func(p0 context.Context, p1 cid.Cid) (*types.Message, error) `perm:"read"`
|
||||||
@ -218,6 +221,68 @@ type FullNodeStruct struct {
|
|||||||
|
|
||||||
CreateBackup func(p0 context.Context, p1 string) error `perm:"admin"`
|
CreateBackup func(p0 context.Context, p1 string) error `perm:"admin"`
|
||||||
|
|
||||||
|
EthAccounts func(p0 context.Context) ([]ethtypes.EthAddress, error) `perm:"read"`
|
||||||
|
|
||||||
|
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"`
|
GasEstimateFeeCap func(p0 context.Context, p1 *types.Message, p2 int64, p3 types.TipSetKey) (types.BigInt, error) `perm:"read"`
|
||||||
|
|
||||||
GasEstimateGasLimit func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (int64, error) `perm:"read"`
|
GasEstimateGasLimit func(p0 context.Context, p1 *types.Message, p2 types.TipSetKey) (int64, error) `perm:"read"`
|
||||||
@ -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"`
|
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"`
|
NodeStatus func(p0 context.Context, p1 bool) (NodeStatus, error) `perm:"read"`
|
||||||
|
|
||||||
PaychAllocateLane func(p0 context.Context, p1 address.Address) (uint64, error) `perm:"sign"`
|
PaychAllocateLane func(p0 context.Context, p1 address.Address) (uint64, error) `perm:"sign"`
|
||||||
@ -687,7 +756,7 @@ type StorageMinerStruct struct {
|
|||||||
|
|
||||||
ComputeDataCid func(p0 context.Context, p1 abi.UnpaddedPieceSize, p2 storiface.Data) (abi.PieceInfo, error) `perm:"admin"`
|
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"`
|
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
|
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) {
|
func (s *FullNodeStruct) ChainGetGenesis(p0 context.Context) (*types.TipSet, error) {
|
||||||
if s.Internal.ChainGetGenesis == nil {
|
if s.Internal.ChainGetGenesis == nil {
|
||||||
return nil, ErrNotSupported
|
return nil, ErrNotSupported
|
||||||
@ -1795,6 +1875,347 @@ func (s *FullNodeStub) CreateBackup(p0 context.Context, p1 string) error {
|
|||||||
return ErrNotSupported
|
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) {
|
func (s *FullNodeStruct) GasEstimateFeeCap(p0 context.Context, p1 *types.Message, p2 int64, p3 types.TipSetKey) (types.BigInt, error) {
|
||||||
if s.Internal.GasEstimateFeeCap == nil {
|
if s.Internal.GasEstimateFeeCap == nil {
|
||||||
return *new(types.BigInt), ErrNotSupported
|
return *new(types.BigInt), ErrNotSupported
|
||||||
@ -2279,6 +2700,28 @@ func (s *FullNodeStub) MsigSwapPropose(p0 context.Context, p1 address.Address, p
|
|||||||
return nil, ErrNotSupported
|
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) {
|
func (s *FullNodeStruct) NodeStatus(p0 context.Context, p1 bool) (NodeStatus, error) {
|
||||||
if s.Internal.NodeStatus == nil {
|
if s.Internal.NodeStatus == nil {
|
||||||
return *new(NodeStatus), ErrNotSupported
|
return *new(NodeStatus), ErrNotSupported
|
||||||
@ -4182,15 +4625,15 @@ func (s *StorageMinerStub) ComputeDataCid(p0 context.Context, p1 abi.UnpaddedPie
|
|||||||
return *new(abi.PieceInfo), ErrNotSupported
|
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 {
|
if s.Internal.ComputeProof == nil {
|
||||||
return *new([]builtin.PoStProof), ErrNotSupported
|
return *new([]builtinactors.PoStProof), ErrNotSupported
|
||||||
}
|
}
|
||||||
return s.Internal.ComputeProof(p0, p1, p2, p3, p4)
|
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) {
|
func (s *StorageMinerStub) ComputeProof(p0 context.Context, p1 []builtinactors.ExtendedSectorInfo, p2 abi.PoStRandomness, p3 abi.ChainEpoch, p4 abinetwork.Version) ([]builtinactors.PoStProof, error) {
|
||||||
return *new([]builtin.PoStProof), ErrNotSupported
|
return *new([]builtinactors.PoStProof), ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StorageMinerStruct) ComputeWindowPoSt(p0 context.Context, p1 uint64, p2 types.TipSetKey) ([]miner.SubmitWindowedPoStParams, error) {
|
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
|
UpgradeOhSnapHeight abi.ChainEpoch
|
||||||
UpgradeSkyrHeight abi.ChainEpoch
|
UpgradeSkyrHeight abi.ChainEpoch
|
||||||
UpgradeSharkHeight abi.ChainEpoch
|
UpgradeSharkHeight abi.ChainEpoch
|
||||||
|
UpgradeHyggeHeight abi.ChainEpoch
|
||||||
}
|
}
|
||||||
|
|
||||||
type NonceMapType map[address.Address]uint64
|
type NonceMapType map[address.Address]uint64
|
||||||
|
@ -905,6 +905,10 @@ func (s *SplitStore) walkChain(ts *types.TipSet, inclState, inclMsgs abi.ChainEp
|
|||||||
walkCnt := new(int64)
|
walkCnt := new(int64)
|
||||||
scanCnt := 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 }
|
stopWalk := func(_ cid.Cid) error { return errStopWalk }
|
||||||
|
|
||||||
walkBlock := func(c cid.Cid) error {
|
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 {
|
err = s.view(c, func(data []byte) error {
|
||||||
return hdr.UnmarshalCBOR(bytes.NewBuffer(data))
|
return hdr.UnmarshalCBOR(bytes.NewBuffer(data))
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("error unmarshaling block header (cid: %s): %w", c, err)
|
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
|
// message are retained if within the inclMsgs boundary
|
||||||
if hdr.Height >= inclMsgs && hdr.Height > 0 {
|
if hdr.Height >= inclMsgs && hdr.Height > 0 {
|
||||||
if inclMsgs < inclState {
|
if inclMsgs < inclState {
|
||||||
@ -981,6 +993,15 @@ func (s *SplitStore) walkChain(ts *types.TipSet, inclState, inclMsgs abi.ChainEp
|
|||||||
return nil
|
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 {
|
for len(toWalk) > 0 {
|
||||||
// walking can take a while, so check this with every opportunity
|
// walking can take a while, so check this with every opportunity
|
||||||
if err := s.checkClosing(); err != nil {
|
if err := s.checkClosing(); err != nil {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/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
|
set -e
|
||||||
|
|
||||||
|
Binary file not shown.
4
build/bootstrap/wallabynet.pi
Normal file
4
build/bootstrap/wallabynet.pi
Normal file
@ -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
|
@ -44,23 +44,24 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
|
|||||||
}, {
|
}, {
|
||||||
Network: "butterflynet",
|
Network: "butterflynet",
|
||||||
Version: 10,
|
Version: 10,
|
||||||
ManifestCid: MustParseCid("bafy2bzaceciz4ytt5gnn6gc4epez7v6xeg6efkgbvwfxkoa34o2gj3hp5f7zc"),
|
ManifestCid: MustParseCid("bafy2bzaceav7txndea2xt6kvaosokp42vyjkhtplbb67tpkov3jbsvbwplnz4"),
|
||||||
Actors: map[string]cid.Cid{
|
Actors: map[string]cid.Cid{
|
||||||
"account": MustParseCid("bafk2bzacedavorwsriewoddjlaganjpsk3o7zfts2wyid3clv5xnctacg37j2"),
|
"account": MustParseCid("bafk2bzacec34ox7drngorgal3ujxat2a2dlsh7eissgiisrv2uubuub2avbe2"),
|
||||||
"cron": MustParseCid("bafk2bzacebtauucwaewxuzgxfpjtmn6xt3kya4om4ugyprlkhhkde76h7fkqg"),
|
"cron": MustParseCid("bafk2bzaceb77n6gkytpkn2wguemnpfqfaynv7u6ci4j247leg2w3dhcoxa5ns"),
|
||||||
"datacap": MustParseCid("bafk2bzacebzdjapqwasq6woxkgq2nm2nre3v7cl2754xwiuo2cfhvsceq4cba"),
|
"datacap": MustParseCid("bafk2bzacebj2ztqmlb7mmkggaqf66sv7gao5722vzmpnngiuncu4efpsjyhy4"),
|
||||||
"eam": MustParseCid("bafk2bzacecmr4zdbpfnemvgo446qby7x4y4v5cbfespt3f6ousv2hxnflyrlk"),
|
"eam": MustParseCid("bafk2bzacecvl6xpmldfk5oyehqhmuasp7cbx3kh3y425curdy65hlmhovc4oi"),
|
||||||
"embryo": MustParseCid("bafk2bzacebj2mj5zlcs3yjlgpbznzistfjkdlwaoncjziliqrxqavvz4dcvnk"),
|
"ethaccount": MustParseCid("bafk2bzacec2wy3fknb63r5zili7qojvt4f3rvstweqvnjne5adarx3lskgz5m"),
|
||||||
"evm": MustParseCid("bafk2bzacebuewexvig54cuvsvwn4k4zr36tm2q5fel4ezq4v7363n2lmn362k"),
|
"evm": MustParseCid("bafk2bzacebtoqzucrh7kvtxpo4ruzisey67z6t3z5cbff4c36du3dlm3aj4l6"),
|
||||||
"init": MustParseCid("bafk2bzacebww5gsctsk5hack2alkt4kh55bmpb4ywzbyyhoaskryymjj3snj6"),
|
"init": MustParseCid("bafk2bzacebvc5t5u3opeyx4rxbeinshjsghjhttdbsyqifb4ikzpa2ic5mkhu"),
|
||||||
"multisig": MustParseCid("bafk2bzacec5k4wxvou34pyjd5kcsrbsfnlk4k753kkscg3ron2r7tsxollfsq"),
|
"multisig": MustParseCid("bafk2bzaceckmb2bcw2m5o4hifhodrq2j6ow5nhouj5wpqsxpzntgveft3hplu"),
|
||||||
"paymentchannel": MustParseCid("bafk2bzacebzdeaxglaqpmegalakmxr6secjd24mu5llo4ctoy7pvom5upyuvs"),
|
"paymentchannel": MustParseCid("bafk2bzacebsvkpbavcdjguev4dxfnjx5j5bqzeeyk3petwbkmfptoej5bqlqc"),
|
||||||
"reward": MustParseCid("bafk2bzaceb4hyabxnyrrsno5erqqwk5ynnjibblzfcaq3aotlz3ek4uu6dyla"),
|
"placeholder": MustParseCid("bafk2bzacedv773z6clfjh7wxvlqd6ki7bncztt73org7apnnt2acjigrjdg4a"),
|
||||||
"storagemarket": MustParseCid("bafk2bzacedpocbf2lg2x2jg6arw2argnwmvo2hyjqvpkrgfu4khz5mtlzxz2o"),
|
"reward": MustParseCid("bafk2bzacea3rkyhzmugj6ap3uv5m5jnhxt64y2775vo6vemdi5aafzxty3nmq"),
|
||||||
"storageminer": MustParseCid("bafk2bzaceacrumah7jdfc62bmvemob4lsh5yiohwodest2cgxakgnn24cenlk"),
|
"storagemarket": MustParseCid("bafk2bzacebfacbnuauxhq63f5jbchoi2xwc5ljrxnwgj2xulkx4yzfu6i4lhg"),
|
||||||
"storagepower": MustParseCid("bafk2bzaceaxz6n5nywermfptnz6dc53vqsa42lic4rf66l4irm3mqfj4ak5ps"),
|
"storageminer": MustParseCid("bafk2bzaceal4ct6gwlzl3owu6d4iiudf4ioxth5gn6cvm37enl465px2bhznk"),
|
||||||
"system": MustParseCid("bafk2bzaceb4w5bblgyu25ylytpmfrixjsk2ra6emd44j4mv42xfxbwnqloyzi"),
|
"storagepower": MustParseCid("bafk2bzaceb5pdkt55d7wxjgmhvzvnlkuw5r6eamypgqm5kem5tz3sxddwtizw"),
|
||||||
"verifiedregistry": MustParseCid("bafk2bzacedbz2koeb6teewobcjdpgfv7qdae7utgoka6wzlkf6gronnis2nn2"),
|
"system": MustParseCid("bafk2bzacecuu2y5b6r4jrj64w5yuh3klnoevrcnbdxozmtagdcyfve7oe27ri"),
|
||||||
|
"verifiedregistry": MustParseCid("bafk2bzacediez3q42tjeit7hbsglv33ltfeamoa43lftwsxh2nyov5ijhuihm"),
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
Network: "calibrationnet",
|
Network: "calibrationnet",
|
||||||
@ -100,23 +101,24 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
|
|||||||
}, {
|
}, {
|
||||||
Network: "calibrationnet",
|
Network: "calibrationnet",
|
||||||
Version: 10,
|
Version: 10,
|
||||||
ManifestCid: MustParseCid("bafy2bzaced7wbd43lvgc55xb37mkoo4ppev6ig4jj4j7dtswtjfjq4u5qmpck"),
|
ManifestCid: MustParseCid("bafy2bzacebb4qaymahytofcakf3vcyuv4tnu4zsgxp4iikc6kkmfagtaierro"),
|
||||||
Actors: map[string]cid.Cid{
|
Actors: map[string]cid.Cid{
|
||||||
"account": MustParseCid("bafk2bzacecq4owv5begvryvpsy4atfb2jnf7g7o4hxovtdb5a4jfkzacownli"),
|
"account": MustParseCid("bafk2bzaceakcix46r7hh4wjhzaksnha6f5elbg62ld6dklz6ttkhisnppmoe2"),
|
||||||
"cron": MustParseCid("bafk2bzaced4uz5w5h5wksx4end27lphd4qc4kh7q336uyt46lba5ddynwftya"),
|
"cron": MustParseCid("bafk2bzaceb5ezi5dlgxjmxffecrmgiajwseiblgivho5qnfejivuqxfclooma"),
|
||||||
"datacap": MustParseCid("bafk2bzacedoc7y4s5n3p2zo4bcmafcrellkakn2e3uyf5wb3mtbuqhvwqn2l4"),
|
"datacap": MustParseCid("bafk2bzaceag4j2myqvwevm3mdtvmqoeguwtjheyezodjcpq5ugibjx6gtz65u"),
|
||||||
"eam": MustParseCid("bafk2bzacealpqjgz5qmucm3v6z6hn36igx7zijixhqrxwoj3g4bdgvyml3adi"),
|
"eam": MustParseCid("bafk2bzacedwnuqthwpl3si5gs27xnxq7bcr5ucg3vg4utltfhnytaqzwlk33g"),
|
||||||
"embryo": MustParseCid("bafk2bzacebj2mj5zlcs3yjlgpbznzistfjkdlwaoncjziliqrxqavvz4dcvnk"),
|
"ethaccount": MustParseCid("bafk2bzacechx3zdc4yw7ehtelecwsp6hb2iguefusfccqxfmdinjjoa64ado4"),
|
||||||
"evm": MustParseCid("bafk2bzacedmlmyy2efbt4qk5ighawiychklhzc6pzyiwvpijwvxoq3xyxlgxw"),
|
"evm": MustParseCid("bafk2bzaceaqtomr2odeyjabgkwnwfgm54b44cpshpkssn7nq35umzogkqqbee"),
|
||||||
"init": MustParseCid("bafk2bzaceaqcfmfylwdemq5bdcelydpf6iqfct4p7b2zwtmqyhuxn522yvic2"),
|
"init": MustParseCid("bafk2bzacebtqjmdudvfl5cq6yqswortlc46cjpz36qj5igzfglu55kppuovyw"),
|
||||||
"multisig": MustParseCid("bafk2bzacebuh55hkbkobmmoaoduruss5nsh6e2gtqtdbqsmw6e7k5vg6heyrm"),
|
"multisig": MustParseCid("bafk2bzaceb2hlrmljz26gecv7zj5ymeleiuebf6mnvc7vng3qbcxvxagrlc22"),
|
||||||
"paymentchannel": MustParseCid("bafk2bzacedcpzw7prdoxnaclcvmtwr6yf54zi4bzzwe5w3xknh72ji6p3qfc6"),
|
"paymentchannel": MustParseCid("bafk2bzacecbn4m6evxxoalujyt4wnas3hdttffzjee5qjp62w7dsjdoeuhzka"),
|
||||||
"reward": MustParseCid("bafk2bzaced74ym6j424zzbr6millasfcyl3r4zm5fnauasrwn3ti6fdarbkym"),
|
"placeholder": MustParseCid("bafk2bzacedv773z6clfjh7wxvlqd6ki7bncztt73org7apnnt2acjigrjdg4a"),
|
||||||
"storagemarket": MustParseCid("bafk2bzacec7delr2q42yj4wu3daa5xjz4zezeivphtx3xwyvpgwpdnfoevhh2"),
|
"reward": MustParseCid("bafk2bzaceds2kn4fn27nwlxx2raawldkytlro6i2qeh6rdtmme6ybd4otpwqq"),
|
||||||
"storageminer": MustParseCid("bafk2bzaced7isnew5lhu237pdtwaqmbv65qqvfmmnve2c5yfobtfqw2fptuvc"),
|
"storagemarket": MustParseCid("bafk2bzacec35rrhgiqqrwqjtuhoseg7e4g67sqaa74b2x2p7f37ylfulc672i"),
|
||||||
"storagepower": MustParseCid("bafk2bzacebe5frk6gcgzcvzkxavhhbs3id3iyacybn7y7gxwzgl5t6zawzswg"),
|
"storageminer": MustParseCid("bafk2bzaceaiwkboswmk4kmzctnzd5txf2axdvladlf6x5as7ey7avxa5dgfd4"),
|
||||||
"system": MustParseCid("bafk2bzacectivaezqijucle5s2f7xeui5uxig7bnk7fe4vsvz3xu7agjtb2ge"),
|
"storagepower": MustParseCid("bafk2bzaceb2nlgx5aw2psgiedc7oqefs6mttwcloczsbucxtit55zzpbgr4fc"),
|
||||||
"verifiedregistry": MustParseCid("bafk2bzaceczgwckte4exultjxyzgzoo6m6r5coyphnlappi4clethhhybslxc"),
|
"system": MustParseCid("bafk2bzacecki2gyvfguathvwva4ilovedftfuxvk3rhuw4y2t4aawkm2e5ttq"),
|
||||||
|
"verifiedregistry": MustParseCid("bafk2bzacebvicauwopayihp5jjegtma26nuhubauya73tkhpdfs27xwjutn4w"),
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
Network: "caterpillarnet",
|
Network: "caterpillarnet",
|
||||||
@ -156,23 +158,24 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
|
|||||||
}, {
|
}, {
|
||||||
Network: "caterpillarnet",
|
Network: "caterpillarnet",
|
||||||
Version: 10,
|
Version: 10,
|
||||||
ManifestCid: MustParseCid("bafy2bzacea5csj2os7h76a6yvf6shgpwkysawijxemk5uvvzejxrwjo6ir4yg"),
|
ManifestCid: MustParseCid("bafy2bzacedktxutlehqmx2uryphph6dln4wbgy6yfsj7un36b2u7l7a32n3km"),
|
||||||
Actors: map[string]cid.Cid{
|
Actors: map[string]cid.Cid{
|
||||||
"account": MustParseCid("bafk2bzacea7tpruyxdgyz4xa7curiphwdw4abmspft3ee24puruazdcl3tq5c"),
|
"account": MustParseCid("bafk2bzaceaoina2vmmq24ij5kqbgawjrlnxkmj6arzucoigabt25ch6cdvbyc"),
|
||||||
"cron": MustParseCid("bafk2bzacebc6kkj7kzsicm5baszjgd37b4b3kijsffqmmkhhjlyd7zhkwfcqm"),
|
"cron": MustParseCid("bafk2bzaceancnphwoym4pmzatrzfxo3bac72gk4bjgaqxedrigfrua62an3n2"),
|
||||||
"datacap": MustParseCid("bafk2bzaceddcmwl6po2jd3tfkkgv4zvub7i47gsx33pkqdspqhgvhe4npc4as"),
|
"datacap": MustParseCid("bafk2bzaceaoebtmqyqvyv7oq7ehdkhl6fxjamz5fjdje7axslxsc7rhqchcdm"),
|
||||||
"eam": MustParseCid("bafk2bzaceccsvcww2rmqnh4plkq6oapqaeqbhydrtup54z4dwunolz5tpgtb4"),
|
"eam": MustParseCid("bafk2bzaceazfxudfagmhdmwx46sjeyqoba3quy7cllqv2nuksh3ikc6gw63yg"),
|
||||||
"embryo": MustParseCid("bafk2bzacebj2mj5zlcs3yjlgpbznzistfjkdlwaoncjziliqrxqavvz4dcvnk"),
|
"ethaccount": MustParseCid("bafk2bzaceblsm6aaymb2ua64eqbe32uyxdoyqzger5recw6k4p43yeu2oyigi"),
|
||||||
"evm": MustParseCid("bafk2bzacea5sig3zpxfkqppoj3t344cvuhzvkx6ge2isgdzc34rfpng2ogdje"),
|
"evm": MustParseCid("bafk2bzacea7jveqmq5u6ijabkbuujtgqzmy3p5zl5x45frnygio3hqqnabbso"),
|
||||||
"init": MustParseCid("bafk2bzacedtby353aho7itoyoj7w6moydmigjm3sgy6djgnfxqehlpae4vcc2"),
|
"init": MustParseCid("bafk2bzacecdewh4goftyp2cmuq3zpkyjinv6faysksjgqxtbk2j5dljv75rgq"),
|
||||||
"multisig": MustParseCid("bafk2bzacedyguvwz5zfveqoqicn3j6lkdzipf247nhvdi6dvmahulr7nzgox6"),
|
"multisig": MustParseCid("bafk2bzacecpscu24o2fwlspi64k3fiaufeh3nnrv6wgumvaeco2jduhposcf4"),
|
||||||
"paymentchannel": MustParseCid("bafk2bzaceavaatmmnsz3v3ksopcbu6jx4iq7u7nnmqbclsiabsfkfu3zfpmka"),
|
"paymentchannel": MustParseCid("bafk2bzacedxc3fy436wlebsusgwcwqf6lzo7yv5iugy75z5hwrdt33pq2rhho"),
|
||||||
"reward": MustParseCid("bafk2bzacecrphs4avteik4yejsqwkpy5bcqramdhnzykbfq3uu2qalj2p26ti"),
|
"placeholder": MustParseCid("bafk2bzacedv773z6clfjh7wxvlqd6ki7bncztt73org7apnnt2acjigrjdg4a"),
|
||||||
"storagemarket": MustParseCid("bafk2bzaceajby2jb5m3fenzarum374zxdzuyrpkspfljwovu7c3hvyceqd5sa"),
|
"reward": MustParseCid("bafk2bzacebzvjtzzuo6ijkbx2yx3ly6vlrgw37fymasdwcdymlxc26znib2og"),
|
||||||
"storageminer": MustParseCid("bafk2bzacebqtn7jdvk756ighri5ajro6gjepnef3c6rxupbbgkth62zytiy5s"),
|
"storagemarket": MustParseCid("bafk2bzaceabdr5l4qluc4rgxjxo4xnoyc5e6slp7s3fojhnv4ng3swu7qv556"),
|
||||||
"storagepower": MustParseCid("bafk2bzacedwlo32brlalpovfkkk7qwo3ou2kpgv2bf7fioy5srn7uejmn7n46"),
|
"storageminer": MustParseCid("bafk2bzaceclwbgfqr7wqepi6xkpoqz2bl6p22mlbmsgs4zarxki2cub5rspxy"),
|
||||||
"system": MustParseCid("bafk2bzacebbt63h26x5vw5fdo2pmdb4q65u3t6lilkugvmjar6zfsc7ethxsi"),
|
"storagepower": MustParseCid("bafk2bzacean3trpjoxvwztrmbw7lx6osapicxzclyz2cgou4upq432norjnaq"),
|
||||||
"verifiedregistry": MustParseCid("bafk2bzacecr5kbyypdxnxlepzk5sji2k72t454vto5ok4owfcuwfpeyivjtu4"),
|
"system": MustParseCid("bafk2bzacedeexlnmp677eauba76trar47p2zddbspiodri5aof6ccasyicxxo"),
|
||||||
|
"verifiedregistry": MustParseCid("bafk2bzaceayctmu2avbckz4scuep3ocxsw5r3eqxz7wu27volaxnvfvoxjhbq"),
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
Network: "devnet",
|
Network: "devnet",
|
||||||
@ -212,23 +215,46 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
|
|||||||
}, {
|
}, {
|
||||||
Network: "devnet",
|
Network: "devnet",
|
||||||
Version: 10,
|
Version: 10,
|
||||||
ManifestCid: MustParseCid("bafy2bzacea73thrlpfejrswlcu5uhe7rcgdewvmrcwoef6jzngsba3i4v5ibi"),
|
ManifestCid: MustParseCid("bafy2bzacea2wblucgi2tztgk52fap2wsjddrrobito5zdklqdhpdwhmyr7lbk"),
|
||||||
Actors: map[string]cid.Cid{
|
Actors: map[string]cid.Cid{
|
||||||
"account": MustParseCid("bafk2bzaceau2o55aripm7kqrbzzog72zcduv5psnxzpohx5rdkykepc4z7aag"),
|
"account": MustParseCid("bafk2bzacealrkumvvuyeefrnedyh2ilgozgrdp5canubuakp723pczjdcogvw"),
|
||||||
"cron": MustParseCid("bafk2bzacec5qc5xluwikf4lolfa4oe356iwep25tiezbxfdyg5jib54rhlh6q"),
|
"cron": MustParseCid("bafk2bzacedcfqpqgwj4tgtccliqzwnjbxiceyc3lzylnf6owu54etiv3udjxi"),
|
||||||
"datacap": MustParseCid("bafk2bzacebo47u6q3xou5exsecjpa4rpfqjfm7vyhz4qlr3nk7p46trsk4occ"),
|
"datacap": MustParseCid("bafk2bzacear73heimtdso2qnw77gx6lzqmnr5f5etlggwevut5di6d7nzaoqu"),
|
||||||
"eam": MustParseCid("bafk2bzacea6yeptevserd7ayf4ahokor4sdpizpxpbqwkuvvhzdkon672shsm"),
|
"eam": MustParseCid("bafk2bzacecff4dgsqjcele3zejp77weofbqkef57r2tcy4alkx7e7n3kbkmyy"),
|
||||||
"embryo": MustParseCid("bafk2bzacebj2mj5zlcs3yjlgpbznzistfjkdlwaoncjziliqrxqavvz4dcvnk"),
|
"ethaccount": MustParseCid("bafk2bzacec75pm3q66lsex2mqpm7fax7h6bfbkpwodf4o5gzgnrc2cdifbvfw"),
|
||||||
"evm": MustParseCid("bafk2bzacebi46zgjili4luu3nqy6mno5k4skvo4cvs7genhkdfaukhtw7xirw"),
|
"evm": MustParseCid("bafk2bzaceacbkauvu7ia3euoz5jfdrkw5s7mk4ga5byf3oqndxeaxyxhgnk4m"),
|
||||||
"init": MustParseCid("bafk2bzacedvf2bij6jovem2dfzkz347yvmydxj7vlgaiagosz5t3c5jyy43zu"),
|
"init": MustParseCid("bafk2bzacebtc7p3fq4d7m76jphagzpav2kfxfok7d56wrkek4zqyfqvtpihwm"),
|
||||||
"multisig": MustParseCid("bafk2bzacecukolwx6y5pcajnxg2aawiubgxo5zyj24a23zg5t4qu3k4qbofh4"),
|
"multisig": MustParseCid("bafk2bzaceci3czx4l42u22iozsgg6zkls5wdtrztekmzy4qnybg4qlv4b3qli"),
|
||||||
"paymentchannel": MustParseCid("bafk2bzacecwyih7nodrwsw5vyl5zk7fapklje76jpowqjr6x6br2bm55smqqy"),
|
"paymentchannel": MustParseCid("bafk2bzacea54hgf2czdhlxvn66pyoon5cw3fwdlwx4kp4fwftv2tat4r4nnqg"),
|
||||||
"reward": MustParseCid("bafk2bzacea6vfrcprxg2i4l5qnigf4c6pyvnjxpzfqr4pmph3elif7sfidrei"),
|
"placeholder": MustParseCid("bafk2bzacedv773z6clfjh7wxvlqd6ki7bncztt73org7apnnt2acjigrjdg4a"),
|
||||||
"storagemarket": MustParseCid("bafk2bzaceahradb3od4ahs46x6yriwvm36iabgtohhoiolubsumto5eravzbu"),
|
"reward": MustParseCid("bafk2bzacebd7ia2qfpxob2enuazpy3yc2wpach5rq2qbm7uwgknyzqqruefmm"),
|
||||||
"storageminer": MustParseCid("bafk2bzacedekivqgvqapbepvzn6jte3xyymyg5yjuwy42xvboa6rcqnzgo74u"),
|
"storagemarket": MustParseCid("bafk2bzaceam7ns7axlv3sghrwdo7kriw2hrlblim2pingllnvatqu2xfjfhgs"),
|
||||||
"storagepower": MustParseCid("bafk2bzacedkmiosllqqqarmr53twspyswdvsm7givwczgo3qqsxzpad4hzjma"),
|
"storageminer": MustParseCid("bafk2bzacecbfmgzg5unc3ia7yme75psji2j6uhalt5jco6niu6wcn3pdufavy"),
|
||||||
"system": MustParseCid("bafk2bzaceagdymtxb4lxqqjgmnphbgdtdgveuuqaouswpzagj4bpbon3ptop4"),
|
"storagepower": MustParseCid("bafk2bzacedxzvoqa3a4lzajoke75q2ujhmazm4inb7robfikgtywr4sp6mgcy"),
|
||||||
"verifiedregistry": MustParseCid("bafk2bzacec556wsqldm22k2abshvvnsrawlm3bbqkwzht6ubcj76m2jsy3azi"),
|
"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",
|
Network: "mainnet",
|
||||||
@ -268,23 +294,24 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
|
|||||||
}, {
|
}, {
|
||||||
Network: "mainnet",
|
Network: "mainnet",
|
||||||
Version: 10,
|
Version: 10,
|
||||||
ManifestCid: MustParseCid("bafy2bzaceduyggnyqhlr346hfw32tbobzrvhzhill33zhe7jw64pmwjci2xoc"),
|
ManifestCid: MustParseCid("bafy2bzacedjq47v3yxxptl3vvtpin4optnhoe7ynxjncuhpak2ifdvff2mrfy"),
|
||||||
Actors: map[string]cid.Cid{
|
Actors: map[string]cid.Cid{
|
||||||
"account": MustParseCid("bafk2bzacedmr3wxl7qmhquageorrt3aavbzqfpm7eymxidakwuhaobu7dseqs"),
|
"account": MustParseCid("bafk2bzaceb7wftmnoa5zbeu6jsrzvqpjfd7kudhueve6duwxcflcaqeagqg6g"),
|
||||||
"cron": MustParseCid("bafk2bzaceblekxapm5nnqnxmw3mk27236iyutvbhhpsc3fyde7zi7guccn7cc"),
|
"cron": MustParseCid("bafk2bzacean2xecc6kfbrueglsujjqswz5nvjstmtvdq2zc5vk4cbh6gvgxcq"),
|
||||||
"datacap": MustParseCid("bafk2bzacedu4jevyvqsilq7bq4uhegbkm75muwebc5ifqpfaojwhexf2j4i6a"),
|
"datacap": MustParseCid("bafk2bzacear4esja4asfsdeqto6o5cjn5dbgxmzvu2uel36tzdp2s26fkte4y"),
|
||||||
"eam": MustParseCid("bafk2bzacedc7224twbolvdq6iwc7ybdpah2ywe3ueo33jv67ecimndinle374"),
|
"eam": MustParseCid("bafk2bzacectduzxzk23xffgohmsmq4gisl4etaguq2xe6h52y7aiaaibmi2pg"),
|
||||||
"embryo": MustParseCid("bafk2bzacebj2mj5zlcs3yjlgpbznzistfjkdlwaoncjziliqrxqavvz4dcvnk"),
|
"ethaccount": MustParseCid("bafk2bzacecqoxzy2p3i46ncuvw6wzlesaw5iobqpp7nmjtkbxyiwblg4frzmg"),
|
||||||
"evm": MustParseCid("bafk2bzaceaggldo6wmkvp5innv4pnjv4xnpedspzofvma3dhu7vk45hh5djoq"),
|
"evm": MustParseCid("bafk2bzacecgz6klga2lwjp3d3iyzkzm4td5aefeaymmn3rmixgg7a4vwoewcu"),
|
||||||
"init": MustParseCid("bafk2bzacedutlaebaczkdi4vqvt3xim24u3whleqk2r4lufjd5jnmxcosea6q"),
|
"init": MustParseCid("bafk2bzacebzrlucqk23kkjv26srpzjgztx7qjm23suqbyzu2qdto5jbpifm7y"),
|
||||||
"multisig": MustParseCid("bafk2bzaceatiqxjwtugpzus3s52zoggnrftxqn7kiw3obvjgkjvtd6zr3636q"),
|
"multisig": MustParseCid("bafk2bzacedls4tgmkfkasgcsfrtnkjoi6yoze5yq4cafqzbjvbty5gfeut4n4"),
|
||||||
"paymentchannel": MustParseCid("bafk2bzacebyviac6i43gtsvmjfg6mzcp6rwgz44axidc7m432btbmvt7i2m2g"),
|
"paymentchannel": MustParseCid("bafk2bzaceazuokt65n3hqjgmwmgoi6gpcvete2b46nlecnynjkgrzp4wnl4ii"),
|
||||||
"reward": MustParseCid("bafk2bzacecbcnlvk2izojpfoaksitqenhzaofn6ynxx5pegl4y45wjlouexdi"),
|
"placeholder": MustParseCid("bafk2bzacedv773z6clfjh7wxvlqd6ki7bncztt73org7apnnt2acjigrjdg4a"),
|
||||||
"storagemarket": MustParseCid("bafk2bzacebobteeoz2jycplgtydfyltzughegz2sopn6pzy2udjfvuo77joyk"),
|
"reward": MustParseCid("bafk2bzacecqjpnbxravwqb7liwxowb5bdml4x2qboo5vqxk7slprq3eo4ujp2"),
|
||||||
"storageminer": MustParseCid("bafk2bzacecwcypas3y6u4rya7qolfwmou437xgrjxh7mnnim7bo3nhk4dscxw"),
|
"storagemarket": MustParseCid("bafk2bzacecuedinzm256nup2pbsdrnxerfk33hqxhakupb3c26fwk576ehgiw"),
|
||||||
"storagepower": MustParseCid("bafk2bzacec62kids6rcrdmdeqhwiz3s5rs35s5gn25ilwemgmm6jqnr2rnaaq"),
|
"storageminer": MustParseCid("bafk2bzaceb4c7iqlmk4lgnkccpdvzdv6kbwqz2leyluuehh2ino2m6e5cd7d6"),
|
||||||
"system": MustParseCid("bafk2bzacecj3c4bjbs2xfttn7zqle7yocqh47u2s7hwuxrsn7fi5h74tcyxoc"),
|
"storagepower": MustParseCid("bafk2bzacedkwcuzvlx43nbwdwms5smerdaeja45rh7d646k4nc4s5toyryuxi"),
|
||||||
"verifiedregistry": MustParseCid("bafk2bzacedgf7zbnlste5ukzueduemkimiit64scz7lvebztufx5jxtx6gkz2"),
|
"system": MustParseCid("bafk2bzacedexhpixywvxk37jyp3sehcqmomyq4kpxu3wjhrehawyjhv6grav2"),
|
||||||
|
"verifiedregistry": MustParseCid("bafk2bzacebsnm343frbrfted3vbia4to7iiav4qm3tvpkcbsgkd5fynop3q7s"),
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
Network: "testing",
|
Network: "testing",
|
||||||
@ -324,23 +351,24 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
|
|||||||
}, {
|
}, {
|
||||||
Network: "testing",
|
Network: "testing",
|
||||||
Version: 10,
|
Version: 10,
|
||||||
ManifestCid: MustParseCid("bafy2bzacearlgbespxi2zdrybtp2rrbwscmtbyou5qa2egbdvcz6v2yjjqvjo"),
|
ManifestCid: MustParseCid("bafy2bzacececfnvx4hay5b6yhtkxdqgkauupeqpwnlgainug6blp2isihwtww"),
|
||||||
Actors: map[string]cid.Cid{
|
Actors: map[string]cid.Cid{
|
||||||
"account": MustParseCid("bafk2bzaceba6me5ipkcijuhyypnzjydhv3ebi2ctailar7mtzlk4vk3rbxfee"),
|
"account": MustParseCid("bafk2bzaceb56iceglbwg3s2skdjj5vhak7j6srlaxvd7v6hzvxpccwsrvfaxi"),
|
||||||
"cron": MustParseCid("bafk2bzacea6k2mai2xnakygqvbigivfrvv5q7d34qrzjv2crkqtwbjxnxmkbe"),
|
"cron": MustParseCid("bafk2bzacearjb3buxy4jwhcn4jeqbof3dinsh52zyj74djkfghmjdoxbsvjkq"),
|
||||||
"datacap": MustParseCid("bafk2bzaceah4oxcgck6bcfkzctm2klpvmltyidq7uxnlkcap6ypi3lnkcvrqk"),
|
"datacap": MustParseCid("bafk2bzacec2dghsnwhyhquwkbsfcct53pgglxzgmw7j66y3keniklbiq4q7ti"),
|
||||||
"eam": MustParseCid("bafk2bzacedjtkvocrnkrot2oztsfrxtpwl32wwbmbkrjfbbm4xipwzrhhxn5c"),
|
"eam": MustParseCid("bafk2bzacedojoymbgz275lzvtlpaf2thoydz7fb274mhvadbpk2thbgpye72s"),
|
||||||
"embryo": MustParseCid("bafk2bzacebj2mj5zlcs3yjlgpbznzistfjkdlwaoncjziliqrxqavvz4dcvnk"),
|
"ethaccount": MustParseCid("bafk2bzaceddhvqqkwc4p7exdgv2bwefkk3lnq2rw6chvar7hdeowahtjdmznw"),
|
||||||
"evm": MustParseCid("bafk2bzaced6vhabkr2ojpjzsybrq5yvksjzpjk6yei6fwobkwwydlj5f473pw"),
|
"evm": MustParseCid("bafk2bzacecgzk3ompisq5n7oualijioce6nhsm6zwil7p5p57nojuyrdckti2"),
|
||||||
"init": MustParseCid("bafk2bzaceaib3o5e7wop7kwjirgpferqarmngrgjkur2yhdnwplctidpxsgme"),
|
"init": MustParseCid("bafk2bzaceacdto7l5qp65ukclc3qqlfpv3tdio7u5lxufg2uc3hrx5hpqt2x2"),
|
||||||
"multisig": MustParseCid("bafk2bzaced4z3awacxumq6yr33a3adu2legb7colahgvqpmigs3fvvjxs3byc"),
|
"multisig": MustParseCid("bafk2bzacebw6ujt54gyhxvo5jmimg3z54crmfzbbcr677ljqmmb2ejh6srlsm"),
|
||||||
"paymentchannel": MustParseCid("bafk2bzaceb6mfi24mpzt7qlkratj2tdtqo7aia67zcztuslrxcjaycz6fnai6"),
|
"paymentchannel": MustParseCid("bafk2bzacebfht4drwm5aagcx4kvuiwclldd6rnosce42474u4asnurjqyxhna"),
|
||||||
"reward": MustParseCid("bafk2bzacebngh5kwtem4ncarpjtxhs4rwyoficttkgxlsjtiz5ucdi4p3czoc"),
|
"placeholder": MustParseCid("bafk2bzacedv773z6clfjh7wxvlqd6ki7bncztt73org7apnnt2acjigrjdg4a"),
|
||||||
"storagemarket": MustParseCid("bafk2bzacecnsibyil62jfq2gbkoe6c2epehfcrxzjmqjnwz7kxab2hkbu3lks"),
|
"reward": MustParseCid("bafk2bzacedqmiebckz7xqs7f7gcj67wzzpko2q3jhom6rwtopogv7iz5bnwlu"),
|
||||||
"storageminer": MustParseCid("bafk2bzacedzw4vkrt3sdkhagpvn62pknyyjkcrzewncvtvae5qgwe6ulzx4a4"),
|
"storagemarket": MustParseCid("bafk2bzaceam3n2xjbvkyyifw7jvkc4z4lxvblnbmx4ruzr5lpesgmpuhbmb2w"),
|
||||||
"storagepower": MustParseCid("bafk2bzacedxgadibot6nzvripqt3z5shvjsoscupinejnsvswq4cbeskblwyy"),
|
"storageminer": MustParseCid("bafk2bzacebcbyuzniiqksk47v7zyfc56noblbsmlqblv3n6s7l5un3heigdwk"),
|
||||||
"system": MustParseCid("bafk2bzacedm24avrmp5o5odhpad43qeglooflygwh4ah7qnzbij2h4c3v6cge"),
|
"storagepower": MustParseCid("bafk2bzacechzbqmunxv6o2zgp4uicswapmgexc3uejco2n2r7cirbijrbgewc"),
|
||||||
"verifiedregistry": MustParseCid("bafk2bzaceapq3j6ww3ofytwq3pz3obumaqsyg3wrm6tksdh7op23a72co3rya"),
|
"system": MustParseCid("bafk2bzaceb6obdybgoyjvdfxvxg5uxhrpnoixtbof663dllo2eelcuvsfycew"),
|
||||||
|
"verifiedregistry": MustParseCid("bafk2bzacedlogwaofqaqou4pckoatwei2ulbz3ucjmbsm3lfwuw3tr7g5opjc"),
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
Network: "testing-fake-proofs",
|
Network: "testing-fake-proofs",
|
||||||
@ -380,22 +408,23 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet
|
|||||||
}, {
|
}, {
|
||||||
Network: "testing-fake-proofs",
|
Network: "testing-fake-proofs",
|
||||||
Version: 10,
|
Version: 10,
|
||||||
ManifestCid: MustParseCid("bafy2bzacea4irr2oxhclwt4mvtrevbzb7mbqddcebjz7bkqjq6eoflpfhencc"),
|
ManifestCid: MustParseCid("bafy2bzacec4yawvg2rbdvzlez4lyf4e7ysjfjdrg5mpclvvwxt7texyeeletg"),
|
||||||
Actors: map[string]cid.Cid{
|
Actors: map[string]cid.Cid{
|
||||||
"account": MustParseCid("bafk2bzaceba6me5ipkcijuhyypnzjydhv3ebi2ctailar7mtzlk4vk3rbxfee"),
|
"account": MustParseCid("bafk2bzaceb56iceglbwg3s2skdjj5vhak7j6srlaxvd7v6hzvxpccwsrvfaxi"),
|
||||||
"cron": MustParseCid("bafk2bzacea6k2mai2xnakygqvbigivfrvv5q7d34qrzjv2crkqtwbjxnxmkbe"),
|
"cron": MustParseCid("bafk2bzacearjb3buxy4jwhcn4jeqbof3dinsh52zyj74djkfghmjdoxbsvjkq"),
|
||||||
"datacap": MustParseCid("bafk2bzaceah4oxcgck6bcfkzctm2klpvmltyidq7uxnlkcap6ypi3lnkcvrqk"),
|
"datacap": MustParseCid("bafk2bzacec2dghsnwhyhquwkbsfcct53pgglxzgmw7j66y3keniklbiq4q7ti"),
|
||||||
"eam": MustParseCid("bafk2bzacedjtkvocrnkrot2oztsfrxtpwl32wwbmbkrjfbbm4xipwzrhhxn5c"),
|
"eam": MustParseCid("bafk2bzacedojoymbgz275lzvtlpaf2thoydz7fb274mhvadbpk2thbgpye72s"),
|
||||||
"embryo": MustParseCid("bafk2bzacebj2mj5zlcs3yjlgpbznzistfjkdlwaoncjziliqrxqavvz4dcvnk"),
|
"ethaccount": MustParseCid("bafk2bzaceddhvqqkwc4p7exdgv2bwefkk3lnq2rw6chvar7hdeowahtjdmznw"),
|
||||||
"evm": MustParseCid("bafk2bzaced6vhabkr2ojpjzsybrq5yvksjzpjk6yei6fwobkwwydlj5f473pw"),
|
"evm": MustParseCid("bafk2bzacecgzk3ompisq5n7oualijioce6nhsm6zwil7p5p57nojuyrdckti2"),
|
||||||
"init": MustParseCid("bafk2bzaceaib3o5e7wop7kwjirgpferqarmngrgjkur2yhdnwplctidpxsgme"),
|
"init": MustParseCid("bafk2bzaceacdto7l5qp65ukclc3qqlfpv3tdio7u5lxufg2uc3hrx5hpqt2x2"),
|
||||||
"multisig": MustParseCid("bafk2bzaced4z3awacxumq6yr33a3adu2legb7colahgvqpmigs3fvvjxs3byc"),
|
"multisig": MustParseCid("bafk2bzacebw6ujt54gyhxvo5jmimg3z54crmfzbbcr677ljqmmb2ejh6srlsm"),
|
||||||
"paymentchannel": MustParseCid("bafk2bzaceb6mfi24mpzt7qlkratj2tdtqo7aia67zcztuslrxcjaycz6fnai6"),
|
"paymentchannel": MustParseCid("bafk2bzacebfht4drwm5aagcx4kvuiwclldd6rnosce42474u4asnurjqyxhna"),
|
||||||
"reward": MustParseCid("bafk2bzacebngh5kwtem4ncarpjtxhs4rwyoficttkgxlsjtiz5ucdi4p3czoc"),
|
"placeholder": MustParseCid("bafk2bzacedv773z6clfjh7wxvlqd6ki7bncztt73org7apnnt2acjigrjdg4a"),
|
||||||
"storagemarket": MustParseCid("bafk2bzacecnsibyil62jfq2gbkoe6c2epehfcrxzjmqjnwz7kxab2hkbu3lks"),
|
"reward": MustParseCid("bafk2bzacedqmiebckz7xqs7f7gcj67wzzpko2q3jhom6rwtopogv7iz5bnwlu"),
|
||||||
"storageminer": MustParseCid("bafk2bzaceb4grddnw54gczgcdak5a2gqvwed66mhibbug6qu4jy35bf45jltg"),
|
"storagemarket": MustParseCid("bafk2bzaceam3n2xjbvkyyifw7jvkc4z4lxvblnbmx4ruzr5lpesgmpuhbmb2w"),
|
||||||
"storagepower": MustParseCid("bafk2bzacedp2dnbk4bg3hhaeztre4q3jv7eqs267rlafszpggb2njjn3x5eru"),
|
"storageminer": MustParseCid("bafk2bzaceataoi4vlifq2roanrfjt2f2cql2dq4osjs5i3nt4v76462mtrcm2"),
|
||||||
"system": MustParseCid("bafk2bzacedm24avrmp5o5odhpad43qeglooflygwh4ah7qnzbij2h4c3v6cge"),
|
"storagepower": MustParseCid("bafk2bzacede4nq6cbym2z7p5vc2gwbxhnd34qxtd7sy4rmwula3kk6yhbqtve"),
|
||||||
"verifiedregistry": MustParseCid("bafk2bzaceapq3j6ww3ofytwq3pz3obumaqsyg3wrm6tksdh7op23a72co3rya"),
|
"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 NetworkBundle = "devnet"
|
||||||
var BundleOverrides map[actorstypes.Version]string
|
var BundleOverrides map[actorstypes.Version]string
|
||||||
|
var ActorDebugging = true
|
||||||
|
|
||||||
const GenesisNetworkVersion = network.Version18
|
const GenesisNetworkVersion = network.Version18
|
||||||
|
|
||||||
@ -58,6 +59,8 @@ var UpgradeSkyrHeight = abi.ChainEpoch(-19)
|
|||||||
|
|
||||||
var UpgradeSharkHeight = abi.ChainEpoch(-20)
|
var UpgradeSharkHeight = abi.ChainEpoch(-20)
|
||||||
|
|
||||||
|
var UpgradeHyggeHeight = abi.ChainEpoch(-21)
|
||||||
|
|
||||||
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||||
0: DrandMainnet,
|
0: DrandMainnet,
|
||||||
}
|
}
|
||||||
@ -110,6 +113,7 @@ func init() {
|
|||||||
UpgradeOhSnapHeight = getUpgradeHeight("LOTUS_OHSNAP_HEIGHT", UpgradeOhSnapHeight)
|
UpgradeOhSnapHeight = getUpgradeHeight("LOTUS_OHSNAP_HEIGHT", UpgradeOhSnapHeight)
|
||||||
UpgradeSkyrHeight = getUpgradeHeight("LOTUS_SKYR_HEIGHT", UpgradeSkyrHeight)
|
UpgradeSkyrHeight = getUpgradeHeight("LOTUS_SKYR_HEIGHT", UpgradeSkyrHeight)
|
||||||
UpgradeSharkHeight = getUpgradeHeight("LOTUS_SHARK_HEIGHT", UpgradeSharkHeight)
|
UpgradeSharkHeight = getUpgradeHeight("LOTUS_SHARK_HEIGHT", UpgradeSharkHeight)
|
||||||
|
UpgradeHyggeHeight = getUpgradeHeight("LOTUS_HYGGE_HEIGHT", UpgradeHyggeHeight)
|
||||||
|
|
||||||
BuildType |= Build2k
|
BuildType |= Build2k
|
||||||
|
|
||||||
@ -130,4 +134,8 @@ const InteractivePoRepConfidence = 6
|
|||||||
|
|
||||||
const BootstrapPeerThreshold = 1
|
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
|
var WhitelistedBlock = cid.Undef
|
||||||
|
@ -23,6 +23,7 @@ const GenesisNetworkVersion = network.Version16
|
|||||||
|
|
||||||
var NetworkBundle = "butterflynet"
|
var NetworkBundle = "butterflynet"
|
||||||
var BundleOverrides map[actorstypes.Version]string
|
var BundleOverrides map[actorstypes.Version]string
|
||||||
|
var ActorDebugging = false
|
||||||
|
|
||||||
const BootstrappersFile = "butterflynet.pi"
|
const BootstrappersFile = "butterflynet.pi"
|
||||||
const GenesisFile = "butterflynet.car"
|
const GenesisFile = "butterflynet.car"
|
||||||
@ -49,7 +50,8 @@ const UpgradeHyperdriveHeight = -16
|
|||||||
const UpgradeChocolateHeight = -17
|
const UpgradeChocolateHeight = -17
|
||||||
const UpgradeOhSnapHeight = -18
|
const UpgradeOhSnapHeight = -18
|
||||||
const UpgradeSkyrHeight = -19
|
const UpgradeSkyrHeight = -19
|
||||||
const UpgradeSharkHeight = abi.ChainEpoch(600)
|
const UpgradeSharkHeight = abi.ChainEpoch(-20)
|
||||||
|
const UpgradeHyggeHeight = abi.ChainEpoch(600)
|
||||||
|
|
||||||
var SupportedProofTypes = []abi.RegisteredSealProof{
|
var SupportedProofTypes = []abi.RegisteredSealProof{
|
||||||
abi.RegisteredSealProof_StackedDrg512MiBV1,
|
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
|
// BootstrapPeerThreshold is the minimum number peers we need to track for a sync worker to start
|
||||||
const BootstrapPeerThreshold = 2
|
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
|
var WhitelistedBlock = cid.Undef
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
package build
|
package build
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
@ -26,6 +27,7 @@ const GenesisNetworkVersion = network.Version0
|
|||||||
|
|
||||||
var NetworkBundle = "calibrationnet"
|
var NetworkBundle = "calibrationnet"
|
||||||
var BundleOverrides map[actorstypes.Version]string
|
var BundleOverrides map[actorstypes.Version]string
|
||||||
|
var ActorDebugging = false
|
||||||
|
|
||||||
const BootstrappersFile = "calibnet.pi"
|
const BootstrappersFile = "calibnet.pi"
|
||||||
const GenesisFile = "calibnet.car"
|
const GenesisFile = "calibnet.car"
|
||||||
@ -69,6 +71,8 @@ const UpgradeSkyrHeight = 510
|
|||||||
|
|
||||||
const UpgradeSharkHeight = 16800 // 6 days after genesis
|
const UpgradeSharkHeight = 16800 // 6 days after genesis
|
||||||
|
|
||||||
|
const UpgradeHyggeHeight = math.MaxInt64
|
||||||
|
|
||||||
var SupportedProofTypes = []abi.RegisteredSealProof{
|
var SupportedProofTypes = []abi.RegisteredSealProof{
|
||||||
abi.RegisteredSealProof_StackedDrg32GiBV1,
|
abi.RegisteredSealProof_StackedDrg32GiBV1,
|
||||||
abi.RegisteredSealProof_StackedDrg64GiBV1,
|
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
|
// BootstrapPeerThreshold is the minimum number peers we need to track for a sync worker to start
|
||||||
const BootstrapPeerThreshold = 4
|
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
|
var WhitelistedBlock = cid.Undef
|
||||||
|
98
build/params_hyperspace.go
Normal file
98
build/params_hyperspace.go
Normal file
@ -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
|
@ -20,6 +20,7 @@ import (
|
|||||||
|
|
||||||
var NetworkBundle = "caterpillarnet"
|
var NetworkBundle = "caterpillarnet"
|
||||||
var BundleOverrides map[actorstypes.Version]string
|
var BundleOverrides map[actorstypes.Version]string
|
||||||
|
var ActorDebugging = false
|
||||||
|
|
||||||
const BootstrappersFile = "interopnet.pi"
|
const BootstrappersFile = "interopnet.pi"
|
||||||
const GenesisFile = "interopnet.car"
|
const GenesisFile = "interopnet.car"
|
||||||
@ -49,7 +50,9 @@ var UpgradeChocolateHeight = abi.ChainEpoch(-17)
|
|||||||
var UpgradeOhSnapHeight = abi.ChainEpoch(-18)
|
var UpgradeOhSnapHeight = abi.ChainEpoch(-18)
|
||||||
var UpgradeSkyrHeight = abi.ChainEpoch(-19)
|
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{
|
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||||
0: DrandMainnet,
|
0: DrandMainnet,
|
||||||
@ -104,6 +107,7 @@ func init() {
|
|||||||
UpgradeOhSnapHeight = getUpgradeHeight("LOTUS_OHSNAP_HEIGHT", UpgradeOhSnapHeight)
|
UpgradeOhSnapHeight = getUpgradeHeight("LOTUS_OHSNAP_HEIGHT", UpgradeOhSnapHeight)
|
||||||
UpgradeSkyrHeight = getUpgradeHeight("LOTUS_SKYR_HEIGHT", UpgradeSkyrHeight)
|
UpgradeSkyrHeight = getUpgradeHeight("LOTUS_SKYR_HEIGHT", UpgradeSkyrHeight)
|
||||||
UpgradeSharkHeight = getUpgradeHeight("LOTUS_SHARK_HEIGHT", UpgradeSharkHeight)
|
UpgradeSharkHeight = getUpgradeHeight("LOTUS_SHARK_HEIGHT", UpgradeSharkHeight)
|
||||||
|
UpgradeHyggeHeight = getUpgradeHeight("LOTUS_HYGGE_HEIGHT", UpgradeHyggeHeight)
|
||||||
|
|
||||||
BuildType |= BuildInteropnet
|
BuildType |= BuildInteropnet
|
||||||
SetAddressNetwork(address.Testnet)
|
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
|
// BootstrapPeerThreshold is the minimum number peers we need to track for a sync worker to start
|
||||||
const BootstrapPeerThreshold = 2
|
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
|
var WhitelistedBlock = cid.Undef
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
//go:build !debug && !2k && !testground && !calibnet && !butterflynet && !interopnet
|
//go:build !debug && !2k && !testground && !calibnet && !butterflynet && !interopnet && !wallabynet && !hyperspacenet
|
||||||
// +build !debug,!2k,!testground,!calibnet,!butterflynet,!interopnet
|
// +build !debug,!2k,!testground,!calibnet,!butterflynet,!interopnet,!wallabynet,!hyperspacenet
|
||||||
|
|
||||||
package build
|
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.
|
// NOTE: DO NOT change this unless you REALLY know what you're doing. This is consensus critical.
|
||||||
var BundleOverrides map[actorstypes.Version]string
|
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 GenesisNetworkVersion = network.Version0
|
||||||
|
|
||||||
const BootstrappersFile = "mainnet.pi"
|
const BootstrappersFile = "mainnet.pi"
|
||||||
@ -56,6 +59,7 @@ const UpgradePersianHeight = UpgradeCalicoHeight + (builtin2.EpochsInHour * 60)
|
|||||||
const UpgradeOrangeHeight = 336458
|
const UpgradeOrangeHeight = 336458
|
||||||
|
|
||||||
// 2020-12-22T02:00:00Z
|
// 2020-12-22T02:00:00Z
|
||||||
|
// var because of wdpost_test.go
|
||||||
var UpgradeClausHeight = abi.ChainEpoch(343200)
|
var UpgradeClausHeight = abi.ChainEpoch(343200)
|
||||||
|
|
||||||
// 2021-03-04T00:00:30Z
|
// 2021-03-04T00:00:30Z
|
||||||
@ -80,7 +84,10 @@ const UpgradeOhSnapHeight = 1594680
|
|||||||
const UpgradeSkyrHeight = 1960320
|
const UpgradeSkyrHeight = 1960320
|
||||||
|
|
||||||
// 2022-11-30T14:00:00Z
|
// 2022-11-30T14:00:00Z
|
||||||
var UpgradeSharkHeight = abi.ChainEpoch(2383680)
|
const UpgradeSharkHeight = 2383680
|
||||||
|
|
||||||
|
// ??????????????
|
||||||
|
var UpgradeHyggeHeight = abi.ChainEpoch(math.MaxInt64)
|
||||||
|
|
||||||
var SupportedProofTypes = []abi.RegisteredSealProof{
|
var SupportedProofTypes = []abi.RegisteredSealProof{
|
||||||
abi.RegisteredSealProof_StackedDrg32GiBV1,
|
abi.RegisteredSealProof_StackedDrg32GiBV1,
|
||||||
@ -95,8 +102,8 @@ func init() {
|
|||||||
SetAddressNetwork(address.Mainnet)
|
SetAddressNetwork(address.Mainnet)
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.Getenv("LOTUS_DISABLE_SHARK") == "1" {
|
if os.Getenv("LOTUS_DISABLE_HYGGE") == "1" {
|
||||||
UpgradeSharkHeight = math.MaxInt64
|
UpgradeHyggeHeight = math.MaxInt64
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: DO NOT change this unless you REALLY know what you're doing. This is not consensus critical, however,
|
// 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
|
// BootstrapPeerThreshold is the minimum number peers we need to track for a sync worker to start
|
||||||
const BootstrapPeerThreshold = 4
|
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
|
// we skip checks on message validity in this block to sidestep the zero-bls signature
|
||||||
var WhitelistedBlock = MustParseCid("bafy2bzaceapyg2uyzk7vueh3xccxkuwbz3nxewjyguoxvhx77malc2lzn2ybi")
|
var WhitelistedBlock = MustParseCid("bafy2bzaceapyg2uyzk7vueh3xccxkuwbz3nxewjyguoxvhx77malc2lzn2ybi")
|
||||||
|
@ -108,6 +108,7 @@ var (
|
|||||||
UpgradeOhSnapHeight abi.ChainEpoch = -17
|
UpgradeOhSnapHeight abi.ChainEpoch = -17
|
||||||
UpgradeSkyrHeight abi.ChainEpoch = -18
|
UpgradeSkyrHeight abi.ChainEpoch = -18
|
||||||
UpgradeSharkHeight abi.ChainEpoch = -19
|
UpgradeSharkHeight abi.ChainEpoch = -19
|
||||||
|
UpgradeHyggeHeight abi.ChainEpoch = -20
|
||||||
|
|
||||||
DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||||
0: DrandMainnet,
|
0: DrandMainnet,
|
||||||
@ -116,6 +117,7 @@ var (
|
|||||||
GenesisNetworkVersion = network.Version0
|
GenesisNetworkVersion = network.Version0
|
||||||
NetworkBundle = "devnet"
|
NetworkBundle = "devnet"
|
||||||
BundleOverrides map[actorstypes.Version]string
|
BundleOverrides map[actorstypes.Version]string
|
||||||
|
ActorDebugging = true
|
||||||
|
|
||||||
NewestNetworkVersion = network.Version16
|
NewestNetworkVersion = network.Version16
|
||||||
ActorUpgradeNetworkVersion = network.Version16
|
ActorUpgradeNetworkVersion = network.Version16
|
||||||
@ -129,3 +131,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const BootstrapPeerThreshold = 1
|
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
|
||||||
|
94
build/params_wallaby.go
Normal file
94
build/params_wallaby.go
Normal file
@ -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,6 +13,8 @@ const (
|
|||||||
BuildCalibnet = 0x4
|
BuildCalibnet = 0x4
|
||||||
BuildInteropnet = 0x5
|
BuildInteropnet = 0x5
|
||||||
BuildButterflynet = 0x7
|
BuildButterflynet = 0x7
|
||||||
|
BuildWallabynet = 0x8
|
||||||
|
BuildHyperspacenet = 0x9
|
||||||
)
|
)
|
||||||
|
|
||||||
func BuildTypeString() string {
|
func BuildTypeString() string {
|
||||||
@ -31,6 +33,10 @@ func BuildTypeString() string {
|
|||||||
return "+interopnet"
|
return "+interopnet"
|
||||||
case BuildButterflynet:
|
case BuildButterflynet:
|
||||||
return "+butterflynet"
|
return "+butterflynet"
|
||||||
|
case BuildWallabynet:
|
||||||
|
return "+wallabynet"
|
||||||
|
case BuildHyperspacenet:
|
||||||
|
return "+hyperspacenet"
|
||||||
default:
|
default:
|
||||||
return "+huh?"
|
return "+huh?"
|
||||||
}
|
}
|
||||||
|
@ -274,6 +274,33 @@ func IsPaymentChannelActor(c cid.Cid) bool {
|
|||||||
return false
|
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 {
|
func makeAddress(addr string) address.Address {
|
||||||
ret, err := address.NewFromString(addr)
|
ret, err := address.NewFromString(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -153,6 +153,33 @@ func IsPaymentChannelActor(c cid.Cid) bool {
|
|||||||
return false
|
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 {
|
func makeAddress(addr string) address.Address {
|
||||||
ret, err := address.NewFromString(addr)
|
ret, err := address.NewFromString(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -13,11 +13,15 @@ import (
|
|||||||
account10 "github.com/filecoin-project/go-state-types/builtin/v10/account"
|
account10 "github.com/filecoin-project/go-state-types/builtin/v10/account"
|
||||||
cron10 "github.com/filecoin-project/go-state-types/builtin/v10/cron"
|
cron10 "github.com/filecoin-project/go-state-types/builtin/v10/cron"
|
||||||
datacap10 "github.com/filecoin-project/go-state-types/builtin/v10/datacap"
|
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"
|
_init10 "github.com/filecoin-project/go-state-types/builtin/v10/init"
|
||||||
market10 "github.com/filecoin-project/go-state-types/builtin/v10/market"
|
market10 "github.com/filecoin-project/go-state-types/builtin/v10/market"
|
||||||
miner10 "github.com/filecoin-project/go-state-types/builtin/v10/miner"
|
miner10 "github.com/filecoin-project/go-state-types/builtin/v10/miner"
|
||||||
multisig10 "github.com/filecoin-project/go-state-types/builtin/v10/multisig"
|
multisig10 "github.com/filecoin-project/go-state-types/builtin/v10/multisig"
|
||||||
paych10 "github.com/filecoin-project/go-state-types/builtin/v10/paych"
|
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"
|
power10 "github.com/filecoin-project/go-state-types/builtin/v10/power"
|
||||||
reward10 "github.com/filecoin-project/go-state-types/builtin/v10/reward"
|
reward10 "github.com/filecoin-project/go-state-types/builtin/v10/reward"
|
||||||
system10 "github.com/filecoin-project/go-state-types/builtin/v10/system"
|
system10 "github.com/filecoin-project/go-state-types/builtin/v10/system"
|
||||||
@ -265,6 +269,7 @@ func MakeRegistry(av actorstypes.Version) []RegistryEntry {
|
|||||||
methods: datacap9.Methods,
|
methods: datacap9.Methods,
|
||||||
state: new(datacap9.State),
|
state: new(datacap9.State),
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,6 +348,32 @@ func MakeRegistry(av actorstypes.Version) []RegistryEntry {
|
|||||||
methods: datacap10.Methods,
|
methods: datacap10.Methods,
|
||||||
state: new(datacap10.State),
|
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)}}
|
{{if (ge . 9)}}
|
||||||
datacap{{.}} "github.com/filecoin-project/go-state-types/builtin/v{{.}}/datacap"
|
datacap{{.}} "github.com/filecoin-project/go-state-types/builtin/v{{.}}/datacap"
|
||||||
{{end}}
|
{{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}}
|
{{end}}
|
||||||
"github.com/filecoin-project/go-state-types/cbor"
|
"github.com/filecoin-project/go-state-types/cbor"
|
||||||
rtt "github.com/filecoin-project/go-state-types/rt"
|
rtt "github.com/filecoin-project/go-state-types/rt"
|
||||||
@ -174,6 +180,32 @@ func MakeRegistry(av actorstypes.Version) []RegistryEntry {
|
|||||||
methods: datacap{{.}}.Methods,
|
methods: datacap{{.}}.Methods,
|
||||||
state: new(datacap{{.}}.State),
|
state: new(datacap{{.}}.State),
|
||||||
}){{end}}
|
}){{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}}
|
{{end}}
|
||||||
|
@ -93,6 +93,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context,
|
|||||||
vmopt := &vm.VMOpts{
|
vmopt := &vm.VMOpts{
|
||||||
StateBase: base,
|
StateBase: base,
|
||||||
Epoch: e,
|
Epoch: e,
|
||||||
|
Timestamp: ts.MinTimestamp(),
|
||||||
Rand: r,
|
Rand: r,
|
||||||
Bstore: sm.ChainStore().StateBlockstore(),
|
Bstore: sm.ChainStore().StateBlockstore(),
|
||||||
Actors: NewActorRegistry(),
|
Actors: NewActorRegistry(),
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
cbor "github.com/ipfs/go-ipld-cbor"
|
cbor "github.com/ipfs/go-ipld-cbor"
|
||||||
logging "github.com/ipfs/go-log/v2"
|
logging "github.com/ipfs/go-log/v2"
|
||||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||||
|
"github.com/multiformats/go-varint"
|
||||||
cbg "github.com/whyrusleeping/cbor-gen"
|
cbg "github.com/whyrusleeping/cbor-gen"
|
||||||
"go.opencensus.io/stats"
|
"go.opencensus.io/stats"
|
||||||
"go.opencensus.io/trace"
|
"go.opencensus.io/trace"
|
||||||
@ -21,6 +22,7 @@ import (
|
|||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"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/crypto"
|
||||||
"github.com/filecoin-project/go-state-types/network"
|
"github.com/filecoin-project/go-state-types/network"
|
||||||
blockadt "github.com/filecoin-project/specs-actors/actors/util/adt"
|
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
|
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
|
// 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 {
|
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)
|
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")
|
return xerrors.New("Sender must be an account actor")
|
||||||
}
|
}
|
||||||
nonces[sender] = act.Nonce
|
nonces[sender] = act.Nonce
|
||||||
@ -542,25 +577,23 @@ func (filec *FilecoinEC) checkBlockMessages(ctx context.Context, b *types.FullBl
|
|||||||
|
|
||||||
smArr := blockadt.MakeEmptyArray(tmpstore)
|
smArr := blockadt.MakeEmptyArray(tmpstore)
|
||||||
for i, m := range b.SecpkMessages {
|
for i, m := range b.SecpkMessages {
|
||||||
if filec.sm.GetNetworkVersion(ctx, b.Header.Height) >= network.Version14 {
|
if nv >= network.Version14 && !chain.IsValidSecpkSigType(nv, m.Signature.Type) {
|
||||||
if m.Signature.Type != crypto.SigTypeSecp256k1 {
|
return xerrors.Errorf("block had invalid signed message at index %d: %w", i, err)
|
||||||
return xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := checkMsg(m); err != nil {
|
if err := checkMsg(m); err != nil {
|
||||||
return xerrors.Errorf("block had invalid secpk message at index %d: %w", i, err)
|
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
|
// `From` being an account actor is only validated inside the `vm.ResolveToDeterministicAddr` call
|
||||||
// in `StateManager.ResolveToKeyAddress` here (and not in `checkMsg`).
|
// in `StateManager.ResolveToDeterministicAddress` here (and not in `checkMsg`).
|
||||||
kaddr, err := filec.sm.ResolveToKeyAddress(ctx, m.Message.From, baseTs)
|
kaddr, err := filec.sm.ResolveToDeterministicAddress(ctx, m.Message.From, baseTs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("failed to resolve key addr: %w", err)
|
return xerrors.Errorf("failed to resolve key addr: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := sigs.Verify(&m.Signature, kaddr, m.Message.Cid().Bytes()); err != nil {
|
if err := chain.AuthenticateMessage(m, kaddr); err != nil {
|
||||||
return xerrors.Errorf("secpk message %s has invalid signature: %w", m.Cid(), err)
|
return xerrors.Errorf("failed to validate signature: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := store.PutMessage(ctx, tmpbs, m)
|
c, err := store.PutMessage(ctx, tmpbs, m)
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/filecoin-project/go-state-types/crypto"
|
"github.com/filecoin-project/go-state-types/crypto"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
"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/consensus"
|
||||||
"github.com/filecoin-project/lotus/chain/stmgr"
|
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"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 blsMsgCids, secpkMsgCids []cid.Cid
|
||||||
var blsSigs []crypto.Signature
|
var blsSigs []crypto.Signature
|
||||||
|
nv := filec.sm.GetNetworkVersion(ctx, bt.Epoch)
|
||||||
for _, msg := range bt.Messages {
|
for _, msg := range bt.Messages {
|
||||||
if msg.Signature.Type == crypto.SigTypeBLS {
|
if msg.Signature.Type == crypto.SigTypeBLS {
|
||||||
blsSigs = append(blsSigs, msg.Signature)
|
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)
|
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)
|
c, err := filec.sm.ChainStore().PutMessage(ctx, msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -18,8 +18,10 @@ import (
|
|||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
||||||
"github.com/filecoin-project/go-state-types/big"
|
"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"
|
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/manifest"
|
||||||
|
"github.com/filecoin-project/go-state-types/migration"
|
||||||
"github.com/filecoin-project/go-state-types/network"
|
"github.com/filecoin-project/go-state-types/network"
|
||||||
"github.com/filecoin-project/go-state-types/rt"
|
"github.com/filecoin-project/go-state-types/rt"
|
||||||
gstStore "github.com/filecoin-project/go-state-types/store"
|
gstStore "github.com/filecoin-project/go-state-types/store"
|
||||||
@ -232,8 +234,18 @@ func DefaultUpgradeSchedule() stmgr.UpgradeSchedule {
|
|||||||
StopWithin: 5,
|
StopWithin: 5,
|
||||||
}},
|
}},
|
||||||
Expensive: true,
|
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 {
|
for _, u := range updates {
|
||||||
@ -1580,11 +1592,110 @@ func upgradeActorsV9Common(
|
|||||||
|
|
||||||
func UpgradeActorsV10(ctx context.Context, sm *stmgr.StateManager, cache stmgr.MigrationCache, cb stmgr.ExecMonitor,
|
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) {
|
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
|
config := migration.Config{
|
||||||
// - the init actor state to include the (empty) installed actors field
|
MaxWorkers: uint(workerCount),
|
||||||
// - state tree migration to v5
|
JobQueueSize: 1000,
|
||||||
return cid.Undef, fmt.Errorf("IMPLEMENTME: v10 migration")
|
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
|
// Example upgrade function if upgrade requires only code changes
|
||||||
|
474
chain/events/filter/event.go
Normal file
474
chain/events/filter/event.go
Normal file
@ -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
|
||||||
|
}
|
431
chain/events/filter/event_test.go
Normal file
431
chain/events/filter/event_test.go
Normal file
@ -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
|
||||||
|
}
|
434
chain/events/filter/index.go
Normal file
434
chain/events/filter/index.go
Normal file
@ -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{}
|
||||||
|
}
|
283
chain/events/filter/index_test.go
Normal file
283
chain/events/filter/index_test.go
Normal file
@ -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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
143
chain/events/filter/mempool.go
Normal file
143
chain/events/filter/mempool.go
Normal file
@ -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
|
||||||
|
}
|
108
chain/events/filter/store.go
Normal file
108
chain/events/filter/store.go
Normal file
@ -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
|
||||||
|
}
|
130
chain/events/filter/tipset.go
Normal file
130
chain/events/filter/tipset.go
Normal file
@ -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)
|
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)
|
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) {
|
func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template genesis.Template) (*state.StateTree, map[address.Address]address.Address, error) {
|
||||||
// Create empty state tree
|
// Create empty state tree
|
||||||
|
|
||||||
cst := cbor.NewCborStore(bs)
|
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)
|
sv, err := state.VersionForNetwork(template.NetworkVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -238,15 +233,12 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
|
|||||||
|
|
||||||
// Create accounts
|
// Create accounts
|
||||||
for _, info := range template.Accounts {
|
for _, info := range template.Accounts {
|
||||||
|
|
||||||
switch info.Type {
|
switch info.Type {
|
||||||
case genesis.TAccount:
|
case genesis.TAccount:
|
||||||
if err := CreateAccountActor(ctx, cst, state, info, keyIDs, av); err != nil {
|
if err := CreateAccountActor(ctx, cst, state, info, keyIDs, av); err != nil {
|
||||||
return nil, nil, xerrors.Errorf("failed to create account actor: %w", err)
|
return nil, nil, xerrors.Errorf("failed to create account actor: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
case genesis.TMultisig:
|
case genesis.TMultisig:
|
||||||
|
|
||||||
ida, err := address.NewIDAddress(uint64(idStart))
|
ida, err := address.NewIDAddress(uint64(idStart))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
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)
|
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)
|
stateroot, err := st.Flush(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("flush state tree failed: %w", err)
|
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)
|
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)
|
stateroot, err = SetupStorageMiners(ctx, cs, sys, stateroot, template.Miners, template.NetworkVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("setup miners failed: %w", err)
|
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))
|
store := adt.WrapStore(ctx, cbor.NewCborStore(bs))
|
||||||
emptyroot, err := adt0.MakeEmptyArray(store).Root()
|
emptyroot, err := adt0.MakeEmptyArray(store).Root()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
139
chain/gen/genesis/genesis_eth.go
Normal file
139
chain/gen/genesis/genesis_eth.go
Normal file
@ -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/api"
|
||||||
"github.com/filecoin-project/lotus/build"
|
"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/stmgr"
|
||||||
"github.com/filecoin-project/lotus/chain/store"
|
"github.com/filecoin-project/lotus/chain/store"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/chain/vm"
|
"github.com/filecoin-project/lotus/chain/vm"
|
||||||
"github.com/filecoin-project/lotus/journal"
|
"github.com/filecoin-project/lotus/journal"
|
||||||
"github.com/filecoin-project/lotus/lib/sigs"
|
|
||||||
"github.com/filecoin-project/lotus/metrics"
|
"github.com/filecoin-project/lotus/metrics"
|
||||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||||
)
|
)
|
||||||
@ -476,7 +477,7 @@ func (mp *MessagePool) resolveToKey(ctx context.Context, addr address.Address) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// resolve the 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 {
|
if err != nil {
|
||||||
return address.Undef, err
|
return address.Undef, err
|
||||||
}
|
}
|
||||||
@ -772,11 +773,9 @@ func sigCacheKey(m *types.SignedMessage) (string, error) {
|
|||||||
if len(m.Signature.Data) != ffi.SignatureBytes {
|
if len(m.Signature.Data) != ffi.SignatureBytes {
|
||||||
return "", fmt.Errorf("bls signature incorrectly sized")
|
return "", fmt.Errorf("bls signature incorrectly sized")
|
||||||
}
|
}
|
||||||
|
|
||||||
hashCache := blake2b.Sum256(append(m.Cid().Bytes(), m.Signature.Data...))
|
hashCache := blake2b.Sum256(append(m.Cid().Bytes(), m.Signature.Data...))
|
||||||
|
|
||||||
return string(hashCache[:]), nil
|
return string(hashCache[:]), nil
|
||||||
case crypto.SigTypeSecp256k1:
|
case crypto.SigTypeSecp256k1, crypto.SigTypeDelegated:
|
||||||
return string(m.Cid().Bytes()), nil
|
return string(m.Cid().Bytes()), nil
|
||||||
default:
|
default:
|
||||||
return "", xerrors.Errorf("unrecognized signature type: %d", m.Signature.Type)
|
return "", xerrors.Errorf("unrecognized signature type: %d", m.Signature.Type)
|
||||||
@ -795,8 +794,8 @@ func (mp *MessagePool) VerifyMsgSig(m *types.SignedMessage) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := sigs.Verify(&m.Signature, m.Message.From, m.Message.Cid().Bytes()); err != nil {
|
if err := chain.AuthenticateMessage(m, m.Message.From); err != nil {
|
||||||
return err
|
return xerrors.Errorf("failed to validate signature: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mp.sigValCache.Add(sck, struct{}{})
|
mp.sigValCache.Add(sck, struct{}{})
|
||||||
@ -853,18 +852,32 @@ func (mp *MessagePool) addTs(ctx context.Context, m *types.SignedMessage, curTs
|
|||||||
mp.lk.Lock()
|
mp.lk.Lock()
|
||||||
defer mp.lk.Unlock()
|
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)
|
publish, err := mp.verifyMsgBeforeAdd(ctx, m, curTs, local)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, xerrors.Errorf("verify msg failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := mp.checkBalance(ctx, m, curTs); err != nil {
|
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)
|
err = mp.addLocked(ctx, m, !local, untrusted)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, xerrors.Errorf("failed to add locked: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if local {
|
if local {
|
||||||
|
@ -155,14 +155,14 @@ func (tma *testMpoolAPI) GetActorAfter(addr address.Address, ts *types.TipSet) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &types.Actor{
|
return &types.Actor{
|
||||||
Code: builtin2.StorageMarketActorCodeID,
|
Code: builtin2.AccountActorCodeID,
|
||||||
Nonce: nonce,
|
Nonce: nonce,
|
||||||
Balance: balance,
|
Balance: balance,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tma *testMpoolAPI) StateAccountKeyAtFinality(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
|
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 {
|
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 address.Undef, fmt.Errorf("given address was not a key addr")
|
||||||
}
|
}
|
||||||
return addr, nil
|
return addr, nil
|
||||||
|
@ -28,7 +28,7 @@ type Provider interface {
|
|||||||
PutMessage(ctx context.Context, m types.ChainMsg) (cid.Cid, error)
|
PutMessage(ctx context.Context, m types.ChainMsg) (cid.Cid, error)
|
||||||
PubSubPublish(string, []byte) error
|
PubSubPublish(string, []byte) error
|
||||||
GetActorAfter(address.Address, *types.TipSet) (*types.Actor, 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
|
StateNetworkVersion(context.Context, abi.ChainEpoch) network.Version
|
||||||
MessagesForBlock(context.Context, *types.BlockHeader) ([]*types.Message, []*types.SignedMessage, error)
|
MessagesForBlock(context.Context, *types.BlockHeader) ([]*types.Message, []*types.SignedMessage, error)
|
||||||
MessagesForTipset(context.Context, *types.TipSet) ([]types.ChainMsg, error)
|
MessagesForTipset(context.Context, *types.TipSet) ([]types.ChainMsg, error)
|
||||||
@ -102,8 +102,8 @@ func (mpp *mpoolProvider) GetActorAfter(addr address.Address, ts *types.TipSet)
|
|||||||
return st.GetActor(addr)
|
return st.GetActor(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mpp *mpoolProvider) StateAccountKeyAtFinality(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
|
func (mpp *mpoolProvider) StateDeterministicAddressAtFinality(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {
|
||||||
return mpp.sm.ResolveToKeyAddressAtFinality(ctx, addr, ts)
|
return mpp.sm.ResolveToDeterministicAddressAtFinality(ctx, addr, ts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mpp *mpoolProvider) StateNetworkVersion(ctx context.Context, height abi.ChainEpoch) network.Version {
|
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.msgs = append(sm.msgs, mc.msgs...)
|
||||||
sm.blsLimit -= l
|
sm.blsLimit -= l
|
||||||
sm.gasLimit -= mc.gasLimit
|
sm.gasLimit -= mc.gasLimit
|
||||||
} else if mc.sigType == crypto.SigTypeSecp256k1 {
|
} else if mc.sigType == crypto.SigTypeSecp256k1 || mc.sigType == crypto.SigTypeDelegated {
|
||||||
if sm.secpLimit < l {
|
if sm.secpLimit < l {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -123,7 +123,7 @@ func (sm *selectedMessages) tryToAddWithDeps(mc *msgChain, mp *MessagePool, base
|
|||||||
|
|
||||||
if mc.sigType == crypto.SigTypeBLS {
|
if mc.sigType == crypto.SigTypeBLS {
|
||||||
smMsgLimit = sm.blsLimit
|
smMsgLimit = sm.blsLimit
|
||||||
} else if mc.sigType == crypto.SigTypeSecp256k1 {
|
} else if mc.sigType == crypto.SigTypeSecp256k1 || mc.sigType == crypto.SigTypeDelegated {
|
||||||
smMsgLimit = sm.secpLimit
|
smMsgLimit = sm.secpLimit
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
@ -174,7 +174,7 @@ func (sm *selectedMessages) tryToAddWithDeps(mc *msgChain, mp *MessagePool, base
|
|||||||
|
|
||||||
if mc.sigType == crypto.SigTypeBLS {
|
if mc.sigType == crypto.SigTypeBLS {
|
||||||
sm.blsLimit -= chainMsgLimit
|
sm.blsLimit -= chainMsgLimit
|
||||||
} else if mc.sigType == crypto.SigTypeSecp256k1 {
|
} else if mc.sigType == crypto.SigTypeSecp256k1 || mc.sigType == crypto.SigTypeDelegated {
|
||||||
sm.secpLimit -= chainMsgLimit
|
sm.secpLimit -= chainMsgLimit
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,7 +187,7 @@ func (sm *selectedMessages) trimChain(mc *msgChain, mp *MessagePool, baseFee typ
|
|||||||
if msgLimit > sm.blsLimit {
|
if msgLimit > sm.blsLimit {
|
||||||
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 {
|
if msgLimit > sm.secpLimit {
|
||||||
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/types/mock"
|
||||||
"github.com/filecoin-project/lotus/chain/wallet"
|
"github.com/filecoin-project/lotus/chain/wallet"
|
||||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
|
_ "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/lib/sigs/secp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
53
chain/signatures.go
Normal file
53
chain/signatures.go
Normal file
@ -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 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) {
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
worker, err := sm.ResolveToKeyAddress(ctx, info.Worker, ts)
|
worker, err := sm.ResolveToDeterministicAddress(ctx, info.Worker, ts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("resolving worker address: %w", err)
|
return nil, xerrors.Errorf("resolving worker address: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -143,6 +143,7 @@ func (sm *StateManager) callInternal(ctx context.Context, msg *types.Message, pr
|
|||||||
vmopt := &vm.VMOpts{
|
vmopt := &vm.VMOpts{
|
||||||
StateBase: stateCid,
|
StateBase: stateCid,
|
||||||
Epoch: vmHeight,
|
Epoch: vmHeight,
|
||||||
|
Timestamp: ts.MinTimestamp(),
|
||||||
Rand: rand.NewStateRand(sm.cs, ts.Cids(), sm.beacon, nvGetter),
|
Rand: rand.NewStateRand(sm.cs, ts.Cids(), sm.beacon, nvGetter),
|
||||||
Bstore: buffStore,
|
Bstore: buffStore,
|
||||||
Actors: sm.tsExec.NewActorRegistry(),
|
Actors: sm.tsExec.NewActorRegistry(),
|
||||||
@ -199,7 +200,7 @@ func (sm *StateManager) callInternal(ctx context.Context, msg *types.Message, pr
|
|||||||
var ret *vm.ApplyRet
|
var ret *vm.ApplyRet
|
||||||
var gasInfo api.MsgGasCost
|
var gasInfo api.MsgGasCost
|
||||||
if checkGas {
|
if checkGas {
|
||||||
fromKey, err := sm.ResolveToKeyAddress(ctx, msg.From, ts)
|
fromKey, err := sm.ResolveToDeterministicAddress(ctx, msg.From, ts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("could not resolve key: %w", err)
|
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),
|
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)
|
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())
|
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())
|
return s.gapi.StateAccountKey(ctx, addr, ts.Key())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ type StateManagerAPI interface {
|
|||||||
GetPaychState(ctx context.Context, addr address.Address, ts *types.TipSet) (*types.Actor, paych.State, error)
|
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)
|
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)
|
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 {
|
type versionSpec struct {
|
||||||
@ -207,11 +207,11 @@ func (sm *StateManager) Beacon() beacon.Schedule {
|
|||||||
return sm.beacon
|
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.
|
// 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() {
|
switch addr.Protocol() {
|
||||||
case address.BLS, address.SECP256K1:
|
case address.BLS, address.SECP256K1, address.Delegated:
|
||||||
return addr, nil
|
return addr, nil
|
||||||
case address.Actor:
|
case address.Actor:
|
||||||
return address.Undef, xerrors.New("cannot resolve actor address to key address")
|
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)
|
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 {
|
if err == nil {
|
||||||
return resolved, 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 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.
|
// 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() {
|
switch addr.Protocol() {
|
||||||
case address.BLS, address.SECP256K1:
|
case address.BLS, address.SECP256K1, address.Delegated:
|
||||||
return addr, nil
|
return addr, nil
|
||||||
case address.Actor:
|
case address.Actor:
|
||||||
return address.Undef, xerrors.New("cannot resolve actor address to key address")
|
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 {
|
if err == nil {
|
||||||
return resolved, 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) {
|
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 {
|
if err != nil {
|
||||||
return pubk, xerrors.Errorf("failed to resolve address to key address: %w", err)
|
return pubk, xerrors.Errorf("failed to resolve address to key address: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package stmgr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
@ -27,6 +28,8 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
"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) {
|
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)
|
act, err := sm.LoadActor(ctx, to, ts)
|
||||||
if err != nil {
|
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]
|
m, found := sm.tsExec.NewActorRegistry().Methods[act.Code][method]
|
||||||
if !found {
|
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
|
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) {
|
func GetParamType(ar *vm.ActorRegistry, actCode cid.Cid, method abi.MethodNum) (cbg.CBORUnmarshaler, error) {
|
||||||
m, found := ar.Methods[actCode][method]
|
m, found := ar.Methods[actCode][method]
|
||||||
if !found {
|
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
|
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{
|
vmopt := &vm.VMOpts{
|
||||||
StateBase: base,
|
StateBase: base,
|
||||||
Epoch: height,
|
Epoch: height,
|
||||||
|
Timestamp: ts.MinTimestamp(),
|
||||||
Rand: r,
|
Rand: r,
|
||||||
Bstore: sm.cs.StateBlockstore(),
|
Bstore: sm.cs.StateBlockstore(),
|
||||||
Actors: sm.tsExec.NewActorRegistry(),
|
Actors: sm.tsExec.NewActorRegistry(),
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package store
|
package store
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"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 {
|
func (cs *ChainStore) PutTipSet(ctx context.Context, ts *types.TipSet) error {
|
||||||
for _, b := range ts.Blocks() {
|
if err := cs.PersistTipset(ctx, ts); err != nil {
|
||||||
if err := cs.PersistBlockHeaders(ctx, b); err != nil {
|
return xerrors.Errorf("failed to persist tipset: %w", err)
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expanded, err := cs.expandTipset(ctx, ts.Blocks()[0])
|
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 {
|
if err := cs.writeHead(ctx, ts); err != nil {
|
||||||
log.Errorf("failed to write chain head: %s", err)
|
log.Errorf("failed to write chain head: %s", err)
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -958,7 +957,24 @@ func (cs *ChainStore) AddToTipSetTracker(ctx context.Context, b *types.BlockHead
|
|||||||
return nil
|
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))
|
sbs := make([]block.Block, len(b))
|
||||||
|
|
||||||
for i, header := range b {
|
for i, header := range b {
|
||||||
@ -1026,23 +1042,6 @@ func (cs *ChainStore) expandTipset(ctx context.Context, b *types.BlockHeader) (*
|
|||||||
return types.NewTipSet(all)
|
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) {
|
func (cs *ChainStore) GetGenesis(ctx context.Context) (*types.BlockHeader, error) {
|
||||||
data, err := cs.metadataDs.Get(ctx, dstore.NewKey("0"))
|
data, err := cs.metadataDs.Get(ctx, dstore.NewKey("0"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1165,6 +1164,24 @@ func (cs *ChainStore) GetTipsetByHeight(ctx context.Context, h abi.ChainEpoch, t
|
|||||||
return cs.LoadTipSet(ctx, lbts.Parents())
|
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
|
func (cs *ChainStore) Weight(ctx context.Context, hts *types.TipSet) (types.BigInt, error) { // todo remove
|
||||||
return cs.weight(ctx, cs.StateBlockstore(), hts)
|
return cs.weight(ctx, cs.StateBlockstore(), hts)
|
||||||
}
|
}
|
||||||
|
@ -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
|
// TODO: IMPORTANT(GARBAGE) this needs to be put in the 'temporary' side of
|
||||||
// the blockstore
|
// 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)
|
log.Warn("failed to persist incoming block header: ", err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -1145,7 +1145,7 @@ func persistMessages(ctx context.Context, bs bstore.Blockstore, bst *exchange.Co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, m := range bst.Secpk {
|
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)
|
return xerrors.Errorf("unknown signature type on message %s: %q", m.Cid(), m.Signature.Type)
|
||||||
}
|
}
|
||||||
//log.Infof("putting secp256k1 message: %s", m.Cid())
|
//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)
|
ss.SetStage(api.StagePersistHeaders)
|
||||||
|
|
||||||
toPersist := make([]*types.BlockHeader, 0, len(headers)*int(build.BlocksPerEpoch))
|
|
||||||
for _, ts := range headers {
|
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)
|
||||||
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)
|
ss.Error(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
toPersist = nil
|
}
|
||||||
|
|
||||||
ss.SetStage(api.StageMessages)
|
ss.SetStage(api.StageMessages)
|
||||||
|
|
||||||
|
@ -306,13 +306,13 @@ func (tu *syncTestUtil) addSourceNode(gen int) {
|
|||||||
require.NoError(tu.t, err)
|
require.NoError(tu.t, err)
|
||||||
tu.t.Cleanup(func() { _ = stop(context.Background()) })
|
tu.t.Cleanup(func() { _ = stop(context.Background()) })
|
||||||
|
|
||||||
lastTs := blocks[len(blocks)-1].Blocks
|
lastTs := blocks[len(blocks)-1]
|
||||||
for _, lastB := range lastTs {
|
|
||||||
cs := out.(*impl.FullNodeAPI).ChainAPI.Chain
|
cs := out.(*impl.FullNodeAPI).ChainAPI.Chain
|
||||||
|
for _, lastB := range lastTs.Blocks {
|
||||||
require.NoError(tu.t, cs.AddToTipSetTracker(context.Background(), lastB.Header))
|
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.genesis = genesis
|
||||||
tu.blocks = blocks
|
tu.blocks = blocks
|
||||||
|
@ -26,7 +26,7 @@ type ActorV5 struct {
|
|||||||
Head cid.Cid
|
Head cid.Cid
|
||||||
Nonce uint64
|
Nonce uint64
|
||||||
Balance BigInt
|
Balance BigInt
|
||||||
// Predictable Address
|
// Deterministic Address.
|
||||||
Address *address.Address
|
Address *address.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@ import (
|
|||||||
address "github.com/filecoin-project/go-address"
|
address "github.com/filecoin-project/go-address"
|
||||||
abi "github.com/filecoin-project/go-state-types/abi"
|
abi "github.com/filecoin-project/go-state-types/abi"
|
||||||
crypto "github.com/filecoin-project/go-state-types/crypto"
|
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"
|
proof "github.com/filecoin-project/go-state-types/proof"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1289,154 +1288,6 @@ func (t *ActorV5) UnmarshalCBOR(r io.Reader) (err error) {
|
|||||||
return nil
|
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}
|
var lengthBufBlockMsg = []byte{131}
|
||||||
|
|
||||||
func (t *BlockMsg) MarshalCBOR(w io.Writer) error {
|
func (t *BlockMsg) MarshalCBOR(w io.Writer) error {
|
||||||
@ -1986,3 +1837,224 @@ func (t *StateInfo0) UnmarshalCBOR(r io.Reader) (err error) {
|
|||||||
|
|
||||||
return nil
|
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
|
||||||
|
}
|
||||||
|
595
chain/types/ethtypes/eth_transactions.go
Normal file
595
chain/types/ethtypes/eth_transactions.go
Normal file
@ -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
|
||||||
|
}
|
251
chain/types/ethtypes/eth_transactions_test.go
Normal file
251
chain/types/ethtypes/eth_transactions_test.go
Normal file
File diff suppressed because one or more lines are too long
600
chain/types/ethtypes/eth_types.go
Normal file
600
chain/types/ethtypes/eth_types.go
Normal file
@ -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
|
||||||
|
}
|
384
chain/types/ethtypes/eth_types_test.go
Normal file
384
chain/types/ethtypes/eth_types_test.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
182
chain/types/ethtypes/rlp.go
Normal file
182
chain/types/ethtypes/rlp.go
Normal file
@ -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
|
||||||
|
}
|
190
chain/types/ethtypes/rlp_test.go
Normal file
190
chain/types/ethtypes/rlp_test.go
Normal file
@ -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)
|
||||||
|
}
|
32
chain/types/event.go
Normal file
32
chain/types/event.go
Normal file
@ -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
|
*kt = KTBLS
|
||||||
case crypto.SigTypeSecp256k1:
|
case crypto.SigTypeSecp256k1:
|
||||||
*kt = KTSecp256k1
|
*kt = KTSecp256k1
|
||||||
|
case crypto.SigTypeDelegated:
|
||||||
|
*kt = KTDelegated
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown sigtype: %d", bst)
|
return fmt.Errorf("unknown sigtype: %d", bst)
|
||||||
}
|
}
|
||||||
@ -51,6 +53,7 @@ const (
|
|||||||
KTBLS KeyType = "bls"
|
KTBLS KeyType = "bls"
|
||||||
KTSecp256k1 KeyType = "secp256k1"
|
KTSecp256k1 KeyType = "secp256k1"
|
||||||
KTSecp256k1Ledger KeyType = "secp256k1-ledger"
|
KTSecp256k1Ledger KeyType = "secp256k1-ledger"
|
||||||
|
KTDelegated KeyType = "delegated"
|
||||||
)
|
)
|
||||||
|
|
||||||
// KeyInfo is used for storing keys in KeyStore
|
// KeyInfo is used for storing keys in KeyStore
|
||||||
|
@ -3,15 +3,59 @@ package types
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
||||||
|
"github.com/ipfs/go-cid"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-state-types/exitcode"
|
"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 {
|
type MessageReceipt struct {
|
||||||
|
version MessageReceiptVersion
|
||||||
|
|
||||||
ExitCode exitcode.ExitCode
|
ExitCode exitcode.ExitCode
|
||||||
Return []byte
|
Return []byte
|
||||||
GasUsed int64
|
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 {
|
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))
|
||||||
}
|
}
|
||||||
|
359
chain/types/message_receipt_cbor.go
Normal file
359
chain/types/message_receipt_cbor.go
Normal file
@ -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
|
||||||
|
}
|
75
chain/types/message_receipt_test.go
Normal file
75
chain/types/message_receipt_test.go
Normal file
@ -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)
|
||||||
|
}
|
@ -196,8 +196,23 @@ func (ts *TipSet) MinTicket() *Ticket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ts *TipSet) MinTimestamp() uint64 {
|
func (ts *TipSet) MinTimestamp() uint64 {
|
||||||
minTs := ts.Blocks()[0].Timestamp
|
if ts == nil {
|
||||||
for _, bh := range ts.Blocks()[1:] {
|
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 {
|
if bh.Timestamp < minTs {
|
||||||
minTs = bh.Timestamp
|
minTs = bh.Timestamp
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,8 @@ type StateTree interface {
|
|||||||
SetActor(addr address.Address, act *Actor) error
|
SetActor(addr address.Address, act *Actor) error
|
||||||
// GetActor returns the actor from any type of `addr` provided.
|
// GetActor returns the actor from any type of `addr` provided.
|
||||||
GetActor(addr address.Address) (*Actor, error)
|
GetActor(addr address.Address) (*Actor, error)
|
||||||
|
|
||||||
|
Version() StateTreeVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
type storageWrapper struct {
|
type storageWrapper struct {
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/vectors"
|
"github.com/filecoin-project/lotus/chain/vectors"
|
||||||
"github.com/filecoin-project/lotus/chain/wallet"
|
"github.com/filecoin-project/lotus/chain/wallet"
|
||||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
|
_ "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/lib/sigs/secp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
||||||
"github.com/filecoin-project/go-state-types/exitcode"
|
"github.com/filecoin-project/go-state-types/exitcode"
|
||||||
"github.com/filecoin-project/go-state-types/manifest"
|
"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/blockstore"
|
||||||
"github.com/filecoin-project/lotus/build"
|
"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
|
return address.Undef, gasUsed, err
|
||||||
}
|
}
|
||||||
|
|
||||||
raddr, err := ResolveToKeyAddr(stateTree, cstWithGas, info.Worker)
|
raddr, err := ResolveToDeterministicAddr(stateTree, cstWithGas, info.Worker)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return address.Undef, gasUsed, err
|
return address.Undef, gasUsed, err
|
||||||
}
|
}
|
||||||
@ -285,6 +286,7 @@ func (x *FvmExtern) workerKeyAtLookback(ctx context.Context, minerId address.Add
|
|||||||
|
|
||||||
type FVM struct {
|
type FVM struct {
|
||||||
fvm *ffi.FVM
|
fvm *ffi.FVM
|
||||||
|
nv network.Version
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultFVMOpts(ctx context.Context, opts *VMOpts) (*ffi.FVMOpts, error) {
|
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,
|
||||||
},
|
},
|
||||||
Epoch: opts.Epoch,
|
Epoch: opts.Epoch,
|
||||||
|
Timestamp: opts.Timestamp,
|
||||||
|
ChainID: build.Eip155ChainId,
|
||||||
BaseFee: opts.BaseFee,
|
BaseFee: opts.BaseFee,
|
||||||
BaseCircSupply: circToReport,
|
BaseCircSupply: circToReport,
|
||||||
NetworkVersion: opts.NetworkVersion,
|
NetworkVersion: opts.NetworkVersion,
|
||||||
StateBase: opts.StateBase,
|
StateBase: opts.StateBase,
|
||||||
Tracing: opts.Tracing || EnableDetailedTracing,
|
Tracing: opts.Tracing || EnableDetailedTracing,
|
||||||
|
Debug: build.ActorDebugging,
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -324,20 +329,6 @@ func NewFVM(ctx context.Context, opts *VMOpts) (*FVM, error) {
|
|||||||
return nil, xerrors.Errorf("creating fvm opts: %w", err)
|
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)
|
fvm, err := ffi.CreateFVM(fvmOpts)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -346,6 +337,7 @@ func NewFVM(ctx context.Context, opts *VMOpts) (*FVM, error) {
|
|||||||
|
|
||||||
return &FVM{
|
return &FVM{
|
||||||
fvm: fvm,
|
fvm: fvm,
|
||||||
|
nv: opts.NetworkVersion,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,6 +440,7 @@ func NewDebugFVM(ctx context.Context, opts *VMOpts) (*FVM, error) {
|
|||||||
|
|
||||||
return &FVM{
|
return &FVM{
|
||||||
fvm: fvm,
|
fvm: fvm,
|
||||||
|
nv: opts.NetworkVersion,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -466,10 +459,12 @@ func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet
|
|||||||
}
|
}
|
||||||
|
|
||||||
duration := time.Since(start)
|
duration := time.Since(start)
|
||||||
receipt := types.MessageReceipt{
|
|
||||||
Return: ret.Return,
|
var receipt types.MessageReceipt
|
||||||
ExitCode: exitcode.ExitCode(ret.ExitCode),
|
if vm.nv >= network.Version18 {
|
||||||
GasUsed: ret.GasUsed,
|
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
|
var aerr aerrors.ActorError
|
||||||
@ -530,10 +525,12 @@ func (vm *FVM) ApplyImplicitMessage(ctx context.Context, cmsg *types.Message) (*
|
|||||||
}
|
}
|
||||||
|
|
||||||
duration := time.Since(start)
|
duration := time.Since(start)
|
||||||
receipt := types.MessageReceipt{
|
|
||||||
Return: ret.Return,
|
var receipt types.MessageReceipt
|
||||||
ExitCode: exitcode.ExitCode(ret.ExitCode),
|
if vm.nv >= network.Version18 {
|
||||||
GasUsed: ret.GasUsed,
|
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
|
var aerr aerrors.ActorError
|
||||||
|
@ -111,6 +111,7 @@ var Prices = map[abi.ChainEpoch]Pricelist{
|
|||||||
verifySignature: map[crypto.SigType]int64{
|
verifySignature: map[crypto.SigType]int64{
|
||||||
crypto.SigTypeBLS: 16598605,
|
crypto.SigTypeBLS: 16598605,
|
||||||
crypto.SigTypeSecp256k1: 1637292,
|
crypto.SigTypeSecp256k1: 1637292,
|
||||||
|
crypto.SigTypeDelegated: 1637292,
|
||||||
},
|
},
|
||||||
|
|
||||||
hashingBase: 31355,
|
hashingBase: 31355,
|
||||||
|
@ -284,16 +284,16 @@ func DecodeParams(b []byte, out interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func DumpActorState(i *ActorRegistry, act *types.Actor, b []byte) (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]
|
actInfo, ok := i.actors[act.Code]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, xerrors.Errorf("state type for actor %s not found", act.Code)
|
return nil, xerrors.Errorf("state type for actor %s not found", act.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
um := actInfo.vmActor.State()
|
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 {
|
if err := um.UnmarshalCBOR(bytes.NewReader(b)); err != nil {
|
||||||
return nil, xerrors.Errorf("unmarshaling actor state: %w", err)
|
return nil, xerrors.Errorf("unmarshaling actor state: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -249,7 +249,7 @@ func (rt *Runtime) GetRandomnessFromBeacon(personalization crypto.DomainSeparati
|
|||||||
|
|
||||||
func (rt *Runtime) NewActorAddress() address.Address {
|
func (rt *Runtime) NewActorAddress() address.Address {
|
||||||
var b bytes.Buffer
|
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?
|
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))
|
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 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 {
|
func (ss *syscallShim) VerifyPoSt(info proof7.WindowPoStVerifyInfo) error {
|
||||||
@ -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 {
|
func (ss *syscallShim) VerifySignature(sig crypto.Signature, addr address.Address, input []byte) error {
|
||||||
// TODO: in genesis setup, we are currently faking signatures
|
// 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -45,9 +45,11 @@ var (
|
|||||||
gasOnActorExec = newGasCharge("OnActorExec", 0, 0)
|
gasOnActorExec = newGasCharge("OnActorExec", 0, 0)
|
||||||
)
|
)
|
||||||
|
|
||||||
// ResolveToKeyAddr returns the public key type of address (`BLS`/`SECP256K1`) of an account actor identified by `addr`.
|
// ResolveToDeterministicAddr returns the public key type of address
|
||||||
func ResolveToKeyAddr(state types.StateTree, cst cbor.IpldStore, addr address.Address) (address.Address, error) {
|
// (`BLS`/`SECP256K1`) of an actor identified by `addr`, or its
|
||||||
if addr.Protocol() == address.BLS || addr.Protocol() == address.SECP256K1 {
|
// 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
|
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)
|
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)
|
aast, err := account.Load(adt.WrapStore(context.TODO(), cst), act)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return address.Undef, xerrors.Errorf("failed to get account actor state for %s: %w", addr, err)
|
return address.Undef, xerrors.Errorf("failed to get account actor state for %s: %w", addr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return aast.PubkeyAddress()
|
return aast.PubkeyAddress()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -216,6 +225,7 @@ type LegacyVM struct {
|
|||||||
type VMOpts struct {
|
type VMOpts struct {
|
||||||
StateBase cid.Cid
|
StateBase cid.Cid
|
||||||
Epoch abi.ChainEpoch
|
Epoch abi.ChainEpoch
|
||||||
|
Timestamp uint64
|
||||||
Rand Rand
|
Rand Rand
|
||||||
Bstore blockstore.Blockstore
|
Bstore blockstore.Blockstore
|
||||||
Actors *ActorRegistry
|
Actors *ActorRegistry
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/filecoin-project/go-state-types/crypto"
|
"github.com/filecoin-project/go-state-types/crypto"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||||
"github.com/filecoin-project/lotus/lib/sigs"
|
"github.com/filecoin-project/lotus/lib/sigs"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -50,6 +51,22 @@ func NewKey(keyinfo types.KeyInfo) (*Key, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("converting Secp256k1 to address: %w", err)
|
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:
|
case types.KTBLS:
|
||||||
k.Address, err = address.NewBLSAddress(k.PublicKey)
|
k.Address, err = address.NewBLSAddress(k.PublicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -58,6 +75,7 @@ func NewKey(keyinfo types.KeyInfo) (*Key, error) {
|
|||||||
default:
|
default:
|
||||||
return nil, xerrors.Errorf("unsupported key type: %s", k.Type)
|
return nil, xerrors.Errorf("unsupported key type: %s", k.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
return k, nil
|
return k, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -68,6 +86,8 @@ func ActSigType(typ types.KeyType) crypto.SigType {
|
|||||||
return crypto.SigTypeBLS
|
return crypto.SigTypeBLS
|
||||||
case types.KTSecp256k1:
|
case types.KTSecp256k1:
|
||||||
return crypto.SigTypeSecp256k1
|
return crypto.SigTypeSecp256k1
|
||||||
|
case types.KTDelegated:
|
||||||
|
return crypto.SigTypeDelegated
|
||||||
default:
|
default:
|
||||||
return crypto.SigTypeUnknown
|
return crypto.SigTypeUnknown
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/wallet/key"
|
"github.com/filecoin-project/lotus/chain/wallet/key"
|
||||||
"github.com/filecoin-project/lotus/lib/sigs"
|
"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
|
_ "github.com/filecoin-project/lotus/lib/sigs/secp" // enable secp signatures
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -81,6 +81,7 @@ var Commands = []*cli.Command{
|
|||||||
WithCategory("developer", LogCmd),
|
WithCategory("developer", LogCmd),
|
||||||
WithCategory("developer", WaitApiCmd),
|
WithCategory("developer", WaitApiCmd),
|
||||||
WithCategory("developer", FetchParamCmd),
|
WithCategory("developer", FetchParamCmd),
|
||||||
|
WithCategory("developer", EvmCmd),
|
||||||
WithCategory("network", NetCmd),
|
WithCategory("network", NetCmd),
|
||||||
WithCategory("network", SyncCmd),
|
WithCategory("network", SyncCmd),
|
||||||
WithCategory("status", StatusCmd),
|
WithCategory("status", StatusCmd),
|
||||||
|
503
cli/evm.go
Normal file
503
cli/evm.go
Normal file
@ -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("Nonce:\t\t%d\n", a.Nonce)
|
||||||
fmt.Printf("Code:\t\t%s (%s)\n", a.Code, strtype)
|
fmt.Printf("Code:\t\t%s (%s)\n", a.Code, strtype)
|
||||||
fmt.Printf("Head:\t\t%s\n", a.Head)
|
fmt.Printf("Head:\t\t%s\n", a.Head)
|
||||||
|
fmt.Printf("Delegated address:\t\t%s\n", a.Address)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
@ -41,6 +41,7 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/vm"
|
"github.com/filecoin-project/lotus/chain/vm"
|
||||||
lcli "github.com/filecoin-project/lotus/cli"
|
lcli "github.com/filecoin-project/lotus/cli"
|
||||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
|
_ "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/lib/sigs/secp"
|
||||||
"github.com/filecoin-project/lotus/node/repo"
|
"github.com/filecoin-project/lotus/node/repo"
|
||||||
"github.com/filecoin-project/lotus/storage/sealer/ffiwrapper"
|
"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/types"
|
||||||
"github.com/filecoin-project/lotus/chain/wallet"
|
"github.com/filecoin-project/lotus/chain/wallet"
|
||||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
|
_ "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/lib/sigs/secp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/wallet"
|
"github.com/filecoin-project/lotus/chain/wallet"
|
||||||
"github.com/filecoin-project/lotus/chain/wallet/key"
|
"github.com/filecoin-project/lotus/chain/wallet/key"
|
||||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
|
_ "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/lib/sigs/secp"
|
||||||
"github.com/filecoin-project/lotus/node/modules"
|
"github.com/filecoin-project/lotus/node/modules"
|
||||||
"github.com/filecoin-project/lotus/node/modules/lp2p"
|
"github.com/filecoin-project/lotus/node/modules/lp2p"
|
||||||
|
@ -4,10 +4,10 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
logging "github.com/ipfs/go-log/v2"
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
cbg "github.com/whyrusleeping/cbor-gen"
|
cbg "github.com/whyrusleeping/cbor-gen"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
@ -25,6 +25,8 @@ import (
|
|||||||
adt9 "github.com/filecoin-project/go-state-types/builtin/v9/util/adt"
|
adt9 "github.com/filecoin-project/go-state-types/builtin/v9/util/adt"
|
||||||
verifreg9 "github.com/filecoin-project/go-state-types/builtin/v9/verifreg"
|
verifreg9 "github.com/filecoin-project/go-state-types/builtin/v9/verifreg"
|
||||||
"github.com/filecoin-project/go-state-types/manifest"
|
"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/specs-actors/v7/actors/migration/nv15"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/blockstore"
|
"github.com/filecoin-project/lotus/blockstore"
|
||||||
@ -47,9 +49,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var migrationsCmd = &cli.Command{
|
var migrationsCmd = &cli.Command{
|
||||||
Name: "migrate-nv17",
|
Name: "migrate-state",
|
||||||
Description: "Run the nv17 migration",
|
Description: "Run a network upgrade migration",
|
||||||
ArgsUsage: "[block to look back from]",
|
ArgsUsage: "[new network version, block to look back from]",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "repo",
|
Name: "repo",
|
||||||
@ -65,16 +67,21 @@ var migrationsCmd = &cli.Command{
|
|||||||
Action: func(cctx *cli.Context) error {
|
Action: func(cctx *cli.Context) error {
|
||||||
ctx := context.TODO()
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if cctx.NArg() != 1 {
|
blkCid, err := cid.Decode(cctx.Args().Get(1))
|
||||||
return lcli.IncorrectNumArgs(cctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
blkCid, err := cid.Decode(cctx.Args().First())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to parse input: %w", err)
|
return fmt.Errorf("failed to parse input: %w", err)
|
||||||
}
|
}
|
||||||
@ -129,7 +136,7 @@ var migrationsCmd = &cli.Command{
|
|||||||
|
|
||||||
startTime := time.Now()
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -142,7 +149,7 @@ var migrationsCmd = &cli.Command{
|
|||||||
fmt.Println("completed round actual (without cache), took ", uncachedMigrationTime)
|
fmt.Println("completed round actual (without cache), took ", uncachedMigrationTime)
|
||||||
|
|
||||||
if !cctx.IsSet("skip-pre-migration") {
|
if !cctx.IsSet("skip-pre-migration") {
|
||||||
cache := nv15.NewMemMigrationCache()
|
cache := mutil.NewMemMigrationCache()
|
||||||
|
|
||||||
ts1, err := cs.GetTipsetByHeight(ctx, blk.Height-240, migrationTs, false)
|
ts1, err := cs.GetTipsetByHeight(ctx, blk.Height-240, migrationTs, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -151,7 +158,7 @@ var migrationsCmd = &cli.Command{
|
|||||||
|
|
||||||
startTime = time.Now()
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -165,7 +172,7 @@ var migrationsCmd = &cli.Command{
|
|||||||
|
|
||||||
startTime = time.Now()
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -174,7 +181,7 @@ var migrationsCmd = &cli.Command{
|
|||||||
|
|
||||||
startTime = time.Now()
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -191,7 +198,10 @@ var migrationsCmd = &cli.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cctx.Bool("check-invariants") {
|
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 {
|
if err != nil {
|
||||||
return err
|
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)
|
actorStore := store.ActorStore(ctx, bs)
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
|
||||||
|
@ -74,14 +74,17 @@ func (sim *Simulation) makeTipSet(ctx context.Context, messages []*types.Message
|
|||||||
Timestamp: uts,
|
Timestamp: uts,
|
||||||
ElectionProof: &types.ElectionProof{WinCount: 1},
|
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)
|
newTipSet, err := types.NewTipSet(blks)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("failed to create new tipset: %w", err)
|
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()
|
now := time.Now()
|
||||||
_, _, err = sim.StateManager.TipSetState(ctx, newTipSet)
|
_, _, err = sim.StateManager.TipSetState(ctx, newTipSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -28,6 +28,7 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/vm"
|
"github.com/filecoin-project/lotus/chain/vm"
|
||||||
"github.com/filecoin-project/lotus/conformance/chaos"
|
"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/lib/sigs/secp" // enable secp signatures
|
||||||
"github.com/filecoin-project/lotus/storage/sealer/ffiwrapper"
|
"github.com/filecoin-project/lotus/storage/sealer/ffiwrapper"
|
||||||
)
|
)
|
||||||
|
@ -464,7 +464,9 @@ Inputs:
|
|||||||
{
|
{
|
||||||
"SealProof": 8,
|
"SealProof": 8,
|
||||||
"SectorNumber": 9,
|
"SectorNumber": 9,
|
||||||
"SectorKey": null,
|
"SectorKey": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"SealedCID": {
|
"SealedCID": {
|
||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
}
|
}
|
||||||
@ -1279,8 +1281,12 @@ Response:
|
|||||||
"ProposalCid": {
|
"ProposalCid": {
|
||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
},
|
},
|
||||||
"AddFundsCid": null,
|
"AddFundsCid": {
|
||||||
"PublishCid": null,
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
|
"PublishCid": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"Miner": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
"Miner": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
||||||
"Client": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
"Client": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
||||||
"State": 42,
|
"State": 42,
|
||||||
@ -1295,7 +1301,9 @@ Response:
|
|||||||
"Root": {
|
"Root": {
|
||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
},
|
},
|
||||||
"PieceCid": null,
|
"PieceCid": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"PieceSize": 1024,
|
"PieceSize": 1024,
|
||||||
"RawBlockSize": 42
|
"RawBlockSize": 42
|
||||||
},
|
},
|
||||||
@ -1457,8 +1465,12 @@ Response:
|
|||||||
"ProposalCid": {
|
"ProposalCid": {
|
||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
},
|
},
|
||||||
"AddFundsCid": null,
|
"AddFundsCid": {
|
||||||
"PublishCid": null,
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
|
"PublishCid": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"Miner": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
"Miner": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
||||||
"Client": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
"Client": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
||||||
"State": 42,
|
"State": 42,
|
||||||
@ -1473,7 +1485,9 @@ Response:
|
|||||||
"Root": {
|
"Root": {
|
||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
},
|
},
|
||||||
"PieceCid": null,
|
"PieceCid": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"PieceSize": 1024,
|
"PieceSize": 1024,
|
||||||
"RawBlockSize": 42
|
"RawBlockSize": 42
|
||||||
},
|
},
|
||||||
@ -1509,7 +1523,9 @@ Response:
|
|||||||
"Selector": {
|
"Selector": {
|
||||||
"Raw": "Ynl0ZSBhcnJheQ=="
|
"Raw": "Ynl0ZSBhcnJheQ=="
|
||||||
},
|
},
|
||||||
"PieceCID": null,
|
"PieceCID": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"PricePerByte": "0",
|
"PricePerByte": "0",
|
||||||
"PaymentInterval": 42,
|
"PaymentInterval": 42,
|
||||||
"PaymentIntervalIncrease": 42,
|
"PaymentIntervalIncrease": 42,
|
||||||
@ -2908,7 +2924,9 @@ Inputs:
|
|||||||
1024,
|
1024,
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
"PublishCid": null,
|
"PublishCid": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"DealID": 5432,
|
"DealID": 5432,
|
||||||
"DealProposal": {
|
"DealProposal": {
|
||||||
"PieceCID": {
|
"PieceCID": {
|
||||||
@ -2962,7 +2980,9 @@ Response:
|
|||||||
"FailedSectors": {
|
"FailedSectors": {
|
||||||
"123": "can't acquire read lock"
|
"123": "can't acquire read lock"
|
||||||
},
|
},
|
||||||
"Msg": null,
|
"Msg": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"Error": "string value"
|
"Error": "string value"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -3156,7 +3176,9 @@ Response:
|
|||||||
123,
|
123,
|
||||||
124
|
124
|
||||||
],
|
],
|
||||||
"Msg": null,
|
"Msg": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"Error": "string value"
|
"Error": "string value"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -3204,7 +3226,9 @@ Inputs:
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"DealInfo": {
|
"DealInfo": {
|
||||||
"PublishCid": null,
|
"PublishCid": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"DealID": 5432,
|
"DealID": 5432,
|
||||||
"DealProposal": {
|
"DealProposal": {
|
||||||
"PieceCID": {
|
"PieceCID": {
|
||||||
@ -3232,8 +3256,12 @@ Inputs:
|
|||||||
"TicketValue": "Bw==",
|
"TicketValue": "Bw==",
|
||||||
"TicketEpoch": 10101,
|
"TicketEpoch": 10101,
|
||||||
"PreCommit1Out": "Bw==",
|
"PreCommit1Out": "Bw==",
|
||||||
"CommD": null,
|
"CommD": {
|
||||||
"CommR": null,
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
|
"CommR": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"PreCommitInfo": {
|
"PreCommitInfo": {
|
||||||
"SealProof": 8,
|
"SealProof": 8,
|
||||||
"SectorNumber": 9,
|
"SectorNumber": 9,
|
||||||
@ -3245,10 +3273,14 @@ Inputs:
|
|||||||
5432
|
5432
|
||||||
],
|
],
|
||||||
"Expiration": 10101,
|
"Expiration": 10101,
|
||||||
"UnsealedCid": null
|
"UnsealedCid": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"PreCommitDeposit": "0",
|
"PreCommitDeposit": "0",
|
||||||
"PreCommitMessage": null,
|
"PreCommitMessage": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"PreCommitTipSet": [
|
"PreCommitTipSet": [
|
||||||
{
|
{
|
||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
@ -3260,7 +3292,9 @@ Inputs:
|
|||||||
"SeedValue": "Bw==",
|
"SeedValue": "Bw==",
|
||||||
"SeedEpoch": 10101,
|
"SeedEpoch": 10101,
|
||||||
"CommitProof": "Ynl0ZSBhcnJheQ==",
|
"CommitProof": "Ynl0ZSBhcnJheQ==",
|
||||||
"CommitMessage": null,
|
"CommitMessage": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"Log": [
|
"Log": [
|
||||||
{
|
{
|
||||||
"Kind": "string value",
|
"Kind": "string value",
|
||||||
@ -3396,7 +3430,12 @@ Perms: admin
|
|||||||
|
|
||||||
Inputs: `null`
|
Inputs: `null`
|
||||||
|
|
||||||
Response: `null`
|
Response:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### SectorTerminatePending
|
### SectorTerminatePending
|
||||||
SectorTerminatePending returns a list of pending sector terminations to be sent in the next batch message
|
SectorTerminatePending returns a list of pending sector terminations to be sent in the next batch message
|
||||||
@ -3497,8 +3536,12 @@ Response:
|
|||||||
{
|
{
|
||||||
"SectorID": 9,
|
"SectorID": 9,
|
||||||
"State": "Proving",
|
"State": "Proving",
|
||||||
"CommD": null,
|
"CommD": {
|
||||||
"CommR": null,
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
|
"CommR": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"Proof": "Ynl0ZSBhcnJheQ==",
|
"Proof": "Ynl0ZSBhcnJheQ==",
|
||||||
"Deals": [
|
"Deals": [
|
||||||
5432
|
5432
|
||||||
@ -3512,7 +3555,9 @@ Response:
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"DealInfo": {
|
"DealInfo": {
|
||||||
"PublishCid": null,
|
"PublishCid": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"DealID": 5432,
|
"DealID": 5432,
|
||||||
"DealProposal": {
|
"DealProposal": {
|
||||||
"PieceCID": {
|
"PieceCID": {
|
||||||
@ -3545,11 +3590,17 @@ Response:
|
|||||||
"Value": "Bw==",
|
"Value": "Bw==",
|
||||||
"Epoch": 10101
|
"Epoch": 10101
|
||||||
},
|
},
|
||||||
"PreCommitMsg": null,
|
"PreCommitMsg": {
|
||||||
"CommitMsg": null,
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
|
"CommitMsg": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"Retries": 42,
|
"Retries": 42,
|
||||||
"ToUpgrade": true,
|
"ToUpgrade": true,
|
||||||
"ReplicaUpdateMessage": null,
|
"ReplicaUpdateMessage": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"LastErr": "string value",
|
"LastErr": "string value",
|
||||||
"Log": [
|
"Log": [
|
||||||
{
|
{
|
||||||
@ -3603,7 +3654,9 @@ Inputs:
|
|||||||
1040384,
|
1040384,
|
||||||
1024,
|
1024,
|
||||||
"Bw==",
|
"Bw==",
|
||||||
null
|
{
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -754,7 +754,10 @@ Response:
|
|||||||
{
|
{
|
||||||
"ExitCode": 0,
|
"ExitCode": 0,
|
||||||
"Return": "Ynl0ZSBhcnJheQ==",
|
"Return": "Ynl0ZSBhcnJheQ==",
|
||||||
"GasUsed": 9
|
"GasUsed": 9,
|
||||||
|
"EventsRoot": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
@ -1247,7 +1250,9 @@ Inputs:
|
|||||||
{
|
{
|
||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
},
|
},
|
||||||
null
|
{
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -1259,7 +1264,9 @@ Response:
|
|||||||
"Root": {
|
"Root": {
|
||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
},
|
},
|
||||||
"Piece": null,
|
"Piece": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"Size": 42,
|
"Size": 42,
|
||||||
"MinPrice": "0",
|
"MinPrice": "0",
|
||||||
"UnsealPrice": "0",
|
"UnsealPrice": "0",
|
||||||
@ -1270,7 +1277,9 @@ Response:
|
|||||||
"MinerPeer": {
|
"MinerPeer": {
|
||||||
"Address": "f01234",
|
"Address": "f01234",
|
||||||
"ID": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
"ID": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
||||||
"PieceCID": null
|
"PieceCID": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -1341,7 +1350,9 @@ Response:
|
|||||||
"Root": {
|
"Root": {
|
||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
},
|
},
|
||||||
"PieceCid": null,
|
"PieceCid": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"PieceSize": 1024,
|
"PieceSize": 1024,
|
||||||
"RawBlockSize": 42
|
"RawBlockSize": 42
|
||||||
},
|
},
|
||||||
@ -1445,7 +1456,9 @@ Response:
|
|||||||
"Root": {
|
"Root": {
|
||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
},
|
},
|
||||||
"PieceCid": null,
|
"PieceCid": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"PieceSize": 1024,
|
"PieceSize": 1024,
|
||||||
"RawBlockSize": 42
|
"RawBlockSize": 42
|
||||||
},
|
},
|
||||||
@ -1510,7 +1523,9 @@ Response:
|
|||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
},
|
},
|
||||||
"ID": 5,
|
"ID": 5,
|
||||||
"PieceCID": null,
|
"PieceCID": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"PricePerByte": "0",
|
"PricePerByte": "0",
|
||||||
"UnsealPrice": "0",
|
"UnsealPrice": "0",
|
||||||
"Status": 0,
|
"Status": 0,
|
||||||
@ -1683,7 +1698,9 @@ Response:
|
|||||||
"Root": {
|
"Root": {
|
||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
},
|
},
|
||||||
"PieceCid": null,
|
"PieceCid": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"PieceSize": 1024,
|
"PieceSize": 1024,
|
||||||
"RawBlockSize": 42
|
"RawBlockSize": 42
|
||||||
},
|
},
|
||||||
@ -1748,7 +1765,9 @@ Response:
|
|||||||
{
|
{
|
||||||
"Key": 50,
|
"Key": 50,
|
||||||
"Err": "string value",
|
"Err": "string value",
|
||||||
"Root": null,
|
"Root": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"Source": "string value",
|
"Source": "string value",
|
||||||
"FilePath": "string value",
|
"FilePath": "string value",
|
||||||
"CARPath": "string value"
|
"CARPath": "string value"
|
||||||
@ -1773,7 +1792,9 @@ Response:
|
|||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
},
|
},
|
||||||
"ID": 5,
|
"ID": 5,
|
||||||
"PieceCID": null,
|
"PieceCID": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"PricePerByte": "0",
|
"PricePerByte": "0",
|
||||||
"UnsealPrice": "0",
|
"UnsealPrice": "0",
|
||||||
"Status": 0,
|
"Status": 0,
|
||||||
@ -1834,7 +1855,9 @@ Inputs:
|
|||||||
{
|
{
|
||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
},
|
},
|
||||||
null
|
{
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -1845,7 +1868,9 @@ Response:
|
|||||||
"Root": {
|
"Root": {
|
||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
},
|
},
|
||||||
"Piece": null,
|
"Piece": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"Size": 42,
|
"Size": 42,
|
||||||
"MinPrice": "0",
|
"MinPrice": "0",
|
||||||
"UnsealPrice": "0",
|
"UnsealPrice": "0",
|
||||||
@ -1856,7 +1881,9 @@ Response:
|
|||||||
"MinerPeer": {
|
"MinerPeer": {
|
||||||
"Address": "f01234",
|
"Address": "f01234",
|
||||||
"ID": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
"ID": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
||||||
"PieceCID": null
|
"PieceCID": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -1933,7 +1960,9 @@ Inputs:
|
|||||||
"Root": {
|
"Root": {
|
||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
},
|
},
|
||||||
"Piece": null,
|
"Piece": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"DatamodelPathSelector": "Links/21/Hash/Links/42/Hash",
|
"DatamodelPathSelector": "Links/21/Hash/Links/42/Hash",
|
||||||
"Size": 42,
|
"Size": 42,
|
||||||
"FromLocalCAR": "string value",
|
"FromLocalCAR": "string value",
|
||||||
@ -1946,7 +1975,9 @@ Inputs:
|
|||||||
"MinerPeer": {
|
"MinerPeer": {
|
||||||
"Address": "f01234",
|
"Address": "f01234",
|
||||||
"ID": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
"ID": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
||||||
"PieceCID": null
|
"PieceCID": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1988,7 +2019,9 @@ Inputs:
|
|||||||
"Root": {
|
"Root": {
|
||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
},
|
},
|
||||||
"Piece": null,
|
"Piece": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"DatamodelPathSelector": "Links/21/Hash/Links/42/Hash",
|
"DatamodelPathSelector": "Links/21/Hash/Links/42/Hash",
|
||||||
"Size": 42,
|
"Size": 42,
|
||||||
"FromLocalCAR": "string value",
|
"FromLocalCAR": "string value",
|
||||||
@ -2001,7 +2034,9 @@ Inputs:
|
|||||||
"MinerPeer": {
|
"MinerPeer": {
|
||||||
"Address": "f01234",
|
"Address": "f01234",
|
||||||
"ID": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
"ID": "12D3KooWGzxzKZYveHXtpG6AsrUJBcWxHBFS2HsEoGTxrMLvKXtf",
|
||||||
"PieceCID": null
|
"PieceCID": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2037,7 +2072,9 @@ Inputs:
|
|||||||
"Root": {
|
"Root": {
|
||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
},
|
},
|
||||||
"PieceCid": null,
|
"PieceCid": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"PieceSize": 1024,
|
"PieceSize": 1024,
|
||||||
"RawBlockSize": 42
|
"RawBlockSize": 42
|
||||||
},
|
},
|
||||||
@ -2053,7 +2090,12 @@ Inputs:
|
|||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
Response: `null`
|
Response:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### ClientStatelessDeal
|
### ClientStatelessDeal
|
||||||
ClientStatelessDeal fire-and-forget-proposes an offline deal to a miner without subsequent tracking.
|
ClientStatelessDeal fire-and-forget-proposes an offline deal to a miner without subsequent tracking.
|
||||||
@ -2070,7 +2112,9 @@ Inputs:
|
|||||||
"Root": {
|
"Root": {
|
||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
},
|
},
|
||||||
"PieceCid": null,
|
"PieceCid": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"PieceSize": 1024,
|
"PieceSize": 1024,
|
||||||
"RawBlockSize": 42
|
"RawBlockSize": 42
|
||||||
},
|
},
|
||||||
@ -2086,7 +2130,12 @@ Inputs:
|
|||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
Response: `null`
|
Response:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Create
|
## Create
|
||||||
|
|
||||||
@ -2613,7 +2662,9 @@ Response:
|
|||||||
{
|
{
|
||||||
"SealProof": 8,
|
"SealProof": 8,
|
||||||
"SectorNumber": 9,
|
"SectorNumber": 9,
|
||||||
"SectorKey": null,
|
"SectorKey": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"SealedCID": {
|
"SealedCID": {
|
||||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
}
|
}
|
||||||
@ -4156,7 +4207,9 @@ Response:
|
|||||||
"PendingAmt": "0",
|
"PendingAmt": "0",
|
||||||
"NonReservedAmt": "0",
|
"NonReservedAmt": "0",
|
||||||
"PendingAvailableAmt": "0",
|
"PendingAvailableAmt": "0",
|
||||||
"PendingWaitSentinel": null,
|
"PendingWaitSentinel": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"QueuedAmt": "0",
|
"QueuedAmt": "0",
|
||||||
"VoucherReedeemedAmt": "0"
|
"VoucherReedeemedAmt": "0"
|
||||||
}
|
}
|
||||||
@ -4185,7 +4238,9 @@ Response:
|
|||||||
"PendingAmt": "0",
|
"PendingAmt": "0",
|
||||||
"NonReservedAmt": "0",
|
"NonReservedAmt": "0",
|
||||||
"PendingAvailableAmt": "0",
|
"PendingAvailableAmt": "0",
|
||||||
"PendingWaitSentinel": null,
|
"PendingWaitSentinel": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"QueuedAmt": "0",
|
"QueuedAmt": "0",
|
||||||
"VoucherReedeemedAmt": "0"
|
"VoucherReedeemedAmt": "0"
|
||||||
}
|
}
|
||||||
@ -4792,7 +4847,10 @@ Response:
|
|||||||
"MsgRct": {
|
"MsgRct": {
|
||||||
"ExitCode": 0,
|
"ExitCode": 0,
|
||||||
"Return": "Ynl0ZSBhcnJheQ==",
|
"Return": "Ynl0ZSBhcnJheQ==",
|
||||||
"GasUsed": 9
|
"GasUsed": 9,
|
||||||
|
"EventsRoot": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"GasCost": {
|
"GasCost": {
|
||||||
"Message": {
|
"Message": {
|
||||||
@ -4825,7 +4883,10 @@ Response:
|
|||||||
"MsgRct": {
|
"MsgRct": {
|
||||||
"ExitCode": 0,
|
"ExitCode": 0,
|
||||||
"Return": "Ynl0ZSBhcnJheQ==",
|
"Return": "Ynl0ZSBhcnJheQ==",
|
||||||
"GasUsed": 9
|
"GasUsed": 9,
|
||||||
|
"EventsRoot": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"Error": "string value",
|
"Error": "string value",
|
||||||
"Duration": 60000000000,
|
"Duration": 60000000000,
|
||||||
@ -4869,7 +4930,10 @@ Response:
|
|||||||
"MsgRct": {
|
"MsgRct": {
|
||||||
"ExitCode": 0,
|
"ExitCode": 0,
|
||||||
"Return": "Ynl0ZSBhcnJheQ==",
|
"Return": "Ynl0ZSBhcnJheQ==",
|
||||||
"GasUsed": 9
|
"GasUsed": 9,
|
||||||
|
"EventsRoot": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"Error": "string value",
|
"Error": "string value",
|
||||||
"Duration": 60000000000,
|
"Duration": 60000000000,
|
||||||
@ -5059,7 +5123,10 @@ Response:
|
|||||||
"MsgRct": {
|
"MsgRct": {
|
||||||
"ExitCode": 0,
|
"ExitCode": 0,
|
||||||
"Return": "Ynl0ZSBhcnJheQ==",
|
"Return": "Ynl0ZSBhcnJheQ==",
|
||||||
"GasUsed": 9
|
"GasUsed": 9,
|
||||||
|
"EventsRoot": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"GasCost": {
|
"GasCost": {
|
||||||
"Message": {
|
"Message": {
|
||||||
@ -5092,7 +5159,10 @@ Response:
|
|||||||
"MsgRct": {
|
"MsgRct": {
|
||||||
"ExitCode": 0,
|
"ExitCode": 0,
|
||||||
"Return": "Ynl0ZSBhcnJheQ==",
|
"Return": "Ynl0ZSBhcnJheQ==",
|
||||||
"GasUsed": 9
|
"GasUsed": 9,
|
||||||
|
"EventsRoot": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"Error": "string value",
|
"Error": "string value",
|
||||||
"Duration": 60000000000,
|
"Duration": 60000000000,
|
||||||
@ -5136,7 +5206,10 @@ Response:
|
|||||||
"MsgRct": {
|
"MsgRct": {
|
||||||
"ExitCode": 0,
|
"ExitCode": 0,
|
||||||
"Return": "Ynl0ZSBhcnJheQ==",
|
"Return": "Ynl0ZSBhcnJheQ==",
|
||||||
"GasUsed": 9
|
"GasUsed": 9,
|
||||||
|
"EventsRoot": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"Error": "string value",
|
"Error": "string value",
|
||||||
"Duration": 60000000000,
|
"Duration": 60000000000,
|
||||||
@ -5460,7 +5533,8 @@ Response:
|
|||||||
"UpgradeChocolateHeight": 10101,
|
"UpgradeChocolateHeight": 10101,
|
||||||
"UpgradeOhSnapHeight": 10101,
|
"UpgradeOhSnapHeight": 10101,
|
||||||
"UpgradeSkyrHeight": 10101,
|
"UpgradeSkyrHeight": 10101,
|
||||||
"UpgradeSharkHeight": 10101
|
"UpgradeSharkHeight": 10101,
|
||||||
|
"UpgradeHyggeHeight": 10101
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -5551,7 +5625,10 @@ Response:
|
|||||||
{
|
{
|
||||||
"ExitCode": 0,
|
"ExitCode": 0,
|
||||||
"Return": "Ynl0ZSBhcnJheQ==",
|
"Return": "Ynl0ZSBhcnJheQ==",
|
||||||
"GasUsed": 9
|
"GasUsed": 9,
|
||||||
|
"EventsRoot": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -5864,7 +5941,9 @@ Response:
|
|||||||
"ExpectedStoragePledge": "0",
|
"ExpectedStoragePledge": "0",
|
||||||
"ReplacedSectorAge": 10101,
|
"ReplacedSectorAge": 10101,
|
||||||
"ReplacedDayReward": "0",
|
"ReplacedDayReward": "0",
|
||||||
"SectorKeyCID": null,
|
"SectorKeyCID": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"SimpleQAPower": true
|
"SimpleQAPower": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -6032,7 +6111,9 @@ Inputs:
|
|||||||
5432
|
5432
|
||||||
],
|
],
|
||||||
"Expiration": 10101,
|
"Expiration": 10101,
|
||||||
"UnsealedCid": null
|
"UnsealedCid": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -6154,7 +6235,9 @@ Inputs:
|
|||||||
5432
|
5432
|
||||||
],
|
],
|
||||||
"Expiration": 10101,
|
"Expiration": 10101,
|
||||||
"UnsealedCid": null
|
"UnsealedCid": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -6337,7 +6420,9 @@ Response:
|
|||||||
"ExpectedStoragePledge": "0",
|
"ExpectedStoragePledge": "0",
|
||||||
"ReplacedSectorAge": 10101,
|
"ReplacedSectorAge": 10101,
|
||||||
"ReplacedDayReward": "0",
|
"ReplacedDayReward": "0",
|
||||||
"SectorKeyCID": null,
|
"SectorKeyCID": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"SimpleQAPower": true
|
"SimpleQAPower": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -6470,7 +6555,10 @@ Response:
|
|||||||
"MsgRct": {
|
"MsgRct": {
|
||||||
"ExitCode": 0,
|
"ExitCode": 0,
|
||||||
"Return": "Ynl0ZSBhcnJheQ==",
|
"Return": "Ynl0ZSBhcnJheQ==",
|
||||||
"GasUsed": 9
|
"GasUsed": 9,
|
||||||
|
"EventsRoot": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"GasCost": {
|
"GasCost": {
|
||||||
"Message": {
|
"Message": {
|
||||||
@ -6503,7 +6591,10 @@ Response:
|
|||||||
"MsgRct": {
|
"MsgRct": {
|
||||||
"ExitCode": 0,
|
"ExitCode": 0,
|
||||||
"Return": "Ynl0ZSBhcnJheQ==",
|
"Return": "Ynl0ZSBhcnJheQ==",
|
||||||
"GasUsed": 9
|
"GasUsed": 9,
|
||||||
|
"EventsRoot": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"Error": "string value",
|
"Error": "string value",
|
||||||
"Duration": 60000000000,
|
"Duration": 60000000000,
|
||||||
@ -6547,7 +6638,10 @@ Response:
|
|||||||
"MsgRct": {
|
"MsgRct": {
|
||||||
"ExitCode": 0,
|
"ExitCode": 0,
|
||||||
"Return": "Ynl0ZSBhcnJheQ==",
|
"Return": "Ynl0ZSBhcnJheQ==",
|
||||||
"GasUsed": 9
|
"GasUsed": 9,
|
||||||
|
"EventsRoot": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"Error": "string value",
|
"Error": "string value",
|
||||||
"Duration": 60000000000,
|
"Duration": 60000000000,
|
||||||
@ -6618,7 +6712,10 @@ Response:
|
|||||||
"Receipt": {
|
"Receipt": {
|
||||||
"ExitCode": 0,
|
"ExitCode": 0,
|
||||||
"Return": "Ynl0ZSBhcnJheQ==",
|
"Return": "Ynl0ZSBhcnJheQ==",
|
||||||
"GasUsed": 9
|
"GasUsed": 9,
|
||||||
|
"EventsRoot": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"ReturnDec": {},
|
"ReturnDec": {},
|
||||||
"TipSet": [
|
"TipSet": [
|
||||||
@ -6672,7 +6769,10 @@ Response:
|
|||||||
"Receipt": {
|
"Receipt": {
|
||||||
"ExitCode": 0,
|
"ExitCode": 0,
|
||||||
"Return": "Ynl0ZSBhcnJheQ==",
|
"Return": "Ynl0ZSBhcnJheQ==",
|
||||||
"GasUsed": 9
|
"GasUsed": 9,
|
||||||
|
"EventsRoot": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"ReturnDec": {},
|
"ReturnDec": {},
|
||||||
"TipSet": [
|
"TipSet": [
|
||||||
@ -6761,7 +6861,9 @@ Response:
|
|||||||
"ExpectedStoragePledge": "0",
|
"ExpectedStoragePledge": "0",
|
||||||
"ReplacedSectorAge": 10101,
|
"ReplacedSectorAge": 10101,
|
||||||
"ReplacedDayReward": "0",
|
"ReplacedDayReward": "0",
|
||||||
"SectorKeyCID": null,
|
"SectorKeyCID": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
},
|
||||||
"SimpleQAPower": true
|
"SimpleQAPower": true
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -6832,7 +6934,9 @@ Response:
|
|||||||
5432
|
5432
|
||||||
],
|
],
|
||||||
"Expiration": 10101,
|
"Expiration": 10101,
|
||||||
"UnsealedCid": null
|
"UnsealedCid": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"PreCommitDeposit": "0",
|
"PreCommitDeposit": "0",
|
||||||
"PreCommitEpoch": 10101
|
"PreCommitEpoch": 10101
|
||||||
@ -6984,7 +7088,10 @@ Response:
|
|||||||
"Receipt": {
|
"Receipt": {
|
||||||
"ExitCode": 0,
|
"ExitCode": 0,
|
||||||
"Return": "Ynl0ZSBhcnJheQ==",
|
"Return": "Ynl0ZSBhcnJheQ==",
|
||||||
"GasUsed": 9
|
"GasUsed": 9,
|
||||||
|
"EventsRoot": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"ReturnDec": {},
|
"ReturnDec": {},
|
||||||
"TipSet": [
|
"TipSet": [
|
||||||
@ -7041,7 +7148,10 @@ Response:
|
|||||||
"Receipt": {
|
"Receipt": {
|
||||||
"ExitCode": 0,
|
"ExitCode": 0,
|
||||||
"Return": "Ynl0ZSBhcnJheQ==",
|
"Return": "Ynl0ZSBhcnJheQ==",
|
||||||
"GasUsed": 9
|
"GasUsed": 9,
|
||||||
|
"EventsRoot": {
|
||||||
|
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"ReturnDec": {},
|
"ReturnDec": {},
|
||||||
"TipSet": [
|
"TipSet": [
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -31,6 +31,7 @@ COMMANDS:
|
|||||||
log Manage logging
|
log Manage logging
|
||||||
wait-api Wait for lotus api to come online
|
wait-api Wait for lotus api to come online
|
||||||
fetch-params Fetch proving parameters
|
fetch-params Fetch proving parameters
|
||||||
|
evm Commands related to the Filecoin EVM runtime
|
||||||
NETWORK:
|
NETWORK:
|
||||||
net Manage P2P Network
|
net Manage P2P Network
|
||||||
sync Inspect or interact with the chain syncer
|
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
|
## lotus net
|
||||||
```
|
```
|
||||||
NAME:
|
NAME:
|
||||||
|
@ -293,3 +293,53 @@
|
|||||||
#Tracing = false
|
#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 = ""
|
||||||
|
|
||||||
|
|
||||||
|
2
extern/filecoin-ffi
vendored
2
extern/filecoin-ffi
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 02ebb2d6169131cfe489e1063e896f14982c463d
|
Subproject commit c4adeb4532719acf7b1c182cb98a3cca7b955a14
|
@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/lib/sigs"
|
"github.com/filecoin-project/lotus/lib/sigs"
|
||||||
_ "github.com/filecoin-project/lotus/lib/sigs/bls"
|
_ "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/lib/sigs/secp"
|
||||||
"github.com/filecoin-project/lotus/metrics"
|
"github.com/filecoin-project/lotus/metrics"
|
||||||
"github.com/filecoin-project/lotus/node/impl/full"
|
"github.com/filecoin-project/lotus/node/impl/full"
|
||||||
|
@ -29,12 +29,14 @@ func main() {
|
|||||||
types.MsgMeta{},
|
types.MsgMeta{},
|
||||||
types.ActorV4{},
|
types.ActorV4{},
|
||||||
types.ActorV5{},
|
types.ActorV5{},
|
||||||
types.MessageReceipt{},
|
// types.MessageReceipt{}, // Custom serde to deal with versioning.
|
||||||
types.BlockMsg{},
|
types.BlockMsg{},
|
||||||
types.ExpTipSet{},
|
types.ExpTipSet{},
|
||||||
types.BeaconEntry{},
|
types.BeaconEntry{},
|
||||||
types.StateRoot{},
|
types.StateRoot{},
|
||||||
types.StateInfo0{},
|
types.StateInfo0{},
|
||||||
|
types.Event{},
|
||||||
|
types.EventEntry{},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
|
11
go.mod
11
go.mod
@ -31,6 +31,7 @@ require (
|
|||||||
github.com/filecoin-project/dagstore v0.5.2
|
github.com/filecoin-project/dagstore v0.5.2
|
||||||
github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200910194244-f640612a1a1f
|
github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200910194244-f640612a1a1f
|
||||||
github.com/filecoin-project/go-address v1.1.0
|
github.com/filecoin-project/go-address v1.1.0
|
||||||
|
github.com/filecoin-project/go-amt-ipld/v4 v4.0.0
|
||||||
github.com/filecoin-project/go-bitfield v0.2.4
|
github.com/filecoin-project/go-bitfield v0.2.4
|
||||||
github.com/filecoin-project/go-cbor-util v0.0.1
|
github.com/filecoin-project/go-cbor-util v0.0.1
|
||||||
github.com/filecoin-project/go-commp-utils v0.1.3
|
github.com/filecoin-project/go-commp-utils v0.1.3
|
||||||
@ -39,11 +40,11 @@ require (
|
|||||||
github.com/filecoin-project/go-fil-commcid v0.1.0
|
github.com/filecoin-project/go-fil-commcid v0.1.0
|
||||||
github.com/filecoin-project/go-fil-commp-hashhash v0.1.0
|
github.com/filecoin-project/go-fil-commp-hashhash v0.1.0
|
||||||
github.com/filecoin-project/go-fil-markets v1.25.2
|
github.com/filecoin-project/go-fil-markets v1.25.2
|
||||||
github.com/filecoin-project/go-jsonrpc v0.1.8
|
github.com/filecoin-project/go-jsonrpc v0.1.9
|
||||||
github.com/filecoin-project/go-legs v0.4.4
|
github.com/filecoin-project/go-legs v0.4.4
|
||||||
github.com/filecoin-project/go-padreader v0.0.1
|
github.com/filecoin-project/go-padreader v0.0.1
|
||||||
github.com/filecoin-project/go-paramfetch v0.0.4
|
github.com/filecoin-project/go-paramfetch v0.0.4
|
||||||
github.com/filecoin-project/go-state-types v0.10.0-alpha-5
|
github.com/filecoin-project/go-state-types v0.10.0-alpha-9
|
||||||
github.com/filecoin-project/go-statemachine v1.0.2
|
github.com/filecoin-project/go-statemachine v1.0.2
|
||||||
github.com/filecoin-project/go-statestore v0.2.0
|
github.com/filecoin-project/go-statestore v0.2.0
|
||||||
github.com/filecoin-project/go-storedcounter v0.1.0
|
github.com/filecoin-project/go-storedcounter v0.1.0
|
||||||
@ -123,6 +124,7 @@ require (
|
|||||||
github.com/libp2p/go-maddr-filter v0.1.0
|
github.com/libp2p/go-maddr-filter v0.1.0
|
||||||
github.com/libp2p/go-msgio v0.2.0
|
github.com/libp2p/go-msgio v0.2.0
|
||||||
github.com/mattn/go-isatty v0.0.16
|
github.com/mattn/go-isatty v0.0.16
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.16
|
||||||
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1
|
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/multiformats/go-base32 v0.1.0
|
github.com/multiformats/go-base32 v0.1.0
|
||||||
@ -140,7 +142,7 @@ require (
|
|||||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
|
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
|
||||||
github.com/urfave/cli/v2 v2.16.3
|
github.com/urfave/cli/v2 v2.16.3
|
||||||
github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba
|
github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba
|
||||||
github.com/whyrusleeping/cbor-gen v0.0.0-20220514204315-f29c37e9c44c
|
github.com/whyrusleeping/cbor-gen v0.0.0-20221021053955-c138aae13722
|
||||||
github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4
|
github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4
|
||||||
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7
|
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7
|
||||||
github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542
|
github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542
|
||||||
@ -152,6 +154,7 @@ require (
|
|||||||
go.uber.org/fx v1.15.0
|
go.uber.org/fx v1.15.0
|
||||||
go.uber.org/multierr v1.8.0
|
go.uber.org/multierr v1.8.0
|
||||||
go.uber.org/zap v1.23.0
|
go.uber.org/zap v1.23.0
|
||||||
|
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90
|
||||||
golang.org/x/exp v0.0.0-20220916125017-b168a2c6b86b
|
golang.org/x/exp v0.0.0-20220916125017-b168a2c6b86b
|
||||||
golang.org/x/net v0.0.0-20220920183852-bf014ff85ad5
|
golang.org/x/net v0.0.0-20220920183852-bf014ff85ad5
|
||||||
golang.org/x/sync v0.0.0-20220907140024-f12130a52804
|
golang.org/x/sync v0.0.0-20220907140024-f12130a52804
|
||||||
@ -193,7 +196,6 @@ require (
|
|||||||
github.com/etclabscore/go-jsonschema-walk v0.0.6 // indirect
|
github.com/etclabscore/go-jsonschema-walk v0.0.6 // indirect
|
||||||
github.com/filecoin-project/go-amt-ipld/v2 v2.1.0 // indirect
|
github.com/filecoin-project/go-amt-ipld/v2 v2.1.0 // indirect
|
||||||
github.com/filecoin-project/go-amt-ipld/v3 v3.1.0 // indirect
|
github.com/filecoin-project/go-amt-ipld/v3 v3.1.0 // indirect
|
||||||
github.com/filecoin-project/go-amt-ipld/v4 v4.0.0 // indirect
|
|
||||||
github.com/filecoin-project/go-commp-utils/nonffi v0.0.0-20220905160352-62059082a837 // indirect
|
github.com/filecoin-project/go-commp-utils/nonffi v0.0.0-20220905160352-62059082a837 // indirect
|
||||||
github.com/filecoin-project/go-ds-versioning v0.1.2 // indirect
|
github.com/filecoin-project/go-ds-versioning v0.1.2 // indirect
|
||||||
github.com/filecoin-project/go-hamt-ipld v0.1.5 // indirect
|
github.com/filecoin-project/go-hamt-ipld v0.1.5 // indirect
|
||||||
@ -331,7 +333,6 @@ require (
|
|||||||
go.uber.org/atomic v1.10.0 // indirect
|
go.uber.org/atomic v1.10.0 // indirect
|
||||||
go.uber.org/dig v1.12.0 // indirect
|
go.uber.org/dig v1.12.0 // indirect
|
||||||
go4.org v0.0.0-20200411211856-f5505b9728dd // indirect
|
go4.org v0.0.0-20200411211856-f5505b9728dd // indirect
|
||||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 // indirect
|
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user