mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 05:18:03 -05:00
Compare commits
9 Commits
5fb96df47e
...
954f76a073
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
954f76a073 | ||
|
|
e9616e8098 | ||
|
|
cd4bf3311e | ||
|
|
d5181c694f | ||
|
|
217c1fe7a1 | ||
|
|
1541558261 | ||
|
|
1a6252ade4 | ||
|
|
27c009e7ff | ||
|
|
ffad861e2c |
10
WORKSPACE
10
WORKSPACE
@@ -273,16 +273,16 @@ filegroup(
|
||||
url = "https://github.com/ethereum/EIPs/archive/5480440fe51742ed23342b68cf106cefd427e39d.tar.gz",
|
||||
)
|
||||
|
||||
consensus_spec_version = "v1.6.0"
|
||||
consensus_spec_version = "v1.7.0-alpha.0"
|
||||
|
||||
load("@prysm//tools:download_spectests.bzl", "consensus_spec_tests")
|
||||
|
||||
consensus_spec_tests(
|
||||
name = "consensus_spec_tests",
|
||||
flavors = {
|
||||
"general": "sha256-54hTaUNF9nLg+hRr3oHoq0yjZpW3MNiiUUuCQu6Rajk=",
|
||||
"minimal": "sha256-1JHIGg3gVMjvcGYRHR5cwdDgOvX47oR/MWp6gyAeZfA=",
|
||||
"mainnet": "sha256-292h3W2Ffts0YExgDTyxYe9Os7R0bZIXuAaMO8P6kl4=",
|
||||
"general": "sha256-b+rJOuVqq+Dy53quPcNYcQwPFoMU7Wp7tdUVe7n0g8w=",
|
||||
"minimal": "sha256-qxRIxtjPxVsVCY90WsBJKhk0027XDSmhjnRvRN14V1c=",
|
||||
"mainnet": "sha256-NsuOQG3LzeiEE1TrWuvQ6vu6BboHv7h7f/RTS0pWkCs=",
|
||||
},
|
||||
version = consensus_spec_version,
|
||||
)
|
||||
@@ -298,7 +298,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
integrity = "sha256-VzBgrEokvYSMIIXVnSA5XS9I3m9oxpvToQGxC1N5lzw=",
|
||||
integrity = "sha256-hwNdUBgdBrkk6pWIpNYbzbwswUuOu6AMD2exN8uv+QQ=",
|
||||
strip_prefix = "consensus-specs-" + consensus_spec_version[1:],
|
||||
url = "https://github.com/ethereum/consensus-specs/archive/refs/tags/%s.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
fieldparams "github.com/OffchainLabs/prysm/v7/config/fieldparams"
|
||||
"github.com/OffchainLabs/prysm/v7/config/params"
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/blocks"
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/interfaces"
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
|
||||
"github.com/OffchainLabs/prysm/v7/encoding/bytesutil"
|
||||
ethpbv1 "github.com/OffchainLabs/prysm/v7/proto/eth/v1"
|
||||
@@ -130,12 +131,10 @@ func TestService_ReceiveBlock(t *testing.T) {
|
||||
block: genFullBlock(t, util.DefaultBlockGenConfig(), 1 /*slot*/),
|
||||
},
|
||||
check: func(t *testing.T, s *Service) {
|
||||
// Hacky sleep, should use a better way to be able to resolve the race
|
||||
// between event being sent out and processed.
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
if recvd := len(s.cfg.StateNotifier.(*blockchainTesting.MockStateNotifier).ReceivedEvents()); recvd < 1 {
|
||||
t.Errorf("Received %d state notifications, expected at least 1", recvd)
|
||||
}
|
||||
notifier := s.cfg.StateNotifier.(*blockchainTesting.MockStateNotifier)
|
||||
require.Eventually(t, func() bool {
|
||||
return len(notifier.ReceivedEvents()) >= 1
|
||||
}, 2*time.Second, 10*time.Millisecond, "Expected at least 1 state notification")
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -222,10 +221,10 @@ func TestService_ReceiveBlockUpdateHead(t *testing.T) {
|
||||
require.NoError(t, s.ReceiveBlock(ctx, wsb, root, nil))
|
||||
})
|
||||
wg.Wait()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
if recvd := len(s.cfg.StateNotifier.(*blockchainTesting.MockStateNotifier).ReceivedEvents()); recvd < 1 {
|
||||
t.Errorf("Received %d state notifications, expected at least 1", recvd)
|
||||
}
|
||||
notifier := s.cfg.StateNotifier.(*blockchainTesting.MockStateNotifier)
|
||||
require.Eventually(t, func() bool {
|
||||
return len(notifier.ReceivedEvents()) >= 1
|
||||
}, 2*time.Second, 10*time.Millisecond, "Expected at least 1 state notification")
|
||||
// Verify fork choice has processed the block. (Genesis block and the new block)
|
||||
assert.Equal(t, 2, s.cfg.ForkChoiceStore.NodeCount())
|
||||
}
|
||||
@@ -265,10 +264,10 @@ func TestService_ReceiveBlockBatch(t *testing.T) {
|
||||
block: genFullBlock(t, util.DefaultBlockGenConfig(), 1 /*slot*/),
|
||||
},
|
||||
check: func(t *testing.T, s *Service) {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
if recvd := len(s.cfg.StateNotifier.(*blockchainTesting.MockStateNotifier).ReceivedEvents()); recvd < 1 {
|
||||
t.Errorf("Received %d state notifications, expected at least 1", recvd)
|
||||
}
|
||||
notifier := s.cfg.StateNotifier.(*blockchainTesting.MockStateNotifier)
|
||||
require.Eventually(t, func() bool {
|
||||
return len(notifier.ReceivedEvents()) >= 1
|
||||
}, 2*time.Second, 10*time.Millisecond, "Expected at least 1 state notification")
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -512,8 +511,9 @@ func Test_executePostFinalizationTasks(t *testing.T) {
|
||||
s.cfg.StateNotifier = notifier
|
||||
s.executePostFinalizationTasks(s.ctx, headState)
|
||||
|
||||
time.Sleep(1 * time.Second) // sleep for a second because event is in a separate go routine
|
||||
require.Equal(t, 1, len(notifier.ReceivedEvents()))
|
||||
require.Eventually(t, func() bool {
|
||||
return len(notifier.ReceivedEvents()) == 1
|
||||
}, 5*time.Second, 50*time.Millisecond, "Expected exactly 1 state notification")
|
||||
e := notifier.ReceivedEvents()[0]
|
||||
assert.Equal(t, statefeed.FinalizedCheckpoint, int(e.Type))
|
||||
fc, ok := e.Data.(*ethpbv1.EventFinalizedCheckpoint)
|
||||
@@ -552,8 +552,9 @@ func Test_executePostFinalizationTasks(t *testing.T) {
|
||||
s.cfg.StateNotifier = notifier
|
||||
s.executePostFinalizationTasks(s.ctx, headState)
|
||||
|
||||
time.Sleep(1 * time.Second) // sleep for a second because event is in a separate go routine
|
||||
require.Equal(t, 1, len(notifier.ReceivedEvents()))
|
||||
require.Eventually(t, func() bool {
|
||||
return len(notifier.ReceivedEvents()) == 1
|
||||
}, 5*time.Second, 50*time.Millisecond, "Expected exactly 1 state notification")
|
||||
e := notifier.ReceivedEvents()[0]
|
||||
assert.Equal(t, statefeed.FinalizedCheckpoint, int(e.Type))
|
||||
fc, ok := e.Data.(*ethpbv1.EventFinalizedCheckpoint)
|
||||
@@ -596,13 +597,13 @@ func TestProcessLightClientBootstrap(t *testing.T) {
|
||||
|
||||
s.executePostFinalizationTasks(s.ctx, l.AttestedState)
|
||||
|
||||
// wait for the goroutine to finish processing
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
// Check that the light client bootstrap is saved
|
||||
b, err := s.lcStore.LightClientBootstrap(ctx, [32]byte(cp.Root))
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, b)
|
||||
// Wait for the light client bootstrap to be saved (runs in goroutine)
|
||||
var b interfaces.LightClientBootstrap
|
||||
require.Eventually(t, func() bool {
|
||||
var err error
|
||||
b, err = s.lcStore.LightClientBootstrap(ctx, [32]byte(cp.Root))
|
||||
return err == nil && b != nil
|
||||
}, 5*time.Second, 50*time.Millisecond, "Light client bootstrap was not saved within timeout")
|
||||
|
||||
btst, err := lightClient.NewLightClientBootstrapFromBeaconState(ctx, l.FinalizedState.Slot(), l.FinalizedState, l.FinalizedBlock)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -212,7 +212,8 @@ func ProcessWithdrawals(st state.BeaconState, executionData interfaces.Execution
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get next withdrawal validator index")
|
||||
}
|
||||
nextValidatorIndex += primitives.ValidatorIndex(params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep)
|
||||
bound := min(uint64(st.NumValidators()), params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep)
|
||||
nextValidatorIndex += primitives.ValidatorIndex(bound)
|
||||
nextValidatorIndex = nextValidatorIndex % primitives.ValidatorIndex(st.NumValidators())
|
||||
} else {
|
||||
nextValidatorIndex = expectedWithdrawals[len(expectedWithdrawals)-1].ValidatorIndex + 1
|
||||
|
||||
@@ -75,7 +75,6 @@ func TestLightClientStore_SetLastFinalityUpdate(t *testing.T) {
|
||||
p2p := p2pTesting.NewTestP2P(t)
|
||||
lcStore := NewLightClientStore(p2p, new(event.Feed), testDB.SetupDB(t))
|
||||
|
||||
timeForGoroutinesToFinish := 20 * time.Microsecond
|
||||
// update 0 with basic data and no supermajority following an empty lastFinalityUpdate - should save and broadcast
|
||||
l0 := util.NewTestLightClient(t, version.Altair)
|
||||
update0, err := NewLightClientFinalityUpdateFromBeaconState(l0.Ctx, l0.State, l0.Block, l0.AttestedState, l0.AttestedBlock, l0.FinalizedBlock)
|
||||
@@ -87,8 +86,9 @@ func TestLightClientStore_SetLastFinalityUpdate(t *testing.T) {
|
||||
|
||||
lcStore.SetLastFinalityUpdate(update0, true)
|
||||
require.Equal(t, update0, lcStore.LastFinalityUpdate(), "lastFinalityUpdate should match the set value")
|
||||
time.Sleep(timeForGoroutinesToFinish) // give some time for the broadcast goroutine to finish
|
||||
require.Equal(t, true, p2p.BroadcastCalled.Load(), "Broadcast should have been called after setting a new last finality update when previous is nil")
|
||||
require.Eventually(t, func() bool {
|
||||
return p2p.BroadcastCalled.Load()
|
||||
}, time.Second, 10*time.Millisecond, "Broadcast should have been called after setting a new last finality update when previous is nil")
|
||||
p2p.BroadcastCalled.Store(false) // Reset for next test
|
||||
|
||||
// update 1 with same finality slot, increased attested slot, and no supermajority - should save but not broadcast
|
||||
@@ -102,7 +102,7 @@ func TestLightClientStore_SetLastFinalityUpdate(t *testing.T) {
|
||||
|
||||
lcStore.SetLastFinalityUpdate(update1, true)
|
||||
require.Equal(t, update1, lcStore.LastFinalityUpdate(), "lastFinalityUpdate should match the set value")
|
||||
time.Sleep(timeForGoroutinesToFinish) // give some time for the broadcast goroutine to finish
|
||||
time.Sleep(50 * time.Millisecond) // Wait briefly to verify broadcast is not called
|
||||
require.Equal(t, false, p2p.BroadcastCalled.Load(), "Broadcast should not have been called after setting a new last finality update without supermajority")
|
||||
p2p.BroadcastCalled.Store(false) // Reset for next test
|
||||
|
||||
@@ -117,8 +117,9 @@ func TestLightClientStore_SetLastFinalityUpdate(t *testing.T) {
|
||||
|
||||
lcStore.SetLastFinalityUpdate(update2, true)
|
||||
require.Equal(t, update2, lcStore.LastFinalityUpdate(), "lastFinalityUpdate should match the set value")
|
||||
time.Sleep(timeForGoroutinesToFinish) // give some time for the broadcast goroutine to finish
|
||||
require.Equal(t, true, p2p.BroadcastCalled.Load(), "Broadcast should have been called after setting a new last finality update with supermajority")
|
||||
require.Eventually(t, func() bool {
|
||||
return p2p.BroadcastCalled.Load()
|
||||
}, time.Second, 10*time.Millisecond, "Broadcast should have been called after setting a new last finality update with supermajority")
|
||||
p2p.BroadcastCalled.Store(false) // Reset for next test
|
||||
|
||||
// update 3 with same finality slot, increased attested slot, and supermajority - should save but not broadcast
|
||||
@@ -132,7 +133,7 @@ func TestLightClientStore_SetLastFinalityUpdate(t *testing.T) {
|
||||
|
||||
lcStore.SetLastFinalityUpdate(update3, true)
|
||||
require.Equal(t, update3, lcStore.LastFinalityUpdate(), "lastFinalityUpdate should match the set value")
|
||||
time.Sleep(timeForGoroutinesToFinish) // give some time for the broadcast goroutine to finish
|
||||
time.Sleep(50 * time.Millisecond) // Wait briefly to verify broadcast is not called
|
||||
require.Equal(t, false, p2p.BroadcastCalled.Load(), "Broadcast should not have been when previous was already broadcast")
|
||||
|
||||
// update 4 with increased finality slot, increased attested slot, and supermajority - should save and broadcast
|
||||
@@ -146,8 +147,9 @@ func TestLightClientStore_SetLastFinalityUpdate(t *testing.T) {
|
||||
|
||||
lcStore.SetLastFinalityUpdate(update4, true)
|
||||
require.Equal(t, update4, lcStore.LastFinalityUpdate(), "lastFinalityUpdate should match the set value")
|
||||
time.Sleep(timeForGoroutinesToFinish) // give some time for the broadcast goroutine to finish
|
||||
require.Equal(t, true, p2p.BroadcastCalled.Load(), "Broadcast should have been called after a new finality update with increased finality slot")
|
||||
require.Eventually(t, func() bool {
|
||||
return p2p.BroadcastCalled.Load()
|
||||
}, time.Second, 10*time.Millisecond, "Broadcast should have been called after a new finality update with increased finality slot")
|
||||
p2p.BroadcastCalled.Store(false) // Reset for next test
|
||||
|
||||
// update 5 with the same new finality slot, increased attested slot, and supermajority - should save but not broadcast
|
||||
@@ -161,7 +163,7 @@ func TestLightClientStore_SetLastFinalityUpdate(t *testing.T) {
|
||||
|
||||
lcStore.SetLastFinalityUpdate(update5, true)
|
||||
require.Equal(t, update5, lcStore.LastFinalityUpdate(), "lastFinalityUpdate should match the set value")
|
||||
time.Sleep(timeForGoroutinesToFinish) // give some time for the broadcast goroutine to finish
|
||||
time.Sleep(50 * time.Millisecond) // Wait briefly to verify broadcast is not called
|
||||
require.Equal(t, false, p2p.BroadcastCalled.Load(), "Broadcast should not have been called when previous was already broadcast with supermajority")
|
||||
|
||||
// update 6 with the same new finality slot, increased attested slot, and no supermajority - should save but not broadcast
|
||||
@@ -175,7 +177,7 @@ func TestLightClientStore_SetLastFinalityUpdate(t *testing.T) {
|
||||
|
||||
lcStore.SetLastFinalityUpdate(update6, true)
|
||||
require.Equal(t, update6, lcStore.LastFinalityUpdate(), "lastFinalityUpdate should match the set value")
|
||||
time.Sleep(timeForGoroutinesToFinish) // give some time for the broadcast goroutine to finish
|
||||
time.Sleep(50 * time.Millisecond) // Wait briefly to verify broadcast is not called
|
||||
require.Equal(t, false, p2p.BroadcastCalled.Load(), "Broadcast should not have been called when previous was already broadcast with supermajority")
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,10 @@ func TestService_Broadcast(t *testing.T) {
|
||||
sub, err := p2.SubscribeToTopic(topic)
|
||||
require.NoError(t, err)
|
||||
|
||||
time.Sleep(50 * time.Millisecond) // libp2p fails without this delay...
|
||||
// Wait for libp2p mesh to establish
|
||||
require.Eventually(t, func() bool {
|
||||
return len(p.pubsub.ListPeers(topic)) > 0
|
||||
}, 5*time.Second, 10*time.Millisecond, "libp2p mesh did not establish")
|
||||
|
||||
// Async listen for the pubsub, must be before the broadcast.
|
||||
var wg sync.WaitGroup
|
||||
@@ -186,7 +189,10 @@ func TestService_BroadcastAttestation(t *testing.T) {
|
||||
sub, err := p2.SubscribeToTopic(topic)
|
||||
require.NoError(t, err)
|
||||
|
||||
time.Sleep(50 * time.Millisecond) // libp2p fails without this delay...
|
||||
// Wait for libp2p mesh to establish
|
||||
require.Eventually(t, func() bool {
|
||||
return len(p.pubsub.ListPeers(topic)) > 0
|
||||
}, 5*time.Second, 10*time.Millisecond, "libp2p mesh did not establish")
|
||||
|
||||
// Async listen for the pubsub, must be before the broadcast.
|
||||
var wg sync.WaitGroup
|
||||
@@ -375,7 +381,15 @@ func TestService_BroadcastAttestationWithDiscoveryAttempts(t *testing.T) {
|
||||
_, err = tpHandle.Subscribe()
|
||||
require.NoError(t, err)
|
||||
|
||||
time.Sleep(500 * time.Millisecond) // libp2p fails without this delay...
|
||||
// This test specifically tests discovery-based peer finding, which requires
|
||||
// time for nodes to discover each other. Using a fixed sleep here is intentional
|
||||
// as we're testing the discovery timing behavior.
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
|
||||
// Verify mesh establishment after discovery
|
||||
require.Eventually(t, func() bool {
|
||||
return len(p.pubsub.ListPeers(topic)) > 0 && len(p2.pubsub.ListPeers(topic)) > 0
|
||||
}, 5*time.Second, 10*time.Millisecond, "libp2p mesh did not establish")
|
||||
|
||||
nodePeers := p.pubsub.ListPeers(topic)
|
||||
nodePeers2 := p2.pubsub.ListPeers(topic)
|
||||
@@ -444,7 +458,10 @@ func TestService_BroadcastSyncCommittee(t *testing.T) {
|
||||
sub, err := p2.SubscribeToTopic(topic)
|
||||
require.NoError(t, err)
|
||||
|
||||
time.Sleep(50 * time.Millisecond) // libp2p fails without this delay...
|
||||
// Wait for libp2p mesh to establish
|
||||
require.Eventually(t, func() bool {
|
||||
return len(p.pubsub.ListPeers(topic)) > 0
|
||||
}, 5*time.Second, 10*time.Millisecond, "libp2p mesh did not establish")
|
||||
|
||||
// Async listen for the pubsub, must be before the broadcast.
|
||||
var wg sync.WaitGroup
|
||||
@@ -521,7 +538,10 @@ func TestService_BroadcastBlob(t *testing.T) {
|
||||
sub, err := p2.SubscribeToTopic(topic)
|
||||
require.NoError(t, err)
|
||||
|
||||
time.Sleep(50 * time.Millisecond) // libp2p fails without this delay...
|
||||
// Wait for libp2p mesh to establish
|
||||
require.Eventually(t, func() bool {
|
||||
return len(p.pubsub.ListPeers(topic)) > 0
|
||||
}, 5*time.Second, 10*time.Millisecond, "libp2p mesh did not establish")
|
||||
|
||||
// Async listen for the pubsub, must be before the broadcast.
|
||||
var wg sync.WaitGroup
|
||||
@@ -584,7 +604,10 @@ func TestService_BroadcastLightClientOptimisticUpdate(t *testing.T) {
|
||||
sub, err := p2.SubscribeToTopic(topic)
|
||||
require.NoError(t, err)
|
||||
|
||||
time.Sleep(50 * time.Millisecond) // libp2p fails without this delay...
|
||||
// Wait for libp2p mesh to establish
|
||||
require.Eventually(t, func() bool {
|
||||
return len(p.pubsub.ListPeers(topic)) > 0
|
||||
}, 5*time.Second, 10*time.Millisecond, "libp2p mesh did not establish")
|
||||
|
||||
// Async listen for the pubsub, must be before the broadcast.
|
||||
var wg sync.WaitGroup
|
||||
@@ -660,7 +683,10 @@ func TestService_BroadcastLightClientFinalityUpdate(t *testing.T) {
|
||||
sub, err := p2.SubscribeToTopic(topic)
|
||||
require.NoError(t, err)
|
||||
|
||||
time.Sleep(50 * time.Millisecond) // libp2p fails without this delay...
|
||||
// Wait for libp2p mesh to establish
|
||||
require.Eventually(t, func() bool {
|
||||
return len(p.pubsub.ListPeers(topic)) > 0
|
||||
}, 5*time.Second, 10*time.Millisecond, "libp2p mesh did not establish")
|
||||
|
||||
// Async listen for the pubsub, must be before the broadcast.
|
||||
var wg sync.WaitGroup
|
||||
@@ -771,8 +797,10 @@ func TestService_BroadcastDataColumn(t *testing.T) {
|
||||
sub, err := p2.SubscribeToTopic(topic)
|
||||
require.NoError(t, err)
|
||||
|
||||
// libp2p fails without this delay
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
// Wait for libp2p mesh to establish
|
||||
require.Eventually(t, func() bool {
|
||||
return len(service.pubsub.ListPeers(topic)) > 0
|
||||
}, 5*time.Second, 10*time.Millisecond, "libp2p mesh did not establish")
|
||||
|
||||
// Broadcast to peers and wait.
|
||||
err = service.BroadcastDataColumnSidecars(ctx, []blocks.VerifiedRODataColumn{verifiedRoSidecar})
|
||||
|
||||
@@ -482,12 +482,12 @@ func TestStaticPeering_PeersAreAdded(t *testing.T) {
|
||||
s.Start()
|
||||
<-exitRoutine
|
||||
}()
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
time.Sleep(50 * time.Millisecond) // Wait for service initialization
|
||||
var vr [32]byte
|
||||
require.NoError(t, cs.SetClock(startup.NewClock(time.Now(), vr)))
|
||||
time.Sleep(4 * time.Second)
|
||||
ps := s.host.Network().Peers()
|
||||
assert.Equal(t, 5, len(ps), "Not all peers added to peerstore")
|
||||
require.Eventually(t, func() bool {
|
||||
return len(s.host.Network().Peers()) == 5
|
||||
}, 10*time.Second, 100*time.Millisecond, "Not all peers added to peerstore")
|
||||
require.NoError(t, s.Stop())
|
||||
exitRoutine <- true
|
||||
}
|
||||
|
||||
@@ -80,8 +80,9 @@ func TestService_Start_OnlyStartsOnce(t *testing.T) {
|
||||
}()
|
||||
var vr [32]byte
|
||||
require.NoError(t, cs.SetClock(startup.NewClock(time.Now(), vr)))
|
||||
time.Sleep(time.Second * 2)
|
||||
assert.Equal(t, true, s.started, "Expected service to be started")
|
||||
require.Eventually(t, func() bool {
|
||||
return s.started
|
||||
}, 5*time.Second, 100*time.Millisecond, "Expected service to be started")
|
||||
s.Start()
|
||||
require.LogsContain(t, hook, "Attempted to start p2p service when it was already started")
|
||||
require.NoError(t, s.Stop())
|
||||
@@ -260,17 +261,9 @@ func TestListenForNewNodes(t *testing.T) {
|
||||
err = cs.SetClock(startup.NewClock(genesisTime, gvr))
|
||||
require.NoError(t, err, "Could not set clock in service")
|
||||
|
||||
actualPeerCount := len(s.host.Network().Peers())
|
||||
for range 40 {
|
||||
if actualPeerCount == peerCount {
|
||||
break
|
||||
}
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
actualPeerCount = len(s.host.Network().Peers())
|
||||
}
|
||||
|
||||
assert.Equal(t, peerCount, actualPeerCount, "Not all peers added to peerstore")
|
||||
require.Eventually(t, func() bool {
|
||||
return len(s.host.Network().Peers()) == peerCount
|
||||
}, 5*time.Second, 100*time.Millisecond, "Not all peers added to peerstore")
|
||||
|
||||
err = s.Stop()
|
||||
require.NoError(t, err, "Failed to stop service")
|
||||
|
||||
@@ -657,8 +657,9 @@ func TestSubmitAttestationsV2(t *testing.T) {
|
||||
assert.Equal(t, primitives.Epoch(0), broadcaster.BroadcastAttestations[0].GetData().Source.Epoch)
|
||||
assert.Equal(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetData().Target.Root))
|
||||
assert.Equal(t, primitives.Epoch(0), broadcaster.BroadcastAttestations[0].GetData().Target.Epoch)
|
||||
time.Sleep(100 * time.Millisecond) // Wait for async pool save
|
||||
assert.Equal(t, 1, s.AttestationsPool.UnaggregatedAttestationCount())
|
||||
require.Eventually(t, func() bool {
|
||||
return s.AttestationsPool.UnaggregatedAttestationCount() == 1
|
||||
}, time.Second, 10*time.Millisecond, "Expected 1 attestation in pool")
|
||||
})
|
||||
t.Run("multiple", func(t *testing.T) {
|
||||
broadcaster := &p2pMock.MockBroadcaster{}
|
||||
@@ -677,8 +678,9 @@ func TestSubmitAttestationsV2(t *testing.T) {
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
assert.Equal(t, true, broadcaster.BroadcastCalled.Load())
|
||||
assert.Equal(t, 2, broadcaster.NumAttestations())
|
||||
time.Sleep(100 * time.Millisecond) // Wait for async pool save
|
||||
assert.Equal(t, 2, s.AttestationsPool.UnaggregatedAttestationCount())
|
||||
require.Eventually(t, func() bool {
|
||||
return s.AttestationsPool.UnaggregatedAttestationCount() == 2
|
||||
}, time.Second, 10*time.Millisecond, "Expected 2 attestations in pool")
|
||||
})
|
||||
t.Run("phase0 att post electra", func(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
@@ -798,8 +800,9 @@ func TestSubmitAttestationsV2(t *testing.T) {
|
||||
assert.Equal(t, primitives.Epoch(0), broadcaster.BroadcastAttestations[0].GetData().Source.Epoch)
|
||||
assert.Equal(t, "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", hexutil.Encode(broadcaster.BroadcastAttestations[0].GetData().Target.Root))
|
||||
assert.Equal(t, primitives.Epoch(0), broadcaster.BroadcastAttestations[0].GetData().Target.Epoch)
|
||||
time.Sleep(100 * time.Millisecond) // Wait for async pool save
|
||||
assert.Equal(t, 1, s.AttestationsPool.UnaggregatedAttestationCount())
|
||||
require.Eventually(t, func() bool {
|
||||
return s.AttestationsPool.UnaggregatedAttestationCount() == 1
|
||||
}, time.Second, 10*time.Millisecond, "Expected 1 attestation in pool")
|
||||
})
|
||||
t.Run("multiple", func(t *testing.T) {
|
||||
broadcaster := &p2pMock.MockBroadcaster{}
|
||||
@@ -818,8 +821,9 @@ func TestSubmitAttestationsV2(t *testing.T) {
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
assert.Equal(t, true, broadcaster.BroadcastCalled.Load())
|
||||
assert.Equal(t, 2, broadcaster.NumAttestations())
|
||||
time.Sleep(100 * time.Millisecond) // Wait for async pool save
|
||||
assert.Equal(t, 2, s.AttestationsPool.UnaggregatedAttestationCount())
|
||||
require.Eventually(t, func() bool {
|
||||
return s.AttestationsPool.UnaggregatedAttestationCount() == 2
|
||||
}, time.Second, 10*time.Millisecond, "Expected 2 attestations in pool")
|
||||
})
|
||||
t.Run("no body", func(t *testing.T) {
|
||||
request := httptest.NewRequest(http.MethodPost, "http://example.com", nil)
|
||||
@@ -1375,9 +1379,9 @@ func TestSubmitSignedBLSToExecutionChanges_Ok(t *testing.T) {
|
||||
writer.Body = &bytes.Buffer{}
|
||||
s.SubmitBLSToExecutionChanges(writer, request)
|
||||
assert.Equal(t, http.StatusOK, writer.Code)
|
||||
time.Sleep(100 * time.Millisecond) // Delay to let the routine start
|
||||
assert.Equal(t, true, broadcaster.BroadcastCalled.Load())
|
||||
assert.Equal(t, numValidators, len(broadcaster.BroadcastMessages))
|
||||
require.Eventually(t, func() bool {
|
||||
return broadcaster.BroadcastCalled.Load() && len(broadcaster.BroadcastMessages) == numValidators
|
||||
}, time.Second, 10*time.Millisecond, "Broadcast should be called with all messages")
|
||||
|
||||
poolChanges, err := s.BLSChangesPool.PendingBLSToExecChanges()
|
||||
require.Equal(t, len(poolChanges), len(signedChanges))
|
||||
@@ -1591,10 +1595,10 @@ func TestSubmitSignedBLSToExecutionChanges_Failures(t *testing.T) {
|
||||
|
||||
s.SubmitBLSToExecutionChanges(writer, request)
|
||||
assert.Equal(t, http.StatusBadRequest, writer.Code)
|
||||
time.Sleep(10 * time.Millisecond) // Delay to allow the routine to start
|
||||
require.StringContains(t, "One or more messages failed validation", writer.Body.String())
|
||||
assert.Equal(t, true, broadcaster.BroadcastCalled.Load())
|
||||
assert.Equal(t, numValidators, len(broadcaster.BroadcastMessages)+1)
|
||||
require.Eventually(t, func() bool {
|
||||
return broadcaster.BroadcastCalled.Load() && len(broadcaster.BroadcastMessages)+1 == numValidators
|
||||
}, time.Second, 10*time.Millisecond, "Broadcast should be called with expected messages")
|
||||
|
||||
poolChanges, err := s.BLSChangesPool.PendingBLSToExecChanges()
|
||||
require.Equal(t, len(poolChanges)+1, len(signedChanges))
|
||||
|
||||
@@ -102,6 +102,7 @@ go_test(
|
||||
"getters_test.go",
|
||||
"getters_validator_test.go",
|
||||
"getters_withdrawal_test.go",
|
||||
"gloas_test.go",
|
||||
"hasher_test.go",
|
||||
"mvslice_fuzz_test.go",
|
||||
"proofs_test.go",
|
||||
@@ -156,6 +157,7 @@ go_test(
|
||||
"@com_github_google_go_cmp//cmp:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_stretchr_testify//require:go_default_library",
|
||||
"@org_golang_google_protobuf//proto:go_default_library",
|
||||
"@org_golang_google_protobuf//testing/protocmp:go_default_library",
|
||||
],
|
||||
|
||||
@@ -72,11 +72,13 @@ type BeaconState struct {
|
||||
|
||||
// Gloas fields
|
||||
latestExecutionPayloadBid *ethpb.ExecutionPayloadBid
|
||||
builders []*ethpb.Builder
|
||||
nextWithdrawalBuilderIndex primitives.BuilderIndex
|
||||
executionPayloadAvailability []byte
|
||||
builderPendingPayments []*ethpb.BuilderPendingPayment
|
||||
builderPendingWithdrawals []*ethpb.BuilderPendingWithdrawal
|
||||
latestBlockHash []byte
|
||||
latestWithdrawalsRoot []byte
|
||||
payloadExpectedWithdrawals []*enginev1.Withdrawal
|
||||
|
||||
id uint64
|
||||
lock sync.RWMutex
|
||||
@@ -134,11 +136,13 @@ type beaconStateMarshalable struct {
|
||||
PendingConsolidations []*ethpb.PendingConsolidation `json:"pending_consolidations" yaml:"pending_consolidations"`
|
||||
ProposerLookahead []primitives.ValidatorIndex `json:"proposer_look_ahead" yaml:"proposer_look_ahead"`
|
||||
LatestExecutionPayloadBid *ethpb.ExecutionPayloadBid `json:"latest_execution_payload_bid" yaml:"latest_execution_payload_bid"`
|
||||
Builders []*ethpb.Builder `json:"builders" yaml:"builders"`
|
||||
NextWithdrawalBuilderIndex primitives.BuilderIndex `json:"next_withdrawal_builder_index" yaml:"next_withdrawal_builder_index"`
|
||||
ExecutionPayloadAvailability []byte `json:"execution_payload_availability" yaml:"execution_payload_availability"`
|
||||
BuilderPendingPayments []*ethpb.BuilderPendingPayment `json:"builder_pending_payments" yaml:"builder_pending_payments"`
|
||||
BuilderPendingWithdrawals []*ethpb.BuilderPendingWithdrawal `json:"builder_pending_withdrawals" yaml:"builder_pending_withdrawals"`
|
||||
LatestBlockHash []byte `json:"latest_block_hash" yaml:"latest_block_hash"`
|
||||
LatestWithdrawalsRoot []byte `json:"latest_withdrawals_root" yaml:"latest_withdrawals_root"`
|
||||
PayloadExpectedWithdrawals []*enginev1.Withdrawal `json:"payload_expected_withdrawals" yaml:"payload_expected_withdrawals"`
|
||||
}
|
||||
|
||||
func (b *BeaconState) MarshalJSON() ([]byte, error) {
|
||||
@@ -194,11 +198,13 @@ func (b *BeaconState) MarshalJSON() ([]byte, error) {
|
||||
PendingConsolidations: b.pendingConsolidations,
|
||||
ProposerLookahead: b.proposerLookahead,
|
||||
LatestExecutionPayloadBid: b.latestExecutionPayloadBid,
|
||||
Builders: b.builders,
|
||||
NextWithdrawalBuilderIndex: b.nextWithdrawalBuilderIndex,
|
||||
ExecutionPayloadAvailability: b.executionPayloadAvailability,
|
||||
BuilderPendingPayments: b.builderPendingPayments,
|
||||
BuilderPendingWithdrawals: b.builderPendingWithdrawals,
|
||||
LatestBlockHash: b.latestBlockHash,
|
||||
LatestWithdrawalsRoot: b.latestWithdrawalsRoot,
|
||||
PayloadExpectedWithdrawals: b.payloadExpectedWithdrawals,
|
||||
}
|
||||
return json.Marshal(marshalable)
|
||||
}
|
||||
|
||||
@@ -305,10 +305,12 @@ func (b *BeaconState) ToProtoUnsafe() any {
|
||||
PendingConsolidations: b.pendingConsolidations,
|
||||
ProposerLookahead: lookahead,
|
||||
ExecutionPayloadAvailability: b.executionPayloadAvailability,
|
||||
Builders: b.builders,
|
||||
NextWithdrawalBuilderIndex: b.nextWithdrawalBuilderIndex,
|
||||
BuilderPendingPayments: b.builderPendingPayments,
|
||||
BuilderPendingWithdrawals: b.builderPendingWithdrawals,
|
||||
LatestBlockHash: b.latestBlockHash,
|
||||
LatestWithdrawalsRoot: b.latestWithdrawalsRoot,
|
||||
PayloadExpectedWithdrawals: b.payloadExpectedWithdrawals,
|
||||
}
|
||||
default:
|
||||
return nil
|
||||
@@ -607,10 +609,12 @@ func (b *BeaconState) ToProto() any {
|
||||
PendingConsolidations: b.pendingConsolidationsVal(),
|
||||
ProposerLookahead: lookahead,
|
||||
ExecutionPayloadAvailability: b.executionPayloadAvailabilityVal(),
|
||||
Builders: b.buildersVal(),
|
||||
NextWithdrawalBuilderIndex: b.nextWithdrawalBuilderIndex,
|
||||
BuilderPendingPayments: b.builderPendingPaymentsVal(),
|
||||
BuilderPendingWithdrawals: b.builderPendingWithdrawalsVal(),
|
||||
LatestBlockHash: b.latestBlockHashVal(),
|
||||
LatestWithdrawalsRoot: b.latestWithdrawalsRootVal(),
|
||||
PayloadExpectedWithdrawals: b.payloadExpectedWithdrawalsVal(),
|
||||
}
|
||||
default:
|
||||
return nil
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1"
|
||||
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
@@ -47,6 +48,22 @@ func (b *BeaconState) builderPendingWithdrawalsVal() []*ethpb.BuilderPendingWith
|
||||
return withdrawals
|
||||
}
|
||||
|
||||
// buildersVal returns a copy of the builders registry.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) buildersVal() []*ethpb.Builder {
|
||||
if b.builders == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
builders := make([]*ethpb.Builder, len(b.builders))
|
||||
for i := range builders {
|
||||
builder := b.builders[i]
|
||||
builders[i] = ethpb.CopyBuilder(builder)
|
||||
}
|
||||
|
||||
return builders
|
||||
}
|
||||
|
||||
// latestBlockHashVal returns a copy of the latest block hash.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) latestBlockHashVal() []byte {
|
||||
@@ -60,15 +77,17 @@ func (b *BeaconState) latestBlockHashVal() []byte {
|
||||
return hash
|
||||
}
|
||||
|
||||
// latestWithdrawalsRootVal returns a copy of the latest withdrawals root.
|
||||
// payloadExpectedWithdrawalsVal returns a copy of the payload expected withdrawals.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) latestWithdrawalsRootVal() []byte {
|
||||
if b.latestWithdrawalsRoot == nil {
|
||||
func (b *BeaconState) payloadExpectedWithdrawalsVal() []*enginev1.Withdrawal {
|
||||
if b.payloadExpectedWithdrawals == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
root := make([]byte, len(b.latestWithdrawalsRoot))
|
||||
copy(root, b.latestWithdrawalsRoot)
|
||||
withdrawals := make([]*enginev1.Withdrawal, len(b.payloadExpectedWithdrawals))
|
||||
for i, withdrawal := range b.payloadExpectedWithdrawals {
|
||||
withdrawals[i] = withdrawal.Copy()
|
||||
}
|
||||
|
||||
return root
|
||||
return withdrawals
|
||||
}
|
||||
|
||||
43
beacon-chain/state/state-native/gloas_test.go
Normal file
43
beacon-chain/state/state-native/gloas_test.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1"
|
||||
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestBuildersVal(t *testing.T) {
|
||||
st := &BeaconState{}
|
||||
|
||||
require.Nil(t, st.buildersVal())
|
||||
|
||||
st.builders = []*ethpb.Builder{
|
||||
{Pubkey: []byte{0x01}, ExecutionAddress: []byte{0x02}, Balance: 3},
|
||||
nil,
|
||||
}
|
||||
|
||||
got := st.buildersVal()
|
||||
require.Len(t, got, 2)
|
||||
require.Nil(t, got[1])
|
||||
require.Equal(t, st.builders[0], got[0])
|
||||
require.NotSame(t, st.builders[0], got[0])
|
||||
}
|
||||
|
||||
func TestPayloadExpectedWithdrawalsVal(t *testing.T) {
|
||||
st := &BeaconState{}
|
||||
|
||||
require.Nil(t, st.payloadExpectedWithdrawalsVal())
|
||||
|
||||
st.payloadExpectedWithdrawals = []*enginev1.Withdrawal{
|
||||
{Index: 1, ValidatorIndex: 2, Address: []byte{0x03}, Amount: 4},
|
||||
nil,
|
||||
}
|
||||
|
||||
got := st.payloadExpectedWithdrawalsVal()
|
||||
require.Len(t, got, 2)
|
||||
require.Nil(t, got[1])
|
||||
require.Equal(t, st.payloadExpectedWithdrawals[0], got[0])
|
||||
require.NotSame(t, st.payloadExpectedWithdrawals[0], got[0])
|
||||
}
|
||||
@@ -342,6 +342,15 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b
|
||||
}
|
||||
|
||||
if state.version >= version.Gloas {
|
||||
buildersRoot, err := stateutil.BuildersRoot(state.builders)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute builders merkleization")
|
||||
}
|
||||
fieldRoots[types.Builders.RealPosition()] = buildersRoot[:]
|
||||
|
||||
nextWithdrawalBuilderIndexRoot := ssz.Uint64Root(uint64(state.nextWithdrawalBuilderIndex))
|
||||
fieldRoots[types.NextWithdrawalBuilderIndex.RealPosition()] = nextWithdrawalBuilderIndexRoot[:]
|
||||
|
||||
epaRoot, err := stateutil.ExecutionPayloadAvailabilityRoot(state.executionPayloadAvailability)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute execution payload availability merkleization")
|
||||
@@ -366,8 +375,12 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b
|
||||
lbhRoot := bytesutil.ToBytes32(state.latestBlockHash)
|
||||
fieldRoots[types.LatestBlockHash.RealPosition()] = lbhRoot[:]
|
||||
|
||||
lwrRoot := bytesutil.ToBytes32(state.latestWithdrawalsRoot)
|
||||
fieldRoots[types.LatestWithdrawalsRoot.RealPosition()] = lwrRoot[:]
|
||||
expectedWithdrawalsRoot, err := ssz.WithdrawalSliceRoot(state.payloadExpectedWithdrawals, fieldparams.MaxWithdrawalsPerPayload)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute payload expected withdrawals root")
|
||||
}
|
||||
|
||||
fieldRoots[types.PayloadExpectedWithdrawals.RealPosition()] = expectedWithdrawalsRoot[:]
|
||||
}
|
||||
return fieldRoots, nil
|
||||
}
|
||||
|
||||
@@ -120,11 +120,13 @@ var (
|
||||
)
|
||||
|
||||
gloasAdditionalFields = []types.FieldIndex{
|
||||
types.Builders,
|
||||
types.NextWithdrawalBuilderIndex,
|
||||
types.ExecutionPayloadAvailability,
|
||||
types.BuilderPendingPayments,
|
||||
types.BuilderPendingWithdrawals,
|
||||
types.LatestBlockHash,
|
||||
types.LatestWithdrawalsRoot,
|
||||
types.PayloadExpectedWithdrawals,
|
||||
}
|
||||
|
||||
gloasFields = slices.Concat(
|
||||
@@ -145,7 +147,7 @@ const (
|
||||
denebSharedFieldRefCount = 7
|
||||
electraSharedFieldRefCount = 10
|
||||
fuluSharedFieldRefCount = 11
|
||||
gloasSharedFieldRefCount = 12 // Adds PendingBuilderWithdrawal to the shared-ref set and LatestExecutionPayloadHeader is removed
|
||||
gloasSharedFieldRefCount = 13 // Adds Builders + BuilderPendingWithdrawals to the shared-ref set and LatestExecutionPayloadHeader is removed
|
||||
)
|
||||
|
||||
// InitializeFromProtoPhase0 the beacon state from a protobuf representation.
|
||||
@@ -817,11 +819,13 @@ func InitializeFromProtoUnsafeGloas(st *ethpb.BeaconStateGloas) (state.BeaconSta
|
||||
pendingConsolidations: st.PendingConsolidations,
|
||||
proposerLookahead: proposerLookahead,
|
||||
latestExecutionPayloadBid: st.LatestExecutionPayloadBid,
|
||||
builders: st.Builders,
|
||||
nextWithdrawalBuilderIndex: st.NextWithdrawalBuilderIndex,
|
||||
executionPayloadAvailability: st.ExecutionPayloadAvailability,
|
||||
builderPendingPayments: st.BuilderPendingPayments,
|
||||
builderPendingWithdrawals: st.BuilderPendingWithdrawals,
|
||||
latestBlockHash: st.LatestBlockHash,
|
||||
latestWithdrawalsRoot: st.LatestWithdrawalsRoot,
|
||||
payloadExpectedWithdrawals: st.PayloadExpectedWithdrawals,
|
||||
dirtyFields: make(map[types.FieldIndex]bool, fieldCount),
|
||||
dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount),
|
||||
stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount),
|
||||
@@ -861,6 +865,7 @@ func InitializeFromProtoUnsafeGloas(st *ethpb.BeaconStateGloas) (state.BeaconSta
|
||||
b.sharedFieldReferences[types.PendingPartialWithdrawals] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.PendingConsolidations] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.ProposerLookahead] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.Builders] = stateutil.NewRef(1) // New in Gloas.
|
||||
b.sharedFieldReferences[types.BuilderPendingWithdrawals] = stateutil.NewRef(1) // New in Gloas.
|
||||
|
||||
state.Count.Inc()
|
||||
@@ -932,6 +937,7 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
pendingDeposits: b.pendingDeposits,
|
||||
pendingPartialWithdrawals: b.pendingPartialWithdrawals,
|
||||
pendingConsolidations: b.pendingConsolidations,
|
||||
builders: b.builders,
|
||||
|
||||
// Everything else, too small to be concerned about, constant size.
|
||||
genesisValidatorsRoot: b.genesisValidatorsRoot,
|
||||
@@ -948,11 +954,12 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
latestExecutionPayloadHeaderCapella: b.latestExecutionPayloadHeaderCapella.Copy(),
|
||||
latestExecutionPayloadHeaderDeneb: b.latestExecutionPayloadHeaderDeneb.Copy(),
|
||||
latestExecutionPayloadBid: b.latestExecutionPayloadBid.Copy(),
|
||||
nextWithdrawalBuilderIndex: b.nextWithdrawalBuilderIndex,
|
||||
executionPayloadAvailability: b.executionPayloadAvailabilityVal(),
|
||||
builderPendingPayments: b.builderPendingPaymentsVal(),
|
||||
builderPendingWithdrawals: b.builderPendingWithdrawalsVal(),
|
||||
latestBlockHash: b.latestBlockHashVal(),
|
||||
latestWithdrawalsRoot: b.latestWithdrawalsRootVal(),
|
||||
payloadExpectedWithdrawals: b.payloadExpectedWithdrawalsVal(),
|
||||
|
||||
id: types.Enumerator.Inc(),
|
||||
|
||||
@@ -1328,6 +1335,10 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex)
|
||||
return stateutil.ProposerLookaheadRoot(b.proposerLookahead)
|
||||
case types.LatestExecutionPayloadBid:
|
||||
return b.latestExecutionPayloadBid.HashTreeRoot()
|
||||
case types.Builders:
|
||||
return stateutil.BuildersRoot(b.builders)
|
||||
case types.NextWithdrawalBuilderIndex:
|
||||
return ssz.Uint64Root(uint64(b.nextWithdrawalBuilderIndex)), nil
|
||||
case types.ExecutionPayloadAvailability:
|
||||
return stateutil.ExecutionPayloadAvailabilityRoot(b.executionPayloadAvailability)
|
||||
|
||||
@@ -1337,8 +1348,8 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex)
|
||||
return stateutil.BuilderPendingWithdrawalsRoot(b.builderPendingWithdrawals)
|
||||
case types.LatestBlockHash:
|
||||
return bytesutil.ToBytes32(b.latestBlockHash), nil
|
||||
case types.LatestWithdrawalsRoot:
|
||||
return bytesutil.ToBytes32(b.latestWithdrawalsRoot), nil
|
||||
case types.PayloadExpectedWithdrawals:
|
||||
return ssz.WithdrawalSliceRoot(b.payloadExpectedWithdrawals, fieldparams.MaxWithdrawalsPerPayload)
|
||||
}
|
||||
return [32]byte{}, errors.New("invalid field index provided")
|
||||
}
|
||||
|
||||
@@ -116,6 +116,10 @@ func (f FieldIndex) String() string {
|
||||
return "pendingConsolidations"
|
||||
case ProposerLookahead:
|
||||
return "proposerLookahead"
|
||||
case Builders:
|
||||
return "builders"
|
||||
case NextWithdrawalBuilderIndex:
|
||||
return "nextWithdrawalBuilderIndex"
|
||||
case ExecutionPayloadAvailability:
|
||||
return "executionPayloadAvailability"
|
||||
case BuilderPendingPayments:
|
||||
@@ -124,8 +128,8 @@ func (f FieldIndex) String() string {
|
||||
return "builderPendingWithdrawals"
|
||||
case LatestBlockHash:
|
||||
return "latestBlockHash"
|
||||
case LatestWithdrawalsRoot:
|
||||
return "latestWithdrawalsRoot"
|
||||
case PayloadExpectedWithdrawals:
|
||||
return "payloadExpectedWithdrawals"
|
||||
default:
|
||||
return fmt.Sprintf("unknown field index number: %d", f)
|
||||
}
|
||||
@@ -211,16 +215,20 @@ func (f FieldIndex) RealPosition() int {
|
||||
return 36
|
||||
case ProposerLookahead:
|
||||
return 37
|
||||
case ExecutionPayloadAvailability:
|
||||
case Builders:
|
||||
return 38
|
||||
case BuilderPendingPayments:
|
||||
case NextWithdrawalBuilderIndex:
|
||||
return 39
|
||||
case BuilderPendingWithdrawals:
|
||||
case ExecutionPayloadAvailability:
|
||||
return 40
|
||||
case LatestBlockHash:
|
||||
case BuilderPendingPayments:
|
||||
return 41
|
||||
case LatestWithdrawalsRoot:
|
||||
case BuilderPendingWithdrawals:
|
||||
return 42
|
||||
case LatestBlockHash:
|
||||
return 43
|
||||
case PayloadExpectedWithdrawals:
|
||||
return 44
|
||||
default:
|
||||
return -1
|
||||
}
|
||||
@@ -287,11 +295,13 @@ const (
|
||||
PendingPartialWithdrawals // Electra: EIP-7251
|
||||
PendingConsolidations // Electra: EIP-7251
|
||||
ProposerLookahead // Fulu: EIP-7917
|
||||
Builders // Gloas: EIP-7732
|
||||
NextWithdrawalBuilderIndex // Gloas: EIP-7732
|
||||
ExecutionPayloadAvailability // Gloas: EIP-7732
|
||||
BuilderPendingPayments // Gloas: EIP-7732
|
||||
BuilderPendingWithdrawals // Gloas: EIP-7732
|
||||
LatestBlockHash // Gloas: EIP-7732
|
||||
LatestWithdrawalsRoot // Gloas: EIP-7732
|
||||
PayloadExpectedWithdrawals // Gloas: EIP-7732
|
||||
)
|
||||
|
||||
// Enumerator keeps track of the number of states created since the node's start.
|
||||
|
||||
@@ -6,6 +6,7 @@ go_library(
|
||||
"block_header_root.go",
|
||||
"builder_pending_payments_root.go",
|
||||
"builder_pending_withdrawals_root.go",
|
||||
"builders_root.go",
|
||||
"eth1_root.go",
|
||||
"execution_payload_availability_root.go",
|
||||
"field_root_attestation.go",
|
||||
|
||||
12
beacon-chain/state/stateutil/builders_root.go
Normal file
12
beacon-chain/state/stateutil/builders_root.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package stateutil
|
||||
|
||||
import (
|
||||
fieldparams "github.com/OffchainLabs/prysm/v7/config/fieldparams"
|
||||
"github.com/OffchainLabs/prysm/v7/encoding/ssz"
|
||||
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
// BuildersRoot computes the SSZ root of a slice of Builder.
|
||||
func BuildersRoot(slice []*ethpb.Builder) ([32]byte, error) {
|
||||
return ssz.SliceRoot(slice, uint64(fieldparams.BuilderRegistryLimit))
|
||||
}
|
||||
@@ -70,7 +70,6 @@ func TestSyncHandlers_WaitToSync(t *testing.T) {
|
||||
|
||||
topic := "/eth2/%x/beacon_block"
|
||||
go r.startDiscoveryAndSubscriptions()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
var vr [32]byte
|
||||
require.NoError(t, gs.SetClock(startup.NewClock(time.Now(), vr)))
|
||||
@@ -83,9 +82,11 @@ func TestSyncHandlers_WaitToSync(t *testing.T) {
|
||||
msg.Block.ParentRoot = util.Random32Bytes(t)
|
||||
msg.Signature = sk.Sign([]byte("data")).Marshal()
|
||||
p2p.ReceivePubSub(topic, msg)
|
||||
// wait for chainstart to be sent
|
||||
time.Sleep(400 * time.Millisecond)
|
||||
require.Equal(t, true, r.chainStarted.IsSet(), "Did not receive chain start event.")
|
||||
|
||||
// Wait for chainstart event to be processed
|
||||
require.Eventually(t, func() bool {
|
||||
return r.chainStarted.IsSet()
|
||||
}, 5*time.Second, 50*time.Millisecond, "Did not receive chain start event.")
|
||||
}
|
||||
|
||||
func TestSyncHandlers_WaitForChainStart(t *testing.T) {
|
||||
@@ -217,20 +218,18 @@ func TestSyncService_StopCleanly(t *testing.T) {
|
||||
p2p.Digest, err = r.currentForkDigest()
|
||||
require.NoError(t, err)
|
||||
|
||||
// wait for chainstart to be sent
|
||||
time.Sleep(2 * time.Second)
|
||||
require.Equal(t, true, r.chainStarted.IsSet(), "Did not receive chain start event.")
|
||||
|
||||
require.NotEqual(t, 0, len(r.cfg.p2p.PubSub().GetTopics()))
|
||||
require.NotEqual(t, 0, len(r.cfg.p2p.Host().Mux().Protocols()))
|
||||
// Wait for chainstart and topics to be registered
|
||||
require.Eventually(t, func() bool {
|
||||
return r.chainStarted.IsSet() && len(r.cfg.p2p.PubSub().GetTopics()) > 0 && len(r.cfg.p2p.Host().Mux().Protocols()) > 0
|
||||
}, 5*time.Second, 50*time.Millisecond, "Did not receive chain start event or topics not registered.")
|
||||
|
||||
// Both pubsub and rpc topics should be unsubscribed.
|
||||
require.NoError(t, r.Stop())
|
||||
|
||||
// Sleep to allow pubsub topics to be deregistered.
|
||||
time.Sleep(1 * time.Second)
|
||||
require.Equal(t, 0, len(r.cfg.p2p.PubSub().GetTopics()))
|
||||
require.Equal(t, 0, len(r.cfg.p2p.Host().Mux().Protocols()))
|
||||
// Wait for pubsub topics to be deregistered.
|
||||
require.Eventually(t, func() bool {
|
||||
return len(r.cfg.p2p.PubSub().GetTopics()) == 0 && len(r.cfg.p2p.Host().Mux().Protocols()) == 0
|
||||
}, 5*time.Second, 50*time.Millisecond, "Pubsub topics were not deregistered")
|
||||
}
|
||||
|
||||
func TestService_Stop_SendsGoodbyeMessages(t *testing.T) {
|
||||
|
||||
@@ -614,11 +614,10 @@ func TestVerifyIndexInCommittee_SeenAggregatorEpoch(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
time.Sleep(10 * time.Millisecond) // Wait for cached value to pass through buffers.
|
||||
if res, err := r.validateAggregateAndProof(t.Context(), "", msg); res == pubsub.ValidationAccept {
|
||||
_ = err
|
||||
t.Fatal("Validated status is true")
|
||||
}
|
||||
require.Eventually(t, func() bool {
|
||||
res, _ := r.validateAggregateAndProof(t.Context(), "", msg)
|
||||
return res != pubsub.ValidationAccept
|
||||
}, time.Second, 10*time.Millisecond, "Expected validation to reject duplicate aggregate")
|
||||
}
|
||||
|
||||
func TestValidateAggregateAndProof_BadBlock(t *testing.T) {
|
||||
|
||||
@@ -992,7 +992,6 @@ func TestValidateBeaconBlockPubSub_SeenProposerSlot(t *testing.T) {
|
||||
|
||||
// Mark the proposer/slot as seen
|
||||
r.setSeenBlockIndexSlot(msg.Block.Slot, msg.Block.ProposerIndex)
|
||||
time.Sleep(10 * time.Millisecond) // Wait for cached value to pass through buffers
|
||||
|
||||
// Prepare and validate the second message (clone)
|
||||
buf := new(bytes.Buffer)
|
||||
@@ -1010,9 +1009,11 @@ func TestValidateBeaconBlockPubSub_SeenProposerSlot(t *testing.T) {
|
||||
}
|
||||
|
||||
// Since this is not an equivocation (same signature), it should be ignored
|
||||
res, err := r.validateBeaconBlockPubSub(ctx, "", m)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, pubsub.ValidationIgnore, res, "block with same signature should be ignored")
|
||||
// Wait for the cached value to propagate through buffers
|
||||
require.Eventually(t, func() bool {
|
||||
res, err := r.validateBeaconBlockPubSub(ctx, "", m)
|
||||
return err == nil && res == pubsub.ValidationIgnore
|
||||
}, time.Second, 10*time.Millisecond, "block with same signature should be ignored")
|
||||
|
||||
// Verify no slashings were created
|
||||
assert.Equal(t, 0, len(slashingPool.PendingPropSlashings), "Expected no slashings for same signature")
|
||||
|
||||
3
changelog/james-prysm_is-ready.md
Normal file
3
changelog/james-prysm_is-ready.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Changed
|
||||
|
||||
- changed IsHealthy check to IsReady for validator client's interpretation from /eth/v1/node/health, 206 will now return false as the node is syncing.
|
||||
3
changelog/jrhea_duplicate_tracer_provider_setting.md
Normal file
3
changelog/jrhea_duplicate_tracer_provider_setting.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Fixed
|
||||
|
||||
- Don't call trace.WithMaxExportBatchSize(trace.DefaultMaxExportBatchSize) twice.
|
||||
2
changelog/potuz_update_spectests.md
Normal file
2
changelog/potuz_update_spectests.md
Normal file
@@ -0,0 +1,2 @@
|
||||
### Added
|
||||
- Update spectests to v1.7.0-alpha.0
|
||||
3
changelog/pvl_fix-flaky-tests-polling.md
Normal file
3
changelog/pvl_fix-flaky-tests-polling.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Changed
|
||||
|
||||
- Replaced `time.Sleep` with `require.Eventually` polling in tests to fix flaky behavior caused by race conditions between goroutines and assertions.
|
||||
3
changelog/t_gloas-builders-registry.md
Normal file
3
changelog/t_gloas-builders-registry.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Added
|
||||
|
||||
- Added basic Gloas builder support (`Builder` message and `BeaconStateGloas` `builders`/`next_withdrawal_builder_index` fields)
|
||||
@@ -9,6 +9,7 @@ const (
|
||||
RandaoMixesLength = 65536 // EPOCHS_PER_HISTORICAL_VECTOR
|
||||
HistoricalRootsLength = 16777216 // HISTORICAL_ROOTS_LIMIT
|
||||
ValidatorRegistryLimit = 1099511627776 // VALIDATOR_REGISTRY_LIMIT
|
||||
BuilderRegistryLimit = 1099511627776 // BUILDER_REGISTRY_LIMIT
|
||||
Eth1DataVotesLength = 2048 // SLOTS_PER_ETH1_VOTING_PERIOD
|
||||
PreviousEpochAttestationsLength = 4096 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH
|
||||
CurrentEpochAttestationsLength = 4096 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH
|
||||
|
||||
@@ -9,6 +9,7 @@ const (
|
||||
RandaoMixesLength = 64 // EPOCHS_PER_HISTORICAL_VECTOR
|
||||
HistoricalRootsLength = 16777216 // HISTORICAL_ROOTS_LIMIT
|
||||
ValidatorRegistryLimit = 1099511627776 // VALIDATOR_REGISTRY_LIMIT
|
||||
BuilderRegistryLimit = 1099511627776 // BUILDER_REGISTRY_LIMIT
|
||||
Eth1DataVotesLength = 32 // SLOTS_PER_ETH1_VOTING_PERIOD
|
||||
PreviousEpochAttestationsLength = 1024 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH
|
||||
CurrentEpochAttestationsLength = 1024 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH
|
||||
|
||||
@@ -55,7 +55,8 @@ var placeholderFields = []string{
|
||||
"MAX_REQUEST_BLOB_SIDECARS_FULU",
|
||||
"MAX_REQUEST_INCLUSION_LIST",
|
||||
"MAX_REQUEST_PAYLOADS", // Compile time constant on BeaconBlockBody.ExecutionRequests
|
||||
"NUMBER_OF_COLUMNS", // Configured as a constant in config/fieldparams/mainnet.go
|
||||
"MIN_BUILDER_WITHDRAWABILITY_DELAY",
|
||||
"NUMBER_OF_COLUMNS", // Configured as a constant in config/fieldparams/mainnet.go
|
||||
"PAYLOAD_ATTESTATION_DUE_BPS",
|
||||
"PROPOSER_INCLUSION_LIST_CUTOFF",
|
||||
"PROPOSER_INCLUSION_LIST_CUTOFF_BPS",
|
||||
|
||||
@@ -206,7 +206,7 @@ var mainnetBeaconConfig = &BeaconChainConfig{
|
||||
BeaconStateDenebFieldCount: 28,
|
||||
BeaconStateElectraFieldCount: 37,
|
||||
BeaconStateFuluFieldCount: 38,
|
||||
BeaconStateGloasFieldCount: 43,
|
||||
BeaconStateGloasFieldCount: 45,
|
||||
|
||||
// Slasher related values.
|
||||
WeakSubjectivityPeriod: 54000,
|
||||
|
||||
@@ -669,6 +669,7 @@ func hydrateBeaconBlockBodyGloas() *eth.BeaconBlockBodyGloas {
|
||||
ParentBlockHash: make([]byte, fieldparams.RootLength),
|
||||
ParentBlockRoot: make([]byte, fieldparams.RootLength),
|
||||
BlockHash: make([]byte, fieldparams.RootLength),
|
||||
PrevRandao: make([]byte, fieldparams.RootLength),
|
||||
FeeRecipient: make([]byte, 20),
|
||||
BlobKzgCommitmentsRoot: make([]byte, fieldparams.RootLength),
|
||||
},
|
||||
|
||||
@@ -45,7 +45,6 @@ func Setup(ctx context.Context, serviceName, processName, endpoint string, sampl
|
||||
exporter,
|
||||
trace.WithMaxExportBatchSize(trace.DefaultMaxExportBatchSize),
|
||||
trace.WithBatchTimeout(trace.DefaultScheduleDelay*time.Millisecond),
|
||||
trace.WithMaxExportBatchSize(trace.DefaultMaxExportBatchSize),
|
||||
),
|
||||
trace.WithResource(
|
||||
resource.NewWithAttributes(
|
||||
|
||||
@@ -35,6 +35,21 @@ func CopyValidator(val *Validator) *Validator {
|
||||
}
|
||||
}
|
||||
|
||||
// CopyBuilder copies the provided builder.
|
||||
func CopyBuilder(builder *Builder) *Builder {
|
||||
if builder == nil {
|
||||
return nil
|
||||
}
|
||||
return &Builder{
|
||||
Pubkey: bytesutil.SafeCopyBytes(builder.Pubkey),
|
||||
Version: bytesutil.SafeCopyBytes(builder.Version),
|
||||
ExecutionAddress: bytesutil.SafeCopyBytes(builder.ExecutionAddress),
|
||||
Balance: builder.Balance,
|
||||
DepositEpoch: builder.DepositEpoch,
|
||||
WithdrawableEpoch: builder.WithdrawableEpoch,
|
||||
}
|
||||
}
|
||||
|
||||
// CopySyncCommitteeMessage copies the provided sync committee message object.
|
||||
func CopySyncCommitteeMessage(s *SyncCommitteeMessage) *SyncCommitteeMessage {
|
||||
if s == nil {
|
||||
|
||||
@@ -1220,7 +1220,7 @@ func genExecutionPayloadBidGloas() *v1alpha1.ExecutionPayloadBid {
|
||||
BlockHash: bytes(32),
|
||||
FeeRecipient: bytes(20),
|
||||
GasLimit: rand.Uint64(),
|
||||
BuilderIndex: primitives.ValidatorIndex(rand.Uint64()),
|
||||
BuilderIndex: primitives.BuilderIndex(rand.Uint64()),
|
||||
Slot: primitives.Slot(rand.Uint64()),
|
||||
Value: primitives.Gwei(rand.Uint64()),
|
||||
BlobKzgCommitmentsRoot: bytes(32),
|
||||
|
||||
@@ -13,11 +13,13 @@ func (header *ExecutionPayloadBid) Copy() *ExecutionPayloadBid {
|
||||
ParentBlockHash: bytesutil.SafeCopyBytes(header.ParentBlockHash),
|
||||
ParentBlockRoot: bytesutil.SafeCopyBytes(header.ParentBlockRoot),
|
||||
BlockHash: bytesutil.SafeCopyBytes(header.BlockHash),
|
||||
PrevRandao: bytesutil.SafeCopyBytes(header.PrevRandao),
|
||||
FeeRecipient: bytesutil.SafeCopyBytes(header.FeeRecipient),
|
||||
GasLimit: header.GasLimit,
|
||||
BuilderIndex: header.BuilderIndex,
|
||||
Slot: header.Slot,
|
||||
Value: header.Value,
|
||||
ExecutionPayment: header.ExecutionPayment,
|
||||
BlobKzgCommitmentsRoot: bytesutil.SafeCopyBytes(header.BlobKzgCommitmentsRoot),
|
||||
}
|
||||
}
|
||||
@@ -28,10 +30,9 @@ func (withdrawal *BuilderPendingWithdrawal) Copy() *BuilderPendingWithdrawal {
|
||||
return nil
|
||||
}
|
||||
return &BuilderPendingWithdrawal{
|
||||
FeeRecipient: bytesutil.SafeCopyBytes(withdrawal.FeeRecipient),
|
||||
Amount: withdrawal.Amount,
|
||||
BuilderIndex: withdrawal.BuilderIndex,
|
||||
WithdrawableEpoch: withdrawal.WithdrawableEpoch,
|
||||
FeeRecipient: bytesutil.SafeCopyBytes(withdrawal.FeeRecipient),
|
||||
Amount: withdrawal.Amount,
|
||||
BuilderIndex: withdrawal.BuilderIndex,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1367
proto/prysm/v1alpha1/gloas.pb.go
generated
1367
proto/prysm/v1alpha1/gloas.pb.go
generated
File diff suppressed because it is too large
Load Diff
@@ -26,30 +26,37 @@ option go_package = "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1;eth";
|
||||
// parent_block_hash: Hash32
|
||||
// parent_block_root: Root
|
||||
// block_hash: Hash32
|
||||
// prev_randao: Bytes32
|
||||
// fee_recipient: ExecutionAddress
|
||||
// gas_limit: uint64
|
||||
// builder_index: ValidatorIndex
|
||||
// builder_index: BuilderIndex
|
||||
// slot: Slot
|
||||
// value: Gwei
|
||||
// execution_payment: Gwei
|
||||
// blob_kzg_commitments_root: Root
|
||||
message ExecutionPayloadBid {
|
||||
bytes parent_block_hash = 1 [ (ethereum.eth.ext.ssz_size) = "32" ];
|
||||
bytes parent_block_root = 2 [ (ethereum.eth.ext.ssz_size) = "32" ];
|
||||
bytes block_hash = 3 [ (ethereum.eth.ext.ssz_size) = "32" ];
|
||||
bytes fee_recipient = 4 [ (ethereum.eth.ext.ssz_size) = "20" ];
|
||||
uint64 gas_limit = 5;
|
||||
uint64 builder_index = 6 [ (ethereum.eth.ext.cast_type) =
|
||||
bytes prev_randao = 4 [ (ethereum.eth.ext.ssz_size) = "32" ];
|
||||
bytes fee_recipient = 5 [ (ethereum.eth.ext.ssz_size) = "20" ];
|
||||
uint64 gas_limit = 6;
|
||||
uint64 builder_index = 7 [ (ethereum.eth.ext.cast_type) =
|
||||
"github.com/OffchainLabs/prysm/v7/"
|
||||
"consensus-types/primitives.ValidatorIndex" ];
|
||||
uint64 slot = 7 [
|
||||
"consensus-types/primitives.BuilderIndex" ];
|
||||
uint64 slot = 8 [
|
||||
(ethereum.eth.ext.cast_type) =
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives.Slot"
|
||||
];
|
||||
uint64 value = 8 [
|
||||
uint64 value = 9 [
|
||||
(ethereum.eth.ext.cast_type) =
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives.Gwei"
|
||||
];
|
||||
bytes blob_kzg_commitments_root = 9 [ (ethereum.eth.ext.ssz_size) = "32" ];
|
||||
uint64 execution_payment = 10 [
|
||||
(ethereum.eth.ext.cast_type) =
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives.Gwei"
|
||||
];
|
||||
bytes blob_kzg_commitments_root = 11 [ (ethereum.eth.ext.ssz_size) = "32" ];
|
||||
}
|
||||
|
||||
// SignedExecutionPayloadBid wraps an execution payload bid with a signature.
|
||||
@@ -185,12 +192,15 @@ message SignedBeaconBlockGloas {
|
||||
// [All previous fields from earlier forks]
|
||||
// # Replaced existing latest execution header position
|
||||
// latest_execution_payload_bid: ExecutionPayloadBid
|
||||
// # New fields in Gloas:EIP7732
|
||||
// builders: List[Builder, BUILDER_REGISTRY_LIMIT]
|
||||
// # [New in Gloas:EIP7732]
|
||||
// next_withdrawal_builder_index: BuilderIndex
|
||||
// # [New in Gloas:EIP7732]
|
||||
// execution_payload_availability: Bitvector[SLOTS_PER_HISTORICAL_ROOT]
|
||||
// builder_pending_payments: Vector[BuilderPendingPayment, 2 * SLOTS_PER_EPOCH]
|
||||
// builder_pending_withdrawals: List[BuilderPendingWithdrawal, BUILDER_PENDING_WITHDRAWALS_LIMIT]
|
||||
// latest_block_hash: Hash32
|
||||
// latest_withdrawals_root: Root
|
||||
// payload_expected_withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]
|
||||
message BeaconStateGloas {
|
||||
// Versioning [1001-2000]
|
||||
uint64 genesis_time = 1001;
|
||||
@@ -300,13 +310,20 @@ message BeaconStateGloas {
|
||||
[ (ethereum.eth.ext.ssz_size) = "proposer_lookahead_size" ];
|
||||
|
||||
// Fields introduced in Gloas fork [14001-15000]
|
||||
bytes execution_payload_availability = 14001 [
|
||||
repeated Builder builders = 14001
|
||||
[ (ethereum.eth.ext.ssz_max) = "builder_registry_limit" ];
|
||||
uint64 next_withdrawal_builder_index = 14002
|
||||
[ (ethereum.eth.ext.cast_type) =
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/"
|
||||
"primitives.BuilderIndex" ];
|
||||
bytes execution_payload_availability = 14003 [
|
||||
(ethereum.eth.ext.ssz_size) = "execution_payload_availability.size"
|
||||
];
|
||||
repeated BuilderPendingPayment builder_pending_payments = 14002 [(ethereum.eth.ext.ssz_size) = "builder_pending_payments.size"];
|
||||
repeated BuilderPendingWithdrawal builder_pending_withdrawals = 14003 [(ethereum.eth.ext.ssz_max) = "1048576"];
|
||||
bytes latest_block_hash = 14004 [ (ethereum.eth.ext.ssz_size) = "32" ];
|
||||
bytes latest_withdrawals_root = 14005 [ (ethereum.eth.ext.ssz_size) = "32" ];
|
||||
repeated BuilderPendingPayment builder_pending_payments = 14004 [(ethereum.eth.ext.ssz_size) = "builder_pending_payments.size"];
|
||||
repeated BuilderPendingWithdrawal builder_pending_withdrawals = 14005 [(ethereum.eth.ext.ssz_max) = "1048576"];
|
||||
bytes latest_block_hash = 14006 [ (ethereum.eth.ext.ssz_size) = "32" ];
|
||||
repeated ethereum.engine.v1.Withdrawal payload_expected_withdrawals = 14007
|
||||
[ (ethereum.eth.ext.ssz_max) = "withdrawal.size" ];
|
||||
}
|
||||
|
||||
// BuilderPendingPayment represents a pending payment to a builder.
|
||||
@@ -329,8 +346,7 @@ message BuilderPendingPayment {
|
||||
// class BuilderPendingWithdrawal(Container):
|
||||
// fee_recipient: ExecutionAddress
|
||||
// amount: Gwei
|
||||
// builder_index: ValidatorIndex
|
||||
// withdrawable_epoch: Epoch
|
||||
// builder_index: BuilderIndex
|
||||
message BuilderPendingWithdrawal {
|
||||
bytes fee_recipient = 1 [ (ethereum.eth.ext.ssz_size) = "20" ];
|
||||
uint64 amount = 2 [
|
||||
@@ -340,11 +356,7 @@ message BuilderPendingWithdrawal {
|
||||
uint64 builder_index = 3
|
||||
[ (ethereum.eth.ext.cast_type) =
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/"
|
||||
"primitives.ValidatorIndex" ];
|
||||
uint64 withdrawable_epoch = 4 [
|
||||
(ethereum.eth.ext.cast_type) =
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives.Epoch"
|
||||
];
|
||||
"primitives.BuilderIndex" ];
|
||||
}
|
||||
|
||||
// DataColumnSidecarGloas represents a data column sidecar in the Gloas fork.
|
||||
@@ -387,7 +399,7 @@ message DataColumnSidecarGloas {
|
||||
// class ExecutionPayloadEnvelope(Container):
|
||||
// payload: ExecutionPayload
|
||||
// execution_requests: ExecutionRequests
|
||||
// builder_index: ValidatorIndex
|
||||
// builder_index: BuilderIndex
|
||||
// beacon_block_root: Root
|
||||
// slot: Slot
|
||||
// blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK]
|
||||
@@ -397,7 +409,7 @@ message ExecutionPayloadEnvelope {
|
||||
ethereum.engine.v1.ExecutionRequests execution_requests = 2;
|
||||
uint64 builder_index = 3 [ (ethereum.eth.ext.cast_type) =
|
||||
"github.com/OffchainLabs/prysm/v7/"
|
||||
"consensus-types/primitives.ValidatorIndex" ];
|
||||
"consensus-types/primitives.BuilderIndex" ];
|
||||
bytes beacon_block_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ];
|
||||
uint64 slot = 5 [
|
||||
(ethereum.eth.ext.cast_type) =
|
||||
@@ -421,3 +433,31 @@ message SignedExecutionPayloadEnvelope {
|
||||
ExecutionPayloadEnvelope message = 1;
|
||||
bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ];
|
||||
}
|
||||
|
||||
// Builder represents a builder in the Gloas fork.
|
||||
//
|
||||
// Spec:
|
||||
// class Builder(Container):
|
||||
// pubkey: BLSPubkey
|
||||
// version: uint8
|
||||
// execution_address: ExecutionAddress
|
||||
// balance: Gwei
|
||||
// deposit_epoch: Epoch
|
||||
// withdrawable_epoch: Epoch
|
||||
message Builder {
|
||||
bytes pubkey = 1 [ (ethereum.eth.ext.ssz_size) = "48" ];
|
||||
bytes version = 2 [ (ethereum.eth.ext.ssz_size) = "1" ];
|
||||
bytes execution_address = 3 [ (ethereum.eth.ext.ssz_size) = "20" ];
|
||||
uint64 balance = 4 [
|
||||
(ethereum.eth.ext.cast_type) =
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives.Gwei"
|
||||
];
|
||||
uint64 deposit_epoch = 5 [
|
||||
(ethereum.eth.ext.cast_type) =
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives.Epoch"
|
||||
];
|
||||
uint64 withdrawable_epoch = 6 [
|
||||
(ethereum.eth.ext.cast_type) =
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives.Epoch"
|
||||
];
|
||||
}
|
||||
|
||||
@@ -37,26 +37,36 @@ func (e *ExecutionPayloadBid) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
}
|
||||
dst = append(dst, e.BlockHash...)
|
||||
|
||||
// Field (3) 'FeeRecipient'
|
||||
// Field (3) 'PrevRandao'
|
||||
if size := len(e.PrevRandao); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.PrevRandao", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, e.PrevRandao...)
|
||||
|
||||
// Field (4) 'FeeRecipient'
|
||||
if size := len(e.FeeRecipient); size != 20 {
|
||||
err = ssz.ErrBytesLengthFn("--.FeeRecipient", size, 20)
|
||||
return
|
||||
}
|
||||
dst = append(dst, e.FeeRecipient...)
|
||||
|
||||
// Field (4) 'GasLimit'
|
||||
// Field (5) 'GasLimit'
|
||||
dst = ssz.MarshalUint64(dst, e.GasLimit)
|
||||
|
||||
// Field (5) 'BuilderIndex'
|
||||
// Field (6) 'BuilderIndex'
|
||||
dst = ssz.MarshalUint64(dst, uint64(e.BuilderIndex))
|
||||
|
||||
// Field (6) 'Slot'
|
||||
// Field (7) 'Slot'
|
||||
dst = ssz.MarshalUint64(dst, uint64(e.Slot))
|
||||
|
||||
// Field (7) 'Value'
|
||||
// Field (8) 'Value'
|
||||
dst = ssz.MarshalUint64(dst, uint64(e.Value))
|
||||
|
||||
// Field (8) 'BlobKzgCommitmentsRoot'
|
||||
// Field (9) 'ExecutionPayment'
|
||||
dst = ssz.MarshalUint64(dst, uint64(e.ExecutionPayment))
|
||||
|
||||
// Field (10) 'BlobKzgCommitmentsRoot'
|
||||
if size := len(e.BlobKzgCommitmentsRoot); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.BlobKzgCommitmentsRoot", size, 32)
|
||||
return
|
||||
@@ -70,7 +80,7 @@ func (e *ExecutionPayloadBid) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
func (e *ExecutionPayloadBid) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size != 180 {
|
||||
if size != 220 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
@@ -92,36 +102,45 @@ func (e *ExecutionPayloadBid) UnmarshalSSZ(buf []byte) error {
|
||||
}
|
||||
e.BlockHash = append(e.BlockHash, buf[64:96]...)
|
||||
|
||||
// Field (3) 'FeeRecipient'
|
||||
// Field (3) 'PrevRandao'
|
||||
if cap(e.PrevRandao) == 0 {
|
||||
e.PrevRandao = make([]byte, 0, len(buf[96:128]))
|
||||
}
|
||||
e.PrevRandao = append(e.PrevRandao, buf[96:128]...)
|
||||
|
||||
// Field (4) 'FeeRecipient'
|
||||
if cap(e.FeeRecipient) == 0 {
|
||||
e.FeeRecipient = make([]byte, 0, len(buf[96:116]))
|
||||
e.FeeRecipient = make([]byte, 0, len(buf[128:148]))
|
||||
}
|
||||
e.FeeRecipient = append(e.FeeRecipient, buf[96:116]...)
|
||||
e.FeeRecipient = append(e.FeeRecipient, buf[128:148]...)
|
||||
|
||||
// Field (4) 'GasLimit'
|
||||
e.GasLimit = ssz.UnmarshallUint64(buf[116:124])
|
||||
// Field (5) 'GasLimit'
|
||||
e.GasLimit = ssz.UnmarshallUint64(buf[148:156])
|
||||
|
||||
// Field (5) 'BuilderIndex'
|
||||
e.BuilderIndex = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[124:132]))
|
||||
// Field (6) 'BuilderIndex'
|
||||
e.BuilderIndex = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.BuilderIndex(ssz.UnmarshallUint64(buf[156:164]))
|
||||
|
||||
// Field (6) 'Slot'
|
||||
e.Slot = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[132:140]))
|
||||
// Field (7) 'Slot'
|
||||
e.Slot = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[164:172]))
|
||||
|
||||
// Field (7) 'Value'
|
||||
e.Value = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[140:148]))
|
||||
// Field (8) 'Value'
|
||||
e.Value = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[172:180]))
|
||||
|
||||
// Field (8) 'BlobKzgCommitmentsRoot'
|
||||
// Field (9) 'ExecutionPayment'
|
||||
e.ExecutionPayment = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[180:188]))
|
||||
|
||||
// Field (10) 'BlobKzgCommitmentsRoot'
|
||||
if cap(e.BlobKzgCommitmentsRoot) == 0 {
|
||||
e.BlobKzgCommitmentsRoot = make([]byte, 0, len(buf[148:180]))
|
||||
e.BlobKzgCommitmentsRoot = make([]byte, 0, len(buf[188:220]))
|
||||
}
|
||||
e.BlobKzgCommitmentsRoot = append(e.BlobKzgCommitmentsRoot, buf[148:180]...)
|
||||
e.BlobKzgCommitmentsRoot = append(e.BlobKzgCommitmentsRoot, buf[188:220]...)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the ExecutionPayloadBid object
|
||||
func (e *ExecutionPayloadBid) SizeSSZ() (size int) {
|
||||
size = 180
|
||||
size = 220
|
||||
return
|
||||
}
|
||||
|
||||
@@ -155,26 +174,36 @@ func (e *ExecutionPayloadBid) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
}
|
||||
hh.PutBytes(e.BlockHash)
|
||||
|
||||
// Field (3) 'FeeRecipient'
|
||||
// Field (3) 'PrevRandao'
|
||||
if size := len(e.PrevRandao); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.PrevRandao", size, 32)
|
||||
return
|
||||
}
|
||||
hh.PutBytes(e.PrevRandao)
|
||||
|
||||
// Field (4) 'FeeRecipient'
|
||||
if size := len(e.FeeRecipient); size != 20 {
|
||||
err = ssz.ErrBytesLengthFn("--.FeeRecipient", size, 20)
|
||||
return
|
||||
}
|
||||
hh.PutBytes(e.FeeRecipient)
|
||||
|
||||
// Field (4) 'GasLimit'
|
||||
// Field (5) 'GasLimit'
|
||||
hh.PutUint64(e.GasLimit)
|
||||
|
||||
// Field (5) 'BuilderIndex'
|
||||
// Field (6) 'BuilderIndex'
|
||||
hh.PutUint64(uint64(e.BuilderIndex))
|
||||
|
||||
// Field (6) 'Slot'
|
||||
// Field (7) 'Slot'
|
||||
hh.PutUint64(uint64(e.Slot))
|
||||
|
||||
// Field (7) 'Value'
|
||||
// Field (8) 'Value'
|
||||
hh.PutUint64(uint64(e.Value))
|
||||
|
||||
// Field (8) 'BlobKzgCommitmentsRoot'
|
||||
// Field (9) 'ExecutionPayment'
|
||||
hh.PutUint64(uint64(e.ExecutionPayment))
|
||||
|
||||
// Field (10) 'BlobKzgCommitmentsRoot'
|
||||
if size := len(e.BlobKzgCommitmentsRoot); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.BlobKzgCommitmentsRoot", size, 32)
|
||||
return
|
||||
@@ -216,7 +245,7 @@ func (s *SignedExecutionPayloadBid) MarshalSSZTo(buf []byte) (dst []byte, err er
|
||||
func (s *SignedExecutionPayloadBid) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size != 276 {
|
||||
if size != 316 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
@@ -224,22 +253,22 @@ func (s *SignedExecutionPayloadBid) UnmarshalSSZ(buf []byte) error {
|
||||
if s.Message == nil {
|
||||
s.Message = new(ExecutionPayloadBid)
|
||||
}
|
||||
if err = s.Message.UnmarshalSSZ(buf[0:180]); err != nil {
|
||||
if err = s.Message.UnmarshalSSZ(buf[0:220]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (1) 'Signature'
|
||||
if cap(s.Signature) == 0 {
|
||||
s.Signature = make([]byte, 0, len(buf[180:276]))
|
||||
s.Signature = make([]byte, 0, len(buf[220:316]))
|
||||
}
|
||||
s.Signature = append(s.Signature, buf[180:276]...)
|
||||
s.Signature = append(s.Signature, buf[220:316]...)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the SignedExecutionPayloadBid object
|
||||
func (s *SignedExecutionPayloadBid) SizeSSZ() (size int) {
|
||||
size = 276
|
||||
size = 316
|
||||
return
|
||||
}
|
||||
|
||||
@@ -713,7 +742,7 @@ func (b *BeaconBlockBodyGloas) MarshalSSZ() ([]byte, error) {
|
||||
// MarshalSSZTo ssz marshals the BeaconBlockBodyGloas object to a target array
|
||||
func (b *BeaconBlockBodyGloas) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
offset := int(664)
|
||||
offset := int(704)
|
||||
|
||||
// Field (0) 'RandaoReveal'
|
||||
if size := len(b.RandaoReveal); size != 96 {
|
||||
@@ -885,7 +914,7 @@ func (b *BeaconBlockBodyGloas) MarshalSSZTo(buf []byte) (dst []byte, err error)
|
||||
func (b *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size < 664 {
|
||||
if size < 704 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
@@ -917,7 +946,7 @@ func (b *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
if o3 != 664 {
|
||||
if o3 != 704 {
|
||||
return ssz.ErrInvalidVariableOffset
|
||||
}
|
||||
|
||||
@@ -958,12 +987,12 @@ func (b *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error {
|
||||
if b.SignedExecutionPayloadBid == nil {
|
||||
b.SignedExecutionPayloadBid = new(SignedExecutionPayloadBid)
|
||||
}
|
||||
if err = b.SignedExecutionPayloadBid.UnmarshalSSZ(buf[384:660]); err != nil {
|
||||
if err = b.SignedExecutionPayloadBid.UnmarshalSSZ(buf[384:700]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Offset (11) 'PayloadAttestations'
|
||||
if o11 = ssz.ReadOffset(buf[660:664]); o11 > size || o9 > o11 {
|
||||
if o11 = ssz.ReadOffset(buf[700:704]); o11 > size || o9 > o11 {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
@@ -1105,7 +1134,7 @@ func (b *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error {
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockBodyGloas object
|
||||
func (b *BeaconBlockBodyGloas) SizeSSZ() (size int) {
|
||||
size = 664
|
||||
size = 704
|
||||
|
||||
// Field (3) 'ProposerSlashings'
|
||||
size += len(b.ProposerSlashings) * 416
|
||||
@@ -1408,7 +1437,7 @@ func (b *BeaconStateGloas) MarshalSSZ() ([]byte, error) {
|
||||
// MarshalSSZTo ssz marshals the BeaconStateGloas object to a target array
|
||||
func (b *BeaconStateGloas) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
offset := int(2741821)
|
||||
offset := int(2741333)
|
||||
|
||||
// Field (0) 'GenesisTime'
|
||||
dst = ssz.MarshalUint64(dst, b.GenesisTime)
|
||||
@@ -1630,14 +1659,21 @@ func (b *BeaconStateGloas) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = ssz.MarshalUint64(dst, b.ProposerLookahead[ii])
|
||||
}
|
||||
|
||||
// Field (38) 'ExecutionPayloadAvailability'
|
||||
// Offset (38) 'Builders'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
offset += len(b.Builders) * 93
|
||||
|
||||
// Field (39) 'NextWithdrawalBuilderIndex'
|
||||
dst = ssz.MarshalUint64(dst, uint64(b.NextWithdrawalBuilderIndex))
|
||||
|
||||
// Field (40) 'ExecutionPayloadAvailability'
|
||||
if size := len(b.ExecutionPayloadAvailability); size != 1024 {
|
||||
err = ssz.ErrBytesLengthFn("--.ExecutionPayloadAvailability", size, 1024)
|
||||
return
|
||||
}
|
||||
dst = append(dst, b.ExecutionPayloadAvailability...)
|
||||
|
||||
// Field (39) 'BuilderPendingPayments'
|
||||
// Field (41) 'BuilderPendingPayments'
|
||||
if size := len(b.BuilderPendingPayments); size != 64 {
|
||||
err = ssz.ErrVectorLengthFn("--.BuilderPendingPayments", size, 64)
|
||||
return
|
||||
@@ -1648,23 +1684,20 @@ func (b *BeaconStateGloas) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Offset (40) 'BuilderPendingWithdrawals'
|
||||
// Offset (42) 'BuilderPendingWithdrawals'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
offset += len(b.BuilderPendingWithdrawals) * 44
|
||||
offset += len(b.BuilderPendingWithdrawals) * 36
|
||||
|
||||
// Field (41) 'LatestBlockHash'
|
||||
// Field (43) 'LatestBlockHash'
|
||||
if size := len(b.LatestBlockHash); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.LatestBlockHash", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, b.LatestBlockHash...)
|
||||
|
||||
// Field (42) 'LatestWithdrawalsRoot'
|
||||
if size := len(b.LatestWithdrawalsRoot); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.LatestWithdrawalsRoot", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, b.LatestWithdrawalsRoot...)
|
||||
// Offset (44) 'PayloadExpectedWithdrawals'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
offset += len(b.PayloadExpectedWithdrawals) * 44
|
||||
|
||||
// Field (7) 'HistoricalRoots'
|
||||
if size := len(b.HistoricalRoots); size > 16777216 {
|
||||
@@ -1777,7 +1810,18 @@ func (b *BeaconStateGloas) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Field (40) 'BuilderPendingWithdrawals'
|
||||
// Field (38) 'Builders'
|
||||
if size := len(b.Builders); size > 1099511627776 {
|
||||
err = ssz.ErrListTooBigFn("--.Builders", size, 1099511627776)
|
||||
return
|
||||
}
|
||||
for ii := 0; ii < len(b.Builders); ii++ {
|
||||
if dst, err = b.Builders[ii].MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Field (42) 'BuilderPendingWithdrawals'
|
||||
if size := len(b.BuilderPendingWithdrawals); size > 1048576 {
|
||||
err = ssz.ErrListTooBigFn("--.BuilderPendingWithdrawals", size, 1048576)
|
||||
return
|
||||
@@ -1788,6 +1832,17 @@ func (b *BeaconStateGloas) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Field (44) 'PayloadExpectedWithdrawals'
|
||||
if size := len(b.PayloadExpectedWithdrawals); size > 16 {
|
||||
err = ssz.ErrListTooBigFn("--.PayloadExpectedWithdrawals", size, 16)
|
||||
return
|
||||
}
|
||||
for ii := 0; ii < len(b.PayloadExpectedWithdrawals); ii++ {
|
||||
if dst, err = b.PayloadExpectedWithdrawals[ii].MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1795,12 +1850,12 @@ func (b *BeaconStateGloas) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
func (b *BeaconStateGloas) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size < 2741821 {
|
||||
if size < 2741333 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
tail := buf
|
||||
var o7, o9, o11, o12, o15, o16, o21, o27, o34, o35, o36, o40 uint64
|
||||
var o7, o9, o11, o12, o15, o16, o21, o27, o34, o35, o36, o38, o42, o44 uint64
|
||||
|
||||
// Field (0) 'GenesisTime'
|
||||
b.GenesisTime = ssz.UnmarshallUint64(buf[0:8])
|
||||
@@ -1853,7 +1908,7 @@ func (b *BeaconStateGloas) UnmarshalSSZ(buf []byte) error {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
if o7 != 2741821 {
|
||||
if o7 != 2741333 {
|
||||
return ssz.ErrInvalidVariableOffset
|
||||
}
|
||||
|
||||
@@ -1963,93 +2018,100 @@ func (b *BeaconStateGloas) UnmarshalSSZ(buf []byte) error {
|
||||
if b.LatestExecutionPayloadBid == nil {
|
||||
b.LatestExecutionPayloadBid = new(ExecutionPayloadBid)
|
||||
}
|
||||
if err = b.LatestExecutionPayloadBid.UnmarshalSSZ(buf[2736629:2736809]); err != nil {
|
||||
if err = b.LatestExecutionPayloadBid.UnmarshalSSZ(buf[2736629:2736849]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (25) 'NextWithdrawalIndex'
|
||||
b.NextWithdrawalIndex = ssz.UnmarshallUint64(buf[2736809:2736817])
|
||||
b.NextWithdrawalIndex = ssz.UnmarshallUint64(buf[2736849:2736857])
|
||||
|
||||
// Field (26) 'NextWithdrawalValidatorIndex'
|
||||
b.NextWithdrawalValidatorIndex = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[2736817:2736825]))
|
||||
b.NextWithdrawalValidatorIndex = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[2736857:2736865]))
|
||||
|
||||
// Offset (27) 'HistoricalSummaries'
|
||||
if o27 = ssz.ReadOffset(buf[2736825:2736829]); o27 > size || o21 > o27 {
|
||||
if o27 = ssz.ReadOffset(buf[2736865:2736869]); o27 > size || o21 > o27 {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
// Field (28) 'DepositRequestsStartIndex'
|
||||
b.DepositRequestsStartIndex = ssz.UnmarshallUint64(buf[2736829:2736837])
|
||||
b.DepositRequestsStartIndex = ssz.UnmarshallUint64(buf[2736869:2736877])
|
||||
|
||||
// Field (29) 'DepositBalanceToConsume'
|
||||
b.DepositBalanceToConsume = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[2736837:2736845]))
|
||||
b.DepositBalanceToConsume = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[2736877:2736885]))
|
||||
|
||||
// Field (30) 'ExitBalanceToConsume'
|
||||
b.ExitBalanceToConsume = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[2736845:2736853]))
|
||||
b.ExitBalanceToConsume = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[2736885:2736893]))
|
||||
|
||||
// Field (31) 'EarliestExitEpoch'
|
||||
b.EarliestExitEpoch = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[2736853:2736861]))
|
||||
b.EarliestExitEpoch = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[2736893:2736901]))
|
||||
|
||||
// Field (32) 'ConsolidationBalanceToConsume'
|
||||
b.ConsolidationBalanceToConsume = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[2736861:2736869]))
|
||||
b.ConsolidationBalanceToConsume = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[2736901:2736909]))
|
||||
|
||||
// Field (33) 'EarliestConsolidationEpoch'
|
||||
b.EarliestConsolidationEpoch = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[2736869:2736877]))
|
||||
b.EarliestConsolidationEpoch = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[2736909:2736917]))
|
||||
|
||||
// Offset (34) 'PendingDeposits'
|
||||
if o34 = ssz.ReadOffset(buf[2736877:2736881]); o34 > size || o27 > o34 {
|
||||
if o34 = ssz.ReadOffset(buf[2736917:2736921]); o34 > size || o27 > o34 {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
// Offset (35) 'PendingPartialWithdrawals'
|
||||
if o35 = ssz.ReadOffset(buf[2736881:2736885]); o35 > size || o34 > o35 {
|
||||
if o35 = ssz.ReadOffset(buf[2736921:2736925]); o35 > size || o34 > o35 {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
// Offset (36) 'PendingConsolidations'
|
||||
if o36 = ssz.ReadOffset(buf[2736885:2736889]); o36 > size || o35 > o36 {
|
||||
if o36 = ssz.ReadOffset(buf[2736925:2736929]); o36 > size || o35 > o36 {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
// Field (37) 'ProposerLookahead'
|
||||
b.ProposerLookahead = ssz.ExtendUint64(b.ProposerLookahead, 64)
|
||||
for ii := 0; ii < 64; ii++ {
|
||||
b.ProposerLookahead[ii] = ssz.UnmarshallUint64(buf[2736889:2737401][ii*8 : (ii+1)*8])
|
||||
b.ProposerLookahead[ii] = ssz.UnmarshallUint64(buf[2736929:2737441][ii*8 : (ii+1)*8])
|
||||
}
|
||||
|
||||
// Field (38) 'ExecutionPayloadAvailability'
|
||||
// Offset (38) 'Builders'
|
||||
if o38 = ssz.ReadOffset(buf[2737441:2737445]); o38 > size || o36 > o38 {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
// Field (39) 'NextWithdrawalBuilderIndex'
|
||||
b.NextWithdrawalBuilderIndex = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.BuilderIndex(ssz.UnmarshallUint64(buf[2737445:2737453]))
|
||||
|
||||
// Field (40) 'ExecutionPayloadAvailability'
|
||||
if cap(b.ExecutionPayloadAvailability) == 0 {
|
||||
b.ExecutionPayloadAvailability = make([]byte, 0, len(buf[2737401:2738425]))
|
||||
b.ExecutionPayloadAvailability = make([]byte, 0, len(buf[2737453:2738477]))
|
||||
}
|
||||
b.ExecutionPayloadAvailability = append(b.ExecutionPayloadAvailability, buf[2737401:2738425]...)
|
||||
b.ExecutionPayloadAvailability = append(b.ExecutionPayloadAvailability, buf[2737453:2738477]...)
|
||||
|
||||
// Field (39) 'BuilderPendingPayments'
|
||||
// Field (41) 'BuilderPendingPayments'
|
||||
b.BuilderPendingPayments = make([]*BuilderPendingPayment, 64)
|
||||
for ii := 0; ii < 64; ii++ {
|
||||
if b.BuilderPendingPayments[ii] == nil {
|
||||
b.BuilderPendingPayments[ii] = new(BuilderPendingPayment)
|
||||
}
|
||||
if err = b.BuilderPendingPayments[ii].UnmarshalSSZ(buf[2738425:2741753][ii*52 : (ii+1)*52]); err != nil {
|
||||
if err = b.BuilderPendingPayments[ii].UnmarshalSSZ(buf[2738477:2741293][ii*44 : (ii+1)*44]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Offset (40) 'BuilderPendingWithdrawals'
|
||||
if o40 = ssz.ReadOffset(buf[2741753:2741757]); o40 > size || o36 > o40 {
|
||||
// Offset (42) 'BuilderPendingWithdrawals'
|
||||
if o42 = ssz.ReadOffset(buf[2741293:2741297]); o42 > size || o38 > o42 {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
// Field (41) 'LatestBlockHash'
|
||||
// Field (43) 'LatestBlockHash'
|
||||
if cap(b.LatestBlockHash) == 0 {
|
||||
b.LatestBlockHash = make([]byte, 0, len(buf[2741757:2741789]))
|
||||
b.LatestBlockHash = make([]byte, 0, len(buf[2741297:2741329]))
|
||||
}
|
||||
b.LatestBlockHash = append(b.LatestBlockHash, buf[2741757:2741789]...)
|
||||
b.LatestBlockHash = append(b.LatestBlockHash, buf[2741297:2741329]...)
|
||||
|
||||
// Field (42) 'LatestWithdrawalsRoot'
|
||||
if cap(b.LatestWithdrawalsRoot) == 0 {
|
||||
b.LatestWithdrawalsRoot = make([]byte, 0, len(buf[2741789:2741821]))
|
||||
// Offset (44) 'PayloadExpectedWithdrawals'
|
||||
if o44 = ssz.ReadOffset(buf[2741329:2741333]); o44 > size || o42 > o44 {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
b.LatestWithdrawalsRoot = append(b.LatestWithdrawalsRoot, buf[2741789:2741821]...)
|
||||
|
||||
// Field (7) 'HistoricalRoots'
|
||||
{
|
||||
@@ -2209,7 +2271,7 @@ func (b *BeaconStateGloas) UnmarshalSSZ(buf []byte) error {
|
||||
|
||||
// Field (36) 'PendingConsolidations'
|
||||
{
|
||||
buf = tail[o36:o40]
|
||||
buf = tail[o36:o38]
|
||||
num, err := ssz.DivideInt2(len(buf), 16, 262144)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -2225,10 +2287,28 @@ func (b *BeaconStateGloas) UnmarshalSSZ(buf []byte) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Field (40) 'BuilderPendingWithdrawals'
|
||||
// Field (38) 'Builders'
|
||||
{
|
||||
buf = tail[o40:]
|
||||
num, err := ssz.DivideInt2(len(buf), 44, 1048576)
|
||||
buf = tail[o38:o42]
|
||||
num, err := ssz.DivideInt2(len(buf), 93, 1099511627776)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.Builders = make([]*Builder, num)
|
||||
for ii := 0; ii < num; ii++ {
|
||||
if b.Builders[ii] == nil {
|
||||
b.Builders[ii] = new(Builder)
|
||||
}
|
||||
if err = b.Builders[ii].UnmarshalSSZ(buf[ii*93 : (ii+1)*93]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Field (42) 'BuilderPendingWithdrawals'
|
||||
{
|
||||
buf = tail[o42:o44]
|
||||
num, err := ssz.DivideInt2(len(buf), 36, 1048576)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -2237,7 +2317,25 @@ func (b *BeaconStateGloas) UnmarshalSSZ(buf []byte) error {
|
||||
if b.BuilderPendingWithdrawals[ii] == nil {
|
||||
b.BuilderPendingWithdrawals[ii] = new(BuilderPendingWithdrawal)
|
||||
}
|
||||
if err = b.BuilderPendingWithdrawals[ii].UnmarshalSSZ(buf[ii*44 : (ii+1)*44]); err != nil {
|
||||
if err = b.BuilderPendingWithdrawals[ii].UnmarshalSSZ(buf[ii*36 : (ii+1)*36]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Field (44) 'PayloadExpectedWithdrawals'
|
||||
{
|
||||
buf = tail[o44:]
|
||||
num, err := ssz.DivideInt2(len(buf), 44, 16)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.PayloadExpectedWithdrawals = make([]*v1.Withdrawal, num)
|
||||
for ii := 0; ii < num; ii++ {
|
||||
if b.PayloadExpectedWithdrawals[ii] == nil {
|
||||
b.PayloadExpectedWithdrawals[ii] = new(v1.Withdrawal)
|
||||
}
|
||||
if err = b.PayloadExpectedWithdrawals[ii].UnmarshalSSZ(buf[ii*44 : (ii+1)*44]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -2247,7 +2345,7 @@ func (b *BeaconStateGloas) UnmarshalSSZ(buf []byte) error {
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the BeaconStateGloas object
|
||||
func (b *BeaconStateGloas) SizeSSZ() (size int) {
|
||||
size = 2741821
|
||||
size = 2741333
|
||||
|
||||
// Field (7) 'HistoricalRoots'
|
||||
size += len(b.HistoricalRoots) * 32
|
||||
@@ -2282,8 +2380,14 @@ func (b *BeaconStateGloas) SizeSSZ() (size int) {
|
||||
// Field (36) 'PendingConsolidations'
|
||||
size += len(b.PendingConsolidations) * 16
|
||||
|
||||
// Field (40) 'BuilderPendingWithdrawals'
|
||||
size += len(b.BuilderPendingWithdrawals) * 44
|
||||
// Field (38) 'Builders'
|
||||
size += len(b.Builders) * 93
|
||||
|
||||
// Field (42) 'BuilderPendingWithdrawals'
|
||||
size += len(b.BuilderPendingWithdrawals) * 36
|
||||
|
||||
// Field (44) 'PayloadExpectedWithdrawals'
|
||||
size += len(b.PayloadExpectedWithdrawals) * 44
|
||||
|
||||
return
|
||||
}
|
||||
@@ -2637,14 +2741,33 @@ func (b *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
hh.Merkleize(subIndx)
|
||||
}
|
||||
|
||||
// Field (38) 'ExecutionPayloadAvailability'
|
||||
// Field (38) 'Builders'
|
||||
{
|
||||
subIndx := hh.Index()
|
||||
num := uint64(len(b.Builders))
|
||||
if num > 1099511627776 {
|
||||
err = ssz.ErrIncorrectListSize
|
||||
return
|
||||
}
|
||||
for _, elem := range b.Builders {
|
||||
if err = elem.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
hh.MerkleizeWithMixin(subIndx, num, 1099511627776)
|
||||
}
|
||||
|
||||
// Field (39) 'NextWithdrawalBuilderIndex'
|
||||
hh.PutUint64(uint64(b.NextWithdrawalBuilderIndex))
|
||||
|
||||
// Field (40) 'ExecutionPayloadAvailability'
|
||||
if size := len(b.ExecutionPayloadAvailability); size != 1024 {
|
||||
err = ssz.ErrBytesLengthFn("--.ExecutionPayloadAvailability", size, 1024)
|
||||
return
|
||||
}
|
||||
hh.PutBytes(b.ExecutionPayloadAvailability)
|
||||
|
||||
// Field (39) 'BuilderPendingPayments'
|
||||
// Field (41) 'BuilderPendingPayments'
|
||||
{
|
||||
subIndx := hh.Index()
|
||||
for _, elem := range b.BuilderPendingPayments {
|
||||
@@ -2655,7 +2778,7 @@ func (b *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
hh.Merkleize(subIndx)
|
||||
}
|
||||
|
||||
// Field (40) 'BuilderPendingWithdrawals'
|
||||
// Field (42) 'BuilderPendingWithdrawals'
|
||||
{
|
||||
subIndx := hh.Index()
|
||||
num := uint64(len(b.BuilderPendingWithdrawals))
|
||||
@@ -2671,19 +2794,28 @@ func (b *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
hh.MerkleizeWithMixin(subIndx, num, 1048576)
|
||||
}
|
||||
|
||||
// Field (41) 'LatestBlockHash'
|
||||
// Field (43) 'LatestBlockHash'
|
||||
if size := len(b.LatestBlockHash); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.LatestBlockHash", size, 32)
|
||||
return
|
||||
}
|
||||
hh.PutBytes(b.LatestBlockHash)
|
||||
|
||||
// Field (42) 'LatestWithdrawalsRoot'
|
||||
if size := len(b.LatestWithdrawalsRoot); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.LatestWithdrawalsRoot", size, 32)
|
||||
return
|
||||
// Field (44) 'PayloadExpectedWithdrawals'
|
||||
{
|
||||
subIndx := hh.Index()
|
||||
num := uint64(len(b.PayloadExpectedWithdrawals))
|
||||
if num > 16 {
|
||||
err = ssz.ErrIncorrectListSize
|
||||
return
|
||||
}
|
||||
for _, elem := range b.PayloadExpectedWithdrawals {
|
||||
if err = elem.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
hh.MerkleizeWithMixin(subIndx, num, 16)
|
||||
}
|
||||
hh.PutBytes(b.LatestWithdrawalsRoot)
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
@@ -2716,7 +2848,7 @@ func (b *BuilderPendingPayment) MarshalSSZTo(buf []byte) (dst []byte, err error)
|
||||
func (b *BuilderPendingPayment) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size != 52 {
|
||||
if size != 44 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
@@ -2727,7 +2859,7 @@ func (b *BuilderPendingPayment) UnmarshalSSZ(buf []byte) error {
|
||||
if b.Withdrawal == nil {
|
||||
b.Withdrawal = new(BuilderPendingWithdrawal)
|
||||
}
|
||||
if err = b.Withdrawal.UnmarshalSSZ(buf[8:52]); err != nil {
|
||||
if err = b.Withdrawal.UnmarshalSSZ(buf[8:44]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -2736,7 +2868,7 @@ func (b *BuilderPendingPayment) UnmarshalSSZ(buf []byte) error {
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the BuilderPendingPayment object
|
||||
func (b *BuilderPendingPayment) SizeSSZ() (size int) {
|
||||
size = 52
|
||||
size = 44
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2783,9 +2915,6 @@ func (b *BuilderPendingWithdrawal) MarshalSSZTo(buf []byte) (dst []byte, err err
|
||||
// Field (2) 'BuilderIndex'
|
||||
dst = ssz.MarshalUint64(dst, uint64(b.BuilderIndex))
|
||||
|
||||
// Field (3) 'WithdrawableEpoch'
|
||||
dst = ssz.MarshalUint64(dst, uint64(b.WithdrawableEpoch))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2793,7 +2922,7 @@ func (b *BuilderPendingWithdrawal) MarshalSSZTo(buf []byte) (dst []byte, err err
|
||||
func (b *BuilderPendingWithdrawal) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size != 44 {
|
||||
if size != 36 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
@@ -2807,17 +2936,14 @@ func (b *BuilderPendingWithdrawal) UnmarshalSSZ(buf []byte) error {
|
||||
b.Amount = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[20:28]))
|
||||
|
||||
// Field (2) 'BuilderIndex'
|
||||
b.BuilderIndex = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[28:36]))
|
||||
|
||||
// Field (3) 'WithdrawableEpoch'
|
||||
b.WithdrawableEpoch = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[36:44]))
|
||||
b.BuilderIndex = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.BuilderIndex(ssz.UnmarshallUint64(buf[28:36]))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the BuilderPendingWithdrawal object
|
||||
func (b *BuilderPendingWithdrawal) SizeSSZ() (size int) {
|
||||
size = 44
|
||||
size = 36
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2843,9 +2969,6 @@ func (b *BuilderPendingWithdrawal) HashTreeRootWith(hh *ssz.Hasher) (err error)
|
||||
// Field (2) 'BuilderIndex'
|
||||
hh.PutUint64(uint64(b.BuilderIndex))
|
||||
|
||||
// Field (3) 'WithdrawableEpoch'
|
||||
hh.PutUint64(uint64(b.WithdrawableEpoch))
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
@@ -3218,7 +3341,7 @@ func (e *ExecutionPayloadEnvelope) UnmarshalSSZ(buf []byte) error {
|
||||
}
|
||||
|
||||
// Field (2) 'BuilderIndex'
|
||||
e.BuilderIndex = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[8:16]))
|
||||
e.BuilderIndex = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.BuilderIndex(ssz.UnmarshallUint64(buf[8:16]))
|
||||
|
||||
// Field (3) 'BeaconBlockRoot'
|
||||
if cap(e.BeaconBlockRoot) == 0 {
|
||||
@@ -3472,3 +3595,132 @@ func (s *SignedExecutionPayloadEnvelope) HashTreeRootWith(hh *ssz.Hasher) (err e
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the Builder object
|
||||
func (b *Builder) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(b)
|
||||
}
|
||||
|
||||
// MarshalSSZTo ssz marshals the Builder object to a target array
|
||||
func (b *Builder) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
|
||||
// Field (0) 'Pubkey'
|
||||
if size := len(b.Pubkey); size != 48 {
|
||||
err = ssz.ErrBytesLengthFn("--.Pubkey", size, 48)
|
||||
return
|
||||
}
|
||||
dst = append(dst, b.Pubkey...)
|
||||
|
||||
// Field (1) 'Version'
|
||||
if size := len(b.Version); size != 1 {
|
||||
err = ssz.ErrBytesLengthFn("--.Version", size, 1)
|
||||
return
|
||||
}
|
||||
dst = append(dst, b.Version...)
|
||||
|
||||
// Field (2) 'ExecutionAddress'
|
||||
if size := len(b.ExecutionAddress); size != 20 {
|
||||
err = ssz.ErrBytesLengthFn("--.ExecutionAddress", size, 20)
|
||||
return
|
||||
}
|
||||
dst = append(dst, b.ExecutionAddress...)
|
||||
|
||||
// Field (3) 'Balance'
|
||||
dst = ssz.MarshalUint64(dst, uint64(b.Balance))
|
||||
|
||||
// Field (4) 'DepositEpoch'
|
||||
dst = ssz.MarshalUint64(dst, uint64(b.DepositEpoch))
|
||||
|
||||
// Field (5) 'WithdrawableEpoch'
|
||||
dst = ssz.MarshalUint64(dst, uint64(b.WithdrawableEpoch))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalSSZ ssz unmarshals the Builder object
|
||||
func (b *Builder) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size != 93 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
// Field (0) 'Pubkey'
|
||||
if cap(b.Pubkey) == 0 {
|
||||
b.Pubkey = make([]byte, 0, len(buf[0:48]))
|
||||
}
|
||||
b.Pubkey = append(b.Pubkey, buf[0:48]...)
|
||||
|
||||
// Field (1) 'Version'
|
||||
if cap(b.Version) == 0 {
|
||||
b.Version = make([]byte, 0, len(buf[48:49]))
|
||||
}
|
||||
b.Version = append(b.Version, buf[48:49]...)
|
||||
|
||||
// Field (2) 'ExecutionAddress'
|
||||
if cap(b.ExecutionAddress) == 0 {
|
||||
b.ExecutionAddress = make([]byte, 0, len(buf[49:69]))
|
||||
}
|
||||
b.ExecutionAddress = append(b.ExecutionAddress, buf[49:69]...)
|
||||
|
||||
// Field (3) 'Balance'
|
||||
b.Balance = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[69:77]))
|
||||
|
||||
// Field (4) 'DepositEpoch'
|
||||
b.DepositEpoch = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[77:85]))
|
||||
|
||||
// Field (5) 'WithdrawableEpoch'
|
||||
b.WithdrawableEpoch = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[85:93]))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the Builder object
|
||||
func (b *Builder) SizeSSZ() (size int) {
|
||||
size = 93
|
||||
return
|
||||
}
|
||||
|
||||
// HashTreeRoot ssz hashes the Builder object
|
||||
func (b *Builder) HashTreeRoot() ([32]byte, error) {
|
||||
return ssz.HashWithDefaultHasher(b)
|
||||
}
|
||||
|
||||
// HashTreeRootWith ssz hashes the Builder object with a hasher
|
||||
func (b *Builder) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
indx := hh.Index()
|
||||
|
||||
// Field (0) 'Pubkey'
|
||||
if size := len(b.Pubkey); size != 48 {
|
||||
err = ssz.ErrBytesLengthFn("--.Pubkey", size, 48)
|
||||
return
|
||||
}
|
||||
hh.PutBytes(b.Pubkey)
|
||||
|
||||
// Field (1) 'Version'
|
||||
if size := len(b.Version); size != 1 {
|
||||
err = ssz.ErrBytesLengthFn("--.Version", size, 1)
|
||||
return
|
||||
}
|
||||
hh.PutBytes(b.Version)
|
||||
|
||||
// Field (2) 'ExecutionAddress'
|
||||
if size := len(b.ExecutionAddress); size != 20 {
|
||||
err = ssz.ErrBytesLengthFn("--.ExecutionAddress", size, 20)
|
||||
return
|
||||
}
|
||||
hh.PutBytes(b.ExecutionAddress)
|
||||
|
||||
// Field (3) 'Balance'
|
||||
hh.PutUint64(uint64(b.Balance))
|
||||
|
||||
// Field (4) 'DepositEpoch'
|
||||
hh.PutUint64(uint64(b.DepositEpoch))
|
||||
|
||||
// Field (5) 'WithdrawableEpoch'
|
||||
hh.PutUint64(uint64(b.WithdrawableEpoch))
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -26,10 +26,12 @@ func TestExecutionPayloadBid_Copy(t *testing.T) {
|
||||
ParentBlockHash: []byte("parent_block_hash_32_bytes_long!"),
|
||||
ParentBlockRoot: []byte("parent_block_root_32_bytes_long!"),
|
||||
BlockHash: []byte("block_hash_32_bytes_are_long!!"),
|
||||
PrevRandao: []byte("prev_randao_32_bytes_long!!!"),
|
||||
FeeRecipient: []byte("fee_recipient_20_byt"),
|
||||
GasLimit: 15000000,
|
||||
BuilderIndex: primitives.ValidatorIndex(42),
|
||||
BuilderIndex: primitives.BuilderIndex(42),
|
||||
Slot: primitives.Slot(12345),
|
||||
ExecutionPayment: 5645654,
|
||||
Value: 1000000000000000000,
|
||||
BlobKzgCommitmentsRoot: []byte("blob_kzg_commitments_32_bytes!!"),
|
||||
},
|
||||
@@ -76,10 +78,9 @@ func TestBuilderPendingWithdrawal_Copy(t *testing.T) {
|
||||
{
|
||||
name: "fully populated withdrawal",
|
||||
withdrawal: &BuilderPendingWithdrawal{
|
||||
FeeRecipient: []byte("fee_recipient_20_byt"),
|
||||
Amount: primitives.Gwei(5000000000),
|
||||
BuilderIndex: primitives.ValidatorIndex(123),
|
||||
WithdrawableEpoch: primitives.Epoch(456),
|
||||
FeeRecipient: []byte("fee_recipient_20_byt"),
|
||||
Amount: primitives.Gwei(5000000000),
|
||||
BuilderIndex: primitives.BuilderIndex(123),
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -134,10 +135,9 @@ func TestBuilderPendingPayment_Copy(t *testing.T) {
|
||||
payment: &BuilderPendingPayment{
|
||||
Weight: primitives.Gwei(2500),
|
||||
Withdrawal: &BuilderPendingWithdrawal{
|
||||
FeeRecipient: []byte("test_recipient_20byt"),
|
||||
Amount: primitives.Gwei(10000),
|
||||
BuilderIndex: primitives.ValidatorIndex(789),
|
||||
WithdrawableEpoch: primitives.Epoch(999),
|
||||
FeeRecipient: []byte("test_recipient_20byt"),
|
||||
Amount: primitives.Gwei(10000),
|
||||
BuilderIndex: primitives.BuilderIndex(789),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -166,3 +166,60 @@ func TestBuilderPendingPayment_Copy(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCopyBuilder(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
builder *Builder
|
||||
}{
|
||||
{
|
||||
name: "nil builder",
|
||||
builder: nil,
|
||||
},
|
||||
{
|
||||
name: "empty builder",
|
||||
builder: &Builder{},
|
||||
},
|
||||
{
|
||||
name: "fully populated builder",
|
||||
builder: &Builder{
|
||||
Pubkey: []byte("pubkey_48_bytes_long_pubkey_48_bytes_long_pubkey_48!"),
|
||||
Version: []byte{'a'},
|
||||
ExecutionAddress: []byte("execution_address_20"),
|
||||
Balance: primitives.Gwei(12345),
|
||||
DepositEpoch: primitives.Epoch(10),
|
||||
WithdrawableEpoch: primitives.Epoch(20),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
copied := CopyBuilder(tt.builder)
|
||||
if tt.builder == nil {
|
||||
if copied != nil {
|
||||
t.Errorf("CopyBuilder() of nil should return nil, got %v", copied)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(tt.builder, copied) {
|
||||
t.Errorf("CopyBuilder() = %v, want %v", copied, tt.builder)
|
||||
}
|
||||
|
||||
if len(tt.builder.Pubkey) > 0 {
|
||||
tt.builder.Pubkey[0] = 0xFF
|
||||
if copied.Pubkey[0] == 0xFF {
|
||||
t.Error("CopyBuilder() did not create deep copy of Pubkey")
|
||||
}
|
||||
}
|
||||
|
||||
if len(tt.builder.ExecutionAddress) > 0 {
|
||||
tt.builder.ExecutionAddress[0] = 0xFF
|
||||
if copied.ExecutionAddress[0] == 0xFF {
|
||||
t.Error("CopyBuilder() did not create deep copy of ExecutionAddress")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ mainnet = {
|
||||
"payload_attestation.size": "4", # Gloas: MAX_PAYLOAD_ATTESTATIONS defined in block body
|
||||
"execution_payload_availability.size": "1024", # Gloas: SLOTS_PER_HISTORICAL_ROOT
|
||||
"builder_pending_payments.size": "64", # Gloas: vector length (2 * SLOTS_PER_EPOCH)
|
||||
"builder_registry_limit": "1099511627776", # Gloas: BUILDER_REGISTRY_LIMIT (same for mainnet/minimal)
|
||||
}
|
||||
|
||||
minimal = {
|
||||
@@ -91,7 +92,8 @@ minimal = {
|
||||
"ptc.type": "github.com/OffchainLabs/go-bitfield.Bitvector2",
|
||||
"payload_attestation.size": "4", # Gloas: MAX_PAYLOAD_ATTESTATIONS defined in block body
|
||||
"execution_payload_availability.size": "8", # Gloas: SLOTS_PER_HISTORICAL_ROOT
|
||||
"builder_pending_payments.size": "16" # Gloas: vector length (2 * SLOTS_PER_EPOCH)
|
||||
"builder_pending_payments.size": "16", # Gloas: vector length (2 * SLOTS_PER_EPOCH)
|
||||
"builder_registry_limit": "1099511627776", # Gloas: BUILDER_REGISTRY_LIMIT (same for mainnet/minimal)
|
||||
}
|
||||
|
||||
###### Rules definitions #######
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
version: v1.6.0
|
||||
version: v1.7.0-alpha.0
|
||||
style: full
|
||||
|
||||
specrefs:
|
||||
@@ -57,6 +57,12 @@ exceptions:
|
||||
- PAYLOAD_STATUS_EMPTY#gloas
|
||||
- PAYLOAD_STATUS_FULL#gloas
|
||||
- PAYLOAD_STATUS_PENDING#gloas
|
||||
- ATTESTATION_TIMELINESS_INDEX#gloas
|
||||
- BUILDER_INDEX_FLAG#gloas
|
||||
- BUILDER_INDEX_SELF_BUILD#gloas
|
||||
- DOMAIN_PROPOSER_PREFERENCES#gloas
|
||||
- NUM_BLOCK_TIMELINESS_DEADLINES#gloas
|
||||
- PTC_TIMELINESS_INDEX#gloas
|
||||
|
||||
configs:
|
||||
# Not implemented (placeholders)
|
||||
@@ -76,6 +82,7 @@ exceptions:
|
||||
- MAX_REQUEST_PAYLOADS#gloas
|
||||
- PAYLOAD_ATTESTATION_DUE_BPS#gloas
|
||||
- SYNC_MESSAGE_DUE_BPS_GLOAS#gloas
|
||||
- MIN_BUILDER_WITHDRAWABILITY_DELAY#gloas
|
||||
|
||||
ssz_objects:
|
||||
# Not implemented
|
||||
@@ -103,6 +110,9 @@ exceptions:
|
||||
- PayloadAttestationMessage#gloas
|
||||
- SignedExecutionPayloadEnvelope#gloas
|
||||
- SignedExecutionPayloadBid#gloas
|
||||
- Builder#gloas
|
||||
- ProposerPreferences#gloas
|
||||
- SignedProposerPreferences#gloas
|
||||
|
||||
dataclasses:
|
||||
# Not implemented
|
||||
@@ -331,10 +341,8 @@ exceptions:
|
||||
- get_ptc#gloas
|
||||
- get_ptc_assignment#gloas
|
||||
- get_weight#gloas
|
||||
- has_builder_withdrawal_credential#gloas
|
||||
- has_compounding_withdrawal_credential#gloas
|
||||
- is_attestation_same_slot#gloas
|
||||
- is_builder_payment_withdrawable#gloas
|
||||
- is_builder_withdrawal_credential#gloas
|
||||
- is_merge_transition_complete#gloas
|
||||
- is_parent_block_full#gloas
|
||||
@@ -358,7 +366,6 @@ exceptions:
|
||||
- process_proposer_slashing#gloas
|
||||
- process_slot#gloas
|
||||
- process_withdrawals#gloas
|
||||
- remove_flag#gloas
|
||||
- should_extend_payload#gloas
|
||||
- update_latest_messages#gloas
|
||||
- upgrade_to_gloas#gloas
|
||||
@@ -368,3 +375,55 @@ exceptions:
|
||||
- verify_data_column_sidecar_inclusion_proof#gloas
|
||||
- verify_execution_payload_envelope_signature#gloas
|
||||
- verify_execution_payload_bid_signature#gloas
|
||||
- add_builder_to_registry#gloas
|
||||
- apply_deposit_for_builder#gloas
|
||||
- apply_withdrawals#capella
|
||||
- apply_withdrawals#gloas
|
||||
- can_builder_cover_bid#gloas
|
||||
- compute_proposer_score#phase0
|
||||
- convert_builder_index_to_validator_index#gloas
|
||||
- convert_validator_index_to_builder_index#gloas
|
||||
- get_attestation_score#gloas
|
||||
- get_attestation_score#phase0
|
||||
- get_balance_after_withdrawals#capella
|
||||
- get_builder_from_deposit#gloas
|
||||
- get_builder_withdrawals#gloas
|
||||
- get_builders_sweep_withdrawals#gloas
|
||||
- get_index_for_new_builder#gloas
|
||||
- get_pending_balance_to_withdraw_for_builder#gloas
|
||||
- get_pending_partial_withdrawals#electra
|
||||
- get_proposer_preferences_signature#gloas
|
||||
- get_upcoming_proposal_slots#gloas
|
||||
- get_validators_sweep_withdrawals#capella
|
||||
- get_validators_sweep_withdrawals#electra
|
||||
- initiate_builder_exit#gloas
|
||||
- is_active_builder#gloas
|
||||
- is_builder_index#gloas
|
||||
- is_eligible_for_partial_withdrawals#electra
|
||||
- is_head_late#gloas
|
||||
- is_head_weak#gloas
|
||||
- is_parent_strong#gloas
|
||||
- is_proposer_equivocation#phase0
|
||||
- is_valid_proposal_slot#gloas
|
||||
- process_deposit_request#gloas
|
||||
- process_voluntary_exit#gloas
|
||||
- record_block_timeliness#gloas
|
||||
- record_block_timeliness#phase0
|
||||
- should_apply_proposer_boost#gloas
|
||||
- update_builder_pending_withdrawals#gloas
|
||||
- update_next_withdrawal_builder_index#gloas
|
||||
- update_next_withdrawal_index#capella
|
||||
- update_next_withdrawal_validator_index#capella
|
||||
- update_payload_expected_withdrawals#gloas
|
||||
- update_pending_partial_withdrawals#electra
|
||||
- update_proposer_boost_root#gloas
|
||||
- update_proposer_boost_root#phase0
|
||||
|
||||
presets:
|
||||
- CELLS_PER_EXT_BLOB#fulu
|
||||
- BUILDER_PENDING_WITHDRAWALS_LIMIT#gloas
|
||||
- BUILDER_REGISTRY_LIMIT#gloas
|
||||
- MAX_BUILDERS_PER_WITHDRAWALS_SWEEP#gloas
|
||||
- MAX_PAYLOAD_ATTESTATIONS#gloas
|
||||
- PTC_SIZE#gloas
|
||||
- UPDATE_TIMEOUT#altair
|
||||
|
||||
@@ -304,16 +304,6 @@
|
||||
GENESIS_SLOT: Slot = 0
|
||||
</spec>
|
||||
|
||||
- name: INTERVALS_PER_SLOT
|
||||
sources:
|
||||
- file: config/params/config.go
|
||||
search: IntervalsPerSlot\s+.*yaml:"INTERVALS_PER_SLOT"
|
||||
regex: true
|
||||
spec: |
|
||||
<spec constant_var="INTERVALS_PER_SLOT" fork="phase0" hash="3352e419">
|
||||
INTERVALS_PER_SLOT: uint64 = 3
|
||||
</spec>
|
||||
|
||||
- name: JUSTIFICATION_BITS_LENGTH
|
||||
sources:
|
||||
- file: config/params/config.go
|
||||
|
||||
@@ -698,7 +698,7 @@
|
||||
- name: compute_matrix
|
||||
sources: []
|
||||
spec: |
|
||||
<spec fn="compute_matrix" fork="fulu" hash="b39370ca">
|
||||
<spec fn="compute_matrix" fork="fulu" hash="0b88eac1">
|
||||
def compute_matrix(blobs: Sequence[Blob]) -> Sequence[MatrixEntry]:
|
||||
"""
|
||||
Return the full, flattened sequence of matrix entries.
|
||||
@@ -714,8 +714,8 @@
|
||||
MatrixEntry(
|
||||
cell=cell,
|
||||
kzg_proof=proof,
|
||||
row_index=blob_index,
|
||||
column_index=cell_index,
|
||||
row_index=blob_index,
|
||||
)
|
||||
)
|
||||
return matrix
|
||||
@@ -739,7 +739,7 @@
|
||||
- file: beacon-chain/rpc/prysm/v1alpha1/validator/proposer_attestations_electra.go
|
||||
search: func computeOnChainAggregate(
|
||||
spec: |
|
||||
<spec fn="compute_on_chain_aggregate" fork="electra" hash="128055d6">
|
||||
<spec fn="compute_on_chain_aggregate" fork="electra" hash="f020af4c">
|
||||
def compute_on_chain_aggregate(network_aggregates: Sequence[Attestation]) -> Attestation:
|
||||
aggregates = sorted(
|
||||
network_aggregates, key=lambda a: get_committee_indices(a.committee_bits)[0]
|
||||
@@ -760,8 +760,8 @@
|
||||
return Attestation(
|
||||
aggregation_bits=aggregation_bits,
|
||||
data=data,
|
||||
committee_bits=committee_bits,
|
||||
signature=signature,
|
||||
committee_bits=committee_bits,
|
||||
)
|
||||
</spec>
|
||||
|
||||
@@ -2366,40 +2366,18 @@
|
||||
- file: beacon-chain/state/state-native/getters_withdrawal.go
|
||||
search: func (b *BeaconState) ExpectedWithdrawals(
|
||||
spec: |
|
||||
<spec fn="get_expected_withdrawals" fork="capella" hash="09191977">
|
||||
def get_expected_withdrawals(state: BeaconState) -> Sequence[Withdrawal]:
|
||||
epoch = get_current_epoch(state)
|
||||
<spec fn="get_expected_withdrawals" fork="capella" hash="d6a98c14">
|
||||
def get_expected_withdrawals(state: BeaconState) -> Tuple[Sequence[Withdrawal], uint64]:
|
||||
withdrawal_index = state.next_withdrawal_index
|
||||
validator_index = state.next_withdrawal_validator_index
|
||||
withdrawals: List[Withdrawal] = []
|
||||
bound = min(len(state.validators), MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP)
|
||||
for _ in range(bound):
|
||||
validator = state.validators[validator_index]
|
||||
balance = state.balances[validator_index]
|
||||
if is_fully_withdrawable_validator(validator, balance, epoch):
|
||||
withdrawals.append(
|
||||
Withdrawal(
|
||||
index=withdrawal_index,
|
||||
validator_index=validator_index,
|
||||
address=ExecutionAddress(validator.withdrawal_credentials[12:]),
|
||||
amount=balance,
|
||||
)
|
||||
)
|
||||
withdrawal_index += WithdrawalIndex(1)
|
||||
elif is_partially_withdrawable_validator(validator, balance):
|
||||
withdrawals.append(
|
||||
Withdrawal(
|
||||
index=withdrawal_index,
|
||||
validator_index=validator_index,
|
||||
address=ExecutionAddress(validator.withdrawal_credentials[12:]),
|
||||
amount=balance - MAX_EFFECTIVE_BALANCE,
|
||||
)
|
||||
)
|
||||
withdrawal_index += WithdrawalIndex(1)
|
||||
if len(withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD:
|
||||
break
|
||||
validator_index = ValidatorIndex((validator_index + 1) % len(state.validators))
|
||||
return withdrawals
|
||||
|
||||
# Get validators sweep withdrawals
|
||||
validators_sweep_withdrawals, withdrawal_index, processed_validators_sweep_count = (
|
||||
get_validators_sweep_withdrawals(state, withdrawal_index, withdrawals)
|
||||
)
|
||||
withdrawals.extend(validators_sweep_withdrawals)
|
||||
|
||||
return withdrawals, processed_validators_sweep_count
|
||||
</spec>
|
||||
|
||||
- name: get_expected_withdrawals#electra
|
||||
@@ -2407,80 +2385,26 @@
|
||||
- file: beacon-chain/state/state-native/getters_withdrawal.go
|
||||
search: func (b *BeaconState) ExpectedWithdrawals(
|
||||
spec: |
|
||||
<spec fn="get_expected_withdrawals" fork="electra" hash="060932cd">
|
||||
def get_expected_withdrawals(state: BeaconState) -> Tuple[Sequence[Withdrawal], uint64]:
|
||||
epoch = get_current_epoch(state)
|
||||
<spec fn="get_expected_withdrawals" fork="electra" hash="cfce862b">
|
||||
def get_expected_withdrawals(state: BeaconState) -> Tuple[Sequence[Withdrawal], uint64, uint64]:
|
||||
withdrawal_index = state.next_withdrawal_index
|
||||
validator_index = state.next_withdrawal_validator_index
|
||||
withdrawals: List[Withdrawal] = []
|
||||
processed_partial_withdrawals_count = 0
|
||||
|
||||
# [New in Electra:EIP7251]
|
||||
# Consume pending partial withdrawals
|
||||
for withdrawal in state.pending_partial_withdrawals:
|
||||
if (
|
||||
withdrawal.withdrawable_epoch > epoch
|
||||
or len(withdrawals) == MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP
|
||||
):
|
||||
break
|
||||
# Get partial withdrawals
|
||||
partial_withdrawals, withdrawal_index, processed_partial_withdrawals_count = (
|
||||
get_pending_partial_withdrawals(state, withdrawal_index, withdrawals)
|
||||
)
|
||||
withdrawals.extend(partial_withdrawals)
|
||||
|
||||
validator = state.validators[withdrawal.validator_index]
|
||||
has_sufficient_effective_balance = validator.effective_balance >= MIN_ACTIVATION_BALANCE
|
||||
total_withdrawn = sum(
|
||||
w.amount for w in withdrawals if w.validator_index == withdrawal.validator_index
|
||||
)
|
||||
balance = state.balances[withdrawal.validator_index] - total_withdrawn
|
||||
has_excess_balance = balance > MIN_ACTIVATION_BALANCE
|
||||
if (
|
||||
validator.exit_epoch == FAR_FUTURE_EPOCH
|
||||
and has_sufficient_effective_balance
|
||||
and has_excess_balance
|
||||
):
|
||||
withdrawable_balance = min(balance - MIN_ACTIVATION_BALANCE, withdrawal.amount)
|
||||
withdrawals.append(
|
||||
Withdrawal(
|
||||
index=withdrawal_index,
|
||||
validator_index=withdrawal.validator_index,
|
||||
address=ExecutionAddress(validator.withdrawal_credentials[12:]),
|
||||
amount=withdrawable_balance,
|
||||
)
|
||||
)
|
||||
withdrawal_index += WithdrawalIndex(1)
|
||||
# Get validators sweep withdrawals
|
||||
validators_sweep_withdrawals, withdrawal_index, processed_validators_sweep_count = (
|
||||
get_validators_sweep_withdrawals(state, withdrawal_index, withdrawals)
|
||||
)
|
||||
withdrawals.extend(validators_sweep_withdrawals)
|
||||
|
||||
processed_partial_withdrawals_count += 1
|
||||
|
||||
# Sweep for remaining.
|
||||
bound = min(len(state.validators), MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP)
|
||||
for _ in range(bound):
|
||||
validator = state.validators[validator_index]
|
||||
# [Modified in Electra:EIP7251]
|
||||
total_withdrawn = sum(w.amount for w in withdrawals if w.validator_index == validator_index)
|
||||
balance = state.balances[validator_index] - total_withdrawn
|
||||
if is_fully_withdrawable_validator(validator, balance, epoch):
|
||||
withdrawals.append(
|
||||
Withdrawal(
|
||||
index=withdrawal_index,
|
||||
validator_index=validator_index,
|
||||
address=ExecutionAddress(validator.withdrawal_credentials[12:]),
|
||||
amount=balance,
|
||||
)
|
||||
)
|
||||
withdrawal_index += WithdrawalIndex(1)
|
||||
elif is_partially_withdrawable_validator(validator, balance):
|
||||
withdrawals.append(
|
||||
Withdrawal(
|
||||
index=withdrawal_index,
|
||||
validator_index=validator_index,
|
||||
address=ExecutionAddress(validator.withdrawal_credentials[12:]),
|
||||
# [Modified in Electra:EIP7251]
|
||||
amount=balance - get_max_effective_balance(validator),
|
||||
)
|
||||
)
|
||||
withdrawal_index += WithdrawalIndex(1)
|
||||
if len(withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD:
|
||||
break
|
||||
validator_index = ValidatorIndex((validator_index + 1) % len(state.validators))
|
||||
return withdrawals, processed_partial_withdrawals_count
|
||||
# [Modified in Electra:EIP7251]
|
||||
return withdrawals, processed_partial_withdrawals_count, processed_validators_sweep_count
|
||||
</spec>
|
||||
|
||||
- name: get_filtered_block_tree
|
||||
@@ -3053,7 +2977,7 @@
|
||||
- name: get_proposer_head
|
||||
sources: []
|
||||
spec: |
|
||||
<spec fn="get_proposer_head" fork="phase0" hash="15d44290">
|
||||
<spec fn="get_proposer_head" fork="phase0" hash="99e8fc05">
|
||||
def get_proposer_head(store: Store, head_root: Root, slot: Slot) -> Root:
|
||||
head_block = store.blocks[head_root]
|
||||
parent_root = head_block.parent_root
|
||||
@@ -3084,7 +3008,10 @@
|
||||
head_weak = is_head_weak(store, head_root)
|
||||
|
||||
# Check that the missing votes are assigned to the parent and not being hoarded.
|
||||
parent_strong = is_parent_strong(store, parent_root)
|
||||
parent_strong = is_parent_strong(store, head_root)
|
||||
|
||||
# Re-org more aggressively if there is a proposer equivocation in the previous slot.
|
||||
proposer_equivocation = is_proposer_equivocation(store, head_root)
|
||||
|
||||
if all(
|
||||
[
|
||||
@@ -3100,6 +3027,8 @@
|
||||
):
|
||||
# We can re-org the current head by building upon its parent block.
|
||||
return parent_root
|
||||
elif all([head_weak, current_time_ok, proposer_equivocation]):
|
||||
return parent_root
|
||||
else:
|
||||
return head_root
|
||||
</spec>
|
||||
@@ -3117,11 +3046,10 @@
|
||||
- name: get_proposer_score
|
||||
sources: []
|
||||
spec: |
|
||||
<spec fn="get_proposer_score" fork="phase0" hash="164b8de0">
|
||||
<spec fn="get_proposer_score" fork="phase0" hash="2c8d8a27">
|
||||
def get_proposer_score(store: Store) -> Gwei:
|
||||
justified_checkpoint_state = store.checkpoint_states[store.justified_checkpoint]
|
||||
committee_weight = get_total_active_balance(justified_checkpoint_state) // SLOTS_PER_EPOCH
|
||||
return (committee_weight * PROPOSER_SCORE_BOOST) // 100
|
||||
return compute_proposer_score(justified_checkpoint_state)
|
||||
</spec>
|
||||
|
||||
- name: get_randao_mix
|
||||
@@ -3509,26 +3437,10 @@
|
||||
- file: beacon-chain/forkchoice/doubly-linked-tree/forkchoice.go
|
||||
search: func (f *ForkChoice) Weight(
|
||||
spec: |
|
||||
<spec fn="get_weight" fork="phase0" hash="f2e4e8ef">
|
||||
<spec fn="get_weight" fork="phase0" hash="b18bf25c">
|
||||
def get_weight(store: Store, root: Root) -> Gwei:
|
||||
state = store.checkpoint_states[store.justified_checkpoint]
|
||||
unslashed_and_active_indices = [
|
||||
i
|
||||
for i in get_active_validator_indices(state, get_current_epoch(state))
|
||||
if not state.validators[i].slashed
|
||||
]
|
||||
attestation_score = Gwei(
|
||||
sum(
|
||||
state.validators[i].effective_balance
|
||||
for i in unslashed_and_active_indices
|
||||
if (
|
||||
i in store.latest_messages
|
||||
and i not in store.equivocating_indices
|
||||
and get_ancestor(store, store.latest_messages[i].root, store.blocks[root].slot)
|
||||
== root
|
||||
)
|
||||
)
|
||||
)
|
||||
attestation_score = get_attestation_score(store, root, state)
|
||||
if store.proposer_boost_root == Root():
|
||||
# Return only attestation score if ``proposer_boost_root`` is not set
|
||||
return attestation_score
|
||||
@@ -3615,7 +3527,7 @@
|
||||
- file: beacon-chain/core/transition/state.go
|
||||
search: func GenesisBeaconState(
|
||||
spec: |
|
||||
<spec fn="initialize_beacon_state_from_eth1" fork="phase0" hash="c69537d6">
|
||||
<spec fn="initialize_beacon_state_from_eth1" fork="phase0" hash="d3a0ddd4">
|
||||
def initialize_beacon_state_from_eth1(
|
||||
eth1_block_hash: Hash32, eth1_timestamp: uint64, deposits: Sequence[Deposit]
|
||||
) -> BeaconState:
|
||||
@@ -3627,7 +3539,7 @@
|
||||
state = BeaconState(
|
||||
genesis_time=eth1_timestamp + GENESIS_DELAY,
|
||||
fork=fork,
|
||||
eth1_data=Eth1Data(block_hash=eth1_block_hash, deposit_count=uint64(len(deposits))),
|
||||
eth1_data=Eth1Data(deposit_count=uint64(len(deposits)), block_hash=eth1_block_hash),
|
||||
latest_block_header=BeaconBlockHeader(body_root=hash_tree_root(BeaconBlockBody())),
|
||||
randao_mixes=[eth1_block_hash]
|
||||
* EPOCHS_PER_HISTORICAL_VECTOR, # Seed RANDAO with Eth1 entropy
|
||||
@@ -4162,10 +4074,11 @@
|
||||
- name: is_parent_strong
|
||||
sources: []
|
||||
spec: |
|
||||
<spec fn="is_parent_strong" fork="phase0" hash="e06641a8">
|
||||
def is_parent_strong(store: Store, parent_root: Root) -> bool:
|
||||
<spec fn="is_parent_strong" fork="phase0" hash="02a3fd0b">
|
||||
def is_parent_strong(store: Store, root: Root) -> bool:
|
||||
justified_state = store.checkpoint_states[store.justified_checkpoint]
|
||||
parent_threshold = calculate_committee_fraction(justified_state, REORG_PARENT_WEIGHT_THRESHOLD)
|
||||
parent_root = store.blocks[root].parent_root
|
||||
parent_weight = get_weight(store, parent_root)
|
||||
return parent_weight > parent_threshold
|
||||
</spec>
|
||||
@@ -4683,7 +4596,7 @@
|
||||
- file: beacon-chain/blockchain/receive_block.go
|
||||
search: func (s *Service) ReceiveBlock(
|
||||
spec: |
|
||||
<spec fn="on_block" fork="phase0" hash="aff24b59">
|
||||
<spec fn="on_block" fork="phase0" hash="5f45947a">
|
||||
def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
|
||||
block = signed_block.message
|
||||
# Parent block must be known
|
||||
@@ -4713,19 +4626,8 @@
|
||||
# Add new state for this block to the store
|
||||
store.block_states[block_root] = state
|
||||
|
||||
# Add block timeliness to the store
|
||||
seconds_since_genesis = store.time - store.genesis_time
|
||||
time_into_slot_ms = seconds_to_milliseconds(seconds_since_genesis) % SLOT_DURATION_MS
|
||||
epoch = get_current_store_epoch(store)
|
||||
attestation_threshold_ms = get_attestation_due_ms(epoch)
|
||||
is_before_attesting_interval = time_into_slot_ms < attestation_threshold_ms
|
||||
is_timely = get_current_slot(store) == block.slot and is_before_attesting_interval
|
||||
store.block_timeliness[hash_tree_root(block)] = is_timely
|
||||
|
||||
# Add proposer score boost if the block is timely and not conflicting with an existing block
|
||||
is_first_block = store.proposer_boost_root == Root()
|
||||
if is_timely and is_first_block:
|
||||
store.proposer_boost_root = hash_tree_root(block)
|
||||
record_block_timeliness(store, block_root)
|
||||
update_proposer_boost_root(store, block_root)
|
||||
|
||||
# Update checkpoints in store if necessary
|
||||
update_checkpoints(store, state.current_justified_checkpoint, state.finalized_checkpoint)
|
||||
@@ -4739,7 +4641,7 @@
|
||||
- file: beacon-chain/blockchain/receive_block.go
|
||||
search: func (s *Service) ReceiveBlock(
|
||||
spec: |
|
||||
<spec fn="on_block" fork="bellatrix" hash="a3193d92">
|
||||
<spec fn="on_block" fork="bellatrix" hash="e81d01c3">
|
||||
def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
|
||||
"""
|
||||
Run ``on_block`` upon receiving a new block.
|
||||
@@ -4780,19 +4682,8 @@
|
||||
# Add new state for this block to the store
|
||||
store.block_states[block_root] = state
|
||||
|
||||
# Add block timeliness to the store
|
||||
seconds_since_genesis = store.time - store.genesis_time
|
||||
time_into_slot_ms = seconds_to_milliseconds(seconds_since_genesis) % SLOT_DURATION_MS
|
||||
epoch = get_current_store_epoch(store)
|
||||
attestation_threshold_ms = get_attestation_due_ms(epoch)
|
||||
is_before_attesting_interval = time_into_slot_ms < attestation_threshold_ms
|
||||
is_timely = get_current_slot(store) == block.slot and is_before_attesting_interval
|
||||
store.block_timeliness[hash_tree_root(block)] = is_timely
|
||||
|
||||
# Add proposer score boost if the block is timely and not conflicting with an existing block
|
||||
is_first_block = store.proposer_boost_root == Root()
|
||||
if is_timely and is_first_block:
|
||||
store.proposer_boost_root = hash_tree_root(block)
|
||||
record_block_timeliness(store, block_root)
|
||||
update_proposer_boost_root(store, block_root)
|
||||
|
||||
# Update checkpoints in store if necessary
|
||||
update_checkpoints(store, state.current_justified_checkpoint, state.finalized_checkpoint)
|
||||
@@ -4806,7 +4697,7 @@
|
||||
- file: beacon-chain/blockchain/receive_block.go
|
||||
search: func (s *Service) ReceiveBlock(
|
||||
spec: |
|
||||
<spec fn="on_block" fork="capella" hash="560056ad">
|
||||
<spec fn="on_block" fork="capella" hash="7450531c">
|
||||
def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
|
||||
"""
|
||||
Run ``on_block`` upon receiving a new block.
|
||||
@@ -4839,19 +4730,8 @@
|
||||
# Add new state for this block to the store
|
||||
store.block_states[block_root] = state
|
||||
|
||||
# Add block timeliness to the store
|
||||
seconds_since_genesis = store.time - store.genesis_time
|
||||
time_into_slot_ms = seconds_to_milliseconds(seconds_since_genesis) % SLOT_DURATION_MS
|
||||
epoch = get_current_store_epoch(store)
|
||||
attestation_threshold_ms = get_attestation_due_ms(epoch)
|
||||
is_before_attesting_interval = time_into_slot_ms < attestation_threshold_ms
|
||||
is_timely = get_current_slot(store) == block.slot and is_before_attesting_interval
|
||||
store.block_timeliness[hash_tree_root(block)] = is_timely
|
||||
|
||||
# Add proposer score boost if the block is timely and not conflicting with an existing block
|
||||
is_first_block = store.proposer_boost_root == Root()
|
||||
if is_timely and is_first_block:
|
||||
store.proposer_boost_root = hash_tree_root(block)
|
||||
record_block_timeliness(store, block_root)
|
||||
update_proposer_boost_root(store, block_root)
|
||||
|
||||
# Update checkpoints in store if necessary
|
||||
update_checkpoints(store, state.current_justified_checkpoint, state.finalized_checkpoint)
|
||||
@@ -4865,7 +4745,7 @@
|
||||
- file: beacon-chain/blockchain/receive_block.go
|
||||
search: func (s *Service) ReceiveBlock(
|
||||
spec: |
|
||||
<spec fn="on_block" fork="deneb" hash="9565acee">
|
||||
<spec fn="on_block" fork="deneb" hash="bbad196e">
|
||||
def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
|
||||
"""
|
||||
Run ``on_block`` upon receiving a new block.
|
||||
@@ -4903,19 +4783,8 @@
|
||||
# Add new state for this block to the store
|
||||
store.block_states[block_root] = state
|
||||
|
||||
# Add block timeliness to the store
|
||||
seconds_since_genesis = store.time - store.genesis_time
|
||||
time_into_slot_ms = seconds_to_milliseconds(seconds_since_genesis) % SLOT_DURATION_MS
|
||||
epoch = get_current_store_epoch(store)
|
||||
attestation_threshold_ms = get_attestation_due_ms(epoch)
|
||||
is_before_attesting_interval = time_into_slot_ms < attestation_threshold_ms
|
||||
is_timely = get_current_slot(store) == block.slot and is_before_attesting_interval
|
||||
store.block_timeliness[hash_tree_root(block)] = is_timely
|
||||
|
||||
# Add proposer score boost if the block is timely and not conflicting with an existing block
|
||||
is_first_block = store.proposer_boost_root == Root()
|
||||
if is_timely and is_first_block:
|
||||
store.proposer_boost_root = hash_tree_root(block)
|
||||
record_block_timeliness(store, block_root)
|
||||
update_proposer_boost_root(store, block_root)
|
||||
|
||||
# Update checkpoints in store if necessary
|
||||
update_checkpoints(store, state.current_justified_checkpoint, state.finalized_checkpoint)
|
||||
@@ -4929,7 +4798,7 @@
|
||||
- file: beacon-chain/blockchain/receive_block.go
|
||||
search: func (s *Service) ReceiveBlock(
|
||||
spec: |
|
||||
<spec fn="on_block" fork="fulu" hash="4f955de9">
|
||||
<spec fn="on_block" fork="fulu" hash="b8f279b9">
|
||||
def on_block(store: Store, signed_block: SignedBeaconBlock) -> None:
|
||||
"""
|
||||
Run ``on_block`` upon receiving a new block.
|
||||
@@ -4967,19 +4836,8 @@
|
||||
# Add new state for this block to the store
|
||||
store.block_states[block_root] = state
|
||||
|
||||
# Add block timeliness to the store
|
||||
seconds_since_genesis = store.time - store.genesis_time
|
||||
time_into_slot_ms = seconds_to_milliseconds(seconds_since_genesis) % SLOT_DURATION_MS
|
||||
epoch = get_current_store_epoch(store)
|
||||
attestation_threshold_ms = get_attestation_due_ms(epoch)
|
||||
is_before_attesting_interval = time_into_slot_ms < attestation_threshold_ms
|
||||
is_timely = get_current_slot(store) == block.slot and is_before_attesting_interval
|
||||
store.block_timeliness[hash_tree_root(block)] = is_timely
|
||||
|
||||
# Add proposer score boost if the block is timely and not conflicting with an existing block
|
||||
is_first_block = store.proposer_boost_root == Root()
|
||||
if is_timely and is_first_block:
|
||||
store.proposer_boost_root = hash_tree_root(block)
|
||||
record_block_timeliness(store, block_root)
|
||||
update_proposer_boost_root(store, block_root)
|
||||
|
||||
# Update checkpoints in store if necessary
|
||||
update_checkpoints(store, state.current_justified_checkpoint, state.finalized_checkpoint)
|
||||
@@ -5074,7 +4932,7 @@
|
||||
- name: prepare_execution_payload#capella
|
||||
sources: []
|
||||
spec: |
|
||||
<spec fn="prepare_execution_payload" fork="capella" hash="28db1590">
|
||||
<spec fn="prepare_execution_payload" fork="capella" hash="c258893e">
|
||||
def prepare_execution_payload(
|
||||
state: BeaconState,
|
||||
safe_block_hash: Hash32,
|
||||
@@ -5087,12 +4945,15 @@
|
||||
parent_hash = state.latest_execution_payload_header.block_hash
|
||||
|
||||
# Set the forkchoice head and initiate the payload build process
|
||||
# [New in Capella]
|
||||
withdrawals, _ = get_expected_withdrawals(state)
|
||||
|
||||
payload_attributes = PayloadAttributes(
|
||||
timestamp=compute_time_at_slot(state, state.slot),
|
||||
prev_randao=get_randao_mix(state, get_current_epoch(state)),
|
||||
suggested_fee_recipient=suggested_fee_recipient,
|
||||
# [New in Capella]
|
||||
withdrawals=get_expected_withdrawals(state),
|
||||
withdrawals=withdrawals,
|
||||
)
|
||||
return execution_engine.notify_forkchoice_updated(
|
||||
head_block_hash=parent_hash,
|
||||
@@ -5105,7 +4966,7 @@
|
||||
- name: prepare_execution_payload#deneb
|
||||
sources: []
|
||||
spec: |
|
||||
<spec fn="prepare_execution_payload" fork="deneb" hash="f3387ec6">
|
||||
<spec fn="prepare_execution_payload" fork="deneb" hash="59f61f3a">
|
||||
def prepare_execution_payload(
|
||||
state: BeaconState,
|
||||
safe_block_hash: Hash32,
|
||||
@@ -5117,11 +4978,13 @@
|
||||
parent_hash = state.latest_execution_payload_header.block_hash
|
||||
|
||||
# Set the forkchoice head and initiate the payload build process
|
||||
withdrawals, _ = get_expected_withdrawals(state)
|
||||
|
||||
payload_attributes = PayloadAttributes(
|
||||
timestamp=compute_time_at_slot(state, state.slot),
|
||||
prev_randao=get_randao_mix(state, get_current_epoch(state)),
|
||||
suggested_fee_recipient=suggested_fee_recipient,
|
||||
withdrawals=get_expected_withdrawals(state),
|
||||
withdrawals=withdrawals,
|
||||
# [New in Deneb:EIP4788]
|
||||
parent_beacon_block_root=hash_tree_root(state.latest_block_header),
|
||||
)
|
||||
@@ -5136,7 +4999,7 @@
|
||||
- name: prepare_execution_payload#electra
|
||||
sources: []
|
||||
spec: |
|
||||
<spec fn="prepare_execution_payload" fork="electra" hash="567b3739">
|
||||
<spec fn="prepare_execution_payload" fork="electra" hash="5414b883">
|
||||
def prepare_execution_payload(
|
||||
state: BeaconState,
|
||||
safe_block_hash: Hash32,
|
||||
@@ -5149,7 +5012,7 @@
|
||||
|
||||
# [Modified in EIP7251]
|
||||
# Set the forkchoice head and initiate the payload build process
|
||||
withdrawals, _ = get_expected_withdrawals(state)
|
||||
withdrawals, _, _ = get_expected_withdrawals(state)
|
||||
|
||||
payload_attributes = PayloadAttributes(
|
||||
timestamp=compute_time_at_slot(state, state.slot),
|
||||
@@ -5171,7 +5034,7 @@
|
||||
- file: beacon-chain/core/blocks/attestation.go
|
||||
search: func ProcessAttestationNoVerifySignature(
|
||||
spec: |
|
||||
<spec fn="process_attestation" fork="phase0" hash="6ac78cd0">
|
||||
<spec fn="process_attestation" fork="phase0" hash="d8e86aa9">
|
||||
def process_attestation(state: BeaconState, attestation: Attestation) -> None:
|
||||
data = attestation.data
|
||||
assert data.target.epoch in (get_previous_epoch(state), get_current_epoch(state))
|
||||
@@ -5183,8 +5046,8 @@
|
||||
assert len(attestation.aggregation_bits) == len(committee)
|
||||
|
||||
pending_attestation = PendingAttestation(
|
||||
data=data,
|
||||
aggregation_bits=attestation.aggregation_bits,
|
||||
data=data,
|
||||
inclusion_delay=state.slot - data.slot,
|
||||
proposer_index=get_beacon_proposer_index(state),
|
||||
)
|
||||
@@ -7208,31 +7071,18 @@
|
||||
- file: beacon-chain/core/blocks/withdrawals.go
|
||||
search: func ProcessWithdrawals(
|
||||
spec: |
|
||||
<spec fn="process_withdrawals" fork="capella" hash="ed6a9c5a">
|
||||
<spec fn="process_withdrawals" fork="capella" hash="901f9fc4">
|
||||
def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None:
|
||||
expected_withdrawals = get_expected_withdrawals(state)
|
||||
assert payload.withdrawals == expected_withdrawals
|
||||
# Get expected withdrawals
|
||||
withdrawals, processed_validators_sweep_count = get_expected_withdrawals(state)
|
||||
assert payload.withdrawals == withdrawals
|
||||
|
||||
for withdrawal in expected_withdrawals:
|
||||
decrease_balance(state, withdrawal.validator_index, withdrawal.amount)
|
||||
# Apply expected withdrawals
|
||||
apply_withdrawals(state, withdrawals)
|
||||
|
||||
# Update the next withdrawal index if this block contained withdrawals
|
||||
if len(expected_withdrawals) != 0:
|
||||
latest_withdrawal = expected_withdrawals[-1]
|
||||
state.next_withdrawal_index = WithdrawalIndex(latest_withdrawal.index + 1)
|
||||
|
||||
# Update the next validator index to start the next withdrawal sweep
|
||||
if len(expected_withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD:
|
||||
# Next sweep starts after the latest withdrawal's validator index
|
||||
next_validator_index = ValidatorIndex(
|
||||
(expected_withdrawals[-1].validator_index + 1) % len(state.validators)
|
||||
)
|
||||
state.next_withdrawal_validator_index = next_validator_index
|
||||
else:
|
||||
# Advance sweep by the max length of the sweep if there was not a full set of withdrawals
|
||||
next_index = state.next_withdrawal_validator_index + MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP
|
||||
next_validator_index = ValidatorIndex(next_index % len(state.validators))
|
||||
state.next_withdrawal_validator_index = next_validator_index
|
||||
# Update withdrawals fields in the state
|
||||
update_next_withdrawal_index(state, withdrawals)
|
||||
update_next_withdrawal_validator_index(state, processed_validators_sweep_count)
|
||||
</spec>
|
||||
|
||||
- name: process_withdrawals#electra
|
||||
@@ -7240,39 +7090,23 @@
|
||||
- file: beacon-chain/core/blocks/withdrawals.go
|
||||
search: func ProcessWithdrawals(
|
||||
spec: |
|
||||
<spec fn="process_withdrawals" fork="electra" hash="dd99a91f">
|
||||
<spec fn="process_withdrawals" fork="electra" hash="67870972">
|
||||
def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None:
|
||||
# [Modified in Electra:EIP7251]
|
||||
expected_withdrawals, processed_partial_withdrawals_count = get_expected_withdrawals(state)
|
||||
# Get expected withdrawals
|
||||
withdrawals, processed_partial_withdrawals_count, processed_validators_sweep_count = (
|
||||
get_expected_withdrawals(state)
|
||||
)
|
||||
assert payload.withdrawals == withdrawals
|
||||
|
||||
assert payload.withdrawals == expected_withdrawals
|
||||
|
||||
for withdrawal in expected_withdrawals:
|
||||
decrease_balance(state, withdrawal.validator_index, withdrawal.amount)
|
||||
# Apply expected withdrawals
|
||||
apply_withdrawals(state, withdrawals)
|
||||
|
||||
# Update withdrawals fields in the state
|
||||
update_next_withdrawal_index(state, withdrawals)
|
||||
# [New in Electra:EIP7251]
|
||||
# Update pending partial withdrawals
|
||||
state.pending_partial_withdrawals = state.pending_partial_withdrawals[
|
||||
processed_partial_withdrawals_count:
|
||||
]
|
||||
|
||||
# Update the next withdrawal index if this block contained withdrawals
|
||||
if len(expected_withdrawals) != 0:
|
||||
latest_withdrawal = expected_withdrawals[-1]
|
||||
state.next_withdrawal_index = WithdrawalIndex(latest_withdrawal.index + 1)
|
||||
|
||||
# Update the next validator index to start the next withdrawal sweep
|
||||
if len(expected_withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD:
|
||||
# Next sweep starts after the latest withdrawal's validator index
|
||||
next_validator_index = ValidatorIndex(
|
||||
(expected_withdrawals[-1].validator_index + 1) % len(state.validators)
|
||||
)
|
||||
state.next_withdrawal_validator_index = next_validator_index
|
||||
else:
|
||||
# Advance sweep by the max length of the sweep if there was not a full set of withdrawals
|
||||
next_index = state.next_withdrawal_validator_index + MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP
|
||||
next_validator_index = ValidatorIndex(next_index % len(state.validators))
|
||||
state.next_withdrawal_validator_index = next_validator_index
|
||||
update_pending_partial_withdrawals(state, processed_partial_withdrawals_count)
|
||||
update_next_withdrawal_validator_index(state, processed_validators_sweep_count)
|
||||
</spec>
|
||||
|
||||
- name: queue_excess_active_balance
|
||||
@@ -7303,7 +7137,7 @@
|
||||
- name: recover_matrix
|
||||
sources: []
|
||||
spec: |
|
||||
<spec fn="recover_matrix" fork="fulu" hash="9b01f005">
|
||||
<spec fn="recover_matrix" fork="fulu" hash="3db21f50">
|
||||
def recover_matrix(
|
||||
partial_matrix: Sequence[MatrixEntry], blob_count: uint64
|
||||
) -> Sequence[MatrixEntry]:
|
||||
@@ -7323,8 +7157,8 @@
|
||||
MatrixEntry(
|
||||
cell=cell,
|
||||
kzg_proof=proof,
|
||||
row_index=blob_index,
|
||||
column_index=cell_index,
|
||||
row_index=blob_index,
|
||||
)
|
||||
)
|
||||
return matrix
|
||||
@@ -7373,7 +7207,7 @@
|
||||
- file: beacon-chain/forkchoice/ro.go
|
||||
search: func (ro *ROForkChoice) ShouldOverrideFCU(
|
||||
spec: |
|
||||
<spec fn="should_override_forkchoice_update" fork="bellatrix" hash="9a8043af">
|
||||
<spec fn="should_override_forkchoice_update" fork="bellatrix" hash="c055d92a">
|
||||
def should_override_forkchoice_update(store: Store, head_root: Root) -> bool:
|
||||
head_block = store.blocks[head_root]
|
||||
parent_root = head_block.parent_root
|
||||
@@ -7414,7 +7248,7 @@
|
||||
# `store.time` early, or by counting queued attestations during the head block's slot.
|
||||
if current_slot > head_block.slot:
|
||||
head_weak = is_head_weak(store, head_root)
|
||||
parent_strong = is_parent_strong(store, parent_root)
|
||||
parent_strong = is_parent_strong(store, head_root)
|
||||
else:
|
||||
head_weak = True
|
||||
parent_strong = True
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v7/encoding/ssz/equality"
|
||||
"github.com/d4l3k/messagediff"
|
||||
@@ -138,12 +139,21 @@ func StringContains(loggerFn assertionLoggerFn, expected, actual string, flag bo
|
||||
|
||||
// NoError asserts that error is nil.
|
||||
func NoError(loggerFn assertionLoggerFn, err error, msg ...any) {
|
||||
// reflect.ValueOf is needed for nil instances of custom types implementing Error
|
||||
if err != nil && !reflect.ValueOf(err).IsNil() {
|
||||
errMsg := parseMsg("Unexpected error", msg...)
|
||||
_, file, line, _ := runtime.Caller(2)
|
||||
loggerFn("%s:%d %s: %v", filepath.Base(file), line, errMsg, err)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
// reflect.ValueOf is needed for nil instances of custom types implementing Error.
|
||||
// Only check IsNil for types that support it to avoid panics on struct types.
|
||||
v := reflect.ValueOf(err)
|
||||
switch v.Kind() {
|
||||
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
|
||||
if v.IsNil() {
|
||||
return
|
||||
}
|
||||
}
|
||||
errMsg := parseMsg("Unexpected error", msg...)
|
||||
_, file, line, _ := runtime.Caller(2)
|
||||
loggerFn("%s:%d %s: %v", filepath.Base(file), line, errMsg, err)
|
||||
}
|
||||
|
||||
// ErrorIs uses Errors.Is to recursively unwrap err looking for target in the chain.
|
||||
@@ -341,3 +351,18 @@ func (tb *TBMock) Errorf(format string, args ...any) {
|
||||
func (tb *TBMock) Fatalf(format string, args ...any) {
|
||||
tb.FatalfMsg = fmt.Sprintf(format, args...)
|
||||
}
|
||||
|
||||
// Eventually asserts that given condition will be met within waitFor time,
|
||||
// periodically checking target function each tick.
|
||||
func Eventually(loggerFn assertionLoggerFn, condition func() bool, waitFor, tick time.Duration, msg ...any) {
|
||||
deadline := time.Now().Add(waitFor)
|
||||
for time.Now().Before(deadline) {
|
||||
if condition() {
|
||||
return
|
||||
}
|
||||
time.Sleep(tick)
|
||||
}
|
||||
errMsg := parseMsg("Condition never satisfied", msg...)
|
||||
_, file, line, _ := runtime.Caller(2)
|
||||
loggerFn("%s:%d %s (waited %v)", filepath.Base(file), line, errMsg, waitFor)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package require
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v7/testing/assertions"
|
||||
"github.com/sirupsen/logrus/hooks/test"
|
||||
)
|
||||
@@ -87,3 +89,9 @@ func ErrorIs(tb assertions.AssertionTestingTB, err, target error, msg ...any) {
|
||||
func StringContains(tb assertions.AssertionTestingTB, expected, actual string, msg ...any) {
|
||||
assertions.StringContains(tb.Fatalf, expected, actual, true, msg)
|
||||
}
|
||||
|
||||
// Eventually asserts that given condition will be met within waitFor time,
|
||||
// periodically checking target function each tick.
|
||||
func Eventually(tb assertions.AssertionTestingTB, condition func() bool, waitFor, tick time.Duration, msg ...any) {
|
||||
assertions.Eventually(tb.Fatalf, condition, waitFor, tick, msg...)
|
||||
}
|
||||
|
||||
@@ -62,8 +62,17 @@ func runTest(t *testing.T, config string, fork int, basePath string) { // nolint
|
||||
if len(testFolders) == 0 {
|
||||
t.Fatalf("No test folders found for %s/%s/%s", config, version.String(fork), folderPath)
|
||||
}
|
||||
|
||||
var skipTests = map[string]bool{
|
||||
// Skipping because of #4807 backporting issues
|
||||
"voting_source_beyond_two_epoch": true,
|
||||
"justified_update_always_if_better": true,
|
||||
"justified_update_not_realized_finality": true,
|
||||
}
|
||||
for _, folder := range testFolders {
|
||||
if skipTests[folder.Name()] {
|
||||
t.Logf("Skipping test %s due to known issues", folder.Name())
|
||||
continue
|
||||
}
|
||||
t.Run(folder.Name(), func(t *testing.T) {
|
||||
helpers.ClearCache()
|
||||
preStepsFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), "steps.yaml")
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"testing"
|
||||
|
||||
state_native "github.com/OffchainLabs/prysm/v7/beacon-chain/state/state-native"
|
||||
// enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1"
|
||||
enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1"
|
||||
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
|
||||
"github.com/OffchainLabs/prysm/v7/testing/require"
|
||||
@@ -56,6 +57,8 @@ func unmarshalledSSZ(t *testing.T, serializedBytes []byte, folderName string) (a
|
||||
obj = ðpb.BeaconBlockBodyGloas{}
|
||||
case "BeaconState":
|
||||
obj = ðpb.BeaconStateGloas{}
|
||||
case "Builder":
|
||||
obj = ðpb.Builder{}
|
||||
case "BuilderPendingPayment":
|
||||
obj = ðpb.BuilderPendingPayment{}
|
||||
case "BuilderPendingWithdrawal":
|
||||
@@ -70,6 +73,8 @@ func unmarshalledSSZ(t *testing.T, serializedBytes []byte, folderName string) (a
|
||||
t.Skip("Not a consensus type")
|
||||
case "DataColumnSidecar":
|
||||
obj = ðpb.DataColumnSidecarGloas{}
|
||||
case "SignedProposerPreferences", "ProposerPreferences":
|
||||
t.Skip("p2p-only type; not part of the consensus state transition")
|
||||
|
||||
// Standard types that also exist in gloas
|
||||
case "ExecutionPayload":
|
||||
|
||||
12
testing/validator-mock/node_client_mock.go
generated
12
testing/validator-mock/node_client_mock.go
generated
@@ -56,18 +56,18 @@ func (mr *MockNodeClientMockRecorder) Genesis(arg0, arg1 any) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Genesis", reflect.TypeOf((*MockNodeClient)(nil).Genesis), arg0, arg1)
|
||||
}
|
||||
|
||||
// IsHealthy mocks base method.
|
||||
func (m *MockNodeClient) IsHealthy(arg0 context.Context) bool {
|
||||
// IsReady mocks base method.
|
||||
func (m *MockNodeClient) IsReady(arg0 context.Context) bool {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "IsHealthy", arg0)
|
||||
ret := m.ctrl.Call(m, "IsReady", arg0)
|
||||
ret0, _ := ret[0].(bool)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// IsHealthy indicates an expected call of IsHealthy.
|
||||
func (mr *MockNodeClientMockRecorder) IsHealthy(arg0 any) *gomock.Call {
|
||||
// IsReady indicates an expected call of IsReady.
|
||||
func (mr *MockNodeClientMockRecorder) IsReady(arg0 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsHealthy", reflect.TypeOf((*MockNodeClient)(nil).IsHealthy), arg0)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsReady", reflect.TypeOf((*MockNodeClient)(nil).IsReady), arg0)
|
||||
}
|
||||
|
||||
// Peers mocks base method.
|
||||
|
||||
@@ -2,6 +2,7 @@ package beacon_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v7/api/server/structs"
|
||||
@@ -101,12 +102,17 @@ func (c *beaconApiNodeClient) Peers(ctx context.Context, in *empty.Empty) (*ethp
|
||||
return nil, errors.New("beaconApiNodeClient.Peers is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiNodeClientWithFallback.")
|
||||
}
|
||||
|
||||
func (c *beaconApiNodeClient) IsHealthy(ctx context.Context) bool {
|
||||
if err := c.jsonRestHandler.Get(ctx, "/eth/v1/node/health", nil); err != nil {
|
||||
// IsReady returns true only if the node is fully synced (200 OK).
|
||||
// A 206 Partial Content response indicates the node is syncing and not ready.
|
||||
func (c *beaconApiNodeClient) IsReady(ctx context.Context) bool {
|
||||
statusCode, err := c.jsonRestHandler.GetStatusCode(ctx, "/eth/v1/node/health")
|
||||
if err != nil {
|
||||
log.WithError(err).Error("failed to get health of node")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
// Only 200 OK means the node is fully synced and ready.
|
||||
// 206 Partial Content means syncing, 503 means unavailable.
|
||||
return statusCode == http.StatusOK
|
||||
}
|
||||
|
||||
func NewNodeClientWithFallback(jsonRestHandler RestHandler, fallbackClient iface.NodeClient) iface.NodeClient {
|
||||
|
||||
@@ -2,6 +2,7 @@ package beacon_api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v7/api/server/structs"
|
||||
@@ -287,3 +288,59 @@ func TestGetVersion(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsReady(t *testing.T) {
|
||||
const healthEndpoint = "/eth/v1/node/health"
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
statusCode int
|
||||
err error
|
||||
expectedResult bool
|
||||
}{
|
||||
{
|
||||
name: "returns true for 200 OK (fully synced)",
|
||||
statusCode: http.StatusOK,
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
name: "returns false for 206 Partial Content (syncing)",
|
||||
statusCode: http.StatusPartialContent,
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
name: "returns false for 503 Service Unavailable",
|
||||
statusCode: http.StatusServiceUnavailable,
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
name: "returns false for 500 Internal Server Error",
|
||||
statusCode: http.StatusInternalServerError,
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
name: "returns false on error",
|
||||
err: errors.New("request failed"),
|
||||
expectedResult: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
ctx := t.Context()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().GetStatusCode(
|
||||
gomock.Any(),
|
||||
healthEndpoint,
|
||||
).Return(tc.statusCode, tc.err)
|
||||
|
||||
nodeClient := &beaconApiNodeClient{jsonRestHandler: jsonRestHandler}
|
||||
result := nodeClient.IsReady(ctx)
|
||||
|
||||
assert.Equal(t, tc.expectedResult, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: validator/client/beacon-api/json_rest_handler.go
|
||||
// Source: validator/client/beacon-api/rest_handler_client.go
|
||||
//
|
||||
// Generated by this command:
|
||||
//
|
||||
// mockgen -package=mock -source=validator/client/beacon-api/json_rest_handler.go -destination=validator/client/beacon-api/mock/json_rest_handler_mock.go
|
||||
// mockgen -package=mock -source=validator/client/beacon-api/rest_handler_client.go -destination=validator/client/beacon-api/mock/json_rest_handler_mock.go RestHandler
|
||||
//
|
||||
|
||||
// Package mock is a generated GoMock package.
|
||||
@@ -18,32 +18,37 @@ import (
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
// MockJsonRestHandler is a mock of JsonRestHandler interface.
|
||||
type MockJsonRestHandler struct {
|
||||
// Backward compatibility aliases for the renamed mock type.
|
||||
type MockJsonRestHandler = MockRestHandler
|
||||
type MockJsonRestHandlerMockRecorder = MockRestHandlerMockRecorder
|
||||
|
||||
var NewMockJsonRestHandler = NewMockRestHandler
|
||||
|
||||
// MockRestHandler is a mock of RestHandler interface.
|
||||
type MockRestHandler struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockJsonRestHandlerMockRecorder
|
||||
isgomock struct{}
|
||||
recorder *MockRestHandlerMockRecorder
|
||||
}
|
||||
|
||||
// MockJsonRestHandlerMockRecorder is the mock recorder for MockJsonRestHandler.
|
||||
type MockJsonRestHandlerMockRecorder struct {
|
||||
mock *MockJsonRestHandler
|
||||
// MockRestHandlerMockRecorder is the mock recorder for MockRestHandler.
|
||||
type MockRestHandlerMockRecorder struct {
|
||||
mock *MockRestHandler
|
||||
}
|
||||
|
||||
// NewMockJsonRestHandler creates a new mock instance.
|
||||
func NewMockJsonRestHandler(ctrl *gomock.Controller) *MockJsonRestHandler {
|
||||
mock := &MockJsonRestHandler{ctrl: ctrl}
|
||||
mock.recorder = &MockJsonRestHandlerMockRecorder{mock}
|
||||
// NewMockRestHandler creates a new mock instance.
|
||||
func NewMockRestHandler(ctrl *gomock.Controller) *MockRestHandler {
|
||||
mock := &MockRestHandler{ctrl: ctrl}
|
||||
mock.recorder = &MockRestHandlerMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockJsonRestHandler) EXPECT() *MockJsonRestHandlerMockRecorder {
|
||||
func (m *MockRestHandler) EXPECT() *MockRestHandlerMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Get mocks base method.
|
||||
func (m *MockJsonRestHandler) Get(ctx context.Context, endpoint string, resp any) error {
|
||||
func (m *MockRestHandler) Get(ctx context.Context, endpoint string, resp any) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Get", ctx, endpoint, resp)
|
||||
ret0, _ := ret[0].(error)
|
||||
@@ -51,13 +56,13 @@ func (m *MockJsonRestHandler) Get(ctx context.Context, endpoint string, resp any
|
||||
}
|
||||
|
||||
// Get indicates an expected call of Get.
|
||||
func (mr *MockJsonRestHandlerMockRecorder) Get(ctx, endpoint, resp any) *gomock.Call {
|
||||
func (mr *MockRestHandlerMockRecorder) Get(ctx, endpoint, resp any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockJsonRestHandler)(nil).Get), ctx, endpoint, resp)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockRestHandler)(nil).Get), ctx, endpoint, resp)
|
||||
}
|
||||
|
||||
// GetSSZ mocks base method.
|
||||
func (m *MockJsonRestHandler) GetSSZ(ctx context.Context, endpoint string) ([]byte, http.Header, error) {
|
||||
func (m *MockRestHandler) GetSSZ(ctx context.Context, endpoint string) ([]byte, http.Header, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetSSZ", ctx, endpoint)
|
||||
ret0, _ := ret[0].([]byte)
|
||||
@@ -67,13 +72,28 @@ func (m *MockJsonRestHandler) GetSSZ(ctx context.Context, endpoint string) ([]by
|
||||
}
|
||||
|
||||
// GetSSZ indicates an expected call of GetSSZ.
|
||||
func (mr *MockJsonRestHandlerMockRecorder) GetSSZ(ctx, endpoint any) *gomock.Call {
|
||||
func (mr *MockRestHandlerMockRecorder) GetSSZ(ctx, endpoint any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSSZ", reflect.TypeOf((*MockJsonRestHandler)(nil).GetSSZ), ctx, endpoint)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSSZ", reflect.TypeOf((*MockRestHandler)(nil).GetSSZ), ctx, endpoint)
|
||||
}
|
||||
|
||||
// GetStatusCode mocks base method.
|
||||
func (m *MockRestHandler) GetStatusCode(ctx context.Context, endpoint string) (int, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetStatusCode", ctx, endpoint)
|
||||
ret0, _ := ret[0].(int)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetStatusCode indicates an expected call of GetStatusCode.
|
||||
func (mr *MockRestHandlerMockRecorder) GetStatusCode(ctx, endpoint any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStatusCode", reflect.TypeOf((*MockRestHandler)(nil).GetStatusCode), ctx, endpoint)
|
||||
}
|
||||
|
||||
// Host mocks base method.
|
||||
func (m *MockJsonRestHandler) Host() string {
|
||||
func (m *MockRestHandler) Host() string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Host")
|
||||
ret0, _ := ret[0].(string)
|
||||
@@ -81,13 +101,13 @@ func (m *MockJsonRestHandler) Host() string {
|
||||
}
|
||||
|
||||
// Host indicates an expected call of Host.
|
||||
func (mr *MockJsonRestHandlerMockRecorder) Host() *gomock.Call {
|
||||
func (mr *MockRestHandlerMockRecorder) Host() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Host", reflect.TypeOf((*MockJsonRestHandler)(nil).Host))
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Host", reflect.TypeOf((*MockRestHandler)(nil).Host))
|
||||
}
|
||||
|
||||
// HttpClient mocks base method.
|
||||
func (m *MockJsonRestHandler) HttpClient() *http.Client {
|
||||
func (m *MockRestHandler) HttpClient() *http.Client {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "HttpClient")
|
||||
ret0, _ := ret[0].(*http.Client)
|
||||
@@ -95,13 +115,13 @@ func (m *MockJsonRestHandler) HttpClient() *http.Client {
|
||||
}
|
||||
|
||||
// HttpClient indicates an expected call of HttpClient.
|
||||
func (mr *MockJsonRestHandlerMockRecorder) HttpClient() *gomock.Call {
|
||||
func (mr *MockRestHandlerMockRecorder) HttpClient() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HttpClient", reflect.TypeOf((*MockJsonRestHandler)(nil).HttpClient))
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HttpClient", reflect.TypeOf((*MockRestHandler)(nil).HttpClient))
|
||||
}
|
||||
|
||||
// Post mocks base method.
|
||||
func (m *MockJsonRestHandler) Post(ctx context.Context, endpoint string, headers map[string]string, data *bytes.Buffer, resp any) error {
|
||||
func (m *MockRestHandler) Post(ctx context.Context, endpoint string, headers map[string]string, data *bytes.Buffer, resp any) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Post", ctx, endpoint, headers, data, resp)
|
||||
ret0, _ := ret[0].(error)
|
||||
@@ -109,13 +129,13 @@ func (m *MockJsonRestHandler) Post(ctx context.Context, endpoint string, headers
|
||||
}
|
||||
|
||||
// Post indicates an expected call of Post.
|
||||
func (mr *MockJsonRestHandlerMockRecorder) Post(ctx, endpoint, headers, data, resp any) *gomock.Call {
|
||||
func (mr *MockRestHandlerMockRecorder) Post(ctx, endpoint, headers, data, resp any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Post", reflect.TypeOf((*MockJsonRestHandler)(nil).Post), ctx, endpoint, headers, data, resp)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Post", reflect.TypeOf((*MockRestHandler)(nil).Post), ctx, endpoint, headers, data, resp)
|
||||
}
|
||||
|
||||
// Post mocks base method.
|
||||
func (m *MockJsonRestHandler) PostSSZ(ctx context.Context, endpoint string, headers map[string]string, data *bytes.Buffer) ([]byte, http.Header, error) {
|
||||
// PostSSZ mocks base method.
|
||||
func (m *MockRestHandler) PostSSZ(ctx context.Context, endpoint string, headers map[string]string, data *bytes.Buffer) ([]byte, http.Header, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "PostSSZ", ctx, endpoint, headers, data)
|
||||
ret0, _ := ret[0].([]byte)
|
||||
@@ -124,20 +144,20 @@ func (m *MockJsonRestHandler) PostSSZ(ctx context.Context, endpoint string, head
|
||||
return ret0, ret1, ret2
|
||||
}
|
||||
|
||||
// Post indicates an expected call of Post.
|
||||
func (mr *MockJsonRestHandlerMockRecorder) PostSSZ(ctx, endpoint, headers, data any) *gomock.Call {
|
||||
// PostSSZ indicates an expected call of PostSSZ.
|
||||
func (mr *MockRestHandlerMockRecorder) PostSSZ(ctx, endpoint, headers, data any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PostSSZ", reflect.TypeOf((*MockJsonRestHandler)(nil).PostSSZ), ctx, endpoint, headers, data)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PostSSZ", reflect.TypeOf((*MockRestHandler)(nil).PostSSZ), ctx, endpoint, headers, data)
|
||||
}
|
||||
|
||||
// SetHost mocks base method.
|
||||
func (m *MockJsonRestHandler) SetHost(host string) {
|
||||
func (m *MockRestHandler) SetHost(host string) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "SetHost", host)
|
||||
}
|
||||
|
||||
// SetHost indicates an expected call of SetHost.
|
||||
func (mr *MockJsonRestHandlerMockRecorder) SetHost(host any) *gomock.Call {
|
||||
func (mr *MockRestHandlerMockRecorder) SetHost(host any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetHost", reflect.TypeOf((*MockJsonRestHandler)(nil).SetHost), host)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetHost", reflect.TypeOf((*MockRestHandler)(nil).SetHost), host)
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ type reqOption func(*http.Request)
|
||||
|
||||
type RestHandler interface {
|
||||
Get(ctx context.Context, endpoint string, resp any) error
|
||||
GetStatusCode(ctx context.Context, endpoint string) (int, error)
|
||||
GetSSZ(ctx context.Context, endpoint string) ([]byte, http.Header, error)
|
||||
Post(ctx context.Context, endpoint string, headers map[string]string, data *bytes.Buffer, resp any) error
|
||||
PostSSZ(ctx context.Context, endpoint string, headers map[string]string, data *bytes.Buffer) ([]byte, http.Header, error)
|
||||
@@ -90,6 +91,28 @@ func (c *BeaconApiRestHandler) Get(ctx context.Context, endpoint string, resp an
|
||||
return decodeResp(httpResp, resp)
|
||||
}
|
||||
|
||||
// GetStatusCode sends a GET request and returns only the HTTP status code.
|
||||
// This is useful for endpoints like /eth/v1/node/health that communicate status via HTTP codes
|
||||
// (200 = ready, 206 = syncing, 503 = unavailable) rather than response bodies.
|
||||
func (c *BeaconApiRestHandler) GetStatusCode(ctx context.Context, endpoint string) (int, error) {
|
||||
url := c.host + endpoint
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return 0, errors.Wrapf(err, "failed to create request for endpoint %s", url)
|
||||
}
|
||||
req.Header.Set("User-Agent", version.BuildData())
|
||||
httpResp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return 0, errors.Wrapf(err, "failed to perform request for endpoint %s", url)
|
||||
}
|
||||
defer func() {
|
||||
if err := httpResp.Body.Close(); err != nil {
|
||||
return
|
||||
}
|
||||
}()
|
||||
return httpResp.StatusCode, nil
|
||||
}
|
||||
|
||||
func (c *BeaconApiRestHandler) GetSSZ(ctx context.Context, endpoint string) ([]byte, http.Header, error) {
|
||||
url := c.host + endpoint
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
|
||||
@@ -359,3 +359,66 @@ func Test_decodeResp(t *testing.T) {
|
||||
assert.ErrorContains(t, "HTTP request unsuccessful (500: foo)", err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetStatusCode(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
const endpoint = "/eth/v1/node/health"
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
serverStatusCode int
|
||||
expectedStatusCode int
|
||||
}{
|
||||
{
|
||||
name: "returns 200 OK",
|
||||
serverStatusCode: http.StatusOK,
|
||||
expectedStatusCode: http.StatusOK,
|
||||
},
|
||||
{
|
||||
name: "returns 206 Partial Content",
|
||||
serverStatusCode: http.StatusPartialContent,
|
||||
expectedStatusCode: http.StatusPartialContent,
|
||||
},
|
||||
{
|
||||
name: "returns 503 Service Unavailable",
|
||||
serverStatusCode: http.StatusServiceUnavailable,
|
||||
expectedStatusCode: http.StatusServiceUnavailable,
|
||||
},
|
||||
{
|
||||
name: "returns 500 Internal Server Error",
|
||||
serverStatusCode: http.StatusInternalServerError,
|
||||
expectedStatusCode: http.StatusInternalServerError,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc(endpoint, func(w http.ResponseWriter, r *http.Request) {
|
||||
assert.Equal(t, version.BuildData(), r.Header.Get("User-Agent"))
|
||||
w.WriteHeader(tc.serverStatusCode)
|
||||
})
|
||||
server := httptest.NewServer(mux)
|
||||
defer server.Close()
|
||||
|
||||
jsonRestHandler := BeaconApiRestHandler{
|
||||
client: http.Client{Timeout: time.Second * 5},
|
||||
host: server.URL,
|
||||
}
|
||||
|
||||
statusCode, err := jsonRestHandler.GetStatusCode(ctx, endpoint)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tc.expectedStatusCode, statusCode)
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("returns error on connection failure", func(t *testing.T) {
|
||||
jsonRestHandler := BeaconApiRestHandler{
|
||||
client: http.Client{Timeout: time.Millisecond * 100},
|
||||
host: "http://localhost:99999", // Invalid port
|
||||
}
|
||||
|
||||
_, err := jsonRestHandler.GetStatusCode(ctx, endpoint)
|
||||
require.ErrorContains(t, "failed to perform request", err)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ func (c *grpcNodeClient) Peers(ctx context.Context, in *empty.Empty) (*ethpb.Pee
|
||||
return c.nodeClient.ListPeers(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcNodeClient) IsHealthy(ctx context.Context) bool {
|
||||
func (c *grpcNodeClient) IsReady(ctx context.Context) bool {
|
||||
_, err := c.nodeClient.GetHealth(ctx, ðpb.HealthRequest{})
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to get health of node")
|
||||
|
||||
@@ -12,5 +12,5 @@ type NodeClient interface {
|
||||
Genesis(ctx context.Context, in *empty.Empty) (*ethpb.Genesis, error)
|
||||
Version(ctx context.Context, in *empty.Empty) (*ethpb.Version, error)
|
||||
Peers(ctx context.Context, in *empty.Empty) (*ethpb.Peers, error)
|
||||
IsHealthy(ctx context.Context) bool
|
||||
IsReady(ctx context.Context) bool
|
||||
}
|
||||
|
||||
@@ -1274,7 +1274,7 @@ func (v *validator) FindHealthyHost(ctx context.Context) bool {
|
||||
// Tail-recursive closure keeps retry count private.
|
||||
var check func(remaining int) bool
|
||||
check = func(remaining int) bool {
|
||||
if v.nodeClient.IsHealthy(ctx) { // healthy → done
|
||||
if v.nodeClient.IsReady(ctx) { // ready → done
|
||||
return true
|
||||
}
|
||||
if len(v.beaconNodeHosts) == 1 && features.Get().EnableBeaconRESTApi {
|
||||
|
||||
Reference in New Issue
Block a user