Merge pull request #61 from status-im/SUSP1

Spec update
This commit is contained in:
Dustin Brody 2019-01-16 15:23:08 +00:00 committed by GitHub
commit 36b07cbf60
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 140 additions and 56 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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