diff --git a/cmd/ef-tests-cl/consensus_tests/sanity.go b/cmd/ef-tests-cl/consensus_tests/sanity.go index 0aaf9abf403..f788fefe5e0 100644 --- a/cmd/ef-tests-cl/consensus_tests/sanity.go +++ b/cmd/ef-tests-cl/consensus_tests/sanity.go @@ -95,7 +95,6 @@ func testSanityFunction(context testContext) error { if err != nil { break } - changes = append(changes, testState.StopCollectingReverseChangeSet()) } if err != nil { return err diff --git a/cmd/erigon-cl/core/beacon_changeset/reverse_beacon_state_changeset.go b/cmd/erigon-cl/core/beacon_changeset/reverse_beacon_state_changeset.go index 3d33fcf97e0..bb49d7458f2 100644 --- a/cmd/erigon-cl/core/beacon_changeset/reverse_beacon_state_changeset.go +++ b/cmd/erigon-cl/core/beacon_changeset/reverse_beacon_state_changeset.go @@ -46,9 +46,11 @@ type ReverseBeaconStateChangeSet struct { ExitEpochChange *ListChangeSet[uint64] WithdrawalEpochChange *ListChangeSet[uint64] // Efficient unwinding on reset (only applicable at epoch boundaries) - PreviousEpochParticipationAtReset cltypes.ParticipationFlagsList - CurrentEpochParticipationAtReset cltypes.ParticipationFlagsList - Eth1DataVotesAtReset []*cltypes.Eth1Data + previousEpochParticipationAtReset cltypes.ParticipationFlagsList + currentEpochParticipationAtReset cltypes.ParticipationFlagsList + eth1DataVotesAtReset []*cltypes.Eth1Data + wasEth1DataVotesReset bool + wasEpochParticipationReset bool } func (r *ReverseBeaconStateChangeSet) OnSlotChange(prevSlot uint64) { @@ -176,25 +178,9 @@ func (r *ReverseBeaconStateChangeSet) HasValidatorSetNotChanged(validatorSetLeng 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) { + if r.HistoricalSummaryChange.Empty() && r.HistoricalSummaryChange.ListLength() == len(output) { return } changed = true @@ -217,12 +203,12 @@ func (r *ReverseBeaconStateChangeSet) CompactChanges() { r.SlashingsChanges.CompactChangesReverse() r.RandaoMixesChanges.CompactChangesReverse() r.BalancesChanges.CompactChangesReverse() - if len(r.Eth1DataVotesAtReset) > 0 { + if len(r.eth1DataVotesAtReset) > 0 { r.Eth1DataVotesChanges = nil } else { r.Eth1DataVotesChanges.CompactChangesReverse() } - if len(r.PreviousEpochParticipationAtReset) > 0 { + if len(r.previousEpochParticipationAtReset) > 0 { r.PreviousEpochParticipationChanges = nil r.CurrentEpochParticipationChanges = nil } else { @@ -239,3 +225,55 @@ func (r *ReverseBeaconStateChangeSet) CompactChanges() { r.SlashedChange.CompactChangesReverse() r.WithdrawalEpochChange.CompactChangesReverse() } + +func (r *ReverseBeaconStateChangeSet) ReportVotesReset(previousVotes []*cltypes.Eth1Data) { + if r.wasEth1DataVotesReset { + return + } + // Copy the slice over + for _, vote := range previousVotes { + copyVote := *vote + r.eth1DataVotesAtReset = append(r.eth1DataVotesAtReset, ©Vote) + } + r.wasEth1DataVotesReset = true +} + +func (r *ReverseBeaconStateChangeSet) ReportEpochParticipationReset(prevParticipation, currParticpation cltypes.ParticipationFlagsList) { + if r.wasEpochParticipationReset { + return + } + r.previousEpochParticipationAtReset = prevParticipation.Copy() + r.currentEpochParticipationAtReset = currParticpation.Copy() + r.wasEpochParticipationReset = true +} + +func (r *ReverseBeaconStateChangeSet) ApplyEth1DataVotesChanges(initialVotes []*cltypes.Eth1Data) (output []*cltypes.Eth1Data, changed bool) { + if r.wasEth1DataVotesReset { + return r.eth1DataVotesAtReset, true + } + output = initialVotes + 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, initialVotes) + } + r.Eth1DataVotesChanges.ChangesWithHandler(func(value cltypes.Eth1Data, index int) { + *output[index] = value + }) + return +} + +func (r *ReverseBeaconStateChangeSet) ApplyEpochParticipationChanges( + previousEpochParticipation cltypes.ParticipationFlagsList, + currentEpochParticipation cltypes.ParticipationFlagsList) (newPreviousEpochParticipation cltypes.ParticipationFlagsList, newCurrentEpochParticipation cltypes.ParticipationFlagsList, + previousParticipationChanged bool, currentParticipationChanged bool) { + if r.wasEpochParticipationReset { + return r.previousEpochParticipationAtReset, r.currentEpochParticipationAtReset, true, true + } + newPreviousEpochParticipation, previousParticipationChanged = r.PreviousEpochParticipationChanges.ApplyChanges(previousEpochParticipation) + newCurrentEpochParticipation, currentParticipationChanged = r.CurrentEpochParticipationChanges.ApplyChanges(currentEpochParticipation) + return +} diff --git a/cmd/erigon-cl/core/state/changeset.go b/cmd/erigon-cl/core/state/changeset.go index 36b489895da..02ee4398ee2 100644 --- a/cmd/erigon-cl/core/state/changeset.go +++ b/cmd/erigon-cl/core/state/changeset.go @@ -138,37 +138,27 @@ func (b *BeaconState) RevertWithChangeset(changeset *beacon_changeset.ReverseBea 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 + // Process votes changes + b.eth1DataVotes, touched = changeset.ApplyEth1DataVotesChanges(b.eth1DataVotes) + if touched { 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 { + // Process epoch participation changes + var touchedPreviousEpochParticipation, touchedCurrentEpochParticipation bool + b.previousEpochParticipation, b.currentEpochParticipation, + touchedPreviousEpochParticipation, + touchedCurrentEpochParticipation = changeset.ApplyEpochParticipationChanges(b.previousEpochParticipation, b.currentEpochParticipation) + if touchedPreviousEpochParticipation { b.touchedLeaves[PreviousEpochParticipationLeafIndex] = true + } + if touchedCurrentEpochParticipation { b.touchedLeaves[CurrentEpochParticipationLeafIndex] = true - b.previousEpochParticipation = changeset.PreviousEpochParticipationAtReset.Copy() - b.currentEpochParticipation = changeset.CurrentEpochParticipationAtReset.Copy() } - + // Process inactivity scores changes. b.inactivityScores, touched = changeset.InactivityScoresChanges.ApplyChanges(b.inactivityScores) if touched { b.touchedLeaves[InactivityScoresLeafIndex] = true @@ -243,17 +233,18 @@ func (b *BeaconState) RevertWithChangeset(changeset *beacon_changeset.ReverseBea } 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 } + b.totalActiveBalanceCache = nil + b.committeeCache.Purge() for epochToBeRemoved := beforeEpoch; epochToBeRemoved < epoch+1; beforeEpoch++ { + b.activeValidatorsCache.Remove(epochToBeRemoved) b.shuffledSetsCache.Remove(b.GetSeed(epochToBeRemoved, b.beaconConfig.DomainBeaconAttester)) b.activeValidatorsCache.Remove(epochToBeRemoved) } diff --git a/cmd/erigon-cl/core/state/setters.go b/cmd/erigon-cl/core/state/setters.go index b9d3386c3f8..8d7caf85cb6 100644 --- a/cmd/erigon-cl/core/state/setters.go +++ b/cmd/erigon-cl/core/state/setters.go @@ -125,7 +125,7 @@ func (b *BeaconState) AddEth1DataVote(vote *cltypes.Eth1Data) { func (b *BeaconState) ResetEth1DataVotes() { if b.reverseChangeset != nil { - b.reverseChangeset.Eth1DataVotesAtReset = b.eth1DataVotes + b.reverseChangeset.ReportVotesReset(b.eth1DataVotes) } b.touchedLeaves[Eth1DataVotesLeafIndex] = true b.eth1DataVotes = nil @@ -213,10 +213,8 @@ func (b *BeaconState) SetValidatorAtIndex(index int, validator *cltypes.Validato } 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() + if b.reverseChangeset != nil { + b.reverseChangeset.ReportEpochParticipationReset(b.previousEpochParticipation, b.currentEpochParticipation) } b.touchedLeaves[PreviousEpochParticipationLeafIndex] = true b.touchedLeaves[CurrentEpochParticipationLeafIndex] = true diff --git a/cmd/erigon-cl/forkchoice/fork_graph/fork_graph.go b/cmd/erigon-cl/forkchoice/fork_graph/fork_graph.go new file mode 100644 index 00000000000..f6762072744 --- /dev/null +++ b/cmd/erigon-cl/forkchoice/fork_graph/fork_graph.go @@ -0,0 +1,221 @@ +package fork_graph + +import ( + "fmt" + + libcommon "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon/cl/cltypes" + "github.com/ledgerwatch/erigon/cmd/erigon-cl/core/beacon_changeset" + "github.com/ledgerwatch/erigon/cmd/erigon-cl/core/state" + "github.com/ledgerwatch/erigon/cmd/erigon-cl/core/transition" + "github.com/ledgerwatch/log/v3" +) + +type ChainSegmentInsertionResult uint + +const ( + Success ChainSegmentInsertionResult = 0 + InvalidBlock ChainSegmentInsertionResult = 1 + MissingSegment ChainSegmentInsertionResult = 2 + BelowAnchor ChainSegmentInsertionResult = 3 + LogisticError ChainSegmentInsertionResult = 4 +) + +const maxGraphExtension = 512 + +/* +* The state store process is related to graph theory in the sense that the Ethereum blockchain can be thought of as a directed graph, +* where each block represents a node and the links between blocks represent directed edges. +* In this context, rolling back the state of Ethereum to a previous state can be thought of as traversing the graph in reverse, +* from the current state to a previous state. +* The process of reverting the state involves undoing the changes made in the blocks that have been added to the blockchain since the previous state. +* This can be thought of as "reversing the edges" in the graph, effectively undoing the changes made to the state of Ethereum. +* By thinking of the Ethereum blockchain as a graph, we can use graph theory concepts, such as traversal algorithms, +* to analyze and manipulate the state of the blockchain. + */ + +// ForkGraph is our graph for ETH 2.0 consensus forkchoice. Each node is a (block root, changes) pair and +// each edge is the path described as (prevBlockRoot, currBlockRoot). if we want to go forward we use blocks. +type ForkGraph struct { + inverseEdges map[inverseForkStoreEdge]*beacon_changeset.ReverseBeaconStateChangeSet + forwardEdges map[libcommon.Hash]*cltypes.SignedBeaconBlock + farthestExtendingPath map[libcommon.Hash]bool // The longest path is used as the "canonical" + badBlocks map[libcommon.Hash]bool // blocks that are invalid and that leads to automatic fail of extension. + lastState *state.BeaconState + // Cap for how farther we can reorg (initial state slot) + anchorSlot uint64 +} + +// StateStoreEdge is the path beetwen 2 nodes unidirectionally. +type inverseForkStoreEdge struct { + destinationStateBlockRoot libcommon.Hash + sourceStateBlockRoot libcommon.Hash + sourceSlot uint64 // Used for cleanups +} + +// Initialize fork graph with a new state +func New(anchorState *state.BeaconState) *ForkGraph { + return &ForkGraph{ + // Bidirectional edges + inverseEdges: make(map[inverseForkStoreEdge]*beacon_changeset.ReverseBeaconStateChangeSet), + forwardEdges: make(map[libcommon.Hash]*cltypes.SignedBeaconBlock), + farthestExtendingPath: make(map[libcommon.Hash]bool), + badBlocks: make(map[libcommon.Hash]bool), + lastState: anchorState, + // Slots configuration + anchorSlot: anchorState.Slot(), + } +} + +// Add a new node and edge to the graph +func (f *ForkGraph) AddChainSegment(signedBlock *cltypes.SignedBeaconBlock) (ChainSegmentInsertionResult, error) { + f.cleanOldNodesAndEdges() + block := signedBlock.Block + blockRoot, err := block.HashSSZ() + if err != nil { + return LogisticError, err + } + + if _, ok := f.forwardEdges[blockRoot]; ok { + return Success, nil + } + // Blocks below anchors are invalid. + if block.Slot <= f.anchorSlot { + log.Debug("block below anchor slot", "slot", block.Slot, "hash", libcommon.Hash(blockRoot)) + f.badBlocks[blockRoot] = true + return BelowAnchor, nil + } + // Check if block being process right now was marked as invalid. + if invalid, ok := f.badBlocks[blockRoot]; ok && invalid { + log.Debug("block has invalid parent", "slot", block.Slot, "hash", libcommon.Hash(blockRoot)) + f.badBlocks[blockRoot] = true + return InvalidBlock, nil + } + currentBlockRoot, err := f.lastState.BlockRoot() + if err != nil { + return LogisticError, err + } + // Check if it extend the farthest state. + if currentBlockRoot == block.ParentRoot { + f.lastState.StartCollectingReverseChangeSet() + // Execute the state + if err := transition.TransitionState(f.lastState, signedBlock /*fullValidation=*/, true); err != nil { + changeset := f.lastState.StopCollectingReverseChangeSet() + // Revert bad block changes + f.lastState.RevertWithChangeset(changeset) + // Add block to list of invalid blocks + log.Debug("Invalid beacon block", "reason", err) + f.badBlocks[blockRoot] = true + return InvalidBlock, nil + } + // if it is finished then update the graph + f.inverseEdges[inverseForkStoreEdge{ + destinationStateBlockRoot: block.ParentRoot, + sourceStateBlockRoot: blockRoot, + sourceSlot: block.Slot, + }] = f.lastState.StopCollectingReverseChangeSet() + f.forwardEdges[blockRoot] = signedBlock + f.farthestExtendingPath[blockRoot] = true + return Success, nil + } + // collect all blocks beetwen greatest extending node path and block. + blockRootsFromFarthestExtendingPath := []libcommon.Hash{} + // Use the parent root as a reverse iterator. + currentIteratorRoot := block.ParentRoot + // try and find the point of recconection + for _, ok := f.farthestExtendingPath[currentIteratorRoot]; !ok; { + fmt.Println(currentIteratorRoot) + currentBlock, isSegmentPresent := f.forwardEdges[currentIteratorRoot] + if !isSegmentPresent { + return MissingSegment, nil + } + currentRoot, err := currentBlock.Block.HashSSZ() + if err != nil { + return LogisticError, err + } + blockRootsFromFarthestExtendingPath = append(blockRootsFromFarthestExtendingPath, currentRoot) + } + // Initalize edge. + edge := inverseForkStoreEdge{ + sourceStateBlockRoot: currentBlockRoot, + destinationStateBlockRoot: f.lastState.LatestBlockHeader().ParentRoot, + sourceSlot: f.lastState.Slot(), + } + inverselyTraversedRoots := []libcommon.Hash{currentBlockRoot} + + // Unwind to the recconection root. + for edge.sourceStateBlockRoot != currentIteratorRoot { + changeset, isChangesetPreset := f.inverseEdges[edge] + if !isChangesetPreset { + return MissingSegment, nil + } + f.lastState.RevertWithChangeset(changeset) + // Recompute currentBlockRoot + currentBlockRoot, err := f.lastState.BlockRoot() + if err != nil { + return LogisticError, err + } + inverselyTraversedRoots = append(inverselyTraversedRoots, currentBlockRoot) + // go on. + edge = inverseForkStoreEdge{ + sourceStateBlockRoot: currentBlockRoot, + destinationStateBlockRoot: f.lastState.LatestBlockHeader().ParentRoot, + sourceSlot: f.lastState.Slot(), + } + } + // Traverse the graph forward now (the nodes are in reverse order). + for i := len(blockRootsFromFarthestExtendingPath) - 1; i >= 0; i-- { + currentBlock := f.forwardEdges[blockRootsFromFarthestExtendingPath[i]] + if err := transition.TransitionState(f.lastState, currentBlock, false); err != nil { + log.Debug("Invalid beacon block", "reason", err) + f.badBlocks[blockRoot] = true + return InvalidBlock, nil + } + } + + // If we have a new farthest extended path, update it accordingly. + for _, root := range inverselyTraversedRoots { + delete(f.farthestExtendingPath, root) + } + for _, root := range blockRootsFromFarthestExtendingPath { + f.farthestExtendingPath[root] = true + } + f.lastState.StartCollectingReverseChangeSet() + // Execute the state + if err := transition.TransitionState(f.lastState, signedBlock /*fullValidation=*/, true); err != nil { + // Revert bad block changes + f.lastState.RevertWithChangeset(f.lastState.StopCollectingReverseChangeSet()) + // Add block to list of invalid blocks + log.Debug("Invalid beacon block", "reason", err) + f.badBlocks[blockRoot] = true + return InvalidBlock, nil + } + // if it is finished then update the graph + f.inverseEdges[inverseForkStoreEdge{ + destinationStateBlockRoot: block.ParentRoot, + sourceStateBlockRoot: blockRoot, + sourceSlot: block.Slot, + }] = f.lastState.StopCollectingReverseChangeSet() + f.forwardEdges[blockRoot] = signedBlock + f.farthestExtendingPath[blockRoot] = true + + return Success, nil +} + +// Graph needs to be constant in extension so clean old nodes and edges periodically. +func (f *ForkGraph) cleanOldNodesAndEdges() { + for edge := range f.inverseEdges { + if edge.sourceSlot+maxGraphExtension <= f.lastState.Slot() { + delete(f.inverseEdges, edge) + delete(f.forwardEdges, edge.destinationStateBlockRoot) + delete(f.forwardEdges, edge.sourceStateBlockRoot) + delete(f.farthestExtendingPath, edge.destinationStateBlockRoot) + delete(f.farthestExtendingPath, edge.sourceStateBlockRoot) + } + } +} + +// LastState returns the last state. +func (f *ForkGraph) LastState() *state.BeaconState { + return f.lastState +} diff --git a/cmd/erigon-cl/forkchoice/fork_graph/fork_graph_test.go b/cmd/erigon-cl/forkchoice/fork_graph/fork_graph_test.go new file mode 100644 index 00000000000..051fc9c8ea4 --- /dev/null +++ b/cmd/erigon-cl/forkchoice/fork_graph/fork_graph_test.go @@ -0,0 +1,54 @@ +package fork_graph_test + +import ( + _ "embed" + "testing" + + "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/state" + "github.com/ledgerwatch/erigon/cmd/erigon-cl/forkchoice/fork_graph" + "github.com/stretchr/testify/require" +) + +//go:embed test_data/block_0xe2a37a22d208ebe969c50e9d44bb3f1f63c5404787b9c214a5f2f28fb9835feb.ssz_snappy +var block1 []byte + +//go:embed test_data/block_0xbf1a9ba2d349f6b5a5095bff40bd103ae39177e36018fb1f589953b9eeb0ca9d.ssz_snappy +var block2 []byte + +//go:embed test_data/anchor_state.ssz_snappy +var anchor []byte + +func TestForkGraph(t *testing.T) { + blockA, blockB, blockC := &cltypes.SignedBeaconBlock{}, &cltypes.SignedBeaconBlock{}, &cltypes.SignedBeaconBlock{} + anchorState := state.New(&clparams.MainnetBeaconConfig) + require.NoError(t, utils.DecodeSSZSnappyWithVersion(blockA, block1, int(clparams.Phase0Version))) + require.NoError(t, utils.DecodeSSZSnappyWithVersion(blockB, block2, int(clparams.Phase0Version))) + require.NoError(t, utils.DecodeSSZSnappyWithVersion(blockC, block2, int(clparams.Phase0Version))) + require.NoError(t, utils.DecodeSSZSnappyWithVersion(anchorState, anchor, int(clparams.Phase0Version))) + graph := fork_graph.New(anchorState) + status, err := graph.AddChainSegment(blockA) + require.NoError(t, err) + // Save current state hash + expectedStateHashPostFail, err := graph.LastState().HashSSZ() + require.NoError(t, err) + require.Equal(t, status, fork_graph.Success) + status, err = graph.AddChainSegment(blockB) + require.NoError(t, err) + require.Equal(t, status, fork_graph.Success) + // Try again with same should yield success + status, err = graph.AddChainSegment(blockB) + require.NoError(t, err) + require.Equal(t, status, fork_graph.Success) + // Now make blockC a bad block + blockC.Block.Slot = 8549 // some invalid thing + status, err = graph.AddChainSegment(blockC) + require.NoError(t, err) + require.Equal(t, status, fork_graph.InvalidBlock) + haveStateHashPostFail, err := graph.LastState().HashSSZ() + // Ensure it ends up on correct state. + require.NoError(t, err) + require.Equal(t, expectedStateHashPostFail, haveStateHashPostFail) +} diff --git a/cmd/erigon-cl/forkchoice/fork_graph/test_data/anchor_state.ssz_snappy b/cmd/erigon-cl/forkchoice/fork_graph/test_data/anchor_state.ssz_snappy new file mode 100644 index 00000000000..199026c4c9b Binary files /dev/null and b/cmd/erigon-cl/forkchoice/fork_graph/test_data/anchor_state.ssz_snappy differ diff --git a/cmd/erigon-cl/forkchoice/fork_graph/test_data/block_0xbf1a9ba2d349f6b5a5095bff40bd103ae39177e36018fb1f589953b9eeb0ca9d.ssz_snappy b/cmd/erigon-cl/forkchoice/fork_graph/test_data/block_0xbf1a9ba2d349f6b5a5095bff40bd103ae39177e36018fb1f589953b9eeb0ca9d.ssz_snappy new file mode 100644 index 00000000000..f8b717f492b Binary files /dev/null and b/cmd/erigon-cl/forkchoice/fork_graph/test_data/block_0xbf1a9ba2d349f6b5a5095bff40bd103ae39177e36018fb1f589953b9eeb0ca9d.ssz_snappy differ diff --git a/cmd/erigon-cl/forkchoice/fork_graph/test_data/block_0xe2a37a22d208ebe969c50e9d44bb3f1f63c5404787b9c214a5f2f28fb9835feb.ssz_snappy b/cmd/erigon-cl/forkchoice/fork_graph/test_data/block_0xe2a37a22d208ebe969c50e9d44bb3f1f63c5404787b9c214a5f2f28fb9835feb.ssz_snappy new file mode 100644 index 00000000000..2da9307d0b3 Binary files /dev/null and b/cmd/erigon-cl/forkchoice/fork_graph/test_data/block_0xe2a37a22d208ebe969c50e9d44bb3f1f63c5404787b9c214a5f2f28fb9835feb.ssz_snappy differ diff --git a/cmd/erigon-cl/forkchoice/forkchoice.go b/cmd/erigon-cl/forkchoice/forkchoice.go new file mode 100644 index 00000000000..ef71778dcad --- /dev/null +++ b/cmd/erigon-cl/forkchoice/forkchoice.go @@ -0,0 +1 @@ +package forkchoice diff --git a/cmd/sentinel/cli/flags/defaultFlags.go b/cmd/sentinel/cli/flags/defaultFlags.go index a8488516ac0..dae92e76530 100644 --- a/cmd/sentinel/cli/flags/defaultFlags.go +++ b/cmd/sentinel/cli/flags/defaultFlags.go @@ -18,6 +18,7 @@ var CLDefaultFlags = []cli.Flag{ &GenesisSSZFlag, &CheckpointSyncUrlFlag, &SentinelStaticPeersFlag, + &TransitionChainFlag, } var LCDefaultFlags = []cli.Flag{ @@ -37,5 +38,4 @@ var LCDefaultFlags = []cli.Flag{ &CheckpointSyncUrlFlag, &SentinelStaticPeersFlag, &ErigonPrivateApiFlag, - &TransitionChainFlag, } diff --git a/cmd/sentinel/sentinel/handlers/blocks.go b/cmd/sentinel/sentinel/handlers/blocks.go index 107a7477a7b..0a8a5006e38 100644 --- a/cmd/sentinel/sentinel/handlers/blocks.go +++ b/cmd/sentinel/sentinel/handlers/blocks.go @@ -20,8 +20,10 @@ import ( func (c *ConsensusHandlers) blocksByRangeHandler(stream network.Stream) { log.Trace("Got block by range handler call") + stream.Close() } func (c *ConsensusHandlers) beaconBlocksByRootHandler(stream network.Stream) { log.Trace("Got beacon block by root handler call") + stream.Close() } diff --git a/cmd/sentinel/sentinel/handlers/handlers.go b/cmd/sentinel/sentinel/handlers/handlers.go index c0b12a92dd8..ac5fcbe55db 100644 --- a/cmd/sentinel/sentinel/handlers/handlers.go +++ b/cmd/sentinel/sentinel/handlers/handlers.go @@ -55,13 +55,13 @@ func NewConsensusHandlers(ctx context.Context, db kv.RoDB, host host.Host, ctx: ctx, } c.handlers = map[protocol.ID]network.StreamHandler{ - protocol.ID(communication.PingProtocolV1): c.pingHandler, - protocol.ID(communication.GoodbyeProtocolV1): c.goodbyeHandler, - protocol.ID(communication.StatusProtocolV1): c.statusHandler, - protocol.ID(communication.MetadataProtocolV1): c.metadataV1Handler, - protocol.ID(communication.MetadataProtocolV2): c.metadataV2Handler, - protocol.ID(communication.BeaconBlocksByRangeProtocolV1): c.blocksByRangeHandler, - protocol.ID(communication.BeaconBlocksByRootProtocolV1): c.beaconBlocksByRootHandler, + protocol.ID(communication.PingProtocolV1): c.pingHandler, + protocol.ID(communication.GoodbyeProtocolV1): c.goodbyeHandler, + protocol.ID(communication.StatusProtocolV1): c.statusHandler, + protocol.ID(communication.MetadataProtocolV1): c.metadataV1Handler, + protocol.ID(communication.MetadataProtocolV2): c.metadataV2Handler, + //protocol.ID(communication.BeaconBlocksByRangeProtocolV1): c.blocksByRangeHandler, + //protocol.ID(communication.BeaconBlocksByRootProtocolV1): c.beaconBlocksByRootHandler, } return c }