Skip to content

Commit 95f590c

Browse files
authored
fix incorrect indexing of attestationdata in attestationpool (#7037)
1 parent 23430ff commit 95f590c

File tree

4 files changed

+63
-22
lines changed

4 files changed

+63
-22
lines changed

AllTests-mainnet.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ AllTests-mainnet
1111
+ Attestations with disjoint comittee bits and equal data into single on-chain aggregate [Pr OK
1212
+ Can add and retrieve simple electra attestations [Preset: mainnet] OK
1313
+ Working with electra aggregates [Preset: mainnet] OK
14+
+ simple add and get with electra nonzero committee [Preset: mainnet] OK
1415
```
1516
## Attestation pool processing [Preset: mainnet]
1617
```diff

beacon_chain/consensus_object_pools/attestation_pool.nim

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
{.push raises: [].}
99

1010
import
11-
std/algorithm,
1211
# Status libraries
1312
metrics,
1413
chronicles, stew/byteutils,
@@ -19,6 +18,7 @@ import
1918
../fork_choice/fork_choice,
2019
../beacon_clock
2120

21+
from std/algorithm import sort
2222
from std/sequtils import keepItIf, maxIndex
2323

2424
export blockchain_dag, fork_choice
@@ -418,6 +418,11 @@ proc addAttestation(
418418
419419
true
420420
421+
func getAttestationCandidateKey(
422+
attestationDataRoot: Eth2Digest, committee_index: CommitteeIndex):
423+
Eth2Digest =
424+
hash_tree_root([attestationDataRoot, hash_tree_root(committee_index.uint64)])
425+
421426
func getAttestationCandidateKey(
422427
data: AttestationData,
423428
committee_index: Opt[CommitteeIndex]): Eth2Digest =
@@ -429,13 +434,7 @@ func getAttestationCandidateKey(
429434
# i.e. no committees selected, so it can't be an actual Electra attestation
430435
hash_tree_root(data)
431436
else:
432-
hash_tree_root([hash_tree_root(data),
433-
hash_tree_root(committee_index.get.uint64)])
434-
435-
func getAttestationCandidateKey(
436-
attestationDataRoot: Eth2Digest, committee_index: CommitteeIndex):
437-
Eth2Digest =
438-
hash_tree_root([attestationDataRoot, hash_tree_root(committee_index.uint64)])
437+
getAttestationCandidateKey(hash_tree_root(data), committee_index.get)
439438

440439
proc addAttestation*(
441440
pool: var AttestationPool,
@@ -476,14 +475,20 @@ proc addAttestation*(
476475
# creating an unnecessary AttestationEntry on the hot path and avoiding
477476
# multiple lookups
478477
template addAttToPool(attCandidates: untyped, entry: untyped, committee_index: untyped) =
479-
let attestation_data_root = getAttestationCandidateKey(entry.data, committee_index)
480-
481-
attCandidates[candidateIdx.get()].withValue(attestation_data_root, entry) do:
478+
# `AttestationData.index == 0` in Electra, but the attestation pool always
479+
# represents an AttestationEntry regardless as having the actual committee
480+
# index. The entry, therefore, is not the same as the AttestationData, and
481+
# thus cannot function as the basis for deriving the hashtable key for the
482+
# entry. Instead use the (correctly data.index == 0) attestation passed to
483+
# addAttestation.
484+
let candidate_key = getAttestationCandidateKey(attestation.data, committee_index)
485+
486+
attCandidates[candidateIdx.get()].withValue(candidate_key, entry) do:
482487
if not addAttestation(entry[], attestation, index_in_committee, signature):
483488
return
484489
do:
485490
if not addAttestation(
486-
attCandidates[candidateIdx.get()].mgetOrPut(attestation_data_root, entry),
491+
attCandidates[candidateIdx.get()].mgetOrPut(candidate_key, entry),
487492
attestation, index_in_committee, signature):
488493
# Returns from overall function, not only template
489494
return

tests/test_attestation_pool.nim

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,22 @@
1111
import
1212
# Status lib
1313
unittest2,
14-
chronicles, chronos,
15-
stew/[byteutils, endians2],
16-
taskpools,
14+
chronicles,
1715
# Internal
18-
../beacon_chain/gossip_processing/[gossip_validation],
19-
../beacon_chain/fork_choice/[fork_choice_types, fork_choice],
2016
../beacon_chain/consensus_object_pools/[
21-
block_quarantine, blockchain_dag, block_clearance, attestation_pool],
22-
../beacon_chain/spec/[beaconstate, helpers, state_transition, validator],
17+
blockchain_dag, block_clearance, attestation_pool],
18+
../beacon_chain/spec/[state_transition, validator],
2319
../beacon_chain/beacon_clock,
2420
# Test utilities
2521
./testutil, ./testdbutil, ./testblockutil, ./consensus_spec/fixtures_utils
2622

2723
from std/sequtils import mapIt, toSeq
24+
from stew/byteutils import `<`
25+
from ../beacon_chain/consensus_object_pools/block_quarantine import
26+
Quarantine, init
27+
from ../beacon_chain/spec/beaconstate import
28+
attester_dependent_root, check_attestation, get_attesting_indices,
29+
latest_block_root
2830
from ./testbcutil import addHeadBlock
2931

3032
func combine(tgt: var (phase0.Attestation | electra.Attestation),
@@ -873,8 +875,7 @@ suite "Attestation pool electra processing" & preset():
873875
get().aggregation_bits.countOnes() == 2
874876
# requests to get and aggregate from different committees should be empty
875877
pool[].getElectraAggregatedAttestation(
876-
2.Slot, combined[0].data.beacon_block_root, 1.CommitteeIndex).isNone()
877-
878+
2.Slot, hash_tree_root(combined[0].data), 1.CommitteeIndex).isNone()
878879

879880
test "Attestations with disjoint comittee bits and equal data into single on-chain aggregate" & preset():
880881
let
@@ -1176,3 +1177,37 @@ suite "Attestation pool electra processing" & preset():
11761177
state[].electraData.data, attestations[1], {}, cache, true).isOk
11771178
pool[].verifyAttestationSignature(state, cache, attestations[0])
11781179
pool[].verifyAttestationSignature(state, cache, attestations[1])
1180+
1181+
test "simple add and get with electra nonzero committee" & preset():
1182+
let
1183+
bc0 = get_beacon_committee(
1184+
state[], getStateField(state[], slot), 0.CommitteeIndex, cache)
1185+
1186+
bc1 = get_beacon_committee(
1187+
state[], getStateField(state[], slot), 1.CommitteeIndex, cache)
1188+
1189+
attestation_1 = makeElectraAttestation(
1190+
state[], state[].latest_block_root, bc0[0], cache)
1191+
1192+
attestation_2 = makeElectraAttestation(
1193+
state[], state[].latest_block_root, bc1[0], cache)
1194+
1195+
pool[].addAttestation(
1196+
attestation_1, @[bc0[0]], attestation_1.aggregation_bits.len,
1197+
attestation_1.loadSig, attestation_1.data.slot.start_beacon_time)
1198+
1199+
pool[].addAttestation(
1200+
attestation_2, @[bc1[0]], attestation_2.aggregation_bits.len,
1201+
attestation_2.loadSig, attestation_2.data.slot.start_beacon_time)
1202+
1203+
check:
1204+
process_slots(
1205+
defaultRuntimeConfig, state[],
1206+
getStateField(state[], slot) + MIN_ATTESTATION_INCLUSION_DELAY, cache,
1207+
info, {}).isOk()
1208+
1209+
check:
1210+
pool[].getElectraAggregatedAttestation(1.Slot, hash_tree_root(attestation_1.data),
1211+
0.CommitteeIndex).isOk
1212+
pool[].getElectraAggregatedAttestation(1.Slot, hash_tree_root(attestation_2.data),
1213+
1.CommitteeIndex).isOk

tests/test_mev_calls.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
{.used.}
1010

1111
import
12-
stew/[bitseqs, endians2, objects, byteutils],
12+
stew/[bitseqs, endians2, objects],
1313
blscurve, bearssl/rand,
1414
results, chronos, presto, unittest2,
1515
chronos/unittest2/asynctests,

0 commit comments

Comments
 (0)