mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-31 08:08:18 -05:00
Compare commits
10 Commits
e2e-debugg
...
benchmark_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b82ec00778 | ||
|
|
8562af7754 | ||
|
|
42e4d5ea2c | ||
|
|
7414e9abcf | ||
|
|
4db40cafcc | ||
|
|
0587d9077a | ||
|
|
70647aa321 | ||
|
|
d8a36384f8 | ||
|
|
1a5c3cb49d | ||
|
|
572cc82ebc |
@@ -80,9 +80,9 @@ func TestHeadRoot_Nil(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestService_ForkChoiceStore(t *testing.T) {
|
func TestService_ForkChoiceStore(t *testing.T) {
|
||||||
c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New(0, 0)}}
|
c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New()}}
|
||||||
p := c.ForkChoiceStore()
|
p := c.ForkChoiceStore()
|
||||||
require.Equal(t, 0, int(p.FinalizedEpoch()))
|
require.Equal(t, types.Epoch(0), p.FinalizedCheckpoint().Epoch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFinalizedCheckpt_CanRetrieve(t *testing.T) {
|
func TestFinalizedCheckpt_CanRetrieve(t *testing.T) {
|
||||||
@@ -327,7 +327,7 @@ func TestService_HeadGenesisValidatorsRoot(t *testing.T) {
|
|||||||
}
|
}
|
||||||
func TestService_ChainHeads_ProtoArray(t *testing.T) {
|
func TestService_ChainHeads_ProtoArray(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
c := &Service{cfg: &config{ForkChoiceStore: protoarray.New(0, 0)}}
|
c := &Service{cfg: &config{ForkChoiceStore: protoarray.New()}}
|
||||||
state, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0)
|
state, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
||||||
@@ -357,7 +357,7 @@ func TestService_ChainHeads_ProtoArray(t *testing.T) {
|
|||||||
|
|
||||||
func TestService_ChainHeads_DoublyLinkedTree(t *testing.T) {
|
func TestService_ChainHeads_DoublyLinkedTree(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New(0, 0)}}
|
c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New()}}
|
||||||
state, blkRoot, err := prepareForkchoiceState(ctx, 0, [32]byte{}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0)
|
state, blkRoot, err := prepareForkchoiceState(ctx, 0, [32]byte{}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
||||||
@@ -452,7 +452,7 @@ func TestService_IsOptimistic_ProtoArray(t *testing.T) {
|
|||||||
params.OverrideBeaconConfig(cfg)
|
params.OverrideBeaconConfig(cfg)
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
c := &Service{cfg: &config{ForkChoiceStore: protoarray.New(0, 0)}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
c := &Service{cfg: &config{ForkChoiceStore: protoarray.New()}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||||
state, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0)
|
state, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
||||||
@@ -472,7 +472,7 @@ func TestService_IsOptimistic_DoublyLinkedTree(t *testing.T) {
|
|||||||
params.OverrideBeaconConfig(cfg)
|
params.OverrideBeaconConfig(cfg)
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New(0, 0)}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New()}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||||
state, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0)
|
state, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
||||||
@@ -495,7 +495,7 @@ func TestService_IsOptimisticBeforeBellatrix(t *testing.T) {
|
|||||||
|
|
||||||
func TestService_IsOptimisticForRoot_ProtoArray(t *testing.T) {
|
func TestService_IsOptimisticForRoot_ProtoArray(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
c := &Service{cfg: &config{ForkChoiceStore: protoarray.New(0, 0)}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
c := &Service{cfg: &config{ForkChoiceStore: protoarray.New()}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||||
state, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0)
|
state, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
||||||
@@ -510,7 +510,7 @@ func TestService_IsOptimisticForRoot_ProtoArray(t *testing.T) {
|
|||||||
|
|
||||||
func TestService_IsOptimisticForRoot_DoublyLinkedTree(t *testing.T) {
|
func TestService_IsOptimisticForRoot_DoublyLinkedTree(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New(0, 0)}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
c := &Service{cfg: &config{ForkChoiceStore: doublylinkedtree.New()}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||||
state, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0)
|
state, blkRoot, err := prepareForkchoiceState(ctx, 100, [32]byte{'a'}, [32]byte{}, params.BeaconConfig().ZeroHash, 0, 0)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, c.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
||||||
@@ -526,7 +526,7 @@ func TestService_IsOptimisticForRoot_DoublyLinkedTree(t *testing.T) {
|
|||||||
func TestService_IsOptimisticForRoot_DB_ProtoArray(t *testing.T) {
|
func TestService_IsOptimisticForRoot_DB_ProtoArray(t *testing.T) {
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
c := &Service{cfg: &config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New(0, 0)}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
c := &Service{cfg: &config{BeaconDB: beaconDB, ForkChoiceStore: protoarray.New()}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||||
c.head = &head{root: params.BeaconConfig().ZeroHash}
|
c.head = &head{root: params.BeaconConfig().ZeroHash}
|
||||||
b := util.NewBeaconBlock()
|
b := util.NewBeaconBlock()
|
||||||
b.Block.Slot = 10
|
b.Block.Slot = 10
|
||||||
@@ -591,7 +591,7 @@ func TestService_IsOptimisticForRoot_DB_ProtoArray(t *testing.T) {
|
|||||||
func TestService_IsOptimisticForRoot_DB_DoublyLinkedTree(t *testing.T) {
|
func TestService_IsOptimisticForRoot_DB_DoublyLinkedTree(t *testing.T) {
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
c := &Service{cfg: &config{BeaconDB: beaconDB, ForkChoiceStore: doublylinkedtree.New(0, 0)}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
c := &Service{cfg: &config{BeaconDB: beaconDB, ForkChoiceStore: doublylinkedtree.New()}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||||
c.head = &head{root: params.BeaconConfig().ZeroHash}
|
c.head = &head{root: params.BeaconConfig().ZeroHash}
|
||||||
b := util.NewBeaconBlock()
|
b := util.NewBeaconBlock()
|
||||||
b.Block.Slot = 10
|
b.Block.Slot = 10
|
||||||
@@ -655,7 +655,7 @@ func TestService_IsOptimisticForRoot_DB_DoublyLinkedTree(t *testing.T) {
|
|||||||
func TestService_IsOptimisticForRoot_DB_non_canonical(t *testing.T) {
|
func TestService_IsOptimisticForRoot_DB_non_canonical(t *testing.T) {
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
c := &Service{cfg: &config{BeaconDB: beaconDB, ForkChoiceStore: doublylinkedtree.New(0, 0)}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
c := &Service{cfg: &config{BeaconDB: beaconDB, ForkChoiceStore: doublylinkedtree.New()}, head: &head{slot: 101, root: [32]byte{'b'}}}
|
||||||
c.head = &head{root: params.BeaconConfig().ZeroHash}
|
c.head = &head{root: params.BeaconConfig().ZeroHash}
|
||||||
b := util.NewBeaconBlock()
|
b := util.NewBeaconBlock()
|
||||||
b.Block.Slot = 10
|
b.Block.Slot = 10
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||||
doublylinkedtree "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/doubly-linked-tree"
|
doublylinkedtree "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/doubly-linked-tree"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||||
|
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
|
||||||
mockPOW "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing"
|
mockPOW "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing"
|
||||||
bstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
bstate "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||||
@@ -43,7 +44,7 @@ func Test_NotifyForkchoiceUpdate(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, beaconDB.SaveBlock(ctx, altairBlk))
|
require.NoError(t, beaconDB.SaveBlock(ctx, altairBlk))
|
||||||
require.NoError(t, beaconDB.SaveBlock(ctx, bellatrixBlk))
|
require.NoError(t, beaconDB.SaveBlock(ctx, bellatrixBlk))
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
@@ -184,7 +185,7 @@ func Test_NotifyForkchoiceUpdate(t *testing.T) {
|
|||||||
st, _ := util.DeterministicGenesisState(t, 1)
|
st, _ := util.DeterministicGenesisState(t, 1)
|
||||||
require.NoError(t, beaconDB.SaveState(ctx, st, tt.finalizedRoot))
|
require.NoError(t, beaconDB.SaveState(ctx, st, tt.finalizedRoot))
|
||||||
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, tt.finalizedRoot))
|
require.NoError(t, beaconDB.SaveGenesisBlockRoot(ctx, tt.finalizedRoot))
|
||||||
fc := ðpb.Checkpoint{Epoch: 1, Root: tt.finalizedRoot[:]}
|
fc := ðpb.Checkpoint{Epoch: 0, Root: tt.finalizedRoot[:]}
|
||||||
service.store.SetFinalizedCheckptAndPayloadHash(fc, [32]byte{'a'})
|
service.store.SetFinalizedCheckptAndPayloadHash(fc, [32]byte{'a'})
|
||||||
service.store.SetJustifiedCheckptAndPayloadHash(fc, [32]byte{'b'})
|
service.store.SetJustifiedCheckptAndPayloadHash(fc, [32]byte{'b'})
|
||||||
arg := ¬ifyForkchoiceUpdateArg{
|
arg := ¬ifyForkchoiceUpdateArg{
|
||||||
@@ -289,7 +290,7 @@ func Test_NotifyForkchoiceUpdateRecursive(t *testing.T) {
|
|||||||
require.NoError(t, beaconDB.SaveBlock(ctx, wbg))
|
require.NoError(t, beaconDB.SaveBlock(ctx, wbg))
|
||||||
|
|
||||||
// Insert blocks into forkchoice
|
// Insert blocks into forkchoice
|
||||||
fcs := doublylinkedtree.New(0, 0)
|
fcs := doublylinkedtree.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
@@ -326,7 +327,9 @@ func Test_NotifyForkchoiceUpdateRecursive(t *testing.T) {
|
|||||||
fcs.ProcessAttestation(ctx, []uint64{0}, brd, 1)
|
fcs.ProcessAttestation(ctx, []uint64{0}, brd, 1)
|
||||||
fcs.ProcessAttestation(ctx, []uint64{1}, brf, 1)
|
fcs.ProcessAttestation(ctx, []uint64{1}, brf, 1)
|
||||||
fcs.ProcessAttestation(ctx, []uint64{2}, brg, 1)
|
fcs.ProcessAttestation(ctx, []uint64{2}, brg, 1)
|
||||||
headRoot, err := fcs.Head(ctx, bra, []uint64{50, 100, 200})
|
jc := &forkchoicetypes.Checkpoint{Epoch: 0, Root: bra}
|
||||||
|
require.NoError(t, fcs.UpdateJustifiedCheckpoint(jc))
|
||||||
|
headRoot, err := fcs.Head(ctx, []uint64{50, 100, 200})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, brg, headRoot)
|
require.Equal(t, brg, headRoot)
|
||||||
|
|
||||||
@@ -347,7 +350,7 @@ func Test_NotifyForkchoiceUpdateRecursive(t *testing.T) {
|
|||||||
_, err = service.notifyForkchoiceUpdate(ctx, a)
|
_, err = service.notifyForkchoiceUpdate(ctx, a)
|
||||||
require.ErrorIs(t, ErrInvalidPayload, err)
|
require.ErrorIs(t, ErrInvalidPayload, err)
|
||||||
// Ensure Head is D
|
// Ensure Head is D
|
||||||
headRoot, err = fcs.Head(ctx, bra, service.justifiedBalances.balances)
|
headRoot, err = fcs.Head(ctx, service.justifiedBalances.balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, brd, headRoot)
|
require.Equal(t, brd, headRoot)
|
||||||
|
|
||||||
@@ -364,7 +367,7 @@ func Test_NotifyNewPayload(t *testing.T) {
|
|||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
@@ -582,7 +585,7 @@ func Test_NotifyNewPayload_SetOptimisticToValid(t *testing.T) {
|
|||||||
params.OverrideBeaconConfig(cfg)
|
params.OverrideBeaconConfig(cfg)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
@@ -625,7 +628,7 @@ func Test_IsOptimisticCandidateBlock(t *testing.T) {
|
|||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
@@ -827,7 +830,7 @@ func Test_UpdateLastValidatedCheckpoint(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
stateGen := stategen.New(beaconDB)
|
stateGen := stategen.New(beaconDB)
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stateGen),
|
WithStateGen(stateGen),
|
||||||
@@ -927,7 +930,7 @@ func TestService_removeInvalidBlockAndState(t *testing.T) {
|
|||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
WithForkChoiceStore(protoarray.New(0, 0)),
|
WithForkChoiceStore(protoarray.New()),
|
||||||
}
|
}
|
||||||
service, err := NewService(ctx, opts...)
|
service, err := NewService(ctx, opts...)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -983,7 +986,7 @@ func TestService_getPayloadHash(t *testing.T) {
|
|||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
WithForkChoiceStore(protoarray.New(0, 0)),
|
WithForkChoiceStore(protoarray.New()),
|
||||||
}
|
}
|
||||||
service, err := NewService(ctx, opts...)
|
service, err := NewService(ctx, opts...)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice"
|
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice"
|
||||||
doublylinkedtree "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/doubly-linked-tree"
|
doublylinkedtree "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/doubly-linked-tree"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||||
|
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||||
"github.com/prysmaticlabs/prysm/config/features"
|
"github.com/prysmaticlabs/prysm/config/features"
|
||||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||||
@@ -95,16 +96,23 @@ func (s *Service) updateHead(ctx context.Context, balances []uint64) ([32]byte,
|
|||||||
return [32]byte{}, err
|
return [32]byte{}, err
|
||||||
}
|
}
|
||||||
if features.Get().EnableForkChoiceDoublyLinkedTree {
|
if features.Get().EnableForkChoiceDoublyLinkedTree {
|
||||||
s.cfg.ForkChoiceStore = doublylinkedtree.New(j.Epoch, f.Epoch)
|
s.cfg.ForkChoiceStore = doublylinkedtree.New()
|
||||||
} else {
|
} else {
|
||||||
s.cfg.ForkChoiceStore = protoarray.New(j.Epoch, f.Epoch)
|
s.cfg.ForkChoiceStore = protoarray.New()
|
||||||
}
|
}
|
||||||
if err := s.insertBlockToForkChoiceStore(ctx, jb.Block(), headStartRoot, st, f, j); err != nil {
|
if err := s.insertBlockToForkChoiceStore(ctx, jb.Block(), headStartRoot, st, f, j); err != nil {
|
||||||
return [32]byte{}, err
|
return [32]byte{}, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
jc := &forkchoicetypes.Checkpoint{Epoch: j.Epoch, Root: headStartRoot}
|
||||||
return s.cfg.ForkChoiceStore.Head(ctx, headStartRoot, balances)
|
fc := &forkchoicetypes.Checkpoint{Epoch: f.Epoch, Root: s.ensureRootNotZeros(bytesutil.ToBytes32(f.Root))}
|
||||||
|
if err := s.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(jc); err != nil {
|
||||||
|
return [32]byte{}, err
|
||||||
|
}
|
||||||
|
if err := s.cfg.ForkChoiceStore.UpdateFinalizedCheckpoint(fc); err != nil {
|
||||||
|
return [32]byte{}, err
|
||||||
|
}
|
||||||
|
return s.cfg.ForkChoiceStore.Head(ctx, balances)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This saves head info to the local service cache, it also saves the
|
// This saves head info to the local service cache, it also saves the
|
||||||
|
|||||||
@@ -174,10 +174,8 @@ func TestUpdateHead_MissingJustifiedRoot(t *testing.T) {
|
|||||||
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: r[:]}, [32]byte{'a'})
|
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: r[:]}, [32]byte{'a'})
|
||||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{}, [32]byte{'b'})
|
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{}, [32]byte{'b'})
|
||||||
service.store.SetBestJustifiedCheckpt(ðpb.Checkpoint{})
|
service.store.SetBestJustifiedCheckpt(ðpb.Checkpoint{})
|
||||||
headRoot, err := service.updateHead(context.Background(), []uint64{})
|
_, err = service.updateHead(context.Background(), []uint64{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
st, _ := util.DeterministicGenesisState(t, 1)
|
|
||||||
require.NoError(t, service.saveHead(context.Background(), headRoot, wsb, st))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_notifyNewHeadEvent(t *testing.T) {
|
func Test_notifyNewHeadEvent(t *testing.T) {
|
||||||
@@ -613,7 +611,7 @@ func TestUpdateHead_noSavedChanges(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
fcs := doublylinkedtree.New(0, 0)
|
fcs := doublylinkedtree.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
@@ -630,7 +628,7 @@ func TestUpdateHead_noSavedChanges(t *testing.T) {
|
|||||||
require.NoError(t, beaconDB.SaveBlock(ctx, bellatrixBlk))
|
require.NoError(t, beaconDB.SaveBlock(ctx, bellatrixBlk))
|
||||||
fcp := ðpb.Checkpoint{
|
fcp := ðpb.Checkpoint{
|
||||||
Root: bellatrixBlkRoot[:],
|
Root: bellatrixBlkRoot[:],
|
||||||
Epoch: 1,
|
Epoch: 0,
|
||||||
}
|
}
|
||||||
service.store.SetFinalizedCheckptAndPayloadHash(fcp, [32]byte{'a'})
|
service.store.SetFinalizedCheckptAndPayloadHash(fcp, [32]byte{'a'})
|
||||||
service.store.SetJustifiedCheckptAndPayloadHash(fcp, [32]byte{'b'})
|
service.store.SetJustifiedCheckptAndPayloadHash(fcp, [32]byte{'b'})
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
|
|
||||||
func testServiceOptsWithDB(t *testing.T) []Option {
|
func testServiceOptsWithDB(t *testing.T) []Option {
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
return []Option{
|
return []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||||
|
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||||
"github.com/prysmaticlabs/prysm/time/slots"
|
"github.com/prysmaticlabs/prysm/time/slots"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -68,7 +70,8 @@ func (s *Service) NewSlot(ctx context.Context, slot types.Slot) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.store.SetJustifiedCheckptAndPayloadHash(bj, h)
|
s.store.SetJustifiedCheckptAndPayloadHash(bj, h)
|
||||||
if err := s.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(bj); err != nil {
|
if err := s.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(&forkchoicetypes.Checkpoint{
|
||||||
|
Epoch: bj.Epoch, Root: bytesutil.ToBytes32(bj.Root)}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import (
|
|||||||
|
|
||||||
func TestService_newSlot(t *testing.T) {
|
func TestService_newSlot(t *testing.T) {
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ func Test_validateMergeBlock(t *testing.T) {
|
|||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
@@ -152,7 +152,7 @@ func Test_validateMergeBlock(t *testing.T) {
|
|||||||
func Test_getBlkParentHashAndTD(t *testing.T) {
|
func Test_getBlkParentHashAndTD(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
|
||||||
doublylinkedtree "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/doubly-linked-tree"
|
doublylinkedtree "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/doubly-linked-tree"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||||
|
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
|
||||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
@@ -28,7 +29,7 @@ func TestStore_OnAttestation_ErrorConditions_ProtoArray(t *testing.T) {
|
|||||||
|
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithForkChoiceStore(protoarray.New(0, 0)),
|
WithForkChoiceStore(protoarray.New()),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
}
|
}
|
||||||
service, err := NewService(ctx, opts...)
|
service, err := NewService(ctx, opts...)
|
||||||
@@ -140,7 +141,7 @@ func TestStore_OnAttestation_ErrorConditions_DoublyLinkedTree(t *testing.T) {
|
|||||||
|
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithForkChoiceStore(doublylinkedtree.New(0, 0)),
|
WithForkChoiceStore(doublylinkedtree.New()),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
}
|
}
|
||||||
service, err := NewService(ctx, opts...)
|
service, err := NewService(ctx, opts...)
|
||||||
@@ -250,7 +251,7 @@ func TestStore_OnAttestation_Ok_ProtoArray(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
|
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
@@ -278,7 +279,7 @@ func TestStore_OnAttestation_Ok_DoublyLinkedTree(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
|
|
||||||
fcs := doublylinkedtree.New(0, 0)
|
fcs := doublylinkedtree.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
@@ -487,7 +488,7 @@ func TestVerifyFinalizedConsistency_InconsistentRoot_ProtoArray(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
|
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
@@ -522,7 +523,7 @@ func TestVerifyFinalizedConsistency_InconsistentRoot_DoublyLinkedTree(t *testing
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
|
|
||||||
fcs := doublylinkedtree.New(0, 0)
|
fcs := doublylinkedtree.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
@@ -610,7 +611,9 @@ func TestVerifyFinalizedConsistency_IsCanonical(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, service.cfg.ForkChoiceStore.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
_, err = service.cfg.ForkChoiceStore.Head(ctx, r32, []uint64{})
|
jc := &forkchoicetypes.Checkpoint{Epoch: 0, Root: r32}
|
||||||
|
require.NoError(t, service.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(jc))
|
||||||
|
_, err = service.cfg.ForkChoiceStore.Head(ctx, []uint64{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = service.VerifyFinalizedConsistency(context.Background(), r33[:])
|
err = service.VerifyFinalizedConsistency(context.Background(), r33[:])
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
@@ -222,10 +222,12 @@ func (s *Service) onBlock(ctx context.Context, signed interfaces.SignedBeaconBlo
|
|||||||
}
|
}
|
||||||
s.store.SetJustifiedCheckptAndPayloadHash(postState.CurrentJustifiedCheckpoint(), h)
|
s.store.SetJustifiedCheckptAndPayloadHash(postState.CurrentJustifiedCheckpoint(), h)
|
||||||
// Update Forkchoice checkpoints
|
// Update Forkchoice checkpoints
|
||||||
if err := s.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(psj); err != nil {
|
if err := s.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(&forkchoicetypes.Checkpoint{
|
||||||
|
Epoch: psj.Epoch, Root: bytesutil.ToBytes32(psj.Root)}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := s.cfg.ForkChoiceStore.UpdateFinalizedCheckpoint(psf); err != nil {
|
if err := s.cfg.ForkChoiceStore.UpdateFinalizedCheckpoint(&forkchoicetypes.Checkpoint{
|
||||||
|
Epoch: psf.Epoch, Root: bytesutil.ToBytes32(psf.Root)}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -441,8 +443,8 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []interfaces.SignedBeac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
args := &forkchoicetypes.BlockAndCheckpoints{Block: b.Block(),
|
args := &forkchoicetypes.BlockAndCheckpoints{Block: b.Block(),
|
||||||
JustifiedEpoch: jCheckpoints[i].Epoch,
|
JustifiedCheckpoint: jCheckpoints[i],
|
||||||
FinalizedEpoch: fCheckpoints[i].Epoch}
|
FinalizedCheckpoint: fCheckpoints[i]}
|
||||||
pendingNodes[len(blks)-i-1] = args
|
pendingNodes[len(blks)-i-1] = args
|
||||||
s.saveInitSyncBlock(blockRoots[i], b)
|
s.saveInitSyncBlock(blockRoots[i], b)
|
||||||
if err = s.handleBlockAfterBatchVerify(ctx, b, blockRoots[i], fCheckpoints[i], jCheckpoints[i]); err != nil {
|
if err = s.handleBlockAfterBatchVerify(ctx, b, blockRoots[i], fCheckpoints[i], jCheckpoints[i]); err != nil {
|
||||||
@@ -461,7 +463,7 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []interfaces.SignedBeac
|
|||||||
}
|
}
|
||||||
// Prune forkchoice store only if the new finalized checkpoint is higher
|
// Prune forkchoice store only if the new finalized checkpoint is higher
|
||||||
// than the finalized checkpoint in forkchoice store.
|
// than the finalized checkpoint in forkchoice store.
|
||||||
if fCheckpoints[len(blks)-1].Epoch > s.cfg.ForkChoiceStore.FinalizedEpoch() {
|
if fCheckpoints[len(blks)-1].Epoch > s.cfg.ForkChoiceStore.FinalizedCheckpoint().Epoch {
|
||||||
if err := s.cfg.ForkChoiceStore.Prune(ctx, s.ensureRootNotZeros(bytesutil.ToBytes32(fCheckpoints[len(blks)-1].Root))); err != nil {
|
if err := s.cfg.ForkChoiceStore.Prune(ctx, s.ensureRootNotZeros(bytesutil.ToBytes32(fCheckpoints[len(blks)-1].Root))); err != nil {
|
||||||
return errors.Wrap(err, "could not prune fork choice nodes")
|
return errors.Wrap(err, "could not prune fork choice nodes")
|
||||||
}
|
}
|
||||||
@@ -543,7 +545,8 @@ func (s *Service) handleBlockAfterBatchVerify(ctx context.Context, signed interf
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.store.SetFinalizedCheckptAndPayloadHash(fCheckpoint, h)
|
s.store.SetFinalizedCheckptAndPayloadHash(fCheckpoint, h)
|
||||||
if err := s.cfg.ForkChoiceStore.UpdateFinalizedCheckpoint(fCheckpoint); err != nil {
|
if err := s.cfg.ForkChoiceStore.UpdateFinalizedCheckpoint(&forkchoicetypes.Checkpoint{
|
||||||
|
Epoch: fCheckpoint.Epoch, Root: bytesutil.ToBytes32(fCheckpoint.Root)}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -218,7 +218,8 @@ func (s *Service) updateJustified(ctx context.Context, state state.ReadOnlyBeaco
|
|||||||
}
|
}
|
||||||
s.store.SetJustifiedCheckptAndPayloadHash(cpt, h)
|
s.store.SetJustifiedCheckptAndPayloadHash(cpt, h)
|
||||||
// Update forkchoice's justified checkpoint
|
// Update forkchoice's justified checkpoint
|
||||||
if err := s.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(cpt); err != nil {
|
if err := s.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(&forkchoicetypes.Checkpoint{
|
||||||
|
Epoch: cpt.Epoch, Root: bytesutil.ToBytes32(cpt.Root)}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -244,7 +245,8 @@ func (s *Service) updateJustifiedInitSync(ctx context.Context, cp *ethpb.Checkpo
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.store.SetJustifiedCheckptAndPayloadHash(cp, h)
|
s.store.SetJustifiedCheckptAndPayloadHash(cp, h)
|
||||||
return s.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(cp)
|
return s.cfg.ForkChoiceStore.UpdateJustifiedCheckpoint(&forkchoicetypes.Checkpoint{
|
||||||
|
Epoch: cp.Epoch, Root: bytesutil.ToBytes32(cp.Root)})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) updateFinalized(ctx context.Context, cp *ethpb.Checkpoint) error {
|
func (s *Service) updateFinalized(ctx context.Context, cp *ethpb.Checkpoint) error {
|
||||||
@@ -360,7 +362,7 @@ func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk interfa
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
pendingNodes = append(pendingNodes, &forkchoicetypes.BlockAndCheckpoints{Block: blk,
|
pendingNodes = append(pendingNodes, &forkchoicetypes.BlockAndCheckpoints{Block: blk,
|
||||||
JustifiedEpoch: jCheckpoint.Epoch, FinalizedEpoch: fCheckpoint.Epoch})
|
JustifiedCheckpoint: jCheckpoint, FinalizedCheckpoint: fCheckpoint})
|
||||||
// As long as parent node is not in fork choice store, and parent node is in DB.
|
// As long as parent node is not in fork choice store, and parent node is in DB.
|
||||||
root := bytesutil.ToBytes32(blk.ParentRoot())
|
root := bytesutil.ToBytes32(blk.ParentRoot())
|
||||||
for !s.cfg.ForkChoiceStore.HasNode(root) && s.cfg.BeaconDB.HasBlock(ctx, root) {
|
for !s.cfg.ForkChoiceStore.HasNode(root) && s.cfg.BeaconDB.HasBlock(ctx, root) {
|
||||||
@@ -373,8 +375,8 @@ func (s *Service) fillInForkChoiceMissingBlocks(ctx context.Context, blk interfa
|
|||||||
}
|
}
|
||||||
root = bytesutil.ToBytes32(b.Block().ParentRoot())
|
root = bytesutil.ToBytes32(b.Block().ParentRoot())
|
||||||
args := &forkchoicetypes.BlockAndCheckpoints{Block: b.Block(),
|
args := &forkchoicetypes.BlockAndCheckpoints{Block: b.Block(),
|
||||||
JustifiedEpoch: jCheckpoint.Epoch,
|
JustifiedCheckpoint: jCheckpoint,
|
||||||
FinalizedEpoch: fCheckpoint.Epoch}
|
FinalizedCheckpoint: fCheckpoint}
|
||||||
pendingNodes = append(pendingNodes, args)
|
pendingNodes = append(pendingNodes, args)
|
||||||
}
|
}
|
||||||
if len(pendingNodes) == 1 {
|
if len(pendingNodes) == 1 {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ func TestStore_OnBlock_ProtoArray(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
@@ -150,7 +150,7 @@ func TestStore_OnBlock_DoublyLinkedTree(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
fcs := doublylinkedtree.New(0, 0)
|
fcs := doublylinkedtree.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
@@ -253,7 +253,7 @@ func TestStore_OnBlock_ProposerBoostEarly(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
fcs := doublylinkedtree.New(0, 0)
|
fcs := doublylinkedtree.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
WithForkChoiceStore(fcs),
|
WithForkChoiceStore(fcs),
|
||||||
@@ -268,7 +268,7 @@ func TestStore_OnBlock_ProposerBoostEarly(t *testing.T) {
|
|||||||
SecondsIntoSlot: 0,
|
SecondsIntoSlot: 0,
|
||||||
}
|
}
|
||||||
require.NoError(t, service.cfg.ForkChoiceStore.BoostProposerRoot(ctx, args))
|
require.NoError(t, service.cfg.ForkChoiceStore.BoostProposerRoot(ctx, args))
|
||||||
_, err = service.cfg.ForkChoiceStore.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{})
|
_, err = service.cfg.ForkChoiceStore.Head(ctx, []uint64{})
|
||||||
require.ErrorContains(t, "could not apply proposer boost score: invalid proposer boost root", err)
|
require.ErrorContains(t, "could not apply proposer boost score: invalid proposer boost root", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,7 +293,7 @@ func TestStore_OnBlockBatch_ProtoArray(t *testing.T) {
|
|||||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'a'})
|
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'a'})
|
||||||
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'b'})
|
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'b'})
|
||||||
|
|
||||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0)
|
service.cfg.ForkChoiceStore = protoarray.New()
|
||||||
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
service.saveInitSyncBlock(gRoot, wsb)
|
service.saveInitSyncBlock(gRoot, wsb)
|
||||||
@@ -340,7 +340,7 @@ func TestStore_OnBlockBatch_ProtoArray(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
jroot := bytesutil.ToBytes32(jcp.Root)
|
jroot := bytesutil.ToBytes32(jcp.Root)
|
||||||
require.Equal(t, blkRoots[63], jroot)
|
require.Equal(t, blkRoots[63], jroot)
|
||||||
require.Equal(t, types.Epoch(2), service.cfg.ForkChoiceStore.JustifiedEpoch())
|
require.Equal(t, types.Epoch(2), service.cfg.ForkChoiceStore.JustifiedCheckpoint().Epoch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStore_OnBlockBatch_PruneOK(t *testing.T) {
|
func TestStore_OnBlockBatch_PruneOK(t *testing.T) {
|
||||||
@@ -362,7 +362,7 @@ func TestStore_OnBlockBatch_PruneOK(t *testing.T) {
|
|||||||
gRoot, err := genesis.Block.HashTreeRoot()
|
gRoot, err := genesis.Block.HashTreeRoot()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0)
|
service.cfg.ForkChoiceStore = protoarray.New()
|
||||||
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
service.saveInitSyncBlock(gRoot, wsb)
|
service.saveInitSyncBlock(gRoot, wsb)
|
||||||
@@ -427,7 +427,7 @@ func TestStore_OnBlockBatch_DoublyLinkedTree(t *testing.T) {
|
|||||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'a'})
|
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'a'})
|
||||||
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'b'})
|
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'b'})
|
||||||
|
|
||||||
service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0)
|
service.cfg.ForkChoiceStore = doublylinkedtree.New()
|
||||||
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
service.saveInitSyncBlock(gRoot, wsb)
|
service.saveInitSyncBlock(gRoot, wsb)
|
||||||
@@ -474,7 +474,7 @@ func TestStore_OnBlockBatch_DoublyLinkedTree(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
jroot := bytesutil.ToBytes32(jcp.Root)
|
jroot := bytesutil.ToBytes32(jcp.Root)
|
||||||
require.Equal(t, blkRoots[63], jroot)
|
require.Equal(t, blkRoots[63], jroot)
|
||||||
require.Equal(t, types.Epoch(2), service.cfg.ForkChoiceStore.JustifiedEpoch())
|
require.Equal(t, types.Epoch(2), service.cfg.ForkChoiceStore.JustifiedCheckpoint().Epoch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStore_OnBlockBatch_NotifyNewPayload(t *testing.T) {
|
func TestStore_OnBlockBatch_NotifyNewPayload(t *testing.T) {
|
||||||
@@ -496,7 +496,7 @@ func TestStore_OnBlockBatch_NotifyNewPayload(t *testing.T) {
|
|||||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'a'})
|
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'a'})
|
||||||
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'b'})
|
service.store.SetJustifiedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{'b'})
|
||||||
|
|
||||||
service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0)
|
service.cfg.ForkChoiceStore = doublylinkedtree.New()
|
||||||
service.saveInitSyncBlock(gRoot, wsb)
|
service.saveInitSyncBlock(gRoot, wsb)
|
||||||
st, keys := util.DeterministicGenesisState(t, 64)
|
st, keys := util.DeterministicGenesisState(t, 64)
|
||||||
bState := st.Copy()
|
bState := st.Copy()
|
||||||
@@ -577,7 +577,7 @@ func TestShouldUpdateJustified_ReturnFalse_ProtoArray(t *testing.T) {
|
|||||||
opts := testServiceOptsWithDB(t)
|
opts := testServiceOptsWithDB(t)
|
||||||
service, err := NewService(ctx, opts...)
|
service, err := NewService(ctx, opts...)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0)
|
service.cfg.ForkChoiceStore = protoarray.New()
|
||||||
lastJustifiedBlk := util.NewBeaconBlock()
|
lastJustifiedBlk := util.NewBeaconBlock()
|
||||||
lastJustifiedBlk.Block.ParentRoot = bytesutil.PadTo([]byte{'G'}, 32)
|
lastJustifiedBlk.Block.ParentRoot = bytesutil.PadTo([]byte{'G'}, 32)
|
||||||
lastJustifiedRoot, err := lastJustifiedBlk.Block.HashTreeRoot()
|
lastJustifiedRoot, err := lastJustifiedBlk.Block.HashTreeRoot()
|
||||||
@@ -610,7 +610,7 @@ func TestShouldUpdateJustified_ReturnFalse_DoublyLinkedTree(t *testing.T) {
|
|||||||
opts := testServiceOptsWithDB(t)
|
opts := testServiceOptsWithDB(t)
|
||||||
service, err := NewService(ctx, opts...)
|
service, err := NewService(ctx, opts...)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0)
|
service.cfg.ForkChoiceStore = doublylinkedtree.New()
|
||||||
lastJustifiedBlk := util.NewBeaconBlock()
|
lastJustifiedBlk := util.NewBeaconBlock()
|
||||||
lastJustifiedBlk.Block.ParentRoot = bytesutil.PadTo([]byte{'G'}, 32)
|
lastJustifiedBlk.Block.ParentRoot = bytesutil.PadTo([]byte{'G'}, 32)
|
||||||
lastJustifiedRoot, err := lastJustifiedBlk.Block.HashTreeRoot()
|
lastJustifiedRoot, err := lastJustifiedBlk.Block.HashTreeRoot()
|
||||||
@@ -657,7 +657,7 @@ func TestCachedPreState_CanGetFromStateSummary_ProtoArray(t *testing.T) {
|
|||||||
gRoot, err := genesis.Block.HashTreeRoot()
|
gRoot, err := genesis.Block.HashTreeRoot()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{})
|
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{})
|
||||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0)
|
service.cfg.ForkChoiceStore = protoarray.New()
|
||||||
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
service.saveInitSyncBlock(gRoot, wsb)
|
service.saveInitSyncBlock(gRoot, wsb)
|
||||||
@@ -694,7 +694,7 @@ func TestCachedPreState_CanGetFromStateSummary_DoublyLinkedTree(t *testing.T) {
|
|||||||
gRoot, err := genesis.Block.HashTreeRoot()
|
gRoot, err := genesis.Block.HashTreeRoot()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{})
|
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{})
|
||||||
service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0)
|
service.cfg.ForkChoiceStore = doublylinkedtree.New()
|
||||||
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
service.saveInitSyncBlock(gRoot, wsb)
|
service.saveInitSyncBlock(gRoot, wsb)
|
||||||
@@ -728,7 +728,7 @@ func TestCachedPreState_CanGetFromDB(t *testing.T) {
|
|||||||
gRoot, err := genesis.Block.HashTreeRoot()
|
gRoot, err := genesis.Block.HashTreeRoot()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{})
|
service.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Root: gRoot[:]}, [32]byte{})
|
||||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0)
|
service.cfg.ForkChoiceStore = protoarray.New()
|
||||||
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
wsb, err = wrapper.WrappedSignedBeaconBlock(genesis)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
service.saveInitSyncBlock(gRoot, wsb)
|
service.saveInitSyncBlock(gRoot, wsb)
|
||||||
@@ -759,7 +759,7 @@ func TestUpdateJustified_CouldUpdateBest(t *testing.T) {
|
|||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
WithForkChoiceStore(protoarray.New(0, 0)),
|
WithForkChoiceStore(protoarray.New()),
|
||||||
}
|
}
|
||||||
service, err := NewService(ctx, opts...)
|
service, err := NewService(ctx, opts...)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -805,7 +805,7 @@ func TestFillForkChoiceMissingBlocks_CanSave_ProtoArray(t *testing.T) {
|
|||||||
}
|
}
|
||||||
service, err := NewService(ctx, opts...)
|
service, err := NewService(ctx, opts...)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0)
|
service.cfg.ForkChoiceStore = protoarray.New()
|
||||||
|
|
||||||
genesisStateRoot := [32]byte{}
|
genesisStateRoot := [32]byte{}
|
||||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||||
@@ -851,7 +851,7 @@ func TestFillForkChoiceMissingBlocks_CanSave_DoublyLinkedTree(t *testing.T) {
|
|||||||
}
|
}
|
||||||
service, err := NewService(ctx, opts...)
|
service, err := NewService(ctx, opts...)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0)
|
service.cfg.ForkChoiceStore = doublylinkedtree.New()
|
||||||
|
|
||||||
genesisStateRoot := [32]byte{}
|
genesisStateRoot := [32]byte{}
|
||||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||||
@@ -898,7 +898,7 @@ func TestFillForkChoiceMissingBlocks_RootsMatch_ProtoArray(t *testing.T) {
|
|||||||
}
|
}
|
||||||
service, err := NewService(ctx, opts...)
|
service, err := NewService(ctx, opts...)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0)
|
service.cfg.ForkChoiceStore = protoarray.New()
|
||||||
|
|
||||||
genesisStateRoot := [32]byte{}
|
genesisStateRoot := [32]byte{}
|
||||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||||
@@ -947,7 +947,7 @@ func TestFillForkChoiceMissingBlocks_RootsMatch_DoublyLinkedTree(t *testing.T) {
|
|||||||
}
|
}
|
||||||
service, err := NewService(ctx, opts...)
|
service, err := NewService(ctx, opts...)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0)
|
service.cfg.ForkChoiceStore = doublylinkedtree.New()
|
||||||
|
|
||||||
genesisStateRoot := [32]byte{}
|
genesisStateRoot := [32]byte{}
|
||||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||||
@@ -996,7 +996,7 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized_ProtoArray(t *testing.T) {
|
|||||||
}
|
}
|
||||||
service, err := NewService(ctx, opts...)
|
service, err := NewService(ctx, opts...)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0)
|
service.cfg.ForkChoiceStore = protoarray.New()
|
||||||
|
|
||||||
genesisStateRoot := [32]byte{}
|
genesisStateRoot := [32]byte{}
|
||||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||||
@@ -1063,7 +1063,7 @@ func TestFillForkChoiceMissingBlocks_FilterFinalized_DoublyLinkedTree(t *testing
|
|||||||
}
|
}
|
||||||
service, err := NewService(ctx, opts...)
|
service, err := NewService(ctx, opts...)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0)
|
service.cfg.ForkChoiceStore = doublylinkedtree.New()
|
||||||
|
|
||||||
genesisStateRoot := [32]byte{}
|
genesisStateRoot := [32]byte{}
|
||||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||||
@@ -1131,7 +1131,7 @@ func TestFillForkChoiceMissingBlocks_FinalizedSibling_DoublyLinkedTree(t *testin
|
|||||||
}
|
}
|
||||||
service, err := NewService(ctx, opts...)
|
service, err := NewService(ctx, opts...)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
service.cfg.ForkChoiceStore = doublylinkedtree.New(0, 0)
|
service.cfg.ForkChoiceStore = doublylinkedtree.New()
|
||||||
|
|
||||||
genesisStateRoot := [32]byte{}
|
genesisStateRoot := [32]byte{}
|
||||||
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
genesis := blocks.NewGenesisBlock(genesisStateRoot[:])
|
||||||
@@ -1272,7 +1272,7 @@ func TestAncestor_HandleSkipSlot(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
|
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
@@ -1363,7 +1363,7 @@ func TestAncestor_CanUseDB(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
|
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
@@ -1425,7 +1425,7 @@ func TestVerifyBlkDescendant(t *testing.T) {
|
|||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
@@ -1570,7 +1570,7 @@ func TestHandleEpochBoundary_UpdateFirstSlot(t *testing.T) {
|
|||||||
func TestOnBlock_CanFinalize(t *testing.T) {
|
func TestOnBlock_CanFinalize(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
depositCache, err := depositcache.New()
|
depositCache, err := depositcache.New()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
@@ -1626,7 +1626,7 @@ func TestOnBlock_CanFinalize(t *testing.T) {
|
|||||||
func TestOnBlock_NilBlock(t *testing.T) {
|
func TestOnBlock_NilBlock(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
depositCache, err := depositcache.New()
|
depositCache, err := depositcache.New()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
@@ -1645,7 +1645,7 @@ func TestOnBlock_NilBlock(t *testing.T) {
|
|||||||
func TestOnBlock_InvalidSignature(t *testing.T) {
|
func TestOnBlock_InvalidSignature(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
depositCache, err := depositcache.New()
|
depositCache, err := depositcache.New()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
@@ -1686,7 +1686,7 @@ func TestOnBlock_CallNewPayloadAndForkchoiceUpdated(t *testing.T) {
|
|||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
depositCache, err := depositcache.New()
|
depositCache, err := depositcache.New()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
@@ -1924,7 +1924,7 @@ func Test_validateMergeTransitionBlock(t *testing.T) {
|
|||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
@@ -2052,7 +2052,7 @@ func Test_validateMergeTransitionBlock(t *testing.T) {
|
|||||||
func TestService_insertSlashingsToForkChoiceStore(t *testing.T) {
|
func TestService_insertSlashingsToForkChoiceStore(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
@@ -2103,7 +2103,7 @@ func TestService_insertSlashingsToForkChoiceStore(t *testing.T) {
|
|||||||
func TestOnBlock_ProcessBlocksParallel(t *testing.T) {
|
func TestOnBlock_ProcessBlocksParallel(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
depositCache, err := depositcache.New()
|
depositCache, err := depositcache.New()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
@@ -2175,7 +2175,7 @@ func TestOnBlock_ProcessBlocksParallel(t *testing.T) {
|
|||||||
require.NoError(t, service.cfg.BeaconDB.DeleteBlock(ctx, r2))
|
require.NoError(t, service.cfg.BeaconDB.DeleteBlock(ctx, r2))
|
||||||
require.NoError(t, service.cfg.BeaconDB.DeleteBlock(ctx, r3))
|
require.NoError(t, service.cfg.BeaconDB.DeleteBlock(ctx, r3))
|
||||||
require.NoError(t, service.cfg.BeaconDB.DeleteBlock(ctx, r4))
|
require.NoError(t, service.cfg.BeaconDB.DeleteBlock(ctx, r4))
|
||||||
service.cfg.ForkChoiceStore = protoarray.New(0, 0)
|
service.cfg.ForkChoiceStore = protoarray.New()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2183,7 +2183,7 @@ func Test_verifyBlkFinalizedSlot_invalidBlock(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
|
|
||||||
fcs := protoarray.New(0, 0)
|
fcs := protoarray.New()
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ func TestService_ReceiveBlock(t *testing.T) {
|
|||||||
|
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithForkChoiceStore(protoarray.New(0, 0)),
|
WithForkChoiceStore(protoarray.New()),
|
||||||
WithAttestationPool(attestations.NewPool()),
|
WithAttestationPool(attestations.NewPool()),
|
||||||
WithExitPool(voluntaryexits.NewPool()),
|
WithExitPool(voluntaryexits.NewPool()),
|
||||||
WithStateNotifier(&blockchainTesting.MockStateNotifier{RecordEvents: true}),
|
WithStateNotifier(&blockchainTesting.MockStateNotifier{RecordEvents: true}),
|
||||||
@@ -168,7 +168,7 @@ func TestService_ReceiveBlockUpdateHead(t *testing.T) {
|
|||||||
require.NoError(t, beaconDB.SaveState(ctx, genesis, genesisBlockRoot))
|
require.NoError(t, beaconDB.SaveState(ctx, genesis, genesisBlockRoot))
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithForkChoiceStore(protoarray.New(0, 0)),
|
WithForkChoiceStore(protoarray.New()),
|
||||||
WithAttestationPool(attestations.NewPool()),
|
WithAttestationPool(attestations.NewPool()),
|
||||||
WithExitPool(voluntaryexits.NewPool()),
|
WithExitPool(voluntaryexits.NewPool()),
|
||||||
WithStateNotifier(&blockchainTesting.MockStateNotifier{RecordEvents: true}),
|
WithStateNotifier(&blockchainTesting.MockStateNotifier{RecordEvents: true}),
|
||||||
@@ -248,7 +248,7 @@ func TestService_ReceiveBlockBatch(t *testing.T) {
|
|||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
opts := []Option{
|
opts := []Option{
|
||||||
WithDatabase(beaconDB),
|
WithDatabase(beaconDB),
|
||||||
WithForkChoiceStore(protoarray.New(0, 0)),
|
WithForkChoiceStore(protoarray.New()),
|
||||||
WithStateNotifier(&blockchainTesting.MockStateNotifier{RecordEvents: true}),
|
WithStateNotifier(&blockchainTesting.MockStateNotifier{RecordEvents: true}),
|
||||||
WithStateGen(stategen.New(beaconDB)),
|
WithStateGen(stategen.New(beaconDB)),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import (
|
|||||||
f "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice"
|
f "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice"
|
||||||
doublylinkedtree "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/doubly-linked-tree"
|
doublylinkedtree "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/doubly-linked-tree"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
|
||||||
|
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations"
|
"github.com/prysmaticlabs/prysm/beacon-chain/operations/attestations"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings"
|
"github.com/prysmaticlabs/prysm/beacon-chain/operations/slashings"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
"github.com/prysmaticlabs/prysm/beacon-chain/operations/voluntaryexits"
|
||||||
@@ -208,11 +209,20 @@ func (s *Service) StartFromSavedState(saved state.BeaconState) error {
|
|||||||
var forkChoicer f.ForkChoicer
|
var forkChoicer f.ForkChoicer
|
||||||
fRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(finalized.Root))
|
fRoot := s.ensureRootNotZeros(bytesutil.ToBytes32(finalized.Root))
|
||||||
if features.Get().EnableForkChoiceDoublyLinkedTree {
|
if features.Get().EnableForkChoiceDoublyLinkedTree {
|
||||||
forkChoicer = doublylinkedtree.New(justified.Epoch, finalized.Epoch)
|
forkChoicer = doublylinkedtree.New()
|
||||||
} else {
|
} else {
|
||||||
forkChoicer = protoarray.New(justified.Epoch, finalized.Epoch)
|
forkChoicer = protoarray.New()
|
||||||
}
|
}
|
||||||
s.cfg.ForkChoiceStore = forkChoicer
|
s.cfg.ForkChoiceStore = forkChoicer
|
||||||
|
if err := forkChoicer.UpdateJustifiedCheckpoint(&forkchoicetypes.Checkpoint{Epoch: justified.Epoch,
|
||||||
|
Root: bytesutil.ToBytes32(justified.Root)}); err != nil {
|
||||||
|
return errors.Wrap(err, "could not update forkchoice's justified checkpoint")
|
||||||
|
}
|
||||||
|
if err := forkChoicer.UpdateFinalizedCheckpoint(&forkchoicetypes.Checkpoint{Epoch: finalized.Epoch,
|
||||||
|
Root: bytesutil.ToBytes32(finalized.Root)}); err != nil {
|
||||||
|
return errors.Wrap(err, "could not update forkchoice's finalized checkpoint")
|
||||||
|
}
|
||||||
|
|
||||||
st, err := s.cfg.StateGen.StateByRoot(s.ctx, fRoot)
|
st, err := s.cfg.StateGen.StateByRoot(s.ctx, fRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "could not get finalized checkpoint state")
|
return errors.Wrap(err, "could not get finalized checkpoint state")
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ func setupBeaconChain(t *testing.T, beaconDB db.Database) *Service {
|
|||||||
WithAttestationPool(attestations.NewPool()),
|
WithAttestationPool(attestations.NewPool()),
|
||||||
WithP2PBroadcaster(&mockBroadcaster{}),
|
WithP2PBroadcaster(&mockBroadcaster{}),
|
||||||
WithStateNotifier(&mockBeaconNode{}),
|
WithStateNotifier(&mockBeaconNode{}),
|
||||||
WithForkChoiceStore(protoarray.New(0, 0)),
|
WithForkChoiceStore(protoarray.New()),
|
||||||
WithAttestationService(attService),
|
WithAttestationService(attService),
|
||||||
WithStateGen(stateGen),
|
WithStateGen(stateGen),
|
||||||
}
|
}
|
||||||
@@ -505,7 +505,7 @@ func TestHasBlock_ForkChoiceAndDB_ProtoArray(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
s := &Service{
|
s := &Service{
|
||||||
cfg: &config{ForkChoiceStore: protoarray.New(0, 0), BeaconDB: beaconDB},
|
cfg: &config{ForkChoiceStore: protoarray.New(), BeaconDB: beaconDB},
|
||||||
store: &store.Store{},
|
store: &store.Store{},
|
||||||
}
|
}
|
||||||
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}, [32]byte{})
|
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}, [32]byte{})
|
||||||
@@ -526,7 +526,7 @@ func TestHasBlock_ForkChoiceAndDB_DoublyLinkedTree(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(t)
|
beaconDB := testDB.SetupDB(t)
|
||||||
s := &Service{
|
s := &Service{
|
||||||
cfg: &config{ForkChoiceStore: doublylinkedtree.New(0, 0), BeaconDB: beaconDB},
|
cfg: &config{ForkChoiceStore: doublylinkedtree.New(), BeaconDB: beaconDB},
|
||||||
store: &store.Store{},
|
store: &store.Store{},
|
||||||
}
|
}
|
||||||
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}, [32]byte{})
|
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}, [32]byte{})
|
||||||
@@ -599,7 +599,7 @@ func BenchmarkHasBlockForkChoiceStore_ProtoArray(b *testing.B) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(b)
|
beaconDB := testDB.SetupDB(b)
|
||||||
s := &Service{
|
s := &Service{
|
||||||
cfg: &config{ForkChoiceStore: protoarray.New(0, 0), BeaconDB: beaconDB},
|
cfg: &config{ForkChoiceStore: protoarray.New(), BeaconDB: beaconDB},
|
||||||
store: &store.Store{},
|
store: &store.Store{},
|
||||||
}
|
}
|
||||||
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}, [32]byte{})
|
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}, [32]byte{})
|
||||||
@@ -622,7 +622,7 @@ func BenchmarkHasBlockForkChoiceStore_DoublyLinkedTree(b *testing.B) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
beaconDB := testDB.SetupDB(b)
|
beaconDB := testDB.SetupDB(b)
|
||||||
s := &Service{
|
s := &Service{
|
||||||
cfg: &config{ForkChoiceStore: doublylinkedtree.New(0, 0), BeaconDB: beaconDB},
|
cfg: &config{ForkChoiceStore: doublylinkedtree.New(), BeaconDB: beaconDB},
|
||||||
store: &store.Store{},
|
store: &store.Store{},
|
||||||
}
|
}
|
||||||
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}, [32]byte{})
|
s.store.SetFinalizedCheckptAndPayloadHash(ðpb.Checkpoint{Epoch: 0, Root: params.BeaconConfig().ZeroHash[:]}, [32]byte{})
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ go_library(
|
|||||||
],
|
],
|
||||||
deps = [
|
deps = [
|
||||||
"//beacon-chain/core/blocks:go_default_library",
|
"//beacon-chain/core/blocks:go_default_library",
|
||||||
|
"//beacon-chain/core/epoch/precompute:go_default_library",
|
||||||
|
"//beacon-chain/core/transition:go_default_library",
|
||||||
"//beacon-chain/forkchoice:go_default_library",
|
"//beacon-chain/forkchoice:go_default_library",
|
||||||
"//beacon-chain/forkchoice/types:go_default_library",
|
"//beacon-chain/forkchoice/types:go_default_library",
|
||||||
"//beacon-chain/state:go_default_library",
|
"//beacon-chain/state:go_default_library",
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||||
@@ -16,7 +17,7 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
// The head should always start at the finalized block.
|
// The head should always start at the finalized block.
|
||||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err := f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
||||||
|
|
||||||
@@ -46,7 +47,7 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
|||||||
// 2
|
// 2
|
||||||
// |
|
// |
|
||||||
// 3 <- head
|
// 3 <- head
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(3), r, "Incorrect head for with justified epoch at 0")
|
assert.Equal(t, indexToHash(3), r, "Incorrect head for with justified epoch at 0")
|
||||||
|
|
||||||
@@ -58,8 +59,8 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
|||||||
// 2 <- head
|
// 2 <- head
|
||||||
// |
|
// |
|
||||||
// 3
|
// 3
|
||||||
f.store.justifiedEpoch = 1
|
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Root: indexToHash(2), Epoch: 1}
|
||||||
r, err = f.Head(context.Background(), indexToHash(2), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(2), r, "Incorrect head with justified epoch at 1")
|
assert.Equal(t, indexToHash(2), r, "Incorrect head with justified epoch at 1")
|
||||||
|
|
||||||
@@ -71,8 +72,8 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
|||||||
// 2 <- start
|
// 2 <- start
|
||||||
// |
|
// |
|
||||||
// 3 <- head
|
// 3 <- head
|
||||||
f.store.justifiedEpoch = 2
|
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Root: indexToHash(3), Epoch: 2}
|
||||||
r, err = f.Head(context.Background(), indexToHash(3), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(3), r, "Incorrect head with justified epoch at 2")
|
assert.Equal(t, indexToHash(3), r, "Incorrect head with justified epoch at 2")
|
||||||
}
|
}
|
||||||
@@ -82,7 +83,7 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
|||||||
f := setup(0, 0)
|
f := setup(0, 0)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err := f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
||||||
|
|
||||||
@@ -143,7 +144,7 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
|||||||
// 7 8
|
// 7 8
|
||||||
// | |
|
// | |
|
||||||
// 9 10 <-- head
|
// 9 10 <-- head
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(10), r, "Incorrect head with justified epoch at 0")
|
assert.Equal(t, indexToHash(10), r, "Incorrect head with justified epoch at 0")
|
||||||
|
|
||||||
@@ -173,7 +174,7 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
|||||||
// 7 8
|
// 7 8
|
||||||
// | |
|
// | |
|
||||||
// head -> 9 10
|
// head -> 9 10
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(9), r, "Incorrect head with justified epoch at 0")
|
assert.Equal(t, indexToHash(9), r, "Incorrect head with justified epoch at 0")
|
||||||
|
|
||||||
@@ -203,19 +204,21 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
|||||||
// 7 8
|
// 7 8
|
||||||
// | |
|
// | |
|
||||||
// 9 10 <-- head
|
// 9 10 <-- head
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(10), r, "Incorrect head with justified epoch at 0")
|
assert.Equal(t, indexToHash(10), r, "Incorrect head with justified epoch at 0")
|
||||||
|
|
||||||
f.store.justifiedEpoch = 1
|
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 1, Root: indexToHash(1)}
|
||||||
r, err = f.Head(context.Background(), indexToHash(1), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(7), r, "Incorrect head with justified epoch at 0")
|
assert.Equal(t, indexToHash(7), r, "Incorrect head with justified epoch at 0")
|
||||||
}
|
}
|
||||||
|
|
||||||
func setup(justifiedEpoch, finalizedEpoch types.Epoch) *ForkChoice {
|
func setup(justifiedEpoch, finalizedEpoch types.Epoch) *ForkChoice {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
f := New(justifiedEpoch, finalizedEpoch)
|
f := New()
|
||||||
|
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: justifiedEpoch, Root: params.BeaconConfig().ZeroHash}
|
||||||
|
f.store.finalizedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: finalizedEpoch, Root: params.BeaconConfig().ZeroHash}
|
||||||
state, blkRoot, err := prepareForkchoiceState(ctx, 0, params.BeaconConfig().ZeroHash, [32]byte{}, params.BeaconConfig().ZeroHash, justifiedEpoch, finalizedEpoch)
|
state, blkRoot, err := prepareForkchoiceState(ctx, 0, params.BeaconConfig().ZeroHash, [32]byte{}, params.BeaconConfig().ZeroHash, justifiedEpoch, finalizedEpoch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -3,9 +3,12 @@ package doublylinkedtree
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||||
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
|
||||||
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/transition"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice"
|
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice"
|
||||||
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||||
@@ -13,22 +16,22 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||||
pbrpc "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||||
"github.com/prysmaticlabs/prysm/runtime/version"
|
"github.com/prysmaticlabs/prysm/runtime/version"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"go.opencensus.io/trace"
|
"go.opencensus.io/trace"
|
||||||
)
|
)
|
||||||
|
|
||||||
// New initializes a new fork choice store.
|
// New initializes a new fork choice store.
|
||||||
func New(justifiedEpoch, finalizedEpoch types.Epoch) *ForkChoice {
|
func New() *ForkChoice {
|
||||||
s := &Store{
|
s := &Store{
|
||||||
justifiedEpoch: justifiedEpoch,
|
justifiedCheckpoint: &forkchoicetypes.Checkpoint{},
|
||||||
finalizedEpoch: finalizedEpoch,
|
finalizedCheckpoint: &forkchoicetypes.Checkpoint{},
|
||||||
proposerBoostRoot: [32]byte{},
|
proposerBoostRoot: [32]byte{},
|
||||||
nodeByRoot: make(map[[fieldparams.RootLength]byte]*Node),
|
nodeByRoot: make(map[[fieldparams.RootLength]byte]*Node),
|
||||||
nodeByPayload: make(map[[fieldparams.RootLength]byte]*Node),
|
nodeByPayload: make(map[[fieldparams.RootLength]byte]*Node),
|
||||||
slashedIndices: make(map[types.ValidatorIndex]bool),
|
slashedIndices: make(map[types.ValidatorIndex]bool),
|
||||||
pruneThreshold: defaultPruneThreshold,
|
pruneThreshold: defaultPruneThreshold,
|
||||||
}
|
}
|
||||||
|
|
||||||
b := make([]uint64, 0)
|
b := make([]uint64, 0)
|
||||||
@@ -47,7 +50,6 @@ func (f *ForkChoice) NodeCount() int {
|
|||||||
// It firsts computes validator's balance changes then recalculates block tree from leaves to root.
|
// It firsts computes validator's balance changes then recalculates block tree from leaves to root.
|
||||||
func (f *ForkChoice) Head(
|
func (f *ForkChoice) Head(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
justifiedRoot [32]byte,
|
|
||||||
justifiedStateBalances []uint64,
|
justifiedStateBalances []uint64,
|
||||||
) ([32]byte, error) {
|
) ([32]byte, error) {
|
||||||
ctx, span := trace.StartSpan(ctx, "doublyLinkedForkchoice.Head")
|
ctx, span := trace.StartSpan(ctx, "doublyLinkedForkchoice.Head")
|
||||||
@@ -73,10 +75,12 @@ func (f *ForkChoice) Head(
|
|||||||
return [32]byte{}, errors.Wrap(err, "could not apply weight changes")
|
return [32]byte{}, errors.Wrap(err, "could not apply weight changes")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := f.store.treeRootNode.updateBestDescendant(ctx, f.store.justifiedEpoch, f.store.finalizedEpoch); err != nil {
|
jc := f.JustifiedCheckpoint()
|
||||||
|
fc := f.FinalizedCheckpoint()
|
||||||
|
if err := f.store.treeRootNode.updateBestDescendant(ctx, jc.Epoch, fc.Epoch); err != nil {
|
||||||
return [32]byte{}, errors.Wrap(err, "could not update best descendant")
|
return [32]byte{}, errors.Wrap(err, "could not update best descendant")
|
||||||
}
|
}
|
||||||
return f.store.head(ctx, justifiedRoot)
|
return f.store.head(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProcessAttestation processes attestation for vote accounting, it iterates around validator indices
|
// ProcessAttestation processes attestation for vote accounting, it iterates around validator indices
|
||||||
@@ -108,7 +112,7 @@ func (f *ForkChoice) ProcessAttestation(ctx context.Context, validatorIndices []
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InsertNode processes a new block by inserting it to the fork choice store.
|
// InsertNode processes a new block by inserting it to the fork choice store.
|
||||||
func (f *ForkChoice) InsertNode(ctx context.Context, state state.ReadOnlyBeaconState, root [32]byte) error {
|
func (f *ForkChoice) InsertNode(ctx context.Context, state state.BeaconState, root [32]byte) error {
|
||||||
ctx, span := trace.StartSpan(ctx, "doublyLinkedForkchoice.InsertNode")
|
ctx, span := trace.StartSpan(ctx, "doublyLinkedForkchoice.InsertNode")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
@@ -138,6 +142,32 @@ func (f *ForkChoice) InsertNode(ctx context.Context, state state.ReadOnlyBeaconS
|
|||||||
return errInvalidNilCheckpoint
|
return errInvalidNilCheckpoint
|
||||||
}
|
}
|
||||||
finalizedEpoch := fc.Epoch
|
finalizedEpoch := fc.Epoch
|
||||||
|
go func() {
|
||||||
|
// compute unrealized checkpoints at N+2
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
stCopy := state.Copy()
|
||||||
|
copyTime := time.Since(start)
|
||||||
|
nextStart := stCopy.Slot() + params.BeaconConfig().SlotsPerEpoch
|
||||||
|
nextStart = nextStart - nextStart%params.BeaconConfig().SlotsPerEpoch
|
||||||
|
|
||||||
|
stCopy, err := transition.ProcessSlots(ctx, stCopy, nextStart)
|
||||||
|
_ = err
|
||||||
|
transitionTime := time.Since(start)
|
||||||
|
ujc, ufc, err := precompute.UnrealizedCheckpoints(stCopy)
|
||||||
|
_ = err
|
||||||
|
elapsed := time.Since(start)
|
||||||
|
log.WithFields(logrus.Fields{
|
||||||
|
"copyTime": copyTime,
|
||||||
|
"epochTransTime": transitionTime - copyTime,
|
||||||
|
"unrealizedJustTime": elapsed - transitionTime,
|
||||||
|
"totalElapsed": elapsed,
|
||||||
|
"CurrentJustification": jc.Epoch,
|
||||||
|
"UnrealizedJustification": ujc.Epoch,
|
||||||
|
"UnrealizedFinalization": ufc.Epoch,
|
||||||
|
}).Info("Pulled block to N+2")
|
||||||
|
}()
|
||||||
|
|
||||||
return f.store.insert(ctx, slot, root, parentRoot, payloadHash, justifiedEpoch, finalizedEpoch)
|
return f.store.insert(ctx, slot, root, parentRoot, payloadHash, justifiedEpoch, finalizedEpoch)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,20 +356,24 @@ func (f *ForkChoice) SetOptimisticToValid(ctx context.Context, root [fieldparams
|
|||||||
return node.setNodeAndParentValidated(ctx)
|
return node.setNodeAndParentValidated(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// JustifiedEpoch of fork choice store.
|
// JustifiedCheckpoint of fork choice store.
|
||||||
func (f *ForkChoice) JustifiedEpoch() types.Epoch {
|
func (f *ForkChoice) JustifiedCheckpoint() *forkchoicetypes.Checkpoint {
|
||||||
return f.store.justifiedEpoch
|
f.store.checkpointsLock.RLock()
|
||||||
|
defer f.store.checkpointsLock.RUnlock()
|
||||||
|
return f.store.justifiedCheckpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
// FinalizedEpoch of fork choice store.
|
// FinalizedCheckpoint of fork choice store.
|
||||||
func (f *ForkChoice) FinalizedEpoch() types.Epoch {
|
func (f *ForkChoice) FinalizedCheckpoint() *forkchoicetypes.Checkpoint {
|
||||||
return f.store.finalizedEpoch
|
f.store.checkpointsLock.RLock()
|
||||||
|
defer f.store.checkpointsLock.RUnlock()
|
||||||
|
return f.store.finalizedCheckpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ForkChoice) ForkChoiceNodes() []*pbrpc.ForkChoiceNode {
|
func (f *ForkChoice) ForkChoiceNodes() []*ethpb.ForkChoiceNode {
|
||||||
f.store.nodesLock.RLock()
|
f.store.nodesLock.RLock()
|
||||||
defer f.store.nodesLock.RUnlock()
|
defer f.store.nodesLock.RUnlock()
|
||||||
ret := make([]*pbrpc.ForkChoiceNode, len(f.store.nodeByRoot))
|
ret := make([]*ethpb.ForkChoiceNode, len(f.store.nodeByRoot))
|
||||||
return f.store.treeRootNode.rpcNodes(ret)
|
return f.store.treeRootNode.rpcNodes(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,25 +418,25 @@ func (f *ForkChoice) InsertSlashedIndex(_ context.Context, index types.Validator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateJustifiedCheckpoint sets the justified epoch to the given one
|
// UpdateJustifiedCheckpoint sets the justified checkpoint to the given one
|
||||||
func (f *ForkChoice) UpdateJustifiedCheckpoint(jc *pbrpc.Checkpoint) error {
|
func (f *ForkChoice) UpdateJustifiedCheckpoint(jc *forkchoicetypes.Checkpoint) error {
|
||||||
if jc == nil {
|
if jc == nil {
|
||||||
return errInvalidNilCheckpoint
|
return errInvalidNilCheckpoint
|
||||||
}
|
}
|
||||||
f.store.nodesLock.Lock()
|
f.store.checkpointsLock.Lock()
|
||||||
defer f.store.nodesLock.Unlock()
|
defer f.store.checkpointsLock.Unlock()
|
||||||
f.store.justifiedEpoch = jc.Epoch
|
f.store.justifiedCheckpoint = jc
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateFinalizedCheckpoint sets the finalized epoch to the given one
|
// UpdateFinalizedCheckpoint sets the finalized checkpoint to the given one
|
||||||
func (f *ForkChoice) UpdateFinalizedCheckpoint(fc *pbrpc.Checkpoint) error {
|
func (f *ForkChoice) UpdateFinalizedCheckpoint(fc *forkchoicetypes.Checkpoint) error {
|
||||||
if fc == nil {
|
if fc == nil {
|
||||||
return errInvalidNilCheckpoint
|
return errInvalidNilCheckpoint
|
||||||
}
|
}
|
||||||
f.store.nodesLock.Lock()
|
f.store.checkpointsLock.Lock()
|
||||||
defer f.store.nodesLock.Unlock()
|
defer f.store.checkpointsLock.Unlock()
|
||||||
f.store.finalizedEpoch = fc.Epoch
|
f.store.finalizedCheckpoint = fc
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -473,7 +507,7 @@ func (f *ForkChoice) InsertOptimisticChain(ctx context.Context, chain []*forkcho
|
|||||||
}
|
}
|
||||||
if err := f.store.insert(ctx,
|
if err := f.store.insert(ctx,
|
||||||
b.Slot(), r, parentRoot, payloadHash,
|
b.Slot(), r, parentRoot, payloadHash,
|
||||||
chain[i].JustifiedEpoch, chain[i].FinalizedEpoch); err != nil {
|
chain[i].JustifiedCheckpoint.Epoch, chain[i].FinalizedCheckpoint.Epoch); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -211,7 +211,9 @@ func TestForkChoice_IsCanonicalReorg(t *testing.T) {
|
|||||||
require.DeepEqual(t, [32]byte{'3'}, f.store.treeRootNode.bestDescendant.root)
|
require.DeepEqual(t, [32]byte{'3'}, f.store.treeRootNode.bestDescendant.root)
|
||||||
f.store.nodesLock.Unlock()
|
f.store.nodesLock.Unlock()
|
||||||
|
|
||||||
h, err := f.store.head(ctx, [32]byte{'1'})
|
r1 := [32]byte{'1'}
|
||||||
|
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 1, Root: r1}
|
||||||
|
h, err := f.store.head(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.DeepEqual(t, [32]byte{'3'}, h)
|
require.DeepEqual(t, [32]byte{'3'}, h)
|
||||||
require.DeepEqual(t, h, f.store.headNode.root)
|
require.DeepEqual(t, h, f.store.headNode.root)
|
||||||
@@ -296,7 +298,7 @@ func TestForkChoice_RemoveEquivocating(t *testing.T) {
|
|||||||
state, blkRoot, err := prepareForkchoiceState(ctx, 1, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1)
|
state, blkRoot, err := prepareForkchoiceState(ctx, 1, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
head, err := f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{})
|
head, err := f.Head(ctx, []uint64{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, [32]byte{'a'}, head)
|
require.Equal(t, [32]byte{'a'}, head)
|
||||||
|
|
||||||
@@ -307,21 +309,21 @@ func TestForkChoice_RemoveEquivocating(t *testing.T) {
|
|||||||
state, blkRoot, err = prepareForkchoiceState(ctx, 3, [32]byte{'c'}, [32]byte{'a'}, [32]byte{'C'}, 1, 1)
|
state, blkRoot, err = prepareForkchoiceState(ctx, 3, [32]byte{'c'}, [32]byte{'a'}, [32]byte{'C'}, 1, 1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
head, err = f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{})
|
head, err = f.Head(ctx, []uint64{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, [32]byte{'c'}, head)
|
require.Equal(t, [32]byte{'c'}, head)
|
||||||
|
|
||||||
// Insert two attestations for block b, one for c it becomes head
|
// Insert two attestations for block b, one for c it becomes head
|
||||||
f.ProcessAttestation(ctx, []uint64{1, 2}, [32]byte{'b'}, 1)
|
f.ProcessAttestation(ctx, []uint64{1, 2}, [32]byte{'b'}, 1)
|
||||||
f.ProcessAttestation(ctx, []uint64{3}, [32]byte{'c'}, 1)
|
f.ProcessAttestation(ctx, []uint64{3}, [32]byte{'c'}, 1)
|
||||||
head, err = f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300})
|
head, err = f.Head(ctx, []uint64{100, 200, 200, 300})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, [32]byte{'b'}, head)
|
require.Equal(t, [32]byte{'b'}, head)
|
||||||
|
|
||||||
// Process b's slashing, c is now head
|
// Process b's slashing, c is now head
|
||||||
f.InsertSlashedIndex(ctx, 1)
|
f.InsertSlashedIndex(ctx, 1)
|
||||||
require.Equal(t, uint64(200), f.store.nodeByRoot[[32]byte{'b'}].balance)
|
require.Equal(t, uint64(200), f.store.nodeByRoot[[32]byte{'b'}].balance)
|
||||||
head, err = f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300})
|
head, err = f.Head(ctx, []uint64{100, 200, 200, 300})
|
||||||
require.Equal(t, uint64(200), f.store.nodeByRoot[[32]byte{'b'}].weight)
|
require.Equal(t, uint64(200), f.store.nodeByRoot[[32]byte{'b'}].weight)
|
||||||
require.Equal(t, uint64(300), f.store.nodeByRoot[[32]byte{'c'}].weight)
|
require.Equal(t, uint64(300), f.store.nodeByRoot[[32]byte{'c'}].weight)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -330,7 +332,7 @@ func TestForkChoice_RemoveEquivocating(t *testing.T) {
|
|||||||
// Process b's slashing again, should be a noop
|
// Process b's slashing again, should be a noop
|
||||||
f.InsertSlashedIndex(ctx, 1)
|
f.InsertSlashedIndex(ctx, 1)
|
||||||
require.Equal(t, uint64(200), f.store.nodeByRoot[[32]byte{'b'}].balance)
|
require.Equal(t, uint64(200), f.store.nodeByRoot[[32]byte{'b'}].balance)
|
||||||
head, err = f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300})
|
head, err = f.Head(ctx, []uint64{100, 200, 200, 300})
|
||||||
require.Equal(t, uint64(200), f.store.nodeByRoot[[32]byte{'b'}].weight)
|
require.Equal(t, uint64(200), f.store.nodeByRoot[[32]byte{'b'}].weight)
|
||||||
require.Equal(t, uint64(300), f.store.nodeByRoot[[32]byte{'c'}].weight)
|
require.Equal(t, uint64(300), f.store.nodeByRoot[[32]byte{'c'}].weight)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -352,12 +354,14 @@ func TestStore_UpdateCheckpoints(t *testing.T) {
|
|||||||
f := setup(1, 1)
|
f := setup(1, 1)
|
||||||
jr := [32]byte{'j'}
|
jr := [32]byte{'j'}
|
||||||
fr := [32]byte{'f'}
|
fr := [32]byte{'f'}
|
||||||
jc := ðpb.Checkpoint{Root: jr[:], Epoch: 3}
|
jc := &forkchoicetypes.Checkpoint{Root: jr, Epoch: 3}
|
||||||
fc := ðpb.Checkpoint{Root: fr[:], Epoch: 2}
|
fc := &forkchoicetypes.Checkpoint{Root: fr, Epoch: 2}
|
||||||
require.NoError(t, f.UpdateJustifiedCheckpoint(jc))
|
require.NoError(t, f.UpdateJustifiedCheckpoint(jc))
|
||||||
require.NoError(t, f.UpdateFinalizedCheckpoint(fc))
|
require.NoError(t, f.UpdateFinalizedCheckpoint(fc))
|
||||||
require.Equal(t, f.store.justifiedEpoch, jc.Epoch)
|
require.Equal(t, f.store.justifiedCheckpoint.Epoch, jc.Epoch)
|
||||||
require.Equal(t, f.store.finalizedEpoch, fc.Epoch)
|
require.Equal(t, f.store.justifiedCheckpoint.Root, jc.Root)
|
||||||
|
require.Equal(t, f.store.finalizedCheckpoint.Epoch, fc.Epoch)
|
||||||
|
require.Equal(t, f.store.finalizedCheckpoint.Root, fc.Root)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStore_CommonAncestor(t *testing.T) {
|
func TestStore_CommonAncestor(t *testing.T) {
|
||||||
@@ -562,8 +566,10 @@ func TestStore_InsertOptimisticChain(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
wsb, err := wrapper.WrappedSignedBeaconBlock(blk)
|
wsb, err := wrapper.WrappedSignedBeaconBlock(blk)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
blks = append(blks, &forkchoicetypes.BlockAndCheckpoints{Block: wsb.Block(), JustifiedEpoch: 1,
|
blks = append(blks, &forkchoicetypes.BlockAndCheckpoints{Block: wsb.Block(),
|
||||||
FinalizedEpoch: 1})
|
JustifiedCheckpoint: ðpb.Checkpoint{Epoch: 1, Root: params.BeaconConfig().ZeroHash[:]},
|
||||||
|
FinalizedCheckpoint: ðpb.Checkpoint{Epoch: 1, Root: params.BeaconConfig().ZeroHash[:]},
|
||||||
|
})
|
||||||
for i := uint64(2); i < 11; i++ {
|
for i := uint64(2); i < 11; i++ {
|
||||||
blk := util.NewBeaconBlock()
|
blk := util.NewBeaconBlock()
|
||||||
blk.Block.Slot = types.Slot(i)
|
blk.Block.Slot = types.Slot(i)
|
||||||
@@ -571,8 +577,10 @@ func TestStore_InsertOptimisticChain(t *testing.T) {
|
|||||||
blk.Block.ParentRoot = copiedRoot[:]
|
blk.Block.ParentRoot = copiedRoot[:]
|
||||||
wsb, err = wrapper.WrappedSignedBeaconBlock(blk)
|
wsb, err = wrapper.WrappedSignedBeaconBlock(blk)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
blks = append(blks, &forkchoicetypes.BlockAndCheckpoints{Block: wsb.Block(), JustifiedEpoch: 1,
|
blks = append(blks, &forkchoicetypes.BlockAndCheckpoints{Block: wsb.Block(),
|
||||||
FinalizedEpoch: 1})
|
JustifiedCheckpoint: ðpb.Checkpoint{Epoch: 1, Root: params.BeaconConfig().ZeroHash[:]},
|
||||||
|
FinalizedCheckpoint: ðpb.Checkpoint{Epoch: 1, Root: params.BeaconConfig().ZeroHash[:]},
|
||||||
|
})
|
||||||
root, err = blk.Block.HashTreeRoot()
|
root, err = blk.Block.HashTreeRoot()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
// The head should always start at the finalized block.
|
// The head should always start at the finalized block.
|
||||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err := f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if r != params.BeaconConfig().ZeroHash {
|
if r != params.BeaconConfig().ZeroHash {
|
||||||
t.Errorf("Incorrect head with genesis")
|
t.Errorf("Incorrect head with genesis")
|
||||||
@@ -28,7 +28,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
|||||||
state, blkRoot, err := prepareForkchoiceState(context.Background(), 0, indexToHash(2), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1)
|
state, blkRoot, err := prepareForkchoiceState(context.Background(), 0, indexToHash(2), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
|||||||
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1)
|
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
|||||||
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(3), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1)
|
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(3), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
|||||||
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(4), indexToHash(2), params.BeaconConfig().ZeroHash, 1, 1)
|
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(4), indexToHash(2), params.BeaconConfig().ZeroHash, 1, 1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
|||||||
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(5), indexToHash(4), params.BeaconConfig().ZeroHash, 2, 1)
|
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(5), indexToHash(4), params.BeaconConfig().ZeroHash, 2, 1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -92,7 +92,8 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
|||||||
// head -> 4 3
|
// head -> 4 3
|
||||||
// |
|
// |
|
||||||
// 5 <- starting from 5 with justified epoch 0 should error
|
// 5 <- starting from 5 with justified epoch 0 should error
|
||||||
_, err = f.Head(context.Background(), indexToHash(5), balances)
|
f.store.justifiedCheckpoint.Root = indexToHash(5)
|
||||||
|
_, err = f.Head(context.Background(), balances)
|
||||||
wanted := "head at slot 0 with weight 0 is not eligible, finalizedEpoch 1 != 1, justifiedEpoch 2 != 1"
|
wanted := "head at slot 0 with weight 0 is not eligible, finalizedEpoch 1 != 1, justifiedEpoch 2 != 1"
|
||||||
require.ErrorContains(t, wanted, err)
|
require.ErrorContains(t, wanted, err)
|
||||||
|
|
||||||
@@ -104,8 +105,8 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
|||||||
// 4 3
|
// 4 3
|
||||||
// |
|
// |
|
||||||
// 5 <- head
|
// 5 <- head
|
||||||
f.store.justifiedEpoch = 2
|
f.store.justifiedCheckpoint.Epoch = 2
|
||||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(5), r, "Incorrect head for with justified epoch at 2")
|
assert.Equal(t, indexToHash(5), r, "Incorrect head for with justified epoch at 2")
|
||||||
|
|
||||||
@@ -122,7 +123,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
|||||||
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(6), indexToHash(5), params.BeaconConfig().ZeroHash, 2, 1)
|
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(6), indexToHash(5), params.BeaconConfig().ZeroHash, 2, 1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(6), r, "Incorrect head for with justified epoch at 2")
|
assert.Equal(t, indexToHash(6), r, "Incorrect head for with justified epoch at 2")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
f := setup(jEpoch, fEpoch)
|
f := setup(jEpoch, fEpoch)
|
||||||
|
|
||||||
// The head should always start at the finalized block.
|
// The head should always start at the finalized block.
|
||||||
headRoot, err := f.Head(ctx, zeroHash, balances)
|
headRoot, err := f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, zeroHash, headRoot, "Incorrect head with genesis")
|
assert.Equal(t, zeroHash, headRoot, "Incorrect head with genesis")
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
f.ProcessAttestation(ctx, []uint64{0}, newRoot, fEpoch)
|
f.ProcessAttestation(ctx, []uint64{0}, newRoot, fEpoch)
|
||||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
headRoot, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 1")
|
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 1")
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
f.ProcessAttestation(ctx, []uint64{1}, newRoot, fEpoch)
|
f.ProcessAttestation(ctx, []uint64{1}, newRoot, fEpoch)
|
||||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
headRoot, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 2")
|
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 2")
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
f.ProcessAttestation(ctx, []uint64{2}, newRoot, fEpoch)
|
f.ProcessAttestation(ctx, []uint64{2}, newRoot, fEpoch)
|
||||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
headRoot, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 3")
|
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 3")
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
require.NoError(t, f.BoostProposerRoot(ctx, args))
|
require.NoError(t, f.BoostProposerRoot(ctx, args))
|
||||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
headRoot, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 3")
|
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 3")
|
||||||
|
|
||||||
@@ -186,7 +186,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
// Regression: process attestations for C, check that it
|
// Regression: process attestations for C, check that it
|
||||||
// becomes head, we need two attestations to have C.weight = 30 > 24 = D.weight
|
// becomes head, we need two attestations to have C.weight = 30 > 24 = D.weight
|
||||||
f.ProcessAttestation(ctx, []uint64{4, 5}, indexToHash(3), fEpoch)
|
f.ProcessAttestation(ctx, []uint64{4, 5}, indexToHash(3), fEpoch)
|
||||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
headRoot, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(3), headRoot, "Incorrect head for justified epoch at slot 4")
|
assert.Equal(t, indexToHash(3), headRoot, "Incorrect head for justified epoch at slot 4")
|
||||||
|
|
||||||
@@ -195,7 +195,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
f := setup(jEpoch, fEpoch)
|
f := setup(jEpoch, fEpoch)
|
||||||
|
|
||||||
// The head should always start at the finalized block.
|
// The head should always start at the finalized block.
|
||||||
r, err := f.Head(ctx, zeroHash, balances)
|
r, err := f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
||||||
|
|
||||||
@@ -220,7 +220,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
r, err = f.Head(ctx, zeroHash, balances)
|
r, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||||
|
|
||||||
@@ -239,7 +239,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
// Ensure the head is C, the honest block.
|
// Ensure the head is C, the honest block.
|
||||||
r, err = f.Head(ctx, zeroHash, balances)
|
r, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||||
|
|
||||||
@@ -260,7 +260,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
f.ProcessAttestation(ctx, votes, honestBlock, fEpoch)
|
f.ProcessAttestation(ctx, votes, honestBlock, fEpoch)
|
||||||
|
|
||||||
// Ensure the head is STILL C, the honest block, as the honest block had proposer boost.
|
// Ensure the head is STILL C, the honest block, as the honest block had proposer boost.
|
||||||
r, err = f.Head(ctx, zeroHash, balances)
|
r, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||||
})
|
})
|
||||||
@@ -268,7 +268,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
f := setup(jEpoch, fEpoch)
|
f := setup(jEpoch, fEpoch)
|
||||||
|
|
||||||
// The head should always start at the finalized block.
|
// The head should always start at the finalized block.
|
||||||
r, err := f.Head(ctx, zeroHash, balances)
|
r, err := f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
||||||
|
|
||||||
@@ -295,7 +295,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
// Ensure C is the head.
|
// Ensure C is the head.
|
||||||
r, err = f.Head(ctx, zeroHash, balances)
|
r, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||||
|
|
||||||
@@ -314,7 +314,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
// Ensure C is still the head after the malicious proposer reveals their block.
|
// Ensure C is still the head after the malicious proposer reveals their block.
|
||||||
r, err = f.Head(ctx, zeroHash, balances)
|
r, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||||
|
|
||||||
@@ -333,7 +333,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
f.ProcessAttestation(ctx, votes, maliciouslyWithheldBlock, fEpoch)
|
f.ProcessAttestation(ctx, votes, maliciouslyWithheldBlock, fEpoch)
|
||||||
|
|
||||||
// Expect the head to have switched to B.
|
// Expect the head to have switched to B.
|
||||||
r, err = f.Head(ctx, zeroHash, balances)
|
r, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, maliciouslyWithheldBlock, r, "Expected B to become the head")
|
assert.Equal(t, maliciouslyWithheldBlock, r, "Expected B to become the head")
|
||||||
})
|
})
|
||||||
@@ -355,7 +355,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
a := zeroHash
|
a := zeroHash
|
||||||
|
|
||||||
// The head should always start at the finalized block.
|
// The head should always start at the finalized block.
|
||||||
r, err := f.Head(ctx, zeroHash, balances)
|
r, err := f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
||||||
|
|
||||||
@@ -374,7 +374,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
// Ensure C is the head.
|
// Ensure C is the head.
|
||||||
r, err = f.Head(ctx, zeroHash, balances)
|
r, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, c, r, "Incorrect head for justified epoch at slot 2")
|
assert.Equal(t, c, r, "Incorrect head for justified epoch at slot 2")
|
||||||
|
|
||||||
@@ -402,7 +402,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
// Ensure C is still the head.
|
// Ensure C is still the head.
|
||||||
r, err = f.Head(ctx, zeroHash, balances)
|
r, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, c, r, "Incorrect head for justified epoch at slot 2")
|
assert.Equal(t, c, r, "Incorrect head for justified epoch at slot 2")
|
||||||
|
|
||||||
@@ -426,7 +426,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
// D cannot win without a boost.
|
// D cannot win without a boost.
|
||||||
r, err = f.Head(ctx, zeroHash, balances)
|
r, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, c, r, "Expected C to remain the head")
|
assert.Equal(t, c, r, "Expected C to remain the head")
|
||||||
|
|
||||||
@@ -442,7 +442,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
require.NoError(t, f.BoostProposerRoot(ctx, args))
|
require.NoError(t, f.BoostProposerRoot(ctx, args))
|
||||||
|
|
||||||
// Ensure D becomes the head thanks to boosting.
|
// Ensure D becomes the head thanks to boosting.
|
||||||
r, err = f.Head(ctx, zeroHash, balances)
|
r, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, d, r, "Expected D to become the head")
|
assert.Equal(t, d, r, "Expected D to become the head")
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -60,12 +60,12 @@ func (s *Store) PruneThreshold() uint64 {
|
|||||||
|
|
||||||
// head starts from justified root and then follows the best descendant links
|
// head starts from justified root and then follows the best descendant links
|
||||||
// to find the best block for head. This function assumes a lock on s.nodesLock
|
// to find the best block for head. This function assumes a lock on s.nodesLock
|
||||||
func (s *Store) head(ctx context.Context, justifiedRoot [32]byte) ([32]byte, error) {
|
func (s *Store) head(ctx context.Context) ([32]byte, error) {
|
||||||
_, span := trace.StartSpan(ctx, "doublyLinkedForkchoice.head")
|
_, span := trace.StartSpan(ctx, "doublyLinkedForkchoice.head")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
// JustifiedRoot has to be known
|
// JustifiedRoot has to be known
|
||||||
justifiedNode, ok := s.nodeByRoot[justifiedRoot]
|
justifiedNode, ok := s.nodeByRoot[s.justifiedCheckpoint.Root]
|
||||||
if !ok || justifiedNode == nil {
|
if !ok || justifiedNode == nil {
|
||||||
return [32]byte{}, errUnknownJustifiedRoot
|
return [32]byte{}, errUnknownJustifiedRoot
|
||||||
}
|
}
|
||||||
@@ -77,9 +77,9 @@ func (s *Store) head(ctx context.Context, justifiedRoot [32]byte) ([32]byte, err
|
|||||||
bestDescendant = justifiedNode
|
bestDescendant = justifiedNode
|
||||||
}
|
}
|
||||||
|
|
||||||
if !bestDescendant.viableForHead(s.justifiedEpoch, s.finalizedEpoch) {
|
if !bestDescendant.viableForHead(s.justifiedCheckpoint.Epoch, s.finalizedCheckpoint.Epoch) {
|
||||||
return [32]byte{}, fmt.Errorf("head at slot %d with weight %d is not eligible, finalizedEpoch %d != %d, justifiedEpoch %d != %d",
|
return [32]byte{}, fmt.Errorf("head at slot %d with weight %d is not eligible, finalizedEpoch %d != %d, justifiedEpoch %d != %d",
|
||||||
bestDescendant.slot, bestDescendant.weight/10e9, bestDescendant.finalizedEpoch, s.finalizedEpoch, bestDescendant.justifiedEpoch, s.justifiedEpoch)
|
bestDescendant.slot, bestDescendant.weight/10e9, bestDescendant.finalizedEpoch, s.finalizedCheckpoint.Epoch, bestDescendant.justifiedEpoch, s.justifiedCheckpoint.Epoch)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update metrics.
|
// Update metrics.
|
||||||
@@ -134,7 +134,8 @@ func (s *Store) insert(ctx context.Context,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
parent.children = append(parent.children, n)
|
parent.children = append(parent.children, n)
|
||||||
if err := s.treeRootNode.updateBestDescendant(ctx, s.justifiedEpoch, s.finalizedEpoch); err != nil {
|
if err := s.treeRootNode.updateBestDescendant(ctx,
|
||||||
|
s.justifiedCheckpoint.Epoch, s.finalizedCheckpoint.Epoch); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||||
@@ -22,13 +23,13 @@ func TestStore_PruneThreshold(t *testing.T) {
|
|||||||
func TestStore_JustifiedEpoch(t *testing.T) {
|
func TestStore_JustifiedEpoch(t *testing.T) {
|
||||||
j := types.Epoch(100)
|
j := types.Epoch(100)
|
||||||
f := setup(j, j)
|
f := setup(j, j)
|
||||||
require.Equal(t, j, f.JustifiedEpoch())
|
require.Equal(t, j, f.JustifiedCheckpoint().Epoch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStore_FinalizedEpoch(t *testing.T) {
|
func TestStore_FinalizedEpoch(t *testing.T) {
|
||||||
j := types.Epoch(50)
|
j := types.Epoch(50)
|
||||||
f := setup(j, j)
|
f := setup(j, j)
|
||||||
require.Equal(t, j, f.FinalizedEpoch())
|
require.Equal(t, j, f.FinalizedCheckpoint().Epoch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStore_NodeCount(t *testing.T) {
|
func TestStore_NodeCount(t *testing.T) {
|
||||||
@@ -78,7 +79,8 @@ func TestForkChoice_HasNode(t *testing.T) {
|
|||||||
func TestStore_Head_UnknownJustifiedRoot(t *testing.T) {
|
func TestStore_Head_UnknownJustifiedRoot(t *testing.T) {
|
||||||
f := setup(0, 0)
|
f := setup(0, 0)
|
||||||
|
|
||||||
_, err := f.store.head(context.Background(), [32]byte{'a'})
|
f.store.justifiedCheckpoint.Root = [32]byte{'a'}
|
||||||
|
_, err := f.store.head(context.Background())
|
||||||
assert.ErrorContains(t, errUnknownJustifiedRoot.Error(), err)
|
assert.ErrorContains(t, errUnknownJustifiedRoot.Error(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +92,8 @@ func TestStore_Head_Itself(t *testing.T) {
|
|||||||
|
|
||||||
// Since the justified node does not have a best descendant so the best node
|
// Since the justified node does not have a best descendant so the best node
|
||||||
// is itself.
|
// is itself.
|
||||||
h, err := f.store.head(context.Background(), indexToHash(1))
|
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 0, Root: indexToHash(1)}
|
||||||
|
h, err := f.store.head(context.Background())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(1), h)
|
assert.Equal(t, indexToHash(1), h)
|
||||||
}
|
}
|
||||||
@@ -110,7 +113,8 @@ func TestStore_Head_BestDescendant(t *testing.T) {
|
|||||||
state, blkRoot, err = prepareForkchoiceState(context.Background(), 4, indexToHash(4), indexToHash(2), params.BeaconConfig().ZeroHash, 0, 0)
|
state, blkRoot, err = prepareForkchoiceState(context.Background(), 4, indexToHash(4), indexToHash(2), params.BeaconConfig().ZeroHash, 0, 0)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
h, err := f.store.head(context.Background(), indexToHash(1))
|
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 0, Root: indexToHash(1)}
|
||||||
|
h, err := f.store.head(context.Background())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, h, indexToHash(4))
|
require.Equal(t, h, indexToHash(4))
|
||||||
}
|
}
|
||||||
@@ -133,7 +137,9 @@ func TestStore_Insert(t *testing.T) {
|
|||||||
treeRootNode := &Node{slot: 0, root: indexToHash(0)}
|
treeRootNode := &Node{slot: 0, root: indexToHash(0)}
|
||||||
nodeByRoot := map[[32]byte]*Node{indexToHash(0): treeRootNode}
|
nodeByRoot := map[[32]byte]*Node{indexToHash(0): treeRootNode}
|
||||||
nodeByPayload := map[[32]byte]*Node{indexToHash(0): treeRootNode}
|
nodeByPayload := map[[32]byte]*Node{indexToHash(0): treeRootNode}
|
||||||
s := &Store{nodeByRoot: nodeByRoot, treeRootNode: treeRootNode, nodeByPayload: nodeByPayload}
|
jc := &forkchoicetypes.Checkpoint{Epoch: 0}
|
||||||
|
fc := &forkchoicetypes.Checkpoint{Epoch: 0}
|
||||||
|
s := &Store{nodeByRoot: nodeByRoot, treeRootNode: treeRootNode, nodeByPayload: nodeByPayload, justifiedCheckpoint: jc, finalizedCheckpoint: fc}
|
||||||
payloadHash := [32]byte{'a'}
|
payloadHash := [32]byte{'a'}
|
||||||
require.NoError(t, s.insert(context.Background(), 100, indexToHash(100), indexToHash(0), payloadHash, 1, 1))
|
require.NoError(t, s.insert(context.Background(), 100, indexToHash(100), indexToHash(0), payloadHash, 1, 1))
|
||||||
assert.Equal(t, 2, len(s.nodeByRoot), "Did not insert block")
|
assert.Equal(t, 2, len(s.nodeByRoot), "Did not insert block")
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package doublylinkedtree
|
|||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||||
)
|
)
|
||||||
@@ -17,8 +18,8 @@ type ForkChoice struct {
|
|||||||
|
|
||||||
// Store defines the fork choice store which includes block nodes and the last view of checkpoint information.
|
// Store defines the fork choice store which includes block nodes and the last view of checkpoint information.
|
||||||
type Store struct {
|
type Store struct {
|
||||||
justifiedEpoch types.Epoch // latest justified epoch in store.
|
justifiedCheckpoint *forkchoicetypes.Checkpoint // latest justified epoch in store.
|
||||||
finalizedEpoch types.Epoch // latest finalized epoch in store.
|
finalizedCheckpoint *forkchoicetypes.Checkpoint // latest finalized epoch in store.
|
||||||
pruneThreshold uint64 // do not prune tree unless threshold is reached.
|
pruneThreshold uint64 // do not prune tree unless threshold is reached.
|
||||||
proposerBoostRoot [fieldparams.RootLength]byte // latest block root that was boosted after being received in a timely manner.
|
proposerBoostRoot [fieldparams.RootLength]byte // latest block root that was boosted after being received in a timely manner.
|
||||||
previousProposerBoostRoot [fieldparams.RootLength]byte // previous block root that was boosted after being received in a timely manner.
|
previousProposerBoostRoot [fieldparams.RootLength]byte // previous block root that was boosted after being received in a timely manner.
|
||||||
@@ -30,6 +31,7 @@ type Store struct {
|
|||||||
slashedIndices map[types.ValidatorIndex]bool // the list of equivocating validator indices
|
slashedIndices map[types.ValidatorIndex]bool // the list of equivocating validator indices
|
||||||
nodesLock sync.RWMutex
|
nodesLock sync.RWMutex
|
||||||
proposerBoostLock sync.RWMutex
|
proposerBoostLock sync.RWMutex
|
||||||
|
checkpointsLock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// Node defines the individual block which includes its block parent, ancestor and how much weight accounted for it.
|
// Node defines the individual block which includes its block parent, ancestor and how much weight accounted for it.
|
||||||
|
|||||||
@@ -44,11 +44,11 @@ func (f *ForkChoice) UpdateUnrealizedCheckpoints() {
|
|||||||
for _, node := range f.store.nodeByRoot {
|
for _, node := range f.store.nodeByRoot {
|
||||||
node.justifiedEpoch = node.unrealizedJustifiedEpoch
|
node.justifiedEpoch = node.unrealizedJustifiedEpoch
|
||||||
node.finalizedEpoch = node.unrealizedFinalizedEpoch
|
node.finalizedEpoch = node.unrealizedFinalizedEpoch
|
||||||
if node.justifiedEpoch > f.store.justifiedEpoch {
|
if node.justifiedEpoch > f.store.justifiedCheckpoint.Epoch {
|
||||||
f.store.justifiedEpoch = node.justifiedEpoch
|
f.store.justifiedCheckpoint.Epoch = node.justifiedEpoch
|
||||||
}
|
}
|
||||||
if node.finalizedEpoch > f.store.finalizedEpoch {
|
if node.finalizedEpoch > f.store.finalizedCheckpoint.Epoch {
|
||||||
f.store.finalizedEpoch = node.finalizedEpoch
|
f.store.finalizedCheckpoint.Epoch = node.finalizedEpoch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
|
||||||
"github.com/prysmaticlabs/prysm/testing/require"
|
"github.com/prysmaticlabs/prysm/testing/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -80,17 +80,17 @@ func TestStore_LongFork(t *testing.T) {
|
|||||||
|
|
||||||
// Add an attestation to c, it is head
|
// Add an attestation to c, it is head
|
||||||
f.ProcessAttestation(ctx, []uint64{0}, [32]byte{'c'}, 1)
|
f.ProcessAttestation(ctx, []uint64{0}, [32]byte{'c'}, 1)
|
||||||
headRoot, err := f.Head(ctx, [32]byte{}, []uint64{100})
|
headRoot, err := f.Head(ctx, []uint64{100})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, [32]byte{'c'}, headRoot)
|
require.Equal(t, [32]byte{'c'}, headRoot)
|
||||||
|
|
||||||
// D is head even though its weight is lower.
|
// D is head even though its weight is lower.
|
||||||
hr := [32]byte{'d'}
|
ha := [32]byte{'a'}
|
||||||
state, blkRoot, err = prepareForkchoiceState(ctx, 103, hr, [32]byte{'b'}, [32]byte{'D'}, 2, 1)
|
state, blkRoot, err = prepareForkchoiceState(ctx, 103, [32]byte{'d'}, [32]byte{'b'}, [32]byte{'D'}, 2, 1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
require.NoError(t, f.UpdateJustifiedCheckpoint(ðpb.Checkpoint{Epoch: 2, Root: hr[:]}))
|
require.NoError(t, f.UpdateJustifiedCheckpoint(&forkchoicetypes.Checkpoint{Epoch: 2, Root: ha}))
|
||||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
headRoot, err = f.Head(ctx, []uint64{100})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, [32]byte{'d'}, headRoot)
|
require.Equal(t, [32]byte{'d'}, headRoot)
|
||||||
require.Equal(t, uint64(0), f.store.nodeByRoot[[32]byte{'d'}].weight)
|
require.Equal(t, uint64(0), f.store.nodeByRoot[[32]byte{'d'}].weight)
|
||||||
@@ -98,7 +98,7 @@ func TestStore_LongFork(t *testing.T) {
|
|||||||
|
|
||||||
// Update unrealized justification, c becomes head
|
// Update unrealized justification, c becomes head
|
||||||
f.UpdateUnrealizedCheckpoints()
|
f.UpdateUnrealizedCheckpoints()
|
||||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
headRoot, err = f.Head(ctx, []uint64{100})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, [32]byte{'c'}, headRoot)
|
require.Equal(t, [32]byte{'c'}, headRoot)
|
||||||
}
|
}
|
||||||
@@ -157,30 +157,31 @@ func TestStore_NoDeadLock(t *testing.T) {
|
|||||||
|
|
||||||
// Epoch 3
|
// Epoch 3
|
||||||
// Current Head is H
|
// Current Head is H
|
||||||
headRoot, err := f.Head(ctx, [32]byte{}, []uint64{100})
|
headRoot, err := f.Head(ctx, []uint64{100})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, [32]byte{'h'}, headRoot)
|
require.Equal(t, [32]byte{'h'}, headRoot)
|
||||||
require.Equal(t, types.Epoch(0), f.JustifiedEpoch())
|
require.Equal(t, types.Epoch(0), f.JustifiedCheckpoint().Epoch)
|
||||||
|
|
||||||
// Insert Block I, it becomes Head
|
// Insert Block I, it becomes Head
|
||||||
hr := [32]byte{'i'}
|
hr := [32]byte{'i'}
|
||||||
state, blkRoot, err = prepareForkchoiceState(ctx, 108, hr, [32]byte{'f'}, [32]byte{'I'}, 1, 0)
|
state, blkRoot, err = prepareForkchoiceState(ctx, 108, hr, [32]byte{'f'}, [32]byte{'I'}, 1, 0)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
require.NoError(t, f.UpdateJustifiedCheckpoint(ðpb.Checkpoint{Epoch: 1, Root: hr[:]}))
|
ha := [32]byte{'a'}
|
||||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
require.NoError(t, f.UpdateJustifiedCheckpoint(&forkchoicetypes.Checkpoint{Epoch: 1, Root: ha}))
|
||||||
|
headRoot, err = f.Head(ctx, []uint64{100})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, [32]byte{'i'}, headRoot)
|
require.Equal(t, [32]byte{'i'}, headRoot)
|
||||||
require.Equal(t, types.Epoch(1), f.JustifiedEpoch())
|
require.Equal(t, types.Epoch(1), f.JustifiedCheckpoint().Epoch)
|
||||||
require.Equal(t, types.Epoch(0), f.FinalizedEpoch())
|
require.Equal(t, types.Epoch(0), f.FinalizedCheckpoint().Epoch)
|
||||||
|
|
||||||
// Realized Justified checkpoints, H becomes head
|
// Realized Justified checkpoints, H becomes head
|
||||||
f.UpdateUnrealizedCheckpoints()
|
f.UpdateUnrealizedCheckpoints()
|
||||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
headRoot, err = f.Head(ctx, []uint64{100})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, [32]byte{'h'}, headRoot)
|
require.Equal(t, [32]byte{'h'}, headRoot)
|
||||||
require.Equal(t, types.Epoch(2), f.JustifiedEpoch())
|
require.Equal(t, types.Epoch(2), f.JustifiedCheckpoint().Epoch)
|
||||||
require.Equal(t, types.Epoch(1), f.FinalizedEpoch())
|
require.Equal(t, types.Epoch(1), f.FinalizedCheckpoint().Epoch)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Epoch 1 | Epoch 2
|
// Epoch 1 | Epoch 2
|
||||||
@@ -225,10 +226,10 @@ func TestStore_ForkNextEpoch(t *testing.T) {
|
|||||||
|
|
||||||
// Insert an attestation to H, H is head
|
// Insert an attestation to H, H is head
|
||||||
f.ProcessAttestation(ctx, []uint64{0}, [32]byte{'h'}, 1)
|
f.ProcessAttestation(ctx, []uint64{0}, [32]byte{'h'}, 1)
|
||||||
headRoot, err := f.Head(ctx, [32]byte{}, []uint64{100})
|
headRoot, err := f.Head(ctx, []uint64{100})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, [32]byte{'h'}, headRoot)
|
require.Equal(t, [32]byte{'h'}, headRoot)
|
||||||
require.Equal(t, types.Epoch(0), f.JustifiedEpoch())
|
require.Equal(t, types.Epoch(0), f.JustifiedCheckpoint().Epoch)
|
||||||
|
|
||||||
// D arrives late, D is head
|
// D arrives late, D is head
|
||||||
state, blkRoot, err = prepareForkchoiceState(ctx, 103, [32]byte{'d'}, [32]byte{'c'}, [32]byte{'D'}, 0, 0)
|
state, blkRoot, err = prepareForkchoiceState(ctx, 103, [32]byte{'d'}, [32]byte{'c'}, [32]byte{'D'}, 0, 0)
|
||||||
@@ -236,10 +237,10 @@ func TestStore_ForkNextEpoch(t *testing.T) {
|
|||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'d'}, 1))
|
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'d'}, 1))
|
||||||
f.UpdateUnrealizedCheckpoints()
|
f.UpdateUnrealizedCheckpoints()
|
||||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
headRoot, err = f.Head(ctx, []uint64{100})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, [32]byte{'d'}, headRoot)
|
require.Equal(t, [32]byte{'d'}, headRoot)
|
||||||
require.Equal(t, types.Epoch(1), f.JustifiedEpoch())
|
require.Equal(t, types.Epoch(1), f.JustifiedCheckpoint().Epoch)
|
||||||
require.Equal(t, uint64(0), f.store.nodeByRoot[[32]byte{'d'}].weight)
|
require.Equal(t, uint64(0), f.store.nodeByRoot[[32]byte{'d'}].weight)
|
||||||
require.Equal(t, uint64(100), f.store.nodeByRoot[[32]byte{'h'}].weight)
|
require.Equal(t, uint64(100), f.store.nodeByRoot[[32]byte{'h'}].weight)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||||
"github.com/prysmaticlabs/prysm/testing/require"
|
"github.com/prysmaticlabs/prysm/testing/require"
|
||||||
@@ -15,7 +16,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
// The head should always start at the finalized block.
|
// The head should always start at the finalized block.
|
||||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err := f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
||||||
|
|
||||||
@@ -27,7 +28,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -39,7 +40,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -48,7 +49,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
// / \
|
// / \
|
||||||
// 2 1 <- +vote, new head
|
// 2 1 <- +vote, new head
|
||||||
f.ProcessAttestation(context.Background(), []uint64{0}, indexToHash(1), 2)
|
f.ProcessAttestation(context.Background(), []uint64{0}, indexToHash(1), 2)
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(1), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(1), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -57,7 +58,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
// / \
|
// / \
|
||||||
// vote, new head -> 2 1
|
// vote, new head -> 2 1
|
||||||
f.ProcessAttestation(context.Background(), []uint64{1}, indexToHash(2), 2)
|
f.ProcessAttestation(context.Background(), []uint64{1}, indexToHash(2), 2)
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -82,7 +83,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
// |
|
// |
|
||||||
// 3 <- new vote
|
// 3 <- new vote
|
||||||
f.ProcessAttestation(context.Background(), []uint64{0}, indexToHash(3), 3)
|
f.ProcessAttestation(context.Background(), []uint64{0}, indexToHash(3), 3)
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -93,7 +94,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
// |
|
// |
|
||||||
// 3 <- head
|
// 3 <- head
|
||||||
f.ProcessAttestation(context.Background(), []uint64{1}, indexToHash(1), 3)
|
f.ProcessAttestation(context.Background(), []uint64{1}, indexToHash(1), 3)
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(3), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(3), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -109,7 +110,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -127,7 +128,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -188,7 +189,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(6), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(6), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -209,9 +210,9 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
// 8
|
// 8
|
||||||
// |
|
// |
|
||||||
// 9 <- head
|
// 9 <- head
|
||||||
f.store.justifiedEpoch = 2
|
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Root: indexToHash(5), Epoch: 2}
|
||||||
f.store.finalizedEpoch = 2
|
f.store.finalizedCheckpoint = &forkchoicetypes.Checkpoint{Root: indexToHash(5), Epoch: 2}
|
||||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||||
|
|
||||||
@@ -237,7 +238,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||||
|
|
||||||
@@ -246,28 +247,28 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
// The new validators voted for 10.
|
// The new validators voted for 10.
|
||||||
f.ProcessAttestation(context.Background(), []uint64{2, 3, 4}, indexToHash(10), 5)
|
f.ProcessAttestation(context.Background(), []uint64{2, 3, 4}, indexToHash(10), 5)
|
||||||
// The new head should be 10.
|
// The new head should be 10.
|
||||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(10), r, "Incorrect head for with justified epoch at 2")
|
assert.Equal(t, indexToHash(10), r, "Incorrect head for with justified epoch at 2")
|
||||||
|
|
||||||
// Set the balances of the last 2 validators to 0.
|
// Set the balances of the last 2 validators to 0.
|
||||||
balances = []uint64{1, 1, 1, 0, 0}
|
balances = []uint64{1, 1, 1, 0, 0}
|
||||||
// The head should be back to 9.
|
// The head should be back to 9.
|
||||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
// Set the balances back to normal.
|
// Set the balances back to normal.
|
||||||
balances = []uint64{1, 1, 1, 1, 1}
|
balances = []uint64{1, 1, 1, 1, 1}
|
||||||
// The head should be back to 10.
|
// The head should be back to 10.
|
||||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(10), r, "Incorrect head for with justified epoch at 2")
|
assert.Equal(t, indexToHash(10), r, "Incorrect head for with justified epoch at 2")
|
||||||
|
|
||||||
// Remove the last 2 validators.
|
// Remove the last 2 validators.
|
||||||
balances = []uint64{1, 1, 1}
|
balances = []uint64{1, 1, 1}
|
||||||
// The head should be back to 9.
|
// The head should be back to 9.
|
||||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -276,7 +277,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
require.NoError(t, f.store.prune(context.Background(), indexToHash(5)))
|
require.NoError(t, f.store.prune(context.Background(), indexToHash(5)))
|
||||||
assert.Equal(t, 11, len(f.store.nodeByRoot), "Incorrect nodes length after prune")
|
assert.Equal(t, 11, len(f.store.nodeByRoot), "Incorrect nodes length after prune")
|
||||||
|
|
||||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||||
|
|
||||||
@@ -300,7 +301,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
require.NoError(t, f.store.prune(context.Background(), indexToHash(5)))
|
require.NoError(t, f.store.prune(context.Background(), indexToHash(5)))
|
||||||
assert.Equal(t, 5, len(f.store.nodeByRoot), "Incorrect nodes length after prune")
|
assert.Equal(t, 5, len(f.store.nodeByRoot), "Incorrect nodes length after prune")
|
||||||
|
|
||||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||||
|
|
||||||
@@ -318,7 +319,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(11), r, "Incorrect head for with justified epoch at 2")
|
assert.Equal(t, indexToHash(11), r, "Incorrect head for with justified epoch at 2")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,14 +23,14 @@ type ForkChoicer interface {
|
|||||||
|
|
||||||
// HeadRetriever retrieves head root and optimistic info of the current chain.
|
// HeadRetriever retrieves head root and optimistic info of the current chain.
|
||||||
type HeadRetriever interface {
|
type HeadRetriever interface {
|
||||||
Head(context.Context, [32]byte, []uint64) ([32]byte, error)
|
Head(context.Context, []uint64) ([32]byte, error)
|
||||||
Tips() ([][32]byte, []types.Slot)
|
Tips() ([][32]byte, []types.Slot)
|
||||||
IsOptimistic(root [32]byte) (bool, error)
|
IsOptimistic(root [32]byte) (bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockProcessor processes the block that's used for accounting fork choice.
|
// BlockProcessor processes the block that's used for accounting fork choice.
|
||||||
type BlockProcessor interface {
|
type BlockProcessor interface {
|
||||||
InsertNode(context.Context, state.ReadOnlyBeaconState, [32]byte) error
|
InsertNode(context.Context, state.BeaconState, [32]byte) error
|
||||||
InsertOptimisticChain(context.Context, []*forkchoicetypes.BlockAndCheckpoints) error
|
InsertOptimisticChain(context.Context, []*forkchoicetypes.BlockAndCheckpoints) error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,8 +59,8 @@ type Getter interface {
|
|||||||
AncestorRoot(ctx context.Context, root [32]byte, slot types.Slot) ([]byte, error)
|
AncestorRoot(ctx context.Context, root [32]byte, slot types.Slot) ([]byte, error)
|
||||||
CommonAncestorRoot(ctx context.Context, root1 [32]byte, root2 [32]byte) ([32]byte, error)
|
CommonAncestorRoot(ctx context.Context, root1 [32]byte, root2 [32]byte) ([32]byte, error)
|
||||||
IsCanonical(root [32]byte) bool
|
IsCanonical(root [32]byte) bool
|
||||||
FinalizedEpoch() types.Epoch
|
FinalizedCheckpoint() *forkchoicetypes.Checkpoint
|
||||||
JustifiedEpoch() types.Epoch
|
JustifiedCheckpoint() *forkchoicetypes.Checkpoint
|
||||||
ForkChoiceNodes() []*ethpb.ForkChoiceNode
|
ForkChoiceNodes() []*ethpb.ForkChoiceNode
|
||||||
NodeCount() int
|
NodeCount() int
|
||||||
}
|
}
|
||||||
@@ -69,6 +69,6 @@ type Getter interface {
|
|||||||
type Setter interface {
|
type Setter interface {
|
||||||
SetOptimisticToValid(context.Context, [fieldparams.RootLength]byte) error
|
SetOptimisticToValid(context.Context, [fieldparams.RootLength]byte) error
|
||||||
SetOptimisticToInvalid(context.Context, [fieldparams.RootLength]byte, [fieldparams.RootLength]byte, [fieldparams.RootLength]byte) ([][32]byte, error)
|
SetOptimisticToInvalid(context.Context, [fieldparams.RootLength]byte, [fieldparams.RootLength]byte, [fieldparams.RootLength]byte) ([][32]byte, error)
|
||||||
UpdateJustifiedCheckpoint(*ethpb.Checkpoint) error
|
UpdateJustifiedCheckpoint(*forkchoicetypes.Checkpoint) error
|
||||||
UpdateFinalizedCheckpoint(*ethpb.Checkpoint) error
|
UpdateFinalizedCheckpoint(*forkchoicetypes.Checkpoint) error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||||
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
"github.com/prysmaticlabs/prysm/beacon-chain/state"
|
||||||
v3 "github.com/prysmaticlabs/prysm/beacon-chain/state/v3"
|
v3 "github.com/prysmaticlabs/prysm/beacon-chain/state/v3"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
@@ -61,7 +62,7 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
// The head should always start at the finalized block.
|
// The head should always start at the finalized block.
|
||||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err := f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
||||||
|
|
||||||
@@ -91,7 +92,7 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
|||||||
// 2
|
// 2
|
||||||
// |
|
// |
|
||||||
// 3 <- head
|
// 3 <- head
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(3), r, "Incorrect head for with justified epoch at 0")
|
assert.Equal(t, indexToHash(3), r, "Incorrect head for with justified epoch at 0")
|
||||||
|
|
||||||
@@ -103,8 +104,9 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
|||||||
// 2 <- head
|
// 2 <- head
|
||||||
// |
|
// |
|
||||||
// 3
|
// 3
|
||||||
f.store.justifiedEpoch = 1
|
jc := &forkchoicetypes.Checkpoint{Epoch: 1, Root: indexToHash(2)}
|
||||||
r, err = f.Head(context.Background(), indexToHash(2), balances)
|
f.store.justifiedCheckpoint = jc
|
||||||
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(2), r, "Incorrect head with justified epoch at 1")
|
assert.Equal(t, indexToHash(2), r, "Incorrect head with justified epoch at 1")
|
||||||
|
|
||||||
@@ -116,8 +118,9 @@ func TestFFGUpdates_OneBranch(t *testing.T) {
|
|||||||
// 2 <- start
|
// 2 <- start
|
||||||
// |
|
// |
|
||||||
// 3 <- head
|
// 3 <- head
|
||||||
f.store.justifiedEpoch = 2
|
jc = &forkchoicetypes.Checkpoint{Epoch: 2, Root: indexToHash(3)}
|
||||||
r, err = f.Head(context.Background(), indexToHash(3), balances)
|
f.store.justifiedCheckpoint = jc
|
||||||
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(3), r, "Incorrect head with justified epoch at 2")
|
assert.Equal(t, indexToHash(3), r, "Incorrect head with justified epoch at 2")
|
||||||
}
|
}
|
||||||
@@ -127,7 +130,7 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
|||||||
f := setup(0, 0)
|
f := setup(0, 0)
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err := f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
||||||
|
|
||||||
@@ -188,7 +191,7 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
|||||||
// 7 8
|
// 7 8
|
||||||
// | |
|
// | |
|
||||||
// 9 10 <-- head
|
// 9 10 <-- head
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(10), r, "Incorrect head with justified epoch at 0")
|
assert.Equal(t, indexToHash(10), r, "Incorrect head with justified epoch at 0")
|
||||||
|
|
||||||
@@ -218,7 +221,7 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
|||||||
// 7 8
|
// 7 8
|
||||||
// | |
|
// | |
|
||||||
// head -> 9 10
|
// head -> 9 10
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(9), r, "Incorrect head with justified epoch at 0")
|
assert.Equal(t, indexToHash(9), r, "Incorrect head with justified epoch at 0")
|
||||||
|
|
||||||
@@ -248,19 +251,22 @@ func TestFFGUpdates_TwoBranches(t *testing.T) {
|
|||||||
// 7 8
|
// 7 8
|
||||||
// | |
|
// | |
|
||||||
// 9 10 <-- head
|
// 9 10 <-- head
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(10), r, "Incorrect head with justified epoch at 0")
|
assert.Equal(t, indexToHash(10), r, "Incorrect head with justified epoch at 0")
|
||||||
|
|
||||||
f.store.justifiedEpoch = 1
|
jc := &forkchoicetypes.Checkpoint{Epoch: 1, Root: indexToHash(1)}
|
||||||
r, err = f.Head(context.Background(), indexToHash(1), balances)
|
f.store.justifiedCheckpoint = jc
|
||||||
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(7), r, "Incorrect head with justified epoch at 0")
|
assert.Equal(t, indexToHash(7), r, "Incorrect head with justified epoch at 0")
|
||||||
}
|
}
|
||||||
|
|
||||||
func setup(justifiedEpoch, finalizedEpoch types.Epoch) *ForkChoice {
|
func setup(justifiedEpoch, finalizedEpoch types.Epoch) *ForkChoice {
|
||||||
f := New(justifiedEpoch, finalizedEpoch)
|
f := New()
|
||||||
f.store.nodesIndices[params.BeaconConfig().ZeroHash] = 0
|
f.store.nodesIndices[params.BeaconConfig().ZeroHash] = 0
|
||||||
|
f.store.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: justifiedEpoch, Root: params.BeaconConfig().ZeroHash}
|
||||||
|
f.store.finalizedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: finalizedEpoch, Root: params.BeaconConfig().ZeroHash}
|
||||||
f.store.nodes = append(f.store.nodes, &Node{
|
f.store.nodes = append(f.store.nodes, &Node{
|
||||||
slot: 0,
|
slot: 0,
|
||||||
root: params.BeaconConfig().ZeroHash,
|
root: params.BeaconConfig().ZeroHash,
|
||||||
@@ -271,6 +277,5 @@ func setup(justifiedEpoch, finalizedEpoch types.Epoch) *ForkChoice {
|
|||||||
bestDescendant: NonExistentNode,
|
bestDescendant: NonExistentNode,
|
||||||
weight: 0,
|
weight: 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
// The head should always start at the finalized block.
|
// The head should always start at the finalized block.
|
||||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err := f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if r != params.BeaconConfig().ZeroHash {
|
if r != params.BeaconConfig().ZeroHash {
|
||||||
t.Errorf("Incorrect head with genesis")
|
t.Errorf("Incorrect head with genesis")
|
||||||
@@ -28,7 +28,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
|||||||
state, blkRoot, err := prepareForkchoiceState(context.Background(), 0, indexToHash(2), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1)
|
state, blkRoot, err := prepareForkchoiceState(context.Background(), 0, indexToHash(2), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
|||||||
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1)
|
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(1), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
|||||||
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(3), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1)
|
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(3), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
|||||||
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(4), indexToHash(2), params.BeaconConfig().ZeroHash, 1, 1)
|
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(4), indexToHash(2), params.BeaconConfig().ZeroHash, 1, 1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
|||||||
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(5), indexToHash(4), params.BeaconConfig().ZeroHash, 2, 1)
|
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(5), indexToHash(4), params.BeaconConfig().ZeroHash, 2, 1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -92,7 +92,8 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
|||||||
// head -> 4 3
|
// head -> 4 3
|
||||||
// |
|
// |
|
||||||
// 5 <- starting from 5 with justified epoch 0 should error
|
// 5 <- starting from 5 with justified epoch 0 should error
|
||||||
_, err = f.Head(context.Background(), indexToHash(5), balances)
|
f.store.justifiedCheckpoint.Root = indexToHash(5)
|
||||||
|
_, err = f.Head(context.Background(), balances)
|
||||||
wanted := "head at slot 0 with weight 0 is not eligible, finalizedEpoch 1 != 1, justifiedEpoch 2 != 1"
|
wanted := "head at slot 0 with weight 0 is not eligible, finalizedEpoch 1 != 1, justifiedEpoch 2 != 1"
|
||||||
require.ErrorContains(t, wanted, err)
|
require.ErrorContains(t, wanted, err)
|
||||||
|
|
||||||
@@ -104,8 +105,8 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
|||||||
// 4 3
|
// 4 3
|
||||||
// |
|
// |
|
||||||
// 5 <- head
|
// 5 <- head
|
||||||
f.store.justifiedEpoch = 2
|
f.store.justifiedCheckpoint.Epoch = 2
|
||||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(5), r, "Incorrect head for with justified epoch at 2")
|
assert.Equal(t, indexToHash(5), r, "Incorrect head for with justified epoch at 2")
|
||||||
|
|
||||||
@@ -122,7 +123,7 @@ func TestNoVote_CanFindHead(t *testing.T) {
|
|||||||
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(6), indexToHash(5), params.BeaconConfig().ZeroHash, 2, 1)
|
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(6), indexToHash(5), params.BeaconConfig().ZeroHash, 2, 1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(6), r, "Incorrect head for with justified epoch at 2")
|
assert.Equal(t, indexToHash(6), r, "Incorrect head for with justified epoch at 2")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
f := setup(jEpoch, fEpoch)
|
f := setup(jEpoch, fEpoch)
|
||||||
|
|
||||||
// The head should always start at the finalized block.
|
// The head should always start at the finalized block.
|
||||||
headRoot, err := f.Head(ctx, zeroHash, balances)
|
headRoot, err := f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, zeroHash, headRoot, "Incorrect head with genesis")
|
assert.Equal(t, zeroHash, headRoot, "Incorrect head with genesis")
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
f.ProcessAttestation(ctx, []uint64{0}, newRoot, fEpoch)
|
f.ProcessAttestation(ctx, []uint64{0}, newRoot, fEpoch)
|
||||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
headRoot, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 1")
|
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 1")
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
f.ProcessAttestation(ctx, []uint64{1}, newRoot, fEpoch)
|
f.ProcessAttestation(ctx, []uint64{1}, newRoot, fEpoch)
|
||||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
headRoot, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 2")
|
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 2")
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
f.ProcessAttestation(ctx, []uint64{2}, newRoot, fEpoch)
|
f.ProcessAttestation(ctx, []uint64{2}, newRoot, fEpoch)
|
||||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
headRoot, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 3")
|
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 3")
|
||||||
|
|
||||||
@@ -142,7 +142,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
SecondsIntoSlot: 0,
|
SecondsIntoSlot: 0,
|
||||||
}
|
}
|
||||||
require.NoError(t, f.BoostProposerRoot(ctx, args))
|
require.NoError(t, f.BoostProposerRoot(ctx, args))
|
||||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
headRoot, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 3")
|
assert.Equal(t, newRoot, headRoot, "Incorrect head for justified epoch at slot 3")
|
||||||
|
|
||||||
@@ -180,7 +180,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
// Regression: process attestations for C, check that it
|
// Regression: process attestations for C, check that it
|
||||||
// becomes head, we need two attestations to have C.weight = 30 > 24 = D.weight
|
// becomes head, we need two attestations to have C.weight = 30 > 24 = D.weight
|
||||||
f.ProcessAttestation(ctx, []uint64{4, 5}, indexToHash(3), fEpoch)
|
f.ProcessAttestation(ctx, []uint64{4, 5}, indexToHash(3), fEpoch)
|
||||||
headRoot, err = f.Head(ctx, zeroHash, balances)
|
headRoot, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(3), headRoot, "Incorrect head for justified epoch at slot 4")
|
assert.Equal(t, indexToHash(3), headRoot, "Incorrect head for justified epoch at slot 4")
|
||||||
})
|
})
|
||||||
@@ -188,7 +188,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
f := setup(jEpoch, fEpoch)
|
f := setup(jEpoch, fEpoch)
|
||||||
|
|
||||||
// The head should always start at the finalized block.
|
// The head should always start at the finalized block.
|
||||||
r, err := f.Head(ctx, zeroHash, balances)
|
r, err := f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
||||||
|
|
||||||
@@ -213,7 +213,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
r, err = f.Head(ctx, zeroHash, balances)
|
r, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||||
|
|
||||||
@@ -232,7 +232,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
// Ensure the head is C, the honest block.
|
// Ensure the head is C, the honest block.
|
||||||
r, err = f.Head(ctx, zeroHash, balances)
|
r, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||||
|
|
||||||
@@ -253,7 +253,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
f.ProcessAttestation(ctx, votes, honestBlock, fEpoch)
|
f.ProcessAttestation(ctx, votes, honestBlock, fEpoch)
|
||||||
|
|
||||||
// Ensure the head is STILL C, the honest block, as the honest block had proposer boost.
|
// Ensure the head is STILL C, the honest block, as the honest block had proposer boost.
|
||||||
r, err = f.Head(ctx, zeroHash, balances)
|
r, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||||
})
|
})
|
||||||
@@ -261,7 +261,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
f := setup(jEpoch, fEpoch)
|
f := setup(jEpoch, fEpoch)
|
||||||
|
|
||||||
// The head should always start at the finalized block.
|
// The head should always start at the finalized block.
|
||||||
r, err := f.Head(ctx, zeroHash, balances)
|
r, err := f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
||||||
|
|
||||||
@@ -288,7 +288,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
// Ensure C is the head.
|
// Ensure C is the head.
|
||||||
r, err = f.Head(ctx, zeroHash, balances)
|
r, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||||
|
|
||||||
@@ -307,7 +307,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
// Ensure C is still the head after the malicious proposer reveals their block.
|
// Ensure C is still the head after the malicious proposer reveals their block.
|
||||||
r, err = f.Head(ctx, zeroHash, balances)
|
r, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
assert.Equal(t, honestBlock, r, "Incorrect head for justified epoch at slot 2")
|
||||||
|
|
||||||
@@ -326,7 +326,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
f.ProcessAttestation(ctx, votes, maliciouslyWithheldBlock, fEpoch)
|
f.ProcessAttestation(ctx, votes, maliciouslyWithheldBlock, fEpoch)
|
||||||
|
|
||||||
// Expect the head to have switched to B.
|
// Expect the head to have switched to B.
|
||||||
r, err = f.Head(ctx, zeroHash, balances)
|
r, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, maliciouslyWithheldBlock, r, "Expected B to become the head")
|
assert.Equal(t, maliciouslyWithheldBlock, r, "Expected B to become the head")
|
||||||
})
|
})
|
||||||
@@ -348,7 +348,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
a := zeroHash
|
a := zeroHash
|
||||||
|
|
||||||
// The head should always start at the finalized block.
|
// The head should always start at the finalized block.
|
||||||
r, err := f.Head(ctx, zeroHash, balances)
|
r, err := f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
assert.Equal(t, zeroHash, r, "Incorrect head with genesis")
|
||||||
|
|
||||||
@@ -367,7 +367,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
// Ensure C is the head.
|
// Ensure C is the head.
|
||||||
r, err = f.Head(ctx, zeroHash, balances)
|
r, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, c, r, "Incorrect head for justified epoch at slot 2")
|
assert.Equal(t, c, r, "Incorrect head for justified epoch at slot 2")
|
||||||
|
|
||||||
@@ -395,7 +395,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
// Ensure C is still the head.
|
// Ensure C is still the head.
|
||||||
r, err = f.Head(ctx, zeroHash, balances)
|
r, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, c, r, "Incorrect head for justified epoch at slot 2")
|
assert.Equal(t, c, r, "Incorrect head for justified epoch at slot 2")
|
||||||
|
|
||||||
@@ -419,7 +419,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
// D cannot win without a boost.
|
// D cannot win without a boost.
|
||||||
r, err = f.Head(ctx, zeroHash, balances)
|
r, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, c, r, "Expected C to remain the head")
|
assert.Equal(t, c, r, "Expected C to remain the head")
|
||||||
|
|
||||||
@@ -435,7 +435,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
|||||||
require.NoError(t, f.BoostProposerRoot(ctx, args))
|
require.NoError(t, f.BoostProposerRoot(ctx, args))
|
||||||
|
|
||||||
// Ensure D becomes the head thanks to boosting.
|
// Ensure D becomes the head thanks to boosting.
|
||||||
r, err = f.Head(ctx, zeroHash, balances)
|
r, err = f.Head(ctx, balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, d, r, "Expected D to become the head")
|
assert.Equal(t, d, r, "Expected D to become the head")
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -29,17 +29,17 @@ const defaultPruneThreshold = 256
|
|||||||
var lastHeadRoot [32]byte
|
var lastHeadRoot [32]byte
|
||||||
|
|
||||||
// New initializes a new fork choice store.
|
// New initializes a new fork choice store.
|
||||||
func New(justifiedEpoch, finalizedEpoch types.Epoch) *ForkChoice {
|
func New() *ForkChoice {
|
||||||
s := &Store{
|
s := &Store{
|
||||||
justifiedEpoch: justifiedEpoch,
|
justifiedCheckpoint: &forkchoicetypes.Checkpoint{},
|
||||||
finalizedEpoch: finalizedEpoch,
|
finalizedCheckpoint: &forkchoicetypes.Checkpoint{},
|
||||||
proposerBoostRoot: [32]byte{},
|
proposerBoostRoot: [32]byte{},
|
||||||
nodes: make([]*Node, 0),
|
nodes: make([]*Node, 0),
|
||||||
nodesIndices: make(map[[32]byte]uint64),
|
nodesIndices: make(map[[32]byte]uint64),
|
||||||
payloadIndices: make(map[[32]byte]uint64),
|
payloadIndices: make(map[[32]byte]uint64),
|
||||||
canonicalNodes: make(map[[32]byte]bool),
|
canonicalNodes: make(map[[32]byte]bool),
|
||||||
slashedIndices: make(map[types.ValidatorIndex]bool),
|
slashedIndices: make(map[types.ValidatorIndex]bool),
|
||||||
pruneThreshold: defaultPruneThreshold,
|
pruneThreshold: defaultPruneThreshold,
|
||||||
}
|
}
|
||||||
|
|
||||||
b := make([]uint64, 0)
|
b := make([]uint64, 0)
|
||||||
@@ -49,11 +49,7 @@ func New(justifiedEpoch, finalizedEpoch types.Epoch) *ForkChoice {
|
|||||||
|
|
||||||
// Head returns the head root from fork choice store.
|
// Head returns the head root from fork choice store.
|
||||||
// It firsts computes validator's balance changes then recalculates block tree from leaves to root.
|
// It firsts computes validator's balance changes then recalculates block tree from leaves to root.
|
||||||
func (f *ForkChoice) Head(
|
func (f *ForkChoice) Head(ctx context.Context, justifiedStateBalances []uint64) ([32]byte, error) {
|
||||||
ctx context.Context,
|
|
||||||
justifiedRoot [32]byte,
|
|
||||||
justifiedStateBalances []uint64,
|
|
||||||
) ([32]byte, error) {
|
|
||||||
ctx, span := trace.StartSpan(ctx, "protoArrayForkChoice.Head")
|
ctx, span := trace.StartSpan(ctx, "protoArrayForkChoice.Head")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
f.votesLock.Lock()
|
f.votesLock.Lock()
|
||||||
@@ -76,7 +72,7 @@ func (f *ForkChoice) Head(
|
|||||||
}
|
}
|
||||||
f.balances = newBalances
|
f.balances = newBalances
|
||||||
|
|
||||||
return f.store.head(ctx, justifiedRoot)
|
return f.store.head(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProcessAttestation processes attestation for vote accounting, it iterates around validator indices
|
// ProcessAttestation processes attestation for vote accounting, it iterates around validator indices
|
||||||
@@ -120,7 +116,7 @@ func (f *ForkChoice) ProposerBoost() [fieldparams.RootLength]byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InsertNode processes a new block by inserting it to the fork choice store.
|
// InsertNode processes a new block by inserting it to the fork choice store.
|
||||||
func (f *ForkChoice) InsertNode(ctx context.Context, state state.ReadOnlyBeaconState, root [32]byte) error {
|
func (f *ForkChoice) InsertNode(ctx context.Context, state state.BeaconState, root [32]byte) error {
|
||||||
ctx, span := trace.StartSpan(ctx, "protoArrayForkChoice.InsertNode")
|
ctx, span := trace.StartSpan(ctx, "protoArrayForkChoice.InsertNode")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
@@ -273,14 +269,18 @@ func (s *Store) PruneThreshold() uint64 {
|
|||||||
return s.pruneThreshold
|
return s.pruneThreshold
|
||||||
}
|
}
|
||||||
|
|
||||||
// JustifiedEpoch of fork choice store.
|
// JustifiedCheckpoint of fork choice store.
|
||||||
func (f *ForkChoice) JustifiedEpoch() types.Epoch {
|
func (f *ForkChoice) JustifiedCheckpoint() *forkchoicetypes.Checkpoint {
|
||||||
return f.store.justifiedEpoch
|
f.store.checkpointsLock.RLock()
|
||||||
|
defer f.store.checkpointsLock.RUnlock()
|
||||||
|
return f.store.justifiedCheckpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
// FinalizedEpoch of fork choice store.
|
// FinalizedCheckpoint of fork choice store.
|
||||||
func (f *ForkChoice) FinalizedEpoch() types.Epoch {
|
func (f *ForkChoice) FinalizedCheckpoint() *forkchoicetypes.Checkpoint {
|
||||||
return f.store.finalizedEpoch
|
f.store.checkpointsLock.RLock()
|
||||||
|
defer f.store.checkpointsLock.RUnlock()
|
||||||
|
return f.store.finalizedCheckpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
// proposerBoost of fork choice store.
|
// proposerBoost of fork choice store.
|
||||||
@@ -291,20 +291,23 @@ func (s *Store) proposerBoost() [fieldparams.RootLength]byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// head starts from justified root and then follows the best descendant links
|
// head starts from justified root and then follows the best descendant links
|
||||||
// to find the best block for head.
|
// to find the best block for head. It assumes the caller has a lock on nodes.
|
||||||
func (s *Store) head(ctx context.Context, justifiedRoot [32]byte) ([32]byte, error) {
|
func (s *Store) head(ctx context.Context) ([32]byte, error) {
|
||||||
ctx, span := trace.StartSpan(ctx, "protoArrayForkChoice.head")
|
ctx, span := trace.StartSpan(ctx, "protoArrayForkChoice.head")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
// Justified index has to be valid in node indices map, and can not be out of bound.
|
// Justified index has to be valid in node indices map, and can not be out of bound.
|
||||||
justifiedIndex, ok := s.nodesIndices[justifiedRoot]
|
if s.justifiedCheckpoint == nil {
|
||||||
|
return [32]byte{}, errInvalidNilCheckpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
justifiedIndex, ok := s.nodesIndices[s.justifiedCheckpoint.Root]
|
||||||
if !ok {
|
if !ok {
|
||||||
return [32]byte{}, errUnknownJustifiedRoot
|
return [32]byte{}, errUnknownJustifiedRoot
|
||||||
}
|
}
|
||||||
if justifiedIndex >= uint64(len(s.nodes)) {
|
if justifiedIndex >= uint64(len(s.nodes)) {
|
||||||
return [32]byte{}, errInvalidJustifiedIndex
|
return [32]byte{}, errInvalidJustifiedIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
justifiedNode := s.nodes[justifiedIndex]
|
justifiedNode := s.nodes[justifiedIndex]
|
||||||
bestDescendantIndex := justifiedNode.bestDescendant
|
bestDescendantIndex := justifiedNode.bestDescendant
|
||||||
// If the justified node doesn't have a best descendant,
|
// If the justified node doesn't have a best descendant,
|
||||||
@@ -315,12 +318,11 @@ func (s *Store) head(ctx context.Context, justifiedRoot [32]byte) ([32]byte, err
|
|||||||
if bestDescendantIndex >= uint64(len(s.nodes)) {
|
if bestDescendantIndex >= uint64(len(s.nodes)) {
|
||||||
return [32]byte{}, errInvalidBestDescendantIndex
|
return [32]byte{}, errInvalidBestDescendantIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
bestNode := s.nodes[bestDescendantIndex]
|
bestNode := s.nodes[bestDescendantIndex]
|
||||||
|
|
||||||
if !s.viableForHead(bestNode) {
|
if !s.viableForHead(bestNode) {
|
||||||
return [32]byte{}, fmt.Errorf("head at slot %d with weight %d is not eligible, finalizedEpoch %d != %d, justifiedEpoch %d != %d",
|
return [32]byte{}, fmt.Errorf("head at slot %d with weight %d is not eligible, finalizedEpoch %d != %d, justifiedEpoch %d != %d",
|
||||||
bestNode.slot, bestNode.weight/10e9, bestNode.finalizedEpoch, s.finalizedEpoch, bestNode.justifiedEpoch, s.justifiedEpoch)
|
bestNode.slot, bestNode.weight/10e9, bestNode.finalizedEpoch, s.finalizedCheckpoint.Epoch, bestNode.justifiedEpoch, s.justifiedCheckpoint.Epoch)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update metrics.
|
// Update metrics.
|
||||||
@@ -743,10 +745,12 @@ func (s *Store) leadsToViableHead(node *Node) (bool, error) {
|
|||||||
// Any node with diff finalized or justified epoch than the ones in fork choice store
|
// Any node with diff finalized or justified epoch than the ones in fork choice store
|
||||||
// should not be viable to head.
|
// should not be viable to head.
|
||||||
func (s *Store) viableForHead(node *Node) bool {
|
func (s *Store) viableForHead(node *Node) bool {
|
||||||
|
s.checkpointsLock.RLock()
|
||||||
|
defer s.checkpointsLock.RUnlock()
|
||||||
// `node` is viable if its justified epoch and finalized epoch are the same as the one in `Store`.
|
// `node` is viable if its justified epoch and finalized epoch are the same as the one in `Store`.
|
||||||
// It's also viable if we are in genesis epoch.
|
// It's also viable if we are in genesis epoch.
|
||||||
justified := s.justifiedEpoch == node.justifiedEpoch || s.justifiedEpoch == 0
|
justified := s.justifiedCheckpoint.Epoch == node.justifiedEpoch || s.justifiedCheckpoint.Epoch == 0
|
||||||
finalized := s.finalizedEpoch == node.finalizedEpoch || s.finalizedEpoch == 0
|
finalized := s.finalizedCheckpoint.Epoch == node.finalizedEpoch || s.finalizedCheckpoint.Epoch == 0
|
||||||
|
|
||||||
return justified && finalized
|
return justified && finalized
|
||||||
}
|
}
|
||||||
@@ -857,25 +861,25 @@ func (f *ForkChoice) InsertSlashedIndex(ctx context.Context, index types.Validat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateJustifiedCheckpoint sets the justified epoch to the given one
|
// UpdateJustifiedCheckpoint sets the justified checkpoint to the given one
|
||||||
func (f *ForkChoice) UpdateJustifiedCheckpoint(jc *pbrpc.Checkpoint) error {
|
func (f *ForkChoice) UpdateJustifiedCheckpoint(jc *forkchoicetypes.Checkpoint) error {
|
||||||
if jc == nil {
|
if jc == nil {
|
||||||
return errInvalidNilCheckpoint
|
return errInvalidNilCheckpoint
|
||||||
}
|
}
|
||||||
f.store.nodesLock.Lock()
|
f.store.checkpointsLock.Lock()
|
||||||
defer f.store.nodesLock.Unlock()
|
defer f.store.checkpointsLock.Unlock()
|
||||||
f.store.justifiedEpoch = jc.Epoch
|
f.store.justifiedCheckpoint = jc
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateFinalizedCheckpoint sets the finalized epoch to the given one
|
// UpdateFinalizedCheckpoint sets the finalized checkpoint to the given one
|
||||||
func (f *ForkChoice) UpdateFinalizedCheckpoint(fc *pbrpc.Checkpoint) error {
|
func (f *ForkChoice) UpdateFinalizedCheckpoint(fc *forkchoicetypes.Checkpoint) error {
|
||||||
if fc == nil {
|
if fc == nil {
|
||||||
return errInvalidNilCheckpoint
|
return errInvalidNilCheckpoint
|
||||||
}
|
}
|
||||||
f.store.nodesLock.Lock()
|
f.store.checkpointsLock.Lock()
|
||||||
defer f.store.nodesLock.Unlock()
|
defer f.store.checkpointsLock.Unlock()
|
||||||
f.store.finalizedEpoch = fc.Epoch
|
f.store.finalizedCheckpoint = fc
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -895,7 +899,7 @@ func (f *ForkChoice) InsertOptimisticChain(ctx context.Context, chain []*forkcho
|
|||||||
}
|
}
|
||||||
if err := f.store.insert(ctx,
|
if err := f.store.insert(ctx,
|
||||||
b.Slot(), r, parentRoot, payloadHash,
|
b.Slot(), r, parentRoot, payloadHash,
|
||||||
chain[i].JustifiedEpoch, chain[i].FinalizedEpoch); err != nil {
|
chain[i].JustifiedCheckpoint.Epoch, chain[i].FinalizedCheckpoint.Epoch); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,13 +28,13 @@ func TestStore_PruneThreshold(t *testing.T) {
|
|||||||
func TestStore_JustifiedEpoch(t *testing.T) {
|
func TestStore_JustifiedEpoch(t *testing.T) {
|
||||||
j := types.Epoch(100)
|
j := types.Epoch(100)
|
||||||
f := setup(j, j)
|
f := setup(j, j)
|
||||||
require.Equal(t, j, f.JustifiedEpoch())
|
require.Equal(t, j, f.JustifiedCheckpoint().Epoch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStore_FinalizedEpoch(t *testing.T) {
|
func TestStore_FinalizedEpoch(t *testing.T) {
|
||||||
j := types.Epoch(50)
|
j := types.Epoch(50)
|
||||||
f := setup(j, j)
|
f := setup(j, j)
|
||||||
require.Equal(t, j, f.FinalizedEpoch())
|
require.Equal(t, j, f.FinalizedCheckpoint().Epoch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestForkChoice_HasNode(t *testing.T) {
|
func TestForkChoice_HasNode(t *testing.T) {
|
||||||
@@ -51,8 +51,9 @@ func TestForkChoice_HasNode(t *testing.T) {
|
|||||||
|
|
||||||
func TestStore_Head_UnknownJustifiedRoot(t *testing.T) {
|
func TestStore_Head_UnknownJustifiedRoot(t *testing.T) {
|
||||||
s := &Store{nodesIndices: make(map[[32]byte]uint64)}
|
s := &Store{nodesIndices: make(map[[32]byte]uint64)}
|
||||||
|
s.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 0, Root: [32]byte{'a'}}
|
||||||
|
|
||||||
_, err := s.head(context.Background(), [32]byte{})
|
_, err := s.head(context.Background())
|
||||||
assert.ErrorContains(t, errUnknownJustifiedRoot.Error(), err)
|
assert.ErrorContains(t, errUnknownJustifiedRoot.Error(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,8 +62,9 @@ func TestStore_Head_UnknownJustifiedIndex(t *testing.T) {
|
|||||||
indices := make(map[[32]byte]uint64)
|
indices := make(map[[32]byte]uint64)
|
||||||
indices[r] = 1
|
indices[r] = 1
|
||||||
s := &Store{nodesIndices: indices}
|
s := &Store{nodesIndices: indices}
|
||||||
|
s.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 0, Root: r}
|
||||||
|
|
||||||
_, err := s.head(context.Background(), r)
|
_, err := s.head(context.Background())
|
||||||
assert.ErrorContains(t, errInvalidJustifiedIndex.Error(), err)
|
assert.ErrorContains(t, errInvalidJustifiedIndex.Error(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +75,9 @@ func TestStore_Head_Itself(t *testing.T) {
|
|||||||
// Since the justified node does not have a best descendant so the best node
|
// Since the justified node does not have a best descendant so the best node
|
||||||
// is itself.
|
// is itself.
|
||||||
s := &Store{nodesIndices: indices, nodes: []*Node{{root: r, parent: NonExistentNode, bestDescendant: NonExistentNode}}, canonicalNodes: make(map[[32]byte]bool)}
|
s := &Store{nodesIndices: indices, nodes: []*Node{{root: r, parent: NonExistentNode, bestDescendant: NonExistentNode}}, canonicalNodes: make(map[[32]byte]bool)}
|
||||||
h, err := s.head(context.Background(), r)
|
s.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 0, Root: r}
|
||||||
|
s.finalizedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 0, Root: r}
|
||||||
|
h, err := s.head(context.Background())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, r, h)
|
assert.Equal(t, r, h)
|
||||||
}
|
}
|
||||||
@@ -86,7 +90,9 @@ func TestStore_Head_BestDescendant(t *testing.T) {
|
|||||||
// Since the justified node's best descendant is at index 1, and its root is `best`,
|
// Since the justified node's best descendant is at index 1, and its root is `best`,
|
||||||
// the head should be `best`.
|
// the head should be `best`.
|
||||||
s := &Store{nodesIndices: indices, nodes: []*Node{{root: r, bestDescendant: 1, parent: NonExistentNode}, {root: best, parent: 0}}, canonicalNodes: make(map[[32]byte]bool)}
|
s := &Store{nodesIndices: indices, nodes: []*Node{{root: r, bestDescendant: 1, parent: NonExistentNode}, {root: best, parent: 0}}, canonicalNodes: make(map[[32]byte]bool)}
|
||||||
h, err := s.head(context.Background(), r)
|
s.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 0, Root: r}
|
||||||
|
s.finalizedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 0, Root: r}
|
||||||
|
h, err := s.head(context.Background())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, best, h)
|
assert.Equal(t, best, h)
|
||||||
}
|
}
|
||||||
@@ -99,7 +105,9 @@ func TestStore_Head_ContextCancelled(t *testing.T) {
|
|||||||
|
|
||||||
s := &Store{nodesIndices: indices, nodes: []*Node{{root: r, parent: NonExistentNode, bestDescendant: 1}, {root: best, parent: 0}}, canonicalNodes: make(map[[32]byte]bool)}
|
s := &Store{nodesIndices: indices, nodes: []*Node{{root: r, parent: NonExistentNode, bestDescendant: 1}, {root: best, parent: 0}}, canonicalNodes: make(map[[32]byte]bool)}
|
||||||
cancel()
|
cancel()
|
||||||
_, err := s.head(ctx, r)
|
s.justifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 0, Root: r}
|
||||||
|
s.finalizedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 0, Root: r}
|
||||||
|
_, err := s.head(ctx)
|
||||||
require.ErrorContains(t, "context canceled", err)
|
require.ErrorContains(t, "context canceled", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,6 +131,8 @@ func TestStore_Insert_KnownParent(t *testing.T) {
|
|||||||
p := [32]byte{'B'}
|
p := [32]byte{'B'}
|
||||||
s.nodesIndices[p] = 0
|
s.nodesIndices[p] = 0
|
||||||
payloadHash := [32]byte{'c'}
|
payloadHash := [32]byte{'c'}
|
||||||
|
s.justifiedCheckpoint = &forkchoicetypes.Checkpoint{}
|
||||||
|
s.finalizedCheckpoint = &forkchoicetypes.Checkpoint{}
|
||||||
require.NoError(t, s.insert(context.Background(), 100, [32]byte{'A'}, p, payloadHash, 1, 1))
|
require.NoError(t, s.insert(context.Background(), 100, [32]byte{'A'}, p, payloadHash, 1, 1))
|
||||||
assert.Equal(t, 2, len(s.nodes), "Did not insert block")
|
assert.Equal(t, 2, len(s.nodes), "Did not insert block")
|
||||||
assert.Equal(t, 2, len(s.nodesIndices), "Did not insert block")
|
assert.Equal(t, 2, len(s.nodesIndices), "Did not insert block")
|
||||||
@@ -150,6 +160,8 @@ func TestStore_ApplyScoreChanges_UpdateWeightsPositiveDelta(t *testing.T) {
|
|||||||
|
|
||||||
// Each node gets one unique vote. The weight should look like 103 <- 102 <- 101 because
|
// Each node gets one unique vote. The weight should look like 103 <- 102 <- 101 because
|
||||||
// they get propagated back.
|
// they get propagated back.
|
||||||
|
s.justifiedCheckpoint = &forkchoicetypes.Checkpoint{}
|
||||||
|
s.finalizedCheckpoint = &forkchoicetypes.Checkpoint{}
|
||||||
require.NoError(t, s.applyWeightChanges(context.Background(), []uint64{}, []int{1, 1, 1}))
|
require.NoError(t, s.applyWeightChanges(context.Background(), []uint64{}, []int{1, 1, 1}))
|
||||||
assert.Equal(t, uint64(103), s.nodes[0].weight)
|
assert.Equal(t, uint64(103), s.nodes[0].weight)
|
||||||
assert.Equal(t, uint64(102), s.nodes[1].weight)
|
assert.Equal(t, uint64(102), s.nodes[1].weight)
|
||||||
@@ -165,6 +177,8 @@ func TestStore_ApplyScoreChanges_UpdateWeightsNegativeDelta(t *testing.T) {
|
|||||||
|
|
||||||
// Each node gets one unique vote which contributes to negative delta.
|
// Each node gets one unique vote which contributes to negative delta.
|
||||||
// The weight should look like 97 <- 98 <- 99 because they get propagated back.
|
// The weight should look like 97 <- 98 <- 99 because they get propagated back.
|
||||||
|
s.justifiedCheckpoint = &forkchoicetypes.Checkpoint{}
|
||||||
|
s.finalizedCheckpoint = &forkchoicetypes.Checkpoint{}
|
||||||
require.NoError(t, s.applyWeightChanges(context.Background(), []uint64{}, []int{-1, -1, -1}))
|
require.NoError(t, s.applyWeightChanges(context.Background(), []uint64{}, []int{-1, -1, -1}))
|
||||||
assert.Equal(t, uint64(97), s.nodes[0].weight)
|
assert.Equal(t, uint64(97), s.nodes[0].weight)
|
||||||
assert.Equal(t, uint64(98), s.nodes[1].weight)
|
assert.Equal(t, uint64(98), s.nodes[1].weight)
|
||||||
@@ -179,6 +193,8 @@ func TestStore_ApplyScoreChanges_UpdateWeightsMixedDelta(t *testing.T) {
|
|||||||
{parent: 1, root: [32]byte{'A'}, weight: 100}}}
|
{parent: 1, root: [32]byte{'A'}, weight: 100}}}
|
||||||
|
|
||||||
// Each node gets one mixed vote. The weight should look like 100 <- 200 <- 250.
|
// Each node gets one mixed vote. The weight should look like 100 <- 200 <- 250.
|
||||||
|
s.justifiedCheckpoint = &forkchoicetypes.Checkpoint{}
|
||||||
|
s.finalizedCheckpoint = &forkchoicetypes.Checkpoint{}
|
||||||
require.NoError(t, s.applyWeightChanges(context.Background(), []uint64{}, []int{-100, -50, 150}))
|
require.NoError(t, s.applyWeightChanges(context.Background(), []uint64{}, []int{-100, -50, 150}))
|
||||||
assert.Equal(t, uint64(100), s.nodes[0].weight)
|
assert.Equal(t, uint64(100), s.nodes[0].weight)
|
||||||
assert.Equal(t, uint64(200), s.nodes[1].weight)
|
assert.Equal(t, uint64(200), s.nodes[1].weight)
|
||||||
@@ -187,7 +203,9 @@ func TestStore_ApplyScoreChanges_UpdateWeightsMixedDelta(t *testing.T) {
|
|||||||
|
|
||||||
func TestStore_UpdateBestChildAndDescendant_RemoveChild(t *testing.T) {
|
func TestStore_UpdateBestChildAndDescendant_RemoveChild(t *testing.T) {
|
||||||
// Make parent's best child equal's to input child index and child is not viable.
|
// Make parent's best child equal's to input child index and child is not viable.
|
||||||
s := &Store{nodes: []*Node{{bestChild: 1}, {}}, justifiedEpoch: 1, finalizedEpoch: 1}
|
jc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||||
|
fc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||||
|
s := &Store{nodes: []*Node{{bestChild: 1}, {}}, justifiedCheckpoint: jc, finalizedCheckpoint: fc}
|
||||||
require.NoError(t, s.updateBestChildAndDescendant(0, 1))
|
require.NoError(t, s.updateBestChildAndDescendant(0, 1))
|
||||||
|
|
||||||
// Verify parent's best child and best descendant are `none`.
|
// Verify parent's best child and best descendant are `none`.
|
||||||
@@ -198,6 +216,8 @@ func TestStore_UpdateBestChildAndDescendant_RemoveChild(t *testing.T) {
|
|||||||
func TestStore_UpdateBestChildAndDescendant_UpdateDescendant(t *testing.T) {
|
func TestStore_UpdateBestChildAndDescendant_UpdateDescendant(t *testing.T) {
|
||||||
// Make parent's best child equal to child index and child is viable.
|
// Make parent's best child equal to child index and child is viable.
|
||||||
s := &Store{nodes: []*Node{{bestChild: 1}, {bestDescendant: NonExistentNode}}}
|
s := &Store{nodes: []*Node{{bestChild: 1}, {bestDescendant: NonExistentNode}}}
|
||||||
|
s.justifiedCheckpoint = &forkchoicetypes.Checkpoint{}
|
||||||
|
s.finalizedCheckpoint = &forkchoicetypes.Checkpoint{}
|
||||||
require.NoError(t, s.updateBestChildAndDescendant(0, 1))
|
require.NoError(t, s.updateBestChildAndDescendant(0, 1))
|
||||||
|
|
||||||
// Verify parent's best child is the same and best descendant is not set to child index.
|
// Verify parent's best child is the same and best descendant is not set to child index.
|
||||||
@@ -208,9 +228,11 @@ func TestStore_UpdateBestChildAndDescendant_UpdateDescendant(t *testing.T) {
|
|||||||
func TestStore_UpdateBestChildAndDescendant_ChangeChildByViability(t *testing.T) {
|
func TestStore_UpdateBestChildAndDescendant_ChangeChildByViability(t *testing.T) {
|
||||||
// Make parent's best child not equal to child index, child leads to viable index and
|
// Make parent's best child not equal to child index, child leads to viable index and
|
||||||
// parent's best child doesn't lead to viable index.
|
// parent's best child doesn't lead to viable index.
|
||||||
|
jc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||||
|
fc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||||
s := &Store{
|
s := &Store{
|
||||||
justifiedEpoch: 1,
|
justifiedCheckpoint: jc,
|
||||||
finalizedEpoch: 1,
|
finalizedCheckpoint: fc,
|
||||||
nodes: []*Node{{bestChild: 1, justifiedEpoch: 1, finalizedEpoch: 1},
|
nodes: []*Node{{bestChild: 1, justifiedEpoch: 1, finalizedEpoch: 1},
|
||||||
{bestDescendant: NonExistentNode},
|
{bestDescendant: NonExistentNode},
|
||||||
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1}}}
|
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1}}}
|
||||||
@@ -224,9 +246,11 @@ func TestStore_UpdateBestChildAndDescendant_ChangeChildByViability(t *testing.T)
|
|||||||
func TestStore_UpdateBestChildAndDescendant_ChangeChildByWeight(t *testing.T) {
|
func TestStore_UpdateBestChildAndDescendant_ChangeChildByWeight(t *testing.T) {
|
||||||
// Make parent's best child not equal to child index, child leads to viable index and
|
// Make parent's best child not equal to child index, child leads to viable index and
|
||||||
// parents best child leads to viable index but child has more weight than parent's best child.
|
// parents best child leads to viable index but child has more weight than parent's best child.
|
||||||
|
jc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||||
|
fc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||||
s := &Store{
|
s := &Store{
|
||||||
justifiedEpoch: 1,
|
justifiedCheckpoint: jc,
|
||||||
finalizedEpoch: 1,
|
finalizedCheckpoint: fc,
|
||||||
nodes: []*Node{{bestChild: 1, justifiedEpoch: 1, finalizedEpoch: 1},
|
nodes: []*Node{{bestChild: 1, justifiedEpoch: 1, finalizedEpoch: 1},
|
||||||
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1},
|
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1},
|
||||||
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1, weight: 1}}}
|
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1, weight: 1}}}
|
||||||
@@ -239,9 +263,11 @@ func TestStore_UpdateBestChildAndDescendant_ChangeChildByWeight(t *testing.T) {
|
|||||||
|
|
||||||
func TestStore_UpdateBestChildAndDescendant_ChangeChildAtLeaf(t *testing.T) {
|
func TestStore_UpdateBestChildAndDescendant_ChangeChildAtLeaf(t *testing.T) {
|
||||||
// Make parent's best child to none and input child leads to viable index.
|
// Make parent's best child to none and input child leads to viable index.
|
||||||
|
jc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||||
|
fc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||||
s := &Store{
|
s := &Store{
|
||||||
justifiedEpoch: 1,
|
justifiedCheckpoint: jc,
|
||||||
finalizedEpoch: 1,
|
finalizedCheckpoint: fc,
|
||||||
nodes: []*Node{{bestChild: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1},
|
nodes: []*Node{{bestChild: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1},
|
||||||
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1},
|
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1},
|
||||||
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1}}}
|
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1}}}
|
||||||
@@ -255,9 +281,11 @@ func TestStore_UpdateBestChildAndDescendant_ChangeChildAtLeaf(t *testing.T) {
|
|||||||
func TestStore_UpdateBestChildAndDescendant_NoChangeByViability(t *testing.T) {
|
func TestStore_UpdateBestChildAndDescendant_NoChangeByViability(t *testing.T) {
|
||||||
// Make parent's best child not equal to child index, child leads to not viable index and
|
// Make parent's best child not equal to child index, child leads to not viable index and
|
||||||
// parents best child leads to viable index.
|
// parents best child leads to viable index.
|
||||||
|
jc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||||
|
fc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||||
s := &Store{
|
s := &Store{
|
||||||
justifiedEpoch: 1,
|
justifiedCheckpoint: jc,
|
||||||
finalizedEpoch: 1,
|
finalizedCheckpoint: fc,
|
||||||
nodes: []*Node{{bestChild: 1, justifiedEpoch: 1, finalizedEpoch: 1},
|
nodes: []*Node{{bestChild: 1, justifiedEpoch: 1, finalizedEpoch: 1},
|
||||||
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1},
|
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1},
|
||||||
{bestDescendant: NonExistentNode}}}
|
{bestDescendant: NonExistentNode}}}
|
||||||
@@ -271,9 +299,11 @@ func TestStore_UpdateBestChildAndDescendant_NoChangeByViability(t *testing.T) {
|
|||||||
func TestStore_UpdateBestChildAndDescendant_NoChangeByWeight(t *testing.T) {
|
func TestStore_UpdateBestChildAndDescendant_NoChangeByWeight(t *testing.T) {
|
||||||
// Make parent's best child not equal to child index, child leads to viable index and
|
// Make parent's best child not equal to child index, child leads to viable index and
|
||||||
// parents best child leads to viable index but parent's best child has more weight.
|
// parents best child leads to viable index but parent's best child has more weight.
|
||||||
|
jc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||||
|
fc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||||
s := &Store{
|
s := &Store{
|
||||||
justifiedEpoch: 1,
|
justifiedCheckpoint: jc,
|
||||||
finalizedEpoch: 1,
|
finalizedCheckpoint: fc,
|
||||||
nodes: []*Node{{bestChild: 1, justifiedEpoch: 1, finalizedEpoch: 1},
|
nodes: []*Node{{bestChild: 1, justifiedEpoch: 1, finalizedEpoch: 1},
|
||||||
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1, weight: 1},
|
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1, weight: 1},
|
||||||
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1}}}
|
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1}}}
|
||||||
@@ -286,9 +316,11 @@ func TestStore_UpdateBestChildAndDescendant_NoChangeByWeight(t *testing.T) {
|
|||||||
|
|
||||||
func TestStore_UpdateBestChildAndDescendant_NoChangeAtLeaf(t *testing.T) {
|
func TestStore_UpdateBestChildAndDescendant_NoChangeAtLeaf(t *testing.T) {
|
||||||
// Make parent's best child to none and input child does not lead to viable index.
|
// Make parent's best child to none and input child does not lead to viable index.
|
||||||
|
jc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||||
|
fc := &forkchoicetypes.Checkpoint{Epoch: 1}
|
||||||
s := &Store{
|
s := &Store{
|
||||||
justifiedEpoch: 1,
|
justifiedCheckpoint: jc,
|
||||||
finalizedEpoch: 1,
|
finalizedCheckpoint: fc,
|
||||||
nodes: []*Node{{bestChild: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1},
|
nodes: []*Node{{bestChild: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1},
|
||||||
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1},
|
{bestDescendant: NonExistentNode, justifiedEpoch: 1, finalizedEpoch: 1},
|
||||||
{bestDescendant: NonExistentNode}}}
|
{bestDescendant: NonExistentNode}}}
|
||||||
@@ -786,10 +818,12 @@ func TestStore_LeadsToViableHead(t *testing.T) {
|
|||||||
{&Node{finalizedEpoch: 3, justifiedEpoch: 4}, 4, 3, true},
|
{&Node{finalizedEpoch: 3, justifiedEpoch: 4}, 4, 3, true},
|
||||||
}
|
}
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
|
jc := &forkchoicetypes.Checkpoint{Epoch: tc.justifiedEpoch}
|
||||||
|
fc := &forkchoicetypes.Checkpoint{Epoch: tc.finalizedEpoch}
|
||||||
s := &Store{
|
s := &Store{
|
||||||
justifiedEpoch: tc.justifiedEpoch,
|
justifiedCheckpoint: jc,
|
||||||
finalizedEpoch: tc.finalizedEpoch,
|
finalizedCheckpoint: fc,
|
||||||
nodes: []*Node{tc.n},
|
nodes: []*Node{tc.n},
|
||||||
}
|
}
|
||||||
got, err := s.leadsToViableHead(tc.n)
|
got, err := s.leadsToViableHead(tc.n)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -812,9 +846,11 @@ func TestStore_ViableForHead(t *testing.T) {
|
|||||||
{&Node{finalizedEpoch: 3, justifiedEpoch: 4}, 4, 3, true},
|
{&Node{finalizedEpoch: 3, justifiedEpoch: 4}, 4, 3, true},
|
||||||
}
|
}
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
|
jc := &forkchoicetypes.Checkpoint{Epoch: tc.justifiedEpoch}
|
||||||
|
fc := &forkchoicetypes.Checkpoint{Epoch: tc.finalizedEpoch}
|
||||||
s := &Store{
|
s := &Store{
|
||||||
justifiedEpoch: tc.justifiedEpoch,
|
justifiedCheckpoint: jc,
|
||||||
finalizedEpoch: tc.finalizedEpoch,
|
finalizedCheckpoint: fc,
|
||||||
}
|
}
|
||||||
assert.Equal(t, tc.want, s.viableForHead(tc.n))
|
assert.Equal(t, tc.want, s.viableForHead(tc.n))
|
||||||
}
|
}
|
||||||
@@ -984,7 +1020,7 @@ func TestStore_RemoveEquivocating(t *testing.T) {
|
|||||||
state, blkRoot, err := prepareForkchoiceState(ctx, 1, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1)
|
state, blkRoot, err := prepareForkchoiceState(ctx, 1, [32]byte{'a'}, params.BeaconConfig().ZeroHash, [32]byte{'A'}, 1, 1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
head, err := f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{})
|
head, err := f.Head(ctx, []uint64{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, [32]byte{'a'}, head)
|
require.Equal(t, [32]byte{'a'}, head)
|
||||||
|
|
||||||
@@ -995,20 +1031,20 @@ func TestStore_RemoveEquivocating(t *testing.T) {
|
|||||||
state, blkRoot, err = prepareForkchoiceState(ctx, 3, [32]byte{'c'}, [32]byte{'a'}, [32]byte{'C'}, 1, 1)
|
state, blkRoot, err = prepareForkchoiceState(ctx, 3, [32]byte{'c'}, [32]byte{'a'}, [32]byte{'C'}, 1, 1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
head, err = f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{})
|
head, err = f.Head(ctx, []uint64{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, [32]byte{'c'}, head)
|
require.Equal(t, [32]byte{'c'}, head)
|
||||||
|
|
||||||
// Insert two attestations for block b, it becomes head
|
// Insert two attestations for block b, it becomes head
|
||||||
f.ProcessAttestation(ctx, []uint64{1, 2}, [32]byte{'b'}, 1)
|
f.ProcessAttestation(ctx, []uint64{1, 2}, [32]byte{'b'}, 1)
|
||||||
f.ProcessAttestation(ctx, []uint64{3}, [32]byte{'c'}, 1)
|
f.ProcessAttestation(ctx, []uint64{3}, [32]byte{'c'}, 1)
|
||||||
head, err = f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300})
|
head, err = f.Head(ctx, []uint64{100, 200, 200, 300})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, [32]byte{'b'}, head)
|
require.Equal(t, [32]byte{'b'}, head)
|
||||||
|
|
||||||
// Process b's slashing, c is now head
|
// Process b's slashing, c is now head
|
||||||
f.InsertSlashedIndex(ctx, 1)
|
f.InsertSlashedIndex(ctx, 1)
|
||||||
head, err = f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300})
|
head, err = f.Head(ctx, []uint64{100, 200, 200, 300})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, [32]byte{'c'}, head)
|
require.Equal(t, [32]byte{'c'}, head)
|
||||||
require.Equal(t, uint64(200), f.store.nodes[2].weight)
|
require.Equal(t, uint64(200), f.store.nodes[2].weight)
|
||||||
@@ -1016,7 +1052,7 @@ func TestStore_RemoveEquivocating(t *testing.T) {
|
|||||||
|
|
||||||
// Process the same slashing again, should be a noop
|
// Process the same slashing again, should be a noop
|
||||||
f.InsertSlashedIndex(ctx, 1)
|
f.InsertSlashedIndex(ctx, 1)
|
||||||
head, err = f.Head(ctx, params.BeaconConfig().ZeroHash, []uint64{100, 200, 200, 300})
|
head, err = f.Head(ctx, []uint64{100, 200, 200, 300})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, [32]byte{'c'}, head)
|
require.Equal(t, [32]byte{'c'}, head)
|
||||||
require.Equal(t, uint64(200), f.store.nodes[2].weight)
|
require.Equal(t, uint64(200), f.store.nodes[2].weight)
|
||||||
@@ -1032,12 +1068,12 @@ func TestStore_UpdateCheckpoints(t *testing.T) {
|
|||||||
f := setup(1, 1)
|
f := setup(1, 1)
|
||||||
jr := [32]byte{'j'}
|
jr := [32]byte{'j'}
|
||||||
fr := [32]byte{'f'}
|
fr := [32]byte{'f'}
|
||||||
jc := ðpb.Checkpoint{Root: jr[:], Epoch: 3}
|
jc := &forkchoicetypes.Checkpoint{Root: jr, Epoch: 3}
|
||||||
fc := ðpb.Checkpoint{Root: fr[:], Epoch: 2}
|
fc := &forkchoicetypes.Checkpoint{Root: fr, Epoch: 2}
|
||||||
require.NoError(t, f.UpdateJustifiedCheckpoint(jc))
|
require.NoError(t, f.UpdateJustifiedCheckpoint(jc))
|
||||||
require.NoError(t, f.UpdateFinalizedCheckpoint(fc))
|
require.NoError(t, f.UpdateFinalizedCheckpoint(fc))
|
||||||
require.Equal(t, f.store.justifiedEpoch, jc.Epoch)
|
require.Equal(t, f.store.justifiedCheckpoint, jc)
|
||||||
require.Equal(t, f.store.finalizedEpoch, fc.Epoch)
|
require.Equal(t, f.store.finalizedCheckpoint, fc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStore_InsertOptimisticChain(t *testing.T) {
|
func TestStore_InsertOptimisticChain(t *testing.T) {
|
||||||
@@ -1051,8 +1087,10 @@ func TestStore_InsertOptimisticChain(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
wsb, err := wrapper.WrappedSignedBeaconBlock(blk)
|
wsb, err := wrapper.WrappedSignedBeaconBlock(blk)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
blks = append(blks, &forkchoicetypes.BlockAndCheckpoints{Block: wsb.Block(), JustifiedEpoch: 1,
|
blks = append(blks, &forkchoicetypes.BlockAndCheckpoints{Block: wsb.Block(),
|
||||||
FinalizedEpoch: 1})
|
JustifiedCheckpoint: ðpb.Checkpoint{Epoch: 1, Root: params.BeaconConfig().ZeroHash[:]},
|
||||||
|
FinalizedCheckpoint: ðpb.Checkpoint{Epoch: 1, Root: params.BeaconConfig().ZeroHash[:]},
|
||||||
|
})
|
||||||
for i := uint64(2); i < 11; i++ {
|
for i := uint64(2); i < 11; i++ {
|
||||||
blk := util.NewBeaconBlock()
|
blk := util.NewBeaconBlock()
|
||||||
blk.Block.Slot = types.Slot(i)
|
blk.Block.Slot = types.Slot(i)
|
||||||
@@ -1060,8 +1098,10 @@ func TestStore_InsertOptimisticChain(t *testing.T) {
|
|||||||
blk.Block.ParentRoot = copiedRoot[:]
|
blk.Block.ParentRoot = copiedRoot[:]
|
||||||
wsb, err = wrapper.WrappedSignedBeaconBlock(blk)
|
wsb, err = wrapper.WrappedSignedBeaconBlock(blk)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
blks = append(blks, &forkchoicetypes.BlockAndCheckpoints{Block: wsb.Block(), JustifiedEpoch: 1,
|
blks = append(blks, &forkchoicetypes.BlockAndCheckpoints{Block: wsb.Block(),
|
||||||
FinalizedEpoch: 1})
|
JustifiedCheckpoint: ðpb.Checkpoint{Epoch: 1, Root: params.BeaconConfig().ZeroHash[:]},
|
||||||
|
FinalizedCheckpoint: ðpb.Checkpoint{Epoch: 1, Root: params.BeaconConfig().ZeroHash[:]},
|
||||||
|
})
|
||||||
root, err = blk.Block.HashTreeRoot()
|
root, err = blk.Block.HashTreeRoot()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package protoarray
|
|||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||||
)
|
)
|
||||||
@@ -18,8 +19,8 @@ type ForkChoice struct {
|
|||||||
// Store defines the fork choice store which includes block nodes and the last view of checkpoint information.
|
// Store defines the fork choice store which includes block nodes and the last view of checkpoint information.
|
||||||
type Store struct {
|
type Store struct {
|
||||||
pruneThreshold uint64 // do not prune tree unless threshold is reached.
|
pruneThreshold uint64 // do not prune tree unless threshold is reached.
|
||||||
justifiedEpoch types.Epoch // latest justified epoch in store.
|
justifiedCheckpoint *forkchoicetypes.Checkpoint // latest justified checkpoint in store.
|
||||||
finalizedEpoch types.Epoch // latest finalized epoch in store.
|
finalizedCheckpoint *forkchoicetypes.Checkpoint // latest finalized checkpoint in store.
|
||||||
proposerBoostRoot [fieldparams.RootLength]byte // latest block root that was boosted after being received in a timely manner.
|
proposerBoostRoot [fieldparams.RootLength]byte // latest block root that was boosted after being received in a timely manner.
|
||||||
previousProposerBoostRoot [fieldparams.RootLength]byte // previous block root that was boosted after being received in a timely manner.
|
previousProposerBoostRoot [fieldparams.RootLength]byte // previous block root that was boosted after being received in a timely manner.
|
||||||
previousProposerBoostScore uint64 // previous proposer boosted root score.
|
previousProposerBoostScore uint64 // previous proposer boosted root score.
|
||||||
@@ -30,6 +31,7 @@ type Store struct {
|
|||||||
slashedIndices map[types.ValidatorIndex]bool // The list of equivocating validators
|
slashedIndices map[types.ValidatorIndex]bool // The list of equivocating validators
|
||||||
nodesLock sync.RWMutex
|
nodesLock sync.RWMutex
|
||||||
proposerBoostLock sync.RWMutex
|
proposerBoostLock sync.RWMutex
|
||||||
|
checkpointsLock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// Node defines the individual block which includes its block parent, ancestor and how much weight accounted for it.
|
// Node defines the individual block which includes its block parent, ancestor and how much weight accounted for it.
|
||||||
|
|||||||
@@ -55,11 +55,11 @@ func (f *ForkChoice) UpdateUnrealizedCheckpoints() {
|
|||||||
for _, node := range f.store.nodes {
|
for _, node := range f.store.nodes {
|
||||||
node.justifiedEpoch = node.unrealizedJustifiedEpoch
|
node.justifiedEpoch = node.unrealizedJustifiedEpoch
|
||||||
node.finalizedEpoch = node.unrealizedFinalizedEpoch
|
node.finalizedEpoch = node.unrealizedFinalizedEpoch
|
||||||
if node.justifiedEpoch > f.store.justifiedEpoch {
|
if node.justifiedEpoch > f.store.justifiedCheckpoint.Epoch {
|
||||||
f.store.justifiedEpoch = node.justifiedEpoch
|
f.store.justifiedCheckpoint.Epoch = node.justifiedEpoch
|
||||||
}
|
}
|
||||||
if node.finalizedEpoch > f.store.finalizedEpoch {
|
if node.finalizedEpoch > f.store.finalizedCheckpoint.Epoch {
|
||||||
f.store.finalizedEpoch = node.finalizedEpoch
|
f.store.finalizedCheckpoint.Epoch = node.finalizedEpoch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import (
|
|||||||
|
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
|
||||||
"github.com/prysmaticlabs/prysm/testing/require"
|
"github.com/prysmaticlabs/prysm/testing/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -81,25 +81,25 @@ func TestStore_LongFork(t *testing.T) {
|
|||||||
|
|
||||||
// Add an attestation to c, it is head
|
// Add an attestation to c, it is head
|
||||||
f.ProcessAttestation(ctx, []uint64{0}, [32]byte{'c'}, 1)
|
f.ProcessAttestation(ctx, []uint64{0}, [32]byte{'c'}, 1)
|
||||||
headRoot, err := f.Head(ctx, [32]byte{}, []uint64{100})
|
headRoot, err := f.Head(ctx, []uint64{100})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, [32]byte{'c'}, headRoot)
|
require.Equal(t, [32]byte{'c'}, headRoot)
|
||||||
|
|
||||||
// D is head even though its weight is lower.
|
// D is head even though its weight is lower.
|
||||||
hr := [32]byte{'d'}
|
ha := [32]byte{'a'}
|
||||||
state, blkRoot, err = prepareForkchoiceState(ctx, 103, hr, [32]byte{'b'}, [32]byte{'D'}, 2, 1)
|
state, blkRoot, err = prepareForkchoiceState(ctx, 103, [32]byte{'d'}, [32]byte{'b'}, [32]byte{'D'}, 2, 1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
require.NoError(t, f.UpdateJustifiedCheckpoint(ðpb.Checkpoint{Epoch: 2, Root: hr[:]}))
|
require.NoError(t, f.UpdateJustifiedCheckpoint(&forkchoicetypes.Checkpoint{Epoch: 2, Root: ha}))
|
||||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
headRoot, err = f.Head(ctx, []uint64{100})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, hr, headRoot)
|
require.Equal(t, [32]byte{'d'}, headRoot)
|
||||||
require.Equal(t, uint64(0), f.store.nodes[4].weight)
|
require.Equal(t, uint64(0), f.store.nodes[4].weight)
|
||||||
require.Equal(t, uint64(100), f.store.nodes[3].weight)
|
require.Equal(t, uint64(100), f.store.nodes[3].weight)
|
||||||
|
|
||||||
// Update unrealized justification, c becomes head
|
// Update unrealized justification, c becomes head
|
||||||
f.UpdateUnrealizedCheckpoints()
|
f.UpdateUnrealizedCheckpoints()
|
||||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
headRoot, err = f.Head(ctx, []uint64{100})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, [32]byte{'c'}, headRoot)
|
require.Equal(t, [32]byte{'c'}, headRoot)
|
||||||
}
|
}
|
||||||
@@ -158,30 +158,31 @@ func TestStore_NoDeadLock(t *testing.T) {
|
|||||||
|
|
||||||
// Epoch 3
|
// Epoch 3
|
||||||
// Current Head is H
|
// Current Head is H
|
||||||
headRoot, err := f.Head(ctx, [32]byte{}, []uint64{100})
|
headRoot, err := f.Head(ctx, []uint64{100})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, [32]byte{'h'}, headRoot)
|
require.Equal(t, [32]byte{'h'}, headRoot)
|
||||||
require.Equal(t, types.Epoch(0), f.JustifiedEpoch())
|
require.Equal(t, types.Epoch(0), f.JustifiedCheckpoint().Epoch)
|
||||||
|
|
||||||
// Insert Block I, it becomes Head
|
// Insert Block I, it becomes Head
|
||||||
hr := [32]byte{'i'}
|
hr := [32]byte{'i'}
|
||||||
state, blkRoot, err = prepareForkchoiceState(ctx, 108, hr, [32]byte{'f'}, [32]byte{'I'}, 1, 0)
|
state, blkRoot, err = prepareForkchoiceState(ctx, 108, hr, [32]byte{'f'}, [32]byte{'I'}, 1, 0)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
require.NoError(t, f.UpdateJustifiedCheckpoint(ðpb.Checkpoint{Epoch: 1, Root: hr[:]}))
|
ha := [32]byte{'a'}
|
||||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
require.NoError(t, f.UpdateJustifiedCheckpoint(&forkchoicetypes.Checkpoint{Epoch: 1, Root: ha}))
|
||||||
|
headRoot, err = f.Head(ctx, []uint64{100})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, hr, headRoot)
|
require.Equal(t, hr, headRoot)
|
||||||
require.Equal(t, types.Epoch(1), f.JustifiedEpoch())
|
require.Equal(t, types.Epoch(1), f.JustifiedCheckpoint().Epoch)
|
||||||
require.Equal(t, types.Epoch(0), f.FinalizedEpoch())
|
require.Equal(t, types.Epoch(0), f.FinalizedCheckpoint().Epoch)
|
||||||
|
|
||||||
// Realized Justified checkpoints, H becomes head
|
// Realized Justified checkpoints, H becomes head
|
||||||
f.UpdateUnrealizedCheckpoints()
|
f.UpdateUnrealizedCheckpoints()
|
||||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
headRoot, err = f.Head(ctx, []uint64{100})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, [32]byte{'h'}, headRoot)
|
require.Equal(t, [32]byte{'h'}, headRoot)
|
||||||
require.Equal(t, types.Epoch(2), f.JustifiedEpoch())
|
require.Equal(t, types.Epoch(2), f.JustifiedCheckpoint().Epoch)
|
||||||
require.Equal(t, types.Epoch(1), f.FinalizedEpoch())
|
require.Equal(t, types.Epoch(1), f.FinalizedCheckpoint().Epoch)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Epoch 1 | Epoch 2
|
// Epoch 1 | Epoch 2
|
||||||
@@ -226,10 +227,10 @@ func TestStore_ForkNextEpoch(t *testing.T) {
|
|||||||
|
|
||||||
// Insert an attestation to H, H is head
|
// Insert an attestation to H, H is head
|
||||||
f.ProcessAttestation(ctx, []uint64{0}, [32]byte{'h'}, 1)
|
f.ProcessAttestation(ctx, []uint64{0}, [32]byte{'h'}, 1)
|
||||||
headRoot, err := f.Head(ctx, [32]byte{}, []uint64{100})
|
headRoot, err := f.Head(ctx, []uint64{100})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, [32]byte{'h'}, headRoot)
|
require.Equal(t, [32]byte{'h'}, headRoot)
|
||||||
require.Equal(t, types.Epoch(0), f.JustifiedEpoch())
|
require.Equal(t, types.Epoch(0), f.JustifiedCheckpoint().Epoch)
|
||||||
|
|
||||||
// D arrives late, D is head
|
// D arrives late, D is head
|
||||||
state, blkRoot, err = prepareForkchoiceState(ctx, 103, [32]byte{'d'}, [32]byte{'c'}, [32]byte{'D'}, 0, 0)
|
state, blkRoot, err = prepareForkchoiceState(ctx, 103, [32]byte{'d'}, [32]byte{'c'}, [32]byte{'D'}, 0, 0)
|
||||||
@@ -237,10 +238,10 @@ func TestStore_ForkNextEpoch(t *testing.T) {
|
|||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'d'}, 1))
|
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'d'}, 1))
|
||||||
f.UpdateUnrealizedCheckpoints()
|
f.UpdateUnrealizedCheckpoints()
|
||||||
headRoot, err = f.Head(ctx, [32]byte{}, []uint64{100})
|
headRoot, err = f.Head(ctx, []uint64{100})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, [32]byte{'d'}, headRoot)
|
require.Equal(t, [32]byte{'d'}, headRoot)
|
||||||
require.Equal(t, types.Epoch(1), f.JustifiedEpoch())
|
require.Equal(t, types.Epoch(1), f.JustifiedCheckpoint().Epoch)
|
||||||
// nodes[8] = D since it's late!
|
// nodes[8] = D since it's late!
|
||||||
require.Equal(t, uint64(0), f.store.nodes[8].weight)
|
require.Equal(t, uint64(0), f.store.nodes[8].weight)
|
||||||
require.Equal(t, uint64(100), f.store.nodes[7].weight)
|
require.Equal(t, uint64(100), f.store.nodes[7].weight)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
|
||||||
"github.com/prysmaticlabs/prysm/config/params"
|
"github.com/prysmaticlabs/prysm/config/params"
|
||||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||||
"github.com/prysmaticlabs/prysm/testing/require"
|
"github.com/prysmaticlabs/prysm/testing/require"
|
||||||
@@ -15,7 +16,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
// The head should always start at the finalized block.
|
// The head should always start at the finalized block.
|
||||||
r, err := f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err := f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
||||||
|
|
||||||
@@ -27,7 +28,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -39,7 +40,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -48,7 +49,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
// / \
|
// / \
|
||||||
// 2 1 <- +vote, new head
|
// 2 1 <- +vote, new head
|
||||||
f.ProcessAttestation(context.Background(), []uint64{0}, indexToHash(1), 2)
|
f.ProcessAttestation(context.Background(), []uint64{0}, indexToHash(1), 2)
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(1), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(1), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -57,7 +58,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
// / \
|
// / \
|
||||||
// vote, new head -> 2 1
|
// vote, new head -> 2 1
|
||||||
f.ProcessAttestation(context.Background(), []uint64{1}, indexToHash(2), 2)
|
f.ProcessAttestation(context.Background(), []uint64{1}, indexToHash(2), 2)
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -82,7 +83,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
// |
|
// |
|
||||||
// 3 <- new vote
|
// 3 <- new vote
|
||||||
f.ProcessAttestation(context.Background(), []uint64{0}, indexToHash(3), 3)
|
f.ProcessAttestation(context.Background(), []uint64{0}, indexToHash(3), 3)
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -93,7 +94,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
// |
|
// |
|
||||||
// 3 <- head
|
// 3 <- head
|
||||||
f.ProcessAttestation(context.Background(), []uint64{1}, indexToHash(1), 3)
|
f.ProcessAttestation(context.Background(), []uint64{1}, indexToHash(1), 3)
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(3), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(3), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -109,7 +110,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -127,7 +128,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -188,7 +189,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
r, err = f.Head(context.Background(), params.BeaconConfig().ZeroHash, balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(6), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(6), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -209,9 +210,11 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
// 8
|
// 8
|
||||||
// |
|
// |
|
||||||
// 9 <- head
|
// 9 <- head
|
||||||
f.store.justifiedEpoch = 2
|
jc := &forkchoicetypes.Checkpoint{Epoch: 2, Root: indexToHash(5)}
|
||||||
f.store.finalizedEpoch = 2
|
fc := &forkchoicetypes.Checkpoint{Epoch: 2, Root: indexToHash(5)}
|
||||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
f.store.justifiedCheckpoint = jc
|
||||||
|
f.store.finalizedCheckpoint = fc
|
||||||
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||||
|
|
||||||
@@ -237,7 +240,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||||
|
|
||||||
@@ -246,28 +249,28 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
// The new validators voted for 10.
|
// The new validators voted for 10.
|
||||||
f.ProcessAttestation(context.Background(), []uint64{2, 3, 4}, indexToHash(10), 5)
|
f.ProcessAttestation(context.Background(), []uint64{2, 3, 4}, indexToHash(10), 5)
|
||||||
// The new head should be 10.
|
// The new head should be 10.
|
||||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(10), r, "Incorrect head for with justified epoch at 2")
|
assert.Equal(t, indexToHash(10), r, "Incorrect head for with justified epoch at 2")
|
||||||
|
|
||||||
// Set the balances of the last 2 validators to 0.
|
// Set the balances of the last 2 validators to 0.
|
||||||
balances = []uint64{1, 1, 1, 0, 0}
|
balances = []uint64{1, 1, 1, 0, 0}
|
||||||
// The head should be back to 9.
|
// The head should be back to 9.
|
||||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
// Set the balances back to normal.
|
// Set the balances back to normal.
|
||||||
balances = []uint64{1, 1, 1, 1, 1}
|
balances = []uint64{1, 1, 1, 1, 1}
|
||||||
// The head should be back to 10.
|
// The head should be back to 10.
|
||||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(10), r, "Incorrect head for with justified epoch at 2")
|
assert.Equal(t, indexToHash(10), r, "Incorrect head for with justified epoch at 2")
|
||||||
|
|
||||||
// Remove the last 2 validators.
|
// Remove the last 2 validators.
|
||||||
balances = []uint64{1, 1, 1}
|
balances = []uint64{1, 1, 1}
|
||||||
// The head should be back to 9.
|
// The head should be back to 9.
|
||||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 1")
|
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 1")
|
||||||
|
|
||||||
@@ -276,7 +279,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
require.NoError(t, f.store.prune(context.Background(), indexToHash(5)))
|
require.NoError(t, f.store.prune(context.Background(), indexToHash(5)))
|
||||||
assert.Equal(t, 11, len(f.store.nodes), "Incorrect nodes length after prune")
|
assert.Equal(t, 11, len(f.store.nodes), "Incorrect nodes length after prune")
|
||||||
|
|
||||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||||
|
|
||||||
@@ -300,7 +303,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
require.NoError(t, f.store.prune(context.Background(), indexToHash(5)))
|
require.NoError(t, f.store.prune(context.Background(), indexToHash(5)))
|
||||||
assert.Equal(t, 5, len(f.store.nodes), "Incorrect nodes length after prune")
|
assert.Equal(t, 5, len(f.store.nodes), "Incorrect nodes length after prune")
|
||||||
|
|
||||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 2")
|
||||||
|
|
||||||
@@ -318,7 +321,7 @@ func TestVotes_CanFindHead(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
||||||
|
|
||||||
r, err = f.Head(context.Background(), indexToHash(5), balances)
|
r, err = f.Head(context.Background(), balances)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, indexToHash(11), r, "Incorrect head for with justified epoch at 2")
|
assert.Equal(t, indexToHash(11), r, "Incorrect head for with justified epoch at 2")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ go_library(
|
|||||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types",
|
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
|
"//config/fieldparams:go_default_library",
|
||||||
"//consensus-types/interfaces:go_default_library",
|
"//consensus-types/interfaces:go_default_library",
|
||||||
"//consensus-types/primitives:go_default_library",
|
"//consensus-types/primitives:go_default_library",
|
||||||
|
"//proto/prysm/v1alpha1:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||||
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
"github.com/prysmaticlabs/prysm/consensus-types/interfaces"
|
||||||
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
types "github.com/prysmaticlabs/prysm/consensus-types/primitives"
|
||||||
|
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProposerBoostRootArgs to call the BoostProposerRoot function.
|
// ProposerBoostRootArgs to call the BoostProposerRoot function.
|
||||||
@@ -13,9 +15,17 @@ type ProposerBoostRootArgs struct {
|
|||||||
SecondsIntoSlot uint64
|
SecondsIntoSlot uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checkpoint is an array version of ethpb.Checkpoint. It is used internally in
|
||||||
|
// forkchoice, while the slice version is used in the interface to legagy code
|
||||||
|
// in other packages
|
||||||
|
type Checkpoint struct {
|
||||||
|
Epoch types.Epoch
|
||||||
|
Root [fieldparams.RootLength]byte
|
||||||
|
}
|
||||||
|
|
||||||
// BlockAndCheckpoints to call the InsertOptimisticChain function
|
// BlockAndCheckpoints to call the InsertOptimisticChain function
|
||||||
type BlockAndCheckpoints struct {
|
type BlockAndCheckpoints struct {
|
||||||
Block interfaces.BeaconBlock
|
Block interfaces.BeaconBlock
|
||||||
JustifiedEpoch types.Epoch
|
JustifiedCheckpoint *ethpb.Checkpoint
|
||||||
FinalizedEpoch types.Epoch
|
FinalizedCheckpoint *ethpb.Checkpoint
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -348,9 +348,9 @@ func (b *BeaconNode) Close() {
|
|||||||
|
|
||||||
func (b *BeaconNode) startForkChoice() {
|
func (b *BeaconNode) startForkChoice() {
|
||||||
if features.Get().EnableForkChoiceDoublyLinkedTree {
|
if features.Get().EnableForkChoiceDoublyLinkedTree {
|
||||||
b.forkChoiceStore = doublylinkedtree.New(0, 0)
|
b.forkChoiceStore = doublylinkedtree.New()
|
||||||
} else {
|
} else {
|
||||||
b.forkChoiceStore = protoarray.New(0, 0)
|
b.forkChoiceStore = protoarray.New()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ func (ds *Server) GetForkChoice(_ context.Context, _ *empty.Empty) (*pbrpc.ForkC
|
|||||||
store := ds.ForkFetcher.ForkChoicer()
|
store := ds.ForkFetcher.ForkChoicer()
|
||||||
|
|
||||||
return &pbrpc.ForkChoiceResponse{
|
return &pbrpc.ForkChoiceResponse{
|
||||||
JustifiedEpoch: store.JustifiedEpoch(),
|
JustifiedEpoch: store.JustifiedCheckpoint().Epoch,
|
||||||
FinalizedEpoch: store.FinalizedEpoch(),
|
FinalizedEpoch: store.FinalizedCheckpoint().Epoch,
|
||||||
ForkchoiceNodes: store.ForkChoiceNodes(),
|
ForkchoiceNodes: store.ForkChoiceNodes(),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestServer_GetForkChoice_ProtoArray(t *testing.T) {
|
func TestServer_GetForkChoice_ProtoArray(t *testing.T) {
|
||||||
store := protoarray.New(0, 0)
|
store := protoarray.New()
|
||||||
bs := &Server{ForkFetcher: &mock.ChainService{ForkChoiceStore: store}}
|
bs := &Server{ForkFetcher: &mock.ChainService{ForkChoiceStore: store}}
|
||||||
res, err := bs.GetForkChoice(context.Background(), &empty.Empty{})
|
res, err := bs.GetForkChoice(context.Background(), &empty.Empty{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, store.JustifiedEpoch(), res.JustifiedEpoch, "Did not get wanted justified epoch")
|
assert.Equal(t, store.JustifiedCheckpoint().Epoch, res.JustifiedEpoch, "Did not get wanted justified epoch")
|
||||||
assert.Equal(t, store.FinalizedEpoch(), res.FinalizedEpoch, "Did not get wanted finalized epoch")
|
assert.Equal(t, store.FinalizedCheckpoint().Epoch, res.FinalizedEpoch, "Did not get wanted finalized epoch")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ func startChainService(t testing.TB, st state.BeaconState, block interfaces.Sign
|
|||||||
blockchain.WithFinalizedStateAtStartUp(st),
|
blockchain.WithFinalizedStateAtStartUp(st),
|
||||||
blockchain.WithDatabase(db),
|
blockchain.WithDatabase(db),
|
||||||
blockchain.WithAttestationService(attPool),
|
blockchain.WithAttestationService(attPool),
|
||||||
blockchain.WithForkChoiceStore(protoarray.New(0, 0)),
|
blockchain.WithForkChoiceStore(protoarray.New()),
|
||||||
blockchain.WithStateGen(stategen.New(db)),
|
blockchain.WithStateGen(stategen.New(db)),
|
||||||
blockchain.WithStateNotifier(&mock.MockStateNotifier{}),
|
blockchain.WithStateNotifier(&mock.MockStateNotifier{}),
|
||||||
blockchain.WithAttestationPool(attestations.NewPool()),
|
blockchain.WithAttestationPool(attestations.NewPool()),
|
||||||
|
|||||||
Reference in New Issue
Block a user