mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-25 21:07:18 +00:00
fc509cc220
* Prune during on_tick * add unit test * fix tests Co-authored-by: terencechain <terence@prysmaticlabs.com> Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
312 lines
11 KiB
Go
312 lines
11 KiB
Go
package doublylinkedtree
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/prysmaticlabs/prysm/v3/config/params"
|
|
"github.com/prysmaticlabs/prysm/v3/testing/assert"
|
|
"github.com/prysmaticlabs/prysm/v3/testing/require"
|
|
)
|
|
|
|
func TestVotes_CanFindHead(t *testing.T) {
|
|
balances := []uint64{1, 1}
|
|
f := setup(1, 1)
|
|
ctx := context.Background()
|
|
|
|
// The head should always start at the finalized block.
|
|
r, err := f.Head(context.Background(), balances)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, params.BeaconConfig().ZeroHash, r, "Incorrect head with genesis")
|
|
|
|
// Insert block 2 into the tree and verify head is at 2:
|
|
// 0
|
|
// /
|
|
// 2 <- head
|
|
state, blkRoot, err := prepareForkchoiceState(context.Background(), 0, indexToHash(2), params.BeaconConfig().ZeroHash, params.BeaconConfig().ZeroHash, 1, 1)
|
|
require.NoError(t, err)
|
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
|
|
|
r, err = f.Head(context.Background(), balances)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
|
|
|
// Insert block 1 into the tree and verify head is still at 2:
|
|
// 0
|
|
// / \
|
|
// head -> 2 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, f.InsertNode(ctx, state, blkRoot))
|
|
|
|
r, err = f.Head(context.Background(), balances)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
|
|
|
// Add a vote to block 1 of the tree and verify head is switched to 1:
|
|
// 0
|
|
// / \
|
|
// 2 1 <- +vote, new head
|
|
f.ProcessAttestation(context.Background(), []uint64{0}, indexToHash(1), 2)
|
|
r, err = f.Head(context.Background(), balances)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, indexToHash(1), r, "Incorrect head for with justified epoch at 1")
|
|
|
|
// Add a vote to block 2 of the tree and verify head is switched to 2:
|
|
// 0
|
|
// / \
|
|
// vote, new head -> 2 1
|
|
f.ProcessAttestation(context.Background(), []uint64{1}, indexToHash(2), 2)
|
|
r, err = f.Head(context.Background(), balances)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
|
|
|
// Insert block 3 into the tree and verify head is still at 2:
|
|
// 0
|
|
// / \
|
|
// head -> 2 1
|
|
// |
|
|
// 3
|
|
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(3), indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1)
|
|
require.NoError(t, err)
|
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
|
|
|
r, err = f.Head(context.Background(), balances)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
|
|
|
// Move validator 0's vote from 1 to 3 and verify head is still at 2:
|
|
// 0
|
|
// / \
|
|
// head -> 2 1 <- old vote
|
|
// |
|
|
// 3 <- new vote
|
|
f.ProcessAttestation(context.Background(), []uint64{0}, indexToHash(3), 3)
|
|
r, err = f.Head(context.Background(), balances)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, indexToHash(2), r, "Incorrect head for with justified epoch at 1")
|
|
|
|
// Move validator 1's vote from 2 to 1 and verify head is switched to 3:
|
|
// 0
|
|
// / \
|
|
// old vote -> 2 1 <- new vote
|
|
// |
|
|
// 3 <- head
|
|
f.ProcessAttestation(context.Background(), []uint64{1}, indexToHash(1), 3)
|
|
r, err = f.Head(context.Background(), balances)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, indexToHash(3), r, "Incorrect head for with justified epoch at 1")
|
|
|
|
// Insert block 4 into the tree and verify head is at 4:
|
|
// 0
|
|
// / \
|
|
// 2 1
|
|
// |
|
|
// 3
|
|
// |
|
|
// 4 <- head
|
|
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(4), indexToHash(3), params.BeaconConfig().ZeroHash, 1, 1)
|
|
require.NoError(t, err)
|
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
|
|
|
r, err = f.Head(context.Background(), balances)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, indexToHash(4), r, "Incorrect head for with justified epoch at 1")
|
|
|
|
// Insert block 5 with justified epoch 2, it becomes head
|
|
// 0
|
|
// / \
|
|
// 2 1
|
|
// |
|
|
// 3
|
|
// |
|
|
// 4 <- head
|
|
// /
|
|
// 5 <- justified epoch = 2
|
|
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(5), indexToHash(4), params.BeaconConfig().ZeroHash, 2, 2)
|
|
require.NoError(t, err)
|
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
|
|
|
r, err = f.Head(context.Background(), balances)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, indexToHash(5), r, "Incorrect head for with justified epoch at 1")
|
|
|
|
// Insert block 6 with justified epoch 3: verify it's head
|
|
// 0
|
|
// / \
|
|
// 2 1
|
|
// |
|
|
// 3
|
|
// |
|
|
// 4 <- head
|
|
// / \
|
|
// 5 6 <- justified epoch = 3
|
|
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(6), indexToHash(4), params.BeaconConfig().ZeroHash, 3, 2)
|
|
require.NoError(t, err)
|
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
|
r, err = f.Head(context.Background(), balances)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, indexToHash(6), r, "Incorrect head for with justified epoch at 1")
|
|
|
|
// Moved 2 votes to block 5:
|
|
f.ProcessAttestation(context.Background(), []uint64{0, 1}, indexToHash(5), 4)
|
|
|
|
// Inset blocks 7 and 8
|
|
// 6 should still be the head, even though 5 has all the votes.
|
|
// 0
|
|
// / \
|
|
// 2 1
|
|
// |
|
|
// 3
|
|
// |
|
|
// 4
|
|
// / \
|
|
// 5 6 <- head
|
|
// |
|
|
// 7
|
|
// |
|
|
// 8
|
|
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(7), indexToHash(5), params.BeaconConfig().ZeroHash, 2, 2)
|
|
require.NoError(t, err)
|
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
|
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(8), indexToHash(7), params.BeaconConfig().ZeroHash, 2, 2)
|
|
require.NoError(t, err)
|
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
|
r, err = f.Head(context.Background(), balances)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, indexToHash(6), r, "Incorrect head for with justified epoch at 1")
|
|
|
|
// Insert block 9 with justified epoch 3, it becomes head
|
|
// Verify 9 is the head:
|
|
// 0
|
|
// / \
|
|
// 2 1
|
|
// |
|
|
// 3
|
|
// |
|
|
// 4
|
|
// / \
|
|
// 5 6
|
|
// |
|
|
// 7
|
|
// |
|
|
// 8
|
|
// |
|
|
// 10 <- head
|
|
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(10), indexToHash(8), params.BeaconConfig().ZeroHash, 3, 2)
|
|
require.NoError(t, err)
|
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
|
r, err = f.Head(context.Background(), balances)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, indexToHash(10), r, "Incorrect head for with justified epoch at 3")
|
|
|
|
// Insert block 9 forking 10 verify it's head (lexicographic order)
|
|
// 0
|
|
// / \
|
|
// 2 1
|
|
// |
|
|
// 3
|
|
// |
|
|
// 4
|
|
// / \
|
|
// 5 6
|
|
// |
|
|
// 7
|
|
// |
|
|
// 8
|
|
// / \
|
|
// 9 10
|
|
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(9), indexToHash(8), params.BeaconConfig().ZeroHash, 3, 2)
|
|
require.NoError(t, err)
|
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
|
|
|
r, err = f.Head(context.Background(), balances)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 3")
|
|
|
|
// Move two votes for 10, verify it's head
|
|
|
|
f.ProcessAttestation(context.Background(), []uint64{0, 1}, indexToHash(10), 5)
|
|
r, err = f.Head(context.Background(), balances)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, indexToHash(10), r, "Incorrect head for with justified epoch at 3")
|
|
|
|
// Add 3 more validators to the system.
|
|
balances = []uint64{1, 1, 1, 1, 1}
|
|
// The new validators voted for 9
|
|
f.ProcessAttestation(context.Background(), []uint64{2, 3, 4}, indexToHash(9), 5)
|
|
// The new head should be 9.
|
|
r, err = f.Head(context.Background(), balances)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 3")
|
|
|
|
// Set the balances of the last 2 validators to 0.
|
|
balances = []uint64{1, 1, 1, 0, 0}
|
|
// The head should be back to 10.
|
|
r, err = f.Head(context.Background(), balances)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, indexToHash(10), r, "Incorrect head for with justified epoch at 3")
|
|
|
|
// Set the balances back to normal.
|
|
balances = []uint64{1, 1, 1, 1, 1}
|
|
// The head should be back to 9.
|
|
r, err = f.Head(context.Background(), balances)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, indexToHash(9), r, "Incorrect head for with justified epoch at 3")
|
|
|
|
// Remove the last 2 validators.
|
|
balances = []uint64{1, 1, 1}
|
|
// The head should be back to 10.
|
|
r, err = f.Head(context.Background(), balances)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, indexToHash(10), r, "Incorrect head for with justified epoch at 3")
|
|
|
|
r, err = f.Head(context.Background(), balances)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, indexToHash(10), r, "Incorrect head for with justified epoch at 3")
|
|
|
|
// Verify pruning above the prune threshold does prune:
|
|
// 0
|
|
// / \
|
|
// 2 1
|
|
// |
|
|
// 3
|
|
// |
|
|
// 4
|
|
// -------pruned here ------
|
|
// 5 6
|
|
// |
|
|
// 7
|
|
// |
|
|
// 8
|
|
// / \
|
|
// 9 10
|
|
f.store.finalizedCheckpoint.Root = indexToHash(5)
|
|
require.NoError(t, f.store.prune(context.Background()))
|
|
assert.Equal(t, 5, len(f.store.nodeByRoot), "Incorrect nodes length after prune")
|
|
// we pruned artificially the justified root.
|
|
f.store.justifiedCheckpoint.Root = indexToHash(5)
|
|
|
|
r, err = f.Head(context.Background(), balances)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, indexToHash(10), r, "Incorrect head for with justified epoch at 2")
|
|
|
|
// Insert new block 11 and verify head is at 11.
|
|
// 5 6
|
|
// |
|
|
// 7
|
|
// |
|
|
// 8
|
|
// / \
|
|
// 10 9
|
|
// |
|
|
// head-> 11
|
|
state, blkRoot, err = prepareForkchoiceState(context.Background(), 0, indexToHash(11), indexToHash(10), params.BeaconConfig().ZeroHash, 3, 2)
|
|
require.NoError(t, err)
|
|
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
|
|
|
|
r, err = f.Head(context.Background(), balances)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, indexToHash(11), r, "Incorrect head for with justified epoch at 3")
|
|
}
|