mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-28 13:05:18 +00:00
cd1d370543
* Update docu * Update Aristo/Kvt constructor prototype why: Previous version used an `enum` value to indicate what backend is to be used. This was replaced by using the backend object type. * Rewrite `hikeUp()` return code into `Result[Hike,(Hike,AristoError)]` why: Better code maintenance. Previously, the `Hike` object was returned. It had an internal error field so partial success was also available on a failure. This error field has been removed. * Use `openArray[byte]` rather than `Blob` in functions prototypes * Provide synchronised multi instance transactions why: The `CoreDB` object was geared towards the legacy DB which used a single transaction for the key-value backend DB. Different state roots are provided by the backend database, so all instances work directly on the same backend. Aristo db instances have different in-memory mappings (aka different state roots) and the transactions are on top of there mappings. So each instance might run different transactions. Multi instance transactions are a compromise to converge towards the legacy behaviour. The synchronised transactions span over all instances available at the time when base transaction was opened. Instances created later are unaffected. * Provide key-value pair database iterator why: Needed in `CoreDB` for `replicate()` emulation also: Some update of internal code * Extend API (i.e. prototype variants) why: Needed for `CoreDB` geared towards the legacy backend which has a more basic API than Aristo.
94 lines
3.4 KiB
Nim
94 lines
3.4 KiB
Nim
# nimbus-eth1
|
|
# Copyright (c) 2021 Status Research & Development GmbH
|
|
# Licensed under either of
|
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
|
# http://www.apache.org/licenses/LICENSE-2.0)
|
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
|
# http://opensource.org/licenses/MIT)
|
|
# at your option. This file may not be copied, modified, or distributed
|
|
# except according to those terms.
|
|
|
|
{.push raises: [].}
|
|
|
|
import
|
|
std/sequtils,
|
|
eth/[common, trie/nibbles],
|
|
results,
|
|
./aristo_desc
|
|
|
|
# Info snippet (just a reminder to keep somewhere)
|
|
#
|
|
# Extension of a compact encoded as prefixed sequence of nibbles (i.e.
|
|
# half bytes with 4 bits.)
|
|
#
|
|
# pfx | bits | vertex type | layout
|
|
# ----+ -----+-------------+----------------------------------------
|
|
# 0 | 0000 | extension | @[<pfx, ignored>, nibble-pair, ..]
|
|
# 1 | 0001 | extension | @[<pfx, first-nibble>, nibble-pair, ..]
|
|
# 2 | 0010 | leaf | @[<pfx, ignored>, nibble-pair, ..]
|
|
# 3 | 0011 | leaf | @[<pfx, first-nibble>, nibble-pair, ..]
|
|
#
|
|
# where the `ignored` part is typically expected a zero nibble.
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Public functions
|
|
# ------------------------------------------------------------------------------
|
|
|
|
proc pathAsBlob*(keyOrTag: HashKey|HashID): Blob =
|
|
keyOrTag.pathAsNibbles.hexPrefixEncode(isLeaf=true)
|
|
|
|
proc pathToKey*(partPath: NibblesSeq): Result[HashKey,AristoError] =
|
|
var key: ByteArray32
|
|
if partPath.len == 64:
|
|
# Trailing dummy nibbles (aka no nibbles) force a nibble seq reorg
|
|
let path = (partPath & EmptyNibbleSeq).getBytes()
|
|
(addr key[0]).copyMem(unsafeAddr path[0], 32)
|
|
return ok(key.HashKey)
|
|
err(PathExpected64Nibbles)
|
|
|
|
proc pathToKey*(
|
|
partPath: openArray[byte];
|
|
): Result[HashKey,AristoError] =
|
|
let (isLeaf,pathSegment) = partPath.hexPrefixDecode
|
|
if isleaf:
|
|
return pathSegment.pathToKey()
|
|
err(PathExpectedLeaf)
|
|
|
|
proc pathToTag*(
|
|
partPath: NibblesSeq|openArray[byte];
|
|
): Result[HashID,AristoError] =
|
|
ok (? partPath.pathToKey).to(HashID)
|
|
|
|
# --------------------
|
|
|
|
proc pathPfxPad*(pfx: NibblesSeq; dblNibble: static[byte]): NibblesSeq =
|
|
## Extend (or cut) the argument nibbles sequence `pfx` for generating a
|
|
## `NibblesSeq` with exactly 64 nibbles, the equivalent of a path key.
|
|
##
|
|
## This function must be handled with some care regarding a meaningful value
|
|
## for the `dblNibble` argument. Currently, only static values `0` and `255`
|
|
## are allowed for padding. This is checked at compile time.
|
|
static:
|
|
doAssert dblNibble == 0 or dblNibble == 255
|
|
|
|
let padLen = 64 - pfx.len
|
|
if 0 <= padLen:
|
|
result = pfx & dblNibble.repeat(padlen div 2).mapIt(it.byte).initNibbleRange
|
|
if (padLen and 1) == 1:
|
|
result = result & @[dblNibble.byte].initNibbleRange.slice(1)
|
|
else:
|
|
let nope = seq[byte].default.initNibbleRange
|
|
result = pfx.slice(0,64) & nope # nope forces re-alignment
|
|
|
|
proc pathPfxPadKey*(pfx: NibblesSeq; dblNibble: static[byte]): HashKey =
|
|
## Variant of `pathPfxPad()`.
|
|
##
|
|
## Extend (or cut) the argument nibbles sequence `pfx` for generating a
|
|
## `HashKey`.
|
|
let bytes = pfx.pathPfxPad(dblNibble).getBytes
|
|
(addr result.ByteArray32[0]).copyMem(unsafeAddr bytes[0], bytes.len)
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# End
|
|
# ------------------------------------------------------------------------------
|