mirror of
https://github.com/status-im/nimbus-eth2.git
synced 2025-01-12 15:24:14 +00:00
begin 0.5.0 spec update (#179)
* begin 0.5.0 spec update: parent_root -> previous_block_root, BeaconState.justified_epoch -> BeaconState.current_justified_epoch, DOMAIN_PROPOSAL -> DOMAIN_BEACON_BLOCK, temporarily rename BeaconBlockHeader to BeaconBlockHeaderRLP to allow for gradual re-merging without disrupting RLP; mark a few unchanged functions and data types, implement get_temporary_block_header/get_empty_block/should_update_validator_registry/processBlockHeader/cacheState; update a few others * a dozen or so more trivial mostly comment changes, finding more unchanged parts of 0.5.0 * several more trivial changes; goal is to reduce noise around the upcoming substantial changes (epoch processing, etc)
This commit is contained in:
parent
8797a903ea
commit
f36c2d86dc
@ -108,4 +108,4 @@ iterator getAncestors*(db: BeaconChainDB, root: Eth2Digest):
|
||||
while (let blck = db.getBlock(root); blck.isSome()):
|
||||
yield (root, blck.get())
|
||||
|
||||
root = blck.get().parent_root
|
||||
root = blck.get().previous_block_root
|
||||
|
@ -290,13 +290,13 @@ proc proposeBlock(node: BeaconNode,
|
||||
# To create a block, we'll first apply a partial block to the state, skipping
|
||||
# some validations.
|
||||
var blockBody = BeaconBlockBody(
|
||||
randao_reveal: validator.genRandaoReveal(node.state.data, slot),
|
||||
eth1_data: node.mainchainMonitor.getBeaconBlockRef(),
|
||||
attestations: node.attestationPool.getAttestationsForBlock(slot))
|
||||
|
||||
var newBlock = BeaconBlock(
|
||||
slot: slot,
|
||||
parent_root: node.state.blck.root,
|
||||
randao_reveal: validator.genRandaoReveal(node.state.data, slot),
|
||||
eth1_data: node.mainchainMonitor.getBeaconBlockRef(),
|
||||
previous_block_root: node.state.blck.root,
|
||||
body: blockBody,
|
||||
signature: ValidatorSig(), # we need the rest of the block first!
|
||||
)
|
||||
@ -325,7 +325,7 @@ proc proposeBlock(node: BeaconNode,
|
||||
info "Block proposed",
|
||||
slot = humaneSlotNum(slot),
|
||||
stateRoot = shortLog(newBlock.state_root),
|
||||
parentRoot = shortLog(newBlock.parent_root),
|
||||
parentRoot = shortLog(newBlock.previous_block_root),
|
||||
validator = shortValidatorKey(node, validator.idx),
|
||||
idx = validator.idx
|
||||
|
||||
@ -537,7 +537,7 @@ proc onBeaconBlock(node: BeaconNode, blck: BeaconBlock) =
|
||||
blockRoot = shortLog(blockRoot),
|
||||
slot = humaneSlotNum(blck.slot),
|
||||
stateRoot = shortLog(blck.state_root),
|
||||
parentRoot = shortLog(blck.parent_root),
|
||||
parentRoot = shortLog(blck.previous_block_root),
|
||||
signature = shortLog(blck.signature),
|
||||
proposer_slashings = blck.body.proposer_slashings.len,
|
||||
attester_slashings = blck.body.attester_slashings.len,
|
||||
@ -549,7 +549,7 @@ proc onBeaconBlock(node: BeaconNode, blck: BeaconBlock) =
|
||||
if not node.blockPool.add(node.state, blockRoot, blck):
|
||||
# TODO the fact that add returns a bool that causes the parent block to be
|
||||
# pre-emptively fetched is quite ugly - fix.
|
||||
node.fetchBlocks(@[blck.parent_root])
|
||||
node.fetchBlocks(@[blck.previous_block_root])
|
||||
|
||||
# The block we received contains attestations, and we might not yet know about
|
||||
# all of them. Let's add them to the attestation pool - in case they block
|
||||
|
@ -100,7 +100,7 @@ proc init*(T: type BlockPool, db: BeaconChainDB): BlockPool =
|
||||
finalizedHead =
|
||||
headRef.findAncestorBySlot(headState.finalized_epoch.get_epoch_start_slot())
|
||||
justifiedHead =
|
||||
headRef.findAncestorBySlot(headState.justified_epoch.get_epoch_start_slot())
|
||||
headRef.findAncestorBySlot(headState.current_justified_epoch.get_epoch_start_slot())
|
||||
|
||||
doAssert justifiedHead.slot >= finalizedHead.slot,
|
||||
"justified head comes before finalized head - database corrupt?"
|
||||
@ -162,7 +162,7 @@ proc add*(
|
||||
|
||||
return true
|
||||
|
||||
let parent = pool.blocks.getOrDefault(blck.parent_root)
|
||||
let parent = pool.blocks.getOrDefault(blck.previous_block_root)
|
||||
|
||||
if parent != nil:
|
||||
# The block might have been in either of these - we don't want any more
|
||||
@ -197,7 +197,7 @@ proc add*(
|
||||
let
|
||||
justifiedBlock =
|
||||
blockRef.findAncestorBySlot(
|
||||
state.data.justified_epoch.get_epoch_start_slot())
|
||||
state.data.current_justified_epoch.get_epoch_start_slot())
|
||||
|
||||
if not justifiedBlock.justified:
|
||||
info "Justified block",
|
||||
@ -227,7 +227,7 @@ proc add*(
|
||||
# think are useful - but, it would also risk filling the database with
|
||||
# junk that's not part of the block graph
|
||||
|
||||
if blck.parent_root in pool.unresolved:
|
||||
if blck.previous_block_root in pool.unresolved:
|
||||
return true
|
||||
|
||||
# This is an unresolved block - put it on the unresolved list for now...
|
||||
@ -244,7 +244,7 @@ proc add*(
|
||||
blck = shortLog(blck),
|
||||
blockRoot = shortLog(blockRoot)
|
||||
|
||||
pool.unresolved[blck.parent_root] = UnresolvedBlock()
|
||||
pool.unresolved[blck.previous_block_root] = UnresolvedBlock()
|
||||
pool.pending[blockRoot] = blck
|
||||
|
||||
false
|
||||
@ -303,8 +303,8 @@ proc checkUnresolved*(pool: var BlockPool): seq[Eth2Digest] =
|
||||
proc skipAndUpdateState(
|
||||
state: var BeaconState, blck: BeaconBlock, flags: UpdateFlags,
|
||||
afterUpdate: proc (state: BeaconState)): bool =
|
||||
skipSlots(state, blck.parent_root, blck.slot - 1, afterUpdate)
|
||||
let ok = updateState(state, blck.parent_root, blck, flags)
|
||||
skipSlots(state, blck.previous_block_root, blck.slot - 1, afterUpdate)
|
||||
let ok = updateState(state, blck.previous_block_root, blck, flags)
|
||||
|
||||
afterUpdate(state)
|
||||
|
||||
@ -337,7 +337,7 @@ proc updateState*(
|
||||
|
||||
# Common case: the last thing that was applied to the state was the parent
|
||||
# of blck
|
||||
if state.blck.root == ancestors[0].data.parent_root and
|
||||
if state.blck.root == ancestors[0].data.previous_block_root and
|
||||
state.data.slot < blck.slot:
|
||||
let ok = skipAndUpdateState(
|
||||
state.data, ancestors[0].data, {skipValidation}) do (state: BeaconState):
|
||||
@ -395,12 +395,12 @@ proc updateState*(
|
||||
let last = ancestors[i]
|
||||
|
||||
skipSlots(
|
||||
state.data, last.data.parent_root,
|
||||
state.data, last.data.previous_block_root,
|
||||
last.data.slot - 1) do(state: BeaconState):
|
||||
pool.maybePutState(state)
|
||||
|
||||
let ok = updateState(
|
||||
state.data, last.data.parent_root, last.data, {skipValidation})
|
||||
state.data, last.data.previous_block_root, last.data, {skipValidation})
|
||||
doAssert ok,
|
||||
"We only keep validated blocks in the database, should never fail"
|
||||
|
||||
@ -443,7 +443,7 @@ proc updateHead*(pool: BlockPool, state: var StateData, blck: BlockRef) =
|
||||
stateRoot = shortLog(state.root),
|
||||
headBlockRoot = shortLog(state.blck.root),
|
||||
stateSlot = humaneSlotNum(state.data.slot),
|
||||
justifiedEpoch = humaneEpochNum(state.data.justified_epoch),
|
||||
justifiedEpoch = humaneEpochNum(state.data.current_justified_epoch),
|
||||
finalizedEpoch = humaneEpochNum(state.data.finalized_epoch)
|
||||
|
||||
let
|
||||
|
@ -10,8 +10,8 @@ import
|
||||
../extras, ../ssz,
|
||||
./crypto, ./datatypes, ./digest, ./helpers, ./validator
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_effective_balance
|
||||
func get_effective_balance*(state: BeaconState, index: ValidatorIndex): uint64 =
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_effective_balance
|
||||
func get_effective_balance*(state: BeaconState, index: ValidatorIndex): Gwei =
|
||||
## Return the effective balance (also known as "balance at stake") for a
|
||||
## validator with the given ``index``.
|
||||
min(state.validator_balances[index], MAX_DEPOSIT_AMOUNT)
|
||||
@ -61,13 +61,13 @@ func process_deposit(state: var BeaconState, deposit: Deposit) =
|
||||
|
||||
state.validator_balances[index] += amount
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_delayed_activation_exit_epoch
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_delayed_activation_exit_epoch
|
||||
func get_delayed_activation_exit_epoch*(epoch: Epoch): Epoch =
|
||||
## Return the epoch at which an activation or exit triggered in ``epoch``
|
||||
## takes effect.
|
||||
epoch + 1 + ACTIVATION_EXIT_DELAY
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#activate_validator
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#activate_validator
|
||||
func activate_validator(state: var BeaconState,
|
||||
index: ValidatorIndex,
|
||||
is_genesis: bool) =
|
||||
@ -81,7 +81,7 @@ func activate_validator(state: var BeaconState,
|
||||
else:
|
||||
get_delayed_activation_exit_epoch(get_current_epoch(state))
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#initiate_validator_exit
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#initiate_validator_exit
|
||||
func initiate_validator_exit*(state: var BeaconState,
|
||||
index: ValidatorIndex) =
|
||||
## Initiate exit for the validator with the given ``index``.
|
||||
@ -107,7 +107,7 @@ func reduce_balance*(balance: var uint64, amount: uint64) =
|
||||
# Not in spec, but useful to avoid underflow.
|
||||
balance -= min(amount, balance)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#slash_validator
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#slash_validator
|
||||
func slash_validator*(state: var BeaconState, index: ValidatorIndex) =
|
||||
## Slash the validator with index ``index``.
|
||||
## Note that this function mutates ``state``.
|
||||
@ -155,7 +155,22 @@ func update_shuffling_cache*(state: var BeaconState) =
|
||||
state.shuffling_cache.shuffling_1 = shuffling_seq
|
||||
state.shuffling_cache.index = 1 - state.shuffling_cache.index
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_temporary_block_header
|
||||
func get_temporary_block_header*(blck: BeaconBlock): BeaconBlockHeader =
|
||||
## Return the block header corresponding to a block with ``state_root`` set
|
||||
## to ``ZERO_HASH``.
|
||||
BeaconBlockHeader(
|
||||
slot: blck.slot.uint64,
|
||||
previous_block_root: blck.previous_block_root,
|
||||
state_root: ZERO_HASH,
|
||||
block_body_root: hash_tree_root_final(blck.body),
|
||||
signature: blck.signature)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#on-genesis
|
||||
func get_empty_block*(): BeaconBlock =
|
||||
# Nim default values fill this in fine, mostly.
|
||||
result.slot = GENESIS_SLOT
|
||||
|
||||
func get_genesis_beacon_state*(
|
||||
genesis_validator_deposits: openArray[Deposit],
|
||||
genesis_time: uint64,
|
||||
@ -204,7 +219,7 @@ func get_genesis_beacon_state*(
|
||||
|
||||
# Finality
|
||||
previous_justified_epoch: GENESIS_EPOCH,
|
||||
justified_epoch: GENESIS_EPOCH,
|
||||
current_justified_epoch: GENESIS_EPOCH,
|
||||
justification_bitfield: 0,
|
||||
finalized_epoch: GENESIS_EPOCH,
|
||||
|
||||
@ -214,6 +229,7 @@ func get_genesis_beacon_state*(
|
||||
# Recent state
|
||||
# latest_block_roots, latest_active_index_roots, latest_slashed_balances,
|
||||
# latest_attestations, and batched_block_roots automatically initialized.
|
||||
latest_block_header: get_temporary_block_header(get_empty_block()),
|
||||
)
|
||||
|
||||
for i in 0 ..< SHARD_COUNT:
|
||||
@ -251,14 +267,14 @@ func get_initial_beacon_block*(state: BeaconState): BeaconBlock =
|
||||
# initialized to default values.
|
||||
)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_block_root
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_block_root
|
||||
func get_block_root*(state: BeaconState,
|
||||
slot: Slot): Eth2Digest =
|
||||
# Return the block root at a recent ``slot``.
|
||||
|
||||
doAssert state.slot <= slot + LATEST_BLOCK_ROOTS_LENGTH
|
||||
doAssert state.slot <= slot + SLOTS_PER_HISTORICAL_ROOT
|
||||
doAssert slot < state.slot
|
||||
state.latest_block_roots[slot mod LATEST_BLOCK_ROOTS_LENGTH]
|
||||
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
|
||||
func get_attestation_participants*(state: BeaconState,
|
||||
@ -304,17 +320,26 @@ func process_ejections*(state: var BeaconState) =
|
||||
## Iterate through the validator registry and eject active validators with
|
||||
## balance below ``EJECTION_BALANCE``
|
||||
for index in get_active_validator_indices(
|
||||
# Spec bug in 0.4.0: is just current_epoch(state)
|
||||
state.validator_registry, get_current_epoch(state)):
|
||||
if state.validator_balances[index] < EJECTION_BALANCE:
|
||||
exit_validator(state, index)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_total_balance
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_total_balance
|
||||
func get_total_balance*(state: BeaconState, validators: auto): Gwei =
|
||||
# Return the combined effective balance of an array of validators.
|
||||
foldl(validators, a + get_effective_balance(state, b), 0'u64)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#validator-registry-and-shuffling-seed-data
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#validator-registry-and-shuffling-seed-data
|
||||
func should_update_validator_registry*(state: BeaconState): bool =
|
||||
# Must have finalized a new block
|
||||
if state.finalized_epoch <= state.validator_registry_update_epoch:
|
||||
return false
|
||||
# Must have processed new crosslinks on all shards of the current epoch
|
||||
allIt(0 ..< get_current_epoch_committee_count(state).int,
|
||||
not (state.latest_crosslinks[
|
||||
((state.current_shuffling_start_shard + it.uint64) mod
|
||||
SHARD_COUNT).int].epoch <= state.validator_registry_update_epoch))
|
||||
|
||||
func update_validator_registry*(state: var BeaconState) =
|
||||
## Update validator registry.
|
||||
## Note that this function mutates ``state``.
|
||||
@ -389,7 +414,7 @@ proc checkAttestation*(
|
||||
|
||||
let expected_justified_epoch =
|
||||
if slot_to_epoch(attestation.data.slot + 1) >= get_current_epoch(state):
|
||||
state.justified_epoch
|
||||
state.current_justified_epoch
|
||||
else:
|
||||
state.previous_justified_epoch
|
||||
|
||||
@ -488,7 +513,7 @@ proc checkAttestation*(
|
||||
|
||||
true
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#prepare_validator_for_withdrawal
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#prepare_validator_for_withdrawal
|
||||
func prepare_validator_for_withdrawal*(state: var BeaconState, index: ValidatorIndex) =
|
||||
## Set the validator with the given ``index`` as withdrawable
|
||||
## ``MIN_VALIDATOR_WITHDRAWABILITY_DELAY`` after the current epoch.
|
||||
@ -511,7 +536,7 @@ proc makeAttestationData*(
|
||||
epoch_boundary_root =
|
||||
if epoch_start_slot == state.slot: beacon_block_root
|
||||
else: get_block_root(state, epoch_start_slot)
|
||||
justified_slot = get_epoch_start_slot(state.justified_epoch)
|
||||
justified_slot = get_epoch_start_slot(state.current_justified_epoch)
|
||||
justified_block_root = get_block_root(state, justified_slot)
|
||||
|
||||
AttestationData(
|
||||
@ -521,6 +546,6 @@ proc makeAttestationData*(
|
||||
epoch_boundary_root: epoch_boundary_root,
|
||||
crosslink_data_root: Eth2Digest(), # Stub in phase0
|
||||
latest_crosslink: state.latest_crosslinks[shard],
|
||||
justified_epoch: state.justified_epoch,
|
||||
justified_epoch: state.current_justified_epoch,
|
||||
justified_block_root: justified_block_root,
|
||||
)
|
||||
|
@ -68,7 +68,7 @@ template hash*(k: ValidatorPubKey|ValidatorPrivKey): Hash =
|
||||
|
||||
func pubKey*(pk: ValidatorPrivKey): ValidatorPubKey = pk.getKey()
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/bls_signature.md#bls_aggregate_pubkeys
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/bls_signature.md#bls_aggregate_pubkeys
|
||||
func bls_aggregate_pubkeys*(keys: openArray[ValidatorPubKey]): ValidatorPubKey =
|
||||
var empty = true
|
||||
for key in keys:
|
||||
@ -78,14 +78,14 @@ func bls_aggregate_pubkeys*(keys: openArray[ValidatorPubKey]): ValidatorPubKey =
|
||||
else:
|
||||
result.combine(key)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/bls_signature.md#bls_verify
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/bls_signature.md#bls_verify
|
||||
func bls_verify*(
|
||||
pubkey: ValidatorPubKey, msg: openArray[byte], sig: ValidatorSig,
|
||||
domain: uint64): bool =
|
||||
# name from spec!
|
||||
sig.verify(msg, domain, pubkey)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/bls_signature.md#bls_verify_multiple
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/bls_signature.md#bls_verify_multiple
|
||||
func bls_verify_multiple*(
|
||||
pubkeys: seq[ValidatorPubKey], message_hashes: seq[array[0..31, byte]],
|
||||
sig: ValidatorSig, domain: uint64): bool =
|
||||
|
@ -82,11 +82,11 @@ const
|
||||
SHUFFLE_ROUND_COUNT* = 90
|
||||
|
||||
# Deposit contract
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#deposit-contract
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#deposit-contract
|
||||
DEPOSIT_CONTRACT_TREE_DEPTH* = 2^5
|
||||
|
||||
# Gwei values
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#gwei-values
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#gwei-values
|
||||
MIN_DEPOSIT_AMOUNT* = 2'u64^0 * 10'u64^9 ##\
|
||||
## Minimum amounth of ETH that can be deposited in one call - deposits can
|
||||
## be used either to top up an existing validator or commit to a new one
|
||||
@ -106,8 +106,7 @@ const
|
||||
## processing is done
|
||||
## Compile with -d:SLOTS_PER_EPOCH=4 for shorter epochs
|
||||
|
||||
# Initial values
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#initial-values
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#initial-values
|
||||
GENESIS_FORK_VERSION* = 0'u64
|
||||
GENESIS_SLOT* = (2'u64^32).Slot
|
||||
GENESIS_EPOCH* = (GENESIS_SLOT.uint64 div SLOTS_PER_EPOCH).Epoch ##\
|
||||
@ -146,18 +145,18 @@ const
|
||||
EPOCHS_PER_ETH1_VOTING_PERIOD* = 2'u64^4 ##\
|
||||
## epochs (~1.7 hours)
|
||||
|
||||
SLOTS_PER_HISTORICAL_ROOT* = 8192 ##\
|
||||
## slots (13 hours)
|
||||
|
||||
MIN_VALIDATOR_WITHDRAWABILITY_DELAY* = 2'u64^8 ##\
|
||||
## epochs (~27 hours)
|
||||
|
||||
# State list lengths
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#state-list-lengths
|
||||
LATEST_BLOCK_ROOTS_LENGTH* = 2'u64^13
|
||||
LATEST_RANDAO_MIXES_LENGTH* = 2'u64^13
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#state-list-lengths
|
||||
LATEST_RANDAO_MIXES_LENGTH* = 8192
|
||||
LATEST_ACTIVE_INDEX_ROOTS_LENGTH* = 8192 # 2'u64^13, epochs
|
||||
LATEST_SLASHED_EXIT_LENGTH* = 8192 # epochs
|
||||
|
||||
# Reward and penalty quotients
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#reward-and-penalty-quotients
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#reward-and-penalty-quotients
|
||||
BASE_REWARD_QUOTIENT* = 2'u64^5 ##\
|
||||
## The `BASE_REWARD_QUOTIENT` parameter dictates the per-epoch reward. It
|
||||
## corresponds to ~2.54% annual interest assuming 10 million participating
|
||||
@ -167,8 +166,7 @@ const
|
||||
INACTIVITY_PENALTY_QUOTIENT* = 2'u64^24
|
||||
MIN_PENALTY_QUOTIENT* = 32 # 2^5
|
||||
|
||||
# Max transactions per block
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#max-transactions-per-block
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#max-transactions-per-block
|
||||
MAX_PROPOSER_SLASHINGS* = 2^4
|
||||
MAX_ATTESTER_SLASHINGS* = 2^0
|
||||
MAX_ATTESTATIONS* = 2^7
|
||||
@ -181,16 +179,16 @@ type
|
||||
|
||||
Gwei* = uint64
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#proposerslashing
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#proposerslashing
|
||||
ProposerSlashing* = object
|
||||
proposer_index*: uint64 ##\
|
||||
## Proposer index
|
||||
|
||||
proposal_1*: Proposal ##\
|
||||
# First proposal
|
||||
header_1*: BeaconBlockHeader ##\
|
||||
# First block header
|
||||
|
||||
proposal_2*: Proposal ##\
|
||||
# Second proposal
|
||||
header_2*: BeaconBlockHeader ##\
|
||||
# Second block header
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#attesterslashing
|
||||
AttesterSlashing* = object
|
||||
@ -199,7 +197,7 @@ type
|
||||
slashable_attestation_2*: SlashableAttestation ## \
|
||||
## Second slashable attestation
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#slashableattestation
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#slashableattestation
|
||||
SlashableAttestation* = object
|
||||
validator_indices*: seq[uint64] ##\
|
||||
## Validator indices
|
||||
@ -253,7 +251,7 @@ type
|
||||
justified_block_root*: Eth2Digest ##\
|
||||
## Hash of the last justified beacon block
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#attestationdataandcustodybit
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#attestationdataandcustodybit
|
||||
AttestationDataAndCustodyBit* = object
|
||||
data*: AttestationData
|
||||
custody_bit*: bool
|
||||
@ -269,20 +267,20 @@ type
|
||||
deposit_data*: DepositData ##\
|
||||
## Data
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#depositdata
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#depositdata
|
||||
DepositData* = object
|
||||
amount*: uint64 ## Amount in Gwei
|
||||
timestamp*: uint64 # Timestamp from deposit contract
|
||||
deposit_input*: DepositInput
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#depositinput
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#depositinput
|
||||
DepositInput* = object
|
||||
pubkey*: ValidatorPubKey
|
||||
withdrawal_credentials*: Eth2Digest
|
||||
proof_of_possession*: ValidatorSig ##\
|
||||
## A BLS signature of this `DepositInput`
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#voluntaryexit
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#voluntaryexit
|
||||
VoluntaryExit* = object
|
||||
# Minimum epoch for processing exit
|
||||
epoch*: Epoch
|
||||
@ -314,7 +312,7 @@ type
|
||||
signature*: ValidatorSig ##\
|
||||
## Sender signature
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#beaconblock
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#beaconblock
|
||||
BeaconBlock* = object
|
||||
## For each slot, a proposer is chosen from the validator pool to propose
|
||||
## a new block. Once the block as been proposed, it is transmitted to
|
||||
@ -323,26 +321,33 @@ type
|
||||
## is formed.
|
||||
|
||||
slot*: Slot
|
||||
parent_root*: Eth2Digest ##\
|
||||
|
||||
previous_block_root*: Eth2Digest ##\
|
||||
##\ Root hash of the previous block
|
||||
|
||||
state_root*: Eth2Digest ##\
|
||||
## The state root, _after_ this block has been processed
|
||||
|
||||
randao_reveal*: ValidatorSig ##\
|
||||
## Proposer RANDAO reveal
|
||||
|
||||
eth1_data*: Eth1Data
|
||||
|
||||
body*: BeaconBlockBody
|
||||
|
||||
signature*: ValidatorSig ##\
|
||||
## Proposer signature
|
||||
|
||||
#https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#beaconblockheader
|
||||
BeaconBlockHeader* = object
|
||||
slot*: uint64
|
||||
previous_block_root*: Eth2Digest
|
||||
state_root*: Eth2Digest
|
||||
block_body_root*: Eth2Digest
|
||||
signature*: ValidatorSig
|
||||
|
||||
BeaconBlockHeaderRLP* = object
|
||||
## Same as BeaconBlock, except `body` is the `hash_tree_root` of the
|
||||
## associated BeaconBlockBody.
|
||||
# TODO: Dry it up with BeaconBlock
|
||||
# TODO: As a first step, don't change RLP output; only previous user,
|
||||
# but as with others, randao_reveal and eth1_data move to body.
|
||||
# This is from before spec had a version.
|
||||
slot*: uint64
|
||||
parent_root*: Eth2Digest
|
||||
state_root*: Eth2Digest
|
||||
@ -351,8 +356,10 @@ type
|
||||
signature*: ValidatorSig
|
||||
body*: Eth2Digest
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#beaconblockbody
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#beaconblockbody
|
||||
BeaconBlockBody* = object
|
||||
randao_reveal*: ValidatorSig
|
||||
eth1_data*: Eth1Data
|
||||
proposer_slashings*: seq[ProposerSlashing]
|
||||
attester_slashings*: seq[AttesterSlashing]
|
||||
attestations*: seq[Attestation]
|
||||
@ -374,7 +381,7 @@ type
|
||||
signature*: ValidatorSig ##\
|
||||
## Signature
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#beaconstate
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#beaconstate
|
||||
BeaconState* = object
|
||||
slot*: Slot
|
||||
genesis_time*: uint64
|
||||
@ -393,7 +400,7 @@ type
|
||||
## For light clients to easily track delta
|
||||
|
||||
# Randomness and committees
|
||||
latest_randao_mixes*: array[LATEST_BLOCK_ROOTS_LENGTH.int, Eth2Digest]
|
||||
latest_randao_mixes*: array[LATEST_RANDAO_MIXES_LENGTH, Eth2Digest]
|
||||
previous_shuffling_start_shard*: uint64
|
||||
current_shuffling_start_shard*: uint64
|
||||
previous_shuffling_epoch*: Epoch
|
||||
@ -402,20 +409,31 @@ type
|
||||
current_shuffling_seed*: Eth2Digest
|
||||
|
||||
# Finality
|
||||
previous_epoch_attestations*: seq[PendingAttestation]
|
||||
current_epoch_attestations*: seq[PendingAttestation]
|
||||
previous_justified_epoch*: Epoch
|
||||
justified_epoch*: Epoch
|
||||
current_justified_epoch*: Epoch
|
||||
previous_justified_root*: Eth2Digest
|
||||
current_justified_root*: Eth2Digest
|
||||
justification_bitfield*: uint64
|
||||
finalized_epoch*: Epoch
|
||||
finalized_root*: Eth2Digest
|
||||
|
||||
# Recent state
|
||||
latest_crosslinks*: array[SHARD_COUNT, Crosslink]
|
||||
latest_block_roots*: array[LATEST_BLOCK_ROOTS_LENGTH.int, Eth2Digest] ##\
|
||||
latest_block_roots*: array[SLOTS_PER_HISTORICAL_ROOT, Eth2Digest] ##\
|
||||
## Needed to process attestations, older to newer
|
||||
latest_active_index_roots*: array[LATEST_ACTIVE_INDEX_ROOTS_LENGTH.int, Eth2Digest]
|
||||
latest_state_roots*: array[SLOTS_PER_HISTORICAL_ROOT, Eth2Digest]
|
||||
latest_active_index_roots*: array[LATEST_ACTIVE_INDEX_ROOTS_LENGTH, Eth2Digest]
|
||||
|
||||
latest_slashed_balances*: array[LATEST_SLASHED_EXIT_LENGTH, uint64] ##\
|
||||
## Balances penalized in the current withdrawal period
|
||||
|
||||
latest_block_header*: BeaconBlockHeader ##\
|
||||
## `latest_block_header.state_root == ZERO_HASH` temporarily
|
||||
historical_roots*: seq[Eth2Digest]
|
||||
|
||||
# TOOD remove these, gone in 0.5
|
||||
latest_attestations*: seq[PendingAttestation]
|
||||
batched_block_roots*: seq[Eth2Digest]
|
||||
|
||||
@ -427,7 +445,7 @@ type
|
||||
# Not in spec. TODO: don't serialize or deserialize this.
|
||||
shuffling_cache*: ShufflingCache
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#validator
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#validator
|
||||
Validator* = object
|
||||
pubkey*: ValidatorPubKey ##\
|
||||
## BLS public key
|
||||
@ -450,7 +468,7 @@ type
|
||||
slashed*: bool ##\
|
||||
## Was the validator slashed
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#crosslink
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#crosslink
|
||||
Crosslink* = object
|
||||
epoch*: Epoch ##\
|
||||
## Epoch number
|
||||
@ -458,20 +476,20 @@ type
|
||||
crosslink_data_root*: Eth2Digest ##\
|
||||
## Shard data since the previous crosslink
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#pendingattestation
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#pendingattestation
|
||||
PendingAttestation* = object
|
||||
aggregation_bitfield*: seq[byte] # Attester participation bitfield
|
||||
data*: AttestationData # Attestation data
|
||||
custody_bitfield*: seq[byte] # Custody bitfield
|
||||
inclusion_slot*: Slot # Inclusion slot
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#fork
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#fork
|
||||
Fork* = object
|
||||
previous_version*: uint64 # Previous fork version
|
||||
current_version*: uint64 # Current fork version
|
||||
epoch*: Epoch # Fork epoch number
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#eth1data
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#eth1data
|
||||
Eth1Data* = object
|
||||
deposit_root*: Eth2Digest ##\
|
||||
## Data being voted for
|
||||
@ -479,7 +497,7 @@ type
|
||||
block_hash*: Eth2Digest ##\
|
||||
## Block hash
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#eth1datavote
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#eth1datavote
|
||||
Eth1DataVote* = object
|
||||
eth1_data*: Eth1Data ##\
|
||||
## Data being voted for
|
||||
@ -493,13 +511,13 @@ type
|
||||
Activation = 0
|
||||
Exit = 1
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#signature-domains
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#signature-domains
|
||||
SignatureDomain* {.pure.} = enum
|
||||
DOMAIN_DEPOSIT = 0
|
||||
DOMAIN_ATTESTATION = 1
|
||||
DOMAIN_PROPOSAL = 2
|
||||
DOMAIN_EXIT = 3
|
||||
DOMAIN_RANDAO = 4
|
||||
DOMAIN_BEACON_BLOCK = 0
|
||||
DOMAIN_RANDAO = 1
|
||||
DOMAIN_ATTESTATION = 2
|
||||
DOMAIN_DEPOSIT = 3
|
||||
DOMAIN_VOLUNTARY_EXIT = 4
|
||||
DOMAIN_TRANSFER = 5
|
||||
|
||||
# TODO: not in spec
|
||||
@ -578,8 +596,8 @@ func humaneEpochNum*(e: Epoch): uint64 =
|
||||
e - GENESIS_EPOCH
|
||||
|
||||
func shortLog*(v: BeaconBlock): tuple[
|
||||
slot: uint64, parent_root: string, state_root: string,
|
||||
randao_reveal: string, #[ eth1_data ]#
|
||||
slot: uint64, previous_block_root: string, state_root: string,
|
||||
#[ eth1_data ]#
|
||||
proposer_slashings_len: int, attester_slashings_len: int,
|
||||
attestations_len: int,
|
||||
deposits_len: int,
|
||||
@ -587,8 +605,8 @@ func shortLog*(v: BeaconBlock): tuple[
|
||||
transfers_len: int,
|
||||
signature: string
|
||||
] = (
|
||||
humaneSlotNum(v.slot), shortLog(v.parent_root), shortLog(v.state_root),
|
||||
shortLog(v.randao_reveal), v.body.proposer_slashings.len(),
|
||||
humaneSlotNum(v.slot), shortLog(v.previous_block_root),
|
||||
shortLog(v.state_root), v.body.proposer_slashings.len(),
|
||||
v.body.attester_slashings.len(), v.body.attestations.len(),
|
||||
v.body.deposits.len(), v.body.voluntary_exits.len(), v.body.transfers.len(),
|
||||
shortLog(v.signature)
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
# Serenity hash function / digest
|
||||
#
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#hash
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#hash
|
||||
#
|
||||
# In Phase 0 the beacon chain is deployed with the same hash function as
|
||||
# Ethereum 1.0, i.e. Keccak-256 (also incorrectly known as SHA3).
|
||||
|
@ -14,14 +14,14 @@ import ./datatypes, ./digest, sequtils, math
|
||||
func bitSet*(bitfield: var openArray[byte], index: int) =
|
||||
bitfield[index div 8] = bitfield[index div 8] or 1'u8 shl (7 - (index mod 8))
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_bitfield_bit
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_bitfield_bit
|
||||
func get_bitfield_bit*(bitfield: openarray[byte], i: int): byte =
|
||||
# Extract the bit in ``bitfield`` at position ``i``.
|
||||
doAssert 0 <= i div 8, "i: " & $i & " i div 8: " & $(i div 8)
|
||||
doAssert i div 8 < bitfield.len, "i: " & $i & " i div 8: " & $(i div 8)
|
||||
(bitfield[i div 8] shr (7 - (i mod 8))) mod 2
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#verify_bitfield
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#verify_bitfield
|
||||
func verify_bitfield*(bitfield: openarray[byte], committee_size: int): bool =
|
||||
# Verify ``bitfield`` against the ``committee_size``.
|
||||
if len(bitfield) != (committee_size + 7) div 8:
|
||||
@ -34,7 +34,7 @@ func verify_bitfield*(bitfield: openarray[byte], committee_size: int): bool =
|
||||
|
||||
true
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#split
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#split
|
||||
func split*[T](lst: openArray[T], N: Positive): seq[seq[T]] =
|
||||
## split lst in N pieces, with each piece having `len(lst) div N` or
|
||||
## `len(lst) div N + 1` pieces
|
||||
@ -56,9 +56,11 @@ func get_new_recent_block_roots*(old_block_roots: seq[Eth2Digest],
|
||||
|
||||
func ceil_div8*(v: int): int = (v + 7) div 8 # TODO use a proper bitarray!
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#integer_squareroot
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#integer_squareroot
|
||||
func integer_squareroot*(n: SomeInteger): SomeInteger =
|
||||
## The largest integer ``x`` such that ``x**2`` is less than ``n``.
|
||||
doAssert n >= 0'u64
|
||||
|
||||
var
|
||||
x = n
|
||||
y = (x + 1) div 2
|
||||
@ -81,8 +83,8 @@ func get_domain*(
|
||||
# Get the domain number that represents the fork meta and signature domain.
|
||||
(get_fork_version(fork, epoch) shl 32) + domain_type.uint32
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#is_power_of_two
|
||||
func is_power_of_2*(v: uint64): bool = (v and (v-1)) == 0
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#is_power_of_two
|
||||
func is_power_of_2*(v: uint64): bool = (v > 0'u64) and (v and (v-1)) == 0
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#merkle_root
|
||||
func merkle_root*(values: openArray[Eth2Digest]): Eth2Digest =
|
||||
@ -119,16 +121,16 @@ func merkle_root*(values: openArray[Eth2Digest]): Eth2Digest =
|
||||
|
||||
o[1]
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#slot_to_epoch
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#slot_to_epoch
|
||||
func slot_to_epoch*(slot: Slot|uint64): Epoch =
|
||||
(slot div SLOTS_PER_EPOCH).Epoch
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_epoch_start_slot
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_epoch_start_slot
|
||||
func get_epoch_start_slot*(epoch: Epoch): Slot =
|
||||
# Return the starting slot of the given ``epoch``.
|
||||
(epoch * SLOTS_PER_EPOCH).Slot
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#is_double_vote
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#is_double_vote
|
||||
func is_double_vote*(attestation_data_1: AttestationData,
|
||||
attestation_data_2: AttestationData): bool =
|
||||
## Check if ``attestation_data_1`` and ``attestation_data_2`` have the same
|
||||
@ -139,7 +141,7 @@ func is_double_vote*(attestation_data_1: AttestationData,
|
||||
target_epoch_2 = slot_to_epoch(attestation_data_2.slot)
|
||||
target_epoch_1 == target_epoch_2
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#is_surround_vote
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#is_surround_vote
|
||||
func is_surround_vote*(attestation_data_1: AttestationData,
|
||||
attestation_data_2: AttestationData): bool =
|
||||
## Check if ``attestation_data_1`` surrounds ``attestation_data_2``.
|
||||
@ -152,7 +154,7 @@ func is_surround_vote*(attestation_data_1: AttestationData,
|
||||
|
||||
source_epoch_1 < source_epoch_2 and target_epoch_2 < target_epoch_1
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#is_active_validator
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#is_active_validator
|
||||
func is_active_validator*(validator: Validator, epoch: Epoch): bool =
|
||||
### Check if ``validator`` is active
|
||||
validator.activation_epoch <= epoch and epoch < validator.exit_epoch
|
||||
@ -170,7 +172,7 @@ func get_epoch_committee_count*(active_validator_count: int): uint64 =
|
||||
active_validator_count div SLOTS_PER_EPOCH div TARGET_COMMITTEE_SIZE,
|
||||
1, SHARD_COUNT div SLOTS_PER_EPOCH).uint64 * SLOTS_PER_EPOCH
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_current_epoch_committee_count
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_current_epoch_committee_count
|
||||
func get_current_epoch_committee_count*(state: BeaconState): uint64 =
|
||||
# Return the number of committees in the current epoch of the given ``state``.
|
||||
let current_active_validators = get_active_validator_indices(
|
||||
@ -179,13 +181,13 @@ func get_current_epoch_committee_count*(state: BeaconState): uint64 =
|
||||
)
|
||||
get_epoch_committee_count(len(current_active_validators))
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_current_epoch
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_current_epoch
|
||||
func get_current_epoch*(state: BeaconState): Epoch =
|
||||
# Return the current epoch of the given ``state``.
|
||||
doAssert state.slot >= GENESIS_SLOT, $state.slot
|
||||
slot_to_epoch(state.slot)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_randao_mix
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_randao_mix
|
||||
func get_randao_mix*(state: BeaconState,
|
||||
epoch: Epoch): Eth2Digest =
|
||||
## Returns the randao mix at a recent ``epoch``.
|
||||
@ -196,7 +198,7 @@ func get_randao_mix*(state: BeaconState,
|
||||
|
||||
state.latest_randao_mixes[epoch mod LATEST_RANDAO_MIXES_LENGTH]
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_active_index_root
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_active_index_root
|
||||
func get_active_index_root(state: BeaconState, epoch: Epoch): Eth2Digest =
|
||||
# Returns the index root at a recent ``epoch``.
|
||||
|
||||
@ -216,7 +218,7 @@ func bytes_to_int*(data: seq[byte]): uint64 =
|
||||
for i in countdown(7, 0):
|
||||
result = result * 256 + data[i]
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#int_to_bytes1-int_to_bytes2-
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#int_to_bytes1-int_to_bytes2-
|
||||
# Have 1, 4, and 32-byte versions. 2+ more and maybe worth metaprogramming.
|
||||
func int_to_bytes32*(x: uint64): array[32, byte] =
|
||||
## Little-endian data representation
|
||||
@ -242,7 +244,7 @@ func int_to_bytes4*(x: uint64): array[4, byte] =
|
||||
result[2] = ((x shr 16) and 0xff).byte
|
||||
result[3] = ((x shr 24) and 0xff).byte
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#generate_seed
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#generate_seed
|
||||
func generate_seed*(state: BeaconState, epoch: Epoch): Eth2Digest =
|
||||
# Generate a seed for the given ``epoch``.
|
||||
|
||||
|
@ -103,7 +103,7 @@ func get_shuffling*(seed: Eth2Digest,
|
||||
result = split(shuffled_seq, committees_per_epoch)
|
||||
doAssert result.len() == committees_per_epoch # what split should do..
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_previous_epoch_committee_count
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_previous_epoch_committee_count
|
||||
func get_previous_epoch_committee_count(state: BeaconState): uint64 =
|
||||
## Return the number of committees in the previous epoch of the given
|
||||
## ``state``.
|
||||
@ -113,7 +113,7 @@ func get_previous_epoch_committee_count(state: BeaconState): uint64 =
|
||||
)
|
||||
get_epoch_committee_count(len(previous_active_validators))
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_next_epoch_committee_count
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_next_epoch_committee_count
|
||||
func get_next_epoch_committee_count(state: BeaconState): uint64 =
|
||||
## Return the number of committees in the next epoch of the given ``state``.
|
||||
let next_active_validators = get_active_validator_indices(
|
||||
@ -140,8 +140,6 @@ func get_crosslink_committees_at_slot*(state: BeaconState, slot: Slot|uint64,
|
||||
# TODO: the + 1 here works around a bug, remove when upgrading to
|
||||
# some more recent version:
|
||||
# https://github.com/ethereum/eth2.0-specs/pull/732
|
||||
# It's not 100% clear to me regarding 0.4.0; waiting until 0.5.0 to remove
|
||||
# TODO recheck
|
||||
epoch = slot_to_epoch(slot + 1)
|
||||
current_epoch = get_current_epoch(state)
|
||||
previous_epoch = get_previous_epoch(state)
|
||||
@ -217,7 +215,7 @@ func get_crosslink_committees_at_slot*(state: BeaconState, slot: Slot|uint64,
|
||||
(slot_start_shard + i.uint64) mod SHARD_COUNT
|
||||
)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_beacon_proposer_index
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_beacon_proposer_index
|
||||
func get_beacon_proposer_index*(state: BeaconState, slot: Slot): ValidatorIndex =
|
||||
## From Casper RPJ mini-spec:
|
||||
## When slot i begins, validator Vidx is expected
|
||||
@ -232,6 +230,15 @@ func get_beacon_proposer_index*(state: BeaconState, slot: Slot): ValidatorIndex
|
||||
# because presently, `state.slot += 1` happens before this function
|
||||
# is called - see also testutil.getNextBeaconProposerIndex
|
||||
# TODO is the above still true? the shuffling has changed since it was written
|
||||
let
|
||||
epoch = slot_to_epoch(slot)
|
||||
current_epoch = get_current_epoch(state)
|
||||
previous_epoch = get_previous_epoch(state)
|
||||
next_epoch = current_epoch + 1
|
||||
|
||||
doAssert previous_epoch <= epoch
|
||||
doAssert epoch <= next_epoch
|
||||
|
||||
let (first_committee, _) = get_crosslink_committees_at_slot(state, slot)[0]
|
||||
let idx = int(slot mod uint64(first_committee.len))
|
||||
first_committee[idx]
|
||||
|
@ -315,14 +315,15 @@ func hash_tree_root*[T: object|tuple](x: T): array[32, byte] =
|
||||
h.update hash_tree_root(field.toSSZType)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/simple-serialize.md#signed-roots
|
||||
func signed_root*[T: object](x: T, field_name: string): array[32, byte] =
|
||||
func signed_root*[T: object](x: T, ignored: string = "sig"): array[32, byte] =
|
||||
# TODO write tests for this (check vs hash_tree_root)
|
||||
|
||||
var found_field_name = false
|
||||
|
||||
## TODO this isn't how 0.5 defines signed_root, but works well enough
|
||||
withHash:
|
||||
for name, field in x.fieldPairs:
|
||||
if name == field_name:
|
||||
if name == "signature":
|
||||
found_field_name = true
|
||||
break
|
||||
h.update hash_tree_root(field.toSSZType)
|
||||
|
@ -57,9 +57,44 @@ func verifyBlockSignature(state: BeaconState, blck: BeaconBlock): bool =
|
||||
proposer.pubkey,
|
||||
signed_root(proposal, "signature"),
|
||||
proposal.signature,
|
||||
get_domain(state.fork, get_current_epoch(state), DOMAIN_PROPOSAL))
|
||||
get_domain(state.fork, get_current_epoch(state), DOMAIN_BEACON_BLOCK))
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#randao
|
||||
# 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 =
|
||||
# Verify that the slots match
|
||||
if not (blck.slot == state.slot):
|
||||
notice "Block header: slot mismatch",
|
||||
block_slot = humaneSlotNum(blck.slot),
|
||||
state_slot = humaneSlotNum(state.slot)
|
||||
return false
|
||||
|
||||
if not (blck.previous_block_root ==
|
||||
hash_tree_root_final(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)
|
||||
|
||||
let proposer =
|
||||
state.validator_registry[get_beacon_proposer_index(state, state.slot)]
|
||||
if skipValidation notin flags and not bls_verify(
|
||||
proposer.pubkey,
|
||||
signed_root(blck),
|
||||
blck.signature,
|
||||
get_domain(state.fork, get_current_epoch(state), DOMAIN_BEACON_BLOCK)):
|
||||
notice "Block header: invalid block header",
|
||||
proposer_pubkey = proposer.pubkey,
|
||||
signed_root_block = signed_root(blck),
|
||||
block_signature = blck.signature
|
||||
return false
|
||||
|
||||
true
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#randao
|
||||
proc processRandao(
|
||||
state: var BeaconState, blck: BeaconBlock, flags: UpdateFlags): bool =
|
||||
let
|
||||
@ -70,20 +105,21 @@ proc processRandao(
|
||||
if not bls_verify(
|
||||
proposer.pubkey,
|
||||
hash_tree_root(get_current_epoch(state).uint64),
|
||||
blck.randao_reveal,
|
||||
blck.body.randao_reveal,
|
||||
get_domain(state.fork, get_current_epoch(state), DOMAIN_RANDAO)):
|
||||
|
||||
notice "Randao mismatch", proposer_pubkey = proposer.pubkey,
|
||||
message = get_current_epoch(state),
|
||||
signature = blck.randao_reveal,
|
||||
signature = blck.body.randao_reveal,
|
||||
slot = state.slot,
|
||||
blck_slot = blck.slot
|
||||
return false
|
||||
|
||||
# Update state and proposer now that we're alright
|
||||
# Mix it in
|
||||
let
|
||||
mix = get_current_epoch(state) mod LATEST_RANDAO_MIXES_LENGTH
|
||||
rr = hash_tree_root_final(blck.randao_reveal).data
|
||||
# TODO hash_tree_root has some overloading for this
|
||||
rr = eth2hash(blck.body.randao_reveal.getBytes()).data
|
||||
|
||||
for i, b in state.latest_randao_mixes[mix].data:
|
||||
state.latest_randao_mixes[mix].data[i] = b xor rr[i]
|
||||
@ -94,16 +130,16 @@ proc processRandao(
|
||||
func processDepositRoot(state: var BeaconState, blck: BeaconBlock) =
|
||||
# TODO verify that there's at most one match
|
||||
for x in state.eth1_data_votes.mitems():
|
||||
if blck.eth1_data == x.eth1_data:
|
||||
if blck.body.eth1_data == x.eth1_data:
|
||||
x.vote_count += 1
|
||||
return
|
||||
|
||||
state.eth1_data_votes.add Eth1DataVote(
|
||||
eth1_data: blck.eth1_data,
|
||||
eth1_data: blck.body.eth1_data,
|
||||
vote_count: 1
|
||||
)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#proposer-slashings-1
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#proposer-slashings
|
||||
proc processProposerSlashings(
|
||||
state: var BeaconState, blck: BeaconBlock, flags: UpdateFlags): bool =
|
||||
if len(blck.body.proposer_slashings) > MAX_PROPOSER_SLASHINGS:
|
||||
@ -114,19 +150,13 @@ proc processProposerSlashings(
|
||||
for proposer_slashing in blck.body.proposer_slashings:
|
||||
let proposer = state.validator_registry[proposer_slashing.proposer_index.int]
|
||||
|
||||
if not (proposer_slashing.proposal_1.slot ==
|
||||
proposer_slashing.proposal_2.slot):
|
||||
notice "PropSlash: slot mismatch"
|
||||
if not (slot_to_epoch(proposer_slashing.header_1.slot) ==
|
||||
slot_to_epoch(proposer_slashing.header_2.slot)):
|
||||
notice "PropSlash: epoch mismatch"
|
||||
return false
|
||||
|
||||
if not (proposer_slashing.proposal_1.shard ==
|
||||
proposer_slashing.proposal_2.shard):
|
||||
notice "PropSlash: shard mismatch"
|
||||
return false
|
||||
|
||||
if not (proposer_slashing.proposal_1.block_root !=
|
||||
proposer_slashing.proposal_2.block_root):
|
||||
notice "PropSlash: block root mismatch"
|
||||
if not (proposer_slashing.header_1 != proposer_slashing.header_2):
|
||||
notice "PropSlash: headers not different"
|
||||
return false
|
||||
|
||||
if not (proposer.slashed == false):
|
||||
@ -134,24 +164,16 @@ proc processProposerSlashings(
|
||||
return false
|
||||
|
||||
if skipValidation notin flags:
|
||||
if not bls_verify(
|
||||
proposer.pubkey,
|
||||
signed_root(proposer_slashing.proposal_1, "signature"),
|
||||
proposer_slashing.proposal_1.signature,
|
||||
get_domain(
|
||||
state.fork, slot_to_epoch(proposer_slashing.proposal_1.slot),
|
||||
DOMAIN_PROPOSAL)):
|
||||
notice "PropSlash: invalid signature 1"
|
||||
return false
|
||||
if not bls_verify(
|
||||
proposer.pubkey,
|
||||
signed_root(proposer_slashing.proposal_2, "signature"),
|
||||
proposer_slashing.proposal_2.signature,
|
||||
get_domain(
|
||||
state.fork, slot_to_epoch(proposer_slashing.proposal_2.slot),
|
||||
DOMAIN_PROPOSAL)):
|
||||
notice "PropSlash: invalid signature 2"
|
||||
return false
|
||||
for i, header in @[proposer_slashing.header_1, proposer_slashing.header_2]:
|
||||
if not bls_verify(
|
||||
proposer.pubkey,
|
||||
signed_root(header),
|
||||
header.signature,
|
||||
get_domain(
|
||||
state.fork, slot_to_epoch(header.slot), DOMAIN_BEACON_BLOCK)):
|
||||
notice "PropSlash: invalid signature",
|
||||
signature_index = i
|
||||
return false
|
||||
|
||||
slashValidator(state, proposer_slashing.proposer_index.ValidatorIndex)
|
||||
|
||||
@ -303,8 +325,8 @@ proc processExits(
|
||||
|
||||
if skipValidation notin flags:
|
||||
if not bls_verify(
|
||||
validator.pubkey, signed_root(exit, "signature"), exit.signature,
|
||||
get_domain(state.fork, exit.epoch, DOMAIN_EXIT)):
|
||||
validator.pubkey, signed_root(exit), exit.signature,
|
||||
get_domain(state.fork, exit.epoch, DOMAIN_VOLUNTARY_EXIT)):
|
||||
notice "Exit: invalid signature"
|
||||
return false
|
||||
|
||||
@ -357,7 +379,7 @@ proc processTransfers(state: var BeaconState, blck: BeaconBlock,
|
||||
return false
|
||||
|
||||
if skipValidation notin flags:
|
||||
let transfer_message = signed_root(transfer, "signature")
|
||||
let transfer_message = signed_root(transfer)
|
||||
if not bls_verify(
|
||||
pubkey=transfer.pubkey, transfer_message, transfer.signature,
|
||||
get_domain(
|
||||
@ -375,20 +397,41 @@ proc processTransfers(state: var BeaconState, blck: BeaconBlock,
|
||||
|
||||
true
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#per-slot-processing
|
||||
func processSlot(state: var BeaconState, previous_block_root: Eth2Digest) =
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#per-slot-processing
|
||||
func advanceSlot(state: var BeaconState) =
|
||||
## Time on the beacon chain moves in slots. Every time we make it to a new
|
||||
## slot, a proposer creates a block to represent the state of the beacon
|
||||
## chain at that time. In case the proposer is missing, it may happen that
|
||||
## the no block is produced during the slot.
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#slot
|
||||
state.slot += 1
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#state-caching
|
||||
func cacheState(state: var BeaconState) =
|
||||
let previous_slot_state_root = hash_tree_root_final(state)
|
||||
|
||||
# store the previous slot's post state transition root
|
||||
state.latest_state_roots[state.slot mod SLOTS_PER_HISTORICAL_ROOT] =
|
||||
previous_slot_state_root
|
||||
|
||||
# cache state root in stored latest_block_header if empty
|
||||
if state.latest_block_header.state_root == ZERO_HASH:
|
||||
state.latest_block_header.state_root = previous_slot_state_root
|
||||
|
||||
# store latest known block for previous slot
|
||||
state.latest_block_roots[state.slot mod SLOTS_PER_HISTORICAL_ROOT] =
|
||||
hash_tree_root_final(state.latest_block_header)
|
||||
|
||||
func processSlot(state: var BeaconState, previous_block_root: Eth2Digest) =
|
||||
advanceSlot(state)
|
||||
|
||||
# TODO "at every slot > GENESIS_SLOT", after rest of epoch restructuring
|
||||
if false and state.slot > GENESIS_SLOT:
|
||||
cacheState(state)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#block-roots
|
||||
state.latest_block_roots[(state.slot - 1) mod LATEST_BLOCK_ROOTS_LENGTH] =
|
||||
state.latest_block_roots[(state.slot - 1) mod SLOTS_PER_HISTORICAL_ROOT] =
|
||||
previous_block_root
|
||||
if state.slot mod LATEST_BLOCK_ROOTS_LENGTH == 0:
|
||||
if state.slot mod SLOTS_PER_HISTORICAL_ROOT == 0:
|
||||
state.batched_block_roots.add(merkle_root(state.latest_block_roots))
|
||||
|
||||
proc processBlock(
|
||||
@ -408,21 +451,26 @@ proc processBlock(
|
||||
|
||||
# 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.parent_root` was used in `processSlot` - but that doesn't cut it for
|
||||
# `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
|
||||
let stateParentRoot =
|
||||
state.latest_block_roots[(state.slot - 1) mod LATEST_BLOCK_ROOTS_LENGTH]
|
||||
if not (blck.parent_root == stateParentRoot):
|
||||
state.latest_block_roots[(state.slot - 1) mod SLOTS_PER_HISTORICAL_ROOT]
|
||||
if not (blck.previous_block_root == stateParentRoot):
|
||||
notice "Unexpected parent root",
|
||||
blockParentRoot = blck.parent_root,
|
||||
blockParentRoot = blck.previous_block_root,
|
||||
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:
|
||||
# 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 verifyBlockSignature(state, blck):
|
||||
notice "Block signature not valid", slot = humaneSlotNum(state.slot)
|
||||
return false
|
||||
@ -683,7 +731,7 @@ func processEpoch(state: var BeaconState) =
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#justification
|
||||
block:
|
||||
# First, update the justification bitfield
|
||||
var new_justified_epoch = state.justified_epoch
|
||||
var new_justified_epoch = state.current_justified_epoch
|
||||
state.justification_bitfield = state.justification_bitfield shl 1
|
||||
if 3'u64 * previous_epoch_boundary_attesting_balance >= 2'u64 * previous_total_balance:
|
||||
state.justification_bitfield = state.justification_bitfield or 2
|
||||
@ -697,14 +745,14 @@ func processEpoch(state: var BeaconState) =
|
||||
state.finalized_epoch = state.previous_justified_epoch
|
||||
if (state.justification_bitfield shr 1) mod 4 == 0b11 and state.previous_justified_epoch == previous_epoch - 1:
|
||||
state.finalized_epoch = state.previous_justified_epoch
|
||||
if (state.justification_bitfield shr 0) mod 8 == 0b111 and state.justified_epoch == previous_epoch - 1:
|
||||
state.finalized_epoch = state.justified_epoch
|
||||
if (state.justification_bitfield shr 0) mod 4 == 0b11 and state.justified_epoch == previous_epoch:
|
||||
state.finalized_epoch = state.justified_epoch
|
||||
if (state.justification_bitfield shr 0) mod 8 == 0b111 and state.current_justified_epoch == previous_epoch - 1:
|
||||
state.finalized_epoch = state.current_justified_epoch
|
||||
if (state.justification_bitfield shr 0) mod 4 == 0b11 and state.current_justified_epoch == previous_epoch:
|
||||
state.finalized_epoch = state.current_justified_epoch
|
||||
|
||||
# Finally, update the following
|
||||
state.previous_justified_epoch = state.justified_epoch
|
||||
state.justified_epoch = new_justified_epoch
|
||||
state.previous_justified_epoch = state.current_justified_epoch
|
||||
state.current_justified_epoch = new_justified_epoch
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#crosslinks
|
||||
block:
|
||||
|
@ -22,30 +22,30 @@ type
|
||||
node*: BeaconNode
|
||||
db*: BeaconChainDB
|
||||
|
||||
func toHeader(b: BeaconBlock): BeaconBlockHeader =
|
||||
BeaconBlockHeader(
|
||||
func toHeader(b: BeaconBlock): BeaconBlockHeaderRLP =
|
||||
BeaconBlockHeaderRLP(
|
||||
slot: b.slot.uint64,
|
||||
parent_root: b.parent_root,
|
||||
parent_root: b.previous_block_root,
|
||||
state_root: b.state_root,
|
||||
randao_reveal: b.randao_reveal,
|
||||
eth1_data : b.eth1_data,
|
||||
randao_reveal: b.body.randao_reveal,
|
||||
eth1_data : b.body.eth1_data,
|
||||
signature: b.signature,
|
||||
body: hash_tree_root_final(b.body)
|
||||
)
|
||||
|
||||
proc fromHeaderAndBody(b: var BeaconBlock, h: BeaconBlockHeader, body: BeaconBlockBody) =
|
||||
proc fromHeaderAndBody(b: var BeaconBlock, h: BeaconBlockHeaderRLP, body: BeaconBlockBody) =
|
||||
doAssert(hash_tree_root_final(body) == h.body)
|
||||
b.slot = h.slot.Slot
|
||||
b.parent_root = h.parent_root
|
||||
b.previous_block_root = h.parent_root
|
||||
b.state_root = h.state_root
|
||||
b.randao_reveal = h.randao_reveal
|
||||
b.eth1_data = h.eth1_data
|
||||
b.body.randao_reveal = h.randao_reveal
|
||||
b.body.eth1_data = h.eth1_data
|
||||
b.signature = h.signature
|
||||
b.body = body
|
||||
|
||||
proc importBlocks(node: BeaconNode,
|
||||
roots: openarray[(Eth2Digest, Slot)],
|
||||
headers: openarray[BeaconBlockHeader],
|
||||
headers: openarray[BeaconBlockHeaderRLP],
|
||||
bodies: openarray[BeaconBlockBody]) =
|
||||
var bodyMap = initTable[Eth2Digest, int]()
|
||||
|
||||
@ -135,7 +135,7 @@ p2pProtocol BeaconSync(version = 1,
|
||||
skipSlots: int) {.libp2pProtocol("rpc/beacon_block_headers", "1.0.0").} =
|
||||
# TODO: validate maxHeaders and implement slipSlots
|
||||
var s = slot.int
|
||||
var headers = newSeqOfCap[BeaconBlockHeader](maxHeaders)
|
||||
var headers = newSeqOfCap[BeaconBlockHeaderRLP](maxHeaders)
|
||||
let db = peer.networkState.db
|
||||
let blockPool = peer.networkState.node.blockPool
|
||||
while headers.len < maxHeaders:
|
||||
@ -147,7 +147,7 @@ p2pProtocol BeaconSync(version = 1,
|
||||
|
||||
proc beaconBlockHeaders(
|
||||
peer: Peer,
|
||||
blockHeaders: openarray[BeaconBlockHeader])
|
||||
blockHeaders: openarray[BeaconBlockHeaderRLP])
|
||||
|
||||
requestResponse:
|
||||
proc getBeaconBlockBodies(
|
||||
|
@ -31,7 +31,7 @@ proc signBlockProposal*(v: AttachedValidator, fork: Fork,
|
||||
let proposalRoot = hash_tree_root_final(proposal)
|
||||
|
||||
result = bls_sign(v.privKey, signed_root(proposal, "signature"),
|
||||
get_domain(fork, slot_to_epoch(proposal.slot), DOMAIN_PROPOSAL))
|
||||
get_domain(fork, slot_to_epoch(proposal.slot), DOMAIN_BEACON_BLOCK))
|
||||
else:
|
||||
# TODO:
|
||||
# send RPC
|
||||
|
@ -56,7 +56,7 @@ func hash(x: BlockHash): Hash =
|
||||
result = cast[array[num_hashes, Hash]](x)[0]
|
||||
|
||||
func get_parent(store: Store, blck: BeaconBlock): BeaconBlock =
|
||||
store.verified_blocks[blck.parent_root]
|
||||
store.verified_blocks[blck.previous_block_root]
|
||||
|
||||
func get_ancestor(store: Store, blck: BeaconBlock, slot: uint64): BeaconBlock =
|
||||
## Find the ancestor with a specific slot number
|
||||
|
@ -57,12 +57,11 @@ suite "Beacon chain DB":
|
||||
check: x == y
|
||||
|
||||
let
|
||||
# TODO Not GENESIS_SLOT?
|
||||
a0 = BeaconBlock(slot: 0.Slot)
|
||||
a0 = BeaconBlock(slot: GENESIS_SLOT + 0)
|
||||
a0r = hash_tree_root_final(a0)
|
||||
a1 = BeaconBlock(slot: 1.Slot, parent_root: a0r)
|
||||
a1 = BeaconBlock(slot: GENESIS_SLOT + 1, previous_block_root: a0r)
|
||||
a1r = hash_tree_root_final(a1)
|
||||
a2 = BeaconBlock(slot: 2.Slot, parent_root: a1r)
|
||||
a2 = BeaconBlock(slot: GENESIS_SLOT + 2, previous_block_root: a1r)
|
||||
a2r = hash_tree_root_final(a2)
|
||||
|
||||
doAssert toSeq(db.getAncestors(a0r)) == []
|
||||
|
@ -92,18 +92,21 @@ proc addBlock*(
|
||||
proposer = state.validator_registry[proposer_index]
|
||||
privKey = hackPrivKey(proposer)
|
||||
|
||||
# TODO ugly hack; API needs rethinking
|
||||
var new_body = body
|
||||
new_body.randao_reveal = privKey.genRandaoReveal(state, state.slot + 1)
|
||||
new_body.eth1_data = Eth1Data()
|
||||
|
||||
var
|
||||
# In order to reuse the state transition function, we first create a dummy
|
||||
# block that has some fields set, and use that to generate the state as it
|
||||
# would look with the new block applied.
|
||||
new_block = BeaconBlock(
|
||||
slot: state.slot + 1,
|
||||
parent_root: previous_block_root,
|
||||
previous_block_root: previous_block_root,
|
||||
state_root: Eth2Digest(), # we need the new state first
|
||||
randao_reveal: privKey.genRandaoReveal(state, state.slot + 1),
|
||||
eth1_data: Eth1Data(), # TODO
|
||||
signature: ValidatorSig(), # we need the rest of the block first!
|
||||
body: body
|
||||
body: new_body
|
||||
)
|
||||
|
||||
let block_ok = updateState(
|
||||
@ -134,12 +137,12 @@ proc addBlock*(
|
||||
# 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_PROPOSAL))
|
||||
get_domain(state.fork, slot_to_epoch(state.slot), DOMAIN_BEACON_BLOCK))
|
||||
|
||||
doAssert bls_verify(
|
||||
proposer.pubkey,
|
||||
proposal_hash, new_block.signature,
|
||||
get_domain(state.fork, slot_to_epoch(state.slot), DOMAIN_PROPOSAL)),
|
||||
get_domain(state.fork, slot_to_epoch(state.slot), DOMAIN_BEACON_BLOCK)),
|
||||
"we just signed this message - it should pass verification!"
|
||||
|
||||
new_block
|
||||
|
Loading…
x
Reference in New Issue
Block a user