support array of uint64

This commit is contained in:
Jacek Sieka 2020-05-29 16:08:14 +02:00
parent f1dcee2749
commit 4fc9a84c57
No known key found for this signature in database
GPG Key ID: A1B09461ABB656B8
4 changed files with 49 additions and 23 deletions

View File

@ -264,7 +264,7 @@ type
## Needed to process attestations, older to newer
state_roots*: HashArray[SLOTS_PER_HISTORICAL_ROOT, Eth2Digest]
historical_roots*: List[Eth2Digest, HISTORICAL_ROOTS_LIMIT]
historical_roots*: HashList[Eth2Digest, HISTORICAL_ROOTS_LIMIT]
# Eth1
eth1_data*: Eth1Data
@ -280,7 +280,7 @@ type
randao_mixes*: HashArray[EPOCHS_PER_HISTORICAL_VECTOR, Eth2Digest]
# Slashings
slashings*: array[EPOCHS_PER_SLASHINGS_VECTOR, uint64] ##\
slashings*: HashArray[EPOCHS_PER_SLASHINGS_VECTOR, uint64] ##\
## Per-epoch sums of slashed effective balances
# Attestations

View File

@ -18,7 +18,7 @@
import
options, algorithm, options, strformat, typetraits,
stew/[bitops2, bitseqs, endians2, objects, varints, ptrops],
stew/[bitops2, byteutils, bitseqs, endians2, objects, varints, ptrops],
stew/ranges/ptr_arith, stew/shims/macros,
faststreams/[inputs, outputs, buffers],
serialization, serialization/testing/tracing,
@ -586,18 +586,27 @@ func hashTreeRootAux[T](x: T): Eth2Digest =
unsupported T
func mergedDataHash(x: HashList|HashArray, dataIdx: int64): Eth2Digest =
trs "DATA HASH ", dataIdx, " ", x.data.len
when x.T is uint64:
when cpuEndian == bigEndian:
unsupported type x
let
pos = offset(cast[ptr byte](unsafeAddr x.data[0]), dataIdx.int * 32)
pos2 = offset(pos, 32)
if dataIdx + 1 > x.data.len():
zeroHashes[x.maxDepth]
elif dataIdx + 1 == x.data.len():
mergeBranches(
hash_tree_root(x.data[dataIdx]),
Eth2Digest())
hash(makeOpenArray(pos, 32), makeOpenArray(pos2, 32))
else:
mergeBranches(
hash_tree_root(x.data[dataIdx]),
hash_tree_root(x.data[dataIdx + 1]))
trs "DATA HASH ", dataIdx, " ", x.data.len
if dataIdx + 1 > x.data.len():
zeroHashes[x.maxDepth]
elif dataIdx + 1 == x.data.len():
mergeBranches(
hash_tree_root(x.data[dataIdx]),
Eth2Digest())
else:
mergeBranches(
hash_tree_root(x.data[dataIdx]),
hash_tree_root(x.data[dataIdx + 1]))
func cachedHash*(x: HashList, vIdx: int64): Eth2Digest =
doAssert vIdx >= 1
@ -655,10 +664,7 @@ func hash_tree_root*(x: auto): Eth2Digest {.raises: [Defect], nbench.} =
mixin toSszType
result = when x is HashArray:
if x.hashes.len < 2:
zeroHashes[log2trunc(uint64(x.data.len() + 1))]
else:
cachedHash(x, 1)
cachedHash(x, 1)
elif x is HashList:
if x.hashes.len < 2:
mixInLength(zeroHashes[x.maxDepth], x.data.len())

View File

@ -9,6 +9,13 @@ import
const
offsetSize* = 4
func hashChunks(maxLen: int64, T: type): int64 =
# For simplificy of implementation, HashArray only supports a few types - this
# could/should obviously be extended
when T is uint64:
maxLen * sizeof(T) div 32
else: maxLen
type
UintN* = SomeUnsignedInt # TODO: Add StUint here
BasicType* = bool|UintN
@ -33,7 +40,7 @@ type
HashArray*[maxLen: static int; T] = object
data*: array[maxLen, T]
hashes* {.dontSerialize.}: array[maxLen, Eth2Digest]
hashes* {.dontSerialize.}: array[hashChunks(maxLen, T), Eth2Digest]
HashList*[T; maxLen: static int64] = object
data*: List[T, maxLen]
@ -98,7 +105,10 @@ template clearCache*(v: var Eth2Digest) =
proc clearTree*(a: var HashArray, dataIdx: auto) =
## Clear all cache entries after data at dataIdx has been modified
var idx = 1 shl (a.maxDepth - 1) + int(dataIdx div 2)
when a.T is uint64:
var idx = 1 shl (a.maxDepth - 1) + int(dataIdx div 8)
else:
var idx = 1 shl (a.maxDepth - 1) + int(dataIdx div 2)
while idx != 0:
clearCache(a.hashes[idx])
idx = idx div 2
@ -123,9 +133,13 @@ template layer*(vIdx: int64): int =
## index 0 for the mixed-in-length
log2trunc(vIdx.uint64).int
template maxChunks*(a: HashList|HashArray): int64 =
## Layer where data is
hashChunks(a.maxLen, a.T)
template maxDepth*(a: HashList|HashArray): int =
## Layer where data is
layer(a.maxLen)
layer(a.maxChunks)
proc clearTree*(a: var HashList, dataIdx: auto) =
if a.hashes.len == 0:

View File

@ -95,9 +95,8 @@ suiteReport "SSZ navigator":
let root = hash_tree_root(leaves)
check $root == "5248085B588FAB1DD1E03F3CD62201602B12E6560665935964F46E805977E8C5"
while leaves.len < leaves.maxLen:
leaves.add c
check hash_tree_root(leaves) == hash_tree_root(leaves.data)
leaves.add c
check hash_tree_root(leaves) == hash_tree_root(leaves.data)
suiteReport "SSZ dynamic navigator":
timedTest "navigating fields":
@ -155,3 +154,10 @@ suiteReport "hash":
both: it.arr[0].data[0] = byte 1
both: it.li.add Eth2Digest()
var y: HashArray[32, uint64]
doAssert hash_tree_root(y) == hash_tree_root(y.data)
y[4] = 42'u64
doAssert hash_tree_root(y) == hash_tree_root(y.data)