Skip to content

Commit abf5e3b

Browse files
committed
fix for get_ptc iterator
1 parent d68a43b commit abf5e3b

File tree

4 files changed

+84
-78
lines changed

4 files changed

+84
-78
lines changed

AllTests-mainnet.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,15 @@ AllTests-mainnet
836836
```diff
837837
+ pre-1.1.0 OK
838838
```
839+
## Payload attestation pool [Preset: mainnet]
840+
```diff
841+
+ Can add and retrieve payload attestations [Preset: mainnet] OK
842+
+ Can get payload attestations for block production [Preset: mainnet] OK
843+
+ Different payload presence values [Preset: mainnet] OK
844+
+ Duplicate validator in PTC - multiple signatures [Preset: mainnet] OK
845+
+ Multiple validators in PTC can attest [Preset: mainnet] OK
846+
+ Payload attestations get pruned [Preset: mainnet] OK
847+
```
839848
## PeerPool testing suite
840849
```diff
841850
+ Access peers by key test OK

beacon_chain/consensus_object_pools/payload_attestation_pool.nim

Lines changed: 15 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import
1616
"."/[spec_cache, blockchain_dag],
1717
../beacon_clock
1818

19-
from ../spec/beaconstate import get_ptc
19+
from ../spec/beaconstate import get_ptc_list
2020

2121
logScope: topics = "payattpool"
2222

@@ -33,7 +33,7 @@ type
3333
dag*: ChainDAGRef
3434
attestations: Table[Slot, Table[Eth2Digest, PayloadAttestationEntry]]
3535

36-
proc init*(T: type PayloadAttestationPool, dag: ChainDAGRef): T =
36+
func init*(T: type PayloadAttestationPool, dag: ChainDAGRef): T =
3737
T(dag: dag)
3838

3939
func pruneOldEntries(pool: var PayloadAttestationPool, wallTime: BeaconTime) =
@@ -77,47 +77,29 @@ proc addPayloadAttestation*(
7777

7878
true
7979

80-
func findAllPtcPositions(
81-
ptc: seq[ValidatorIndex], validator_index: ValidatorIndex
82-
): seq[int] =
83-
# Find all positions where validator appears in the PTC
84-
var positions: seq[int]
85-
for i, ptc_member in ptc:
86-
if ptc_member == validator_index:
87-
positions.add(i)
88-
positions
89-
9080
proc aggregateMessages(
9181
pool: PayloadAttestationPool, slot: Slot,
92-
entry: ptr PayloadAttestationEntry, cache: var StateCache
82+
entry: var PayloadAttestationEntry, cache: var StateCache
9383
): Opt[PayloadAttestation] =
94-
## Aggregate individual messages into a single PayloadAttestation
9584

96-
if entry[].messages.len == 0:
85+
if entry.messages.len == 0:
9786
return Opt.none(PayloadAttestation)
9887

9988
withState(pool.dag.headState):
10089
when consensusFork >= ConsensusFork.Gloas:
101-
var ptc = newSeqOfCap[ValidatorIndex](PTC_SIZE)
102-
for validator_index in get_ptc(forkyState.data, slot, cache):
103-
ptc.add(validator_index)
104-
10590
var
106-
aggregation_bits = BitArray[int(PTC_SIZE)].init()
91+
aggregation_bits: BitArray[int(PTC_SIZE)]
10792
signatures: seq[CookedSig]
93+
ptc_index = 0
10894

109-
for validator_index, message in entry.messages:
110-
# Find all positions where this validator appears in PTC,
111-
# a single member might appear multiple times in a committee
112-
let ptc_positions = findAllPtcPositions(ptc, validator_index)
113-
114-
let cookedSig = message.signature.load().valueOr:
115-
continue
116-
117-
# set the aggregation bits and add the signature for each position
118-
for ptc_index in ptc_positions:
95+
let ptc_list = get_ptc_list(forkyState.data, slot, cache)
96+
for ptc_validator_index in ptc_list:
97+
entry.messages.withValue(ptc_validator_index, message):
98+
let cookedSig = message[].signature.load().valueOr:
99+
continue
119100
aggregation_bits[ptc_index] = true
120101
signatures.add(cookedSig)
102+
ptc_index += 1
121103

122104
if signatures.len == 0:
123105
return Opt.none(PayloadAttestation)
@@ -126,13 +108,13 @@ proc aggregateMessages(
126108
for i in 1..<signatures.len:
127109
aggregated_signature.aggregate(signatures[i])
128110

129-
return Opt.some(PayloadAttestation(
111+
Opt.some(PayloadAttestation(
130112
aggregation_bits: aggregation_bits,
131113
data: entry.data,
132114
signature: aggregated_signature.finish().toValidatorSig()
133115
))
134116
else:
135-
return Opt.none(PayloadAttestation)
117+
Opt.none(PayloadAttestation)
136118

137119
proc getAggregatedPayloadAttestation*(
138120
pool: var PayloadAttestationPool, slot: Slot,
@@ -143,7 +125,7 @@ proc getAggregatedPayloadAttestation*(
143125
pool.attestations.withValue(slot, slotEntries):
144126
slotEntries[].withValue(beacon_block_root, entry):
145127
if entry[].aggregated.isNone():
146-
entry[].aggregated = pool.aggregateMessages(slot, entry, cache)
128+
entry[].aggregated = pool.aggregateMessages(slot, entry[], cache)
147129
return entry[].aggregated
148130

149131
Opt.none(PayloadAttestation)

beacon_chain/spec/beaconstate.nim

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2761,7 +2761,7 @@ func can_advance_slots*(
27612761
withState(state): forkyState.can_advance_slots(block_root, target_slot)
27622762

27632763
# https://github.com/ethereum/consensus-specs/blob/v1.6.0-alpha.6/specs/gloas/beacon-chain.md#new-get_ptc
2764-
iterator get_ptc*(state: gloas.BeaconState, slot: Slot, cache: var StateCache):
2764+
iterator get_ptc(state: gloas.BeaconState, slot: Slot, cache: var StateCache):
27652765
ValidatorIndex =
27662766
## Get the payload timeliness committee for the given ``slot``
27672767
let epoch = slot.epoch()
@@ -2782,6 +2782,12 @@ iterator get_ptc*(state: gloas.BeaconState, slot: Slot, cache: var StateCache):
27822782
state, indices, seed, size=PTC_SIZE, shuffle_indices=false):
27832783
yield candidate_index
27842784

2785+
func get_ptc_list*(state: gloas.BeaconState, slot: Slot,
2786+
cache: var StateCache): seq[ValidatorIndex] =
2787+
# workaround for https://github.com/nim-lang/Nim/issues/25287
2788+
# TODO: Remove if issue gets fixed and use iterator directly
2789+
toSeq(get_ptc(state, slot, cache))
2790+
27852791
# https://github.com/ethereum/consensus-specs/blob/v1.6.0-alpha.6/specs/gloas/beacon-chain.md#new-get_indexed_payload_attestation
27862792
func get_indexed_payload_attestation*(
27872793
state: gloas.BeaconState, slot: Slot,

tests/test_payload_attestation_pool.nim

Lines changed: 53 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ import
1616
../beacon_chain/consensus_object_pools/[
1717
blockchain_dag, payload_attestation_pool, spec_cache],
1818
../beacon_chain/spec/[
19-
datatypes/gloas, forks, helpers, signatures, state_transition],
19+
forks, helpers, signatures, state_transition],
2020
../beacon_chain/beacon_clock,
2121
# Test utilities
22-
./testutil, ./testdbutil, ./testblockutil
22+
./testutil, ./testdbutil, ./testblockutil, ./consensus_spec/fixtures_utils
2323

24-
from ../beacon_chain/spec/beaconstate import get_ptc
24+
from ../beacon_chain/spec/beaconstate import get_ptc_list
2525

2626
proc makePayloadAttestationMessage(
2727
state: gloas.HashedBeaconState,
@@ -30,7 +30,8 @@ proc makePayloadAttestationMessage(
3030
privkey: ValidatorPrivKey,
3131
cache: var StateCache,
3232
payload_present: bool = true,
33-
blob_data_available: bool = true): PayloadAttestationMessage =
33+
blob_data_available: bool = true
34+
): PayloadAttestationMessage =
3435

3536
let
3637
slot = state.data.slot
@@ -58,22 +59,29 @@ proc makePayloadAttestationMessage(
5859

5960
suite "Payload attestation pool" & preset():
6061
setup:
62+
# Genesis state that results in 512 members in a committee
6163
let rng = HmacDrbgContext.new()
64+
const TOTAL_COMMITTEES = 1
6265
var
63-
cfg = defaultRuntimeConfig
66+
cfg = genesisTestRuntimeConfig(ConsensusFork.Gloas)
6467
validatorMonitor = newClone(ValidatorMonitor.init(cfg.timeParams))
6568
dag = init(
6669
ChainDAGRef, cfg,
67-
cfg.makeTestDB(128),
70+
cfg.makeTestDB(
71+
TOTAL_COMMITTEES * PTC_SIZE),
6872
validatorMonitor, {})
69-
pool = PayloadAttestationPool.init(dag)
73+
pool = newClone(PayloadAttestationPool.init(dag))
7074
state = newClone(dag.headState)
7175
cache = StateCache()
7276
info = ForkedEpochInfo()
73-
7477
check:
75-
process_slots(dag.cfg, state[], getStateField(state[], slot) + 2, cache,
76-
info, {}).isOk()
78+
process_slots(
79+
dag.cfg,
80+
state[],
81+
getStateField(state[], slot) + 1,
82+
cache,
83+
info,
84+
{}).isOk()
7785

7886
test "Can add and retrieve payload attestations" & preset():
7987
let
@@ -85,10 +93,10 @@ suite "Payload attestation pool" & preset():
8593
when consensusFork >= ConsensusFork.Gloas:
8694
var ptc_member: ValidatorIndex
8795
var found = false
88-
for validator_index in get_ptc(forkyState.data, slot, cache):
89-
ptc_member = validator_index
90-
found = true
91-
break
96+
for validator_index in get_ptc_list(forkyState.data, slot, cache):
97+
ptc_member = validator_index
98+
found = true
99+
break
92100

93101
check found
94102

@@ -97,13 +105,14 @@ suite "Payload attestation pool" & preset():
97105
message = makePayloadAttestationMessage(
98106
forkyState, beacon_block_root, ptc_member, privkey, cache)
99107

100-
check pool.addPayloadAttestation(message, wallTime)
108+
check pool[].addPayloadAttestation(message, wallTime)
101109

102110
# Should not be able to add the same attestation twice
103-
check not pool.addPayloadAttestation(message, wallTime)
111+
check not pool[].addPayloadAttestation(message, wallTime)
112+
113+
let aggregated = pool[].getAggregatedPayloadAttestation(
114+
slot, beacon_block_root, cache)
104115

105-
let aggregated = pool.getAggregatedPayloadAttestation(
106-
slot, beacon_block_root, cache)
107116
check aggregated.isSome()
108117
check aggregated.get().data == message.data
109118
check aggregated.get().aggregation_bits.countOnes() > 0
@@ -119,8 +128,7 @@ suite "Payload attestation pool" & preset():
119128
var messages: seq[PayloadAttestationMessage]
120129
var ptc_members: seq[ValidatorIndex]
121130

122-
# Get multiple validators from PTC
123-
for validator_index in get_ptc(forkyState.data, slot, cache):
131+
for validator_index in get_ptc_list(forkyState.data, slot, cache):
124132
if ptc_members.len >= 3:
125133
break
126134
ptc_members.add(validator_index)
@@ -133,9 +141,9 @@ suite "Payload attestation pool" & preset():
133141
message = makePayloadAttestationMessage(
134142
forkyState, beacon_block_root, ptc_member, privkey, cache)
135143
messages.add(message)
136-
check pool.addPayloadAttestation(message, wallTime)
144+
check pool[].addPayloadAttestation(message, wallTime)
137145

138-
let aggregated = pool.getAggregatedPayloadAttestation(
146+
let aggregated = pool[].getAggregatedPayloadAttestation(
139147
slot, beacon_block_root, cache)
140148
check aggregated.isSome()
141149
check aggregated.get().aggregation_bits.countOnes() >= ptc_members.len
@@ -148,18 +156,20 @@ suite "Payload attestation pool" & preset():
148156

149157
withState(state[]):
150158
when consensusFork >= ConsensusFork.Gloas:
151-
var validator_positions: Table[ValidatorIndex, seq[int]]
152-
var ptc_index = 0
159+
var
160+
validator_positions: Table[ValidatorIndex, seq[int]]
161+
ptc_index = 0
153162

154-
for validator_index in get_ptc(forkyState.data, slot, cache):
163+
for validator_index in get_ptc_list(forkyState.data, slot, cache):
155164
if validator_index notin validator_positions:
156165
validator_positions[validator_index] = @[]
157166
validator_positions[validator_index].add(ptc_index)
158167
ptc_index += 1
159168

160-
var multi_position_validator: ValidatorIndex
161-
var positions: seq[int]
162-
var found = false
169+
var
170+
multi_position_validator: ValidatorIndex
171+
positions: seq[int]
172+
found = false
163173

164174
for validator_index, position_list in validator_positions:
165175
if position_list.len > 1:
@@ -174,9 +184,9 @@ suite "Payload attestation pool" & preset():
174184
message = makePayloadAttestationMessage(
175185
forkyState, beacon_block_root, multi_position_validator, privkey, cache)
176186

177-
check pool.addPayloadAttestation(message, wallTime)
187+
check pool[].addPayloadAttestation(message, wallTime)
178188

179-
let aggregated = pool.getAggregatedPayloadAttestation(
189+
let aggregated = pool[].getAggregatedPayloadAttestation(
180190
slot, beacon_block_root, cache)
181191
check aggregated.isSome()
182192

@@ -194,17 +204,17 @@ suite "Payload attestation pool" & preset():
194204
withState(state[]):
195205
when consensusFork >= ConsensusFork.Gloas:
196206
var added_count = 0
197-
for validator_index in get_ptc(forkyState.data, slot, cache):
207+
for validator_index in get_ptc_list(forkyState.data, slot, cache):
198208
if added_count >= 2:
199209
break
200210
let
201211
privkey = MockPrivKeys[validator_index]
202212
message = makePayloadAttestationMessage(
203213
forkyState, beacon_block_root, validator_index, privkey, cache)
204-
check pool.addPayloadAttestation(message, wallTime)
214+
check pool[].addPayloadAttestation(message, wallTime)
205215
added_count += 1
206216

207-
let attestations = pool.getPayloadAttestationsForBlock(target_slot, cache)
217+
let attestations = pool[].getPayloadAttestationsForBlock(target_slot, cache)
208218
check attestations.len > 0
209219
check attestations[0].data.slot == slot
210220

@@ -213,12 +223,12 @@ suite "Payload attestation pool" & preset():
213223
slot = getStateField(state[], slot)
214224
beacon_block_root = withState(state[]): hash_tree_root(forkyState.data.latest_block_header)
215225
wallTime = slot.start_beacon_time(dag.cfg.timeParams)
216-
future_time = (slot + 5).start_beacon_time(dag.cfg.timeParams) # Much later
226+
future_time = (slot + 5).start_beacon_time(dag.cfg.timeParams)
217227

218228
withState(state[]):
219229
when consensusFork >= ConsensusFork.Gloas:
220230
var ptc_member: ValidatorIndex
221-
for validator_index in get_ptc(forkyState.data, slot, cache):
231+
for validator_index in get_ptc_list(forkyState.data, slot, cache):
222232
ptc_member = validator_index
223233
break
224234

@@ -228,13 +238,13 @@ suite "Payload attestation pool" & preset():
228238
forkyState, beacon_block_root, ptc_member, privkey, cache)
229239

230240
# Add attestation
231-
check pool.addPayloadAttestation(message, wallTime)
241+
check pool[].addPayloadAttestation(message, wallTime)
232242

233-
# Add another attestation at a future time (should automatically prune old ones)
234-
check pool.addPayloadAttestation(message, future_time)
243+
# Add another attestation at a future time (should trigger pruning)
244+
check pool[].addPayloadAttestation(message, future_time)
235245

236246
# Old attestation should no longer be retrievable
237-
let attestations = pool.getPayloadAttestationsForBlock(slot + 6, cache)
247+
let attestations = pool[].getPayloadAttestationsForBlock(slot + 6, cache)
238248
check attestations.len == 0
239249

240250
test "Different payload presence values" & preset():
@@ -246,7 +256,7 @@ suite "Payload attestation pool" & preset():
246256
withState(state[]):
247257
when consensusFork >= ConsensusFork.Gloas:
248258
var ptc_members: seq[ValidatorIndex]
249-
for validator_index in get_ptc(forkyState.data, slot, cache):
259+
for validator_index in get_ptc_list(forkyState.data, slot, cache):
250260
if ptc_members.len >= 2:
251261
break
252262
ptc_members.add(validator_index)
@@ -263,10 +273,9 @@ suite "Payload attestation pool" & preset():
263273
MockPrivKeys[ptc_members[1]], cache,
264274
payload_present = false, blob_data_available = false)
265275

266-
check pool.addPayloadAttestation(message1, wallTime)
267-
check pool.addPayloadAttestation(message2, wallTime)
276+
check pool[].addPayloadAttestation(message1, wallTime)
277+
check pool[].addPayloadAttestation(message2, wallTime)
268278

269279
let
270-
agg1 = pool.getAggregatedPayloadAttestation(slot, beacon_block_root, cache)
271-
280+
agg1 = pool[].getAggregatedPayloadAttestation(slot, beacon_block_root, cache)
272281
check agg1.isSome()

0 commit comments

Comments
 (0)