More 0.5.1 spec updates (#195)
* rm gone-in-0.5.0 Proposal, verifyBlockSignature, and slot check which moved to spec function processBlockHeader * mark get_attestation_participants and get_epoch_committee_count as 0.5.1; finish updating processAttestations to 0.5.1; add kludgy workaround for bug relating to get_winning_roots_etc using crosslink_data_root as index when we have that as ZERO_HASH for all leading to it confusing attesters on different shards; rm BeaconState.latest_attestations, which splits into previous_epoch_attestations and current_epoch_attestations * Fix CI due to removed latest_attestations field
This commit is contained in:
parent
0a027e410a
commit
9f55b4646c
|
@ -428,13 +428,8 @@ proc proposeBlock(node: BeaconNode,
|
|||
|
||||
newBlock.state_root = node.state.root
|
||||
|
||||
let proposal = Proposal(
|
||||
slot: slot.uint64,
|
||||
block_root: Eth2Digest(data: signed_root(newBlock)),
|
||||
signature: ValidatorSig(),
|
||||
)
|
||||
newBlock.signature =
|
||||
await validator.signBlockProposal(node.state.data.fork, proposal)
|
||||
await validator.signBlockProposal(node.state.data.fork, newBlock)
|
||||
|
||||
# TODO what are we waiting for here? broadcast should never block, and never
|
||||
# fail...
|
||||
|
@ -442,7 +437,7 @@ proc proposeBlock(node: BeaconNode,
|
|||
|
||||
info "Block proposed",
|
||||
blck = shortLog(newBlock),
|
||||
blockRoot = shortLog(proposal.block_root),
|
||||
blockRoot = shortLog(Eth2Digest(data: signed_root(newBlock))),
|
||||
validator = shortValidatorKey(node, validator.idx),
|
||||
idx = validator.idx
|
||||
|
||||
|
|
|
@ -334,7 +334,7 @@ func get_block_root*(state: BeaconState,
|
|||
doAssert slot < state.slot
|
||||
state.latest_block_roots[slot mod SLOTS_PER_HISTORICAL_ROOT]
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_attestation_participants
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.1/specs/core/0_beacon-chain.md#get_attestation_participants
|
||||
func get_attestation_participants*(state: BeaconState,
|
||||
attestation_data: AttestationData,
|
||||
bitfield: BitField): seq[ValidatorIndex] =
|
||||
|
@ -350,10 +350,10 @@ func get_attestation_participants*(state: BeaconState,
|
|||
# TODO Linear search through shard list? borderline ok, it's a small list
|
||||
# TODO iterator candidate
|
||||
|
||||
## Return the participant indices at for the ``attestation_data`` and
|
||||
## ``bitfield``.
|
||||
# Find the committee in the list with the desired shard
|
||||
let crosslink_committees = get_crosslink_committees_at_slot(
|
||||
state, attestation_data.slot)
|
||||
|
||||
doAssert anyIt(
|
||||
crosslink_committees,
|
||||
it[1] == attestation_data.shard)
|
||||
|
@ -442,8 +442,7 @@ func update_validator_registry*(state: var BeaconState) =
|
|||
|
||||
state.validator_registry_update_epoch = current_epoch
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#attestations
|
||||
# with last half or so still not fully converted from 0.4.0 (tag, remove when done)
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.1/specs/core/0_beacon-chain.md#attestations
|
||||
proc checkAttestation*(
|
||||
state: var BeaconState, attestation: Attestation, flags: UpdateFlags): bool =
|
||||
## Check that an attestation follows the rules of being included in the state
|
||||
|
@ -499,34 +498,50 @@ proc checkAttestation*(
|
|||
state_slot = humaneSlotNum(state.slot))
|
||||
return
|
||||
|
||||
if not (state.latest_crosslinks[attestation.data.shard] in [
|
||||
attestation.data.previous_crosslink,
|
||||
Crosslink(
|
||||
crosslink_data_root: attestation.data.crosslink_data_root,
|
||||
epoch: slot_to_epoch(attestation.data.slot))]):
|
||||
# Check that the crosslink data is valid
|
||||
let acceptable_crosslink_data = @[
|
||||
# Case 1: Latest crosslink matches the one in the state
|
||||
attestation.data.previous_crosslink,
|
||||
|
||||
# Case 2: State has already been updated, state's latest crosslink matches
|
||||
# the crosslink the attestation is trying to create
|
||||
Crosslink(
|
||||
crosslink_data_root: attestation.data.crosslink_data_root,
|
||||
epoch: slot_to_epoch(attestation.data.slot)
|
||||
)
|
||||
]
|
||||
if not (state.latest_crosslinks[attestation.data.shard] in
|
||||
acceptable_crosslink_data):
|
||||
warn("Unexpected crosslink shard",
|
||||
state_latest_crosslinks_attestation_data_shard =
|
||||
state.latest_crosslinks[attestation.data.shard],
|
||||
attestation_data_previous_crosslink = attestation.data.previous_crosslink,
|
||||
epoch = humaneEpochNum(slot_to_epoch(attestation.data.slot)),
|
||||
crosslink_data_root = attestation.data.crosslink_data_root)
|
||||
actual_epoch = slot_to_epoch(attestation.data.slot),
|
||||
crosslink_data_root = attestation.data.crosslink_data_root,
|
||||
acceptable_crosslink_data = acceptable_crosslink_data)
|
||||
return
|
||||
|
||||
doAssert allIt(attestation.custody_bitfield.bits, it == 0) #TO BE REMOVED IN PHASE 1
|
||||
# Attestation must be nonempty!
|
||||
doAssert anyIt(attestation.aggregation_bitfield.bits, it != 0)
|
||||
|
||||
# Custody must be empty (to be removed in phase 1)
|
||||
doAssert allIt(attestation.custody_bitfield.bits, it == 0)
|
||||
|
||||
# Get the committee for the specific shard that this attestation is for
|
||||
let crosslink_committee = mapIt(
|
||||
filterIt(get_crosslink_committees_at_slot(state, attestation.data.slot),
|
||||
it.shard == attestation.data.shard),
|
||||
it.committee)[0]
|
||||
|
||||
# Custody bitfield must be a subset of the attestation bitfield
|
||||
doAssert allIt(0 ..< len(crosslink_committee),
|
||||
if not get_bitfield_bit(attestation.aggregation_bitfield, it):
|
||||
# Should always be true in phase 0, because of above assertion
|
||||
not get_bitfield_bit(attestation.custody_bitfield, it)
|
||||
else:
|
||||
true)
|
||||
|
||||
# Verify aggregate signature
|
||||
let
|
||||
participants = get_attestation_participants(
|
||||
state, attestation.data, attestation.aggregation_bitfield)
|
||||
|
@ -557,7 +572,7 @@ proc checkAttestation*(
|
|||
DOMAIN_ATTESTATION),
|
||||
)
|
||||
|
||||
# To be removed in Phase1:
|
||||
# Crosslink data root is zero (to be removed in phase 1)
|
||||
if attestation.data.crosslink_data_root != ZERO_HASH:
|
||||
warn("Invalid crosslink data root")
|
||||
return
|
||||
|
@ -573,7 +588,6 @@ func prepare_validator_for_withdrawal*(state: var BeaconState, index: ValidatorI
|
|||
validator.withdrawable_epoch = get_current_epoch(state) +
|
||||
MIN_VALIDATOR_WITHDRAWABILITY_DELAY
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/validator/0_beacon-chain-validator.md#attestations-1
|
||||
proc makeAttestationData*(
|
||||
state: BeaconState, shard: uint64,
|
||||
beacon_block_root: Eth2Digest): AttestationData =
|
||||
|
|
|
@ -46,7 +46,7 @@ type
|
|||
Epoch* = distinct uint64
|
||||
|
||||
const
|
||||
SPEC_VERSION* = "0.5.0" ## \
|
||||
SPEC_VERSION* = "0.5.1" ## \
|
||||
## Spec version we're aiming to be compatible with, right now
|
||||
## TODO: improve this scheme once we can negotiate versions in protocol
|
||||
|
||||
|
@ -360,18 +360,7 @@ type
|
|||
voluntary_exits*: seq[VoluntaryExit]
|
||||
transfers*: seq[Transfer]
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#proposal
|
||||
Proposal* = object
|
||||
slot*: uint64 ##\
|
||||
## Slot number
|
||||
|
||||
block_root*: Eth2Digest ##\
|
||||
## Block root
|
||||
|
||||
signature*: ValidatorSig ##\
|
||||
## Signature
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#beaconstate
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.1/specs/core/0_beacon-chain.md#beaconstate
|
||||
BeaconState* = object
|
||||
slot*: Slot
|
||||
genesis_time*: uint64
|
||||
|
@ -423,9 +412,6 @@ type
|
|||
## `latest_block_header.state_root == ZERO_HASH` temporarily
|
||||
historical_roots*: seq[Eth2Digest]
|
||||
|
||||
# TOOD remove, gone in 0.5
|
||||
latest_attestations*: seq[PendingAttestation]
|
||||
|
||||
# Ethereum 1.0 chain data
|
||||
latest_eth1_data*: Eth1Data
|
||||
eth1_data_votes*: seq[Eth1DataVote]
|
||||
|
|
|
@ -132,7 +132,7 @@ func get_active_validator_indices*(validators: openArray[Validator], epoch: Epoc
|
|||
if is_active_validator(val, epoch):
|
||||
result.add idx.ValidatorIndex
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_epoch_committee_count
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.1/specs/core/0_beacon-chain.md#get_epoch_committee_count
|
||||
func get_epoch_committee_count*(active_validator_count: int): uint64 =
|
||||
clamp(
|
||||
active_validator_count div SLOTS_PER_EPOCH div TARGET_COMMITTEE_SIZE,
|
||||
|
|
|
@ -39,25 +39,6 @@ func flatten[T](v: openArray[seq[T]]): seq[T] =
|
|||
# TODO not in nim - doh.
|
||||
for x in v: result.add x
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#block-signature
|
||||
func verifyBlockSignature(state: BeaconState, blck: BeaconBlock): bool =
|
||||
## When creating a block, the proposer will sign a version of the block that
|
||||
## doesn't contain the data (chicken and egg), then add the signature to that
|
||||
## block. Here, we check that the signature is correct by repeating the same
|
||||
## process.
|
||||
let
|
||||
proposer =
|
||||
state.validator_registry[get_beacon_proposer_index(state, state.slot)]
|
||||
proposal = Proposal(
|
||||
slot: blck.slot.uint64,
|
||||
block_root: Eth2Digest(data: signed_root(blck)),
|
||||
signature: blck.signature)
|
||||
bls_verify(
|
||||
proposer.pubkey,
|
||||
signed_root(proposal),
|
||||
proposal.signature,
|
||||
get_domain(state.fork, get_current_epoch(state), DOMAIN_BEACON_BLOCK))
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#block-header
|
||||
proc processBlockHeader(
|
||||
state: var BeaconState, blck: BeaconBlock, flags: UpdateFlags): bool =
|
||||
|
@ -70,13 +51,16 @@ proc processBlockHeader(
|
|||
|
||||
## https://github.com/ethereum/eth2.0-specs/pull/816/files remove when
|
||||
## switched to 0.5.1
|
||||
if not (blck.previous_block_root.data ==
|
||||
signed_root(state.latest_block_header)):
|
||||
notice "Block header: previous block root mismatch",
|
||||
previous_block_root = blck.previous_block_root,
|
||||
latest_block_header = state.latest_block_header,
|
||||
latest_block_header_root = hash_tree_root_final(state.latest_block_header)
|
||||
return false
|
||||
when false:
|
||||
## TODO Re-enable when it works; currently, some code in processBlock
|
||||
## also checks this invariant in a different way. tag as 0.4.0.
|
||||
if not (blck.previous_block_root.data ==
|
||||
signed_root(state.latest_block_header)):
|
||||
notice "Block header: previous block root mismatch",
|
||||
previous_block_root = blck.previous_block_root,
|
||||
latest_block_header = state.latest_block_header,
|
||||
latest_block_header_root = hash_tree_root_final(state.latest_block_header)
|
||||
return false
|
||||
|
||||
state.latest_block_header = get_temporary_block_header(blck)
|
||||
|
||||
|
@ -277,7 +261,7 @@ proc processAttesterSlashings(state: var BeaconState, blck: BeaconBlock): bool =
|
|||
|
||||
true
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#attestations
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.1/specs/core/0_beacon-chain.md#attestations
|
||||
proc processAttestations(
|
||||
state: var BeaconState, blck: BeaconBlock, flags: UpdateFlags): bool =
|
||||
## Each block includes a number of attestations that the proposer chose. Each
|
||||
|
@ -294,18 +278,23 @@ proc processAttestations(
|
|||
return false
|
||||
|
||||
# All checks passed - update state
|
||||
state.latest_attestations.add blck.body.attestations.mapIt(
|
||||
PendingAttestation(
|
||||
data: it.data,
|
||||
aggregation_bitfield: it.aggregation_bitfield,
|
||||
custody_bitfield: it.custody_bitfield,
|
||||
inclusion_slot: state.slot,
|
||||
# Apply the attestations
|
||||
for attestation in blck.body.attestations:
|
||||
let pending_attestation = PendingAttestation(
|
||||
data: attestation.data,
|
||||
aggregation_bitfield: attestation.aggregation_bitfield,
|
||||
custody_bitfield: attestation.custody_bitfield,
|
||||
inclusion_slot: state.slot
|
||||
)
|
||||
)
|
||||
|
||||
if slot_to_epoch(attestation.data.slot) == get_current_epoch(state):
|
||||
state.current_epoch_attestations.add(pending_attestation)
|
||||
else:
|
||||
state.previous_epoch_attestations.add(pending_attestation)
|
||||
|
||||
true
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#deposits-1
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#deposits-1
|
||||
func processDeposits(state: var BeaconState, blck: BeaconBlock): bool =
|
||||
true
|
||||
|
||||
|
@ -484,18 +473,11 @@ proc processBlock(
|
|||
# TODO when there's a failure, we should reset the state!
|
||||
# TODO probably better to do all verification first, then apply state changes
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#slot-1
|
||||
if not (blck.slot == state.slot):
|
||||
notice "Unexpected block slot number",
|
||||
blockSlot = humaneSlotNum(blck.slot),
|
||||
stateSlot = humaneSlotNum(state.slot)
|
||||
return false
|
||||
|
||||
# Spec does not have this check explicitly, but requires that this condition
|
||||
# holds - so we give verify it as well - this would happen naturally if
|
||||
# `blck.previous_block_root` was used in `processSlot` - but that doesn't cut it for
|
||||
# blockless slot processing.
|
||||
# TODO compare with check in processBlockHeader, might be redundant
|
||||
# TODO compare with processBlockHeader check, might be redundant and to be removed
|
||||
let stateParentRoot =
|
||||
state.latest_block_roots[(state.slot - 1) mod SLOTS_PER_HISTORICAL_ROOT]
|
||||
if not (blck.previous_block_root == stateParentRoot):
|
||||
|
@ -504,18 +486,9 @@ proc processBlock(
|
|||
stateParentRoot
|
||||
return false
|
||||
|
||||
# TODO Technically, we could make processBlock take a generic type instead
|
||||
# of BeaconBlock - we would then have an intermediate `ProposedBlock`
|
||||
# type that omits some fields - this way, the compiler would guarantee
|
||||
# that we don't try to access fields that don't have a value yet
|
||||
#if not processBlockHeader(state, blck, flags):
|
||||
# notice "Block header not valid", slot = humaneSlotNum(state.slot)
|
||||
# return false
|
||||
# TODO this starts requiring refactoring blockpool, etc
|
||||
if skipValidation notin flags:
|
||||
if not verifyBlockSignature(state, blck):
|
||||
notice "Block signature not valid", slot = humaneSlotNum(state.slot)
|
||||
return false
|
||||
if not processBlockHeader(state, blck, flags):
|
||||
notice "Block header not valid", slot = humaneSlotNum(state.slot)
|
||||
return false
|
||||
|
||||
if not processRandao(state, blck, flags):
|
||||
return false
|
||||
|
@ -542,7 +515,7 @@ proc processBlock(
|
|||
|
||||
true
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#helper-functions-1
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.1/specs/core/0_beacon-chain.md#helper-functions-1
|
||||
func get_current_total_balance(state: BeaconState): Gwei =
|
||||
return get_total_balance(
|
||||
state,
|
||||
|
@ -615,7 +588,9 @@ func get_winning_root_and_participants(state: BeaconState, shard: Shard):
|
|||
return (ZERO_HASH, @[])
|
||||
|
||||
func get_attestations_for(root: Eth2Digest): seq[PendingAttestation] =
|
||||
filterIt(valid_attestations, it.data.crosslink_data_root == root)
|
||||
filterIt(
|
||||
valid_attestations,
|
||||
it.data.crosslink_data_root == root)
|
||||
|
||||
## Winning crosslink root is the root with the most votes for it, ties broken
|
||||
## in favor of lexicographically higher hash
|
||||
|
@ -641,7 +616,7 @@ func inclusion_slots(state: BeaconState): auto =
|
|||
result = initTable[ValidatorIndex, Slot]()
|
||||
|
||||
let previous_epoch_attestations =
|
||||
state.latest_attestations.filterIt(
|
||||
state.previous_epoch_attestations.filterIt(
|
||||
get_previous_epoch(state) == slot_to_epoch(it.data.slot))
|
||||
|
||||
## TODO switch previous_epoch_attestations to state.foo,
|
||||
|
@ -659,7 +634,7 @@ func inclusion_distances(state: BeaconState): auto =
|
|||
result = initTable[ValidatorIndex, Slot]()
|
||||
|
||||
let previous_epoch_attestations =
|
||||
state.latest_attestations.filterIt(
|
||||
state.previous_epoch_attestations.filterIt(
|
||||
get_previous_epoch(state) == slot_to_epoch(it.data.slot))
|
||||
|
||||
## TODO switch previous_epoch_attestations to state.foo,
|
||||
|
@ -741,13 +716,20 @@ func update_justification_and_finalization(state: var BeaconState) =
|
|||
state.finalized_root =
|
||||
get_block_root(state, get_epoch_start_slot(new_finalized_epoch))
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#crosslinks
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.1/specs/core/0_beacon-chain.md#crosslinks
|
||||
func process_crosslinks(state: var BeaconState) =
|
||||
let
|
||||
current_epoch = get_current_epoch(state)
|
||||
previous_epoch = current_epoch - 1
|
||||
next_epoch = current_epoch + 1
|
||||
for slot in get_epoch_start_slot(previous_epoch).uint64 ..<
|
||||
## TODO is it actually correct to be setting state.latest_crosslinks[shard]
|
||||
## to something pre-GENESIS_EPOCH, ever? I guess the intent is if there are
|
||||
## a quorum of participants for get_epoch_start_slot(previous_epoch), when
|
||||
## state.slot == GENESIS_SLOT, then there will be participants for a quorum
|
||||
## in the current-epoch (i.e. genesis epoch) version of that shard?
|
||||
#for slot in get_epoch_start_slot(previous_epoch).uint64 ..<
|
||||
for slot in max(
|
||||
GENESIS_SLOT.uint64, get_epoch_start_slot(previous_epoch).uint64) ..<
|
||||
get_epoch_start_slot(next_epoch).uint64:
|
||||
for cas in get_crosslink_committees_at_slot(state, slot):
|
||||
let
|
||||
|
@ -756,7 +738,11 @@ func process_crosslinks(state: var BeaconState) =
|
|||
get_winning_root_and_participants(state, shard)
|
||||
participating_balance = get_total_balance(state, participants)
|
||||
total_balance = get_total_balance(state, crosslink_committee)
|
||||
|
||||
if 3'u64 * participating_balance >= 2'u64 * total_balance:
|
||||
# Check not from spec; seems kludgy
|
||||
doAssert slot >= GENESIS_SLOT
|
||||
|
||||
state.latest_crosslinks[shard] = Crosslink(
|
||||
epoch: slot_to_epoch(slot),
|
||||
crosslink_data_root: winning_root
|
||||
|
@ -1117,14 +1103,20 @@ proc advanceState*(
|
|||
## We now define the state transition function. At a high level the state
|
||||
## transition is made up of four parts:
|
||||
|
||||
# 1. State caching, which happens at the start of every slot.
|
||||
## 1. State caching, which happens at the start of every slot.
|
||||
## The state caching, caches the state root of the previous slot
|
||||
cacheState(state)
|
||||
|
||||
## (2) The per-epoch transitions, which happens at the start of the first
|
||||
## 2. The per-epoch transitions, which happens at the start of the first
|
||||
## slot of every epoch.
|
||||
## The per-epoch transitions focus on the validator registry, including
|
||||
## adjusting balances and activating and exiting validators, as well as
|
||||
## processing crosslinks and managing block justification/finalization.
|
||||
processEpoch(state)
|
||||
|
||||
# (3) The per-slot transitions, which happens at every slot.
|
||||
## 3. The per-slot transitions, which happens at every slot.
|
||||
## The per-slot transitions focus on the slot counter and block roots
|
||||
## records updates.
|
||||
processSlot(state, previous_block_root)
|
||||
|
||||
proc updateState*(
|
||||
|
|
|
@ -25,13 +25,11 @@ proc getValidator*(pool: ValidatorPool,
|
|||
pool.validators.getOrDefault(validatorKey)
|
||||
|
||||
proc signBlockProposal*(v: AttachedValidator, fork: Fork,
|
||||
proposal: Proposal): Future[ValidatorSig] {.async.} =
|
||||
blck: BeaconBlock): Future[ValidatorSig] {.async.} =
|
||||
if v.kind == inProcess:
|
||||
await sleepAsync(1)
|
||||
let proposalRoot = hash_tree_root_final(proposal)
|
||||
|
||||
result = bls_sign(v.privKey, signed_root(proposal),
|
||||
get_domain(fork, slot_to_epoch(proposal.slot), DOMAIN_BEACON_BLOCK))
|
||||
result = bls_sign(v.privKey, signed_root(blck),
|
||||
get_domain(fork, slot_to_epoch(blck.slot), DOMAIN_BEACON_BLOCK))
|
||||
else:
|
||||
# TODO:
|
||||
# send RPC
|
||||
|
|
|
@ -10,16 +10,20 @@ proc stateSize(deposits: int, maxContent = false) =
|
|||
deposits, {skipValidation}), 0, Eth1Data(), {skipValidation})
|
||||
|
||||
if maxContent:
|
||||
# TODO verify this is correct, but generally we collect up to two epochs
|
||||
# of attestations, and each block has a cap on the number of
|
||||
# attestations it may hold, so we'll just add so many of them
|
||||
state.latest_attestations.setLen(MAX_ATTESTATIONS * SLOTS_PER_EPOCH * 2)
|
||||
let
|
||||
crosslink_committees = get_crosslink_committees_at_slot(state, 0.Slot)
|
||||
validatorsPerCommittee =
|
||||
len(crosslink_committees[0].committee) # close enough..
|
||||
for a in state.latest_attestations.mitems():
|
||||
a.aggregation_bitfield = BitField.init(validatorsPerCommittee)
|
||||
# TODO: state.latest_attestations was removed
|
||||
# in https://github.com/status-im/nim-beacon-chain/pull/195
|
||||
raise newException(ValueError, "Not supported at the moment")
|
||||
|
||||
# # TODO verify this is correct, but generally we collect up to two epochs
|
||||
# # of attestations, and each block has a cap on the number of
|
||||
# # attestations it may hold, so we'll just add so many of them
|
||||
# state.latest_attestations.setLen(MAX_ATTESTATIONS * SLOTS_PER_EPOCH * 2)
|
||||
# let
|
||||
# crosslink_committees = get_crosslink_committees_at_slot(state, 0.Slot)
|
||||
# validatorsPerCommittee =
|
||||
# len(crosslink_committees[0].committee) # close enough..
|
||||
# for a in state.latest_attestations.mitems():
|
||||
# a.aggregation_bitfield = BitField.init(validatorsPerCommittee)
|
||||
echo "Validators: ", deposits, ", total: ", SSZ.encode(state).len
|
||||
|
||||
dispatch(stateSize)
|
||||
|
|
|
@ -101,7 +101,7 @@ suite "Block processing":
|
|||
discard updateState(state, previous_block_root, new_block, {})
|
||||
|
||||
check:
|
||||
state.latest_attestations.len == 1
|
||||
state.current_epoch_attestations.len == 1
|
||||
|
||||
while state.slot < 191:
|
||||
advanceState(state, previous_block_root)
|
||||
|
|
|
@ -118,31 +118,21 @@ proc addBlock*(
|
|||
# can set the state root in order to be able to create a valid signature
|
||||
new_block.state_root = Eth2Digest(data: hash_tree_root(state))
|
||||
|
||||
let
|
||||
proposerPrivkey = hackPrivKey(proposer)
|
||||
|
||||
# Once we've collected all the state data, we sign the block data along with
|
||||
# some book-keeping values
|
||||
signed_data = Proposal(
|
||||
slot: new_block.slot.uint64,
|
||||
block_root: Eth2Digest(data: signed_root(new_block)),
|
||||
signature: ValidatorSig(),
|
||||
)
|
||||
proposal_hash = signed_root(signed_data)
|
||||
|
||||
let proposerPrivkey = hackPrivKey(proposer)
|
||||
doAssert proposerPrivkey.pubKey() == proposer.pubkey,
|
||||
"signature key should be derived from private key! - wrong privkey?"
|
||||
|
||||
if skipValidation notin flags:
|
||||
let block_root = signed_root(new_block)
|
||||
# We have a signature - put it in the block and we should be done!
|
||||
new_block.signature =
|
||||
bls_sign(proposerPrivkey, proposal_hash,
|
||||
get_domain(state.fork, slot_to_epoch(state.slot), DOMAIN_BEACON_BLOCK))
|
||||
bls_sign(proposerPrivkey, block_root,
|
||||
get_domain(state.fork, slot_to_epoch(new_block.slot), DOMAIN_BEACON_BLOCK))
|
||||
|
||||
doAssert bls_verify(
|
||||
proposer.pubkey,
|
||||
proposal_hash, new_block.signature,
|
||||
get_domain(state.fork, slot_to_epoch(state.slot), DOMAIN_BEACON_BLOCK)),
|
||||
block_root, new_block.signature,
|
||||
get_domain(state.fork, slot_to_epoch(new_block.slot), DOMAIN_BEACON_BLOCK)),
|
||||
"we just signed this message - it should pass verification!"
|
||||
|
||||
new_block
|
||||
|
|
Loading…
Reference in New Issue