diff --git a/beacon_chain/spec/beaconstate.nim b/beacon_chain/spec/beaconstate.nim index d80531650..7e36c1378 100644 --- a/beacon_chain/spec/beaconstate.nim +++ b/beacon_chain/spec/beaconstate.nim @@ -82,7 +82,7 @@ func on_startup*(initial_validator_entries: openArray[InitialValidator], # Recent state latest_state_recalculation_slot: INITIAL_SLOT_NUMBER, - latest_block_hashes: repeat(ZERO_HASH, EPOCH_LENGTH * 2), + latest_block_roots: repeat(ZERO_HASH, EPOCH_LENGTH * 2), # PoW receipt root processed_pow_receipt_root: processed_pow_receipt_root, @@ -95,19 +95,19 @@ func on_startup*(initial_validator_entries: openArray[InitialValidator], ), ) -func get_block_hash*(state: BeaconState, +func get_block_root*(state: BeaconState, slot: uint64): Eth2Digest = let earliest_slot_in_array = - state.slot - len(state.latest_block_hashes).uint64 + state.slot - len(state.latest_block_roots).uint64 assert earliest_slot_in_array <= slot assert slot < state.slot - state.latest_block_hashes[(slot - earliest_slot_in_array).int] + state.latest_block_roots[(slot - earliest_slot_in_array).int] -func append_to_recent_block_hashes*(old_block_hashes: seq[Eth2Digest], +func append_to_recent_block_roots*(old_block_roots: seq[Eth2Digest], parent_slot, current_slot: uint64, parent_hash: Eth2Digest): seq[Eth2Digest] = let d = current_slot - parent_slot - result = old_block_hashes + result = old_block_roots result.add repeat(parent_hash, d) func get_attestation_participants*(state: BeaconState, @@ -180,14 +180,14 @@ func checkAttestation*(state: BeaconState, attestation: Attestation): bool = if attestation.data.justified_slot != expected_justified_slot: return - let expected_justified_block_hash = - get_block_hash(state, attestation.data.justified_slot) - if attestation.data.justified_block_hash != expected_justified_block_hash: + let expected_justified_block_root = + get_block_root(state, attestation.data.justified_slot) + if attestation.data.justified_block_root != expected_justified_block_root: return - if state.latest_crosslinks[attestation.data.shard].shard_block_hash notin [ - attestation.data.latest_crosslink_hash, - attestation.data.shard_block_hash]: + if state.latest_crosslinks[attestation.data.shard].shard_block_root notin [ + attestation.data.latest_crosslink_root, + attestation.data.shard_block_root]: return let @@ -197,7 +197,7 @@ func checkAttestation*(state: BeaconState, attestation: Attestation): bool = participants, state.validator_registry[it].pubkey)) # Verify that aggregate_signature verifies using the group pubkey. - let msg = hashSSZ(attestation.data) + let msg = hash_tree_root(attestation.data) if not BLSVerify( group_public_key, @msg & @[0'u8], attestation.aggregate_signature, @@ -206,7 +206,7 @@ func checkAttestation*(state: BeaconState, attestation: Attestation): bool = return # To be removed in Phase1: - if attestation.data.shard_block_hash != ZERO_HASH: + if attestation.data.shard_block_root != ZERO_HASH: return true diff --git a/beacon_chain/spec/datatypes.nim b/beacon_chain/spec/datatypes.nim index d13c68491..f7f32171b 100644 --- a/beacon_chain/spec/datatypes.nim +++ b/beacon_chain/spec/datatypes.nim @@ -154,22 +154,22 @@ type AttestationData* = object slot*: uint64 shard*: uint64 - beacon_block_hash*: Eth2Digest ##\ + beacon_block_root*: Eth2Digest ##\ ## Hash of the block we're signing - epoch_boundary_hash*: Eth2Digest ##\ + epoch_boundary_root*: Eth2Digest ##\ ## Hash of the ancestor at the cycle boundary - shard_block_hash*: Eth2Digest ##\ + shard_block_root*: Eth2Digest ##\ ## Shard block hash being attested to - latest_crosslink_hash*: Eth2Digest ##\ + latest_crosslink_root*: Eth2Digest ##\ ## Last crosslink hash justified_slot*: uint64 ##\ ## Slot of last justified beacon block - justified_block_hash*: Eth2Digest ##\ + justified_block_root*: Eth2Digest ##\ ## Hash of last justified beacon block Deposit* = object @@ -237,7 +237,7 @@ type slot*: uint64 shard*: uint64 ##\ ## Shard number (or `BEACON_CHAIN_SHARD_NUMBER` for beacon chain) - block_hash*: Eth2Digest + block_root*: Eth2Digest BeaconState* = object slot*: uint64 @@ -269,7 +269,7 @@ type latest_crosslinks*: array[SHARD_COUNT, CrosslinkRecord] latest_state_recalculation_slot*: uint64 - latest_block_hashes*: seq[Eth2Digest] ##\ + latest_block_roots*: seq[Eth2Digest] ##\ ## Needed to process attestations, older to newer latest_penalized_exit_balances*: seq[uint64] ##\ ## Balances penalized in the current withdrawal period @@ -290,7 +290,7 @@ type CrosslinkRecord* = object slot*: uint64 # Slot number - shard_block_hash*: Eth2Digest # Shard chain block hash + shard_block_root*: Eth2Digest # Shard chain block hash ShardCommittee* = object shard*: uint64 # Shard number diff --git a/beacon_chain/spec/helpers.nim b/beacon_chain/spec/helpers.nim index 923419215..b2a0452d2 100644 --- a/beacon_chain/spec/helpers.nim +++ b/beacon_chain/spec/helpers.nim @@ -68,15 +68,15 @@ 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 -func get_new_recent_block_hashes*(old_block_hashes: seq[Eth2Digest], +func get_new_recent_block_roots*(old_block_roots: seq[Eth2Digest], parent_slot, current_slot: int64, parent_hash: Eth2Digest ): seq[Eth2Digest] = # Should throw for `current_slot - CYCLE_LENGTH * 2 - 1` according to spec comment let d = current_slot - parent_slot - result = old_block_hashes[d .. ^1] - for _ in 0 ..< min(d, old_block_hashes.len): + result = old_block_roots[d .. ^1] + for _ in 0 ..< min(d, old_block_roots.len): result.add parent_hash func ceil_div8*(v: int): int = (v + 7) div 8 # TODO use a proper bitarray! diff --git a/beacon_chain/spec/validator.nim b/beacon_chain/spec/validator.nim index c5df8e605..031c6ba2b 100644 --- a/beacon_chain/spec/validator.nim +++ b/beacon_chain/spec/validator.nim @@ -36,7 +36,7 @@ func get_new_validators*(current_validators: seq[ValidatorRecord], # # Check that validator really did register # TODO fix tests and enable (nightmare) - # let msg = hashSSZ((pubkey, withdrawal_credentials, randao_commitment)) + # let msg = hash_tree_root((pubkey, withdrawal_credentials, randao_commitment)) # assert BLSVerify( # pubkey, msg, proof_of_possession, # get_domain(fork_data, current_slot, DOMAIN_DEPOSIT)) @@ -121,10 +121,10 @@ func get_new_validator_registry_delta_chain_tip( ## Compute the next hash in the validator registry delta hash chain. withEth2Hash: - h.update hashSSZ(current_validator_registry_delta_chain_tip) - h.update hashSSZ(flag.uint8) - h.update hashSSZ(index) - h.update hashSSZ(pubkey) + h.update hash_tree_root(current_validator_registry_delta_chain_tip) + h.update hash_tree_root(flag.uint8) + h.update hash_tree_root(index) + h.update hash_tree_root(pubkey) func get_effective_balance*(validator: ValidatorRecord): uint64 = min(validator.balance, MAX_DEPOSIT) diff --git a/beacon_chain/ssz.nim b/beacon_chain/ssz.nim index 72d33f19a..34965bc63 100644 --- a/beacon_chain/ssz.nim +++ b/beacon_chain/ssz.nim @@ -130,7 +130,7 @@ func serialize*[T](value: T): seq[byte] = # ################### Hashing ################################### -# Sample hashSSZ implementation based on: +# Sample hash_tree_root implementation based on: # https://github.com/ethereum/eth2.0-specs/blob/98312f40b5742de6aa73f24e6225ee68277c4614/specs/simple-serialize.md # and # https://github.com/ethereum/beacon_chain/pull/134 @@ -163,46 +163,46 @@ func merkleHash[T](lst: seq[T]): array[32, byte] # ################### Hashing interface ################################### -func hashSSZ*(x: SomeInteger): array[sizeof(x), byte] = +func hash_tree_root*(x: SomeInteger): array[sizeof(x), byte] = ## Convert directly to bytes the size of the int. (e.g. ``uint16 = 2 bytes``) ## All integers are serialized as **big endian**. toBytesSSZ(x) -func hashSSZ*(x: Uint24): array[3, byte] = +func hash_tree_root*(x: Uint24): array[3, byte] = ## Convert directly to bytes the size of the int. (e.g. ``uint16 = 2 bytes``) ## All integers are serialized as **big endian**. toBytesSSZ(x) -func hashSSZ*(x: EthAddress): array[sizeof(x), byte] = +func hash_tree_root*(x: EthAddress): array[sizeof(x), byte] = ## Addresses copied as-is toBytesSSZ(x) -func hashSSZ*(x: Eth2Digest): array[32, byte] = +func hash_tree_root*(x: Eth2Digest): array[32, byte] = ## Hash32 copied as-is toBytesSSZ(x) -func hashSSZ*(x: openArray[byte]): array[32, byte] = +func hash_tree_root*(x: openArray[byte]): array[32, byte] = ## Blobs are hashed hash(x) -func hashSSZ*(x: ValidatorRecord): array[32, byte] = +func hash_tree_root*(x: ValidatorRecord): array[32, byte] = ## Containers have their fields recursively hashed, concatenated and hashed # TODO hash_ssz.py code contains special cases for some types, why? withHash: # tmp.add(x.pubkey) # TODO uncertain future of public key format - h.update hashSSZ(x.withdrawal_credentials) - h.update hashSSZ(x.randao_skips) - h.update hashSSZ(x.balance) - # h.update hashSSZ(x.status) # TODO it's an enum, deal with it - h.update hashSSZ(x.latest_status_change_slot) - h.update hashSSZ(x.exit_count) + h.update hash_tree_root(x.withdrawal_credentials) + h.update hash_tree_root(x.randao_skips) + h.update hash_tree_root(x.balance) + # h.update hash_tree_root(x.status) # TODO it's an enum, deal with it + h.update hash_tree_root(x.latest_status_change_slot) + h.update hash_tree_root(x.exit_count) -func hashSSZ*(x: ShardCommittee): array[32, byte] = +func hash_tree_root*(x: ShardCommittee): array[32, byte] = withHash: - h.update hashSSZ(x.shard) + h.update hash_tree_root(x.shard) h.update merkleHash(x.committee) -func hashSSZ*[T: not enum](x: T): array[32, byte] = +func hash_tree_root*[T: not enum](x: T): array[32, byte] = when T is seq: ## Sequences are tree-hashed merkleHash(x) @@ -212,15 +212,15 @@ func hashSSZ*[T: not enum](x: T): array[32, byte] = # TODO or.. https://github.com/ethereum/eth2.0-specs/issues/275 var fields: seq[tuple[name: string, value: seq[byte]]] for name, field in x.fieldPairs: - fields.add (name, @(hashSSZ(field))) + fields.add (name, @(hash_tree_root(field))) withHash: for name, value in fields.sortedByIt(it.name): - h.update hashSSZ(value.value) + h.update hash_tree_root(value.value) # ################################# -# HashSSZ not part of official spec -func hashSSZ*(x: enum): array[32, byte] = +# hash_tree_root not part of official spec +func hash_tree_root*(x: enum): array[32, byte] = ## TODO - Warning ⚠️: not part of the spec ## as of https://github.com/ethereum/beacon_chain/pull/133/files ## This is a "stub" needed for BeaconBlock hashing @@ -228,13 +228,13 @@ func hashSSZ*(x: enum): array[32, byte] = withHash: h.update [uint8 x] -func hashSSZ*(x: ValidatorPubKey): array[32, byte] = +func hash_tree_root*(x: ValidatorPubKey): array[32, byte] = ## TODO - Warning ⚠️: not part of the spec ## as of https://github.com/ethereum/beacon_chain/pull/133/files ## This is a "stub" needed for BeaconBlock hashing x.getRaw().hash() -func hashSSZ*(x: ValidatorSig): array[32, byte] = +func hash_tree_root*(x: ValidatorSig): array[32, byte] = ## TODO - Warning ⚠️: not part of the spec ## as of https://github.com/ethereum/beacon_chain/pull/133/files ## This is a "stub" needed for BeaconBlock hashing @@ -258,9 +258,9 @@ func merkleHash[T](lst: seq[T]): array[32, byte] = if len(lst) == 0: chunkz.add @emptyChunk - elif sizeof(hashSSZ(lst[0])) < CHUNK_SIZE: + elif sizeof(hash_tree_root(lst[0])) < CHUNK_SIZE: # See how many items fit in a chunk - let itemsPerChunk = CHUNK_SIZE div sizeof(hashSSZ(lst[0])) + let itemsPerChunk = CHUNK_SIZE div sizeof(hash_tree_root(lst[0])) chunkz.setLen((len(lst) + itemsPerChunk - 1) div itemsPerChunk) @@ -270,12 +270,12 @@ func merkleHash[T](lst: seq[T]): array[32, byte] = if i == chunkz.len - 1: let idx = i * itemsPerChunk + j if idx >= lst.len: break # Last chunk may be partial! - chunkz[i].add hashSSZ(lst[i * itemsPerChunk + j]) + chunkz[i].add hash_tree_root(lst[i * itemsPerChunk + j]) else: # Leave large items alone chunkz.setLen(len(lst)) for i in 0.. 1: if chunkz.len() mod 2 == 1: diff --git a/beacon_chain/state_transition.nim b/beacon_chain/state_transition.nim index 08199e003..39420a0e4 100644 --- a/beacon_chain/state_transition.nim +++ b/beacon_chain/state_transition.nim @@ -72,10 +72,10 @@ func verifyProposerSignature(state: BeaconState, blck: BeaconBlock): bool = blck_without_sig.signature = ValidatorSig() let - proposal_hash = hashSSZ(ProposalSignedData( + proposal_hash = hash_tree_root(ProposalSignedData( slot: state.slot, shard: BEACON_CHAIN_SHARD, - block_hash: Eth2Digest(data: hashSSZ(blck_without_sig)) + block_root: Eth2Digest(data: hash_tree_root(blck_without_sig)) )) let validator_idx = get_beacon_proposer_index(state, state.slot) @@ -139,13 +139,13 @@ func processSlot(state: var BeaconState, latest_block: BeaconBlock): bool = # TODO state not rolled back in case of failure let - latest_hash = Eth2Digest(data: hashSSZ(latest_block)) + latest_hash = Eth2Digest(data: hash_tree_root(latest_block)) state.slot += 1 - state.latest_block_hashes.add latest_hash + state.latest_block_roots.add latest_hash - if state.latest_block_hashes.len < 2 or - state.latest_block_hashes[^2] != state.latest_block_hashes[^1]: + if state.latest_block_roots.len < 2 or + state.latest_block_roots[^2] != state.latest_block_roots[^1]: # TODO a bit late for the following checks? # https://github.com/ethereum/eth2.0-specs/issues/284 if latest_block.slot != state.slot: @@ -181,7 +181,7 @@ func boundary_attestations( ): seq[PendingAttestationRecord] = # TODO spec - add as helper? filterIt(attestations, - it.data.epoch_boundary_hash == boundary_hash and + it.data.epoch_boundary_root == boundary_hash and it.data.justified_slot == state.justified_slot) func sum_effective_balances( @@ -193,7 +193,7 @@ func sum_effective_balances( func lowerThan(candidate, current: Eth2Digest): bool = # return true iff candidate is "lower" than current, per spec rule: - # "ties broken by favoring lower `shard_block_hash` values" + # "ties broken by favoring lower `shard_block_root` values" # TODO spec - clarify hash ordering.. for i, v in current.data: if v > candidate.data[i]: return true @@ -220,7 +220,7 @@ func processEpoch(state: var BeaconState, blck: BeaconBlock): bool = reward_quotient = BASE_REWARD_QUOTIENT * int_sqrt(total_balance_in_eth) # TODO not in spec, convenient - epoch_boundary_hash = get_block_hash(state, s) + epoch_boundary_root = get_block_root(state, s) proc base_reward(v: ValidatorRecord): uint64 = get_effective_balance(v) div reward_quotient.uint64 @@ -232,7 +232,7 @@ func processEpoch(state: var BeaconState, blck: BeaconBlock): bool = s <= it.data.slot and it.data.slot < s + EPOCH_LENGTH) this_epoch_boundary_attestations = - boundary_attestations(state, epoch_boundary_hash, + boundary_attestations(state, epoch_boundary_root, this_epoch_attestations) this_epoch_boundary_attesters = @@ -246,7 +246,7 @@ func processEpoch(state: var BeaconState, blck: BeaconBlock): bool = s <= it.data.slot + EPOCH_LENGTH and it.data.slot < s) previous_epoch_boundary_attestations = - boundary_attestations(state, epoch_boundary_hash, + boundary_attestations(state, epoch_boundary_root, previous_epoch_attestations) previous_epoch_boundary_attesters = @@ -260,23 +260,23 @@ func processEpoch(state: var BeaconState, blck: BeaconBlock): bool = # these closures outside this scope, but still.. let statePtr = state.addr func attesting_validators( - obj: ShardCommittee, shard_block_hash: Eth2Digest): seq[Uint24] = + obj: ShardCommittee, shard_block_root: Eth2Digest): seq[Uint24] = flatten( mapIt( filterIt(concat(this_epoch_attestations, previous_epoch_attestations), it.data.shard == obj.shard and - it.data.shard_block_hash == shard_block_hash), + it.data.shard_block_root == shard_block_root), get_attestation_participants(statePtr[], it.data, it.participation_bitfield))) func winning_hash(obj: ShardCommittee): Eth2Digest = - # * Let `winning_hash(obj)` be the winning `shard_block_hash` value. - # ... such that `sum([get_effective_balance(v) for v in attesting_validators(obj, shard_block_hash)])` - # is maximized (ties broken by favoring lower `shard_block_hash` values). + # * Let `winning_hash(obj)` be the winning `shard_block_root` value. + # ... such that `sum([get_effective_balance(v) for v in attesting_validators(obj, shard_block_root)])` + # is maximized (ties broken by favoring lower `shard_block_root` values). let candidates = mapIt( filterIt(concat(this_epoch_attestations, previous_epoch_attestations), it.data.shard == obj.shard), - it.data.shard_block_hash) + it.data.shard_block_root) var max_hash = candidates[0] var max_val = @@ -351,7 +351,7 @@ func processEpoch(state: var BeaconState, blck: BeaconBlock): bool = 2'u64 * total_balance_sac(obj): state.latest_crosslinks[obj.shard] = CrosslinkRecord( slot: state.latest_state_recalculation_slot + EPOCH_LENGTH, - shard_block_hash: winning_hash(obj)) + shard_block_root: winning_hash(obj)) block: # Justification and finalization rewards and penalties let @@ -468,7 +468,7 @@ func processEpoch(state: var BeaconState, blck: BeaconBlock): bool = block: # Final updates # TODO Remove all attestation records older than slot `s`. - state.latest_block_hashes = state.latest_block_hashes[EPOCH_LENGTH..^1] + state.latest_block_roots = state.latest_block_roots[EPOCH_LENGTH..^1] true diff --git a/benchmarks/bench_bls_sig_agggregation.nim b/benchmarks/bench_bls_sig_agggregation.nim index 19400477a..7f7fc7239 100644 --- a/benchmarks/bench_bls_sig_agggregation.nim +++ b/benchmarks/bench_bls_sig_agggregation.nim @@ -9,7 +9,7 @@ func attestation_signed_data( slot: int64, shard_id: int16, parent_hashes: seq[array[32, byte]], - shard_block_hash: array[32, byte], + shard_block_root: array[32, byte], justified_slot: int64 ): MDigest[256]= @@ -27,7 +27,7 @@ func attestation_signed_data( bigEndian16(be_shard_id.addr, shard_id.unsafeAddr) ctx.update be_shard_id - ctx.update shard_block_hash + ctx.update shard_block_root var be_justified_slot: array[8, byte] bigEndian64(be_justified_slot[0].addr, justified_slot.unsafeAddr) @@ -55,7 +55,7 @@ proc main(nb_samples: Natural) = slot = rand(4096 .. 4096 + 256) # 256 slots = 1.1 hour shard_id = int16 rand(high(int16)) parent_hashes = newSeqWith(num_parent_hashes, randBytes32()) - shard_block_hash = randBytes32() + shard_block_root = randBytes32() echo '\n' echo "######################" @@ -70,7 +70,7 @@ proc main(nb_samples: Natural) = echo &"Slot: {slot:>64}" echo &"Shard_id: {shard_id:>64}" echo &"Parent_hash[0]: {parent_hashes[0].toHex:>64}" - echo &"Shard_block_hash: {shard_block_hash.toHex:>64}" + echo &"shard_block_root: {shard_block_root.toHex:>64}" echo &"justified_slot: {justified_slot:>64}" echo '\n' @@ -102,7 +102,7 @@ proc main(nb_samples: Natural) = slot, shard_id, parent_hashes, - shard_block_hash, + shard_block_root, justified_slot ) stop = cpuTime() diff --git a/tests/test_ssz.nim b/tests/test_ssz.nim index 4e0303fdb..1e61dbbb1 100644 --- a/tests/test_ssz.nim +++ b/tests/test_ssz.nim @@ -64,17 +64,17 @@ suite "Tree hashing": test "Hash ValidatorRecord": let vr = ValidatorRecord() - check: hashSSZ(vr).len > 0 + check: hash_tree_root(vr).len > 0 test "Hash ShardCommittee": let sc = ShardCommittee() - check: hashSSZ(sc).len > 0 + check: hash_tree_root(sc).len > 0 test "Hash BeaconBlock": ## TODO: Test genesis hash when spec is updated let bb = BeaconBlock() - check: hashSSZ(bb).len > 0 + check: hash_tree_root(bb).len > 0 test "Hash integer": - check: hashSSZ(0x01'u32) == [0'u8, 0, 0, 1] # big endian! - check: hashSSZ(Uint24(0x01)) == [0'u8, 0, 1] # big endian! + check: hash_tree_root(0x01'u32) == [0'u8, 0, 0, 1] # big endian! + check: hash_tree_root(Uint24(0x01)) == [0'u8, 0, 1] # big endian!