From 58fb7bf89a88e743e8659868b8573df5daed05ca Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Tue, 25 Feb 2025 13:05:39 +0100 Subject: [PATCH 1/6] core/types: add benchmark --- core/types/transaction_test.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go index 17a7dda3578c..3cebc6ca76cc 100644 --- a/core/types/transaction_test.go +++ b/core/types/transaction_test.go @@ -576,3 +576,22 @@ func TestYParityJSONUnmarshalling(t *testing.T) { } } } + +func BenchmarkHash(b *testing.B) { + signer := NewLondonSigner(big.NewInt(1)) + to := common.Address{} + tx := NewTx(&DynamicFeeTx{ + ChainID: big.NewInt(123), + Nonce: 1, + Gas: 1000000, + To: &to, + Value: big.NewInt(1), + GasTipCap: big.NewInt(500), + GasFeeCap: big.NewInt(500), + }) + for i := 0; i < b.N; i++ { + signer.Hash(tx) + } +} + +// BenchmarkHash-8 541969 2320 ns/op 240 B/op 6 allocs/op From a650a400a068d901af6eba1aad0199a465550a8d Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Tue, 25 Feb 2025 13:05:59 +0100 Subject: [PATCH 2/6] core/types: use fields directly --- core/types/transaction_signing.go | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/core/types/transaction_signing.go b/core/types/transaction_signing.go index 030fc472a00a..3380bcc2c0ac 100644 --- a/core/types/transaction_signing.go +++ b/core/types/transaction_signing.go @@ -366,21 +366,22 @@ func (s londonSigner) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big // Hash returns the hash to be signed by the sender. // It does not uniquely identify the transaction. func (s londonSigner) Hash(tx *Transaction) common.Hash { - if tx.Type() != DynamicFeeTxType { + inner, ok := tx.inner.(*DynamicFeeTx) + if !ok { return s.eip2930Signer.Hash(tx) } return prefixedRlpHash( - tx.Type(), + inner.txType(), []interface{}{ s.chainId, - tx.Nonce(), - tx.GasTipCap(), - tx.GasFeeCap(), - tx.Gas(), - tx.To(), - tx.Value(), - tx.Data(), - tx.AccessList(), + inner.nonce(), + inner.gasTipCap(), + inner.gasFeeCap(), + inner.gas(), + inner.to(), + inner.value(), + inner.data(), + inner.accessList(), }) } From 8b5ebf47c7f7a645458187277879cceabae75402 Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Tue, 25 Feb 2025 13:41:13 +0100 Subject: [PATCH 3/6] core/types: add sigHash to txdata --- core/types/transaction.go | 3 ++ core/types/transaction_signing.go | 58 ++++--------------------------- core/types/transaction_test.go | 3 +- core/types/tx_access_list.go | 15 ++++++++ core/types/tx_blob.go | 18 ++++++++++ core/types/tx_dynamic_fee.go | 16 +++++++++ core/types/tx_legacy.go | 13 +++++++ core/types/tx_setcode.go | 17 +++++++++ 8 files changed, 90 insertions(+), 53 deletions(-) diff --git a/core/types/transaction.go b/core/types/transaction.go index 4e48248b4a8b..a2f410463516 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -100,6 +100,9 @@ type TxData interface { encode(*bytes.Buffer) error decode([]byte) error + + // sigHash returns the hash of the transaction that is ought to be signed + sigHash(*big.Int) common.Hash } // EncodeRLP implements rlp.Encoder diff --git a/core/types/transaction_signing.go b/core/types/transaction_signing.go index 3380bcc2c0ac..2addb14aeada 100644 --- a/core/types/transaction_signing.go +++ b/core/types/transaction_signing.go @@ -301,21 +301,7 @@ func (s cancunSigner) Hash(tx *Transaction) common.Hash { if tx.Type() != BlobTxType { return s.londonSigner.Hash(tx) } - return prefixedRlpHash( - tx.Type(), - []interface{}{ - s.chainId, - tx.Nonce(), - tx.GasTipCap(), - tx.GasFeeCap(), - tx.Gas(), - tx.To(), - tx.Value(), - tx.Data(), - tx.AccessList(), - tx.BlobGasFeeCap(), - tx.BlobHashes(), - }) + return tx.inner.sigHash(s.chainId) } type londonSigner struct{ eip2930Signer } @@ -366,23 +352,10 @@ func (s londonSigner) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big // Hash returns the hash to be signed by the sender. // It does not uniquely identify the transaction. func (s londonSigner) Hash(tx *Transaction) common.Hash { - inner, ok := tx.inner.(*DynamicFeeTx) - if !ok { + if tx.Type() != DynamicFeeTxType { return s.eip2930Signer.Hash(tx) } - return prefixedRlpHash( - inner.txType(), - []interface{}{ - s.chainId, - inner.nonce(), - inner.gasTipCap(), - inner.gasFeeCap(), - inner.gas(), - inner.to(), - inner.value(), - inner.data(), - inner.accessList(), - }) + return tx.inner.sigHash(s.chainId) } type eip2930Signer struct{ EIP155Signer } @@ -445,18 +418,7 @@ func (s eip2930Signer) Hash(tx *Transaction) common.Hash { case LegacyTxType: return s.EIP155Signer.Hash(tx) case AccessListTxType: - return prefixedRlpHash( - tx.Type(), - []interface{}{ - s.chainId, - tx.Nonce(), - tx.GasPrice(), - tx.Gas(), - tx.To(), - tx.Value(), - tx.Data(), - tx.AccessList(), - }) + return tx.inner.sigHash(s.chainId) default: // This _should_ not happen, but in case someone sends in a bad // json struct via RPC, it's probably more prudent to return an @@ -526,15 +488,7 @@ func (s EIP155Signer) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big // Hash returns the hash to be signed by the sender. // It does not uniquely identify the transaction. func (s EIP155Signer) Hash(tx *Transaction) common.Hash { - return rlpHash([]interface{}{ - tx.Nonce(), - tx.GasPrice(), - tx.Gas(), - tx.To(), - tx.Value(), - tx.Data(), - s.chainId, uint(0), uint(0), - }) + return tx.inner.sigHash(s.chainId) } // HomesteadSigner implements Signer interface using the @@ -598,7 +552,7 @@ func (fs FrontierSigner) SignatureValues(tx *Transaction, sig []byte) (r, s, v * // Hash returns the hash to be signed by the sender. // It does not uniquely identify the transaction. func (fs FrontierSigner) Hash(tx *Transaction) common.Hash { - return rlpHash([]interface{}{ + return rlpHash([]any{ tx.Nonce(), tx.GasPrice(), tx.Gas(), diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go index 3cebc6ca76cc..a999eff77fd3 100644 --- a/core/types/transaction_test.go +++ b/core/types/transaction_test.go @@ -594,4 +594,5 @@ func BenchmarkHash(b *testing.B) { } } -// BenchmarkHash-8 541969 2320 ns/op 240 B/op 6 allocs/op +// BenchmarkHash-8 440082 2639 ns/op 384 B/op 13 allocs/op +// BenchmarkHash-8 493566 2033 ns/op 240 B/op 6 allocs/op diff --git a/core/types/tx_access_list.go b/core/types/tx_access_list.go index 730a77b75286..915de9a8ab2a 100644 --- a/core/types/tx_access_list.go +++ b/core/types/tx_access_list.go @@ -127,3 +127,18 @@ func (tx *AccessListTx) encode(b *bytes.Buffer) error { func (tx *AccessListTx) decode(input []byte) error { return rlp.DecodeBytes(input, tx) } + +func (tx *AccessListTx) sigHash(chainID *big.Int) common.Hash { + return prefixedRlpHash( + AccessListTxType, + []any{ + chainID, + tx.Nonce, + tx.GasPrice, + tx.Gas, + tx.To, + tx.Value, + tx.Data, + tx.AccessList, + }) +} diff --git a/core/types/tx_blob.go b/core/types/tx_blob.go index 32401db101bf..9b1d53958fed 100644 --- a/core/types/tx_blob.go +++ b/core/types/tx_blob.go @@ -259,3 +259,21 @@ func (tx *BlobTx) decode(input []byte) error { } return nil } + +func (tx *BlobTx) sigHash(chainID *big.Int) common.Hash { + return prefixedRlpHash( + BlobTxType, + []any{ + chainID, + tx.Nonce, + tx.GasTipCap, + tx.GasFeeCap, + tx.Gas, + tx.To, + tx.Value, + tx.Data, + tx.AccessList, + tx.BlobFeeCap, + tx.BlobHashes, + }) +} diff --git a/core/types/tx_dynamic_fee.go b/core/types/tx_dynamic_fee.go index 981755cf7007..bba81464f849 100644 --- a/core/types/tx_dynamic_fee.go +++ b/core/types/tx_dynamic_fee.go @@ -123,3 +123,19 @@ func (tx *DynamicFeeTx) encode(b *bytes.Buffer) error { func (tx *DynamicFeeTx) decode(input []byte) error { return rlp.DecodeBytes(input, tx) } + +func (tx *DynamicFeeTx) sigHash(chainID *big.Int) common.Hash { + return prefixedRlpHash( + DynamicFeeTxType, + []any{ + chainID, + tx.Nonce, + tx.GasTipCap, + tx.GasFeeCap, + tx.Gas, + tx.To, + tx.Value, + tx.Data, + tx.AccessList, + }) +} diff --git a/core/types/tx_legacy.go b/core/types/tx_legacy.go index 71025b78fc06..3eed683f2428 100644 --- a/core/types/tx_legacy.go +++ b/core/types/tx_legacy.go @@ -123,3 +123,16 @@ func (tx *LegacyTx) encode(*bytes.Buffer) error { func (tx *LegacyTx) decode([]byte) error { panic("decode called on LegacyTx)") } + +// OBS: This is the post-frontier hash, the pre-frontier does not contain a chainID +func (tx *LegacyTx) sigHash(chainID *big.Int) common.Hash { + return rlpHash([]any{ + tx.Nonce, + tx.GasPrice, + tx.Gas, + tx.To, + tx.Value, + tx.Data, + chainID, uint(0), uint(0), + }) +} diff --git a/core/types/tx_setcode.go b/core/types/tx_setcode.go index 894bac10a33f..b8e38ef1f705 100644 --- a/core/types/tx_setcode.go +++ b/core/types/tx_setcode.go @@ -223,3 +223,20 @@ func (tx *SetCodeTx) encode(b *bytes.Buffer) error { func (tx *SetCodeTx) decode(input []byte) error { return rlp.DecodeBytes(input, tx) } + +func (tx *SetCodeTx) sigHash(chainID *big.Int) common.Hash { + return prefixedRlpHash( + SetCodeTxType, + []any{ + chainID, + tx.Nonce, + tx.GasTipCap, + tx.GasFeeCap, + tx.Gas, + tx.To, + tx.Value, + tx.Data, + tx.AccessList, + tx.AuthList, + }) +} From 4524162004e5bee023e4c3e49c3e71bbd7338396 Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Tue, 25 Feb 2025 13:43:04 +0100 Subject: [PATCH 4/6] core/types: add sigHash to txdata --- core/types/transaction_test.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go index a999eff77fd3..8922448d97d5 100644 --- a/core/types/transaction_test.go +++ b/core/types/transaction_test.go @@ -593,6 +593,3 @@ func BenchmarkHash(b *testing.B) { signer.Hash(tx) } } - -// BenchmarkHash-8 440082 2639 ns/op 384 B/op 13 allocs/op -// BenchmarkHash-8 493566 2033 ns/op 240 B/op 6 allocs/op From d3f230f8ed726661ace6a33444c4e73db91d0487 Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Tue, 25 Feb 2025 13:49:09 +0100 Subject: [PATCH 5/6] core/types: add sigHash to txdata --- core/types/transaction_signing.go | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/core/types/transaction_signing.go b/core/types/transaction_signing.go index 2addb14aeada..89c08aeddd58 100644 --- a/core/types/transaction_signing.go +++ b/core/types/transaction_signing.go @@ -233,20 +233,7 @@ func (s pragueSigner) Hash(tx *Transaction) common.Hash { if tx.Type() != SetCodeTxType { return s.cancunSigner.Hash(tx) } - return prefixedRlpHash( - tx.Type(), - []interface{}{ - s.chainId, - tx.Nonce(), - tx.GasTipCap(), - tx.GasFeeCap(), - tx.Gas(), - tx.To(), - tx.Value(), - tx.Data(), - tx.AccessList(), - tx.SetCodeAuthorizations(), - }) + return tx.inner.sigHash(s.chainId) } type cancunSigner struct{ londonSigner } From 16188c703ec0aa326d2b81c9e08c71463cb4382b Mon Sep 17 00:00:00 2001 From: Gary Rong Date: Wed, 19 Mar 2025 09:51:22 +0800 Subject: [PATCH 6/6] core/types: fix comment --- core/types/tx_legacy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/types/tx_legacy.go b/core/types/tx_legacy.go index 3eed683f2428..49f0a98809fd 100644 --- a/core/types/tx_legacy.go +++ b/core/types/tx_legacy.go @@ -124,7 +124,7 @@ func (tx *LegacyTx) decode([]byte) error { panic("decode called on LegacyTx)") } -// OBS: This is the post-frontier hash, the pre-frontier does not contain a chainID +// OBS: This is the post-EIP155 hash, the pre-EIP155 does not contain a chainID. func (tx *LegacyTx) sigHash(chainID *big.Int) common.Hash { return rlpHash([]any{ tx.Nonce,