Skip to content

Commit 33dbd64

Browse files
cuiweixiefjl
andauthored
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 <[email protected]>
1 parent 447b5f7 commit 33dbd64

File tree

2 files changed

+34
-11
lines changed

2 files changed

+34
-11
lines changed

core/types/transaction_signing.go

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"crypto/ecdsa"
2121
"errors"
2222
"fmt"
23-
"maps"
2423
"math/big"
2524

2625
"github.com/ethereum/go-ethereum/common"
@@ -183,18 +182,31 @@ type Signer interface {
183182
// modernSigner is the signer implementation that handles non-legacy transaction types.
184183
// For legacy transactions, it defers to one of the legacy signers (frontier, homestead, eip155).
185184
type modernSigner struct {
186-
txtypes map[byte]struct{}
185+
txtypes txtypeSet
187186
chainID *big.Int
188187
legacy Signer
189188
}
190189

190+
// txtypeSet is a bitmap for transaction types.
191+
type txtypeSet [2]uint64
192+
193+
func (v *txtypeSet) set(txType byte) {
194+
v[txType/64] |= 1 << (txType % 64)
195+
}
196+
197+
func (v *txtypeSet) has(txType byte) bool {
198+
if txType >= byte(len(v)*64) {
199+
return false
200+
}
201+
return v[txType/64]&(1<<(txType%64)) != 0
202+
}
203+
191204
func newModernSigner(chainID *big.Int, fork forks.Fork) Signer {
192205
if chainID == nil || chainID.Sign() <= 0 {
193206
panic(fmt.Sprintf("invalid chainID %v", chainID))
194207
}
195208
s := &modernSigner{
196209
chainID: chainID,
197-
txtypes: make(map[byte]struct{}, 4),
198210
}
199211
// configure legacy signer
200212
switch {
@@ -205,19 +217,19 @@ func newModernSigner(chainID *big.Int, fork forks.Fork) Signer {
205217
default:
206218
s.legacy = FrontierSigner{}
207219
}
208-
s.txtypes[LegacyTxType] = struct{}{}
220+
s.txtypes.set(LegacyTxType)
209221
// configure tx types
210222
if fork >= forks.Berlin {
211-
s.txtypes[AccessListTxType] = struct{}{}
223+
s.txtypes.set(AccessListTxType)
212224
}
213225
if fork >= forks.London {
214-
s.txtypes[DynamicFeeTxType] = struct{}{}
226+
s.txtypes.set(DynamicFeeTxType)
215227
}
216228
if fork >= forks.Cancun {
217-
s.txtypes[BlobTxType] = struct{}{}
229+
s.txtypes.set(BlobTxType)
218230
}
219231
if fork >= forks.Prague {
220-
s.txtypes[SetCodeTxType] = struct{}{}
232+
s.txtypes.set(SetCodeTxType)
221233
}
222234
return s
223235
}
@@ -228,16 +240,15 @@ func (s *modernSigner) ChainID() *big.Int {
228240

229241
func (s *modernSigner) Equal(s2 Signer) bool {
230242
other, ok := s2.(*modernSigner)
231-
return ok && s.chainID.Cmp(other.chainID) == 0 && maps.Equal(s.txtypes, other.txtypes) && s.legacy.Equal(other.legacy)
243+
return ok && s.chainID.Cmp(other.chainID) == 0 && s.txtypes == other.txtypes && s.legacy.Equal(other.legacy)
232244
}
233245

234246
func (s *modernSigner) Hash(tx *Transaction) common.Hash {
235247
return tx.inner.sigHash(s.chainID)
236248
}
237249

238250
func (s *modernSigner) supportsType(txtype byte) bool {
239-
_, ok := s.txtypes[txtype]
240-
return ok
251+
return s.txtypes.has(txtype)
241252
}
242253

243254
func (s *modernSigner) Sender(tx *Transaction) (common.Address, error) {

core/types/transaction_signing_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/ethereum/go-ethereum/common"
2626
"github.com/ethereum/go-ethereum/crypto"
2727
"github.com/ethereum/go-ethereum/params"
28+
"github.com/ethereum/go-ethereum/params/forks"
2829
"github.com/ethereum/go-ethereum/rlp"
2930
)
3031

@@ -188,3 +189,14 @@ func createTestLegacyTxInner() *LegacyTx {
188189
Data: nil,
189190
}
190191
}
192+
193+
func Benchmark_modernSigner_Equal(b *testing.B) {
194+
signer1 := newModernSigner(big.NewInt(1), forks.Amsterdam)
195+
signer2 := newModernSigner(big.NewInt(1), forks.Amsterdam)
196+
197+
for b.Loop() {
198+
if !signer1.Equal(signer2) {
199+
b.Fatal("expected signers to be equal")
200+
}
201+
}
202+
}

0 commit comments

Comments
 (0)