AttestationData.justified epoch -> AttestationData.source_epoch and AttestationData.latest_crosslink -> AttestationData.previous_crosslink; implement verify_merkle_branch and update process_deposit to use it; rm BeaconState.batched_block_roots; Transfer.{from, to} -> Transfer.{sender, recipient}; update Fork data type and code to use bytes4; implement int_to_bytes8 (close to metaprogramming time); adjust signed_root and all callers to use 0.5.0 calling signature; processDepositRoot -> processEth1Data (#182)
This commit is contained in:
parent
6bb38095c9
commit
2bc632c29b
|
@ -239,7 +239,7 @@ proc add*(pool: var AttestationPool,
|
|||
slot = humaneSlotNum(attestation.data.slot),
|
||||
shard = attestation.data.shard,
|
||||
beaconBlockRoot = shortLog(attestation.data.beacon_block_root),
|
||||
justifiedEpoch = humaneEpochNum(attestation.data.justified_epoch),
|
||||
sourceEpoch = humaneEpochNum(attestation.data.source_epoch),
|
||||
justifiedBlockRoot = shortLog(attestation.data.justified_block_root),
|
||||
signature = shortLog(attestation.aggregate_signature),
|
||||
validations = a.validations.len() # TODO popcount of union
|
||||
|
@ -262,7 +262,7 @@ proc add*(pool: var AttestationPool,
|
|||
slot = humaneSlotNum(attestation.data.slot),
|
||||
shard = attestation.data.shard,
|
||||
beaconBlockRoot = shortLog(attestation.data.beacon_block_root),
|
||||
justifiedEpoch = humaneEpochNum(attestation.data.justified_epoch),
|
||||
sourceEpoch = humaneEpochNum(attestation.data.source_epoch),
|
||||
justifiedBlockRoot = shortLog(attestation.data.justified_block_root),
|
||||
signature = shortLog(attestation.aggregate_signature),
|
||||
validations = 1
|
||||
|
|
|
@ -387,7 +387,7 @@ proc proposeBlock(node: BeaconNode,
|
|||
let proposal = Proposal(
|
||||
slot: slot.uint64,
|
||||
shard: BEACON_CHAIN_SHARD_NUMBER,
|
||||
block_root: Eth2Digest(data: signed_root(newBlock, "signature")),
|
||||
block_root: Eth2Digest(data: signed_root(newBlock)),
|
||||
signature: ValidatorSig(),
|
||||
)
|
||||
newBlock.signature =
|
||||
|
@ -598,7 +598,7 @@ proc onAttestation(node: BeaconNode, attestation: Attestation) =
|
|||
slot = humaneSlotNum(attestation.data.slot),
|
||||
shard = attestation.data.shard,
|
||||
beaconBlockRoot = shortLog(attestation.data.beacon_block_root),
|
||||
justifiedEpoch = humaneEpochNum(attestation.data.justified_epoch),
|
||||
sourceEpoch = humaneEpochNum(attestation.data.source_epoch),
|
||||
justifiedBlockRoot = shortLog(attestation.data.justified_block_root),
|
||||
signature = shortLog(attestation.aggregate_signature)
|
||||
|
||||
|
|
|
@ -16,6 +16,24 @@ func get_effective_balance*(state: BeaconState, index: ValidatorIndex): Gwei =
|
|||
## validator with the given ``index``.
|
||||
min(state.validator_balances[index], MAX_DEPOSIT_AMOUNT)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.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``.
|
||||
var
|
||||
value = leaf
|
||||
buf: array[64, byte]
|
||||
|
||||
for i in 0 ..< depth.int:
|
||||
if (index div (1'u64 shl i)) mod 2 != 0:
|
||||
buf[0..31] = proof[i.int].data
|
||||
buf[32..63] = value.data
|
||||
else:
|
||||
buf[0..31] = value.data
|
||||
buf[32..63] = proof[i.int].data
|
||||
value = eth2hash(buf)
|
||||
value == root
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#process_deposit
|
||||
func process_deposit(state: var BeaconState, deposit: Deposit) =
|
||||
## Process a deposit from Ethereum 1.0.
|
||||
|
@ -23,6 +41,42 @@ func process_deposit(state: var BeaconState, deposit: Deposit) =
|
|||
|
||||
let deposit_input = deposit.deposit_data.deposit_input
|
||||
|
||||
## Should equal 8 bytes for deposit_data.amount +
|
||||
## 8 bytes for deposit_data.timestamp +
|
||||
## 176 bytes for deposit_data.deposit_input
|
||||
## It should match the deposit_data in the eth1.0 deposit contract
|
||||
## TODO actual serialize func useful after all
|
||||
var serialized_deposit_data: array[8 + 8 + 176, byte]
|
||||
serialized_deposit_data[0..7] = deposit.deposit_data.amount.int_to_bytes8()
|
||||
serialized_deposit_data[8..15] =
|
||||
deposit.deposit_data.timestamp.int_to_bytes8()
|
||||
serialized_deposit_data[16..63] = deposit_input.pubkey.getBytes()
|
||||
serialized_deposit_data[64..95] = deposit_input.withdrawal_credentials.data
|
||||
serialized_deposit_data[96..191] =
|
||||
deposit_input.proof_of_possession.getBytes()
|
||||
|
||||
# Verify the Merkle branch
|
||||
let merkle_branch_is_valid = verify_merkle_branch(
|
||||
eth2hash(serialized_deposit_data),
|
||||
deposit.proof,
|
||||
DEPOSIT_CONTRACT_TREE_DEPTH,
|
||||
deposit.index,
|
||||
state.latest_eth1_data.deposit_root)
|
||||
## TODO enable this check, after using merkle_root (not in spec anymore, but
|
||||
## useful to construct proofs) to build proofs (i.e. the other child in each
|
||||
## pair of children at each level of the merkle tree), and injecting a proof
|
||||
## sequence corresponding to their hash values, into the `Deposits`, in that
|
||||
## tests/testutil.nim area of code. Currently it's checking against garbage,
|
||||
## either when creating genesis states or in the block processing of deposit
|
||||
## lists from Eth1Data.
|
||||
# doAssert merkle_branch_is_valid
|
||||
|
||||
## Increment the next deposit index we are expecting. Note that this
|
||||
## needs to be done here because while the deposit contract will never
|
||||
## create an invalid Merkle branch, it may admit an invalid deposit
|
||||
## object, and we need to be able to skip over it
|
||||
state.deposit_index += 1
|
||||
|
||||
## if not validate_proof_of_possession(
|
||||
## state, pubkey, proof_of_possession, withdrawal_credentials):
|
||||
## return
|
||||
|
@ -89,19 +143,22 @@ func initiate_validator_exit*(state: var BeaconState,
|
|||
var validator = addr state.validator_registry[index]
|
||||
validator.initiated_exit = true
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#exit_validator
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#exit_validator
|
||||
func exit_validator*(state: var BeaconState,
|
||||
index: ValidatorIndex) =
|
||||
## Exit the validator with the given ``index``.
|
||||
## Note that this function mutates ``state``.
|
||||
|
||||
let validator = addr state.validator_registry[index]
|
||||
let
|
||||
validator = addr state.validator_registry[index]
|
||||
delayed_activation_exit_epoch =
|
||||
get_delayed_activation_exit_epoch(get_current_epoch(state))
|
||||
|
||||
# The following updates only occur if not previous exited
|
||||
if validator.exit_epoch <= get_delayed_activation_exit_epoch(get_current_epoch(state)):
|
||||
if validator.exit_epoch <= delayed_activation_exit_epoch:
|
||||
return
|
||||
|
||||
validator.exit_epoch = get_delayed_activation_exit_epoch(get_current_epoch(state))
|
||||
validator.exit_epoch = delayed_activation_exit_epoch
|
||||
|
||||
func reduce_balance*(balance: var uint64, amount: uint64) =
|
||||
# Not in spec, but useful to avoid underflow.
|
||||
|
@ -228,7 +285,7 @@ func get_genesis_beacon_state*(
|
|||
|
||||
# Recent state
|
||||
# latest_block_roots, latest_active_index_roots, latest_slashed_balances,
|
||||
# latest_attestations, and batched_block_roots automatically initialized.
|
||||
# and latest_attestations automatically initialized.
|
||||
latest_block_header: get_temporary_block_header(get_empty_block()),
|
||||
)
|
||||
|
||||
|
@ -386,6 +443,7 @@ func update_validator_registry*(state: var BeaconState) =
|
|||
state.validator_registry_update_epoch = current_epoch
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#attestations-1
|
||||
# TODO this is https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#attestations now
|
||||
proc checkAttestation*(
|
||||
state: BeaconState, attestation: Attestation, flags: UpdateFlags): bool =
|
||||
## Check that an attestation follows the rules of being included in the state
|
||||
|
@ -418,15 +476,15 @@ proc checkAttestation*(
|
|||
else:
|
||||
state.previous_justified_epoch
|
||||
|
||||
if not (attestation.data.justified_epoch == expected_justified_epoch):
|
||||
if not (attestation.data.source_epoch == expected_justified_epoch):
|
||||
warn("Unexpected justified epoch",
|
||||
attestation_justified_epoch =
|
||||
humaneEpochNum(attestation.data.justified_epoch),
|
||||
humaneEpochNum(attestation.data.source_epoch),
|
||||
expected_justified_epoch = humaneEpochNum(expected_justified_epoch))
|
||||
return
|
||||
|
||||
let expected_justified_block_root =
|
||||
get_block_root(state, get_epoch_start_slot(attestation.data.justified_epoch))
|
||||
get_block_root(state, get_epoch_start_slot(attestation.data.source_epoch))
|
||||
if not (attestation.data.justified_block_root == expected_justified_block_root):
|
||||
warn("Unexpected justified block root",
|
||||
attestation_justified_block_root = attestation.data.justified_block_root,
|
||||
|
@ -434,14 +492,14 @@ proc checkAttestation*(
|
|||
return
|
||||
|
||||
if not (state.latest_crosslinks[attestation.data.shard] in [
|
||||
attestation.data.latest_crosslink,
|
||||
attestation.data.previous_crosslink,
|
||||
Crosslink(
|
||||
crosslink_data_root: attestation.data.crosslink_data_root,
|
||||
epoch: slot_to_epoch(attestation_data_slot))]):
|
||||
warn("Unexpected crosslink shard",
|
||||
state_latest_crosslinks_attestation_data_shard =
|
||||
state.latest_crosslinks[attestation.data.shard],
|
||||
attestation_data_latest_crosslink = attestation.data.latest_crosslink,
|
||||
attestation_data_previous_crosslink = attestation.data.previous_crosslink,
|
||||
epoch = humaneEpochNum(slot_to_epoch(attestation_data_slot)),
|
||||
crosslink_data_root = attestation.data.crosslink_data_root)
|
||||
return
|
||||
|
@ -545,7 +603,7 @@ proc makeAttestationData*(
|
|||
beacon_block_root: beacon_block_root,
|
||||
epoch_boundary_root: epoch_boundary_root,
|
||||
crosslink_data_root: Eth2Digest(), # Stub in phase0
|
||||
latest_crosslink: state.latest_crosslinks[shard],
|
||||
justified_epoch: state.current_justified_epoch,
|
||||
previous_crosslink: state.latest_crosslinks[shard],
|
||||
source_epoch: state.current_justified_epoch,
|
||||
justified_block_root: justified_block_root,
|
||||
)
|
||||
|
|
|
@ -83,7 +83,7 @@ const
|
|||
|
||||
# Deposit contract
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#deposit-contract
|
||||
DEPOSIT_CONTRACT_TREE_DEPTH* = 2^5
|
||||
DEPOSIT_CONTRACT_TREE_DEPTH* = 32
|
||||
|
||||
# Gwei values
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#gwei-values
|
||||
|
@ -107,7 +107,8 @@ const
|
|||
## Compile with -d:SLOTS_PER_EPOCH=4 for shorter epochs
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#initial-values
|
||||
GENESIS_FORK_VERSION* = 0'u64
|
||||
# TODO: in 0.5.0, GENESIS_FORK_VERSION defined as int, but used as [byte]
|
||||
GENESIS_FORK_VERSION* = [0'u8, 0'u8, 0'u8, 0'u8]
|
||||
GENESIS_SLOT* = (2'u64^32).Slot
|
||||
GENESIS_EPOCH* = (GENESIS_SLOT.uint64 div SLOTS_PER_EPOCH).Epoch ##\
|
||||
## slot_to_epoch(GENESIS_SLOT)
|
||||
|
@ -118,7 +119,7 @@ const
|
|||
BLS_WITHDRAWAL_PREFIX_BYTE* = 0'u8
|
||||
|
||||
# Time parameters
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#time-parameters
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#time-parameters
|
||||
SECONDS_PER_SLOT*{.intdefine.} = 6'u64 # Compile with -d:SECONDS_PER_SLOT=1 for 6x faster slots
|
||||
## TODO consistent time unit across projects, similar to C++ chrono?
|
||||
|
||||
|
@ -151,6 +152,9 @@ const
|
|||
MIN_VALIDATOR_WITHDRAWABILITY_DELAY* = 2'u64^8 ##\
|
||||
## epochs (~27 hours)
|
||||
|
||||
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
|
||||
LATEST_RANDAO_MIXES_LENGTH* = 8192
|
||||
LATEST_ACTIVE_INDEX_ROOTS_LENGTH* = 8192 # 2'u64^13, epochs
|
||||
|
@ -190,7 +194,7 @@ type
|
|||
header_2*: BeaconBlockHeader ##\
|
||||
# Second block header
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#attesterslashing
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#attesterslashing
|
||||
AttesterSlashing* = object
|
||||
slashable_attestation_1*: SlashableAttestation ## \
|
||||
## First slashable attestation
|
||||
|
@ -211,7 +215,7 @@ type
|
|||
aggregate_signature*: ValidatorSig ## \
|
||||
## Aggregate signature
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#attestation
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#attestation
|
||||
Attestation* = object
|
||||
aggregation_bitfield*: seq[byte] ##\
|
||||
## Attester aggregation bitfield
|
||||
|
@ -227,38 +231,31 @@ type
|
|||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#attestationdata
|
||||
AttestationData* = object
|
||||
slot*: Slot ##\
|
||||
## Slot number
|
||||
# LMD GHOST vote
|
||||
slot*: Slot
|
||||
beacon_block_root*: Eth2Digest
|
||||
|
||||
shard*: uint64 ##\
|
||||
## Shard number
|
||||
# FFG vote
|
||||
source_epoch*: Epoch
|
||||
## TODO epoch_boundary_root and justified_block_root are creatures of new
|
||||
## epoch processing and don't function quite as straightforwardly as just
|
||||
## renamings, so do that as part of epoch processing change.
|
||||
epoch_boundary_root*: Eth2Digest
|
||||
justified_block_root*: Eth2Digest
|
||||
|
||||
beacon_block_root*: Eth2Digest ##\
|
||||
## Hash of root of the signed beacon block
|
||||
|
||||
epoch_boundary_root*: Eth2Digest ##\
|
||||
## Hash of root of the ancestor at the epoch boundary
|
||||
|
||||
crosslink_data_root*: Eth2Digest ##\
|
||||
## Data from the shard since the last attestation
|
||||
|
||||
latest_crosslink*: Crosslink ##\
|
||||
## Last crosslink
|
||||
|
||||
justified_epoch*: Epoch ##\
|
||||
## Last justified epoch in the beacon state
|
||||
|
||||
justified_block_root*: Eth2Digest ##\
|
||||
## Hash of the last justified beacon block
|
||||
# Crosslink vote
|
||||
shard*: uint64
|
||||
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
|
||||
AttestationDataAndCustodyBit* = object
|
||||
data*: AttestationData
|
||||
custody_bit*: bool
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#deposit
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#deposit
|
||||
Deposit* = object
|
||||
branch*: seq[Eth2Digest] ##\
|
||||
proof*: array[DEPOSIT_CONTRACT_TREE_DEPTH, Eth2Digest] ##\
|
||||
## Branch in the deposit tree
|
||||
|
||||
index*: uint64 ##\
|
||||
|
@ -289,12 +286,12 @@ type
|
|||
# Validator signature
|
||||
signature*: ValidatorSig
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#transfer
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#transfer
|
||||
Transfer* = object
|
||||
from_field*: uint64 ##\
|
||||
sender*: uint64 ##\
|
||||
## Sender index
|
||||
|
||||
to*: uint64 ##\
|
||||
recipient*: uint64 ##\
|
||||
## Recipient index
|
||||
|
||||
amount*: uint64 ##\
|
||||
|
@ -433,9 +430,8 @@ type
|
|||
## `latest_block_header.state_root == ZERO_HASH` temporarily
|
||||
historical_roots*: seq[Eth2Digest]
|
||||
|
||||
# TOOD remove these, gone in 0.5
|
||||
# TOOD remove, gone in 0.5
|
||||
latest_attestations*: seq[PendingAttestation]
|
||||
batched_block_roots*: seq[Eth2Digest]
|
||||
|
||||
# Ethereum 1.0 chain data
|
||||
latest_eth1_data*: Eth1Data
|
||||
|
@ -485,9 +481,14 @@ type
|
|||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#fork
|
||||
Fork* = object
|
||||
previous_version*: uint64 # Previous fork version
|
||||
current_version*: uint64 # Current fork version
|
||||
epoch*: Epoch # Fork epoch number
|
||||
previous_version*: array[4, byte] ##\
|
||||
## Previous fork version
|
||||
|
||||
current_version*: array[4, byte] ##\
|
||||
## Current fork version
|
||||
|
||||
epoch*: Epoch ##\
|
||||
## Fork epoch number
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#eth1data
|
||||
Eth1Data* = object
|
||||
|
|
|
@ -69,24 +69,17 @@ func integer_squareroot*(n: SomeInteger): SomeInteger =
|
|||
y = (x + n div x) div 2
|
||||
x
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_fork_version
|
||||
func get_fork_version*(fork: Fork, epoch: Epoch): uint64 =
|
||||
# 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/0.4.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.
|
||||
(get_fork_version(fork, epoch) shl 32) + domain_type.uint32
|
||||
|
||||
# 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
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#merkle_root
|
||||
func merkle_root*(values: openArray[Eth2Digest]): Eth2Digest =
|
||||
## Merkleize ``values`` (where ``len(values)`` is a power of two) and return
|
||||
## the Merkle root.
|
||||
|
@ -146,8 +139,8 @@ 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.justified_epoch
|
||||
source_epoch_2 = attestation_data_2.justified_epoch
|
||||
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)
|
||||
|
@ -159,7 +152,7 @@ func is_active_validator*(validator: Validator, epoch: Epoch): bool =
|
|||
### Check if ``validator`` is active
|
||||
validator.activation_epoch <= epoch and epoch < validator.exit_epoch
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_active_validator_indices
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_active_validator_indices
|
||||
func get_active_validator_indices*(validators: openArray[Validator], epoch: Epoch): seq[ValidatorIndex] =
|
||||
## Gets indices of active validators from validators
|
||||
for idx, val in validators:
|
||||
|
@ -210,7 +203,7 @@ func get_active_index_root(state: BeaconState, epoch: Epoch): Eth2Digest =
|
|||
state.latest_active_index_roots[epoch mod LATEST_ACTIVE_INDEX_ROOTS_LENGTH]
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.2.0/specs/core/0_beacon-chain.md#bytes_to_int
|
||||
func bytes_to_int*(data: seq[byte]): uint64 =
|
||||
func bytes_to_int*(data: openarray[byte]): uint64 =
|
||||
doAssert data.len == 8
|
||||
|
||||
# Little-endian data representation
|
||||
|
@ -219,7 +212,7 @@ func bytes_to_int*(data: seq[byte]): uint64 =
|
|||
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-
|
||||
# Have 1, 4, and 32-byte versions. 2+ 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] =
|
||||
## Little-endian data representation
|
||||
## TODO remove uint64 when those callers fade away
|
||||
|
@ -228,6 +221,10 @@ func int_to_bytes32*(x: uint64): array[32, byte] =
|
|||
|
||||
func int_to_bytes32*(x: Epoch): array[32, byte] {.borrow.}
|
||||
|
||||
func int_to_bytes8*(x: uint64): array[8, byte] =
|
||||
for i in 0 ..< 8:
|
||||
result[i] = byte((x shr i*8) and 0xff)
|
||||
|
||||
func int_to_bytes1*(x: int): array[1, byte] =
|
||||
doAssert x >= 0
|
||||
doAssert x < 256
|
||||
|
@ -244,6 +241,15 @@ 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
|
||||
func get_domain*(
|
||||
fork: Fork, epoch: Epoch, domain_type: SignatureDomain): uint64 =
|
||||
# Get the domain number that represents the fork meta and signature domain.
|
||||
var buf: array[8, byte]
|
||||
buf[0..3] = get_fork_version(fork, epoch)
|
||||
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 generate_seed*(state: BeaconState, epoch: Epoch): Eth2Digest =
|
||||
# Generate a seed for the given ``epoch``.
|
||||
|
|
|
@ -12,8 +12,8 @@ import
|
|||
../ssz,
|
||||
./crypto, ./datatypes, ./digest, ./helpers
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_shuffling
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#get_permuted_index
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_shuffling
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#get_permuted_index
|
||||
func get_shuffled_seq*(seed: Eth2Digest,
|
||||
list_size: uint64,
|
||||
): seq[ValidatorIndex] =
|
||||
|
|
|
@ -315,12 +315,13 @@ func hash_tree_root*[T: object|tuple](x: T): array[32, byte] =
|
|||
h.update hash_tree_root(field.toSSZType)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/simple-serialize.md#signed-roots
|
||||
func signed_root*[T: object](x: T, ignored: string = "sig"): array[32, byte] =
|
||||
func signed_root*[T: object](x: T): array[32, byte] =
|
||||
# TODO write tests for this (check vs hash_tree_root)
|
||||
|
||||
var found_field_name = false
|
||||
|
||||
## TODO this isn't how 0.5 defines signed_root, but works well enough
|
||||
## for now.
|
||||
withHash:
|
||||
for name, field in x.fieldPairs:
|
||||
if name == "signature":
|
||||
|
|
|
@ -51,11 +51,11 @@ func verifyBlockSignature(state: BeaconState, blck: BeaconBlock): bool =
|
|||
proposal = Proposal(
|
||||
slot: blck.slot.uint64,
|
||||
shard: BEACON_CHAIN_SHARD_NUMBER,
|
||||
block_root: Eth2Digest(data: signed_root(blck, "signature")),
|
||||
block_root: Eth2Digest(data: signed_root(blck)),
|
||||
signature: blck.signature)
|
||||
bls_verify(
|
||||
proposer.pubkey,
|
||||
signed_root(proposal, "signature"),
|
||||
signed_root(proposal),
|
||||
proposal.signature,
|
||||
get_domain(state.fork, get_current_epoch(state), DOMAIN_BEACON_BLOCK))
|
||||
|
||||
|
@ -126,8 +126,8 @@ proc processRandao(
|
|||
|
||||
true
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#eth1-data
|
||||
func processDepositRoot(state: var BeaconState, blck: BeaconBlock) =
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#eth1-data-1
|
||||
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:
|
||||
|
@ -344,7 +344,7 @@ proc processTransfers(state: var BeaconState, blck: BeaconBlock,
|
|||
return false
|
||||
|
||||
for transfer in blck.body.transfers:
|
||||
let from_balance = state.validator_balances[transfer.from_field.int]
|
||||
let from_balance = state.validator_balances[transfer.sender.int]
|
||||
|
||||
if not (from_balance >= transfer.amount):
|
||||
notice "Transfer: source balance too low for amount"
|
||||
|
@ -365,13 +365,13 @@ proc processTransfers(state: var BeaconState, blck: BeaconBlock,
|
|||
|
||||
if not (get_current_epoch(state) >=
|
||||
state.validator_registry[
|
||||
transfer.from_field.int].withdrawable_epoch or
|
||||
state.validator_registry[transfer.from_field.int].activation_epoch ==
|
||||
transfer.sender.int].withdrawable_epoch or
|
||||
state.validator_registry[transfer.sender.int].activation_epoch ==
|
||||
FAR_FUTURE_EPOCH):
|
||||
notice "Transfer: epoch mismatch"
|
||||
return false
|
||||
|
||||
let wc = state.validator_registry[transfer.from_field.int].
|
||||
let wc = state.validator_registry[transfer.sender.int].
|
||||
withdrawal_credentials
|
||||
if not (wc.data[0] == BLS_WITHDRAWAL_PREFIX_BYTE and
|
||||
wc.data[1..^1] == eth2hash(transfer.pubkey.getBytes).data[1..^1]):
|
||||
|
@ -389,9 +389,9 @@ proc processTransfers(state: var BeaconState, blck: BeaconBlock,
|
|||
|
||||
# TODO https://github.com/ethereum/eth2.0-specs/issues/727
|
||||
reduce_balance(
|
||||
state.validator_balances[transfer.from_field.int],
|
||||
state.validator_balances[transfer.sender.int],
|
||||
transfer.amount + transfer.fee)
|
||||
state.validator_balances[transfer.to.int] += transfer.amount
|
||||
state.validator_balances[transfer.recipient.int] += transfer.amount
|
||||
state.validator_balances[
|
||||
get_beacon_proposer_index(state, state.slot)] += transfer.fee
|
||||
|
||||
|
@ -431,8 +431,6 @@ func processSlot(state: var BeaconState, previous_block_root: Eth2Digest) =
|
|||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#block-roots
|
||||
state.latest_block_roots[(state.slot - 1) mod SLOTS_PER_HISTORICAL_ROOT] =
|
||||
previous_block_root
|
||||
if state.slot mod SLOTS_PER_HISTORICAL_ROOT == 0:
|
||||
state.batched_block_roots.add(merkle_root(state.latest_block_roots))
|
||||
|
||||
proc processBlock(
|
||||
state: var BeaconState, blck: BeaconBlock, flags: UpdateFlags): bool =
|
||||
|
@ -478,7 +476,7 @@ proc processBlock(
|
|||
if not processRandao(state, blck, flags):
|
||||
return false
|
||||
|
||||
processDepositRoot(state, blck)
|
||||
processEth1Data(state, blck)
|
||||
|
||||
if not processProposerSlashings(state, blck, flags):
|
||||
return false
|
||||
|
@ -534,7 +532,6 @@ func process_slashings(state: var BeaconState) =
|
|||
current_epoch = get_current_epoch(state)
|
||||
active_validator_indices = get_active_validator_indices(
|
||||
state.validator_registry, current_epoch)
|
||||
# 0.4.0 spec doesn't use this helper function?
|
||||
total_balance = get_total_balance(state, active_validator_indices)
|
||||
|
||||
for index, validator in state.validator_registry:
|
||||
|
@ -591,7 +588,6 @@ func processEpoch(state: var BeaconState) =
|
|||
if (state.slot + 1) mod SLOTS_PER_EPOCH != 0:
|
||||
return
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#helper-variables
|
||||
let
|
||||
current_epoch = get_current_epoch(state)
|
||||
previous_epoch = get_previous_epoch(state)
|
||||
|
@ -998,7 +994,7 @@ func processEpoch(state: var BeaconState) =
|
|||
not (slot_to_epoch(it.data.slot) < current_epoch)
|
||||
)
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#state-root-verification
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#state-root-verification
|
||||
proc verifyStateRoot(state: BeaconState, blck: BeaconBlock): bool =
|
||||
let state_root = hash_tree_root_final(state)
|
||||
if state_root != blck.state_root:
|
||||
|
|
|
@ -30,7 +30,7 @@ proc signBlockProposal*(v: AttachedValidator, fork: Fork,
|
|||
await sleepAsync(1)
|
||||
let proposalRoot = hash_tree_root_final(proposal)
|
||||
|
||||
result = bls_sign(v.privKey, signed_root(proposal, "signature"),
|
||||
result = bls_sign(v.privKey, signed_root(proposal),
|
||||
get_domain(fork, slot_to_epoch(proposal.slot), DOMAIN_BEACON_BLOCK))
|
||||
else:
|
||||
# TODO:
|
||||
|
|
|
@ -47,6 +47,7 @@ func makeDeposit(i: int, flags: UpdateFlags): Deposit =
|
|||
bls_sign(privkey, hash_tree_root_final(proof_of_possession_data).data, domain)
|
||||
|
||||
Deposit(
|
||||
index: i.uint64,
|
||||
deposit_data: DepositData(
|
||||
deposit_input: DepositInput(
|
||||
pubkey: pubkey,
|
||||
|
@ -85,7 +86,7 @@ proc addBlock*(
|
|||
# Ferret out remaining GENESIS_EPOCH == 0 assumptions in test code
|
||||
doAssert allIt(
|
||||
body.attestations,
|
||||
it.data.latest_crosslink.epoch >= GENESIS_EPOCH)
|
||||
it.data.previous_crosslink.epoch >= GENESIS_EPOCH)
|
||||
|
||||
let
|
||||
# Index from the new state, but registry from the old state.. hmm...
|
||||
|
@ -125,10 +126,10 @@ proc addBlock*(
|
|||
signed_data = Proposal(
|
||||
slot: new_block.slot.uint64,
|
||||
shard: BEACON_CHAIN_SHARD_NUMBER,
|
||||
block_root: Eth2Digest(data: signed_root(new_block, "signature")),
|
||||
block_root: Eth2Digest(data: signed_root(new_block)),
|
||||
signature: ValidatorSig(),
|
||||
)
|
||||
proposal_hash = signed_root(signed_data, "signature")
|
||||
proposal_hash = signed_root(signed_data)
|
||||
|
||||
doAssert proposerPrivkey.pubKey() == proposer.pubkey,
|
||||
"signature key should be derived from private key! - wrong privkey?"
|
||||
|
|
Loading…
Reference in New Issue