Skip to content

Commit f02eb4f

Browse files
authored
execution/types: using defined struct to optimize sigHash (#18602)
Benchmark Code: ``` package types import ( "testing" "github.com/erigontech/erigon/common" "github.com/erigontech/erigon/common/u256" "github.com/holiman/uint256" ) // BenchmarkSigHash_DynamicFeeTx benchmarks the sigHash method for DynamicFeeTx // with all fields populated. func BenchmarkSigHash_DynamicFeeTx(b *testing.B) { to := common.HexToAddress("0x000000000000000000000000000000000000dead") tx := &DynamicFeeTransaction{ CommonTx: CommonTx{ Nonce: 3, To: &to, Value: uint256.NewInt(10), GasLimit: 25000, Data: common.FromHex("5544"), V: *uint256.NewInt(27), R: *uint256.NewInt(123456789), S: *uint256.NewInt(987654321), }, ChainID: uint256.NewInt(1), TipCap: uint256.NewInt(1_000_000_000), // 1 gwei FeeCap: uint256.NewInt(2_000_000_000), // 2 gwei AccessList: AccessList{ AccessTuple{ Address: common.HexToAddress("0x0000000000000000000000000000000000000001"), StorageKeys: []common.Hash{ common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001"), common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000002"), }, }, AccessTuple{ Address: common.HexToAddress("0x0000000000000000000000000000000000000002"), StorageKeys: []common.Hash{ common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000003"), }, }, }, } b.ResetTimer() for i := 0; i < b.N; i++ { _ = tx.SigningHash(tx.ChainID.ToBig()) } } // BenchmarkSigHash_AccessListTx benchmarks the sigHash method for AccessListTx // with all fields populated. func BenchmarkSigHash_AccessListTx(b *testing.B) { to := common.HexToAddress("0x000000000000000000000000000000000000dead") tx := &AccessListTx{ LegacyTx: LegacyTx{ CommonTx: CommonTx{ Nonce: 3, To: &to, Value: uint256.NewInt(10), GasLimit: 25000, Data: common.FromHex("5544"), V: *uint256.NewInt(27), R: *uint256.NewInt(123456789), S: *uint256.NewInt(987654321), }, GasPrice: uint256.NewInt(2_000_000_000), // 2 gwei }, ChainID: uint256.NewInt(1), AccessList: AccessList{ AccessTuple{ Address: common.HexToAddress("0x0000000000000000000000000000000000000001"), StorageKeys: []common.Hash{ common.HexToHash("0x01"), common.HexToHash("0x02"), }, }, AccessTuple{ Address: common.HexToAddress("0x0000000000000000000000000000000000000002"), StorageKeys: []common.Hash{ common.HexToHash("0x03"), }, }, }, } chainID := tx.ChainID.ToBig() for b.Loop() { _ = tx.SigningHash(chainID) } } // BenchmarkSigHash_LegacyTx benchmarks the sigHash method for LegacyTx // with all fields populated. func BenchmarkSigHash_LegacyTx(b *testing.B) { to := common.HexToAddress("0x000000000000000000000000000000000000dead") tx := &LegacyTx{ CommonTx: CommonTx{ Nonce: 42, To: &to, Value: uint256.NewInt(1_000_000_000_000_000_000), // 1 ether GasLimit: 21000, Data: []byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}, V: *uint256.NewInt(27), R: *uint256.NewInt(123456789), S: *uint256.NewInt(987654321), }, GasPrice: uint256.NewInt(2_000_000_000), // 2 gwei } b.ResetTimer() for i := 0; i < b.N; i++ { _ = tx.SigningHash(u256.Num1.ToBig()) } } // BenchmarkSigHash_BlobTx benchmarks the sigHash method for BlobTx // with all fields populated. func BenchmarkSigHash_BlobTx(b *testing.B) { to := common.HexToAddress("0x000000000000000000000000000000000000dead") tx := &BlobTx{ DynamicFeeTransaction: DynamicFeeTransaction{ CommonTx: CommonTx{ Nonce: 42, To: &to, Value: uint256.NewInt(1_000_000_000_000_000_000), // 1 ether GasLimit: 21000, Data: []byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}, V: *uint256.NewInt(27), R: *uint256.NewInt(123456789), S: *uint256.NewInt(987654321), }, ChainID: &u256.Num1, TipCap: uint256.NewInt(1_000_000_000), // 1 gwei FeeCap: uint256.NewInt(2_000_000_000), // 2 gwei AccessList: AccessList{ { Address: common.HexToAddress("0x0000000000000000000000000000000000000001"), StorageKeys: []common.Hash{ common.HexToHash("0x01"), common.HexToHash("0x02"), }, }, { Address: common.HexToAddress("0x0000000000000000000000000000000000000002"), StorageKeys: []common.Hash{ common.HexToHash("0x03"), }, }, }, }, MaxFeePerBlobGas: uint256.NewInt(100_000_000), BlobVersionedHashes: []common.Hash{ common.HexToHash("0x01"), common.HexToHash("0x02"), }, } b.ResetTimer() for i := 0; i < b.N; i++ { _ = tx.SigningHash(tx.ChainID.ToBig()) } } ``` Result: ``` goos: linux goarch: amd64 pkg: github.com/erigontech/erigon/execution/types cpu: Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz │ old_bench.txt │ new_bench.txt │ │ sec/op │ sec/op vs base │ SigHash_DynamicFeeTx-8 2.274µ ± 2% 1.849µ ± 3% -18.69% (p=0.000 n=10) SigHash_AccessListTx-8 2.125µ ± 1% 1.755µ ± 3% -17.39% (p=0.000 n=10) SigHash_LegacyTx-8 1379.5n ± 5% 913.4n ± 2% -33.79% (p=0.000 n=10) SigHash_BlobTx-8 3.079µ ± 2% 2.599µ ± 5% -15.58% (p=0.000 n=10) geomean 2.128µ 1.666µ -21.72% │ old_bench.txt │ new_bench.txt │ │ B/op │ B/op vs base │ SigHash_DynamicFeeTx-8 328.0 ± 0% 209.0 ± 0% -36.28% (p=0.000 n=10) SigHash_AccessListTx-8 248.0 ± 0% 129.0 ± 0% -47.98% (p=0.000 n=10) SigHash_LegacyTx-8 296.0 ± 0% 192.0 ± 0% -35.14% (p=0.000 n=10) SigHash_BlobTx-8 384.0 ± 0% 241.0 ± 0% -37.24% (p=0.000 n=10) geomean 310.1 187.9 -39.39% │ old_bench.txt │ new_bench.txt │ │ allocs/op │ allocs/op vs base │ SigHash_DynamicFeeTx-8 9.000 ± 0% 5.000 ± 0% -44.44% (p=0.000 n=10) SigHash_AccessListTx-8 7.000 ± 0% 3.000 ± 0% -57.14% (p=0.000 n=10) SigHash_LegacyTx-8 7.000 ± 0% 4.000 ± 0% -42.86% (p=0.000 n=10) SigHash_BlobTx-8 10.000 ± 0% 5.000 ± 0% -50.00% (p=0.000 n=10) geomean 8.149 4.162 -48.93% ```
1 parent 9db4598 commit f02eb4f

5 files changed

Lines changed: 114 additions & 50 deletions

File tree

execution/types/access_list_tx.go

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -462,18 +462,29 @@ func (tx *AccessListTx) Hash() common.Hash {
462462
return hash
463463
}
464464

465+
type accessListTxSigHash struct {
466+
ChainID *big.Int
467+
Nonce uint64
468+
GasPrice *uint256.Int
469+
Gas uint64
470+
To *common.Address `rlp:"nil"`
471+
Value *uint256.Int
472+
Data []byte
473+
AccessList AccessList
474+
}
475+
465476
func (tx *AccessListTx) SigningHash(chainID *big.Int) common.Hash {
466477
return prefixedRlpHash(
467478
AccessListTxType,
468-
[]any{
469-
chainID,
470-
tx.Nonce,
471-
tx.GasPrice,
472-
tx.GasLimit,
473-
tx.To,
474-
tx.Value,
475-
tx.Data,
476-
tx.AccessList,
479+
&accessListTxSigHash{
480+
ChainID: chainID,
481+
Nonce: tx.Nonce,
482+
GasPrice: tx.GasPrice,
483+
Gas: tx.GasLimit,
484+
To: tx.To,
485+
Value: tx.Value,
486+
Data: tx.Data,
487+
AccessList: tx.AccessList,
477488
})
478489
}
479490

execution/types/blob_tx.go

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -135,21 +135,35 @@ func (stx *BlobTx) Hash() common.Hash {
135135
return hash
136136
}
137137

138+
type blobTxSigHash struct {
139+
ChainID *big.Int
140+
Nonce uint64
141+
GasTipCap *uint256.Int
142+
GasFeeCap *uint256.Int
143+
Gas uint64
144+
To *common.Address
145+
Value *uint256.Int
146+
Data []byte
147+
AccessList AccessList
148+
BlobFeeCap *uint256.Int
149+
BlobHashes []common.Hash
150+
}
151+
138152
func (stx *BlobTx) SigningHash(chainID *big.Int) common.Hash {
139153
return prefixedRlpHash(
140154
BlobTxType,
141-
[]any{
142-
chainID,
143-
stx.Nonce,
144-
stx.TipCap,
145-
stx.FeeCap,
146-
stx.GasLimit,
147-
stx.To,
148-
stx.Value,
149-
stx.Data,
150-
stx.AccessList,
151-
stx.MaxFeePerBlobGas,
152-
stx.BlobVersionedHashes,
155+
&blobTxSigHash{
156+
ChainID: chainID,
157+
Nonce: stx.Nonce,
158+
GasTipCap: stx.TipCap,
159+
GasFeeCap: stx.FeeCap,
160+
Gas: stx.GasLimit,
161+
To: stx.To,
162+
Value: stx.Value,
163+
Data: stx.Data,
164+
AccessList: stx.AccessList,
165+
BlobFeeCap: stx.MaxFeePerBlobGas,
166+
BlobHashes: stx.BlobVersionedHashes,
153167
})
154168
}
155169

execution/types/dynamic_fee_tx.go

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -379,19 +379,31 @@ func (tx *DynamicFeeTransaction) Hash() common.Hash {
379379
return hash
380380
}
381381

382+
type dynamicFeeTxSigHash struct {
383+
ChainID *big.Int
384+
Nonce uint64
385+
GasTipCap *uint256.Int
386+
GasFeeCap *uint256.Int
387+
Gas uint64
388+
To *common.Address `rlp:"nil"`
389+
Value *uint256.Int
390+
Data []byte
391+
AccessList AccessList
392+
}
393+
382394
func (tx *DynamicFeeTransaction) SigningHash(chainID *big.Int) common.Hash {
383395
return prefixedRlpHash(
384396
DynamicFeeTxType,
385-
[]any{
386-
chainID,
387-
tx.Nonce,
388-
tx.TipCap,
389-
tx.FeeCap,
390-
tx.GasLimit,
391-
tx.To,
392-
tx.Value,
393-
tx.Data,
394-
tx.AccessList,
397+
&dynamicFeeTxSigHash{
398+
ChainID: chainID,
399+
Nonce: tx.Nonce,
400+
GasTipCap: tx.TipCap,
401+
GasFeeCap: tx.FeeCap,
402+
Gas: tx.GasLimit,
403+
To: tx.To,
404+
Value: tx.Value,
405+
Data: tx.Data,
406+
AccessList: tx.AccessList,
395407
})
396408
}
397409

execution/types/legacy_tx.go

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -384,16 +384,30 @@ func (tx *LegacyTx) Hash() common.Hash {
384384
return hash
385385
}
386386

387+
type legacyTxSigHash struct {
388+
Nonce uint64
389+
GasPrice *uint256.Int
390+
Gas uint64
391+
To *common.Address `rlp:"nil"`
392+
Value *uint256.Int
393+
Data []byte
394+
ChainID *big.Int
395+
V uint
396+
R uint
397+
}
398+
387399
func (tx *LegacyTx) SigningHash(chainID *big.Int) common.Hash {
388400
if chainID != nil && chainID.Sign() != 0 {
389-
return rlpHash([]any{
390-
tx.Nonce,
391-
tx.GasPrice,
392-
tx.GasLimit,
393-
tx.To,
394-
tx.Value,
395-
tx.Data,
396-
chainID, uint(0), uint(0),
401+
return rlpHash(&legacyTxSigHash{
402+
Nonce: tx.Nonce,
403+
GasPrice: tx.GasPrice,
404+
Gas: tx.GasLimit,
405+
To: tx.To,
406+
Value: tx.Value,
407+
Data: tx.Data,
408+
ChainID: chainID,
409+
V: uint(0),
410+
R: uint(0),
397411
})
398412
}
399413
return rlpHash([]any{

execution/types/set_code_tx.go

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -196,20 +196,33 @@ func (tx *SetCodeTransaction) Hash() common.Hash {
196196
return hash
197197
}
198198

199+
type setCodeTxSigHash struct {
200+
ChainID *big.Int
201+
Nonce uint64
202+
GasTipCap *uint256.Int
203+
GasFeeCap *uint256.Int
204+
Gas uint64
205+
To *common.Address
206+
Value *uint256.Int
207+
Data []byte
208+
AccessList AccessList
209+
AuthList []Authorization
210+
}
211+
199212
func (tx *SetCodeTransaction) SigningHash(chainID *big.Int) common.Hash {
200213
return prefixedRlpHash(
201214
SetCodeTxType,
202-
[]any{
203-
chainID,
204-
tx.Nonce,
205-
tx.TipCap,
206-
tx.FeeCap,
207-
tx.GasLimit,
208-
tx.To,
209-
tx.Value,
210-
tx.Data,
211-
tx.AccessList,
212-
tx.Authorizations,
215+
&setCodeTxSigHash{
216+
ChainID: chainID,
217+
Nonce: tx.Nonce,
218+
GasTipCap: tx.TipCap,
219+
GasFeeCap: tx.FeeCap,
220+
Gas: tx.GasLimit,
221+
To: tx.To,
222+
Value: tx.Value,
223+
Data: tx.Data,
224+
AccessList: tx.AccessList,
225+
AuthList: tx.Authorizations,
213226
})
214227
}
215228

0 commit comments

Comments
 (0)