Compare commits

...

7 Commits

Author SHA1 Message Date
kasey
41e7607092 Decrease att batch deadline to 5ms for faster net prop (#15882)
Co-authored-by: Kasey Kirkham <kasey@users.noreply.github.com>
2025-10-16 17:30:59 +00:00
Jun Song
cd429dc253 SSZ-QL: Access n-th element in List/Vector. (#15767)
* Add basic parsing feature for accessing by index

* Add more tests for 2d byte vector

* Add List case for access indexing

* Handle 2D bytes List example

* Fix misleading cases for CalculateOffsetAndLength

* Use elementSizes[index] if it is the last path element

* Add variable_container_list field for mocking attester_slashings in BeaconBlockBody

* Remove redundant protobuf message

* Better documentation

* Changelog

* Fix `expectedSize` of `VariableTestContainer`: as we added `variable_container_list` here

* Apply reviews from Radek
2025-10-15 16:11:12 +00:00
phrwlk
5ced1125f2 fix: reject out-of-range attestation committee index (#15855)
* reject committee index >= committees_per_slot in unaggregated attestation validation

* Create phrwlk_fix-attestation-committee-index-bound.md

* add a unit test

* fix test

* fixing test

---------

Co-authored-by: james-prysm <90280386+james-prysm@users.noreply.github.com>
Co-authored-by: james-prysm <james@prysmaticlabs.com>
2025-10-15 16:02:08 +00:00
Potuz
f67ca6ae5e Fix epoch transition on head event (#15871)
h/t to the NuConstruct team for reporting this. The event feed
incorrectly sends epoch transition flag on head events when the first
slot of the epoch is missing (or reorgs across epoch transition).

Co-authored-by: james-prysm <90280386+james-prysm@users.noreply.github.com>
2025-10-15 15:13:49 +00:00
Manu NALEPA
9742333f68 WithDataColumnRetentionEpochs: Use dataColumnRetentionEpoch instead of blobColumnRetentionEpoch. (#15872) 2025-10-15 14:44:49 +00:00
Manu NALEPA
c811fadf33 VerifyDataColumnSidecar: Check if there is no too many commitments. (#15859)
* `VerifyDataColumnSidecar`: Check if there is no too many commitments.

* `TestVerifyDataColumnSidecar`: Refactor using test cases.

* Add changelog.
2025-10-15 12:18:04 +00:00
Manu NALEPA
55b9448d41 dataColumnSidecarsByRangeRPCHandler: Gracefully close the stream if no data to return. (#15866)
* `TestDataColumnSidecarsByRangeRPCHandler`: Remove commented code.

* Remove double import

* `dataColumnSidecarsByRangeRPCHandler`: Gracefully close the stream if no data to return.

* Tests: Change `require` to `assert` in goroutines in tests.

https://pkg.go.dev/github.com/stretchr/testify/require#hdr-Assertions

* Add changelog.
2025-10-15 12:16:05 +00:00
30 changed files with 978 additions and 166 deletions

View File

@@ -346,13 +346,24 @@ func (s *Service) notifyNewHeadEvent(
if err != nil {
return errors.Wrap(err, "could not check if node is optimistically synced")
}
parentRoot, err := s.ParentRoot([32]byte(newHeadRoot))
if err != nil {
return errors.Wrap(err, "could not obtain parent root in forkchoice")
}
parentSlot, err := s.RecentBlockSlot(parentRoot)
if err != nil {
return errors.Wrap(err, "could not obtain parent slot in forkchoice")
}
epochTransition := slots.ToEpoch(newHeadSlot) > slots.ToEpoch(parentSlot)
s.cfg.StateNotifier.StateFeed().Send(&feed.Event{
Type: statefeed.NewHead,
Data: &ethpbv1.EventHead{
Slot: newHeadSlot,
Block: newHeadRoot,
State: newHeadStateRoot,
EpochTransition: slots.IsEpochStart(newHeadSlot),
EpochTransition: epochTransition,
PreviousDutyDependentRoot: previousDutyDependentRoot[:],
CurrentDutyDependentRoot: currentDutyDependentRoot[:],
ExecutionOptimistic: isOptimistic,

View File

@@ -162,6 +162,9 @@ func Test_notifyNewHeadEvent(t *testing.T) {
require.NoError(t, srv.cfg.ForkChoiceStore.InsertNode(t.Context(), st, blk))
newHeadStateRoot := [32]byte{2}
newHeadRoot := [32]byte{3}
st, blk, err = prepareForkchoiceState(t.Context(), 1, newHeadRoot, [32]byte{}, [32]byte{}, &ethpb.Checkpoint{}, &ethpb.Checkpoint{})
require.NoError(t, err)
require.NoError(t, srv.cfg.ForkChoiceStore.InsertNode(t.Context(), st, blk))
require.NoError(t, srv.notifyNewHeadEvent(t.Context(), 1, bState, newHeadStateRoot[:], newHeadRoot[:]))
events := notifier.ReceivedEvents()
require.Equal(t, 1, len(events))
@@ -196,6 +199,9 @@ func Test_notifyNewHeadEvent(t *testing.T) {
newHeadStateRoot := [32]byte{2}
newHeadRoot := [32]byte{3}
st, blk, err = prepareForkchoiceState(t.Context(), 0, newHeadRoot, [32]byte{}, [32]byte{}, &ethpb.Checkpoint{}, &ethpb.Checkpoint{})
require.NoError(t, err)
require.NoError(t, srv.cfg.ForkChoiceStore.InsertNode(t.Context(), st, blk))
err = srv.notifyNewHeadEvent(t.Context(), epoch2Start, bState, newHeadStateRoot[:], newHeadRoot[:])
require.NoError(t, err)
events := notifier.ReceivedEvents()
@@ -213,6 +219,37 @@ func Test_notifyNewHeadEvent(t *testing.T) {
}
require.DeepSSZEqual(t, wanted, eventHead)
})
t.Run("epoch transition", func(t *testing.T) {
bState, _ := util.DeterministicGenesisState(t, 10)
srv := testServiceWithDB(t)
srv.SetGenesisTime(time.Now())
notifier := srv.cfg.StateNotifier.(*mock.MockStateNotifier)
srv.originBlockRoot = [32]byte{1}
st, blk, err := prepareForkchoiceState(t.Context(), 0, [32]byte{}, [32]byte{}, [32]byte{}, &ethpb.Checkpoint{}, &ethpb.Checkpoint{})
require.NoError(t, err)
require.NoError(t, srv.cfg.ForkChoiceStore.InsertNode(t.Context(), st, blk))
newHeadStateRoot := [32]byte{2}
newHeadRoot := [32]byte{3}
st, blk, err = prepareForkchoiceState(t.Context(), 32, newHeadRoot, [32]byte{}, [32]byte{}, &ethpb.Checkpoint{}, &ethpb.Checkpoint{})
require.NoError(t, err)
require.NoError(t, srv.cfg.ForkChoiceStore.InsertNode(t.Context(), st, blk))
newHeadSlot := params.BeaconConfig().SlotsPerEpoch
require.NoError(t, srv.notifyNewHeadEvent(t.Context(), newHeadSlot, bState, newHeadStateRoot[:], newHeadRoot[:]))
events := notifier.ReceivedEvents()
require.Equal(t, 1, len(events))
eventHead, ok := events[0].Data.(*ethpbv1.EventHead)
require.Equal(t, true, ok)
wanted := &ethpbv1.EventHead{
Slot: newHeadSlot,
Block: newHeadRoot[:],
State: newHeadStateRoot[:],
EpochTransition: true,
PreviousDutyDependentRoot: params.BeaconConfig().ZeroHash[:],
CurrentDutyDependentRoot: srv.originBlockRoot[:],
}
require.DeepSSZEqual(t, wanted, eventHead)
})
}
func TestRetrieveHead_ReadOnly(t *testing.T) {

View File

@@ -43,6 +43,13 @@ func VerifyDataColumnSidecar(sidecar blocks.RODataColumn) error {
return ErrNoKzgCommitments
}
// A sidecar with more commitments than the max blob count for this block is invalid.
slot := sidecar.Slot()
maxBlobsPerBlock := params.BeaconConfig().MaxBlobsPerBlock(slot)
if len(sidecar.KzgCommitments) > maxBlobsPerBlock {
return ErrTooManyCommitments
}
// The column length must be equal to the number of commitments/proofs.
if len(sidecar.Column) != len(sidecar.KzgCommitments) || len(sidecar.Column) != len(sidecar.KzgProofs) {
return ErrMismatchLength

View File

@@ -18,38 +18,46 @@ import (
)
func TestVerifyDataColumnSidecar(t *testing.T) {
t.Run("index too large", func(t *testing.T) {
roSidecar := createTestSidecar(t, 1_000_000, nil, nil, nil)
err := peerdas.VerifyDataColumnSidecar(roSidecar)
require.ErrorIs(t, err, peerdas.ErrIndexTooLarge)
})
testCases := []struct {
name string
index uint64
blobCount int
commitmentCount int
proofCount int
maxBlobsPerBlock uint64
expectedError error
}{
{name: "index too large", index: 1_000_000, expectedError: peerdas.ErrIndexTooLarge},
{name: "no commitments", expectedError: peerdas.ErrNoKzgCommitments},
{name: "too many commitments", blobCount: 10, commitmentCount: 10, proofCount: 10, maxBlobsPerBlock: 2, expectedError: peerdas.ErrTooManyCommitments},
{name: "commitments size mismatch", commitmentCount: 1, maxBlobsPerBlock: 1, expectedError: peerdas.ErrMismatchLength},
{name: "proofs size mismatch", blobCount: 1, commitmentCount: 1, maxBlobsPerBlock: 1, expectedError: peerdas.ErrMismatchLength},
{name: "nominal", blobCount: 1, commitmentCount: 1, proofCount: 1, maxBlobsPerBlock: 1, expectedError: nil},
}
t.Run("no commitments", func(t *testing.T) {
roSidecar := createTestSidecar(t, 0, nil, nil, nil)
err := peerdas.VerifyDataColumnSidecar(roSidecar)
require.ErrorIs(t, err, peerdas.ErrNoKzgCommitments)
})
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
params.SetupTestConfigCleanup(t)
cfg := params.BeaconConfig()
cfg.FuluForkEpoch = 0
cfg.BlobSchedule = []params.BlobScheduleEntry{{Epoch: 0, MaxBlobsPerBlock: tc.maxBlobsPerBlock}}
params.OverrideBeaconConfig(cfg)
t.Run("KZG commitments size mismatch", func(t *testing.T) {
kzgCommitments := make([][]byte, 1)
roSidecar := createTestSidecar(t, 0, nil, kzgCommitments, nil)
err := peerdas.VerifyDataColumnSidecar(roSidecar)
require.ErrorIs(t, err, peerdas.ErrMismatchLength)
})
column := make([][]byte, tc.blobCount)
kzgCommitments := make([][]byte, tc.commitmentCount)
kzgProof := make([][]byte, tc.proofCount)
t.Run("KZG proofs size mismatch", func(t *testing.T) {
column, kzgCommitments := make([][]byte, 1), make([][]byte, 1)
roSidecar := createTestSidecar(t, 0, column, kzgCommitments, nil)
err := peerdas.VerifyDataColumnSidecar(roSidecar)
require.ErrorIs(t, err, peerdas.ErrMismatchLength)
})
roSidecar := createTestSidecar(t, tc.index, column, kzgCommitments, kzgProof)
err := peerdas.VerifyDataColumnSidecar(roSidecar)
t.Run("nominal", func(t *testing.T) {
column, kzgCommitments, kzgProofs := make([][]byte, 1), make([][]byte, 1), make([][]byte, 1)
roSidecar := createTestSidecar(t, 0, column, kzgCommitments, kzgProofs)
err := peerdas.VerifyDataColumnSidecar(roSidecar)
require.NoError(t, err)
})
if tc.expectedError != nil {
require.ErrorIs(t, err, tc.expectedError)
return
}
require.NoError(t, err)
})
}
}
func TestVerifyDataColumnSidecarKZGProofs(t *testing.T) {

View File

@@ -1032,5 +1032,5 @@ func extractFileMetadata(path string) (*fileMetadata, error) {
// period computes the period of a given epoch.
func period(epoch primitives.Epoch) uint64 {
return uint64(epoch / params.BeaconConfig().MinEpochsForBlobsSidecarsRequest)
return uint64(epoch / params.BeaconConfig().MinEpochsForDataColumnSidecarsRequest)
}

View File

@@ -126,7 +126,7 @@ func NewWarmedEphemeralDataColumnStorageUsingFs(t testing.TB, fs afero.Fs, opts
func NewEphemeralDataColumnStorageUsingFs(t testing.TB, fs afero.Fs, opts ...DataColumnStorageOption) *DataColumnStorage {
opts = append(opts,
WithDataColumnRetentionEpochs(params.BeaconConfig().MinEpochsForBlobsSidecarsRequest),
WithDataColumnRetentionEpochs(params.BeaconConfig().MinEpochsForDataColumnSidecarsRequest),
WithDataColumnFs(fs),
)

View File

@@ -14,7 +14,7 @@ import (
"github.com/pkg/errors"
)
const signatureVerificationInterval = 50 * time.Millisecond
const signatureVerificationInterval = 5 * time.Millisecond
type signatureVerifier struct {
set *bls.SignatureBatch

View File

@@ -45,6 +45,7 @@ func TestFetchDataColumnSidecars(t *testing.T) {
params.SetupTestConfigCleanup(t)
cfg := params.BeaconConfig().Copy()
cfg.FuluForkEpoch = 0
cfg.BlobSchedule = []params.BlobScheduleEntry{{Epoch: 0, MaxBlobsPerBlock: 10}}
params.OverrideBeaconConfig(cfg)
// Start the trusted setup.
@@ -760,6 +761,12 @@ func TestVerifyDataColumnSidecarsByPeer(t *testing.T) {
err := kzg.Start()
require.NoError(t, err)
params.SetupTestConfigCleanup(t)
cfg := params.BeaconConfig()
cfg.FuluForkEpoch = 0
cfg.BlobSchedule = []params.BlobScheduleEntry{{Epoch: 0, MaxBlobsPerBlock: 2}}
params.OverrideBeaconConfig(cfg)
t.Run("nominal", func(t *testing.T) {
const (
start, stop = 0, 15

View File

@@ -683,6 +683,7 @@ func TestFetchOriginColumns(t *testing.T) {
params.SetupTestConfigCleanup(t)
cfg := params.BeaconConfig().Copy()
cfg.FuluForkEpoch = 0
cfg.BlobSchedule = []params.BlobScheduleEntry{{Epoch: 0, MaxBlobsPerBlock: 10}}
params.OverrideBeaconConfig(cfg)
const (

View File

@@ -70,6 +70,7 @@ func (s *Service) dataColumnSidecarsByRangeRPCHandler(ctx context.Context, msg i
log.Trace("Serving data column sidecars by range")
if rangeParameters == nil {
closeStream(stream, log)
return nil
}

View File

@@ -23,16 +23,15 @@ import (
fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams"
"github.com/OffchainLabs/prysm/v6/config/params"
"github.com/OffchainLabs/prysm/v6/consensus-types/blocks"
consensusblocks "github.com/OffchainLabs/prysm/v6/consensus-types/blocks"
"github.com/OffchainLabs/prysm/v6/consensus-types/primitives"
pb "github.com/OffchainLabs/prysm/v6/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v6/testing/assert"
"github.com/OffchainLabs/prysm/v6/testing/util"
)
func TestDataColumnSidecarsByRangeRPCHandler(t *testing.T) {
params.SetupTestConfigCleanup(t)
beaconConfig := params.BeaconConfig()
//beaconConfig.FuluForkEpoch = beaconConfig.ElectraForkEpoch + 100
beaconConfig.FuluForkEpoch = 0
params.OverrideBeaconConfig(beaconConfig)
params.BeaconConfig().InitializeForkSchedule()
@@ -47,6 +46,7 @@ func TestDataColumnSidecarsByRangeRPCHandler(t *testing.T) {
ctxMap, err := ContextByteVersionsForValRoot(params.BeaconConfig().GenesisValidatorsRoot)
require.NoError(t, err)
t.Run("invalid request", func(t *testing.T) {
slot := primitives.Slot(400)
mockNower.SetSlot(t, clock, slot)
@@ -72,8 +72,8 @@ func TestDataColumnSidecarsByRangeRPCHandler(t *testing.T) {
remoteP2P.BHost.SetStreamHandler(protocolID, func(stream network.Stream) {
defer wg.Done()
code, _, err := readStatusCodeNoDeadline(stream, localP2P.Encoding())
require.NoError(t, err)
require.Equal(t, responseCodeInvalidRequest, code)
assert.NoError(t, err)
assert.Equal(t, responseCodeInvalidRequest, code)
})
localP2P.Connect(remoteP2P)
@@ -94,6 +94,48 @@ func TestDataColumnSidecarsByRangeRPCHandler(t *testing.T) {
}
})
t.Run("in the future", func(t *testing.T) {
slot := primitives.Slot(400)
mockNower.SetSlot(t, clock, slot)
localP2P, remoteP2P := p2ptest.NewTestP2P(t), p2ptest.NewTestP2P(t)
protocolID := protocol.ID(fmt.Sprintf("%s/ssz_snappy", p2p.RPCDataColumnSidecarsByRangeTopicV1))
service := &Service{
cfg: &config{
p2p: localP2P,
chain: &chainMock.ChainService{
Slot: &slot,
},
clock: clock,
},
rateLimiter: newRateLimiter(localP2P),
}
var wg sync.WaitGroup
wg.Add(1)
remoteP2P.BHost.SetStreamHandler(protocolID, func(stream network.Stream) {
defer wg.Done()
_, err := readChunkedDataColumnSidecar(stream, remoteP2P, ctxMap)
assert.Equal(t, true, errors.Is(err, io.EOF))
})
localP2P.Connect(remoteP2P)
stream, err := localP2P.BHost.NewStream(ctx, remoteP2P.BHost.ID(), protocolID)
require.NoError(t, err)
msg := &pb.DataColumnSidecarsByRangeRequest{
StartSlot: slot + 1,
Count: 50,
Columns: []uint64{1, 2, 3, 4, 6, 7, 8, 9, 10},
}
err = service.dataColumnSidecarsByRangeRPCHandler(ctx, msg, stream)
require.NoError(t, err)
})
t.Run("nominal", func(t *testing.T) {
slot := primitives.Slot(400)
@@ -133,12 +175,12 @@ func TestDataColumnSidecarsByRangeRPCHandler(t *testing.T) {
signedBeaconBlockPb.Block.ParentRoot = roots[i-1][:]
}
signedBeaconBlock, err := consensusblocks.NewSignedBeaconBlock(signedBeaconBlockPb)
signedBeaconBlock, err := blocks.NewSignedBeaconBlock(signedBeaconBlockPb)
require.NoError(t, err)
// There is a discrepancy between the root of the beacon block and the rodata column root,
// but for the sake of this test, we actually don't care.
roblock, err := consensusblocks.NewROBlockWithRoot(signedBeaconBlock, roots[i])
roblock, err := blocks.NewROBlockWithRoot(signedBeaconBlock, roots[i])
require.NoError(t, err)
roBlocks = append(roBlocks, roblock)
@@ -178,28 +220,28 @@ func TestDataColumnSidecarsByRangeRPCHandler(t *testing.T) {
break
}
require.NoError(t, err)
assert.NoError(t, err)
sidecars = append(sidecars, sidecar)
}
require.Equal(t, 8, len(sidecars))
require.Equal(t, root0, sidecars[0].BlockRoot())
require.Equal(t, root0, sidecars[1].BlockRoot())
require.Equal(t, root0, sidecars[2].BlockRoot())
require.Equal(t, root3, sidecars[3].BlockRoot())
require.Equal(t, root3, sidecars[4].BlockRoot())
require.Equal(t, root5, sidecars[5].BlockRoot())
require.Equal(t, root5, sidecars[6].BlockRoot())
require.Equal(t, root5, sidecars[7].BlockRoot())
assert.Equal(t, 8, len(sidecars))
assert.Equal(t, root0, sidecars[0].BlockRoot())
assert.Equal(t, root0, sidecars[1].BlockRoot())
assert.Equal(t, root0, sidecars[2].BlockRoot())
assert.Equal(t, root3, sidecars[3].BlockRoot())
assert.Equal(t, root3, sidecars[4].BlockRoot())
assert.Equal(t, root5, sidecars[5].BlockRoot())
assert.Equal(t, root5, sidecars[6].BlockRoot())
assert.Equal(t, root5, sidecars[7].BlockRoot())
require.Equal(t, uint64(1), sidecars[0].Index)
require.Equal(t, uint64(2), sidecars[1].Index)
require.Equal(t, uint64(3), sidecars[2].Index)
require.Equal(t, uint64(4), sidecars[3].Index)
require.Equal(t, uint64(6), sidecars[4].Index)
require.Equal(t, uint64(7), sidecars[5].Index)
require.Equal(t, uint64(8), sidecars[6].Index)
require.Equal(t, uint64(9), sidecars[7].Index)
assert.Equal(t, uint64(1), sidecars[0].Index)
assert.Equal(t, uint64(2), sidecars[1].Index)
assert.Equal(t, uint64(3), sidecars[2].Index)
assert.Equal(t, uint64(4), sidecars[3].Index)
assert.Equal(t, uint64(6), sidecars[4].Index)
assert.Equal(t, uint64(7), sidecars[5].Index)
assert.Equal(t, uint64(8), sidecars[6].Index)
assert.Equal(t, uint64(9), sidecars[7].Index)
})
localP2P.Connect(remoteP2P)
@@ -215,7 +257,6 @@ func TestDataColumnSidecarsByRangeRPCHandler(t *testing.T) {
err = service.dataColumnSidecarsByRangeRPCHandler(ctx, msg, stream)
require.NoError(t, err)
})
}
func TestValidateDataColumnsByRange(t *testing.T) {

View File

@@ -94,9 +94,11 @@ func TestVerifyIndexInCommittee_ExistsInBeaconCommittee(t *testing.T) {
assert.ErrorContains(t, wanted, err)
assert.Equal(t, pubsub.ValidationReject, result)
att.Data.CommitteeIndex = 10000
// Test the edge case where committee index equals count (should be rejected)
// With 64 validators and minimal config, count = 2, so valid indices are 0 and 1
att.Data.CommitteeIndex = 2
_, _, result, err = service.validateCommitteeIndexAndCount(ctx, att, s)
require.ErrorContains(t, "committee index 10000 > 2", err)
require.ErrorContains(t, "committee index 2 >= 2", err)
assert.Equal(t, pubsub.ValidationReject, result)
}

View File

@@ -278,8 +278,8 @@ func (s *Service) validateCommitteeIndexAndCount(
} else {
ci = a.GetCommitteeIndex()
}
if uint64(ci) > count {
return 0, 0, pubsub.ValidationReject, fmt.Errorf("committee index %d > %d", ci, count)
if uint64(ci) >= count {
return 0, 0, pubsub.ValidationReject, fmt.Errorf("committee index %d >= %d", ci, count)
}
return ci, valCount, pubsub.ValidationAccept, nil
}

View File

@@ -611,3 +611,41 @@ func TestService_setSeenUnaggregatedAtt(t *testing.T) {
})
})
}
func Test_validateCommitteeIndexAndCount_Boundary(t *testing.T) {
ctx := t.Context()
// Create a minimal state with a known number of validators.
validators := uint64(64)
bs, _ := util.DeterministicGenesisState(t, validators)
require.NoError(t, bs.SetSlot(1))
s := &Service{}
// Build a minimal Phase0 attestation (unaggregated path).
att := &ethpb.Attestation{
Data: &ethpb.AttestationData{
Slot: 1,
CommitteeIndex: 0,
},
}
// First call to obtain the active validator count used to derive committees per slot.
_, valCount, res, err := s.validateCommitteeIndexAndCount(ctx, att, bs)
require.NoError(t, err)
require.Equal(t, pubsub.ValidationAccept, res)
count := helpers.SlotCommitteeCount(valCount)
// committee_index == count - 1 should be accepted.
att.Data.CommitteeIndex = primitives.CommitteeIndex(count - 1)
_, _, res, err = s.validateCommitteeIndexAndCount(ctx, att, bs)
require.NoError(t, err)
require.Equal(t, pubsub.ValidationAccept, res)
// committee_index == count should be rejected (out of range).
att.Data.CommitteeIndex = primitives.CommitteeIndex(count)
_, _, res, err = s.validateCommitteeIndexAndCount(ctx, att, bs)
require.ErrorContains(t, "committee index", err)
require.Equal(t, pubsub.ValidationReject, res)
}

View File

@@ -58,7 +58,6 @@ func TestValid(t *testing.T) {
t.Run("one invalid column", func(t *testing.T) {
columns := GenerateTestDataColumns(t, [fieldparams.RootLength]byte{}, 1, 1)
columns[0].KzgCommitments = [][]byte{}
verifier := initializer.NewDataColumnsVerifier(columns, GossipDataColumnSidecarRequirements)
err := verifier.ValidFields()
@@ -67,6 +66,14 @@ func TestValid(t *testing.T) {
})
t.Run("nominal", func(t *testing.T) {
const maxBlobsPerBlock = 2
params.SetupTestConfigCleanup(t)
cfg := params.BeaconConfig()
cfg.FuluForkEpoch = 0
cfg.BlobSchedule = []params.BlobScheduleEntry{{Epoch: 0, MaxBlobsPerBlock: maxBlobsPerBlock}}
params.OverrideBeaconConfig(cfg)
columns := GenerateTestDataColumns(t, [fieldparams.RootLength]byte{}, 1, 1)
verifier := initializer.NewDataColumnsVerifier(columns, GossipDataColumnSidecarRequirements)

View File

@@ -0,0 +1,2 @@
### Fixed
- Decreased attestation gossip validation batch deadline to 5ms.

View File

@@ -0,0 +1,2 @@
### Fixed
- `VerifyDataColumnSidecar`: Check if there is no too many commitments.

View File

@@ -0,0 +1,2 @@
### Fixed
- `WithDataColumnRetentionEpochs`: Use `dataColumnRetentionEpoch` instead of `blobColumnRetentionEpoch`.

View File

@@ -0,0 +1,2 @@
### Fixed
- `dataColumnSidecarsByRangeRPCHandler`: Gracefully close the stream if no data to return.

View File

@@ -0,0 +1,3 @@
### Fixed
- reject committee index >= committees_per_slot in unaggregated attestation validation

View File

@@ -0,0 +1,3 @@
### Fixed
- Mark epoch transition correctly on new head events

View File

@@ -0,0 +1,3 @@
### Added
- SSZ-QL: Access n-th element in `List`/`Vector`.

View File

@@ -68,8 +68,13 @@ func BeaconNodeOptions(c *cli.Context) ([]node.Option, error) {
filesystem.WithLayout(c.String(BlobStorageLayout.Name)), // This is validated in the Action func for BlobStorageLayout.
)
dataColumnRetentionEpoch, err := dataColumnRetentionEpoch(c)
if err != nil {
return nil, errors.Wrap(err, "data column retention epoch")
}
dataColumnStorageOption := node.WithDataColumnStorageOptions(
filesystem.WithDataColumnRetentionEpochs(blobRetentionEpoch),
filesystem.WithDataColumnRetentionEpochs(dataColumnRetentionEpoch),
filesystem.WithDataColumnBasePath(dataColumnStoragePath(c)),
)
@@ -116,6 +121,26 @@ func blobRetentionEpoch(cliCtx *cli.Context) (primitives.Epoch, error) {
return re, nil
}
// dataColumnRetentionEpoch returns the spec default MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUEST
// or a user-specified flag overriding this value. If a user-specified override is
// smaller than the spec default, an error will be returned.
func dataColumnRetentionEpoch(cliCtx *cli.Context) (primitives.Epoch, error) {
defaultValue := params.BeaconConfig().MinEpochsForDataColumnSidecarsRequest
if !cliCtx.IsSet(BlobRetentionEpochFlag.Name) {
return defaultValue, nil
}
// We use on purpose the same retention flag for both blobs and data columns.
customValue := primitives.Epoch(cliCtx.Uint64(BlobRetentionEpochFlag.Name))
// Validate the epoch value against the spec default.
if customValue < defaultValue {
return defaultValue, errors.Wrapf(errInvalidBlobRetentionEpochs, "%s=%d, spec=%d", BlobRetentionEpochFlag.Name, customValue, defaultValue)
}
return customValue, nil
}
func init() {
BlobStorageLayout.Action = validateLayoutFlag
}

View File

@@ -61,6 +61,45 @@ func TestConfigureBlobRetentionEpoch(t *testing.T) {
_, err = blobRetentionEpoch(cliCtx)
require.ErrorIs(t, err, errInvalidBlobRetentionEpochs)
}
func TestConfigureDataColumnRetentionEpoch(t *testing.T) {
specValue := params.BeaconConfig().MinEpochsForDataColumnSidecarsRequest
app := cli.App{}
set := flag.NewFlagSet("test", 0)
cliCtx := cli.NewContext(&app, set, nil)
// Test case: Specification value
expected := specValue
actual, err := dataColumnRetentionEpoch(cliCtx)
require.NoError(t, err)
require.Equal(t, expected, actual)
// Manually define the flag in the set, so the following code can use set.Set
set.Uint64(BlobRetentionEpochFlag.Name, 0, "")
// Test case: Input epoch is greater than or equal to specification value.
expected = specValue + 1
err = set.Set(BlobRetentionEpochFlag.Name, fmt.Sprintf("%d", expected))
require.NoError(t, err)
actual, err = dataColumnRetentionEpoch(cliCtx)
require.NoError(t, err)
require.Equal(t, primitives.Epoch(expected), actual)
// Test case: Input epoch is less than specification value.
expected = specValue - 1
err = set.Set(BlobRetentionEpochFlag.Name, fmt.Sprintf("%d", expected))
require.NoError(t, err)
actual, err = dataColumnRetentionEpoch(cliCtx)
require.ErrorIs(t, err, errInvalidBlobRetentionEpochs)
require.Equal(t, specValue, actual)
}
func TestDataColumnStoragePath_FlagSpecified(t *testing.T) {
app := cli.App{}
set := flag.NewFlagSet("test", 0)

View File

@@ -2,12 +2,16 @@ package query
import (
"errors"
"fmt"
"strconv"
"strings"
)
// PathElement represents a single element in a path.
type PathElement struct {
Name string
// [Optional] Index for List/Vector elements
Index *uint64
}
func ParsePath(rawPath string) ([]PathElement, error) {
@@ -24,7 +28,34 @@ func ParsePath(rawPath string) ([]PathElement, error) {
var path []PathElement
for _, elem := range rawElements {
path = append(path, PathElement{Name: elem})
if elem == "" {
return nil, errors.New("invalid path: consecutive dots or trailing dot")
}
fieldName := elem
var index *uint64
// Check for index notation, e.g., "field[0]"
if strings.Contains(elem, "[") {
parts := strings.SplitN(elem, "[", 2)
if len(parts) != 2 {
return nil, fmt.Errorf("invalid index notation in path element %s", elem)
}
fieldName = parts[0]
indexPart := strings.TrimSuffix(parts[1], "]")
if indexPart == "" {
return nil, errors.New("index cannot be empty")
}
indexValue, err := strconv.ParseUint(indexPart, 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid index in path element %s: %w", elem, err)
}
index = &indexValue
}
path = append(path, PathElement{Name: fieldName, Index: index})
}
return path, nil

View File

@@ -19,7 +19,7 @@ func CalculateOffsetAndLength(sszInfo *sszInfo, path []PathElement) (*sszInfo, u
walk := sszInfo
offset := uint64(0)
for _, elem := range path {
for pathIndex, elem := range path {
containerInfo, err := walk.ContainerInfo()
if err != nil {
return nil, 0, 0, fmt.Errorf("could not get field infos: %w", err)
@@ -32,6 +32,51 @@ func CalculateOffsetAndLength(sszInfo *sszInfo, path []PathElement) (*sszInfo, u
offset += fieldInfo.offset
walk = fieldInfo.sszInfo
// Check for accessing List/Vector elements by index
if elem.Index != nil {
switch walk.sszType {
case List:
index := *elem.Index
listInfo := walk.listInfo
if index >= listInfo.length {
return nil, 0, 0, fmt.Errorf("index %d out of bounds for field %s with size %d", index, elem.Name, listInfo.length)
}
walk = listInfo.element
if walk.isVariable {
// Cumulative sum of sizes of previous elements to get the offset.
for i := range index {
offset += listInfo.elementSizes[i]
}
// NOTE: When populating recursively, the shared element template is updated for each
// list item, causing it to retain the size information of the last processed element.
// This wouldn't be an issue if this is in the middle of the path, as the walk would be updated
// to the next field's sszInfo, which would have the correct size information.
// However, if this is the last element in the path, we need to ensure we return the correct size
// for the indexed element. Hence, we return the size from elementSizes.
if pathIndex == len(path)-1 {
return walk, offset, listInfo.elementSizes[index], nil
}
} else {
offset += index * listInfo.element.Size()
}
case Vector:
index := *elem.Index
vectorInfo := walk.vectorInfo
if index >= vectorInfo.length {
return nil, 0, 0, fmt.Errorf("index %d out of bounds for field %s with size %d", index, elem.Name, vectorInfo.length)
}
offset += index * vectorInfo.element.Size()
walk = vectorInfo.element
default:
return nil, 0, 0, fmt.Errorf("field %s of type %s does not support index access", elem.Name, walk.sszType)
}
}
}
return walk, offset, walk.Size(), nil

View File

@@ -25,7 +25,7 @@ func TestSize(t *testing.T) {
{
name: "VariableTestContainer",
obj: &sszquerypb.VariableTestContainer{},
expectedSize: 128,
expectedSize: 132,
},
}
@@ -102,6 +102,19 @@ func TestCalculateOffsetAndLength(t *testing.T) {
expectedOffset: 85,
expectedLength: 192, // 24 * 8 bytes
},
// Accessing an element in the vector
{
name: "vector field (0th element)",
path: ".vector_field[0]",
expectedOffset: 85,
expectedLength: 8,
},
{
name: "vector field (10th element)",
path: ".vector_field[10]",
expectedOffset: 165,
expectedLength: 8,
},
// 2D bytes field
{
name: "two_dimension_bytes_field",
@@ -109,6 +122,13 @@ func TestCalculateOffsetAndLength(t *testing.T) {
expectedOffset: 277,
expectedLength: 160, // 5 * 32 bytes
},
// Accessing an element in the 2D bytes field
{
name: "two_dimension_bytes_field (1st element)",
path: ".two_dimension_bytes_field[1]",
expectedOffset: 309,
expectedLength: 32,
},
// Bitvector fields
{
name: "bitvector64_field",
@@ -161,26 +181,53 @@ func TestCalculateOffsetAndLength(t *testing.T) {
{
name: "field_list_uint64",
path: ".field_list_uint64",
expectedOffset: 112, // First part of variable-sized type.
expectedOffset: 116, // First part of variable-sized type.
expectedLength: 40, // 5 elements * uint64 (8 bytes each)
},
// Accessing an element in the list
{
name: "field_list_uint64 (2nd element)",
path: ".field_list_uint64[2]",
expectedOffset: 132,
expectedLength: 8,
},
{
name: "field_list_container",
path: ".field_list_container",
expectedOffset: 152, // Second part of variable-sized type.
expectedOffset: 156, // Second part of variable-sized type.
expectedLength: 120, // 3 elements * FixedNestedContainer (40 bytes each)
},
// Accessing an element in the list of containers
{
name: "field_list_container (1st element)",
path: ".field_list_container[1]",
expectedOffset: 196,
expectedLength: 40,
},
{
name: "field_list_bytes32",
path: ".field_list_bytes32",
expectedOffset: 272,
expectedOffset: 276,
expectedLength: 96, // 3 elements * 32 bytes each
},
// Accessing an element in the list of bytes32
{
name: "field_list_bytes32 (0th element)",
path: ".field_list_bytes32[0]",
expectedOffset: 276,
expectedLength: 32,
},
{
name: "field_list_bytes32 (2nd element)",
path: ".field_list_bytes32[2]",
expectedOffset: 340,
expectedLength: 32,
},
// Nested paths
{
name: "nested",
path: ".nested",
expectedOffset: 368,
expectedOffset: 372,
// Calculated with:
// - Value1: 8 bytes
// - field_list_uint64 offset: 4 bytes
@@ -194,40 +241,85 @@ func TestCalculateOffsetAndLength(t *testing.T) {
{
name: "nested.value1",
path: ".nested.value1",
expectedOffset: 368,
expectedOffset: 372,
expectedLength: 8,
},
{
name: "nested.field_list_uint64",
path: ".nested.field_list_uint64",
expectedOffset: 384,
expectedOffset: 388,
expectedLength: 40,
},
{
name: "nested.field_list_uint64 (3rd element)",
path: ".nested.field_list_uint64[3]",
expectedOffset: 412,
expectedLength: 8,
},
{
name: "nested.nested_list_field",
path: ".nested.nested_list_field",
expectedOffset: 436,
expectedOffset: 440,
expectedLength: 99,
},
// Accessing an element in the nested list of bytes
{
name: "nested.nested_list_field (1st element)",
path: ".nested.nested_list_field[1]",
expectedOffset: 472,
expectedLength: 33,
},
{
name: "nested.nested_list_field (2nd element)",
path: ".nested.nested_list_field[2]",
expectedOffset: 505,
expectedLength: 34,
},
// Variable list of variable-sized containers
{
name: "variable_container_list",
path: ".variable_container_list",
expectedOffset: 547,
expectedLength: 604,
},
// Bitlist field
{
name: "bitlist_field",
path: ".bitlist_field",
expectedOffset: 535,
expectedOffset: 1151,
expectedLength: 33, // 32 bytes + 1 byte for length delimiter
},
// 2D bytes field
{
name: "nested_list_field",
path: ".nested_list_field",
expectedOffset: 580,
expectedOffset: 1196,
expectedLength: 99,
},
// Accessing an element in the list of nested bytes
{
name: "nested_list_field (0th element)",
path: ".nested_list_field[0]",
expectedOffset: 1196,
expectedLength: 32,
},
{
name: "nested_list_field (1st element)",
path: ".nested_list_field[1]",
expectedOffset: 1228,
expectedLength: 33,
},
{
name: "nested_list_field (2nd element)",
path: ".nested_list_field[2]",
expectedOffset: 1261,
expectedLength: 34,
},
// Fixed trailing field
{
name: "trailing_field",
path: ".trailing_field",
expectedOffset: 56, // After leading_field + 6 offset pointers
expectedOffset: 60, // After leading_field + 7 offset pointers
expectedLength: 56,
},
}
@@ -419,11 +511,27 @@ func getFixedTestContainerSpec() testutil.TestSpec {
Path: ".vector_field",
Expected: testContainer.VectorField,
},
{
Path: ".vector_field[0]",
Expected: testContainer.VectorField[0],
},
{
Path: ".vector_field[10]",
Expected: testContainer.VectorField[10],
},
// 2D bytes field
{
Path: ".two_dimension_bytes_field",
Expected: testContainer.TwoDimensionBytesField,
},
{
Path: ".two_dimension_bytes_field[0]",
Expected: testContainer.TwoDimensionBytesField[0],
},
{
Path: ".two_dimension_bytes_field[1]",
Expected: testContainer.TwoDimensionBytesField[1],
},
// Bitvector fields
{
Path: ".bitvector64_field",
@@ -481,6 +589,28 @@ func createVariableTestContainer() *sszquerypb.VariableTestContainer {
}
}
// Two VariableOuterContainer elements, each with two VariableInnerContainer elements
variableContainerList := make([]*sszquerypb.VariableOuterContainer, 2)
for i := range variableContainerList {
// Inner1: 8 + 4 + 4 + (8*3) + (4*3) + 99 = 151 bytes
inner1 := &sszquerypb.VariableNestedContainer{
Value1: 42,
FieldListUint64: []uint64{uint64(i), uint64(i + 1), uint64(i + 2)},
NestedListField: nestedListField,
}
// Inner2: 8 + 4 + 4 + (8*2) + (4*3) + 99 = 143 bytes
inner2 := &sszquerypb.VariableNestedContainer{
Value1: 84,
FieldListUint64: []uint64{uint64(i + 3), uint64(i + 4)},
NestedListField: nestedListField,
}
// (4*2) + 151 + 143 = 302 bytes per VariableOuterContainer
variableContainerList[i] = &sszquerypb.VariableOuterContainer{
Inner_1: inner1,
Inner_2: inner2,
}
}
return &sszquerypb.VariableTestContainer{
// Fixed leading field
LeadingField: leadingField,
@@ -501,6 +631,9 @@ func createVariableTestContainer() *sszquerypb.VariableTestContainer {
NestedListField: nestedListField,
},
// Variable list of variable-sized containers
VariableContainerList: variableContainerList,
// Bitlist field
BitlistField: bitlistField,
@@ -530,11 +663,24 @@ func getVariableTestContainerSpec() testutil.TestSpec {
Path: ".field_list_uint64",
Expected: testContainer.FieldListUint64,
},
{
Path: ".field_list_uint64[2]",
Expected: testContainer.FieldListUint64[2],
},
// Variable-size list of (fixed-size) containers
{
Path: ".field_list_container",
Expected: testContainer.FieldListContainer,
},
// Accessing an element in the list of containers
{
Path: ".field_list_container[0]",
Expected: testContainer.FieldListContainer[0],
},
{
Path: ".field_list_container[1]",
Expected: testContainer.FieldListContainer[1],
},
// Variable-size list of bytes32
{
Path: ".field_list_bytes32",
@@ -553,10 +699,55 @@ func getVariableTestContainerSpec() testutil.TestSpec {
Path: ".nested.field_list_uint64",
Expected: testContainer.Nested.FieldListUint64,
},
{
Path: ".nested.field_list_uint64[3]",
Expected: testContainer.Nested.FieldListUint64[3],
},
{
Path: ".nested.nested_list_field",
Expected: testContainer.Nested.NestedListField,
},
{
Path: ".nested.nested_list_field[0]",
Expected: testContainer.Nested.NestedListField[0],
},
{
Path: ".nested.nested_list_field[1]",
Expected: testContainer.Nested.NestedListField[1],
},
{
Path: ".nested.nested_list_field[2]",
Expected: testContainer.Nested.NestedListField[2],
},
// Variable list of variable-sized containers
{
Path: ".variable_container_list",
Expected: testContainer.VariableContainerList,
},
{
Path: ".variable_container_list[0]",
Expected: testContainer.VariableContainerList[0],
},
{
Path: ".variable_container_list[0].inner_1.field_list_uint64[1]",
Expected: testContainer.VariableContainerList[0].Inner_1.FieldListUint64[1],
},
{
Path: ".variable_container_list[0].inner_2.field_list_uint64[1]",
Expected: testContainer.VariableContainerList[0].Inner_2.FieldListUint64[1],
},
{
Path: ".variable_container_list[1]",
Expected: testContainer.VariableContainerList[1],
},
{
Path: ".variable_container_list[1].inner_1.field_list_uint64[1]",
Expected: testContainer.VariableContainerList[1].Inner_1.FieldListUint64[1],
},
{
Path: ".variable_container_list[1].inner_2.field_list_uint64[1]",
Expected: testContainer.VariableContainerList[1].Inner_2.FieldListUint64[1],
},
// Bitlist field
{
Path: ".bitlist_field",
@@ -567,6 +758,18 @@ func getVariableTestContainerSpec() testutil.TestSpec {
Path: ".nested_list_field",
Expected: testContainer.NestedListField,
},
{
Path: ".nested_list_field[0]",
Expected: testContainer.NestedListField[0],
},
{
Path: ".nested_list_field[1]",
Expected: testContainer.NestedListField[1],
},
{
Path: ".nested_list_field[2]",
Expected: testContainer.NestedListField[2],
},
// Fixed trailing field
{
Path: ".trailing_field",

View File

@@ -251,23 +251,76 @@ func (x *VariableNestedContainer) GetNestedListField() [][]byte {
return nil
}
type VariableOuterContainer struct {
state protoimpl.MessageState `protogen:"open.v1"`
Inner_1 *VariableNestedContainer `protobuf:"bytes,1,opt,name=inner_1,json=inner1,proto3" json:"inner_1,omitempty"`
Inner_2 *VariableNestedContainer `protobuf:"bytes,2,opt,name=inner_2,json=inner2,proto3" json:"inner_2,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *VariableOuterContainer) Reset() {
*x = VariableOuterContainer{}
mi := &file_proto_ssz_query_ssz_query_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *VariableOuterContainer) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*VariableOuterContainer) ProtoMessage() {}
func (x *VariableOuterContainer) ProtoReflect() protoreflect.Message {
mi := &file_proto_ssz_query_ssz_query_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use VariableOuterContainer.ProtoReflect.Descriptor instead.
func (*VariableOuterContainer) Descriptor() ([]byte, []int) {
return file_proto_ssz_query_ssz_query_proto_rawDescGZIP(), []int{3}
}
func (x *VariableOuterContainer) GetInner_1() *VariableNestedContainer {
if x != nil {
return x.Inner_1
}
return nil
}
func (x *VariableOuterContainer) GetInner_2() *VariableNestedContainer {
if x != nil {
return x.Inner_2
}
return nil
}
type VariableTestContainer struct {
state protoimpl.MessageState `protogen:"open.v1"`
LeadingField []byte `protobuf:"bytes,1,opt,name=leading_field,json=leadingField,proto3" json:"leading_field,omitempty" ssz-size:"32"`
FieldListUint64 []uint64 `protobuf:"varint,2,rep,packed,name=field_list_uint64,json=fieldListUint64,proto3" json:"field_list_uint64,omitempty" ssz-max:"2048"`
FieldListContainer []*FixedNestedContainer `protobuf:"bytes,3,rep,name=field_list_container,json=fieldListContainer,proto3" json:"field_list_container,omitempty" ssz-max:"128"`
FieldListBytes32 [][]byte `protobuf:"bytes,4,rep,name=field_list_bytes32,json=fieldListBytes32,proto3" json:"field_list_bytes32,omitempty" ssz-max:"100" ssz-size:"?,32"`
Nested *VariableNestedContainer `protobuf:"bytes,5,opt,name=nested,proto3" json:"nested,omitempty"`
BitlistField github_com_prysmaticlabs_go_bitfield.Bitlist `protobuf:"bytes,6,opt,name=bitlist_field,json=bitlistField,proto3" json:"bitlist_field,omitempty" cast-type:"github.com/prysmaticlabs/go-bitfield.Bitlist" ssz-max:"2048"`
NestedListField [][]byte `protobuf:"bytes,7,rep,name=nested_list_field,json=nestedListField,proto3" json:"nested_list_field,omitempty" ssz-max:"100,50" ssz-size:"?,?"`
TrailingField []byte `protobuf:"bytes,8,opt,name=trailing_field,json=trailingField,proto3" json:"trailing_field,omitempty" ssz-size:"56"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
LeadingField []byte `protobuf:"bytes,1,opt,name=leading_field,json=leadingField,proto3" json:"leading_field,omitempty" ssz-size:"32"`
FieldListUint64 []uint64 `protobuf:"varint,2,rep,packed,name=field_list_uint64,json=fieldListUint64,proto3" json:"field_list_uint64,omitempty" ssz-max:"2048"`
FieldListContainer []*FixedNestedContainer `protobuf:"bytes,3,rep,name=field_list_container,json=fieldListContainer,proto3" json:"field_list_container,omitempty" ssz-max:"128"`
FieldListBytes32 [][]byte `protobuf:"bytes,4,rep,name=field_list_bytes32,json=fieldListBytes32,proto3" json:"field_list_bytes32,omitempty" ssz-max:"100" ssz-size:"?,32"`
Nested *VariableNestedContainer `protobuf:"bytes,5,opt,name=nested,proto3" json:"nested,omitempty"`
VariableContainerList []*VariableOuterContainer `protobuf:"bytes,6,rep,name=variable_container_list,json=variableContainerList,proto3" json:"variable_container_list,omitempty" ssz-max:"10"`
BitlistField github_com_prysmaticlabs_go_bitfield.Bitlist `protobuf:"bytes,7,opt,name=bitlist_field,json=bitlistField,proto3" json:"bitlist_field,omitempty" cast-type:"github.com/prysmaticlabs/go-bitfield.Bitlist" ssz-max:"2048"`
NestedListField [][]byte `protobuf:"bytes,8,rep,name=nested_list_field,json=nestedListField,proto3" json:"nested_list_field,omitempty" ssz-max:"100,50" ssz-size:"?,?"`
TrailingField []byte `protobuf:"bytes,9,opt,name=trailing_field,json=trailingField,proto3" json:"trailing_field,omitempty" ssz-size:"56"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *VariableTestContainer) Reset() {
*x = VariableTestContainer{}
mi := &file_proto_ssz_query_ssz_query_proto_msgTypes[3]
mi := &file_proto_ssz_query_ssz_query_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -279,7 +332,7 @@ func (x *VariableTestContainer) String() string {
func (*VariableTestContainer) ProtoMessage() {}
func (x *VariableTestContainer) ProtoReflect() protoreflect.Message {
mi := &file_proto_ssz_query_ssz_query_proto_msgTypes[3]
mi := &file_proto_ssz_query_ssz_query_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -292,7 +345,7 @@ func (x *VariableTestContainer) ProtoReflect() protoreflect.Message {
// Deprecated: Use VariableTestContainer.ProtoReflect.Descriptor instead.
func (*VariableTestContainer) Descriptor() ([]byte, []int) {
return file_proto_ssz_query_ssz_query_proto_rawDescGZIP(), []int{3}
return file_proto_ssz_query_ssz_query_proto_rawDescGZIP(), []int{4}
}
func (x *VariableTestContainer) GetLeadingField() []byte {
@@ -330,6 +383,13 @@ func (x *VariableTestContainer) GetNested() *VariableNestedContainer {
return nil
}
func (x *VariableTestContainer) GetVariableContainerList() []*VariableOuterContainer {
if x != nil {
return x.VariableContainerList
}
return nil
}
func (x *VariableTestContainer) GetBitlistField() github_com_prysmaticlabs_go_bitfield.Bitlist {
if x != nil {
return x.BitlistField
@@ -411,45 +471,60 @@ var file_proto_ssz_query_ssz_query_proto_rawDesc = []byte{
0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x03, 0x20, 0x03,
0x28, 0x0c, 0x42, 0x11, 0x8a, 0xb5, 0x18, 0x03, 0x3f, 0x2c, 0x3f, 0x92, 0xb5, 0x18, 0x06, 0x31,
0x30, 0x30, 0x2c, 0x35, 0x30, 0x52, 0x0f, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x4c, 0x69, 0x73,
0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x22, 0x9e, 0x04, 0x0a, 0x15, 0x56, 0x61, 0x72, 0x69, 0x61,
0x62, 0x6c, 0x65, 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
0x12, 0x2b, 0x0a, 0x0d, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x69, 0x65, 0x6c,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52,
0x0c, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x34, 0x0a,
0x11, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x75, 0x69, 0x6e, 0x74,
0x36, 0x34, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x42, 0x08, 0x92, 0xb5, 0x18, 0x04, 0x32, 0x30,
0x34, 0x38, 0x52, 0x0f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x69, 0x6e,
0x74, 0x36, 0x34, 0x12, 0x5a, 0x0a, 0x14, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x73,
0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x1f, 0x2e, 0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x46, 0x69,
0x78, 0x65, 0x64, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
0x65, 0x72, 0x42, 0x07, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38, 0x52, 0x12, 0x66, 0x69, 0x65,
0x6c, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12,
0x3d, 0x0a, 0x12, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x62, 0x79,
0x74, 0x65, 0x73, 0x33, 0x32, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x0f, 0x8a, 0xb5, 0x18,
0x04, 0x3f, 0x2c, 0x33, 0x32, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x30, 0x30, 0x52, 0x10, 0x66, 0x69,
0x65, 0x6c, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x33, 0x32, 0x12, 0x3a,
0x0a, 0x06, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22,
0x2e, 0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x56, 0x61, 0x72, 0x69, 0x61,
0x62, 0x6c, 0x65, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
0x65, 0x72, 0x52, 0x06, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x12, 0x5d, 0x0a, 0x0d, 0x62, 0x69,
0x74, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28,
0x0c, 0x42, 0x38, 0x82, 0xb5, 0x18, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f,
0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, 0x74, 0x6c,
0x69, 0x73, 0x74, 0x92, 0xb5, 0x18, 0x04, 0x32, 0x30, 0x34, 0x38, 0x52, 0x0c, 0x62, 0x69, 0x74,
0x6c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x3d, 0x0a, 0x11, 0x6e, 0x65, 0x73,
0x74, 0x65, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x07,
0x20, 0x03, 0x28, 0x0c, 0x42, 0x11, 0x8a, 0xb5, 0x18, 0x03, 0x3f, 0x2c, 0x3f, 0x92, 0xb5, 0x18,
0x06, 0x31, 0x30, 0x30, 0x2c, 0x35, 0x30, 0x52, 0x0f, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x4c,
0x69, 0x73, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x2d, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x69,
0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c,
0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x35, 0x36, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69,
0x6e, 0x67, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75,
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x4f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x61,
0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x36, 0x2f, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x2f, 0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x22, 0x92, 0x01, 0x0a, 0x16, 0x56, 0x61, 0x72, 0x69, 0x61,
0x62, 0x6c, 0x65, 0x4f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65,
0x72, 0x12, 0x3b, 0x0a, 0x07, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x5f, 0x31, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x22, 0x2e, 0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x56,
0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e,
0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x06, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x31, 0x12, 0x3b,
0x0a, 0x07, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x5f, 0x32, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x22, 0x2e, 0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x56, 0x61, 0x72, 0x69,
0x61, 0x62, 0x6c, 0x65, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69,
0x6e, 0x65, 0x72, 0x52, 0x06, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x32, 0x22, 0x81, 0x05, 0x0a, 0x15,
0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74,
0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x0d, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67,
0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5,
0x18, 0x02, 0x33, 0x32, 0x52, 0x0c, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x46, 0x69, 0x65,
0x6c, 0x64, 0x12, 0x34, 0x0a, 0x11, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74,
0x5f, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x42, 0x08, 0x92,
0xb5, 0x18, 0x04, 0x32, 0x30, 0x34, 0x38, 0x52, 0x0f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4c, 0x69,
0x73, 0x74, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x5a, 0x0a, 0x14, 0x66, 0x69, 0x65, 0x6c,
0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75, 0x65,
0x72, 0x79, 0x2e, 0x46, 0x69, 0x78, 0x65, 0x64, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6f,
0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x42, 0x07, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x32, 0x38,
0x52, 0x12, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61,
0x69, 0x6e, 0x65, 0x72, 0x12, 0x3d, 0x0a, 0x12, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6c, 0x69,
0x73, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x33, 0x32, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c,
0x42, 0x0f, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x33, 0x32, 0x92, 0xb5, 0x18, 0x03, 0x31, 0x30,
0x30, 0x52, 0x10, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x74, 0x65,
0x73, 0x33, 0x32, 0x12, 0x3a, 0x0a, 0x06, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e,
0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6f,
0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x06, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x12,
0x61, 0x0a, 0x17, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74,
0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x21, 0x2e, 0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x56, 0x61, 0x72,
0x69, 0x61, 0x62, 0x6c, 0x65, 0x4f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69,
0x6e, 0x65, 0x72, 0x42, 0x06, 0x92, 0xb5, 0x18, 0x02, 0x31, 0x30, 0x52, 0x15, 0x76, 0x61, 0x72,
0x69, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69,
0x73, 0x74, 0x12, 0x5d, 0x0a, 0x0d, 0x62, 0x69, 0x74, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x66, 0x69,
0x65, 0x6c, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x38, 0x82, 0xb5, 0x18, 0x2c, 0x67,
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61,
0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x67, 0x6f, 0x2d, 0x62, 0x69, 0x74, 0x66, 0x69,
0x65, 0x6c, 0x64, 0x2e, 0x42, 0x69, 0x74, 0x6c, 0x69, 0x73, 0x74, 0x92, 0xb5, 0x18, 0x04, 0x32,
0x30, 0x34, 0x38, 0x52, 0x0c, 0x62, 0x69, 0x74, 0x6c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x65, 0x6c,
0x64, 0x12, 0x3d, 0x0a, 0x11, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x6c, 0x69, 0x73, 0x74,
0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x11, 0x8a, 0xb5,
0x18, 0x03, 0x3f, 0x2c, 0x3f, 0x92, 0xb5, 0x18, 0x06, 0x31, 0x30, 0x30, 0x2c, 0x35, 0x30, 0x52,
0x0f, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64,
0x12, 0x2d, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x69, 0x65,
0x6c, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x35, 0x36,
0x52, 0x0d, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x42,
0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x4f, 0x66,
0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d,
0x2f, 0x76, 0x36, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x73, 0x7a, 0x5f, 0x71, 0x75,
0x65, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -464,22 +539,26 @@ func file_proto_ssz_query_ssz_query_proto_rawDescGZIP() []byte {
return file_proto_ssz_query_ssz_query_proto_rawDescData
}
var file_proto_ssz_query_ssz_query_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_proto_ssz_query_ssz_query_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
var file_proto_ssz_query_ssz_query_proto_goTypes = []any{
(*FixedNestedContainer)(nil), // 0: ssz_query.FixedNestedContainer
(*FixedTestContainer)(nil), // 1: ssz_query.FixedTestContainer
(*VariableNestedContainer)(nil), // 2: ssz_query.VariableNestedContainer
(*VariableTestContainer)(nil), // 3: ssz_query.VariableTestContainer
(*VariableOuterContainer)(nil), // 3: ssz_query.VariableOuterContainer
(*VariableTestContainer)(nil), // 4: ssz_query.VariableTestContainer
}
var file_proto_ssz_query_ssz_query_proto_depIdxs = []int32{
0, // 0: ssz_query.FixedTestContainer.nested:type_name -> ssz_query.FixedNestedContainer
0, // 1: ssz_query.VariableTestContainer.field_list_container:type_name -> ssz_query.FixedNestedContainer
2, // 2: ssz_query.VariableTestContainer.nested:type_name -> ssz_query.VariableNestedContainer
3, // [3:3] is the sub-list for method output_type
3, // [3:3] is the sub-list for method input_type
3, // [3:3] is the sub-list for extension type_name
3, // [3:3] is the sub-list for extension extendee
0, // [0:3] is the sub-list for field type_name
2, // 1: ssz_query.VariableOuterContainer.inner_1:type_name -> ssz_query.VariableNestedContainer
2, // 2: ssz_query.VariableOuterContainer.inner_2:type_name -> ssz_query.VariableNestedContainer
0, // 3: ssz_query.VariableTestContainer.field_list_container:type_name -> ssz_query.FixedNestedContainer
2, // 4: ssz_query.VariableTestContainer.nested:type_name -> ssz_query.VariableNestedContainer
3, // 5: ssz_query.VariableTestContainer.variable_container_list:type_name -> ssz_query.VariableOuterContainer
6, // [6:6] is the sub-list for method output_type
6, // [6:6] is the sub-list for method input_type
6, // [6:6] is the sub-list for extension type_name
6, // [6:6] is the sub-list for extension extendee
0, // [0:6] is the sub-list for field type_name
}
func init() { file_proto_ssz_query_ssz_query_proto_init() }
@@ -493,7 +572,7 @@ func file_proto_ssz_query_ssz_query_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_proto_ssz_query_ssz_query_proto_rawDesc,
NumEnums: 0,
NumMessages: 4,
NumMessages: 5,
NumExtensions: 0,
NumServices: 0,
},

View File

@@ -71,6 +71,13 @@ message VariableNestedContainer {
];
}
// Mock of AttesterSlashingElectra
message VariableOuterContainer {
VariableNestedContainer inner_1 = 1;
VariableNestedContainer inner_2 = 2;
}
// VariableTestContainer - comprehensive variable-size container for SSZ query testing
// Tests: Variable-size lists, offsets in variable containers, mixed fixed/variable fields
message VariableTestContainer {
@@ -93,8 +100,12 @@ message VariableTestContainer {
// Variable nested container - test nested container access within variable container
VariableNestedContainer nested = 5;
// List of variable-sized containers
// e.g., BeaconBlockBody.attester_slashings
repeated VariableOuterContainer variable_container_list = 6 [ (ethereum.eth.ext.ssz_max) = "10" ]; // Test: List[VariableOuterContainer, 10]
// Bitlist type - test bitlist serialization
bytes bitlist_field = 6 [
bytes bitlist_field = 7 [
(ethereum.eth.ext.ssz_max) = "2048",
(ethereum.eth.ext.cast_type) =
"github.com/prysmaticlabs/go-bitfield.Bitlist"
@@ -102,12 +113,12 @@ message VariableTestContainer {
// 2D bytes list - test list of bytelists.
// e.g., ExecutionPayload.transactions
repeated bytes nested_list_field = 7 [
repeated bytes nested_list_field = 8 [
(ethereum.eth.ext.ssz_size) = "?,?",
(ethereum.eth.ext.ssz_max) = "100,50"
];
// Fixed-size trailing field - test fixed field after variable fields
// Verifies correct offset calculation after variable-size fields
bytes trailing_field = 8 [ (ethereum.eth.ext.ssz_size) = "56" ]; // Test: fixed 56-byte field at end, offset: 32 + 4 + 4 + 4 + 4 + 4 + 4 = 56
bytes trailing_field = 9 [ (ethereum.eth.ext.ssz_size) = "56" ]; // Test: fixed 56-byte field at end, offset: 32 + 4 + 4 + 4 + 4 + 4 + 4 + 4 = 60
}

View File

@@ -509,6 +509,134 @@ func (v *VariableNestedContainer) HashTreeRootWith(hh *ssz.Hasher) (err error) {
return
}
// MarshalSSZ ssz marshals the VariableOuterContainer object
func (v *VariableOuterContainer) MarshalSSZ() ([]byte, error) {
return ssz.MarshalSSZ(v)
}
// MarshalSSZTo ssz marshals the VariableOuterContainer object to a target array
func (v *VariableOuterContainer) MarshalSSZTo(buf []byte) (dst []byte, err error) {
dst = buf
offset := int(8)
// Offset (0) 'Inner_1'
dst = ssz.WriteOffset(dst, offset)
if v.Inner_1 == nil {
v.Inner_1 = new(VariableNestedContainer)
}
offset += v.Inner_1.SizeSSZ()
// Offset (1) 'Inner_2'
dst = ssz.WriteOffset(dst, offset)
if v.Inner_2 == nil {
v.Inner_2 = new(VariableNestedContainer)
}
offset += v.Inner_2.SizeSSZ()
// Field (0) 'Inner_1'
if dst, err = v.Inner_1.MarshalSSZTo(dst); err != nil {
return
}
// Field (1) 'Inner_2'
if dst, err = v.Inner_2.MarshalSSZTo(dst); err != nil {
return
}
return
}
// UnmarshalSSZ ssz unmarshals the VariableOuterContainer object
func (v *VariableOuterContainer) UnmarshalSSZ(buf []byte) error {
var err error
size := uint64(len(buf))
if size < 8 {
return ssz.ErrSize
}
tail := buf
var o0, o1 uint64
// Offset (0) 'Inner_1'
if o0 = ssz.ReadOffset(buf[0:4]); o0 > size {
return ssz.ErrOffset
}
if o0 != 8 {
return ssz.ErrInvalidVariableOffset
}
// Offset (1) 'Inner_2'
if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 {
return ssz.ErrOffset
}
// Field (0) 'Inner_1'
{
buf = tail[o0:o1]
if v.Inner_1 == nil {
v.Inner_1 = new(VariableNestedContainer)
}
if err = v.Inner_1.UnmarshalSSZ(buf); err != nil {
return err
}
}
// Field (1) 'Inner_2'
{
buf = tail[o1:]
if v.Inner_2 == nil {
v.Inner_2 = new(VariableNestedContainer)
}
if err = v.Inner_2.UnmarshalSSZ(buf); err != nil {
return err
}
}
return err
}
// SizeSSZ returns the ssz encoded size in bytes for the VariableOuterContainer object
func (v *VariableOuterContainer) SizeSSZ() (size int) {
size = 8
// Field (0) 'Inner_1'
if v.Inner_1 == nil {
v.Inner_1 = new(VariableNestedContainer)
}
size += v.Inner_1.SizeSSZ()
// Field (1) 'Inner_2'
if v.Inner_2 == nil {
v.Inner_2 = new(VariableNestedContainer)
}
size += v.Inner_2.SizeSSZ()
return
}
// HashTreeRoot ssz hashes the VariableOuterContainer object
func (v *VariableOuterContainer) HashTreeRoot() ([32]byte, error) {
return ssz.HashWithDefaultHasher(v)
}
// HashTreeRootWith ssz hashes the VariableOuterContainer object with a hasher
func (v *VariableOuterContainer) HashTreeRootWith(hh *ssz.Hasher) (err error) {
indx := hh.Index()
// Field (0) 'Inner_1'
if err = v.Inner_1.HashTreeRootWith(hh); err != nil {
return
}
// Field (1) 'Inner_2'
if err = v.Inner_2.HashTreeRootWith(hh); err != nil {
return
}
hh.Merkleize(indx)
return
}
// MarshalSSZ ssz marshals the VariableTestContainer object
func (v *VariableTestContainer) MarshalSSZ() ([]byte, error) {
return ssz.MarshalSSZ(v)
@@ -517,7 +645,7 @@ func (v *VariableTestContainer) MarshalSSZ() ([]byte, error) {
// MarshalSSZTo ssz marshals the VariableTestContainer object to a target array
func (v *VariableTestContainer) MarshalSSZTo(buf []byte) (dst []byte, err error) {
dst = buf
offset := int(112)
offset := int(116)
// Field (0) 'LeadingField'
if size := len(v.LeadingField); size != 32 {
@@ -545,18 +673,25 @@ func (v *VariableTestContainer) MarshalSSZTo(buf []byte) (dst []byte, err error)
}
offset += v.Nested.SizeSSZ()
// Offset (5) 'BitlistField'
// Offset (5) 'VariableContainerList'
dst = ssz.WriteOffset(dst, offset)
for ii := 0; ii < len(v.VariableContainerList); ii++ {
offset += 4
offset += v.VariableContainerList[ii].SizeSSZ()
}
// Offset (6) 'BitlistField'
dst = ssz.WriteOffset(dst, offset)
offset += len(v.BitlistField)
// Offset (6) 'NestedListField'
// Offset (7) 'NestedListField'
dst = ssz.WriteOffset(dst, offset)
for ii := 0; ii < len(v.NestedListField); ii++ {
offset += 4
offset += len(v.NestedListField[ii])
}
// Field (7) 'TrailingField'
// Field (8) 'TrailingField'
if size := len(v.TrailingField); size != 56 {
err = ssz.ErrBytesLengthFn("--.TrailingField", size, 56)
return
@@ -601,14 +736,32 @@ func (v *VariableTestContainer) MarshalSSZTo(buf []byte) (dst []byte, err error)
return
}
// Field (5) 'BitlistField'
// Field (5) 'VariableContainerList'
if size := len(v.VariableContainerList); size > 10 {
err = ssz.ErrListTooBigFn("--.VariableContainerList", size, 10)
return
}
{
offset = 4 * len(v.VariableContainerList)
for ii := 0; ii < len(v.VariableContainerList); ii++ {
dst = ssz.WriteOffset(dst, offset)
offset += v.VariableContainerList[ii].SizeSSZ()
}
}
for ii := 0; ii < len(v.VariableContainerList); ii++ {
if dst, err = v.VariableContainerList[ii].MarshalSSZTo(dst); err != nil {
return
}
}
// Field (6) 'BitlistField'
if size := len(v.BitlistField); size > 2048 {
err = ssz.ErrBytesLengthFn("--.BitlistField", size, 2048)
return
}
dst = append(dst, v.BitlistField...)
// Field (6) 'NestedListField'
// Field (7) 'NestedListField'
if size := len(v.NestedListField); size > 100 {
err = ssz.ErrListTooBigFn("--.NestedListField", size, 100)
return
@@ -635,12 +788,12 @@ func (v *VariableTestContainer) MarshalSSZTo(buf []byte) (dst []byte, err error)
func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error {
var err error
size := uint64(len(buf))
if size < 112 {
if size < 116 {
return ssz.ErrSize
}
tail := buf
var o1, o2, o3, o4, o5, o6 uint64
var o1, o2, o3, o4, o5, o6, o7 uint64
// Field (0) 'LeadingField'
if cap(v.LeadingField) == 0 {
@@ -653,7 +806,7 @@ func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error {
return ssz.ErrOffset
}
if o1 != 112 {
if o1 != 116 {
return ssz.ErrInvalidVariableOffset
}
@@ -672,21 +825,26 @@ func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error {
return ssz.ErrOffset
}
// Offset (5) 'BitlistField'
// Offset (5) 'VariableContainerList'
if o5 = ssz.ReadOffset(buf[48:52]); o5 > size || o4 > o5 {
return ssz.ErrOffset
}
// Offset (6) 'NestedListField'
// Offset (6) 'BitlistField'
if o6 = ssz.ReadOffset(buf[52:56]); o6 > size || o5 > o6 {
return ssz.ErrOffset
}
// Field (7) 'TrailingField'
if cap(v.TrailingField) == 0 {
v.TrailingField = make([]byte, 0, len(buf[56:112]))
// Offset (7) 'NestedListField'
if o7 = ssz.ReadOffset(buf[56:60]); o7 > size || o6 > o7 {
return ssz.ErrOffset
}
v.TrailingField = append(v.TrailingField, buf[56:112]...)
// Field (8) 'TrailingField'
if cap(v.TrailingField) == 0 {
v.TrailingField = make([]byte, 0, len(buf[60:116]))
}
v.TrailingField = append(v.TrailingField, buf[60:116]...)
// Field (1) 'FieldListUint64'
{
@@ -746,9 +904,31 @@ func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error {
}
}
// Field (5) 'BitlistField'
// Field (5) 'VariableContainerList'
{
buf = tail[o5:o6]
num, err := ssz.DecodeDynamicLength(buf, 10)
if err != nil {
return err
}
v.VariableContainerList = make([]*VariableOuterContainer, num)
err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) {
if v.VariableContainerList[indx] == nil {
v.VariableContainerList[indx] = new(VariableOuterContainer)
}
if err = v.VariableContainerList[indx].UnmarshalSSZ(buf); err != nil {
return err
}
return nil
})
if err != nil {
return err
}
}
// Field (6) 'BitlistField'
{
buf = tail[o6:o7]
if err = ssz.ValidateBitlist(buf, 2048); err != nil {
return err
}
@@ -758,9 +938,9 @@ func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error {
v.BitlistField = append(v.BitlistField, buf...)
}
// Field (6) 'NestedListField'
// Field (7) 'NestedListField'
{
buf = tail[o6:]
buf = tail[o7:]
num, err := ssz.DecodeDynamicLength(buf, 100)
if err != nil {
return err
@@ -785,7 +965,7 @@ func (v *VariableTestContainer) UnmarshalSSZ(buf []byte) error {
// SizeSSZ returns the ssz encoded size in bytes for the VariableTestContainer object
func (v *VariableTestContainer) SizeSSZ() (size int) {
size = 112
size = 116
// Field (1) 'FieldListUint64'
size += len(v.FieldListUint64) * 8
@@ -802,10 +982,16 @@ func (v *VariableTestContainer) SizeSSZ() (size int) {
}
size += v.Nested.SizeSSZ()
// Field (5) 'BitlistField'
// Field (5) 'VariableContainerList'
for ii := 0; ii < len(v.VariableContainerList); ii++ {
size += 4
size += v.VariableContainerList[ii].SizeSSZ()
}
// Field (6) 'BitlistField'
size += len(v.BitlistField)
// Field (6) 'NestedListField'
// Field (7) 'NestedListField'
for ii := 0; ii < len(v.NestedListField); ii++ {
size += 4
size += len(v.NestedListField[ii])
@@ -886,14 +1072,30 @@ func (v *VariableTestContainer) HashTreeRootWith(hh *ssz.Hasher) (err error) {
return
}
// Field (5) 'BitlistField'
// Field (5) 'VariableContainerList'
{
subIndx := hh.Index()
num := uint64(len(v.VariableContainerList))
if num > 10 {
err = ssz.ErrIncorrectListSize
return
}
for _, elem := range v.VariableContainerList {
if err = elem.HashTreeRootWith(hh); err != nil {
return
}
}
hh.MerkleizeWithMixin(subIndx, num, 10)
}
// Field (6) 'BitlistField'
if len(v.BitlistField) == 0 {
err = ssz.ErrEmptyBitlist
return
}
hh.PutBitlist(v.BitlistField, 2048)
// Field (6) 'NestedListField'
// Field (7) 'NestedListField'
{
subIndx := hh.Index()
num := uint64(len(v.NestedListField))
@@ -916,7 +1118,7 @@ func (v *VariableTestContainer) HashTreeRootWith(hh *ssz.Hasher) (err error) {
hh.MerkleizeWithMixin(subIndx, num, 100)
}
// Field (7) 'TrailingField'
// Field (8) 'TrailingField'
if size := len(v.TrailingField); size != 56 {
err = ssz.ErrBytesLengthFn("--.TrailingField", size, 56)
return