refactoring: Deduplicate code (#10090)

* Deduplicate sync committee indices from state

* Deduplicate code in listblocks RPC endpoints, which only differ in response object

* Deduplicate test code in config/fieldparams

* Delete stale benchmark target. This is already included in go_default_test

* deduplicate test cases in TestIsSlashableValidator_OK and fix blst
BUILD file

* Deduplicate TestStore_IsFinalizedChildBlock

* Revert crypto/bls/blst/BUILD.bazel

* Deduplicate TestStore_SaveBlock_NoDuplicates

* Use a generic wrapper for beacon blocks to streamline test

* Deduplicate TestStore_BlocksCRUD

* Deduplicate TestStore_BlocksHandleZeroCase

* Deduplicate TestStore_BlocksBatchDelete

* deduplicate TestStore_BlocksHandleInvalidEndSlot

* Deduplicate TestStore_BlocksCRUD_NoCache

* Deduplicate common block test setup. Make TestStore_Blocks_FiltersCorrectly support multiple forks in test

* Deduplicate the rest of these tests

* lint

* Deprecation warning

* Add test for WrappedSignedBeaconBlock

* Test error path
This commit is contained in:
Preston Van Loon
2022-01-16 12:44:42 -06:00
committed by GitHub
parent 3c54eb1cf6
commit 182bd615ac
15 changed files with 678 additions and 1809 deletions

View File

@@ -131,94 +131,19 @@ func TestIsSlashableValidator_OK(t *testing.T) {
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
slashableValidator := IsSlashableValidator(test.validator.ActivationEpoch, t.Run("without trie", func(t *testing.T) {
test.validator.WithdrawableEpoch, test.validator.Slashed, test.epoch) slashableValidator := IsSlashableValidator(test.validator.ActivationEpoch,
assert.Equal(t, test.slashable, slashableValidator, "Expected active validator slashable to be %t", test.slashable) test.validator.WithdrawableEpoch, test.validator.Slashed, test.epoch)
}) assert.Equal(t, test.slashable, slashableValidator, "Expected active validator slashable to be %t", test.slashable)
} })
} t.Run("with trie", func(t *testing.T) {
beaconState, err := v1.InitializeFromProto(&ethpb.BeaconState{Validators: []*ethpb.Validator{test.validator}})
func TestIsSlashableValidatorUsingTrie_OK(t *testing.T) { require.NoError(t, err)
tests := []struct { readOnlyVal, err := beaconState.ValidatorAtIndexReadOnly(0)
name string require.NoError(t, err)
validator *ethpb.Validator slashableValidator := IsSlashableValidatorUsingTrie(readOnlyVal, test.epoch)
epoch types.Epoch assert.Equal(t, test.slashable, slashableValidator, "Expected active validator slashable to be %t", test.slashable)
slashable bool })
}{
{
name: "Unset withdrawable, slashable",
validator: &ethpb.Validator{
WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch,
},
epoch: 0,
slashable: true,
},
{
name: "before withdrawable, slashable",
validator: &ethpb.Validator{
WithdrawableEpoch: 5,
},
epoch: 3,
slashable: true,
},
{
name: "inactive, not slashable",
validator: &ethpb.Validator{
ActivationEpoch: 5,
WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch,
},
epoch: 2,
slashable: false,
},
{
name: "after withdrawable, not slashable",
validator: &ethpb.Validator{
WithdrawableEpoch: 3,
},
epoch: 3,
slashable: false,
},
{
name: "slashed and withdrawable, not slashable",
validator: &ethpb.Validator{
Slashed: true,
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
WithdrawableEpoch: 1,
},
epoch: 2,
slashable: false,
},
{
name: "slashed, not slashable",
validator: &ethpb.Validator{
Slashed: true,
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch,
},
epoch: 2,
slashable: false,
},
{
name: "inactive and slashed, not slashable",
validator: &ethpb.Validator{
Slashed: true,
ActivationEpoch: 4,
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch,
},
epoch: 2,
slashable: false,
},
}
for _, test := range tests {
beaconState, err := v1.InitializeFromProto(&ethpb.BeaconState{Validators: []*ethpb.Validator{test.validator}})
require.NoError(t, err)
readOnlyVal, err := beaconState.ValidatorAtIndexReadOnly(0)
require.NoError(t, err)
t.Run(test.name, func(t *testing.T) {
slashableValidator := IsSlashableValidatorUsingTrie(readOnlyVal, test.epoch)
assert.Equal(t, test.slashable, slashableValidator, "Expected active validator slashable to be %t", test.slashable)
}) })
} }
} }

View File

@@ -1,7 +1,5 @@
load("@prysm//tools/go:def.bzl", "go_library", "go_test") load("@prysm//tools/go:def.bzl", "go_library", "go_test")
# gazelle:exclude testdata
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = [ srcs = [
@@ -105,31 +103,3 @@ go_test(
"@org_golang_google_protobuf//proto:go_default_library", "@org_golang_google_protobuf//proto:go_default_library",
], ],
) )
go_test(
name = "go_benchmark_test",
size = "large",
srcs = ["benchmarks_test.go"],
args = [
"-test.bench=.",
"-test.benchmem",
"-test.v",
],
local = True,
tags = [
"benchmark",
"manual",
"no-cache",
],
deps = [
"//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/transition:go_default_library",
"//beacon-chain/state/v1:go_default_library",
"//config/params:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//testing/benchmark:go_default_library",
"//testing/require:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
],
)

View File

@@ -77,8 +77,6 @@ go_test(
srcs = [ srcs = [
"archived_point_test.go", "archived_point_test.go",
"backup_test.go", "backup_test.go",
"block_altair_test.go",
"block_merge_test.go",
"blocks_test.go", "blocks_test.go",
"checkpoint_test.go", "checkpoint_test.go",
"deposit_contract_test.go", "deposit_contract_test.go",

View File

@@ -1,534 +0,0 @@
package kv
import (
"context"
"sort"
"testing"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/db/filters"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
v2 "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/testing/assert"
"github.com/prysmaticlabs/prysm/testing/require"
"github.com/prysmaticlabs/prysm/testing/util"
"google.golang.org/protobuf/proto"
)
func TestStore_SaveAltairBlock_NoDuplicates(t *testing.T) {
BlockCacheSize = 1
db := setupDB(t)
slot := types.Slot(20)
ctx := context.Background()
// First we save a previous block to ensure the cache max size is reached.
prevBlock := util.NewBeaconBlockAltair()
prevBlock.Block.Slot = slot - 1
prevBlock.Block.ParentRoot = bytesutil.PadTo([]byte{1, 2, 3}, 32)
wsb, err := wrapper.WrappedAltairSignedBeaconBlock(prevBlock)
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wsb))
block := util.NewBeaconBlockAltair()
block.Block.Slot = slot
block.Block.ParentRoot = bytesutil.PadTo([]byte{1, 2, 3}, 32)
// Even with a full cache, saving new blocks should not cause
// duplicated blocks in the DB.
for i := 0; i < 100; i++ {
wsb, err = wrapper.WrappedAltairSignedBeaconBlock(block)
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wsb))
}
f := filters.NewFilter().SetStartSlot(slot).SetEndSlot(slot)
retrieved, _, err := db.Blocks(ctx, f)
require.NoError(t, err)
assert.Equal(t, 1, len(retrieved))
// We reset the block cache size.
BlockCacheSize = 256
}
func TestStore_AltairBlocksCRUD(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
block := util.NewBeaconBlockAltair()
block.Block.Slot = 20
block.Block.ParentRoot = bytesutil.PadTo([]byte{1, 2, 3}, 32)
blockRoot, err := block.Block.HashTreeRoot()
require.NoError(t, err)
retrievedBlock, err := db.Block(ctx, blockRoot)
require.NoError(t, err)
assert.DeepEqual(t, nil, retrievedBlock, "Expected nil block")
wsb, err := wrapper.WrappedAltairSignedBeaconBlock(block)
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wsb))
assert.Equal(t, true, db.HasBlock(ctx, blockRoot), "Expected block to exist in the db")
retrievedBlock, err = db.Block(ctx, blockRoot)
require.NoError(t, err)
assert.Equal(t, true, proto.Equal(block, retrievedBlock.Proto()), "Wanted: %v, received: %v", block, retrievedBlock)
require.NoError(t, db.deleteBlock(ctx, blockRoot))
assert.Equal(t, false, db.HasBlock(ctx, blockRoot), "Expected block to have been deleted from the db")
}
func TestStore_AltairBlocksBatchDelete(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
numBlocks := 10
totalBlocks := make([]block.SignedBeaconBlock, numBlocks)
blockRoots := make([][32]byte, 0)
oddBlocks := make([]block.SignedBeaconBlock, 0)
for i := 0; i < len(totalBlocks); i++ {
b := util.NewBeaconBlockAltair()
b.Block.Slot = types.Slot(i)
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
wb, err := wrapper.WrappedAltairSignedBeaconBlock(b)
require.NoError(t, err)
totalBlocks[i] = wb
if i%2 == 0 {
r, err := totalBlocks[i].Block().HashTreeRoot()
require.NoError(t, err)
blockRoots = append(blockRoots, r)
} else {
oddBlocks = append(oddBlocks, totalBlocks[i])
}
}
require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
retrieved, _, err := db.Blocks(ctx, filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte("parent"), 32)))
require.NoError(t, err)
assert.Equal(t, numBlocks, len(retrieved), "Unexpected number of blocks received")
// We delete all even indexed blocks.
require.NoError(t, db.deleteBlocks(ctx, blockRoots))
// When we retrieve the data, only the odd indexed blocks should remain.
retrieved, _, err = db.Blocks(ctx, filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte("parent"), 32)))
require.NoError(t, err)
sort.Slice(retrieved, func(i, j int) bool {
return retrieved[i].Block().Slot() < retrieved[j].Block().Slot()
})
for i, block := range retrieved {
assert.Equal(t, true, proto.Equal(block.Proto(), oddBlocks[i].Proto()), "Wanted: %v, received: %v", block, oddBlocks[i])
}
}
func TestStore_AltairBlocksHandleZeroCase(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
numBlocks := 10
totalBlocks := make([]block.SignedBeaconBlock, numBlocks)
for i := 0; i < len(totalBlocks); i++ {
b := util.NewBeaconBlockAltair()
b.Block.Slot = types.Slot(i)
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
wb, err := wrapper.WrappedAltairSignedBeaconBlock(b)
require.NoError(t, err)
totalBlocks[i] = wb
_, err = totalBlocks[i].Block().HashTreeRoot()
require.NoError(t, err)
}
require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
zeroFilter := filters.NewFilter().SetStartSlot(0).SetEndSlot(0)
retrieved, _, err := db.Blocks(ctx, zeroFilter)
require.NoError(t, err)
assert.Equal(t, 1, len(retrieved), "Unexpected number of blocks received, expected one")
}
func TestStore_AltairBlocksHandleInvalidEndSlot(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
numBlocks := 10
totalBlocks := make([]block.SignedBeaconBlock, numBlocks)
// Save blocks from slot 1 onwards.
for i := 0; i < len(totalBlocks); i++ {
b := util.NewBeaconBlockAltair()
b.Block.Slot = types.Slot(i) + 1
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
wb, err := wrapper.WrappedAltairSignedBeaconBlock(b)
require.NoError(t, err)
totalBlocks[i] = wb
_, err = totalBlocks[i].Block().HashTreeRoot()
require.NoError(t, err)
}
require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
badFilter := filters.NewFilter().SetStartSlot(5).SetEndSlot(1)
_, _, err := db.Blocks(ctx, badFilter)
require.ErrorContains(t, errInvalidSlotRange.Error(), err)
goodFilter := filters.NewFilter().SetStartSlot(0).SetEndSlot(1)
requested, _, err := db.Blocks(ctx, goodFilter)
require.NoError(t, err)
assert.Equal(t, 1, len(requested), "Unexpected number of blocks received, only expected two")
}
func TestStore_AltairBlocksCRUD_NoCache(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
block := util.NewBeaconBlockAltair()
block.Block.Slot = 20
block.Block.ParentRoot = bytesutil.PadTo([]byte{1, 2, 3}, 32)
blockRoot, err := block.Block.HashTreeRoot()
require.NoError(t, err)
retrievedBlock, err := db.Block(ctx, blockRoot)
require.NoError(t, err)
require.DeepEqual(t, nil, retrievedBlock, "Expected nil block")
wsb, err := wrapper.WrappedAltairSignedBeaconBlock(block)
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wsb))
db.blockCache.Del(string(blockRoot[:]))
assert.Equal(t, true, db.HasBlock(ctx, blockRoot), "Expected block to exist in the db")
retrievedBlock, err = db.Block(ctx, blockRoot)
require.NoError(t, err)
assert.Equal(t, true, proto.Equal(block, retrievedBlock.Proto()), "Wanted: %v, received: %v", block, retrievedBlock)
require.NoError(t, db.deleteBlock(ctx, blockRoot))
assert.Equal(t, false, db.HasBlock(ctx, blockRoot), "Expected block to have been deleted from the db")
}
func TestStore_AltairBlocks_FiltersCorrectly(t *testing.T) {
db := setupDB(t)
b4 := util.NewBeaconBlockAltair()
b4.Block.Slot = 4
b4.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
b5 := util.NewBeaconBlockAltair()
b5.Block.Slot = 5
b5.Block.ParentRoot = bytesutil.PadTo([]byte("parent2"), 32)
b6 := util.NewBeaconBlockAltair()
b6.Block.Slot = 6
b6.Block.ParentRoot = bytesutil.PadTo([]byte("parent2"), 32)
b7 := util.NewBeaconBlockAltair()
b7.Block.Slot = 7
b7.Block.ParentRoot = bytesutil.PadTo([]byte("parent3"), 32)
b8 := util.NewBeaconBlockAltair()
b8.Block.Slot = 8
b8.Block.ParentRoot = bytesutil.PadTo([]byte("parent4"), 32)
blocks := make([]block.SignedBeaconBlock, 0)
for _, b := range []*v2.SignedBeaconBlockAltair{b4, b5, b6, b7, b8} {
blk, err := wrapper.WrappedAltairSignedBeaconBlock(b)
require.NoError(t, err)
blocks = append(blocks, blk)
}
ctx := context.Background()
require.NoError(t, db.SaveBlocks(ctx, blocks))
tests := []struct {
filter *filters.QueryFilter
expectedNumBlocks int
}{
{
filter: filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte("parent2"), 32)),
expectedNumBlocks: 2,
},
{
// No block meets the criteria below.
filter: filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte{3, 4, 5}, 32)),
expectedNumBlocks: 0,
},
{
// Block slot range filter criteria.
filter: filters.NewFilter().SetStartSlot(5).SetEndSlot(7),
expectedNumBlocks: 3,
},
{
filter: filters.NewFilter().SetStartSlot(7).SetEndSlot(7),
expectedNumBlocks: 1,
},
{
filter: filters.NewFilter().SetStartSlot(4).SetEndSlot(8),
expectedNumBlocks: 5,
},
{
filter: filters.NewFilter().SetStartSlot(4).SetEndSlot(5),
expectedNumBlocks: 2,
},
{
filter: filters.NewFilter().SetStartSlot(5).SetEndSlot(9),
expectedNumBlocks: 4,
},
{
filter: filters.NewFilter().SetEndSlot(7),
expectedNumBlocks: 4,
},
{
filter: filters.NewFilter().SetEndSlot(8),
expectedNumBlocks: 5,
},
{
filter: filters.NewFilter().SetStartSlot(5).SetEndSlot(10),
expectedNumBlocks: 4,
},
{
// Composite filter criteria.
filter: filters.NewFilter().
SetParentRoot(bytesutil.PadTo([]byte("parent2"), 32)).
SetStartSlot(6).
SetEndSlot(8),
expectedNumBlocks: 1,
},
}
for _, tt := range tests {
retrievedBlocks, _, err := db.Blocks(ctx, tt.filter)
require.NoError(t, err)
assert.Equal(t, tt.expectedNumBlocks, len(retrievedBlocks), "Unexpected number of blocks")
}
}
func TestStore_AltairBlocks_VerifyBlockRoots(t *testing.T) {
ctx := context.Background()
db := setupDB(t)
b1 := util.NewBeaconBlockAltair()
b1.Block.Slot = 1
r1, err := b1.Block.HashTreeRoot()
require.NoError(t, err)
b2 := util.NewBeaconBlockAltair()
b2.Block.Slot = 2
r2, err := b2.Block.HashTreeRoot()
require.NoError(t, err)
for _, b := range []*v2.SignedBeaconBlockAltair{b1, b2} {
wsb, err := wrapper.WrappedAltairSignedBeaconBlock(b)
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wsb))
}
filter := filters.NewFilter().SetStartSlot(b1.Block.Slot).SetEndSlot(b2.Block.Slot)
roots, err := db.BlockRoots(ctx, filter)
require.NoError(t, err)
assert.DeepEqual(t, [][32]byte{r1, r2}, roots)
}
func TestStore_AltairBlocks_Retrieve_SlotRange(t *testing.T) {
db := setupDB(t)
totalBlocks := make([]block.SignedBeaconBlock, 500)
for i := 0; i < 500; i++ {
b := util.NewBeaconBlockAltair()
b.Block.Slot = types.Slot(i)
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
wb, err := wrapper.WrappedAltairSignedBeaconBlock(b)
require.NoError(t, err)
totalBlocks[i] = wb
}
ctx := context.Background()
require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
retrieved, _, err := db.Blocks(ctx, filters.NewFilter().SetStartSlot(100).SetEndSlot(399))
require.NoError(t, err)
assert.Equal(t, 300, len(retrieved))
}
func TestStore_AltairBlocks_Retrieve_Epoch(t *testing.T) {
db := setupDB(t)
slots := params.BeaconConfig().SlotsPerEpoch.Mul(7)
totalBlocks := make([]block.SignedBeaconBlock, slots)
for i := types.Slot(0); i < slots; i++ {
b := util.NewBeaconBlockAltair()
b.Block.Slot = i
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
wb, err := wrapper.WrappedAltairSignedBeaconBlock(b)
require.NoError(t, err)
totalBlocks[i] = wb
}
ctx := context.Background()
require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
retrieved, _, err := db.Blocks(ctx, filters.NewFilter().SetStartEpoch(5).SetEndEpoch(6))
require.NoError(t, err)
want := params.BeaconConfig().SlotsPerEpoch.Mul(2)
assert.Equal(t, uint64(want), uint64(len(retrieved)))
retrieved, _, err = db.Blocks(ctx, filters.NewFilter().SetStartEpoch(0).SetEndEpoch(0))
require.NoError(t, err)
want = params.BeaconConfig().SlotsPerEpoch
assert.Equal(t, uint64(want), uint64(len(retrieved)))
}
func TestStore_AltairBlocks_Retrieve_SlotRangeWithStep(t *testing.T) {
db := setupDB(t)
totalBlocks := make([]block.SignedBeaconBlock, 500)
for i := 0; i < 500; i++ {
b := util.NewBeaconBlockAltair()
b.Block.Slot = types.Slot(i)
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
wb, err := wrapper.WrappedAltairSignedBeaconBlock(b)
require.NoError(t, err)
totalBlocks[i] = wb
}
const step = 2
ctx := context.Background()
require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
retrieved, _, err := db.Blocks(ctx, filters.NewFilter().SetStartSlot(100).SetEndSlot(399).SetSlotStep(step))
require.NoError(t, err)
assert.Equal(t, 150, len(retrieved))
for _, b := range retrieved {
assert.Equal(t, types.Slot(0), (b.Block().Slot()-100)%step, "Unexpect block slot %d", b.Block().Slot())
}
}
func TestStore_SaveAltairBlock_CanGetHighestAt(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
block1 := util.NewBeaconBlockAltair()
block1.Block.Slot = 1
block2 := util.NewBeaconBlockAltair()
block2.Block.Slot = 10
block3 := util.NewBeaconBlockAltair()
block3.Block.Slot = 100
for _, b := range []*v2.SignedBeaconBlockAltair{block1, block2, block3} {
wsb, err := wrapper.WrappedAltairSignedBeaconBlock(b)
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wsb))
}
highestAt, err := db.HighestSlotBlocksBelow(ctx, 2)
require.NoError(t, err)
assert.Equal(t, false, len(highestAt) <= 0, "Got empty highest at slice")
assert.Equal(t, true, proto.Equal(block1, highestAt[0].Proto()), "Wanted: %v, received: %v", block1, highestAt[0])
highestAt, err = db.HighestSlotBlocksBelow(ctx, 11)
require.NoError(t, err)
assert.Equal(t, false, len(highestAt) <= 0, "Got empty highest at slice")
assert.Equal(t, true, proto.Equal(block2, highestAt[0].Proto()), "Wanted: %v, received: %v", block2, highestAt[0])
highestAt, err = db.HighestSlotBlocksBelow(ctx, 101)
require.NoError(t, err)
assert.Equal(t, false, len(highestAt) <= 0, "Got empty highest at slice")
assert.Equal(t, true, proto.Equal(block3, highestAt[0].Proto()), "Wanted: %v, received: %v", block3, highestAt[0])
r3, err := block3.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, db.deleteBlock(ctx, r3))
highestAt, err = db.HighestSlotBlocksBelow(ctx, 101)
require.NoError(t, err)
assert.Equal(t, true, proto.Equal(block2, highestAt[0].Proto()), "Wanted: %v, received: %v", block2, highestAt[0])
}
func TestStore_GenesisAltairBlock_CanGetHighestAt(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
genesisBlock := util.NewBeaconBlockAltair()
genesisRoot, err := genesisBlock.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, db.SaveGenesisBlockRoot(ctx, genesisRoot))
wsb, err := wrapper.WrappedAltairSignedBeaconBlock(genesisBlock)
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wsb))
block1 := util.NewBeaconBlockAltair()
block1.Block.Slot = 1
wsb, err = wrapper.WrappedAltairSignedBeaconBlock(block1)
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wsb))
highestAt, err := db.HighestSlotBlocksBelow(ctx, 2)
require.NoError(t, err)
assert.Equal(t, true, proto.Equal(block1, highestAt[0].Proto()), "Wanted: %v, received: %v", block1, highestAt[0])
highestAt, err = db.HighestSlotBlocksBelow(ctx, 1)
require.NoError(t, err)
assert.Equal(t, true, proto.Equal(genesisBlock, highestAt[0].Proto()), "Wanted: %v, received: %v", genesisBlock, highestAt[0])
highestAt, err = db.HighestSlotBlocksBelow(ctx, 0)
require.NoError(t, err)
assert.Equal(t, true, proto.Equal(genesisBlock, highestAt[0].Proto()), "Wanted: %v, received: %v", genesisBlock, highestAt[0])
}
func TestStore_SaveAltairBlocks_HasCachedBlocks(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
var err error
b := make([]block.SignedBeaconBlock, 500)
for i := 0; i < 500; i++ {
blk := util.NewBeaconBlockAltair()
blk.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
blk.Block.Slot = types.Slot(i)
b[i], err = wrapper.WrappedAltairSignedBeaconBlock(blk)
require.NoError(t, err)
}
require.NoError(t, db.SaveBlock(ctx, b[0]))
require.NoError(t, db.SaveBlocks(ctx, b))
f := filters.NewFilter().SetStartSlot(0).SetEndSlot(500)
blks, _, err := db.Blocks(ctx, f)
require.NoError(t, err)
assert.Equal(t, 500, len(blks), "Did not get wanted blocks")
}
func TestStore_SaveAltairBlocks_HasRootsMatched(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
var err error
b := make([]block.SignedBeaconBlock, 500)
for i := 0; i < 500; i++ {
blk := util.NewBeaconBlockAltair()
blk.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
blk.Block.Slot = types.Slot(i)
b[i], err = wrapper.WrappedAltairSignedBeaconBlock(blk)
require.NoError(t, err)
}
require.NoError(t, db.SaveBlocks(ctx, b))
f := filters.NewFilter().SetStartSlot(0).SetEndSlot(500)
blks, roots, err := db.Blocks(ctx, f)
require.NoError(t, err)
assert.Equal(t, 500, len(blks), "Did not get wanted blocks")
for i, blk := range blks {
rt, err := blk.Block().HashTreeRoot()
require.NoError(t, err)
assert.Equal(t, roots[i], rt, "mismatch of block roots")
}
}
func TestStore_AltairBlocksBySlot_BlockRootsBySlot(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
b1 := util.NewBeaconBlockAltair()
b1.Block.Slot = 20
b2 := util.NewBeaconBlockAltair()
b2.Block.Slot = 100
b2.Block.ParentRoot = bytesutil.PadTo([]byte("parent1"), 32)
b3 := util.NewBeaconBlockAltair()
b3.Block.Slot = 100
b3.Block.ParentRoot = bytesutil.PadTo([]byte("parent2"), 32)
for _, b := range []*v2.SignedBeaconBlockAltair{b1, b2, b3} {
wsb, err := wrapper.WrappedAltairSignedBeaconBlock(b)
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wsb))
}
r1, err := b1.Block.HashTreeRoot()
require.NoError(t, err)
r2, err := b2.Block.HashTreeRoot()
require.NoError(t, err)
r3, err := b3.Block.HashTreeRoot()
require.NoError(t, err)
hasBlocks, retrievedBlocks, err := db.BlocksBySlot(ctx, 1)
require.NoError(t, err)
assert.Equal(t, 0, len(retrievedBlocks), "Unexpected number of blocks received, expected none")
assert.Equal(t, false, hasBlocks, "Expected no blocks")
hasBlocks, retrievedBlocks, err = db.BlocksBySlot(ctx, 20)
require.NoError(t, err)
assert.Equal(t, true, proto.Equal(b1, retrievedBlocks[0].Proto()), "Wanted: %v, received: %v", b1, retrievedBlocks[0])
assert.Equal(t, true, hasBlocks, "Expected to have blocks")
hasBlocks, retrievedBlocks, err = db.BlocksBySlot(ctx, 100)
require.NoError(t, err)
assert.Equal(t, true, proto.Equal(b2, retrievedBlocks[0].Proto()), "Wanted: %v, received: %v", b2, retrievedBlocks[0])
assert.Equal(t, true, proto.Equal(b3, retrievedBlocks[1].Proto()), "Wanted: %v, received: %v", b3, retrievedBlocks[1])
assert.Equal(t, true, hasBlocks, "Expected to have blocks")
hasBlockRoots, retrievedBlockRoots, err := db.BlockRootsBySlot(ctx, 1)
require.NoError(t, err)
assert.DeepEqual(t, [][32]byte{}, retrievedBlockRoots)
assert.Equal(t, false, hasBlockRoots, "Expected no block roots")
hasBlockRoots, retrievedBlockRoots, err = db.BlockRootsBySlot(ctx, 20)
require.NoError(t, err)
assert.DeepEqual(t, [][32]byte{r1}, retrievedBlockRoots)
assert.Equal(t, true, hasBlockRoots, "Expected no block roots")
hasBlockRoots, retrievedBlockRoots, err = db.BlockRootsBySlot(ctx, 100)
require.NoError(t, err)
assert.DeepEqual(t, [][32]byte{r2, r3}, retrievedBlockRoots)
assert.Equal(t, true, hasBlockRoots, "Expected no block roots")
}

View File

@@ -1,534 +0,0 @@
package kv
import (
"context"
"sort"
"testing"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/db/filters"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
v2 "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/testing/assert"
"github.com/prysmaticlabs/prysm/testing/require"
"github.com/prysmaticlabs/prysm/testing/util"
"google.golang.org/protobuf/proto"
)
func TestStore_SaveBellatrixBlock_NoDuplicates(t *testing.T) {
BlockCacheSize = 1
db := setupDB(t)
slot := types.Slot(20)
ctx := context.Background()
// First we save a previous block to ensure the cache max size is reached.
prevBlock := util.NewBeaconBlockMerge()
prevBlock.Block.Slot = slot - 1
prevBlock.Block.ParentRoot = bytesutil.PadTo([]byte{1, 2, 3}, 32)
wsb, err := wrapper.WrappedMergeSignedBeaconBlock(prevBlock)
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wsb))
block := util.NewBeaconBlockMerge()
block.Block.Slot = slot
block.Block.ParentRoot = bytesutil.PadTo([]byte{1, 2, 3}, 32)
// Even with a full cache, saving new blocks should not cause
// duplicated blocks in the DB.
for i := 0; i < 100; i++ {
wsb, err = wrapper.WrappedMergeSignedBeaconBlock(block)
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wsb))
}
f := filters.NewFilter().SetStartSlot(slot).SetEndSlot(slot)
retrieved, _, err := db.Blocks(ctx, f)
require.NoError(t, err)
assert.Equal(t, 1, len(retrieved))
// We reset the block cache size.
BlockCacheSize = 256
}
func TestStore_BellatrixBlocksCRUD(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
block := util.NewBeaconBlockMerge()
block.Block.Slot = 20
block.Block.ParentRoot = bytesutil.PadTo([]byte{1, 2, 3}, 32)
blockRoot, err := block.Block.HashTreeRoot()
require.NoError(t, err)
retrievedBlock, err := db.Block(ctx, blockRoot)
require.NoError(t, err)
assert.DeepEqual(t, nil, retrievedBlock, "Expected nil block")
wsb, err := wrapper.WrappedMergeSignedBeaconBlock(block)
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wsb))
assert.Equal(t, true, db.HasBlock(ctx, blockRoot), "Expected block to exist in the db")
retrievedBlock, err = db.Block(ctx, blockRoot)
require.NoError(t, err)
assert.Equal(t, true, proto.Equal(block, retrievedBlock.Proto()), "Wanted: %v, received: %v", block, retrievedBlock)
require.NoError(t, db.deleteBlock(ctx, blockRoot))
assert.Equal(t, false, db.HasBlock(ctx, blockRoot), "Expected block to have been deleted from the db")
}
func TestStore_BellatrixBlocksBatchDelete(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
numBlocks := 10
totalBlocks := make([]block.SignedBeaconBlock, numBlocks)
blockRoots := make([][32]byte, 0)
oddBlocks := make([]block.SignedBeaconBlock, 0)
for i := 0; i < len(totalBlocks); i++ {
b := util.NewBeaconBlockMerge()
b.Block.Slot = types.Slot(i)
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
wb, err := wrapper.WrappedMergeSignedBeaconBlock(b)
require.NoError(t, err)
totalBlocks[i] = wb
if i%2 == 0 {
r, err := totalBlocks[i].Block().HashTreeRoot()
require.NoError(t, err)
blockRoots = append(blockRoots, r)
} else {
oddBlocks = append(oddBlocks, totalBlocks[i])
}
}
require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
retrieved, _, err := db.Blocks(ctx, filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte("parent"), 32)))
require.NoError(t, err)
assert.Equal(t, numBlocks, len(retrieved), "Unexpected number of blocks received")
// We delete all even indexed blocks.
require.NoError(t, db.deleteBlocks(ctx, blockRoots))
// When we retrieve the data, only the odd indexed blocks should remain.
retrieved, _, err = db.Blocks(ctx, filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte("parent"), 32)))
require.NoError(t, err)
sort.Slice(retrieved, func(i, j int) bool {
return retrieved[i].Block().Slot() < retrieved[j].Block().Slot()
})
for i, block := range retrieved {
assert.Equal(t, true, proto.Equal(block.Proto(), oddBlocks[i].Proto()), "Wanted: %v, received: %v", block, oddBlocks[i])
}
}
func TestStore_BellatrixBlocksHandleZeroCase(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
numBlocks := 10
totalBlocks := make([]block.SignedBeaconBlock, numBlocks)
for i := 0; i < len(totalBlocks); i++ {
b := util.NewBeaconBlockMerge()
b.Block.Slot = types.Slot(i)
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
wb, err := wrapper.WrappedMergeSignedBeaconBlock(b)
require.NoError(t, err)
totalBlocks[i] = wb
_, err = totalBlocks[i].Block().HashTreeRoot()
require.NoError(t, err)
}
require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
zeroFilter := filters.NewFilter().SetStartSlot(0).SetEndSlot(0)
retrieved, _, err := db.Blocks(ctx, zeroFilter)
require.NoError(t, err)
assert.Equal(t, 1, len(retrieved), "Unexpected number of blocks received, expected one")
}
func TestStore_BellatrixBlocksHandleInvalidEndSlot(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
numBlocks := 10
totalBlocks := make([]block.SignedBeaconBlock, numBlocks)
// Save blocks from slot 1 onwards.
for i := 0; i < len(totalBlocks); i++ {
b := util.NewBeaconBlockMerge()
b.Block.Slot = types.Slot(i) + 1
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
wb, err := wrapper.WrappedMergeSignedBeaconBlock(b)
require.NoError(t, err)
totalBlocks[i] = wb
_, err = totalBlocks[i].Block().HashTreeRoot()
require.NoError(t, err)
}
require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
badFilter := filters.NewFilter().SetStartSlot(5).SetEndSlot(1)
_, _, err := db.Blocks(ctx, badFilter)
require.ErrorContains(t, errInvalidSlotRange.Error(), err)
goodFilter := filters.NewFilter().SetStartSlot(0).SetEndSlot(1)
requested, _, err := db.Blocks(ctx, goodFilter)
require.NoError(t, err)
assert.Equal(t, 1, len(requested), "Unexpected number of blocks received, only expected two")
}
func TestStore_BellatrixBlocksCRUD_NoCache(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
block := util.NewBeaconBlockMerge()
block.Block.Slot = 20
block.Block.ParentRoot = bytesutil.PadTo([]byte{1, 2, 3}, 32)
blockRoot, err := block.Block.HashTreeRoot()
require.NoError(t, err)
retrievedBlock, err := db.Block(ctx, blockRoot)
require.NoError(t, err)
require.DeepEqual(t, nil, retrievedBlock, "Expected nil block")
wsb, err := wrapper.WrappedMergeSignedBeaconBlock(block)
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wsb))
db.blockCache.Del(string(blockRoot[:]))
assert.Equal(t, true, db.HasBlock(ctx, blockRoot), "Expected block to exist in the db")
retrievedBlock, err = db.Block(ctx, blockRoot)
require.NoError(t, err)
assert.Equal(t, true, proto.Equal(block, retrievedBlock.Proto()), "Wanted: %v, received: %v", block, retrievedBlock)
require.NoError(t, db.deleteBlock(ctx, blockRoot))
assert.Equal(t, false, db.HasBlock(ctx, blockRoot), "Expected block to have been deleted from the db")
}
func TestStore_BellatrixBlocks_FiltersCorrectly(t *testing.T) {
db := setupDB(t)
b4 := util.NewBeaconBlockMerge()
b4.Block.Slot = 4
b4.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
b5 := util.NewBeaconBlockMerge()
b5.Block.Slot = 5
b5.Block.ParentRoot = bytesutil.PadTo([]byte("parent2"), 32)
b6 := util.NewBeaconBlockMerge()
b6.Block.Slot = 6
b6.Block.ParentRoot = bytesutil.PadTo([]byte("parent2"), 32)
b7 := util.NewBeaconBlockMerge()
b7.Block.Slot = 7
b7.Block.ParentRoot = bytesutil.PadTo([]byte("parent3"), 32)
b8 := util.NewBeaconBlockMerge()
b8.Block.Slot = 8
b8.Block.ParentRoot = bytesutil.PadTo([]byte("parent4"), 32)
blocks := make([]block.SignedBeaconBlock, 0)
for _, b := range []*v2.SignedBeaconBlockMerge{b4, b5, b6, b7, b8} {
blk, err := wrapper.WrappedMergeSignedBeaconBlock(b)
require.NoError(t, err)
blocks = append(blocks, blk)
}
ctx := context.Background()
require.NoError(t, db.SaveBlocks(ctx, blocks))
tests := []struct {
filter *filters.QueryFilter
expectedNumBlocks int
}{
{
filter: filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte("parent2"), 32)),
expectedNumBlocks: 2,
},
{
// No block meets the criteria below.
filter: filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte{3, 4, 5}, 32)),
expectedNumBlocks: 0,
},
{
// Block slot range filter criteria.
filter: filters.NewFilter().SetStartSlot(5).SetEndSlot(7),
expectedNumBlocks: 3,
},
{
filter: filters.NewFilter().SetStartSlot(7).SetEndSlot(7),
expectedNumBlocks: 1,
},
{
filter: filters.NewFilter().SetStartSlot(4).SetEndSlot(8),
expectedNumBlocks: 5,
},
{
filter: filters.NewFilter().SetStartSlot(4).SetEndSlot(5),
expectedNumBlocks: 2,
},
{
filter: filters.NewFilter().SetStartSlot(5).SetEndSlot(9),
expectedNumBlocks: 4,
},
{
filter: filters.NewFilter().SetEndSlot(7),
expectedNumBlocks: 4,
},
{
filter: filters.NewFilter().SetEndSlot(8),
expectedNumBlocks: 5,
},
{
filter: filters.NewFilter().SetStartSlot(5).SetEndSlot(10),
expectedNumBlocks: 4,
},
{
// Composite filter criteria.
filter: filters.NewFilter().
SetParentRoot(bytesutil.PadTo([]byte("parent2"), 32)).
SetStartSlot(6).
SetEndSlot(8),
expectedNumBlocks: 1,
},
}
for _, tt := range tests {
retrievedBlocks, _, err := db.Blocks(ctx, tt.filter)
require.NoError(t, err)
assert.Equal(t, tt.expectedNumBlocks, len(retrievedBlocks), "Unexpected number of blocks")
}
}
func TestStore_BellatrixBlocks_VerifyBlockRoots(t *testing.T) {
ctx := context.Background()
db := setupDB(t)
b1 := util.NewBeaconBlockMerge()
b1.Block.Slot = 1
r1, err := b1.Block.HashTreeRoot()
require.NoError(t, err)
b2 := util.NewBeaconBlockMerge()
b2.Block.Slot = 2
r2, err := b2.Block.HashTreeRoot()
require.NoError(t, err)
for _, b := range []*v2.SignedBeaconBlockMerge{b1, b2} {
wsb, err := wrapper.WrappedMergeSignedBeaconBlock(b)
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wsb))
}
filter := filters.NewFilter().SetStartSlot(b1.Block.Slot).SetEndSlot(b2.Block.Slot)
roots, err := db.BlockRoots(ctx, filter)
require.NoError(t, err)
assert.DeepEqual(t, [][32]byte{r1, r2}, roots)
}
func TestStore_BellatrixBlocks_Retrieve_SlotRange(t *testing.T) {
db := setupDB(t)
totalBlocks := make([]block.SignedBeaconBlock, 500)
for i := 0; i < 500; i++ {
b := util.NewBeaconBlockMerge()
b.Block.Slot = types.Slot(i)
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
wb, err := wrapper.WrappedMergeSignedBeaconBlock(b)
require.NoError(t, err)
totalBlocks[i] = wb
}
ctx := context.Background()
require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
retrieved, _, err := db.Blocks(ctx, filters.NewFilter().SetStartSlot(100).SetEndSlot(399))
require.NoError(t, err)
assert.Equal(t, 300, len(retrieved))
}
func TestStore_BellatrixBlocks_Retrieve_Epoch(t *testing.T) {
db := setupDB(t)
slots := params.BeaconConfig().SlotsPerEpoch.Mul(7)
totalBlocks := make([]block.SignedBeaconBlock, slots)
for i := types.Slot(0); i < slots; i++ {
b := util.NewBeaconBlockMerge()
b.Block.Slot = i
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
wb, err := wrapper.WrappedMergeSignedBeaconBlock(b)
require.NoError(t, err)
totalBlocks[i] = wb
}
ctx := context.Background()
require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
retrieved, _, err := db.Blocks(ctx, filters.NewFilter().SetStartEpoch(5).SetEndEpoch(6))
require.NoError(t, err)
want := params.BeaconConfig().SlotsPerEpoch.Mul(2)
assert.Equal(t, uint64(want), uint64(len(retrieved)))
retrieved, _, err = db.Blocks(ctx, filters.NewFilter().SetStartEpoch(0).SetEndEpoch(0))
require.NoError(t, err)
want = params.BeaconConfig().SlotsPerEpoch
assert.Equal(t, uint64(want), uint64(len(retrieved)))
}
func TestStore_BellatrixBlocks_Retrieve_SlotRangeWithStep(t *testing.T) {
db := setupDB(t)
totalBlocks := make([]block.SignedBeaconBlock, 500)
for i := 0; i < 500; i++ {
b := util.NewBeaconBlockMerge()
b.Block.Slot = types.Slot(i)
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
wb, err := wrapper.WrappedMergeSignedBeaconBlock(b)
require.NoError(t, err)
totalBlocks[i] = wb
}
const step = 2
ctx := context.Background()
require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
retrieved, _, err := db.Blocks(ctx, filters.NewFilter().SetStartSlot(100).SetEndSlot(399).SetSlotStep(step))
require.NoError(t, err)
assert.Equal(t, 150, len(retrieved))
for _, b := range retrieved {
assert.Equal(t, types.Slot(0), (b.Block().Slot()-100)%step, "Unexpect block slot %d", b.Block().Slot())
}
}
func TestStore_SaveBellatrixBlock_CanGetHighestAt(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
block1 := util.NewBeaconBlockMerge()
block1.Block.Slot = 1
block2 := util.NewBeaconBlockMerge()
block2.Block.Slot = 10
block3 := util.NewBeaconBlockMerge()
block3.Block.Slot = 100
for _, b := range []*v2.SignedBeaconBlockMerge{block1, block2, block3} {
wsb, err := wrapper.WrappedMergeSignedBeaconBlock(b)
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wsb))
}
highestAt, err := db.HighestSlotBlocksBelow(ctx, 2)
require.NoError(t, err)
assert.Equal(t, false, len(highestAt) <= 0, "Got empty highest at slice")
assert.Equal(t, true, proto.Equal(block1, highestAt[0].Proto()), "Wanted: %v, received: %v", block1, highestAt[0])
highestAt, err = db.HighestSlotBlocksBelow(ctx, 11)
require.NoError(t, err)
assert.Equal(t, false, len(highestAt) <= 0, "Got empty highest at slice")
assert.Equal(t, true, proto.Equal(block2, highestAt[0].Proto()), "Wanted: %v, received: %v", block2, highestAt[0])
highestAt, err = db.HighestSlotBlocksBelow(ctx, 101)
require.NoError(t, err)
assert.Equal(t, false, len(highestAt) <= 0, "Got empty highest at slice")
assert.Equal(t, true, proto.Equal(block3, highestAt[0].Proto()), "Wanted: %v, received: %v", block3, highestAt[0])
r3, err := block3.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, db.deleteBlock(ctx, r3))
highestAt, err = db.HighestSlotBlocksBelow(ctx, 101)
require.NoError(t, err)
assert.Equal(t, true, proto.Equal(block2, highestAt[0].Proto()), "Wanted: %v, received: %v", block2, highestAt[0])
}
func TestStore_GenesisBellatrixBlock_CanGetHighestAt(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
genesisBlock := util.NewBeaconBlockMerge()
genesisRoot, err := genesisBlock.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, db.SaveGenesisBlockRoot(ctx, genesisRoot))
wsb, err := wrapper.WrappedMergeSignedBeaconBlock(genesisBlock)
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wsb))
block1 := util.NewBeaconBlockMerge()
block1.Block.Slot = 1
wsb, err = wrapper.WrappedMergeSignedBeaconBlock(block1)
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wsb))
highestAt, err := db.HighestSlotBlocksBelow(ctx, 2)
require.NoError(t, err)
assert.Equal(t, true, proto.Equal(block1, highestAt[0].Proto()), "Wanted: %v, received: %v", block1, highestAt[0])
highestAt, err = db.HighestSlotBlocksBelow(ctx, 1)
require.NoError(t, err)
assert.Equal(t, true, proto.Equal(genesisBlock, highestAt[0].Proto()), "Wanted: %v, received: %v", genesisBlock, highestAt[0])
highestAt, err = db.HighestSlotBlocksBelow(ctx, 0)
require.NoError(t, err)
assert.Equal(t, true, proto.Equal(genesisBlock, highestAt[0].Proto()), "Wanted: %v, received: %v", genesisBlock, highestAt[0])
}
func TestStore_SaveBellatrixBlocks_HasCachedBlocks(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
var err error
b := make([]block.SignedBeaconBlock, 500)
for i := 0; i < 500; i++ {
blk := util.NewBeaconBlockMerge()
blk.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
blk.Block.Slot = types.Slot(i)
b[i], err = wrapper.WrappedMergeSignedBeaconBlock(blk)
require.NoError(t, err)
}
require.NoError(t, db.SaveBlock(ctx, b[0]))
require.NoError(t, db.SaveBlocks(ctx, b))
f := filters.NewFilter().SetStartSlot(0).SetEndSlot(500)
blks, _, err := db.Blocks(ctx, f)
require.NoError(t, err)
assert.Equal(t, 500, len(blks), "Did not get wanted blocks")
}
func TestStore_SaveBellatrixBlocks_HasRootsMatched(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
var err error
b := make([]block.SignedBeaconBlock, 500)
for i := 0; i < 500; i++ {
blk := util.NewBeaconBlockMerge()
blk.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32)
blk.Block.Slot = types.Slot(i)
b[i], err = wrapper.WrappedMergeSignedBeaconBlock(blk)
require.NoError(t, err)
}
require.NoError(t, db.SaveBlocks(ctx, b))
f := filters.NewFilter().SetStartSlot(0).SetEndSlot(500)
blks, roots, err := db.Blocks(ctx, f)
require.NoError(t, err)
assert.Equal(t, 500, len(blks), "Did not get wanted blocks")
for i, blk := range blks {
rt, err := blk.Block().HashTreeRoot()
require.NoError(t, err)
assert.Equal(t, roots[i], rt, "mismatch of block roots")
}
}
func TestStore_BellatrixBlocksBySlot_BlockRootsBySlot(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
b1 := util.NewBeaconBlockMerge()
b1.Block.Slot = 20
b2 := util.NewBeaconBlockMerge()
b2.Block.Slot = 100
b2.Block.ParentRoot = bytesutil.PadTo([]byte("parent1"), 32)
b3 := util.NewBeaconBlockMerge()
b3.Block.Slot = 100
b3.Block.ParentRoot = bytesutil.PadTo([]byte("parent2"), 32)
for _, b := range []*v2.SignedBeaconBlockMerge{b1, b2, b3} {
wsb, err := wrapper.WrappedMergeSignedBeaconBlock(b)
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wsb))
}
r1, err := b1.Block.HashTreeRoot()
require.NoError(t, err)
r2, err := b2.Block.HashTreeRoot()
require.NoError(t, err)
r3, err := b3.Block.HashTreeRoot()
require.NoError(t, err)
hasBlocks, retrievedBlocks, err := db.BlocksBySlot(ctx, 1)
require.NoError(t, err)
assert.Equal(t, 0, len(retrievedBlocks), "Unexpected number of blocks received, expected none")
assert.Equal(t, false, hasBlocks, "Expected no blocks")
hasBlocks, retrievedBlocks, err = db.BlocksBySlot(ctx, 20)
require.NoError(t, err)
assert.Equal(t, true, proto.Equal(b1, retrievedBlocks[0].Proto()), "Wanted: %v, received: %v", b1, retrievedBlocks[0])
assert.Equal(t, true, hasBlocks, "Expected to have blocks")
hasBlocks, retrievedBlocks, err = db.BlocksBySlot(ctx, 100)
require.NoError(t, err)
assert.Equal(t, true, proto.Equal(b2, retrievedBlocks[0].Proto()), "Wanted: %v, received: %v", b2, retrievedBlocks[0])
assert.Equal(t, true, proto.Equal(b3, retrievedBlocks[1].Proto()), "Wanted: %v, received: %v", b3, retrievedBlocks[1])
assert.Equal(t, true, hasBlocks, "Expected to have blocks")
hasBlockRoots, retrievedBlockRoots, err := db.BlockRootsBySlot(ctx, 1)
require.NoError(t, err)
assert.DeepEqual(t, [][32]byte{}, retrievedBlockRoots)
assert.Equal(t, false, hasBlockRoots, "Expected no block roots")
hasBlockRoots, retrievedBlockRoots, err = db.BlockRootsBySlot(ctx, 20)
require.NoError(t, err)
assert.DeepEqual(t, [][32]byte{r1}, retrievedBlockRoots)
assert.Equal(t, true, hasBlockRoots, "Expected no block roots")
hasBlockRoots, retrievedBlockRoots, err = db.BlockRootsBySlot(ctx, 100)
require.NoError(t, err)
assert.DeepEqual(t, [][32]byte{r2, r3}, retrievedBlockRoots)
assert.Equal(t, true, hasBlockRoots, "Expected no block roots")
}

View File

@@ -17,135 +17,193 @@ import (
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
var blockTests = []struct {
name string
newBlock func(types.Slot, []byte) (block.SignedBeaconBlock, error)
}{
{
name: "phase0",
newBlock: func(slot types.Slot, root []byte) (block.SignedBeaconBlock, error) {
b := util.NewBeaconBlock()
b.Block.Slot = slot
if root != nil {
b.Block.ParentRoot = root
}
return wrapper.WrappedPhase0SignedBeaconBlock(b), nil
},
},
{
name: "altair",
newBlock: func(slot types.Slot, root []byte) (block.SignedBeaconBlock, error) {
b := util.NewBeaconBlockAltair()
b.Block.Slot = slot
if root != nil {
b.Block.ParentRoot = root
}
return wrapper.WrappedAltairSignedBeaconBlock(b)
},
},
{
name: "bellatrix",
newBlock: func(slot types.Slot, root []byte) (block.SignedBeaconBlock, error) {
b := util.NewBeaconBlockMerge()
b.Block.Slot = slot
if root != nil {
b.Block.ParentRoot = root
}
return wrapper.WrappedMergeSignedBeaconBlock(b)
},
},
}
func TestStore_SaveBlock_NoDuplicates(t *testing.T) { func TestStore_SaveBlock_NoDuplicates(t *testing.T) {
BlockCacheSize = 1 BlockCacheSize = 1
db := setupDB(t)
slot := types.Slot(20) slot := types.Slot(20)
ctx := context.Background() ctx := context.Background()
// First we save a previous block to ensure the cache max size is reached.
prevBlock := util.NewBeaconBlock()
prevBlock.Block.Slot = slot - 1
prevBlock.Block.ParentRoot = bytesutil.PadTo([]byte{1, 2, 3}, 32)
require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(prevBlock)))
block := util.NewBeaconBlock() for _, tt := range blockTests {
block.Block.Slot = slot t.Run(tt.name, func(t *testing.T) {
block.Block.ParentRoot = bytesutil.PadTo([]byte{1, 2, 3}, 32) db := setupDB(t)
// Even with a full cache, saving new blocks should not cause
// duplicated blocks in the DB. // First we save a previous block to ensure the cache max size is reached.
for i := 0; i < 100; i++ { prevBlock, err := tt.newBlock(slot-1, bytesutil.PadTo([]byte{1, 2, 3}, 32))
require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(block))) require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, prevBlock))
blk, err := tt.newBlock(slot, bytesutil.PadTo([]byte{1, 2, 3}, 32))
require.NoError(t, err)
// Even with a full cache, saving new blocks should not cause
// duplicated blocks in the DB.
for i := 0; i < 100; i++ {
require.NoError(t, db.SaveBlock(ctx, blk))
}
f := filters.NewFilter().SetStartSlot(slot).SetEndSlot(slot)
retrieved, _, err := db.Blocks(ctx, f)
require.NoError(t, err)
assert.Equal(t, 1, len(retrieved))
})
} }
f := filters.NewFilter().SetStartSlot(slot).SetEndSlot(slot)
retrieved, _, err := db.Blocks(ctx, f)
require.NoError(t, err)
assert.Equal(t, 1, len(retrieved))
// We reset the block cache size. // We reset the block cache size.
BlockCacheSize = 256 BlockCacheSize = 256
} }
func TestStore_BlocksCRUD(t *testing.T) { func TestStore_BlocksCRUD(t *testing.T) {
db := setupDB(t)
ctx := context.Background() ctx := context.Background()
block := util.NewBeaconBlock() for _, tt := range blockTests {
block.Block.Slot = 20 t.Run(tt.name, func(t *testing.T) {
block.Block.ParentRoot = bytesutil.PadTo([]byte{1, 2, 3}, 32) db := setupDB(t)
blockRoot, err := block.Block.HashTreeRoot() blk, err := tt.newBlock(types.Slot(20), bytesutil.PadTo([]byte{1, 2, 3}, 32))
require.NoError(t, err) require.NoError(t, err)
retrievedBlock, err := db.Block(ctx, blockRoot) blockRoot, err := blk.Block().HashTreeRoot()
require.NoError(t, err) require.NoError(t, err)
assert.DeepEqual(t, nil, retrievedBlock, "Expected nil block")
require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(block))) retrievedBlock, err := db.Block(ctx, blockRoot)
assert.Equal(t, true, db.HasBlock(ctx, blockRoot), "Expected block to exist in the db") require.NoError(t, err)
retrievedBlock, err = db.Block(ctx, blockRoot) assert.DeepEqual(t, nil, retrievedBlock, "Expected nil block")
require.NoError(t, err) require.NoError(t, db.SaveBlock(ctx, blk))
assert.Equal(t, true, proto.Equal(block, retrievedBlock.Proto()), "Wanted: %v, received: %v", block, retrievedBlock) assert.Equal(t, true, db.HasBlock(ctx, blockRoot), "Expected block to exist in the db")
require.NoError(t, db.deleteBlock(ctx, blockRoot)) retrievedBlock, err = db.Block(ctx, blockRoot)
assert.Equal(t, false, db.HasBlock(ctx, blockRoot), "Expected block to have been deleted from the db") require.NoError(t, err)
assert.Equal(t, true, proto.Equal(blk.Proto(), retrievedBlock.Proto()), "Wanted: %v, received: %v", blk, retrievedBlock)
require.NoError(t, db.deleteBlock(ctx, blockRoot))
assert.Equal(t, false, db.HasBlock(ctx, blockRoot), "Expected block to have been deleted from the db")
})
}
} }
func TestStore_BlocksBatchDelete(t *testing.T) { func TestStore_BlocksBatchDelete(t *testing.T) {
db := setupDB(t) for _, tt := range blockTests {
ctx := context.Background() t.Run(tt.name, func(t *testing.T) {
numBlocks := 10 db := setupDB(t)
totalBlocks := make([]block.SignedBeaconBlock, numBlocks) ctx := context.Background()
blockRoots := make([][32]byte, 0) numBlocks := 10
oddBlocks := make([]block.SignedBeaconBlock, 0) totalBlocks := make([]block.SignedBeaconBlock, numBlocks)
for i := 0; i < len(totalBlocks); i++ { blockRoots := make([][32]byte, 0)
b := util.NewBeaconBlock() oddBlocks := make([]block.SignedBeaconBlock, 0)
b.Block.Slot = types.Slot(i) for i := 0; i < len(totalBlocks); i++ {
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32) b, err := tt.newBlock(types.Slot(i), bytesutil.PadTo([]byte("parent"), 32))
totalBlocks[i] = wrapper.WrappedPhase0SignedBeaconBlock(b) require.NoError(t, err)
if i%2 == 0 { totalBlocks[i] = b
r, err := totalBlocks[i].Block().HashTreeRoot() if i%2 == 0 {
r, err := totalBlocks[i].Block().HashTreeRoot()
require.NoError(t, err)
blockRoots = append(blockRoots, r)
} else {
oddBlocks = append(oddBlocks, totalBlocks[i])
}
}
require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
retrieved, _, err := db.Blocks(ctx, filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte("parent"), 32)))
require.NoError(t, err) require.NoError(t, err)
blockRoots = append(blockRoots, r) assert.Equal(t, numBlocks, len(retrieved), "Unexpected number of blocks received")
} else { // We delete all even indexed blocks.
oddBlocks = append(oddBlocks, totalBlocks[i]) require.NoError(t, db.deleteBlocks(ctx, blockRoots))
} // When we retrieve the data, only the odd indexed blocks should remain.
} retrieved, _, err = db.Blocks(ctx, filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte("parent"), 32)))
require.NoError(t, db.SaveBlocks(ctx, totalBlocks)) require.NoError(t, err)
retrieved, _, err := db.Blocks(ctx, filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte("parent"), 32))) sort.Slice(retrieved, func(i, j int) bool {
require.NoError(t, err) return retrieved[i].Block().Slot() < retrieved[j].Block().Slot()
assert.Equal(t, numBlocks, len(retrieved), "Unexpected number of blocks received") })
// We delete all even indexed blocks. for i, blk := range retrieved {
require.NoError(t, db.deleteBlocks(ctx, blockRoots)) assert.Equal(t, true, proto.Equal(blk.Proto(), oddBlocks[i].Proto()), "Wanted: %v, received: %v", blk, oddBlocks[i])
// When we retrieve the data, only the odd indexed blocks should remain. }
retrieved, _, err = db.Blocks(ctx, filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte("parent"), 32))) })
require.NoError(t, err)
sort.Slice(retrieved, func(i, j int) bool {
return retrieved[i].Block().Slot() < retrieved[j].Block().Slot()
})
for i, block := range retrieved {
assert.Equal(t, true, proto.Equal(block.Proto(), oddBlocks[i].Proto()), "Wanted: %v, received: %v", block, oddBlocks[i])
} }
} }
func TestStore_BlocksHandleZeroCase(t *testing.T) { func TestStore_BlocksHandleZeroCase(t *testing.T) {
db := setupDB(t) for _, tt := range blockTests {
ctx := context.Background() t.Run(tt.name, func(t *testing.T) {
numBlocks := 10 db := setupDB(t)
totalBlocks := make([]block.SignedBeaconBlock, numBlocks) ctx := context.Background()
for i := 0; i < len(totalBlocks); i++ { numBlocks := 10
b := util.NewBeaconBlock() totalBlocks := make([]block.SignedBeaconBlock, numBlocks)
b.Block.Slot = types.Slot(i) for i := 0; i < len(totalBlocks); i++ {
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32) b, err := tt.newBlock(types.Slot(i), bytesutil.PadTo([]byte("parent"), 32))
totalBlocks[i] = wrapper.WrappedPhase0SignedBeaconBlock(b) require.NoError(t, err)
_, err := totalBlocks[i].Block().HashTreeRoot() totalBlocks[i] = b
require.NoError(t, err) _, err = totalBlocks[i].Block().HashTreeRoot()
require.NoError(t, err)
}
require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
zeroFilter := filters.NewFilter().SetStartSlot(0).SetEndSlot(0)
retrieved, _, err := db.Blocks(ctx, zeroFilter)
require.NoError(t, err)
assert.Equal(t, 1, len(retrieved), "Unexpected number of blocks received, expected one")
})
} }
require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
zeroFilter := filters.NewFilter().SetStartSlot(0).SetEndSlot(0)
retrieved, _, err := db.Blocks(ctx, zeroFilter)
require.NoError(t, err)
assert.Equal(t, 1, len(retrieved), "Unexpected number of blocks received, expected one")
} }
func TestStore_BlocksHandleInvalidEndSlot(t *testing.T) { func TestStore_BlocksHandleInvalidEndSlot(t *testing.T) {
db := setupDB(t) for _, tt := range blockTests {
ctx := context.Background() t.Run(tt.name, func(t *testing.T) {
numBlocks := 10 db := setupDB(t)
totalBlocks := make([]block.SignedBeaconBlock, numBlocks) ctx := context.Background()
// Save blocks from slot 1 onwards. numBlocks := 10
for i := 0; i < len(totalBlocks); i++ { totalBlocks := make([]block.SignedBeaconBlock, numBlocks)
b := util.NewBeaconBlock() // Save blocks from slot 1 onwards.
b.Block.Slot = types.Slot(i) + 1 for i := 0; i < len(totalBlocks); i++ {
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32) b, err := tt.newBlock(types.Slot(i+1), bytesutil.PadTo([]byte("parent"), 32))
totalBlocks[i] = wrapper.WrappedPhase0SignedBeaconBlock(b) require.NoError(t, err)
_, err := totalBlocks[i].Block().HashTreeRoot() totalBlocks[i] = b
require.NoError(t, err) _, err = totalBlocks[i].Block().HashTreeRoot()
} require.NoError(t, err)
require.NoError(t, db.SaveBlocks(ctx, totalBlocks)) }
badFilter := filters.NewFilter().SetStartSlot(5).SetEndSlot(1) require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
_, _, err := db.Blocks(ctx, badFilter) badFilter := filters.NewFilter().SetStartSlot(5).SetEndSlot(1)
require.ErrorContains(t, errInvalidSlotRange.Error(), err) _, _, err := db.Blocks(ctx, badFilter)
require.ErrorContains(t, errInvalidSlotRange.Error(), err)
goodFilter := filters.NewFilter().SetStartSlot(0).SetEndSlot(1) goodFilter := filters.NewFilter().SetStartSlot(0).SetEndSlot(1)
requested, _, err := db.Blocks(ctx, goodFilter) requested, _, err := db.Blocks(ctx, goodFilter)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, 1, len(requested), "Unexpected number of blocks received, only expected two") assert.Equal(t, 1, len(requested), "Unexpected number of blocks received, only expected two")
})
}
} }
func TestStore_GenesisBlock(t *testing.T) { func TestStore_GenesisBlock(t *testing.T) {
@@ -163,349 +221,385 @@ func TestStore_GenesisBlock(t *testing.T) {
} }
func TestStore_BlocksCRUD_NoCache(t *testing.T) { func TestStore_BlocksCRUD_NoCache(t *testing.T) {
db := setupDB(t) for _, tt := range blockTests {
ctx := context.Background() t.Run(tt.name, func(t *testing.T) {
block := util.NewBeaconBlock() db := setupDB(t)
block.Block.Slot = 20 ctx := context.Background()
block.Block.ParentRoot = bytesutil.PadTo([]byte{1, 2, 3}, 32) blk, err := tt.newBlock(types.Slot(20), bytesutil.PadTo([]byte{1, 2, 3}, 32))
blockRoot, err := block.Block.HashTreeRoot() require.NoError(t, err)
require.NoError(t, err) blockRoot, err := blk.Block().HashTreeRoot()
retrievedBlock, err := db.Block(ctx, blockRoot) require.NoError(t, err)
require.NoError(t, err) retrievedBlock, err := db.Block(ctx, blockRoot)
require.DeepEqual(t, nil, retrievedBlock, "Expected nil block") require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(block))) require.DeepEqual(t, nil, retrievedBlock, "Expected nil block")
db.blockCache.Del(string(blockRoot[:])) require.NoError(t, db.SaveBlock(ctx, blk))
assert.Equal(t, true, db.HasBlock(ctx, blockRoot), "Expected block to exist in the db") db.blockCache.Del(string(blockRoot[:]))
retrievedBlock, err = db.Block(ctx, blockRoot) assert.Equal(t, true, db.HasBlock(ctx, blockRoot), "Expected block to exist in the db")
require.NoError(t, err) retrievedBlock, err = db.Block(ctx, blockRoot)
assert.Equal(t, true, proto.Equal(block, retrievedBlock.Proto()), "Wanted: %v, received: %v", block, retrievedBlock) require.NoError(t, err)
require.NoError(t, db.deleteBlock(ctx, blockRoot)) assert.Equal(t, true, proto.Equal(blk.Proto(), retrievedBlock.Proto()), "Wanted: %v, received: %v", blk, retrievedBlock)
assert.Equal(t, false, db.HasBlock(ctx, blockRoot), "Expected block to have been deleted from the db") require.NoError(t, db.deleteBlock(ctx, blockRoot))
assert.Equal(t, false, db.HasBlock(ctx, blockRoot), "Expected block to have been deleted from the db")
})
}
} }
func TestStore_Blocks_FiltersCorrectly(t *testing.T) { func TestStore_Blocks_FiltersCorrectly(t *testing.T) {
db := setupDB(t) for _, tt := range blockTests {
b4 := util.NewBeaconBlock() t.Run(tt.name, func(t *testing.T) {
b4.Block.Slot = 4 db := setupDB(t)
b4.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32) b4, err := tt.newBlock(types.Slot(4), bytesutil.PadTo([]byte("parent"), 32))
b5 := util.NewBeaconBlock() require.NoError(t, err)
b5.Block.Slot = 5 b5, err := tt.newBlock(types.Slot(5), bytesutil.PadTo([]byte("parent2"), 32))
b5.Block.ParentRoot = bytesutil.PadTo([]byte("parent2"), 32) require.NoError(t, err)
b6 := util.NewBeaconBlock() b6, err := tt.newBlock(types.Slot(6), bytesutil.PadTo([]byte("parent2"), 32))
b6.Block.Slot = 6 require.NoError(t, err)
b6.Block.ParentRoot = bytesutil.PadTo([]byte("parent2"), 32) b7, err := tt.newBlock(types.Slot(7), bytesutil.PadTo([]byte("parent3"), 32))
b7 := util.NewBeaconBlock() require.NoError(t, err)
b7.Block.Slot = 7 b8, err := tt.newBlock(types.Slot(8), bytesutil.PadTo([]byte("parent4"), 32))
b7.Block.ParentRoot = bytesutil.PadTo([]byte("parent3"), 32) require.NoError(t, err)
b8 := util.NewBeaconBlock() blocks := []block.SignedBeaconBlock{
b8.Block.Slot = 8 b4,
b8.Block.ParentRoot = bytesutil.PadTo([]byte("parent4"), 32) b5,
blocks := []block.SignedBeaconBlock{ b6,
wrapper.WrappedPhase0SignedBeaconBlock(b4), b7,
wrapper.WrappedPhase0SignedBeaconBlock(b5), b8,
wrapper.WrappedPhase0SignedBeaconBlock(b6), }
wrapper.WrappedPhase0SignedBeaconBlock(b7), ctx := context.Background()
wrapper.WrappedPhase0SignedBeaconBlock(b8), require.NoError(t, db.SaveBlocks(ctx, blocks))
}
ctx := context.Background()
require.NoError(t, db.SaveBlocks(ctx, blocks))
tests := []struct { tests := []struct {
filter *filters.QueryFilter filter *filters.QueryFilter
expectedNumBlocks int expectedNumBlocks int
}{ }{
{ {
filter: filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte("parent2"), 32)), filter: filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte("parent2"), 32)),
expectedNumBlocks: 2, expectedNumBlocks: 2,
}, },
{ {
// No block meets the criteria below. // No block meets the criteria below.
filter: filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte{3, 4, 5}, 32)), filter: filters.NewFilter().SetParentRoot(bytesutil.PadTo([]byte{3, 4, 5}, 32)),
expectedNumBlocks: 0, expectedNumBlocks: 0,
}, },
{ {
// Block slot range filter criteria. // Block slot range filter criteria.
filter: filters.NewFilter().SetStartSlot(5).SetEndSlot(7), filter: filters.NewFilter().SetStartSlot(5).SetEndSlot(7),
expectedNumBlocks: 3, expectedNumBlocks: 3,
}, },
{ {
filter: filters.NewFilter().SetStartSlot(7).SetEndSlot(7), filter: filters.NewFilter().SetStartSlot(7).SetEndSlot(7),
expectedNumBlocks: 1, expectedNumBlocks: 1,
}, },
{ {
filter: filters.NewFilter().SetStartSlot(4).SetEndSlot(8), filter: filters.NewFilter().SetStartSlot(4).SetEndSlot(8),
expectedNumBlocks: 5, expectedNumBlocks: 5,
}, },
{ {
filter: filters.NewFilter().SetStartSlot(4).SetEndSlot(5), filter: filters.NewFilter().SetStartSlot(4).SetEndSlot(5),
expectedNumBlocks: 2, expectedNumBlocks: 2,
}, },
{ {
filter: filters.NewFilter().SetStartSlot(5).SetEndSlot(9), filter: filters.NewFilter().SetStartSlot(5).SetEndSlot(9),
expectedNumBlocks: 4, expectedNumBlocks: 4,
}, },
{ {
filter: filters.NewFilter().SetEndSlot(7), filter: filters.NewFilter().SetEndSlot(7),
expectedNumBlocks: 4, expectedNumBlocks: 4,
}, },
{ {
filter: filters.NewFilter().SetEndSlot(8), filter: filters.NewFilter().SetEndSlot(8),
expectedNumBlocks: 5, expectedNumBlocks: 5,
}, },
{ {
filter: filters.NewFilter().SetStartSlot(5).SetEndSlot(10), filter: filters.NewFilter().SetStartSlot(5).SetEndSlot(10),
expectedNumBlocks: 4, expectedNumBlocks: 4,
}, },
{ {
// Composite filter criteria. // Composite filter criteria.
filter: filters.NewFilter(). filter: filters.NewFilter().
SetParentRoot(bytesutil.PadTo([]byte("parent2"), 32)). SetParentRoot(bytesutil.PadTo([]byte("parent2"), 32)).
SetStartSlot(6). SetStartSlot(6).
SetEndSlot(8), SetEndSlot(8),
expectedNumBlocks: 1, expectedNumBlocks: 1,
}, },
} }
for _, tt := range tests { for _, tt2 := range tests {
retrievedBlocks, _, err := db.Blocks(ctx, tt.filter) retrievedBlocks, _, err := db.Blocks(ctx, tt2.filter)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, tt.expectedNumBlocks, len(retrievedBlocks), "Unexpected number of blocks") assert.Equal(t, tt2.expectedNumBlocks, len(retrievedBlocks), "Unexpected number of blocks")
}
})
} }
} }
func TestStore_Blocks_VerifyBlockRoots(t *testing.T) { func TestStore_Blocks_VerifyBlockRoots(t *testing.T) {
ctx := context.Background() for _, tt := range blockTests {
db := setupDB(t) t.Run(tt.name, func(t *testing.T) {
b1 := util.NewBeaconBlock() ctx := context.Background()
b1.Block.Slot = 1 db := setupDB(t)
r1, err := b1.Block.HashTreeRoot() b1, err := tt.newBlock(types.Slot(1), nil)
require.NoError(t, err) require.NoError(t, err)
b2 := util.NewBeaconBlock() r1, err := b1.Block().HashTreeRoot()
b2.Block.Slot = 2 require.NoError(t, err)
r2, err := b2.Block.HashTreeRoot() b2, err := tt.newBlock(types.Slot(2), nil)
require.NoError(t, err) require.NoError(t, err)
r2, err := b2.Block().HashTreeRoot()
require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b1))) require.NoError(t, db.SaveBlock(ctx, b1))
require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b2))) require.NoError(t, db.SaveBlock(ctx, b2))
filter := filters.NewFilter().SetStartSlot(b1.Block.Slot).SetEndSlot(b2.Block.Slot) filter := filters.NewFilter().SetStartSlot(b1.Block().Slot()).SetEndSlot(b2.Block().Slot())
roots, err := db.BlockRoots(ctx, filter) roots, err := db.BlockRoots(ctx, filter)
require.NoError(t, err) require.NoError(t, err)
assert.DeepEqual(t, [][32]byte{r1, r2}, roots) assert.DeepEqual(t, [][32]byte{r1, r2}, roots)
})
}
} }
func TestStore_Blocks_Retrieve_SlotRange(t *testing.T) { func TestStore_Blocks_Retrieve_SlotRange(t *testing.T) {
db := setupDB(t) for _, tt := range blockTests {
totalBlocks := make([]block.SignedBeaconBlock, 500) t.Run(tt.name, func(t *testing.T) {
for i := 0; i < 500; i++ { db := setupDB(t)
b := util.NewBeaconBlock() totalBlocks := make([]block.SignedBeaconBlock, 500)
b.Block.Slot = types.Slot(i) for i := 0; i < 500; i++ {
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32) b, err := tt.newBlock(types.Slot(i), bytesutil.PadTo([]byte("parent"), 32))
totalBlocks[i] = wrapper.WrappedPhase0SignedBeaconBlock(b) require.NoError(t, err)
totalBlocks[i] = b
}
ctx := context.Background()
require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
retrieved, _, err := db.Blocks(ctx, filters.NewFilter().SetStartSlot(100).SetEndSlot(399))
require.NoError(t, err)
assert.Equal(t, 300, len(retrieved))
})
} }
ctx := context.Background()
require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
retrieved, _, err := db.Blocks(ctx, filters.NewFilter().SetStartSlot(100).SetEndSlot(399))
require.NoError(t, err)
assert.Equal(t, 300, len(retrieved))
} }
func TestStore_Blocks_Retrieve_Epoch(t *testing.T) { func TestStore_Blocks_Retrieve_Epoch(t *testing.T) {
db := setupDB(t) for _, tt := range blockTests {
slots := params.BeaconConfig().SlotsPerEpoch.Mul(7) t.Run(tt.name, func(t *testing.T) {
totalBlocks := make([]block.SignedBeaconBlock, slots) db := setupDB(t)
for i := types.Slot(0); i < slots; i++ { slots := params.BeaconConfig().SlotsPerEpoch.Mul(7)
b := util.NewBeaconBlock() totalBlocks := make([]block.SignedBeaconBlock, slots)
b.Block.Slot = i for i := types.Slot(0); i < slots; i++ {
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32) b, err := tt.newBlock(i, bytesutil.PadTo([]byte("parent"), 32))
totalBlocks[i] = wrapper.WrappedPhase0SignedBeaconBlock(b) require.NoError(t, err)
totalBlocks[i] = b
}
ctx := context.Background()
require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
retrieved, _, err := db.Blocks(ctx, filters.NewFilter().SetStartEpoch(5).SetEndEpoch(6))
require.NoError(t, err)
want := params.BeaconConfig().SlotsPerEpoch.Mul(2)
assert.Equal(t, uint64(want), uint64(len(retrieved)))
retrieved, _, err = db.Blocks(ctx, filters.NewFilter().SetStartEpoch(0).SetEndEpoch(0))
require.NoError(t, err)
want = params.BeaconConfig().SlotsPerEpoch
assert.Equal(t, uint64(want), uint64(len(retrieved)))
})
} }
ctx := context.Background()
require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
retrieved, _, err := db.Blocks(ctx, filters.NewFilter().SetStartEpoch(5).SetEndEpoch(6))
require.NoError(t, err)
want := params.BeaconConfig().SlotsPerEpoch.Mul(2)
assert.Equal(t, uint64(want), uint64(len(retrieved)))
retrieved, _, err = db.Blocks(ctx, filters.NewFilter().SetStartEpoch(0).SetEndEpoch(0))
require.NoError(t, err)
want = params.BeaconConfig().SlotsPerEpoch
assert.Equal(t, uint64(want), uint64(len(retrieved)))
} }
func TestStore_Blocks_Retrieve_SlotRangeWithStep(t *testing.T) { func TestStore_Blocks_Retrieve_SlotRangeWithStep(t *testing.T) {
db := setupDB(t) for _, tt := range blockTests {
totalBlocks := make([]block.SignedBeaconBlock, 500) t.Run(tt.name, func(t *testing.T) {
for i := 0; i < 500; i++ { db := setupDB(t)
b := util.NewBeaconBlock() totalBlocks := make([]block.SignedBeaconBlock, 500)
b.Block.Slot = types.Slot(i) for i := 0; i < 500; i++ {
b.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32) b, err := tt.newBlock(types.Slot(i), bytesutil.PadTo([]byte("parent"), 32))
totalBlocks[i] = wrapper.WrappedPhase0SignedBeaconBlock(b) require.NoError(t, err)
} totalBlocks[i] = b
const step = 2 }
ctx := context.Background() const step = 2
require.NoError(t, db.SaveBlocks(ctx, totalBlocks)) ctx := context.Background()
retrieved, _, err := db.Blocks(ctx, filters.NewFilter().SetStartSlot(100).SetEndSlot(399).SetSlotStep(step)) require.NoError(t, db.SaveBlocks(ctx, totalBlocks))
require.NoError(t, err) retrieved, _, err := db.Blocks(ctx, filters.NewFilter().SetStartSlot(100).SetEndSlot(399).SetSlotStep(step))
assert.Equal(t, 150, len(retrieved)) require.NoError(t, err)
for _, b := range retrieved { assert.Equal(t, 150, len(retrieved))
assert.Equal(t, types.Slot(0), (b.Block().Slot()-100)%step, "Unexpect block slot %d", b.Block().Slot()) for _, b := range retrieved {
assert.Equal(t, types.Slot(0), (b.Block().Slot()-100)%step, "Unexpect block slot %d", b.Block().Slot())
}
})
} }
} }
func TestStore_SaveBlock_CanGetHighestAt(t *testing.T) { func TestStore_SaveBlock_CanGetHighestAt(t *testing.T) {
db := setupDB(t) for _, tt := range blockTests {
ctx := context.Background() t.Run(tt.name, func(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
block1 := util.NewBeaconBlock() block1, err := tt.newBlock(types.Slot(1), nil)
block1.Block.Slot = 1 require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(block1))) block2, err := tt.newBlock(types.Slot(10), nil)
block2 := util.NewBeaconBlock() require.NoError(t, err)
block2.Block.Slot = 10 block3, err := tt.newBlock(types.Slot(100), nil)
require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(block2))) require.NoError(t, err)
block3 := util.NewBeaconBlock()
block3.Block.Slot = 100
require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(block3)))
highestAt, err := db.HighestSlotBlocksBelow(ctx, 2) require.NoError(t, db.SaveBlock(ctx, block1))
require.NoError(t, err) require.NoError(t, db.SaveBlock(ctx, block2))
assert.Equal(t, false, len(highestAt) <= 0, "Got empty highest at slice") require.NoError(t, db.SaveBlock(ctx, block3))
assert.Equal(t, true, proto.Equal(block1, highestAt[0].Proto()), "Wanted: %v, received: %v", block1, highestAt[0])
highestAt, err = db.HighestSlotBlocksBelow(ctx, 11)
require.NoError(t, err)
assert.Equal(t, false, len(highestAt) <= 0, "Got empty highest at slice")
assert.Equal(t, true, proto.Equal(block2, highestAt[0].Proto()), "Wanted: %v, received: %v", block2, highestAt[0])
highestAt, err = db.HighestSlotBlocksBelow(ctx, 101)
require.NoError(t, err)
assert.Equal(t, false, len(highestAt) <= 0, "Got empty highest at slice")
assert.Equal(t, true, proto.Equal(block3, highestAt[0].Proto()), "Wanted: %v, received: %v", block3, highestAt[0])
r3, err := block3.Block.HashTreeRoot() highestAt, err := db.HighestSlotBlocksBelow(ctx, 2)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, db.deleteBlock(ctx, r3)) assert.Equal(t, false, len(highestAt) <= 0, "Got empty highest at slice")
assert.Equal(t, true, proto.Equal(block1.Proto(), highestAt[0].Proto()), "Wanted: %v, received: %v", block1, highestAt[0])
highestAt, err = db.HighestSlotBlocksBelow(ctx, 11)
require.NoError(t, err)
assert.Equal(t, false, len(highestAt) <= 0, "Got empty highest at slice")
assert.Equal(t, true, proto.Equal(block2.Proto(), highestAt[0].Proto()), "Wanted: %v, received: %v", block2, highestAt[0])
highestAt, err = db.HighestSlotBlocksBelow(ctx, 101)
require.NoError(t, err)
assert.Equal(t, false, len(highestAt) <= 0, "Got empty highest at slice")
assert.Equal(t, true, proto.Equal(block3.Proto(), highestAt[0].Proto()), "Wanted: %v, received: %v", block3, highestAt[0])
highestAt, err = db.HighestSlotBlocksBelow(ctx, 101) r3, err := block3.Block().HashTreeRoot()
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, true, proto.Equal(block2, highestAt[0].Proto()), "Wanted: %v, received: %v", block2, highestAt[0]) require.NoError(t, db.deleteBlock(ctx, r3))
highestAt, err = db.HighestSlotBlocksBelow(ctx, 101)
require.NoError(t, err)
assert.Equal(t, true, proto.Equal(block2.Proto(), highestAt[0].Proto()), "Wanted: %v, received: %v", block2, highestAt[0])
})
}
} }
func TestStore_GenesisBlock_CanGetHighestAt(t *testing.T) { func TestStore_GenesisBlock_CanGetHighestAt(t *testing.T) {
db := setupDB(t) for _, tt := range blockTests {
ctx := context.Background() t.Run(tt.name, func(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
genesisBlock := util.NewBeaconBlock() genesisBlock, err := tt.newBlock(types.Slot(0), nil)
genesisRoot, err := genesisBlock.Block.HashTreeRoot() require.NoError(t, err)
require.NoError(t, err) genesisRoot, err := genesisBlock.Block().HashTreeRoot()
require.NoError(t, db.SaveGenesisBlockRoot(ctx, genesisRoot)) require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(genesisBlock))) require.NoError(t, db.SaveGenesisBlockRoot(ctx, genesisRoot))
block1 := util.NewBeaconBlock() require.NoError(t, db.SaveBlock(ctx, genesisBlock))
block1.Block.Slot = 1 block1, err := tt.newBlock(types.Slot(1), nil)
require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(block1))) require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, block1))
highestAt, err := db.HighestSlotBlocksBelow(ctx, 2) highestAt, err := db.HighestSlotBlocksBelow(ctx, 2)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, true, proto.Equal(block1, highestAt[0].Proto()), "Wanted: %v, received: %v", block1, highestAt[0]) assert.Equal(t, true, proto.Equal(block1.Proto(), highestAt[0].Proto()), "Wanted: %v, received: %v", block1, highestAt[0])
highestAt, err = db.HighestSlotBlocksBelow(ctx, 1) highestAt, err = db.HighestSlotBlocksBelow(ctx, 1)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, true, proto.Equal(genesisBlock, highestAt[0].Proto()), "Wanted: %v, received: %v", genesisBlock, highestAt[0]) assert.Equal(t, true, proto.Equal(genesisBlock.Proto(), highestAt[0].Proto()), "Wanted: %v, received: %v", genesisBlock, highestAt[0])
highestAt, err = db.HighestSlotBlocksBelow(ctx, 0) highestAt, err = db.HighestSlotBlocksBelow(ctx, 0)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, true, proto.Equal(genesisBlock, highestAt[0].Proto()), "Wanted: %v, received: %v", genesisBlock, highestAt[0]) assert.Equal(t, true, proto.Equal(genesisBlock.Proto(), highestAt[0].Proto()), "Wanted: %v, received: %v", genesisBlock, highestAt[0])
})
}
} }
func TestStore_SaveBlocks_HasCachedBlocks(t *testing.T) { func TestStore_SaveBlocks_HasCachedBlocks(t *testing.T) {
db := setupDB(t) for _, tt := range blockTests {
ctx := context.Background() t.Run(tt.name, func(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
b := make([]block.SignedBeaconBlock, 500) b := make([]block.SignedBeaconBlock, 500)
for i := 0; i < 500; i++ { for i := 0; i < 500; i++ {
blk := util.NewBeaconBlock() blk, err := tt.newBlock(types.Slot(i), bytesutil.PadTo([]byte("parent"), 32))
blk.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32) require.NoError(t, err)
blk.Block.Slot = types.Slot(i) b[i] = blk
b[i] = wrapper.WrappedPhase0SignedBeaconBlock(blk) }
require.NoError(t, db.SaveBlock(ctx, b[0]))
require.NoError(t, db.SaveBlocks(ctx, b))
f := filters.NewFilter().SetStartSlot(0).SetEndSlot(500)
blks, _, err := db.Blocks(ctx, f)
require.NoError(t, err)
assert.Equal(t, 500, len(blks), "Did not get wanted blocks")
})
} }
require.NoError(t, db.SaveBlock(ctx, b[0]))
require.NoError(t, db.SaveBlocks(ctx, b))
f := filters.NewFilter().SetStartSlot(0).SetEndSlot(500)
blks, _, err := db.Blocks(ctx, f)
require.NoError(t, err)
assert.Equal(t, 500, len(blks), "Did not get wanted blocks")
} }
func TestStore_SaveBlocks_HasRootsMatched(t *testing.T) { func TestStore_SaveBlocks_HasRootsMatched(t *testing.T) {
db := setupDB(t) for _, tt := range blockTests {
ctx := context.Background() t.Run(tt.name, func(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
b := make([]block.SignedBeaconBlock, 500) b := make([]block.SignedBeaconBlock, 500)
for i := 0; i < 500; i++ { for i := 0; i < 500; i++ {
blk := util.NewBeaconBlock() blk, err := tt.newBlock(types.Slot(i), bytesutil.PadTo([]byte("parent"), 32))
blk.Block.ParentRoot = bytesutil.PadTo([]byte("parent"), 32) require.NoError(t, err)
blk.Block.Slot = types.Slot(i) b[i] = blk
b[i] = wrapper.WrappedPhase0SignedBeaconBlock(blk) }
}
require.NoError(t, db.SaveBlocks(ctx, b)) require.NoError(t, db.SaveBlocks(ctx, b))
f := filters.NewFilter().SetStartSlot(0).SetEndSlot(500) f := filters.NewFilter().SetStartSlot(0).SetEndSlot(500)
blks, roots, err := db.Blocks(ctx, f) blks, roots, err := db.Blocks(ctx, f)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, 500, len(blks), "Did not get wanted blocks") assert.Equal(t, 500, len(blks), "Did not get wanted blocks")
for i, blk := range blks { for i, blk := range blks {
rt, err := blk.Block().HashTreeRoot() rt, err := blk.Block().HashTreeRoot()
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, roots[i], rt, "mismatch of block roots") assert.Equal(t, roots[i], rt, "mismatch of block roots")
}
})
} }
} }
func TestStore_BlocksBySlot_BlockRootsBySlot(t *testing.T) { func TestStore_BlocksBySlot_BlockRootsBySlot(t *testing.T) {
db := setupDB(t) for _, tt := range blockTests {
ctx := context.Background() t.Run(tt.name, func(t *testing.T) {
db := setupDB(t)
ctx := context.Background()
b1 := util.NewBeaconBlock() b1, err := tt.newBlock(types.Slot(20), nil)
b1.Block.Slot = 20 require.NoError(t, err)
require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b1))) require.NoError(t, db.SaveBlock(ctx, b1))
b2 := util.NewBeaconBlock() b2, err := tt.newBlock(types.Slot(100), bytesutil.PadTo([]byte("parent1"), 32))
b2.Block.Slot = 100 require.NoError(t, err)
b2.Block.ParentRoot = bytesutil.PadTo([]byte("parent1"), 32) require.NoError(t, db.SaveBlock(ctx, b2))
require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b2))) b3, err := tt.newBlock(types.Slot(100), bytesutil.PadTo([]byte("parent2"), 32))
b3 := util.NewBeaconBlock() require.NoError(t, err)
b3.Block.Slot = 100 require.NoError(t, db.SaveBlock(ctx, b3))
b3.Block.ParentRoot = bytesutil.PadTo([]byte("parent2"), 32)
require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(b3)))
r1, err := b1.Block.HashTreeRoot() r1, err := b1.Block().HashTreeRoot()
require.NoError(t, err) require.NoError(t, err)
r2, err := b2.Block.HashTreeRoot() r2, err := b2.Block().HashTreeRoot()
require.NoError(t, err) require.NoError(t, err)
r3, err := b3.Block.HashTreeRoot() r3, err := b3.Block().HashTreeRoot()
require.NoError(t, err) require.NoError(t, err)
hasBlocks, retrievedBlocks, err := db.BlocksBySlot(ctx, 1) hasBlocks, retrievedBlocks, err := db.BlocksBySlot(ctx, 1)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, 0, len(retrievedBlocks), "Unexpected number of blocks received, expected none") assert.Equal(t, 0, len(retrievedBlocks), "Unexpected number of blocks received, expected none")
assert.Equal(t, false, hasBlocks, "Expected no blocks") assert.Equal(t, false, hasBlocks, "Expected no blocks")
hasBlocks, retrievedBlocks, err = db.BlocksBySlot(ctx, 20) hasBlocks, retrievedBlocks, err = db.BlocksBySlot(ctx, 20)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, true, proto.Equal(b1, retrievedBlocks[0].Proto()), "Wanted: %v, received: %v", b1, retrievedBlocks[0]) assert.Equal(t, true, proto.Equal(b1.Proto(), retrievedBlocks[0].Proto()), "Wanted: %v, received: %v", b1, retrievedBlocks[0])
assert.Equal(t, true, hasBlocks, "Expected to have blocks") assert.Equal(t, true, hasBlocks, "Expected to have blocks")
hasBlocks, retrievedBlocks, err = db.BlocksBySlot(ctx, 100) hasBlocks, retrievedBlocks, err = db.BlocksBySlot(ctx, 100)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, true, proto.Equal(b2, retrievedBlocks[0].Proto()), "Wanted: %v, received: %v", b2, retrievedBlocks[0]) if len(retrievedBlocks) != 2 {
assert.Equal(t, true, proto.Equal(b3, retrievedBlocks[1].Proto()), "Wanted: %v, received: %v", b3, retrievedBlocks[1]) t.Fatalf("Expected 2 blocks, received %d blocks", len(retrievedBlocks))
assert.Equal(t, true, hasBlocks, "Expected to have blocks") }
assert.Equal(t, true, proto.Equal(b2.Proto(), retrievedBlocks[0].Proto()), "Wanted: %v, received: %v", b2, retrievedBlocks[0])
assert.Equal(t, true, proto.Equal(b3.Proto(), retrievedBlocks[1].Proto()), "Wanted: %v, received: %v", b3, retrievedBlocks[1])
assert.Equal(t, true, hasBlocks, "Expected to have blocks")
hasBlockRoots, retrievedBlockRoots, err := db.BlockRootsBySlot(ctx, 1) hasBlockRoots, retrievedBlockRoots, err := db.BlockRootsBySlot(ctx, 1)
require.NoError(t, err) require.NoError(t, err)
assert.DeepEqual(t, [][32]byte{}, retrievedBlockRoots) assert.DeepEqual(t, [][32]byte{}, retrievedBlockRoots)
assert.Equal(t, false, hasBlockRoots, "Expected no block roots") assert.Equal(t, false, hasBlockRoots, "Expected no block roots")
hasBlockRoots, retrievedBlockRoots, err = db.BlockRootsBySlot(ctx, 20) hasBlockRoots, retrievedBlockRoots, err = db.BlockRootsBySlot(ctx, 20)
require.NoError(t, err) require.NoError(t, err)
assert.DeepEqual(t, [][32]byte{r1}, retrievedBlockRoots) assert.DeepEqual(t, [][32]byte{r1}, retrievedBlockRoots)
assert.Equal(t, true, hasBlockRoots, "Expected no block roots") assert.Equal(t, true, hasBlockRoots, "Expected no block roots")
hasBlockRoots, retrievedBlockRoots, err = db.BlockRootsBySlot(ctx, 100) hasBlockRoots, retrievedBlockRoots, err = db.BlockRootsBySlot(ctx, 100)
require.NoError(t, err) require.NoError(t, err)
assert.DeepEqual(t, [][32]byte{r2, r3}, retrievedBlockRoots) assert.DeepEqual(t, [][32]byte{r2, r3}, retrievedBlockRoots)
assert.Equal(t, true, hasBlockRoots, "Expected no block roots") assert.Equal(t, true, hasBlockRoots, "Expected no block roots")
})
}
} }

View File

@@ -136,76 +136,57 @@ func TestStore_IsFinalized_ForkEdgeCase(t *testing.T) {
func TestStore_IsFinalizedChildBlock(t *testing.T) { func TestStore_IsFinalizedChildBlock(t *testing.T) {
slotsPerEpoch := uint64(params.BeaconConfig().SlotsPerEpoch) slotsPerEpoch := uint64(params.BeaconConfig().SlotsPerEpoch)
db := setupDB(t)
ctx := context.Background() ctx := context.Background()
require.NoError(t, db.SaveGenesisBlockRoot(ctx, genesisBlockRoot)) eval := func(t testing.TB, ctx context.Context, db *Store, blks []block.SignedBeaconBlock) {
require.NoError(t, db.SaveBlocks(ctx, blks))
blks := makeBlocks(t, 0, slotsPerEpoch*3, genesisBlockRoot) root, err := blks[slotsPerEpoch].Block().HashTreeRoot()
require.NoError(t, db.SaveBlocks(ctx, blks))
root, err := blks[slotsPerEpoch].Block().HashTreeRoot()
require.NoError(t, err)
cp := &ethpb.Checkpoint{
Epoch: 1,
Root: root[:],
}
st, err := util.NewBeaconState()
require.NoError(t, err)
// a state is required to save checkpoint
require.NoError(t, db.SaveState(ctx, st, root))
require.NoError(t, db.SaveFinalizedCheckpoint(ctx, cp))
// All blocks up to slotsPerEpoch should have a finalized child block.
for i := uint64(0); i < slotsPerEpoch; i++ {
root, err := blks[i].Block().HashTreeRoot()
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, true, db.IsFinalizedBlock(ctx, root), "Block at index %d was not considered finalized in the index", i)
blk, err := db.FinalizedChildBlock(ctx, root) cp := &ethpb.Checkpoint{
assert.NoError(t, err) Epoch: 1,
if blk == nil { Root: root[:],
t.Error("Child block doesn't exist for valid finalized block.") }
st, err := util.NewBeaconState()
require.NoError(t, err)
// a state is required to save checkpoint
require.NoError(t, db.SaveState(ctx, st, root))
require.NoError(t, db.SaveFinalizedCheckpoint(ctx, cp))
// All blocks up to slotsPerEpoch should have a finalized child block.
for i := uint64(0); i < slotsPerEpoch; i++ {
root, err := blks[i].Block().HashTreeRoot()
require.NoError(t, err)
assert.Equal(t, true, db.IsFinalizedBlock(ctx, root), "Block at index %d was not considered finalized in the index", i)
blk, err := db.FinalizedChildBlock(ctx, root)
assert.NoError(t, err)
if blk == nil {
t.Error("Child block doesn't exist for valid finalized block.")
}
} }
} }
}
func TestStore_IsFinalizedChildBlockAltair(t *testing.T) { setup := func(t testing.TB) *Store {
slotsPerEpoch := uint64(params.BeaconConfig().SlotsPerEpoch) db := setupDB(t)
db := setupDB(t) require.NoError(t, db.SaveGenesisBlockRoot(ctx, genesisBlockRoot))
ctx := context.Background()
require.NoError(t, db.SaveGenesisBlockRoot(ctx, genesisBlockRoot)) return db
blks := makeBlocksAltair(t, 0, slotsPerEpoch*3, genesisBlockRoot)
require.NoError(t, db.SaveBlocks(ctx, blks))
root, err := blks[slotsPerEpoch].Block().HashTreeRoot()
require.NoError(t, err)
cp := &ethpb.Checkpoint{
Epoch: 1,
Root: root[:],
} }
st, err := util.NewBeaconState() t.Run("phase0", func(t *testing.T) {
require.NoError(t, err) db := setup(t)
// a state is required to save checkpoint
require.NoError(t, db.SaveState(ctx, st, root))
require.NoError(t, db.SaveFinalizedCheckpoint(ctx, cp))
// All blocks up to slotsPerEpoch should have a finalized child block. blks := makeBlocks(t, 0, slotsPerEpoch*3, genesisBlockRoot)
for i := uint64(0); i < slotsPerEpoch; i++ { eval(t, ctx, db, blks)
root, err := blks[i].Block().HashTreeRoot() })
require.NoError(t, err)
assert.Equal(t, true, db.IsFinalizedBlock(ctx, root), "Block at index %d was not considered finalized in the index", i) t.Run("altair", func(t *testing.T) {
blk, err := db.FinalizedChildBlock(ctx, root) db := setup(t)
assert.NoError(t, err)
if blk == nil { blks := makeBlocksAltair(t, 0, slotsPerEpoch*3, genesisBlockRoot)
t.Error("Child block doesn't exist for valid finalized block.") eval(t, ctx, db, blks)
} })
}
} }
func sszRootOrDie(t *testing.T, block block.SignedBeaconBlock) []byte { func sszRootOrDie(t *testing.T, block block.SignedBeaconBlock) []byte {

View File

@@ -99,14 +99,7 @@ func (bs *Server) ListSyncCommittees(ctx context.Context, req *ethpbv2.StateSync
}, nil }, nil
} }
func currentCommitteeIndicesFromState(st state.BeaconState) ([]types.ValidatorIndex, *ethpbalpha.SyncCommittee, error) { func committeeIndicesFromState(st state.BeaconState, committee *ethpbalpha.SyncCommittee) ([]types.ValidatorIndex, *ethpbalpha.SyncCommittee, error) {
committee, err := st.CurrentSyncCommittee()
if err != nil {
return nil, nil, fmt.Errorf(
"could not get sync committee: %v", err,
)
}
committeeIndices := make([]types.ValidatorIndex, len(committee.Pubkeys)) committeeIndices := make([]types.ValidatorIndex, len(committee.Pubkeys))
for i, key := range committee.Pubkeys { for i, key := range committee.Pubkeys {
index, ok := st.ValidatorIndexByPubkey(bytesutil.ToBytes48(key)) index, ok := st.ValidatorIndexByPubkey(bytesutil.ToBytes48(key))
@@ -121,6 +114,17 @@ func currentCommitteeIndicesFromState(st state.BeaconState) ([]types.ValidatorIn
return committeeIndices, committee, nil return committeeIndices, committee, nil
} }
func currentCommitteeIndicesFromState(st state.BeaconState) ([]types.ValidatorIndex, *ethpbalpha.SyncCommittee, error) {
committee, err := st.CurrentSyncCommittee()
if err != nil {
return nil, nil, fmt.Errorf(
"could not get sync committee: %v", err,
)
}
return committeeIndicesFromState(st, committee)
}
func nextCommitteeIndicesFromState(st state.BeaconState) ([]types.ValidatorIndex, *ethpbalpha.SyncCommittee, error) { func nextCommitteeIndicesFromState(st state.BeaconState) ([]types.ValidatorIndex, *ethpbalpha.SyncCommittee, error) {
committee, err := st.NextSyncCommittee() committee, err := st.NextSyncCommittee()
if err != nil { if err != nil {
@@ -129,18 +133,7 @@ func nextCommitteeIndicesFromState(st state.BeaconState) ([]types.ValidatorIndex
) )
} }
committeeIndices := make([]types.ValidatorIndex, len(committee.Pubkeys)) return committeeIndicesFromState(st, committee)
for i, key := range committee.Pubkeys {
index, ok := st.ValidatorIndexByPubkey(bytesutil.ToBytes48(key))
if !ok {
return nil, nil, fmt.Errorf(
"validator index not found for pubkey %#x",
bytesutil.Trunc(key),
)
}
committeeIndices[i] = index
}
return committeeIndices, committee, nil
} }
func extractSyncSubcommittees(st state.BeaconState, committee *ethpbalpha.SyncCommittee) ([]*ethpbv2.SyncSubcommitteeValidators, error) { func extractSyncSubcommittees(st state.BeaconState, committee *ethpbalpha.SyncCommittee) ([]*ethpbv2.SyncSubcommitteeValidators, error) {

View File

@@ -41,75 +41,20 @@ type blockContainer struct {
func (bs *Server) ListBlocks( func (bs *Server) ListBlocks(
ctx context.Context, req *ethpb.ListBlocksRequest, ctx context.Context, req *ethpb.ListBlocksRequest,
) (*ethpb.ListBlocksResponse, error) { ) (*ethpb.ListBlocksResponse, error) {
if int(req.PageSize) > cmd.Get().MaxRPCPageSize { ctrs, numBlks, nextPageToken, err := bs.listBlocks(ctx, req)
return nil, status.Errorf(codes.InvalidArgument, "Requested page size %d can not be greater than max size %d", if err != nil {
req.PageSize, cmd.Get().MaxRPCPageSize) return nil, err
}
blkContainers, err := convertToProto(ctrs)
if err != nil {
return nil, err
} }
switch q := req.QueryFilter.(type) { return &ethpb.ListBlocksResponse{
case *ethpb.ListBlocksRequest_Epoch: BlockContainers: blkContainers,
ctrs, numBlks, nextPageToken, err := bs.listBlocksForEpoch(ctx, req, q) TotalSize: int32(numBlks),
if err != nil { NextPageToken: nextPageToken,
return nil, err }, nil
}
blkContainers, err := convertToProto(ctrs)
if err != nil {
return nil, err
}
return &ethpb.ListBlocksResponse{
BlockContainers: blkContainers,
TotalSize: int32(numBlks),
NextPageToken: nextPageToken,
}, nil
case *ethpb.ListBlocksRequest_Root:
ctrs, numBlks, nextPageToken, err := bs.listBlocksForRoot(ctx, req, q)
if err != nil {
return nil, err
}
blkContainers, err := convertToProto(ctrs)
if err != nil {
return nil, err
}
return &ethpb.ListBlocksResponse{
BlockContainers: blkContainers,
TotalSize: int32(numBlks),
NextPageToken: nextPageToken,
}, nil
case *ethpb.ListBlocksRequest_Slot:
ctrs, numBlks, nextPageToken, err := bs.listBlocksForSlot(ctx, req, q)
if err != nil {
return nil, err
}
blkContainers, err := convertToProto(ctrs)
if err != nil {
return nil, err
}
return &ethpb.ListBlocksResponse{
BlockContainers: blkContainers,
TotalSize: int32(numBlks),
NextPageToken: nextPageToken,
}, nil
case *ethpb.ListBlocksRequest_Genesis:
ctrs, numBlks, nextPageToken, err := bs.listBlocksForGenesis(ctx, req, q)
if err != nil {
return nil, err
}
blkContainers, err := convertToProto(ctrs)
if err != nil {
return nil, err
}
return &ethpb.ListBlocksResponse{
BlockContainers: blkContainers,
TotalSize: int32(numBlks),
NextPageToken: nextPageToken,
}, nil
}
return nil, status.Error(codes.InvalidArgument, "Must specify a filter criteria for fetching blocks")
} }
// ListBeaconBlocks retrieves blocks by root, slot, or epoch. // ListBeaconBlocks retrieves blocks by root, slot, or epoch.
@@ -121,72 +66,39 @@ func (bs *Server) ListBlocks(
func (bs *Server) ListBeaconBlocks( func (bs *Server) ListBeaconBlocks(
ctx context.Context, req *ethpb.ListBlocksRequest, ctx context.Context, req *ethpb.ListBlocksRequest,
) (*ethpb.ListBeaconBlocksResponse, error) { ) (*ethpb.ListBeaconBlocksResponse, error) {
ctrs, numBlks, nextPageToken, err := bs.listBlocks(ctx, req)
if err != nil {
return nil, err
}
altCtrs, err := convertFromV1Containers(ctrs)
if err != nil {
return nil, err
}
return &ethpb.ListBeaconBlocksResponse{
BlockContainers: altCtrs,
TotalSize: int32(numBlks),
NextPageToken: nextPageToken,
}, nil
}
func (bs *Server) listBlocks(ctx context.Context, req *ethpb.ListBlocksRequest) ([]blockContainer, int, string, error) {
if int(req.PageSize) > cmd.Get().MaxRPCPageSize { if int(req.PageSize) > cmd.Get().MaxRPCPageSize {
return nil, status.Errorf(codes.InvalidArgument, "Requested page size %d can not be greater than max size %d", return nil, 0, "", status.Errorf(codes.InvalidArgument, "Requested page size %d can not be greater than max size %d",
req.PageSize, cmd.Get().MaxRPCPageSize) req.PageSize, cmd.Get().MaxRPCPageSize)
} }
switch q := req.QueryFilter.(type) { switch q := req.QueryFilter.(type) {
case *ethpb.ListBlocksRequest_Epoch: case *ethpb.ListBlocksRequest_Epoch:
ctrs, numBlks, nextPageToken, err := bs.listBlocksForEpoch(ctx, req, q) return bs.listBlocksForEpoch(ctx, req, q)
if err != nil {
return nil, err
}
altCtrs, err := convertFromV1Containers(ctrs)
if err != nil {
return nil, err
}
return &ethpb.ListBeaconBlocksResponse{
BlockContainers: altCtrs,
TotalSize: int32(numBlks),
NextPageToken: nextPageToken,
}, nil
case *ethpb.ListBlocksRequest_Root: case *ethpb.ListBlocksRequest_Root:
ctrs, numBlks, nextPageToken, err := bs.listBlocksForRoot(ctx, req, q) return bs.listBlocksForRoot(ctx, req, q)
if err != nil {
return nil, err
}
altCtrs, err := convertFromV1Containers(ctrs)
if err != nil {
return nil, err
}
return &ethpb.ListBeaconBlocksResponse{
BlockContainers: altCtrs,
TotalSize: int32(numBlks),
NextPageToken: nextPageToken,
}, nil
case *ethpb.ListBlocksRequest_Slot: case *ethpb.ListBlocksRequest_Slot:
ctrs, numBlks, nextPageToken, err := bs.listBlocksForSlot(ctx, req, q) return bs.listBlocksForSlot(ctx, req, q)
if err != nil {
return nil, err
}
altCtrs, err := convertFromV1Containers(ctrs)
if err != nil {
return nil, err
}
return &ethpb.ListBeaconBlocksResponse{
BlockContainers: altCtrs,
TotalSize: int32(numBlks),
NextPageToken: nextPageToken,
}, nil
case *ethpb.ListBlocksRequest_Genesis: case *ethpb.ListBlocksRequest_Genesis:
ctrs, numBlks, nextPageToken, err := bs.listBlocksForGenesis(ctx, req, q) return bs.listBlocksForGenesis(ctx, req, q)
if err != nil { default:
return nil, err return nil, 0, "", status.Errorf(codes.InvalidArgument, "Must specify a filter criteria for fetching blocks. Criteria %T not supported", q)
}
altCtrs, err := convertFromV1Containers(ctrs)
if err != nil {
return nil, err
}
return &ethpb.ListBeaconBlocksResponse{
BlockContainers: altCtrs,
TotalSize: int32(numBlks),
NextPageToken: nextPageToken,
}, nil
} }
return nil, status.Error(codes.InvalidArgument, "Must specify a filter criteria for fetching blocks")
} }
func convertFromV1Containers(ctrs []blockContainer) ([]*ethpb.BeaconBlockContainer, error) { func convertFromV1Containers(ctrs []blockContainer) ([]*ethpb.BeaconBlockContainer, error) {

View File

@@ -12,7 +12,10 @@ go_library(
go_test( go_test(
name = "go_default_test", name = "go_default_test",
srcs = ["mainnet_test.go"], srcs = [
"common_test.go",
"mainnet_test.go",
],
deps = [ deps = [
":go_default_library", ":go_default_library",
"//config/params:go_default_library", "//config/params:go_default_library",
@@ -22,7 +25,10 @@ go_test(
go_test( go_test(
name = "go_minimal_test", name = "go_minimal_test",
srcs = ["minimal_test.go"], srcs = [
"common_test.go",
"minimal_test.go",
],
eth_network = "minimal", eth_network = "minimal",
deps = [ deps = [
":go_default_library", ":go_default_library",

View File

@@ -0,0 +1,22 @@
package field_params_test
import (
"testing"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/testing/assert"
)
func testFieldParametersMatchConfig(t *testing.T) {
assert.Equal(t, uint64(params.BeaconConfig().SlotsPerHistoricalRoot), uint64(fieldparams.BlockRootsLength))
assert.Equal(t, uint64(params.BeaconConfig().SlotsPerHistoricalRoot), uint64(fieldparams.StateRootsLength))
assert.Equal(t, params.BeaconConfig().HistoricalRootsLimit, uint64(fieldparams.HistoricalRootsLength))
assert.Equal(t, uint64(params.BeaconConfig().EpochsPerHistoricalVector), uint64(fieldparams.RandaoMixesLength))
assert.Equal(t, params.BeaconConfig().ValidatorRegistryLimit, uint64(fieldparams.ValidatorRegistryLimit))
assert.Equal(t, uint64(params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().EpochsPerEth1VotingPeriod))), uint64(fieldparams.Eth1DataVotesLength))
assert.Equal(t, uint64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().MaxAttestations)), uint64(fieldparams.PreviousEpochAttestationsLength))
assert.Equal(t, uint64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().MaxAttestations)), uint64(fieldparams.CurrentEpochAttestationsLength))
assert.Equal(t, uint64(params.BeaconConfig().EpochsPerSlashingsVector), uint64(fieldparams.SlashingsLength))
assert.Equal(t, params.BeaconConfig().SyncCommitteeSize, uint64(fieldparams.SyncCommitteeLength))
}

View File

@@ -5,21 +5,10 @@ package field_params_test
import ( import (
"testing" "testing"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/testing/assert"
) )
func TestFieldParametersValues(t *testing.T) { func TestFieldParametersValues(t *testing.T) {
params.UseMainnetConfig() params.UseMainnetConfig()
assert.Equal(t, uint64(params.BeaconConfig().SlotsPerHistoricalRoot), uint64(fieldparams.BlockRootsLength)) testFieldParametersMatchConfig(t)
assert.Equal(t, uint64(params.BeaconConfig().SlotsPerHistoricalRoot), uint64(fieldparams.StateRootsLength))
assert.Equal(t, params.BeaconConfig().HistoricalRootsLimit, uint64(fieldparams.HistoricalRootsLength))
assert.Equal(t, uint64(params.BeaconConfig().EpochsPerHistoricalVector), uint64(fieldparams.RandaoMixesLength))
assert.Equal(t, params.BeaconConfig().ValidatorRegistryLimit, uint64(fieldparams.ValidatorRegistryLimit))
assert.Equal(t, uint64(params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().EpochsPerEth1VotingPeriod))), uint64(fieldparams.Eth1DataVotesLength))
assert.Equal(t, uint64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().MaxAttestations)), uint64(fieldparams.PreviousEpochAttestationsLength))
assert.Equal(t, uint64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().MaxAttestations)), uint64(fieldparams.CurrentEpochAttestationsLength))
assert.Equal(t, uint64(params.BeaconConfig().EpochsPerSlashingsVector), uint64(fieldparams.SlashingsLength))
assert.Equal(t, params.BeaconConfig().SyncCommitteeSize, uint64(fieldparams.SyncCommitteeLength))
} }

View File

@@ -5,21 +5,10 @@ package field_params_test
import ( import (
"testing" "testing"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/testing/assert"
) )
func TestFieldParametersValues(t *testing.T) { func TestFieldParametersValues(t *testing.T) {
params.UseMinimalConfig() params.UseMinimalConfig()
assert.Equal(t, uint64(params.BeaconConfig().SlotsPerHistoricalRoot), uint64(fieldparams.BlockRootsLength)) testFieldParametersMatchConfig(t)
assert.Equal(t, uint64(params.BeaconConfig().SlotsPerHistoricalRoot), uint64(fieldparams.StateRootsLength))
assert.Equal(t, params.BeaconConfig().HistoricalRootsLimit, uint64(fieldparams.HistoricalRootsLength))
assert.Equal(t, uint64(params.BeaconConfig().EpochsPerHistoricalVector), uint64(fieldparams.RandaoMixesLength))
assert.Equal(t, params.BeaconConfig().ValidatorRegistryLimit, uint64(fieldparams.ValidatorRegistryLimit))
assert.Equal(t, uint64(params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().EpochsPerEth1VotingPeriod))), uint64(fieldparams.Eth1DataVotesLength))
assert.Equal(t, uint64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().MaxAttestations)), uint64(fieldparams.PreviousEpochAttestationsLength))
assert.Equal(t, uint64(params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().MaxAttestations)), uint64(fieldparams.CurrentEpochAttestationsLength))
assert.Equal(t, uint64(params.BeaconConfig().EpochsPerSlashingsVector), uint64(fieldparams.SlashingsLength))
assert.Equal(t, params.BeaconConfig().SyncCommitteeSize, uint64(fieldparams.SyncCommitteeLength))
} }

View File

@@ -13,8 +13,27 @@ var (
_ = block.SignedBeaconBlock(&altairSignedBeaconBlock{}) _ = block.SignedBeaconBlock(&altairSignedBeaconBlock{})
_ = block.BeaconBlock(&altairBeaconBlock{}) _ = block.BeaconBlock(&altairBeaconBlock{})
_ = block.BeaconBlockBody(&altairBeaconBlockBody{}) _ = block.BeaconBlockBody(&altairBeaconBlockBody{})
// ErrUnsupportedSignedBeaconBlock is returned when the struct type is not a supported signed
// beacon block type.
ErrUnsupportedSignedBeaconBlock = errors.New("unsupported signed beacon block")
) )
// WrappedSignedBeaconBlock will wrap a signed beacon block to conform to the
// signed beacon block interface.
func WrappedSignedBeaconBlock(i interface{}) (block.SignedBeaconBlock, error) {
switch b := i.(type) {
case *eth.SignedBeaconBlock:
return WrappedPhase0SignedBeaconBlock(b), nil
case *eth.SignedBeaconBlockAltair:
return WrappedAltairSignedBeaconBlock(b)
case *eth.SignedBeaconBlockMerge:
return WrappedMergeSignedBeaconBlock(b)
default:
return nil, errors.Wrapf(ErrUnsupportedSignedBeaconBlock, "unable to wrap block of type %T", i)
}
}
// Phase0SignedBeaconBlock is a convenience wrapper around a phase 0 beacon block // Phase0SignedBeaconBlock is a convenience wrapper around a phase 0 beacon block
// object. This wrapper allows us to conform to a common interface so that beacon // object. This wrapper allows us to conform to a common interface so that beacon
// blocks for future forks can also be applied across prysm without issues. // blocks for future forks can also be applied across prysm without issues.
@@ -24,6 +43,7 @@ type Phase0SignedBeaconBlock struct {
// WrappedPhase0SignedBeaconBlock is constructor which wraps a protobuf phase 0 block // WrappedPhase0SignedBeaconBlock is constructor which wraps a protobuf phase 0 block
// with the block wrapper. // with the block wrapper.
// Deprecated: use WrappedSignedBeaconBlock instead.
func WrappedPhase0SignedBeaconBlock(b *eth.SignedBeaconBlock) block.SignedBeaconBlock { func WrappedPhase0SignedBeaconBlock(b *eth.SignedBeaconBlock) block.SignedBeaconBlock {
return Phase0SignedBeaconBlock{b: b} return Phase0SignedBeaconBlock{b: b}
} }
@@ -291,6 +311,7 @@ type altairSignedBeaconBlock struct {
// WrappedAltairSignedBeaconBlock is constructor which wraps a protobuf altair block // WrappedAltairSignedBeaconBlock is constructor which wraps a protobuf altair block
// with the block wrapper. // with the block wrapper.
// Deprecated: use WrappedSignedBeaconBlock instead.
func WrappedAltairSignedBeaconBlock(b *eth.SignedBeaconBlockAltair) (block.SignedBeaconBlock, error) { func WrappedAltairSignedBeaconBlock(b *eth.SignedBeaconBlockAltair) (block.SignedBeaconBlock, error) {
w := altairSignedBeaconBlock{b: b} w := altairSignedBeaconBlock{b: b}
if w.IsNil() { if w.IsNil() {
@@ -561,6 +582,7 @@ type mergeSignedBeaconBlock struct {
} }
// WrappedMergeSignedBeaconBlock is constructor which wraps a protobuf merge block with the block wrapper. // WrappedMergeSignedBeaconBlock is constructor which wraps a protobuf merge block with the block wrapper.
// Deprecated: use WrappedSignedBeaconBlock instead.
func WrappedMergeSignedBeaconBlock(b *eth.SignedBeaconBlockMerge) (block.SignedBeaconBlock, error) { func WrappedMergeSignedBeaconBlock(b *eth.SignedBeaconBlockMerge) (block.SignedBeaconBlock, error) {
w := mergeSignedBeaconBlock{b: b} w := mergeSignedBeaconBlock{b: b}
if w.IsNil() { if w.IsNil() {

View File

@@ -14,6 +14,42 @@ import (
"github.com/prysmaticlabs/prysm/testing/util" "github.com/prysmaticlabs/prysm/testing/util"
) )
func TestWrappedSignedBeaconBlock(t *testing.T) {
tests := []struct {
name string
blk interface{}
wantErr bool
}{
{
name: "unsupported type",
blk: "not a beacon block",
wantErr: true,
},
{
name: "phase0",
blk: util.NewBeaconBlock(),
},
{
name: "altair",
blk: util.NewBeaconBlockAltair(),
},
{
name: "bellatrix",
blk: util.NewBeaconBlockMerge(),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := wrapper.WrappedSignedBeaconBlock(tt.blk)
if tt.wantErr {
require.ErrorIs(t, err, wrapper.ErrUnsupportedSignedBeaconBlock)
} else {
require.NoError(t, err)
}
})
}
}
func TestAltairSignedBeaconBlock_Signature(t *testing.T) { func TestAltairSignedBeaconBlock_Signature(t *testing.T) {
sig := []byte{0x11, 0x22} sig := []byte{0x11, 0x22}
wsb, err := wrapper.WrappedAltairSignedBeaconBlock(&ethpb.SignedBeaconBlockAltair{Block: &ethpb.BeaconBlockAltair{}, Signature: sig}) wsb, err := wrapper.WrappedAltairSignedBeaconBlock(&ethpb.SignedBeaconBlockAltair{Block: &ethpb.BeaconBlockAltair{}, Signature: sig})