0.6.1 - signing_root, deposits, validator indices and committee count (#261)

* signed_root -> signing_root

* implement new process_deposit; update timing parameters to 0.6.1; update Deposit to 0.6.1 and remove DepositInput

* update get_active_validator_indices and get_epoch_committee_count to 0.6.1; rm get_current_epoch_committee_count, get_previous_epoch_committee_count, and get_next_epoch_committee_count; bump state_sim default validator count a bit more

* re-introduce 0.5.1-ish get_active_validator_indices, get_epoch_committee_count as scaffolding for still-0.5.1ish shuffling
This commit is contained in:
Dustin Brody 2019-05-09 12:27:37 +00:00 committed by Mamy Ratsimbazafy
parent f385467cd3
commit d977c96ae1
19 changed files with 210 additions and 239 deletions

View File

@ -85,7 +85,7 @@ proc putStateRoot*(db: BeaconChainDB, root: Eth2Digest, slot: Slot,
db.backend.put(subkey(root, slot), value.data)
proc putBlock*(db: BeaconChainDB, value: BeaconBlock) =
db.putBlock(signed_root(value), value)
db.putBlock(signing_root(value), value)
proc putHeadBlock*(db: BeaconChainDB, key: Eth2Digest) =
db.backend.put(subkey(kHeadBlock), key.data) # TODO head block?

View File

@ -375,7 +375,7 @@ proc proposeBlock(node: BeaconNode,
newBlock.state_root = tmpState.root
let blockRoot = signed_root(newBlock)
let blockRoot = signing_root(newBlock)
# Careful, state no longer valid after here..
newBlock.signature =
@ -418,7 +418,7 @@ proc onAttestation(node: BeaconNode, attestation: Attestation) =
proc onBeaconBlock(node: BeaconNode, blck: BeaconBlock) =
# We received a block but don't know much about it yet - in particular, we
# don't know if it's part of the chain we're currently building.
let blockRoot = signed_root(blck)
let blockRoot = signing_root(blck)
debug "Block received",
blck = shortLog(blck),
blockRoot = shortLog(blockRoot)

View File

@ -203,7 +203,7 @@ proc add*(
## the state parameter may be updated to include the given block, if
## everything checks out
# TODO reevaluate passing the state in like this
doAssert blockRoot == signed_root(blck)
doAssert blockRoot == signing_root(blck)
# Already seen this block??
if blockRoot in pool.blocks:
@ -597,7 +597,7 @@ proc preInit*(
# state - but there's more refactoring needed to make it nice - doing
# a minimal patch for now..
let
blockRoot = signed_root(blck)
blockRoot = signing_root(blck)
notice "Creating new database from snapshot",
blockRoot = shortLog(blockRoot),

View File

@ -25,7 +25,7 @@ proc lmdGhost*(
let
active_validator_indices =
get_active_validator_indices(
start_state.validator_registry, slot_to_epoch(start_state.slot))
start_state, slot_to_epoch(start_state.slot))
var attestation_targets: seq[tuple[validator: ValidatorIndex, blck: BlockRef]]
for i in active_validator_indices:

View File

@ -35,86 +35,82 @@ func verify_merkle_branch(leaf: Eth2Digest, proof: openarray[Eth2Digest], depth:
value = eth2hash(buf)
value == root
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.1/specs/core/0_beacon-chain.md#process_deposit
func process_deposit*(state: var BeaconState, deposit: Deposit): bool =
## Process a deposit from Ethereum 1.0.
## Note that this function mutates ``state``.
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#increase_balance
func increase_balance*(
state: var BeaconState, index: ValidatorIndex, delta: Gwei) =
# Increase validator balance by ``delta``.
state.balances[index] += delta
let deposit_input = deposit.deposit_data.deposit_input
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#decrease_balance
func decrease_balance*(
state: var BeaconState, index: ValidatorIndex, delta: Gwei) =
# Decrease validator balance by ``delta`` with underflow protection.
state.balances[index] =
if delta > state.balances[index]:
0'u64
else:
state.balances[index] - delta
## Should equal 8 bytes for deposit_data.amount +
## 8 bytes for deposit_data.timestamp +
## 176 bytes for deposit_data.deposit_input
## It should match the deposit_data in the eth1.0 deposit contract
## TODO actual serialize func useful after all
var serialized_deposit_data: array[8 + 8 + 176, byte]
serialized_deposit_data[0..7] = deposit.deposit_data.amount.int_to_bytes8()
serialized_deposit_data[8..15] =
deposit.deposit_data.timestamp.int_to_bytes8()
serialized_deposit_data[16..63] = deposit_input.pubkey.getBytes()
serialized_deposit_data[64..95] = deposit_input.withdrawal_credentials.data
serialized_deposit_data[96..191] =
deposit_input.proof_of_possession.getBytes()
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#deposits
func process_deposit*(
state: var BeaconState, deposit: Deposit, flags: UpdateFlags = {}): bool =
# Process an Eth1 deposit, registering a validator or increasing its balance.
# Verify the Merkle branch
let merkle_branch_is_valid = verify_merkle_branch(
eth2hash(serialized_deposit_data),
deposit.proof,
DEPOSIT_CONTRACT_TREE_DEPTH,
deposit.index,
state.latest_eth1_data.deposit_root)
## TODO enable this check, after using merkle_root (not in spec anymore, but
## useful to construct proofs) to build proofs (i.e. the other child in each
## pair of children at each level of the merkle tree), and injecting a proof
## sequence corresponding to their hash values, into the `Deposits`, in that
## tests/testutil.nim area of code. Currently it's checking against garbage,
## either when creating genesis states or in the block processing of deposit
## lists from Eth1Data.
# doAssert merkle_branch_is_valid
# TODO enable this check, but don't use doAssert
if not verify_merkle_branch(
hash_tree_root(deposit.data),
deposit.proof,
DEPOSIT_CONTRACT_TREE_DEPTH,
deposit.index,
state.latest_eth1_data.deposit_root,
):
## TODO: a notice-like mechanism which works in a func
## here and elsewhere, one minimal approach is a check-if-true
## and return false iff so.
## obviously, better/more principled ones exist, but
## generally require broader rearchitecting, and this is what
## mostly happens now, just haphazardly.
discard
# Deposits must be processed in order
if not (deposit.index == state.deposit_index):
## TODO see above, re errors
## it becomes even more important, as one might might sometimes want
## to flag such things as higher/lower priority. chronicles?
return false
## Increment the next deposit index we are expecting. Note that this
## needs to be done here because while the deposit contract will never
## create an invalid Merkle branch, it may admit an invalid deposit
## object, and we need to be able to skip over it
state.deposit_index += 1
## if not validate_proof_of_possession(
## state, pubkey, proof_of_possession, withdrawal_credentials):
## return
## TODO re-enable (but it wasn't running to begin with, and
## PoP isn't really a phase 0 concern, so this isn't meaningful
## regardless.
let
validator_pubkeys = state.validator_registry.mapIt(it.pubkey)
pubkey = deposit_input.pubkey
amount = deposit.deposit_data.amount
withdrawal_credentials = deposit_input.withdrawal_credentials
pubkey = deposit.data.pubkey
amount = deposit.data.amount
validator_pubkeys = mapIt(state.validator_registry, it.pubkey)
index = validator_pubkeys.find(pubkey)
if pubkey notin validator_pubkeys:
# Add new validator
let validator = Validator(
if index == -1:
# Verify the deposit signature (proof of possession)
# TODO should be get_domain(state, DOMAIN_DEPOSIT)
if skipValidation notin flags and not bls_verify(
pubkey, signing_root(deposit.data).data, deposit.data.signature,
3'u64):
return false
# Add validator and balance entries
state.validator_registry.add(Validator(
pubkey: pubkey,
withdrawal_credentials: withdrawal_credentials,
withdrawal_credentials: deposit.data.withdrawal_credentials,
activation_eligibility_epoch: FAR_FUTURE_EPOCH,
activation_epoch: FAR_FUTURE_EPOCH,
exit_epoch: FAR_FUTURE_EPOCH,
withdrawable_epoch: FAR_FUTURE_EPOCH,
initiated_exit: false,
slashed: false,
)
## Note: In phase 2 registry indices that have been withdrawn for a long
## time will be recycled.
state.validator_registry.add(validator)
effective_balance: min(amount - amount mod EFFECTIVE_BALANCE_INCREMENT,
MAX_EFFECTIVE_BALANCE)
))
state.balances.add(amount)
else:
# Increase balance by deposit amount
let index = validator_pubkeys.find(pubkey)
let validator = addr state.validator_registry[index]
doAssert state.validator_registry[index].withdrawal_credentials ==
withdrawal_credentials
state.balances[index] += amount
# Increase balance by deposit amount
increase_balance(state, index.ValidatorIndex, amount)
true
@ -204,7 +200,7 @@ func get_temporary_block_header*(blck: BeaconBlock): BeaconBlockHeader =
previous_block_root: blck.previous_block_root,
state_root: ZERO_HASH,
block_body_root: hash_tree_root(blck.body),
# signed_root(block) is used for block id purposes so signature is a stub
# signing_root(block) is used for block id purposes so signature is a stub
signature: EMPTY_SIGNATURE,
)
@ -284,7 +280,7 @@ func get_genesis_beacon_state*(
# Process genesis deposits
for deposit in genesis_validator_deposits:
discard process_deposit(state, deposit)
discard process_deposit(state, deposit, flags)
# Process genesis activations
for validator_index in 0 ..< state.validator_registry.len:
@ -293,7 +289,7 @@ func get_genesis_beacon_state*(
activate_validator(state, vi, true)
let genesis_active_index_root = hash_tree_root(
get_active_validator_indices(state.validator_registry, GENESIS_EPOCH))
get_active_validator_indices(state, GENESIS_EPOCH))
for index in 0 ..< LATEST_ACTIVE_INDEX_ROOTS_LENGTH:
state.latest_active_index_roots[index] = genesis_active_index_root
state.current_shuffling_seed = generate_seed(state, GENESIS_EPOCH)
@ -399,7 +395,7 @@ 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(
state.validator_registry, get_current_epoch(state)):
state, get_current_epoch(state)):
if state.balances[index] < EJECTION_BALANCE:
exit_validator(state, index)
@ -414,7 +410,7 @@ func should_update_validator_registry*(state: BeaconState): bool =
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,
allIt(0 ..< get_epoch_committee_count(state, get_current_epoch(state)).int,
not (state.latest_crosslinks[
((state.current_shuffling_start_shard + it.uint64) mod
SHARD_COUNT).int].epoch <= state.validator_registry_update_epoch))
@ -426,7 +422,7 @@ func update_validator_registry*(state: var BeaconState) =
current_epoch = get_current_epoch(state)
# The active validators
active_validator_indices =
get_active_validator_indices(state.validator_registry, current_epoch)
get_active_validator_indices(state, current_epoch)
# The total effective balance of active validators
total_balance = get_total_balance(state, active_validator_indices)
@ -622,22 +618,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/v0.6.0/specs/core/0_beacon-chain.md#increase_balance
func increase_balance*(
state: var BeaconState, index: ValidatorIndex, delta: Gwei) =
# Increase validator balance by ``delta``.
state.balances[index] += delta
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#decrease_balance
func decrease_balance*(
state: var BeaconState, index: ValidatorIndex, delta: Gwei) =
# Decrease validator balance by ``delta`` with underflow protection.
state.balances[index] =
if delta > state.balances[index]:
0'u64
else:
state.balances[index] - delta
proc makeAttestationData*(
state: BeaconState, shard: uint64,
beacon_block_root: Eth2Digest): AttestationData =

View File

@ -91,16 +91,21 @@ const
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
MAX_EFFECTIVE_BALANCE* = 2'u64^5 * 10'u64^9 ##\
## Maximum amounth of ETH that can be deposited in one call
# TODO remove erstwhile blob/v0.5.0
FORK_CHOICE_BALANCE_INCREMENT* = 2'u64^0 * 10'u64^9
EJECTION_BALANCE* = 2'u64^4 * 10'u64^9 ##\
## Once the balance of a validator drops below this, it will be ejected from
## the validator pool
EFFECTIVE_BALANCE_INCREMENT* = 2'u64^0 * 10'u64^9
# Time parameter, here so that GENESIS_EPOCH can access it
# TODO re-merge
SLOTS_PER_EPOCH* {.intdefine.} = 64 ##\
## (~6.4 minutes)
## slots that make up an epoch, at the end of which more heavy
@ -119,11 +124,11 @@ const
EMPTY_SIGNATURE* = ValidatorSig()
BLS_WITHDRAWAL_PREFIX_BYTE* = 0'u8
# Time parameters
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#time-parameters
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_fork-choice.md#time-parameters
SECONDS_PER_SLOT*{.intdefine.} = 6'u64 # Compile with -d:SECONDS_PER_SLOT=1 for 6x faster slots
## TODO consistent time unit across projects, similar to C++ chrono?
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#time-parameters
MIN_ATTESTATION_INCLUSION_DELAY* = 2'u64^2 ##\
## (24 seconds)
## Number of slots that attestations stay in the attestation
@ -137,6 +142,7 @@ const
## attestation.
# SLOTS_PER_EPOCH is defined above.
# TODO it doesn't need to be anymore
MIN_SEED_LOOKAHEAD* = 1 ##\
## epochs (~6.4 minutes)
@ -156,6 +162,12 @@ const
PERSISTENT_COMMITTEE_PERIOD* = 2'u64^11 ##\
## epochs (9 days)
MAX_CROSSLINK_EPOCHS* = 2'u64^6 ##\
## epochs (~7 hours)
MIN_EPOCHS_TO_INACTIVITY_PENALTY* = 2'u64^2 ##\
## epochs (25.6 minutes)
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.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
@ -249,7 +261,7 @@ type
data*: AttestationData
custody_bit*: bool
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#deposit
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#deposit
Deposit* = object
proof*: array[DEPOSIT_CONTRACT_TREE_DEPTH, Eth2Digest] ##\
## Branch in the deposit tree
@ -257,21 +269,24 @@ type
index*: uint64 ##\
## Index in the deposit tree
deposit_data*: DepositData ##\
data*: DepositData ##\
## Data
# 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
pubkey*: ValidatorPubKey ##\
## BLS pubkey
# 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`
withdrawal_credentials*: Eth2Digest ##\
## Withdrawal credentials
amount*: uint64 ##\
## Amount in Gwei
dummy*: uint64
signature*: ValidatorSig ##\
## Container self-signature
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#voluntaryexit
VoluntaryExit* = object
@ -421,6 +436,9 @@ type
withdrawal_credentials*: Eth2Digest ##\
## Withdrawal credentials
activation_eligibility_epoch*: Epoch ##\
## Epoch when validator activated
activation_epoch*: Epoch ##\
## Epoch when validator activated
@ -436,6 +454,9 @@ type
slashed*: bool ##\
## Was the validator slashed
effective_balance*: uint64 ##\
## Effective balance
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#crosslink
Crosslink* = object
epoch*: Epoch ##\
@ -505,7 +526,7 @@ type
# TODO to be replaced with some magic hash caching
HashedBeaconState* = object
data*: BeaconState
root*: Eth2Digest # hash_tree_root (not signed_root!)
root*: Eth2Digest # hash_tree_root (not signing_root!)
func shortValidatorKey*(state: BeaconState, validatorIdx: int): string =
($state.validator_registry[validatorIdx].pubkey)[0..7]

View File

@ -105,27 +105,40 @@ func is_active_validator*(validator: Validator, epoch: Epoch): bool =
### Check if ``validator`` is active
validator.activation_epoch <= epoch and epoch < validator.exit_epoch
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_active_validator_indices
func get_active_validator_indices*(validators: openArray[Validator], epoch: Epoch): seq[ValidatorIndex] =
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.1/specs/core/0_beacon-chain.md#get_active_validator_indices
func get_active_validator_indices*(
validators: openarray[Validator], epoch: Epoch): seq[ValidatorIndex] =
## Gets indices of active validators from validators
## TODO remove when shuffling's refactored persuant to 0.6.1
for idx, val in validators:
if is_active_validator(val, epoch):
result.add idx.ValidatorIndex
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#get_active_validator_indices
func get_active_validator_indices*(state: BeaconState, epoch: Epoch):
seq[ValidatorIndex] =
## Gets indices of active validators from validators
for idx, val in state.validator_registry:
if is_active_validator(val, epoch):
result.add idx.ValidatorIndex
# 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 =
# Not quite the 0.5.1 version. TODO remove when shuffling refactoring complete
func get_epoch_committee_count*(
validators: openarray[Validator], epoch: Epoch): uint64 =
# Return the number of committees at ``epoch``.
let active_validator_indices = get_active_validator_indices(validators, epoch)
clamp(
active_validator_count div SLOTS_PER_EPOCH div TARGET_COMMITTEE_SIZE,
len(active_validator_indices) 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/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(
state.validator_registry,
state.current_shuffling_epoch,
)
get_epoch_committee_count(len(current_active_validators))
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#get_epoch_committee_count
func get_epoch_committee_count*(state: BeaconState, epoch: Epoch): uint64 =
# Return the number of committees at ``epoch``.
let active_validator_indices = get_active_validator_indices(state, epoch)
clamp(
len(active_validator_indices) 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/v0.6.0/specs/core/0_beacon-chain.md#get_current_epoch
func get_current_epoch*(state: BeaconState): Epoch =

View File

@ -84,32 +84,13 @@ func get_shuffling*(seed: Eth2Digest,
active_validator_indices = get_active_validator_indices(validators, epoch)
list_size = active_validator_indices.len.uint64
committees_per_epoch = get_epoch_committee_count(
len(active_validator_indices)).int
validators, epoch).int
shuffled_seq = get_shuffled_seq(seed, list_size)
# Split the shuffled list into committees_per_epoch pieces
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/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``.
let previous_active_validators = get_active_validator_indices(
state.validator_registry,
state.previous_shuffling_epoch,
)
get_epoch_committee_count(len(previous_active_validators))
# 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(
state.validator_registry,
get_current_epoch(state) + 1,
)
get_epoch_committee_count(len(next_active_validators))
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_previous_epoch
func get_previous_epoch*(state: BeaconState): Epoch =
## Return the previous epoch of the given ``state``.
@ -152,14 +133,14 @@ func get_crosslink_committees_at_slot*(state: BeaconState, slot: Slot|uint64,
template get_epoch_specific_params(): auto =
if epoch == current_epoch:
let
committees_per_epoch = get_current_epoch_committee_count(state)
committees_per_epoch = get_epoch_committee_count(state, current_epoch)
seed = state.current_shuffling_seed
shuffling_epoch = state.current_shuffling_epoch
shuffling_start_shard = state.current_shuffling_start_shard
(committees_per_epoch, seed, shuffling_epoch, shuffling_start_shard)
elif epoch == previous_epoch:
let
committees_per_epoch = get_previous_epoch_committee_count(state)
committees_per_epoch = get_epoch_committee_count(state, previous_epoch)
seed = state.previous_shuffling_seed
shuffling_epoch = state.previous_shuffling_epoch
shuffling_start_shard = state.previous_shuffling_start_shard
@ -177,9 +158,9 @@ func get_crosslink_committees_at_slot*(state: BeaconState, slot: Slot|uint64,
use_next = registry_change or condition
committees_per_epoch =
if use_next:
get_next_epoch_committee_count(state)
get_epoch_committee_count(state, next_epoch)
else:
get_current_epoch_committee_count(state)
get_epoch_committee_count(state, current_epoch)
seed =
if use_next:
generate_seed(state, next_epoch)
@ -190,7 +171,7 @@ func get_crosslink_committees_at_slot*(state: BeaconState, slot: Slot|uint64,
shuffling_start_shard =
if registry_change:
(state.current_shuffling_start_shard +
get_current_epoch_committee_count(state)) mod SHARD_COUNT
get_epoch_committee_count(state, current_epoch)) mod SHARD_COUNT
else:
state.current_shuffling_start_shard
(committees_per_epoch, seed, shuffling_epoch, shuffling_start_shard)
@ -199,13 +180,7 @@ func get_crosslink_committees_at_slot*(state: BeaconState, slot: Slot|uint64,
get_epoch_specific_params()
let
shuffling = get_shuffling(
seed,
state.validator_registry,
shuffling_epoch
# Not in spec
)
shuffling = get_shuffling(seed, state.validator_registry, shuffling_epoch)
offset = slot mod SLOTS_PER_EPOCH
committees_per_slot = committees_per_epoch div SLOTS_PER_EPOCH
slot_start_shard = (shuffling_start_shard + committees_per_slot * offset) mod SHARD_COUNT

View File

@ -427,7 +427,7 @@ iterator hash_tree_most(v: object): Chunk =
doAssert found_field_name
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/simple-serialize.md#signed-roots
func signed_root*[T: object](x: T): Eth2Digest =
func signing_root*[T: object](x: T): Eth2Digest =
# TODO write tests for this (check vs hash_tree_root)
let root = merkleize(hash_tree_most(x))

View File

@ -47,11 +47,11 @@ proc processBlockHeader(
# state_root not set yet, when skipping validation
if skipValidation notin flags and not (blck.previous_block_root ==
signed_root(state.latest_block_header)):
signing_root(state.latest_block_header)):
notice "Block header: previous block root mismatch",
latest_block_header = state.latest_block_header,
blck = shortLog(blck),
latest_block_header_root = shortLog(signed_root(state.latest_block_header))
latest_block_header_root = shortLog(signing_root(state.latest_block_header))
return false
state.latest_block_header = get_temporary_block_header(blck)
@ -60,12 +60,12 @@ proc processBlockHeader(
state.validator_registry[get_beacon_proposer_index(state, state.slot)]
if skipValidation notin flags and not bls_verify(
proposer.pubkey,
signed_root(blck).data,
signing_root(blck).data,
blck.signature,
get_domain(state, DOMAIN_BEACON_PROPOSER, get_current_epoch(state))):
notice "Block header: invalid block header",
proposer_pubkey = proposer.pubkey,
block_root = shortLog(signed_root(blck)),
block_root = shortLog(signing_root(blck)),
block_signature = blck.signature
return false
@ -138,7 +138,7 @@ proc processProposerSlashings(
for i, header in @[proposer_slashing.header_1, proposer_slashing.header_2]:
if not bls_verify(
proposer.pubkey,
signed_root(header).data,
signing_root(header).data,
header.signature,
get_domain(
state, DOMAIN_BEACON_PROPOSER, slot_to_epoch(header.slot))):
@ -330,7 +330,7 @@ proc processExits(
# Verify signature
if skipValidation notin flags:
if not bls_verify(
validator.pubkey, signed_root(exit).data, exit.signature,
validator.pubkey, signing_root(exit).data, exit.signature,
get_domain(state, DOMAIN_VOLUNTARY_EXIT, exit.epoch)):
notice "Exit: invalid signature"
return false
@ -358,7 +358,7 @@ func update_registry_and_shuffling_data(state: var BeaconState) =
state.current_shuffling_epoch = next_epoch
state.current_shuffling_start_shard = (
state.current_shuffling_start_shard +
get_current_epoch_committee_count(state) mod SHARD_COUNT
get_epoch_committee_count(state, current_epoch) mod SHARD_COUNT
) mod SHARD_COUNT
state.current_shuffling_seed =
generate_seed(state, state.current_shuffling_epoch)
@ -418,7 +418,7 @@ proc processTransfers(state: var BeaconState, blck: BeaconBlock,
# Verify that the signature is valid
if skipValidation notin flags:
if not bls_verify(
transfer.pubkey, signed_root(transfer).data, transfer.signature,
transfer.pubkey, signing_root(transfer).data, transfer.signature,
get_domain(state, DOMAIN_TRANSFER)):
notice "Transfer: incorrect signature"
return false
@ -468,7 +468,7 @@ func cacheState(state: var BeaconState) =
# store latest known block for previous slot
state.latest_block_roots[state.slot mod SLOTS_PER_HISTORICAL_ROOT] =
signed_root(state.latest_block_header)
signing_root(state.latest_block_header)
proc processBlock(
state: var BeaconState, blck: BeaconBlock, flags: UpdateFlags): bool =
@ -518,14 +518,12 @@ proc processBlock(
func get_current_total_balance(state: BeaconState): Gwei =
return get_total_balance(
state,
get_active_validator_indices(state.validator_registry,
get_current_epoch(state)))
get_active_validator_indices(state, get_current_epoch(state)))
func get_previous_total_balance(state: BeaconState): Gwei =
get_total_balance(
state,
get_active_validator_indices(state.validator_registry,
get_previous_epoch(state)))
get_active_validator_indices(state, get_previous_epoch(state)))
func get_attesting_indices(
state: BeaconState,
@ -821,8 +819,7 @@ func compute_normal_justification_and_finalization_deltas(state: BeaconState):
matching_head_attestation_indices =
get_attesting_indices(state, matching_head_attestations)
# Process rewards or penalties for all validators
for index in get_active_validator_indices(
state.validator_registry, get_previous_epoch(state)):
for index in get_active_validator_indices(state, get_previous_epoch(state)):
# Expected FFG source
if index in previous_epoch_attestation_indices:
deltas[0][index] +=
@ -872,7 +869,7 @@ func compute_inactivity_leak_deltas(state: BeaconState):
matching_head_attestations =
get_previous_epoch_matching_head_attestations(state)
active_validator_indices = toSet(get_active_validator_indices(
state.validator_registry, get_previous_epoch(state)))
state, get_previous_epoch(state)))
epochs_since_finality =
get_current_epoch(state) + 1 - state.finalized_epoch
let
@ -982,7 +979,7 @@ func process_slashings(state: var BeaconState) =
let
current_epoch = get_current_epoch(state)
active_validator_indices = get_active_validator_indices(
state.validator_registry, current_epoch)
state, current_epoch)
total_balance = get_total_balance(state, active_validator_indices)
# Compute `total_penalties`
@ -1048,7 +1045,7 @@ func finish_epoch_update(state: var BeaconState) =
(next_epoch + ACTIVATION_EXIT_DELAY) mod LATEST_ACTIVE_INDEX_ROOTS_LENGTH
state.latest_active_index_roots[index_root_position] =
hash_tree_root(get_active_validator_indices(
state.validator_registry, next_epoch + ACTIVATION_EXIT_DELAY)
state, next_epoch + ACTIVATION_EXIT_DELAY)
)
# Set total slashed balances
@ -1089,7 +1086,7 @@ func processEpoch(state: var BeaconState) =
var per_epoch_cache = get_empty_per_epoch_cache()
# 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.6.1/specs/core/0_beacon-chain.md#crosslinks
process_crosslinks(state, per_epoch_cache)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#apply-rewards
@ -1228,7 +1225,7 @@ func cacheState(state: var HashedBeaconState) =
# store latest known block for previous slot
state.data.latest_block_roots[state.data.slot mod SLOTS_PER_HISTORICAL_ROOT] =
signed_root(state.data.latest_block_header)
signing_root(state.data.latest_block_header)
proc advanceState*(state: var HashedBeaconState) =
cacheState(state)

View File

@ -32,25 +32,18 @@ cli do (totalValidators: int = 125000,
let
withdrawalCredentials = makeFakeHash(i)
domain = 3'u64
proofOfPossessionData = DepositInput(
pubkey: pubKey,
withdrawal_credentials: withdrawalCredentials)
proofOfPossession = bls_sign(
privkey, hash_tree_root(proofOfPossessionData).data,
0 # TODO - domain
)
let
var
deposit = Deposit(
deposit_data: DepositData(
data: DepositData(
amount: MAX_EFFECTIVE_BALANCE,
timestamp: 0, # TODO https://github.com/ethereum/eth2.0-specs/pull/834
deposit_input: DepositInput(
pubkey: pubKey,
proof_of_possession: proofOfPossession,
withdrawal_credentials: withdrawalCredentials)))
pubkey: pubKey,
withdrawal_credentials: withdrawalCredentials))
deposit.data.signature =
bls_sign(privkey, signing_root(deposit.data).data,
domain)
writeTextFile(privKeyFn, $privKey)
writeFile(depositFn, deposit)

View File

@ -46,7 +46,7 @@ proc writeJson*(prefix, slot, v: auto) =
write(f, pretty(%*(v)))
cli do(slots = 1945,
validators = SLOTS_PER_EPOCH * 5, # One per shard is minimum
validators = SLOTS_PER_EPOCH * 8, # One per shard is minimum
json_interval = SLOTS_PER_EPOCH,
prefix = 0,
attesterRatio {.desc: "ratio of validators that attest in each round"} = 0.9,
@ -60,7 +60,7 @@ cli do(slots = 1945,
var
attestations: array[MIN_ATTESTATION_INCLUSION_DELAY, seq[Attestation]]
state = genesisState
latest_block_root = signed_root(genesisBlock)
latest_block_root = signing_root(genesisBlock)
timers: array[Timers, RunningStat]
attesters: RunningStat
r: Rand
@ -90,7 +90,7 @@ cli do(slots = 1945,
withTimer(timers[t]):
blck = addBlock(state, latest_block_root, body, flags)
latest_block_root = withTimerRet(timers[tHashBlock]):
signed_root(blck)
signing_root(blck)
if attesterRatio > 0.0:
# attesterRatio is the fraction of attesters that actually do their

View File

@ -109,7 +109,7 @@ proc build_empty_block_for_next_slot*(state: BeaconState): BeaconBlock =
# var previous_block_header = state.latest_block_header
# if previous_block_header.state_root == ZERO_HASH:
# previous_block_header.state_root = state.hash_tree_root()
# result.previous_block_root = signed_root(previous_block_header)
# result.previous_block_root = signing_root(previous_block_header)
## TODO: `makeBlock` from testutil.nim
## doesn't work either due to use of fake private keys

View File

@ -31,9 +31,9 @@ suite "Official - State tests": # Initializing a beacon state from the deposits
# TODO: Currently we are unable to use the official EF tests:
# - The provided zero signature "0x0000..." is an invalid compressed BLS signature
# - Block headers are using that signature
# - Block processing checks that block.previous_block_root == signed_root(state.latest_block_header)
# - Block processing checks that block.previous_block_root == signing_root(state.latest_block_header)
# -> Changing EF provided previous_block_root would render the block transition tests meaningless
# -> Changing the signature to a valid "0xc000..." makes all hashes/signed_root wrong ...
# -> Changing the signature to a valid "0xc000..." makes all hashes/signing_root wrong ...
#
# So we only test that block header signing in Nimbus matches block header signing from the EF
# And we can't deserialize from the raw YAML/JSON to avoid sanity checks on the signature
@ -54,7 +54,7 @@ suite "Official - State tests": # Initializing a beacon state from the deposits
hexToByteArray[32]("0x1179346f489d8be1731377cb199af5cc61faa38353e2d67e096bed182677062a")
)
echo " Expected previous block root: 0x", previous_block_root
echo " Computed header signed root: 0x", signed_root(header)
echo " Computed header signed root: 0x", signing_root(header)
test "[For information] Print list of official tests to implement":
for i, test in stateTests.test_cases:
@ -91,7 +91,7 @@ suite "[For information - non-blocking] Extra state tests":
deposits.add Deposit(
proof: default(array[DEPOSIT_CONTRACT_TREE_DEPTH, Eth2Digest]),
index: index,
deposit_data: DepositData(
data: DepositData(
amount: 32000000000'u64, # TODO: read that from validator_balances
timestamp: 0'u64, # TODO: not initialized in test
deposit_input: DepositInput(

View File

@ -25,7 +25,7 @@ suite "Beacon chain DB":
let
blck = BeaconBlock()
root = signed_root(blck)
root = signing_root(blck)
db.putBlock(blck)
@ -62,11 +62,11 @@ suite "Beacon chain DB":
let
a0 = BeaconBlock(slot: GENESIS_SLOT + 0)
a0r = signed_root(a0)
a0r = signing_root(a0)
a1 = BeaconBlock(slot: GENESIS_SLOT + 1, previous_block_root: a0r)
a1r = signed_root(a1)
a1r = signing_root(a1)
a2 = BeaconBlock(slot: GENESIS_SLOT + 2, previous_block_root: a1r)
a2r = signed_root(a2)
a2r = signing_root(a2)
doAssert toSeq(db.getAncestors(a0r)) == []
doAssert toSeq(db.getAncestors(a2r)) == []

View File

@ -36,7 +36,7 @@ suite "Block pool processing":
let
b1 = makeBlock(state.data.data, state.blck.root, BeaconBlockBody())
b1Root = signed_root(b1)
b1Root = signing_root(b1)
# TODO the return value is ugly here, need to fix and test..
discard pool.add(state, b1Root, b1)
@ -56,9 +56,9 @@ suite "Block pool processing":
let
b1 = addBlock(state.data.data, state.blck.root, BeaconBlockBody(), {})
b1Root = signed_root(b1)
b1Root = signing_root(b1)
b2 = addBlock(state.data.data, b1Root, BeaconBlockBody(), {})
b2Root = signed_root(b2)
b2Root = signing_root(b2)
discard pool.add(state, b2Root, b2)

View File

@ -21,7 +21,7 @@ suite "Block processing":
genesisState = get_genesis_beacon_state(
makeInitialDeposits(), 0, Eth1Data(), {})
genesisBlock = get_initial_beacon_block(genesisState)
genesisRoot = signed_root(genesisBlock)
genesisRoot = signing_root(genesisBlock)
test "Passes from genesis state, no block":
var
@ -34,7 +34,7 @@ suite "Block processing":
test "Passes from genesis state, empty block":
var
state = genesisState
previous_block_root = signed_root(genesisBlock)
previous_block_root = signing_root(genesisBlock)
new_block = makeBlock(state, previous_block_root, BeaconBlockBody())
let block_ok = updateState(state, new_block, {})
@ -67,7 +67,7 @@ suite "Block processing":
check:
block_ok
previous_block_root = signed_root(new_block)
previous_block_root = signing_root(new_block)
check:
state.slot == genesisState.slot + SLOTS_PER_EPOCH

View File

@ -5,8 +5,9 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
math,unittest, sequtils,
../beacon_chain/spec/[helpers, datatypes, digest, validator]
math, unittest, sequtils, testutil,
../beacon_chain/spec/[helpers, datatypes, digest, validator, beaconstate],
../beacon_chain/extras
func sumCommittees(v: openArray[seq[ValidatorIndex]], reqCommitteeLen: int): int =
for x in v:
@ -28,13 +29,13 @@ suite "Validators":
## https://github.com/sigp/lighthouse/blob/ba548e49a52687a655c61b443b6835d79c6d4236/beacon_chain/validator_shuffling/src/shuffle.rs
test "Validator shuffling":
let
num_validators = 32*1024
validators = repeat(
Validator(
exit_epoch: FAR_FUTURE_EPOCH
), num_validators)
s = get_shuffling(Eth2Digest(), validators, GENESIS_EPOCH)
committees = get_epoch_committee_count(len(validators)).int
num_validators = 4096
genState = get_genesis_beacon_state(
makeInitialDeposits(num_validators, flags = {skipValidation}), 0,
Eth1Data(), {skipValidation})
s = get_shuffling(
Eth2Digest(), genState.validator_registry, GENESIS_EPOCH)
committees = get_epoch_committee_count(genState, GENESIS_EPOCH).int
check:
# def b(s): return "Eth2Digest(data: [0x" + "'u8, 0x".join((s[i:i+2] for i in range(0, 64, 2))) + "'u8])"
# TODO read YAML file directly from test case generator
@ -79,6 +80,5 @@ suite "Validators":
checkPermutation(1660, 3932, 3046, Eth2Digest(data: [0x86'u8, 0x87'u8, 0xc0'u8, 0x29'u8, 0xff'u8, 0xc4'u8, 0x43'u8, 0x87'u8, 0x95'u8, 0x27'u8, 0xa6'u8, 0x4c'u8, 0x31'u8, 0xb7'u8, 0xac'u8, 0xbb'u8, 0x38'u8, 0xab'u8, 0x6e'u8, 0x34'u8, 0x37'u8, 0x79'u8, 0xd0'u8, 0xb2'u8, 0xc6'u8, 0xe2'u8, 0x50'u8, 0x04'u8, 0x6f'u8, 0xdb'u8, 0x9d'u8, 0xe8'u8]))
checkPermutation(379, 646, 32, Eth2Digest(data: [0x17'u8, 0xe8'u8, 0x54'u8, 0xf4'u8, 0xe8'u8, 0x04'u8, 0x01'u8, 0x34'u8, 0x5e'u8, 0x13'u8, 0xf7'u8, 0x2a'u8, 0xf4'u8, 0x5b'u8, 0x22'u8, 0x1c'u8, 0x9f'u8, 0x7a'u8, 0x84'u8, 0x0f'u8, 0x6a'u8, 0x8c'u8, 0x13'u8, 0x28'u8, 0xdd'u8, 0xf9'u8, 0xc9'u8, 0xca'u8, 0x9a'u8, 0x08'u8, 0x83'u8, 0x79'u8]))
s.len == committees
# 32k validators: SLOTS_PER_EPOCH slots * committee_count_per_slot =
# get_epoch_committee_count committees.
sumCommittees(s, num_validators div committees) == validators.len() # all validators accounted for
sumCommittees(s, num_validators div committees) ==
get_active_validator_indices(genState, GENESIS_EPOCH).len()

View File

@ -36,34 +36,26 @@ func makeDeposit(i: int, flags: UpdateFlags): Deposit =
privkey = makeFakeValidatorPrivKey(i)
pubkey = privkey.pubKey()
withdrawal_credentials = makeFakeHash(i)
domain = 3'u64
let pop =
if skipValidation in flags:
ValidatorSig()
else:
let proof_of_possession_data = DepositInput(
pubkey: pubkey,
withdrawal_credentials: withdrawal_credentials,
)
let domain = 0'u64
bls_sign(privkey, hash_tree_root(proof_of_possession_data).data, domain)
Deposit(
result = Deposit(
index: i.uint64,
deposit_data: DepositData(
deposit_input: DepositInput(
pubkey: pubkey,
proof_of_possession: pop,
withdrawal_credentials: withdrawal_credentials,
),
data: DepositData(
pubkey: pubkey,
withdrawal_credentials: withdrawal_credentials,
amount: MAX_EFFECTIVE_BALANCE,
)
)
if skipValidation notin flags:
result.data.signature =
bls_sign(privkey, signing_root(result.data).data,
domain)
func makeInitialDeposits*(
n = SLOTS_PER_EPOCH, flags: UpdateFlags = {}): seq[Deposit] =
for i in 0..<n.int:
result.add makeDeposit(i + 1, flags)
result.add makeDeposit(i, flags)
func getNextBeaconProposerIndex*(state: BeaconState): ValidatorIndex =
# TODO: This is a special version of get_beacon_proposer_index that takes into
@ -124,7 +116,7 @@ proc addBlock*(
"signature key should be derived from private key! - wrong privkey?"
if skipValidation notin flags:
let block_root = signed_root(new_block)
let block_root = signing_root(new_block)
# We have a signature - put it in the block and we should be done!
new_block.signature =
bls_sign(proposerPrivkey, block_root.data,
@ -193,7 +185,7 @@ proc makeAttestation*(
proc makeTestDB*(tailState: BeaconState, tailBlock: BeaconBlock): BeaconChainDB =
let
tailRoot = signed_root(tailBlock)
tailRoot = signing_root(tailBlock)
result = init(BeaconChainDB, newMemoryDB())
BlockPool.preInit(result, tailState, tailBlock)