0.6.2 updates (#275)

* update process_justification_and_finalization to 0.6.2; mark AttesterSlashing as 0.6.2

* replace get_effective_balance(...) with state.validator_registry[idx].effective_balance; rm get_effective_balance, process_ejections, should_update_validator_registry, update_validator_registry, and update_registry_and_shuffling_data; update get_total_balance to 0.6.2; implement process_registry_updates

* rm exit_validator; implement is_slashable_attestation_data; partly update processAttesterSlashings

* mark HistoricalBatch and Eth1Data as 0.6.2; implement get_shard_delta(...); replace 0.5 finish_epoch_update with 0.6 process_final_updates

* mark increase_balance, decrease_balance, get_delayed_activation_exit_epoch, bls_aggregate_pubkeys, bls_verify_multiple, Attestation, Transfer, slot_to_epoch, Crosslink, get_current_epoch, int_to_bytes*, various constants, processEth1Data, processTransfers, and verifyStateRoot as 0.6.2; rm is_double_vote and is_surround_vote

* mark get_bitfield_bit, verify_bitfield, ProposerSlashing, DepositData, VoluntaryExit, PendingAttestation, Fork, integer_squareroot, get_epoch_start_slot, is_active_validator, generate_seed, some constants to 0.6.2; rename MIN_PENALTY_QUOTIENT to MIN_SLASHING_PENALTY_QUOTIENT

* rm get_previous_total_balance, get_current_epoch_boundary_attestations, get_previous_epoch_boundary_attestations, and get_previous_epoch_matching_head_attestations

* update BeaconState to 0.6.2; simplify legacy get_crosslink_committees_at_slot infrastructure a bit by noting that registry_change is always false; reimplment 0.5 get_crosslink_committees_at_slot in terms of 0.6 get_crosslink_committee

* mark process_deposit(...), get_block_root_at_slot(...), get_block_root(...), Deposit, BeaconBlockHeader, BeaconBlockBody, hash(...), get_active_index_root(...), various constants, get_shard_delta(...), get_epoch_start_shard(...), get_crosslink_committee(...), processRandao(...), processVoluntaryExits(...), cacheState(...) as 0.6.2

* rm removed-since-0.5 split(...), is_power_of_2(...), get_shuffling(...); rm 0.5 versions of get_active_validator_indices and get_epoch_committee_count; add a few tests for integer_squareroot

* mark bytes_to_int(...) and advanceState(...) as 0.6.2

* rm 0.5 get_attesting_indices; update get_attesting_balance to 0.6.2

* another tiny commit to poke AppVeyor to maybe not timeout at connecting to GitHub partway through CI: mark get_churn_limit(...), initiate_validator_exit(...), and Validator as 0.6.2

* mark get_attestation_slot(...), AttestationDataAndCustodyBit, and BeaconBlock as 0.6.2
This commit is contained in:
Dustin Brody 2019-06-03 10:31:04 +00:00 committed by GitHub
parent 16fb9e8d11
commit 2e1515b107
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 304 additions and 553 deletions

View File

@ -39,7 +39,8 @@ proc lmdGhost*(
if get_ancestor(target, blck.slot) == blck:
# The div on the balance is to chop off the insignification bits that
# fluctuate a lot epoch to epoch to have a more stable fork choice
res += get_effective_balance(start_state, validator_index) div
res +=
start_state.validator_registry[validator_index].effective_balance div
FORK_CHOICE_BALANCE_INCREMENT
res

View File

@ -6,17 +6,11 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
chronicles, math, options, sequtils,
algorithm, chronicles, math, options, sequtils,
../extras, ../ssz, ../beacon_node_types,
./bitfield, ./crypto, ./datatypes, ./digest, ./helpers, ./validator,
tables
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_effective_balance
func get_effective_balance*(state: BeaconState, index: ValidatorIndex): Gwei =
## Return the effective balance (also known as "balance at stake") for a
## validator with the given ``index``.
min(state.balances[index], MAX_EFFECTIVE_BALANCE)
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#verify_merkle_branch
func verify_merkle_branch(leaf: Eth2Digest, proof: openarray[Eth2Digest], depth: uint64, index: uint64, root: Eth2Digest): bool =
## Verify that the given ``leaf`` is on the merkle branch ``proof``
@ -35,13 +29,13 @@ func verify_merkle_branch(leaf: Eth2Digest, proof: openarray[Eth2Digest], depth:
value = eth2hash(buf)
value == root
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#increase_balance
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/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
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/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.
@ -51,7 +45,7 @@ func decrease_balance*(
else:
state.balances[index] - delta
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#deposits
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/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.
@ -114,13 +108,13 @@ func process_deposit*(
true
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#get_delayed_activation_exit_epoch
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#get_delayed_activation_exit_epoch
func get_delayed_activation_exit_epoch*(epoch: Epoch): Epoch =
## 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/v0.6.1/specs/core/0_beacon-chain.md#get_churn_limit
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#get_churn_limit
func get_churn_limit(state: BeaconState): uint64 =
max(
MIN_PER_EPOCH_CHURN_LIMIT,
@ -128,7 +122,7 @@ func get_churn_limit(state: BeaconState): uint64 =
CHURN_LIMIT_QUOTIENT
).uint64
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#initiate_validator_exit
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#initiate_validator_exit
func initiate_validator_exit*(state: var BeaconState,
index: ValidatorIndex) =
# Initiate the validator of the given ``index``.
@ -139,6 +133,7 @@ func initiate_validator_exit*(state: var BeaconState,
return
# Compute exit queue epoch
# TODO try zero-functional here
let exit_epochs = mapIt(
filterIt(state.validator_registry, it.exit_epoch != FAR_FUTURE_EPOCH),
it.exit_epoch)
@ -158,23 +153,6 @@ func initiate_validator_exit*(state: var BeaconState,
validator.withdrawable_epoch =
validator.exit_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#exit_validator
func exit_validator*(state: var BeaconState,
index: ValidatorIndex) =
## Exit the validator with the given ``index``.
## Note that this function mutates ``state``.
let
validator = addr state.validator_registry[index]
delayed_activation_exit_epoch =
get_delayed_activation_exit_epoch(get_current_epoch(state))
# The following updates only occur if not previous exited
if validator.exit_epoch <= delayed_activation_exit_epoch:
return
validator.exit_epoch = delayed_activation_exit_epoch
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#slash_validator
func slash_validator*(state: var BeaconState, slashed_index: ValidatorIndex) =
# Slash the validator with index ``index``.
@ -247,18 +225,10 @@ func get_genesis_beacon_state*(
epoch: GENESIS_EPOCH,
),
validator_registry_update_epoch: GENESIS_EPOCH,
# validator_registry and balances automatically initalized
# Randomness and committees
# latest_randao_mixes automatically initialized
previous_shuffling_start_shard: GENESIS_START_SHARD,
current_shuffling_start_shard: GENESIS_START_SHARD,
previous_shuffling_epoch: GENESIS_EPOCH,
current_shuffling_epoch: GENESIS_EPOCH,
previous_shuffling_seed: ZERO_HASH,
current_shuffling_seed: ZERO_HASH,
# Finality
# previous_epoch_attestations and current_epoch_attestations automatically
@ -282,7 +252,7 @@ func get_genesis_beacon_state*(
)
for i in 0 ..< SHARD_COUNT:
state.latest_crosslinks[i] = Crosslink(
state.current_crosslinks[i] = Crosslink(
epoch: GENESIS_EPOCH, crosslink_data_root: ZERO_HASH)
# Process genesis deposits
@ -300,7 +270,6 @@ func get_genesis_beacon_state*(
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)
state
@ -314,7 +283,7 @@ func get_initial_beacon_block*(state: BeaconState): BeaconBlock =
# initialized to default values.
)
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#get_attestation_slot
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#get_attestation_slot
func get_attestation_slot*(state: BeaconState,
attestation: Attestation|PendingAttestation,
committee_count: uint64): Slot =
@ -331,7 +300,7 @@ func get_attestation_slot*(state: BeaconState,
get_attestation_slot(
state, attestation, get_epoch_committee_count(state, epoch))
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#get_block_root_at_slot
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#get_block_root_at_slot
func get_block_root_at_slot*(state: BeaconState,
slot: Slot): Eth2Digest =
# Return the block root at a recent ``slot``.
@ -340,7 +309,7 @@ func get_block_root_at_slot*(state: BeaconState,
doAssert slot < state.slot
state.latest_block_roots[slot mod SLOTS_PER_HISTORICAL_ROOT]
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#get_block_root
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#get_block_root
func get_block_root*(state: BeaconState, epoch: Epoch): Eth2Digest =
# Return the block root at a recent ``epoch``.
get_block_root_at_slot(state, get_epoch_start_slot(epoch))
@ -405,7 +374,7 @@ iterator get_attestation_participants_cached*(state: BeaconState,
var found = false
for crosslink_committee in get_crosslink_committees_at_slot_cached(
state, attestation_data.slot, false, cache):
state, attestation_data.slot, cache):
if crosslink_committee.shard == attestation_data.shard:
# TODO this and other attestation-based fields need validation so we don't
# crash on a malicious attestation!
@ -420,75 +389,48 @@ iterator get_attestation_participants_cached*(state: BeaconState,
break
doAssert found, "Couldn't find crosslink committee"
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#ejections
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, get_current_epoch(state)):
if state.balances[index] < EJECTION_BALANCE:
exit_validator(state, index)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_total_balance
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#get_total_balance
func get_total_balance*(state: BeaconState, validators: auto): Gwei =
# Return the combined effective balance of an array of validators.
foldl(validators, a + get_effective_balance(state, b), 0'u64)
# Return the combined effective balance of an array of ``validators``.
foldl(validators, a + state.validator_registry[b].effective_balance, 0'u64)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#validator-registry-and-shuffling-seed-data
func should_update_validator_registry*(state: BeaconState): bool =
# Must have finalized a new block
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_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))
func update_validator_registry*(state: var BeaconState) =
## Update validator registry.
## Note that this function mutates ``state``.
let
current_epoch = get_current_epoch(state)
# The active validators
active_validator_indices =
get_active_validator_indices(state, current_epoch)
# The total effective balance of active validators
total_balance = get_total_balance(state, active_validator_indices)
# The maximum balance churn in Gwei (for deposits and exits separately)
max_balance_churn = max(
MAX_EFFECTIVE_BALANCE,
total_balance div (2 * MAX_BALANCE_CHURN_QUOTIENT)
)
# Activate validators within the allowable balance churn
var balance_churn = 0'u64
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#registry-updates
func process_registry_updates*(state: var BeaconState) =
# Process activation eligibility and ejections
for index, validator in state.validator_registry:
if validator.activation_epoch == FAR_FUTURE_EPOCH and
state.balances[index] >= MAX_EFFECTIVE_BALANCE:
# Check the balance churn would be within the allowance
balance_churn += get_effective_balance(state, index.ValidatorIndex)
if balance_churn > max_balance_churn:
break
# Activate validator
if validator.activation_eligibility_epoch == FAR_FUTURE_EPOCH and
validator.effective_balance >= MAX_EFFECTIVE_BALANCE:
state.validator_registry[index].activation_eligibility_epoch =
get_current_epoch(state)
# Exit validators within the allowable balance churn
balance_churn = 0
if is_active_validator(validator, get_current_epoch(state)) and
validator.effective_balance <= EJECTION_BALANCE:
initiate_validator_exit(state, index.ValidatorIndex)
## Queue validators eligible for activation and not dequeued for activation
## prior to finalized epoch
var activation_queue : seq[tuple[a: Epoch, b: int]] = @[]
for index, validator in state.validator_registry:
if validator.activation_eligibility_epoch != FAR_FUTURE_EPOCH and
validator.activation_epoch >=
get_delayed_activation_exit_epoch(state.finalized_epoch):
activation_queue.add (
state.validator_registry[index].activation_eligibility_epoch, index)
activation_queue.sort(system.cmp)
## Dequeued validators for activation up to churn limit (without resetting
## activation epoch)
let churn_limit = get_churn_limit(state)
for i, epoch_and_index in activation_queue:
if i.uint64 >= churn_limit:
break
let
(epoch, index) = epoch_and_index
validator = addr state.validator_registry[index]
if validator.activation_epoch == FAR_FUTURE_EPOCH:
# Check the balance churn would be within the allowance
balance_churn += get_effective_balance(state, index.ValidatorIndex)
if balance_churn > max_balance_churn:
break
# Exit validator
exit_validator(state, index.ValidatorIndex)
state.validator_registry_update_epoch = current_epoch
validator.activation_epoch =
get_delayed_activation_exit_epoch(get_current_epoch(state))
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.1/specs/core/0_beacon-chain.md#attestations
proc checkAttestation*(
@ -562,11 +504,11 @@ proc checkAttestation*(
epoch: slot_to_epoch(attestation.data.slot)
)
]
if not (state.latest_crosslinks[attestation.data.shard] in
if not (state.current_crosslinks[attestation.data.shard] in
acceptable_crosslink_data):
warn("Unexpected crosslink shard",
state_latest_crosslinks_attestation_data_shard =
state.latest_crosslinks[attestation.data.shard],
state.current_crosslinks[attestation.data.shard],
attestation_data_previous_crosslink = attestation.data.previous_crosslink,
epoch = humaneEpochNum(slot_to_epoch(attestation.data.slot)),
actual_epoch = slot_to_epoch(attestation.data.slot),
@ -658,7 +600,7 @@ proc makeAttestationData*(
beacon_block_root: beacon_block_root,
target_root: target_root,
crosslink_data_root: Eth2Digest(), # Stub in phase0
previous_crosslink: state.latest_crosslinks[shard],
previous_crosslink: state.current_crosslinks[shard],
source_epoch: state.current_justified_epoch,
source_root: state.current_justified_root,
target_epoch: slot_to_epoch(epoch_start_slot)

View File

@ -17,14 +17,14 @@ func init*(T: type BitField, bits: int): BitField =
#proc readValue*(r: var JsonReader, a: var BitField) {.inline.} =
# a.bits = r.readValue(string).hexToSeqByte()
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#get_bitfield_bit
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#get_bitfield_bit
func get_bitfield_bit*(bitfield: BitField, i: int): bool =
# Extract the bit in ``bitfield`` at position ``i``.
doAssert 0 <= i div 8, "i: " & $i & " i div 8: " & $(i div 8)
doAssert i div 8 < bitfield.bits.len, "i: " & $i & " i div 8: " & $(i div 8)
((bitfield.bits[i div 8] shr (i mod 8)) mod 2) > 0'u8
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#verify_bitfield
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#verify_bitfield
func verify_bitfield*(bitfield: BitField, committee_size: int): bool =
# Verify ``bitfield`` against the ``committee_size``.
if len(bitfield.bits) != (committee_size + 7) div 8:

View File

@ -69,7 +69,7 @@ template hash*(k: ValidatorPubKey|ValidatorPrivKey): Hash =
func pubKey*(pk: ValidatorPrivKey): ValidatorPubKey = pk.getKey()
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/bls_signature.md#bls_aggregate_pubkeys
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/bls_signature.md#bls_aggregate_pubkeys
func bls_aggregate_pubkeys*(keys: openArray[ValidatorPubKey]): ValidatorPubKey =
var empty = true
for key in keys:
@ -79,14 +79,14 @@ func bls_aggregate_pubkeys*(keys: openArray[ValidatorPubKey]): ValidatorPubKey =
else:
result.combine(key)
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/bls_signature.md#bls_verify
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/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.6.0/specs/bls_signature.md#bls_verify_multiple
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/bls_signature.md#bls_verify_multiple
func bls_verify_multiple*(
pubkeys: seq[ValidatorPubKey], message_hashes: openArray[Eth2Digest],
sig: ValidatorSig, domain: uint64): bool =

View File

@ -40,7 +40,7 @@ import
# Constant presets
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/configs/constant_presets/
# https://github.com/ethereum/eth2.0-specs/tree/v0.6.2/configs/constant_presets/
const const_preset*{.strdefine.} = "mainnet"
when const_preset == "mainnet":
@ -53,17 +53,10 @@ else:
{.fatal: "Preset \"" & const_preset ".nim\" is not supported.".}
const
SPEC_VERSION* = "0.6.1" ## \
SPEC_VERSION* = "0.6.2" ## \
## Spec version we're aiming to be compatible with, right now
## TODO: improve this scheme once we can negotiate versions in protocol
# Misc
# ---------------------------------------------------------------
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#misc
# TODO remove, not in post-0.5.1
MAX_BALANCE_CHURN_QUOTIENT* = 2^5 ##\
# Gwei values
# ---------------------------------------------------------------
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#gwei-values
@ -86,7 +79,7 @@ type
Shard* = uint64
Gwei* = uint64
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#proposerslashing
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#proposerslashing
ProposerSlashing* = object
proposer_index*: uint64 ##\
## Proposer index
@ -97,7 +90,7 @@ type
header_2*: BeaconBlockHeader ##\
# Second block header
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#attesterslashing
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#attesterslashing
AttesterSlashing* = object
attestation_1*: IndexedAttestation ## \
## First attestation
@ -118,7 +111,7 @@ type
aggregate_signature*: ValidatorSig ## \
## Aggregate signature
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#attestation
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#attestation
Attestation* = object
aggregation_bitfield*: BitField ##\
## Attester aggregation bitfield
@ -149,12 +142,12 @@ type
previous_crosslink*: Crosslink
crosslink_data_root*: Eth2Digest
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#attestationdataandcustodybit
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#attestationdataandcustodybit
AttestationDataAndCustodyBit* = object
data*: AttestationData
custody_bit*: bool
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#deposit
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#deposit
Deposit* = object
proof*: array[DEPOSIT_CONTRACT_TREE_DEPTH, Eth2Digest] ##\
## Branch in the deposit tree
@ -165,7 +158,7 @@ type
data*: DepositData ##\
## Data
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#depositdata
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#depositdata
DepositData* = object
pubkey*: ValidatorPubKey ##\
## BLS pubkey
@ -181,7 +174,7 @@ type
signature*: ValidatorSig ##\
## Container self-signature
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#voluntaryexit
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#voluntaryexit
VoluntaryExit* = object
# Minimum epoch for processing exit
epoch*: Epoch
@ -190,7 +183,7 @@ type
# Validator signature
signature*: ValidatorSig
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#transfer
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#transfer
Transfer* = object
sender*: uint64 ##\
## Sender index
@ -213,7 +206,7 @@ type
signature*: ValidatorSig ##\
## Sender signature
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#beaconblock
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#beaconblock
BeaconBlock* = object
## For each slot, a proposer is chosen from the validator pool to propose
## a new block. Once the block as been proposed, it is transmitted to
@ -234,7 +227,7 @@ type
signature*: ValidatorSig ##\
## Proposer signature
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#beaconblockheader
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#beaconblockheader
BeaconBlockHeader* = object
slot*: Slot
previous_block_root*: Eth2Digest
@ -257,7 +250,7 @@ type
signature*: ValidatorSig
body*: Eth2Digest
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#beaconblockbody
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#beaconblockbody
BeaconBlockBody* = object
randao_reveal*: ValidatorSig
eth1_data*: Eth1Data
@ -269,7 +262,7 @@ type
voluntary_exits*: seq[VoluntaryExit]
transfers*: seq[Transfer]
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.1/specs/core/0_beacon-chain.md#beaconstate
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#beaconstate
BeaconState* = object
slot*: Slot
genesis_time*: uint64
@ -281,17 +274,9 @@ type
balances*: seq[uint64] ##\
## Validator balances in Gwei!
validator_registry_update_epoch*: Epoch
# Randomness and committees
latest_randao_mixes*: array[LATEST_RANDAO_MIXES_LENGTH, Eth2Digest]
latest_start_shard*: Shard
previous_shuffling_start_shard*: uint64
current_shuffling_start_shard*: uint64
previous_shuffling_epoch*: Epoch
current_shuffling_epoch*: Epoch
previous_shuffling_seed*: Eth2Digest
current_shuffling_seed*: Eth2Digest
# Finality
previous_epoch_attestations*: seq[PendingAttestation]
@ -305,7 +290,8 @@ type
finalized_root*: Eth2Digest
# Recent state
latest_crosslinks*: array[SHARD_COUNT, Crosslink]
current_crosslinks*: array[SHARD_COUNT, Crosslink]
previous_crosslinks*: array[SHARD_COUNT, Crosslink]
latest_block_roots*: array[SLOTS_PER_HISTORICAL_ROOT, Eth2Digest] ##\
## Needed to process attestations, older to newer
latest_state_roots*: array[SLOTS_PER_HISTORICAL_ROOT, Eth2Digest]
@ -323,7 +309,7 @@ type
eth1_data_votes*: seq[Eth1Data]
deposit_index*: uint64
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#validator
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#validator
Validator* = object
pubkey*: ValidatorPubKey ##\
## BLS public key
@ -349,7 +335,7 @@ type
effective_balance*: uint64 ##\
## Effective balance
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#crosslink
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#crosslink
Crosslink* = object
epoch*: Epoch ##\
## Epoch number
@ -360,18 +346,14 @@ type
crosslink_data_root*: Eth2Digest ##\
## Shard data since the previous crosslink
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#pendingattestation
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#pendingattestation
PendingAttestation* = object
aggregation_bitfield*: BitField ## Attester participation bitfield
data*: AttestationData ## Attestation data
# TODO remove
inclusion_slot*: Slot ## Inclusion slot
inclusion_delay*: uint64 ## Inclusion delay
proposer_index*: ValidatorIndex ## Proposer index
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#historicalbatch
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#historicalbatch
HistoricalBatch* = object
block_roots* : array[SLOTS_PER_HISTORICAL_ROOT, Eth2Digest] ##\
## Block roots
@ -379,7 +361,7 @@ type
state_roots* : array[SLOTS_PER_HISTORICAL_ROOT, Eth2Digest] ##\
## State roots
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#fork
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#fork
Fork* = object
previous_version*: array[4, byte] ##\
## Previous fork version
@ -390,10 +372,10 @@ type
epoch*: Epoch ##\
## Fork epoch number
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#eth1data
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#eth1data
Eth1Data* = object
deposit_root*: Eth2Digest ##\
## Data being voted for
## Root of the deposit tree
deposit_count*: uint64 ##\
## Total number of deposits

View File

@ -7,7 +7,7 @@
# Serenity hash function / digest
#
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#hash
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#hash
#
# In Phase 0 the beacon chain is deployed with SHA256 (SHA2-256).
# Note that is is different from Keccak256 (often mistakenly called SHA3-256)

View File

@ -9,18 +9,10 @@
import ./datatypes, ./digest, sequtils, math
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.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
# TODO: implement as an iterator
result = newSeq[seq[T]](N)
for i in 0 ..< N:
result[i] = lst[lst.len * i div N ..< lst.len * (i+1) div N] # TODO: avoid alloc via toOpenArray
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#integer_squareroot
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/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``.
## The largest integer ``x`` such that ``x**2`` is less than or equal to
## ``n``.
doAssert n >= 0'u64
var
@ -31,9 +23,6 @@ func integer_squareroot*(n: SomeInteger): SomeInteger =
y = (x + n div x) div 2
x
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#is_power_of_two
func is_power_of_2*(v: uint64): bool = (v > 0'u64) and (v and (v-1)) == 0
# TODO reuse as necessary/useful for merkle proof building
func merkle_root*(values: openArray[Eth2Digest]): Eth2Digest =
## Merkleize ``values`` (where ``len(values)`` is a power of two) and return
@ -69,52 +58,22 @@ func merkle_root*(values: openArray[Eth2Digest]): Eth2Digest =
o[1]
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#slot_to_epoch
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#slot_to_epoch
func slot_to_epoch*(slot: Slot|uint64): Epoch =
# Return the epoch number of the given ``slot``.
(slot div SLOTS_PER_EPOCH).Epoch
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#get_epoch_start_slot
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#get_epoch_start_slot
func get_epoch_start_slot*(epoch: Epoch): Slot =
# Return the starting slot of the given ``epoch``.
(epoch * SLOTS_PER_EPOCH).Slot
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.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
## target.
let
target_epoch_1 = slot_to_epoch(attestation_data_1.slot)
target_epoch_2 = slot_to_epoch(attestation_data_2.slot)
target_epoch_1 == target_epoch_2
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#is_surround_vote
func is_surround_vote*(attestation_data_1: AttestationData,
attestation_data_2: AttestationData): bool =
## Check if ``attestation_data_1`` surrounds ``attestation_data_2``.
let
source_epoch_1 = attestation_data_1.source_epoch
source_epoch_2 = attestation_data_2.source_epoch
target_epoch_1 = slot_to_epoch(attestation_data_1.slot)
target_epoch_2 = slot_to_epoch(attestation_data_2.slot)
source_epoch_1 < source_epoch_2 and target_epoch_2 < target_epoch_1
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#state-list-lengths
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#is_active_validator
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.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
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/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
@ -122,16 +81,6 @@ func get_active_validator_indices*(state: BeaconState, epoch: Epoch):
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
# 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(
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.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``.
@ -140,7 +89,7 @@ func get_epoch_committee_count*(state: BeaconState, epoch: Epoch): uint64 =
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
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#get_current_epoch
func get_current_epoch*(state: BeaconState): Epoch =
# Return the current epoch of the given ``state``.
doAssert state.slot >= GENESIS_SLOT, $state.slot
@ -155,14 +104,16 @@ func get_randao_mix*(state: BeaconState,
## current_epoch + ACTIVATION_EXIT_DELAY].
state.latest_randao_mixes[epoch mod LATEST_RANDAO_MIXES_LENGTH]
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#get_active_index_root
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/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``.
## ``epoch`` expected to be between
## (current_epoch - LATEST_ACTIVE_INDEX_ROOTS_LENGTH + ACTIVATION_EXIT_DELAY, current_epoch + ACTIVATION_EXIT_DELAY].
## TODO maybe assert this, but omission of such seems conspicuously
## intentional
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
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#bytes_to_int
func bytes_to_int*(data: openarray[byte]): uint64 =
doAssert data.len == 8
@ -171,7 +122,7 @@ func bytes_to_int*(data: openarray[byte]): uint64 =
for i in countdown(7, 0):
result = result * 256 + data[i]
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#int_to_bytes1-int_to_bytes2-
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#int_to_bytes1-int_to_bytes2-
# Have 1, 4, 8, and 32-byte versions. 1+ more and maybe worth metaprogramming.
func int_to_bytes32*(x: uint64): array[32, byte] =
## Little-endian data representation
@ -220,12 +171,15 @@ func get_domain*(
func get_domain*(state: BeaconState, domain_type: SignatureDomain): uint64 =
get_domain(state, domain_type, get_current_epoch(state))
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#generate_seed
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#generate_seed
func generate_seed*(state: BeaconState, epoch: Epoch): Eth2Digest =
# Generate a seed for the given ``epoch``.
var seed_input : array[32*3, byte]
# Detect potential underflow
doAssert LATEST_RANDAO_MIXES_LENGTH >= MIN_SEED_LOOKAHEAD
seed_input[0..31] =
get_randao_mix(state,
epoch + LATEST_RANDAO_MIXES_LENGTH - MIN_SEED_LOOKAHEAD).data

View File

@ -57,7 +57,7 @@ const
# Deposit contract
# ---------------------------------------------------------------
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#deposit-contract
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#deposit-contract
DEPOSIT_CONTRACT_ADDRESS = "0x1234567890123456789012345678901234567890"
# TODO
@ -66,7 +66,7 @@ const
# Gwei values
# ---------------------------------------------------------------
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#gwei-values
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#gwei-values
MIN_DEPOSIT_AMOUNT* = 2'u64^0 * 10'u64^9 ##\
## Minimum amounth of ETH that can be deposited in one call - deposits can
@ -141,23 +141,23 @@ const
# State list lengths
# ---------------------------------------------------------------
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#state-list-lengths
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#state-list-lengths
LATEST_RANDAO_MIXES_LENGTH* = 8192
LATEST_ACTIVE_INDEX_ROOTS_LENGTH* = 8192 # 2'u64^13, epochs
LATEST_SLASHED_EXIT_LENGTH* = 8192 # epochs
# Reward and penalty quotients
# ---------------------------------------------------------------
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#reward-and-penalty-quotients
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#reward-and-penalty-quotients
BASE_REWARD_QUOTIENT* = 2'u64^5
WHISTLEBLOWING_REWARD_QUOTIENT* = 2'u64^9
PROPOSER_REWARD_QUOTIENT* = 2'u64^3
INACTIVITY_PENALTY_QUOTIENT* = 2'u64^25
MIN_PENALTY_QUOTIENT* = 32 # 2^5
MIN_SLASHING_PENALTY_QUOTIENT* = 32 # 2^5
# Max operations per block
# ---------------------------------------------------------------
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#max-operations-per-block
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#max-operations-per-block
MAX_PROPOSER_SLASHINGS* = 2^4
MAX_ATTESTER_SLASHINGS* = 2^0
MAX_ATTESTATIONS* = 2^7
@ -168,7 +168,7 @@ const
type
# Signature domains
# ---------------------------------------------------------------
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#signature-domains
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#signature-domains
SignatureDomain* {.pure.} = enum
DOMAIN_BEACON_PROPOSER = 0
DOMAIN_RANDAO = 1

View File

@ -22,7 +22,7 @@ type
{.experimental: "codeReordering".} # SLOTS_PER_EPOCH is use before being defined in spec
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/configs/constant_presets/minimal.yaml
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/configs/constant_presets/minimal.yaml
const
# Misc
# ---------------------------------------------------------------
@ -43,7 +43,7 @@ const
# Deposit contract
# ---------------------------------------------------------------
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#deposit-contract
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#deposit-contract
# Unchanged
DEPOSIT_CONTRACT_ADDRESS = "0x1234567890123456789012345678901234567890"
@ -51,7 +51,7 @@ const
# Gwei values
# ---------------------------------------------------------------
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#gwei-values
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#gwei-values
# Unchanged
MIN_DEPOSIT_AMOUNT* = 2'u64^0 * 10'u64^9
@ -71,10 +71,13 @@ const
# Time parameters
# ---------------------------------------------------------------
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_fork-choice.md#time-parameters
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_fork-choice.md#time-parameters
# Unchanged
SECONDS_PER_SLOT*{.intdefine.} = 6'u64
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#time-parameters
# Unchanged
MIN_ATTESTATION_INCLUSION_DELAY* = 2'u64^2
# Changed
@ -96,7 +99,7 @@ const
# State list lengths
# ---------------------------------------------------------------
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#state-list-lengths
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#state-list-lengths
# Changed
LATEST_RANDAO_MIXES_LENGTH* = 64
@ -105,18 +108,18 @@ const
# Reward and penalty quotients
# ---------------------------------------------------------------
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#reward-and-penalty-quotients
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#reward-and-penalty-quotients
# Unchanged
BASE_REWARD_QUOTIENT* = 2'u64^5
WHISTLEBLOWING_REWARD_QUOTIENT* = 2'u64^9
PROPOSER_REWARD_QUOTIENT* = 2'u64^3
INACTIVITY_PENALTY_QUOTIENT* = 2'u64^25
MIN_PENALTY_QUOTIENT* = 32 # 2^5
MIN_SLASHING_PENALTY_QUOTIENT* = 32 # 2^5
# Max operations per block
# ---------------------------------------------------------------
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#max-operations-per-block
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#max-operations-per-block
# Unchanged
MAX_PROPOSER_SLASHINGS* = 2^4
@ -129,7 +132,7 @@ const
type
# Signature domains
# ---------------------------------------------------------------
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#signature-domains
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#signature-domains
SignatureDomain* {.pure.} = enum
DOMAIN_BEACON_PROPOSER = 0
DOMAIN_RANDAO = 1

View File

@ -118,26 +118,6 @@ func get_shuffled_index(index: ValidatorIndex, index_count: uint64, seed: Eth2Di
if bit != 0:
result = flip
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.1/specs/core/0_beacon-chain.md#get_shuffling
func get_shuffling*(seed: Eth2Digest,
validators: openArray[Validator],
epoch: Epoch,
): seq[seq[ValidatorIndex]] =
## This function is factored to facilitate testing with
## https://github.com/ethereum/eth2.0-test-generators/tree/master/permutated_index
## test vectors, which the split of get_shuffling obfuscates.
let
active_validator_indices = get_active_validator_indices(validators, epoch)
list_size = active_validator_indices.len.uint64
committees_per_epoch = get_epoch_committee_count(
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.6.1/specs/core/0_beacon-chain.md#get_previous_epoch
func get_previous_epoch*(state: BeaconState): Epoch =
## Return the previous epoch of the given ``state``.
@ -148,114 +128,14 @@ func get_previous_epoch*(state: BeaconState): Epoch =
else:
current_epoch
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_crosslink_committees_at_slot
func get_crosslink_committees_at_slot*(state: BeaconState, slot: Slot|uint64,
registry_change: bool = false):
seq[CrosslinkCommittee] =
## Returns the list of ``(committee, shard)`` tuples for the ``slot``.
##
## Note: There are two possible shufflings for crosslink committees for a
## ``slot`` in the next epoch -- with and without a `registry_change`
let
epoch = slot_to_epoch(slot) # TODO, enforce slot to be a Slot
current_epoch = get_current_epoch(state)
previous_epoch = get_previous_epoch(state)
next_epoch = current_epoch + 1
doAssert previous_epoch <= epoch,
"Previous epoch: " & $humaneEpochNum(previous_epoch) &
", epoch: " & $humaneEpochNum(epoch) &
" (slot: " & $humaneSlotNum(slot.Slot) & ")" &
", Next epoch: " & $humaneEpochNum(next_epoch)
doAssert epoch <= next_epoch,
"Previous epoch: " & $humaneEpochNum(previous_epoch) &
", epoch: " & $humaneEpochNum(epoch) &
" (slot: " & $humaneSlotNum(slot.Slot) & ")" &
", Next epoch: " & $humaneEpochNum(next_epoch)
template get_epoch_specific_params(): auto =
if epoch == current_epoch:
let
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_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
(committees_per_epoch, seed, shuffling_epoch, shuffling_start_shard)
else:
doAssert epoch == next_epoch
let
shuffling_epoch = next_epoch
epochs_since_last_registry_update =
current_epoch - state.validator_registry_update_epoch
condition = epochs_since_last_registry_update > 1'u64 and
is_power_of_2(epochs_since_last_registry_update)
use_next = registry_change or condition
committees_per_epoch =
if use_next:
get_epoch_committee_count(state, next_epoch)
else:
get_epoch_committee_count(state, current_epoch)
seed =
if use_next:
generate_seed(state, next_epoch)
else:
state.current_shuffling_seed
shuffling_epoch =
if use_next: next_epoch else: state.current_shuffling_epoch
shuffling_start_shard =
if registry_change:
(state.current_shuffling_start_shard +
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)
let (committees_per_epoch, seed, shuffling_epoch, shuffling_start_shard) =
get_epoch_specific_params()
let
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
for i in 0 ..< committees_per_slot.int:
result.add (
shuffling[(committees_per_slot * offset + i.uint64).int],
(slot_start_shard + i.uint64) mod SHARD_COUNT
)
iterator get_crosslink_committees_at_slot_cached*(
state: BeaconState, slot: Slot|uint64,
registry_change: bool = false, cache: var StateCache):
CrosslinkCommittee =
let key = (slot.uint64, registry_change)
if key in cache.crosslink_committee_cache:
for v in cache.crosslink_committee_cache[key]: yield v
#debugEcho "get_crosslink_committees_at_slot_cached: MISS"
let result = get_crosslink_committees_at_slot(state, slot, registry_change)
cache.crosslink_committee_cache[key] = result
for v in result: yield v
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#get_shard_delta
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#get_shard_delta
func get_shard_delta(state: BeaconState, epoch: Epoch): uint64 =
## Return the number of shards to increment ``state.latest_start_shard``
## during ``epoch``.
min(get_epoch_committee_count(state, epoch),
(SHARD_COUNT - SHARD_COUNT div SLOTS_PER_EPOCH).uint64)
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#get_epoch_start_shard
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#get_epoch_start_shard
func get_epoch_start_shard*(state: BeaconState, epoch: Epoch): Shard =
doAssert epoch <= get_current_epoch(state) + 1
var
@ -281,7 +161,7 @@ func compute_committee(indices: seq[ValidatorIndex], seed: Eth2Digest,
indices[
get_shuffled_index(it.ValidatorIndex, len(indices).uint64, seed).int])
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#get_crosslink_committee
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#get_crosslink_committee
func get_crosslink_committee*(state: BeaconState, epoch: Epoch, shard: Shard):
seq[ValidatorIndex] =
compute_committee(
@ -291,6 +171,47 @@ func get_crosslink_committee*(state: BeaconState, epoch: Epoch, shard: Shard):
get_epoch_committee_count(state, epoch),
)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_crosslink_committees_at_slot
func get_crosslink_committees_at_slot*(state: BeaconState, slot: Slot|uint64):
seq[CrosslinkCommittee] =
## Returns the list of ``(committee, shard)`` tuples for the ``slot``.
let
epoch = slot_to_epoch(slot) # TODO, enforce slot to be a Slot
current_epoch = get_current_epoch(state)
previous_epoch = get_previous_epoch(state)
next_epoch = current_epoch + 1
doAssert previous_epoch <= epoch,
"Previous epoch: " & $humaneEpochNum(previous_epoch) &
", epoch: " & $humaneEpochNum(epoch) &
" (slot: " & $humaneSlotNum(slot.Slot) & ")" &
", Next epoch: " & $humaneEpochNum(next_epoch)
doAssert epoch <= next_epoch,
"Previous epoch: " & $humaneEpochNum(previous_epoch) &
", epoch: " & $humaneEpochNum(epoch) &
" (slot: " & $humaneSlotNum(slot.Slot) & ")" &
", Next epoch: " & $humaneEpochNum(next_epoch)
for i in 0'u64 ..< get_epoch_committee_count(state, epoch):
let shard = i mod SHARD_COUNT
result.add (
get_crosslink_committee(state, epoch, shard),
shard
)
iterator get_crosslink_committees_at_slot_cached*(
state: BeaconState, slot: Slot|uint64, cache: var StateCache):
CrosslinkCommittee =
let key = (slot_to_epoch(slot).uint64, false)
if key in cache.crosslink_committee_cache:
for v in cache.crosslink_committee_cache[key]: yield v
#debugEcho "get_crosslink_committees_at_slot_cached: MISS"
let result = get_crosslink_committees_at_slot(state, slot)
cache.crosslink_committee_cache[key] = result
for v in result: yield v
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#get_beacon_proposer_index
func get_beacon_proposer_index*(state: BeaconState): ValidatorIndex =
# Return the current beacon proposer index.

View File

@ -263,7 +263,7 @@ proc readValue*(r: var SszReader, result: var auto) =
# ################### Hashing ###################################
# Sample hash_tree_root implementation based on:
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/simple-serialize.md
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/simple-serialize.md
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/test_libs/pyspec/eth2spec/utils/minimal_ssz.py
# TODO Probably wrong - the spec is pretty bare-bones and no test vectors yet

View File

@ -81,7 +81,7 @@ proc processBlockHeader(
true
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#randao
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#randao
proc processRandao(
state: var BeaconState, blck: BeaconBlock, flags: UpdateFlags): bool =
let
@ -94,7 +94,7 @@ proc processRandao(
proposer.pubkey,
hash_tree_root(get_current_epoch(state).uint64).data,
blck.body.randao_reveal,
get_domain(state, DOMAIN_RANDAO, get_current_epoch(state))):
get_domain(state, DOMAIN_RANDAO)):
notice "Randao mismatch", proposer_pubkey = proposer.pubkey,
message = get_current_epoch(state),
@ -113,7 +113,7 @@ proc processRandao(
true
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#eth1-data
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#eth1-data
func processEth1Data(state: var BeaconState, blck: BeaconBlock) =
state.eth1_data_votes.add blck.body.eth1_data
if state.eth1_data_votes.count(blck.body.eth1_data) * 2 >
@ -221,42 +221,49 @@ func verify_slashable_attestation(state: BeaconState, slashable_attestation: Ind
),
)
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#is_slashable_attestation_data
func is_slashable_attestation_data(
data_1: AttestationData, data_2: AttestationData): bool =
## Check if ``data_1`` and ``data_2`` are slashable according to Casper FFG
## rules.
# Double vote
(data_1 != data_2 and data_1.target_epoch == data_2.target_epoch) or
# Surround vote
(data_1.source_epoch < data_2.source_epoch and
data_2.target_epoch < data_1.target_epoch)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#attester-slashings
proc processAttesterSlashings(state: var BeaconState, blck: BeaconBlock): bool =
## Process ``AttesterSlashing`` transaction.
## Note that this function mutates ``state``.
# Process ``AttesterSlashing`` operation.
if len(blck.body.attester_slashings) > MAX_ATTESTER_SLASHINGS:
notice "CaspSlash: too many!"
return false
for attester_slashing in blck.body.attester_slashings:
let
slashable_attestation_1 = attester_slashing.attestation_1
slashable_attestation_2 = attester_slashing.attestation_2
attestation_1 = attester_slashing.attestation_1
attestation_2 = attester_slashing.attestation_2
# Check that the attestations are conflicting
if not (slashable_attestation_1.data != slashable_attestation_2.data):
notice "CaspSlash: invalid data"
return false
if not (
is_double_vote(slashable_attestation_1.data, slashable_attestation_2.data) or
is_surround_vote(slashable_attestation_1.data, slashable_attestation_2.data)):
if not is_slashable_attestation_data(
attestation_1.data, attestation_2.data):
notice "CaspSlash: surround or double vote check failed"
return false
if not verify_slashable_attestation(state, slashable_attestation_1):
if not verify_slashable_attestation(state, attestation_1):
notice "CaspSlash: invalid votes 1"
return false
if not verify_slashable_attestation(state, slashable_attestation_2):
if not verify_slashable_attestation(state, attestation_2):
notice "CaspSlash: invalid votes 2"
return false
var slashed_any = false
let
indices2 = toSet(slashable_attestation_2.validator_indices)
indices2 = toSet(attestation_2.validator_indices)
slashable_indices =
slashable_attestation_1.validator_indices.filterIt(
attestation_1.validator_indices.filterIt(
it in indices2 and not state.validator_registry[it.int].slashed)
if not (len(slashable_indices) >= 1):
@ -301,7 +308,6 @@ proc processAttestations(
let pending_attestation = PendingAttestation(
data: attestation.data,
aggregation_bitfield: attestation.aggregation_bitfield,
inclusion_slot: state.slot,
inclusion_delay: state.slot - attestation_slot,
proposer_index: get_beacon_proposer_index(state),
)
@ -326,7 +332,7 @@ proc processDeposits(state: var BeaconState, blck: BeaconBlock): bool =
true
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#voluntary-exits
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#voluntary-exits
proc processVoluntaryExits(
state: var BeaconState, blck: BeaconBlock, flags: UpdateFlags): bool =
# Process ``VoluntaryExit`` transaction.
@ -354,6 +360,7 @@ proc processVoluntaryExits(
return false
# Verify the validator has been active long enough
# TODO detect underflow
if not (get_current_epoch(state) - validator.activation_epoch >=
PERSISTENT_COMMITTEE_PERIOD):
notice "Exit: not in validator set long enough"
@ -372,40 +379,7 @@ proc processVoluntaryExits(
true
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.1/specs/core/0_beacon-chain.md#validator-registry-and-shuffling-seed-data
func update_registry_and_shuffling_data(state: var BeaconState) =
# First set previous shuffling data to current shuffling data
state.previous_shuffling_epoch = state.current_shuffling_epoch
state.previous_shuffling_start_shard = state.current_shuffling_start_shard
state.previous_shuffling_seed = state.current_shuffling_seed
let
current_epoch = get_current_epoch(state)
next_epoch = current_epoch + 1
# Check if we should update, and if so, update
if should_update_validator_registry(state):
update_validator_registry(state)
# If we update the registry, update the shuffling data and shards as well
state.current_shuffling_epoch = next_epoch
state.current_shuffling_start_shard = (
state.current_shuffling_start_shard +
get_epoch_committee_count(state, current_epoch) mod SHARD_COUNT
) mod SHARD_COUNT
state.current_shuffling_seed =
generate_seed(state, state.current_shuffling_epoch)
else:
## If processing at least one crosslink keeps failing, then reshuffle every
## power of two, but don't update the current_shuffling_start_shard
let epochs_since_last_registry_update =
current_epoch - state.validator_registry_update_epoch
if epochs_since_last_registry_update > 1'u64 and
is_power_of_2(epochs_since_last_registry_update):
state.current_shuffling_epoch = next_epoch
state.current_shuffling_seed =
generate_seed(state, state.current_shuffling_epoch)
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#transfers
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#transfers
proc processTransfers(state: var BeaconState, blck: BeaconBlock,
flags: UpdateFlags): bool =
if not (len(blck.body.transfers) <= MAX_TRANSFERS):
@ -486,7 +460,7 @@ func advance_slot(state: var BeaconState) =
state.slot += 1
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#state-caching
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#state-caching
func cacheState(state: var BeaconState) =
let previous_slot_state_root = hash_tree_root(state)
@ -593,18 +567,8 @@ func get_attesting_indices(state: BeaconState,
if get_bitfield_bit(bitfield, i):
result.incl index
# TODO remove this 0.5ish one when callers disappear
func get_attesting_indices(
state: BeaconState,
attestations: openArray[PendingAttestation]): HashSet[ValidatorIndex] =
# Union of attesters that participated in some attestations
result = initSet[ValidatorIndex]()
for attestation in attestations:
for validator_index in get_attestation_participants(
state, attestation.data, attestation.aggregation_bitfield):
result.incl validator_index
# TODO this cached version corresponds to the 0.5ish get_attesting_indices
# TODO this cached version corresponds to the blob/v0.5.1ish get_attesting_indices
# rm/make consistent with 0.6 version above
func get_attesting_indices_cached(
state: BeaconState,
attestations: openArray[PendingAttestation], cache: var StateCache):
@ -629,15 +593,9 @@ func get_unslashed_attesting_indices(
if state.validator_registry[index].slashed:
result.excl index
# TODO check for blob/v0.5.0 removal
func get_previous_total_balance(state: BeaconState): Gwei =
get_total_balance(
state,
get_active_validator_indices(state, get_previous_epoch(state)))
func get_attesting_balance(state: BeaconState,
attestations: seq[PendingAttestation]): Gwei =
get_total_balance(state, get_attesting_indices(state, attestations))
get_total_balance(state, get_unslashed_attesting_indices(state, attestations))
func get_attesting_balance_cached(
state: BeaconState, attestations: seq[PendingAttestation],
@ -645,26 +603,6 @@ func get_attesting_balance_cached(
get_total_balance(state, get_attesting_indices_cached(
state, attestations, cache))
func get_current_epoch_boundary_attestations(state: BeaconState):
seq[PendingAttestation] =
filterIt(
state.current_epoch_attestations,
it.data.target_root == get_block_root_at_slot(
state, get_epoch_start_slot(get_current_epoch(state))))
func get_previous_epoch_boundary_attestations(state: BeaconState):
seq[PendingAttestation] =
filterIt(
state.previous_epoch_attestations,
it.data.target_root ==
get_block_root_at_slot(state, get_epoch_start_slot(get_previous_epoch(state))))
func get_previous_epoch_matching_head_attestations(state: BeaconState):
seq[PendingAttestation] =
filterIt(
state.previous_epoch_attestations,
it.data.beacon_block_root == get_block_root_at_slot(state, it.data.slot))
# Not exactly in spec, but for get_winning_root_and_participants
func lowerThan(candidate, current: Eth2Digest): bool =
# return true iff candidate is "lower" than current, per spec rule:
@ -683,7 +621,7 @@ func get_winning_root_and_participants(
valid_attestations =
filterIt(
all_attestations,
it.data.previous_crosslink == state.latest_crosslinks[shard])
it.data.previous_crosslink == state.current_crosslinks[shard])
all_roots = mapIt(valid_attestations, it.data.crosslink_data_root)
# handle when no attestations for shard available
@ -720,74 +658,70 @@ func get_winning_root_and_participants(
state,
attestations_for.getOrDefault(winning_root), cache))
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#justification
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#justification-and-finalization
func process_justification_and_finalization(state: var BeaconState) =
var
new_justified_epoch = state.current_justified_epoch
new_finalized_epoch = state.finalized_epoch
if get_current_epoch(state) <= GENESIS_EPOCH + 1:
return
## Rotate the justification bitfield up one epoch to make room for the
## current epoch
state.justification_bitfield = state.justification_bitfield shl 1
# If the previous epoch gets justified, fill the second last bit
let previous_boundary_attesting_balance =
get_attesting_balance(
state, get_previous_epoch_boundary_attestations(state))
if previous_boundary_attesting_balance * 3'u64 >=
get_previous_total_balance(state) * 2'u64:
new_justified_epoch = get_current_epoch(state) - 1
state.justification_bitfield = state.justification_bitfield or 2
# If the current epoch gets justified, fill the last bit
let current_boundary_attesting_balance =
get_attesting_balance(
state, get_current_epoch_boundary_attestations(state))
if current_boundary_attesting_balance * 3'u64 >=
get_total_active_balance(state) * 2'u64:
new_justified_epoch = get_current_epoch(state)
state.justification_bitfield = state.justification_bitfield or 1
# Process finalizations
let
bitfield = state.justification_bitfield
previous_epoch = get_previous_epoch(state)
current_epoch = get_current_epoch(state)
old_previous_justified_epoch = state.previous_justified_epoch
old_current_justified_epoch = state.current_justified_epoch
## The 2nd/3rd/4th most recent epochs are all justified, the 2nd using the
## 4th as source
if (bitfield shr 1) mod 8 == 0b111 and
state.previous_justified_epoch == current_epoch - 3:
new_finalized_epoch = state.previous_justified_epoch
## The 2nd/3rd most recent epochs are both justified, the 2nd using the 3rd
## as source
if (bitfield shr 1) mod 4 == 0b11 and
state.previous_justified_epoch == current_epoch - 2:
new_finalized_epoch = state.previous_justified_epoch
## The 1st/2nd/3rd most recent epochs are all justified, the 1st using the
## 3rd as source
if (bitfield shr 0) mod 8 == 0b111 and
state.current_justified_epoch == current_epoch - 2:
new_finalized_epoch = state.current_justified_epoch
## The 1st/2nd most recent epochs are both justified, the 1st using the 2nd
## as source
if (bitfield shr 0) mod 4 == 0b11 and
state.current_justified_epoch == current_epoch - 1:
new_finalized_epoch = state.current_justified_epoch
# Update state jusification/finality fields
# Process justifications
state.previous_justified_epoch = state.current_justified_epoch
state.previous_justified_root = state.current_justified_root
if new_justified_epoch != state.current_justified_epoch:
state.current_justified_epoch = new_justified_epoch
state.justification_bitfield = (state.justification_bitfield shl 1)
let previous_epoch_matching_target_balance =
get_attesting_balance(state,
get_matching_target_attestations(state, previous_epoch))
if previous_epoch_matching_target_balance * 3 >=
get_total_active_balance(state) * 2:
state.current_justified_epoch = previous_epoch
state.current_justified_root =
get_block_root_at_slot(state, get_epoch_start_slot(new_justified_epoch))
if new_finalized_epoch != state.finalized_epoch:
state.finalized_epoch = new_finalized_epoch
state.finalized_root =
get_block_root_at_slot(state, get_epoch_start_slot(new_finalized_epoch))
get_block_root(state, state.current_justified_epoch)
state.justification_bitfield = state.justification_bitfield or (1 shl 1)
let current_epoch_matching_target_balance =
get_attesting_balance(state,
get_matching_target_attestations(state, current_epoch))
if current_epoch_matching_target_balance * 3 >=
get_total_active_balance(state) * 2:
state.current_justified_epoch = current_epoch
state.current_justified_root =
get_block_root(state, state.current_justified_epoch)
state.justification_bitfield = state.justification_bitfield or (1 shl 0)
# Process finalizations
let bitfield = state.justification_bitfield
## The 2nd/3rd/4th most recent epochs are justified, the 2nd using the 4th
## as source
if (bitfield shr 1) mod 8 == 0b111 and old_previous_justified_epoch ==
current_epoch - 3:
state.finalized_epoch = old_previous_justified_epoch
state.finalized_root = get_block_root(state, state.finalized_epoch)
## The 2nd/3rd most recent epochs are justified, the 2nd using the 3rd as
## source
if (bitfield shr 1) mod 4 == 0b11 and old_previous_justified_epoch ==
current_epoch - 2:
state.finalized_epoch = old_previous_justified_epoch
state.finalized_root = get_block_root(state, state.finalized_epoch)
## The 1st/2nd/3rd most recent epochs are justified, the 1st using the 3rd as
## source
if (bitfield shr 0) mod 8 == 0b111 and old_current_justified_epoch ==
current_epoch - 2:
state.finalized_epoch = old_current_justified_epoch
state.finalized_root = get_block_root(state, state.finalized_epoch)
## The 1st/2nd most recent epochs are justified, the 1st using the 2nd as
## source
if (bitfield shr 0) mod 4 == 0b11 and old_current_justified_epoch ==
current_epoch - 1:
state.finalized_epoch = old_current_justified_epoch
state.finalized_root = get_block_root(state, state.finalized_epoch)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.1/specs/core/0_beacon-chain.md#crosslinks
func process_crosslinks(
@ -797,7 +731,7 @@ func process_crosslinks(
previous_epoch = current_epoch - 1
next_epoch = current_epoch + 1
## TODO is it actually correct to be setting state.latest_crosslinks[shard]
## TODO is it actually correct to be setting state.current_crosslinks[shard]
## to something pre-GENESIS_EPOCH, ever? I guess the intent is if there are
## a quorum of participants for get_epoch_start_slot(previous_epoch), when
## state.slot == GENESIS_SLOT, then there will be participants for a quorum
@ -807,7 +741,7 @@ func process_crosslinks(
GENESIS_SLOT.uint64, get_epoch_start_slot(previous_epoch).uint64) ..<
get_epoch_start_slot(next_epoch).uint64:
for cas in get_crosslink_committees_at_slot_cached(
state, slot, false, per_epoch_cache):
state, slot, per_epoch_cache):
let
(crosslink_committee, shard) = cas
# In general, it'll loop over the same shards twice, and
@ -827,7 +761,7 @@ func process_crosslinks(
# Check not from spec; seems kludgy
doAssert slot >= GENESIS_SLOT
state.latest_crosslinks[shard] = Crosslink(
state.current_crosslinks[shard] = Crosslink(
epoch: slot_to_epoch(slot),
crosslink_data_root: winning_root
)
@ -925,7 +859,7 @@ func get_crosslink_deltas(state: BeaconState, cache: var StateCache):
get_epoch_start_slot(get_current_epoch(state))
for slot in previous_epoch_start_slot.uint64 ..<
current_epoch_start_slot.uint64:
for cas in get_crosslink_committees_at_slot_cached(state, slot, false, cache):
for cas in get_crosslink_committees_at_slot_cached(state, slot, cache):
let
(crosslink_committee, shard) = cas
(winning_root, participants) =
@ -976,25 +910,42 @@ func process_slashings(state: var BeaconState) =
LATEST_SLASHED_EXIT_LENGTH div 2:
let
penalty = max(
get_effective_balance(state, index.ValidatorIndex) *
validator.effective_balance *
min(total_penalties * 3, total_balance) div total_balance,
get_effective_balance(state, index.ValidatorIndex) div
MIN_PENALTY_QUOTIENT)
validator.effective_balance div MIN_SLASHING_PENALTY_QUOTIENT)
decrease_balance(state, index.ValidatorIndex, penalty)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#final-updates
func finish_epoch_update(state: var BeaconState) =
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#get_shard_delta
func get_shard_delta(state: BeaconState, epoch: Epoch): uint64 =
# Return the number of shards to increment ``state.latest_start_shard`` during ``epoch``.
min(get_epoch_committee_count(state, epoch),
(SHARD_COUNT - SHARD_COUNT div SLOTS_PER_EPOCH).uint64)
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#final-updates
func process_final_updates(state: var BeaconState) =
let
current_epoch = get_current_epoch(state)
next_epoch = current_epoch + 1
# Set active index root
let index_root_position =
(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, next_epoch + ACTIVATION_EXIT_DELAY)
)
# Reset eth1 data votes
if (state.slot + 1) mod SLOTS_PER_ETH1_VOTING_PERIOD == 0:
state.eth1_data_votes = @[]
# Update effective balances with hysteresis
for index, validator in state.validator_registry:
let balance = state.balances[index]
const HALF_INCREMENT = EFFECTIVE_BALANCE_INCREMENT div 2
if balance < validator.effective_balance or
validator.effective_balance + 3'u64 * HALF_INCREMENT < balance:
state.validator_registry[index].effective_balance =
min(
balance - balance mod EFFECTIVE_BALANCE_INCREMENT,
MAX_EFFECTIVE_BALANCE)
# Update start shard
state.latest_start_shard =
(state.latest_start_shard + get_shard_delta(state, current_epoch)) mod
SHARD_COUNT
# Set total slashed balances
state.latest_slashed_balances[next_epoch mod LATEST_SLASHED_EXIT_LENGTH] = (
@ -1017,7 +968,7 @@ func finish_epoch_update(state: var BeaconState) =
state.previous_epoch_attestations = state.current_epoch_attestations
state.current_epoch_attestations = @[]
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#per-epoch-processing
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#per-epoch-processing
func get_empty_per_epoch_cache(): StateCache =
result.crosslink_committee_cache =
initTable[tuple[a: uint64, b: bool], seq[CrosslinkCommittee]]()
@ -1034,26 +985,22 @@ func processEpoch(state: var BeaconState) =
var per_epoch_cache = get_empty_per_epoch_cache()
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.1/specs/core/0_beacon-chain.md#crosslinks
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#crosslinks
process_crosslinks(state, per_epoch_cache)
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#rewards-and-penalties
process_rewards_and_penalties(state, per_epoch_cache)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#ejections
process_ejections(state)
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#registry-updates
process_registry_updates(state)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#validator-registry-and-shuffling-seed-data
update_registry_and_shuffling_data(state)
## Regardless of whether or not a validator set change happens run
## process_slashings(state) and process_exit_queue(state)
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#slashings
process_slashings(state)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#final-updates
finish_epoch_update(state)
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#final-updates
process_final_updates(state)
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#state-root-verification
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#state-root-verification
proc verifyStateRoot(state: BeaconState, blck: BeaconBlock): bool =
let state_root = hash_tree_root(state)
if state_root != blck.state_root:
@ -1068,7 +1015,7 @@ proc advanceState*(state: var BeaconState) =
## hand - this happens for example when a block proposer fails to produce a
## a block.
## https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#beacon-chain-state-transition-function
## https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_beacon-chain.md#beacon-chain-state-transition-function
## We now define the state transition function. At a high level the state
## transition is made up of four parts:

View File

@ -14,7 +14,7 @@ type
## which blocks are valid - in particular, blocks are not valid if they
## come from the future as seen from the local clock.
##
## https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_fork-choice.md#beacon-chain-processing
## https://github.com/ethereum/eth2.0-specs/blob/v0.6.2/specs/core/0_fork-choice.md#beacon-chain-processing
##
# TODO replace time in chronos with a proper unit type, then this code can
# follow:

View File

@ -55,7 +55,7 @@ type
WHISTLEBLOWING_REWARD_QUOTIENT*: uint64
PROPOSER_REWARD_QUOTIENT*: uint64
INACTIVITY_PENALTY_QUOTIENT*: uint64
MIN_PENALTY_QUOTIENT*: int
MIN_SLASHING_PENALTY_QUOTIENT*: int
MAX_PROPOSER_SLASHINGS*: int
MAX_ATTESTER_SLASHINGS*: int
MAX_ATTESTATIONS*: int

View File

@ -10,10 +10,11 @@ import
../beacon_chain/spec/[helpers]
suite "Spec helpers":
test "is_power_of_2 should do its job":
test "integer_squareroot":
check:
is_power_of_2(1) == true
is_power_of_2(2) == true
is_power_of_2(3) == false
is_power_of_2(4) == true
is_power_of_2(not 0'u64) == false
integer_squareroot(0'u64) == 0'u64
integer_squareroot(1'u64) == 1'u64
integer_squareroot(2'u64) == 1'u64
integer_squareroot(3'u64) == 1'u64
integer_squareroot(4'u64) == 2'u64
integer_squareroot(5'u64) == 2'u64