From c9c19bcd8a1e5ecc71357ba06ac19fee984dac5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Negovanovi=C4=87?= <93934272+Stefan-Ethernal@users.noreply.github.com> Date: Thu, 10 Aug 2023 13:38:23 +0200 Subject: [PATCH] Fix hash calculation for dynamic fee and access list transactions (#253) * Simplify and make signing more readable * Include Dynamic fee transactions signing in the test * Hash using provided chain id instead the one from transaction * Change transaction type to uint8 data type --- structs.go | 2 +- wallet/signer.go | 20 ++++++++------------ wallet/signer_test.go | 19 +++++++++++++------ 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/structs.go b/structs.go index f8a24c13..699d5899 100644 --- a/structs.go +++ b/structs.go @@ -164,7 +164,7 @@ func (b *Block) Copy() *Block { return bb } -type TransactionType int +type TransactionType uint8 const ( TransactionLegacy TransactionType = 0 diff --git a/wallet/signer.go b/wallet/signer.go index 0d12a56a..dad25ec7 100644 --- a/wallet/signer.go +++ b/wallet/signer.go @@ -75,12 +75,13 @@ func (e *EIP1155Signer) SignTx(tx *ethgo.Transaction, key ethgo.Key) (*ethgo.Tra func signHash(tx *ethgo.Transaction, chainID uint64) []byte { a := fastrlp.DefaultArenaPool.Get() + defer fastrlp.DefaultArenaPool.Put(a) v := a.NewArray() - if tx.Type != 0 { + if tx.Type != ethgo.TransactionLegacy { // either dynamic and access type - v.Set(a.NewBigInt(tx.ChainID)) + v.Set(a.NewBigInt(new(big.Int).SetUint64(chainID))) } v.Set(a.NewUint(tx.Nonce)) @@ -103,7 +104,7 @@ func signHash(tx *ethgo.Transaction, chainID uint64) []byte { v.Set(a.NewBigInt(tx.Value)) v.Set(a.NewCopyBytes(tx.Input)) - if tx.Type != 0 { + if tx.Type != ethgo.TransactionLegacy { // either dynamic and access type accessList, err := tx.AccessList.MarshalRLPWith(a) if err != nil { @@ -113,7 +114,7 @@ func signHash(tx *ethgo.Transaction, chainID uint64) []byte { } // EIP155 - if chainID != 0 && tx.Type == 0 { + if chainID != 0 && tx.Type == ethgo.TransactionLegacy { v.Set(a.NewUint(chainID)) v.Set(a.NewUint(0)) v.Set(a.NewUint(0)) @@ -122,15 +123,10 @@ func signHash(tx *ethgo.Transaction, chainID uint64) []byte { dst := v.MarshalTo(nil) // append the tx type byte - if tx.Type == ethgo.TransactionAccessList { - dst = append([]byte{0x1}, dst...) - } else if tx.Type == ethgo.TransactionDynamicFee { - dst = append([]byte{0x2}, dst...) + if tx.Type != ethgo.TransactionLegacy { + dst = append([]byte{byte(tx.Type)}, dst...) } - - hash := ethgo.Keccak256(dst) - fastrlp.DefaultArenaPool.Put(a) - return hash + return ethgo.Keccak256(dst) } func encodeSignature(R, S []byte, V byte) ([]byte, error) { diff --git a/wallet/signer_test.go b/wallet/signer_test.go index dcff5fa4..dde31c44 100644 --- a/wallet/signer_test.go +++ b/wallet/signer_test.go @@ -12,8 +12,6 @@ import ( func TestSigner_SignAndRecover(t *testing.T) { rapid.Check(t, func(t *rapid.T) { - istyped := rapid.Bool().Draw(t, "istyped") - // fill in common types for a transaction txn := ðgo.Transaction{} @@ -22,15 +20,24 @@ func TestSigner_SignAndRecover(t *testing.T) { txn.To = &to } + txType := rapid.IntRange(0, 2).Draw(t, "tx type") + // fill in specific fields depending on the type // of the transaction. - if istyped { - txn.Type = ethgo.TransactionAccessList + txn.Type = ethgo.TransactionType(txType) + if txn.Type == ethgo.TransactionDynamicFee { + maxFeePerGas := rapid.Int64Range(1, 1000000000).Draw(t, "maxFeePerGas") + txn.MaxFeePerGas = big.NewInt(maxFeePerGas) + maxPriorityFeePerGas := rapid.Int64Range(1, 1000000000).Draw(t, "maxPriorityFeePerGas") + txn.MaxPriorityFeePerGas = big.NewInt(maxPriorityFeePerGas) + } else { + gasPrice := rapid.Uint64Range(1, 1000000000).Draw(t, "gasPrice") + txn.GasPrice = gasPrice } // signer is from a random chain - chainid := rapid.Uint64().Draw(t, "chainid") - signer := NewEIP155Signer(chainid) + chainId := rapid.Uint64().Draw(t, "chainId") + signer := NewEIP155Signer(chainId) key, err := GenerateKey() require.NoError(t, err)