mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-03 23:02:55 +00:00
core/types: optimize modernSigner.Equal (#32971)
Equal is called every time the transaction sender is accessed, even when the sender is cached, so it is worth optimizing. --------- Co-authored-by: Felix Lange <fjl@twurst.com>
This commit is contained in:
parent
447b5f7e19
commit
33dbd64a23
2 changed files with 34 additions and 11 deletions
|
|
@ -20,7 +20,6 @@ import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"maps"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
|
@ -183,18 +182,31 @@ type Signer interface {
|
||||||
// modernSigner is the signer implementation that handles non-legacy transaction types.
|
// 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).
|
// For legacy transactions, it defers to one of the legacy signers (frontier, homestead, eip155).
|
||||||
type modernSigner struct {
|
type modernSigner struct {
|
||||||
txtypes map[byte]struct{}
|
txtypes txtypeSet
|
||||||
chainID *big.Int
|
chainID *big.Int
|
||||||
legacy Signer
|
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 {
|
func newModernSigner(chainID *big.Int, fork forks.Fork) Signer {
|
||||||
if chainID == nil || chainID.Sign() <= 0 {
|
if chainID == nil || chainID.Sign() <= 0 {
|
||||||
panic(fmt.Sprintf("invalid chainID %v", chainID))
|
panic(fmt.Sprintf("invalid chainID %v", chainID))
|
||||||
}
|
}
|
||||||
s := &modernSigner{
|
s := &modernSigner{
|
||||||
chainID: chainID,
|
chainID: chainID,
|
||||||
txtypes: make(map[byte]struct{}, 4),
|
|
||||||
}
|
}
|
||||||
// configure legacy signer
|
// configure legacy signer
|
||||||
switch {
|
switch {
|
||||||
|
|
@ -205,19 +217,19 @@ func newModernSigner(chainID *big.Int, fork forks.Fork) Signer {
|
||||||
default:
|
default:
|
||||||
s.legacy = FrontierSigner{}
|
s.legacy = FrontierSigner{}
|
||||||
}
|
}
|
||||||
s.txtypes[LegacyTxType] = struct{}{}
|
s.txtypes.set(LegacyTxType)
|
||||||
// configure tx types
|
// configure tx types
|
||||||
if fork >= forks.Berlin {
|
if fork >= forks.Berlin {
|
||||||
s.txtypes[AccessListTxType] = struct{}{}
|
s.txtypes.set(AccessListTxType)
|
||||||
}
|
}
|
||||||
if fork >= forks.London {
|
if fork >= forks.London {
|
||||||
s.txtypes[DynamicFeeTxType] = struct{}{}
|
s.txtypes.set(DynamicFeeTxType)
|
||||||
}
|
}
|
||||||
if fork >= forks.Cancun {
|
if fork >= forks.Cancun {
|
||||||
s.txtypes[BlobTxType] = struct{}{}
|
s.txtypes.set(BlobTxType)
|
||||||
}
|
}
|
||||||
if fork >= forks.Prague {
|
if fork >= forks.Prague {
|
||||||
s.txtypes[SetCodeTxType] = struct{}{}
|
s.txtypes.set(SetCodeTxType)
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
@ -228,7 +240,7 @@ func (s *modernSigner) ChainID() *big.Int {
|
||||||
|
|
||||||
func (s *modernSigner) Equal(s2 Signer) bool {
|
func (s *modernSigner) Equal(s2 Signer) bool {
|
||||||
other, ok := s2.(*modernSigner)
|
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 {
|
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 {
|
func (s *modernSigner) supportsType(txtype byte) bool {
|
||||||
_, ok := s.txtypes[txtype]
|
return s.txtypes.has(txtype)
|
||||||
return ok
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *modernSigner) Sender(tx *Transaction) (common.Address, error) {
|
func (s *modernSigner) Sender(tx *Transaction) (common.Address, error) {
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"github.com/ethereum/go-ethereum/params/forks"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -188,3 +189,14 @@ func createTestLegacyTxInner() *LegacyTx {
|
||||||
Data: nil,
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue