diff --git a/api/api_full.go b/api/api_full.go index c2a494dcf..b17fad3b5 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -779,6 +779,7 @@ type FullNode interface { 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 EthGetTransactionHashByCid(ctx context.Context, cid cid.Cid) (*ethtypes.EthHash, error) //perm:read + EthGetMessageCidByTransactionHash(ctx context.Context, txHash *ethtypes.EthHash) (*cid.Cid, 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 diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index 18eb15bae..b32fc7d8b 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -1177,6 +1177,21 @@ func (mr *MockFullNodeMockRecorder) EthGetLogs(arg0, arg1 interface{}) *gomock.C return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthGetLogs", reflect.TypeOf((*MockFullNode)(nil).EthGetLogs), arg0, arg1) } +// EthGetMessageCidByTransactionHash mocks base method. +func (m *MockFullNode) EthGetMessageCidByTransactionHash(arg0 context.Context, arg1 *ethtypes.EthHash) (*cid.Cid, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "EthGetMessageCidByTransactionHash", arg0, arg1) + ret0, _ := ret[0].(*cid.Cid) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// EthGetMessageCidByTransactionHash indicates an expected call of EthGetMessageCidByTransactionHash. +func (mr *MockFullNodeMockRecorder) EthGetMessageCidByTransactionHash(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EthGetMessageCidByTransactionHash", reflect.TypeOf((*MockFullNode)(nil).EthGetMessageCidByTransactionHash), 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() diff --git a/api/proxy_gen.go b/api/proxy_gen.go index d1df2a215..aaa1d87c7 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -253,6 +253,8 @@ type FullNodeStruct struct { EthGetLogs func(p0 context.Context, p1 *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) `perm:"read"` + EthGetMessageCidByTransactionHash func(p0 context.Context, p1 *ethtypes.EthHash) (*cid.Cid, error) `perm:"read"` + 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"` @@ -2119,6 +2121,17 @@ func (s *FullNodeStub) EthGetLogs(p0 context.Context, p1 *ethtypes.EthFilterSpec return nil, ErrNotSupported } +func (s *FullNodeStruct) EthGetMessageCidByTransactionHash(p0 context.Context, p1 *ethtypes.EthHash) (*cid.Cid, error) { + if s.Internal.EthGetMessageCidByTransactionHash == nil { + return nil, ErrNotSupported + } + return s.Internal.EthGetMessageCidByTransactionHash(p0, p1) +} + +func (s *FullNodeStub) EthGetMessageCidByTransactionHash(p0 context.Context, p1 *ethtypes.EthHash) (*cid.Cid, 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 diff --git a/build/actors/v10.tar.zst b/build/actors/v10.tar.zst index f12e7b251..b0c9e5ce8 100644 Binary files a/build/actors/v10.tar.zst and b/build/actors/v10.tar.zst differ diff --git a/build/builtin_actors_gen.go b/build/builtin_actors_gen.go index 4beb8ff68..830be20cc 100644 --- a/build/builtin_actors_gen.go +++ b/build/builtin_actors_gen.go @@ -53,14 +53,14 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet }, { Network: "butterflynet", Version: 10, - ManifestCid: MustParseCid("bafy2bzacecjs7xvhtejsh47b2tx2iwe7mbad4kxovbfs7a6wxfl47kcnl25bm"), + ManifestCid: MustParseCid("bafy2bzaced2wq4k4i2deknam6ehbynaoo37bhysud7eze7su3ftlaggwwjuje"), Actors: map[string]cid.Cid{ "account": MustParseCid("bafk2bzacebd5zetyjtragjwrv2nqktct6u2pmsi4eifbanovxohx3a7lszjxi"), "cron": MustParseCid("bafk2bzacecrszortqkc7har77ssgajglymv6ftrqvmdko5h2yqqh5k2qospl2"), "datacap": MustParseCid("bafk2bzacecapjnxnyw4talwqv5ajbtbkzmzqiosztj5cb3sortyp73ndjl76e"), - "eam": MustParseCid("bafk2bzaceavdyeveel5iohjg7t6twc2cbdo7bt3m5xajwtibekudyhzv2xojy"), + "eam": MustParseCid("bafk2bzacebsvtqzp7g7vpufbyqrwwcpuo2yu3y7kenm7auidyiwzcv6jdw724"), "ethaccount": MustParseCid("bafk2bzacedl4pmkfxkzoqajs6im3ranmopozsmxjcxsnk3kwvd3vv7mfwwrf4"), - "evm": MustParseCid("bafk2bzacebgzvmvwv7rsnnhp3zhqbiqkumvyrc7pazfovpptgpgtqkalrli74"), + "evm": MustParseCid("bafk2bzacedx5wdyaihi22pwqqqtfxmuwh5acem46mzaep3znmhh5bsuqmxogq"), "init": MustParseCid("bafk2bzacecbxp66q3ytjkg37nyv4rmzezbfaigvx4i5yhvqbm5gg4amjeaias"), "multisig": MustParseCid("bafk2bzacecjltag3mn75dsnmrmopjow27buxqhabissowayqlmavrcfetqswc"), "paymentchannel": MustParseCid("bafk2bzacednzxg263eqbl2imwz3uhujov63tjkffieyl4hl3dhrgxyhwep6hc"), @@ -132,14 +132,14 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet }, { Network: "calibrationnet", Version: 10, - ManifestCid: MustParseCid("bafy2bzaceaklxgrzd34i53rm4eeq6477nlq2ckpex27evftbsmjd2yrdbj4ba"), + ManifestCid: MustParseCid("bafy2bzacearpwvmcqlailxyq2d2wtzmtudxqhvfot77tbdqotek5qiq5hyhzg"), Actors: map[string]cid.Cid{ "account": MustParseCid("bafk2bzacea7zmrdz2rjbzlbmrmx3ko6pm3cbyqxxgogiqldsccbqffuok7m6s"), "cron": MustParseCid("bafk2bzacec7bxugi7ouh75nglycy7qwdq7e2hnku3w6yafq4fwdwvvq2mtrl2"), "datacap": MustParseCid("bafk2bzacedii4stmlo3ccdff7eevcolmgnuxy5ftkzbzwtkqa4iinlfzq4mei"), - "eam": MustParseCid("bafk2bzacea6du2tjdewnfd2zofjp342d2lw7rdl6hx4ejawup744kpym2xsf4"), + "eam": MustParseCid("bafk2bzacedykxiyewqijj5nksr7qi6o4wu5yz4rezb747ntql4rpidyfdpes4"), "ethaccount": MustParseCid("bafk2bzacecgbcbh3uk7olcfdqo44no5nxxayeqnycdznrlekqigbifor2revm"), - "evm": MustParseCid("bafk2bzaceanxhvz5czs6xfunhbysbttmim5e7poftibsu53uqn4by5nqmdaj6"), + "evm": MustParseCid("bafk2bzaceau5n66rabegik55kymni6uyk7n7jb5eymfywybs543yifpl7du2m"), "init": MustParseCid("bafk2bzacea7lxnvgxupwwgoxlmwtrca75w73qabe324wnwx43qranbgf5zdqo"), "multisig": MustParseCid("bafk2bzacear5eu5gpbjlroqkmsgpqerzc4aemp2uqcaeq7s2h4ur4ucgpzesg"), "paymentchannel": MustParseCid("bafk2bzacecwxuruxawcru7xfcx3rmt4hmhlfh4hi6jvfumerazz6jpvfmxxcw"), @@ -220,14 +220,14 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet }, { Network: "caterpillarnet", Version: 10, - ManifestCid: MustParseCid("bafy2bzaceawh5opc4uqctlzc6xnq3pb7ycchfqwprjysbfa5xlrmiicbbvkrm"), + ManifestCid: MustParseCid("bafy2bzacebxr4uvnf5g3373shjzbaca6pf4th6nnfubytjfbrlxcpvbjw4ane"), Actors: map[string]cid.Cid{ "account": MustParseCid("bafk2bzacedfms6w3ghqtljpgsfuiqa6ztjx7kcuin6myjezj6rypj3zjbqms6"), "cron": MustParseCid("bafk2bzaceaganmlpozvy4jywigs46pfrtdmhjjey6uyhpurplqbasojsislba"), "datacap": MustParseCid("bafk2bzacebafqqe3wv5ytkfwmqzbmchgem66pw6yq6rl7w6vlhqsbkxnisswq"), - "eam": MustParseCid("bafk2bzaceawl3twv7iontkiiwgezkub2vvgd7cprhv7wvgpqjpeh4o6ygshlg"), + "eam": MustParseCid("bafk2bzacedwk5eqczflcsuisqsyeomgkpg54olojjq2ieb2ozu5s45wfwluti"), "ethaccount": MustParseCid("bafk2bzaceburkmtd63nmzxpux5rcxsbqr6x5didl2ce7al32g4tqrvo4pjz2i"), - "evm": MustParseCid("bafk2bzacea7tp4lop7ivhay3ozitkmxxurk74v4zse42ant47rh2uw5z3tq5e"), + "evm": MustParseCid("bafk2bzacedbroioygjnbjtc7ykcjjs4wfbwnaa6gkzubi7c5enifoqqqu66s6"), "init": MustParseCid("bafk2bzaced23r54kwuebl7t6mdantbby5qpfduxwxfryeliof2enyqzhokix6"), "multisig": MustParseCid("bafk2bzacebcn3rib6j6jvclys7dkf62hco45ssgamczkrtzt6xyewd6gt3mtu"), "paymentchannel": MustParseCid("bafk2bzacecvas4leo44pqdguj22nnwqoqdgwajzrpm5d6ltkehc37ni6p6doq"), @@ -299,14 +299,14 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet }, { Network: "devnet", Version: 10, - ManifestCid: MustParseCid("bafy2bzacedfwwsn5weycwkqrnusc37m6ut2uf42z5qvbukl67wi76mqtgafw2"), + ManifestCid: MustParseCid("bafy2bzacebixrjysarwxdadewlllfp4rwfoejxstwdutghghei54uvuuxlsbq"), Actors: map[string]cid.Cid{ "account": MustParseCid("bafk2bzacebb5txxkfexeaxa2th3rckxsxchzyss3ijgqbicf265h7rre2rvhm"), "cron": MustParseCid("bafk2bzacecotn4gwluhamoqwnzgbg7ogehv26o5xnhjzltnzfv6utrlyanzek"), "datacap": MustParseCid("bafk2bzacea4hket2srrtbewkf3tip6ellwpxdfbrzt5u47y57i2k6iojqqgba"), - "eam": MustParseCid("bafk2bzacecrg5sjpnmk3nu3vqyegkmjnvsjoumptseuu7zabeggu745bd2kwo"), + "eam": MustParseCid("bafk2bzacecxm2gr6tevzzan6oqp6aiqydjm5b7eo34mlzo5jdm7mnlbbueikq"), "ethaccount": MustParseCid("bafk2bzacedh4y3zvtgft3i6ift4rpptgr2dx67pvenowvq7yaspuf25gqgcdc"), - "evm": MustParseCid("bafk2bzacecrjgqoozymyoplrmtpi7bmkmggiqgpbgwkzooy2a67fjivuedm6a"), + "evm": MustParseCid("bafk2bzacec26myls7vg6anr5yjbb2r75dryhdzwlwnrhjcyuhahlaoxdrua6i"), "init": MustParseCid("bafk2bzacedof2ckc6w2qboxzxv4w67njcug4ut4cq3nnlrfybzsvlgnp4kt24"), "multisig": MustParseCid("bafk2bzacec4eqajjqhl53tnkbs7glu7njlbtlditi7lxhvw33ezmxk6jae46y"), "paymentchannel": MustParseCid("bafk2bzacec6nvdprqja7dy3qp5islebbbh2ifiyg2p7arbe6pocjhfe6xwkfy"), @@ -387,14 +387,14 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet }, { Network: "hyperspace", Version: 10, - ManifestCid: MustParseCid("bafy2bzacedimb4dzty5tsyy3ucbcxai7crli452wn5cguhpmuelq74i4bffoo"), + ManifestCid: MustParseCid("bafy2bzaced6hc7ujjmypg6mkrxdmf32oh2udhmhpmwkqyxusdkxoi2uoodyxg"), Actors: map[string]cid.Cid{ "account": MustParseCid("bafk2bzacecim7uybic2qprbkjhowg7qkniv4zywj5h5g4u4ss72urco2akzuo"), "cron": MustParseCid("bafk2bzaceahgq64awp4f7li3hdgimc4upqvdvltpmeywckvens33umcxt424a"), "datacap": MustParseCid("bafk2bzacebkxn52ttooaslkwncijk3bgd3tm2zw7vijdhwvg2cxnxbrzmmq5e"), - "eam": MustParseCid("bafk2bzacedg5bnw3ic2ub4mb2agrvdowpqd7xyjv6v2ndlkugnrtjgzzfxqlw"), + "eam": MustParseCid("bafk2bzaceaftiqwpx6dcjfqxyq7pazn2p55diukf32pz74755vj7pgg5joexw"), "ethaccount": MustParseCid("bafk2bzacealn5enbxyxbfs7gbsjbyma2zk3bcr7okvflxhpr753d4eh6ixooa"), - "evm": MustParseCid("bafk2bzacedljkrmazyewawpnddrkzrt55556374dw2pm2hokgkompgzw4vx5y"), + "evm": MustParseCid("bafk2bzacea6etsvrqejjl7uej5dxlswja5gxzqyggsjjvg27timvtiedf7nsg"), "init": MustParseCid("bafk2bzacec55gyyaqjrw7zughywocgwcjvv6k5fijjpjw4xgckuqz6pjtff5a"), "multisig": MustParseCid("bafk2bzaceblozbdzybdivvjdiid4jwm2jc6x5a66sunh2vvwsqba6wzqmr7i6"), "paymentchannel": MustParseCid("bafk2bzacealcyke5a6n24efs6qe4iikynpk2twqssyugy7jcyf6p6shgw2iwa"), @@ -466,14 +466,14 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet }, { Network: "mainnet", Version: 10, - ManifestCid: MustParseCid("bafy2bzaceat4ut5xv3qn4lvvkvwvdn6gtlbnqzvueh67fjqlemw6eled5oqnc"), + ManifestCid: MustParseCid("bafy2bzacea5vylkbby7rb42fknkk4g4byhj7hkqlxp4z4urydi3vlpwsgllik"), Actors: map[string]cid.Cid{ "account": MustParseCid("bafk2bzacedsn6i2flkpk6sb4iuejo7gfl5n6fhsdawggtbsihlrrjtvs7oepu"), "cron": MustParseCid("bafk2bzacecw4guere7ba2canyi2622lw52b5qbn7iubckcp5cwlmx2kw7qqwy"), "datacap": MustParseCid("bafk2bzaceat2ncckd2jjjqcovd3ib4sylwff7jk7rlk6gr5d2gmrrc7isrmu2"), - "eam": MustParseCid("bafk2bzacebl7267zqf7aubpl7n6ligulayhz65dpgn3ii26b3wwjwytlsdc3i"), + "eam": MustParseCid("bafk2bzacebbpu5smjrjqpkrvvlhcpk23yvlovlndqmwzhfz5kuuph54tdw732"), "ethaccount": MustParseCid("bafk2bzacedmwzkbytxfn7exmxxosomvix4mpyxrmupeqw45aofqmdq5q7mgqe"), - "evm": MustParseCid("bafk2bzacecrrwixyqwphxaybhy5zxuawkhncq5tgtuz2ind4bl22oivzjidoq"), + "evm": MustParseCid("bafk2bzacechkf43lmddynxmc35hvz5kwr3fdxrbg6fxbcvysfsihgiopbrb7o"), "init": MustParseCid("bafk2bzacec6276d7ls3hhuqibqorn3yp45mv7hroczf3bgb6jkhmbb2zqt3bw"), "multisig": MustParseCid("bafk2bzaceahggxrnjj3w3cgtko54srssqyhcs4x6y55ytego6jf2owg5piw3y"), "paymentchannel": MustParseCid("bafk2bzaceaobaqjamso57bkjv3n4ilv7lfropgrncnnej666w3tegmr4cfgve"), @@ -545,14 +545,14 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet }, { Network: "testing", Version: 10, - ManifestCid: MustParseCid("bafy2bzacearh2dy6uzcfvruckai5qbf7banklkg6uezaa7w6onsmdfxn2qxbs"), + ManifestCid: MustParseCid("bafy2bzacea7tbn4p232ecrjvlp2uvpci5pexqjqq2vpv4t5ihktpja2zsj3ek"), Actors: map[string]cid.Cid{ "account": MustParseCid("bafk2bzaceds3iy5qjgr3stoywxt4uxvhybca23q7d2kxhitedgudrkhxaxa6o"), "cron": MustParseCid("bafk2bzacebxp4whb4ocqxnbvqlz3kckarabtyvhjbhqvrdwhejuffwactyiss"), "datacap": MustParseCid("bafk2bzacedepm3zas6vqryruwiz7d3axkneo7v66q65gf2dlpfd53pjlycrg4"), - "eam": MustParseCid("bafk2bzacedl4q6l3m5uvunuviwlxicyweszrahipxfpf3nt6wspvcdi4ryzyk"), + "eam": MustParseCid("bafk2bzacea2uascrtv6xnsqlxyf3tcf4onpgrs7frh55p6dnrdeum2uup7wx4"), "ethaccount": MustParseCid("bafk2bzacecbhz4ipg773lsovgpjysm6fxl2i7y2wuxadqnt4s4vm3nd2qodb4"), - "evm": MustParseCid("bafk2bzaced5efc2bi7ulqsep4ej74hxwbjap2qi7lojiqzfsowxr4kylkwzk6"), + "evm": MustParseCid("bafk2bzaceabwn4i62od3i4qkuj5zx4vn5w5cbcl53tqnszk6kl43bfl55hl6c"), "init": MustParseCid("bafk2bzacebqym5i5eciyyyzsimu73z6bkffpm5hzjpx3gwcm64pm2fh7okrja"), "multisig": MustParseCid("bafk2bzacecmlyngek7qvj5ezaaitadrycapup3mbty4ijlzun6g23tcoysxle"), "paymentchannel": MustParseCid("bafk2bzacedspin4hxpgnxkjen3hsxpcc52oc5q4ypukl4qq6vaytcgmmi7hl4"), @@ -624,14 +624,14 @@ var EmbeddedBuiltinActorsMetadata []*BuiltinActorsMetadata = []*BuiltinActorsMet }, { Network: "testing-fake-proofs", Version: 10, - ManifestCid: MustParseCid("bafy2bzacedw6kk3u2vjexzqmm3vtvusd42lllk7wbnsrlxxmt35smsnmiatca"), + ManifestCid: MustParseCid("bafy2bzacecyqfyzmw72234rvbk6vzq2omnmt3cbfezkq2h3ewnn33w42b2s62"), Actors: map[string]cid.Cid{ "account": MustParseCid("bafk2bzaceds3iy5qjgr3stoywxt4uxvhybca23q7d2kxhitedgudrkhxaxa6o"), "cron": MustParseCid("bafk2bzacebxp4whb4ocqxnbvqlz3kckarabtyvhjbhqvrdwhejuffwactyiss"), "datacap": MustParseCid("bafk2bzacedepm3zas6vqryruwiz7d3axkneo7v66q65gf2dlpfd53pjlycrg4"), - "eam": MustParseCid("bafk2bzacedl4q6l3m5uvunuviwlxicyweszrahipxfpf3nt6wspvcdi4ryzyk"), + "eam": MustParseCid("bafk2bzacea2uascrtv6xnsqlxyf3tcf4onpgrs7frh55p6dnrdeum2uup7wx4"), "ethaccount": MustParseCid("bafk2bzacecbhz4ipg773lsovgpjysm6fxl2i7y2wuxadqnt4s4vm3nd2qodb4"), - "evm": MustParseCid("bafk2bzaced5efc2bi7ulqsep4ej74hxwbjap2qi7lojiqzfsowxr4kylkwzk6"), + "evm": MustParseCid("bafk2bzaceabwn4i62od3i4qkuj5zx4vn5w5cbcl53tqnszk6kl43bfl55hl6c"), "init": MustParseCid("bafk2bzacebqym5i5eciyyyzsimu73z6bkffpm5hzjpx3gwcm64pm2fh7okrja"), "multisig": MustParseCid("bafk2bzacecmlyngek7qvj5ezaaitadrycapup3mbty4ijlzun6g23tcoysxle"), "paymentchannel": MustParseCid("bafk2bzacedspin4hxpgnxkjen3hsxpcc52oc5q4ypukl4qq6vaytcgmmi7hl4"), diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 7058771b9..e1dc3762d 100644 Binary files a/build/openrpc/full.json.gz and b/build/openrpc/full.json.gz differ diff --git a/build/openrpc/gateway.json.gz b/build/openrpc/gateway.json.gz index 0b78bf471..73cfe7a50 100644 Binary files a/build/openrpc/gateway.json.gz and b/build/openrpc/gateway.json.gz differ diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 87d122f39..e15fb18aa 100644 Binary files a/build/openrpc/miner.json.gz and b/build/openrpc/miner.json.gz differ diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index a0c275004..e84f7f5d1 100644 Binary files a/build/openrpc/worker.json.gz and b/build/openrpc/worker.json.gz differ diff --git a/chain/store/snapshot.go b/chain/store/snapshot.go index f9e65f4bf..3c264d192 100644 --- a/chain/store/snapshot.go +++ b/chain/store/snapshot.go @@ -22,6 +22,8 @@ import ( "github.com/filecoin-project/lotus/chain/types" ) +const TIPSETKEY_BACKFILL_RANGE = 2 * build.Finality + func (cs *ChainStore) UnionStore() bstore.Blockstore { return bstore.Union(cs.stateBlockstore, cs.chainBlockstore) } @@ -113,6 +115,20 @@ func (cs *ChainStore) Import(ctx context.Context, r io.Reader) (*types.TipSet, e return nil, xerrors.Errorf("failed to load root tipset from chainfile: %w", err) } + ts := root + for i := 0; i < int(TIPSETKEY_BACKFILL_RANGE); i++ { + err = cs.PersistTipset(ctx, ts) + if err != nil { + return nil, err + } + parentTsKey := ts.Parents() + ts, err = cs.LoadTipSet(ctx, parentTsKey) + if ts == nil || err != nil { + log.Warnf("Only able to load the last %d tipsets", i) + break + } + } + return root, nil } diff --git a/chain/store/store.go b/chain/store/store.go index 9ab08c74f..5ed037ee5 100644 --- a/chain/store/store.go +++ b/chain/store/store.go @@ -1097,6 +1097,10 @@ func (cs *ChainStore) StateBlockstore() bstore.Blockstore { return cs.stateBlockstore } +func (cs *ChainStore) ChainLocalBlockstore() bstore.Blockstore { + return cs.chainLocalBlockstore +} + func ActorStore(ctx context.Context, bs bstore.Blockstore) adt.Store { return adt.WrapStore(ctx, cbor.NewCborStore(bs)) } diff --git a/chain/store/store_test.go b/chain/store/store_test.go index 6dc340737..89d0caa2c 100644 --- a/chain/store/store_test.go +++ b/chain/store/store_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/ipfs/go-datastore" + "github.com/stretchr/testify/require" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/crypto" @@ -124,6 +125,51 @@ func TestChainExportImport(t *testing.T) { } } +// Test to check if tipset key cids are being stored on snapshot +func TestChainImportTipsetKeyCid(t *testing.T) { + + ctx := context.Background() + cg, err := gen.NewGenerator() + require.NoError(t, err) + + buf := new(bytes.Buffer) + var last *types.TipSet + var tsKeys []types.TipSetKey + for i := 0; i < 10; i++ { + ts, err := cg.NextTipSet() + require.NoError(t, err) + last = ts.TipSet.TipSet() + tsKeys = append(tsKeys, last.Key()) + } + + if err := cg.ChainStore().Export(ctx, last, last.Height(), false, buf); err != nil { + t.Fatal(err) + } + + nbs := blockstore.NewMemorySync() + cs := store.NewChainStore(nbs, nbs, datastore.NewMapDatastore(), filcns.Weight, nil) + defer cs.Close() //nolint:errcheck + + root, err := cs.Import(ctx, buf) + require.NoError(t, err) + + require.Truef(t, root.Equals(last), "imported chain differed from exported chain") + + err = cs.SetHead(ctx, last) + require.NoError(t, err) + + for _, tsKey := range tsKeys { + _, err := cs.LoadTipSet(ctx, tsKey) + require.NoError(t, err) + + tsCid, err := tsKey.Cid() + require.NoError(t, err) + _, err = cs.ChainLocalBlockstore().Get(ctx, tsCid) + require.NoError(t, err) + + } +} + func TestChainExportImportFull(t *testing.T) { //stm: @CHAIN_GEN_NEXT_TIPSET_001 //stm: @CHAIN_STORE_IMPORT_001, @CHAIN_STORE_EXPORT_001, @CHAIN_STORE_SET_HEAD_001 diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index 1265f7c42..9be56b756 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -83,6 +83,7 @@ * [EthGetFilterChanges](#EthGetFilterChanges) * [EthGetFilterLogs](#EthGetFilterLogs) * [EthGetLogs](#EthGetLogs) + * [EthGetMessageCidByTransactionHash](#EthGetMessageCidByTransactionHash) * [EthGetStorageAt](#EthGetStorageAt) * [EthGetTransactionByBlockHashAndIndex](#EthGetTransactionByBlockHashAndIndex) * [EthGetTransactionByBlockNumberAndIndex](#EthGetTransactionByBlockNumberAndIndex) @@ -2641,6 +2642,25 @@ Response: ] ``` +### EthGetMessageCidByTransactionHash + + +Perms: read + +Inputs: +```json +[ + "0x37690cfec6c1bf4c3b9288c7a5d783e98731e90b0a4c177c2a374c7a9427355e" +] +``` + +Response: +```json +{ + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" +} +``` + ### EthGetStorageAt diff --git a/itests/eth_hash_lookup_test.go b/itests/eth_hash_lookup_test.go index 37948c768..bad705fe1 100644 --- a/itests/eth_hash_lookup_test.go +++ b/itests/eth_hash_lookup_test.go @@ -338,3 +338,261 @@ func TestTransactionHashLookupSecpFilecoinMessage(t *testing.T) { require.NotNil(t, chainTx.TransactionIndex) require.Equal(t, uint64(*chainTx.TransactionIndex), uint64(0)) // only transaction } + +// TestTransactionHashLookupSecpFilecoinMessage tests to see if lotus can find a Secp Filecoin Message using the transaction hash +func TestTransactionHashLookupNonexistentMessage(t *testing.T) { + kit.QuietMiningLogs() + + blocktime := 1 * time.Second + client, _, ens := kit.EnsembleMinimal( + t, + kit.MockProofs(), + kit.ThroughRPC(), + kit.EthTxHashLookup(), + ) + ens.InterconnectAll().BeginMining(blocktime) + + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + cid := build.MustParseCid("bafk2bzacecapjnxnyw4talwqv5ajbtbkzmzqiosztj5cb3sortyp73ndjl76e") + + // We shouldn't be able to return a hash for this fake cid + chainHash, err := client.EthGetTransactionHashByCid(ctx, cid) + require.NoError(t, err) + require.Nil(t, chainHash) + + calculatedHash, err := ethtypes.EthHashFromCid(cid) + require.NoError(t, err) + + // We shouldn't be able to return a cid for this fake hash + chainCid, err := client.EthGetMessageCidByTransactionHash(ctx, &calculatedHash) + require.NoError(t, err) + require.Nil(t, chainCid) +} + +func TestEthGetMessageCidByTransactionHashEthTx(t *testing.T) { + kit.QuietMiningLogs() + + blocktime := 1 * time.Second + client, _, ens := kit.EnsembleMinimal( + t, + kit.MockProofs(), + kit.ThroughRPC(), + kit.EthTxHashLookup(), + ) + ens.InterconnectAll().BeginMining(blocktime) + + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + // install contract + contractHex, err := os.ReadFile("./contracts/SimpleCoin.hex") + require.NoError(t, err) + + contract, err := hex.DecodeString(string(contractHex)) + require.NoError(t, err) + + // create a new Ethereum account + key, ethAddr, deployer := client.EVM().NewAccount() + + // send some funds to the f410 address + kit.SendFunds(ctx, t, client, deployer, types.FromFil(10)) + + gaslimit, err := client.EthEstimateGas(ctx, ethtypes.EthCall{ + From: ðAddr, + Data: contract, + }) + require.NoError(t, err) + + maxPriorityFeePerGas, err := client.EthMaxPriorityFeePerGas(ctx) + require.NoError(t, err) + + // now deploy a contract from the embryo, and validate it went well + tx := ethtypes.EthTxArgs{ + ChainID: build.Eip155ChainId, + Value: big.Zero(), + Nonce: 0, + MaxFeePerGas: types.NanoFil, + MaxPriorityFeePerGas: big.Int(maxPriorityFeePerGas), + GasLimit: int(gaslimit), + Input: contract, + V: big.Zero(), + R: big.Zero(), + S: big.Zero(), + } + + client.EVM().SignTransaction(&tx, key.PrivateKey) + + sender, err := tx.Sender() + require.NoError(t, err) + + unsignedMessage, err := tx.ToUnsignedMessage(sender) + require.NoError(t, err) + + rawTxHash, err := tx.TxHash() + require.NoError(t, err) + + hash := client.EVM().SubmitTransaction(ctx, &tx) + require.Equal(t, rawTxHash, hash) + + mpoolCid, err := client.EthGetMessageCidByTransactionHash(ctx, &hash) + require.NoError(t, err) + require.NotNil(t, mpoolCid) + + mpoolTx, err := client.ChainGetMessage(ctx, *mpoolCid) + require.NoError(t, err) + require.NotNil(t, mpoolTx) + require.Equal(t, *unsignedMessage, *mpoolTx) + + // Wait for message to land on chain + var receipt *api.EthTxReceipt + for i := 0; i < 20; i++ { + receipt, err = client.EthGetTransactionReceipt(ctx, hash) + if err != nil || receipt == nil { + time.Sleep(blocktime) + continue + } + break + } + require.NoError(t, err) + require.NotNil(t, receipt) + + chainCid, err := client.EthGetMessageCidByTransactionHash(ctx, &hash) + require.NoError(t, err) + require.NotNil(t, chainCid) + + chainTx, err := client.ChainGetMessage(ctx, *mpoolCid) + require.NoError(t, err) + require.NotNil(t, chainTx) + require.Equal(t, *unsignedMessage, *chainTx) +} + +func TestEthGetMessageCidByTransactionHashSecp(t *testing.T) { + kit.QuietMiningLogs() + + blocktime := 1 * time.Second + client, _, ens := kit.EnsembleMinimal( + t, + kit.MockProofs(), + kit.ThroughRPC(), + kit.EthTxHashLookup(), + ) + ens.InterconnectAll().BeginMining(blocktime) + + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + // get the existing balance from the default wallet to then split it. + bal, err := client.WalletBalance(ctx, client.DefaultKey.Address) + require.NoError(t, err) + + // create a new address where to send funds. + addr, err := client.WalletNew(ctx, types.KTSecp256k1) + require.NoError(t, err) + + toSend := big.Div(bal, big.NewInt(2)) + setupMsg := &types.Message{ + From: client.DefaultKey.Address, + To: addr, + Value: toSend, + } + + setupSmsg, err := client.MpoolPushMessage(ctx, setupMsg, nil) + require.NoError(t, err) + + _, err = client.StateWaitMsg(ctx, setupSmsg.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + + // Send message for secp account + secpMsg := &types.Message{ + From: addr, + To: client.DefaultKey.Address, + Value: big.Div(toSend, big.NewInt(2)), + } + + secpSmsg, err := client.MpoolPushMessage(ctx, secpMsg, nil) + require.NoError(t, err) + + hash, err := ethtypes.EthHashFromCid(secpSmsg.Cid()) + require.NoError(t, err) + + mpoolCid, err := client.EthGetMessageCidByTransactionHash(ctx, &hash) + require.NoError(t, err) + require.NotNil(t, mpoolCid) + + mpoolTx, err := client.ChainGetMessage(ctx, *mpoolCid) + require.NoError(t, err) + require.NotNil(t, mpoolTx) + require.Equal(t, secpSmsg.Message, *mpoolTx) + + _, err = client.StateWaitMsg(ctx, secpSmsg.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + + chainCid, err := client.EthGetMessageCidByTransactionHash(ctx, &hash) + require.NoError(t, err) + require.NotNil(t, chainCid) + + chainTx, err := client.ChainGetMessage(ctx, *mpoolCid) + require.NoError(t, err) + require.NotNil(t, chainTx) + require.Equal(t, secpSmsg.Message, *chainTx) +} + +func TestEthGetMessageCidByTransactionHashBLS(t *testing.T) { + kit.QuietMiningLogs() + + blocktime := 1 * time.Second + client, _, ens := kit.EnsembleMinimal( + t, + kit.MockProofs(), + kit.ThroughRPC(), + kit.EthTxHashLookup(), + ) + ens.InterconnectAll().BeginMining(blocktime) + + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + // get the existing balance from the default wallet to then split it. + bal, err := client.WalletBalance(ctx, client.DefaultKey.Address) + require.NoError(t, err) + + // create a new address where to send funds. + addr, err := client.WalletNew(ctx, types.KTBLS) + require.NoError(t, err) + + toSend := big.Div(bal, big.NewInt(2)) + msg := &types.Message{ + From: client.DefaultKey.Address, + To: addr, + Value: toSend, + } + + sm, err := client.MpoolPushMessage(ctx, msg, nil) + require.NoError(t, err) + + hash, err := ethtypes.EthHashFromCid(sm.Cid()) + require.NoError(t, err) + + mpoolCid, err := client.EthGetMessageCidByTransactionHash(ctx, &hash) + require.NoError(t, err) + require.NotNil(t, mpoolCid) + + mpoolTx, err := client.ChainGetMessage(ctx, *mpoolCid) + require.NoError(t, err) + require.NotNil(t, mpoolTx) + require.Equal(t, sm.Message, *mpoolTx) + + _, err = client.StateWaitMsg(ctx, sm.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(t, err) + + chainCid, err := client.EthGetMessageCidByTransactionHash(ctx, &hash) + require.NoError(t, err) + require.NotNil(t, chainCid) + + chainTx, err := client.ChainGetMessage(ctx, *mpoolCid) + require.NoError(t, err) + require.NotNil(t, chainTx) + require.Equal(t, sm.Message, *chainTx) +} diff --git a/node/config/def.go b/node/config/def.go index cc301b276..12efc408f 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -109,6 +109,7 @@ func DefaultFullNode() *FullNode { }, Fevm: FevmConfig{ EnableEthHashToFilecoinCidMapping: false, + EthTxHashMappingLifetimeDays: 0, }, } } diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index 7b35c5206..755aacba1 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -45,6 +45,7 @@ type EthModuleAPI interface { EthGetBlockByHash(ctx context.Context, blkHash ethtypes.EthHash, fullTxInfo bool) (ethtypes.EthBlock, error) EthGetBlockByNumber(ctx context.Context, blkNum string, fullTxInfo bool) (ethtypes.EthBlock, error) EthGetTransactionByHash(ctx context.Context, txHash *ethtypes.EthHash) (*ethtypes.EthTx, error) + EthGetMessageCidByTransactionHash(ctx context.Context, txHash *ethtypes.EthHash) (*cid.Cid, error) EthGetTransactionHashByCid(ctx context.Context, cid cid.Cid) (*ethtypes.EthHash, error) EthGetTransactionCount(ctx context.Context, sender ethtypes.EthAddress, blkOpt string) (ethtypes.EthUint64, error) EthGetTransactionReceipt(ctx context.Context, txHash ethtypes.EthHash) (*api.EthTxReceipt, error) @@ -299,8 +300,53 @@ func (a *EthModule) EthGetTransactionByHash(ctx context.Context, txHash *ethtype return nil, nil } +func (a *EthModule) EthGetMessageCidByTransactionHash(ctx context.Context, txHash *ethtypes.EthHash) (*cid.Cid, error) { + // Ethereum's behavior is to return null when the txHash is invalid, so we use nil to check if txHash is valid + if txHash == nil { + return nil, nil + } + + c := cid.Undef + if a.EthTxHashManager != nil { + var err error + c, err = a.EthTxHashManager.TransactionHashLookup.GetCidFromHash(*txHash) + // We fall out of the first condition and continue + if errors.Is(err, ethhashlookup.ErrNotFound) { + log.Debug("could not find transaction hash %s in lookup table", txHash.String()) + } else if err != nil { + return nil, xerrors.Errorf("database error: %w", err) + } else { + return &c, nil + } + } + // This isn't an eth transaction we have the mapping for, so let's try looking it up as a filecoin message + if c == cid.Undef { + c = txHash.ToCid() + } + + _, err := a.StateAPI.Chain.GetSignedMessage(ctx, c) + if err == nil { + // This is an Eth Tx, Secp message, Or BLS message in the mpool + return &c, nil + } + + _, err = a.StateAPI.Chain.GetMessage(ctx, c) + if err == nil { + // This is a BLS message + return &c, nil + } + + // Ethereum clients expect an empty response when the message was not found + return nil, nil +} + func (a *EthModule) EthGetTransactionHashByCid(ctx context.Context, cid cid.Cid) (*ethtypes.EthHash, error) { hash, err := EthTxHashFromFilecoinMessageCid(ctx, cid, a.StateAPI) + if hash == ethtypes.EmptyEthHash { + // not found + return nil, nil + } + return &hash, err } @@ -1483,10 +1529,17 @@ func lookupEthAddress(ctx context.Context, addr address.Address, sa StateAPI) (e func EthTxHashFromFilecoinMessageCid(ctx context.Context, c cid.Cid, sa StateAPI) (ethtypes.EthHash, error) { smsg, err := sa.Chain.GetSignedMessage(ctx, c) if err == nil { + // This is an Eth Tx, Secp message, Or BLS message in the mpool return EthTxHashFromSignedFilecoinMessage(ctx, smsg, sa) } - return ethtypes.EthHashFromCid(c) + _, err = sa.Chain.GetMessage(ctx, c) + if err == nil { + // This is a BLS message + return ethtypes.EthHashFromCid(c) + } + + return ethtypes.EmptyEthHash, nil } func EthTxHashFromSignedFilecoinMessage(ctx context.Context, smsg *types.SignedMessage, sa StateAPI) (ethtypes.EthHash, error) {