mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-22 03:30:37 +00:00
Added reverse beacon changeset for beacon state rewind (#7185)
Added changesets for beacon chain to implement memory efficient fork choice
This commit is contained in:
parent
e38605b8b2
commit
628f52dd6c
@ -531,7 +531,6 @@ func (a *PendingAttestation) EncodeSSZ(buf []byte) (dst []byte, err error) {
|
||||
if dst, err = a.Data.EncodeSSZ(dst); err != nil {
|
||||
return
|
||||
}
|
||||
fmt.Println(dst)
|
||||
dst = append(dst, ssz.Uint64SSZ(a.InclusionDelay)...)
|
||||
dst = append(dst, ssz.Uint64SSZ(a.ProposerIndex)...)
|
||||
|
||||
|
@ -33,3 +33,7 @@ func (j JustificationBits) CheckRange(start int, end int) bool {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (j JustificationBits) Copy() JustificationBits {
|
||||
return JustificationBits{j[0], j[1], j[2], j[3]}
|
||||
}
|
||||
|
@ -25,6 +25,12 @@ func (p ParticipationFlagsList) Bytes() []byte {
|
||||
return b
|
||||
}
|
||||
|
||||
func (p ParticipationFlagsList) Copy() ParticipationFlagsList {
|
||||
c := make(ParticipationFlagsList, len(p))
|
||||
copy(c, p)
|
||||
return c
|
||||
}
|
||||
|
||||
func ParticipationFlagsListFromBytes(buf []byte) ParticipationFlagsList {
|
||||
flagsList := make([]ParticipationFlags, len(buf))
|
||||
for i := range flagsList {
|
||||
|
@ -20,6 +20,7 @@ func forkTest(context testContext) error {
|
||||
return err
|
||||
}
|
||||
|
||||
preState.StartCollectingReverseChangeSet()
|
||||
if preState.Version() == clparams.Phase0Version {
|
||||
if err := preState.UpgradeToAltair(); err != nil {
|
||||
return err
|
||||
@ -33,6 +34,8 @@ func forkTest(context testContext) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
change := preState.StopCollectingReverseChangeSet()
|
||||
|
||||
if expectedError {
|
||||
return fmt.Errorf("expected error")
|
||||
}
|
||||
@ -47,5 +50,25 @@ func forkTest(context testContext) error {
|
||||
if root != expectedRoot {
|
||||
return fmt.Errorf("mismatching state roots")
|
||||
}
|
||||
if context.version == clparams.AltairVersion {
|
||||
return nil
|
||||
}
|
||||
// now do unwind
|
||||
initialState, err := decodeStateFromFile(prevContext, "pre.ssz_snappy")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
preState.RevertWithChangeset(change)
|
||||
root, err = preState.HashSSZ()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
expectedRoot, err = initialState.HashSSZ()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if root != expectedRoot {
|
||||
return fmt.Errorf("mismatching state roots with unwind")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -4,7 +4,9 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/ledgerwatch/erigon/cl/clparams"
|
||||
"github.com/ledgerwatch/erigon/cl/cltypes"
|
||||
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/beacon_changeset"
|
||||
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/transition"
|
||||
)
|
||||
|
||||
@ -28,12 +30,16 @@ func testSanityFunction(context testContext) error {
|
||||
return err
|
||||
}
|
||||
startSlot := testState.Slot()
|
||||
|
||||
changes := []*beacon_changeset.ReverseBeaconStateChangeSet{}
|
||||
var block *cltypes.SignedBeaconBlock
|
||||
for _, block = range blocks {
|
||||
testState.StartCollectingReverseChangeSet()
|
||||
err = transition.TransitionState(testState, block, true)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
changes = append(changes, testState.StopCollectingReverseChangeSet())
|
||||
}
|
||||
// Deal with transition error
|
||||
if expectedError && err == nil {
|
||||
@ -45,7 +51,7 @@ func testSanityFunction(context testContext) error {
|
||||
}
|
||||
return fmt.Errorf("cannot transition state: %s. slot=%d. start_slot=%d", err, block.Block.Slot, startSlot)
|
||||
}
|
||||
expectedRoot, err := expectedState.HashSSZ()
|
||||
finalRoot, err := expectedState.HashSSZ()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -53,9 +59,47 @@ func testSanityFunction(context testContext) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if haveRoot != expectedRoot {
|
||||
if haveRoot != finalRoot {
|
||||
return fmt.Errorf("mismatching state roots")
|
||||
}
|
||||
if context.version == clparams.Phase0Version {
|
||||
return nil
|
||||
}
|
||||
// Now do the unwind
|
||||
initialState, err := decodeStateFromFile(context, "pre.ssz_snappy")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_ = initialState
|
||||
for i := len(changes) - 1; i >= 0; i-- {
|
||||
testState.RevertWithChangeset(changes[i])
|
||||
}
|
||||
|
||||
expectedRoot, err := initialState.HashSSZ()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
haveRoot, err = testState.HashSSZ()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if haveRoot != expectedRoot {
|
||||
return fmt.Errorf("mismatching state roots with unwind")
|
||||
}
|
||||
// Execute them back (ensure cache is good.)
|
||||
for _, block = range blocks {
|
||||
testState.StartCollectingReverseChangeSet()
|
||||
err = transition.TransitionState(testState, block, true)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
changes = append(changes, testState.StopCollectingReverseChangeSet())
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
146
cmd/erigon-cl/core/beacon_changeset/list_changeset.go
Normal file
146
cmd/erigon-cl/core/beacon_changeset/list_changeset.go
Normal file
@ -0,0 +1,146 @@
|
||||
package beacon_changeset
|
||||
|
||||
import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
type ListChangeSet[T any] struct {
|
||||
list []*listElementChangeset[T]
|
||||
listLength int
|
||||
nextId int
|
||||
compact bool
|
||||
}
|
||||
|
||||
type listElementChangeset[T any] struct {
|
||||
value T
|
||||
listIndex int
|
||||
id int
|
||||
}
|
||||
|
||||
// NewListChangeSet creates new list with given length.
|
||||
func NewListChangeSet[T any](length int) *ListChangeSet[T] {
|
||||
return &ListChangeSet[T]{listLength: length}
|
||||
}
|
||||
|
||||
// AddChange appens to a new change to the changeset of the list.
|
||||
func (l *ListChangeSet[T]) AddChange(index int, elem T) {
|
||||
l.compact = false
|
||||
l.list = append(l.list, &listElementChangeset[T]{
|
||||
value: elem,
|
||||
listIndex: index,
|
||||
id: l.nextId,
|
||||
})
|
||||
l.nextId++
|
||||
}
|
||||
|
||||
// CompactChanges removes duplicates from a list using QuickSort and linear scan.
|
||||
// duplicates may appear if one state parameter is changed more than once.
|
||||
func (l *ListChangeSet[T]) CompactChanges() {
|
||||
if l.compact {
|
||||
return
|
||||
}
|
||||
l.compact = true
|
||||
// Check if there are any duplicates to remove.
|
||||
if len(l.list) < 2 {
|
||||
return
|
||||
}
|
||||
|
||||
// Sort the list using QuickSort.
|
||||
sort.Slice(l.list, func(i, j int) bool {
|
||||
if l.list[i].listIndex == l.list[j].listIndex {
|
||||
return l.list[i].id < l.list[j].id
|
||||
}
|
||||
return l.list[i].listIndex < l.list[j].listIndex
|
||||
})
|
||||
|
||||
// Create a new list buffer for the compacted list.
|
||||
compactList := []*listElementChangeset[T]{}
|
||||
|
||||
// Do a linear scan through the sorted list and remove duplicates.
|
||||
previousIndexElement := l.list[0]
|
||||
for _, listElement := range l.list {
|
||||
if listElement.listIndex != previousIndexElement.listIndex {
|
||||
compactList = append(compactList, previousIndexElement)
|
||||
}
|
||||
previousIndexElement = listElement
|
||||
}
|
||||
compactList = append(compactList, previousIndexElement)
|
||||
|
||||
// Update the original list with the compacted list.
|
||||
l.list = compactList
|
||||
}
|
||||
|
||||
// CompactChangesReverse removes duplicates from a list using QuickSort and linear scan.
|
||||
// duplicates may appear if one state parameter is changed more than once.
|
||||
// Difference with CompactChanges is that the sorting is reversed.
|
||||
func (l *ListChangeSet[T]) CompactChangesReverse() {
|
||||
if l.compact {
|
||||
return
|
||||
}
|
||||
l.compact = true
|
||||
// Check if there are any duplicates to remove.
|
||||
if len(l.list) < 2 {
|
||||
return
|
||||
}
|
||||
|
||||
// Sort the list using QuickSort.
|
||||
sort.Slice(l.list, func(i, j int) bool {
|
||||
if l.list[i].listIndex == l.list[j].listIndex {
|
||||
return l.list[i].id > l.list[j].id
|
||||
}
|
||||
return l.list[i].listIndex < l.list[j].listIndex
|
||||
})
|
||||
|
||||
// Create a new list buffer for the compacted list.
|
||||
compactList := []*listElementChangeset[T]{}
|
||||
|
||||
// Do a linear scan through the sorted list and remove duplicates.
|
||||
previousIndexElement := l.list[0]
|
||||
for _, listElement := range l.list {
|
||||
if listElement.listIndex != previousIndexElement.listIndex {
|
||||
compactList = append(compactList, previousIndexElement)
|
||||
}
|
||||
previousIndexElement = listElement
|
||||
}
|
||||
compactList = append(compactList, previousIndexElement)
|
||||
// Update the original list with the compacted list.
|
||||
l.list = compactList
|
||||
}
|
||||
|
||||
// ApplyChanges Apply changes without any mercy. if it is reverse, you need to call CompactChangesReverse before.
|
||||
func (l *ListChangeSet[T]) ApplyChanges(input []T) (output []T, changed bool) {
|
||||
if len(l.list) == 0 && l.listLength == len(input) {
|
||||
output = input
|
||||
return
|
||||
}
|
||||
changed = true
|
||||
// Re-adjust list size.
|
||||
output = make([]T, l.listLength)
|
||||
copy(output, input)
|
||||
// Now apply changes to the given list
|
||||
for _, elem := range l.list {
|
||||
if elem.listIndex >= len(output) {
|
||||
continue
|
||||
}
|
||||
output[elem.listIndex] = elem.value
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ChangesWithHandler uses custom handler to handle changes.
|
||||
func (l *ListChangeSet[T]) ChangesWithHandler(fn func(value T, index int)) {
|
||||
// Now apply changes to the given list
|
||||
for _, elem := range l.list {
|
||||
fn(elem.value, elem.listIndex)
|
||||
}
|
||||
}
|
||||
|
||||
// ListLength return full list length
|
||||
func (l *ListChangeSet[T]) ListLength() int {
|
||||
return l.listLength
|
||||
}
|
||||
|
||||
// Empty return whether current list diff is empty
|
||||
func (l *ListChangeSet[T]) Empty() bool {
|
||||
return len(l.list) == 0
|
||||
}
|
45
cmd/erigon-cl/core/beacon_changeset/list_changeset_test.go
Normal file
45
cmd/erigon-cl/core/beacon_changeset/list_changeset_test.go
Normal file
@ -0,0 +1,45 @@
|
||||
package beacon_changeset
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestListChangeset(t *testing.T) {
|
||||
pre := []int{6, 8, 9}
|
||||
changeset := NewListChangeSet[int](3)
|
||||
changeset.AddChange(1, 45)
|
||||
changeset.AddChange(1, 1)
|
||||
changeset.AddChange(2, 45)
|
||||
changeset.CompactChanges()
|
||||
require.Equal(t, len(changeset.list), 2)
|
||||
post, changed := changeset.ApplyChanges(pre)
|
||||
require.Equal(t, post, []int{6, 1, 45})
|
||||
require.Equal(t, changed, true)
|
||||
}
|
||||
|
||||
func TestListChangesetWithReverse(t *testing.T) {
|
||||
pre := []int{6, 8, 9}
|
||||
changeset := NewListChangeSet[int](3)
|
||||
changeset.AddChange(1, 45)
|
||||
changeset.AddChange(1, 1)
|
||||
changeset.AddChange(2, 45)
|
||||
changeset.CompactChangesReverse()
|
||||
require.Equal(t, len(changeset.list), 2)
|
||||
post, changed := changeset.ApplyChanges(pre)
|
||||
require.Equal(t, post, []int{6, 45, 45})
|
||||
require.Equal(t, changed, true)
|
||||
}
|
||||
|
||||
func TestListChangesetWithoutCompact(t *testing.T) {
|
||||
pre := []int{6, 8, 9}
|
||||
changeset := NewListChangeSet[int](3)
|
||||
changeset.AddChange(1, 45)
|
||||
changeset.AddChange(1, 1)
|
||||
changeset.AddChange(2, 45)
|
||||
require.Equal(t, len(changeset.list), 3)
|
||||
post, changed := changeset.ApplyChanges(pre)
|
||||
require.Equal(t, post, []int{6, 1, 45})
|
||||
require.Equal(t, changed, true)
|
||||
}
|
@ -0,0 +1,241 @@
|
||||
package beacon_changeset
|
||||
|
||||
import (
|
||||
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
||||
"github.com/ledgerwatch/erigon/cl/clparams"
|
||||
"github.com/ledgerwatch/erigon/cl/cltypes"
|
||||
)
|
||||
|
||||
// This type of changeset is the diff beetwen next state and input state and is used to reverse beacon state.
|
||||
// It does not work the other way around. So they apply [curr state] + [reverse change set] = [prev state]
|
||||
type ReverseBeaconStateChangeSet struct {
|
||||
// Single types.
|
||||
SlotChange *uint64
|
||||
ForkChange *cltypes.Fork
|
||||
LatestBlockHeaderChange *cltypes.BeaconBlockHeader
|
||||
Eth1DataChange *cltypes.Eth1Data
|
||||
Eth1DepositIndexChange *uint64
|
||||
JustificationBitsChange *cltypes.JustificationBits
|
||||
PreviousJustifiedCheckpointChange *cltypes.Checkpoint
|
||||
CurrentJustifiedCheckpointChange *cltypes.Checkpoint
|
||||
FinalizedCheckpointChange *cltypes.Checkpoint
|
||||
CurrentSyncCommitteeChange *cltypes.SyncCommittee
|
||||
NextSyncCommitteeChange *cltypes.SyncCommittee
|
||||
LatestExecutionPayloadHeaderChange *cltypes.Eth1Header
|
||||
NextWithdrawalIndexChange *uint64
|
||||
NextWithdrawalValidatorIndexChange *uint64
|
||||
VersionChange *clparams.StateVersion
|
||||
// Lists and arrays changesets
|
||||
BlockRootsChanges *ListChangeSet[libcommon.Hash]
|
||||
StateRootsChanges *ListChangeSet[libcommon.Hash]
|
||||
HistoricalRootsChanges *ListChangeSet[libcommon.Hash]
|
||||
Eth1DataVotesChanges *ListChangeSet[cltypes.Eth1Data]
|
||||
BalancesChanges *ListChangeSet[uint64]
|
||||
RandaoMixesChanges *ListChangeSet[libcommon.Hash]
|
||||
SlashingsChanges *ListChangeSet[uint64]
|
||||
PreviousEpochParticipationChanges *ListChangeSet[cltypes.ParticipationFlags]
|
||||
CurrentEpochParticipationChanges *ListChangeSet[cltypes.ParticipationFlags]
|
||||
InactivityScoresChanges *ListChangeSet[uint64]
|
||||
HistoricalSummaryChange *ListChangeSet[cltypes.HistoricalSummary]
|
||||
// Validator fields.
|
||||
WithdrawalCredentialsChange *ListChangeSet[libcommon.Hash]
|
||||
EffectiveBalanceChange *ListChangeSet[uint64]
|
||||
SlashedChange *ListChangeSet[bool]
|
||||
ActivationEligibilityEpochChange *ListChangeSet[uint64]
|
||||
ActivationEpochChange *ListChangeSet[uint64]
|
||||
ExitEpochChange *ListChangeSet[uint64]
|
||||
WithdrawalEpochChange *ListChangeSet[uint64]
|
||||
// Efficient unwinding on reset (only applicable at epoch boundaries)
|
||||
PreviousEpochParticipationAtReset cltypes.ParticipationFlagsList
|
||||
CurrentEpochParticipationAtReset cltypes.ParticipationFlagsList
|
||||
Eth1DataVotesAtReset []*cltypes.Eth1Data
|
||||
}
|
||||
|
||||
func (r *ReverseBeaconStateChangeSet) OnSlotChange(prevSlot uint64) {
|
||||
if r.SlotChange != nil {
|
||||
return
|
||||
}
|
||||
r.SlotChange = new(uint64)
|
||||
*r.SlotChange = prevSlot
|
||||
}
|
||||
|
||||
func (r *ReverseBeaconStateChangeSet) OnForkChange(fork *cltypes.Fork) {
|
||||
if r.ForkChange != nil {
|
||||
return
|
||||
}
|
||||
r.ForkChange = new(cltypes.Fork)
|
||||
*r.ForkChange = *fork
|
||||
}
|
||||
|
||||
func (r *ReverseBeaconStateChangeSet) OnLatestHeaderChange(h *cltypes.BeaconBlockHeader) {
|
||||
if r.LatestBlockHeaderChange != nil {
|
||||
return
|
||||
}
|
||||
r.LatestBlockHeaderChange = new(cltypes.BeaconBlockHeader)
|
||||
*r.LatestBlockHeaderChange = *h
|
||||
}
|
||||
|
||||
func (r *ReverseBeaconStateChangeSet) OnEth1DataChange(e *cltypes.Eth1Data) {
|
||||
if r.LatestBlockHeaderChange != nil {
|
||||
return
|
||||
}
|
||||
r.Eth1DataChange = new(cltypes.Eth1Data)
|
||||
*r.Eth1DataChange = *e
|
||||
}
|
||||
|
||||
func (r *ReverseBeaconStateChangeSet) OnJustificationBitsChange(j cltypes.JustificationBits) {
|
||||
if r.JustificationBitsChange != nil {
|
||||
return
|
||||
}
|
||||
r.JustificationBitsChange = new(cltypes.JustificationBits)
|
||||
*r.JustificationBitsChange = j.Copy()
|
||||
}
|
||||
|
||||
func (r *ReverseBeaconStateChangeSet) OnEth1DepositIndexChange(e uint64) {
|
||||
if r.Eth1DepositIndexChange != nil {
|
||||
return
|
||||
}
|
||||
r.Eth1DepositIndexChange = new(uint64)
|
||||
*r.Eth1DepositIndexChange = e
|
||||
}
|
||||
|
||||
func (r *ReverseBeaconStateChangeSet) OnPreviousJustifiedCheckpointChange(c *cltypes.Checkpoint) {
|
||||
if r.PreviousJustifiedCheckpointChange != nil {
|
||||
return
|
||||
}
|
||||
r.PreviousJustifiedCheckpointChange = new(cltypes.Checkpoint)
|
||||
*r.PreviousJustifiedCheckpointChange = *c
|
||||
}
|
||||
|
||||
func (r *ReverseBeaconStateChangeSet) OnCurrentJustifiedCheckpointChange(c *cltypes.Checkpoint) {
|
||||
if r.CurrentJustifiedCheckpointChange != nil {
|
||||
return
|
||||
}
|
||||
r.CurrentJustifiedCheckpointChange = new(cltypes.Checkpoint)
|
||||
*r.CurrentJustifiedCheckpointChange = *c
|
||||
}
|
||||
|
||||
func (r *ReverseBeaconStateChangeSet) OnFinalizedCheckpointChange(c *cltypes.Checkpoint) {
|
||||
if r.FinalizedCheckpointChange != nil {
|
||||
return
|
||||
}
|
||||
r.FinalizedCheckpointChange = new(cltypes.Checkpoint)
|
||||
*r.FinalizedCheckpointChange = *c
|
||||
}
|
||||
|
||||
func (r *ReverseBeaconStateChangeSet) OnCurrentSyncCommitteeChange(c *cltypes.SyncCommittee) {
|
||||
if r.CurrentSyncCommitteeChange != nil {
|
||||
return
|
||||
}
|
||||
r.CurrentSyncCommitteeChange = new(cltypes.SyncCommittee)
|
||||
*r.CurrentSyncCommitteeChange = *c
|
||||
}
|
||||
|
||||
func (r *ReverseBeaconStateChangeSet) OnNextSyncCommitteeChange(c *cltypes.SyncCommittee) {
|
||||
if r.NextSyncCommitteeChange != nil {
|
||||
return
|
||||
}
|
||||
r.NextSyncCommitteeChange = new(cltypes.SyncCommittee)
|
||||
*r.NextSyncCommitteeChange = *c
|
||||
}
|
||||
|
||||
func (r *ReverseBeaconStateChangeSet) OnEth1Header(e *cltypes.Eth1Header) {
|
||||
if r.LatestExecutionPayloadHeaderChange != nil {
|
||||
return
|
||||
}
|
||||
r.LatestExecutionPayloadHeaderChange = new(cltypes.Eth1Header)
|
||||
*r.LatestExecutionPayloadHeaderChange = *e
|
||||
}
|
||||
|
||||
func (r *ReverseBeaconStateChangeSet) OnNextWithdrawalIndexChange(index uint64) {
|
||||
if r.NextWithdrawalIndexChange != nil {
|
||||
return
|
||||
}
|
||||
r.NextWithdrawalIndexChange = new(uint64)
|
||||
*r.NextWithdrawalIndexChange = index
|
||||
}
|
||||
|
||||
func (r *ReverseBeaconStateChangeSet) OnNextWithdrawalValidatorIndexChange(index uint64) {
|
||||
if r.NextWithdrawalValidatorIndexChange != nil {
|
||||
return
|
||||
}
|
||||
r.NextWithdrawalValidatorIndexChange = new(uint64)
|
||||
*r.NextWithdrawalValidatorIndexChange = index
|
||||
}
|
||||
|
||||
func (r *ReverseBeaconStateChangeSet) OnVersionChange(v clparams.StateVersion) {
|
||||
if r.VersionChange != nil {
|
||||
return
|
||||
}
|
||||
r.VersionChange = new(clparams.StateVersion)
|
||||
*r.VersionChange = v
|
||||
}
|
||||
|
||||
func (r *ReverseBeaconStateChangeSet) HasValidatorSetNotChanged(validatorSetLength int) bool {
|
||||
return validatorSetLength == r.WithdrawalCredentialsChange.ListLength() && r.WithdrawalCredentialsChange.Empty() && r.ActivationEligibilityEpochChange.Empty() && r.ActivationEpochChange.Empty() &&
|
||||
r.EffectiveBalanceChange.Empty() && r.SlashedChange.Empty() && r.ExitEpochChange.Empty() && r.WithdrawalEpochChange.Empty()
|
||||
}
|
||||
|
||||
func (r *ReverseBeaconStateChangeSet) ApplyEth1DataVotesChanges(input []*cltypes.Eth1Data) (output []*cltypes.Eth1Data, changed bool) {
|
||||
output = input
|
||||
if r.Eth1DataVotesChanges.Empty() && r.Eth1DataVotesChanges.ListLength() == len(output) {
|
||||
return
|
||||
}
|
||||
changed = true
|
||||
if r.Eth1DataVotesChanges.ListLength() != len(output) {
|
||||
output = make([]*cltypes.Eth1Data, r.Eth1DataVotesChanges.ListLength())
|
||||
copy(output, input)
|
||||
}
|
||||
r.Eth1DataVotesChanges.ChangesWithHandler(func(value cltypes.Eth1Data, index int) {
|
||||
*output[index] = value
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (r *ReverseBeaconStateChangeSet) ApplyHistoricalSummaryChanges(input []*cltypes.HistoricalSummary) (output []*cltypes.HistoricalSummary, changed bool) {
|
||||
output = input
|
||||
if r.HistoricalSummaryChange.Empty() && r.Eth1DataVotesChanges.ListLength() == len(output) {
|
||||
return
|
||||
}
|
||||
changed = true
|
||||
historicalSummarryLength := r.HistoricalSummaryChange.ListLength()
|
||||
if historicalSummarryLength != len(output) {
|
||||
output = make([]*cltypes.HistoricalSummary, historicalSummarryLength)
|
||||
copy(output, input)
|
||||
}
|
||||
r.HistoricalSummaryChange.ChangesWithHandler(func(value cltypes.HistoricalSummary, index int) {
|
||||
*output[index] = value
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (r *ReverseBeaconStateChangeSet) CompactChanges() {
|
||||
|
||||
r.BlockRootsChanges.CompactChangesReverse()
|
||||
r.StateRootsChanges.CompactChangesReverse()
|
||||
r.HistoricalRootsChanges.CompactChangesReverse()
|
||||
r.SlashingsChanges.CompactChangesReverse()
|
||||
r.RandaoMixesChanges.CompactChangesReverse()
|
||||
r.BalancesChanges.CompactChangesReverse()
|
||||
if len(r.Eth1DataVotesAtReset) > 0 {
|
||||
r.Eth1DataVotesChanges = nil
|
||||
} else {
|
||||
r.Eth1DataVotesChanges.CompactChangesReverse()
|
||||
}
|
||||
if len(r.PreviousEpochParticipationAtReset) > 0 {
|
||||
r.PreviousEpochParticipationChanges = nil
|
||||
r.CurrentEpochParticipationChanges = nil
|
||||
} else {
|
||||
r.PreviousEpochParticipationChanges.CompactChangesReverse()
|
||||
r.CurrentEpochParticipationChanges.CompactChangesReverse()
|
||||
}
|
||||
r.InactivityScoresChanges.CompactChangesReverse()
|
||||
r.HistoricalRootsChanges.CompactChangesReverse()
|
||||
r.WithdrawalCredentialsChange.CompactChangesReverse()
|
||||
r.EffectiveBalanceChange.CompactChangesReverse()
|
||||
r.ExitEpochChange.CompactChangesReverse()
|
||||
r.ActivationEligibilityEpochChange.CompactChangesReverse()
|
||||
r.ActivationEpochChange.CompactChangesReverse()
|
||||
r.SlashedChange.CompactChangesReverse()
|
||||
r.WithdrawalEpochChange.CompactChangesReverse()
|
||||
}
|
@ -70,7 +70,7 @@ func (b *BeaconState) GetUnslashedParticipatingIndices(flagIndex int, epoch uint
|
||||
return nil, fmt.Errorf("getUnslashedParticipatingIndices: only epoch and previous epoch can be used")
|
||||
}
|
||||
// Iterate over all validators and include the active ones that have flag_index enabled and are not slashed.
|
||||
for i, validator := range b.Validators() {
|
||||
for i, validator := range b.validators {
|
||||
if !validator.Active(epoch) ||
|
||||
!participation[i].HasFlag(flagIndex) ||
|
||||
validator.Slashed {
|
||||
@ -228,7 +228,7 @@ func (b *BeaconState) ComputeProposerIndex(indices []uint64, seed [32]byte) (uin
|
||||
input := append(seed[:], buf...)
|
||||
randomByte := uint64(utils.Keccak256(input)[i%32])
|
||||
|
||||
validator, err := b.ValidatorAt(int(candidateIndex))
|
||||
validator, err := b.ValidatorForValidatorIndex(int(candidateIndex))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -565,7 +565,7 @@ func (b *BeaconState) ComputeNextSyncCommittee() (*cltypes.SyncCommittee, error)
|
||||
input := append(seed[:], buf...)
|
||||
randomByte := uint64(utils.Keccak256(input)[i%32])
|
||||
// retrieve validator.
|
||||
validator, err := b.ValidatorAt(int(candidateIndex))
|
||||
validator, err := b.ValidatorForValidatorIndex(int(candidateIndex))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -33,33 +33,6 @@ func getTestState(t *testing.T) *state.BeaconState {
|
||||
return b
|
||||
}
|
||||
|
||||
func TestActiveValidatorIndices(t *testing.T) {
|
||||
epoch := uint64(2)
|
||||
testState := state.GetEmptyBeaconState()
|
||||
// Not Active validator
|
||||
testState.AddValidator(&cltypes.Validator{
|
||||
ActivationEpoch: 3,
|
||||
ExitEpoch: 9,
|
||||
EffectiveBalance: 2e9,
|
||||
}, 2e9)
|
||||
// Active Validator
|
||||
testState.AddValidator(&cltypes.Validator{
|
||||
ActivationEpoch: 1,
|
||||
ExitEpoch: 9,
|
||||
EffectiveBalance: 2e9,
|
||||
}, 2e9)
|
||||
testState.SetSlot(epoch * 32) // Epoch
|
||||
testFlags := cltypes.ParticipationFlagsListFromBytes([]byte{1, 1})
|
||||
testState.SetCurrentEpochParticipation(testFlags)
|
||||
// Only validator at index 1 (second validator) is active.
|
||||
require.Equal(t, testState.GetActiveValidatorsIndices(epoch), []uint64{1})
|
||||
set, err := testState.GetUnslashedParticipatingIndices(0x00, epoch)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, set, []uint64{1})
|
||||
// Check if balances are retrieved correctly
|
||||
require.Equal(t, testState.GetTotalActiveBalance(), uint64(2e9))
|
||||
}
|
||||
|
||||
func TestGetBlockRoot(t *testing.T) {
|
||||
epoch := uint64(2)
|
||||
testState := state.GetEmptyBeaconState()
|
||||
|
260
cmd/erigon-cl/core/state/changeset.go
Normal file
260
cmd/erigon-cl/core/state/changeset.go
Normal file
@ -0,0 +1,260 @@
|
||||
package state
|
||||
|
||||
import (
|
||||
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
||||
"github.com/ledgerwatch/erigon/cl/clparams"
|
||||
"github.com/ledgerwatch/erigon/cl/cltypes"
|
||||
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/beacon_changeset"
|
||||
)
|
||||
|
||||
// StartCollectingReverseChangeSet starts collection change sets.
|
||||
func (b *BeaconState) StartCollectingReverseChangeSet() {
|
||||
b.reverseChangeset = &beacon_changeset.ReverseBeaconStateChangeSet{
|
||||
BlockRootsChanges: beacon_changeset.NewListChangeSet[libcommon.Hash](len(b.blockRoots)),
|
||||
StateRootsChanges: beacon_changeset.NewListChangeSet[libcommon.Hash](len(b.stateRoots)),
|
||||
HistoricalRootsChanges: beacon_changeset.NewListChangeSet[libcommon.Hash](len(b.historicalRoots)),
|
||||
Eth1DataVotesChanges: beacon_changeset.NewListChangeSet[cltypes.Eth1Data](len(b.eth1DataVotes)),
|
||||
BalancesChanges: beacon_changeset.NewListChangeSet[uint64](len(b.balances)),
|
||||
RandaoMixesChanges: beacon_changeset.NewListChangeSet[libcommon.Hash](len(b.randaoMixes)),
|
||||
SlashingsChanges: beacon_changeset.NewListChangeSet[uint64](len(b.slashings)),
|
||||
PreviousEpochParticipationChanges: beacon_changeset.NewListChangeSet[cltypes.ParticipationFlags](len(b.previousEpochParticipation)),
|
||||
CurrentEpochParticipationChanges: beacon_changeset.NewListChangeSet[cltypes.ParticipationFlags](len(b.currentEpochParticipation)),
|
||||
InactivityScoresChanges: beacon_changeset.NewListChangeSet[uint64](len(b.inactivityScores)),
|
||||
HistoricalSummaryChange: beacon_changeset.NewListChangeSet[cltypes.HistoricalSummary](len(b.historicalSummaries)),
|
||||
// Validators section
|
||||
WithdrawalCredentialsChange: beacon_changeset.NewListChangeSet[libcommon.Hash](len(b.validators)),
|
||||
EffectiveBalanceChange: beacon_changeset.NewListChangeSet[uint64](len(b.validators)),
|
||||
ActivationEligibilityEpochChange: beacon_changeset.NewListChangeSet[uint64](len(b.validators)),
|
||||
ActivationEpochChange: beacon_changeset.NewListChangeSet[uint64](len(b.validators)),
|
||||
ExitEpochChange: beacon_changeset.NewListChangeSet[uint64](len(b.validators)),
|
||||
WithdrawalEpochChange: beacon_changeset.NewListChangeSet[uint64](len(b.validators)),
|
||||
SlashedChange: beacon_changeset.NewListChangeSet[bool](len(b.validators)),
|
||||
}
|
||||
}
|
||||
|
||||
// StopCollectingReverseChangeSet stops collection change sets.
|
||||
func (b *BeaconState) StopCollectingReverseChangeSet() *beacon_changeset.ReverseBeaconStateChangeSet {
|
||||
ret := b.reverseChangeset
|
||||
b.reverseChangeset = nil
|
||||
return ret
|
||||
}
|
||||
|
||||
func (b *BeaconState) RevertWithChangeset(changeset *beacon_changeset.ReverseBeaconStateChangeSet) {
|
||||
changeset.CompactChanges()
|
||||
beforeSlot := b.slot
|
||||
var touched bool
|
||||
// Updates all single types accordingly.
|
||||
if changeset.SlotChange != nil {
|
||||
b.slot = *changeset.SlotChange
|
||||
b.touchedLeaves[SlotLeafIndex] = true
|
||||
}
|
||||
if changeset.ForkChange != nil {
|
||||
b.fork = changeset.ForkChange
|
||||
b.touchedLeaves[ForkLeafIndex] = true
|
||||
}
|
||||
if changeset.LatestBlockHeaderChange != nil {
|
||||
b.latestBlockHeader = changeset.LatestBlockHeaderChange
|
||||
b.touchedLeaves[LatestBlockHeaderLeafIndex] = true
|
||||
}
|
||||
if changeset.Eth1DataChange != nil {
|
||||
b.eth1Data = changeset.Eth1DataChange
|
||||
b.touchedLeaves[Eth1DataLeafIndex] = true
|
||||
}
|
||||
if changeset.Eth1DepositIndexChange != nil {
|
||||
b.eth1DepositIndex = *changeset.Eth1DepositIndexChange
|
||||
b.touchedLeaves[Eth1DepositIndexLeafIndex] = true
|
||||
}
|
||||
if changeset.JustificationBitsChange != nil {
|
||||
b.justificationBits = *changeset.JustificationBitsChange
|
||||
b.touchedLeaves[JustificationBitsLeafIndex] = true
|
||||
}
|
||||
if changeset.PreviousJustifiedCheckpointChange != nil {
|
||||
b.previousJustifiedCheckpoint = changeset.PreviousJustifiedCheckpointChange
|
||||
b.touchedLeaves[PreviousJustifiedCheckpointLeafIndex] = true
|
||||
}
|
||||
if changeset.CurrentJustifiedCheckpointChange != nil {
|
||||
b.currentJustifiedCheckpoint = changeset.CurrentJustifiedCheckpointChange
|
||||
b.touchedLeaves[CurrentJustifiedCheckpointLeafIndex] = true
|
||||
}
|
||||
if changeset.FinalizedCheckpointChange != nil {
|
||||
b.finalizedCheckpoint = changeset.FinalizedCheckpointChange
|
||||
b.touchedLeaves[FinalizedCheckpointLeafIndex] = true
|
||||
}
|
||||
if changeset.CurrentSyncCommitteeChange != nil {
|
||||
b.currentSyncCommittee = changeset.CurrentSyncCommitteeChange
|
||||
b.touchedLeaves[CurrentSyncCommitteeLeafIndex] = true
|
||||
}
|
||||
if changeset.NextSyncCommitteeChange != nil {
|
||||
b.nextSyncCommittee = changeset.NextSyncCommitteeChange
|
||||
b.touchedLeaves[NextSyncCommitteeLeafIndex] = true
|
||||
}
|
||||
if changeset.LatestExecutionPayloadHeaderChange != nil {
|
||||
b.latestExecutionPayloadHeader = changeset.LatestExecutionPayloadHeaderChange
|
||||
b.touchedLeaves[LatestExecutionPayloadHeaderLeafIndex] = true
|
||||
}
|
||||
if changeset.NextWithdrawalIndexChange != nil {
|
||||
b.nextWithdrawalIndex = *changeset.NextWithdrawalIndexChange
|
||||
b.touchedLeaves[NextWithdrawalIndexLeafIndex] = true
|
||||
}
|
||||
if changeset.NextWithdrawalValidatorIndexChange != nil {
|
||||
b.nextWithdrawalValidatorIndex = *changeset.NextWithdrawalValidatorIndexChange
|
||||
b.touchedLeaves[NextWithdrawalValidatorIndexLeafIndex] = true
|
||||
}
|
||||
if changeset.VersionChange != nil {
|
||||
b.version = *changeset.VersionChange
|
||||
if b.version == clparams.AltairVersion {
|
||||
b.leaves[LatestExecutionPayloadHeaderLeafIndex] = libcommon.Hash{}
|
||||
b.touchedLeaves[LatestExecutionPayloadHeaderLeafIndex] = false
|
||||
}
|
||||
if b.version == clparams.BellatrixVersion {
|
||||
b.leaves[NextWithdrawalIndexLeafIndex] = libcommon.Hash{}
|
||||
b.leaves[NextWithdrawalValidatorIndexLeafIndex] = libcommon.Hash{}
|
||||
b.leaves[HistoricalSummariesLeafIndex] = libcommon.Hash{}
|
||||
b.touchedLeaves[NextWithdrawalIndexLeafIndex] = false
|
||||
b.touchedLeaves[NextWithdrawalValidatorIndexLeafIndex] = false
|
||||
b.touchedLeaves[HistoricalSummariesLeafIndex] = false
|
||||
}
|
||||
}
|
||||
// Process all the lists now.
|
||||
// Start with arrays first
|
||||
changeset.BlockRootsChanges.ChangesWithHandler(func(value libcommon.Hash, index int) {
|
||||
b.blockRoots[index] = value
|
||||
b.touchedLeaves[BlockRootsLeafIndex] = true
|
||||
})
|
||||
changeset.StateRootsChanges.ChangesWithHandler(func(value libcommon.Hash, index int) {
|
||||
b.stateRoots[index] = value
|
||||
b.touchedLeaves[StateRootsLeafIndex] = true
|
||||
})
|
||||
changeset.RandaoMixesChanges.ChangesWithHandler(func(value libcommon.Hash, index int) {
|
||||
b.randaoMixes[index] = value
|
||||
b.touchedLeaves[RandaoMixesLeafIndex] = true
|
||||
})
|
||||
changeset.SlashingsChanges.ChangesWithHandler(func(value uint64, index int) {
|
||||
b.slashings[index] = value
|
||||
b.touchedLeaves[SlashingsLeafIndex] = true
|
||||
})
|
||||
// Process the lists now.
|
||||
b.historicalRoots, touched = changeset.HistoricalRootsChanges.ApplyChanges(b.historicalRoots)
|
||||
if touched {
|
||||
b.touchedLeaves[HistoricalRootsLeafIndex] = true
|
||||
}
|
||||
// This is a special case, as reset will lead to complete change of votes
|
||||
if len(changeset.Eth1DataVotesAtReset) == 0 {
|
||||
b.eth1DataVotes, touched = changeset.ApplyEth1DataVotesChanges(b.eth1DataVotes)
|
||||
if touched {
|
||||
b.touchedLeaves[Eth1DataVotesLeafIndex] = true
|
||||
}
|
||||
} else {
|
||||
b.eth1DataVotes = changeset.Eth1DataVotesAtReset
|
||||
b.touchedLeaves[Eth1DataVotesLeafIndex] = true
|
||||
}
|
||||
b.balances, touched = changeset.BalancesChanges.ApplyChanges(b.balances)
|
||||
if touched {
|
||||
b.touchedLeaves[BalancesLeafIndex] = true
|
||||
}
|
||||
// This also a special case, as this is another victim of reset, we use rotation with curr and prev to handle it efficiently
|
||||
if len(changeset.PreviousEpochParticipationAtReset) == 0 && len(changeset.CurrentEpochParticipationAtReset) == 0 {
|
||||
b.previousEpochParticipation, touched = changeset.PreviousEpochParticipationChanges.ApplyChanges(b.previousEpochParticipation)
|
||||
if touched {
|
||||
b.touchedLeaves[PreviousEpochParticipationLeafIndex] = true
|
||||
}
|
||||
b.currentEpochParticipation, touched = changeset.CurrentEpochParticipationChanges.ApplyChanges(b.currentEpochParticipation)
|
||||
if touched {
|
||||
b.touchedLeaves[CurrentEpochParticipationLeafIndex] = true
|
||||
}
|
||||
} else {
|
||||
b.touchedLeaves[PreviousEpochParticipationLeafIndex] = true
|
||||
b.touchedLeaves[CurrentEpochParticipationLeafIndex] = true
|
||||
b.previousEpochParticipation = changeset.PreviousEpochParticipationAtReset.Copy()
|
||||
b.currentEpochParticipation = changeset.CurrentEpochParticipationAtReset.Copy()
|
||||
}
|
||||
|
||||
b.inactivityScores, touched = changeset.InactivityScoresChanges.ApplyChanges(b.inactivityScores)
|
||||
if touched {
|
||||
b.touchedLeaves[InactivityScoresLeafIndex] = true
|
||||
}
|
||||
b.historicalSummaries, touched = changeset.ApplyHistoricalSummaryChanges(b.historicalSummaries)
|
||||
if touched {
|
||||
b.touchedLeaves[HistoricalSummariesLeafIndex] = true
|
||||
}
|
||||
// Now start processing validators if there are any.
|
||||
if changeset.HasValidatorSetNotChanged(len(b.validators)) {
|
||||
b.revertCachesOnBoundary(beforeSlot)
|
||||
return
|
||||
}
|
||||
// We do it like this because validators diff can get quite big so we only save individual fields.
|
||||
b.touchedLeaves[ValidatorsLeafIndex] = true
|
||||
newValidatorsSet := b.validators
|
||||
// All changes habe same length
|
||||
previousValidatorSetLength := changeset.WithdrawalCredentialsChange.ListLength()
|
||||
|
||||
if previousValidatorSetLength != len(b.validators) {
|
||||
for _, removedValidator := range b.validators[previousValidatorSetLength:] {
|
||||
delete(b.publicKeyIndicies, removedValidator.PublicKey)
|
||||
}
|
||||
newValidatorsSet = make([]*cltypes.Validator, previousValidatorSetLength)
|
||||
copy(newValidatorsSet, b.validators)
|
||||
}
|
||||
b.validators = newValidatorsSet
|
||||
// Now start processing all of the validator fields
|
||||
changeset.WithdrawalCredentialsChange.ChangesWithHandler(func(value libcommon.Hash, index int) {
|
||||
if index >= len(b.validators) {
|
||||
return
|
||||
}
|
||||
b.validators[index].WithdrawalCredentials = value
|
||||
})
|
||||
changeset.ExitEpochChange.ChangesWithHandler(func(value uint64, index int) {
|
||||
if index >= len(b.validators) {
|
||||
return
|
||||
}
|
||||
b.validators[index].ExitEpoch = value
|
||||
})
|
||||
changeset.ActivationEligibilityEpochChange.ChangesWithHandler(func(value uint64, index int) {
|
||||
if index >= len(b.validators) {
|
||||
return
|
||||
}
|
||||
b.validators[index].ActivationEligibilityEpoch = value
|
||||
})
|
||||
changeset.ActivationEpochChange.ChangesWithHandler(func(value uint64, index int) {
|
||||
if index >= len(b.validators) {
|
||||
return
|
||||
}
|
||||
b.validators[index].ActivationEpoch = value
|
||||
})
|
||||
changeset.SlashedChange.ChangesWithHandler(func(value bool, index int) {
|
||||
if index >= len(b.validators) {
|
||||
return
|
||||
}
|
||||
b.validators[index].Slashed = value
|
||||
})
|
||||
changeset.WithdrawalEpochChange.ChangesWithHandler(func(value uint64, index int) {
|
||||
if index >= len(b.validators) {
|
||||
return
|
||||
}
|
||||
b.validators[index].WithdrawableEpoch = value
|
||||
})
|
||||
changeset.EffectiveBalanceChange.ChangesWithHandler(func(value uint64, index int) {
|
||||
if index >= len(b.validators) {
|
||||
return
|
||||
}
|
||||
b.validators[index].EffectiveBalance = value
|
||||
})
|
||||
b.revertCachesOnBoundary(beforeSlot)
|
||||
}
|
||||
|
||||
func (b *BeaconState) revertCachesOnBoundary(beforeSlot uint64) {
|
||||
b.activeValidatorsCache.Purge()
|
||||
beforeEpoch := beforeSlot / b.beaconConfig.SlotsPerEpoch
|
||||
epoch := b.Epoch()
|
||||
b.committeeCache.Purge()
|
||||
b.previousStateRoot = libcommon.Hash{}
|
||||
b.proposerIndex = nil
|
||||
b.totalActiveBalanceCache = nil
|
||||
if epoch <= beforeEpoch {
|
||||
return
|
||||
}
|
||||
for epochToBeRemoved := beforeEpoch; epochToBeRemoved < epoch+1; beforeEpoch++ {
|
||||
b.shuffledSetsCache.Remove(b.GetSeed(epochToBeRemoved, b.beaconConfig.DomainBeaconAttester))
|
||||
b.activeValidatorsCache.Remove(epochToBeRemoved)
|
||||
}
|
||||
}
|
@ -39,8 +39,8 @@ func (b *BeaconState) Fork() *cltypes.Fork {
|
||||
return b.fork
|
||||
}
|
||||
|
||||
func (b *BeaconState) LatestBlockHeader() *cltypes.BeaconBlockHeader {
|
||||
return b.latestBlockHeader
|
||||
func (b *BeaconState) LatestBlockHeader() cltypes.BeaconBlockHeader {
|
||||
return *b.latestBlockHeader
|
||||
}
|
||||
|
||||
func (b *BeaconState) BlockRoots() [blockRootsLength]libcommon.Hash {
|
||||
@ -71,7 +71,7 @@ func (b *BeaconState) Validators() []*cltypes.Validator {
|
||||
return b.validators
|
||||
}
|
||||
|
||||
func (b *BeaconState) ValidatorAt(index int) (*cltypes.Validator, error) {
|
||||
func (b *BeaconState) ValidatorForValidatorIndex(index int) (*cltypes.Validator, error) {
|
||||
if index >= len(b.validators) {
|
||||
return nil, ErrInvalidValidatorIndex
|
||||
}
|
||||
@ -101,18 +101,24 @@ func (b *BeaconState) SlashingSegmentAt(pos int) uint64 {
|
||||
return b.slashings[pos]
|
||||
}
|
||||
|
||||
func (b *BeaconState) PreviousEpochParticipation() cltypes.ParticipationFlagsList {
|
||||
func (b *BeaconState) EpochParticipation(currentEpoch bool) cltypes.ParticipationFlagsList {
|
||||
if currentEpoch {
|
||||
return b.currentEpochParticipation
|
||||
}
|
||||
return b.previousEpochParticipation
|
||||
}
|
||||
|
||||
func (b *BeaconState) CurrentEpochParticipation() cltypes.ParticipationFlagsList {
|
||||
return b.currentEpochParticipation
|
||||
}
|
||||
|
||||
func (b *BeaconState) JustificationBits() cltypes.JustificationBits {
|
||||
return b.justificationBits
|
||||
}
|
||||
|
||||
func (b *BeaconState) EpochParticipationForValidatorIndex(isCurrentEpoch bool, index int) cltypes.ParticipationFlags {
|
||||
if isCurrentEpoch {
|
||||
return b.currentEpochParticipation[index]
|
||||
}
|
||||
return b.previousEpochParticipation[index]
|
||||
}
|
||||
|
||||
func (b *BeaconState) PreviousJustifiedCheckpoint() *cltypes.Checkpoint {
|
||||
return b.previousJustifiedCheckpoint
|
||||
}
|
||||
|
@ -60,12 +60,13 @@ func (b *BeaconState) InitiateValidatorExit(index uint64) error {
|
||||
exitQueueEpoch += 1
|
||||
}
|
||||
|
||||
b.validators[index].ExitEpoch = exitQueueEpoch
|
||||
var overflow bool
|
||||
if b.validators[index].WithdrawableEpoch, overflow = math.SafeAdd(b.validators[index].ExitEpoch, b.beaconConfig.MinValidatorWithdrawabilityDelay); overflow {
|
||||
var newWithdrawableEpoch uint64
|
||||
if newWithdrawableEpoch, overflow = math.SafeAdd(exitQueueEpoch, b.beaconConfig.MinValidatorWithdrawabilityDelay); overflow {
|
||||
return fmt.Errorf("withdrawable epoch is too big")
|
||||
}
|
||||
b.touchedLeaves[ValidatorsLeafIndex] = true
|
||||
b.SetExitEpochForValidatorAtIndex(int(index), exitQueueEpoch)
|
||||
b.SetWithdrawableEpochForValidatorAtIndex(int(index), newWithdrawableEpoch)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -81,12 +82,20 @@ func (b *BeaconState) SlashValidator(slashedInd uint64, whistleblowerInd *uint64
|
||||
if err := b.InitiateValidatorExit(slashedInd); err != nil {
|
||||
return err
|
||||
}
|
||||
// Record changes in changeset
|
||||
slashingsIndex := int(epoch % b.beaconConfig.EpochsPerSlashingsVector)
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.SlashedChange.AddChange(int(slashedInd), b.validators[slashedInd].Slashed)
|
||||
b.reverseChangeset.WithdrawalEpochChange.AddChange(int(slashedInd), b.validators[slashedInd].WithdrawableEpoch)
|
||||
b.reverseChangeset.SlashingsChanges.AddChange(slashingsIndex, b.slashings[slashingsIndex])
|
||||
}
|
||||
|
||||
// Change the validator to be slashed
|
||||
b.validators[slashedInd].Slashed = true
|
||||
b.validators[slashedInd].WithdrawableEpoch = utils.Max64(b.validators[slashedInd].WithdrawableEpoch, epoch+b.beaconConfig.EpochsPerSlashingsVector)
|
||||
b.touchedLeaves[ValidatorsLeafIndex] = true
|
||||
// Update slashings vector
|
||||
b.slashings[epoch%b.beaconConfig.EpochsPerSlashingsVector] += b.validators[slashedInd].EffectiveBalance
|
||||
b.slashings[slashingsIndex] += b.validators[slashedInd].EffectiveBalance
|
||||
b.touchedLeaves[SlashingsLeafIndex] = true
|
||||
if err := b.DecreaseBalance(slashedInd, b.validators[slashedInd].EffectiveBalance/b.beaconConfig.GetMinSlashingPenaltyQuotient(b.version)); err != nil {
|
||||
return err
|
||||
|
@ -119,7 +119,7 @@ func TestInitiatieValidatorExit(t *testing.T) {
|
||||
state.SetValidators(append(state.Validators(), tc.validator))
|
||||
testInd := uint64(len(state.Validators()) - 1)
|
||||
state.InitiateValidatorExit(testInd)
|
||||
val, err := state.ValidatorAt(int(testInd))
|
||||
val, err := state.ValidatorForValidatorIndex(int(testInd))
|
||||
require.NoError(t, err)
|
||||
if val.ExitEpoch != tc.expectedExitEpoch {
|
||||
t.Errorf("unexpected exit epoch: got %d, want %d", val.ExitEpoch, tc.expectedExitEpoch)
|
||||
@ -146,9 +146,9 @@ func TestSlashValidator(t *testing.T) {
|
||||
// Set up slashed balance.
|
||||
preSlashBalance := uint64(1 << 20)
|
||||
successState.Balances()[slashedInd] = preSlashBalance
|
||||
vali, err := successState.ValidatorAt(slashedInd)
|
||||
vali, err := successState.ValidatorForValidatorIndex(slashedInd)
|
||||
require.NoError(t, err)
|
||||
successState.SetValidatorAt(slashedInd, vali)
|
||||
successState.SetValidatorAtIndex(slashedInd, vali)
|
||||
vali.EffectiveBalance = preSlashBalance
|
||||
|
||||
testCases := []struct {
|
||||
@ -177,7 +177,7 @@ func TestSlashValidator(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error, wanted success: %v", err)
|
||||
}
|
||||
vali, err := tc.state.ValidatorAt(slashedInd)
|
||||
vali, err := tc.state.ValidatorForValidatorIndex(slashedInd)
|
||||
require.NoError(t, err)
|
||||
// Check that the validator is slashed.
|
||||
if !vali.Slashed {
|
||||
|
@ -4,31 +4,34 @@ type StateLeafIndex uint
|
||||
|
||||
// All position of all the leaves of the state merkle tree.
|
||||
const (
|
||||
GenesisTimeLeafIndex StateLeafIndex = 0
|
||||
GenesisValidatorsRootLeafIndex StateLeafIndex = 1
|
||||
SlotLeafIndex StateLeafIndex = 2
|
||||
ForkLeafIndex StateLeafIndex = 3
|
||||
LatestBlockHeaderLeafIndex StateLeafIndex = 4
|
||||
BlockRootsLeafIndex StateLeafIndex = 5
|
||||
StateRootsLeafIndex StateLeafIndex = 6
|
||||
HistoricalRootsLeafIndex StateLeafIndex = 7
|
||||
Eth1DataLeafIndex StateLeafIndex = 8
|
||||
Eth1DataVotesLeafIndex StateLeafIndex = 9
|
||||
Eth1DepositIndexLeafIndex StateLeafIndex = 10
|
||||
ValidatorsLeafIndex StateLeafIndex = 11
|
||||
BalancesLeafIndex StateLeafIndex = 12
|
||||
RandaoMixesLeafIndex StateLeafIndex = 13
|
||||
SlashingsLeafIndex StateLeafIndex = 14
|
||||
PreviousEpochParticipationLeafIndex StateLeafIndex = 15
|
||||
CurrentEpochParticipationLeafIndex StateLeafIndex = 16
|
||||
JustificationBitsLeafIndex StateLeafIndex = 17
|
||||
PreviousJustifiedCheckpointLeafIndex StateLeafIndex = 18
|
||||
CurrentJustifiedCheckpointLeafIndex StateLeafIndex = 19
|
||||
FinalizedCheckpointLeafIndex StateLeafIndex = 20
|
||||
InactivityScoresLeafIndex StateLeafIndex = 21
|
||||
CurrentSyncCommitteeLeafIndex StateLeafIndex = 22
|
||||
NextSyncCommitteeLeafIndex StateLeafIndex = 23
|
||||
GenesisTimeLeafIndex StateLeafIndex = 0
|
||||
GenesisValidatorsRootLeafIndex StateLeafIndex = 1
|
||||
SlotLeafIndex StateLeafIndex = 2
|
||||
ForkLeafIndex StateLeafIndex = 3
|
||||
LatestBlockHeaderLeafIndex StateLeafIndex = 4
|
||||
BlockRootsLeafIndex StateLeafIndex = 5
|
||||
StateRootsLeafIndex StateLeafIndex = 6
|
||||
HistoricalRootsLeafIndex StateLeafIndex = 7
|
||||
Eth1DataLeafIndex StateLeafIndex = 8
|
||||
Eth1DataVotesLeafIndex StateLeafIndex = 9
|
||||
Eth1DepositIndexLeafIndex StateLeafIndex = 10
|
||||
ValidatorsLeafIndex StateLeafIndex = 11
|
||||
BalancesLeafIndex StateLeafIndex = 12
|
||||
RandaoMixesLeafIndex StateLeafIndex = 13
|
||||
SlashingsLeafIndex StateLeafIndex = 14
|
||||
PreviousEpochParticipationLeafIndex StateLeafIndex = 15
|
||||
CurrentEpochParticipationLeafIndex StateLeafIndex = 16
|
||||
JustificationBitsLeafIndex StateLeafIndex = 17
|
||||
PreviousJustifiedCheckpointLeafIndex StateLeafIndex = 18
|
||||
CurrentJustifiedCheckpointLeafIndex StateLeafIndex = 19
|
||||
FinalizedCheckpointLeafIndex StateLeafIndex = 20
|
||||
// Altair
|
||||
InactivityScoresLeafIndex StateLeafIndex = 21
|
||||
CurrentSyncCommitteeLeafIndex StateLeafIndex = 22
|
||||
NextSyncCommitteeLeafIndex StateLeafIndex = 23
|
||||
// Bellatrix
|
||||
LatestExecutionPayloadHeaderLeafIndex StateLeafIndex = 24
|
||||
// Capella
|
||||
NextWithdrawalIndexLeafIndex StateLeafIndex = 25
|
||||
NextWithdrawalValidatorIndexLeafIndex StateLeafIndex = 26
|
||||
HistoricalSummariesLeafIndex StateLeafIndex = 27
|
||||
|
@ -3,7 +3,6 @@ package state
|
||||
import (
|
||||
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
||||
|
||||
"github.com/ledgerwatch/erigon/cl/clparams"
|
||||
"github.com/ledgerwatch/erigon/cl/cltypes"
|
||||
)
|
||||
|
||||
@ -11,17 +10,10 @@ const maxEth1Votes = 2048
|
||||
|
||||
// Below are setters. Note that they also dirty the state.
|
||||
|
||||
func (b *BeaconState) SetGenesisTime(genesisTime uint64) {
|
||||
b.touchedLeaves[GenesisTimeLeafIndex] = true
|
||||
b.genesisTime = genesisTime
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetGenesisValidatorsRoot(genesisValidatorRoot libcommon.Hash) {
|
||||
b.touchedLeaves[GenesisValidatorsRootLeafIndex] = true
|
||||
b.genesisValidatorsRoot = genesisValidatorRoot
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetSlot(slot uint64) {
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.OnSlotChange(b.slot)
|
||||
}
|
||||
b.touchedLeaves[SlotLeafIndex] = true
|
||||
b.slot = slot
|
||||
b.proposerIndex = nil
|
||||
@ -32,47 +24,97 @@ func (b *BeaconState) SetSlot(slot uint64) {
|
||||
|
||||
func (b *BeaconState) SetFork(fork *cltypes.Fork) {
|
||||
b.touchedLeaves[ForkLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.OnForkChange(b.fork)
|
||||
}
|
||||
b.fork = fork
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetLatestBlockHeader(header *cltypes.BeaconBlockHeader) {
|
||||
b.touchedLeaves[LatestBlockHeaderLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.OnLatestHeaderChange(b.latestBlockHeader)
|
||||
}
|
||||
b.latestBlockHeader = header
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetHistoricalRoots(historicalRoots []libcommon.Hash) {
|
||||
b.touchedLeaves[HistoricalRootsLeafIndex] = true
|
||||
b.historicalRoots = historicalRoots
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetBlockRootAt(index int, root libcommon.Hash) {
|
||||
b.touchedLeaves[BlockRootsLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.BlockRootsChanges.AddChange(index, b.blockRoots[index])
|
||||
}
|
||||
b.blockRoots[index] = root
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetStateRootAt(index int, root libcommon.Hash) {
|
||||
b.touchedLeaves[StateRootsLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.StateRootsChanges.AddChange(index, b.stateRoots[index])
|
||||
}
|
||||
b.stateRoots[index] = root
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetHistoricalRootAt(index int, root [32]byte) {
|
||||
b.touchedLeaves[HistoricalRootsLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.HistoricalRootsChanges.AddChange(index, b.historicalRoots[index])
|
||||
}
|
||||
b.historicalRoots[index] = root
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetValidatorAt(index int, validator *cltypes.Validator) error {
|
||||
if index >= len(b.validators) {
|
||||
return ErrInvalidValidatorIndex
|
||||
}
|
||||
b.validators[index] = validator
|
||||
func (b *BeaconState) SetWithdrawalCredentialForValidatorAtIndex(index int, creds libcommon.Hash) {
|
||||
b.touchedLeaves[ValidatorsLeafIndex] = true
|
||||
// change in validator set means cache purging
|
||||
b.totalActiveBalanceCache = nil
|
||||
return nil
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.WithdrawalCredentialsChange.AddChange(index, b.validators[index].WithdrawalCredentials)
|
||||
}
|
||||
b.validators[index].WithdrawalCredentials = creds
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetExitEpochForValidatorAtIndex(index int, epoch uint64) {
|
||||
b.touchedLeaves[ValidatorsLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.ExitEpochChange.AddChange(index, b.validators[index].ExitEpoch)
|
||||
}
|
||||
b.validators[index].ExitEpoch = epoch
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetWithdrawableEpochForValidatorAtIndex(index int, epoch uint64) {
|
||||
b.touchedLeaves[ValidatorsLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.WithdrawalEpochChange.AddChange(index, b.validators[index].WithdrawableEpoch)
|
||||
}
|
||||
b.validators[index].WithdrawableEpoch = epoch
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetEffectiveBalanceForValidatorAtIndex(index int, balance uint64) {
|
||||
b.touchedLeaves[ValidatorsLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.EffectiveBalanceChange.AddChange(index, b.validators[index].EffectiveBalance)
|
||||
}
|
||||
b.validators[index].EffectiveBalance = balance
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetActivationEpochForValidatorAtIndex(index int, epoch uint64) {
|
||||
b.touchedLeaves[ValidatorsLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.ActivationEpochChange.AddChange(index, b.validators[index].ActivationEpoch)
|
||||
}
|
||||
b.validators[index].ActivationEpoch = epoch
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetActivationEligibilityEpochForValidatorAtIndex(index int, epoch uint64) {
|
||||
b.touchedLeaves[ValidatorsLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.ActivationEligibilityEpochChange.AddChange(index, b.validators[index].ActivationEligibilityEpoch)
|
||||
}
|
||||
b.validators[index].ActivationEligibilityEpoch = epoch
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetEth1Data(eth1Data *cltypes.Eth1Data) {
|
||||
b.touchedLeaves[Eth1DataLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.OnEth1DataChange(eth1Data)
|
||||
}
|
||||
b.eth1Data = eth1Data
|
||||
}
|
||||
|
||||
@ -82,12 +124,18 @@ func (b *BeaconState) AddEth1DataVote(vote *cltypes.Eth1Data) {
|
||||
}
|
||||
|
||||
func (b *BeaconState) ResetEth1DataVotes() {
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.Eth1DataVotesAtReset = b.eth1DataVotes
|
||||
}
|
||||
b.touchedLeaves[Eth1DataVotesLeafIndex] = true
|
||||
b.eth1DataVotes = b.eth1DataVotes[:0]
|
||||
b.eth1DataVotes = nil
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetEth1DepositIndex(eth1DepositIndex uint64) {
|
||||
b.touchedLeaves[Eth1DepositIndexLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.OnEth1DepositIndexChange(b.eth1DepositIndex)
|
||||
}
|
||||
b.eth1DepositIndex = eth1DepositIndex
|
||||
}
|
||||
|
||||
@ -120,72 +168,131 @@ func (b *BeaconState) SetValidatorBalance(index int, balance uint64) error {
|
||||
}
|
||||
|
||||
b.touchedLeaves[BalancesLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.BalancesChanges.AddChange(index, b.balances[index])
|
||||
}
|
||||
b.balances[index] = balance
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetRandaoMixAt(index int, mix libcommon.Hash) {
|
||||
b.touchedLeaves[RandaoMixesLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.RandaoMixesChanges.AddChange(index, b.randaoMixes[index])
|
||||
}
|
||||
b.randaoMixes[index] = mix
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetSlashingSegmentAt(index int, segment uint64) {
|
||||
b.touchedLeaves[SlashingsLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.SlashingsChanges.AddChange(index, b.slashings[index])
|
||||
}
|
||||
b.slashings[index] = segment
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetPreviousEpochParticipation(previousEpochParticipation []cltypes.ParticipationFlags) {
|
||||
func (b *BeaconState) SetEpochParticipationForValidatorIndex(isCurrentEpoch bool, index int, flags cltypes.ParticipationFlags) {
|
||||
if isCurrentEpoch {
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.CurrentEpochParticipationChanges.AddChange(index, b.currentEpochParticipation[index])
|
||||
}
|
||||
b.touchedLeaves[CurrentEpochParticipationLeafIndex] = true
|
||||
b.currentEpochParticipation[index] = flags
|
||||
return
|
||||
}
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.PreviousEpochParticipationChanges.AddChange(index, b.previousEpochParticipation[index])
|
||||
}
|
||||
b.touchedLeaves[PreviousEpochParticipationLeafIndex] = true
|
||||
b.previousEpochParticipation = previousEpochParticipation
|
||||
b.previousEpochParticipation[index] = flags
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetCurrentEpochParticipation(currentEpochParticipation []cltypes.ParticipationFlags) {
|
||||
func (b *BeaconState) SetValidatorAtIndex(index int, validator *cltypes.Validator) {
|
||||
b.touchedLeaves[ValidatorsLeafIndex] = true
|
||||
b.validators[index] = validator
|
||||
}
|
||||
|
||||
func (b *BeaconState) ResetEpochParticipation() {
|
||||
if b.reverseChangeset != nil && len(b.reverseChangeset.CurrentEpochParticipationAtReset) == 0 &&
|
||||
len(b.reverseChangeset.PreviousEpochParticipationAtReset) == 0 {
|
||||
b.reverseChangeset.CurrentEpochParticipationAtReset = b.currentEpochParticipation.Copy()
|
||||
b.reverseChangeset.PreviousEpochParticipationAtReset = b.previousEpochParticipation.Copy()
|
||||
}
|
||||
b.touchedLeaves[PreviousEpochParticipationLeafIndex] = true
|
||||
b.touchedLeaves[CurrentEpochParticipationLeafIndex] = true
|
||||
b.currentEpochParticipation = currentEpochParticipation
|
||||
b.previousEpochParticipation = b.currentEpochParticipation
|
||||
b.currentEpochParticipation = make(cltypes.ParticipationFlagsList, len(b.validators))
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetJustificationBits(justificationBits cltypes.JustificationBits) {
|
||||
b.touchedLeaves[JustificationBitsLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.OnJustificationBitsChange(b.justificationBits)
|
||||
}
|
||||
b.justificationBits = justificationBits
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetPreviousJustifiedCheckpoint(previousJustifiedCheckpoint *cltypes.Checkpoint) {
|
||||
b.touchedLeaves[PreviousJustifiedCheckpointLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.OnPreviousJustifiedCheckpointChange(b.previousJustifiedCheckpoint)
|
||||
}
|
||||
b.previousJustifiedCheckpoint = previousJustifiedCheckpoint
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetCurrentJustifiedCheckpoint(currentJustifiedCheckpoint *cltypes.Checkpoint) {
|
||||
b.touchedLeaves[CurrentJustifiedCheckpointLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.OnCurrentJustifiedCheckpointChange(b.currentJustifiedCheckpoint)
|
||||
}
|
||||
b.currentJustifiedCheckpoint = currentJustifiedCheckpoint
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetFinalizedCheckpoint(finalizedCheckpoint *cltypes.Checkpoint) {
|
||||
b.touchedLeaves[FinalizedCheckpointLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.OnFinalizedCheckpointChange(b.finalizedCheckpoint)
|
||||
}
|
||||
b.finalizedCheckpoint = finalizedCheckpoint
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetCurrentSyncCommittee(currentSyncCommittee *cltypes.SyncCommittee) {
|
||||
b.touchedLeaves[CurrentSyncCommitteeLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.OnCurrentSyncCommitteeChange(b.currentSyncCommittee)
|
||||
}
|
||||
b.currentSyncCommittee = currentSyncCommittee
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetNextSyncCommittee(nextSyncCommittee *cltypes.SyncCommittee) {
|
||||
b.touchedLeaves[NextSyncCommitteeLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.OnNextSyncCommitteeChange(b.nextSyncCommittee)
|
||||
}
|
||||
b.nextSyncCommittee = nextSyncCommittee
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetLatestExecutionPayloadHeader(header *cltypes.Eth1Header) {
|
||||
b.touchedLeaves[LatestExecutionPayloadHeaderLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.OnEth1Header(b.latestExecutionPayloadHeader)
|
||||
}
|
||||
b.latestExecutionPayloadHeader = header
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetNextWithdrawalIndex(index uint64) {
|
||||
b.touchedLeaves[NextWithdrawalIndexLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.OnNextWithdrawalIndexChange(b.nextWithdrawalIndex)
|
||||
}
|
||||
b.nextWithdrawalIndex = index
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetNextWithdrawalValidatorIndex(index uint64) {
|
||||
b.touchedLeaves[NextWithdrawalValidatorIndexLeafIndex] = true
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.OnNextWithdrawalValidatorIndexChange(b.nextWithdrawalValidatorIndex)
|
||||
}
|
||||
b.nextWithdrawalValidatorIndex = index
|
||||
}
|
||||
|
||||
@ -208,55 +315,40 @@ func (b *BeaconState) SetValidatorInactivityScore(index int, score uint64) error
|
||||
if index >= len(b.inactivityScores) {
|
||||
return ErrInvalidValidatorIndex
|
||||
}
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.InactivityScoresChanges.AddChange(index, b.inactivityScores[index])
|
||||
}
|
||||
b.touchedLeaves[InactivityScoresLeafIndex] = true
|
||||
b.inactivityScores[index] = score
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *BeaconState) AddCurrentEpochParticipationFlags(flags cltypes.ParticipationFlags) {
|
||||
if b.version == clparams.Phase0Version {
|
||||
panic("cannot call AddCurrentEpochParticipationFlags on phase0")
|
||||
}
|
||||
b.touchedLeaves[CurrentEpochParticipationLeafIndex] = true
|
||||
b.currentEpochParticipation = append(b.currentEpochParticipation, flags)
|
||||
}
|
||||
|
||||
func (b *BeaconState) AddPreviousEpochParticipationFlags(flags cltypes.ParticipationFlags) {
|
||||
if b.version == clparams.Phase0Version {
|
||||
panic("cannot call AddPreviousEpochParticipationFlags on phase0")
|
||||
}
|
||||
b.touchedLeaves[PreviousEpochParticipationLeafIndex] = true
|
||||
b.previousEpochParticipation = append(b.previousEpochParticipation, flags)
|
||||
}
|
||||
|
||||
func (b *BeaconState) AddCurrentEpochAtteastation(attestation *cltypes.PendingAttestation) {
|
||||
if b.version != clparams.Phase0Version {
|
||||
panic("can call AddCurrentEpochAtteastation only on phase0")
|
||||
}
|
||||
b.touchedLeaves[CurrentEpochParticipationLeafIndex] = true
|
||||
b.currentEpochAttestations = append(b.currentEpochAttestations, attestation)
|
||||
}
|
||||
|
||||
func (b *BeaconState) AddPreviousEpochAtteastation(attestation *cltypes.PendingAttestation) {
|
||||
if b.version != clparams.Phase0Version {
|
||||
panic("can call AddPreviousEpochAtteastation only on phase0")
|
||||
}
|
||||
func (b *BeaconState) AddPreviousEpochAttestation(attestation *cltypes.PendingAttestation) {
|
||||
b.touchedLeaves[PreviousEpochParticipationLeafIndex] = true
|
||||
b.previousEpochAttestations = append(b.previousEpochAttestations, attestation)
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetCurrentEpochAtteastations(attestations []*cltypes.PendingAttestation) {
|
||||
if b.version != clparams.Phase0Version {
|
||||
panic("can call SetCurrentEpochAtteastations only on phase0")
|
||||
}
|
||||
func (b *BeaconState) ResetCurrentEpochAttestations() {
|
||||
b.touchedLeaves[CurrentEpochParticipationLeafIndex] = true
|
||||
b.currentEpochAttestations = attestations
|
||||
b.currentEpochAttestations = nil
|
||||
}
|
||||
|
||||
func (b *BeaconState) SetPreviousEpochAtteastations(attestations []*cltypes.PendingAttestation) {
|
||||
if b.version != clparams.Phase0Version {
|
||||
panic("can call SetPreviousEpochAtteastations only on phase0")
|
||||
}
|
||||
func (b *BeaconState) SetPreviousEpochAttestations(attestations []*cltypes.PendingAttestation) {
|
||||
b.touchedLeaves[PreviousEpochParticipationLeafIndex] = true
|
||||
b.previousEpochAttestations = attestations
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"github.com/ledgerwatch/erigon/cl/clparams"
|
||||
"github.com/ledgerwatch/erigon/cl/cltypes"
|
||||
"github.com/ledgerwatch/erigon/cl/utils"
|
||||
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/beacon_changeset"
|
||||
)
|
||||
|
||||
type HashFunc func([]byte) ([32]byte, error)
|
||||
@ -73,6 +74,8 @@ type BeaconState struct {
|
||||
previousStateRoot libcommon.Hash
|
||||
// Configs
|
||||
beaconConfig *clparams.BeaconChainConfig
|
||||
// Changesets
|
||||
reverseChangeset *beacon_changeset.ReverseBeaconStateChangeSet
|
||||
}
|
||||
|
||||
func New(cfg *clparams.BeaconChainConfig) *BeaconState {
|
||||
|
@ -59,6 +59,10 @@ func (b *BeaconState) UpgradeToAltair() error {
|
||||
func (b *BeaconState) UpgradeToBellatrix() error {
|
||||
b.previousStateRoot = libcommon.Hash{}
|
||||
epoch := b.Epoch()
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.OnVersionChange(b.version)
|
||||
b.reverseChangeset.OnForkChange(b.fork)
|
||||
}
|
||||
// update version
|
||||
b.fork.Epoch = epoch
|
||||
b.fork.PreviousVersion = b.fork.CurrentVersion
|
||||
@ -74,6 +78,11 @@ func (b *BeaconState) UpgradeToBellatrix() error {
|
||||
func (b *BeaconState) UpgradeToCapella() error {
|
||||
b.previousStateRoot = libcommon.Hash{}
|
||||
epoch := b.Epoch()
|
||||
if b.reverseChangeset != nil {
|
||||
b.reverseChangeset.OnVersionChange(b.version)
|
||||
b.reverseChangeset.OnForkChange(b.fork)
|
||||
b.reverseChangeset.OnEth1Header(b.latestExecutionPayloadHeader)
|
||||
}
|
||||
// update version
|
||||
b.fork.Epoch = epoch
|
||||
b.fork.PreviousVersion = b.fork.CurrentVersion
|
||||
|
@ -84,7 +84,7 @@ func ProcessJustificationBitsAndFinality(state *state.BeaconState) error {
|
||||
}
|
||||
} else {
|
||||
// Use bitlists to determine finality.
|
||||
previousParticipation, currentParticipation := state.PreviousEpochParticipation(), state.CurrentEpochParticipation()
|
||||
previousParticipation, currentParticipation := state.EpochParticipation(false), state.EpochParticipation(true)
|
||||
for i, validator := range state.Validators() {
|
||||
if validator.Slashed {
|
||||
continue
|
||||
|
@ -26,7 +26,7 @@ func isValidIndexedAttestation(state *state.BeaconState, att *cltypes.IndexedAtt
|
||||
|
||||
pks := [][]byte{}
|
||||
for _, v := range inds {
|
||||
val, err := state.ValidatorAt(int(v))
|
||||
val, err := state.ValidatorForValidatorIndex(int(v))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -77,7 +77,7 @@ func ProcessProposerSlashing(state *state.BeaconState, propSlashing *cltypes.Pro
|
||||
return fmt.Errorf("propose slashing headers are the same: %v == %v", h1Root, h2Root)
|
||||
}
|
||||
|
||||
proposer, err := state.ValidatorAt(int(h1.ProposerIndex))
|
||||
proposer, err := state.ValidatorForValidatorIndex(int(h1.ProposerIndex))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -135,7 +135,7 @@ func ProcessAttesterSlashing(state *state.BeaconState, attSlashing *cltypes.Atte
|
||||
slashedAny := false
|
||||
currentEpoch := state.GetEpochAtSlot(state.Slot())
|
||||
for _, ind := range utils.IntersectionOfSortedSets(att1.AttestingIndices, att2.AttestingIndices) {
|
||||
validator, err := state.ValidatorAt(int(ind))
|
||||
validator, err := state.ValidatorForValidatorIndex(int(ind))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -217,7 +217,7 @@ func ProcessVoluntaryExit(state *state.BeaconState, signedVoluntaryExit *cltypes
|
||||
// Sanity checks so that we know it is good.
|
||||
voluntaryExit := signedVoluntaryExit.VolunaryExit
|
||||
currentEpoch := state.Epoch()
|
||||
validator, err := state.ValidatorAt(int(voluntaryExit.ValidatorIndex))
|
||||
validator, err := state.ValidatorForValidatorIndex(int(voluntaryExit.ValidatorIndex))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ func getSuccessfulAttesterSlashing() *cltypes.AttesterSlashing {
|
||||
|
||||
func TestProcessProposerSlashing(t *testing.T) {
|
||||
unchangingState := getTestState(t)
|
||||
unchangingState.SetValidatorAt(propInd, &cltypes.Validator{
|
||||
unchangingState.SetValidatorAtIndex(propInd, &cltypes.Validator{
|
||||
Slashed: false,
|
||||
ActivationEpoch: 0,
|
||||
WithdrawableEpoch: 10000,
|
||||
@ -86,7 +86,7 @@ func TestProcessProposerSlashing(t *testing.T) {
|
||||
})
|
||||
|
||||
successState := getTestState(t)
|
||||
successState.SetValidatorAt(propInd, &cltypes.Validator{
|
||||
successState.SetValidatorAtIndex(propInd, &cltypes.Validator{
|
||||
Slashed: false,
|
||||
ActivationEpoch: 0,
|
||||
WithdrawableEpoch: 10000,
|
||||
@ -187,13 +187,13 @@ func TestProcessProposerSlashing(t *testing.T) {
|
||||
|
||||
func TestProcessAttesterSlashing(t *testing.T) {
|
||||
unchangingState := getTestState(t)
|
||||
unchangingState.SetValidatorAt(0, &cltypes.Validator{
|
||||
unchangingState.SetValidatorAtIndex(0, &cltypes.Validator{
|
||||
Slashed: false,
|
||||
ActivationEpoch: 0,
|
||||
WithdrawableEpoch: 10000,
|
||||
PublicKey: testPublicKeySlashing,
|
||||
})
|
||||
unchangingState.SetValidatorAt(1, &cltypes.Validator{
|
||||
unchangingState.SetValidatorAtIndex(1, &cltypes.Validator{
|
||||
Slashed: false,
|
||||
ActivationEpoch: 0,
|
||||
WithdrawableEpoch: 10000,
|
||||
@ -201,13 +201,13 @@ func TestProcessAttesterSlashing(t *testing.T) {
|
||||
})
|
||||
|
||||
successState := getTestState(t)
|
||||
successState.SetValidatorAt(0, &cltypes.Validator{
|
||||
successState.SetValidatorAtIndex(0, &cltypes.Validator{
|
||||
Slashed: false,
|
||||
ActivationEpoch: 0,
|
||||
WithdrawableEpoch: 10000,
|
||||
PublicKey: testPublicKeySlashing,
|
||||
})
|
||||
successState.SetValidatorAt(1, &cltypes.Validator{
|
||||
successState.SetValidatorAtIndex(1, &cltypes.Validator{
|
||||
Slashed: false,
|
||||
ActivationEpoch: 0,
|
||||
WithdrawableEpoch: 10000,
|
||||
|
@ -52,21 +52,17 @@ func processAttestationPostAltair(state *state.BeaconState, attestation *cltypes
|
||||
}
|
||||
var proposerRewardNumerator uint64
|
||||
|
||||
var epochParticipation cltypes.ParticipationFlagsList
|
||||
if data.Target.Epoch == currentEpoch {
|
||||
epochParticipation = state.CurrentEpochParticipation()
|
||||
} else {
|
||||
epochParticipation = state.PreviousEpochParticipation()
|
||||
}
|
||||
validators := state.Validators()
|
||||
isCurrentEpoch := data.Target.Epoch == currentEpoch
|
||||
|
||||
validators := state.Validators()
|
||||
for _, attesterIndex := range attestingIndicies {
|
||||
baseReward := (validators[attesterIndex].EffectiveBalance / beaconConfig.EffectiveBalanceIncrement) * baseRewardPerIncrement
|
||||
for flagIndex, weight := range beaconConfig.ParticipationWeights() {
|
||||
if !slices.Contains(participationFlagsIndicies, uint8(flagIndex)) || epochParticipation[attesterIndex].HasFlag(flagIndex) {
|
||||
flagParticipation := state.EpochParticipationForValidatorIndex(isCurrentEpoch, int(attesterIndex))
|
||||
if !slices.Contains(participationFlagsIndicies, uint8(flagIndex)) || flagParticipation.HasFlag(flagIndex) {
|
||||
continue
|
||||
}
|
||||
epochParticipation[attesterIndex] = epochParticipation[attesterIndex].Add(flagIndex)
|
||||
state.SetEpochParticipationForValidatorIndex(isCurrentEpoch, int(attesterIndex), flagParticipation.Add(flagIndex))
|
||||
proposerRewardNumerator += baseReward * weight
|
||||
}
|
||||
}
|
||||
@ -75,12 +71,6 @@ func processAttestationPostAltair(state *state.BeaconState, attestation *cltypes
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Set participation
|
||||
if data.Target.Epoch == currentEpoch {
|
||||
state.SetCurrentEpochParticipation(epochParticipation)
|
||||
} else {
|
||||
state.SetPreviousEpochParticipation(epochParticipation)
|
||||
}
|
||||
proposerRewardDenominator := (beaconConfig.WeightDenominator - beaconConfig.ProposerWeight) * beaconConfig.WeightDenominator / beaconConfig.ProposerWeight
|
||||
reward := proposerRewardNumerator / proposerRewardDenominator
|
||||
return attestingIndicies, state.IncreaseBalance(proposer, reward)
|
||||
@ -120,7 +110,7 @@ func processAttestationPhase0(state *state.BeaconState, attestation *cltypes.Att
|
||||
if !data.Source.Equal(state.PreviousJustifiedCheckpoint()) {
|
||||
return nil, fmt.Errorf("processAttestationPhase0: mismatching sources")
|
||||
}
|
||||
state.AddPreviousEpochAtteastation(pendingAttestation)
|
||||
state.AddPreviousEpochAttestation(pendingAttestation)
|
||||
}
|
||||
// Not required by specs but needed if we want performant epoch transition.
|
||||
indicies, err := state.GetAttestingIndicies(attestation.Data, attestation.AggregationBits, true)
|
||||
@ -137,7 +127,7 @@ func processAttestationPhase0(state *state.BeaconState, attestation *cltypes.Att
|
||||
}
|
||||
// Basically we flag all validators we are currently attesting. will be important for rewards/finalization processing.
|
||||
for _, index := range indicies {
|
||||
validator, err := state.ValidatorAt(int(index))
|
||||
validator, err := state.ValidatorForValidatorIndex(int(index))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -169,10 +159,6 @@ func processAttestationPhase0(state *state.BeaconState, attestation *cltypes.Att
|
||||
validator.IsPreviousMatchingHeadAttester = true
|
||||
}
|
||||
}
|
||||
|
||||
if err := state.SetValidatorAt(int(index), validator); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return indicies, nil
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ func ProcessBlsToExecutionChange(state *state.BeaconState, signedChange *cltypes
|
||||
change := signedChange.Message
|
||||
|
||||
beaconConfig := state.BeaconConfig()
|
||||
validator, err := state.ValidatorAt(int(change.ValidatorIndex))
|
||||
validator, err := state.ValidatorForValidatorIndex(int(change.ValidatorIndex))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -51,12 +51,13 @@ func ProcessBlsToExecutionChange(state *state.BeaconState, signedChange *cltypes
|
||||
return fmt.Errorf("invalid signature")
|
||||
}
|
||||
}
|
||||
|
||||
credentials := validator.WithdrawalCredentials
|
||||
// Reset the validator's withdrawal credentials.
|
||||
validator.WithdrawalCredentials[0] = beaconConfig.ETH1AddressWithdrawalPrefixByte
|
||||
copy(validator.WithdrawalCredentials[1:], make([]byte, 11))
|
||||
copy(validator.WithdrawalCredentials[12:], change.To[:])
|
||||
credentials[0] = beaconConfig.ETH1AddressWithdrawalPrefixByte
|
||||
copy(credentials[1:], make([]byte, 11))
|
||||
copy(credentials[12:], change.To[:])
|
||||
|
||||
// Update the state with the modified validator.
|
||||
return state.SetValidatorAt(int(change.ValidatorIndex), validator)
|
||||
state.SetWithdrawalCredentialForValidatorAtIndex(int(change.ValidatorIndex), credentials)
|
||||
return nil
|
||||
}
|
||||
|
@ -21,10 +21,8 @@ func ProcessEffectiveBalanceUpdates(state *state.BeaconState) error {
|
||||
if balance+downwardThreshold < validator.EffectiveBalance ||
|
||||
validator.EffectiveBalance+upwardThreshold < balance {
|
||||
// Set new effective balance
|
||||
validator.EffectiveBalance = utils.Min64(balance-(balance%beaconConfig.EffectiveBalanceIncrement), beaconConfig.MaxEffectiveBalance)
|
||||
if err := state.SetValidatorAt(index, validator); err != nil {
|
||||
return err
|
||||
}
|
||||
effectiveBalance := utils.Min64(balance-(balance%beaconConfig.EffectiveBalanceIncrement), beaconConfig.MaxEffectiveBalance)
|
||||
state.SetEffectiveBalanceForValidatorAtIndex(index, effectiveBalance)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -49,10 +49,10 @@ func ProcessEpoch(state *state.BeaconState) error {
|
||||
}
|
||||
|
||||
func ProcessParticipationRecordUpdates(state *state.BeaconState) error {
|
||||
state.SetPreviousEpochAtteastations(state.CurrentEpochAttestations())
|
||||
state.SetCurrentEpochAtteastations(nil)
|
||||
state.SetPreviousEpochAttestations(state.CurrentEpochAttestations())
|
||||
state.ResetCurrentEpochAttestations()
|
||||
// Also mark all current attesters as previous
|
||||
for validatorIndex, validator := range state.Validators() {
|
||||
for _, validator := range state.Validators() {
|
||||
// Previous sources/target/head
|
||||
validator.IsPreviousMatchingSourceAttester = validator.IsCurrentMatchingSourceAttester
|
||||
validator.IsPreviousMatchingTargetAttester = validator.IsCurrentMatchingTargetAttester
|
||||
@ -63,10 +63,6 @@ func ProcessParticipationRecordUpdates(state *state.BeaconState) error {
|
||||
validator.IsCurrentMatchingSourceAttester = false
|
||||
validator.IsCurrentMatchingTargetAttester = false
|
||||
validator.IsCurrentMatchingHeadAttester = false
|
||||
// Setting the validator
|
||||
if err := state.SetValidatorAt(validatorIndex, validator); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -22,10 +22,7 @@ func ProcessRegistryUpdates(state *state.BeaconState) error {
|
||||
// Process activation eligibility and ejections.
|
||||
for validatorIndex, validator := range validators {
|
||||
if state.IsValidatorEligibleForActivationQueue(validator) {
|
||||
validator.ActivationEligibilityEpoch = currentEpoch + 1
|
||||
if err := state.SetValidatorAt(validatorIndex, validator); err != nil {
|
||||
return err
|
||||
}
|
||||
state.SetActivationEligibilityEpochForValidatorAtIndex(validatorIndex, currentEpoch+1)
|
||||
}
|
||||
if validator.Active(currentEpoch) && validator.EffectiveBalance <= beaconConfig.EjectionBalance {
|
||||
if err := state.InitiateValidatorExit(uint64(validatorIndex)); err != nil {
|
||||
@ -51,14 +48,7 @@ func ProcessRegistryUpdates(state *state.BeaconState) error {
|
||||
}
|
||||
// Only process up to epoch limit.
|
||||
for _, validatorIndex := range activationQueue {
|
||||
validator, err := state.ValidatorAt(int(validatorIndex))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
validator.ActivationEpoch = computeActivationExitEpoch(beaconConfig, currentEpoch)
|
||||
if err := state.SetValidatorAt(int(validatorIndex), validator); err != nil {
|
||||
return err
|
||||
}
|
||||
state.SetActivationEpochForValidatorAtIndex(int(validatorIndex), computeActivationExitEpoch(beaconConfig, currentEpoch))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -70,10 +70,11 @@ func transitionSlot(state *state.BeaconState) error {
|
||||
latestBlockHeader := state.LatestBlockHeader()
|
||||
if latestBlockHeader.Root == [32]byte{} {
|
||||
latestBlockHeader.Root = previousStateRoot
|
||||
state.SetLatestBlockHeader(latestBlockHeader)
|
||||
state.SetLatestBlockHeader(&latestBlockHeader)
|
||||
}
|
||||
blockHeader := state.LatestBlockHeader()
|
||||
|
||||
previousBlockRoot, err := state.LatestBlockHeader().HashSSZ()
|
||||
previousBlockRoot, err := (&blockHeader).HashSSZ()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -127,7 +128,7 @@ func ProcessSlots(state *state.BeaconState, slot uint64) error {
|
||||
}
|
||||
|
||||
func verifyBlockSignature(state *state.BeaconState, block *cltypes.SignedBeaconBlock) (bool, error) {
|
||||
proposer, err := state.ValidatorAt(int(block.Block.ProposerIndex))
|
||||
proposer, err := state.ValidatorForValidatorIndex(int(block.Block.ProposerIndex))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ func prepareNextBeaconState(t *testing.T, slots []uint64, stateHashs, blockHashs
|
||||
// Only copy if the previous is empty.
|
||||
if latestBlockHeader.Root == [32]byte{} {
|
||||
latestBlockHeader.Root = libcommon.BytesToHash(hash)
|
||||
nextState.SetLatestBlockHeader(latestBlockHeader)
|
||||
nextState.SetLatestBlockHeader(&latestBlockHeader)
|
||||
}
|
||||
hash, err = hex.DecodeString(blockHashs[i])
|
||||
if err != nil {
|
||||
|
@ -33,7 +33,8 @@ func ProcessBlockHeader(state *state.BeaconState, block *cltypes.BeaconBlock, fu
|
||||
if block.ProposerIndex != propInd {
|
||||
return fmt.Errorf("block proposer index: %d, does not match beacon proposer index: %d", block.ProposerIndex, propInd)
|
||||
}
|
||||
latestRoot, err := state.LatestBlockHeader().HashSSZ()
|
||||
blockHeader := state.LatestBlockHeader()
|
||||
latestRoot, err := (&blockHeader).HashSSZ()
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to hash tree root of latest block header: %v", err)
|
||||
}
|
||||
@ -53,7 +54,7 @@ func ProcessBlockHeader(state *state.BeaconState, block *cltypes.BeaconBlock, fu
|
||||
BodyRoot: bodyRoot,
|
||||
})
|
||||
|
||||
proposer, err := state.ValidatorAt(int(block.ProposerIndex))
|
||||
proposer, err := state.ValidatorForValidatorIndex(int(block.ProposerIndex))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -65,7 +66,7 @@ func ProcessBlockHeader(state *state.BeaconState, block *cltypes.BeaconBlock, fu
|
||||
|
||||
func ProcessRandao(state *state.BeaconState, randao [96]byte, proposerIndex uint64, fullValidation bool) error {
|
||||
epoch := state.Epoch()
|
||||
proposer, err := state.ValidatorAt(int(proposerIndex))
|
||||
proposer, err := state.ValidatorForValidatorIndex(int(proposerIndex))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -93,7 +94,6 @@ func ProcessRandao(state *state.BeaconState, randao [96]byte, proposerIndex uint
|
||||
for i := range mix {
|
||||
mix[i] = randaoMixes[i] ^ randaoHash[i]
|
||||
}
|
||||
|
||||
state.SetRandaoMixAt(int(epoch%state.BeaconConfig().EpochsPerHistoricalVector), mix)
|
||||
return nil
|
||||
}
|
||||
|
@ -83,10 +83,10 @@ func TestProcessBlockHeader(t *testing.T) {
|
||||
badBlockBodyHash.Body.Attestations = append(badBlockBodyHash.Body.Attestations, &cltypes.Attestation{})
|
||||
|
||||
badStateSlashed := getTestState(t)
|
||||
validator, err := badStateSlashed.ValidatorAt(int(testBlock.ProposerIndex))
|
||||
validator, err := badStateSlashed.ValidatorForValidatorIndex(int(testBlock.ProposerIndex))
|
||||
require.NoError(t, err)
|
||||
validator.Slashed = true
|
||||
badStateSlashed.SetValidatorAt(int(testBlock.ProposerIndex), validator)
|
||||
badStateSlashed.SetValidatorAtIndex(int(testBlock.ProposerIndex), validator)
|
||||
|
||||
testCases := []struct {
|
||||
description string
|
||||
@ -160,10 +160,10 @@ func TestProcessRandao(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get proposer index: %v", err)
|
||||
}
|
||||
validator, err := testStateSuccess.ValidatorAt(int(propInd))
|
||||
validator, err := testStateSuccess.ValidatorForValidatorIndex(int(propInd))
|
||||
require.NoError(t, err)
|
||||
validator.PublicKey = testPublicKeyRandao
|
||||
testStateSuccess.SetValidatorAt(int(propInd), validator)
|
||||
testStateSuccess.SetValidatorAtIndex(int(propInd), validator)
|
||||
testBlock := getTestBlock(t)
|
||||
testBlock.Body.RandaoReveal = testSignatureRandao
|
||||
testBody := testBlock.Body
|
||||
|
@ -1,7 +1,6 @@
|
||||
package transition
|
||||
|
||||
import (
|
||||
"github.com/ledgerwatch/erigon/cl/cltypes"
|
||||
"github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state"
|
||||
)
|
||||
|
||||
@ -24,6 +23,5 @@ func ProcessRandaoMixesReset(state *state.BeaconState) {
|
||||
}
|
||||
|
||||
func ProcessParticipationFlagUpdates(state *state.BeaconState) {
|
||||
state.SetPreviousEpochParticipation(state.CurrentEpochParticipation())
|
||||
state.SetCurrentEpochParticipation(make([]cltypes.ParticipationFlags, len(state.Validators())))
|
||||
state.ResetEpochParticipation()
|
||||
}
|
||||
|
@ -64,9 +64,8 @@ func SpawnStageBeaconsBlocks(cfg StageBeaconsBlockCfg, s *stagedsync.StageState,
|
||||
|
||||
log.Info(fmt.Sprintf("[%s] Started", s.LogPrefix()), "start", progress, "target", targetSlot)
|
||||
cfg.downloader.SetHighestProcessedSlot(progress)
|
||||
if cfg.downloader.HighestProcessedRoot() == (libcommon.Hash{}) {
|
||||
cfg.downloader.SetHighestProcessedRoot(lastRoot)
|
||||
}
|
||||
cfg.downloader.SetHighestProcessedRoot(lastRoot)
|
||||
|
||||
cfg.downloader.SetTargetSlot(targetSlot)
|
||||
cfg.downloader.SetLimitSegmentsLength(1024)
|
||||
// On new blocks we just check slot sequencing for now :)
|
||||
|
Loading…
Reference in New Issue
Block a user