diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c2ae81a51a..cf4d73178ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - https://github.com/filecoin-project/lotus/pull/12221: Fix a nil reference panic in the ETH Trace API - https://github.com/filecoin-project/lotus/pull/12112: Moved consts from build/ to build/buildconstants/ for ligher curio deps. - https://github.com/filecoin-project/lotus/pull/12237: Upgrade to go-f3 `v0.0.4`. +- https://github.com/filecoin-project/lotus/pull/12269 Fix `logIndex` ordering in `EthGetTransactionReceipt` by using the EventIndex to fetch logs ## ☢️ Upgrade Warnings ☢️ diff --git a/itests/contracts/MultipleEvents.hex b/itests/contracts/MultipleEvents.hex new file mode 100644 index 00000000000..355e547f8d4 --- /dev/null +++ b/itests/contracts/MultipleEvents.hex @@ -0,0 +1 @@ +6080604052348015600e575f80fd5b5061058b8061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c806305734db71461003857806398e8da0014610054575b5f80fd5b610052600480360381019061004d91906102c0565b61005e565b005b61005c61013a565b005b8173ffffffffffffffffffffffffffffffffffffffff167fd76645dad5a7864a79954383dacf5c3f9cf3bf86d0a21241fcbae7b08cbbcb9660405160405180910390a2807f42d45d4e904b929a49443ad704c27633daae11d6ff7a0d0dedc9dbe70004d7d76040516100cf90610358565b60405180910390a27f5c362dbc3ba7b340d21482342acacf25f578611b2e5a4f136ff1a280ac0d9408828260405160200161010b9291906103db565b6040516020818303038152906040528051906020012060405161012e919061041e565b60405180910390a15050565b3373ffffffffffffffffffffffffffffffffffffffff167fb30247b59cead5e1c696f81be8486379fbc9d20feae266f6df16fcc2143ad355426040516101809190610446565b60405180910390a27f0c49df121e06fc3a0f60cfc2c9b92fce5c5232e223b63a51a780d4e8aae0132d6040516101b5906104a9565b60405180910390a17f38ee5a08acae32a0ccec0eef68b73ba44f4b09e2f3df37062af8e885a7fd23af602a6040516101ed9190610509565b60405180910390a17fd0916c673494f5a60c9f5d12c864ebec8398c930a7f2b57e0665c2feb63448846001604051610225919061053c565b60405180910390a1565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61025c82610233565b9050919050565b61026c81610252565b8114610276575f80fd5b50565b5f8135905061028781610263565b92915050565b5f819050919050565b61029f8161028d565b81146102a9575f80fd5b50565b5f813590506102ba81610296565b92915050565b5f80604083850312156102d6576102d561022f565b5b5f6102e385828601610279565b92505060206102f4858286016102ac565b9150509250929050565b5f82825260208201905092915050565b7f5468726565206576656e74732066756e6374696f6e2063616c6c6564000000005f82015250565b5f610342601c836102fe565b915061034d8261030e565b602082019050919050565b5f6020820190508181035f83015261036f81610336565b9050919050565b5f8160601b9050919050565b5f61038c82610376565b9050919050565b5f61039d82610382565b9050919050565b6103b56103b082610252565b610393565b82525050565b5f819050919050565b6103d56103d08261028d565b6103bb565b82525050565b5f6103e682856103a4565b6014820191506103f682846103c4565b6020820191508190509392505050565b5f819050919050565b61041881610406565b82525050565b5f6020820190506104315f83018461040f565b92915050565b6104408161028d565b82525050565b5f6020820190506104595f830184610437565b92915050565b7f466f7572206576656e74732066756e6374696f6e2063616c6c656400000000005f82015250565b5f610493601b836102fe565b915061049e8261045f565b602082019050919050565b5f6020820190508181035f8301526104c081610487565b9050919050565b5f819050919050565b5f819050919050565b5f6104f36104ee6104e9846104c7565b6104d0565b61028d565b9050919050565b610503816104d9565b82525050565b5f60208201905061051c5f8301846104fa565b92915050565b5f8115159050919050565b61053681610522565b82525050565b5f60208201905061054f5f83018461052d565b9291505056fea26469706673582212207d4001220d45b88d2efb387a0bb0c06f00739212df2c528db0db9850a48046c064736f6c63430008190033 \ No newline at end of file diff --git a/itests/contracts/MultipleEvents.sol b/itests/contracts/MultipleEvents.sol new file mode 100644 index 00000000000..57ae602ced9 --- /dev/null +++ b/itests/contracts/MultipleEvents.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; + +contract MultipleEventEmitter { + // Define events + event Event1(address indexed sender, uint256 timestamp); + event Event2(string message); + event Event3(uint256 value); + event Event4(bool flag); + event Event5(address indexed recipient); + event Event6(uint256 indexed id, string data); + event Event7(bytes32 hash); + + // Function that emits four events + function emitFourEvents() public { + emit Event1(msg.sender, block.timestamp); + emit Event2("Four events function called"); + emit Event3(42); + emit Event4(true); + } + + // Function that emits three events + function emitThreeEvents(address _recipient, uint256 _id) public { + emit Event5(_recipient); + emit Event6(_id, "Three events function called"); + emit Event7(keccak256(abi.encodePacked(_recipient, _id))); + } +} \ No newline at end of file diff --git a/itests/eth_filter_test.go b/itests/eth_filter_test.go index 1b4366d6eee..16991069c9c 100644 --- a/itests/eth_filter_test.go +++ b/itests/eth_filter_test.go @@ -26,6 +26,7 @@ import ( "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types/ethtypes" @@ -509,6 +510,20 @@ func TestEthGetLogsBasic(t *testing.T) { elogs, err := parseEthLogsFromFilterResult(res) require.NoError(err) AssertEthLogs(t, elogs, expected, received) + + require.Len(elogs, 1) + rct, err := client.EthGetTransactionReceipt(ctx, elogs[0].TransactionHash) + require.NoError(err) + require.NotNil(rct) + + require.Len(rct.Logs, 1) + var rctLogs []*ethtypes.EthLog + for _, rctLog := range rct.Logs { + addr := &rctLog + rctLogs = append(rctLogs, addr) + } + + AssertEthLogs(t, rctLogs, expected, received) } func TestEthSubscribeLogsNoTopicSpec(t *testing.T) { @@ -622,6 +637,145 @@ func TestTxReceiptBloom(t *testing.T) { require.Equal(t, 6, bitsSet) } +func TestMultipleEvents(t *testing.T) { + blockTime := 500 * time.Millisecond + client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC()) + + ens.InterconnectAll().BeginMining(blockTime) + + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + // 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)) + + // DEPLOY CONTRACT + tx := deployContractWithEthTx(ctx, t, client, ethAddr, "./contracts/MultipleEvents.hex") + + client.EVM().SignTransaction(tx, key.PrivateKey) + hash := client.EVM().SubmitTransaction(ctx, tx) + + receipt, err := client.EVM().WaitTransaction(ctx, hash) + require.NoError(t, err) + require.NotNil(t, receipt) + require.EqualValues(t, ethtypes.EthUint64(0x1), receipt.Status) + + // invoke function to emit four events + contractAddr := client.EVM().ComputeContractAddress(ethAddr, 0) + + // https://abi.hashex.org/ + params4Events, err := hex.DecodeString("98e8da00") + require.NoError(t, err) + + params3Events, err := hex.DecodeString("05734db70000000000000000000000001cd1eeecac00fe01f9d11803e48c15c478fe1d22000000000000000000000000000000000000000000000000000000000000000b") + require.NoError(t, err) + + gasParams, err := json.Marshal(ethtypes.EthEstimateGasParams{Tx: ethtypes.EthCall{ + From: ðAddr, + To: &contractAddr, + Data: params4Events, + }}) + require.NoError(t, err) + + gaslimit, err := client.EthEstimateGas(ctx, gasParams) + require.NoError(t, err) + + maxPriorityFeePerGas, err := client.EthMaxPriorityFeePerGas(ctx) + require.NoError(t, err) + + paramsArray := [][]byte{params4Events, params3Events, params3Events} + + var receipts []*api.EthTxReceipt + var hashes []ethtypes.EthHash + + nonce := 1 + for { + receipts = nil + hashes = nil + + for _, params := range paramsArray { + invokeTx := ethtypes.Eth1559TxArgs{ + ChainID: build.Eip155ChainId, + To: &contractAddr, + Value: big.Zero(), + Nonce: nonce, + MaxFeePerGas: types.NanoFil, + MaxPriorityFeePerGas: big.Int(maxPriorityFeePerGas), + GasLimit: int(gaslimit), + Input: params, + V: big.Zero(), + R: big.Zero(), + S: big.Zero(), + } + + // Submit transaction with valid signature + client.EVM().SignTransaction(&invokeTx, key.PrivateKey) + hash := client.EVM().SubmitTransaction(ctx, &invokeTx) + hashes = append(hashes, hash) + nonce++ + require.True(t, nonce <= 10, "tried too many times to land messages in same tipset") + } + + for _, hash := range hashes { + receipt, err := client.EVM().WaitTransaction(ctx, hash) + require.NoError(t, err) + require.NotNil(t, receipt) + receipts = append(receipts, receipt) + } + + // Check if all receipts are in the same tipset + allInSameTipset := true + for i := 1; i < len(receipts); i++ { + if receipts[i].BlockHash != receipts[0].BlockHash { + allInSameTipset = false + break + } + } + + if allInSameTipset { + break + } + } + + // Assert that first receipt has 4 event logs and the other two have 3 each + require.Equal(t, 4, len(receipts[0].Logs), "First transaction should have 4 event logs") + require.Equal(t, 3, len(receipts[1].Logs), "Second transaction should have 3 event logs") + require.Equal(t, 3, len(receipts[2].Logs), "Third transaction should have 3 event logs") + + // Iterate over all logs in all receipts and assert that the logIndex field is numbered from 0 to 9 + expectedLogIndex := 0 + var receiptLogs []ethtypes.EthLog + for _, receipt := range receipts { + for _, log := range receipt.Logs { + require.Equal(t, ethtypes.EthUint64(expectedLogIndex), log.LogIndex, "LogIndex should be sequential") + expectedLogIndex++ + receiptLogs = append(receiptLogs, log) + } + } + require.Equal(t, 10, expectedLogIndex, "Total number of logs should be 10") + + // assert that all logs match b/w ethGetLogs and receipts + res, err := client.EthGetLogs(ctx, ðtypes.EthFilterSpec{ + BlockHash: &receipts[0].BlockHash, + }) + require.NoError(t, err) + + logs, err := parseEthLogsFromFilterResult(res) + // Convert []*EthLog to []EthLog + ethLogs := make([]ethtypes.EthLog, len(logs)) + for i, log := range logs { + if log != nil { + ethLogs[i] = *log + } + } + require.NoError(t, err) + require.Equal(t, 10, len(logs), "Total number of logs should be 10") + + require.Equal(t, receiptLogs, ethLogs, "Logs from ethGetLogs and receipts should match") +} + func TestEthGetLogs(t *testing.T) { require := require.New(t) kit.QuietAllLogsExcept("events", "messagepool") @@ -649,6 +803,20 @@ func TestEthGetLogs(t *testing.T) { elogs, err := parseEthLogsFromFilterResult(res) require.NoError(err) AssertEthLogs(t, elogs, tc.expected, messages) + + for _, elog := range elogs { + rct, err := client.EthGetTransactionReceipt(ctx, elog.TransactionHash) + require.NoError(err) + require.NotNil(rct) + require.Len(rct.Logs, 1) + require.EqualValues(rct.Logs[0].LogIndex, elog.LogIndex) + require.EqualValues(rct.Logs[0].BlockNumber, elog.BlockNumber) + require.EqualValues(rct.Logs[0].TransactionIndex, elog.TransactionIndex) + require.EqualValues(rct.Logs[0].TransactionHash, elog.TransactionHash) + require.EqualValues(rct.Logs[0].Data, elog.Data) + require.EqualValues(rct.Logs[0].Topics, elog.Topics) + require.EqualValues(rct.Logs[0].Address, elog.Address) + } }) } } @@ -2349,3 +2517,42 @@ func unpackUint64Values(data []byte) []uint64 { } return vals } + +// deployContractWithEthTx returns an Ethereum transaction that can be used to deploy the smart contract at "contractPath" on chain +// It is different from `DeployContractFromFilename` because it used an Ethereum transaction to deploy the contract whereas the +// latter uses a FIL transaction. +func deployContractWithEthTx(ctx context.Context, t *testing.T, client *kit.TestFullNode, ethAddr ethtypes.EthAddress, + contractPath string) *ethtypes.Eth1559TxArgs { + // install contract + contractHex, err := os.ReadFile(contractPath) + require.NoError(t, err) + + contract, err := hex.DecodeString(string(contractHex)) + require.NoError(t, err) + + gasParams, err := json.Marshal(ethtypes.EthEstimateGasParams{Tx: ethtypes.EthCall{ + From: ðAddr, + Data: contract, + }}) + require.NoError(t, err) + + gaslimit, err := client.EthEstimateGas(ctx, gasParams) + 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 + return ðtypes.Eth1559TxArgs{ + 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(), + } +} diff --git a/node/builder_chain.go b/node/builder_chain.go index 23b16a12fd4..882ad25ef90 100644 --- a/node/builder_chain.go +++ b/node/builder_chain.go @@ -255,8 +255,9 @@ func ConfigFullNode(c interface{}) Option { // in lite-mode Eth api is provided by gateway ApplyIf(isFullNode, If(cfg.Fevm.EnableEthRPC, + Override(new(*full.EthEventHandler), modules.EthEventHandler(cfg.Events, cfg.Fevm.EnableEthRPC)), Override(new(full.EthModuleAPI), modules.EthModuleAPI(cfg.Fevm)), - Override(new(full.EthEventAPI), modules.EthEventHandler(cfg.Events, cfg.Fevm.EnableEthRPC)), + Override(new(full.EthEventAPI), From(new(*full.EthEventHandler))), ), If(!cfg.Fevm.EnableEthRPC, Override(new(full.EthModuleAPI), &full.EthModuleDummy{}), diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index 129b89c3cd9..8c5c4eb003d 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -135,6 +135,7 @@ type EthModule struct { Mpool *messagepool.MessagePool StateManager *stmgr.StateManager EthTxHashManager *EthTxHashManager + EthEventHandler *EthEventHandler ChainAPI MpoolAPI @@ -432,7 +433,7 @@ func (a *EthModule) EthGetTransactionReceiptLimited(ctx context.Context, txHash return nil, xerrors.Errorf("failed to convert %s into an Eth Txn: %w", txHash, err) } - receipt, err := newEthTxReceipt(ctx, tx, msgLookup, a.ChainAPI, a.StateAPI) + receipt, err := newEthTxReceipt(ctx, tx, msgLookup, a.ChainAPI, a.StateAPI, a.EthEventHandler) if err != nil { return nil, xerrors.Errorf("failed to convert %s into an Eth Receipt: %w", txHash, err) } @@ -1270,7 +1271,36 @@ func (a *EthModule) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam e return ethtypes.EthBytes{}, nil } +// TODO: For now, we're fetching logs from the index for the entire block and then filtering them by the transaction hash +// This allows us to use the current schema of the event Index DB that has been optimised to use the "tipset_key_cid" index +// However, this can be replaced to filter logs in the event Index DB by the "msgCid" if we pass it down to the query generator +func (e *EthEventHandler) getEthLogsForBlockAndTransaction(ctx context.Context, blockHash *ethtypes.EthHash, txHash ethtypes.EthHash) ([]ethtypes.EthLog, error) { + ces, err := e.ethGetEventsForFilter(ctx, ðtypes.EthFilterSpec{BlockHash: blockHash}) + if err != nil { + return nil, err + } + logs, err := ethFilterLogsFromEvents(ctx, ces, e.SubManager.StateAPI) + if err != nil { + return nil, err + } + var out []ethtypes.EthLog + for _, log := range logs { + if log.TransactionHash == txHash { + out = append(out, log) + } + } + return out, nil +} + func (e *EthEventHandler) EthGetLogs(ctx context.Context, filterSpec *ethtypes.EthFilterSpec) (*ethtypes.EthFilterResult, error) { + ces, err := e.ethGetEventsForFilter(ctx, filterSpec) + if err != nil { + return nil, err + } + return ethFilterResultFromEvents(ctx, ces, e.SubManager.StateAPI) +} + +func (e *EthEventHandler) ethGetEventsForFilter(ctx context.Context, filterSpec *ethtypes.EthFilterSpec) ([]*filter.CollectedEvent, error) { if e.EventFilterManager == nil { return nil, api.ErrNotSupported } @@ -1279,7 +1309,7 @@ func (e *EthEventHandler) EthGetLogs(ctx context.Context, filterSpec *ethtypes.E return nil, xerrors.Errorf("cannot use eth_get_logs if historical event index is disabled") } - pf, err := e.parseEthFilterSpec(ctx, filterSpec) + pf, err := e.parseEthFilterSpec(filterSpec) if err != nil { return nil, xerrors.Errorf("failed to parse eth filter spec: %w", err) } @@ -1340,7 +1370,7 @@ func (e *EthEventHandler) EthGetLogs(ctx context.Context, filterSpec *ethtypes.E _ = e.uninstallFilter(ctx, f) - return ethFilterResultFromEvents(ctx, ces, e.SubManager.StateAPI) + return ces, nil } // note that we can have null blocks at the given height and the event Index is not null block aware @@ -1492,7 +1522,7 @@ type parsedFilter struct { keys map[string][]types.ActorEventBlock } -func (e *EthEventHandler) parseEthFilterSpec(ctx context.Context, filterSpec *ethtypes.EthFilterSpec) (*parsedFilter, error) { +func (e *EthEventHandler) parseEthFilterSpec(filterSpec *ethtypes.EthFilterSpec) (*parsedFilter, error) { var ( minHeight abi.ChainEpoch maxHeight abi.ChainEpoch @@ -1556,7 +1586,7 @@ func (e *EthEventHandler) EthNewFilter(ctx context.Context, filterSpec *ethtypes return ethtypes.EthFilterID{}, api.ErrNotSupported } - pf, err := e.parseEthFilterSpec(ctx, filterSpec) + pf, err := e.parseEthFilterSpec(filterSpec) if err != nil { return ethtypes.EthFilterID{}, err } diff --git a/node/impl/full/eth_events.go b/node/impl/full/eth_events.go index b82fe264f5b..0c474b92fe2 100644 --- a/node/impl/full/eth_events.go +++ b/node/impl/full/eth_events.go @@ -93,8 +93,8 @@ func ethLogFromEvent(entries []types.EventEntry) (data []byte, topics []ethtypes return data, topics, true } -func ethFilterResultFromEvents(ctx context.Context, evs []*filter.CollectedEvent, sa StateAPI) (*ethtypes.EthFilterResult, error) { - res := ðtypes.EthFilterResult{} +func ethFilterLogsFromEvents(ctx context.Context, evs []*filter.CollectedEvent, sa StateAPI) ([]ethtypes.EthLog, error) { + var logs []ethtypes.EthLog for _, ev := range evs { log := ethtypes.EthLog{ Removed: ev.Reverted, @@ -134,6 +134,20 @@ func ethFilterResultFromEvents(ctx context.Context, evs []*filter.CollectedEvent return nil, err } + logs = append(logs, log) + } + + return logs, nil +} + +func ethFilterResultFromEvents(ctx context.Context, evs []*filter.CollectedEvent, sa StateAPI) (*ethtypes.EthFilterResult, error) { + logs, err := ethFilterLogsFromEvents(ctx, evs, sa) + if err != nil { + return nil, err + } + + res := ðtypes.EthFilterResult{} + for _, log := range logs { res.Results = append(res.Results, log) } diff --git a/node/impl/full/eth_utils.go b/node/impl/full/eth_utils.go index 61a66689b2f..40c4486966f 100644 --- a/node/impl/full/eth_utils.go +++ b/node/impl/full/eth_utils.go @@ -675,7 +675,7 @@ func newEthTxFromMessageLookup(ctx context.Context, msgLookup *api.MsgLookup, tx return tx, nil } -func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLookup, ca ChainAPI, sa StateAPI) (api.EthTxReceipt, error) { +func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLookup, ca ChainAPI, sa StateAPI, ev *EthEventHandler) (api.EthTxReceipt, error) { var ( transactionIndex ethtypes.EthUint64 blockHash ethtypes.EthHash @@ -721,11 +721,6 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook return api.EthTxReceipt{}, xerrors.Errorf("failed to lookup tipset %s when constructing the eth txn receipt: %w", lookup.TipSet, err) } - st, err := sa.StateManager.StateTree(ts.ParentState()) - if err != nil { - return api.EthTxReceipt{}, xerrors.Errorf("failed to load the state %s when constructing the eth txn receipt: %w", ts.ParentState(), err) - } - // The tx is located in the parent tipset parentTs, err := ca.Chain.LoadTipSet(ctx, ts.Parents()) if err != nil { @@ -763,61 +758,21 @@ func newEthTxReceipt(ctx context.Context, tx ethtypes.EthTx, lookup *api.MsgLook receipt.ContractAddress = &addr } - var events []types.Event if rct := lookup.Receipt; rct.EventsRoot != nil { - events, err = ca.ChainGetEvents(ctx, *rct.EventsRoot) + logs, err := ev.getEthLogsForBlockAndTransaction(ctx, &blockHash, tx.Hash) if err != nil { - // Fore-recompute, we must have enabled the Event APIs after computing this - // tipset. - if _, _, err := sa.StateManager.RecomputeTipSetState(ctx, ts); err != nil { - - return api.EthTxReceipt{}, xerrors.Errorf("failed get events: %w", err) - } - // Try again - events, err = ca.ChainGetEvents(ctx, *rct.EventsRoot) - if err != nil { - return api.EthTxReceipt{}, xerrors.Errorf("failed get events: %w", err) - } + return api.EthTxReceipt{}, xerrors.Errorf("failed to get eth logs for block and transaction: %w", err) + } + if len(logs) > 0 { + receipt.Logs = logs } } - if len(events) > 0 { - receipt.Logs = make([]ethtypes.EthLog, 0, len(events)) - for i, evt := range events { - l := ethtypes.EthLog{ - Removed: false, - LogIndex: ethtypes.EthUint64(i), - TransactionHash: tx.Hash, - TransactionIndex: transactionIndex, - BlockHash: blockHash, - BlockNumber: blockNumber, - } - - data, topics, ok := ethLogFromEvent(evt.Entries) - if !ok { - // not an eth event. - continue - } - for _, topic := range topics { - log.Debug("LogsBloom set for ", topic) - ethtypes.EthBloomSet(receipt.LogsBloom, topic[:]) - } - l.Data = data - l.Topics = topics - - addr, err := address.NewIDAddress(uint64(evt.Emitter)) - if err != nil { - return api.EthTxReceipt{}, xerrors.Errorf("failed to create ID address: %w", err) - } - - l.Address, err = lookupEthAddress(addr, st) - if err != nil { - return api.EthTxReceipt{}, xerrors.Errorf("failed to resolve Ethereum address: %w", err) - } - - ethtypes.EthBloomSet(receipt.LogsBloom, l.Address[:]) - receipt.Logs = append(receipt.Logs, l) + for _, log := range receipt.Logs { + for _, topic := range log.Topics { + ethtypes.EthBloomSet(receipt.LogsBloom, topic[:]) } + ethtypes.EthBloomSet(receipt.LogsBloom, log.Address[:]) } return receipt, nil diff --git a/node/modules/ethmodule.go b/node/modules/ethmodule.go index 1360daf1a89..40f81cabf4b 100644 --- a/node/modules/ethmodule.go +++ b/node/modules/ethmodule.go @@ -21,8 +21,8 @@ import ( "github.com/filecoin-project/lotus/node/repo" ) -func EthModuleAPI(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRepo, fx.Lifecycle, *store.ChainStore, *stmgr.StateManager, EventHelperAPI, *messagepool.MessagePool, full.StateAPI, full.ChainAPI, full.MpoolAPI, full.SyncAPI) (*full.EthModule, error) { - return func(mctx helpers.MetricsCtx, r repo.LockedRepo, lc fx.Lifecycle, cs *store.ChainStore, sm *stmgr.StateManager, evapi EventHelperAPI, mp *messagepool.MessagePool, stateapi full.StateAPI, chainapi full.ChainAPI, mpoolapi full.MpoolAPI, syncapi full.SyncAPI) (*full.EthModule, error) { +func EthModuleAPI(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRepo, fx.Lifecycle, *store.ChainStore, *stmgr.StateManager, EventHelperAPI, *messagepool.MessagePool, full.StateAPI, full.ChainAPI, full.MpoolAPI, full.SyncAPI, *full.EthEventHandler) (*full.EthModule, error) { + return func(mctx helpers.MetricsCtx, r repo.LockedRepo, lc fx.Lifecycle, cs *store.ChainStore, sm *stmgr.StateManager, evapi EventHelperAPI, mp *messagepool.MessagePool, stateapi full.StateAPI, chainapi full.ChainAPI, mpoolapi full.MpoolAPI, syncapi full.SyncAPI, ethEventHandler *full.EthEventHandler) (*full.EthModule, error) { ctx := helpers.LifecycleCtx(mctx, lc) sqlitePath, err := r.SqlitePath() @@ -96,10 +96,11 @@ func EthModuleAPI(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRep Mpool: mp, StateManager: sm, - ChainAPI: chainapi, - MpoolAPI: mpoolapi, - StateAPI: stateapi, - SyncAPI: syncapi, + ChainAPI: chainapi, + MpoolAPI: mpoolapi, + StateAPI: stateapi, + SyncAPI: syncapi, + EthEventHandler: ethEventHandler, EthTxHashManager: ðTxHashManager, }, nil