avoid hash tree root calculation when loading blocks from database (#1572)
This commit is contained in:
parent
c2384246bc
commit
29e56232a7
|
@ -112,7 +112,7 @@ proc get[T](db: BeaconChainDB, key: openArray[byte], output: var T): GetResult =
|
||||||
try:
|
try:
|
||||||
let decompressed = snappy.decode(data, maxDecompressedDbRecordSize)
|
let decompressed = snappy.decode(data, maxDecompressedDbRecordSize)
|
||||||
if decompressed.len > 0:
|
if decompressed.len > 0:
|
||||||
outputPtr[] = SSZ.decode(decompressed, T)
|
outputPtr[] = SSZ.decode(decompressed, T, updateRoot = false)
|
||||||
status = GetResult.found
|
status = GetResult.found
|
||||||
else:
|
else:
|
||||||
warn "Corrupt snappy record found in database", typ = name(T)
|
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] =
|
proc getBlock*(db: BeaconChainDB, key: Eth2Digest): Opt[TrustedSignedBeaconBlock] =
|
||||||
# We only store blocks that we trust in the database
|
# 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:
|
if db.get(subkey(SignedBeaconBlock, key), result.get) != GetResult.found:
|
||||||
result.err()
|
result.err()
|
||||||
|
else:
|
||||||
|
# set root after deserializing (so it doesn't get zeroed)
|
||||||
|
result.get().root = key
|
||||||
|
|
||||||
proc getState*(
|
proc getState*(
|
||||||
db: BeaconChainDB, key: Eth2Digest, output: var BeaconState,
|
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.
|
## The search will go on until the ancestor cannot be found.
|
||||||
|
|
||||||
var res: TrustedSignedBeaconBlock
|
var
|
||||||
|
res: TrustedSignedBeaconBlock
|
||||||
|
root = root
|
||||||
|
while db.get(subkey(SignedBeaconBlock, root), res) == GetResult.found:
|
||||||
res.root = root
|
res.root = root
|
||||||
while db.get(subkey(SignedBeaconBlock, res.root), res) == GetResult.found:
|
|
||||||
yield res
|
yield res
|
||||||
res.root = res.message.parent_root
|
root = res.message.parent_root
|
||||||
|
|
|
@ -84,7 +84,8 @@ template checkForForbiddenBits(ResulType: type,
|
||||||
if (input[^1] and forbiddenBitsMask) != 0:
|
if (input[^1] and forbiddenBitsMask) != 0:
|
||||||
raiseIncorrectSize ResulType
|
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
|
mixin fromSszBytes, toSszType
|
||||||
|
|
||||||
template readOffsetUnchecked(n: int): uint32 {.used.}=
|
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)))
|
input.toOpenArray(int(startOffset), int(endOffset - 1)))
|
||||||
|
|
||||||
when val is SignedBeaconBlock | TrustedSignedBeaconBlock:
|
when val is SignedBeaconBlock | TrustedSignedBeaconBlock:
|
||||||
|
if updateRoot:
|
||||||
val.root = hash_tree_root(val.message)
|
val.root = hash_tree_root(val.message)
|
||||||
else:
|
else:
|
||||||
unsupported T
|
unsupported T
|
||||||
|
|
|
@ -19,6 +19,7 @@ export
|
||||||
type
|
type
|
||||||
SszReader* = object
|
SszReader* = object
|
||||||
stream: InputStream
|
stream: InputStream
|
||||||
|
updateRoot: bool
|
||||||
|
|
||||||
SszWriter* = object
|
SszWriter* = object
|
||||||
stream: OutputStream
|
stream: OutputStream
|
||||||
|
@ -41,8 +42,10 @@ template sizePrefixed*[TT](x: TT): untyped =
|
||||||
type T = TT
|
type T = TT
|
||||||
SizePrefixed[T](x)
|
SizePrefixed[T](x)
|
||||||
|
|
||||||
proc init*(T: type SszReader, stream: InputStream): T {.raises: [Defect].} =
|
proc init*(T: type SszReader,
|
||||||
T(stream: stream)
|
stream: InputStream,
|
||||||
|
updateRoot: bool = true): T {.raises: [Defect].} =
|
||||||
|
T(stream: stream, updateRoot: updateRoot)
|
||||||
|
|
||||||
proc writeFixedSized(s: var (OutputStream|WriteCursor), x: auto) {.raises: [Defect, IOError].} =
|
proc writeFixedSized(s: var (OutputStream|WriteCursor), x: auto) {.raises: [Defect, IOError].} =
|
||||||
mixin toSszType
|
mixin toSszType
|
||||||
|
@ -226,11 +229,10 @@ proc readValue*[T](r: var SszReader, val: var T) {.raises: [Defect, MalformedSsz
|
||||||
when isFixedSize(T):
|
when isFixedSize(T):
|
||||||
const minimalSize = fixedPortionSize(T)
|
const minimalSize = fixedPortionSize(T)
|
||||||
if r.stream.readable(minimalSize):
|
if r.stream.readable(minimalSize):
|
||||||
readSszValue(r.stream.read(minimalSize), val)
|
readSszValue(r.stream.read(minimalSize), val, r.updateRoot)
|
||||||
else:
|
else:
|
||||||
raise newException(MalformedSszError, "SSZ input of insufficient size")
|
raise newException(MalformedSszError, "SSZ input of insufficient size")
|
||||||
else:
|
else:
|
||||||
# TODO Read the fixed portion first and precisely measure the size of
|
# TODO Read the fixed portion first and precisely measure the size of
|
||||||
# the dynamic portion to consume the right number of bytes.
|
# 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)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue