diff --git a/CHANGELOG.md b/CHANGELOG.md index 96b3cf04..dc8cdc4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,9 +42,15 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (deps) [tharsis#1046](https://github.com/tharsis/ethermint/pull/1046) Bump Cosmos SDK version to [`v0.45.3`](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.45.3) +### Bug Fixes + +* (rpc) [tharsis#1050](https://github.com/tharsis/ethermint/pull/1050) `eth_getBlockByNumber` fix on batch transactions + ### API Breaking + * (evm) [tharsis#1051](https://github.com/tharsis/ethermint/pull/1051) Context block height fix on TraceTx. Removes `tx_index` on `QueryTraceTxRequest` proto type. + ## [v0.13.0] - 2022-04-05 ### API Breaking diff --git a/rpc/ethereum/backend/backend.go b/rpc/ethereum/backend/backend.go index c3374441..51565b28 100644 --- a/rpc/ethereum/backend/backend.go +++ b/rpc/ethereum/backend/backend.go @@ -362,6 +362,7 @@ func (e *EVMBackend) EthBlockFromTendermint( } txResults := resBlockResult.TxsResults + txIndex := uint64(0) for i, txBz := range block.Txs { tx, err := e.clientCtx.TxConfig.TxDecoder()(txBz) @@ -394,7 +395,7 @@ func (e *EVMBackend) EthBlockFromTendermint( tx, common.BytesToHash(block.Hash()), uint64(block.Height), - uint64(i), + txIndex, baseFee, ) if err != nil { @@ -402,6 +403,7 @@ func (e *EVMBackend) EthBlockFromTendermint( continue } ethRPCTxs = append(ethRPCTxs, rpcTx) + txIndex++ } } diff --git a/tests/e2e/integration_test.go b/tests/e2e/integration_test.go index 0052ee2c..520c8643 100644 --- a/tests/e2e/integration_test.go +++ b/tests/e2e/integration_test.go @@ -4,6 +4,10 @@ import ( "bytes" "context" "fmt" + "github.com/cosmos/cosmos-sdk/client/flags" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" + "github.com/tharsis/ethermint/rpc/ethereum/types" "math/big" "testing" @@ -132,7 +136,6 @@ func (s *IntegrationTestSuite) TestBlock() { s.Require().NotNil(blockByNum) // compare the ethereum header with the tendermint header - s.Require().Equal(len(block.Block.Txs), len(blockByNum.Body().Transactions)) s.Require().Equal(block.Block.LastBlockID.Hash.Bytes(), blockByNum.Header().ParentHash.Bytes()) hash := common.BytesToHash(block.Block.Hash()) @@ -143,7 +146,12 @@ func (s *IntegrationTestSuite) TestBlock() { blockByHash, err := s.network.Validators[0].JSONRPCClient.BlockByHash(s.ctx, hash) s.Require().NoError(err) s.Require().NotNil(blockByHash) - s.Require().Equal(blockByNum, blockByHash) + + //Compare blockByNumber and blockByHash results + s.Require().Equal(blockByNum.Hash(), blockByHash.Hash()) + s.Require().Equal(blockByNum.Transactions().Len(), blockByHash.Transactions().Len()) + s.Require().Equal(blockByNum.ParentHash(), blockByHash.ParentHash()) + s.Require().Equal(blockByNum.Root(), blockByHash.Root()) // TODO: parse Tm block to Ethereum and compare } @@ -747,3 +755,85 @@ func (s *IntegrationTestSuite) TestPendingTransactionFilter() { s.Require().NoError(err) s.Require().Equal([]common.Hash{signedTx.Hash()}, filterResult) } + +// TODO: add transactionIndex tests once we have OpenRPC interfaces +func (s *IntegrationTestSuite) TestBatchETHTransactions() { + const ethTxs = 2 + txBuilder := s.network.Validators[0].ClientCtx.TxConfig.NewTxBuilder() + builder, ok := txBuilder.(authtx.ExtensionOptionsTxBuilder) + s.Require().True(ok) + + recipient := common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec") + accountNonce := s.getAccountNonce(recipient) + feeAmount := sdk.ZeroInt() + + var gasLimit uint64 + var msgs []sdk.Msg + + for i := 0; i < ethTxs; i++ { + chainId, err := s.network.Validators[0].JSONRPCClient.ChainID(s.ctx) + s.Require().NoError(err) + + gasPrice := s.getGasPrice() + from := common.BytesToAddress(s.network.Validators[0].Address) + nonce := accountNonce + uint64(i) + 1 + + msgTx := evmtypes.NewTx( + chainId, + nonce, + &recipient, + big.NewInt(10), + 100000, + gasPrice, + big.NewInt(200), + nil, + nil, + nil, + ) + msgTx.From = from.Hex() + err = msgTx.Sign(s.ethSigner, s.network.Validators[0].ClientCtx.Keyring) + s.Require().NoError(err) + + msgs = append(msgs, msgTx.GetMsgs()...) + txData, err := evmtypes.UnpackTxData(msgTx.Data) + s.Require().NoError(err) + feeAmount = feeAmount.Add(sdk.NewIntFromBigInt(txData.Fee())) + gasLimit = gasLimit + txData.GetGas() + } + + option, err := codectypes.NewAnyWithValue(&evmtypes.ExtensionOptionsEthereumTx{}) + s.Require().NoError(err) + + queryClient := types.NewQueryClient(s.network.Validators[0].ClientCtx) + res, err := queryClient.Params(s.ctx, &evmtypes.QueryParamsRequest{}) + + fees := make(sdk.Coins, 0) + if feeAmount.Sign() > 0 { + fees = fees.Add(sdk.Coin{Denom: res.Params.EvmDenom, Amount: feeAmount}) + } + + builder.SetExtensionOptions(option) + err = builder.SetMsgs(msgs...) + s.Require().NoError(err) + builder.SetFeeAmount(fees) + builder.SetGasLimit(gasLimit) + + tx := builder.GetTx() + txEncoder := s.network.Validators[0].ClientCtx.TxConfig.TxEncoder() + txBytes, err := txEncoder(tx) + s.Require().NoError(err) + + syncCtx := s.network.Validators[0].ClientCtx.WithBroadcastMode(flags.BroadcastBlock) + txResponse, err := syncCtx.BroadcastTx(txBytes) + s.Require().NoError(err) + s.Require().Equal(uint32(0), txResponse.Code) + + block, err := s.network.Validators[0].JSONRPCClient.BlockByNumber(s.ctx, big.NewInt(txResponse.Height)) + s.Require().NoError(err) + + txs := block.Transactions() + s.Require().Len(txs, ethTxs) + for i, tx := range txs { + s.Require().Equal(accountNonce+uint64(i)+1, tx.Nonce()) + } +}