Skip to content

Commit deba80e

Browse files
committed
Include tx compression level in calldata units cache
1 parent de229c2 commit deba80e

File tree

2 files changed

+90
-2
lines changed

2 files changed

+90
-2
lines changed

core/types/transaction.go

+41-2
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,54 @@ type Transaction struct {
6464
inner TxData // Consensus contents of a transaction
6565
time time.Time // Time first seen locally (spam avoidance)
6666

67-
// Arbitrum cache: must be atomically accessed
68-
CalldataUnits uint64
67+
// Arbitrum cache of the calldata units at a brotli compression level.
68+
// The top 8 bits are the brotli compression level last used to compute this,
69+
// and the remaining 56 bits are the calldata units at that compression level.
70+
calldataUnitsForBrotliCompressionLevel atomic.Uint64
6971

7072
// caches
7173
hash atomic.Pointer[common.Hash]
7274
size atomic.Uint64
7375
from atomic.Pointer[sigCache]
7476
}
7577

78+
// GetRawCachedCalldataUnits returns the cached brotli compression level and corresponding calldata units,
79+
// or (0, 0) if the cache is empty.
80+
func (tx *Transaction) GetRawCachedCalldataUnits() (uint64, uint64) {
81+
repr := tx.calldataUnitsForBrotliCompressionLevel.Load()
82+
cachedCompressionLevel := repr >> 56
83+
calldataUnits := repr & ((1 << 56) - 1)
84+
return cachedCompressionLevel, calldataUnits
85+
}
86+
87+
// GetCachedCalldataUnits returns the cached calldata units for a given brotli compression level,
88+
// returning nil if no cache is present or the cache is for a different compression level.
89+
func (tx *Transaction) GetCachedCalldataUnits(requestedCompressionLevel uint64) *uint64 {
90+
cachedCompressionLevel, cachedUnits := tx.GetRawCachedCalldataUnits()
91+
if cachedUnits == 0 {
92+
// empty cache
93+
return nil
94+
}
95+
if cachedCompressionLevel != requestedCompressionLevel {
96+
// wrong compression level
97+
return nil
98+
}
99+
return &cachedUnits
100+
}
101+
102+
// SetCachedCalldataUnits sets the cached brotli compression level and corresponding calldata units,
103+
// or clears the cache if the values are too large to fit (at least 2**8 and 2**56 respectively).
104+
// Note that a zero calldataUnits is also treated as an empty cache.
105+
func (tx *Transaction) SetCachedCalldataUnits(compressionLevel uint64, calldataUnits uint64) {
106+
var repr uint64
107+
// Ensure the compressionLevel and calldataUnits will fit.
108+
// Otherwise, just clear the cache.
109+
if compressionLevel < 1<<8 && calldataUnits < 1<<56 {
110+
repr = uint64(compressionLevel)<<56 | calldataUnits
111+
}
112+
tx.calldataUnitsForBrotliCompressionLevel.Store(repr)
113+
}
114+
76115
// NewTx creates a new transaction.
77116
func NewTx(inner TxData) *Transaction {
78117
tx := new(Transaction)
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright 2014 The go-ethereum Authors
2+
// This file is part of the go-ethereum library.
3+
//
4+
// The go-ethereum library is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Lesser General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// The go-ethereum library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Lesser General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Lesser General Public License
15+
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package types
18+
19+
import "testing"
20+
21+
func TestTxCalldataUnitsCache(t *testing.T) {
22+
tx := &Transaction{}
23+
units := tx.GetCachedCalldataUnits(0)
24+
if units != nil {
25+
t.Errorf("unexpected initial cache present %v for compression 0", units)
26+
}
27+
units = tx.GetCachedCalldataUnits(1)
28+
if units != nil {
29+
t.Errorf("unexpected initial cache present %v for compression 1", units)
30+
}
31+
tx.SetCachedCalldataUnits(200, 1000)
32+
units = tx.GetCachedCalldataUnits(100)
33+
if units != nil {
34+
t.Errorf("unexpected cached units %v present for incorrect compression 100", units)
35+
}
36+
units = tx.GetCachedCalldataUnits(0)
37+
if units != nil {
38+
t.Errorf("unexpected cached units %v present for incorrect compression 0", units)
39+
}
40+
units = tx.GetCachedCalldataUnits(200)
41+
if units == nil || *units != 1000 {
42+
t.Errorf("unexpected cached units %v for correct compression 200", units)
43+
}
44+
tx.SetCachedCalldataUnits(1, 1<<60)
45+
units = tx.GetCachedCalldataUnits(1)
46+
if units != nil {
47+
t.Errorf("unexpected cache value %v present after reset", units)
48+
}
49+
}

0 commit comments

Comments
 (0)