Merge branch 'release/v1.20.0' into asr/merge-release-into-master
This commit is contained in:
commit
693f230fbb
@ -656,6 +656,12 @@ workflows:
|
||||
- build
|
||||
suite: itest-deals
|
||||
target: "./itests/deals_test.go"
|
||||
- test:
|
||||
name: test-itest-decode_params
|
||||
requires:
|
||||
- build
|
||||
suite: itest-decode_params
|
||||
target: "./itests/decode_params_test.go"
|
||||
- test:
|
||||
name: test-itest-dup_mpool_messages
|
||||
requires:
|
||||
@ -686,6 +692,12 @@ workflows:
|
||||
- build
|
||||
suite: itest-eth_config
|
||||
target: "./itests/eth_config_test.go"
|
||||
- test:
|
||||
name: test-itest-eth_conformance
|
||||
requires:
|
||||
- build
|
||||
suite: itest-eth_conformance
|
||||
target: "./itests/eth_conformance_test.go"
|
||||
- test:
|
||||
name: test-itest-eth_deploy
|
||||
requires:
|
||||
|
@ -853,7 +853,7 @@ type FullNode interface {
|
||||
// reverse interface to the client, called after EthSubscribe
|
||||
type EthSubscriber interface {
|
||||
// note: the parameter is ethtypes.EthSubscriptionResponse serialized as json object
|
||||
EthSubscription(ctx context.Context, r jsonrpc.RawParams) error //rpc_method:eth_subscription notify:true
|
||||
EthSubscription(ctx context.Context, r jsonrpc.RawParams) error // rpc_method:eth_subscription notify:true
|
||||
}
|
||||
|
||||
type StorageAsk struct {
|
||||
|
Binary file not shown.
Binary file not shown.
@ -22,6 +22,7 @@ import (
|
||||
builtintypes "github.com/filecoin-project/go-state-types/builtin"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/lib/must"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -144,7 +145,7 @@ type EthBlock struct {
|
||||
GasLimit EthUint64 `json:"gasLimit"`
|
||||
GasUsed EthUint64 `json:"gasUsed"`
|
||||
Timestamp EthUint64 `json:"timestamp"`
|
||||
Extradata []byte `json:"extraData"`
|
||||
Extradata EthBytes `json:"extraData"`
|
||||
MixHash EthHash `json:"mixHash"`
|
||||
Nonce EthNonce `json:"nonce"`
|
||||
BaseFeePerGas EthBigInt `json:"baseFeePerGas"`
|
||||
@ -155,17 +156,19 @@ type EthBlock struct {
|
||||
}
|
||||
|
||||
var (
|
||||
EmptyEthBloom = [256]byte{}
|
||||
EmptyEthHash = EthHash{}
|
||||
EmptyEthInt = EthUint64(0)
|
||||
EmptyEthNonce = [8]byte{0, 0, 0, 0, 0, 0, 0, 0}
|
||||
EmptyEthBloom = [256]byte{}
|
||||
EmptyEthHash = EthHash{}
|
||||
EmptyUncleHash = must.One(ParseEthHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")) // Keccak-256 of an RLP of an empty array
|
||||
EmptyRootHash = must.One(ParseEthHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")) // Keccak-256 hash of the RLP of null
|
||||
EmptyEthInt = EthUint64(0)
|
||||
EmptyEthNonce = [8]byte{0, 0, 0, 0, 0, 0, 0, 0}
|
||||
)
|
||||
|
||||
func NewEthBlock() EthBlock {
|
||||
return EthBlock{
|
||||
Sha3Uncles: EmptyEthHash,
|
||||
func NewEthBlock(hasTransactions bool) EthBlock {
|
||||
b := EthBlock{
|
||||
Sha3Uncles: EmptyUncleHash, // Sha3Uncles set to a hardcoded value which is used by some clients to determine if has no uncles.
|
||||
StateRoot: EmptyEthHash,
|
||||
TransactionsRoot: EmptyEthHash,
|
||||
TransactionsRoot: EmptyRootHash, // TransactionsRoot set to a hardcoded value which is used by some clients to determine if has no transactions.
|
||||
ReceiptsRoot: EmptyEthHash,
|
||||
Difficulty: EmptyEthInt,
|
||||
LogsBloom: EmptyEthBloom[:],
|
||||
@ -176,6 +179,11 @@ func NewEthBlock() EthBlock {
|
||||
Uncles: []EthHash{},
|
||||
Transactions: []interface{}{},
|
||||
}
|
||||
if hasTransactions {
|
||||
b.TransactionsRoot = EmptyEthHash
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
type EthCall struct {
|
||||
@ -433,7 +441,7 @@ func EthHashFromTxBytes(b []byte) EthHash {
|
||||
}
|
||||
|
||||
type EthFeeHistory struct {
|
||||
OldestBlock uint64 `json:"oldestBlock"`
|
||||
OldestBlock EthUint64 `json:"oldestBlock"`
|
||||
BaseFeePerGas []EthBigInt `json:"baseFeePerGas"`
|
||||
GasUsedRatio []float64 `json:"gasUsedRatio"`
|
||||
Reward *[][]EthBigInt `json:"reward,omitempty"`
|
||||
|
@ -1360,7 +1360,7 @@ func ComputeStateHTMLTempl(w io.Writer, ts *types.TipSet, o *api.ComputeStateOut
|
||||
"GetMethod": getMethod,
|
||||
"ToFil": toFil,
|
||||
"JsonParams": JsonParams,
|
||||
"JsonReturn": jsonReturn,
|
||||
"JsonReturn": JsonReturn,
|
||||
"IsSlow": isSlow,
|
||||
"IsVerySlow": isVerySlow,
|
||||
"IntExit": func(i exitcode.ExitCode) int64 { return int64(i) },
|
||||
@ -1446,7 +1446,7 @@ func JsonParams(code cid.Cid, method abi.MethodNum, params []byte) (string, erro
|
||||
return string(b), err
|
||||
}
|
||||
|
||||
func jsonReturn(code cid.Cid, method abi.MethodNum, ret []byte) (string, error) {
|
||||
func JsonReturn(code cid.Cid, method abi.MethodNum, ret []byte) (string, error) {
|
||||
methodMeta, found := consensus.NewActorRegistry().Methods[code][method] // TODO: use remote
|
||||
if !found {
|
||||
return "", fmt.Errorf("method %d not found on actor %s", method, code)
|
||||
@ -1555,7 +1555,7 @@ func printReceiptReturn(ctx context.Context, api v0api.FullNode, m *types.Messag
|
||||
return err
|
||||
}
|
||||
|
||||
jret, err := jsonReturn(act.Code, m.Method, r.Return)
|
||||
jret, err := JsonReturn(act.Code, m.Method, r.Return)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -1695,7 +1695,7 @@ var StateCallCmd = &cli.Command{
|
||||
return xerrors.Errorf("getting actor: %w", err)
|
||||
}
|
||||
|
||||
retStr, err := jsonReturn(act.Code, abi.MethodNum(method), ret.MsgRct.Return)
|
||||
retStr, err := JsonReturn(act.Code, abi.MethodNum(method), ret.MsgRct.Return)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("decoding return: %w", err)
|
||||
}
|
||||
|
@ -2342,7 +2342,7 @@ Inputs:
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"oldestBlock": 42,
|
||||
"oldestBlock": "0x5",
|
||||
"baseFeePerGas": [
|
||||
"0x0"
|
||||
],
|
||||
@ -2407,7 +2407,7 @@ Response:
|
||||
"gasLimit": "0x5",
|
||||
"gasUsed": "0x5",
|
||||
"timestamp": "0x5",
|
||||
"extraData": "Ynl0ZSBhcnJheQ==",
|
||||
"extraData": "0x07",
|
||||
"mixHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e",
|
||||
"nonce": "0x0707070707070707",
|
||||
"baseFeePerGas": "0x0",
|
||||
@ -2451,7 +2451,7 @@ Response:
|
||||
"gasLimit": "0x5",
|
||||
"gasUsed": "0x5",
|
||||
"timestamp": "0x5",
|
||||
"extraData": "Ynl0ZSBhcnJheQ==",
|
||||
"extraData": "0x07",
|
||||
"mixHash": "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e",
|
||||
"nonce": "0x0707070707070707",
|
||||
"baseFeePerGas": "0x0",
|
||||
|
6
go.mod
6
go.mod
@ -61,10 +61,12 @@ require (
|
||||
github.com/gbrlsnchs/jwt/v3 v3.0.1
|
||||
github.com/gdamore/tcell/v2 v2.2.0
|
||||
github.com/go-kit/kit v0.12.0
|
||||
github.com/go-openapi/spec v0.19.11
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
github.com/gregdhill/go-openrpc v0.0.0-20220114144539-ae6f44720487
|
||||
github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026
|
||||
github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
@ -144,6 +146,7 @@ require (
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20221021053955-c138aae13722
|
||||
github.com/whyrusleeping/ledger-filecoin-go v0.9.1-0.20201010031517-c3dcc1bddce4
|
||||
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7
|
||||
github.com/xeipuuv/gojsonschema v1.2.0
|
||||
github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542
|
||||
go.opencensus.io v0.23.0
|
||||
go.opentelemetry.io/otel v1.11.1
|
||||
@ -211,7 +214,6 @@ require (
|
||||
github.com/go-ole/go-ole v1.2.5 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.3 // indirect
|
||||
github.com/go-openapi/jsonreference v0.19.4 // indirect
|
||||
github.com/go-openapi/spec v0.19.11 // indirect
|
||||
github.com/go-openapi/swag v0.19.11 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||
@ -324,6 +326,8 @@ require (
|
||||
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect
|
||||
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect
|
||||
github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
github.com/zondax/hid v0.9.1 // indirect
|
||||
github.com/zondax/ledger-go v0.12.1 // indirect
|
||||
|
26
go.sum
26
go.sum
@ -447,6 +447,7 @@ github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwoh
|
||||
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
|
||||
github.com/go-openapi/jsonreference v0.19.4 h1:3Vw+rh13uq2JFNxgnMTGE1rnoieU9FmyE1gvnyylsYg=
|
||||
github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
|
||||
github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=
|
||||
github.com/go-openapi/spec v0.19.7/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk=
|
||||
github.com/go-openapi/spec v0.19.11 h1:ogU5q8dtp3MMPn59a9VRrPKVxvJHEs5P7yNMR5sNnis=
|
||||
github.com/go-openapi/spec v0.19.11/go.mod h1:vqK/dIdLGCosfvYsQV3WfC7N3TiZSnGY2RZKoFK7X28=
|
||||
@ -460,6 +461,10 @@ github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
|
||||
github.com/gobuffalo/logger v1.0.0/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs=
|
||||
github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q=
|
||||
github.com/gobuffalo/packr/v2 v2.6.0/go.mod h1:sgEE1xNZ6G0FNN5xn9pevVu4nywaxHvgup67xisti08=
|
||||
github.com/godbus/dbus v0.0.0-20190402143921-271e53dc4968/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
@ -582,6 +587,8 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gregdhill/go-openrpc v0.0.0-20220114144539-ae6f44720487 h1:NyaWOSkqFK1d9o+HLfnMIGzrHuUUPeBNIZyi5Zoe/lY=
|
||||
github.com/gregdhill/go-openrpc v0.0.0-20220114144539-ae6f44720487/go.mod h1:a1eRkbhd3DYpRH2lnuUsVG+QMTI+v0hGnsis8C9hMrA=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE=
|
||||
@ -661,6 +668,7 @@ github.com/icza/backscanner v0.0.0-20210726202459-ac2ffc679f94 h1:9tcYMdi+7Rb1y0
|
||||
github.com/icza/backscanner v0.0.0-20210726202459-ac2ffc679f94/go.mod h1:GYeBD1CF7AqnKZK+UCytLcY3G+UKo0ByXX/3xfdNyqQ=
|
||||
github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6 h1:8UsGZ2rr2ksmEru6lToqnXgA8Mz1DP11X4zSJ159C3k=
|
||||
github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6/go.mod h1:xQig96I1VNBDIWGCdTt54nHt6EeI639SmHycLYL7FkA=
|
||||
github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab h1:HqW4xhhynfjrtEiiSGcQUd6vrK23iMam1FO8rI7mwig=
|
||||
@ -926,6 +934,7 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht
|
||||
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
|
||||
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8l6qbCUTSiRLG/iKnW3K3/QfPPuSsBt4=
|
||||
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901/go.mod h1:Z86h9688Y0wesXCyonoVr47MasHilkuLMqGhRZ4Hpak=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jonboulle/clockwork v0.1.1-0.20190114141812-62fb9bc030d1/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ=
|
||||
@ -954,6 +963,7 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kabukky/httpscerts v0.0.0-20150320125433-617593d7dcb3/go.mod h1:BYpt4ufZiIGv2nXn4gMxnfKV306n3mWXgNu/d2TqdTU=
|
||||
github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0=
|
||||
github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
|
||||
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
|
||||
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
|
||||
github.com/kilic/bls12-381 v0.0.0-20200607163746-32e1441c8a9f/go.mod h1:XXfR6YFCRSrkEXbNlIyDsgXVNJWVUV30m/ebkVy9n6s=
|
||||
@ -979,6 +989,7 @@ github.com/klauspost/cpuid/v2 v2.1.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8t
|
||||
github.com/koalacxr/quantile v0.0.1 h1:wAW+SQ286Erny9wOjVww96t8ws+x5Zj6AKHDULUK+o0=
|
||||
github.com/koalacxr/quantile v0.0.1/go.mod h1:bGN/mCZLZ4lrSDHRQ6Lglj9chowGux8sGUIND+DQeD0=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk=
|
||||
github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk=
|
||||
@ -993,6 +1004,7 @@ github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
@ -1696,6 +1708,7 @@ github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
|
||||
@ -1782,6 +1795,7 @@ github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3
|
||||
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
@ -1800,6 +1814,8 @@ github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpP
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||
github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE=
|
||||
github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU=
|
||||
github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g=
|
||||
github.com/tidwall/gjson v1.6.0 h1:9VEQWz6LLMUsUl6PueE49ir4Ka6CzLymOAZDxpFsTDc=
|
||||
github.com/tidwall/gjson v1.6.0/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls=
|
||||
@ -1885,6 +1901,12 @@ github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.
|
||||
github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow=
|
||||
github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1:m2aV4LZI4Aez7dP5PMyVKEHhUyEJ/RjmPEDOpDvudHg=
|
||||
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xorcare/golden v0.6.0/go.mod h1:7T39/ZMvaSEZlBPoYfVFmsBLmUl3uz9IuzWj/U6FtvQ=
|
||||
github.com/xorcare/golden v0.6.1-0.20191112154924-b87f686d7542 h1:oWgZJmC1DorFZDpfMfWg7xk29yEOZiXmo/wZl+utTI8=
|
||||
@ -2009,6 +2031,7 @@ golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
@ -2196,12 +2219,14 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190524122548-abf6ff778158/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190524152521-dbbf3f1254d4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -2313,6 +2338,7 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
|
@ -1 +1 @@
|
||||
608060405234801561001057600080fd5b506105eb806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c8063c755553811610071578063c755553814610198578063cbfc3b58146101c6578063cc6f8faf14610212578063cd5b6c3d14610254578063e2a614731461028c578063fb62b28b146102d8576100a9565b80630919b8be146100ae5780636199074d146100e657806366eef3461461012857806375091b1f14610132578063a63ae81a1461016a575b600080fd5b6100e4600480360360408110156100c457600080fd5b81019080803590602001909291908035906020019092919050505061031a565b005b610126600480360360608110156100fc57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919050505061035d565b005b610130610391565b005b6101686004803603604081101561014857600080fd5b8101908080359060200190929190803590602001909291905050506103bf565b005b6101966004803603602081101561018057600080fd5b81019080803590602001909291905050506103fb565b005b6101c4600480360360208110156101ae57600080fd5b8101908080359060200190929190505050610435565b005b610210600480360360808110156101dc57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919080359060200190929190505050610465565b005b6102526004803603606081101561022857600080fd5b810190808035906020019092919080359060200190929190803590602001909291905050506104ba565b005b61028a6004803603604081101561026a57600080fd5b8101908080359060200190929190803590602001909291905050506104f8565b005b6102d6600480360360808110156102a257600080fd5b810190808035906020019092919080359060200190929190803590602001909291908035906020019092919050505061052a565b005b610318600480360360608110156102ee57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919050505061056a565b005b7f5469c6b769315f5668523937f05ca07d4cc87849432bc5f5907f1d90fa73b9f98282604051808381526020018281526020019250505060405180910390a15050565b8082847fb89dabcdb7ff41f1794c0da92f65ece6c19b6b0caeac5407b2a721efe27c080460405160405180910390a4505050565b7fc3f6f1c76bd4e74ee5782052b0b4f8bd5c50b86c3c5a2f52638e03066e50a91b60405160405180910390a1565b817f6709824ebe5f6e620ca3f4b02a3428e8ce2dc97c550816eaeeb3a342b214bd85826040518082815260200191505060405180910390a25050565b7fc804e53d6048af1b3e6a352e246d5f3864fea9d635ace499e023a58c383b3a88816040518082815260200191505060405180910390a150565b807f44a227a31429ab5eb00daf6611c6422f10571619f2267e0e149e9ebe6d2a5d0560405160405180910390a250565b7f28d45631a87b2a52a9625f8520fa37ff8c4d926cdf17042e241985da5cb7b850848484846040518085815260200184815260200183815260200182815260200194505050505060405180910390a150505050565b81837fcd5fe5fbc1d27b90036997224cea7aa565e3779622867265081f636b3a5ccb08836040518082815260200191505060405180910390a3505050565b80827f232f09cef3babc26e58d1cc1346c0a8bc626ffe600c9605b5d747783eda484a760405160405180910390a35050565b8183857f812e73dbcf7e267f27ecb1383bfc902a6650b41b6e7d03ac265108c369673d95846040518082815260200191505060405180910390a450505050565b7fd4d143faaf60340ad98e1f2c96fc26f5695834c21b5200edad339ee7e9a372cc83838360405180848152602001838152602001828152602001935050505060405180910390a150505056fea265627a7a72315820954561fde80ab925299e0a9f3356b01f64fb1976dd335ac2ebd9367441e29f0564736f6c63430005110032
|
||||
608060405234801561001057600080fd5b506106af806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c8063c755553811610071578063c755553814610128578063cbfc3b5814610144578063cc6f8faf14610160578063cd5b6c3d1461017c578063e2a6147314610198578063fb62b28b146101b4576100a9565b80630919b8be146100ae5780636199074d146100ca57806366eef346146100e657806375091b1f146100f0578063a63ae81a1461010c575b600080fd5b6100c860048036038101906100c39190610483565b6101d0565b005b6100e460048036038101906100df91906104c3565b61020d565b005b6100ee610241565b005b61010a60048036038101906101059190610483565b61026f565b005b61012660048036038101906101219190610516565b6102ab565b005b610142600480360381019061013d9190610516565b6102e5565b005b61015e60048036038101906101599190610543565b610315565b005b61017a600480360381019061017591906104c3565b610358565b005b61019660048036038101906101919190610483565b610396565b005b6101b260048036038101906101ad9190610543565b6103c8565b005b6101ce60048036038101906101c991906104c3565b610408565b005b7f5469c6b769315f5668523937f05ca07d4cc87849432bc5f5907f1d90fa73b9f982826040516102019291906105b9565b60405180910390a15050565b8082847fb89dabcdb7ff41f1794c0da92f65ece6c19b6b0caeac5407b2a721efe27c080460405160405180910390a4505050565b7fc3f6f1c76bd4e74ee5782052b0b4f8bd5c50b86c3c5a2f52638e03066e50a91b60405160405180910390a1565b817f6709824ebe5f6e620ca3f4b02a3428e8ce2dc97c550816eaeeb3a342b214bd858260405161029f91906105e2565b60405180910390a25050565b7fc804e53d6048af1b3e6a352e246d5f3864fea9d635ace499e023a58c383b3a88816040516102da91906105e2565b60405180910390a150565b807f44a227a31429ab5eb00daf6611c6422f10571619f2267e0e149e9ebe6d2a5d0560405160405180910390a250565b7f28d45631a87b2a52a9625f8520fa37ff8c4d926cdf17042e241985da5cb7b8508484848460405161034a94939291906105fd565b60405180910390a150505050565b81837fcd5fe5fbc1d27b90036997224cea7aa565e3779622867265081f636b3a5ccb088360405161038991906105e2565b60405180910390a3505050565b80827f232f09cef3babc26e58d1cc1346c0a8bc626ffe600c9605b5d747783eda484a760405160405180910390a35050565b8183857f812e73dbcf7e267f27ecb1383bfc902a6650b41b6e7d03ac265108c369673d95846040516103fa91906105e2565b60405180910390a450505050565b7fd4d143faaf60340ad98e1f2c96fc26f5695834c21b5200edad339ee7e9a372cc83838360405161043b93929190610642565b60405180910390a1505050565b600080fd5b6000819050919050565b6104608161044d565b811461046b57600080fd5b50565b60008135905061047d81610457565b92915050565b6000806040838503121561049a57610499610448565b5b60006104a88582860161046e565b92505060206104b98582860161046e565b9150509250929050565b6000806000606084860312156104dc576104db610448565b5b60006104ea8682870161046e565b93505060206104fb8682870161046e565b925050604061050c8682870161046e565b9150509250925092565b60006020828403121561052c5761052b610448565b5b600061053a8482850161046e565b91505092915050565b6000806000806080858703121561055d5761055c610448565b5b600061056b8782880161046e565b945050602061057c8782880161046e565b935050604061058d8782880161046e565b925050606061059e8782880161046e565b91505092959194509250565b6105b38161044d565b82525050565b60006040820190506105ce60008301856105aa565b6105db60208301846105aa565b9392505050565b60006020820190506105f760008301846105aa565b92915050565b600060808201905061061260008301876105aa565b61061f60208301866105aa565b61062c60408301856105aa565b61063960608301846105aa565b95945050505050565b600060608201905061065760008301866105aa565b61066460208301856105aa565b61067160408301846105aa565b94935050505056fea26469706673582212201b2f4de851da592b926eb2cd07ccfbbd02270fde6dee2459ba942e5dcf5685d364736f6c63430008110033
|
@ -1,4 +1,5 @@
|
||||
pragma solidity ^0.5.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.5.0;
|
||||
|
||||
contract EventMatrix {
|
||||
event EventZeroData();
|
||||
|
1
itests/contracts/ExternalRecursiveCallSimple.hex
Normal file
1
itests/contracts/ExternalRecursiveCallSimple.hex
Normal file
@ -0,0 +1 @@
|
||||
608060405234801561001057600080fd5b506101ee806100206000396000f3fe60806040526004361061001e5760003560e01c8063c38e07dd14610023575b600080fd5b61003d600480360381019061003891906100fe565b61003f565b005b60008111156100c0573073ffffffffffffffffffffffffffffffffffffffff1663c38e07dd600183610071919061015a565b6040518263ffffffff1660e01b815260040161008d919061019d565b600060405180830381600087803b1580156100a757600080fd5b505af11580156100bb573d6000803e3d6000fd5b505050505b50565b600080fd5b6000819050919050565b6100db816100c8565b81146100e657600080fd5b50565b6000813590506100f8816100d2565b92915050565b600060208284031215610114576101136100c3565b5b6000610122848285016100e9565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610165826100c8565b9150610170836100c8565b92508282039050818111156101885761018761012b565b5b92915050565b610197816100c8565b82525050565b60006020820190506101b2600083018461018e565b9291505056fea264697066735822122033d012e17f5d7a62bb724021b5c4e0d109aeb28d1cd5b5c0a0b1b801c0b5032164736f6c63430008110033
|
13
itests/contracts/ExternalRecursiveCallSimple.sol
Normal file
13
itests/contracts/ExternalRecursiveCallSimple.sol
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.17;
|
||||
|
||||
contract StackRecCallExp {
|
||||
function exec1(uint256 r) public payable {
|
||||
if(r > 0) {
|
||||
StackRecCallExp(address(this)).exec1(r-1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
124
itests/decode_params_test.go
Normal file
124
itests/decode_params_test.go
Normal file
@ -0,0 +1,124 @@
|
||||
// stm: #integration
|
||||
package itests
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
||||
"github.com/filecoin-project/go-state-types/builtin"
|
||||
"github.com/filecoin-project/go-state-types/builtin/v10/eam"
|
||||
"github.com/filecoin-project/go-state-types/cbor"
|
||||
"github.com/filecoin-project/go-state-types/manifest"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/cli"
|
||||
)
|
||||
|
||||
type marshalable interface {
|
||||
cbor.Marshaler
|
||||
cbor.Unmarshaler
|
||||
}
|
||||
|
||||
type testCase struct {
|
||||
ActorKey string
|
||||
MethodNum abi.MethodNum
|
||||
retVal marshalable
|
||||
}
|
||||
|
||||
// Used './lotus state replay --show-trace <msg-cid>' to get params/return to decode.
|
||||
func TestDecodeParams(t *testing.T) {
|
||||
testCborBytes := abi.CborBytes([]byte{1, 2, 3})
|
||||
|
||||
testCases := []testCase{
|
||||
{
|
||||
ActorKey: manifest.EvmKey,
|
||||
MethodNum: builtin.MethodsEVM.InvokeContract,
|
||||
retVal: &testCborBytes,
|
||||
},
|
||||
{
|
||||
ActorKey: manifest.EamKey,
|
||||
MethodNum: builtin.MethodsEAM.CreateExternal,
|
||||
retVal: &testCborBytes,
|
||||
},
|
||||
}
|
||||
|
||||
for _, _tc := range testCases {
|
||||
tc := _tc
|
||||
t.Run(tc.ActorKey+" "+tc.MethodNum.String(), func(t *testing.T) {
|
||||
av, err := actorstypes.VersionForNetwork(build.TestNetworkVersion)
|
||||
require.NoError(t, err)
|
||||
actorCodeCid, found := actors.GetActorCodeID(av, tc.ActorKey)
|
||||
require.True(t, found)
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
if err := tc.retVal.MarshalCBOR(buf); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
paramString, err := cli.JsonParams(actorCodeCid, tc.MethodNum, buf.Bytes())
|
||||
require.NoError(t, err)
|
||||
|
||||
jsonParams, err := json.MarshalIndent(tc.retVal, "", " ")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, string(jsonParams), paramString)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeReturn(t *testing.T) {
|
||||
testCborBytes := abi.CborBytes([]byte{1, 2, 3})
|
||||
|
||||
robustAddr, err := address.NewIDAddress(12345)
|
||||
require.NoError(t, err)
|
||||
|
||||
//ethAddr, err := ethtypes.ParseEthAddress("d4c5fb16488Aa48081296299d54b0c648C9333dA")
|
||||
//require.NoError(t, err)
|
||||
|
||||
testReturn := eam.CreateExternalReturn{
|
||||
ActorID: 12345,
|
||||
RobustAddress: &robustAddr,
|
||||
EthAddress: [20]byte{},
|
||||
}
|
||||
|
||||
testCases := []testCase{
|
||||
{
|
||||
ActorKey: manifest.EvmKey,
|
||||
MethodNum: builtin.MethodsEVM.InvokeContract,
|
||||
retVal: &testCborBytes,
|
||||
},
|
||||
{
|
||||
ActorKey: manifest.EamKey,
|
||||
MethodNum: builtin.MethodsEAM.CreateExternal,
|
||||
retVal: &testReturn,
|
||||
},
|
||||
}
|
||||
|
||||
for _, _tc := range testCases {
|
||||
tc := _tc
|
||||
t.Run(tc.ActorKey+" "+tc.MethodNum.String(), func(t *testing.T) {
|
||||
av, err := actorstypes.VersionForNetwork(build.TestNetworkVersion)
|
||||
require.NoError(t, err)
|
||||
actorCodeCid, found := actors.GetActorCodeID(av, tc.ActorKey)
|
||||
require.True(t, found)
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
if err := tc.retVal.MarshalCBOR(buf); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
returnString, err := cli.JsonReturn(actorCodeCid, tc.MethodNum, buf.Bytes())
|
||||
require.NoError(t, err)
|
||||
|
||||
jsonReturn, err := json.MarshalIndent(tc.retVal, "", " ")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, string(jsonReturn), returnString)
|
||||
})
|
||||
}
|
||||
}
|
520
itests/eth_conformance_test.go
Normal file
520
itests/eth_conformance_test.go
Normal file
@ -0,0 +1,520 @@
|
||||
package itests
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/gregdhill/go-openrpc/parse"
|
||||
orpctypes "github.com/gregdhill/go-openrpc/types"
|
||||
manet "github.com/multiformats/go-multiaddr/net"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/xeipuuv/gojsonschema"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-jsonrpc"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
"github.com/filecoin-project/lotus/chain/wallet/key"
|
||||
"github.com/filecoin-project/lotus/itests/kit"
|
||||
)
|
||||
|
||||
// TODO generate this using reflection. It's the same as the EthAPI except every return value is a json.RawMessage
|
||||
type ethAPIRaw struct {
|
||||
EthAccounts func(context.Context) (json.RawMessage, error)
|
||||
EthBlockNumber func(context.Context) (json.RawMessage, error)
|
||||
EthCall func(context.Context, ethtypes.EthCall, string) (json.RawMessage, error)
|
||||
EthChainId func(context.Context) (json.RawMessage, error)
|
||||
EthEstimateGas func(context.Context, ethtypes.EthCall) (json.RawMessage, error)
|
||||
EthFeeHistory func(context.Context, ethtypes.EthUint64, string, []float64) (json.RawMessage, error)
|
||||
EthGasPrice func(context.Context) (json.RawMessage, error)
|
||||
EthGetBalance func(context.Context, ethtypes.EthAddress, string) (json.RawMessage, error)
|
||||
EthGetBlockByHash func(context.Context, ethtypes.EthHash, bool) (json.RawMessage, error)
|
||||
EthGetBlockByNumber func(context.Context, string, bool) (json.RawMessage, error)
|
||||
EthGetBlockTransactionCountByHash func(context.Context, ethtypes.EthHash) (json.RawMessage, error)
|
||||
EthGetBlockTransactionCountByNumber func(context.Context, ethtypes.EthUint64) (json.RawMessage, error)
|
||||
EthGetCode func(context.Context, ethtypes.EthAddress, string) (json.RawMessage, error)
|
||||
EthGetFilterChanges func(context.Context, ethtypes.EthFilterID) (json.RawMessage, error)
|
||||
EthGetFilterLogs func(context.Context, ethtypes.EthFilterID) (json.RawMessage, error)
|
||||
EthGetLogs func(context.Context, *ethtypes.EthFilterSpec) (json.RawMessage, error)
|
||||
EthGetStorageAt func(context.Context, ethtypes.EthAddress, ethtypes.EthBytes, string) (json.RawMessage, error)
|
||||
EthGetTransactionByBlockHashAndIndex func(context.Context, ethtypes.EthHash, ethtypes.EthUint64) (json.RawMessage, error)
|
||||
EthGetTransactionByBlockNumberAndIndex func(context.Context, ethtypes.EthUint64, ethtypes.EthUint64) (json.RawMessage, error)
|
||||
EthGetTransactionByHash func(context.Context, *ethtypes.EthHash) (json.RawMessage, error)
|
||||
EthGetTransactionCount func(context.Context, ethtypes.EthAddress, string) (json.RawMessage, error)
|
||||
EthGetTransactionReceipt func(context.Context, ethtypes.EthHash) (json.RawMessage, error)
|
||||
EthMaxPriorityFeePerGas func(context.Context) (json.RawMessage, error)
|
||||
EthNewBlockFilter func(context.Context) (json.RawMessage, error)
|
||||
EthNewFilter func(context.Context, *ethtypes.EthFilterSpec) (json.RawMessage, error)
|
||||
EthNewPendingTransactionFilter func(context.Context) (json.RawMessage, error)
|
||||
EthSendRawTransaction func(context.Context, ethtypes.EthBytes) (json.RawMessage, error)
|
||||
EthSubscribe func(context.Context, string, *ethtypes.EthSubscriptionParams) (json.RawMessage, error)
|
||||
EthUninstallFilter func(context.Context, ethtypes.EthFilterID) (json.RawMessage, error)
|
||||
EthUnsubscribe func(context.Context, ethtypes.EthSubscriptionID) (json.RawMessage, error)
|
||||
}
|
||||
|
||||
func TestEthOpenRPCConformance(t *testing.T) {
|
||||
kit.QuietAllLogsExcept("events", "messagepool")
|
||||
|
||||
// specs/eth_openrpc.json is built from https://github.com/ethereum/execution-apis
|
||||
specJSON, err := os.ReadFile("specs/eth_openrpc.json")
|
||||
require.NoError(t, err)
|
||||
|
||||
specParsed := orpctypes.NewOpenRPCSpec1()
|
||||
err = json.Unmarshal(specJSON, specParsed)
|
||||
require.NoError(t, err)
|
||||
parse.GetTypes(specParsed, specParsed.Objects)
|
||||
|
||||
schemas := make(map[string]spec.Schema)
|
||||
for _, method := range specParsed.Methods {
|
||||
if method.Result != nil {
|
||||
schemas[method.Name] = method.Result.Schema
|
||||
}
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC(), kit.WithEthRPC())
|
||||
ens.InterconnectAll().BeginMining(10 * time.Millisecond)
|
||||
|
||||
contractHex, err := os.ReadFile("contracts/EventMatrix.hex")
|
||||
require.NoError(t, err)
|
||||
|
||||
// strip any trailing newlines from the file
|
||||
contractHex = bytes.TrimRight(contractHex, "\n")
|
||||
|
||||
contractBin, err := hex.DecodeString(string(contractHex))
|
||||
require.NoError(t, err)
|
||||
|
||||
senderKey, senderEthAddr, senderFilAddr := client.EVM().NewAccount()
|
||||
_, receiverEthAddr, _ := client.EVM().NewAccount()
|
||||
kit.SendFunds(ctx, t, client, senderFilAddr, types.FromFil(1000))
|
||||
|
||||
deployerAddr, err := client.EVM().WalletDefaultAddress(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
pendingTransactionFilterID, err := client.EthNewPendingTransactionFilter(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
blockFilterID, err := client.EthNewBlockFilter(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
filterAllLogs := kit.NewEthFilterBuilder().FromBlockEpoch(0).Filter()
|
||||
|
||||
logFilterID, err := client.EthNewFilter(ctx, filterAllLogs)
|
||||
require.NoError(t, err)
|
||||
|
||||
uninstallableFilterID, err := client.EthNewFilter(ctx, filterAllLogs)
|
||||
require.NoError(t, err)
|
||||
|
||||
rawSignedEthTx := createRawSignedEthTx(ctx, t, client, senderEthAddr, receiverEthAddr, senderKey, contractBin)
|
||||
|
||||
result := client.EVM().DeployContract(ctx, deployerAddr, contractBin)
|
||||
contractAddr, err := address.NewIDAddress(result.ActorID)
|
||||
require.NoError(t, err)
|
||||
|
||||
contractEthAddr := ethtypes.EthAddress(result.EthAddress)
|
||||
|
||||
messageWithEvents, blockHashWithMessage, blockNumberWithMessage := waitForMessageWithEvents(ctx, t, client, deployerAddr, contractAddr)
|
||||
|
||||
// create a json-rpc client that returns raw json responses
|
||||
var ethapi ethAPIRaw
|
||||
|
||||
netAddr, err := manet.ToNetAddr(client.ListenAddr)
|
||||
require.NoError(t, err)
|
||||
rpcAddr := "ws://" + netAddr.String() + "/rpc/v1"
|
||||
|
||||
closer, err := jsonrpc.NewClient(ctx, rpcAddr, "Filecoin", ðapi, nil)
|
||||
require.NoError(t, err)
|
||||
defer closer()
|
||||
|
||||
const skipUntilIssue10106 = "Skipped until EthTx is updated, see https://github.com/filecoin-project/lotus/issues/10106"
|
||||
|
||||
testCases := []struct {
|
||||
method string
|
||||
variant string // suffix applied to the test name to distinguish different variants of a method call
|
||||
call func(*ethAPIRaw) (json.RawMessage, error)
|
||||
skipReason string
|
||||
}{
|
||||
// Alphabetical order
|
||||
|
||||
{
|
||||
method: "eth_accounts",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthAccounts(context.Background())
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_blockNumber",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthBlockNumber(context.Background())
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_call",
|
||||
variant: "latest",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthCall(context.Background(), ethtypes.EthCall{
|
||||
From: &senderEthAddr,
|
||||
Data: contractBin,
|
||||
}, "latest")
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_chainId",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthChainId(context.Background())
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_estimateGas",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthEstimateGas(context.Background(), ethtypes.EthCall{
|
||||
From: &senderEthAddr,
|
||||
Data: contractBin,
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_feeHistory",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthFeeHistory(context.Background(), ethtypes.EthUint64(2), "", nil)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_gasPrice",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthGasPrice(context.Background())
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_getBalance",
|
||||
variant: "blocknumber",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthGetBalance(context.Background(), contractEthAddr, "0x0")
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_getBlockByHash",
|
||||
variant: "txhashes",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthGetBlockByHash(context.Background(), blockHashWithMessage, false)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_getBlockByHash",
|
||||
variant: "txfull",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthGetBlockByHash(context.Background(), blockHashWithMessage, true)
|
||||
},
|
||||
skipReason: skipUntilIssue10106,
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_getBlockByNumber",
|
||||
variant: "earliest",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthGetBlockByNumber(context.Background(), "earliest", true)
|
||||
},
|
||||
skipReason: skipUntilIssue10106,
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_getBlockByNumber",
|
||||
variant: "pending",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthGetBlockByNumber(context.Background(), "pending", true)
|
||||
},
|
||||
skipReason: skipUntilIssue10106,
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_getBlockByNumber",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthGetBlockByNumber(context.Background(), blockNumberWithMessage.Hex(), true)
|
||||
},
|
||||
skipReason: skipUntilIssue10106,
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_getBlockTransactionCountByHash",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthGetBlockTransactionCountByHash(context.Background(), blockHashWithMessage)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_getBlockTransactionCountByNumber",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthGetBlockTransactionCountByNumber(context.Background(), blockNumberWithMessage)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_getCode",
|
||||
variant: "blocknumber",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthGetCode(context.Background(), contractEthAddr, blockNumberWithMessage.Hex())
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_getFilterChanges",
|
||||
variant: "pendingtransaction",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return a.EthGetFilterChanges(ctx, pendingTransactionFilterID)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_getFilterChanges",
|
||||
variant: "block",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return a.EthGetFilterChanges(ctx, blockFilterID)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_getFilterChanges",
|
||||
variant: "logs",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return a.EthGetFilterChanges(ctx, logFilterID)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_getFilterLogs",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return a.EthGetFilterLogs(ctx, logFilterID)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_getLogs",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthGetLogs(context.Background(), filterAllLogs)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_getStorageAt",
|
||||
variant: "blocknumber",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthGetStorageAt(context.Background(), contractEthAddr, ethtypes.EthBytes{0}, "0x0")
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_getTransactionByBlockHashAndIndex",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthGetTransactionByBlockHashAndIndex(context.Background(), blockHashWithMessage, ethtypes.EthUint64(0))
|
||||
},
|
||||
skipReason: skipUntilIssue10106,
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_getTransactionByBlockNumberAndIndex",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthGetTransactionByBlockNumberAndIndex(context.Background(), blockNumberWithMessage, ethtypes.EthUint64(0))
|
||||
},
|
||||
skipReason: skipUntilIssue10106,
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_getTransactionByHash",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthGetTransactionByHash(context.Background(), &messageWithEvents)
|
||||
},
|
||||
skipReason: skipUntilIssue10106,
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_getTransactionCount",
|
||||
variant: "blocknumber",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthGetTransactionCount(context.Background(), senderEthAddr, blockNumberWithMessage.Hex())
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_getTransactionReceipt",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthGetTransactionReceipt(context.Background(), messageWithEvents)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_maxPriorityFeePerGas",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthMaxPriorityFeePerGas(context.Background())
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_newBlockFilter",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthNewBlockFilter(context.Background())
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_newFilter",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthNewFilter(context.Background(), filterAllLogs)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_newPendingTransactionFilter",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthNewPendingTransactionFilter(context.Background())
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
method: "eth_sendRawTransaction",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return ethapi.EthSendRawTransaction(context.Background(), rawSignedEthTx)
|
||||
},
|
||||
},
|
||||
{
|
||||
method: "eth_uninstallFilter",
|
||||
call: func(a *ethAPIRaw) (json.RawMessage, error) {
|
||||
return a.EthUninstallFilter(ctx, uninstallableFilterID)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
name := tc.method
|
||||
if tc.variant != "" {
|
||||
name += "_" + tc.variant
|
||||
}
|
||||
t.Run(name, func(t *testing.T) {
|
||||
if tc.skipReason != "" {
|
||||
t.Skipf(tc.skipReason)
|
||||
}
|
||||
|
||||
schema, ok := schemas[tc.method]
|
||||
require.True(t, ok, "method not found in openrpc spec")
|
||||
|
||||
resp, err := tc.call(ðapi)
|
||||
require.NoError(t, err)
|
||||
|
||||
respJson, err := json.Marshal(resp)
|
||||
require.NoError(t, err)
|
||||
|
||||
loader := gojsonschema.NewGoLoader(schema)
|
||||
resploader := gojsonschema.NewBytesLoader(respJson)
|
||||
result, err := gojsonschema.Validate(loader, resploader)
|
||||
require.NoError(t, err)
|
||||
|
||||
if !result.Valid() {
|
||||
if len(result.Errors()) == 1 && strings.Contains(result.Errors()[0].String(), "Must validate one and only one schema (oneOf)") {
|
||||
// Ignore this error, since it seems the openrpc spec can't handle it
|
||||
// New transaction and block filters have the same schema: an array of 32 byte hashes
|
||||
return
|
||||
}
|
||||
|
||||
niceRespJson, err := json.MarshalIndent(resp, "", " ")
|
||||
if err == nil {
|
||||
t.Logf("response was %s", niceRespJson)
|
||||
}
|
||||
|
||||
schemaJson, err := json.MarshalIndent(schema, "", " ")
|
||||
if err == nil {
|
||||
t.Logf("schema was %s", schemaJson)
|
||||
}
|
||||
|
||||
// check against https://www.jsonschemavalidator.net/
|
||||
|
||||
for _, desc := range result.Errors() {
|
||||
t.Logf("- %s\n", desc)
|
||||
}
|
||||
|
||||
t.Errorf("response did not validate")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func createRawSignedEthTx(ctx context.Context, t *testing.T, client *kit.TestFullNode, senderEthAddr ethtypes.EthAddress, receiverEthAddr ethtypes.EthAddress, senderKey *key.Key, contractBin []byte) []byte {
|
||||
gaslimit, err := client.EthEstimateGas(ctx, ethtypes.EthCall{
|
||||
From: &senderEthAddr,
|
||||
Data: contractBin,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
maxPriorityFeePerGas, err := client.EthMaxPriorityFeePerGas(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
tx := ethtypes.EthTxArgs{
|
||||
ChainID: build.Eip155ChainId,
|
||||
Value: big.NewInt(100),
|
||||
Nonce: 0,
|
||||
To: &receiverEthAddr,
|
||||
MaxFeePerGas: types.NanoFil,
|
||||
MaxPriorityFeePerGas: big.Int(maxPriorityFeePerGas),
|
||||
GasLimit: int(gaslimit),
|
||||
V: big.Zero(),
|
||||
R: big.Zero(),
|
||||
S: big.Zero(),
|
||||
}
|
||||
|
||||
client.EVM().SignTransaction(&tx, senderKey.PrivateKey)
|
||||
signed, err := tx.ToRlpSignedMsg()
|
||||
require.NoError(t, err)
|
||||
return signed
|
||||
}
|
||||
|
||||
func waitForMessageWithEvents(ctx context.Context, t *testing.T, client *kit.TestFullNode, sender address.Address, target address.Address) (ethtypes.EthHash, ethtypes.EthHash, ethtypes.EthUint64) {
|
||||
vals := []uint64{44, 27, 19, 12}
|
||||
inputData := []byte{}
|
||||
for _, v := range vals {
|
||||
buf := make([]byte, 32)
|
||||
binary.BigEndian.PutUint64(buf[24:], v)
|
||||
inputData = append(inputData, buf...)
|
||||
}
|
||||
|
||||
// send a message that exercises event logs
|
||||
ret, err := client.EVM().InvokeSolidity(ctx, sender, target, kit.EventMatrixContract.Fn["logEventThreeIndexedWithData"], inputData)
|
||||
require.NoError(t, err)
|
||||
require.True(t, ret.Receipt.ExitCode.IsSuccess(), "contract execution failed")
|
||||
|
||||
msgHash, err := client.EthGetTransactionHashByCid(ctx, ret.Message)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, msgHash)
|
||||
|
||||
ts, err := client.ChainGetTipSet(ctx, ret.TipSet)
|
||||
require.NoError(t, err)
|
||||
|
||||
blockNumber := ethtypes.EthUint64(ts.Height())
|
||||
|
||||
tsCid, err := ts.Key().Cid()
|
||||
require.NoError(t, err)
|
||||
|
||||
blockHash, err := ethtypes.EthHashFromCid(tsCid)
|
||||
require.NoError(t, err)
|
||||
return *msgHash, blockHash, blockNumber
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -117,11 +117,9 @@ func TestLegacyTransaction(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
_, err = client.EVM().EthSendRawTransaction(ctx, txBytes)
|
||||
require.ErrorContains(t, err, "legacy transaction is not supported")
|
||||
|
||||
}
|
||||
|
||||
func TestContractDeploymentValidSignature(t *testing.T) {
|
||||
|
||||
blockTime := 100 * time.Millisecond
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
|
||||
|
||||
@ -270,7 +268,6 @@ func TestContractInvocation(t *testing.T) {
|
||||
|
||||
// Success.
|
||||
require.EqualValues(t, ethtypes.EthUint64(0x1), receipt.Status)
|
||||
|
||||
}
|
||||
|
||||
func deployContractTx(ctx context.Context, client *kit.TestFullNode, ethAddr ethtypes.EthAddress, contract []byte) (*ethtypes.EthTxArgs, error) {
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/filecoin-project/go-state-types/exitcode"
|
||||
"github.com/filecoin-project/go-state-types/manifest"
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
"github.com/filecoin-project/lotus/itests/kit"
|
||||
@ -56,7 +57,7 @@ func buildInputFromuint64(number uint64) []byte {
|
||||
// recursive delegate calls that fail due to gas limits are currently getting to 229 iterations
|
||||
// before running out of gas
|
||||
func recursiveDelegatecallFail(ctx context.Context, t *testing.T, client *kit.TestFullNode, filename string, count uint64) {
|
||||
expectedIterationsBeforeFailing := int(229)
|
||||
expectedIterationsBeforeFailing := int(228)
|
||||
fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, filename)
|
||||
t.Log("recursion count - ", count)
|
||||
inputData := buildInputFromuint64(count)
|
||||
@ -122,7 +123,7 @@ func TestFEVMRecursiveFail(t *testing.T) {
|
||||
t.Run(fmt.Sprintf("TestFEVMRecursiveFail%d", failCallCount), func(t *testing.T) {
|
||||
_, wait, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "recursiveCall(uint256)", buildInputFromuint64(failCallCount))
|
||||
require.Error(t, err)
|
||||
require.Equal(t, exitcode.ExitCode(23), wait.Receipt.ExitCode)
|
||||
require.Equal(t, exitcode.ExitCode(37), wait.Receipt.ExitCode)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -149,24 +150,26 @@ func TestFEVMRecursive2(t *testing.T) {
|
||||
require.Equal(t, 2, len(events))
|
||||
}
|
||||
|
||||
// TestFEVMBasic does a basic fevm contract installation and invocation
|
||||
// recursive delegate call succeeds up to 238 times
|
||||
func TestFEVMRecursiveDelegatecall(t *testing.T) {
|
||||
// TestFEVMRecursiveDelegatecallCount tests the maximum delegatecall recursion depth. It currently
|
||||
// succeeds succeeds up to 237 times.
|
||||
func TestFEVMRecursiveDelegatecallCount(t *testing.T) {
|
||||
|
||||
ctx, cancel, client := kit.SetupFEVMTest(t)
|
||||
defer cancel()
|
||||
|
||||
highestSuccessCount := uint64(237)
|
||||
|
||||
filename := "contracts/RecursiveDelegeatecall.hex"
|
||||
recursiveDelegatecallSuccess(ctx, t, client, filename, uint64(1))
|
||||
recursiveDelegatecallSuccess(ctx, t, client, filename, uint64(2))
|
||||
recursiveDelegatecallSuccess(ctx, t, client, filename, uint64(10))
|
||||
recursiveDelegatecallSuccess(ctx, t, client, filename, uint64(100))
|
||||
recursiveDelegatecallSuccess(ctx, t, client, filename, highestSuccessCount)
|
||||
|
||||
//success with 238 or fewer calls
|
||||
for i := uint64(1); i <= 238; i += 30 {
|
||||
recursiveDelegatecallSuccess(ctx, t, client, filename, i)
|
||||
}
|
||||
recursiveDelegatecallSuccess(ctx, t, client, filename, uint64(238))
|
||||
recursiveDelegatecallFail(ctx, t, client, filename, highestSuccessCount+1)
|
||||
recursiveDelegatecallFail(ctx, t, client, filename, uint64(1000))
|
||||
recursiveDelegatecallFail(ctx, t, client, filename, uint64(10000000))
|
||||
|
||||
for i := uint64(239); i <= 800; i += 40 {
|
||||
recursiveDelegatecallFail(ctx, t, client, filename, i)
|
||||
}
|
||||
}
|
||||
|
||||
// TestFEVMBasic does a basic fevm contract installation and invocation
|
||||
@ -469,10 +472,9 @@ func TestFEVMSendGasLimit(t *testing.T) {
|
||||
}
|
||||
|
||||
// TestFEVMDelegateCall deploys the two contracts in TestFEVMDelegateCall but instead of A calling B, A calls A which should cause A to cause A in an infinite loop and should give a reasonable error
|
||||
// XXX should not be fatal errors
|
||||
func TestFEVMDelegateCallRecursiveFail(t *testing.T) {
|
||||
//TODO change the gas limit of this invocation and confirm that the number of errors is different
|
||||
//also TODO should we not have fatal error show up here?
|
||||
//TODO change the gas limit of this invocation and confirm that the number of errors is
|
||||
// different
|
||||
ctx, cancel, client := kit.SetupFEVMTest(t)
|
||||
defer cancel()
|
||||
|
||||
@ -485,17 +487,16 @@ func TestFEVMDelegateCallRecursiveFail(t *testing.T) {
|
||||
inputDataValue := inputDataFromArray([]byte{7})
|
||||
inputData := append(inputDataContract, inputDataValue...)
|
||||
|
||||
//verify that the returned value of the call to setvars is 7
|
||||
//verify that we run out of gas then revert.
|
||||
_, wait, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, actorAddr, "setVarsSelf(address,uint256)", inputData)
|
||||
require.Error(t, err)
|
||||
require.Equal(t, exitcode.SysErrorIllegalArgument, wait.Receipt.ExitCode)
|
||||
require.Equal(t, exitcode.ExitCode(33), wait.Receipt.ExitCode)
|
||||
|
||||
//assert no fatal errors but still there are errors::
|
||||
errorAny := "fatal error"
|
||||
require.NotContains(t, err.Error(), errorAny)
|
||||
}
|
||||
|
||||
// XXX Currently fails as self destruct has a bug
|
||||
// TestFEVMTestSendValueThroughContracts creates A and B contract and exchanges value
|
||||
// and self destructs and accounts for value sent
|
||||
func TestFEVMTestSendValueThroughContractsAndDestroy(t *testing.T) {
|
||||
@ -606,3 +607,100 @@ func TestFEVMRecursiveActorCall(t *testing.T) {
|
||||
t.Run("n=0,r=256-fails", testN(0, 256, exitcode.ExitCode(33))) // 33 means transaction reverted
|
||||
t.Run("n=251,r=167-fails", testN(251, 167, exitcode.ExitCode(33)))
|
||||
}
|
||||
|
||||
// TestFEVMRecursiveActorCallEstimate
|
||||
func TestFEVMRecursiveActorCallEstimate(t *testing.T) {
|
||||
ctx, cancel, client := kit.SetupFEVMTest(t)
|
||||
defer cancel()
|
||||
|
||||
//install contract Actor
|
||||
filenameActor := "contracts/ExternalRecursiveCallSimple.hex"
|
||||
_, actorAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor)
|
||||
|
||||
contractAddr, err := ethtypes.EthAddressFromFilecoinAddress(actorAddr)
|
||||
require.NoError(t, err)
|
||||
|
||||
// create a new Ethereum account
|
||||
key, ethAddr, ethFilAddr := client.EVM().NewAccount()
|
||||
kit.SendFunds(ctx, t, client, ethFilAddr, types.FromFil(1000))
|
||||
|
||||
makeParams := func(r int) []byte {
|
||||
funcSignature := "exec1(uint256)"
|
||||
entryPoint := kit.CalcFuncSignature(funcSignature)
|
||||
|
||||
inputData := make([]byte, 32)
|
||||
binary.BigEndian.PutUint64(inputData[24:], uint64(r))
|
||||
|
||||
params := append(entryPoint, inputData...)
|
||||
|
||||
return params
|
||||
}
|
||||
|
||||
testN := func(r int) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
t.Logf("running with %d recursive calls", r)
|
||||
|
||||
params := makeParams(r)
|
||||
gaslimit, err := client.EthEstimateGas(ctx, ethtypes.EthCall{
|
||||
From: ðAddr,
|
||||
To: &contractAddr,
|
||||
Data: params,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.LessOrEqual(t, int64(gaslimit), build.BlockGasLimit)
|
||||
|
||||
t.Logf("EthEstimateGas GasLimit=%d", gaslimit)
|
||||
|
||||
maxPriorityFeePerGas, err := client.EthMaxPriorityFeePerGas(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
nonce, err := client.MpoolGetNonce(ctx, ethFilAddr)
|
||||
require.NoError(t, err)
|
||||
|
||||
tx := ðtypes.EthTxArgs{
|
||||
ChainID: build.Eip155ChainId,
|
||||
To: &contractAddr,
|
||||
Value: big.Zero(),
|
||||
Nonce: int(nonce),
|
||||
MaxFeePerGas: types.NanoFil,
|
||||
MaxPriorityFeePerGas: big.Int(maxPriorityFeePerGas),
|
||||
GasLimit: int(gaslimit),
|
||||
Input: params,
|
||||
V: big.Zero(),
|
||||
R: big.Zero(),
|
||||
S: big.Zero(),
|
||||
}
|
||||
|
||||
client.EVM().SignTransaction(tx, key.PrivateKey)
|
||||
hash := client.EVM().SubmitTransaction(ctx, tx)
|
||||
|
||||
smsg, err := tx.ToSignedMessage()
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = client.StateWaitMsg(ctx, smsg.Cid(), 0, 0, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
receipt, err := client.EthGetTransactionReceipt(ctx, hash)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, receipt)
|
||||
|
||||
t.Logf("Receipt GasUsed=%d", receipt.GasUsed)
|
||||
t.Logf("Ratio %0.2f", float64(receipt.GasUsed)/float64(gaslimit))
|
||||
t.Logf("Overestimate %0.2f", ((float64(gaslimit)/float64(receipt.GasUsed))-1)*100)
|
||||
|
||||
require.EqualValues(t, ethtypes.EthUint64(1), receipt.Status)
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("n=1", testN(1))
|
||||
t.Run("n=2", testN(2))
|
||||
t.Run("n=3", testN(3))
|
||||
t.Run("n=4", testN(4))
|
||||
t.Run("n=5", testN(5))
|
||||
t.Run("n=10", testN(10))
|
||||
t.Run("n=20", testN(20))
|
||||
t.Run("n=30", testN(30))
|
||||
t.Run("n=40", testN(40))
|
||||
t.Run("n=50", testN(50))
|
||||
t.Run("n=100", testN(100))
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
@ -126,7 +127,11 @@ func (e *EVM) InvokeSolidity(ctx context.Context, sender address.Address, target
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !wait.Receipt.ExitCode.IsSuccess() {
|
||||
result, err := e.StateReplay(ctx, types.EmptyTSK, wait.Message)
|
||||
require.NoError(e.t, err)
|
||||
e.t.Log(result.Error)
|
||||
}
|
||||
return wait, nil
|
||||
}
|
||||
|
||||
@ -244,7 +249,9 @@ func (e *EVM) InvokeContractByFuncName(ctx context.Context, fromAddr address.Add
|
||||
return nil, wait, err
|
||||
}
|
||||
if !wait.Receipt.ExitCode.IsSuccess() {
|
||||
return nil, wait, fmt.Errorf("contract execution failed - %v", wait.Receipt.ExitCode)
|
||||
result, err := e.StateReplay(ctx, types.EmptyTSK, wait.Message)
|
||||
require.NoError(e.t, err)
|
||||
return nil, wait, errors.New(result.Error)
|
||||
}
|
||||
result, err := cbg.ReadByteArray(bytes.NewBuffer(wait.Receipt.Return), uint64(len(wait.Receipt.Return)))
|
||||
if err != nil {
|
||||
@ -319,7 +326,7 @@ func removeLeadingZeros(data []byte) []byte {
|
||||
}
|
||||
|
||||
func SetupFEVMTest(t *testing.T) (context.Context, context.CancelFunc, *TestFullNode) {
|
||||
//make all logs extra quiet for fevm tests
|
||||
// make all logs extra quiet for fevm tests
|
||||
lvl, err := logging.LevelFromString("error")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -354,3 +361,77 @@ func (e *EVM) TransferValueOrFail(ctx context.Context, fromAddr address.Address,
|
||||
require.NoError(e.t, err)
|
||||
require.Equal(e.t, exitcode.Ok, mLookup.Receipt.ExitCode)
|
||||
}
|
||||
|
||||
func NewEthFilterBuilder() *EthFilterBuilder {
|
||||
return &EthFilterBuilder{}
|
||||
}
|
||||
|
||||
type EthFilterBuilder struct {
|
||||
filter ethtypes.EthFilterSpec
|
||||
}
|
||||
|
||||
func (e *EthFilterBuilder) Filter() *ethtypes.EthFilterSpec { return &e.filter }
|
||||
|
||||
func (e *EthFilterBuilder) FromBlock(v string) *EthFilterBuilder {
|
||||
e.filter.FromBlock = &v
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *EthFilterBuilder) FromBlockEpoch(v abi.ChainEpoch) *EthFilterBuilder {
|
||||
s := ethtypes.EthUint64(v).Hex()
|
||||
e.filter.FromBlock = &s
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *EthFilterBuilder) ToBlock(v string) *EthFilterBuilder {
|
||||
e.filter.ToBlock = &v
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *EthFilterBuilder) ToBlockEpoch(v abi.ChainEpoch) *EthFilterBuilder {
|
||||
s := ethtypes.EthUint64(v).Hex()
|
||||
e.filter.ToBlock = &s
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *EthFilterBuilder) BlockHash(h ethtypes.EthHash) *EthFilterBuilder {
|
||||
e.filter.BlockHash = &h
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *EthFilterBuilder) AddressOneOf(as ...ethtypes.EthAddress) *EthFilterBuilder {
|
||||
e.filter.Address = as
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *EthFilterBuilder) Topic1OneOf(hs ...ethtypes.EthHash) *EthFilterBuilder {
|
||||
if len(e.filter.Topics) == 0 {
|
||||
e.filter.Topics = make(ethtypes.EthTopicSpec, 1)
|
||||
}
|
||||
e.filter.Topics[0] = hs
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *EthFilterBuilder) Topic2OneOf(hs ...ethtypes.EthHash) *EthFilterBuilder {
|
||||
for len(e.filter.Topics) < 2 {
|
||||
e.filter.Topics = append(e.filter.Topics, nil)
|
||||
}
|
||||
e.filter.Topics[1] = hs
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *EthFilterBuilder) Topic3OneOf(hs ...ethtypes.EthHash) *EthFilterBuilder {
|
||||
for len(e.filter.Topics) < 3 {
|
||||
e.filter.Topics = append(e.filter.Topics, nil)
|
||||
}
|
||||
e.filter.Topics[2] = hs
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *EthFilterBuilder) Topic4OneOf(hs ...ethtypes.EthHash) *EthFilterBuilder {
|
||||
for len(e.filter.Topics) < 4 {
|
||||
e.filter.Topics = append(e.filter.Topics, nil)
|
||||
}
|
||||
e.filter.Topics[3] = hs
|
||||
return e
|
||||
}
|
||||
|
64
itests/kit/solidity.go
Normal file
64
itests/kit/solidity.go
Normal file
@ -0,0 +1,64 @@
|
||||
package kit
|
||||
|
||||
import (
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
func EthTopicHash(sig string) []byte {
|
||||
hasher := sha3.NewLegacyKeccak256()
|
||||
hasher.Write([]byte(sig))
|
||||
return hasher.Sum(nil)
|
||||
}
|
||||
|
||||
func EthFunctionHash(sig string) []byte {
|
||||
hasher := sha3.NewLegacyKeccak256()
|
||||
hasher.Write([]byte(sig))
|
||||
return hasher.Sum(nil)[:4]
|
||||
}
|
||||
|
||||
// SolidityContractDef holds information about one of the test contracts
|
||||
type SolidityContractDef struct {
|
||||
Filename string // filename of the hex of the contract, e.g. contracts/EventMatrix.hex
|
||||
Fn map[string][]byte // mapping of function names to 32-bit selector
|
||||
Ev map[string][]byte // mapping of event names to 256-bit signature hashes
|
||||
}
|
||||
|
||||
var EventMatrixContract = SolidityContractDef{
|
||||
Filename: "contracts/EventMatrix.hex",
|
||||
Fn: map[string][]byte{
|
||||
"logEventZeroData": EthFunctionHash("logEventZeroData()"),
|
||||
"logEventOneData": EthFunctionHash("logEventOneData(uint256)"),
|
||||
"logEventTwoData": EthFunctionHash("logEventTwoData(uint256,uint256)"),
|
||||
"logEventThreeData": EthFunctionHash("logEventThreeData(uint256,uint256,uint256)"),
|
||||
"logEventFourData": EthFunctionHash("logEventFourData(uint256,uint256,uint256,uint256)"),
|
||||
"logEventOneIndexed": EthFunctionHash("logEventOneIndexed(uint256)"),
|
||||
"logEventTwoIndexed": EthFunctionHash("logEventTwoIndexed(uint256,uint256)"),
|
||||
"logEventThreeIndexed": EthFunctionHash("logEventThreeIndexed(uint256,uint256,uint256)"),
|
||||
"logEventOneIndexedWithData": EthFunctionHash("logEventOneIndexedWithData(uint256,uint256)"),
|
||||
"logEventTwoIndexedWithData": EthFunctionHash("logEventTwoIndexedWithData(uint256,uint256,uint256)"),
|
||||
"logEventThreeIndexedWithData": EthFunctionHash("logEventThreeIndexedWithData(uint256,uint256,uint256,uint256)"),
|
||||
},
|
||||
Ev: map[string][]byte{
|
||||
"EventZeroData": EthTopicHash("EventZeroData()"),
|
||||
"EventOneData": EthTopicHash("EventOneData(uint256)"),
|
||||
"EventTwoData": EthTopicHash("EventTwoData(uint256,uint256)"),
|
||||
"EventThreeData": EthTopicHash("EventThreeData(uint256,uint256,uint256)"),
|
||||
"EventFourData": EthTopicHash("EventFourData(uint256,uint256,uint256,uint256)"),
|
||||
"EventOneIndexed": EthTopicHash("EventOneIndexed(uint256)"),
|
||||
"EventTwoIndexed": EthTopicHash("EventTwoIndexed(uint256,uint256)"),
|
||||
"EventThreeIndexed": EthTopicHash("EventThreeIndexed(uint256,uint256,uint256)"),
|
||||
"EventOneIndexedWithData": EthTopicHash("EventOneIndexedWithData(uint256,uint256)"),
|
||||
"EventTwoIndexedWithData": EthTopicHash("EventTwoIndexedWithData(uint256,uint256,uint256)"),
|
||||
"EventThreeIndexedWithData": EthTopicHash("EventThreeIndexedWithData(uint256,uint256,uint256,uint256)"),
|
||||
},
|
||||
}
|
||||
|
||||
var EventsContract = SolidityContractDef{
|
||||
Filename: "contracts/events.bin",
|
||||
Fn: map[string][]byte{
|
||||
"log_zero_data": {0x00, 0x00, 0x00, 0x00},
|
||||
"log_zero_nodata": {0x00, 0x00, 0x00, 0x01},
|
||||
"log_four_data": {0x00, 0x00, 0x00, 0x02},
|
||||
},
|
||||
Ev: map[string][]byte{},
|
||||
}
|
4392
itests/specs/eth_openrpc.json
Normal file
4392
itests/specs/eth_openrpc.json
Normal file
File diff suppressed because it is too large
Load Diff
9
lib/must/must.go
Normal file
9
lib/must/must.go
Normal file
@ -0,0 +1,9 @@
|
||||
package must
|
||||
|
||||
func One[R any](r R, err error) R {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
@ -24,6 +24,7 @@ import (
|
||||
"github.com/filecoin-project/go-state-types/builtin/v10/eam"
|
||||
"github.com/filecoin-project/go-state-types/builtin/v10/evm"
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
"github.com/filecoin-project/go-state-types/exitcode"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
@ -446,6 +447,11 @@ func (a *EthModule) EthGetCode(ctx context.Context, ethAddr ethtypes.EthAddress,
|
||||
return nil, xerrors.Errorf("cannot parse block param: %s", blkParam)
|
||||
}
|
||||
|
||||
// StateManager.Call will panic if there is no parent
|
||||
if ts.Height() == 0 {
|
||||
return nil, xerrors.Errorf("block param must not specify genesis block")
|
||||
}
|
||||
|
||||
// Try calling until we find a height with no migration.
|
||||
var res *api.InvocResult
|
||||
for {
|
||||
@ -636,7 +642,7 @@ func (a *EthModule) EthFeeHistory(ctx context.Context, blkCount ethtypes.EthUint
|
||||
}
|
||||
|
||||
return ethtypes.EthFeeHistory{
|
||||
OldestBlock: oldestBlkHeight,
|
||||
OldestBlock: ethtypes.EthUint64(oldestBlkHeight),
|
||||
BaseFeePerGas: baseFeeArray,
|
||||
GasUsedRatio: gasUsedRatioArray,
|
||||
}, nil
|
||||
@ -809,12 +815,137 @@ func (a *EthModule) EthEstimateGas(ctx context.Context, tx ethtypes.EthCall) (et
|
||||
// gas estimation actually run.
|
||||
msg.GasLimit = 0
|
||||
|
||||
msg, err = a.GasAPI.GasEstimateMessageGas(ctx, msg, nil, types.EmptyTSK)
|
||||
ts := a.Chain.GetHeaviestTipSet()
|
||||
msg, err = a.GasAPI.GasEstimateMessageGas(ctx, msg, nil, ts.Key())
|
||||
if err != nil {
|
||||
return ethtypes.EthUint64(0), err
|
||||
return ethtypes.EthUint64(0), xerrors.Errorf("failed to estimate gas: %w", err)
|
||||
}
|
||||
|
||||
return ethtypes.EthUint64(msg.GasLimit), nil
|
||||
expectedGas, err := ethGasSearch(ctx, a.Chain, a.Stmgr, a.Mpool, msg, ts)
|
||||
if err != nil {
|
||||
log.Errorw("expected gas", "err", err)
|
||||
}
|
||||
|
||||
return ethtypes.EthUint64(expectedGas), nil
|
||||
}
|
||||
|
||||
// gasSearch does an exponential search to find a gas value to execute the
|
||||
// message with. It first finds a high gas limit that allows the message to execute
|
||||
// by doubling the previous gas limit until it succeeds then does a binary
|
||||
// search till it gets within a range of 1%
|
||||
func gasSearch(
|
||||
ctx context.Context,
|
||||
smgr *stmgr.StateManager,
|
||||
msgIn *types.Message,
|
||||
priorMsgs []types.ChainMsg,
|
||||
ts *types.TipSet,
|
||||
) (int64, error) {
|
||||
msg := *msgIn
|
||||
|
||||
high := msg.GasLimit
|
||||
low := msg.GasLimit
|
||||
|
||||
canSucceed := func(limit int64) (bool, error) {
|
||||
msg.GasLimit = limit
|
||||
|
||||
res, err := smgr.CallWithGas(ctx, &msg, priorMsgs, ts)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("CallWithGas failed: %w", err)
|
||||
}
|
||||
|
||||
if res.MsgRct.ExitCode.IsSuccess() {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
for {
|
||||
ok, err := canSucceed(high)
|
||||
if err != nil {
|
||||
return -1, xerrors.Errorf("searching for high gas limit failed: %w", err)
|
||||
}
|
||||
if ok {
|
||||
break
|
||||
}
|
||||
|
||||
low = high
|
||||
high = high * 2
|
||||
|
||||
if high > build.BlockGasLimit {
|
||||
high = build.BlockGasLimit
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
checkThreshold := high / 100
|
||||
for (high - low) > checkThreshold {
|
||||
median := (low + high) / 2
|
||||
ok, err := canSucceed(median)
|
||||
if err != nil {
|
||||
return -1, xerrors.Errorf("searching for optimal gas limit failed: %w", err)
|
||||
}
|
||||
|
||||
if ok {
|
||||
high = median
|
||||
} else {
|
||||
low = median
|
||||
}
|
||||
|
||||
checkThreshold = median / 100
|
||||
}
|
||||
|
||||
return high, nil
|
||||
}
|
||||
|
||||
func traceContainsExitCode(et types.ExecutionTrace, ex exitcode.ExitCode) bool {
|
||||
if et.MsgRct.ExitCode == ex {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, et := range et.Subcalls {
|
||||
if traceContainsExitCode(et, ex) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// ethGasSearch executes a message for gas estimation using the previously estimated gas.
|
||||
// If the message fails due to an out of gas error then a gas search is performed.
|
||||
// See gasSearch.
|
||||
func ethGasSearch(
|
||||
ctx context.Context,
|
||||
cstore *store.ChainStore,
|
||||
smgr *stmgr.StateManager,
|
||||
mpool *messagepool.MessagePool,
|
||||
msgIn *types.Message,
|
||||
ts *types.TipSet,
|
||||
) (int64, error) {
|
||||
msg := *msgIn
|
||||
currTs := ts
|
||||
|
||||
res, priorMsgs, ts, err := gasEstimateCallWithGas(ctx, cstore, smgr, mpool, &msg, currTs)
|
||||
if err != nil {
|
||||
return -1, xerrors.Errorf("gas estimation failed: %w", err)
|
||||
}
|
||||
|
||||
if res.MsgRct.ExitCode.IsSuccess() {
|
||||
return msg.GasLimit, nil
|
||||
}
|
||||
|
||||
if traceContainsExitCode(res.ExecutionTrace, exitcode.SysErrOutOfGas) {
|
||||
ret, err := gasSearch(ctx, smgr, &msg, priorMsgs, ts)
|
||||
if err != nil {
|
||||
return -1, xerrors.Errorf("gas estimation search failed: %w", err)
|
||||
}
|
||||
|
||||
ret = int64(float64(ret) * mpool.GetConfig().GasLimitOverestimation)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
return -1, xerrors.Errorf("message execution failed: exit %s, reason: %s", res.MsgRct.ExitCode, res.Error)
|
||||
}
|
||||
|
||||
func (a *EthModule) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam string) (ethtypes.EthBytes, error) {
|
||||
@ -836,7 +967,6 @@ func (a *EthModule) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam s
|
||||
if msg.To == builtintypes.EthereumAddressManagerActorAddr {
|
||||
// As far as I can tell, the Eth API always returns empty on contract deployment
|
||||
return ethtypes.EthBytes{}, nil
|
||||
|
||||
} else if len(invokeResult.MsgRct.Return) > 0 {
|
||||
return cbg.ReadByteArray(bytes.NewReader(invokeResult.MsgRct.Return), uint64(len(invokeResult.MsgRct.Return)))
|
||||
}
|
||||
@ -1468,7 +1598,7 @@ func newEthBlockFromFilecoinTipSet(ctx context.Context, ts *types.TipSet, fullTx
|
||||
return ethtypes.EthBlock{}, xerrors.Errorf("error loading messages for tipset: %v: %w", ts, err)
|
||||
}
|
||||
|
||||
block := ethtypes.NewEthBlock()
|
||||
block := ethtypes.NewEthBlock(len(msgs) > 0)
|
||||
|
||||
// this seems to be a very expensive way to get gasUsed of the block. may need to find an efficient way to do it
|
||||
gasUsed := int64(0)
|
||||
|
@ -248,22 +248,23 @@ func (m *GasModule) GasEstimateGasLimit(ctx context.Context, msgIn *types.Messag
|
||||
}
|
||||
return gasEstimateGasLimit(ctx, m.Chain, m.Stmgr, m.Mpool, msgIn, ts)
|
||||
}
|
||||
func gasEstimateGasLimit(
|
||||
|
||||
// gasEstimateCallWithGas invokes a message "msgIn" on the earliest available tipset with pending
|
||||
// messages in the message pool. The function returns the result of the message invocation, the
|
||||
// pending messages, the tipset used for the invocation, and an error if occurred.
|
||||
// The returned information can be used to make subsequent calls to CallWithGas with the same parameters.
|
||||
func gasEstimateCallWithGas(
|
||||
ctx context.Context,
|
||||
cstore *store.ChainStore,
|
||||
smgr *stmgr.StateManager,
|
||||
mpool *messagepool.MessagePool,
|
||||
msgIn *types.Message,
|
||||
currTs *types.TipSet,
|
||||
) (int64, error) {
|
||||
) (*api.InvocResult, []types.ChainMsg, *types.TipSet, error) {
|
||||
msg := *msgIn
|
||||
msg.GasLimit = build.BlockGasLimit
|
||||
msg.GasFeeCap = big.Zero()
|
||||
msg.GasPremium = big.Zero()
|
||||
|
||||
fromA, err := smgr.ResolveToDeterministicAddress(ctx, msgIn.From, currTs)
|
||||
if err != nil {
|
||||
return -1, xerrors.Errorf("getting key address: %w", err)
|
||||
return nil, []types.ChainMsg{}, nil, xerrors.Errorf("getting key address: %w", err)
|
||||
}
|
||||
|
||||
pending, ts := mpool.PendingFor(ctx, fromA)
|
||||
@ -284,12 +285,34 @@ func gasEstimateGasLimit(
|
||||
}
|
||||
ts, err = cstore.GetTipSetFromKey(ctx, ts.Parents())
|
||||
if err != nil {
|
||||
return -1, xerrors.Errorf("getting parent tipset: %w", err)
|
||||
return nil, []types.ChainMsg{}, nil, xerrors.Errorf("getting parent tipset: %w", err)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return -1, xerrors.Errorf("CallWithGas failed: %w", err)
|
||||
return nil, []types.ChainMsg{}, nil, xerrors.Errorf("CallWithGas failed: %w", err)
|
||||
}
|
||||
|
||||
return res, priorMsgs, ts, nil
|
||||
}
|
||||
|
||||
func gasEstimateGasLimit(
|
||||
ctx context.Context,
|
||||
cstore *store.ChainStore,
|
||||
smgr *stmgr.StateManager,
|
||||
mpool *messagepool.MessagePool,
|
||||
msgIn *types.Message,
|
||||
currTs *types.TipSet,
|
||||
) (int64, error) {
|
||||
msg := *msgIn
|
||||
msg.GasLimit = build.BlockGasLimit
|
||||
msg.GasFeeCap = big.Zero()
|
||||
msg.GasPremium = big.Zero()
|
||||
|
||||
res, _, ts, err := gasEstimateCallWithGas(ctx, cstore, smgr, mpool, &msg, currTs)
|
||||
if err != nil {
|
||||
return -1, xerrors.Errorf("gas estimation failed: %w", err)
|
||||
}
|
||||
|
||||
if res.MsgRct.ExitCode == exitcode.SysErrOutOfGas {
|
||||
return -1, &api.ErrOutOfGas{}
|
||||
}
|
||||
@ -300,6 +323,8 @@ func gasEstimateGasLimit(
|
||||
|
||||
ret := res.MsgRct.GasUsed
|
||||
|
||||
log.Infow("GasEstimateMessageGas CallWithGas Result", "GasUsed", ret, "ExitCode", res.MsgRct.ExitCode)
|
||||
|
||||
transitionalMulti := 1.0
|
||||
// Overestimate gas around the upgrade
|
||||
if ts.Height() <= build.UpgradeSkyrHeight && (build.UpgradeSkyrHeight-ts.Height() <= 20) {
|
||||
|
Loading…
Reference in New Issue
Block a user