Fixed epoch actions (#105)
* Fixed epoch actions
* debugging asserts
* Revert "debugging asserts"
This reverts commit 9a11f5a7d8
.
This commit is contained in:
parent
433e2f78c2
commit
56a48cc60f
|
@ -30,8 +30,6 @@ const
|
|||
|
||||
stateStoragePeriod = EPOCH_LENGTH * 10 # Save states once per this number of slots. TODO: Find a good number.
|
||||
|
||||
func humaneSlotNum(s: SlotNumber): SlotNumber =
|
||||
s - GENESIS_SLOT
|
||||
|
||||
func shortHash(x: auto): string =
|
||||
($x)[0..7]
|
||||
|
@ -51,7 +49,7 @@ proc init*(T: type BeaconNode, conf: BeaconNodeConf): T =
|
|||
result.config = conf
|
||||
|
||||
result.attachedValidators = ValidatorPool.init
|
||||
init result.attestationPool, 0
|
||||
init result.attestationPool, GENESIS_SLOT
|
||||
init result.mainchainMonitor, "", Port(0) # TODO: specify geth address and port
|
||||
|
||||
let trieDB = trieDB newChainDb(string conf.dataDir)
|
||||
|
@ -236,7 +234,8 @@ proc proposeBlock(node: BeaconNode,
|
|||
|
||||
info "Block proposed", slot = humaneSlotNum(slot),
|
||||
stateRoot = shortHash(newBlock.state_root),
|
||||
validator = shortValidatorKey(node, validator.idx)
|
||||
validator = shortValidatorKey(node, validator.idx),
|
||||
idx = validator.idx
|
||||
|
||||
proc scheduleBlockProposal(node: BeaconNode,
|
||||
slot: uint64,
|
||||
|
@ -251,6 +250,7 @@ proc scheduleBlockProposal(node: BeaconNode,
|
|||
|
||||
info "Scheduling block proposal",
|
||||
validator = shortValidatorKey(node, validator.idx),
|
||||
idx = validator.idx,
|
||||
slot = humaneSlotNum(slot),
|
||||
fromNow = (at - fastEpochTime()) div 1000
|
||||
|
||||
|
@ -288,9 +288,11 @@ proc scheduleEpochActions(node: BeaconNode, epoch: uint64) =
|
|||
# see the comments in `get_beacon_proposer_index`
|
||||
var nextState = node.beaconState
|
||||
|
||||
for i in 0.uint64 ..< EPOCH_LENGTH:
|
||||
let start = if epoch == GENESIS_EPOCH: 1.uint64 else: 0.uint64
|
||||
|
||||
for i in start ..< EPOCH_LENGTH:
|
||||
# Schedule block proposals
|
||||
let slot = epoch * EPOCH_LENGTH + i + 1
|
||||
let slot = epoch * EPOCH_LENGTH + i
|
||||
nextState.slot = slot
|
||||
let proposerIdx = get_beacon_proposer_index(nextState, slot)
|
||||
let validator = node.getAttachedValidator(proposerIdx)
|
||||
|
|
|
@ -15,7 +15,7 @@ type
|
|||
# shard number. When we haven't received an attestation for a particular
|
||||
# shard yet, the Option value will be `none`
|
||||
attestations: Deque[array[SHARD_COUNT, Option[Attestation]]]
|
||||
startingSlot: int
|
||||
startingSlot: uint64
|
||||
|
||||
# TODO:
|
||||
# The compilicated Deque above is not needed.
|
||||
|
@ -37,7 +37,7 @@ type
|
|||
# substantial difficulties in network layer aggregation, then adding bits to
|
||||
# aid in supporting overlaps is one potential solution
|
||||
|
||||
proc init*(T: type AttestationPool, startingSlot: int): T =
|
||||
proc init*(T: type AttestationPool, startingSlot: uint64): T =
|
||||
result.attestations = initDeque[array[SHARD_COUNT, Option[Attestation]]]()
|
||||
result.startingSlot = startingSlot
|
||||
|
||||
|
@ -74,14 +74,14 @@ proc add*(pool: var AttestationPool,
|
|||
beaconState: BeaconState) =
|
||||
# The caller of this function is responsible for ensuring that
|
||||
# the attestations will be given in a strictly slot increasing order:
|
||||
doAssert attestation.data.slot.int >= pool.startingSlot
|
||||
doAssert attestation.data.slot >= pool.startingSlot
|
||||
|
||||
# TODO:
|
||||
# Validate that the attestation is authentic (it's properly signed)
|
||||
# and make sure that the validator is supposed to make an attestation
|
||||
# for the specific shard/slot
|
||||
|
||||
let slotIdxInPool = attestation.data.slot.int - pool.startingSlot
|
||||
let slotIdxInPool = int(attestation.data.slot - pool.startingSlot)
|
||||
if slotIdxInPool >= pool.attestations.len:
|
||||
pool.attestations.setLen(slotIdxInPool + 1)
|
||||
|
||||
|
@ -104,20 +104,20 @@ proc getAttestationsForBlock*(pool: AttestationPool,
|
|||
firstSlot = 0.uint64
|
||||
lastSlot = newBlockSlot - MIN_ATTESTATION_INCLUSION_DELAY
|
||||
|
||||
if pool.startingSlot.uint64 + MIN_ATTESTATION_INCLUSION_DELAY <= lastState.slot:
|
||||
if pool.startingSlot + MIN_ATTESTATION_INCLUSION_DELAY <= lastState.slot:
|
||||
firstSlot = lastState.slot - MIN_ATTESTATION_INCLUSION_DELAY
|
||||
|
||||
for slot in firstSlot .. lastSlot:
|
||||
let slotDequeIdx = slot.int - pool.startingSlot
|
||||
let slotDequeIdx = int(slot - pool.startingSlot)
|
||||
if slotDequeIdx >= pool.attestations.len: return
|
||||
let shardAndComittees = get_crosslink_committees_at_slot(lastState, slot)
|
||||
for s in shardAndComittees:
|
||||
if pool.attestations[slotDequeIdx][s.shard].isSome:
|
||||
result.add pool.attestations[slotDequeIdx][s.shard].get
|
||||
|
||||
proc discardHistoryToSlot*(pool: var AttestationPool, slot: int) =
|
||||
proc discardHistoryToSlot*(pool: var AttestationPool, slot: uint64) =
|
||||
## The index is treated inclusively
|
||||
let slot = slot - MIN_ATTESTATION_INCLUSION_DELAY.int
|
||||
let slot = slot - MIN_ATTESTATION_INCLUSION_DELAY
|
||||
if slot < pool.startingSlot:
|
||||
return
|
||||
let slotIdx = int(slot - pool.startingSlot)
|
||||
|
@ -187,7 +187,7 @@ func getVoteCount(aggregation_bitfield: openarray[byte]): int =
|
|||
for validatorIdx in 0 ..< aggregation_bitfield.len * 8:
|
||||
result += int aggregation_bitfield.get_bitfield_bit(validatorIdx)
|
||||
|
||||
func getAttestationVoteCount(pool: AttestationPool, current_slot: int): CountTable[Eth2Digest] =
|
||||
func getAttestationVoteCount(pool: AttestationPool, current_slot: uint64): CountTable[Eth2Digest] =
|
||||
## Returns all blocks more recent that the current slot
|
||||
## that were attested and their vote count
|
||||
# This replaces:
|
||||
|
@ -202,7 +202,7 @@ func getAttestationVoteCount(pool: AttestationPool, current_slot: int): CountTab
|
|||
# while the following implementation will count such blockhash multiple times instead.
|
||||
result = initCountTable[Eth2Digest]()
|
||||
|
||||
for slot in current_slot - pool.startingSlot ..< pool.attestations.len:
|
||||
for slot in current_slot - pool.startingSlot ..< pool.attestations.len.uint64:
|
||||
for attestation in pool.attestations[slot]:
|
||||
if attestation.isSome:
|
||||
# Increase the block attestation counts by the number of validators aggregated
|
||||
|
@ -218,7 +218,7 @@ proc lmdGhost*(
|
|||
# LMD GHOST (Latest Message Driven - Greediest Heaviest Observed SubTree)
|
||||
|
||||
# Raw vote count from all attestations
|
||||
let rawVoteCount = pool.getAttestationVoteCount(state.slot.int)
|
||||
let rawVoteCount = pool.getAttestationVoteCount(state.slot)
|
||||
|
||||
# The real vote count for a block also takes into account votes for its children
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ func validate_proof_of_possession(state: BeaconState,
|
|||
proof_of_possession,
|
||||
get_domain(
|
||||
state.fork,
|
||||
state.slot,
|
||||
slot_to_epoch(state.slot),
|
||||
DOMAIN_DEPOSIT,
|
||||
)
|
||||
)
|
||||
|
|
|
@ -469,6 +469,12 @@ when true:
|
|||
proc read*(rlp: var Rlp, T: type ValidatorSig): T {.inline.} =
|
||||
discard
|
||||
|
||||
func shortValidatorKey*(state: BeaconState, validatorIdx: int): string =
|
||||
($state.validator_registry[validatorIdx].pubkey)[0..7]
|
||||
|
||||
func humaneSlotNum*(s: SlotNumber): SlotNumber =
|
||||
s - GENESIS_SLOT
|
||||
|
||||
export
|
||||
writeValue, readValue
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ func flatten[T](v: openArray[seq[T]]): seq[T] =
|
|||
# TODO not in nim - doh.
|
||||
for x in v: result.add x
|
||||
|
||||
func verifyProposerSignature(state: BeaconState, blck: BeaconBlock): bool =
|
||||
proc verifyProposerSignature(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
|
||||
|
@ -61,7 +61,7 @@ func verifyProposerSignature(state: BeaconState, blck: BeaconBlock): bool =
|
|||
bls_verify(
|
||||
state.validator_registry[proposer_index].pubkey,
|
||||
proposal_hash.data, blck.signature,
|
||||
get_domain(state.fork, state.slot, DOMAIN_PROPOSAL))
|
||||
get_domain(state.fork, slot_to_epoch(state.slot), DOMAIN_PROPOSAL))
|
||||
|
||||
proc processRandao(
|
||||
state: var BeaconState, blck: BeaconBlock, flags: UpdateFlags): bool =
|
||||
|
@ -147,7 +147,7 @@ proc processProposerSlashings(
|
|||
hash_tree_root_final(proposer_slashing.proposal_data_1).data,
|
||||
proposer_slashing.proposal_signature_1,
|
||||
get_domain(
|
||||
state.fork, proposer_slashing.proposal_data_1.slot,
|
||||
state.fork, slot_to_epoch(proposer_slashing.proposal_data_1.slot),
|
||||
DOMAIN_PROPOSAL)):
|
||||
notice "PropSlash: invalid signature 1"
|
||||
return false
|
||||
|
@ -156,7 +156,7 @@ proc processProposerSlashings(
|
|||
hash_tree_root_final(proposer_slashing.proposal_data_2).data,
|
||||
proposer_slashing.proposal_signature_2,
|
||||
get_domain(
|
||||
state.fork, proposer_slashing.proposal_data_2.slot,
|
||||
state.fork, slot_to_epoch(proposer_slashing.proposal_data_2.slot),
|
||||
DOMAIN_PROPOSAL)):
|
||||
notice "PropSlash: invalid signature 2"
|
||||
return false
|
||||
|
@ -401,7 +401,7 @@ proc processBlock(
|
|||
# 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 verifyProposerSignature(state, blck):
|
||||
notice "Proposer signature not valid"
|
||||
notice "Proposer signature not valid", slot = humaneSlotNum(state.slot)
|
||||
return false
|
||||
|
||||
if not processRandao(state, blck, flags):
|
||||
|
|
|
@ -51,7 +51,7 @@ proc signBlockProposal*(v: AttachedValidator, fork: Fork,
|
|||
|
||||
# TODO: Should we use proposalRoot as data, or digest in regards to signature?
|
||||
result = bls_sign(v.privKey, proposalRoot.data,
|
||||
get_domain(fork, proposal.slot, DOMAIN_PROPOSAL))
|
||||
get_domain(fork, slot_to_epoch(proposal.slot), DOMAIN_PROPOSAL))
|
||||
else:
|
||||
# TODO:
|
||||
# send RPC
|
||||
|
|
|
@ -134,12 +134,12 @@ proc addBlock*(
|
|||
# TODO domain present do something!
|
||||
new_block.signature =
|
||||
bls_sign(proposerPrivkey, proposal_hash,
|
||||
get_domain(state.fork, state.slot, DOMAIN_PROPOSAL))
|
||||
get_domain(state.fork, slot_to_epoch(state.slot), DOMAIN_PROPOSAL))
|
||||
|
||||
assert bls_verify(
|
||||
proposer.pubkey,
|
||||
proposal_hash, new_block.signature,
|
||||
get_domain(state.fork, state.slot, DOMAIN_PROPOSAL)),
|
||||
get_domain(state.fork, slot_to_epoch(state.slot), DOMAIN_PROPOSAL)),
|
||||
"we just signed this message - it should pass verification!"
|
||||
|
||||
new_block
|
||||
|
|
Loading…
Reference in New Issue