diff --git a/beacon_chain/beacon_chain_db.nim b/beacon_chain/beacon_chain_db.nim index ffe734040..a34efd597 100644 --- a/beacon_chain/beacon_chain_db.nim +++ b/beacon_chain/beacon_chain_db.nim @@ -112,7 +112,7 @@ proc get[T](db: BeaconChainDB, key: openArray[byte], output: var T): GetResult = try: let decompressed = snappy.decode(data, maxDecompressedDbRecordSize) if decompressed.len > 0: - outputPtr[] = SSZ.decode(decompressed, T) + outputPtr[] = SSZ.decode(decompressed, T, updateRoot = false) status = GetResult.found else: warn "Corrupt snappy record found in database", typ = name(T) @@ -164,9 +164,12 @@ proc putTailBlock*(db: BeaconChainDB, key: Eth2Digest) = proc getBlock*(db: BeaconChainDB, key: Eth2Digest): Opt[TrustedSignedBeaconBlock] = # We only store blocks that we trust in the database - result.ok(TrustedSignedBeaconBlock(root: key)) + result.ok(TrustedSignedBeaconBlock()) if db.get(subkey(SignedBeaconBlock, key), result.get) != GetResult.found: result.err() + else: + # set root after deserializing (so it doesn't get zeroed) + result.get().root = key proc getState*( db: BeaconChainDB, key: Eth2Digest, output: var BeaconState, @@ -214,8 +217,10 @@ iterator getAncestors*(db: BeaconChainDB, root: Eth2Digest): ## ## The search will go on until the ancestor cannot be found. - var res: TrustedSignedBeaconBlock - res.root = root - while db.get(subkey(SignedBeaconBlock, res.root), res) == GetResult.found: + var + res: TrustedSignedBeaconBlock + root = root + while db.get(subkey(SignedBeaconBlock, root), res) == GetResult.found: + res.root = root yield res - res.root = res.message.parent_root + root = res.message.parent_root diff --git a/beacon_chain/ssz/bytes_reader.nim b/beacon_chain/ssz/bytes_reader.nim index 023a31a13..148f7a9c4 100644 --- a/beacon_chain/ssz/bytes_reader.nim +++ b/beacon_chain/ssz/bytes_reader.nim @@ -84,7 +84,8 @@ template checkForForbiddenBits(ResulType: type, if (input[^1] and forbiddenBitsMask) != 0: raiseIncorrectSize ResulType -func readSszValue*[T](input: openarray[byte], val: var T) {.raisesssz.} = +func readSszValue*[T](input: openarray[byte], + val: var T, updateRoot: bool = true) {.raisesssz.} = mixin fromSszBytes, toSszType template readOffsetUnchecked(n: int): uint32 {.used.}= @@ -268,6 +269,7 @@ func readSszValue*[T](input: openarray[byte], val: var T) {.raisesssz.} = input.toOpenArray(int(startOffset), int(endOffset - 1))) when val is SignedBeaconBlock | TrustedSignedBeaconBlock: - val.root = hash_tree_root(val.message) + if updateRoot: + val.root = hash_tree_root(val.message) else: unsupported T diff --git a/beacon_chain/ssz/ssz_serialization.nim b/beacon_chain/ssz/ssz_serialization.nim index 4991b83fa..c26563ee4 100644 --- a/beacon_chain/ssz/ssz_serialization.nim +++ b/beacon_chain/ssz/ssz_serialization.nim @@ -19,6 +19,7 @@ export type SszReader* = object stream: InputStream + updateRoot: bool SszWriter* = object stream: OutputStream @@ -41,8 +42,10 @@ template sizePrefixed*[TT](x: TT): untyped = type T = TT SizePrefixed[T](x) -proc init*(T: type SszReader, stream: InputStream): T {.raises: [Defect].} = - T(stream: stream) +proc init*(T: type SszReader, + stream: InputStream, + updateRoot: bool = true): T {.raises: [Defect].} = + T(stream: stream, updateRoot: updateRoot) proc writeFixedSized(s: var (OutputStream|WriteCursor), x: auto) {.raises: [Defect, IOError].} = mixin toSszType @@ -226,11 +229,10 @@ proc readValue*[T](r: var SszReader, val: var T) {.raises: [Defect, MalformedSsz when isFixedSize(T): const minimalSize = fixedPortionSize(T) if r.stream.readable(minimalSize): - readSszValue(r.stream.read(minimalSize), val) + readSszValue(r.stream.read(minimalSize), val, r.updateRoot) else: raise newException(MalformedSszError, "SSZ input of insufficient size") else: # TODO Read the fixed portion first and precisely measure the size of # the dynamic portion to consume the right number of bytes. - readSszValue(r.stream.read(r.stream.len.get), val) - + readSszValue(r.stream.read(r.stream.len.get), val, r.updateRoot)