Compare commits

...

3 Commits

Author SHA1 Message Date
Chen Kai 57355ad8ad
Merge fd550f5408 into dab746b3ef 2025-02-18 22:54:41 +01:00
Matthieu Vachon dab746b3ef
eth/catalyst: support earlier forks in SimulatedBeacon (#31084)
Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
2025-02-18 21:08:43 +01:00
Chen Kai fd550f5408 feat:change the discv5 challenge behavior to send same node only one time.
Signed-off-by: Chen Kai <281165273grape@gmail.com>
2025-02-02 12:58:28 +08:00
3 changed files with 88 additions and 26 deletions

View File

@ -33,6 +33,8 @@ import (
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/params/forks"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
) )
@ -95,6 +97,16 @@ type SimulatedBeacon struct {
lastBlockTime uint64 lastBlockTime uint64
} }
func payloadVersion(config *params.ChainConfig, time uint64) engine.PayloadVersion {
switch config.LatestFork(time) {
case forks.Prague, forks.Cancun:
return engine.PayloadV3
case forks.Paris, forks.Shanghai:
return engine.PayloadV2
}
panic("invalid fork, simulated beacon needs to be started post-merge")
}
// NewSimulatedBeacon constructs a new simulated beacon chain. // NewSimulatedBeacon constructs a new simulated beacon chain.
func NewSimulatedBeacon(period uint64, eth *eth.Ethereum) (*SimulatedBeacon, error) { func NewSimulatedBeacon(period uint64, eth *eth.Ethereum) (*SimulatedBeacon, error) {
block := eth.BlockChain().CurrentBlock() block := eth.BlockChain().CurrentBlock()
@ -107,7 +119,8 @@ func NewSimulatedBeacon(period uint64, eth *eth.Ethereum) (*SimulatedBeacon, err
// if genesis block, send forkchoiceUpdated to trigger transition to PoS // if genesis block, send forkchoiceUpdated to trigger transition to PoS
if block.Number.Sign() == 0 { if block.Number.Sign() == 0 {
if _, err := engineAPI.ForkchoiceUpdatedV3(current, nil); err != nil { version := payloadVersion(eth.BlockChain().Config(), block.Time)
if _, err := engineAPI.forkchoiceUpdated(current, nil, version, false); err != nil {
return nil, err return nil, err
} }
} }
@ -171,6 +184,8 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp u
return fmt.Errorf("failed to sync txpool: %w", err) return fmt.Errorf("failed to sync txpool: %w", err)
} }
version := payloadVersion(c.eth.BlockChain().Config(), timestamp)
var random [32]byte var random [32]byte
rand.Read(random[:]) rand.Read(random[:])
fcResponse, err := c.engineAPI.forkchoiceUpdated(c.curForkchoiceState, &engine.PayloadAttributes{ fcResponse, err := c.engineAPI.forkchoiceUpdated(c.curForkchoiceState, &engine.PayloadAttributes{
@ -179,7 +194,7 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp u
Withdrawals: withdrawals, Withdrawals: withdrawals,
Random: random, Random: random,
BeaconRoot: &common.Hash{}, BeaconRoot: &common.Hash{},
}, engine.PayloadV3, false) }, version, false)
if err != nil { if err != nil {
return err return err
} }
@ -204,28 +219,39 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp u
} }
} }
// Independently calculate the blob hashes from sidecars. var (
blobHashes := make([]common.Hash, 0) blobHashes []common.Hash
if envelope.BlobsBundle != nil { beaconRoot *common.Hash
hasher := sha256.New() requests [][]byte
for _, commit := range envelope.BlobsBundle.Commitments { )
var c kzg4844.Commitment // Compute post-shanghai fields
if len(commit) != len(c) { if version > engine.PayloadV2 {
return errors.New("invalid commitment length") // Independently calculate the blob hashes from sidecars.
blobHashes = make([]common.Hash, 0)
if envelope.BlobsBundle != nil {
hasher := sha256.New()
for _, commit := range envelope.BlobsBundle.Commitments {
var c kzg4844.Commitment
if len(commit) != len(c) {
return errors.New("invalid commitment length")
}
copy(c[:], commit)
blobHashes = append(blobHashes, kzg4844.CalcBlobHashV1(hasher, &c))
} }
copy(c[:], commit)
blobHashes = append(blobHashes, kzg4844.CalcBlobHashV1(hasher, &c))
} }
beaconRoot = &common.Hash{}
requests = envelope.Requests
} }
// Mark the payload as canon // Mark the payload as canon
_, err = c.engineAPI.newPayload(*payload, blobHashes, &common.Hash{}, envelope.Requests, false) _, err = c.engineAPI.newPayload(*payload, blobHashes, beaconRoot, requests, false)
if err != nil { if err != nil {
return err return err
} }
c.setCurrentState(payload.BlockHash, finalizedHash) c.setCurrentState(payload.BlockHash, finalizedHash)
// Mark the block containing the payload as canonical // Mark the block containing the payload as canonical
if _, err = c.engineAPI.ForkchoiceUpdatedV3(c.curForkchoiceState, nil); err != nil { if _, err = c.engineAPI.forkchoiceUpdated(c.curForkchoiceState, nil, version, false); err != nil {
return err return err
} }
c.lastBlockTime = payload.Timestamp c.lastBlockTime = payload.Timestamp

View File

@ -104,18 +104,19 @@ var DefaultProtocolID = [6]byte{'d', 'i', 's', 'c', 'v', '5'}
// Errors. // Errors.
var ( var (
errTooShort = errors.New("packet too short") errTooShort = errors.New("packet too short")
errInvalidHeader = errors.New("invalid packet header") errInvalidHeader = errors.New("invalid packet header")
errInvalidFlag = errors.New("invalid flag value in header") errInvalidFlag = errors.New("invalid flag value in header")
errMinVersion = errors.New("version of packet header below minimum") errMinVersion = errors.New("version of packet header below minimum")
errMsgTooShort = errors.New("message/handshake packet below minimum size") errMsgTooShort = errors.New("message/handshake packet below minimum size")
errAuthSize = errors.New("declared auth size is beyond packet length") errAuthSize = errors.New("declared auth size is beyond packet length")
errUnexpectedHandshake = errors.New("unexpected auth response, not in handshake") errUnexpectedHandshake = errors.New("unexpected auth response, not in handshake")
errInvalidAuthKey = errors.New("invalid ephemeral pubkey") errInvalidAuthKey = errors.New("invalid ephemeral pubkey")
errNoRecord = errors.New("expected ENR in handshake but none sent") errNoRecord = errors.New("expected ENR in handshake but none sent")
errInvalidNonceSig = errors.New("invalid ID nonce signature") errInvalidNonceSig = errors.New("invalid ID nonce signature")
errMessageTooShort = errors.New("message contains no data") errMessageTooShort = errors.New("message contains no data")
errMessageDecrypt = errors.New("cannot decrypt message") errMessageDecrypt = errors.New("cannot decrypt message")
errChallengeAlreadySent = errors.New("challenge already sent to this node")
) )
// Public errors. // Public errors.
@ -217,6 +218,10 @@ func (c *Codec) Encode(id enode.ID, addr string, packet Packet, challenge *Whoar
// Store sent WHOAREYOU challenges. // Store sent WHOAREYOU challenges.
if challenge, ok := packet.(*Whoareyou); ok { if challenge, ok := packet.(*Whoareyou); ok {
// check if we already sent a challenge to this node
if c.sc.getHandshake(id, addr) != nil {
return nil, Nonce{}, errChallengeAlreadySent
}
challenge.ChallengeData = bytesCopy(&c.buf) challenge.ChallengeData = bytesCopy(&c.buf)
c.sc.storeSentHandshake(id, addr, challenge) c.sc.storeSentHandshake(id, addr, challenge)
} else if msgData == nil { } else if msgData == nil {

View File

@ -155,6 +155,37 @@ func TestHandshake_norecord(t *testing.T) {
net.nodeA.expectDecode(t, NodesMsg, nodes) net.nodeA.expectDecode(t, NodesMsg, nodes)
} }
func TestEncodeWhoareyouAlreadySent(t *testing.T) {
t.Parallel()
net := newHandshakeTest()
defer net.close()
// A -> B RANDOM PACKET
packet, _ := net.nodeA.encode(t, net.nodeB, &Findnode{})
resp := net.nodeB.expectDecode(t, UnknownPacket, packet)
// A <- B First WHOAREYOU
challenge1 := &Whoareyou{
Nonce: resp.(*Unknown).Nonce,
IDNonce: testIDnonce,
RecordSeq: 0,
}
whoareyou1, _ := net.nodeB.encode(t, net.nodeA, challenge1)
net.nodeA.expectDecode(t, WhoareyouPacket, whoareyou1)
// A <- B Second WHOAREYOU (should fail)
challenge2 := &Whoareyou{
Nonce: resp.(*Unknown).Nonce,
IDNonce: testIDnonce,
RecordSeq: 0,
}
_, _, err := net.nodeB.c.Encode(net.nodeA.id(), net.nodeA.addr(), challenge2, nil)
if !errors.Is(err, errChallengeAlreadySent) {
t.Fatalf("second challenge should fail with errChallengeAlreadySent, got %v", err)
}
}
// In this test, A tries to send FINDNODE with existing secrets but B doesn't know // In this test, A tries to send FINDNODE with existing secrets but B doesn't know
// anything about A. // anything about A.
func TestHandshake_rekey(t *testing.T) { func TestHandshake_rekey(t *testing.T) {