From a851e39cbecf116ef2dc64f0b37b0300dc762931 Mon Sep 17 00:00:00 2001 From: lmittmann <3458786+lmittmann@users.noreply.github.com> Date: Thu, 4 Apr 2024 15:50:31 +0200 Subject: [PATCH] core/types: use new atomic types in caches (#29411) * use generic atomic types in tx caches * use generic atomic types in block caches * eth/catalyst: avoid copying tx in test --------- Co-authored-by: lmittmann Co-authored-by: Felix Lange --- core/types/block.go | 16 ++++++++-------- core/types/transaction.go | 14 +++++++------- core/types/transaction_signing.go | 5 ++--- eth/catalyst/simulated_beacon_test.go | 4 ++-- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/core/types/block.go b/core/types/block.go index 1a357baa3a..53054f52d3 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -197,8 +197,8 @@ type Block struct { withdrawals Withdrawals // caches - hash atomic.Value - size atomic.Value + hash atomic.Pointer[common.Hash] + size atomic.Uint64 // These fields are used by package eth to track // inter-peer block relay. @@ -406,8 +406,8 @@ func (b *Block) BlobGasUsed() *uint64 { // Size returns the true RLP encoded storage size of the block, either by encoding // and returning it, or returning a previously cached value. func (b *Block) Size() uint64 { - if size := b.size.Load(); size != nil { - return size.(uint64) + if size := b.size.Load(); size > 0 { + return size } c := writeCounter(0) rlp.Encode(&c, b) @@ -486,11 +486,11 @@ func (b *Block) WithWithdrawals(withdrawals []*Withdrawal) *Block { // The hash is computed on the first call and cached thereafter. func (b *Block) Hash() common.Hash { if hash := b.hash.Load(); hash != nil { - return hash.(common.Hash) + return *hash } - v := b.header.Hash() - b.hash.Store(v) - return v + h := b.header.Hash() + b.hash.Store(&h) + return h } type Blocks []*Block diff --git a/core/types/transaction.go b/core/types/transaction.go index 7d2e9d5325..d6de9ae73e 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -57,9 +57,9 @@ type Transaction struct { time time.Time // Time first seen locally (spam avoidance) // caches - hash atomic.Value - size atomic.Value - from atomic.Value + hash atomic.Pointer[common.Hash] + size atomic.Uint64 + from atomic.Pointer[sigCache] } // NewTx creates a new transaction. @@ -462,7 +462,7 @@ func (tx *Transaction) Time() time.Time { // Hash returns the transaction hash. func (tx *Transaction) Hash() common.Hash { if hash := tx.hash.Load(); hash != nil { - return hash.(common.Hash) + return *hash } var h common.Hash @@ -471,15 +471,15 @@ func (tx *Transaction) Hash() common.Hash { } else { h = prefixedRlpHash(tx.Type(), tx.inner) } - tx.hash.Store(h) + tx.hash.Store(&h) return h } // Size returns the true encoded storage size of the transaction, either by encoding // and returning it, or returning a previously cached value. func (tx *Transaction) Size() uint64 { - if size := tx.size.Load(); size != nil { - return size.(uint64) + if size := tx.size.Load(); size > 0 { + return size } // Cache miss, encode and cache. diff --git a/core/types/transaction_signing.go b/core/types/transaction_signing.go index 70dee0776e..6e5f6712f8 100644 --- a/core/types/transaction_signing.go +++ b/core/types/transaction_signing.go @@ -128,8 +128,7 @@ func MustSignNewTx(prv *ecdsa.PrivateKey, s Signer, txdata TxData) *Transaction // signing method. The cache is invalidated if the cached signer does // not match the signer used in the current call. func Sender(signer Signer, tx *Transaction) (common.Address, error) { - if sc := tx.from.Load(); sc != nil { - sigCache := sc.(sigCache) + if sigCache := tx.from.Load(); sigCache != nil { // If the signer used to derive from in a previous // call is not the same as used current, invalidate // the cache. @@ -142,7 +141,7 @@ func Sender(signer Signer, tx *Transaction) (common.Address, error) { if err != nil { return common.Address{}, err } - tx.from.Store(sigCache{signer: signer, from: addr}) + tx.from.Store(&sigCache{signer: signer, from: addr}) return addr, nil } diff --git a/eth/catalyst/simulated_beacon_test.go b/eth/catalyst/simulated_beacon_test.go index df682b49d9..bb10938c35 100644 --- a/eth/catalyst/simulated_beacon_test.go +++ b/eth/catalyst/simulated_beacon_test.go @@ -74,7 +74,7 @@ func startSimulatedBeaconEthService(t *testing.T, genesis *core.Genesis) (*node. // send enough transactions to fill multiple blocks func TestSimulatedBeaconSendWithdrawals(t *testing.T) { var withdrawals []types.Withdrawal - txs := make(map[common.Hash]types.Transaction) + txs := make(map[common.Hash]*types.Transaction) var ( // testKey is a private key to use for funding a tester account. @@ -110,7 +110,7 @@ func TestSimulatedBeaconSendWithdrawals(t *testing.T) { if err != nil { t.Fatalf("error signing transaction, err=%v", err) } - txs[tx.Hash()] = *tx + txs[tx.Hash()] = tx if err := ethService.APIBackend.SendTx(context.Background(), tx); err != nil { t.Fatal("SendTx failed", err)