@@ -30,41 +30,41 @@ import (
30
30
)
31
31
32
32
const (
33
- CustodySubnetCountEnrKey = "csc "
33
+ CustodyGroupCountEnrKey = "cgc "
34
34
)
35
35
36
- // https://github.com/ethereum/consensus-specs/blob/dev /specs/_features/eip7594 /p2p-interface.md#the-discovery-domain-discv5
37
- type Csc uint64
36
+ // https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.10 /specs/fulu /p2p-interface.md#the-discovery-domain-discv5
37
+ type Cgc uint64
38
38
39
- func (Csc ) ENRKey () string { return CustodySubnetCountEnrKey }
39
+ func (Cgc ) ENRKey () string { return CustodyGroupCountEnrKey }
40
40
41
41
var (
42
42
// Custom errors
43
- errCustodySubnetCountTooLarge = errors .New ("custody subnet count larger than data column sidecar subnet count" )
44
- errIndexTooLarge = errors .New ("column index is larger than the specified columns count" )
45
- errMismatchLength = errors .New ("mismatch in the length of the commitments and proofs" )
46
- errRecordNil = errors .New ("record is nil" )
47
- errCannotLoadCustodySubnetCount = errors .New ("cannot load the custody subnet count from peer" )
43
+ errCustodyGroupCountTooLarge = errors .New ("custody group count too large" )
44
+ errWrongComputedCustodyGroupCount = errors .New ("wrong computed custody group count, should never happen" )
45
+ errIndexTooLarge = errors .New ("column index is larger than the specified columns count" )
46
+ errMismatchLength = errors .New ("mismatch in the length of the commitments and proofs" )
47
+ errRecordNil = errors .New ("record is nil" )
48
+ errCannotLoadCustodyGroupCount = errors .New ("cannot load the custody group count from peer" )
48
49
49
50
// maxUint256 is the maximum value of a uint256.
50
51
maxUint256 = & uint256.Int {math .MaxUint64 , math .MaxUint64 , math .MaxUint64 , math .MaxUint64 }
51
52
)
52
53
53
- // CustodyColumnSubnets computes the subnets the node should participate in for custody.
54
- func CustodyColumnSubnets (nodeId enode.ID , custodySubnetCount uint64 ) (map [uint64 ]bool , error ) {
55
- dataColumnSidecarSubnetCount := params .BeaconConfig ().DataColumnSidecarSubnetCount
54
+ // CustodyGroups computes the custody groups the node should participate in for custody.
55
+ // https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.10/specs/fulu/das-core.md#get_custody_groups
56
+ func CustodyGroups (nodeId enode.ID , custodyGroupCount uint64 ) (map [uint64 ]bool , error ) {
57
+ numberOfCustodyGroup := params .BeaconConfig ().NumberOfCustodyGroups
56
58
57
- // Check if the custody subnet count is larger than the data column sidecar subnet count .
58
- if custodySubnetCount > dataColumnSidecarSubnetCount {
59
- return nil , errCustodySubnetCountTooLarge
59
+ // Check if the custody group count is larger than the number of custody groups .
60
+ if custodyGroupCount > numberOfCustodyGroup {
61
+ return nil , errCustodyGroupCountTooLarge
60
62
}
61
63
62
- // First, compute the subnet IDs that the node should participate in.
63
- subnetIds := make (map [uint64 ]bool , custodySubnetCount )
64
-
64
+ custodyGroups := make (map [uint64 ]bool , custodyGroupCount )
65
65
one := uint256 .NewInt (1 )
66
66
67
- for currentId := new (uint256.Int ).SetBytes (nodeId .Bytes ()); uint64 (len (subnetIds )) < custodySubnetCount ; currentId .Add (currentId , one ) {
67
+ for currentId := new (uint256.Int ).SetBytes (nodeId .Bytes ()); uint64 (len (custodyGroups )) < custodyGroupCount ; currentId .Add (currentId , one ) {
68
68
// Convert to big endian bytes.
69
69
currentIdBytesBigEndian := currentId .Bytes32 ()
70
70
@@ -74,49 +74,112 @@ func CustodyColumnSubnets(nodeId enode.ID, custodySubnetCount uint64) (map[uint6
74
74
// Hash the result.
75
75
hashedCurrentId := hash .Hash (currentIdBytesLittleEndian )
76
76
77
- // Get the subnet ID.
78
- subnetId := binary .LittleEndian .Uint64 (hashedCurrentId [:8 ]) % dataColumnSidecarSubnetCount
77
+ // Get the custody group ID.
78
+ custodyGroupId := binary .LittleEndian .Uint64 (hashedCurrentId [:8 ]) % numberOfCustodyGroup
79
79
80
- // Add the subnet to the map.
81
- subnetIds [ subnetId ] = true
80
+ // Add the custody group to the map.
81
+ custodyGroups [ custodyGroupId ] = true
82
82
83
83
// Overflow prevention.
84
84
if currentId .Cmp (maxUint256 ) == 0 {
85
85
currentId = uint256 .NewInt (0 )
86
86
}
87
87
}
88
88
89
- return subnetIds , nil
89
+ // Final check.
90
+ if uint64 (len (custodyGroups )) != custodyGroupCount {
91
+ return nil , errWrongComputedCustodyGroupCount
92
+ }
93
+
94
+ return custodyGroups , nil
90
95
}
91
96
92
- // CustodyColumns computes the columns the node should custody.
93
- // https://github.com/ethereum/consensus-specs/blob/dev/specs/_features/eip7594/das-core.md#helper-functions
94
- func CustodyColumns (nodeId enode.ID , custodySubnetCount uint64 ) (map [uint64 ]bool , error ) {
95
- dataColumnSidecarSubnetCount := params .BeaconConfig ().DataColumnSidecarSubnetCount
97
+ // ComputeColumnsForCustodyGroup computes the columns for a given custody group.
98
+ // https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.10/specs/fulu/das-core.md#compute_columns_for_custody_group
99
+ func ComputeColumnsForCustodyGroup (custodyGroup uint64 ) ([]uint64 , error ) {
100
+ beaconConfig := params .BeaconConfig ()
101
+ numberOfCustodyGroup := beaconConfig .NumberOfCustodyGroups
96
102
97
- // Compute the custody subnets.
98
- subnetIds , err := CustodyColumnSubnets (nodeId , custodySubnetCount )
99
- if err != nil {
100
- return nil , errors .Wrap (err , "custody subnets" )
103
+ if custodyGroup > numberOfCustodyGroup {
104
+ return nil , errCustodyGroupCountTooLarge
105
+ }
106
+
107
+ numberOfColumns := beaconConfig .NumberOfColumns
108
+
109
+ columnsPerGroup := numberOfColumns / numberOfCustodyGroup
110
+
111
+ columns := make ([]uint64 , 0 , columnsPerGroup )
112
+ for i := range columnsPerGroup {
113
+ column := numberOfCustodyGroup * i + custodyGroup
114
+ columns = append (columns , column )
101
115
}
102
116
103
- columnsPerSubnet := fieldparams .NumberOfColumns / dataColumnSidecarSubnetCount
117
+ return columns , nil
118
+ }
119
+
120
+ // ComputeCustodyGroupForColumn computes the custody group for a given column.
121
+ // It is the reciprocal function of ComputeColumnsForCustodyGroup.
122
+ func ComputeCustodyGroupForColumn (columnIndex uint64 ) (uint64 , error ) {
123
+ beaconConfig := params .BeaconConfig ()
124
+ numberOfColumns := beaconConfig .NumberOfColumns
125
+
126
+ if columnIndex >= numberOfColumns {
127
+ return 0 , errIndexTooLarge
128
+ }
129
+
130
+ numberOfCustodyGroups := beaconConfig .NumberOfCustodyGroups
131
+ columnsPerGroup := numberOfColumns / numberOfCustodyGroups
132
+
133
+ return columnIndex / columnsPerGroup , nil
134
+ }
135
+
136
+ // ComputeSubnetForDataColumnSidecar computes the subnet for a data column sidecar.
137
+ // https://github.com/ethereum/consensus-specs/blob/dev/specs/fulu/p2p-interface.md#compute_subnet_for_data_column_sidecar
138
+ func ComputeSubnetForDataColumnSidecar (columnIndex uint64 ) uint64 {
139
+ dataColumnSidecarSubnetCount := params .BeaconConfig ().DataColumnSidecarSubnetCount
140
+ return columnIndex % dataColumnSidecarSubnetCount
141
+ }
104
142
105
- // Knowing the subnet ID and the number of columns per subnet, select all the columns the node should custody.
106
- // Columns belonging to the same subnet are contiguous.
107
- columnIndices := make (map [uint64 ]bool , custodySubnetCount * columnsPerSubnet )
108
- for i := uint64 (0 ); i < columnsPerSubnet ; i ++ {
109
- for subnetId := range subnetIds {
110
- columnIndex := dataColumnSidecarSubnetCount * i + subnetId
111
- columnIndices [columnIndex ] = true
143
+ // CustodyColumns computes the columns the node should custody.
144
+ func CustodyColumns (custodyGroups map [uint64 ]bool ) (map [uint64 ]bool , error ) {
145
+ numberOfCustodyGroups := params .BeaconConfig ().NumberOfCustodyGroups
146
+
147
+ custodyGroupCount := len (custodyGroups )
148
+
149
+ // Compute the columns for each custody group.
150
+ columns := make (map [uint64 ]bool , custodyGroupCount )
151
+ for group := range custodyGroups {
152
+ if group >= numberOfCustodyGroups {
153
+ return nil , errCustodyGroupCountTooLarge
154
+ }
155
+
156
+ groupColumns , err := ComputeColumnsForCustodyGroup (group )
157
+ if err != nil {
158
+ return nil , errors .Wrap (err , "compute columns for custody group" )
159
+ }
160
+
161
+ for _ , column := range groupColumns {
162
+ columns [column ] = true
112
163
}
113
164
}
114
165
115
- return columnIndices , nil
166
+ return columns , nil
167
+ }
168
+
169
+ // DataColumnSubnets computes the subnets for the data columns.
170
+ func DataColumnSubnets (dataColumns map [uint64 ]bool ) map [uint64 ]bool {
171
+ subnets := make (map [uint64 ]bool , len (dataColumns ))
172
+
173
+ for column := range dataColumns {
174
+ subnet := ComputeSubnetForDataColumnSidecar (column )
175
+ subnets [subnet ] = true
176
+ }
177
+
178
+ return subnets
116
179
}
117
180
118
181
// DataColumnSidecars computes the data column sidecars from the signed block and blobs.
119
- // https://github.com/ethereum/consensus-specs/blob/dev/specs/_features/eip7594/ das-core.md#recover_matrix
182
+ // https://github.com/ethereum/consensus-specs/blob/dev/specs/fulu/ das-core.md#get_data_column_sidecars
120
183
func DataColumnSidecars (signedBlock interfaces.ReadOnlySignedBeaconBlock , blobs []kzg.Blob ) ([]* ethpb.DataColumnSidecar , error ) {
121
184
startTime := time .Now ()
122
185
blobsCount := len (blobs )
@@ -454,39 +517,22 @@ func VerifyDataColumnsSidecarKZGProofs(sidecars []blocks.RODataColumn) (bool, er
454
517
return verified , nil
455
518
}
456
519
457
- // CustodySubnetCount returns the number of subnets the node should participate in for custody.
458
- func CustodySubnetCount () uint64 {
520
+ // CustodyGroupCount returns the number of groups the node should participate in for custody.
521
+ func CustodyGroupCount () uint64 {
459
522
if flags .Get ().SubscribeToAllSubnets {
460
- return params .BeaconConfig ().DataColumnSidecarSubnetCount
523
+ return params .BeaconConfig ().NumberOfCustodyGroups
461
524
}
462
525
463
526
return params .BeaconConfig ().CustodyRequirement
464
527
}
465
528
466
- // SubnetSamplingSize returns the number of subnets the node should sample from.
467
- // https://github.com/ethereum/consensus-specs/blob/dev /specs/_features/eip7594/ das-core.md#subnet -sampling
468
- func SubnetSamplingSize () uint64 {
529
+ // CustodyGroupSamplingSize returns the number of custody groups the node should sample from.
530
+ // https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.10 /specs/fulu/ das-core.md#custody -sampling
531
+ func CustodyGroupSamplingSize () uint64 {
469
532
samplesPerSlot := params .BeaconConfig ().SamplesPerSlot
470
- custodySubnetCount := CustodySubnetCount ()
471
-
472
- return max (samplesPerSlot , custodySubnetCount )
473
- }
474
-
475
- // CustodyColumnCount returns the number of columns the node should custody.
476
- func CustodyColumnCount () uint64 {
477
- // Get the number of subnets.
478
- dataColumnSidecarSubnetCount := params .BeaconConfig ().DataColumnSidecarSubnetCount
479
-
480
- // Compute the number of columns per subnet.
481
- columnsPerSubnet := fieldparams .NumberOfColumns / dataColumnSidecarSubnetCount
482
-
483
- // Get the number of subnets we custody
484
- custodySubnetCount := CustodySubnetCount ()
485
-
486
- // Finally, compute the number of columns we should custody.
487
- custodyColumnCount := custodySubnetCount * columnsPerSubnet
533
+ custodyGroupCount := CustodyGroupCount ()
488
534
489
- return custodyColumnCount
535
+ return max ( samplesPerSlot , custodyGroupCount )
490
536
}
491
537
492
538
// HypergeomCDF computes the hypergeometric cumulative distribution function.
@@ -538,27 +584,27 @@ func ExtendedSampleCount(samplesPerSlot, allowedFailures uint64) uint64 {
538
584
return sampleCount
539
585
}
540
586
541
- func CustodyCountFromRecord ( record * enr. Record ) ( uint64 , error ) {
542
- // By default, we assume the peer custodies the minimum number of subnets.
587
+ // CustodyGroupCountFromRecord extracts the custody group count from an ENR record.
588
+ func CustodyGroupCountFromRecord ( record * enr. Record ) ( uint64 , error ) {
543
589
if record == nil {
544
590
return 0 , errRecordNil
545
591
}
546
592
547
- // Load the `custody_subnet_count `
548
- var csc Csc
549
- if err := record .Load (& csc ); err != nil {
550
- return 0 , errCannotLoadCustodySubnetCount
593
+ // Load the `cgc `
594
+ var cgc Cgc
595
+ if cgc := record .Load (& cgc ); cgc != nil {
596
+ return 0 , errCannotLoadCustodyGroupCount
551
597
}
552
598
553
- return uint64 (csc ), nil
599
+ return uint64 (cgc ), nil
554
600
}
555
601
556
- func CanSelfReconstruct (numCol uint64 ) bool {
557
- total := params .BeaconConfig ().NumberOfColumns
558
- // if total is odd, then we need total / 2 + 1 columns to reconstruct
559
- // if total is even, then we need total / 2 columns to reconstruct
560
- columnsNeeded := total / 2 + total % 2
561
- return numCol >= columnsNeeded
602
+ func CanSelfReconstruct (custodyGroupCount uint64 ) bool {
603
+ total := params .BeaconConfig ().NumberOfCustodyGroups
604
+ // If total is odd, then we need total / 2 + 1 columns to reconstruct.
605
+ // If total is even, then we need total / 2 columns to reconstruct.
606
+ custodyGroupsNeeded := total / 2 + total % 2
607
+ return custodyGroupCount >= custodyGroupsNeeded
562
608
}
563
609
564
610
// RecoverCellsAndProofs recovers the cells and proofs from the data column sidecars.
0 commit comments