mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-17 23:38:46 +00:00
57a323f083
* Compiling main beacon-chain binary * Add feature flag * passing protoarray tests * passing nodetree tests * passing blockchain package tests * passing rpc tests * go fmt * re-export forkchoice store from blockchain package * remove duplicated import * remove unused var * add nodetree rpc method * remove slot from IsOptimisticForRoot * release lock in IsOptimistic * change package name * Revert "change package name" This reverts commit 679112f9ef795922c631e7823dbdfb3746838f3c. * rename package * Update doc * Fix span names * Terence + Raul review * remove go:build flags * add errors dep * spec tests * fix call to IsOptimisticForRoot * fix test * Fix conflict * change name of function * remove ctx from store.head Co-authored-by: terence tsao <terence@prysmaticlabs.com>
169 lines
6.8 KiB
Go
169 lines
6.8 KiB
Go
package doublylinkedtree
|
|
|
|
import (
|
|
"context"
|
|
"encoding/binary"
|
|
"testing"
|
|
|
|
"github.com/prysmaticlabs/prysm/config/params"
|
|
"github.com/prysmaticlabs/prysm/crypto/hash"
|
|
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
|
"github.com/prysmaticlabs/prysm/testing/assert"
|
|
"github.com/prysmaticlabs/prysm/testing/require"
|
|
)
|
|
|
|
func TestForkChoice_UpdateBalancesPositiveChange(t *testing.T) {
|
|
f := setup(0, 0)
|
|
ctx := context.Background()
|
|
require.NoError(t, f.ProcessBlock(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, 0, 0, false))
|
|
require.NoError(t, f.ProcessBlock(ctx, 2, indexToHash(2), indexToHash(1), 0, 0, false))
|
|
require.NoError(t, f.ProcessBlock(ctx, 3, indexToHash(3), indexToHash(2), 0, 0, false))
|
|
|
|
f.votes = []Vote{
|
|
{indexToHash(1), indexToHash(1), 0},
|
|
{indexToHash(2), indexToHash(2), 0},
|
|
{indexToHash(3), indexToHash(3), 0},
|
|
}
|
|
|
|
// Each node gets one unique vote. The weight should look like 103 <- 102 <- 101 because
|
|
// they get propagated back.
|
|
require.NoError(t, f.updateBalances([]uint64{10, 20, 30}))
|
|
s := f.store
|
|
assert.Equal(t, uint64(10), s.nodeByRoot[indexToHash(1)].balance)
|
|
assert.Equal(t, uint64(20), s.nodeByRoot[indexToHash(2)].balance)
|
|
assert.Equal(t, uint64(30), s.nodeByRoot[indexToHash(3)].balance)
|
|
}
|
|
|
|
func TestForkChoice_UpdateBalancesNegativeChange(t *testing.T) {
|
|
f := setup(0, 0)
|
|
ctx := context.Background()
|
|
require.NoError(t, f.ProcessBlock(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, 0, 0, false))
|
|
require.NoError(t, f.ProcessBlock(ctx, 2, indexToHash(2), indexToHash(1), 0, 0, false))
|
|
require.NoError(t, f.ProcessBlock(ctx, 3, indexToHash(3), indexToHash(2), 0, 0, false))
|
|
s := f.store
|
|
s.nodeByRoot[indexToHash(1)].balance = 100
|
|
s.nodeByRoot[indexToHash(2)].balance = 100
|
|
s.nodeByRoot[indexToHash(3)].balance = 100
|
|
|
|
f.balances = []uint64{100, 100, 100}
|
|
f.votes = []Vote{
|
|
{indexToHash(1), indexToHash(1), 0},
|
|
{indexToHash(2), indexToHash(2), 0},
|
|
{indexToHash(3), indexToHash(3), 0},
|
|
}
|
|
|
|
require.NoError(t, f.updateBalances([]uint64{10, 20, 30}))
|
|
assert.Equal(t, uint64(10), s.nodeByRoot[indexToHash(1)].balance)
|
|
assert.Equal(t, uint64(20), s.nodeByRoot[indexToHash(2)].balance)
|
|
assert.Equal(t, uint64(30), s.nodeByRoot[indexToHash(3)].balance)
|
|
}
|
|
|
|
func TestForkChoice_IsCanonical(t *testing.T) {
|
|
f := setup(1, 1)
|
|
ctx := context.Background()
|
|
require.NoError(t, f.ProcessBlock(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1, false))
|
|
require.NoError(t, f.ProcessBlock(ctx, 2, indexToHash(2), params.BeaconConfig().ZeroHash, 1, 1, false))
|
|
require.NoError(t, f.ProcessBlock(ctx, 3, indexToHash(3), indexToHash(1), 1, 1, false))
|
|
require.NoError(t, f.ProcessBlock(ctx, 4, indexToHash(4), indexToHash(2), 1, 1, false))
|
|
require.NoError(t, f.ProcessBlock(ctx, 5, indexToHash(5), indexToHash(4), 1, 1, false))
|
|
require.NoError(t, f.ProcessBlock(ctx, 6, indexToHash(6), indexToHash(5), 1, 1, false))
|
|
|
|
require.Equal(t, true, f.IsCanonical(params.BeaconConfig().ZeroHash))
|
|
require.Equal(t, false, f.IsCanonical(indexToHash(1)))
|
|
require.Equal(t, true, f.IsCanonical(indexToHash(2)))
|
|
require.Equal(t, false, f.IsCanonical(indexToHash(3)))
|
|
require.Equal(t, true, f.IsCanonical(indexToHash(4)))
|
|
require.Equal(t, true, f.IsCanonical(indexToHash(5)))
|
|
require.Equal(t, true, f.IsCanonical(indexToHash(6)))
|
|
}
|
|
|
|
func TestForkChoice_IsCanonicalReorg(t *testing.T) {
|
|
f := setup(1, 1)
|
|
ctx := context.Background()
|
|
require.NoError(t, f.ProcessBlock(ctx, 1, [32]byte{'1'}, params.BeaconConfig().ZeroHash, 1, 1, false))
|
|
require.NoError(t, f.ProcessBlock(ctx, 2, [32]byte{'2'}, params.BeaconConfig().ZeroHash, 1, 1, false))
|
|
require.NoError(t, f.ProcessBlock(ctx, 3, [32]byte{'3'}, [32]byte{'1'}, 1, 1, false))
|
|
require.NoError(t, f.ProcessBlock(ctx, 4, [32]byte{'4'}, [32]byte{'2'}, 1, 1, false))
|
|
require.NoError(t, f.ProcessBlock(ctx, 5, [32]byte{'5'}, [32]byte{'4'}, 1, 1, false))
|
|
require.NoError(t, f.ProcessBlock(ctx, 6, [32]byte{'6'}, [32]byte{'5'}, 1, 1, false))
|
|
|
|
f.store.nodesLock.Lock()
|
|
f.store.nodeByRoot[[32]byte{'3'}].balance = 10
|
|
require.NoError(t, f.store.treeRootNode.applyWeightChanges(ctx))
|
|
require.Equal(t, uint64(10), f.store.nodeByRoot[[32]byte{'1'}].weight)
|
|
require.Equal(t, uint64(0), f.store.nodeByRoot[[32]byte{'2'}].weight)
|
|
|
|
require.NoError(t, f.store.treeRootNode.updateBestDescendant(ctx, 1, 1))
|
|
require.DeepEqual(t, [32]byte{'3'}, f.store.treeRootNode.bestDescendant.root)
|
|
f.store.nodesLock.Unlock()
|
|
|
|
h, err := f.store.head(ctx, [32]byte{'1'})
|
|
require.NoError(t, err)
|
|
require.DeepEqual(t, [32]byte{'3'}, h)
|
|
require.DeepEqual(t, h, f.store.headNode.root)
|
|
|
|
require.Equal(t, true, f.IsCanonical(params.BeaconConfig().ZeroHash))
|
|
require.Equal(t, true, f.IsCanonical([32]byte{'1'}))
|
|
require.Equal(t, false, f.IsCanonical([32]byte{'2'}))
|
|
require.Equal(t, true, f.IsCanonical([32]byte{'3'}))
|
|
require.Equal(t, false, f.IsCanonical([32]byte{'4'}))
|
|
require.Equal(t, false, f.IsCanonical([32]byte{'5'}))
|
|
require.Equal(t, false, f.IsCanonical([32]byte{'6'}))
|
|
}
|
|
|
|
func TestForkChoice_AncestorRoot(t *testing.T) {
|
|
f := setup(1, 1)
|
|
ctx := context.Background()
|
|
require.NoError(t, f.ProcessBlock(ctx, 1, indexToHash(1), params.BeaconConfig().ZeroHash, 1, 1, false))
|
|
require.NoError(t, f.ProcessBlock(ctx, 2, indexToHash(2), indexToHash(1), 1, 1, false))
|
|
require.NoError(t, f.ProcessBlock(ctx, 5, indexToHash(3), indexToHash(2), 1, 1, false))
|
|
f.store.treeRootNode = f.store.nodeByRoot[indexToHash(1)]
|
|
f.store.treeRootNode.parent = nil
|
|
|
|
r, err := f.AncestorRoot(ctx, indexToHash(3), 6)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, bytesutil.ToBytes32(r), indexToHash(3))
|
|
|
|
_, err = f.AncestorRoot(ctx, indexToHash(3), 0)
|
|
assert.ErrorContains(t, errNilNode.Error(), err)
|
|
|
|
root, err := f.AncestorRoot(ctx, indexToHash(3), 5)
|
|
require.NoError(t, err)
|
|
hash3 := indexToHash(3)
|
|
require.DeepEqual(t, hash3[:], root)
|
|
root, err = f.AncestorRoot(ctx, indexToHash(3), 1)
|
|
require.NoError(t, err)
|
|
hash1 := indexToHash(1)
|
|
require.DeepEqual(t, hash1[:], root)
|
|
}
|
|
|
|
func TestForkChoice_AncestorEqualSlot(t *testing.T) {
|
|
f := setup(1, 1)
|
|
ctx := context.Background()
|
|
require.NoError(t, f.ProcessBlock(ctx, 100, [32]byte{'1'}, params.BeaconConfig().ZeroHash, 1, 1, false))
|
|
require.NoError(t, f.ProcessBlock(ctx, 101, [32]byte{'3'}, [32]byte{'1'}, 1, 1, false))
|
|
|
|
r, err := f.AncestorRoot(ctx, [32]byte{'3'}, 100)
|
|
require.NoError(t, err)
|
|
root := bytesutil.ToBytes32(r)
|
|
require.Equal(t, root, [32]byte{'1'})
|
|
}
|
|
|
|
func TestForkChoice_AncestorLowerSlot(t *testing.T) {
|
|
f := setup(1, 1)
|
|
ctx := context.Background()
|
|
require.NoError(t, f.ProcessBlock(ctx, 100, [32]byte{'1'}, params.BeaconConfig().ZeroHash, 1, 1, false))
|
|
require.NoError(t, f.ProcessBlock(ctx, 200, [32]byte{'3'}, [32]byte{'1'}, 1, 1, false))
|
|
|
|
r, err := f.AncestorRoot(ctx, [32]byte{'3'}, 150)
|
|
require.NoError(t, err)
|
|
root := bytesutil.ToBytes32(r)
|
|
require.Equal(t, root, [32]byte{'1'})
|
|
}
|
|
|
|
func indexToHash(i uint64) [32]byte {
|
|
var b [8]byte
|
|
binary.LittleEndian.PutUint64(b[:], i)
|
|
return hash.Hash(b[:])
|
|
}
|