diff --git a/core/types/transaction_signing.go b/core/types/transaction_signing.go index 01aa67c6ba4..ef8fb194d5f 100644 --- a/core/types/transaction_signing.go +++ b/core/types/transaction_signing.go @@ -20,7 +20,6 @@ import ( "crypto/ecdsa" "errors" "fmt" - "maps" "math/big" "github.com/ethereum/go-ethereum/common" @@ -183,18 +182,31 @@ type Signer interface { // modernSigner is the signer implementation that handles non-legacy transaction types. // For legacy transactions, it defers to one of the legacy signers (frontier, homestead, eip155). type modernSigner struct { - txtypes map[byte]struct{} + txtypes txtypeSet chainID *big.Int legacy Signer } +// txtypeSet is a bitmap for transaction types. +type txtypeSet [2]uint64 + +func (v *txtypeSet) set(txType byte) { + v[txType/64] |= 1 << (txType % 64) +} + +func (v *txtypeSet) has(txType byte) bool { + if txType >= byte(len(v)*64) { + return false + } + return v[txType/64]&(1<<(txType%64)) != 0 +} + func newModernSigner(chainID *big.Int, fork forks.Fork) Signer { if chainID == nil || chainID.Sign() <= 0 { panic(fmt.Sprintf("invalid chainID %v", chainID)) } s := &modernSigner{ chainID: chainID, - txtypes: make(map[byte]struct{}, 4), } // configure legacy signer switch { @@ -205,19 +217,19 @@ func newModernSigner(chainID *big.Int, fork forks.Fork) Signer { default: s.legacy = FrontierSigner{} } - s.txtypes[LegacyTxType] = struct{}{} + s.txtypes.set(LegacyTxType) // configure tx types if fork >= forks.Berlin { - s.txtypes[AccessListTxType] = struct{}{} + s.txtypes.set(AccessListTxType) } if fork >= forks.London { - s.txtypes[DynamicFeeTxType] = struct{}{} + s.txtypes.set(DynamicFeeTxType) } if fork >= forks.Cancun { - s.txtypes[BlobTxType] = struct{}{} + s.txtypes.set(BlobTxType) } if fork >= forks.Prague { - s.txtypes[SetCodeTxType] = struct{}{} + s.txtypes.set(SetCodeTxType) } return s } @@ -228,7 +240,7 @@ func (s *modernSigner) ChainID() *big.Int { func (s *modernSigner) Equal(s2 Signer) bool { other, ok := s2.(*modernSigner) - return ok && s.chainID.Cmp(other.chainID) == 0 && maps.Equal(s.txtypes, other.txtypes) && s.legacy.Equal(other.legacy) + return ok && s.chainID.Cmp(other.chainID) == 0 && s.txtypes == other.txtypes && s.legacy.Equal(other.legacy) } func (s *modernSigner) Hash(tx *Transaction) common.Hash { @@ -236,8 +248,7 @@ func (s *modernSigner) Hash(tx *Transaction) common.Hash { } func (s *modernSigner) supportsType(txtype byte) bool { - _, ok := s.txtypes[txtype] - return ok + return s.txtypes.has(txtype) } func (s *modernSigner) Sender(tx *Transaction) (common.Address, error) { diff --git a/core/types/transaction_signing_test.go b/core/types/transaction_signing_test.go index b66577f7ed5..02a65fda139 100644 --- a/core/types/transaction_signing_test.go +++ b/core/types/transaction_signing_test.go @@ -25,6 +25,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/params/forks" "github.com/ethereum/go-ethereum/rlp" ) @@ -188,3 +189,14 @@ func createTestLegacyTxInner() *LegacyTx { Data: nil, } } + +func Benchmark_modernSigner_Equal(b *testing.B) { + signer1 := newModernSigner(big.NewInt(1), forks.Amsterdam) + signer2 := newModernSigner(big.NewInt(1), forks.Amsterdam) + + for b.Loop() { + if !signer1.Equal(signer2) { + b.Fatal("expected signers to be equal") + } + } +}