begin 0.6.0 (#256)

* begin 0.6.0: new get_domain/increase_balance/reduce_balance, BeaconState.validator_balances -> BeaconState.balances, some renamed constants, transaction processing changes, SlashableAttestation field name changes, 0.6.0 get_beacon_proposer_index always uses given state's slot, update tests subrepo

* mark get_bitfield_bit/bls_verify_multiple/stat-list-lengths/is_active_validator/is_surround_vote/slot_to_epoch/int_to_bytes/etc as unchanged in 0.6.0; rm Eth1DataVote/maybe_reset_eth1_period and thus adjust expected tree hash test results

* mark verify_bitfield/bls_verify/deposit-contract/VoluntaryExit/PendingAttestation/Historicalbatch/Fork as 0.6.0; update DOMAIN_BEACON_BLOCK to DOMAIN_BEACON_PROPOSER

* update Crosslink to 0.6.0 (also requires tree hashing test result change, so isolate in individual commit)

* mark verify_merkle_branch/get_delayed_activation_exit_epoch/ProposerSlashing/Attestation/AttestationDataAndCustodyBit/hash/integer_squareroot/get_epoch_start_slot/is_double_vote/get_randao_mix/generate_seed as 0.6.0; update reward and penalty quotients; SlashableAttestation -> IndexedAttestation; rm get_fork_version; ATTESTATION_INCLUSION_REWARD_QUOTIENT -> PROPOSER_REWARD_QUOTIENT
This commit is contained in:
Dustin Brody 2019-04-29 16:48:30 +00:00 committed by Jacek Sieka
parent 5784b2d7f7
commit 46b4154ce8
18 changed files with 193 additions and 187 deletions

View File

@ -97,8 +97,8 @@ proc validate(
data: attestation.data, custody_bit: true)), data: attestation.data, custody_bit: true)),
], ],
attestation.aggregate_signature, attestation.aggregate_signature,
get_domain(state.fork, slot_to_epoch(attestation.data.slot), get_domain(state, DOMAIN_ATTESTATION,
DOMAIN_ATTESTATION), slot_to_epoch(attestation.data.slot)),
): ):
notice "Invalid signature", participants notice "Invalid signature", participants
return false return false

View File

@ -380,7 +380,7 @@ proc proposeBlock(node: BeaconNode,
# Careful, state no longer valid after here.. # Careful, state no longer valid after here..
newBlock.signature = newBlock.signature =
await validator.signBlockProposal(state.fork, slot, blockRoot) await validator.signBlockProposal(state, slot, blockRoot)
(blockRoot, newBlock) (blockRoot, newBlock)

View File

@ -15,9 +15,9 @@ import
func get_effective_balance*(state: BeaconState, index: ValidatorIndex): Gwei = func get_effective_balance*(state: BeaconState, index: ValidatorIndex): Gwei =
## Return the effective balance (also known as "balance at stake") for a ## Return the effective balance (also known as "balance at stake") for a
## validator with the given ``index``. ## validator with the given ``index``.
min(state.validator_balances[index], MAX_DEPOSIT_AMOUNT) min(state.balances[index], MAX_EFFECTIVE_BALANCE)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#verify_merkle_branch # 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 = 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`` ## Verify that the given ``leaf`` is on the merkle branch ``proof``
## starting with the given ``root``. ## starting with the given ``root``.
@ -106,7 +106,7 @@ func process_deposit*(state: var BeaconState, deposit: Deposit): bool =
## Note: In phase 2 registry indices that have been withdrawn for a long ## Note: In phase 2 registry indices that have been withdrawn for a long
## time will be recycled. ## time will be recycled.
state.validator_registry.add(validator) state.validator_registry.add(validator)
state.validator_balances.add(amount) state.balances.add(amount)
else: else:
# Increase balance by deposit amount # Increase balance by deposit amount
let index = validator_pubkeys.find(pubkey) let index = validator_pubkeys.find(pubkey)
@ -114,11 +114,11 @@ func process_deposit*(state: var BeaconState, deposit: Deposit): bool =
doAssert state.validator_registry[index].withdrawal_credentials == doAssert state.validator_registry[index].withdrawal_credentials ==
withdrawal_credentials withdrawal_credentials
state.validator_balances[index] += amount state.balances[index] += amount
true true
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_delayed_activation_exit_epoch # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#get_delayed_activation_exit_epoch
func get_delayed_activation_exit_epoch*(epoch: Epoch): Epoch = func get_delayed_activation_exit_epoch*(epoch: Epoch): Epoch =
## Return the epoch at which an activation or exit triggered in ``epoch`` ## Return the epoch at which an activation or exit triggered in ``epoch``
## takes effect. ## takes effect.
@ -189,8 +189,8 @@ func slash_validator*(state: var BeaconState, index: ValidatorIndex) =
## TODO here and elsewhere, if reduce_balance can't reduce balance by full ## TODO here and elsewhere, if reduce_balance can't reduce balance by full
## whistleblower_reward (to prevent underflow) should increase be full? It ## whistleblower_reward (to prevent underflow) should increase be full? It
## seems wrong for the amounts to differ. ## seems wrong for the amounts to differ.
state.validator_balances[whistleblower_index] += whistleblower_reward state.balances[whistleblower_index] += whistleblower_reward
reduce_balance(state.validator_balances[index], whistleblower_reward) reduce_balance(state.balances[index], whistleblower_reward)
validator.slashed = true validator.slashed = true
validator.withdrawable_epoch = validator.withdrawable_epoch =
get_current_epoch(state) + LATEST_SLASHED_EXIT_LENGTH get_current_epoch(state) + LATEST_SLASHED_EXIT_LENGTH
@ -246,7 +246,7 @@ func get_genesis_beacon_state*(
validator_registry_update_epoch: GENESIS_EPOCH, validator_registry_update_epoch: GENESIS_EPOCH,
# validator_registry and validator_balances automatically initalized # validator_registry and balances automatically initalized
# Randomness and committees # Randomness and committees
# latest_randao_mixes automatically initialized # latest_randao_mixes automatically initialized
@ -289,7 +289,7 @@ func get_genesis_beacon_state*(
# Process genesis activations # Process genesis activations
for validator_index in 0 ..< state.validator_registry.len: for validator_index in 0 ..< state.validator_registry.len:
let vi = validator_index.ValidatorIndex let vi = validator_index.ValidatorIndex
if get_effective_balance(state, vi) >= MAX_DEPOSIT_AMOUNT: if get_effective_balance(state, vi) >= MAX_EFFECTIVE_BALANCE:
activate_validator(state, vi, true) activate_validator(state, vi, true)
let genesis_active_index_root = hash_tree_root( let genesis_active_index_root = hash_tree_root(
@ -400,7 +400,7 @@ func process_ejections*(state: var BeaconState) =
## balance below ``EJECTION_BALANCE`` ## balance below ``EJECTION_BALANCE``
for index in get_active_validator_indices( for index in get_active_validator_indices(
state.validator_registry, get_current_epoch(state)): state.validator_registry, get_current_epoch(state)):
if state.validator_balances[index] < EJECTION_BALANCE: if state.balances[index] < EJECTION_BALANCE:
exit_validator(state, index) 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.5.0/specs/core/0_beacon-chain.md#get_total_balance
@ -432,7 +432,7 @@ func update_validator_registry*(state: var BeaconState) =
# The maximum balance churn in Gwei (for deposits and exits separately) # The maximum balance churn in Gwei (for deposits and exits separately)
max_balance_churn = max( max_balance_churn = max(
MAX_DEPOSIT_AMOUNT, MAX_EFFECTIVE_BALANCE,
total_balance div (2 * MAX_BALANCE_CHURN_QUOTIENT) total_balance div (2 * MAX_BALANCE_CHURN_QUOTIENT)
) )
@ -440,7 +440,7 @@ func update_validator_registry*(state: var BeaconState) =
var balance_churn = 0'u64 var balance_churn = 0'u64
for index, validator in state.validator_registry: for index, validator in state.validator_registry:
if validator.activation_epoch == FAR_FUTURE_EPOCH and if validator.activation_epoch == FAR_FUTURE_EPOCH and
state.validator_balances[index] >= MAX_DEPOSIT_AMOUNT: state.balances[index] >= MAX_EFFECTIVE_BALANCE:
# Check the balance churn would be within the allowance # Check the balance churn would be within the allowance
balance_churn += get_effective_balance(state, index.ValidatorIndex) balance_churn += get_effective_balance(state, index.ValidatorIndex)
if balance_churn > max_balance_churn: if balance_churn > max_balance_churn:
@ -600,8 +600,8 @@ proc checkAttestation*(
data: attestation.data, custody_bit: true)), data: attestation.data, custody_bit: true)),
], ],
attestation.aggregate_signature, attestation.aggregate_signature,
get_domain(state.fork, slot_to_epoch(attestation.data.slot), get_domain(state, DOMAIN_ATTESTATION,
DOMAIN_ATTESTATION), slot_to_epoch(attestation.data.slot))
): ):
warn("Invalid attestation signature") warn("Invalid attestation signature")
return return
@ -622,6 +622,22 @@ func prepare_validator_for_withdrawal*(state: var BeaconState, index: ValidatorI
validator.withdrawable_epoch = get_current_epoch(state) + validator.withdrawable_epoch = get_current_epoch(state) +
MIN_VALIDATOR_WITHDRAWABILITY_DELAY MIN_VALIDATOR_WITHDRAWABILITY_DELAY
# https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/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
func decrease_balance*(
state: var BeaconState, index: ValidatorIndex, delta: Gwei) =
# Decrease validator balance by ``delta`` with underflow protection.
state.balances[index] =
if delta > state.balances[index]:
0'u64
else:
state.balances[index] - delta
proc makeAttestationData*( proc makeAttestationData*(
state: BeaconState, shard: uint64, state: BeaconState, shard: uint64,
beacon_block_root: Eth2Digest): AttestationData = beacon_block_root: Eth2Digest): AttestationData =

View File

@ -16,14 +16,14 @@ func init*(T: type BitField, bits: int): BitField =
proc readValue*(r: var JsonReader, a: var BitField) {.inline.} = proc readValue*(r: var JsonReader, a: var BitField) {.inline.} =
a.bits = r.readValue(string).hexToSeqByte() a.bits = r.readValue(string).hexToSeqByte()
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_bitfield_bit # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#get_bitfield_bit
func get_bitfield_bit*(bitfield: BitField, i: int): bool = func get_bitfield_bit*(bitfield: BitField, i: int): bool =
# Extract the bit in ``bitfield`` at position ``i``. # Extract the bit in ``bitfield`` at position ``i``.
doAssert 0 <= i div 8, "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.bits.len, "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 ((bitfield.bits[i div 8] shr (i mod 8)) mod 2) > 0'u8
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#verify_bitfield # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#verify_bitfield
func verify_bitfield*(bitfield: BitField, committee_size: int): bool = func verify_bitfield*(bitfield: BitField, committee_size: int): bool =
# Verify ``bitfield`` against the ``committee_size``. # Verify ``bitfield`` against the ``committee_size``.
if len(bitfield.bits) != (committee_size + 7) div 8: 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() func pubKey*(pk: ValidatorPrivKey): ValidatorPubKey = pk.getKey()
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/bls_signature.md#bls_aggregate_pubkeys # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/bls_signature.md#bls_aggregate_pubkeys
func bls_aggregate_pubkeys*(keys: openArray[ValidatorPubKey]): ValidatorPubKey = func bls_aggregate_pubkeys*(keys: openArray[ValidatorPubKey]): ValidatorPubKey =
var empty = true var empty = true
for key in keys: for key in keys:
@ -79,14 +79,14 @@ func bls_aggregate_pubkeys*(keys: openArray[ValidatorPubKey]): ValidatorPubKey =
else: else:
result.combine(key) result.combine(key)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/bls_signature.md#bls_verify # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/bls_signature.md#bls_verify
func bls_verify*( func bls_verify*(
pubkey: ValidatorPubKey, msg: openArray[byte], sig: ValidatorSig, pubkey: ValidatorPubKey, msg: openArray[byte], sig: ValidatorSig,
domain: uint64): bool = domain: uint64): bool =
# name from spec! # name from spec!
sig.verify(msg, domain, pubkey) sig.verify(msg, domain, pubkey)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/bls_signature.md#bls_verify_multiple # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/bls_signature.md#bls_verify_multiple
func bls_verify_multiple*( func bls_verify_multiple*(
pubkeys: seq[ValidatorPubKey], message_hashes: openArray[Eth2Digest], pubkeys: seq[ValidatorPubKey], message_hashes: openArray[Eth2Digest],
sig: ValidatorSig, domain: uint64): bool = sig: ValidatorSig, domain: uint64): bool =

View File

@ -68,19 +68,22 @@ const
## with a Verifiable Delay Function (VDF) will improve committee robustness ## with a Verifiable Delay Function (VDF) will improve committee robustness
## and lower the safe minimum committee size.) ## and lower the safe minimum committee size.)
# TODO remove, not in post-0.5.1
MAX_BALANCE_CHURN_QUOTIENT* = 2^5 ##\ MAX_BALANCE_CHURN_QUOTIENT* = 2^5 ##\
## At most `1/MAX_BALANCE_CHURN_QUOTIENT` of the validators can change during
## each validator registry change.
MAX_INDICES_PER_SLASHABLE_VOTE* = 2^12 ##\ MAX_INDICES_PER_ATTESTATION* = 2^12 ##\
## votes ## votes
MAX_EXIT_DEQUEUES_PER_EPOCH* = 4 MIN_PER_EPOCH_CHURN_LIMIT* = 4
CHURN_LIMIT_QUOTIENT* = 2^16
BASE_REWARDS_PER_EPOCH* = 5
SHUFFLE_ROUND_COUNT* = 90 SHUFFLE_ROUND_COUNT* = 90
# Deposit contract # Deposit contract
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#deposit-contract # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#deposit-contract
DEPOSIT_CONTRACT_TREE_DEPTH* = 32 DEPOSIT_CONTRACT_TREE_DEPTH* = 32
# Gwei values # Gwei values
@ -88,7 +91,7 @@ const
MIN_DEPOSIT_AMOUNT* = 2'u64^0 * 10'u64^9 ##\ MIN_DEPOSIT_AMOUNT* = 2'u64^0 * 10'u64^9 ##\
## Minimum amounth of ETH that can be deposited in one call - deposits can ## Minimum amounth of ETH that can be deposited in one call - deposits can
## be used either to top up an existing validator or commit to a new one ## be used either to top up an existing validator or commit to a new one
MAX_DEPOSIT_AMOUNT* = 2'u64^5 * 10'u64^9 ##\ MAX_EFFECTIVE_BALANCE* = 2'u64^5 * 10'u64^9 ##\
## Maximum amounth of ETH that can be deposited in one call ## Maximum amounth of ETH that can be deposited in one call
FORK_CHOICE_BALANCE_INCREMENT* = 2'u64^0 * 10'u64^9 FORK_CHOICE_BALANCE_INCREMENT* = 2'u64^0 * 10'u64^9
@ -141,8 +144,8 @@ const
ACTIVATION_EXIT_DELAY* = 4 ##\ ACTIVATION_EXIT_DELAY* = 4 ##\
## epochs (~25.6 minutes) ## epochs (~25.6 minutes)
EPOCHS_PER_ETH1_VOTING_PERIOD* = 2'u64^4 ##\ SLOTS_PER_ETH1_VOTING_PERIOD* = 1024 ##\
## epochs (~1.7 hours) ## slots (~1.7 hours)
SLOTS_PER_HISTORICAL_ROOT* = 8192 ##\ SLOTS_PER_HISTORICAL_ROOT* = 8192 ##\
## slots (13 hours) ## slots (13 hours)
@ -153,28 +156,25 @@ const
PERSISTENT_COMMITTEE_PERIOD* = 2'u64^11 ##\ PERSISTENT_COMMITTEE_PERIOD* = 2'u64^11 ##\
## epochs (9 days) ## epochs (9 days)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#state-list-lengths # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#state-list-lengths
LATEST_RANDAO_MIXES_LENGTH* = 8192 LATEST_RANDAO_MIXES_LENGTH* = 8192
LATEST_ACTIVE_INDEX_ROOTS_LENGTH* = 8192 # 2'u64^13, epochs LATEST_ACTIVE_INDEX_ROOTS_LENGTH* = 8192 # 2'u64^13, epochs
LATEST_SLASHED_EXIT_LENGTH* = 8192 # epochs LATEST_SLASHED_EXIT_LENGTH* = 8192 # epochs
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#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
BASE_REWARD_QUOTIENT* = 2'u64^5 ##\ BASE_REWARD_QUOTIENT* = 2'u64^5
## The `BASE_REWARD_QUOTIENT` parameter dictates the per-epoch reward. It
## corresponds to ~2.54% annual interest assuming 10 million participating
## ETH in every epoch.
WHISTLEBLOWER_REWARD_QUOTIENT* = 2'u64^9 WHISTLEBLOWER_REWARD_QUOTIENT* = 2'u64^9
ATTESTATION_INCLUSION_REWARD_QUOTIENT* = 2'u64^3 PROPOSER_REWARD_QUOTIENT* = 2'u64^3
INACTIVITY_PENALTY_QUOTIENT* = 2'u64^24 INACTIVITY_PENALTY_QUOTIENT* = 2'u64^25
MIN_PENALTY_QUOTIENT* = 32 # 2^5 MIN_PENALTY_QUOTIENT* = 32 # 2^5
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#max-transactions-per-block # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#max-operations-per-block
MAX_PROPOSER_SLASHINGS* = 2^4 MAX_PROPOSER_SLASHINGS* = 2^4
MAX_ATTESTER_SLASHINGS* = 2^0 MAX_ATTESTER_SLASHINGS* = 2^0
MAX_ATTESTATIONS* = 2^7 MAX_ATTESTATIONS* = 2^7
MAX_DEPOSITS* = 2^4 MAX_DEPOSITS* = 2^4
MAX_VOLUNTARY_EXITS* = 2^4 MAX_VOLUNTARY_EXITS* = 2^4
MAX_TRANSFERS* = 2^4 MAX_TRANSFERS* = 0
type type
ValidatorIndex* = range[0'u32 .. 0xFFFFFF'u32] # TODO: wrap-around ValidatorIndex* = range[0'u32 .. 0xFFFFFF'u32] # TODO: wrap-around
@ -182,7 +182,7 @@ type
Shard* = uint64 Shard* = uint64
Gwei* = uint64 Gwei* = uint64
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#proposerslashing # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#proposerslashing
ProposerSlashing* = object ProposerSlashing* = object
proposer_index*: uint64 ##\ proposer_index*: uint64 ##\
## Proposer index ## Proposer index
@ -193,15 +193,15 @@ type
header_2*: BeaconBlockHeader ##\ header_2*: BeaconBlockHeader ##\
# Second block header # Second block header
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#attesterslashing # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#attesterslashing
AttesterSlashing* = object AttesterSlashing* = object
slashable_attestation_1*: SlashableAttestation ## \ attestation_1*: IndexedAttestation ## \
## First slashable attestation ## First attestation
slashable_attestation_2*: SlashableAttestation ## \ attestation_2*: IndexedAttestation ## \
## Second slashable attestation ## Second attestation
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#slashableattestation # https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#slashableattestation
SlashableAttestation* = object IndexedAttestation* = object
validator_indices*: seq[uint64] ##\ validator_indices*: seq[uint64] ##\
## Validator indices ## Validator indices
@ -214,7 +214,7 @@ type
aggregate_signature*: ValidatorSig ## \ aggregate_signature*: ValidatorSig ## \
## Aggregate signature ## Aggregate signature
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#attestation # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#attestation
Attestation* = object Attestation* = object
aggregation_bitfield*: BitField ##\ aggregation_bitfield*: BitField ##\
## Attester aggregation bitfield ## Attester aggregation bitfield
@ -244,7 +244,7 @@ type
previous_crosslink*: Crosslink previous_crosslink*: Crosslink
crosslink_data_root*: Eth2Digest crosslink_data_root*: Eth2Digest
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#attestationdataandcustodybit # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#attestationdataandcustodybit
AttestationDataAndCustodyBit* = object AttestationDataAndCustodyBit* = object
data*: AttestationData data*: AttestationData
custody_bit*: bool custody_bit*: bool
@ -273,7 +273,7 @@ type
proof_of_possession*: ValidatorSig ##\ 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.5.0/specs/core/0_beacon-chain.md#voluntaryexit # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#voluntaryexit
VoluntaryExit* = object VoluntaryExit* = object
# Minimum epoch for processing exit # Minimum epoch for processing exit
epoch*: Epoch epoch*: Epoch
@ -282,7 +282,7 @@ type
# Validator signature # Validator signature
signature*: ValidatorSig signature*: ValidatorSig
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#transfer # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#transfer
Transfer* = object Transfer* = object
sender*: uint64 ##\ sender*: uint64 ##\
## Sender index ## Sender index
@ -369,7 +369,7 @@ type
# Validator registry # Validator registry
validator_registry*: seq[Validator] validator_registry*: seq[Validator]
validator_balances*: seq[uint64] ##\ balances*: seq[uint64] ##\
## Validator balances in Gwei! ## Validator balances in Gwei!
validator_registry_update_epoch*: Epoch validator_registry_update_epoch*: Epoch
@ -410,7 +410,7 @@ type
# Ethereum 1.0 chain data # Ethereum 1.0 chain data
latest_eth1_data*: Eth1Data latest_eth1_data*: Eth1Data
eth1_data_votes*: seq[Eth1DataVote] eth1_data_votes*: seq[Eth1Data]
deposit_index*: uint64 deposit_index*: uint64
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#validator # https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#validator
@ -436,22 +436,25 @@ type
slashed*: bool ##\ slashed*: bool ##\
## Was the validator slashed ## Was the validator slashed
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#crosslink # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#crosslink
Crosslink* = object Crosslink* = object
epoch*: Epoch ##\ epoch*: Epoch ##\
## Epoch number ## Epoch number
previous_crosslink_root*: Eth2Digest ##\
## Root of the previous crosslink
crosslink_data_root*: Eth2Digest ##\ crosslink_data_root*: Eth2Digest ##\
## Shard data since the previous crosslink ## Shard data since the previous crosslink
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#pendingattestation # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#pendingattestation
PendingAttestation* = object PendingAttestation* = object
aggregation_bitfield*: BitField ## Attester participation bitfield aggregation_bitfield*: BitField ## Attester participation bitfield
data*: AttestationData ## Attestation data data*: AttestationData ## Attestation data
custody_bitfield*: BitField ## Custody bitfield
inclusion_slot*: Slot ## Inclusion slot inclusion_slot*: Slot ## Inclusion slot
proposer_index*: ValidatorIndex ## Proposer index
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#historicalbatch # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#historicalbatch
HistoricalBatch* = object HistoricalBatch* = object
block_roots* : array[SLOTS_PER_HISTORICAL_ROOT, Eth2Digest] ##\ block_roots* : array[SLOTS_PER_HISTORICAL_ROOT, Eth2Digest] ##\
## Block roots ## Block roots
@ -459,7 +462,7 @@ type
state_roots* : array[SLOTS_PER_HISTORICAL_ROOT, Eth2Digest] ##\ state_roots* : array[SLOTS_PER_HISTORICAL_ROOT, Eth2Digest] ##\
## State roots ## State roots
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#fork # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#fork
Fork* = object Fork* = object
previous_version*: array[4, byte] ##\ previous_version*: array[4, byte] ##\
## Previous fork version ## Previous fork version
@ -470,31 +473,26 @@ type
epoch*: Epoch ##\ epoch*: Epoch ##\
## Fork epoch number ## Fork epoch number
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#eth1data # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#eth1data
Eth1Data* = object Eth1Data* = object
deposit_root*: Eth2Digest ##\ deposit_root*: Eth2Digest ##\
## Data being voted for ## Data being voted for
deposit_count*: uint64 ##\
## Total number of deposits
block_hash*: Eth2Digest ##\ block_hash*: Eth2Digest ##\
## Block hash ## Block hash
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#eth1datavote
Eth1DataVote* = object
eth1_data*: Eth1Data ##\
## Data being voted for
vote_count*: uint64 ##\
## Vote count
## TODO remove or otherwise conditional-compile this, since it's for light ## TODO remove or otherwise conditional-compile this, since it's for light
## client but not in spec ## client but not in spec
ValidatorSetDeltaFlags* {.pure.} = enum ValidatorSetDeltaFlags* {.pure.} = enum
Activation = 0 Activation = 0
Exit = 1 Exit = 1
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#signature-domains # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#signature-domains
SignatureDomain* {.pure.} = enum SignatureDomain* {.pure.} = enum
DOMAIN_BEACON_BLOCK = 0 DOMAIN_BEACON_PROPOSER = 0
DOMAIN_RANDAO = 1 DOMAIN_RANDAO = 1
DOMAIN_ATTESTATION = 2 DOMAIN_ATTESTATION = 2
DOMAIN_DEPOSIT = 3 DOMAIN_DEPOSIT = 3

View File

@ -7,7 +7,7 @@
# Serenity hash function / digest # Serenity hash function / digest
# #
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#hash # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#hash
# #
# In Phase 0 the beacon chain is deployed with the same hash function as # In Phase 0 the beacon chain is deployed with the same hash function as
# Ethereum 1.0, i.e. Keccak-256 (also incorrectly known as SHA3). # Ethereum 1.0, i.e. Keccak-256 (also incorrectly known as SHA3).

View File

@ -18,7 +18,7 @@ func split*[T](lst: openArray[T], N: Positive): seq[seq[T]] =
for i in 0 ..< 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 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.5.0/specs/core/0_beacon-chain.md#integer_squareroot # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#integer_squareroot
func integer_squareroot*(n: SomeInteger): SomeInteger = 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 ``n``.
doAssert n >= 0'u64 doAssert n >= 0'u64
@ -31,14 +31,6 @@ func integer_squareroot*(n: SomeInteger): SomeInteger =
y = (x + n div x) div 2 y = (x + n div x) div 2
x x
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_fork_version
func get_fork_version*(fork: Fork, epoch: Epoch): array[4, byte] =
## Return the fork version of the given ``epoch``.
if epoch < fork.epoch:
fork.previous_version
else:
fork.current_version
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#is_power_of_two # 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 func is_power_of_2*(v: uint64): bool = (v > 0'u64) and (v and (v-1)) == 0
@ -77,40 +69,38 @@ func merkle_root*(values: openArray[Eth2Digest]): Eth2Digest =
o[1] o[1]
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#slot_to_epoch # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#slot_to_epoch
func slot_to_epoch*(slot: Slot|uint64): Epoch = func slot_to_epoch*(slot: Slot|uint64): Epoch =
(slot div SLOTS_PER_EPOCH).Epoch (slot div SLOTS_PER_EPOCH).Epoch
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_epoch_start_slot # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#get_epoch_start_slot
func get_epoch_start_slot*(epoch: Epoch): Slot = func get_epoch_start_slot*(epoch: Epoch): Slot =
# Return the starting slot of the given ``epoch``. # Return the starting slot of the given ``epoch``.
(epoch * SLOTS_PER_EPOCH).Slot (epoch * SLOTS_PER_EPOCH).Slot
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#is_double_vote # 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, func is_double_vote*(attestation_data_1: AttestationData,
attestation_data_2: AttestationData): bool = attestation_data_2: AttestationData): bool =
## Check if ``attestation_data_1`` and ``attestation_data_2`` have the same ## Check if ``attestation_data_1`` and ``attestation_data_2`` have the same
## target. ## target.
let let
# RLP artifact
target_epoch_1 = slot_to_epoch(attestation_data_1.slot) target_epoch_1 = slot_to_epoch(attestation_data_1.slot)
target_epoch_2 = slot_to_epoch(attestation_data_2.slot) target_epoch_2 = slot_to_epoch(attestation_data_2.slot)
target_epoch_1 == target_epoch_2 target_epoch_1 == target_epoch_2
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#is_surround_vote # 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, func is_surround_vote*(attestation_data_1: AttestationData,
attestation_data_2: AttestationData): bool = attestation_data_2: AttestationData): bool =
## Check if ``attestation_data_1`` surrounds ``attestation_data_2``. ## Check if ``attestation_data_1`` surrounds ``attestation_data_2``.
let let
source_epoch_1 = attestation_data_1.source_epoch source_epoch_1 = attestation_data_1.source_epoch
source_epoch_2 = attestation_data_2.source_epoch source_epoch_2 = attestation_data_2.source_epoch
# RLP artifact
target_epoch_1 = slot_to_epoch(attestation_data_1.slot) target_epoch_1 = slot_to_epoch(attestation_data_1.slot)
target_epoch_2 = slot_to_epoch(attestation_data_2.slot) target_epoch_2 = slot_to_epoch(attestation_data_2.slot)
source_epoch_1 < source_epoch_2 and target_epoch_2 < target_epoch_1 source_epoch_1 < source_epoch_2 and target_epoch_2 < target_epoch_1
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#is_active_validator # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#state-list-lengths
func is_active_validator*(validator: Validator, epoch: Epoch): bool = func is_active_validator*(validator: Validator, epoch: Epoch): bool =
### Check if ``validator`` is active ### Check if ``validator`` is active
validator.activation_epoch <= epoch and epoch < validator.exit_epoch validator.activation_epoch <= epoch and epoch < validator.exit_epoch
@ -137,13 +127,13 @@ func get_current_epoch_committee_count*(state: BeaconState): uint64 =
) )
get_epoch_committee_count(len(current_active_validators)) get_epoch_committee_count(len(current_active_validators))
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_current_epoch # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#get_current_epoch
func get_current_epoch*(state: BeaconState): Epoch = func get_current_epoch*(state: BeaconState): Epoch =
# Return the current epoch of the given ``state``. # Return the current epoch of the given ``state``.
doAssert state.slot >= GENESIS_SLOT, $state.slot doAssert state.slot >= GENESIS_SLOT, $state.slot
slot_to_epoch(state.slot) slot_to_epoch(state.slot)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_randao_mix # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#get_randao_mix
func get_randao_mix*(state: BeaconState, func get_randao_mix*(state: BeaconState,
epoch: Epoch): Eth2Digest = epoch: Epoch): Eth2Digest =
## Returns the randao mix at a recent ``epoch``. ## Returns the randao mix at a recent ``epoch``.
@ -177,7 +167,7 @@ func bytes_to_int*(data: openarray[byte]): uint64 =
for i in countdown(7, 0): for i in countdown(7, 0):
result = result * 256 + data[i] result = result * 256 + data[i]
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#int_to_bytes1-int_to_bytes2- # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/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. # Have 1, 4, 8, and 32-byte versions. 1+ more and maybe worth metaprogramming.
func int_to_bytes32*(x: uint64): array[32, byte] = func int_to_bytes32*(x: uint64): array[32, byte] =
## Little-endian data representation ## Little-endian data representation
@ -207,22 +197,31 @@ func int_to_bytes4*(x: uint64): array[4, byte] =
result[2] = ((x shr 16) and 0xff).byte result[2] = ((x shr 16) and 0xff).byte
result[3] = ((x shr 24) and 0xff).byte result[3] = ((x shr 24) and 0xff).byte
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_domain # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#get_domain
func get_domain*( func get_domain*(
fork: Fork, epoch: Epoch, domain_type: SignatureDomain): uint64 = state: BeaconState, domain_type: SignatureDomain, message_epoch: Epoch): uint64 =
# Get the domain number that represents the fork meta and signature domain. ## Return the signature domain (fork version concatenated with domain type)
## of a message.
var buf: array[8, byte] var buf: array[8, byte]
buf[0..3] = get_fork_version(fork, epoch) let
epoch = message_epoch
fork_version = if epoch < state.fork.epoch:
state.fork.previous_version
else:
state.fork.current_version
buf[0..3] = fork_version
buf[4..7] = int_to_bytes4(domain_type.uint64) buf[4..7] = int_to_bytes4(domain_type.uint64)
bytes_to_int(buf) bytes_to_int(buf)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#generate_seed 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
func generate_seed*(state: BeaconState, epoch: Epoch): Eth2Digest = func generate_seed*(state: BeaconState, epoch: Epoch): Eth2Digest =
# Generate a seed for the given ``epoch``. # Generate a seed for the given ``epoch``.
var seed_input : array[32*3, byte] var seed_input : array[32*3, byte]
# Cannot underflow, since GENESIS_EPOCH > MIN_SEED_LOOKAHEAD
doAssert GENESIS_EPOCH > MIN_SEED_LOOKAHEAD doAssert GENESIS_EPOCH > MIN_SEED_LOOKAHEAD
seed_input[0..31] = get_randao_mix(state, epoch - MIN_SEED_LOOKAHEAD).data seed_input[0..31] = get_randao_mix(state, epoch - MIN_SEED_LOOKAHEAD).data

View File

@ -229,6 +229,7 @@ iterator get_crosslink_committees_at_slot_cached*(
for v in result: yield v for v in result: yield v
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_beacon_proposer_index # https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_beacon_proposer_index
# TODO remove/merge these back together once 0.5.1 callers removed
func get_beacon_proposer_index*(state: BeaconState, slot: Slot): ValidatorIndex = func get_beacon_proposer_index*(state: BeaconState, slot: Slot): ValidatorIndex =
## From Casper RPJ mini-spec: ## From Casper RPJ mini-spec:
## When slot i begins, validator Vidx is expected ## When slot i begins, validator Vidx is expected
@ -255,3 +256,8 @@ func get_beacon_proposer_index*(state: BeaconState, slot: Slot): ValidatorIndex
let (first_committee, _) = get_crosslink_committees_at_slot(state, slot)[0] let (first_committee, _) = get_crosslink_committees_at_slot(state, slot)[0]
let idx = int(slot mod uint64(first_committee.len)) let idx = int(slot mod uint64(first_committee.len))
first_committee[idx] first_committee[idx]
func get_beacon_proposer_index*(state: BeaconState): ValidatorIndex =
# Return the beacon proposer index at ``state.slot``.
# TODO there are some other changes here
get_beacon_proposer_index(state, state.slot)

View File

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

View File

@ -62,7 +62,7 @@ proc processBlockHeader(
proposer.pubkey, proposer.pubkey,
signed_root(blck).data, signed_root(blck).data,
blck.signature, blck.signature,
get_domain(state.fork, get_current_epoch(state), DOMAIN_BEACON_BLOCK)): get_domain(state, DOMAIN_BEACON_PROPOSER, get_current_epoch(state))):
notice "Block header: invalid block header", notice "Block header: invalid block header",
proposer_pubkey = proposer.pubkey, proposer_pubkey = proposer.pubkey,
block_root = shortLog(signed_root(blck)), block_root = shortLog(signed_root(blck)),
@ -83,7 +83,7 @@ proc processRandao(
proposer.pubkey, proposer.pubkey,
hash_tree_root(get_current_epoch(state).uint64).data, hash_tree_root(get_current_epoch(state).uint64).data,
blck.body.randao_reveal, blck.body.randao_reveal,
get_domain(state.fork, get_current_epoch(state), DOMAIN_RANDAO)): get_domain(state, DOMAIN_RANDAO, get_current_epoch(state))):
notice "Randao mismatch", proposer_pubkey = proposer.pubkey, notice "Randao mismatch", proposer_pubkey = proposer.pubkey,
message = get_current_epoch(state), message = get_current_epoch(state),
@ -103,18 +103,12 @@ proc processRandao(
true true
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#eth1-data-1 # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#eth1-data
func processEth1Data(state: var BeaconState, blck: BeaconBlock) = func processEth1Data(state: var BeaconState, blck: BeaconBlock) =
# TODO verify that there's at most one match state.eth1_data_votes.add blck.body.eth1_data
for x in state.eth1_data_votes.mitems(): if state.eth1_data_votes.count(blck.body.eth1_data) * 2 >
if blck.body.eth1_data == x.eth1_data: SLOTS_PER_ETH1_VOTING_PERIOD:
x.vote_count += 1 state.latest_eth1_data = blck.body.eth1_data
return
state.eth1_data_votes.add Eth1DataVote(
eth1_data: blck.body.eth1_data,
vote_count: 1
)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#proposer-slashings # https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#proposer-slashings
proc processProposerSlashings( proc processProposerSlashings(
@ -147,7 +141,7 @@ proc processProposerSlashings(
signed_root(header).data, signed_root(header).data,
header.signature, header.signature,
get_domain( get_domain(
state.fork, slot_to_epoch(header.slot), DOMAIN_BEACON_BLOCK)): state, DOMAIN_BEACON_PROPOSER, slot_to_epoch(header.slot))):
notice "PropSlash: invalid signature", notice "PropSlash: invalid signature",
signature_index = i signature_index = i
return false return false
@ -157,7 +151,7 @@ proc processProposerSlashings(
true true
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#verify_slashable_attestation # https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#verify_slashable_attestation
func verify_slashable_attestation(state: BeaconState, slashable_attestation: SlashableAttestation): bool = func verify_slashable_attestation(state: BeaconState, slashable_attestation: IndexedAttestation): bool =
# Verify validity of ``slashable_attestation`` fields. # Verify validity of ``slashable_attestation`` fields.
if anyIt(slashable_attestation.custody_bitfield.bits, it != 0): # [TO BE REMOVED IN PHASE 1] if anyIt(slashable_attestation.custody_bitfield.bits, it != 0): # [TO BE REMOVED IN PHASE 1]
@ -174,7 +168,7 @@ func verify_slashable_attestation(state: BeaconState, slashable_attestation: Sla
len(slashable_attestation.validator_indices)): len(slashable_attestation.validator_indices)):
return false return false
if len(slashable_attestation.validator_indices) > MAX_INDICES_PER_SLASHABLE_VOTE: if len(slashable_attestation.validator_indices) > MAX_INDICES_PER_ATTESTATION:
return false return false
var var
@ -200,9 +194,9 @@ func verify_slashable_attestation(state: BeaconState, slashable_attestation: Sla
], ],
slashable_attestation.aggregate_signature, slashable_attestation.aggregate_signature,
get_domain( get_domain(
state.fork, state,
slot_to_epoch(slashable_attestation.data.slot),
DOMAIN_ATTESTATION, DOMAIN_ATTESTATION,
slot_to_epoch(slashable_attestation.data.slot),
), ),
) )
@ -216,8 +210,8 @@ proc processAttesterSlashings(state: var BeaconState, blck: BeaconBlock): bool =
for attester_slashing in blck.body.attester_slashings: for attester_slashing in blck.body.attester_slashings:
let let
slashable_attestation_1 = attester_slashing.slashable_attestation_1 slashable_attestation_1 = attester_slashing.attestation_1
slashable_attestation_2 = attester_slashing.slashable_attestation_2 slashable_attestation_2 = attester_slashing.attestation_2
# Check that the attestations are conflicting # Check that the attestations are conflicting
if not (slashable_attestation_1.data != slashable_attestation_2.data): if not (slashable_attestation_1.data != slashable_attestation_2.data):
@ -253,7 +247,7 @@ proc processAttesterSlashings(state: var BeaconState, blck: BeaconBlock): bool =
true true
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.1/specs/core/0_beacon-chain.md#attestations # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#attestations
proc processAttestations( proc processAttestations(
state: var BeaconState, blck: BeaconBlock, flags: UpdateFlags): bool = state: var BeaconState, blck: BeaconBlock, flags: UpdateFlags): bool =
## Each block includes a number of attestations that the proposer chose. Each ## Each block includes a number of attestations that the proposer chose. Each
@ -275,8 +269,8 @@ proc processAttestations(
let pending_attestation = PendingAttestation( let pending_attestation = PendingAttestation(
data: attestation.data, data: attestation.data,
aggregation_bitfield: attestation.aggregation_bitfield, aggregation_bitfield: attestation.aggregation_bitfield,
custody_bitfield: attestation.custody_bitfield, inclusion_slot: state.slot,
inclusion_slot: state.slot proposer_index: get_beacon_proposer_index(state),
) )
if slot_to_epoch(attestation.data.slot) == get_current_epoch(state): if slot_to_epoch(attestation.data.slot) == get_current_epoch(state):
@ -337,7 +331,7 @@ proc processExits(
if skipValidation notin flags: if skipValidation notin flags:
if not bls_verify( if not bls_verify(
validator.pubkey, signed_root(exit).data, exit.signature, validator.pubkey, signed_root(exit).data, exit.signature,
get_domain(state.fork, exit.epoch, DOMAIN_VOLUNTARY_EXIT)): get_domain(state, DOMAIN_VOLUNTARY_EXIT, exit.epoch)):
notice "Exit: invalid signature" notice "Exit: invalid signature"
return false return false
@ -379,44 +373,38 @@ func update_registry_and_shuffling_data(state: var BeaconState) =
state.current_shuffling_seed = state.current_shuffling_seed =
generate_seed(state, state.current_shuffling_epoch) generate_seed(state, state.current_shuffling_epoch)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#transfers # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#transfers
proc processTransfers(state: var BeaconState, blck: BeaconBlock, proc processTransfers(state: var BeaconState, blck: BeaconBlock,
flags: UpdateFlags): bool = flags: UpdateFlags): bool =
## Note: Transfers are a temporary functionality for phases 0 and 1, to be
## removed in phase 2.
if not (len(blck.body.transfers) <= MAX_TRANSFERS): if not (len(blck.body.transfers) <= MAX_TRANSFERS):
notice "Transfer: too many transfers" notice "Transfer: too many transfers"
return false return false
for transfer in blck.body.transfers: for transfer in blck.body.transfers:
let sender_balance = state.validator_balances[transfer.sender.int] let sender_balance = state.balances[transfer.sender.int]
## Verify the amount and fee aren't individually too big (for anti-overflow ## Verify the amount and fee are not individually too big (for anti-overflow
## purposes) ## purposes)
if not (sender_balance >= max(transfer.amount, transfer.fee)): if not (sender_balance >= max(transfer.amount, transfer.fee)):
notice "Transfer: sender balance too low for transfer amount or fee" notice "Transfer: sender balance too low for transfer amount or fee"
return false return false
## Verify that we have enough ETH to send, and that after the transfer the
## balance will be either exactly zero or at least MIN_DEPOSIT_AMOUNT
if not (
sender_balance == transfer.amount + transfer.fee or
sender_balance >= transfer.amount + transfer.fee + MIN_DEPOSIT_AMOUNT):
notice "Transfer: sender balance too low for amount + fee"
return false
# A transfer is valid in only one slot # A transfer is valid in only one slot
if not (state.slot == transfer.slot): if not (state.slot == transfer.slot):
notice "Transfer: slot mismatch" notice "Transfer: slot mismatch"
return false return false
# Only withdrawn or not-yet-deposited accounts can transfer ## Sender must be not yet eligible for activation, withdrawn, or transfer
if not (get_current_epoch(state) >= ## balance over MAX_EFFECTIVE_BALANCE
if not (
state.validator_registry[transfer.sender.int].activation_epoch ==
FAR_FUTURE_EPOCH or
get_current_epoch(state) >=
state.validator_registry[ state.validator_registry[
transfer.sender.int].withdrawable_epoch or transfer.sender.int].withdrawable_epoch or
state.validator_registry[transfer.sender.int].activation_epoch == transfer.amount + transfer.fee + MAX_EFFECTIVE_BALANCE <=
FAR_FUTURE_EPOCH): state.balances[transfer.sender.int]):
notice "Transfer: only withdrawn or not-deposited accounts can transfer" notice "Transfer: only withdrawn or not-activated accounts with sufficient balance can transfer"
return false return false
# Verify that the pubkey is valid # Verify that the pubkey is valid
@ -431,18 +419,29 @@ proc processTransfers(state: var BeaconState, blck: BeaconBlock,
if skipValidation notin flags: if skipValidation notin flags:
if not bls_verify( if not bls_verify(
transfer.pubkey, signed_root(transfer).data, transfer.signature, transfer.pubkey, signed_root(transfer).data, transfer.signature,
get_domain( get_domain(state, DOMAIN_TRANSFER)):
state.fork, slot_to_epoch(transfer.slot), DOMAIN_TRANSFER)):
notice "Transfer: incorrect signature" notice "Transfer: incorrect signature"
return false return false
# TODO https://github.com/ethereum/eth2.0-specs/issues/727 # Process the transfer
reduce_balance( decrease_balance(
state.validator_balances[transfer.sender.int], state, transfer.sender.ValidatorIndex, transfer.amount + transfer.fee)
transfer.amount + transfer.fee) increase_balance(
state.validator_balances[transfer.recipient.int] += transfer.amount state, transfer.recipient.ValidatorIndex, transfer.amount)
state.validator_balances[ increase_balance(state, get_beacon_proposer_index(state), transfer.fee)
get_beacon_proposer_index(state, state.slot)] += transfer.fee
# Verify balances are not dust
if not (
0'u64 < state.balances[transfer.sender.int] and
state.balances[transfer.sender.int] < MIN_DEPOSIT_AMOUNT):
notice "Transfer: sender balance too low for transfer amount or fee"
return false
if not (
0'u64 < state.balances[transfer.recipient.int] and
state.balances[transfer.recipient.int] < MIN_DEPOSIT_AMOUNT):
notice "Transfer: sender balance too low for transfer amount or fee"
return false
true true
@ -772,17 +771,6 @@ func process_crosslinks(
crosslink_data_root: winning_root crosslink_data_root: winning_root
) )
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#eth1-data
func maybe_reset_eth1_period(state: var BeaconState) =
if (get_current_epoch(state) + 1) mod EPOCHS_PER_ETH1_VOTING_PERIOD == 0:
for eth1_data_vote in state.eth1_data_votes:
## If a majority of all votes were for a particular eth1_data value,
## then set that as the new canonical value
if eth1_data_vote.vote_count * 2 >
EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH:
state.latest_eth1_data = eth1_data_vote.eth1_data
state.eth1_data_votes = @[]
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#rewards-and-penalties # https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#rewards-and-penalties
func get_base_reward(state: BeaconState, index: ValidatorIndex): uint64 = func get_base_reward(state: BeaconState, index: ValidatorIndex): uint64 =
if get_previous_total_balance(state) == 0: if get_previous_total_balance(state) == 0:
@ -866,7 +854,7 @@ func compute_normal_justification_and_finalization_deltas(state: BeaconState):
let proposer_index = let proposer_index =
get_beacon_proposer_index(state, inclusion_slot[index]) get_beacon_proposer_index(state, inclusion_slot[index])
deltas[0][proposer_index] += deltas[0][proposer_index] +=
get_base_reward(state, index) div ATTESTATION_INCLUSION_REWARD_QUOTIENT get_base_reward(state, index) div PROPOSER_REWARD_QUOTIENT
deltas deltas
func compute_inactivity_leak_deltas(state: BeaconState): func compute_inactivity_leak_deltas(state: BeaconState):
@ -981,10 +969,10 @@ func apply_rewards(state: var BeaconState, cache: var StateCache) =
deltas1 = get_justification_and_finalization_deltas(state) deltas1 = get_justification_and_finalization_deltas(state)
deltas2 = get_crosslink_deltas(state, cache) deltas2 = get_crosslink_deltas(state, cache)
for i in 0 ..< len(state.validator_registry): for i in 0 ..< len(state.validator_registry):
state.validator_balances[i] = state.balances[i] =
max( max(
0'u64, 0'u64,
state.validator_balances[i] + deltas1[0][i] + deltas2[0][i] - state.balances[i] + deltas1[0][i] + deltas2[0][i] -
deltas1[1][i] - deltas2[1][i]) deltas1[1][i] - deltas2[1][i])
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#slashings-and-exit-queue # https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#slashings-and-exit-queue
@ -1014,7 +1002,7 @@ func process_slashings(state: var BeaconState) =
min(total_penalties * 3, total_balance) div total_balance, min(total_penalties * 3, total_balance) div total_balance,
get_effective_balance(state, index.ValidatorIndex) div get_effective_balance(state, index.ValidatorIndex) div
MIN_PENALTY_QUOTIENT) MIN_PENALTY_QUOTIENT)
reduce_balance(state.validator_balances[index], penalty) reduce_balance(state.balances[index], penalty)
func process_exit_queue(state: var BeaconState) = func process_exit_queue(state: var BeaconState) =
## Process the exit queue. ## Process the exit queue.
@ -1045,7 +1033,7 @@ func process_exit_queue(state: var BeaconState) =
state.validator_registry[y].exit_epoch)) state.validator_registry[y].exit_epoch))
for dequeues, index in sorted_indices: for dequeues, index in sorted_indices:
if dequeues >= MAX_EXIT_DEQUEUES_PER_EPOCH: if dequeues >= MIN_PER_EPOCH_CHURN_LIMIT:
break break
prepare_validator_for_withdrawal(state, index) prepare_validator_for_withdrawal(state, index)
@ -1104,9 +1092,6 @@ func processEpoch(state: var BeaconState) =
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#crosslinks # https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#crosslinks
process_crosslinks(state, per_epoch_cache) process_crosslinks(state, per_epoch_cache)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#eth1-data
maybe_reset_eth1_period(state)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#apply-rewards # https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#apply-rewards
apply_rewards(state, per_epoch_cache) apply_rewards(state, per_epoch_cache)
@ -1124,7 +1109,7 @@ func processEpoch(state: var BeaconState) =
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#final-updates # https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#final-updates
finish_epoch_update(state) finish_epoch_update(state)
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#state-root-verification # https://github.com/ethereum/eth2.0-specs/blob/v0.6.0/specs/core/0_beacon-chain.md#state-root-verification
proc verifyStateRoot(state: BeaconState, blck: BeaconBlock): bool = proc verifyStateRoot(state: BeaconState, blck: BeaconBlock): bool =
let state_root = hash_tree_root(state) let state_root = hash_tree_root(state)
if state_root != blck.state_root: if state_root != blck.state_root:

View File

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

View File

@ -45,7 +45,7 @@ cli do (totalValidators: int = 125000,
let let
deposit = Deposit( deposit = Deposit(
deposit_data: DepositData( deposit_data: DepositData(
amount: MAX_DEPOSIT_AMOUNT, amount: MAX_EFFECTIVE_BALANCE,
timestamp: 0, # TODO https://github.com/ethereum/eth2.0-specs/pull/834 timestamp: 0, # TODO https://github.com/ethereum/eth2.0-specs/pull/834
deposit_input: DepositInput( deposit_input: DepositInput(
pubkey: pubKey, pubkey: pubKey,

View File

@ -25,12 +25,12 @@ proc getValidator*(pool: ValidatorPool,
validatorKey: ValidatorPubKey): AttachedValidator = validatorKey: ValidatorPubKey): AttachedValidator =
pool.validators.getOrDefault(validatorKey) pool.validators.getOrDefault(validatorKey)
proc signBlockProposal*(v: AttachedValidator, fork: Fork, slot: Slot, proc signBlockProposal*(v: AttachedValidator, state: BeaconState, slot: Slot,
blockRoot: Eth2Digest): Future[ValidatorSig] {.async.} = blockRoot: Eth2Digest): Future[ValidatorSig] {.async.} =
if v.kind == inProcess: if v.kind == inProcess:
await sleepAsync(chronos.milliseconds(1)) await sleepAsync(chronos.milliseconds(1))
result = bls_sign(v.privKey, blockRoot.data, result = bls_sign(v.privKey, blockRoot.data,
get_domain(fork, slot_to_epoch(slot), DOMAIN_BEACON_BLOCK)) get_domain(state, DOMAIN_BEACON_PROPOSER, slot_to_epoch(slot)))
else: else:
# TODO: # TODO:
# send RPC # send RPC
@ -60,7 +60,7 @@ func genRandaoReveal*(k: ValidatorPrivKey, state: BeaconState, slot: Slot):
# Off-by-one? I often get slot == state.slot but the check was "doAssert slot > state.slot" (Mamy) # Off-by-one? I often get slot == state.slot but the check was "doAssert slot > state.slot" (Mamy)
doAssert slot >= state.slot, "input slot: " & $humaneSlotNum(slot) & " - beacon state slot: " & $humaneSlotNum(state.slot) doAssert slot >= state.slot, "input slot: " & $humaneSlotNum(slot) & " - beacon state slot: " & $humaneSlotNum(state.slot)
bls_sign(k, hash_tree_root(slot_to_epoch(slot).uint64).data, bls_sign(k, hash_tree_root(slot_to_epoch(slot).uint64).data,
get_domain(state.fork, slot_to_epoch(slot), DOMAIN_RANDAO)) get_domain(state, DOMAIN_RANDAO, slot_to_epoch(slot)))
func genRandaoReveal*(v: AttachedValidator, state: BeaconState, slot: Slot): func genRandaoReveal*(v: AttachedValidator, state: BeaconState, slot: Slot):
ValidatorSig = ValidatorSig =

View File

@ -16,5 +16,7 @@ import
./test_ssz, ./test_ssz,
./test_state_transition, ./test_state_transition,
./test_sync_protocol, ./test_sync_protocol,
./test_validator, ./test_validator
./official/test_fixture_state
# TODO - re-enable once official test fixtures arrive
#./official/test_fixture_state

View File

@ -23,12 +23,12 @@ type
SHARD_COUNT*: int SHARD_COUNT*: int
TARGET_COMMITTEE_SIZE*: int TARGET_COMMITTEE_SIZE*: int
MAX_BALANCE_CHURN_QUOTIENT*: int MAX_BALANCE_CHURN_QUOTIENT*: int
MAX_INDICES_PER_SLASHABLE_VOTE*: int MAX_INDICES_PER_ATTESTATION*: int
MAX_EXIT_DEQUEUES_PER_EPOCH*: int MIN_PER_EPOCH_CHURN_LIMIT*: int
SHUFFLE_ROUND_COUNT*: int SHUFFLE_ROUND_COUNT*: int
DEPOSIT_CONTRACT_TREE_DEPTH*: int DEPOSIT_CONTRACT_TREE_DEPTH*: int
MIN_DEPOSIT_AMOUNT*: uint64 MIN_DEPOSIT_AMOUNT*: uint64
MAX_DEPOSIT_AMOUNT*: uint64 MAX_EFFECTIVE_BALANCE*: uint64
FORK_CHOICE_BALANCE_INCREMENT*: uint64 FORK_CHOICE_BALANCE_INCREMENT*: uint64
EJECTION_BALANCE*: uint64 EJECTION_BALANCE*: uint64
GENESIS_FORK_VERSION*: uint32 GENESIS_FORK_VERSION*: uint32
@ -50,7 +50,7 @@ type
LATEST_SLASHED_EXIT_LENGTH*: int LATEST_SLASHED_EXIT_LENGTH*: int
BASE_REWARD_QUOTIENT*: uint64 BASE_REWARD_QUOTIENT*: uint64
WHISTLEBLOWER_REWARD_QUOTIENT*: uint64 WHISTLEBLOWER_REWARD_QUOTIENT*: uint64
ATTESTATION_INCLUSION_REWARD_QUOTIENT*: uint64 PROPOSER_REWARD_QUOTIENT*: uint64
INACTIVITY_PENALTY_QUOTIENT*: uint64 INACTIVITY_PENALTY_QUOTIENT*: uint64
MIN_PENALTY_QUOTIENT*: int MIN_PENALTY_QUOTIENT*: int
MAX_PROPOSER_SLASHINGS*: int MAX_PROPOSER_SLASHINGS*: int
@ -59,7 +59,7 @@ type
MAX_DEPOSITS*: int MAX_DEPOSITS*: int
MAX_VOLUNTARY_EXITS*: int MAX_VOLUNTARY_EXITS*: int
MAX_TRANSFERS*: int MAX_TRANSFERS*: int
DOMAIN_BEACON_BLOCK*: SignatureDomain DOMAIN_BEACON_PROPOSER*: SignatureDomain
DOMAIN_RANDAO*: SignatureDomain DOMAIN_RANDAO*: SignatureDomain
DOMAIN_ATTESTATION*: SignatureDomain DOMAIN_ATTESTATION*: SignatureDomain
DOMAIN_DEPOSIT*: SignatureDomain DOMAIN_DEPOSIT*: SignatureDomain

View File

@ -86,10 +86,10 @@ suite "Tree hashing":
let vr = BeaconBlock() let vr = BeaconBlock()
check: check:
$hash_tree_root(vr) == $hash_tree_root(vr) ==
"1BD5D8577A7806CC524C367808C53AE2480F35A3C4BB11A90D6E1AC304E27201" "8951C9C64ABA469EBA78F5D9F9A0666FB697B8C4D86901445777E4445D0B1543"
test "Hash BeaconState": test "Hash BeaconState":
let vr = BeaconState() let vr = BeaconState()
check: check:
$hash_tree_root(vr) == $hash_tree_root(vr) ==
"17E30FC7BC442CEF2045C4FB3CC6B1D975F041C4629DA7395B607281FD1521A6" "66F9BF92A690F1FBD36488D98BE70DA6C84100EDF935BC6D0B30FF14A2976455"

View File

@ -56,7 +56,7 @@ func makeDeposit(i: int, flags: UpdateFlags): Deposit =
proof_of_possession: pop, proof_of_possession: pop,
withdrawal_credentials: withdrawal_credentials, withdrawal_credentials: withdrawal_credentials,
), ),
amount: MAX_DEPOSIT_AMOUNT, amount: MAX_EFFECTIVE_BALANCE,
) )
) )
@ -128,12 +128,12 @@ proc addBlock*(
# We have a signature - put it in the block and we should be done! # We have a signature - put it in the block and we should be done!
new_block.signature = new_block.signature =
bls_sign(proposerPrivkey, block_root.data, bls_sign(proposerPrivkey, block_root.data,
get_domain(state.fork, slot_to_epoch(new_block.slot), DOMAIN_BEACON_BLOCK)) get_domain(state, DOMAIN_BEACON_PROPOSER, slot_to_epoch(new_block.slot)))
doAssert bls_verify( doAssert bls_verify(
proposer.pubkey, proposer.pubkey,
block_root.data, new_block.signature, block_root.data, new_block.signature,
get_domain(state.fork, slot_to_epoch(new_block.slot), DOMAIN_BEACON_BLOCK)), get_domain(state, DOMAIN_BEACON_PROPOSER, slot_to_epoch(new_block.slot))),
"we just signed this message - it should pass verification!" "we just signed this message - it should pass verification!"
new_block new_block
@ -178,9 +178,9 @@ proc makeAttestation*(
bls_sign( bls_sign(
hackPrivKey(validator), @(msg.data), hackPrivKey(validator), @(msg.data),
get_domain( get_domain(
state.fork, state,
slot_to_epoch(state.slot), DOMAIN_ATTESTATION,
DOMAIN_ATTESTATION)) slot_to_epoch(state.slot)))
else: else:
ValidatorSig() ValidatorSig()