mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-19 11:20:45 +00:00
Merge remote-tracking branch 'origin/master' into bs/cell-blobpool/sparse-v2
This commit is contained in:
commit
fdce1ff22f
16 changed files with 194 additions and 13 deletions
|
|
@ -4,8 +4,10 @@
|
|||
package {{.Package}}
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
"strings"
|
||||
"time"
|
||||
"errors"
|
||||
|
||||
ethereum "github.com/ethereum/go-ethereum"
|
||||
|
|
@ -27,6 +29,8 @@ var (
|
|||
_ = types.BloomLookup
|
||||
_ = event.NewSubscription
|
||||
_ = abi.ConvertType
|
||||
_ = time.Tick
|
||||
_ = context.Background
|
||||
)
|
||||
|
||||
{{$structs := .Structs}}
|
||||
|
|
@ -77,7 +81,11 @@ var (
|
|||
return common.Address{}, nil, nil, errors.New("GetABI returned nil")
|
||||
}
|
||||
{{range $pattern, $name := .Libraries}}
|
||||
{{decapitalise $name}}Addr, _, _, _ := Deploy{{capitalise $name}}(auth, backend)
|
||||
{{decapitalise $name}}Addr, tx, _, _ := Deploy{{capitalise $name}}(auth, backend)
|
||||
ctx, _ := context.WithTimeout(context.Background(), 5 * time.Second)
|
||||
if err := bind.WaitAccepted(ctx, backend, tx); err != nil {
|
||||
return common.Address{}, nil, nil, err
|
||||
}
|
||||
{{$contract.Type}}Bin = strings.ReplaceAll({{$contract.Type}}Bin, "__${{$pattern}}$__", {{decapitalise $name}}Addr.String()[2:])
|
||||
{{end}}
|
||||
address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex({{.Type}}Bin), backend {{range .Constructor.Inputs}}, {{.Name}}{{end}})
|
||||
|
|
|
|||
|
|
@ -273,6 +273,12 @@ func (m *MetaData) GetAbi() (*abi.ABI, error) {
|
|||
|
||||
// util.go
|
||||
|
||||
// WaitAccepted waits for a tx to be accepted into the pool.
|
||||
// It stops waiting when the context is canceled.
|
||||
func WaitAccepted(ctx context.Context, b ContractBackend, tx *types.Transaction) error {
|
||||
return bind2.WaitAccepted(ctx, b, tx.Hash())
|
||||
}
|
||||
|
||||
// WaitMined waits for tx to be mined on the blockchain.
|
||||
// It stops waiting when the context is canceled.
|
||||
func WaitMined(ctx context.Context, b DeployBackend, tx *types.Transaction) (*types.Receipt, error) {
|
||||
|
|
|
|||
|
|
@ -103,6 +103,9 @@ type ContractTransactor interface {
|
|||
|
||||
// PendingNonceAt retrieves the current pending nonce associated with an account.
|
||||
PendingNonceAt(ctx context.Context, account common.Address) (uint64, error)
|
||||
|
||||
// TransactionByHash retrieves the transaction associated with the hash, if it exists in the pool.
|
||||
TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error)
|
||||
}
|
||||
|
||||
// DeployBackend wraps the operations needed by WaitMined and WaitDeployed.
|
||||
|
|
|
|||
|
|
@ -320,7 +320,7 @@ func (c *BoundContract) createDynamicTx(opts *TransactOpts, contract *common.Add
|
|||
}
|
||||
}
|
||||
// create the transaction
|
||||
nonce, err := c.getNonce(opts)
|
||||
nonce, err := c.GetNonce(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -365,7 +365,7 @@ func (c *BoundContract) createLegacyTx(opts *TransactOpts, contract *common.Addr
|
|||
}
|
||||
}
|
||||
// create the transaction
|
||||
nonce, err := c.getNonce(opts)
|
||||
nonce, err := c.GetNonce(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -402,7 +402,7 @@ func (c *BoundContract) estimateGasLimit(opts *TransactOpts, contract *common.Ad
|
|||
return c.transactor.EstimateGas(ensureContext(opts.Context), msg)
|
||||
}
|
||||
|
||||
func (c *BoundContract) getNonce(opts *TransactOpts) (uint64, error) {
|
||||
func (c *BoundContract) GetNonce(opts *TransactOpts) (uint64, error) {
|
||||
if opts.Nonce == nil {
|
||||
return c.transactor.PendingNonceAt(ensureContext(opts.Context), opts.From)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -75,6 +75,10 @@ func (mt *mockTransactor) SendTransaction(ctx context.Context, tx *types.Transac
|
|||
return nil
|
||||
}
|
||||
|
||||
func (mt *mockTransactor) TransactionByHash(ctx context.Context, hash common.Hash) (*types.Transaction, bool, error) {
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
type mockCaller struct {
|
||||
codeAtBlockNumber *big.Int
|
||||
callContractBlockNumber *big.Int
|
||||
|
|
|
|||
|
|
@ -75,3 +75,28 @@ func WaitDeployed(ctx context.Context, b DeployBackend, hash common.Hash) (commo
|
|||
}
|
||||
return receipt.ContractAddress, err
|
||||
}
|
||||
|
||||
func WaitAccepted(ctx context.Context, d ContractBackend, txHash common.Hash) error {
|
||||
queryTicker := time.NewTicker(time.Second)
|
||||
defer queryTicker.Stop()
|
||||
logger := log.New("hash", txHash)
|
||||
for {
|
||||
_, _, err := d.TransactionByHash(ctx, txHash)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if errors.Is(err, ethereum.NotFound) { // TODO: check this is emitted
|
||||
logger.Trace("Transaction not yet accepted")
|
||||
} else {
|
||||
logger.Trace("Transaction submission failed", "err", err)
|
||||
}
|
||||
|
||||
// Wait for the next round.
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-queryTicker.C:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,6 +141,7 @@ var filterFlags = map[string]nodeFilterC{
|
|||
"-eth-network": {1, ethFilter},
|
||||
"-les-server": {0, lesFilter},
|
||||
"-snap": {0, snapFilter},
|
||||
"-dialable": {0, dialableFilter},
|
||||
}
|
||||
|
||||
// parseFilters parses nodeFilters from args.
|
||||
|
|
@ -272,3 +273,15 @@ func snapFilter(args []string) (nodeFilter, error) {
|
|||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func dialableFilter(args []string) (nodeFilter, error) {
|
||||
f := func(n nodeJSON) bool {
|
||||
var tcp, tcp6, quic, quic6 uint16
|
||||
n.N.Load((*enr.TCP)(&tcp))
|
||||
n.N.Load((*enr.TCP6)(&tcp6))
|
||||
n.N.Load((*enr.QUIC)(&quic))
|
||||
n.N.Load((*enr.QUIC6)(&quic6))
|
||||
return tcp != 0 || tcp6 != 0 || quic != 0 || quic6 != 0
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
|
|
|||
70
cmd/devp2p/nodesetcmd_test.go
Normal file
70
cmd/devp2p/nodesetcmd_test.go
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright 2026 The go-ethereum Authors
|
||||
// This file is part of go-ethereum.
|
||||
//
|
||||
// go-ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// go-ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||
"github.com/ethereum/go-ethereum/p2p/enr"
|
||||
)
|
||||
|
||||
func TestDialableFilter(t *testing.T) {
|
||||
filter, err := dialableFilter(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
makeNode := func(entries ...enr.Entry) nodeJSON {
|
||||
r := new(enr.Record)
|
||||
for _, e := range entries {
|
||||
r.Set(e)
|
||||
}
|
||||
key, err := crypto.GenerateKey()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := enode.SignV4(r, key); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
n, err := enode.New(enode.ValidSchemes, r)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return nodeJSON{N: n}
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
node nodeJSON
|
||||
want bool
|
||||
}{
|
||||
{"tcp", makeNode(enr.TCP(30303)), true},
|
||||
{"tcp6", makeNode(enr.TCP6(30303)), true},
|
||||
{"quic", makeNode(enr.QUIC(30303)), true},
|
||||
{"no ports", makeNode(), false},
|
||||
{"udp only", makeNode(enr.UDP(30303)), false},
|
||||
{"zero tcp", makeNode(enr.TCP(0)), false},
|
||||
{"oversized tcp", makeNode(enr.WithEntry("tcp", uint32(70000))), false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
if got := filter(tt.node); got != tt.want {
|
||||
t.Errorf("%s: dialable = %v, want %v", tt.name, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -102,6 +102,7 @@ var (
|
|||
utils.CachePreimagesFlag,
|
||||
utils.CacheLogSizeFlag,
|
||||
utils.FDLimitFlag,
|
||||
utils.MemoryLimitFlag,
|
||||
utils.CryptoKZGFlag,
|
||||
utils.ListenPortFlag,
|
||||
utils.DiscoveryPortFlag,
|
||||
|
|
|
|||
|
|
@ -561,6 +561,11 @@ var (
|
|||
Usage: "Raise the open file descriptor resource limit (default = system fd limit)",
|
||||
Category: flags.PerfCategory,
|
||||
}
|
||||
MemoryLimitFlag = &cli.IntFlag{
|
||||
Name: "memorylimit",
|
||||
Usage: "Soft memory limit for the Go runtime in megabytes (default = no limit)",
|
||||
Category: flags.PerfCategory,
|
||||
}
|
||||
CryptoKZGFlag = &cli.StringFlag{
|
||||
Name: "crypto.kzg",
|
||||
Usage: "KZG library implementation to use; gokzg (recommended) or ckzg",
|
||||
|
|
@ -1772,12 +1777,13 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
|||
ctx.Set(CacheFlag.Name, strconv.Itoa(allowance))
|
||||
}
|
||||
}
|
||||
// Ensure Go's GC ignores the database cache for trigger percentage
|
||||
cache := ctx.Int(CacheFlag.Name)
|
||||
gogc := max(20, min(100, 100/(float64(cache)/1024)))
|
||||
|
||||
log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc))
|
||||
godebug.SetGCPercent(int(gogc))
|
||||
godebug.SetGCPercent(100)
|
||||
if ctx.IsSet(MemoryLimitFlag.Name) {
|
||||
memLimit := int64(ctx.Int(MemoryLimitFlag.Name)) * 1024 * 1024
|
||||
log.Debug("Setting Go memory limit", "MB", memLimit/1024/1024)
|
||||
godebug.SetMemoryLimit(memLimit)
|
||||
}
|
||||
|
||||
if ctx.IsSet(SyncTargetFlag.Name) {
|
||||
cfg.SyncMode = ethconfig.FullSync // dev sync target forces full sync
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ func decodeV2(file *os.File) *freezerTableMeta {
|
|||
return nil
|
||||
}
|
||||
if o.Offset > math.MaxInt64 {
|
||||
log.Error("Invalid flushOffset %d in freezer metadata", "offset", o.Offset, "file", file.Name())
|
||||
log.Error("Invalid flushOffset in freezer metadata", "offset", o.Offset, "file", file.Name())
|
||||
return nil
|
||||
}
|
||||
return &freezerTableMeta{
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ func payloadVersion(config *params.ChainConfig, time uint64) engine.PayloadVersi
|
|||
switch config.LatestFork(time) {
|
||||
case forks.Amsterdam:
|
||||
return engine.PayloadV4
|
||||
case forks.BPO5, forks.BPO4, forks.BPO3, forks.BPO2, forks.BPO1, forks.Osaka, forks.Prague, forks.Cancun:
|
||||
case forks.Bogota, forks.BPO5, forks.BPO4, forks.BPO3, forks.BPO2, forks.BPO1, forks.Osaka, forks.Prague, forks.Cancun:
|
||||
return engine.PayloadV3
|
||||
case forks.Paris, forks.Shanghai:
|
||||
return engine.PayloadV2
|
||||
|
|
|
|||
|
|
@ -258,10 +258,10 @@ func handleMessage(backend Backend, peer *Peer) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer msg.Discard()
|
||||
if msg.Size > maxMessageSize {
|
||||
return fmt.Errorf("%w: %v > %v", errMsgTooLarge, msg.Size, maxMessageSize)
|
||||
}
|
||||
defer msg.Discard()
|
||||
|
||||
var handlers map[uint64]msgHandler
|
||||
switch peer.version {
|
||||
|
|
|
|||
|
|
@ -160,10 +160,10 @@ func HandleMessage(backend Backend, peer *Peer) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer msg.Discard()
|
||||
if msg.Size > maxMessageSize {
|
||||
return fmt.Errorf("%w: %v > %v", errMsgTooLarge, msg.Size, maxMessageSize)
|
||||
}
|
||||
defer msg.Discard()
|
||||
|
||||
var handlers map[uint64]msgHandler
|
||||
switch peer.version {
|
||||
|
|
|
|||
|
|
@ -162,6 +162,9 @@ func MakeTree(seq uint, nodes []*enode.Node, links []string) (*Tree, error) {
|
|||
if len(n.Record().Signature()) == 0 {
|
||||
return nil, fmt.Errorf("can't add node %v: unsigned node record", n.ID())
|
||||
}
|
||||
if err := checkRecordPorts(n.Record()); err != nil {
|
||||
return nil, fmt.Errorf("can't add node %v: %v", n.ID(), err)
|
||||
}
|
||||
}
|
||||
|
||||
// Create the leaf list.
|
||||
|
|
@ -393,6 +396,30 @@ func parseENR(e string, validSchemes enr.IdentityScheme) (entry, error) {
|
|||
return &enrEntry{n}, nil
|
||||
}
|
||||
|
||||
var portKeys = []string{
|
||||
enr.TCP(0).ENRKey(), enr.TCP6(0).ENRKey(),
|
||||
enr.UDP(0).ENRKey(), enr.UDP6(0).ENRKey(),
|
||||
enr.QUIC(0).ENRKey(), enr.QUIC6(0).ENRKey(),
|
||||
}
|
||||
|
||||
// checkRecordPorts verifies that port entries, if present, decode as a uint16.
|
||||
// enr.Record keeps undecodable pairs as raw RLP, so an out-of-range port in a record
|
||||
// from an external source would otherwise round-trip into a signed tree and fail to
|
||||
// decode for consumers that read the port strictly.
|
||||
func checkRecordPorts(r *enr.Record) error {
|
||||
for _, key := range portKeys {
|
||||
var port uint16
|
||||
err := r.Load(enr.WithEntry(key, &port))
|
||||
if enr.IsNotFound(err) {
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isValidHash(s string) bool {
|
||||
dlen := b32format.DecodedLen(len(s))
|
||||
if dlen < minHashLength || dlen > 32 || strings.ContainsAny(s, "\n\r") {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import (
|
|||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||
"github.com/ethereum/go-ethereum/p2p/enr"
|
||||
)
|
||||
|
||||
func TestParseRoot(t *testing.T) {
|
||||
|
|
@ -149,3 +150,20 @@ func TestMakeTree(t *testing.T) {
|
|||
t.Fatal("too few TXT records in output")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMakeTreeRejectsUndecodablePort(t *testing.T) {
|
||||
keys := testKeys(1)
|
||||
|
||||
oversized := new(enr.Record)
|
||||
oversized.Set(enr.WithEntry("udp", uint32(70000)))
|
||||
if err := enode.SignV4(oversized, keys[0]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
n, err := enode.New(enode.ValidSchemes, oversized)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := MakeTree(1, []*enode.Node{n}, nil); err == nil {
|
||||
t.Errorf("MakeTree accepted record with out-of-range port: %s", n.String())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue