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 <lmittmann@users.noreply.github.com>
Co-authored-by: Felix Lange <fjl@twurst.com>
This commit is contained in:
lmittmann 2024-04-04 15:50:31 +02:00 committed by GitHub
parent 9cb8de8703
commit a851e39cbe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 19 additions and 20 deletions

@ -197,8 +197,8 @@ type Block struct {
withdrawals Withdrawals withdrawals Withdrawals
// caches // caches
hash atomic.Value hash atomic.Pointer[common.Hash]
size atomic.Value size atomic.Uint64
// These fields are used by package eth to track // These fields are used by package eth to track
// inter-peer block relay. // 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 // Size returns the true RLP encoded storage size of the block, either by encoding
// and returning it, or returning a previously cached value. // and returning it, or returning a previously cached value.
func (b *Block) Size() uint64 { func (b *Block) Size() uint64 {
if size := b.size.Load(); size != nil { if size := b.size.Load(); size > 0 {
return size.(uint64) return size
} }
c := writeCounter(0) c := writeCounter(0)
rlp.Encode(&c, b) 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. // The hash is computed on the first call and cached thereafter.
func (b *Block) Hash() common.Hash { func (b *Block) Hash() common.Hash {
if hash := b.hash.Load(); hash != nil { if hash := b.hash.Load(); hash != nil {
return hash.(common.Hash) return *hash
} }
v := b.header.Hash() h := b.header.Hash()
b.hash.Store(v) b.hash.Store(&h)
return v return h
} }
type Blocks []*Block type Blocks []*Block

@ -57,9 +57,9 @@ type Transaction struct {
time time.Time // Time first seen locally (spam avoidance) time time.Time // Time first seen locally (spam avoidance)
// caches // caches
hash atomic.Value hash atomic.Pointer[common.Hash]
size atomic.Value size atomic.Uint64
from atomic.Value from atomic.Pointer[sigCache]
} }
// NewTx creates a new transaction. // NewTx creates a new transaction.
@ -462,7 +462,7 @@ func (tx *Transaction) Time() time.Time {
// Hash returns the transaction hash. // Hash returns the transaction hash.
func (tx *Transaction) Hash() common.Hash { func (tx *Transaction) Hash() common.Hash {
if hash := tx.hash.Load(); hash != nil { if hash := tx.hash.Load(); hash != nil {
return hash.(common.Hash) return *hash
} }
var h common.Hash var h common.Hash
@ -471,15 +471,15 @@ func (tx *Transaction) Hash() common.Hash {
} else { } else {
h = prefixedRlpHash(tx.Type(), tx.inner) h = prefixedRlpHash(tx.Type(), tx.inner)
} }
tx.hash.Store(h) tx.hash.Store(&h)
return h return h
} }
// Size returns the true encoded storage size of the transaction, either by encoding // Size returns the true encoded storage size of the transaction, either by encoding
// and returning it, or returning a previously cached value. // and returning it, or returning a previously cached value.
func (tx *Transaction) Size() uint64 { func (tx *Transaction) Size() uint64 {
if size := tx.size.Load(); size != nil { if size := tx.size.Load(); size > 0 {
return size.(uint64) return size
} }
// Cache miss, encode and cache. // Cache miss, encode and cache.

@ -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 // signing method. The cache is invalidated if the cached signer does
// not match the signer used in the current call. // not match the signer used in the current call.
func Sender(signer Signer, tx *Transaction) (common.Address, error) { func Sender(signer Signer, tx *Transaction) (common.Address, error) {
if sc := tx.from.Load(); sc != nil { if sigCache := tx.from.Load(); sigCache != nil {
sigCache := sc.(sigCache)
// If the signer used to derive from in a previous // If the signer used to derive from in a previous
// call is not the same as used current, invalidate // call is not the same as used current, invalidate
// the cache. // the cache.
@ -142,7 +141,7 @@ func Sender(signer Signer, tx *Transaction) (common.Address, error) {
if err != nil { if err != nil {
return common.Address{}, err return common.Address{}, err
} }
tx.from.Store(sigCache{signer: signer, from: addr}) tx.from.Store(&sigCache{signer: signer, from: addr})
return addr, nil return addr, nil
} }

@ -74,7 +74,7 @@ func startSimulatedBeaconEthService(t *testing.T, genesis *core.Genesis) (*node.
// send enough transactions to fill multiple blocks // send enough transactions to fill multiple blocks
func TestSimulatedBeaconSendWithdrawals(t *testing.T) { func TestSimulatedBeaconSendWithdrawals(t *testing.T) {
var withdrawals []types.Withdrawal var withdrawals []types.Withdrawal
txs := make(map[common.Hash]types.Transaction) txs := make(map[common.Hash]*types.Transaction)
var ( var (
// testKey is a private key to use for funding a tester account. // testKey is a private key to use for funding a tester account.
@ -110,7 +110,7 @@ func TestSimulatedBeaconSendWithdrawals(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("error signing transaction, err=%v", err) 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 { if err := ethService.APIBackend.SendTx(context.Background(), tx); err != nil {
t.Fatal("SendTx failed", err) t.Fatal("SendTx failed", err)