From 798197879b47ca51d12863495855f67bb6be5e48 Mon Sep 17 00:00:00 2001 From: Dustin Brody Date: Sun, 17 Mar 2019 15:24:50 -0700 Subject: [PATCH] Revert "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" This reverts commit 18f1d000a19cd88db6ea832af74d2b489b730cfb. --- beacon_chain/attestation_pool.nim | 6 +-- 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, 90 insertions(+), 153 deletions(-) diff --git a/beacon_chain/attestation_pool.nim b/beacon_chain/attestation_pool.nim index 5fab6c1fc..bc40bc9af 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), - sourceEpoch = humaneEpochNum(attestation.data.source_epoch), + justifiedEpoch = humaneEpochNum(attestation.data.justified_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), - sourceEpoch = humaneEpochNum(attestation.data.source_epoch), + justifiedEpoch = humaneEpochNum(attestation.data.justified_epoch), justifiedBlockRoot = shortLog(attestation.data.justified_block_root), signature = shortLog(attestation.aggregate_signature), validations = 1 @@ -350,4 +350,4 @@ proc resolve*(pool: var AttestationPool, state: BeaconState) = proc latestAttestation*( pool: AttestationPool, pubKey: ValidatorPubKey): BlockRef = - pool.latestAttestations.getOrDefault(pubKey) + pool.latestAttestations.getOrDefault(pubKey) \ No newline at end of file diff --git a/beacon_chain/beacon_node.nim b/beacon_chain/beacon_node.nim index ab130236c..3bed51190 100644 --- a/beacon_chain/beacon_node.nim +++ b/beacon_chain/beacon_node.nim @@ -312,7 +312,7 @@ proc proposeBlock(node: BeaconNode, let proposal = Proposal( slot: slot.uint64, shard: BEACON_CHAIN_SHARD_NUMBER, - block_root: Eth2Digest(data: signed_root(newBlock)), + block_root: Eth2Digest(data: signed_root(newBlock, "signature")), signature: ValidatorSig(), ) newBlock.signature = @@ -523,7 +523,7 @@ proc onAttestation(node: BeaconNode, attestation: Attestation) = slot = humaneSlotNum(attestation.data.slot), shard = attestation.data.shard, beaconBlockRoot = shortLog(attestation.data.beacon_block_root), - sourceEpoch = humaneEpochNum(attestation.data.source_epoch), + justifiedEpoch = humaneEpochNum(attestation.data.justified_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 4371bda59..25241e4dc 100644 --- a/beacon_chain/spec/beaconstate.nim +++ b/beacon_chain/spec/beaconstate.nim @@ -16,24 +16,6 @@ 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. @@ -41,42 +23,6 @@ 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 @@ -143,22 +89,19 @@ 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/v0.5.0/specs/core/0_beacon-chain.md#exit_validator +# https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#exit_validator func exit_validator*(state: var BeaconState, index: ValidatorIndex) = ## Exit the validator with the given ``index``. ## Note that this function mutates ``state``. - let - validator = addr state.validator_registry[index] - delayed_activation_exit_epoch = - get_delayed_activation_exit_epoch(get_current_epoch(state)) + let validator = addr state.validator_registry[index] # The following updates only occur if not previous exited - if validator.exit_epoch <= delayed_activation_exit_epoch: + if validator.exit_epoch <= get_delayed_activation_exit_epoch(get_current_epoch(state)): return - validator.exit_epoch = delayed_activation_exit_epoch + validator.exit_epoch = get_delayed_activation_exit_epoch(get_current_epoch(state)) func reduce_balance*(balance: var uint64, amount: uint64) = # Not in spec, but useful to avoid underflow. @@ -285,7 +228,7 @@ func get_genesis_beacon_state*( # Recent state # latest_block_roots, latest_active_index_roots, latest_slashed_balances, - # and latest_attestations automatically initialized. + # latest_attestations, and batched_block_roots automatically initialized. latest_block_header: get_temporary_block_header(get_empty_block()), ) @@ -443,7 +386,6 @@ 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 @@ -476,15 +418,15 @@ proc checkAttestation*( else: state.previous_justified_epoch - if not (attestation.data.source_epoch == expected_justified_epoch): + if not (attestation.data.justified_epoch == expected_justified_epoch): warn("Unexpected justified epoch", attestation_justified_epoch = - humaneEpochNum(attestation.data.source_epoch), + humaneEpochNum(attestation.data.justified_epoch), expected_justified_epoch = humaneEpochNum(expected_justified_epoch)) return let expected_justified_block_root = - get_block_root(state, get_epoch_start_slot(attestation.data.source_epoch)) + get_block_root(state, get_epoch_start_slot(attestation.data.justified_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, @@ -492,14 +434,14 @@ proc checkAttestation*( return if not (state.latest_crosslinks[attestation.data.shard] in [ - attestation.data.previous_crosslink, + attestation.data.latest_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_previous_crosslink = attestation.data.previous_crosslink, + attestation_data_latest_crosslink = attestation.data.latest_crosslink, epoch = humaneEpochNum(slot_to_epoch(attestation_data_slot)), crosslink_data_root = attestation.data.crosslink_data_root) return @@ -603,7 +545,7 @@ proc makeAttestationData*( beacon_block_root: beacon_block_root, epoch_boundary_root: epoch_boundary_root, crosslink_data_root: Eth2Digest(), # Stub in phase0 - previous_crosslink: state.latest_crosslinks[shard], - source_epoch: state.current_justified_epoch, + latest_crosslink: state.latest_crosslinks[shard], + justified_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 d8ff5445b..6d1721029 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* = 32 + DEPOSIT_CONTRACT_TREE_DEPTH* = 2^5 # Gwei values # https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#gwei-values @@ -107,8 +107,7 @@ 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 - # 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_FORK_VERSION* = 0'u64 GENESIS_SLOT* = (2'u64^32).Slot GENESIS_EPOCH* = (GENESIS_SLOT.uint64 div SLOTS_PER_EPOCH).Epoch ##\ ## slot_to_epoch(GENESIS_SLOT) @@ -119,7 +118,7 @@ const BLS_WITHDRAWAL_PREFIX_BYTE* = 0'u8 # Time parameters - # https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#time-parameters + # https://github.com/ethereum/eth2.0-specs/blob/0.4.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? @@ -152,9 +151,6 @@ 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 @@ -194,7 +190,7 @@ 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/0.4.0/specs/core/0_beacon-chain.md#attesterslashing AttesterSlashing* = object slashable_attestation_1*: SlashableAttestation ## \ ## First slashable attestation @@ -215,7 +211,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/0.4.0/specs/core/0_beacon-chain.md#attestation Attestation* = object aggregation_bitfield*: seq[byte] ##\ ## Attester aggregation bitfield @@ -231,31 +227,38 @@ type # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#attestationdata AttestationData* = object - # LMD GHOST vote - slot*: Slot - beacon_block_root*: Eth2Digest + slot*: Slot ##\ + ## Slot 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 + shard*: uint64 ##\ + ## Shard number - # Crosslink vote - shard*: uint64 - previous_crosslink*: Crosslink - crosslink_data_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 # 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/v0.5.0/specs/core/0_beacon-chain.md#deposit + # https://github.com/ethereum/eth2.0-specs/blob/0.4.0/specs/core/0_beacon-chain.md#deposit Deposit* = object - proof*: array[DEPOSIT_CONTRACT_TREE_DEPTH, Eth2Digest] ##\ + branch*: seq[Eth2Digest] ##\ ## Branch in the deposit tree index*: uint64 ##\ @@ -286,12 +289,12 @@ 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/0.4.0/specs/core/0_beacon-chain.md#transfer Transfer* = object - sender*: uint64 ##\ + from_field*: uint64 ##\ ## Sender index - recipient*: uint64 ##\ + to*: uint64 ##\ ## Recipient index amount*: uint64 ##\ @@ -430,8 +433,9 @@ type ## `latest_block_header.state_root == ZERO_HASH` temporarily historical_roots*: seq[Eth2Digest] - # TOOD remove, gone in 0.5 + # TOOD remove these, gone in 0.5 latest_attestations*: seq[PendingAttestation] + batched_block_roots*: seq[Eth2Digest] # Ethereum 1.0 chain data latest_eth1_data*: Eth1Data @@ -481,14 +485,9 @@ type # https://github.com/ethereum/eth2.0-specs/blob/v0.5.0/specs/core/0_beacon-chain.md#fork Fork* = object - previous_version*: array[4, byte] ##\ - ## Previous fork version - - current_version*: array[4, byte] ##\ - ## Current fork version - - epoch*: Epoch ##\ - ## Fork epoch number + previous_version*: uint64 # Previous fork version + current_version*: uint64 # 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 9fad0a288..a02d2deef 100644 --- a/beacon_chain/spec/helpers.nim +++ b/beacon_chain/spec/helpers.nim @@ -69,17 +69,24 @@ 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] = +# 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 = ## 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. @@ -139,8 +146,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.source_epoch - source_epoch_2 = attestation_data_2.source_epoch + source_epoch_1 = attestation_data_1.justified_epoch + source_epoch_2 = attestation_data_2.justified_epoch # RLP artifact target_epoch_1 = slot_to_epoch(attestation_data_1.slot) target_epoch_2 = slot_to_epoch(attestation_data_2.slot) @@ -152,7 +159,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/v0.5.0/specs/core/0_beacon-chain.md#get_active_validator_indices +# https://github.com/ethereum/eth2.0-specs/blob/0.4.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: @@ -203,7 +210,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: openarray[byte]): uint64 = +func bytes_to_int*(data: seq[byte]): uint64 = doAssert data.len == 8 # Little-endian data representation @@ -212,7 +219,7 @@ func bytes_to_int*(data: openarray[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, 8, and 32-byte versions. 1+ more and maybe worth metaprogramming. +# Have 1, 4, and 32-byte versions. 2+ 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 @@ -221,10 +228,6 @@ 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 @@ -241,15 +244,6 @@ 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 9d510714d..040ff77f5 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/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 +# 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 func get_shuffled_seq*(seed: Eth2Digest, list_size: uint64, ): seq[ValidatorIndex] = diff --git a/beacon_chain/ssz.nim b/beacon_chain/ssz.nim index 60e21f615..9b9e085ce 100644 --- a/beacon_chain/ssz.nim +++ b/beacon_chain/ssz.nim @@ -315,13 +315,12 @@ 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): array[32, byte] = +func signed_root*[T: object](x: T, ignored: string = "sig"): 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 6fbda28d1..876acc396 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)), + block_root: Eth2Digest(data: signed_root(blck, "signature")), signature: blck.signature) bls_verify( proposer.pubkey, - signed_root(proposal), + signed_root(proposal, "signature"), 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/v0.5.0/specs/core/0_beacon-chain.md#eth1-data-1 -func processEth1Data(state: var BeaconState, blck: BeaconBlock) = +# 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) = # 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.sender.int] + let from_balance = state.validator_balances[transfer.from_field.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.sender.int].withdrawable_epoch or - state.validator_registry[transfer.sender.int].activation_epoch == + transfer.from_field.int].withdrawable_epoch or + state.validator_registry[transfer.from_field.int].activation_epoch == FAR_FUTURE_EPOCH): notice "Transfer: epoch mismatch" return false - let wc = state.validator_registry[transfer.sender.int]. + let wc = state.validator_registry[transfer.from_field.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.sender.int], + state.validator_balances[transfer.from_field.int], transfer.amount + transfer.fee) - state.validator_balances[transfer.recipient.int] += transfer.amount + state.validator_balances[transfer.to.int] += transfer.amount state.validator_balances[ get_beacon_proposer_index(state, state.slot)] += transfer.fee @@ -431,6 +431,8 @@ 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 = @@ -476,7 +478,7 @@ proc processBlock( if not processRandao(state, blck, flags): return false - processEth1Data(state, blck) + processDepositRoot(state, blck) if not processProposerSlashings(state, blck, flags): return false @@ -532,6 +534,7 @@ 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: @@ -588,6 +591,7 @@ 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) @@ -994,7 +998,7 @@ func processEpoch(state: var BeaconState) = not (slot_to_epoch(it.data.slot) < current_epoch) ) -# 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/0.4.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 ede42c3d5..46d493202 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), + result = bls_sign(v.privKey, signed_root(proposal, "signature"), get_domain(fork, slot_to_epoch(proposal.slot), DOMAIN_BEACON_BLOCK)) else: # TODO: diff --git a/tests/testutil.nim b/tests/testutil.nim index f2236652c..abfdec495 100644 --- a/tests/testutil.nim +++ b/tests/testutil.nim @@ -47,7 +47,6 @@ 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, @@ -86,7 +85,7 @@ proc addBlock*( # Ferret out remaining GENESIS_EPOCH == 0 assumptions in test code doAssert allIt( body.attestations, - it.data.previous_crosslink.epoch >= GENESIS_EPOCH) + it.data.latest_crosslink.epoch >= GENESIS_EPOCH) let # Index from the new state, but registry from the old state.. hmm... @@ -126,10 +125,10 @@ proc addBlock*( signed_data = Proposal( slot: new_block.slot.uint64, shard: BEACON_CHAIN_SHARD_NUMBER, - block_root: Eth2Digest(data: signed_root(new_block)), + block_root: Eth2Digest(data: signed_root(new_block, "signature")), signature: ValidatorSig(), ) - proposal_hash = signed_root(signed_data) + proposal_hash = signed_root(signed_data, "signature") doAssert proposerPrivkey.pubKey() == proposer.pubkey, "signature key should be derived from private key! - wrong privkey?"