Skip to content

Commit e95e52f

Browse files
committed
Merge branch 'main' into arr4n/min-gas-spend
2 parents 632db38 + 2672fbd commit e95e52f

File tree

19 files changed

+5368
-239
lines changed

19 files changed

+5368
-239
lines changed

core/state/snapshot/snapshot.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,8 @@ func (t *Tree) disklayer() *diskLayer {
832832
case *diskLayer:
833833
return layer
834834
case *diffLayer:
835+
layer.lock.RLock()
836+
defer layer.lock.RUnlock()
835837
return layer.origin
836838
default:
837839
panic(fmt.Sprintf("%T: undefined layer", snap))
@@ -863,7 +865,7 @@ func (t *Tree) generating() (bool, error) {
863865
return layer.genMarker != nil, nil
864866
}
865867

866-
// DiskRoot is a external helper function to return the disk layer root.
868+
// DiskRoot is an external helper function to return the disk layer root.
867869
func (t *Tree) DiskRoot() common.Hash {
868870
t.lock.Lock()
869871
defer t.lock.Unlock()

core/state/statedb.go

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package state
1919

2020
import (
2121
"fmt"
22+
"maps"
2223
"sort"
2324
"time"
2425

@@ -693,18 +694,18 @@ func (s *StateDB) Copy() *StateDB {
693694
db: s.db,
694695
trie: s.db.CopyTrie(s.trie),
695696
originalRoot: s.originalRoot,
696-
accounts: make(map[common.Hash][]byte),
697-
storages: make(map[common.Hash]map[common.Hash][]byte),
698-
accountsOrigin: make(map[common.Address][]byte),
699-
storagesOrigin: make(map[common.Address]map[common.Hash][]byte),
697+
accounts: copySet(s.accounts),
698+
storages: copy2DSet(s.storages),
699+
accountsOrigin: copySet(s.accountsOrigin),
700+
storagesOrigin: copy2DSet(s.storagesOrigin),
700701
stateObjects: make(map[common.Address]*stateObject, len(s.journal.dirties)),
701702
stateObjectsPending: make(map[common.Address]struct{}, len(s.stateObjectsPending)),
702703
stateObjectsDirty: make(map[common.Address]struct{}, len(s.journal.dirties)),
703-
stateObjectsDestruct: make(map[common.Address]*types.StateAccount, len(s.stateObjectsDestruct)),
704+
stateObjectsDestruct: maps.Clone(s.stateObjectsDestruct),
704705
refund: s.refund,
705706
logs: make(map[common.Hash][]*types.Log, len(s.logs)),
706707
logSize: s.logSize,
707-
preimages: make(map[common.Hash][]byte, len(s.preimages)),
708+
preimages: maps.Clone(s.preimages),
708709
journal: newJournal(),
709710
hasher: crypto.NewKeccakState(),
710711

@@ -747,16 +748,6 @@ func (s *StateDB) Copy() *StateDB {
747748
}
748749
state.stateObjectsDirty[addr] = struct{}{}
749750
}
750-
// Deep copy the destruction markers.
751-
for addr, value := range s.stateObjectsDestruct {
752-
state.stateObjectsDestruct[addr] = value
753-
}
754-
// Deep copy the state changes made in the scope of block
755-
// along with their original values.
756-
state.accounts = copySet(s.accounts)
757-
state.storages = copy2DSet(s.storages)
758-
state.accountsOrigin = copySet(state.accountsOrigin)
759-
state.storagesOrigin = copy2DSet(state.storagesOrigin)
760751

761752
// Deep copy the logs occurred in the scope of block
762753
for hash, logs := range s.logs {
@@ -767,10 +758,7 @@ func (s *StateDB) Copy() *StateDB {
767758
}
768759
state.logs[hash] = cpy
769760
}
770-
// Deep copy the preimages occurred in the scope of block
771-
for hash, preimage := range s.preimages {
772-
state.preimages[hash] = preimage
773-
}
761+
774762
// Do we need to copy the access list and transient storage?
775763
// In practice: No. At the start of a transaction, these two lists are empty.
776764
// In practice, we only ever copy state _between_ transactions/blocks, never

crypto/crypto.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,9 @@ func UnmarshalPubkey(pub []byte) (*ecdsa.PublicKey, error) {
169169
if x == nil {
170170
return nil, errInvalidPubkey
171171
}
172+
if !S256().IsOnCurve(x, y) {
173+
return nil, errInvalidPubkey
174+
}
172175
return &ecdsa.PublicKey{Curve: S256(), X: x, Y: y}, nil
173176
}
174177

eth/gasprice/feehistory.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ const (
4242
// maxBlockFetchers is the max number of goroutines to spin up to pull blocks
4343
// for the fee history calculation (mostly relevant for LES).
4444
maxBlockFetchers = 4
45+
maxQueryLimit = 100
4546
)
4647

4748
// blockFees represents a single block for processing
@@ -219,6 +220,9 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks uint64, unresolvedL
219220
if len(rewardPercentiles) != 0 {
220221
maxFeeHistory = oracle.maxBlockHistory
221222
}
223+
if len(rewardPercentiles) > maxQueryLimit {
224+
return common.Big0, nil, nil, nil, fmt.Errorf("%w: over the query limit %d", errInvalidPercentile, maxQueryLimit)
225+
}
222226
if blocks > maxFeeHistory {
223227
log.Warn("Sanitizing fee history length", "requested", blocks, "truncated", maxFeeHistory)
224228
blocks = maxFeeHistory

internal/build/download.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,12 @@ func (db *ChecksumDB) DownloadFile(url, dstPath string) error {
8484
resp, err := http.Get(url)
8585
if err != nil {
8686
return fmt.Errorf("download error: %v", err)
87-
} else if resp.StatusCode != http.StatusOK {
88-
return fmt.Errorf("download error: status %d", resp.StatusCode)
8987
}
9088
defer resp.Body.Close()
89+
90+
if resp.StatusCode != http.StatusOK {
91+
return fmt.Errorf("download error: status %d", resp.StatusCode)
92+
}
9193
if err := os.MkdirAll(filepath.Dir(dstPath), 0755); err != nil {
9294
return err
9395
}

internal/ethapi/api.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1992,7 +1992,7 @@ func (api *DebugAPI) GetRawHeader(ctx context.Context, blockNrOrHash rpc.BlockNu
19921992
hash = h
19931993
} else {
19941994
block, err := api.b.BlockByNumberOrHash(ctx, blockNrOrHash)
1995-
if err != nil {
1995+
if block == nil || err != nil {
19961996
return nil, err
19971997
}
19981998
hash = block.Hash()
@@ -2011,7 +2011,7 @@ func (api *DebugAPI) GetRawBlock(ctx context.Context, blockNrOrHash rpc.BlockNum
20112011
hash = h
20122012
} else {
20132013
block, err := api.b.BlockByNumberOrHash(ctx, blockNrOrHash)
2014-
if err != nil {
2014+
if block == nil || err != nil {
20152015
return nil, err
20162016
}
20172017
hash = block.Hash()
@@ -2030,7 +2030,7 @@ func (api *DebugAPI) GetRawReceipts(ctx context.Context, blockNrOrHash rpc.Block
20302030
hash = h
20312031
} else {
20322032
block, err := api.b.BlockByNumberOrHash(ctx, blockNrOrHash)
2033-
if err != nil {
2033+
if block == nil || err != nil {
20342034
return nil, err
20352035
}
20362036
hash = block.Hash()
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// Copyright 2025 the libevm authors.
2+
//
3+
// The libevm additions to go-ethereum are free software: you can redistribute
4+
// them and/or modify them under the terms of the GNU Lesser General Public License
5+
// as published by the Free Software Foundation, either version 3 of the License,
6+
// or (at your option) any later version.
7+
//
8+
// The libevm additions are distributed in the hope that they will be useful,
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
11+
// General Public License for more details.
12+
//
13+
// You should have received a copy of the GNU Lesser General Public License
14+
// along with the go-ethereum library. If not, see
15+
// <http://www.gnu.org/licenses/>.
16+
17+
// Package p256verify implements an EVM precompile to verify P256 ECDSA
18+
// signatures, as described in RIP-7212.
19+
package p256verify
20+
21+
import (
22+
"crypto/ecdsa"
23+
"crypto/elliptic"
24+
"math/big"
25+
26+
"github.com/ava-labs/libevm/params"
27+
)
28+
29+
// Precompile implements ECDSA verification on the P256 curve, as defined by
30+
// [RIP-7212].
31+
//
32+
// [RIP-7212]: https://github.com/ethereum/RIPs/blob/1f55794f65caa4c4bb2b8d9bda7d713b8c734157/RIPS/rip-7212.md
33+
type Precompile struct{}
34+
35+
// RequiredGas returns [params.P256VerifyGas].
36+
func (Precompile) RequiredGas([]byte) uint64 {
37+
return params.P256VerifyGas
38+
}
39+
40+
const (
41+
wordLen = 32
42+
inputLen = 5 * wordLen
43+
)
44+
45+
type input [inputLen]byte
46+
47+
type index int
48+
49+
const (
50+
hashPos index = iota * wordLen
51+
rPos
52+
sPos
53+
xPos
54+
yPos
55+
)
56+
57+
// Run parses and verifies the signature. On success it returns a 32-byte
58+
// big-endian representation of the number 1, otherwise it returns an empty
59+
// slice. The returned error is always nil.
60+
func (Precompile) Run(sig []byte) ([]byte, error) {
61+
if len(sig) != inputLen || !(*input)(sig).verify() {
62+
return nil, nil
63+
}
64+
return bigEndianOne(), nil
65+
}
66+
67+
func bigEndianOne() []byte {
68+
return []byte{wordLen - 1: 1}
69+
}
70+
71+
func (in *input) verify() bool {
72+
key, ok := in.pubkey()
73+
if !ok {
74+
return false
75+
}
76+
return ecdsa.Verify(key, in.word(hashPos), in.bigWord(rPos), in.bigWord(sPos))
77+
}
78+
79+
func (in *input) pubkey() (*ecdsa.PublicKey, bool) {
80+
x := in.bigWord(xPos)
81+
y := in.bigWord(yPos)
82+
83+
// There is no need to explicitly check for the point at infinity because
84+
// [elliptic.Curve] documentation states that it's not on the curve and the
85+
// check would therefore be performed twice.
86+
// See https://cs.opensource.google/go/go/+/refs/tags/go1.24.3:src/crypto/elliptic/nistec.go;l=132
87+
curve := elliptic.P256()
88+
if !curve.IsOnCurve(x, y) {
89+
return nil, false
90+
}
91+
return &ecdsa.PublicKey{
92+
Curve: curve,
93+
X: x,
94+
Y: y,
95+
}, true
96+
}
97+
98+
func (in *input) word(i index) []byte {
99+
return in[i : i+wordLen]
100+
}
101+
102+
func (in *input) bigWord(i index) *big.Int {
103+
return new(big.Int).SetBytes(in.word(i))
104+
}
105+
106+
// Pack packs the arguments into a byte slice compatible with [Precompile.Run].
107+
// It does NOT perform any validation on its inputs and therefore may panic if,
108+
// for example, a [big.Int] with >256 bits is received. Keys and signatures
109+
// generated with [elliptic.GenerateKey] and [ecdsa.Sign] are valid inputs.
110+
func Pack(hash [32]byte, r, s *big.Int, key *ecdsa.PublicKey) []byte {
111+
var in input
112+
113+
copy(in.word(hashPos), hash[:])
114+
115+
r.FillBytes(in.word(rPos))
116+
s.FillBytes(in.word(sPos))
117+
118+
key.X.FillBytes(in.word(xPos))
119+
key.Y.FillBytes(in.word(yPos))
120+
121+
return in[:]
122+
}

0 commit comments

Comments
 (0)