attestation and aggregated attestation BN fixes for Electra (#6641)
* attestation and aggregated attestation BN fixes for Electra * disable electra transition for this PR * use cleaned-up verification function everywhere
This commit is contained in:
parent
e9e0149d55
commit
c01cf6601a
2
Makefile
2
Makefile
|
@ -92,8 +92,6 @@ TOOLS_CSV := $(subst $(SPACE),$(COMMA),$(TOOLS))
|
||||||
deps \
|
deps \
|
||||||
update \
|
update \
|
||||||
test \
|
test \
|
||||||
clean_eth2_network_simulation_all \
|
|
||||||
eth2_network_simulation \
|
|
||||||
clean \
|
clean \
|
||||||
libbacktrace \
|
libbacktrace \
|
||||||
book \
|
book \
|
||||||
|
|
|
@ -394,17 +394,21 @@ proc addAttestation(
|
||||||
|
|
||||||
func getAttestationCandidateKey(
|
func getAttestationCandidateKey(
|
||||||
data: AttestationData,
|
data: AttestationData,
|
||||||
committee_bits: AttestationCommitteeBits =
|
committee_index: Opt[CommitteeIndex]): Eth2Digest =
|
||||||
default(AttestationCommitteeBits)): Eth2Digest =
|
|
||||||
# Some callers might have used for the key just htr(data), so rather than
|
# Some callers might have used for the key just htr(data), so rather than
|
||||||
# risk some random regression (one was caught in test suite, but there is
|
# risk some random regression (one was caught in test suite, but there is
|
||||||
# not any particular reason other code could not have manually calculated
|
# not any particular reason other code could not have manually calculated
|
||||||
# the key, too), special-case the phase0 case as htr(data).
|
# the key, too), special-case the phase0 case as htr(data).
|
||||||
if committee_bits == static(default(typeof(committee_bits))):
|
if committee_index.isNone:
|
||||||
# i.e. no committees selected, so it can't be an actual Electra attestation
|
# i.e. no committees selected, so it can't be an actual Electra attestation
|
||||||
hash_tree_root(data)
|
hash_tree_root(data)
|
||||||
else:
|
else:
|
||||||
hash_tree_root([hash_tree_root(data), hash_tree_root(committee_bits)])
|
hash_tree_root([hash_tree_root(data), hash_tree_root(committee_index.get.uint64)])
|
||||||
|
|
||||||
|
func getAttestationCandidateKey(
|
||||||
|
attestationDataRoot: Eth2Digest, committee_index: CommitteeIndex):
|
||||||
|
Eth2Digest =
|
||||||
|
hash_tree_root([attestationDataRoot, hash_tree_root(committee_index.uint64)])
|
||||||
|
|
||||||
proc addAttestation*(
|
proc addAttestation*(
|
||||||
pool: var AttestationPool,
|
pool: var AttestationPool,
|
||||||
|
@ -437,8 +441,8 @@ proc addAttestation*(
|
||||||
# TODO withValue is an abomination but hard to use anything else too without
|
# TODO withValue is an abomination but hard to use anything else too without
|
||||||
# creating an unnecessary AttestationEntry on the hot path and avoiding
|
# creating an unnecessary AttestationEntry on the hot path and avoiding
|
||||||
# multiple lookups
|
# multiple lookups
|
||||||
template addAttToPool(attCandidates: untyped, entry: untyped) =
|
template addAttToPool(attCandidates: untyped, entry: untyped, committee_index: untyped) =
|
||||||
let attestation_data_root = hash_tree_root(entry.data)
|
let attestation_data_root = getAttestationCandidateKey(entry.data, committee_index)
|
||||||
|
|
||||||
attCandidates[candidateIdx.get()].withValue(attestation_data_root, entry) do:
|
attCandidates[candidateIdx.get()].withValue(attestation_data_root, entry) do:
|
||||||
if not addAttestation(entry[], attestation, signature):
|
if not addAttestation(entry[], attestation, signature):
|
||||||
|
@ -453,7 +457,7 @@ proc addAttestation*(
|
||||||
template addAttToPool(_: phase0.Attestation) {.used.} =
|
template addAttToPool(_: phase0.Attestation) {.used.} =
|
||||||
let newAttEntry = Phase0AttestationEntry(
|
let newAttEntry = Phase0AttestationEntry(
|
||||||
data: attestation.data, committee_len: attestation.aggregation_bits.len)
|
data: attestation.data, committee_len: attestation.aggregation_bits.len)
|
||||||
addAttToPool(pool.phase0Candidates, newAttEntry)
|
addAttToPool(pool.phase0Candidates, newAttEntry, Opt.none CommitteeIndex)
|
||||||
pool.addForkChoiceVotes(
|
pool.addForkChoiceVotes(
|
||||||
attestation.data.slot, attesting_indices,
|
attestation.data.slot, attesting_indices,
|
||||||
attestation.data.beacon_block_root, wallTime)
|
attestation.data.beacon_block_root, wallTime)
|
||||||
|
@ -474,7 +478,7 @@ proc addAttestation*(
|
||||||
let newAttEntry = ElectraAttestationEntry(
|
let newAttEntry = ElectraAttestationEntry(
|
||||||
data: data,
|
data: data,
|
||||||
committee_len: attestation.aggregation_bits.len)
|
committee_len: attestation.aggregation_bits.len)
|
||||||
addAttToPool(pool.electraCandidates, newAttEntry)
|
addAttToPool(pool.electraCandidates, newAttEntry, Opt.some committee_index)
|
||||||
pool.addForkChoiceVotes(
|
pool.addForkChoiceVotes(
|
||||||
attestation.data.slot, attesting_indices,
|
attestation.data.slot, attesting_indices,
|
||||||
attestation.data.beacon_block_root, wallTime)
|
attestation.data.beacon_block_root, wallTime)
|
||||||
|
@ -497,7 +501,7 @@ func covers*(
|
||||||
return false
|
return false
|
||||||
|
|
||||||
pool.phase0Candidates[candidateIdx.get()].withValue(
|
pool.phase0Candidates[candidateIdx.get()].withValue(
|
||||||
getAttestationCandidateKey(data), entry):
|
getAttestationCandidateKey(data, Opt.none CommitteeIndex), entry):
|
||||||
if entry[].covers(bits):
|
if entry[].covers(bits):
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
@ -955,7 +959,11 @@ proc getElectraAttestationsForBlock*(
|
||||||
# and score possible on-chain attestations while collecting candidates
|
# and score possible on-chain attestations while collecting candidates
|
||||||
# (previous loop) and reavaluate cache key definition
|
# (previous loop) and reavaluate cache key definition
|
||||||
let
|
let
|
||||||
key = (entry.data.beacon_block_root, entry.data.slot)
|
entry2 = block:
|
||||||
|
var e2 = entry.data
|
||||||
|
e2.index = 0
|
||||||
|
e2
|
||||||
|
key = (hash_tree_root(entry2), entry.data.slot)
|
||||||
newAtt = entry[].toElectraAttestation(entry[].aggregates[j])
|
newAtt = entry[].toElectraAttestation(entry[].aggregates[j])
|
||||||
|
|
||||||
candidatesPerBlock.withValue(key, candidate):
|
candidatesPerBlock.withValue(key, candidate):
|
||||||
|
@ -988,25 +996,22 @@ proc getElectraAttestationsForBlock*(
|
||||||
# Sort candidates by score use slot as a tie-breaker
|
# Sort candidates by score use slot as a tie-breaker
|
||||||
candidates.sort()
|
candidates.sort()
|
||||||
|
|
||||||
# Consolidate attestation aggregates with disjoint comittee bits into single
|
# Consolidate attestation aggregates with disjoint committee bits into single
|
||||||
# attestation
|
# attestation
|
||||||
var res: seq[electra.Attestation]
|
var res: seq[electra.Attestation]
|
||||||
for a in candidatesPerBlock.values():
|
for a in candidatesPerBlock.values():
|
||||||
|
|
||||||
if a.len > 1:
|
if a.len > 1:
|
||||||
let
|
let att = compute_on_chain_aggregate(a).valueOr:
|
||||||
att = compute_on_chain_aggregate(a).valueOr:
|
|
||||||
continue
|
continue
|
||||||
res.add(att)
|
res.add(att)
|
||||||
#no on chain candidates
|
# no on-chain candidates
|
||||||
else:
|
else:
|
||||||
res.add(a)
|
res.add(a)
|
||||||
|
|
||||||
if res.lenu64 == MAX_ATTESTATIONS_ELECTRA:
|
if res.lenu64 == MAX_ATTESTATIONS_ELECTRA:
|
||||||
break
|
break
|
||||||
|
|
||||||
let
|
let packingDur = Moment.now() - startPackingTick
|
||||||
packingDur = Moment.now() - startPackingTick
|
|
||||||
|
|
||||||
debug "Packed attestations for block",
|
debug "Packed attestations for block",
|
||||||
newBlockSlot, packingDur, totalCandidates, attestations = res.len()
|
newBlockSlot, packingDur, totalCandidates, attestations = res.len()
|
||||||
|
@ -1051,8 +1056,7 @@ func getElectraAggregatedAttestation*(
|
||||||
return Opt.none(electra.Attestation)
|
return Opt.none(electra.Attestation)
|
||||||
|
|
||||||
pool.electraCandidates[candidateIdx.get].withValue(
|
pool.electraCandidates[candidateIdx.get].withValue(
|
||||||
attestationDataRoot, entry):
|
getAttestationCandidateKey(attestationDataRoot, committeeIndex), entry):
|
||||||
|
|
||||||
if entry.data.index == committeeIndex.distinctBase:
|
if entry.data.index == committeeIndex.distinctBase:
|
||||||
entry[].updateAggregates()
|
entry[].updateAggregates()
|
||||||
|
|
||||||
|
|
|
@ -237,7 +237,7 @@ func get_attesting_indices_one*(shufflingRef: ShufflingRef,
|
||||||
Opt[ValidatorIndex] =
|
Opt[ValidatorIndex] =
|
||||||
# A variation on get_attesting_indices that returns the validator index only
|
# A variation on get_attesting_indices that returns the validator index only
|
||||||
# if only one validator index is set
|
# if only one validator index is set
|
||||||
static: doAssert not on_chain, "only on_chain supported"
|
static: doAssert not on_chain, "only not on_chain supported"
|
||||||
|
|
||||||
var res = Opt.none(ValidatorIndex)
|
var res = Opt.none(ValidatorIndex)
|
||||||
let committee_index = ? get_committee_index_one(committee_bits)
|
let committee_index = ? get_committee_index_one(committee_bits)
|
||||||
|
|
|
@ -577,13 +577,22 @@ proc compute_on_chain_aggregate*(
|
||||||
for i, a in aggregates:
|
for i, a in aggregates:
|
||||||
totalLen += a.aggregation_bits.len
|
totalLen += a.aggregation_bits.len
|
||||||
|
|
||||||
|
# TODO doesn't work if a committee is skipped
|
||||||
var aggregation_bits = ElectraCommitteeValidatorsBits.init(totalLen)
|
var aggregation_bits = ElectraCommitteeValidatorsBits.init(totalLen)
|
||||||
var pos = 0
|
var pos = 0
|
||||||
|
var prev_committee_index: Opt[CommitteeIndex]
|
||||||
for i, a in aggregates:
|
for i, a in aggregates:
|
||||||
let
|
let
|
||||||
committee_index = ? get_committee_index_one(a.committee_bits)
|
committee_index = ? get_committee_index_one(a.committee_bits)
|
||||||
first = pos == 0
|
first = pos == 0
|
||||||
|
|
||||||
|
when false:
|
||||||
|
if prev_committee_index.isNone:
|
||||||
|
prev_committee_index = Opt.some committee_index
|
||||||
|
elif committee_index.distinctBase <= prev_committee_index.get.distinctBase:
|
||||||
|
continue
|
||||||
|
prev_committee_index = Opt.some committee_index
|
||||||
|
|
||||||
for b in a.aggregation_bits:
|
for b in a.aggregation_bits:
|
||||||
aggregation_bits[pos] = b
|
aggregation_bits[pos] = b
|
||||||
pos += 1
|
pos += 1
|
||||||
|
|
|
@ -1592,7 +1592,7 @@ proc signAndSendAggregate(
|
||||||
if not is_aggregator(shufflingRef, slot, committee_index, selectionProof):
|
if not is_aggregator(shufflingRef, slot, committee_index, selectionProof):
|
||||||
return
|
return
|
||||||
|
|
||||||
template signAndSendAggregate() =
|
template signAndSendAggregatedAttestations() =
|
||||||
msg.signature = block:
|
msg.signature = block:
|
||||||
let res = await validator.getAggregateAndProofSignature(
|
let res = await validator.getAggregateAndProofSignature(
|
||||||
fork, genesis_validators_root, msg.message)
|
fork, genesis_validators_root, msg.message)
|
||||||
|
@ -1612,22 +1612,20 @@ proc signAndSendAggregate(
|
||||||
if node.dag.cfg.consensusForkAtEpoch(slot.epoch) >= ConsensusFork.Electra:
|
if node.dag.cfg.consensusForkAtEpoch(slot.epoch) >= ConsensusFork.Electra:
|
||||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/specs/electra/validator.md#construct-aggregate
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/specs/electra/validator.md#construct-aggregate
|
||||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/specs/electra/validator.md#aggregateandproof
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/specs/electra/validator.md#aggregateandproof
|
||||||
var
|
var msg = electra.SignedAggregateAndProof(
|
||||||
msg = electra.SignedAggregateAndProof(
|
|
||||||
message: electra.AggregateAndProof(
|
message: electra.AggregateAndProof(
|
||||||
aggregator_index: distinctBase validator_index,
|
aggregator_index: distinctBase validator_index,
|
||||||
selection_proof: selectionProof))
|
selection_proof: selectionProof))
|
||||||
|
|
||||||
msg.message.aggregate = node.attestationPool[].getElectraAggregatedAttestation(
|
msg.message.aggregate = node.attestationPool[].getElectraAggregatedAttestation(
|
||||||
slot, default(Eth2Digest), committee_index).valueOr:
|
slot, committee_index).valueOr:
|
||||||
return
|
return
|
||||||
|
|
||||||
signAndSendAggregate()
|
signAndSendAggregatedAttestations()
|
||||||
else:
|
else:
|
||||||
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/specs/phase0/validator.md#construct-aggregate
|
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/specs/phase0/validator.md#construct-aggregate
|
||||||
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/validator.md#aggregateandproof
|
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/phase0/validator.md#aggregateandproof
|
||||||
var
|
var msg = phase0.SignedAggregateAndProof(
|
||||||
msg = phase0.SignedAggregateAndProof(
|
|
||||||
message: phase0.AggregateAndProof(
|
message: phase0.AggregateAndProof(
|
||||||
aggregator_index: distinctBase validator_index,
|
aggregator_index: distinctBase validator_index,
|
||||||
selection_proof: selectionProof))
|
selection_proof: selectionProof))
|
||||||
|
@ -1636,7 +1634,7 @@ proc signAndSendAggregate(
|
||||||
slot, committee_index).valueOr:
|
slot, committee_index).valueOr:
|
||||||
return
|
return
|
||||||
|
|
||||||
signAndSendAggregate()
|
signAndSendAggregatedAttestations()
|
||||||
|
|
||||||
proc sendAggregatedAttestations(
|
proc sendAggregatedAttestations(
|
||||||
node: BeaconNode, head: BlockRef, slot: Slot) =
|
node: BeaconNode, head: BlockRef, slot: Slot) =
|
||||||
|
|
|
@ -104,7 +104,7 @@ DL_GETH="0"
|
||||||
|
|
||||||
: ${BEACON_NODE_COMMAND:="./build/nimbus_beacon_node$EXE_EXTENSION"}
|
: ${BEACON_NODE_COMMAND:="./build/nimbus_beacon_node$EXE_EXTENSION"}
|
||||||
: ${DENEB_FORK_EPOCH:=0}
|
: ${DENEB_FORK_EPOCH:=0}
|
||||||
: ${ELECTRA_FORK_EPOCH:=5000}
|
: ${ELECTRA_FORK_EPOCH:=500}
|
||||||
|
|
||||||
#NIMBUS EL VARS
|
#NIMBUS EL VARS
|
||||||
RUN_NIMBUS_ETH1="0"
|
RUN_NIMBUS_ETH1="0"
|
||||||
|
@ -216,6 +216,10 @@ while true; do
|
||||||
DENEB_FORK_EPOCH="$2"
|
DENEB_FORK_EPOCH="$2"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
|
--electra-fork-epoch)
|
||||||
|
ELECTRA_FORK_EPOCH="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
--stop-at-epoch)
|
--stop-at-epoch)
|
||||||
STOP_AT_EPOCH=$2
|
STOP_AT_EPOCH=$2
|
||||||
STOP_AT_EPOCH_FLAG="--debug-stop-at-epoch=$2"
|
STOP_AT_EPOCH_FLAG="--debug-stop-at-epoch=$2"
|
||||||
|
|
|
@ -24,7 +24,7 @@ import
|
||||||
# Test utilities
|
# Test utilities
|
||||||
./testutil, ./testdbutil, ./testblockutil, ./consensus_spec/fixtures_utils
|
./testutil, ./testdbutil, ./testblockutil, ./consensus_spec/fixtures_utils
|
||||||
|
|
||||||
from std/sequtils import toSeq
|
from std/sequtils import mapIt, toSeq
|
||||||
from ./testbcutil import addHeadBlock
|
from ./testbcutil import addHeadBlock
|
||||||
|
|
||||||
func combine(tgt: var (phase0.Attestation | electra.Attestation),
|
func combine(tgt: var (phase0.Attestation | electra.Attestation),
|
||||||
|
@ -898,8 +898,21 @@ suite "Attestation pool electra processing" & preset():
|
||||||
attestations[0].aggregation_bits.countOnes() == 2
|
attestations[0].aggregation_bits.countOnes() == 2
|
||||||
attestations[0].committee_bits.countOnes() == 2
|
attestations[0].committee_bits.countOnes() == 2
|
||||||
|
|
||||||
|
|
||||||
test "Aggregated attestations with disjoint comittee bits into a single on-chain aggregate" & preset():
|
test "Aggregated attestations with disjoint comittee bits into a single on-chain aggregate" & preset():
|
||||||
|
proc verifyAttestationSignature(attestation: electra.Attestation): bool =
|
||||||
|
withState(state[]):
|
||||||
|
when consensusFork == ConsensusFork.Electra:
|
||||||
|
let
|
||||||
|
fork = pool.dag.cfg.forkAtEpoch(forkyState.data.slot.epoch)
|
||||||
|
attesting_indices = get_attesting_indices(
|
||||||
|
forkyState.data, attestation.data, attestation.aggregation_bits,
|
||||||
|
attestation.committee_bits, cache)
|
||||||
|
verify_attestation_signature(
|
||||||
|
fork, pool.dag.genesis_validators_root, attestation.data,
|
||||||
|
attesting_indices.mapIt(forkyState.data.validators.item(it).pubkey),
|
||||||
|
attestation.signature)
|
||||||
|
else:
|
||||||
|
raiseAssert "must be electra"
|
||||||
|
|
||||||
let
|
let
|
||||||
bc0 = get_beacon_committee(
|
bc0 = get_beacon_committee(
|
||||||
|
@ -921,6 +934,11 @@ suite "Attestation pool electra processing" & preset():
|
||||||
attestation_3 = makeElectraAttestation(
|
attestation_3 = makeElectraAttestation(
|
||||||
state[], state[].latest_block_root, bc1[1], cache)
|
state[], state[].latest_block_root, bc1[1], cache)
|
||||||
|
|
||||||
|
check:
|
||||||
|
verifyAttestationSignature(attestation_1)
|
||||||
|
verifyAttestationSignature(attestation_2)
|
||||||
|
verifyAttestationSignature(attestation_3)
|
||||||
|
|
||||||
pool[].addAttestation(
|
pool[].addAttestation(
|
||||||
attestation_1, @[bc0[0]], attestation_1.loadSig,
|
attestation_1, @[bc0[0]], attestation_1.loadSig,
|
||||||
attestation_1.data.slot.start_beacon_time)
|
attestation_1.data.slot.start_beacon_time)
|
||||||
|
@ -942,6 +960,8 @@ suite "Attestation pool electra processing" & preset():
|
||||||
let attestations = pool[].getElectraAttestationsForBlock(state[], cache)
|
let attestations = pool[].getElectraAttestationsForBlock(state[], cache)
|
||||||
|
|
||||||
check:
|
check:
|
||||||
|
verifyAttestationSignature(attestations[0])
|
||||||
|
|
||||||
# A single final chain aggregated attestation should be created
|
# A single final chain aggregated attestation should be created
|
||||||
# with same data, 2 committee bits and 3 aggregation bits
|
# with same data, 2 committee bits and 3 aggregation bits
|
||||||
attestations.len == 1
|
attestations.len == 1
|
||||||
|
@ -966,11 +986,35 @@ suite "Attestation pool electra processing" & preset():
|
||||||
att3 = makeElectraAttestation(
|
att3 = makeElectraAttestation(
|
||||||
state[], state[].latest_block_root, bc0[3], cache)
|
state[], state[].latest_block_root, bc0[3], cache)
|
||||||
|
|
||||||
|
proc verifyAttestationSignature(attestation: electra.Attestation): bool =
|
||||||
|
withState(state[]):
|
||||||
|
when consensusFork == ConsensusFork.Electra:
|
||||||
|
let
|
||||||
|
fork = pool.dag.cfg.forkAtEpoch(forkyState.data.slot.epoch)
|
||||||
|
attesting_indices = get_attesting_indices(
|
||||||
|
forkyState.data, attestation.data, attestation.aggregation_bits,
|
||||||
|
attestation.committee_bits, cache)
|
||||||
|
verify_attestation_signature(
|
||||||
|
fork, pool.dag.genesis_validators_root, attestation.data,
|
||||||
|
attesting_indices.mapIt(forkyState.data.validators.item(it).pubkey),
|
||||||
|
attestation.signature)
|
||||||
|
else:
|
||||||
|
raiseAssert "must be electra"
|
||||||
|
|
||||||
|
check:
|
||||||
|
verifyAttestationSignature(att0)
|
||||||
|
verifyAttestationSignature(att0x)
|
||||||
|
verifyAttestationSignature(att1)
|
||||||
|
verifyAttestationSignature(att2)
|
||||||
|
verifyAttestationSignature(att3)
|
||||||
|
|
||||||
# Both attestations include member 2 but neither is a subset of the other
|
# Both attestations include member 2 but neither is a subset of the other
|
||||||
att0.combine(att2)
|
att0.combine(att2)
|
||||||
att1.combine(att2)
|
att1.combine(att2)
|
||||||
|
|
||||||
check:
|
check:
|
||||||
|
verifyAttestationSignature(att0)
|
||||||
|
verifyAttestationSignature(att1)
|
||||||
not pool[].covers(att0.data, att0.aggregation_bits)
|
not pool[].covers(att0.data, att0.aggregation_bits)
|
||||||
|
|
||||||
pool[].addAttestation(
|
pool[].addAttestation(
|
||||||
|
@ -978,17 +1022,23 @@ suite "Attestation pool electra processing" & preset():
|
||||||
pool[].addAttestation(
|
pool[].addAttestation(
|
||||||
att1, @[bc0[1], bc0[2]], att1.loadSig, att1.data.slot.start_beacon_time)
|
att1, @[bc0[1], bc0[2]], att1.loadSig, att1.data.slot.start_beacon_time)
|
||||||
|
|
||||||
|
for att in pool[].electraAttestations(Opt.none Slot, Opt.none CommitteeIndex):
|
||||||
|
check: verifyAttestationSignature(att)
|
||||||
|
|
||||||
check:
|
check:
|
||||||
process_slots(
|
process_slots(
|
||||||
defaultRuntimeConfig, state[],
|
defaultRuntimeConfig, state[],
|
||||||
getStateField(state[], slot) + MIN_ATTESTATION_INCLUSION_DELAY, cache,
|
getStateField(state[], slot) + MIN_ATTESTATION_INCLUSION_DELAY, cache,
|
||||||
info, {}).isOk()
|
info, {}).isOk()
|
||||||
|
|
||||||
|
for att in pool[].electraAttestations(Opt.none Slot, Opt.none CommitteeIndex):
|
||||||
|
check: verifyAttestationSignature(att)
|
||||||
|
|
||||||
check:
|
check:
|
||||||
pool[].getElectraAttestationsForBlock(state[], cache).len() == 1
|
pool[].getElectraAttestationsForBlock(state[], cache).len() == 1
|
||||||
# Can get either aggregate here, random!
|
# Can get either aggregate here, random!
|
||||||
pool[].getElectraAggregatedAttestation(
|
verifyAttestationSignature(pool[].getElectraAggregatedAttestation(
|
||||||
1.Slot, hash_tree_root(att0.data), 0.CommitteeIndex).isSome()
|
1.Slot, hash_tree_root(att0.data), 0.CommitteeIndex).get)
|
||||||
|
|
||||||
# Add in attestation 3 - both aggregates should now have it added
|
# Add in attestation 3 - both aggregates should now have it added
|
||||||
pool[].addAttestation(
|
pool[].addAttestation(
|
||||||
|
@ -999,6 +1049,7 @@ suite "Attestation pool electra processing" & preset():
|
||||||
check:
|
check:
|
||||||
attestations.len() == 1
|
attestations.len() == 1
|
||||||
attestations[0].aggregation_bits.countOnes() == 6
|
attestations[0].aggregation_bits.countOnes() == 6
|
||||||
|
#TODO: verifyAttestationSignature(attestations[0]) fails
|
||||||
# Can get either aggregate here, random!
|
# Can get either aggregate here, random!
|
||||||
pool[].getElectraAggregatedAttestation(
|
pool[].getElectraAggregatedAttestation(
|
||||||
1.Slot, hash_tree_root(attestations[0].data), 0.CommitteeIndex).isSome()
|
1.Slot, hash_tree_root(attestations[0].data), 0.CommitteeIndex).isSome()
|
||||||
|
@ -1013,6 +1064,7 @@ suite "Attestation pool electra processing" & preset():
|
||||||
check:
|
check:
|
||||||
attestations.len() == 1
|
attestations.len() == 1
|
||||||
attestations[0].aggregation_bits.countOnes() == 4
|
attestations[0].aggregation_bits.countOnes() == 4
|
||||||
|
verifyAttestationSignature(attestations[0])
|
||||||
pool[].getElectraAggregatedAttestation(
|
pool[].getElectraAggregatedAttestation(
|
||||||
1.Slot, hash_tree_root(attestations[0].data), 0.CommitteeIndex).isSome()
|
1.Slot, hash_tree_root(attestations[0].data), 0.CommitteeIndex).isSome()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue