Fixed epoch actions (#105)

* Fixed epoch actions

* debugging asserts

* Revert "debugging asserts"

This reverts commit 9a11f5a7d8.
This commit is contained in:
Yuriy Glukhov 2019-02-12 17:56:58 +02:00 committed by Mamy Ratsimbazafy
parent 433e2f78c2
commit 56a48cc60f
7 changed files with 34 additions and 26 deletions

View File

@ -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)

View File

@ -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

View File

@ -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,
)
)

View File

@ -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

View File

@ -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):

View File

@ -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

View File

@ -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