From 2bc632c29b019caaadb2edd259d5b6b94aea8a71 Mon Sep 17 00:00:00 2001 From: Dustin Brody Date: Mon, 18 Mar 2019 15:42:42 +0000 Subject: [PATCH] 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) --- beacon_chain/attestation_pool.nim | 4 +- beacon_chain/beacon_node.nim | 4 +- beacon_chain/spec/beaconstate.nim | 82 ++++++++++++++++++++++++++----- beacon_chain/spec/datatypes.nim | 73 +++++++++++++-------------- beacon_chain/spec/helpers.nim | 34 +++++++------ beacon_chain/spec/validator.nim | 4 +- beacon_chain/ssz.nim | 3 +- beacon_chain/state_transition.nim | 28 +++++------ beacon_chain/validator_pool.nim | 2 +- tests/testutil.nim | 7 +-- 10 files changed, 152 insertions(+), 89 deletions(-) diff --git a/beacon_chain/attestation_pool.nim b/beacon_chain/attestation_pool.nim index f9128f28f..5b3bd8067 100644 --- a/beacon_chain/attestation_pool.nim +++ b/beacon_chain/attestation_pool.nim @@ -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 diff --git a/beacon_chain/beacon_node.nim b/beacon_chain/beacon_node.nim index a842b24d4..f6bc17ecb 100644 --- a/beacon_chain/beacon_node.nim +++ b/beacon_chain/beacon_node.nim @@ -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) diff --git a/beacon_chain/spec/beaconstate.nim b/beacon_chain/spec/beaconstate.nim index 25241e4dc..4371bda59 100644 --- a/beacon_chain/spec/beaconstate.nim +++ b/beacon_chain/spec/beaconstate.nim @@ -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, ) diff --git a/beacon_chain/spec/datatypes.nim b/beacon_chain/spec/datatypes.nim index 6d1721029..d8ff5445b 100644 --- a/beacon_chain/spec/datatypes.nim +++ b/beacon_chain/spec/datatypes.nim @@ -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 diff --git a/beacon_chain/spec/helpers.nim b/beacon_chain/spec/helpers.nim index a02d2deef..9fad0a288 100644 --- a/beacon_chain/spec/helpers.nim +++ b/beacon_chain/spec/helpers.nim @@ -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``. diff --git a/beacon_chain/spec/validator.nim b/beacon_chain/spec/validator.nim index 040ff77f5..9d510714d 100644 --- a/beacon_chain/spec/validator.nim +++ b/beacon_chain/spec/validator.nim @@ -12,8 +12,8 @@ import ../ssz, ./crypto, ./datatypes, ./digest, ./helpers -# https://github.com/ethereum/eth2.0-specs/blob/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] = diff --git a/beacon_chain/ssz.nim b/beacon_chain/ssz.nim index 9b9e085ce..60e21f615 100644 --- a/beacon_chain/ssz.nim +++ b/beacon_chain/ssz.nim @@ -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": diff --git a/beacon_chain/state_transition.nim b/beacon_chain/state_transition.nim index 876acc396..6fbda28d1 100644 --- a/beacon_chain/state_transition.nim +++ b/beacon_chain/state_transition.nim @@ -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: diff --git a/beacon_chain/validator_pool.nim b/beacon_chain/validator_pool.nim index 46d493202..ede42c3d5 100644 --- a/beacon_chain/validator_pool.nim +++ b/beacon_chain/validator_pool.nim @@ -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: diff --git a/tests/testutil.nim b/tests/testutil.nim index abfdec495..f2236652c 100644 --- a/tests/testutil.nim +++ b/tests/testutil.nim @@ -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?"