From fa2a703a173edb2981cfa3e730ceb563391ca19d Mon Sep 17 00:00:00 2001 From: Dustin Brody Date: Mon, 25 Nov 2019 12:46:47 +0100 Subject: [PATCH] switch more funcs and procs from global to module scope; create scaffolding for non-O(n^2) eth1 deposit processing with assertions for equivalent functionality; fix a few more shellcheck warnings --- beacon_chain/spec/beaconstate.nim | 9 +++++++-- beacon_chain/ssz.nim | 24 ++++++++++++++++++------ tests/simulation/vars.sh | 8 ++++++-- tests/testutil.nim | 6 +++--- 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/beacon_chain/spec/beaconstate.nim b/beacon_chain/spec/beaconstate.nim index c0de8db6e..919c1b7c5 100644 --- a/beacon_chain/spec/beaconstate.nim +++ b/beacon_chain/spec/beaconstate.nim @@ -227,12 +227,17 @@ func initialize_beacon_state_from_eth1*( state.randao_mixes.fill(eth1_block_hash) # Process deposits - let leaves = deposits.mapIt(it.data) + let + leaves = deposits.mapIt(it.data) + prefix_roots = + hash_tree_roots_prefix(leaves, 2'i64^DEPOSIT_CONTRACT_TREE_DEPTH) for i, deposit in deposits: let deposit_data_list = leaves[0..i] - state.eth1_data.deposit_root = hash_tree_root( + let prev_calc_method_deposit_root = hash_tree_root( sszList(deposit_data_list, 2'i64^DEPOSIT_CONTRACT_TREE_DEPTH)) + state.eth1_data.deposit_root = prefix_roots[i] + doAssert state.eth1_data.deposit_root == prev_calc_method_deposit_root discard process_deposit(state, deposit, flags) # Process activations diff --git a/beacon_chain/ssz.nim b/beacon_chain/ssz.nim index 33f3be963..f0ea63cd0 100644 --- a/beacon_chain/ssz.nim +++ b/beacon_chain/ssz.nim @@ -73,7 +73,7 @@ proc init*(T: type SszReader, maxObjectSize = defaultMaxObjectSize): T = T(stream: stream, maxObjectSize: maxObjectSize) -proc mount*(F: type SSZ, stream: ByteStreamVar, T: type): T = +proc mount(F: type SSZ, stream: ByteStreamVar, T: type): T = mixin readValue var reader = init(SszReader, stream) reader.readValue(T) @@ -166,7 +166,7 @@ template enumerateSubFields(holder, fieldVar, body: untyped) = func writeVarSizeType(w: var SszWriter, value: auto) {.gcsafe.} -func beginRecord*(w: var SszWriter, TT: type): auto = +func beginRecord(w: var SszWriter, TT: type): auto = type T = TT when isFixedSize(T): FixedSizedWriterCtx() @@ -269,7 +269,7 @@ template fromSszBytes*[T; N](_: type TypeWithMaxLen[T, N], mixin fromSszBytes fromSszBytes(T, bytes) -func fromSszBytes*(T: type BlsCurveType, bytes: openarray[byte]): auto = +func fromSszBytes(T: type BlsCurveType, bytes: openarray[byte]): auto = init(T, bytes) proc readValue*(r: var SszReader, val: var auto) = @@ -327,7 +327,7 @@ func getZeroHashWithoutSideEffect(idx: int): Eth2Digest = {.noSideEffect.}: zeroHashes[idx] -func addChunk*(merkelizer: SszChunksMerkelizer, data: openarray[byte]) = +func addChunk(merkelizer: SszChunksMerkelizer, data: openarray[byte]) = doAssert data.len > 0 and data.len <= bytesPerChunk if not getBitLE(merkelizer.totalChunks, 0): @@ -350,7 +350,7 @@ func addChunk*(merkelizer: SszChunksMerkelizer, data: openarray[byte]) = inc merkelizer.totalChunks -func getFinalHash*(merkelizer: SszChunksMerkelizer): Eth2Digest = +func getFinalHash(merkelizer: SszChunksMerkelizer): Eth2Digest = let limit = merkelizer.limit if merkelizer.totalChunks == 0: @@ -573,11 +573,23 @@ func hash_tree_root*(x: auto): Eth2Digest = trs "HASH TREE ROOT FOR ", name(type x), " = ", "0x", $result +func hash_tree_roots_prefix*[T](lst: openarray[T], limit: auto): + seq[Eth2Digest] = + # This is a particular type's instantiation of a general fold, reduce, + # accumulation, prefix sums, etc family of operations. As long as that + # Eth1 deposit case is the only notable example -- the usual uses of a + # list involve, at some point, tree-hashing it -- finalized hashes are + # the only abstraction that escapes from this module this way. + var merkelizer = SszChunksMerkelizer(limit: uint64(limit)) + for i, elem in lst: + merkelizer.addChunk(hash_tree_root(elem).data) + result.add mixInLength(merkelizer.getFinalHash(), i + 1) + func lastFieldName(RecordType: type): string {.compileTime.} = enumAllSerializedFields(RecordType): result = fieldName -func hasSigningRoot*(T: type): bool {.compileTime.} = +func hasSigningRoot(T: type): bool {.compileTime.} = lastFieldName(T) == "signature" func signingRoot*(obj: object): Eth2Digest = diff --git a/tests/simulation/vars.sh b/tests/simulation/vars.sh index 7396a71dd..5fb061db7 100644 --- a/tests/simulation/vars.sh +++ b/tests/simulation/vars.sh @@ -1,15 +1,19 @@ #!/bin/bash +# https://github.com/koalaman/shellcheck/wiki/SC2034 +# shellcheck disable=2034 +true + PWD_CMD="pwd" # get native Windows paths on Mingw uname | grep -qi mingw && PWD_CMD="pwd -W" -cd $(dirname $0) +cd "$(dirname "$0")" SIM_ROOT="$($PWD_CMD)" # Set a default value for the env vars usually supplied by a Makefile -cd $(git rev-parse --show-toplevel) +cd "$(git rev-parse --show-toplevel)" : ${GIT_ROOT:="$($PWD_CMD)"} cd - &>/dev/null diff --git a/tests/testutil.nim b/tests/testutil.nim index b0f998bce..bc4054396 100644 --- a/tests/testutil.nim +++ b/tests/testutil.nim @@ -17,7 +17,7 @@ func preset*(): string = " [Preset: " & const_preset & ']' when ValidatorPrivKey is BlsValue: - func makeFakeValidatorPrivKey*(i: int): ValidatorPrivKey = + func makeFakeValidatorPrivKey(i: int): ValidatorPrivKey = # 0 is not a valid BLS private key - 1000 helps interop with rust BLS library, # lighthouse. # TODO: switch to https://github.com/ethereum/eth2.0-pm/issues/60 @@ -25,14 +25,14 @@ when ValidatorPrivKey is BlsValue: var bytes = uint64(i + 1000).toBytesLE() copyMem(addr result.blsValue.x[0], addr bytes[0], sizeof(bytes)) else: - func makeFakeValidatorPrivKey*(i: int): ValidatorPrivKey = + func makeFakeValidatorPrivKey(i: int): ValidatorPrivKey = # 0 is not a valid BLS private key - 1000 helps interop with rust BLS library, # lighthouse. # TODO: switch to https://github.com/ethereum/eth2.0-pm/issues/60 var bytes = uint64(i + 1000).toBytesLE() copyMem(addr result.x[0], addr bytes[0], sizeof(bytes)) -func makeFakeHash*(i: int): Eth2Digest = +func makeFakeHash(i: int): Eth2Digest = var bytes = uint64(i).toBytesLE() static: doAssert sizeof(bytes) <= sizeof(result.data) copyMem(addr result.data[0], addr bytes[0], sizeof(bytes))