mirror of
https://github.com/status-im/nimbus-eth2.git
synced 2025-01-11 06:46:10 +00:00
commit
36b07cbf60
@ -197,7 +197,7 @@ proc proposeBlock(node: BeaconNode,
|
||||
slot: slot,
|
||||
parent_root: node.headBlockRoot,
|
||||
randao_reveal: randaoReveal,
|
||||
candidate_pow_receipt_root: node.mainchainMonitor.getBeaconBlockRef(),
|
||||
deposit_root: node.mainchainMonitor.getBeaconBlockRef(),
|
||||
signature: ValidatorSig(), # we need the rest of the block first!
|
||||
body: blockBody)
|
||||
|
||||
|
@ -187,7 +187,7 @@ func update_validator_status*(state: var BeaconState,
|
||||
func get_initial_beacon_state*(
|
||||
initial_validator_deposits: openArray[Deposit],
|
||||
genesis_time: uint64,
|
||||
processed_pow_receipt_root: Eth2Digest,
|
||||
latest_deposit_root: Eth2Digest,
|
||||
flags: UpdateFlags = {}): BeaconState =
|
||||
## BeaconState constructor
|
||||
##
|
||||
@ -207,25 +207,25 @@ func get_initial_beacon_state*(
|
||||
|
||||
var state = BeaconState(
|
||||
# Misc
|
||||
slot: INITIAL_SLOT_NUMBER,
|
||||
slot: GENESIS_SLOT,
|
||||
genesis_time: genesis_time,
|
||||
fork_data: ForkData(
|
||||
pre_fork_version: INITIAL_FORK_VERSION,
|
||||
post_fork_version: INITIAL_FORK_VERSION,
|
||||
fork_slot: INITIAL_SLOT_NUMBER,
|
||||
pre_fork_version: GENESIS_FORK_VERSION,
|
||||
post_fork_version: GENESIS_FORK_VERSION,
|
||||
fork_slot: GENESIS_SLOT,
|
||||
),
|
||||
|
||||
validator_registry_latest_change_slot: INITIAL_SLOT_NUMBER,
|
||||
validator_registry_latest_change_slot: GENESIS_SLOT,
|
||||
validator_registry_exit_count: 0,
|
||||
validator_registry_delta_chain_tip: ZERO_HASH,
|
||||
|
||||
# Finality
|
||||
previous_justified_slot: INITIAL_SLOT_NUMBER,
|
||||
justified_slot: INITIAL_SLOT_NUMBER,
|
||||
finalized_slot: INITIAL_SLOT_NUMBER,
|
||||
previous_justified_slot: GENESIS_SLOT,
|
||||
justified_slot: GENESIS_SLOT,
|
||||
finalized_slot: GENESIS_SLOT,
|
||||
|
||||
# PoW receipt root
|
||||
processed_pow_receipt_root: processed_pow_receipt_root,
|
||||
latest_deposit_root: latest_deposit_root,
|
||||
)
|
||||
|
||||
# handle initial deposits and activations
|
||||
@ -233,7 +233,7 @@ func get_initial_beacon_state*(
|
||||
let validator_index = process_deposit(
|
||||
state,
|
||||
deposit.deposit_data.deposit_input.pubkey,
|
||||
deposit.deposit_data.value,
|
||||
deposit.deposit_data.amount,
|
||||
deposit.deposit_data.deposit_input.proof_of_possession,
|
||||
deposit.deposit_data.deposit_input.withdrawal_credentials,
|
||||
deposit.deposit_data.deposit_input.randao_commitment,
|
||||
@ -245,7 +245,7 @@ func get_initial_beacon_state*(
|
||||
# set initial committee shuffling
|
||||
let
|
||||
initial_shuffling =
|
||||
get_new_shuffling(Eth2Digest(), state.validator_registry, 0)
|
||||
get_shuffling(Eth2Digest(), state.validator_registry, 0)
|
||||
|
||||
# initial_shuffling + initial_shuffling in spec, but more ugly
|
||||
for i, n in initial_shuffling:
|
||||
@ -267,6 +267,13 @@ func get_block_root*(state: BeaconState,
|
||||
doAssert slot < state.slot
|
||||
state.latest_block_roots[slot mod LATEST_BLOCK_ROOTS_LENGTH]
|
||||
|
||||
func get_randao_mix*(state: BeaconState,
|
||||
slot: uint64): Eth2Digest =
|
||||
## Returns the randao mix at a recent ``slot``.
|
||||
assert state.slot < slot + LATEST_RANDAO_MIXES_LENGTH
|
||||
assert slot <= state.slot
|
||||
state.latest_randao_mixes[slot mod LATEST_RANDAO_MIXES_LENGTH]
|
||||
|
||||
func get_attestation_participants*(state: BeaconState,
|
||||
attestation_data: AttestationData,
|
||||
participation_bitfield: seq[byte]): seq[Uint24] =
|
||||
@ -356,6 +363,18 @@ func update_validator_registry*(state: var BeaconState) =
|
||||
get_effective_balance(state, index.Uint24) *
|
||||
min(total_penalties * 3, total_balance) div total_balance
|
||||
|
||||
# Perform additional updates
|
||||
state.previous_epoch_calculation_slot = state.current_epoch_calculation_slot
|
||||
state.previous_epoch_start_shard = state.current_epoch_start_shard
|
||||
state.previous_epoch_randao_mix = state.current_epoch_randao_mix
|
||||
state.current_epoch_calculation_slot = state.slot
|
||||
state.current_epoch_start_shard = (state.current_epoch_start_shard + get_current_epoch_committee_count_per_slot(state) * EPOCH_LENGTH) mod SHARD_COUNT
|
||||
state.current_epoch_randao_mix = get_randao_mix(state, state.current_epoch_calculation_slot - SEED_LOOKAHEAD)
|
||||
|
||||
# TODO "If a validator registry update does not happen do the following: ..."
|
||||
|
||||
#process_penalties_and_exits(state)
|
||||
|
||||
proc checkAttestation*(
|
||||
state: BeaconState, attestation: Attestation, flags: UpdateFlags): bool =
|
||||
## Check that an attestation follows the rules of being included in the state
|
||||
|
@ -46,6 +46,7 @@ import
|
||||
# TODO Many of these constants should go into a config object that can be used
|
||||
# to run.. well.. a chain with different constants!
|
||||
const
|
||||
# Misc
|
||||
SHARD_COUNT* = 1024 ##\
|
||||
## Number of shards supported by the network - validators will jump around
|
||||
## between these shards and provide attestations to their state.
|
||||
@ -73,12 +74,13 @@ const
|
||||
|
||||
BEACON_CHAIN_SHARD_NUMBER* = not 0'u64 # 2^64 - 1 in spec
|
||||
|
||||
BLS_WITHDRAWAL_PREFIX_BYTE* = 0'u8
|
||||
|
||||
MAX_CASPER_VOTES* = 2^10
|
||||
LATEST_BLOCK_ROOTS_LENGTH* = 2'u64^13
|
||||
LATEST_RANDAO_MIXES_LENGTH* = 2'u64^13
|
||||
LATEST_PENALIZED_EXIT_LENGTH* = 8192 # epochs
|
||||
MAX_WITHDRAWALS_PER_EPOCHS* = 4 # withdrawals
|
||||
|
||||
# Deposit contract
|
||||
DEPOSIT_CONTRACT_TREE_DEPTH* = 2^5
|
||||
|
||||
MIN_DEPOSIT* = 2'u64^0 ##\
|
||||
@ -89,11 +91,15 @@ const
|
||||
|
||||
# Initial values
|
||||
|
||||
INITIAL_FORK_VERSION* = 0'u64
|
||||
INITIAL_SLOT_NUMBER* = 0'u64
|
||||
GENESIS_FORK_VERSION* = 0'u64
|
||||
GENESIS_SLOT* = 0'u64
|
||||
GENESIS_START_SHARD* = 0'u64
|
||||
FAR_FUTURE_SLOT* = not 0'u64 # 2^64 - 1 in spec
|
||||
ZERO_HASH* = Eth2Digest()
|
||||
# TODO EMPTY_SIGNATURE* =
|
||||
BLS_WITHDRAWAL_PREFIX_BYTE* = 0'u8
|
||||
|
||||
# Time constants
|
||||
# Time parameters
|
||||
SLOT_DURATION* = 6'u64 ## \
|
||||
## TODO consistent time unit across projects, similar to C++ chrono?
|
||||
|
||||
@ -117,6 +123,9 @@ const
|
||||
POW_RECEIPT_ROOT_VOTING_PERIOD* = 2'u64^10 ##\
|
||||
## slots (~1.7 hours)
|
||||
|
||||
SEED_LOOKAHEAD* = 64 ##\
|
||||
## slots (~6.4 minutes)
|
||||
|
||||
SHARD_PERSISTENT_COMMITTEE_CHANGE_PERIOD* = 2'u64^17 ##\
|
||||
## slots (~9 days)
|
||||
|
||||
@ -126,6 +135,12 @@ const
|
||||
ZERO_BALANCE_VALIDATOR_TTL* = 2'u64^22 ##\
|
||||
## slots (~291 days)
|
||||
|
||||
DEPOSIT_ROOT_VOTING_PERIOD* = 2'u64^10 ##\
|
||||
## slots (~1.7 hours)
|
||||
|
||||
MIN_VALIDATOR_WITHDRAWAL_TIME* = 2'u64^14 ##\
|
||||
## slots (~27 hours)
|
||||
|
||||
# Quotients
|
||||
BASE_REWARD_QUOTIENT* = 2'u64^10 ##\
|
||||
## The `BASE_REWARD_QUOTIENT` parameter dictates the per-epoch reward. It
|
||||
@ -135,6 +150,12 @@ const
|
||||
INCLUDER_REWARD_QUOTIENT* = 2'u64^3
|
||||
INACTIVITY_PENALTY_QUOTIENT* = 2'u64^24
|
||||
|
||||
# Status flags
|
||||
# Could model this with enum, but following spec closely here
|
||||
INITIATED_EXIT* = 1'u64
|
||||
WITHDRAWABLE* = 2'u64
|
||||
|
||||
# Max operations per block
|
||||
MAX_PROPOSER_SLASHINGS* = 2^4
|
||||
MAX_CASPER_SLASHINGS* = 2^4
|
||||
MAX_ATTESTATIONS* = 2^7
|
||||
@ -203,24 +224,25 @@ type
|
||||
poc_bit: bool
|
||||
|
||||
Deposit* = object
|
||||
merkle_branch*: seq[Eth2Digest] ##\
|
||||
## Receipt Merkle branch
|
||||
branch*: seq[Eth2Digest] ##\
|
||||
## Branch in the deposit tree
|
||||
|
||||
merkle_tree_index*: uint64
|
||||
index*: uint64 ##\
|
||||
## Index in the deposit tree
|
||||
|
||||
## Deposit data
|
||||
deposit_data*: DepositData
|
||||
deposit_data*: DepositData ##\
|
||||
## Data
|
||||
|
||||
DepositData* = object
|
||||
amount*: uint64 ## Value in Gwei
|
||||
deposit_input*: DepositInput
|
||||
value*: uint64 ## Value in Gwei
|
||||
timestamp*: uint64 # Timestamp from deposit contract
|
||||
|
||||
DepositInput* = object
|
||||
pubkey*: ValidatorPubKey
|
||||
withdrawal_credentials*: Eth2Digest
|
||||
randao_commitment*: Eth2Digest # Initial RANDAO commitment
|
||||
poc_commitment*: Eth2Digest
|
||||
custody_commitment*: Eth2Digest
|
||||
proof_of_possession*: ValidatorSig ##\
|
||||
## BLS proof of possession (a BLS signature)
|
||||
|
||||
@ -249,7 +271,7 @@ type
|
||||
randao_reveal*: Eth2Digest ##\
|
||||
## Proposer RANDAO reveal
|
||||
|
||||
candidate_pow_receipt_root*: Eth2Digest
|
||||
deposit_root*: Eth2Digest
|
||||
|
||||
signature*: ValidatorSig ##\
|
||||
## Proposer signature
|
||||
@ -261,14 +283,14 @@ type
|
||||
casper_slashings*: seq[CasperSlashing]
|
||||
attestations*: seq[Attestation]
|
||||
poc_seed_changes*: seq[ProofOfCustodySeedChange]
|
||||
poc_challenges*: seq[ProofOfCustodyChallenge]
|
||||
poc_challenges*: seq[CustodyChallenge]
|
||||
poc_responses*: seq[ProofOfCustodyResponse]
|
||||
deposits*: seq[Deposit]
|
||||
exits*: seq[Exit]
|
||||
|
||||
# Phase1:
|
||||
ProofOfCustodySeedChange* = object
|
||||
ProofOfCustodyChallenge* = object
|
||||
CustodyChallenge* = object
|
||||
ProofOfCustodyResponse* = object
|
||||
|
||||
ProposalSignedData* = object
|
||||
@ -302,10 +324,17 @@ type
|
||||
## Committee members and their assigned shard, per slot, covers 2 cycles
|
||||
## worth of assignments
|
||||
|
||||
previous_epoch_start_shard*: uint64
|
||||
current_epoch_start_shard*: uint64
|
||||
previous_epoch_calculation_slot*: uint64
|
||||
current_epoch_calculation_slot*: uint64
|
||||
previous_epoch_randao_mix*: Eth2Digest
|
||||
current_epoch_randao_mix*: Eth2Digest
|
||||
|
||||
persistent_committees*: seq[seq[Uint24]]
|
||||
persistent_committee_reassignments*: seq[ShardReassignmentRecord]
|
||||
|
||||
poc_challenges*: seq[ProofOfCustodyChallenge]
|
||||
poc_challenges*: seq[CustodyChallenge]
|
||||
|
||||
# Finality
|
||||
previous_justified_slot*: uint64
|
||||
@ -313,6 +342,7 @@ type
|
||||
justification_bitfield*: uint64
|
||||
finalized_slot*: uint64
|
||||
|
||||
# Recent state
|
||||
latest_crosslinks*: array[SHARD_COUNT, CrosslinkRecord]
|
||||
latest_block_roots*: array[LATEST_BLOCK_ROOTS_LENGTH.int, Eth2Digest] ##\
|
||||
## Needed to process attestations, older to newer
|
||||
@ -323,8 +353,8 @@ type
|
||||
latest_attestations*: seq[PendingAttestationRecord]
|
||||
batched_block_roots*: seq[Eth2Digest]
|
||||
|
||||
processed_pow_receipt_root*: Eth2Digest
|
||||
candidate_pow_receipt_roots*: seq[CandidatePoWReceiptRootRecord]
|
||||
latest_deposit_root*: Eth2Digest
|
||||
deposit_roots*: seq[DepositRootVote]
|
||||
|
||||
ValidatorRecord* = object
|
||||
pubkey*: ValidatorPubKey
|
||||
@ -345,10 +375,22 @@ type
|
||||
latest_status_change_slot*: uint64 ##\
|
||||
## Slot when validator last changed status (or 0)
|
||||
|
||||
activation_slot*: uint64 ##\
|
||||
## Slot when validator activated
|
||||
|
||||
exit_slot*: uint64 ##\
|
||||
## Slot when validator exited
|
||||
|
||||
withdrawal_slot*: uint64 ##\
|
||||
## Slot when validator withdrew
|
||||
|
||||
penalized_slot*: uint64 ##\
|
||||
## Slot when validator penalized
|
||||
|
||||
exit_count*: uint64 ##\
|
||||
## Exit counter when validator exited (or 0)
|
||||
|
||||
poc_commitment*: Eth2Digest
|
||||
custody_commitment*: Eth2Digest
|
||||
|
||||
last_poc_change_slot*: uint64
|
||||
second_last_poc_change_slot*: uint64
|
||||
@ -377,8 +419,8 @@ type
|
||||
slot*: uint64 ##\
|
||||
## When
|
||||
|
||||
CandidatePoWReceiptRootRecord* = object
|
||||
candidate_pow_receipt_root*: Eth2Digest # Candidate PoW receipt root
|
||||
DepositRootVote* = object
|
||||
deposit_root*: Eth2Digest
|
||||
vote_count*: uint64 # Vote count
|
||||
|
||||
PendingAttestationRecord* = object
|
||||
|
@ -180,3 +180,29 @@ proc is_surround_vote*(attestation_data_1: AttestationData,
|
||||
(attestation_data_1.justified_slot + 1 == attestation_data_2.slot) and
|
||||
(attestation_data_2.slot < attestation_data_1.slot)
|
||||
)
|
||||
|
||||
#func is_active_validator*(validator: ValidatorRecord, slot: uint64): bool =
|
||||
# ### Checks if validator is active
|
||||
# validator.activation_slot <= slot and slot < validator.exit_slot
|
||||
|
||||
func is_active_validator*(validator: ValidatorRecord): bool =
|
||||
validator.status in {ACTIVE, ACTIVE_PENDING_EXIT}
|
||||
|
||||
func get_active_validator_indices*(validators: openArray[ValidatorRecord], slot: uint64): seq[Uint24] =
|
||||
## Gets indices of active validators from validators
|
||||
for idx, val in validators:
|
||||
#if is_active_validator(val, slot):
|
||||
if is_active_validator(val):
|
||||
result.add idx.Uint24
|
||||
|
||||
func get_committee_count_per_slot*(active_validator_count: int): uint64 =
|
||||
clamp(
|
||||
active_validator_count div EPOCH_LENGTH div TARGET_COMMITTEE_SIZE,
|
||||
1, SHARD_COUNT div EPOCH_LENGTH).uint64
|
||||
|
||||
func get_current_epoch_committee_count_per_slot*(state: BeaconState): uint64 =
|
||||
let current_active_validators = get_active_validator_indices(
|
||||
state.validator_registry,
|
||||
state.current_epoch_calculation_slot,
|
||||
)
|
||||
return get_committee_count_per_slot(len(current_active_validators))
|
||||
|
@ -12,9 +12,6 @@ import
|
||||
../ssz,
|
||||
./crypto, ./datatypes, ./digest, ./helpers
|
||||
|
||||
func is_active_validator*(validator: ValidatorRecord): bool =
|
||||
validator.status in {ACTIVE, ACTIVE_PENDING_EXIT}
|
||||
|
||||
func min_empty_validator_index*(
|
||||
validators: seq[ValidatorRecord],
|
||||
validator_balances: seq[uint64],
|
||||
@ -31,10 +28,10 @@ func get_active_validator_indices*(validators: openArray[ValidatorRecord]): seq[
|
||||
if is_active_validator(val):
|
||||
result.add idx.Uint24
|
||||
|
||||
func get_new_shuffling*(seed: Eth2Digest,
|
||||
validators: openArray[ValidatorRecord],
|
||||
crosslinking_start_shard: uint64
|
||||
): array[EPOCH_LENGTH, seq[ShardCommittee]] =
|
||||
func get_shuffling*(seed: Eth2Digest,
|
||||
validators: openArray[ValidatorRecord],
|
||||
crosslinking_start_shard: uint64
|
||||
): array[EPOCH_LENGTH, seq[ShardCommittee]] =
|
||||
## Split up validators into groups at the start of every epoch,
|
||||
## determining at what height they can make attestations and what shard they are making crosslinks for
|
||||
## Implementation should do the following: http://vitalik.ca/files/ShuffleAndAssign.png
|
||||
|
@ -100,16 +100,16 @@ func processRandao(
|
||||
|
||||
return true
|
||||
|
||||
func processPoWReceiptRoot(state: var BeaconState, blck: BeaconBlock) =
|
||||
func processDepositRoot(state: var BeaconState, blck: BeaconBlock) =
|
||||
## https://github.com/ethereum/eth2.0-specs/blob/master/specs/core/0_beacon-chain.md#pow-receipt-root
|
||||
|
||||
for x in state.candidate_pow_receipt_roots.mitems():
|
||||
if blck.candidate_pow_receipt_root == x.candidate_pow_receipt_root:
|
||||
for x in state.deposit_roots.mitems():
|
||||
if blck.deposit_root == x.deposit_root:
|
||||
x.vote_count += 1
|
||||
return
|
||||
|
||||
state.candidate_pow_receipt_roots.add CandidatePoWReceiptRootRecord(
|
||||
candidate_pow_receipt_root: blck.candidate_pow_receipt_root,
|
||||
state.deposit_roots.add DepositRootVote(
|
||||
deposit_root: blck.deposit_root,
|
||||
vote_count: 1
|
||||
)
|
||||
|
||||
@ -362,7 +362,7 @@ proc processBlock(
|
||||
warn("Randao reveal failed")
|
||||
return false
|
||||
|
||||
processPoWReceiptRoot(state, blck)
|
||||
processDepositRoot(state, blck)
|
||||
|
||||
if not processProposerSlashings(state, blck, flags):
|
||||
return false
|
||||
@ -565,11 +565,11 @@ func processEpoch(state: var BeaconState) =
|
||||
|
||||
block: # Receipt roots
|
||||
if state.slot mod POW_RECEIPT_ROOT_VOTING_PERIOD == 0:
|
||||
for x in state.candidate_pow_receipt_roots:
|
||||
for x in state.deposit_roots:
|
||||
if x.vote_count * 2 >= POW_RECEIPT_ROOT_VOTING_PERIOD:
|
||||
state.processed_pow_receipt_root = x.candidate_pow_receipt_root
|
||||
state.latest_deposit_root = x.deposit_root
|
||||
break
|
||||
state.candidate_pow_receipt_roots = @[]
|
||||
state.deposit_roots = @[]
|
||||
|
||||
block: # Justification
|
||||
state.previous_justified_slot = state.justified_slot
|
||||
@ -700,7 +700,7 @@ func processEpoch(state: var BeaconState) =
|
||||
|
||||
let next_start_shard =
|
||||
(state.shard_committees_at_slots[^1][^1].shard + 1) mod SHARD_COUNT
|
||||
for i, v in get_new_shuffling(
|
||||
for i, v in get_shuffling(
|
||||
state.latest_randao_mixes[
|
||||
(state.slot - EPOCH_LENGTH) mod LATEST_RANDAO_MIXES_LENGTH],
|
||||
state.validator_registry, next_start_shard):
|
||||
@ -719,7 +719,7 @@ func processEpoch(state: var BeaconState) =
|
||||
start_shard = state.shard_committees_at_slots[0][0].shard
|
||||
|
||||
if is_power_of_2(epochs_since_last_registry_change):
|
||||
for i, v in get_new_shuffling(
|
||||
for i, v in get_shuffling(
|
||||
state.latest_randao_mixes[
|
||||
(state.slot - EPOCH_LENGTH) mod LATEST_RANDAO_MIXES_LENGTH],
|
||||
state.validator_registry, start_shard):
|
||||
|
@ -25,7 +25,7 @@ suite "Validators":
|
||||
), 32*1024)
|
||||
|
||||
# TODO the shuffling looks really odd, probably buggy
|
||||
let s = get_new_shuffling(Eth2Digest(), validators, 0)
|
||||
let s = get_shuffling(Eth2Digest(), validators, 0)
|
||||
check:
|
||||
s.len == EPOCH_LENGTH
|
||||
# 32k validators means 2 shards validated per slot - the aim is to get
|
||||
|
@ -67,7 +67,7 @@ func makeDeposit(i: int, flags: UpdateFlags): Deposit =
|
||||
withdrawal_credentials: withdrawal_credentials,
|
||||
randao_commitment: randao_commitment
|
||||
),
|
||||
value: MAX_DEPOSIT * GWEI_PER_ETH,
|
||||
amount: MAX_DEPOSIT * GWEI_PER_ETH,
|
||||
)
|
||||
)
|
||||
|
||||
@ -78,7 +78,7 @@ func makeInitialDeposits*(
|
||||
|
||||
func makeGenesisBlock*(state: BeaconState): BeaconBlock =
|
||||
BeaconBlock(
|
||||
slot: INITIAL_SLOT_NUMBER,
|
||||
slot: GENESIS_SLOT,
|
||||
state_root: Eth2Digest(data: hash_tree_root(state))
|
||||
)
|
||||
|
||||
@ -115,7 +115,7 @@ proc addBlock*(
|
||||
parent_root: previous_block_root,
|
||||
state_root: Eth2Digest(), # we need the new state first
|
||||
randao_reveal: hackReveal(proposer),
|
||||
candidate_pow_receipt_root: Eth2Digest(), # TODO
|
||||
deposit_root: Eth2Digest(), # TODO
|
||||
signature: ValidatorSig(), # we need the rest of the block first!
|
||||
body: body
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user