PeerDAS: Implement core. (#15192)

* Fulu: Implement params.

* KZG tests: Re-implement `getRandBlob` to avoid tests cyclical dependencies.

Not ideal, but any better idea welcome.

* Fulu testing util: Implement `GenerateCellsAndProofs`.

* Create `RODataColumn`.

* Implement `MerkleProofKZGCommitments`.

* Export `leavesFromCommitments`.

* Implement peerDAS core.

* Add changelog.

* Update beacon-chain/core/peerdas/das_core.go

Co-authored-by: terence <terence@prysmaticlabs.com>

* Fix Terence's comment: Use `IsNil`.

* Fix Terence's comment: Avoid useless `filteredIndices`.

* Fix Terence's comment: Simplify odd/even cases.

* Fix Terence's comment: Use `IsNil`.

* Spectests: Add Fulu networking

* Fix Terence's comment: `CustodyGroups`: Stick to the spec by returning a (sorted) slice.

* Fix Terence's comment: `CustodyGroups`: Handle correctly the `maxUint256` case.

* Update beacon-chain/core/peerdas/das_core.go

Co-authored-by: terence <terence@prysmaticlabs.com>

* Fix Terence's comment: `ComputeColumnsForCustodyGroup`: Add test if `custodyGroup == numberOfCustodyGroup`

* `CustodyGroups`: Test if `custodyGroupCount > numberOfCustodyGroup`.

* `CustodyGroups`: Add a shortcut if all custody groups are needed.

* `ComputeCystodyGroupForColumn`: Move from `p2p_interface.go` to `das_core.go`.

* Fix Terence's comment: Fix `ComputeCustodyGroupForColumn`.

* Fix Terence's comment: Remove `constructCellsAndProofs` function.

* Fix Terence's comment: `ValidatorsCustodyRequirement`: Use effective balance instead of balance.

* `MerkleProofKZGCommitments`: Add tests

* Remove peer sampling.

* `DataColumnSidecars`: Add missing tests.

* Fix Jame's comment.

* Fix James' comment.

* Fix James' comment.

* Fix James' coment.

* Fix James' comment.

---------

Co-authored-by: terence <terence@prysmaticlabs.com>
This commit is contained in:
Manu NALEPA
2025-05-06 23:37:07 +02:00
committed by GitHub
parent 24cf930952
commit 7da7019a20
39 changed files with 2517 additions and 47 deletions

View File

@@ -242,7 +242,7 @@ type BeaconChainConfig struct {
MaxPerEpochActivationChurnLimit uint64 `yaml:"MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT" spec:"true"` // MaxPerEpochActivationChurnLimit is the maximum amount of churn allotted for validator activation.
MinEpochsForBlobsSidecarsRequest primitives.Epoch `yaml:"MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS" spec:"true"` // MinEpochsForBlobsSidecarsRequest is the minimum number of epochs the node will keep the blobs for.
MaxRequestBlobSidecars uint64 `yaml:"MAX_REQUEST_BLOB_SIDECARS" spec:"true"` // MaxRequestBlobSidecars is the maximum number of blobs to request in a single request.
MaxRequestBlobSidecarsElectra uint64 `yaml:"MAX_REQUEST_BLOB_SIDECARS_ELECTRA" spec:"true"` // MaxRequestBlobSidecarsElectra is the maximum number of blobs to request in a single request.
MaxRequestBlobSidecarsElectra uint64 `yaml:"MAX_REQUEST_BLOB_SIDECARS_ELECTRA" spec:"true"` // MaxRequestBlobSidecarsElectra is the maximum number of blobs to request in a single request after the electra epoch.
MaxRequestBlocksDeneb uint64 `yaml:"MAX_REQUEST_BLOCKS_DENEB" spec:"true"` // MaxRequestBlocksDeneb is the maximum number of blocks in a single request after the deneb epoch.
FieldElementsPerBlob uint64 `yaml:"FIELD_ELEMENTS_PER_BLOB" spec:"true"` // FieldElementsPerBlob is the number of field elements that constitute a single blob.
MaxBlobCommitmentsPerBlock uint64 `yaml:"MAX_BLOB_COMMITMENTS_PER_BLOCK" spec:"true"` // MaxBlobCommitmentsPerBlock is the maximum number of KZG commitments that a block can have.
@@ -265,14 +265,17 @@ type BeaconChainConfig struct {
MaxDepositRequestsPerPayload uint64 `yaml:"MAX_DEPOSIT_REQUESTS_PER_PAYLOAD" spec:"true"` // MaxDepositRequestsPerPayload is the maximum number of execution layer deposits in each payload
UnsetDepositRequestsStartIndex uint64 `yaml:"UNSET_DEPOSIT_REQUESTS_START_INDEX" spec:"true"` // UnsetDepositRequestsStartIndex is used to check the start index for eip6110
// PeerDAS Values
SamplesPerSlot uint64 `yaml:"SAMPLES_PER_SLOT"` // SamplesPerSlot refers to the number of random samples a node queries per slot.
CustodyRequirement uint64 `yaml:"CUSTODY_REQUIREMENT"` // CustodyRequirement refers to the minimum amount of subnets a peer must custody and serve samples from.
MinEpochsForDataColumnSidecarsRequest primitives.Epoch `yaml:"MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS"` // MinEpochsForDataColumnSidecarsRequest is the minimum number of epochs the node will keep the data columns for.
MaxRequestDataColumnSidecars uint64 `yaml:"MAX_REQUEST_DATA_COLUMN_SIDECARS" spec:"true"` // MaxRequestDataColumnSidecars is the maximum number of data column sidecars in a single request
MaxCellsInExtendedMatrix uint64 `yaml:"MAX_CELLS_IN_EXTENDED_MATRIX" spec:"true"` // MaxCellsInExtendedMatrix is the full data of one-dimensional erasure coding extended blobs (in row major format).
NumberOfColumns uint64 `yaml:"NUMBER_OF_COLUMNS" spec:"true"` // NumberOfColumns in the extended data matrix.
DataColumnSidecarSubnetCount uint64 `yaml:"DATA_COLUMN_SIDECAR_SUBNET_COUNT" spec:"true"` // DataColumnSidecarSubnetCount is the number of data column sidecar subnets used in the gossipsub protocol
// Values introduced in Fulu upgrade
NumberOfColumns uint64 `yaml:"NUMBER_OF_COLUMNS" spec:"true"` // NumberOfColumns in the extended data matrix.
SamplesPerSlot uint64 `yaml:"SAMPLES_PER_SLOT" spec:"true"` // SamplesPerSlot refers to the number of random samples a node queries per slot.
NumberOfCustodyGroups uint64 `yaml:"NUMBER_OF_CUSTODY_GROUPS" spec:"true"` // NumberOfCustodyGroups available for nodes to custody.
CustodyRequirement uint64 `yaml:"CUSTODY_REQUIREMENT" spec:"true"` // CustodyRequirement refers to the minimum amount of subnets a peer must custody and serve samples from.
MinEpochsForDataColumnSidecarsRequest primitives.Epoch `yaml:"MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS" spec:"true"` // MinEpochsForDataColumnSidecarsRequest is the minimum number of epochs the node will keep the data columns for.
MaxCellsInExtendedMatrix uint64 `yaml:"MAX_CELLS_IN_EXTENDED_MATRIX"` // MaxCellsInExtendedMatrix is the full data of one-dimensional erasure coding extended blobs (in row major format).
DataColumnSidecarSubnetCount uint64 `yaml:"DATA_COLUMN_SIDECAR_SUBNET_COUNT" spec:"true"` // DataColumnSidecarSubnetCount is the number of data column sidecar subnets used in the gossipsub protocol
MaxRequestDataColumnSidecars uint64 `yaml:"MAX_REQUEST_DATA_COLUMN_SIDECARS" spec:"true"` // MaxRequestDataColumnSidecars is the maximum number of data column sidecars in a single request
ValidatorCustodyRequirement uint64 `yaml:"VALIDATOR_CUSTODY_REQUIREMENT" spec:"true"` // ValidatorCustodyRequirement is the minimum number of custody groups an honest node with validators attached custodies and serves samples from
BalancePerAdditionalCustodyGroup uint64 `yaml:"BALANCE_PER_ADDITIONAL_CUSTODY_GROUP" spec:"true"` // BalancePerAdditionalCustodyGroup is the balance increment corresponding to one additional group to custody.
// Networking Specific Parameters
MaxPayloadSize uint64 `yaml:"MAX_PAYLOAD_SIZE" spec:"true"` // MAX_PAYLOAD_SIZE is the maximum allowed size of uncompressed payload in gossip messages and rpc chunks.
@@ -304,6 +307,10 @@ type BeaconChainConfig struct {
// DeprecatedTargetBlobsPerBlockElectra defines the target number of blobs per block post Electra hard fork.
// Deprecated: This field is no longer supported. Avoid using it.
DeprecatedTargetBlobsPerBlockElectra int `yaml:"TARGET_BLOBS_PER_BLOCK_ELECTRA" spec:"true"`
// DeprecatedMaxBlobsPerBlockFulu defines the max blobs that could exist in a block post Fulu hard fork.
// Deprecated: This field is no longer supported. Avoid using it.
DeprecatedMaxBlobsPerBlockFulu int `yaml:"MAX_BLOBS_PER_BLOCK_FULU" spec:"true"`
}
// InitializeForkSchedule initializes the schedules forks baked into the config.
@@ -389,32 +396,49 @@ func (b *BeaconChainConfig) TargetBlobsPerBlock(slot primitives.Slot) int {
if primitives.Epoch(slot.DivSlot(b.SlotsPerEpoch)) >= b.ElectraForkEpoch {
return b.DeprecatedTargetBlobsPerBlockElectra
}
return b.DeprecatedMaxBlobsPerBlock / 2
}
// MaxBlobsPerBlock returns the maximum number of blobs per block for the given slot,
// adjusting for the Electra fork.
// MaxBlobsPerBlock returns the maximum number of blobs per block for the given slot.
func (b *BeaconChainConfig) MaxBlobsPerBlock(slot primitives.Slot) int {
if primitives.Epoch(slot.DivSlot(b.SlotsPerEpoch)) >= b.ElectraForkEpoch {
epoch := primitives.Epoch(slot.DivSlot(b.SlotsPerEpoch))
if epoch >= b.FuluForkEpoch {
return b.DeprecatedMaxBlobsPerBlockFulu
}
if epoch >= b.ElectraForkEpoch {
return b.DeprecatedMaxBlobsPerBlockElectra
}
return b.DeprecatedMaxBlobsPerBlock
}
// MaxBlobsPerBlockByVersion returns the maximum number of blobs per block for the given fork version
func (b *BeaconChainConfig) MaxBlobsPerBlockByVersion(v int) int {
if v >= version.Fulu {
return b.DeprecatedMaxBlobsPerBlockFulu
}
if v >= version.Electra {
return b.DeprecatedMaxBlobsPerBlockElectra
}
return b.DeprecatedMaxBlobsPerBlock
}
// MaxBlobsPerBlockByEpoch returns the maximum number of blobs per block for the given epoch,
// adjusting for the Electra fork.
func (b *BeaconChainConfig) MaxBlobsPerBlockAtEpoch(epoch primitives.Epoch) int {
if epoch >= b.FuluForkEpoch {
return b.DeprecatedMaxBlobsPerBlockFulu
}
if epoch >= b.ElectraForkEpoch {
return b.DeprecatedMaxBlobsPerBlockElectra
}
return b.DeprecatedMaxBlobsPerBlock
}
@@ -432,9 +456,9 @@ func ElectraEnabled() bool {
return BeaconConfig().ElectraForkEpoch < math.MaxUint64
}
// PeerDASEnabled centralizes the check to determine if code paths
// that are specific to peerdas should be allowed to execute.
func PeerDASEnabled() bool {
// FuluEnabled centralizes the check to determine if code paths that are specific to Fulu should be allowed to execute.
// This will make it easier to find call sites that do this kind of check and remove them post-fulu.
func FuluEnabled() bool {
return BeaconConfig().FuluForkEpoch < math.MaxUint64
}

View File

@@ -141,9 +141,14 @@ func TestMaxBlobsPerBlockByVersion(t *testing.T) {
want: params.BeaconConfig().DeprecatedMaxBlobsPerBlockElectra,
},
{
name: "Version above Electra",
v: version.Electra + 1,
want: params.BeaconConfig().DeprecatedMaxBlobsPerBlockElectra,
name: "Version equal to Fulu",
v: version.Fulu,
want: params.BeaconConfig().DeprecatedMaxBlobsPerBlockFulu,
},
{
name: "Version above Fulu",
v: version.Fulu + 1,
want: params.BeaconConfig().DeprecatedMaxBlobsPerBlockFulu,
},
}

View File

@@ -241,6 +241,7 @@ func ConfigToYaml(cfg *BeaconChainConfig) []byte {
fmt.Sprintf("MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA: %d", cfg.MinPerEpochChurnLimitElectra),
fmt.Sprintf("MAX_BLOBS_PER_BLOCK: %d", cfg.DeprecatedMaxBlobsPerBlock),
fmt.Sprintf("MAX_BLOBS_PER_BLOCK_ELECTRA: %d", cfg.DeprecatedMaxBlobsPerBlockElectra),
fmt.Sprintf("MAX_BLOBS_PER_BLOCK_FULU: %d", cfg.DeprecatedMaxBlobsPerBlockFulu),
}
yamlFile := []byte(strings.Join(lines, "\n"))

View File

@@ -25,7 +25,6 @@ import (
// IMPORTANT: Use one field per line and sort these alphabetically to reduce conflicts.
var placeholderFields = []string{
"ATTESTATION_DEADLINE",
"BALANCE_PER_ADDITIONAL_CUSTODY_GROUP",
"BLOB_SIDECAR_SUBNET_COUNT_FULU",
"EIP6110_FORK_EPOCH",
"EIP6110_FORK_VERSION",
@@ -38,15 +37,12 @@ var placeholderFields = []string{
"EIP7805_FORK_EPOCH",
"EIP7805_FORK_VERSION",
"EPOCHS_PER_SHUFFLING_PHASE",
"MAX_BLOBS_PER_BLOCK_FULU",
"MAX_REQUEST_BLOB_SIDECARS_FULU",
"MAX_REQUEST_PAYLOADS", // Compile time constant on BeaconBlockBody.ExecutionRequests
"NUMBER_OF_CUSTODY_GROUPS",
"PROPOSER_INCLUSION_LIST_CUT_OFF",
"PROPOSER_SELECTION_GAP",
"TARGET_NUMBER_OF_PEERS",
"UPDATE_TIMEOUT",
"VALIDATOR_CUSTODY_REQUIREMENT",
"VIEW_FREEZE_DEADLINE",
"WHISK_EPOCHS_PER_SHUFFLING_PHASE",
"WHISK_FORK_EPOCH",

View File

@@ -37,6 +37,7 @@ var mainnetNetworkConfig = &NetworkConfig{
ETH2Key: "eth2",
AttSubnetKey: "attnets",
SyncCommsSubnetKey: "syncnets",
CustodyGroupCountKey: "cgc",
MinimumPeersInSubnetSearch: 20,
ContractDeploymentBlock: 11184524, // Note: contract was deployed in block 11052984 but no transactions were sent until 11184524.
BootstrapNodes: []string{
@@ -286,10 +287,9 @@ var mainnetBeaconConfig = &BeaconChainConfig{
FieldElementsPerBlob: 4096,
MaxBlobCommitmentsPerBlock: 4096,
KzgCommitmentInclusionProofDepth: 17,
DeprecatedMaxBlobsPerBlock: 6,
// Values related to electra
MaxRequestDataColumnSidecars: 16384,
DataColumnSidecarSubnetCount: 128,
MinPerEpochChurnLimitElectra: 128_000_000_000,
MaxPerEpochActivationExitChurnLimit: 256_000_000_000,
MaxEffectiveBalanceElectra: 2048_000_000_000,
@@ -306,13 +306,22 @@ var mainnetBeaconConfig = &BeaconChainConfig{
MaxWithdrawalRequestsPerPayload: 16,
MaxDepositRequestsPerPayload: 8192, // 2**13 (= 8192)
UnsetDepositRequestsStartIndex: math.MaxUint64,
DeprecatedMaxBlobsPerBlockElectra: 9,
DeprecatedTargetBlobsPerBlockElectra: 6,
MaxRequestBlobSidecarsElectra: 1152,
// PeerDAS
// Values related to fulu
MaxRequestDataColumnSidecars: 16384,
DataColumnSidecarSubnetCount: 128,
NumberOfColumns: 128,
MaxCellsInExtendedMatrix: 768,
SamplesPerSlot: 8,
NumberOfCustodyGroups: 128,
CustodyRequirement: 4,
MinEpochsForDataColumnSidecarsRequest: 4096,
MaxCellsInExtendedMatrix: 768,
ValidatorCustodyRequirement: 8,
BalancePerAdditionalCustodyGroup: 32_000_000_000,
DeprecatedMaxBlobsPerBlockFulu: 12,
// Values related to networking parameters.
MaxPayloadSize: 10 * 1 << 20, // 10 MiB
@@ -330,11 +339,6 @@ var mainnetBeaconConfig = &BeaconChainConfig{
AttestationSubnetPrefixBits: 6,
SubnetsPerNode: 2,
NodeIdBits: 256,
DeprecatedMaxBlobsPerBlock: 6,
DeprecatedMaxBlobsPerBlockElectra: 9,
DeprecatedTargetBlobsPerBlockElectra: 6,
MaxRequestBlobSidecarsElectra: 1152,
}
// MainnetTestConfig provides a version of the mainnet config that has a different name

View File

@@ -8,9 +8,10 @@ import (
// NetworkConfig defines the spec based network parameters.
type NetworkConfig struct {
// DiscoveryV5 Config
ETH2Key string // ETH2Key is the ENR key of the Ethereum consensus object in an enr.
AttSubnetKey string // AttSubnetKey is the ENR key of the subnet bitfield in the enr.
SyncCommsSubnetKey string // SyncCommsSubnetKey is the ENR key of the sync committee subnet bitfield in the enr.
ETH2Key string // ETH2Key is the ENR key of the Ethereum consensus object.
AttSubnetKey string // AttSubnetKey is the ENR key of the subnet bitfield.
SyncCommsSubnetKey string // SyncCommsSubnetKey is the ENR key of the sync committee subnet bitfield.
CustodyGroupCountKey string // CustodyGroupsCountKey is the ENR key of the custody group count.
MinimumPeersInSubnetSearch uint64 // PeersInSubnetSearch is the required amount of peers that we need to be able to lookup in a subnet search.
// Chain Network Config