From 434ba5727f2ab5b0f6f2d89452968c5c62b39a36 Mon Sep 17 00:00:00 2001 From: Dustin Brody Date: Tue, 12 Mar 2019 09:59:43 +0000 Subject: [PATCH] finish all but 3 items for 0.4.0 spec update (#167) --- beacon_chain/spec/beaconstate.nim | 14 +++++---- beacon_chain/spec/crypto.nim | 6 ++-- beacon_chain/spec/datatypes.nim | 28 ++++++++--------- beacon_chain/spec/helpers.nim | 30 +++++++++--------- beacon_chain/spec/validator.nim | 38 +++++++++++----------- beacon_chain/state_transition.nim | 52 +++++++++++++------------------ 6 files changed, 81 insertions(+), 87 deletions(-) diff --git a/beacon_chain/spec/beaconstate.nim b/beacon_chain/spec/beaconstate.nim index a607f5c96..accf57279 100644 --- a/beacon_chain/spec/beaconstate.nim +++ b/beacon_chain/spec/beaconstate.nim @@ -10,7 +10,7 @@ import ../extras, ../ssz, ./crypto, ./datatypes, ./digest, ./helpers, ./validator -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_effective_balance +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_effective_balance func get_effective_balance*(state: BeaconState, index: ValidatorIndex): uint64 = ## Return the effective balance (also known as "balance at stake") for a ## validator with the given ``index``. @@ -61,10 +61,10 @@ func process_deposit(state: var BeaconState, deposit: Deposit) = state.validator_balances[index] += amount -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_delayed_activation_exit_epoch +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_delayed_activation_exit_epoch func get_delayed_activation_exit_epoch*(epoch: Epoch): Epoch = - ## An entry or exit triggered in the ``epoch`` given by the input takes effect at - ## the epoch given by the output. + ## Return the epoch at which an activation or exit triggered in ``epoch`` + ## takes effect. epoch + 1 + ACTIVATION_EXIT_DELAY # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#activate_validator @@ -242,11 +242,13 @@ func get_genesis_beacon_state*( state # TODO candidate for spec? -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#on-genesis +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#on-genesis func get_initial_beacon_block*(state: BeaconState): BeaconBlock = BeaconBlock( slot: GENESIS_SLOT, state_root: Eth2Digest(data: hash_tree_root(state)) + # parent_root, randao_reveal, eth1_data, signature, and body automatically + # initialized to default values. ) # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_block_root @@ -258,7 +260,7 @@ func get_block_root*(state: BeaconState, doAssert slot < state.slot state.latest_block_roots[slot mod LATEST_BLOCK_ROOTS_LENGTH] -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_attestation_participants +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_attestation_participants func get_attestation_participants*(state: BeaconState, attestation_data: AttestationData, bitfield: seq[byte]): seq[ValidatorIndex] = diff --git a/beacon_chain/spec/crypto.nim b/beacon_chain/spec/crypto.nim index bf4068bd4..7dfbf59b1 100644 --- a/beacon_chain/spec/crypto.nim +++ b/beacon_chain/spec/crypto.nim @@ -68,7 +68,7 @@ template hash*(k: ValidatorPubKey|ValidatorPrivKey): Hash = func pubKey*(pk: ValidatorPrivKey): ValidatorPubKey = pk.getKey() -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/bls_signature.md#bls_aggregate_pubkeys +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/bls_signature.md#bls_aggregate_pubkeys func bls_aggregate_pubkeys*(keys: openArray[ValidatorPubKey]): ValidatorPubKey = var empty = true for key in keys: @@ -78,14 +78,14 @@ func bls_aggregate_pubkeys*(keys: openArray[ValidatorPubKey]): ValidatorPubKey = else: result.combine(key) -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/bls_signature.md#bls_verify +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/bls_signature.md#bls_verify func bls_verify*( pubkey: ValidatorPubKey, msg: openArray[byte], sig: ValidatorSig, domain: uint64): bool = # name from spec! sig.verify(msg, domain, pubkey) -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/bls_signature.md#bls_verify_multiple +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/bls_signature.md#bls_verify_multiple func bls_verify_multiple*( pubkeys: seq[ValidatorPubKey], message_hashes: seq[array[0..31, byte]], sig: ValidatorSig, domain: uint64): bool = diff --git a/beacon_chain/spec/datatypes.nim b/beacon_chain/spec/datatypes.nim index 53e0dff29..68617c326 100644 --- a/beacon_chain/spec/datatypes.nim +++ b/beacon_chain/spec/datatypes.nim @@ -198,7 +198,7 @@ type slashable_attestation_2*: SlashableAttestation ## \ ## Second slashable attestation - # https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#slashableattestation + # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#slashableattestation SlashableAttestation* = object validator_indices*: seq[uint64] ##\ ## Validator indices @@ -212,7 +212,7 @@ type aggregate_signature*: ValidatorSig ## \ ## Aggregate signature - # https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#attestation + # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#attestation Attestation* = object aggregation_bitfield*: seq[byte] ##\ ## Attester aggregation bitfield @@ -257,7 +257,7 @@ type data*: AttestationData custody_bit*: bool - # https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#deposit + # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#deposit Deposit* = object branch*: seq[Eth2Digest] ##\ ## Branch in the deposit tree @@ -268,20 +268,20 @@ type deposit_data*: DepositData ##\ ## Data - # https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#depositdata + # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#depositdata DepositData* = object - amount*: uint64 ## Value in Gwei + amount*: uint64 ## Amount in Gwei timestamp*: uint64 # Timestamp from deposit contract deposit_input*: DepositInput - # https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#depositinput + # https://github.com/ethereum/eth2.0-specs/blob/0.4.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 + ## A BLS signature of this `DepositInput` - # https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#voluntaryexit + # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#voluntaryexit VoluntaryExit* = object # Minimum epoch for processing exit epoch*: uint64 @@ -290,7 +290,7 @@ type # Validator signature signature*: ValidatorSig - # https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#transfer + # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#transfer Transfer* = object from_field*: uint64 ##\ ## Sender index @@ -373,7 +373,7 @@ type signature*: ValidatorSig ##\ ## Signature - # https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#beaconstate + # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#beaconstate BeaconState* = object slot*: uint64 genesis_time*: uint64 @@ -464,13 +464,13 @@ type custody_bitfield*: seq[byte] # Custody bitfield inclusion_slot*: uint64 # Inclusion slot - # https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#fork + # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#fork Fork* = object previous_version*: uint64 # Previous fork version current_version*: uint64 # Current fork version epoch*: uint64 # Fork epoch number - # https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#eth1data + # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#eth1data Eth1Data* = object deposit_root*: Eth2Digest ##\ ## Data being voted for @@ -478,7 +478,7 @@ type block_hash*: Eth2Digest ##\ ## Block hash - # https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#eth1datavote + # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#eth1datavote Eth1DataVote* = object eth1_data*: Eth1Data ##\ ## Data being voted for @@ -504,7 +504,7 @@ type # TODO: not in spec CrosslinkCommittee* = tuple[committee: seq[ValidatorIndex], shard: uint64] ShufflingCache* = object - ## https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_shuffling + ## https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_shuffling ## Note: this definition and the next few definitions make heavy use of ## repetitive computing. Production implementations are expected to ## appropriately use caching/memoization to avoid redoing work. diff --git a/beacon_chain/spec/helpers.nim b/beacon_chain/spec/helpers.nim index 50df351fc..6b4ee174f 100644 --- a/beacon_chain/spec/helpers.nim +++ b/beacon_chain/spec/helpers.nim @@ -14,14 +14,14 @@ import ./datatypes, ./digest, sequtils, math func bitSet*(bitfield: var openArray[byte], index: int) = bitfield[index div 8] = bitfield[index div 8] or 1'u8 shl (7 - (index mod 8)) -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_bitfield_bit +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_bitfield_bit func get_bitfield_bit*(bitfield: openarray[byte], i: int): byte = # Extract the bit in ``bitfield`` at position ``i``. - assert 0 <= i div 8, "i: " & $i & " i div 8: " & $(i div 8) - assert i div 8 < bitfield.len, "i: " & $i & " i div 8: " & $(i div 8) + doAssert 0 <= i div 8, "i: " & $i & " i div 8: " & $(i div 8) + doAssert i div 8 < bitfield.len, "i: " & $i & " i div 8: " & $(i div 8) (bitfield[i div 8] shr (7 - (i mod 8))) mod 2 -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#verify_bitfield +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#verify_bitfield func verify_bitfield*(bitfield: openarray[byte], committee_size: int): bool = # Verify ``bitfield`` against the ``committee_size``. if len(bitfield) != (committee_size + 7) div 8: @@ -34,7 +34,7 @@ func verify_bitfield*(bitfield: openarray[byte], committee_size: int): bool = true -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#split +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#split func split*[T](lst: openArray[T], N: Positive): seq[seq[T]] = ## split lst in N pieces, with each piece having `len(lst) div N` or ## `len(lst) div N + 1` pieces @@ -56,7 +56,7 @@ func get_new_recent_block_roots*(old_block_roots: seq[Eth2Digest], func ceil_div8*(v: int): int = (v + 7) div 8 # TODO use a proper bitarray! -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#integer_squareroot +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#integer_squareroot func integer_squareroot*(n: SomeInteger): SomeInteger = ## The largest integer ``x`` such that ``x**2`` is less than ``n``. var @@ -67,7 +67,7 @@ func integer_squareroot*(n: SomeInteger): SomeInteger = y = (x + n div x) div 2 x -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_fork_version +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_fork_version func get_fork_version*(fork: Fork, epoch: Epoch): uint64 = ## Return the fork version of the given ``epoch``. if epoch < fork.epoch: @@ -84,7 +84,7 @@ func get_domain*( # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#is_power_of_two func is_power_of_2*(v: uint64): bool = (v and (v-1)) == 0 -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#merkle_root +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#merkle_root func merkle_root*(values: openArray[Eth2Digest]): Eth2Digest = ## Merkleize ``values`` (where ``len(values)`` is a power of two) and return ## the Merkle root. @@ -128,7 +128,7 @@ func get_epoch_start_slot*(epoch: Epoch): Slot = # Return the starting slot of the given ``epoch``. epoch * SLOTS_PER_EPOCH -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#is_double_vote +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#is_double_vote func is_double_vote*(attestation_data_1: AttestationData, attestation_data_2: AttestationData): bool = ## Check if ``attestation_data_1`` and ``attestation_data_2`` have the same @@ -150,9 +150,9 @@ func is_surround_vote*(attestation_data_1: AttestationData, source_epoch_1 < source_epoch_2 and target_epoch_2 < target_epoch_1 -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#is_active_validator +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#is_active_validator func is_active_validator*(validator: Validator, epoch: Epoch): bool = - ### Checks if validator is active + ### Check if ``validator`` is active validator.activation_epoch <= epoch and epoch < validator.exit_epoch # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_active_validator_indices @@ -194,15 +194,15 @@ func get_randao_mix*(state: BeaconState, state.latest_randao_mixes[epoch mod LATEST_RANDAO_MIXES_LENGTH] -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_active_index_root +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_active_index_root func get_active_index_root(state: BeaconState, epoch: Epoch): Eth2Digest = # Returns the index root at a recent ``epoch``. ## Cannot underflow, since GENESIS_EPOCH > LATEST_RANDAO_MIXES_LENGTH ## and ACTIVATION_EXIT_DELAY > 0. - assert get_current_epoch(state) - LATEST_ACTIVE_INDEX_ROOTS_LENGTH + + doAssert get_current_epoch(state) - LATEST_ACTIVE_INDEX_ROOTS_LENGTH + ACTIVATION_EXIT_DELAY < epoch - assert epoch <= get_current_epoch(state) + ACTIVATION_EXIT_DELAY + doAssert epoch <= get_current_epoch(state) + ACTIVATION_EXIT_DELAY state.latest_active_index_roots[epoch mod LATEST_ACTIVE_INDEX_ROOTS_LENGTH] # https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#bytes_to_int @@ -214,7 +214,7 @@ func bytes_to_int*(data: seq[byte]): uint64 = for i in countdown(7, 0): result = result * 256 + data[i] -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#int_to_bytes1-int_to_bytes2- +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#int_to_bytes1-int_to_bytes2- # Have 1, 4, and 32-byte versions. 2+ more and maybe worth metaprogramming. func int_to_bytes32*(x: uint64) : array[32, byte] = # Little-endian data representation diff --git a/beacon_chain/spec/validator.nim b/beacon_chain/spec/validator.nim index 56dd8c3bc..0ade06e41 100644 --- a/beacon_chain/spec/validator.nim +++ b/beacon_chain/spec/validator.nim @@ -12,8 +12,8 @@ import ../ssz, ./crypto, ./datatypes, ./digest, ./helpers -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_shuffling -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_permuted_index +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_shuffling +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_permuted_index func get_shuffled_seq*(seed: Eth2Digest, list_size: uint64, ): seq[ValidatorIndex] = @@ -101,9 +101,10 @@ func get_shuffling*(seed: Eth2Digest, result = split(shuffled_seq, committees_per_epoch) assert result.len() == committees_per_epoch # what split should do.. -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_previous_epoch_committee_count +# https://github.com/ethereum/eth2.0-specs/blob/0.4.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``. + ## 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, @@ -124,7 +125,7 @@ func get_previous_epoch*(state: BeaconState): Epoch = ## Return the previous epoch of the given ``state``. max(get_current_epoch(state) - 1, GENESIS_EPOCH) -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_crosslink_committees_at_slot +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_crosslink_committees_at_slot func get_crosslink_committees_at_slot*(state: BeaconState, slot: Slot, registry_change: bool = false): seq[CrosslinkCommittee] = @@ -137,6 +138,8 @@ func get_crosslink_committees_at_slot*(state: BeaconState, slot: Slot, # TODO: the + 1 here works around a bug, remove when upgrading to # some more recent version: # https://github.com/ethereum/eth2.0-specs/pull/732 + # It's not 100% clear to me regarding 0.4.0; waiting until 0.5.0 to remove + # TODO recheck epoch = slot_to_epoch(slot + 1) current_epoch = get_current_epoch(state) previous_epoch = get_previous_epoch(state) @@ -151,27 +154,22 @@ func get_crosslink_committees_at_slot*(state: BeaconState, slot: Slot, "Previous epoch: " & $humaneEpochNum(previous_epoch) & ", epoch: " & $humaneEpochNum(epoch) & ", Next epoch: " & $humaneEpochNum(next_epoch) - # TODO - Hack: used to be "epoch < next_epoch" (exlusive interval) - # until https://github.com/status-im/nim-beacon-chain/issues/97 template get_epoch_specific_params(): auto = - if epoch < current_epoch: - let - ## TODO this might be pointless copying; RVO exists, but not sure if - ## Nim optimizes out both copies per. Could directly construct tuple - ## but this hews closer to spec helper code. - committees_per_epoch = get_previous_epoch_committee_count(state) - seed = state.previous_shuffling_seed - shuffling_epoch = state.previous_shuffling_epoch - shuffling_start_shard = state.previous_shuffling_start_shard - (committees_per_epoch, seed, shuffling_epoch, shuffling_start_shard) - elif epoch == current_epoch: + if epoch == current_epoch: let committees_per_epoch = get_current_epoch_committee_count(state) 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) + seed = state.previous_shuffling_seed + shuffling_epoch = state.previous_shuffling_epoch + shuffling_start_shard = state.previous_shuffling_start_shard + (committees_per_epoch, seed, shuffling_epoch, shuffling_start_shard) else: doAssert epoch == next_epoch @@ -203,6 +201,8 @@ func get_crosslink_committees_at_slot*(state: BeaconState, slot: Slot, seed, state.validator_registry, shuffling_epoch, + + # Not in spec state.shuffling_cache ) offset = slot mod SLOTS_PER_EPOCH @@ -215,7 +215,7 @@ func get_crosslink_committees_at_slot*(state: BeaconState, slot: Slot, (slot_start_shard + i.uint64) mod SHARD_COUNT ) -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#get_beacon_proposer_index +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_beacon_proposer_index func get_beacon_proposer_index*(state: BeaconState, slot: Slot): ValidatorIndex = ## From Casper RPJ mini-spec: ## When slot i begins, validator Vidx is expected diff --git a/beacon_chain/state_transition.nim b/beacon_chain/state_transition.nim index 9f58b9f26..343797858 100644 --- a/beacon_chain/state_transition.nim +++ b/beacon_chain/state_transition.nim @@ -90,7 +90,7 @@ proc processRandao( true -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#eth1-data +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#eth1-data func processDepositRoot(state: var BeaconState, blck: BeaconBlock) = # TODO verify that there's at most one match for x in state.eth1_data_votes.mitems(): @@ -157,7 +157,7 @@ proc processProposerSlashings( true -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#verify_slashable_attestation +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#verify_slashable_attestation func verify_slashable_attestation(state: BeaconState, slashable_attestation: SlashableAttestation): bool = # Verify validity of ``slashable_attestation`` fields. @@ -250,7 +250,7 @@ proc processAttesterSlashings(state: var BeaconState, blck: BeaconBlock): bool = true -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#attestations-1 +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#attestations-1 proc processAttestations( state: var BeaconState, blck: BeaconBlock, flags: UpdateFlags): bool = ## Each block includes a number of attestations that the proposer chose. Each @@ -283,7 +283,7 @@ func processDeposits(state: var BeaconState, blck: BeaconBlock): bool = # TODO! Spec writing in progress as of v0.3.0 true -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#voluntary-exits-1 +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#voluntary-exits-1 proc processExits( state: var BeaconState, blck: BeaconBlock, flags: UpdateFlags): bool = if len(blck.body.voluntary_exits) > MAX_VOLUNTARY_EXITS: @@ -293,7 +293,8 @@ proc processExits( for exit in blck.body.voluntary_exits: let validator = state.validator_registry[exit.validator_index.int] - if not (validator.exit_epoch > get_delayed_activation_exit_epoch(get_current_epoch(state))): + if not (validator.exit_epoch > + get_delayed_activation_exit_epoch(get_current_epoch(state))): notice "Exit: exit/entry too close" return false @@ -302,13 +303,8 @@ proc processExits( return false if skipValidation notin flags: - let exit_message = hash_tree_root( - # In 0.3.0 spec, this is "Exit", but that's a renaming mismatch - VoluntaryExit( - epoch: exit.epoch, validator_index: exit.validator_index, - signature: EMPTY_SIGNATURE)) if not bls_verify( - validator.pubkey, exit_message, exit.signature, + validator.pubkey, signed_root(exit, "signature"), exit.signature, get_domain(state.fork, exit.epoch, DOMAIN_EXIT)): notice "Exit: invalid signature" return false @@ -317,7 +313,7 @@ proc processExits( true -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#transfers-1 +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#transfers-1 proc processTransfers(state: var BeaconState, blck: BeaconBlock, flags: UpdateFlags): bool = ## Note: Transfers are a temporary functionality for phases 0 and 1, to be @@ -369,6 +365,7 @@ proc processTransfers(state: var BeaconState, blck: BeaconBlock, notice "Transfer: incorrect signature" return false + # TODO https://github.com/ethereum/eth2.0-specs/issues/727 reduce_balance( state.validator_balances[transfer.from_field.int], transfer.amount + transfer.fee) @@ -378,7 +375,7 @@ proc processTransfers(state: var BeaconState, blck: BeaconBlock, true -# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#per-slot-processing +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#per-slot-processing func processSlot(state: var BeaconState, previous_block_root: Eth2Digest) = ## Time on the beacon chain moves in slots. Every time we make it to a new ## slot, a proposer creates a block to represent the state of the beacon @@ -388,7 +385,7 @@ func processSlot(state: var BeaconState, previous_block_root: Eth2Digest) = # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#slot state.slot += 1 - # https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#block-roots + # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#block-roots state.latest_block_roots[(state.slot - 1) mod LATEST_BLOCK_ROOTS_LENGTH] = previous_block_root if state.slot mod LATEST_BLOCK_ROOTS_LENGTH == 0: @@ -402,7 +399,7 @@ proc processBlock( # TODO when there's a failure, we should reset the state! # TODO probably better to do all verification first, then apply state changes - # https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#slot-1 + # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#slot-1 if not (blck.slot == state.slot): notice "Unexpected block slot number", blockSlot = humaneSlotNum(blck.slot), @@ -673,7 +670,7 @@ func processEpoch(state: var BeaconState) = ## Regarding inclusion_slot and inclusion_distance, as defined they result in ## O(n^2) behavior, so implement slightly differently. - # https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#eth1-data-1 + # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#eth1-data-1 block: if next_epoch mod EPOCHS_PER_ETH1_VOTING_PERIOD == 0: for x in state.eth1_data_votes: @@ -683,7 +680,7 @@ func processEpoch(state: var BeaconState) = break state.eth1_data_votes = @[] - # https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#justification + # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#justification block: # First, update the justification bitfield var new_justified_epoch = state.justified_epoch @@ -709,7 +706,7 @@ func processEpoch(state: var BeaconState) = state.previous_justified_epoch = state.justified_epoch state.justified_epoch = new_justified_epoch - # https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#crosslinks + # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#crosslinks block: for slot in get_epoch_start_slot(previous_epoch) ..< get_epoch_start_slot(next_epoch): let crosslink_committees_at_slot = get_crosslink_committees_at_slot(state, slot) @@ -721,7 +718,7 @@ func processEpoch(state: var BeaconState) = epoch: slot_to_epoch(slot), crosslink_data_root: winning_root(crosslink_committee)) - # https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#rewards-and-penalties + # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#rewards-and-penalties ## First, we define some additional helpers ## Note: When applying penalties in the following balance recalculations ## implementers should make sure the uint64 does not underflow @@ -733,6 +730,7 @@ func processEpoch(state: var BeaconState) = func inactivity_penalty( state: BeaconState, index: ValidatorIndex, epochs_since_finality: uint64): uint64 = + # TODO Left/right associativity sensitivity on * and div? base_reward(state, index) + get_effective_balance(state, index) * epochs_since_finality div INACTIVITY_PENALTY_QUOTIENT div 2 @@ -830,7 +828,7 @@ func processEpoch(state: var BeaconState) = base_reward(state, index) * MIN_ATTESTATION_INCLUSION_DELAY div inclusion_distance[index]) - # https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#attestation-inclusion + # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#attestation-inclusion block: ## Minimally transform spec algorithm into something non-quadratic, while ## retaining enough resemblance to both verify equivalence and update, if @@ -858,12 +856,6 @@ func processEpoch(state: var BeaconState) = let proposer_index = get_beacon_proposer_index(state, proposer_indexes[v]) - # Ensure this keeps getting compiled to some extent to help compare. - when false: - let proposer_index_slow = - get_beacon_proposer_index(state, inclusion_slot(state, v)) - doAssert proposer_index == proposer_index_slow - state.validator_balances[proposer_index] += base_reward(state, v) div ATTESTATION_INCLUSION_REWARD_QUOTIENT @@ -896,7 +888,7 @@ func processEpoch(state: var BeaconState) = # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#ejections process_ejections(state) - # https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#validator-registry-and-shuffling-seed-data + # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#validator-registry-and-shuffling-seed-data block: state.previous_shuffling_epoch = state.current_shuffling_epoch state.previous_shuffling_start_shard = state.current_shuffling_start_shard @@ -929,6 +921,7 @@ func processEpoch(state: var BeaconState) = state.current_shuffling_seed = generate_seed(state, state.current_shuffling_epoch) # /Note/ that state.current_shuffling_start_shard is left unchanged + # Not in spec. updateShufflingCache(state) ## Regardless of whether or not a validator set change happens run @@ -936,13 +929,12 @@ func processEpoch(state: var BeaconState) = process_slashings(state) process_exit_queue(state) - # https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#final-updates + # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#final-updates block: state.latest_active_index_roots[ (next_epoch + ACTIVATION_EXIT_DELAY) mod LATEST_ACTIVE_INDEX_ROOTS_LENGTH] = Eth2Digest(data: hash_tree_root(get_active_validator_indices( - # TODO 0.3.0 spec here has bug: get_active_validator_indices(state, ...) state.validator_registry, next_epoch + ACTIVATION_EXIT_DELAY))) state.latest_slashed_balances[(next_epoch mod LATEST_SLASHED_EXIT_LENGTH).int] = @@ -954,7 +946,7 @@ func processEpoch(state: var BeaconState) = not (slot_to_epoch(it.data.slot) < current_epoch) ) -# https://github.com/ethereum/eth2.0-specs/blob/v0.3.0/specs/core/0_beacon-chain.md#state-root-verification +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#state-root-verification proc verifyStateRoot(state: BeaconState, blck: BeaconBlock): bool = let state_root = hash_tree_root_final(state) if state_root != blck.state_root: