From 33ab63ef15a7b2ba7d28575feeb17f7785f605c0 Mon Sep 17 00:00:00 2001 From: Austin Abell Date: Mon, 13 Apr 2020 19:08:43 -0400 Subject: [PATCH] update web3 transaction hash from RLP (#250) * remove ethereum hash of web3 transaction type (always amino hash) * Update changelog --- CHANGELOG.md | 9 +++++++-- rpc/backend.go | 2 +- rpc/eth_api.go | 10 +++++----- x/evm/handler.go | 8 +++++--- x/evm/types/msg.go | 12 ------------ x/evm/types/msg_test.go | 8 -------- 6 files changed, 18 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf7eb3cb..6994ac11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,7 +51,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (keys) Marked `ExportEthKeyCommand` as **UNSAFE** * (x/evm) Moved `BeginBlock` and `EndBlock` to `x/evm/abci.go` -## Features +### Features * (rpc) [\#231](https://github.com/ChainSafe/ethermint/issues/231) Implement NewBlockFilter in rpc/filters.go which instantiates a polling block filter * Polls for new blocks via BlockNumber rpc call; if block number changes, it requests the new block via GetBlockByNumber rpc call and adds it to its internal list of blocks @@ -63,4 +63,9 @@ Ref: https://keepachangelog.com/en/1.0.0/ Implement eth_getFilterLogs and eth_getLogs * for a given filter, look through each block for transactions. If there are transactions in the block, get the logs from it, and filter using the filterLogs method * eth_getLogs and eth_getFilterChanges for log filters use the same underlying method as eth_getFilterLogs - * update HandleMsgEthereumTx to store logs using the ethereum hash \ No newline at end of file + * update HandleMsgEthereumTx to store logs using the ethereum hash + +### Bug Fixes + +* (x/evm) [\#176](https://github.com/ChainSafe/ethermint/issues/176) Updated Web3 transaction hash from using RLP hash. Now all transaction hashes exposed are amino hashes. + * Removes `Hash()` (RLP) function from `MsgEthereumTx` to avoid confusion or misuse in future. diff --git a/rpc/backend.go b/rpc/backend.go index 5bd9ae55..fc4b6581 100644 --- a/rpc/backend.go +++ b/rpc/backend.go @@ -188,7 +188,7 @@ func (e *EthermintBackend) PendingTransactions() ([]*Transaction, error) { } // * Should check signer and reference against accounts the node manages in future - rpcTx, err := newRPCTransaction(*ethTx, common.Hash{}, nil, 0) + rpcTx, err := newRPCTransaction(*ethTx, common.BytesToHash(tx.Hash()), common.Hash{}, nil, 0) if err != nil { return nil, err } diff --git a/rpc/eth_api.go b/rpc/eth_api.go index a4c9b511..31c9d1b9 100644 --- a/rpc/eth_api.go +++ b/rpc/eth_api.go @@ -514,7 +514,7 @@ func convertTransactionsToRPC(cliCtx context.CLIContext, txs []tmtypes.Tx, block } // TODO: Remove gas usage calculation if saving gasUsed per block gasUsed.Add(gasUsed, ethTx.Fee()) - tx, err := newRPCTransaction(*ethTx, blockHash, &height, uint64(i)) + tx, err := newRPCTransaction(*ethTx, common.BytesToHash(tx.Hash()), blockHash, &height, uint64(i)) if err != nil { return nil, nil, err } @@ -558,7 +558,7 @@ func bytesToEthTx(cliCtx context.CLIContext, bz []byte) (*types.MsgEthereumTx, e // newRPCTransaction returns a transaction that will serialize to the RPC // representation, with the given location metadata set (if available). -func newRPCTransaction(tx types.MsgEthereumTx, blockHash common.Hash, blockNumber *uint64, index uint64) (*Transaction, error) { +func newRPCTransaction(tx types.MsgEthereumTx, txHash, blockHash common.Hash, blockNumber *uint64, index uint64) (*Transaction, error) { // Verify signature and retrieve sender address from, err := tx.VerifySig(tx.ChainID()) if err != nil { @@ -569,7 +569,7 @@ func newRPCTransaction(tx types.MsgEthereumTx, blockHash common.Hash, blockNumbe From: from, Gas: hexutil.Uint64(tx.Data.GasLimit), GasPrice: (*hexutil.Big)(tx.Data.Price), - Hash: tx.Hash(), + Hash: txHash, Input: hexutil.Bytes(tx.Data.Payload), Nonce: hexutil.Uint64(tx.Data.AccountNonce), To: tx.To(), @@ -609,7 +609,7 @@ func (e *PublicEthAPI) GetTransactionByHash(hash common.Hash) (*Transaction, err } height := uint64(tx.Height) - return newRPCTransaction(*ethTx, blockHash, &height, uint64(tx.Index)) + return newRPCTransaction(*ethTx, common.BytesToHash(tx.Tx.Hash()), blockHash, &height, uint64(tx.Index)) } // GetTransactionByBlockHashAndIndex returns the transaction identified by hash and index. @@ -647,7 +647,7 @@ func (e *PublicEthAPI) getTransactionByBlockNumberAndIndex(number int64, idx hex } height := uint64(header.Height) - return newRPCTransaction(*ethTx, common.BytesToHash(header.Hash()), &height, uint64(idx)) + return newRPCTransaction(*ethTx, common.BytesToHash(txs[idx].Hash()), common.BytesToHash(header.Hash()), &height, uint64(idx)) } // GetTransactionReceipt returns the transaction receipt identified by hash. diff --git a/x/evm/handler.go b/x/evm/handler.go index 06680517..69cea3ad 100644 --- a/x/evm/handler.go +++ b/x/evm/handler.go @@ -43,7 +43,8 @@ func HandleMsgEthereumTx(ctx sdk.Context, k Keeper, msg types.MsgEthereumTx) sdk return sdk.ResultFromError(err) } - txHash := msg.Hash() + txHash := tmtypes.Tx(ctx.TxBytes()).Hash() + ethHash := common.BytesToHash(txHash) st := types.StateTransition{ Sender: sender, @@ -55,12 +56,13 @@ func HandleMsgEthereumTx(ctx sdk.Context, k Keeper, msg types.MsgEthereumTx) sdk Payload: msg.Data.Payload, Csdb: k.CommitStateDB.WithContext(ctx), ChainID: intChainID, - THash: &txHash, + THash: ðHash, Simulate: ctx.IsCheckTx(), } + // Prepare db for logs // TODO: block hash - k.CommitStateDB.Prepare(txHash, txHash, k.TxCount) + k.CommitStateDB.Prepare(ethHash, common.Hash{}, k.TxCount) k.TxCount++ // TODO: move to keeper diff --git a/x/evm/types/msg.go b/x/evm/types/msg.go index 2300ce1f..ca7a0a6a 100644 --- a/x/evm/types/msg.go +++ b/x/evm/types/msg.go @@ -198,18 +198,6 @@ func (msg *MsgEthereumTx) DecodeRLP(s *rlp.Stream) error { return err } -// Hash hashes the RLP encoding of a transaction. -func (msg *MsgEthereumTx) Hash() ethcmn.Hash { - if hash := msg.hash.Load(); hash != nil { - return hash.(ethcmn.Hash) - } - - v := rlpHash(msg) - msg.hash.Store(v) - - return v -} - // Sign calculates a secp256k1 ECDSA signature and signs the transaction. It // takes a private key and chainID to sign an Ethereum transaction according to // EIP155 standard. It mutates the transaction as it populates the V, R, S diff --git a/x/evm/types/msg_test.go b/x/evm/types/msg_test.go index c25281db..13cc89f0 100644 --- a/x/evm/types/msg_test.go +++ b/x/evm/types/msg_test.go @@ -89,14 +89,6 @@ func TestMsgEthereumTxRLPDecode(t *testing.T) { require.Equal(t, expectedMsg.Data, msg.Data) } -func TestMsgEthereumTxHash(t *testing.T) { - addr := ethcmn.BytesToAddress([]byte("test_address")) - msg := NewMsgEthereumTx(0, &addr, nil, 100000, nil, []byte("test")) - - hash := msg.Hash() - require.Equal(t, "E2AA2E68E7586AE9700F1D3D643330866B6AC2B6CA4C804F7C85ECB11D0B0B29", fmt.Sprintf("%X", hash)) -} - func TestMsgEthereumTxSig(t *testing.T) { chainID := big.NewInt(3)