data type updates from spec (#25)

* data type updates from spec
This commit is contained in:
tersec 2018-12-03 17:46:22 +00:00 committed by Jacek Sieka
parent 0d775eefcb
commit 0141c84fe5
9 changed files with 66 additions and 61 deletions

View File

@ -131,7 +131,7 @@ proc scheduleCycleActions(node: BeaconNode) =
## attestations from our attached validators. ## attestations from our attached validators.
let cycleStart = node.beaconState.last_state_recalculation_slot.int let cycleStart = node.beaconState.last_state_recalculation_slot.int
for i in 0 ..< CYCLE_LENGTH: for i in 0 ..< EPOCH_LENGTH:
# Schedule block proposals # Schedule block proposals
let let
slot = cycleStart + i slot = cycleStart + i
@ -170,7 +170,7 @@ proc processBlocks*(node: BeaconNode) {.async.} =
# 3. Peform block processing / state recalculation / etc # 3. Peform block processing / state recalculation / etc
# #
if b.slot mod CYCLE_LENGTH == 0: if b.slot mod EPOCH_LENGTH == 0:
node.scheduleCycleActions() node.scheduleCycleActions()
node.attestations.discardHistoryToSlot(b.slot) node.attestations.discardHistoryToSlot(b.slot)

View File

@ -26,11 +26,11 @@ func on_startup*(initial_validator_entries: openArray[InitialValidator],
## must be calculated before creating the genesis block. ## must be calculated before creating the genesis block.
# #
# Induct validators # Induct validators
# Not in spec: the system doesn't work unless there are at least CYCLE_LENGTH # Not in spec: the system doesn't work unless there are at least EPOCH_LENGTH
# validators - there needs to be at least one member in each committee - # validators - there needs to be at least one member in each committee -
# good to know for testing, though arguably the system is not that useful at # good to know for testing, though arguably the system is not that useful at
# at that point :) # at that point :)
assert initial_validator_entries.len >= CYCLE_LENGTH assert initial_validator_entries.len >= EPOCH_LENGTH
var validators: seq[ValidatorRecord] var validators: seq[ValidatorRecord]
@ -55,10 +55,10 @@ func on_startup*(initial_validator_entries: openArray[InitialValidator],
x = get_new_shuffling(Eth2Digest(), validators, 0) x = get_new_shuffling(Eth2Digest(), validators, 0)
# x + x in spec, but more ugly # x + x in spec, but more ugly
var tmp: array[2 * CYCLE_LENGTH, seq[ShardAndCommittee]] var tmp: array[2 * EPOCH_LENGTH, seq[ShardAndCommittee]]
for i, n in x: for i, n in x:
tmp[i] = n tmp[i] = n
tmp[CYCLE_LENGTH + i] = n tmp[EPOCH_LENGTH + i] = n
# The spec says to use validators, but it's actually indices.. # The spec says to use validators, but it's actually indices..
let validator_indices = get_active_validator_indices(validators) let validator_indices = get_active_validator_indices(validators)
@ -77,13 +77,13 @@ func on_startup*(initial_validator_entries: openArray[InitialValidator],
func get_shards_and_committees_index*(state: BeaconState, slot: uint64): uint64 = func get_shards_and_committees_index*(state: BeaconState, slot: uint64): uint64 =
# TODO spec unsigned-unsafe here # TODO spec unsigned-unsafe here
let earliest_slot_in_array = let earliest_slot_in_array =
if state.last_state_recalculation_slot > CYCLE_LENGTH.uint64: if state.last_state_recalculation_slot > EPOCH_LENGTH.uint64:
state.last_state_recalculation_slot - CYCLE_LENGTH state.last_state_recalculation_slot - EPOCH_LENGTH
else: else:
0 0
doAssert earliest_slot_in_array <= slot and doAssert earliest_slot_in_array <= slot and
slot < earliest_slot_in_array + CYCLE_LENGTH * 2 slot < earliest_slot_in_array + EPOCH_LENGTH * 2
slot - earliest_slot_in_array slot - earliest_slot_in_array
proc get_shards_and_committees_for_slot*( proc get_shards_and_committees_for_slot*(

View File

@ -16,7 +16,7 @@
# https://github.com/ethereum/eth2.0-specs/blob/master/specs/beacon-chain.md # https://github.com/ethereum/eth2.0-specs/blob/master/specs/beacon-chain.md
# #
# How wrong the code is: # How wrong the code is:
# https://github.com/ethereum/eth2.0-specs/compare/126a7abfa86448091a0e037f52966b6a9531a857...master # https://github.com/ethereum/eth2.0-specs/compare/2983e68f0305551083fac7fcf9330c1fc9da3411...master
# #
# These datatypes are used as specifications for serialization - thus should not # These datatypes are used as specifications for serialization - thus should not
# be altered outside of what the spec says. Likewise, they should not be made # be altered outside of what the spec says. Likewise, they should not be made
@ -29,36 +29,41 @@ import
const const
SHARD_COUNT* = 1024 # a constant referring to the number of shards SHARD_COUNT* = 1024 # a constant referring to the number of shards
DEPOSIT_SIZE* = 2^5 # You need to deposit 32 ETH to be a validator in Casper
MIN_TOPUP_SIZE* = 1 # ETH
MIN_ONLINE_DEPOSIT_SIZE* = 2^4 # ETH
GWEI_PER_ETH* = 10^9 # Gwei/ETH
DEPOSITS_FOR_CHAIN_START* = 2^14 # deposits
TARGET_COMMITTEE_SIZE* = 2^8 # validators TARGET_COMMITTEE_SIZE* = 2^8 # validators
SLOT_DURATION* = 6 # seconds MAX_ATTESTATIONS_PER_BLOCK* = 2^7 # attestations
CYCLE_LENGTH* = 64 # slots (~ 6 minutes) MAX_DEPOSIT* = 2^5 # ETH
MIN_VALIDATOR_SET_CHANGE_INTERVAL* = 2^8 # slots (~25 minutes) MIN_BALANCE* = 2^4 # ETH
SHARD_PERSISTENT_COMMITTEE_CHANGE_PERIOD* = 2^17 # slots (~9 days) POW_CONTRACT_MERKLE_TREE_DEPTH* = 2^5 #
MIN_ATTESTATION_INCLUSION_DELAY* = 4 # slots (~25 minutes) INITIAL_FORK_VERSION* = 0 #
SQRT_E_DROP_TIME* = 2^9 # slots (~9 days); amount of time it takes for the INITIAL_SLOT_NUMBER* = 0 #
# quadratic leak to cut deposits of non-participating GWEI_PER_ETH* = 10^9 # Gwei/ETH
# validators by ~39.4% BEACON_CHAIN_SHARD_NUMBER* = not 0'u64
WITHDRAWALS_PER_CYCLE* = 2^2 # validators (5.2m ETH in ~6 months) WITHDRAWALS_PER_CYCLE* = 2^2 # validators (5.2m ETH in ~6 months)
MIN_WITHDRAWAL_PERIOD* = 2^13 # slots (~14 hours) MIN_WITHDRAWAL_PERIOD* = 2^13 # slots (~14 hours)
DELETION_PERIOD* = 2^22 # slots (~290 days)
COLLECTIVE_PENALTY_CALCULATION_PERIOD* = 2^20 # slots (~2.4 months) # Time constants
SLOT_DURATION* = 6 # seconds
MIN_ATTESTATION_INCLUSION_DELAY* = 4 # slots (~25 minutes)
EPOCH_LENGTH* = 64 # slots (~6.4 minutes)
MIN_VALIDATOR_SET_CHANGE_INTERVAL* = 2^8 # slots (~25.6 minutes)
POW_RECEIPT_ROOT_VOTING_PERIOD* = 2^10 # slots (~1.7 hours) POW_RECEIPT_ROOT_VOTING_PERIOD* = 2^10 # slots (~1.7 hours)
SLASHING_WHISTLEBLOWER_REWARD_DENOMINATOR* = 2^9 # ? SHARD_PERSISTENT_COMMITTEE_CHANGE_PERIOD* = 2^17 # slots (~9 days)
SQRT_E_DROP_TIME* = 2^17 # slots (~9 days); amount of time it takes for the
# quadratic leak to cut deposits of non-participating
# validators by ~39.4%
COLLECTIVE_PENALTY_CALCULATION_PERIOD* = 2^20 # slots (~2.4 months)
DELETION_PERIOD* = 2^22 # slots (~290 days)
# Quotients
BASE_REWARD_QUOTIENT* = 2^11 # per-cycle interest rate assuming all validators are BASE_REWARD_QUOTIENT* = 2^11 # per-cycle interest rate assuming all validators are
# participating, assuming total deposits of 1 ETH. It # participating, assuming total deposits of 1 ETH. It
# corresponds to ~2.57% annual interest assuming 10 # corresponds to ~2.57% annual interest assuming 10
# million participating ETH. # million participating ETH.
MAX_VALIDATOR_CHURN_QUOTIENT* = 2^5 # At most `1/MAX_VALIDATOR_CHURN_QUOTIENT` of the WHISTLEBLOWER_REWARD_QUOTIENT* = 2^9 # ?
INCLUDER_REWARD_QUOTIENT* = 2^3 #
MAX_CHURN_QUOTIENT* = 2^5 # At most `1/MAX_VALIDATOR_CHURN_QUOTIENT` of the
# validators can change during each validator set # validators can change during each validator set
# change. # change.
POW_CONTRACT_MERKLE_TREE_DEPTH* = 2^5 #
MAX_ATTESTATION_COUNT* = 2^7 #
INITIAL_FORK_VERSION* = 0 #
type type
Uint24* = range[0'u32 .. 0xFFFFFF'u32] # TODO: wrap-around Uint24* = range[0'u32 .. 0xFFFFFF'u32] # TODO: wrap-around
@ -110,7 +115,7 @@ type
justification_source*: uint64 # Justification source justification_source*: uint64 # Justification source
prev_cycle_justification_source*: uint64 # prev_cycle_justification_source*: uint64 #
justified_slot_bitfield*: uint64 # Recent justified slot bitmask justified_slot_bitfield*: uint64 # Recent justified slot bitmask
shard_and_committee_for_slots*: array[2 * CYCLE_LENGTH, seq[ShardAndCommittee]] ## \ shard_and_committee_for_slots*: array[2 * EPOCH_LENGTH, seq[ShardAndCommittee]] ## \
## Committee members and their assigned shard, per slot, covers 2 cycles ## Committee members and their assigned shard, per slot, covers 2 cycles
## worth of assignments ## worth of assignments
persistent_committees*: seq[seq[Uint24]] # Persistent shard committees persistent_committees*: seq[seq[Uint24]] # Persistent shard committees
@ -167,20 +172,20 @@ type
slot_included*: uint64 # Slot in which it was included slot_included*: uint64 # Slot in which it was included
ValidatorStatusCodes* {.pure.} = enum ValidatorStatusCodes* {.pure.} = enum
PendingActivation = 0 PENDING_ACITVATION = 0
Active = 1 ACTIVE = 1
PendingExit = 2 EXITED_WITHOUT_PENALTY = 2
PendingWithdraw = 3 EXITED_WITH_PENALTY = 3
Withdrawn = 4 PENDING_EXIT = 29 # https://github.com/ethereum/eth2.0-specs/issues/216
Penalized = 127
SpecialRecordType* {.pure.} = enum SpecialRecordType* {.pure.} = enum
Logout = 0 Logout = 0
CasperSlashing = 1 CasperSlashing = 1
RandaoChange = 2 RandaoChange = 2
DepositProof = 3
ValidatorSetDeltaFlags* {.pure.} = enum ValidatorSetDeltaFlags* {.pure.} = enum
Entry = 0 Activation = 0
Exit = 1 Exit = 1
# Note: # Note:

View File

@ -11,15 +11,15 @@ import
eth_common, eth_common,
./crypto, ./datatypes, ./digest, ./helpers ./crypto, ./datatypes, ./digest, ./helpers
func min_empty_validator(validators: seq[ValidatorRecord], current_slot: uint64): Option[int] = func min_empty_validator_index(validators: seq[ValidatorRecord], current_slot: uint64): Option[int] =
for i, v in validators: for i, v in validators:
if v.status == WITHDRAWN and v.last_status_change_slot + DELETION_PERIOD.uint64 <= current_slot: if v.balance == 0 and v.last_status_change_slot + DELETION_PERIOD.uint64 <= current_slot:
return some(i) return some(i)
func get_new_validators*(current_validators: seq[ValidatorRecord], func get_new_validators*(current_validators: seq[ValidatorRecord],
fork_data: ForkData, fork_data: ForkData,
pubkey: ValidatorPubKey, pubkey: ValidatorPubKey,
deposit_size: uint64, deposit: uint64,
proof_of_possession: seq[byte], proof_of_possession: seq[byte],
withdrawal_credentials: Eth2Digest, withdrawal_credentials: Eth2Digest,
randao_commitment: Eth2Digest, randao_commitment: Eth2Digest,
@ -47,7 +47,7 @@ func get_new_validators*(current_validators: seq[ValidatorRecord],
# assert val.status != WITHDRAWN # assert val.status != WITHDRAWN
# assert val.withdrawal_credentials == withdrawal_credentials # assert val.withdrawal_credentials == withdrawal_credentials
val.balance.inc(deposit_size.int) val.balance.inc(deposit.int)
return (new_validators, index) return (new_validators, index)
# new validator # new validator
@ -57,13 +57,13 @@ func get_new_validators*(current_validators: seq[ValidatorRecord],
withdrawal_credentials: withdrawal_credentials, withdrawal_credentials: withdrawal_credentials,
randao_commitment: randao_commitment, randao_commitment: randao_commitment,
randao_skips: 0, randao_skips: 0,
balance: DEPOSIT_SIZE * GWEI_PER_ETH, balance: deposit,
status: status, status: status,
last_status_change_slot: current_slot, last_status_change_slot: current_slot,
exit_seq: 0 exit_seq: 0
) )
let index = min_empty_validator(new_validators, current_slot) let index = min_empty_validator_index(new_validators, current_slot)
if index.isNone: if index.isNone:
new_validators.add(rec) new_validators.add(rec)
(new_validators, len(new_validators) - 1) (new_validators, len(new_validators) - 1)
@ -74,13 +74,13 @@ func get_new_validators*(current_validators: seq[ValidatorRecord],
func get_active_validator_indices*(validators: openArray[ValidatorRecord]): seq[Uint24] = func get_active_validator_indices*(validators: openArray[ValidatorRecord]): seq[Uint24] =
## Select the active validators ## Select the active validators
for idx, val in validators: for idx, val in validators:
if val.status == ACTIVE: if val.status == ACTIVE or val.status == PENDING_EXIT:
result.add idx.Uint24 result.add idx.Uint24
func get_new_shuffling*(seed: Eth2Digest, func get_new_shuffling*(seed: Eth2Digest,
validators: openArray[ValidatorRecord], validators: openArray[ValidatorRecord],
crosslinking_start_shard: int crosslinking_start_shard: int
): array[CYCLE_LENGTH, seq[ShardAndCommittee]] = ): array[EPOCH_LENGTH, seq[ShardAndCommittee]] =
## Split up validators into groups at the start of every epoch, ## 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 ## 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 ## Implementation should do the following: http://vitalik.ca/files/ShuffleAndAssign.png
@ -88,14 +88,14 @@ func get_new_shuffling*(seed: Eth2Digest,
let let
active_validators = get_active_validator_indices(validators) active_validators = get_active_validator_indices(validators)
committees_per_slot = clamp( committees_per_slot = clamp(
len(active_validators) div CYCLE_LENGTH div TARGET_COMMITTEE_SIZE, len(active_validators) div EPOCH_LENGTH div TARGET_COMMITTEE_SIZE,
1, SHARD_COUNT div CYCLE_LENGTH) 1, SHARD_COUNT div EPOCH_LENGTH)
# Shuffle with seed # Shuffle with seed
shuffled_active_validator_indices = shuffle(active_validators, seed) shuffled_active_validator_indices = shuffle(active_validators, seed)
# Split the shuffled list into cycle_length pieces # Split the shuffled list into cycle_length pieces
validators_per_slot = split(shuffled_active_validator_indices, CYCLE_LENGTH) validators_per_slot = split(shuffled_active_validator_indices, EPOCH_LENGTH)
assert validators_per_slot.len() == CYCLE_LENGTH # what split should do.. assert validators_per_slot.len() == EPOCH_LENGTH # what split should do..
for slot, slot_indices in validators_per_slot: for slot, slot_indices in validators_per_slot:
let let

View File

@ -26,14 +26,14 @@ func checkAttestations(state: BeaconState,
blck: BeaconBlock, blck: BeaconBlock,
parent_slot: uint64): Option[seq[ProcessedAttestation]] = parent_slot: uint64): Option[seq[ProcessedAttestation]] =
# TODO perf improvement potential.. # TODO perf improvement potential..
if blck.attestations.len > MAX_ATTESTATION_COUNT: if blck.attestations.len > MAX_ATTESTATIONS_PER_BLOCK:
return return
var res: seq[ProcessedAttestation] var res: seq[ProcessedAttestation]
for attestation in blck.attestations: for attestation in blck.attestations:
if attestation.data.slot <= blck.slot - MIN_ATTESTATION_INCLUSION_DELAY: if attestation.data.slot <= blck.slot - MIN_ATTESTATION_INCLUSION_DELAY:
return return
if attestation.data.slot >= max(parent_slot - CYCLE_LENGTH + 1, 0): if attestation.data.slot >= max(parent_slot - EPOCH_LENGTH + 1, 0):
return return
#doAssert attestation.data.justified_slot == justification_source if attestation.data.slot >= state.last_state_recalculation_slot else prev_cycle_justification_source #doAssert attestation.data.justified_slot == justification_source if attestation.data.slot >= state.last_state_recalculation_slot else prev_cycle_justification_source
# doAssert attestation.data.justified_block_hash == get_block_hash(state, block, attestation.data.justified_slot). # doAssert attestation.data.justified_block_hash == get_block_hash(state, block, attestation.data.justified_slot).

View File

@ -6,7 +6,7 @@ import
type type
ValidatorChangeLogEntry* = object ValidatorChangeLogEntry* = object
case kind*: ValidatorSetDeltaFlags case kind*: ValidatorSetDeltaFlags
of Entry: of Activation:
pubkey: ValidatorPubKey pubkey: ValidatorPubKey
else: else:
index: uint32 index: uint32
@ -55,7 +55,7 @@ iterator changes*(log: ChangeLog): ChangeLogEntry =
for i in 0 ..< bits: for i in 0 ..< bits:
yield if log.order.getBit(i): yield if log.order.getBit(i):
ChangeLogEntry(kind: Entry, pubkey: nextItem(added)) ChangeLogEntry(kind: Activation, pubkey: nextItem(added))
else: else:
ChangeLogEntry(kind: Exit, index: nextItem(removed)) ChangeLogEntry(kind: Exit, index: nextItem(removed))
@ -86,7 +86,7 @@ proc applyValidatorChangeLog*(log: ChangeLog,
# #
outBeaconState.last_finalized_slot = outBeaconState.last_finalized_slot =
log.signedBlock.slot div CYCLE_LENGTH log.signedBlock.slot div EPOCH_LENGTH
outBeaconState.validator_set_delta_hash_chain = outBeaconState.validator_set_delta_hash_chain =
log.beaconState.validator_set_delta_hash_chain log.beaconState.validator_set_delta_hash_chain

View File

@ -15,5 +15,5 @@ suite "Beacon state":
# Smoke test # Smoke test
test "Smoke on_startup": test "Smoke on_startup":
let state = on_startup(makeInitialValidators(CYCLE_LENGTH), 0, Eth2Digest()) let state = on_startup(makeInitialValidators(EPOCH_LENGTH), 0, Eth2Digest())
check: state.validators.len == CYCLE_LENGTH check: state.validators.len == EPOCH_LENGTH

View File

@ -27,9 +27,9 @@ suite "Validators":
# TODO the shuffling looks really odd, probably buggy # TODO the shuffling looks really odd, probably buggy
let s = get_new_shuffling(Eth2Digest(), validators, 0) let s = get_new_shuffling(Eth2Digest(), validators, 0)
check: check:
s.len == CYCLE_LENGTH s.len == EPOCH_LENGTH
# 32k validators means 2 shards validated per slot - the aim is to get # 32k validators means 2 shards validated per slot - the aim is to get
# TARGET_COMMITTEE_SIZE validators in each shard and there are # TARGET_COMMITTEE_SIZE validators in each shard and there are
# CYCLE_LENGTH slots which each will crosslink a different shard # EPOCH_LENGTH slots which each will crosslink a different shard
s[0].len == 32 * 1024 div (TARGET_COMMITTEE_SIZE * CYCLE_LENGTH) s[0].len == 32 * 1024 div (TARGET_COMMITTEE_SIZE * EPOCH_LENGTH)
sumCommittees(s) == validators.len() # all validators accounted for sumCommittees(s) == validators.len() # all validators accounted for

View File

@ -12,7 +12,7 @@ import
func makeValidatorPubKey(n: int): ValidatorPubKey = func makeValidatorPubKey(n: int): ValidatorPubKey =
result.point.x.a.g[0] = n result.point.x.a.g[0] = n
func makeInitialValidators*(n = CYCLE_LENGTH): seq[InitialValidator] = func makeInitialValidators*(n = EPOCH_LENGTH): seq[InitialValidator] =
for i in 0..<n: for i in 0..<n:
result.add InitialValidator( result.add InitialValidator(
pubkey: makeValidatorPubKey(i) pubkey: makeValidatorPubKey(i)