Some updates to the envelope module (#1353)
details: + Add detailed error return codes + Remove cruft + Some prototype wrappers
This commit is contained in:
parent
85de03fd6e
commit
3766eddf5a
|
@ -9,11 +9,11 @@
|
||||||
# except according to those terms.
|
# except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[algorithm, sequtils, sets, tables],
|
std/[algorithm, sequtils, tables],
|
||||||
eth/[common, trie/nibbles],
|
eth/[common, trie/nibbles],
|
||||||
stew/[byteutils, interval_set],
|
stew/interval_set,
|
||||||
../../range_desc,
|
../../range_desc,
|
||||||
"."/[hexary_desc, hexary_nearby, hexary_paths]
|
"."/[hexary_desc, hexary_error, hexary_nearby, hexary_paths]
|
||||||
|
|
||||||
{.push raises: [Defect].}
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
|
@ -88,7 +88,10 @@ proc padPartialPath(pfx: NibblesSeq; dblNibble: byte): NodeKey =
|
||||||
(addr result.ByteArray32[0]).copyMem(unsafeAddr bytes[0], bytes.len)
|
(addr result.ByteArray32[0]).copyMem(unsafeAddr bytes[0], bytes.len)
|
||||||
|
|
||||||
|
|
||||||
proc decomposeLeft(envPt, ivPt: RPath|XPath): Result[seq[NodeSpecs],void] =
|
proc decomposeLeft(
|
||||||
|
envPt: RPath|XPath;
|
||||||
|
ivPt: RPath|XPath;
|
||||||
|
): Result[seq[NodeSpecs],HexaryError] =
|
||||||
## Helper for `hexaryEnvelopeDecompose()` for handling left side of
|
## Helper for `hexaryEnvelopeDecompose()` for handling left side of
|
||||||
## envelope from partial path argument
|
## envelope from partial path argument
|
||||||
#
|
#
|
||||||
|
@ -131,48 +134,14 @@ proc decomposeLeft(envPt, ivPt: RPath|XPath): Result[seq[NodeSpecs],void] =
|
||||||
# `rootKey` is the hash of this node. In that case, `pMin == 0` and
|
# `rootKey` is the hash of this node. In that case, `pMin == 0` and
|
||||||
# `pMax == high(NodeTag)` and `iv == [a,a]`.
|
# `pMax == high(NodeTag)` and `iv == [a,a]`.
|
||||||
#
|
#
|
||||||
return err()
|
return err(DecomposeDegenerated)
|
||||||
|
|
||||||
ok(collect)
|
ok(collect)
|
||||||
|
|
||||||
proc decomposeLeftDebug(
|
proc decomposeRight(
|
||||||
envPt, ivPt: RPath;
|
envPt: RPath|XPath;
|
||||||
db: HexaryTreeDbRef;
|
ivPt: RPath|XPath;
|
||||||
): Result[seq[NodeSpecs],void] =
|
): Result[seq[NodeSpecs],HexaryError] =
|
||||||
## Debugging only
|
|
||||||
var collect: seq[NodeSpecs]
|
|
||||||
block rightCurbEnvelope:
|
|
||||||
echo ">>> decomposeLeft",
|
|
||||||
" range 0..", min(envPt.path.len, ivPt.path.len),
|
|
||||||
"\n ", ivPt.pp(db)
|
|
||||||
for n in 0 ..< min(envPt.path.len+1, ivPt.path.len):
|
|
||||||
if n == envPt.path.len or envPt.path[n] != ivPt.path[n]:
|
|
||||||
for m in n ..< ivPt.path.len:
|
|
||||||
let
|
|
||||||
pfx = ivPt.getNibbles(0, m) # common path segment
|
|
||||||
top = ivPt.path[m].nibble # need nibbles smaller than top
|
|
||||||
echo ">>> decomposeLeft",
|
|
||||||
" len=", ivPt.path.len,
|
|
||||||
" m=", m,
|
|
||||||
" top=", top,
|
|
||||||
" pfx=", pfx,
|
|
||||||
" stepKey=", ivPt.path[m].pp(db)
|
|
||||||
for nibble in 0 ..< top:
|
|
||||||
let nodeKey = ivPt.path[m].node.bLink[nibble]
|
|
||||||
if not nodeKey.isZeroLink:
|
|
||||||
echo ">>> decomposeLeft",
|
|
||||||
" nibble=", nibble,
|
|
||||||
" nodeKey=", nodeKey.pp(db)
|
|
||||||
collect.add nodeKey.toNodeSpecs hexPrefixEncode(
|
|
||||||
pfx & @[nibble.byte].initNibbleRange.slice(1),isLeaf=false)
|
|
||||||
break rightCurbEnvelope
|
|
||||||
echo ">>> decomposeLeft oops"
|
|
||||||
return err()
|
|
||||||
|
|
||||||
ok(collect)
|
|
||||||
|
|
||||||
|
|
||||||
proc decomposeRight(envPt, ivPt: RPath|XPath): Result[seq[NodeSpecs],void] =
|
|
||||||
## Helper for `hexaryEnvelopeDecompose()` for handling right side of
|
## Helper for `hexaryEnvelopeDecompose()` for handling right side of
|
||||||
## envelope from partial path argument
|
## envelope from partial path argument
|
||||||
#
|
#
|
||||||
|
@ -198,7 +167,7 @@ proc decomposeRight(envPt, ivPt: RPath|XPath): Result[seq[NodeSpecs],void] =
|
||||||
collect.add nodeKey.toNodeSpecs hexPrefixEncode(
|
collect.add nodeKey.toNodeSpecs hexPrefixEncode(
|
||||||
pfx & @[nibble.byte].initNibbleRange.slice(1),isLeaf=false)
|
pfx & @[nibble.byte].initNibbleRange.slice(1),isLeaf=false)
|
||||||
break leftCurbEnvelope
|
break leftCurbEnvelope
|
||||||
return err()
|
return err(DecomposeDegenerated)
|
||||||
|
|
||||||
ok(collect)
|
ok(collect)
|
||||||
|
|
||||||
|
@ -208,12 +177,12 @@ proc decomposeImpl(
|
||||||
rootKey: NodeKey; ## State root
|
rootKey: NodeKey; ## State root
|
||||||
iv: NodeTagRange; ## Proofed range of leaf paths
|
iv: NodeTagRange; ## Proofed range of leaf paths
|
||||||
db: HexaryGetFn|HexaryTreeDbRef; ## Database abstraction
|
db: HexaryGetFn|HexaryTreeDbRef; ## Database abstraction
|
||||||
): Result[seq[NodeSpecs],void]
|
): Result[seq[NodeSpecs],HexaryError]
|
||||||
{.gcsafe, raises: [Defect,RlpError,KeyError]} =
|
{.gcsafe, raises: [Defect,RlpError,KeyError].} =
|
||||||
## Database agnostic implementation of `hexaryEnvelopeDecompose()`.
|
## Database agnostic implementation of `hexaryEnvelopeDecompose()`.
|
||||||
let env = partialPath.hexaryEnvelope
|
let env = partialPath.hexaryEnvelope
|
||||||
if iv.maxPt < env.minPt or env.maxPt < iv.minPt:
|
if iv.maxPt < env.minPt or env.maxPt < iv.minPt:
|
||||||
return err()
|
return err(DecomposeDisjuct) # empty result
|
||||||
|
|
||||||
var nodeSpex: seq[NodeSpecs]
|
var nodeSpex: seq[NodeSpecs]
|
||||||
|
|
||||||
|
@ -227,12 +196,12 @@ proc decomposeImpl(
|
||||||
ivPt = block:
|
ivPt = block:
|
||||||
let rc = iv.minPt.hexaryPath(rootKey, db).hexaryNearbyRight(db)
|
let rc = iv.minPt.hexaryPath(rootKey, db).hexaryNearbyRight(db)
|
||||||
if rc.isErr:
|
if rc.isErr:
|
||||||
return err()
|
return err(rc.error)
|
||||||
rc.value
|
rc.value
|
||||||
block:
|
block:
|
||||||
let rc = envPt.decomposeLeft ivPt
|
let rc = envPt.decomposeLeft ivPt
|
||||||
if rc.isErr:
|
if rc.isErr:
|
||||||
return err()
|
return err(rc.error)
|
||||||
nodeSpex &= rc.value
|
nodeSpex &= rc.value
|
||||||
|
|
||||||
if iv.maxPt < env.maxPt:
|
if iv.maxPt < env.maxPt:
|
||||||
|
@ -241,12 +210,12 @@ proc decomposeImpl(
|
||||||
ivPt = block:
|
ivPt = block:
|
||||||
let rc = iv.maxPt.hexaryPath(rootKey, db).hexaryNearbyLeft(db)
|
let rc = iv.maxPt.hexaryPath(rootKey, db).hexaryNearbyLeft(db)
|
||||||
if rc.isErr:
|
if rc.isErr:
|
||||||
return err()
|
return err(rc.error)
|
||||||
rc.value
|
rc.value
|
||||||
block:
|
block:
|
||||||
let rc = envPt.decomposeRight ivPt
|
let rc = envPt.decomposeRight ivPt
|
||||||
if rc.isErr:
|
if rc.isErr:
|
||||||
return err()
|
return err(rc.error)
|
||||||
nodeSpex &= rc.value
|
nodeSpex &= rc.value
|
||||||
|
|
||||||
ok(nodeSpex)
|
ok(nodeSpex)
|
||||||
|
@ -263,6 +232,10 @@ proc hexaryEnvelope*(partialPath: Blob): NodeTagRange =
|
||||||
pfx.padPartialPath(0).to(NodeTag),
|
pfx.padPartialPath(0).to(NodeTag),
|
||||||
pfx.padPartialPath(255).to(NodeTag))
|
pfx.padPartialPath(255).to(NodeTag))
|
||||||
|
|
||||||
|
proc hexaryEnvelope*(node: NodeSpecs): NodeTagRange =
|
||||||
|
## variant of `hexaryEnvelope()`
|
||||||
|
node.partialPath.hexaryEnvelope()
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Public functions, helpers
|
# Public functions, helpers
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -270,7 +243,7 @@ proc hexaryEnvelope*(partialPath: Blob): NodeTagRange =
|
||||||
proc hexaryEnvelopeUniq*(
|
proc hexaryEnvelopeUniq*(
|
||||||
partialPaths: openArray[Blob];
|
partialPaths: openArray[Blob];
|
||||||
): seq[Blob]
|
): seq[Blob]
|
||||||
{.gcsafe, raises: [Defect,KeyError]} =
|
{.gcsafe, raises: [Defect,KeyError].} =
|
||||||
## Sort and simplify a list of partial paths by sorting envelopes while
|
## Sort and simplify a list of partial paths by sorting envelopes while
|
||||||
## removing nested entries.
|
## removing nested entries.
|
||||||
var tab: Table[NodeTag,(Blob,bool)]
|
var tab: Table[NodeTag,(Blob,bool)]
|
||||||
|
@ -302,7 +275,7 @@ proc hexaryEnvelopeUniq*(
|
||||||
proc hexaryEnvelopeUniq*(
|
proc hexaryEnvelopeUniq*(
|
||||||
nodes: openArray[NodeSpecs];
|
nodes: openArray[NodeSpecs];
|
||||||
): seq[NodeSpecs]
|
): seq[NodeSpecs]
|
||||||
{.gcsafe, raises: [Defect,KeyError]} =
|
{.gcsafe, raises: [Defect,KeyError].} =
|
||||||
## Variant of `hexaryEnvelopeUniq` for sorting a `NodeSpecs` list by
|
## Variant of `hexaryEnvelopeUniq` for sorting a `NodeSpecs` list by
|
||||||
## partial paths.
|
## partial paths.
|
||||||
var tab: Table[NodeTag,(NodeSpecs,bool)]
|
var tab: Table[NodeTag,(NodeSpecs,bool)]
|
||||||
|
@ -385,6 +358,12 @@ proc hexaryEnvelopeTouchedBy*(
|
||||||
elif probe.maxPt < w.minPt:
|
elif probe.maxPt < w.minPt:
|
||||||
break # all the `w` following will be disjuct, too
|
break # all the `w` following will be disjuct, too
|
||||||
|
|
||||||
|
proc hexaryEnvelopeTouchedBy*(
|
||||||
|
rangeSet: NodeTagRangeSet; ## Set of intervals (aka ranges)
|
||||||
|
node: NodeSpecs; ## Node w/hex encoded partial path
|
||||||
|
): NodeTagRangeSet =
|
||||||
|
## Variant of `hexaryEnvelopeTouchedBy()`
|
||||||
|
rangeSet.hexaryEnvelopeTouchedBy(node)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Public functions, complement sub-tries
|
# Public functions, complement sub-tries
|
||||||
|
@ -395,8 +374,8 @@ proc hexaryEnvelopeDecompose*(
|
||||||
rootKey: NodeKey; ## State root
|
rootKey: NodeKey; ## State root
|
||||||
iv: NodeTagRange; ## Proofed range of leaf paths
|
iv: NodeTagRange; ## Proofed range of leaf paths
|
||||||
db: HexaryTreeDbRef; ## Database
|
db: HexaryTreeDbRef; ## Database
|
||||||
): Result[seq[NodeSpecs],void]
|
): Result[seq[NodeSpecs],HexaryError]
|
||||||
{.gcsafe, raises: [Defect,KeyError]} =
|
{.gcsafe, raises: [Defect,KeyError].} =
|
||||||
## The idea of this function is to compute the difference of the envelope
|
## The idea of this function is to compute the difference of the envelope
|
||||||
## of a `partialPath` off the range `iv` and express the result as a
|
## of a `partialPath` off the range `iv` and express the result as a
|
||||||
## list of envelopes (represented by nodes.)
|
## list of envelopes (represented by nodes.)
|
||||||
|
@ -474,69 +453,16 @@ proc hexaryEnvelopeDecompose*(
|
||||||
## above though it is highly redundant. All bottom level nodes with
|
## above though it is highly redundant. All bottom level nodes with
|
||||||
## envelopes disjunct from `iv` can be removed for a `boundary proof`.
|
## envelopes disjunct from `iv` can be removed for a `boundary proof`.
|
||||||
##
|
##
|
||||||
when false: # or true:
|
noRlpErrorOops("in-memory hexaryEnvelopeDecompose"):
|
||||||
noRlpErrorOops("in-memory hexaryEnvelopeDecompose"):
|
return partialPath.decomposeImpl(rootKey, iv, db)
|
||||||
return partialPath.decomposeImpl(rootKey, iv, db)
|
|
||||||
else:
|
|
||||||
let env = partialPath.hexaryEnvelope
|
|
||||||
if iv.maxPt < env.minPt or env.maxPt < iv.minPt:
|
|
||||||
return err()
|
|
||||||
|
|
||||||
var nodeSpex: seq[NodeSpecs]
|
|
||||||
if env.minPt < iv.minPt:
|
|
||||||
let
|
|
||||||
envPt = env.minPt.hexaryPath(rootKey, db)
|
|
||||||
# Make sure that the min point is the nearest node to the right
|
|
||||||
ivPt = block:
|
|
||||||
let rc = iv.minPt.hexaryPath(rootKey, db).hexaryNearbyRight(db)
|
|
||||||
if rc.isErr:
|
|
||||||
return err()
|
|
||||||
rc.value
|
|
||||||
when false: # or true:
|
|
||||||
echo ">>> chop envelope right end => decomposeLeft",
|
|
||||||
"\n envPt=", env.minPt,
|
|
||||||
"\n ", envPt.pp(db),
|
|
||||||
"\n -----",
|
|
||||||
"\n ivPt=", iv.minPt,
|
|
||||||
"\n ", ivPt.pp(db)
|
|
||||||
block:
|
|
||||||
#let rc = envPt.decomposeLeftDebug(ivPt,db)
|
|
||||||
let rc = envPt.decomposeLeft(ivPt)
|
|
||||||
if rc.isErr:
|
|
||||||
return err()
|
|
||||||
nodeSpex &= rc.value
|
|
||||||
|
|
||||||
if iv.maxPt < env.maxPt:
|
|
||||||
let
|
|
||||||
envPt = env.maxPt.hexaryPath(rootKey, db)
|
|
||||||
ivPt = block:
|
|
||||||
let rc = iv.maxPt.hexaryPath(rootKey, db).hexaryNearbyLeft(db)
|
|
||||||
if rc.isErr:
|
|
||||||
return err()
|
|
||||||
rc.value
|
|
||||||
when false: # or true:
|
|
||||||
echo ">>> chop envelope left end => decomposeRight",
|
|
||||||
"\n envPt=", env.maxPt,
|
|
||||||
"\n ", envPt.pp(db),
|
|
||||||
"\n -----",
|
|
||||||
"\n ivPt=", iv.maxPt,
|
|
||||||
"\n ", ivPt.pp(db)
|
|
||||||
block:
|
|
||||||
let rc = envPt.decomposeRight(ivPt)
|
|
||||||
if rc.isErr:
|
|
||||||
return err()
|
|
||||||
nodeSpex &= rc.value
|
|
||||||
|
|
||||||
ok(nodeSpex)
|
|
||||||
|
|
||||||
|
|
||||||
proc hexaryEnvelopeDecompose*(
|
proc hexaryEnvelopeDecompose*(
|
||||||
partialPath: Blob; ## Hex encoded partial path
|
partialPath: Blob; ## Hex encoded partial path
|
||||||
rootKey: NodeKey; ## State root
|
rootKey: NodeKey; ## State root
|
||||||
iv: NodeTagRange; ## Proofed range of leaf paths
|
iv: NodeTagRange; ## Proofed range of leaf paths
|
||||||
getFn: HexaryGetFn; ## Database abstraction
|
getFn: HexaryGetFn; ## Database abstraction
|
||||||
): Result[seq[NodeSpecs],void]
|
): Result[seq[NodeSpecs],HexaryError]
|
||||||
{.gcsafe, raises: [Defect,RlpError]} =
|
{.gcsafe, raises: [Defect,RlpError].} =
|
||||||
## Variant of `decompose()` for persistent database.
|
## Variant of `decompose()` for persistent database.
|
||||||
noKeyErrorOops("persistent hexaryEnvelopeDecompose"):
|
noKeyErrorOops("persistent hexaryEnvelopeDecompose"):
|
||||||
return partialPath.decomposeImpl(rootKey, iv, getFn)
|
return partialPath.decomposeImpl(rootKey, iv, getFn)
|
||||||
|
|
|
@ -37,6 +37,10 @@ type
|
||||||
NearbyLeafExpected
|
NearbyLeafExpected
|
||||||
NearbyDanglingLink
|
NearbyDanglingLink
|
||||||
|
|
||||||
|
# envelope
|
||||||
|
DecomposeDegenerated
|
||||||
|
DecomposeDisjuct
|
||||||
|
|
||||||
# import
|
# import
|
||||||
DifferentNodeValueExists
|
DifferentNodeValueExists
|
||||||
ExpectedNodeKeyDiffers
|
ExpectedNodeKeyDiffers
|
||||||
|
|
|
@ -1261,8 +1261,7 @@ when isMainModule:
|
||||||
import ./test_sync_snap/snap_other_xx
|
import ./test_sync_snap/snap_other_xx
|
||||||
noisy.showElapsed("accountsRunner()"):
|
noisy.showElapsed("accountsRunner()"):
|
||||||
for n,sam in snapOtherList:
|
for n,sam in snapOtherList:
|
||||||
if n == 3:
|
false.accountsRunner(persistent=true, sam)
|
||||||
false.accountsRunner(persistent=true, sam)
|
|
||||||
noisy.showElapsed("inspectRunner()"):
|
noisy.showElapsed("inspectRunner()"):
|
||||||
for n,sam in snapOtherHealingList:
|
for n,sam in snapOtherHealingList:
|
||||||
false.inspectionRunner(persistent=true, cascaded=false, sam)
|
false.inspectionRunner(persistent=true, cascaded=false, sam)
|
||||||
|
|
Loading…
Reference in New Issue