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:
parent
5784b2d7f7
commit
46b4154ce8
|
@ -97,8 +97,8 @@ proc validate(
|
|||
data: attestation.data, custody_bit: true)),
|
||||
],
|
||||
attestation.aggregate_signature,
|
||||
get_domain(state.fork, slot_to_epoch(attestation.data.slot),
|
||||
DOMAIN_ATTESTATION),
|
||||
get_domain(state, DOMAIN_ATTESTATION,
|
||||
slot_to_epoch(attestation.data.slot)),
|
||||
):
|
||||
notice "Invalid signature", participants
|
||||
return false
|
||||
|
|
|
@ -380,7 +380,7 @@ proc proposeBlock(node: BeaconNode,
|
|||
|
||||
# Careful, state no longer valid after here..
|
||||
newBlock.signature =
|
||||
await validator.signBlockProposal(state.fork, slot, blockRoot)
|
||||
await validator.signBlockProposal(state, slot, blockRoot)
|
||||
|
||||
(blockRoot, newBlock)
|
||||
|
||||
|
|
|
@ -15,9 +15,9 @@ import
|
|||
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.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 =
|
||||
## Verify that the given ``leaf`` is on the merkle branch ``proof``
|
||||
## 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
|
||||
## time will be recycled.
|
||||
state.validator_registry.add(validator)
|
||||
state.validator_balances.add(amount)
|
||||
state.balances.add(amount)
|
||||
else:
|
||||
# Increase balance by deposit amount
|
||||
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 ==
|
||||
withdrawal_credentials
|
||||
|
||||
state.validator_balances[index] += amount
|
||||
state.balances[index] += amount
|
||||
|
||||
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 =
|
||||
## Return the epoch at which an activation or exit triggered in ``epoch``
|
||||
## 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
|
||||
## whistleblower_reward (to prevent underflow) should increase be full? It
|
||||
## seems wrong for the amounts to differ.
|
||||
state.validator_balances[whistleblower_index] += whistleblower_reward
|
||||
reduce_balance(state.validator_balances[index], whistleblower_reward)
|
||||
state.balances[whistleblower_index] += whistleblower_reward
|
||||
reduce_balance(state.balances[index], whistleblower_reward)
|
||||
validator.slashed = true
|
||||
validator.withdrawable_epoch =
|
||||
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 and validator_balances automatically initalized
|
||||
# validator_registry and balances automatically initalized
|
||||
|
||||
# Randomness and committees
|
||||
# latest_randao_mixes automatically initialized
|
||||
|
@ -289,7 +289,7 @@ func get_genesis_beacon_state*(
|
|||
# Process genesis activations
|
||||
for validator_index in 0 ..< state.validator_registry.len:
|
||||
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)
|
||||
|
||||
let genesis_active_index_root = hash_tree_root(
|
||||
|
@ -400,7 +400,7 @@ func process_ejections*(state: var BeaconState) =
|
|||
## balance below ``EJECTION_BALANCE``
|
||||
for index in get_active_validator_indices(
|
||||
state.validator_registry, get_current_epoch(state)):
|
||||
if state.validator_balances[index] < EJECTION_BALANCE:
|
||||
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
|
||||
|
@ -432,7 +432,7 @@ func update_validator_registry*(state: var BeaconState) =
|
|||
|
||||
# The maximum balance churn in Gwei (for deposits and exits separately)
|
||||
max_balance_churn = max(
|
||||
MAX_DEPOSIT_AMOUNT,
|
||||
MAX_EFFECTIVE_BALANCE,
|
||||
total_balance div (2 * MAX_BALANCE_CHURN_QUOTIENT)
|
||||
)
|
||||
|
||||
|
@ -440,7 +440,7 @@ func update_validator_registry*(state: var BeaconState) =
|
|||
var balance_churn = 0'u64
|
||||
for index, validator in state.validator_registry:
|
||||
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
|
||||
balance_churn += get_effective_balance(state, index.ValidatorIndex)
|
||||
if balance_churn > max_balance_churn:
|
||||
|
@ -600,8 +600,8 @@ proc checkAttestation*(
|
|||
data: attestation.data, custody_bit: true)),
|
||||
],
|
||||
attestation.aggregate_signature,
|
||||
get_domain(state.fork, slot_to_epoch(attestation.data.slot),
|
||||
DOMAIN_ATTESTATION),
|
||||
get_domain(state, DOMAIN_ATTESTATION,
|
||||
slot_to_epoch(attestation.data.slot))
|
||||
):
|
||||
warn("Invalid attestation signature")
|
||||
return
|
||||
|
@ -622,6 +622,22 @@ func prepare_validator_for_withdrawal*(state: var BeaconState, index: ValidatorI
|
|||
validator.withdrawable_epoch = get_current_epoch(state) +
|
||||
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*(
|
||||
state: BeaconState, shard: uint64,
|
||||
beacon_block_root: Eth2Digest): AttestationData =
|
||||
|
|
|
@ -16,14 +16,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.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 =
|
||||
# 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.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 =
|
||||
# Verify ``bitfield`` against the ``committee_size``.
|
||||
if len(bitfield.bits) != (committee_size + 7) div 8:
|
||||
|
|
|
@ -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.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 =
|
||||
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.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*(
|
||||
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.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*(
|
||||
pubkeys: seq[ValidatorPubKey], message_hashes: openArray[Eth2Digest],
|
||||
sig: ValidatorSig, domain: uint64): bool =
|
||||
|
|
|
@ -68,19 +68,22 @@ const
|
|||
## with a Verifiable Delay Function (VDF) will improve committee robustness
|
||||
## and lower the safe minimum committee size.)
|
||||
|
||||
# TODO remove, not in post-0.5.1
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
# 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
|
||||
|
||||
# Gwei values
|
||||
|
@ -88,7 +91,7 @@ const
|
|||
MIN_DEPOSIT_AMOUNT* = 2'u64^0 * 10'u64^9 ##\
|
||||
## 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
|
||||
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
|
||||
|
||||
FORK_CHOICE_BALANCE_INCREMENT* = 2'u64^0 * 10'u64^9
|
||||
|
@ -141,8 +144,8 @@ const
|
|||
ACTIVATION_EXIT_DELAY* = 4 ##\
|
||||
## epochs (~25.6 minutes)
|
||||
|
||||
EPOCHS_PER_ETH1_VOTING_PERIOD* = 2'u64^4 ##\
|
||||
## epochs (~1.7 hours)
|
||||
SLOTS_PER_ETH1_VOTING_PERIOD* = 1024 ##\
|
||||
## slots (~1.7 hours)
|
||||
|
||||
SLOTS_PER_HISTORICAL_ROOT* = 8192 ##\
|
||||
## slots (13 hours)
|
||||
|
@ -153,28 +156,25 @@ const
|
|||
PERSISTENT_COMMITTEE_PERIOD* = 2'u64^11 ##\
|
||||
## 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_ACTIVE_INDEX_ROOTS_LENGTH* = 8192 # 2'u64^13, 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
|
||||
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.
|
||||
# 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
|
||||
WHISTLEBLOWER_REWARD_QUOTIENT* = 2'u64^9
|
||||
ATTESTATION_INCLUSION_REWARD_QUOTIENT* = 2'u64^3
|
||||
INACTIVITY_PENALTY_QUOTIENT* = 2'u64^24
|
||||
PROPOSER_REWARD_QUOTIENT* = 2'u64^3
|
||||
INACTIVITY_PENALTY_QUOTIENT* = 2'u64^25
|
||||
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_ATTESTER_SLASHINGS* = 2^0
|
||||
MAX_ATTESTATIONS* = 2^7
|
||||
MAX_DEPOSITS* = 2^4
|
||||
MAX_VOLUNTARY_EXITS* = 2^4
|
||||
MAX_TRANSFERS* = 2^4
|
||||
MAX_TRANSFERS* = 0
|
||||
|
||||
type
|
||||
ValidatorIndex* = range[0'u32 .. 0xFFFFFF'u32] # TODO: wrap-around
|
||||
|
@ -182,7 +182,7 @@ type
|
|||
Shard* = 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
|
||||
proposer_index*: uint64 ##\
|
||||
## Proposer index
|
||||
|
@ -193,15 +193,15 @@ type
|
|||
header_2*: BeaconBlockHeader ##\
|
||||
# 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
|
||||
slashable_attestation_1*: SlashableAttestation ## \
|
||||
## First slashable attestation
|
||||
slashable_attestation_2*: SlashableAttestation ## \
|
||||
## Second slashable attestation
|
||||
attestation_1*: IndexedAttestation ## \
|
||||
## First attestation
|
||||
attestation_2*: IndexedAttestation ## \
|
||||
## Second attestation
|
||||
|
||||
# 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
|
||||
|
||||
|
@ -214,7 +214,7 @@ type
|
|||
aggregate_signature*: ValidatorSig ## \
|
||||
## 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
|
||||
aggregation_bitfield*: BitField ##\
|
||||
## Attester aggregation bitfield
|
||||
|
@ -244,7 +244,7 @@ type
|
|||
previous_crosslink*: Crosslink
|
||||
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
|
||||
data*: AttestationData
|
||||
custody_bit*: bool
|
||||
|
@ -273,7 +273,7 @@ type
|
|||
proof_of_possession*: ValidatorSig ##\
|
||||
## 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
|
||||
# Minimum epoch for processing exit
|
||||
epoch*: Epoch
|
||||
|
@ -282,7 +282,7 @@ type
|
|||
# Validator signature
|
||||
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
|
||||
sender*: uint64 ##\
|
||||
## Sender index
|
||||
|
@ -369,7 +369,7 @@ type
|
|||
|
||||
# Validator registry
|
||||
validator_registry*: seq[Validator]
|
||||
validator_balances*: seq[uint64] ##\
|
||||
balances*: seq[uint64] ##\
|
||||
## Validator balances in Gwei!
|
||||
|
||||
validator_registry_update_epoch*: Epoch
|
||||
|
@ -410,7 +410,7 @@ type
|
|||
|
||||
# Ethereum 1.0 chain data
|
||||
latest_eth1_data*: Eth1Data
|
||||
eth1_data_votes*: seq[Eth1DataVote]
|
||||
eth1_data_votes*: seq[Eth1Data]
|
||||
deposit_index*: uint64
|
||||
|
||||
# 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 ##\
|
||||
## 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
|
||||
epoch*: Epoch ##\
|
||||
## Epoch number
|
||||
|
||||
previous_crosslink_root*: Eth2Digest ##\
|
||||
## Root of the previous crosslink
|
||||
|
||||
crosslink_data_root*: Eth2Digest ##\
|
||||
## 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
|
||||
aggregation_bitfield*: BitField ## Attester participation bitfield
|
||||
data*: AttestationData ## Attestation data
|
||||
custody_bitfield*: BitField ## Custody bitfield
|
||||
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
|
||||
block_roots* : array[SLOTS_PER_HISTORICAL_ROOT, Eth2Digest] ##\
|
||||
## Block roots
|
||||
|
@ -459,7 +462,7 @@ type
|
|||
state_roots* : array[SLOTS_PER_HISTORICAL_ROOT, Eth2Digest] ##\
|
||||
## 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
|
||||
previous_version*: array[4, byte] ##\
|
||||
## Previous fork version
|
||||
|
@ -470,31 +473,26 @@ type
|
|||
epoch*: Epoch ##\
|
||||
## 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
|
||||
deposit_root*: Eth2Digest ##\
|
||||
## Data being voted for
|
||||
|
||||
deposit_count*: uint64 ##\
|
||||
## Total number of deposits
|
||||
|
||||
block_hash*: Eth2Digest ##\
|
||||
## 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
|
||||
## client but not in spec
|
||||
ValidatorSetDeltaFlags* {.pure.} = enum
|
||||
Activation = 0
|
||||
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
|
||||
DOMAIN_BEACON_BLOCK = 0
|
||||
DOMAIN_BEACON_PROPOSER = 0
|
||||
DOMAIN_RANDAO = 1
|
||||
DOMAIN_ATTESTATION = 2
|
||||
DOMAIN_DEPOSIT = 3
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
# 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
|
||||
# Ethereum 1.0, i.e. Keccak-256 (also incorrectly known as SHA3).
|
||||
|
|
|
@ -18,7 +18,7 @@ func split*[T](lst: openArray[T], N: Positive): seq[seq[T]] =
|
|||
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.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 =
|
||||
## The largest integer ``x`` such that ``x**2`` is less than ``n``.
|
||||
doAssert n >= 0'u64
|
||||
|
@ -31,14 +31,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#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
|
||||
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]
|
||||
|
||||
# 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 =
|
||||
(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 =
|
||||
# Return the starting slot of the given ``epoch``.
|
||||
(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,
|
||||
attestation_data_2: AttestationData): bool =
|
||||
## Check if ``attestation_data_1`` and ``attestation_data_2`` have the same
|
||||
## target.
|
||||
let
|
||||
# RLP artifact
|
||||
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.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,
|
||||
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
|
||||
# RLP artifact
|
||||
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.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 =
|
||||
### Check if ``validator`` is active
|
||||
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))
|
||||
|
||||
# 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 =
|
||||
# Return the current epoch of the given ``state``.
|
||||
doAssert state.slot >= GENESIS_SLOT, $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,
|
||||
epoch: Epoch): Eth2Digest =
|
||||
## 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):
|
||||
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.
|
||||
func int_to_bytes32*(x: uint64): array[32, byte] =
|
||||
## 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[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*(
|
||||
fork: Fork, epoch: Epoch, domain_type: SignatureDomain): uint64 =
|
||||
# Get the domain number that represents the fork meta and signature domain.
|
||||
state: BeaconState, domain_type: SignatureDomain, message_epoch: Epoch): uint64 =
|
||||
## Return the signature domain (fork version concatenated with domain type)
|
||||
## of a message.
|
||||
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)
|
||||
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 =
|
||||
# Generate a seed for the given ``epoch``.
|
||||
|
||||
var seed_input : array[32*3, byte]
|
||||
|
||||
# Cannot underflow, since GENESIS_EPOCH > MIN_SEED_LOOKAHEAD
|
||||
doAssert GENESIS_EPOCH > MIN_SEED_LOOKAHEAD
|
||||
|
||||
seed_input[0..31] = get_randao_mix(state, epoch - MIN_SEED_LOOKAHEAD).data
|
||||
|
|
|
@ -229,6 +229,7 @@ iterator get_crosslink_committees_at_slot_cached*(
|
|||
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
|
||||
# TODO remove/merge these back together once 0.5.1 callers removed
|
||||
func get_beacon_proposer_index*(state: BeaconState, slot: Slot): ValidatorIndex =
|
||||
## From Casper RPJ mini-spec:
|
||||
## 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 idx = int(slot mod uint64(first_committee.len))
|
||||
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)
|
||||
|
|
|
@ -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.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
|
||||
# TODO Probably wrong - the spec is pretty bare-bones and no test vectors yet
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ proc processBlockHeader(
|
|||
proposer.pubkey,
|
||||
signed_root(blck).data,
|
||||
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",
|
||||
proposer_pubkey = proposer.pubkey,
|
||||
block_root = shortLog(signed_root(blck)),
|
||||
|
@ -83,7 +83,7 @@ proc processRandao(
|
|||
proposer.pubkey,
|
||||
hash_tree_root(get_current_epoch(state).uint64).data,
|
||||
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,
|
||||
message = get_current_epoch(state),
|
||||
|
@ -103,18 +103,12 @@ proc processRandao(
|
|||
|
||||
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) =
|
||||
# TODO verify that there's at most one match
|
||||
for x in state.eth1_data_votes.mitems():
|
||||
if blck.body.eth1_data == x.eth1_data:
|
||||
x.vote_count += 1
|
||||
return
|
||||
|
||||
state.eth1_data_votes.add Eth1DataVote(
|
||||
eth1_data: blck.body.eth1_data,
|
||||
vote_count: 1
|
||||
)
|
||||
state.eth1_data_votes.add blck.body.eth1_data
|
||||
if state.eth1_data_votes.count(blck.body.eth1_data) * 2 >
|
||||
SLOTS_PER_ETH1_VOTING_PERIOD:
|
||||
state.latest_eth1_data = blck.body.eth1_data
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#proposer-slashings
|
||||
proc processProposerSlashings(
|
||||
|
@ -147,7 +141,7 @@ proc processProposerSlashings(
|
|||
signed_root(header).data,
|
||||
header.signature,
|
||||
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",
|
||||
signature_index = i
|
||||
return false
|
||||
|
@ -157,7 +151,7 @@ proc processProposerSlashings(
|
|||
true
|
||||
|
||||
# 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.
|
||||
|
||||
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)):
|
||||
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
|
||||
|
||||
var
|
||||
|
@ -200,9 +194,9 @@ func verify_slashable_attestation(state: BeaconState, slashable_attestation: Sla
|
|||
],
|
||||
slashable_attestation.aggregate_signature,
|
||||
get_domain(
|
||||
state.fork,
|
||||
slot_to_epoch(slashable_attestation.data.slot),
|
||||
state,
|
||||
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:
|
||||
let
|
||||
slashable_attestation_1 = attester_slashing.slashable_attestation_1
|
||||
slashable_attestation_2 = attester_slashing.slashable_attestation_2
|
||||
slashable_attestation_1 = attester_slashing.attestation_1
|
||||
slashable_attestation_2 = attester_slashing.attestation_2
|
||||
|
||||
# Check that the attestations are conflicting
|
||||
if not (slashable_attestation_1.data != slashable_attestation_2.data):
|
||||
|
@ -253,7 +247,7 @@ proc processAttesterSlashings(state: var BeaconState, blck: BeaconBlock): bool =
|
|||
|
||||
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(
|
||||
state: var BeaconState, blck: BeaconBlock, flags: UpdateFlags): bool =
|
||||
## Each block includes a number of attestations that the proposer chose. Each
|
||||
|
@ -275,8 +269,8 @@ proc processAttestations(
|
|||
let pending_attestation = PendingAttestation(
|
||||
data: attestation.data,
|
||||
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):
|
||||
|
@ -337,7 +331,7 @@ proc processExits(
|
|||
if skipValidation notin flags:
|
||||
if not bls_verify(
|
||||
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"
|
||||
return false
|
||||
|
||||
|
@ -379,44 +373,38 @@ func update_registry_and_shuffling_data(state: var BeaconState) =
|
|||
state.current_shuffling_seed =
|
||||
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,
|
||||
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):
|
||||
notice "Transfer: too many transfers"
|
||||
return false
|
||||
|
||||
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)
|
||||
if not (sender_balance >= max(transfer.amount, transfer.fee)):
|
||||
notice "Transfer: sender balance too low for transfer amount or fee"
|
||||
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
|
||||
if not (state.slot == transfer.slot):
|
||||
notice "Transfer: slot mismatch"
|
||||
return false
|
||||
|
||||
# Only withdrawn or not-yet-deposited accounts can transfer
|
||||
if not (get_current_epoch(state) >=
|
||||
## Sender must be not yet eligible for activation, withdrawn, or transfer
|
||||
## 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[
|
||||
transfer.sender.int].withdrawable_epoch or
|
||||
state.validator_registry[transfer.sender.int].activation_epoch ==
|
||||
FAR_FUTURE_EPOCH):
|
||||
notice "Transfer: only withdrawn or not-deposited accounts can transfer"
|
||||
transfer.amount + transfer.fee + MAX_EFFECTIVE_BALANCE <=
|
||||
state.balances[transfer.sender.int]):
|
||||
notice "Transfer: only withdrawn or not-activated accounts with sufficient balance can transfer"
|
||||
return false
|
||||
|
||||
# Verify that the pubkey is valid
|
||||
|
@ -431,18 +419,29 @@ proc processTransfers(state: var BeaconState, blck: BeaconBlock,
|
|||
if skipValidation notin flags:
|
||||
if not bls_verify(
|
||||
transfer.pubkey, signed_root(transfer).data, transfer.signature,
|
||||
get_domain(
|
||||
state.fork, slot_to_epoch(transfer.slot), DOMAIN_TRANSFER)):
|
||||
get_domain(state, DOMAIN_TRANSFER)):
|
||||
notice "Transfer: incorrect signature"
|
||||
return false
|
||||
|
||||
# TODO https://github.com/ethereum/eth2.0-specs/issues/727
|
||||
reduce_balance(
|
||||
state.validator_balances[transfer.sender.int],
|
||||
transfer.amount + transfer.fee)
|
||||
state.validator_balances[transfer.recipient.int] += transfer.amount
|
||||
state.validator_balances[
|
||||
get_beacon_proposer_index(state, state.slot)] += transfer.fee
|
||||
# Process the transfer
|
||||
decrease_balance(
|
||||
state, transfer.sender.ValidatorIndex, transfer.amount + transfer.fee)
|
||||
increase_balance(
|
||||
state, transfer.recipient.ValidatorIndex, transfer.amount)
|
||||
increase_balance(state, get_beacon_proposer_index(state), 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
|
||||
|
||||
|
@ -772,17 +771,6 @@ func process_crosslinks(
|
|||
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
|
||||
func get_base_reward(state: BeaconState, index: ValidatorIndex): uint64 =
|
||||
if get_previous_total_balance(state) == 0:
|
||||
|
@ -866,7 +854,7 @@ func compute_normal_justification_and_finalization_deltas(state: BeaconState):
|
|||
let proposer_index =
|
||||
get_beacon_proposer_index(state, inclusion_slot[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
|
||||
|
||||
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)
|
||||
deltas2 = get_crosslink_deltas(state, cache)
|
||||
for i in 0 ..< len(state.validator_registry):
|
||||
state.validator_balances[i] =
|
||||
state.balances[i] =
|
||||
max(
|
||||
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])
|
||||
|
||||
# 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,
|
||||
get_effective_balance(state, index.ValidatorIndex) div
|
||||
MIN_PENALTY_QUOTIENT)
|
||||
reduce_balance(state.validator_balances[index], penalty)
|
||||
reduce_balance(state.balances[index], penalty)
|
||||
|
||||
func process_exit_queue(state: var BeaconState) =
|
||||
## Process the exit queue.
|
||||
|
@ -1045,7 +1033,7 @@ func process_exit_queue(state: var BeaconState) =
|
|||
state.validator_registry[y].exit_epoch))
|
||||
|
||||
for dequeues, index in sorted_indices:
|
||||
if dequeues >= MAX_EXIT_DEQUEUES_PER_EPOCH:
|
||||
if dequeues >= MIN_PER_EPOCH_CHURN_LIMIT:
|
||||
break
|
||||
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
|
||||
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
|
||||
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
|
||||
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 =
|
||||
let state_root = hash_tree_root(state)
|
||||
if state_root != blck.state_root:
|
||||
|
|
|
@ -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.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
|
||||
# follow:
|
||||
|
|
|
@ -45,7 +45,7 @@ cli do (totalValidators: int = 125000,
|
|||
let
|
||||
deposit = Deposit(
|
||||
deposit_data: DepositData(
|
||||
amount: MAX_DEPOSIT_AMOUNT,
|
||||
amount: MAX_EFFECTIVE_BALANCE,
|
||||
timestamp: 0, # TODO https://github.com/ethereum/eth2.0-specs/pull/834
|
||||
deposit_input: DepositInput(
|
||||
pubkey: pubKey,
|
||||
|
|
|
@ -25,12 +25,12 @@ proc getValidator*(pool: ValidatorPool,
|
|||
validatorKey: ValidatorPubKey): AttachedValidator =
|
||||
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.} =
|
||||
if v.kind == inProcess:
|
||||
await sleepAsync(chronos.milliseconds(1))
|
||||
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:
|
||||
# TODO:
|
||||
# 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)
|
||||
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,
|
||||
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):
|
||||
ValidatorSig =
|
||||
|
|
|
@ -16,5 +16,7 @@ import
|
|||
./test_ssz,
|
||||
./test_state_transition,
|
||||
./test_sync_protocol,
|
||||
./test_validator,
|
||||
./official/test_fixture_state
|
||||
./test_validator
|
||||
|
||||
# TODO - re-enable once official test fixtures arrive
|
||||
#./official/test_fixture_state
|
||||
|
|
|
@ -23,12 +23,12 @@ type
|
|||
SHARD_COUNT*: int
|
||||
TARGET_COMMITTEE_SIZE*: int
|
||||
MAX_BALANCE_CHURN_QUOTIENT*: int
|
||||
MAX_INDICES_PER_SLASHABLE_VOTE*: int
|
||||
MAX_EXIT_DEQUEUES_PER_EPOCH*: int
|
||||
MAX_INDICES_PER_ATTESTATION*: int
|
||||
MIN_PER_EPOCH_CHURN_LIMIT*: int
|
||||
SHUFFLE_ROUND_COUNT*: int
|
||||
DEPOSIT_CONTRACT_TREE_DEPTH*: int
|
||||
MIN_DEPOSIT_AMOUNT*: uint64
|
||||
MAX_DEPOSIT_AMOUNT*: uint64
|
||||
MAX_EFFECTIVE_BALANCE*: uint64
|
||||
FORK_CHOICE_BALANCE_INCREMENT*: uint64
|
||||
EJECTION_BALANCE*: uint64
|
||||
GENESIS_FORK_VERSION*: uint32
|
||||
|
@ -50,7 +50,7 @@ type
|
|||
LATEST_SLASHED_EXIT_LENGTH*: int
|
||||
BASE_REWARD_QUOTIENT*: uint64
|
||||
WHISTLEBLOWER_REWARD_QUOTIENT*: uint64
|
||||
ATTESTATION_INCLUSION_REWARD_QUOTIENT*: uint64
|
||||
PROPOSER_REWARD_QUOTIENT*: uint64
|
||||
INACTIVITY_PENALTY_QUOTIENT*: uint64
|
||||
MIN_PENALTY_QUOTIENT*: int
|
||||
MAX_PROPOSER_SLASHINGS*: int
|
||||
|
@ -59,7 +59,7 @@ type
|
|||
MAX_DEPOSITS*: int
|
||||
MAX_VOLUNTARY_EXITS*: int
|
||||
MAX_TRANSFERS*: int
|
||||
DOMAIN_BEACON_BLOCK*: SignatureDomain
|
||||
DOMAIN_BEACON_PROPOSER*: SignatureDomain
|
||||
DOMAIN_RANDAO*: SignatureDomain
|
||||
DOMAIN_ATTESTATION*: SignatureDomain
|
||||
DOMAIN_DEPOSIT*: SignatureDomain
|
||||
|
|
|
@ -86,10 +86,10 @@ suite "Tree hashing":
|
|||
let vr = BeaconBlock()
|
||||
check:
|
||||
$hash_tree_root(vr) ==
|
||||
"1BD5D8577A7806CC524C367808C53AE2480F35A3C4BB11A90D6E1AC304E27201"
|
||||
"8951C9C64ABA469EBA78F5D9F9A0666FB697B8C4D86901445777E4445D0B1543"
|
||||
|
||||
test "Hash BeaconState":
|
||||
let vr = BeaconState()
|
||||
check:
|
||||
$hash_tree_root(vr) ==
|
||||
"17E30FC7BC442CEF2045C4FB3CC6B1D975F041C4629DA7395B607281FD1521A6"
|
||||
"66F9BF92A690F1FBD36488D98BE70DA6C84100EDF935BC6D0B30FF14A2976455"
|
||||
|
|
|
@ -56,7 +56,7 @@ func makeDeposit(i: int, flags: UpdateFlags): Deposit =
|
|||
proof_of_possession: pop,
|
||||
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!
|
||||
new_block.signature =
|
||||
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(
|
||||
proposer.pubkey,
|
||||
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!"
|
||||
|
||||
new_block
|
||||
|
@ -178,9 +178,9 @@ proc makeAttestation*(
|
|||
bls_sign(
|
||||
hackPrivKey(validator), @(msg.data),
|
||||
get_domain(
|
||||
state.fork,
|
||||
slot_to_epoch(state.slot),
|
||||
DOMAIN_ATTESTATION))
|
||||
state,
|
||||
DOMAIN_ATTESTATION,
|
||||
slot_to_epoch(state.slot)))
|
||||
else:
|
||||
ValidatorSig()
|
||||
|
||||
|
|
Loading…
Reference in New Issue