# nimbus-eth1 # Copyright (c) 2024 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 eth/common, results, ".."/[aristo_desc, aristo_get, aristo_utils, aristo_compute, aristo_serialise] # ------------------------------------------------------------------------------ # Public functions # ------------------------------------------------------------------------------ proc chainRlpNodes*( db: AristoDbRef; rvid: RootedVertexID; path: NibblesBuf, chain: var seq[Blob]; ): Result[void,AristoError] = ## Inspired by the `getBranchAux()` function from `hexary.nim` let key = ? db.computeKey rvid (vtx,_) = ? db.getVtxRc rvid node = vtx.toNode(rvid.root, db).valueOr: return err(PartChnNodeConvError) # Save rpl encoded node(s) chain &= node.to(seq[Blob]) # Follow up child node case vtx.vType: of Leaf: if path != vtx.lPfx: err(PartChnLeafPathMismatch) else: ok() of Branch: let nChewOff = sharedPrefixLen(vtx.ePfx, path) if nChewOff != vtx.ePfx.len: err(PartChnExtPfxMismatch) elif path.len == nChewOff: err(PartChnBranchPathExhausted) else: let nibble = path[nChewOff] rest = path.slice(nChewOff+1) # Recursion! db.chainRlpNodes((rvid.root,vtx.bVid[nibble]), rest, chain) proc trackRlpNodes*( chain: openArray[Blob]; topKey: HashKey; path: NibblesBuf; start = false; ): Result[Blob,AristoError] {.gcsafe, raises: [RlpError]} = ## Verify rlp-encoded node chain created by `chainRlpNodes()`. if path.len == 0: return err(PartTrkEmptyPath) # Verify key against rlp-node let digest = chain[0].digestTo(HashKey) if start: if topKey.to(Hash256) != digest.to(Hash256): return err(PartTrkFollowUpKeyMismatch) else: if topKey != digest: return err(PartTrkFollowUpKeyMismatch) var node = rlpFromBytes chain[0] nChewOff = 0 link: Blob # Decode rlp-node and prepare for recursion case node.listLen of 2: let (isLeaf, segm) = NibblesBuf.fromHexPrefix node.listElem(0).toBytes nChewOff = sharedPrefixLen(path, segm) link = node.listElem(1).toBytes # link or payload if isLeaf: if nChewOff == path.len: return ok(link) return err(PartTrkLeafPfxMismatch) of 17: nChewOff = 1 link = node.listElem(path[0].int).toBytes else: return err(PartTrkGarbledNode) let nextKey = HashKey.fromBytes(link).valueOr: return err(PartTrkLinkExpected) chain.toOpenArray(1,chain.len-1).trackRlpNodes(nextKey, path.slice nChewOff) # ------------------------------------------------------------------------------ # End # ------------------------------------------------------------------------------