From 25b446c1b1ee34586fe00f1a5b586c95997ff7a3 Mon Sep 17 00:00:00 2001 From: Dmitriy Ryajov Date: Mon, 23 Oct 2023 16:25:42 -0600 Subject: [PATCH] wip --- codex/manifest/manifest.nim | 11 +- codex/merkletree/merkletree.nim | 407 ++++++-------------------------- codex/utils.nim | 1 - 3 files changed, 76 insertions(+), 343 deletions(-) diff --git a/codex/manifest/manifest.nim b/codex/manifest/manifest.nim index 7c7ef7c1..eb2161f3 100644 --- a/codex/manifest/manifest.nim +++ b/codex/manifest/manifest.nim @@ -225,9 +225,8 @@ proc new*( originalDatasetSize: manifest.datasetSize) proc new*( - T: type Manifest, - manifest: Manifest -): Manifest = + T: type Manifest, + manifest: Manifest): Manifest = ## Create an unprotected dataset from an ## erasure protected one ## @@ -244,8 +243,7 @@ proc new*( proc new*( T: type Manifest, data: openArray[byte], - decoder = ManifestContainers[$DagPBCodec] -): ?!Manifest = + decoder = ManifestContainers[$DagPBCodec]): ?!Manifest = ## Create a manifest instance from given data ## Manifest.decode(data, decoder) @@ -263,8 +261,7 @@ proc new*( ecM: int, originalTreeCid: Cid, originalTreeRoot: MultiHash, - originalDatasetSize: NBytes -): Manifest = + originalDatasetSize: NBytes): Manifest = Manifest( treeCid: treeCid, treeRoot: treeRoot, diff --git a/codex/merkletree/merkletree.nim b/codex/merkletree/merkletree.nim index 0e1ee4b4..af9c54dc 100644 --- a/codex/merkletree/merkletree.nim +++ b/codex/merkletree/merkletree.nim @@ -26,79 +26,65 @@ logScope: type MerkleTree* = object - mcodec: MultiCodec - digestSize: Natural - leavesCount: Natural - nodesBuffer*: seq[byte] + mcodec: MultiCodec # multicodec of the hash function + maxWidth: Natural # max width of the tree + height: Natural # current height of the tree (levels - 1) + levels: Natural # number of levels in the tree (height + 1) + leafs: Natural # total number of leafs, if odd the last leaf will be hashed twice + nodes: seq[seq[byte]] # nodes of the tree (this should be an iterator) + MerkleProof* = object mcodec: MultiCodec - digestSize: Natural index: Natural - nodesBuffer*: seq[byte] - MerkleTreeBuilder* = object - mcodec: MultiCodec - digestSize: Natural - buffer: seq[byte] + nodes*: seq[seq[byte]] ########################################################### -# Helper functions +# MerkleTree ########################################################### -func computeTreeHeight(leavesCount: int): int = - if isPowerOfTwo(leavesCount): - fastLog2(leavesCount) + 1 - else: - fastLog2(leavesCount) + 2 +proc root*(self: MerkleTree): ?!MultiHash = + echo self.nodes.len + if self.nodes.len == 0 or self.nodes[^1].len == 0: + return failure("Tree hasn't been build") -func computeLevels(leavesCount: int): seq[tuple[offset: int, width: int, index: int]] = - let height = computeTreeHeight(leavesCount) - var levels = newSeq[tuple[offset: int, width: int, index: int]](height) - - levels[0].offset = 0 - levels[0].width = leavesCount - levels[0].index = 0 - for i in 1.. dst.len: - return failure("Not enough space in a destination buffer") - dst[dstPos.. self.nodeBufferToMultiHash(i)) - -proc mcodec*(self: (MerkleTree | MerkleProof)): MultiCodec = - self.mcodec - -proc digestSize*(self: (MerkleTree | MerkleProof)): Natural = - self.digestSize - -proc root*(self: MerkleTree): MultiHash = - let rootIndex = self.len - 1 - self.nodeBufferToMultiHash(rootIndex) - -proc leaves*(self: MerkleTree): seq[MultiHash] = - toSeq(0.. self.nodeBufferToMultiHash(i)) - -proc leavesCount*(self: MerkleTree): Natural = - self.leavesCount - -proc getLeaf*(self: MerkleTree, index: Natural): ?!MultiHash = - if index >= self.leavesCount: - return failure("Index " & $index & " out of range [0.." & $(self.leavesCount - 1) & "]" ) - - success(self.nodeBufferToMultiHash(index)) - -proc height*(self: MerkleTree): Natural = - computeTreeHeight(self.leavesCount) - -proc getProof*(self: MerkleTree, index: Natural): ?!MerkleProof = - ## Extracts proof from a tree for a given index - ## - ## Given a tree built from data blocks A, B and C - ## H5 - ## / \ - ## H3 H4 - ## / \ / - ## H0 H1 H2 - ## | | | - ## A B C - ## - ## Proofs of inclusion (index and path) are - ## - 0,[H1, H4] for data block A - ## - 1,[H0, H4] for data block B - ## - 2,[0x00, H3] for data block C - ## - if index >= self.leavesCount: - return failure("Index " & $index & " out of range [0.." & $(self.leavesCount - 1) & "]" ) - - var zero = newSeq[byte](self.digestSize) - var one = newSeq[byte](self.digestSize) - one[^1] = 0x01 - - let levels = computeLevels(self.leavesCount) - var proofNodesBuffer = newSeq[byte]((levels.len - 1) * self.digestSize) - for level in levels[0..^2]: - let lr = index shr level.index - let siblingIndex = if lr mod 2 == 0: - level.offset + lr + 1 + length = if bool(self.leafs and 1): + self.nodes[self.leafs] = self.nodes[self.leafs - 1] # even out the tree + self.leafs + 1 else: - level.offset + lr - 1 + self.leafs - var dummyValue = if level.index == 0: zero else: one + while length > 1: + for i in 0..