mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-06 22:23:56 -05:00
**What type of PR is this?** Other **What does this PR do? Why is it needed?** This pull request removes `NUMBER_OF_COLUMNS` and `MAX_CELLS_IN_EXTENDED_MATRIX` configuration. **Other notes for review** Please read commit by commit, with commit messages. **Acknowledgements** - [x] I have read [CONTRIBUTING.md](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md). - [x] I have included a uniquely named [changelog fragment file](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md#maintaining-changelogmd). - [x] I have added a description to this PR with sufficient context for reviewers to understand this PR.
271 lines
9.4 KiB
Go
271 lines
9.4 KiB
Go
package peerdas_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/OffchainLabs/prysm/v7/beacon-chain/blockchain/kzg"
|
|
"github.com/OffchainLabs/prysm/v7/beacon-chain/core/peerdas"
|
|
state_native "github.com/OffchainLabs/prysm/v7/beacon-chain/state/state-native"
|
|
fieldparams "github.com/OffchainLabs/prysm/v7/config/fieldparams"
|
|
"github.com/OffchainLabs/prysm/v7/consensus-types/blocks"
|
|
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
|
|
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
|
|
"github.com/OffchainLabs/prysm/v7/testing/require"
|
|
"github.com/OffchainLabs/prysm/v7/testing/util"
|
|
)
|
|
|
|
func TestValidatorsCustodyRequirement(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
count uint64
|
|
expected uint64
|
|
}{
|
|
{name: "0 validators", count: 0, expected: 8},
|
|
{name: "1 validator", count: 1, expected: 8},
|
|
{name: "8 validators", count: 8, expected: 8},
|
|
{name: "9 validators", count: 9, expected: 9},
|
|
{name: "100 validators", count: 100, expected: 100},
|
|
{name: "128 validators", count: 128, expected: 128},
|
|
{name: "129 validators", count: 129, expected: 128},
|
|
{name: "1000 validators", count: 1000, expected: 128},
|
|
}
|
|
|
|
const balance = uint64(32_000_000_000)
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
validators := make([]*ethpb.Validator, 0, tc.count)
|
|
for range tc.count {
|
|
validator := ðpb.Validator{
|
|
EffectiveBalance: balance,
|
|
}
|
|
|
|
validators = append(validators, validator)
|
|
}
|
|
|
|
validatorsIndex := make(map[primitives.ValidatorIndex]bool)
|
|
for i := range tc.count {
|
|
validatorsIndex[primitives.ValidatorIndex(i)] = true
|
|
}
|
|
|
|
beaconState, err := state_native.InitializeFromProtoFulu(ðpb.BeaconStateFulu{Validators: validators})
|
|
require.NoError(t, err)
|
|
|
|
actual, err := peerdas.ValidatorsCustodyRequirement(beaconState, validatorsIndex)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tc.expected, actual)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDataColumnSidecars(t *testing.T) {
|
|
const numberOfColumns = fieldparams.NumberOfColumns
|
|
|
|
t.Run("sizes mismatch", func(t *testing.T) {
|
|
// Create a protobuf signed beacon block.
|
|
signedBeaconBlockPb := util.NewBeaconBlockDeneb()
|
|
|
|
// Create a signed beacon block from the protobuf.
|
|
signedBeaconBlock, err := blocks.NewSignedBeaconBlock(signedBeaconBlockPb)
|
|
require.NoError(t, err)
|
|
|
|
// Create cells and proofs.
|
|
cellsPerBlob := [][]kzg.Cell{
|
|
make([]kzg.Cell, numberOfColumns),
|
|
}
|
|
proofsPerBlob := [][]kzg.Proof{
|
|
make([]kzg.Proof, numberOfColumns),
|
|
}
|
|
|
|
rob, err := blocks.NewROBlock(signedBeaconBlock)
|
|
require.NoError(t, err)
|
|
_, err = peerdas.DataColumnSidecars(cellsPerBlob, proofsPerBlob, peerdas.PopulateFromBlock(rob))
|
|
require.ErrorIs(t, err, peerdas.ErrSizeMismatch)
|
|
})
|
|
|
|
t.Run("cells array too short for column index", func(t *testing.T) {
|
|
// Create a Fulu block with a blob commitment.
|
|
signedBeaconBlockPb := util.NewBeaconBlockFulu()
|
|
signedBeaconBlockPb.Block.Body.BlobKzgCommitments = [][]byte{make([]byte, 48)}
|
|
|
|
// Create a signed beacon block from the protobuf.
|
|
signedBeaconBlock, err := blocks.NewSignedBeaconBlock(signedBeaconBlockPb)
|
|
require.NoError(t, err)
|
|
|
|
// Create cells and proofs with insufficient cells for the number of columns.
|
|
// This simulates a scenario where cellsAndProofs has fewer cells than expected columns.
|
|
cellsPerBlob := [][]kzg.Cell{
|
|
make([]kzg.Cell, 10), // Only 10 cells
|
|
}
|
|
proofsPerBlob := [][]kzg.Proof{
|
|
make([]kzg.Proof, 10), // Only 10 proofs
|
|
}
|
|
|
|
// This should fail because the function will try to access columns up to NumberOfColumns
|
|
// but we only have 10 cells/proofs.
|
|
rob, err := blocks.NewROBlock(signedBeaconBlock)
|
|
require.NoError(t, err)
|
|
_, err = peerdas.DataColumnSidecars(cellsPerBlob, proofsPerBlob, peerdas.PopulateFromBlock(rob))
|
|
require.ErrorIs(t, err, peerdas.ErrNotEnoughDataColumnSidecars)
|
|
})
|
|
|
|
t.Run("proofs array too short for column index", func(t *testing.T) {
|
|
// Create a Fulu block with a blob commitment.
|
|
signedBeaconBlockPb := util.NewBeaconBlockFulu()
|
|
signedBeaconBlockPb.Block.Body.BlobKzgCommitments = [][]byte{make([]byte, 48)}
|
|
|
|
// Create a signed beacon block from the protobuf.
|
|
signedBeaconBlock, err := blocks.NewSignedBeaconBlock(signedBeaconBlockPb)
|
|
require.NoError(t, err)
|
|
|
|
// Create cells and proofs with sufficient cells but insufficient proofs.
|
|
cellsPerBlob := [][]kzg.Cell{
|
|
make([]kzg.Cell, numberOfColumns),
|
|
}
|
|
proofsPerBlob := [][]kzg.Proof{
|
|
make([]kzg.Proof, 5), // Only 5 proofs, less than columns
|
|
}
|
|
|
|
// This should fail when trying to access proof beyond index 4.
|
|
rob, err := blocks.NewROBlock(signedBeaconBlock)
|
|
require.NoError(t, err)
|
|
_, err = peerdas.DataColumnSidecars(cellsPerBlob, proofsPerBlob, peerdas.PopulateFromBlock(rob))
|
|
require.ErrorIs(t, err, peerdas.ErrNotEnoughDataColumnSidecars)
|
|
require.ErrorContains(t, "not enough proofs", err)
|
|
})
|
|
|
|
t.Run("nominal", func(t *testing.T) {
|
|
// Create a Fulu block with blob commitments.
|
|
signedBeaconBlockPb := util.NewBeaconBlockFulu()
|
|
commitment1 := make([]byte, 48)
|
|
commitment2 := make([]byte, 48)
|
|
|
|
// Set different values to distinguish commitments
|
|
commitment1[0] = 0x01
|
|
commitment2[0] = 0x02
|
|
signedBeaconBlockPb.Block.Body.BlobKzgCommitments = [][]byte{commitment1, commitment2}
|
|
|
|
// Create a signed beacon block from the protobuf.
|
|
signedBeaconBlock, err := blocks.NewSignedBeaconBlock(signedBeaconBlockPb)
|
|
require.NoError(t, err)
|
|
|
|
// Create cells and proofs with correct dimensions.
|
|
cellsPerBlob := [][]kzg.Cell{
|
|
make([]kzg.Cell, numberOfColumns),
|
|
make([]kzg.Cell, numberOfColumns),
|
|
}
|
|
proofsPerBlob := [][]kzg.Proof{
|
|
make([]kzg.Proof, numberOfColumns),
|
|
make([]kzg.Proof, numberOfColumns),
|
|
}
|
|
|
|
// Set distinct values in cells and proofs for testing
|
|
for i := range numberOfColumns {
|
|
cellsPerBlob[0][i][0] = byte(i)
|
|
proofsPerBlob[0][i][0] = byte(i)
|
|
cellsPerBlob[1][i][0] = byte(i + 128)
|
|
proofsPerBlob[1][i][0] = byte(i + 128)
|
|
}
|
|
|
|
rob, err := blocks.NewROBlock(signedBeaconBlock)
|
|
require.NoError(t, err)
|
|
sidecars, err := peerdas.DataColumnSidecars(cellsPerBlob, proofsPerBlob, peerdas.PopulateFromBlock(rob))
|
|
require.NoError(t, err)
|
|
require.NotNil(t, sidecars)
|
|
require.Equal(t, int(numberOfColumns), len(sidecars))
|
|
|
|
// Verify each sidecar has the expected structure
|
|
for i, sidecar := range sidecars {
|
|
require.Equal(t, uint64(i), sidecar.Index)
|
|
require.Equal(t, 2, len(sidecar.Column))
|
|
require.Equal(t, 2, len(sidecar.KzgCommitments))
|
|
require.Equal(t, 2, len(sidecar.KzgProofs))
|
|
|
|
// Verify commitments match what we set
|
|
require.DeepEqual(t, commitment1, sidecar.KzgCommitments[0])
|
|
require.DeepEqual(t, commitment2, sidecar.KzgCommitments[1])
|
|
|
|
// Verify column data comes from the correct cells
|
|
require.Equal(t, byte(i), sidecar.Column[0][0])
|
|
require.Equal(t, byte(i+128), sidecar.Column[1][0])
|
|
|
|
// Verify proofs come from the correct proofs
|
|
require.Equal(t, byte(i), sidecar.KzgProofs[0][0])
|
|
require.Equal(t, byte(i+128), sidecar.KzgProofs[1][0])
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestReconstructionSource(t *testing.T) {
|
|
const numberOfColumns = fieldparams.NumberOfColumns
|
|
// Create a Fulu block with blob commitments.
|
|
signedBeaconBlockPb := util.NewBeaconBlockFulu()
|
|
commitment1 := make([]byte, 48)
|
|
commitment2 := make([]byte, 48)
|
|
|
|
// Set different values to distinguish commitments
|
|
commitment1[0] = 0x01
|
|
commitment2[0] = 0x02
|
|
signedBeaconBlockPb.Block.Body.BlobKzgCommitments = [][]byte{commitment1, commitment2}
|
|
|
|
// Create a signed beacon block from the protobuf.
|
|
signedBeaconBlock, err := blocks.NewSignedBeaconBlock(signedBeaconBlockPb)
|
|
require.NoError(t, err)
|
|
|
|
// Create cells and proofs with correct dimensions.
|
|
cellsPerBlob := [][]kzg.Cell{
|
|
make([]kzg.Cell, numberOfColumns),
|
|
make([]kzg.Cell, numberOfColumns),
|
|
}
|
|
proofsPerBlob := [][]kzg.Proof{
|
|
make([]kzg.Proof, numberOfColumns),
|
|
make([]kzg.Proof, numberOfColumns),
|
|
}
|
|
|
|
// Set distinct values in cells and proofs for testing
|
|
for i := range numberOfColumns {
|
|
cellsPerBlob[0][i][0] = byte(i)
|
|
proofsPerBlob[0][i][0] = byte(i)
|
|
cellsPerBlob[1][i][0] = byte(i + 128)
|
|
proofsPerBlob[1][i][0] = byte(i + 128)
|
|
}
|
|
|
|
rob, err := blocks.NewROBlock(signedBeaconBlock)
|
|
require.NoError(t, err)
|
|
sidecars, err := peerdas.DataColumnSidecars(cellsPerBlob, proofsPerBlob, peerdas.PopulateFromBlock(rob))
|
|
require.NoError(t, err)
|
|
require.NotNil(t, sidecars)
|
|
require.Equal(t, int(numberOfColumns), len(sidecars))
|
|
|
|
t.Run("from block", func(t *testing.T) {
|
|
src := peerdas.PopulateFromBlock(rob)
|
|
require.Equal(t, rob.Block().Slot(), src.Slot())
|
|
require.Equal(t, rob.Root(), src.Root())
|
|
require.Equal(t, rob.Block().ProposerIndex(), src.ProposerIndex())
|
|
|
|
commitments, err := src.Commitments()
|
|
require.NoError(t, err)
|
|
require.Equal(t, 2, len(commitments))
|
|
require.DeepEqual(t, commitment1, commitments[0])
|
|
require.DeepEqual(t, commitment2, commitments[1])
|
|
|
|
require.Equal(t, peerdas.BlockType, src.Type())
|
|
})
|
|
|
|
t.Run("from sidecar", func(t *testing.T) {
|
|
referenceSidecar := blocks.NewVerifiedRODataColumn(sidecars[0])
|
|
src := peerdas.PopulateFromSidecar(referenceSidecar)
|
|
require.Equal(t, referenceSidecar.Slot(), src.Slot())
|
|
require.Equal(t, referenceSidecar.BlockRoot(), src.Root())
|
|
require.Equal(t, referenceSidecar.ProposerIndex(), src.ProposerIndex())
|
|
|
|
commitments, err := src.Commitments()
|
|
require.NoError(t, err)
|
|
require.Equal(t, 2, len(commitments))
|
|
require.DeepEqual(t, commitment1, commitments[0])
|
|
require.DeepEqual(t, commitment2, commitments[1])
|
|
|
|
require.Equal(t, peerdas.SidecarType, src.Type())
|
|
})
|
|
}
|