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:
parent
f385467cd3
commit
d977c96ae1
|
@ -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?
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)) == []
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue