diff --git a/codex/merkletree/merkletreeold.nim b/codex/merkletree/merkletreeold.nim deleted file mode 100644 index 74ddba6d..00000000 --- a/codex/merkletree/merkletreeold.nim +++ /dev/null @@ -1,418 +0,0 @@ -## Nim-Codex -## Copyright (c) 2023 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. - -import std/math -import std/bitops -import std/sequtils -import std/sugar -import std/algorithm - -import pkg/chronicles -import pkg/questionable -import pkg/questionable/results -import pkg/nimcrypto/sha2 -import pkg/libp2p/[cid, multicodec, multihash, vbuffer] -import pkg/stew/byteutils - -import ../errors - -logScope: - topics = "codex merkletree" - -type - MerkleTree* = object - mcodec: MultiCodec - digestSize: Natural - leavesCount: Natural - nodesBuffer*: seq[byte] - MerkleProof* = object - mcodec: MultiCodec - digestSize: Natural - index: Natural - nodesBuffer*: seq[byte] - MerkleTreeBuilder* = object - mcodec: MultiCodec - digestSize: Natural - buffer: seq[byte] - -########################################################### -# Helper functions -########################################################### - -func computeTreeHeight(leavesCount: int): int = - if isPowerOfTwo(leavesCount): - fastLog2(leavesCount) + 1 - else: - fastLog2(leavesCount) + 2 - -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 rootCid*(self: MerkleTree, version = CIDv1, dataCodec = multiCodec("raw")): ?!Cid = - Cid.init(version, dataCodec, self.root).mapFailure - -iterator leaves*(self: MerkleTree): MultiHash = - for i in 0..= self.leavesCount: - return failure("Index " & $index & " out of range [0.." & $(self.leavesCount - 1) & "]" ) - - success(self.nodeBufferToMultiHash(index)) - -proc getLeafCid*(self: MerkleTree, index: Natural, version = CIDv1, dataCodec = multiCodec("raw")): ?!Cid = - let leaf = ? self.getLeaf(index) - Cid.init(version, dataCodec, leaf).mapFailure - -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 - else: - level.offset + lr - 1 - - var dummyValue = if level.index == 0: zero else: one - - if siblingIndex < level.offset + level.width: - proofNodesBuffer[level.index * self.digestSize..<(level.index + 1) * self.digestSize] = - self.nodesBuffer[siblingIndex * self.digestSize..<(siblingIndex + 1) * self.digestSize] - else: - proofNodesBuffer[level.index * self.digestSize..<(level.index + 1) * self.digestSize] = dummyValue - - success(MerkleProof(mcodec: self.mcodec, digestSize: self.digestSize, index: index, nodesBuffer: proofNodesBuffer)) - -proc `$`*(self: MerkleTree): string {.noSideEffect.} = - "mcodec:" & $self.mcodec & - ", digestSize: " & $self.digestSize & - ", leavesCount: " & $self.leavesCount & - ", nodes: " & $self.nodes - -proc `==`*(a, b: MerkleTree): bool = - (a.mcodec == b.mcodec) and - (a.digestSize == b.digestSize) and - (a.leavesCount == b.leavesCount) and - (a.nodesBuffer == b.nodesBuffer) - -proc init*( - T: type MerkleTree, - mcodec: MultiCodec, - digestSize: Natural, - leavesCount: Natural, - nodesBuffer: seq[byte] -): ?!MerkleTree = - let levels = computeLevels(leavesCount) - let totalNodes = levels[^1].offset + 1 - if totalNodes * digestSize == nodesBuffer.len: - success( - MerkleTree( - mcodec: mcodec, - digestSize: digestSize, - leavesCount: leavesCount, - nodesBuffer: nodesBuffer - ) - ) - else: - failure("Expected nodesBuffer len to be " & $(totalNodes * digestSize) & " but was " & $nodesBuffer.len) - -proc init*( - T: type MerkleTree, - leaves: openArray[MultiHash] -): ?!MerkleTree = - without leaf =? leaves.?[0]: - return failure("At least one leaf is required") - - var builder = ? MerkleTreeBuilder.init(mcodec = leaf.mcodec) - - for l in leaves: - let res = builder.addLeaf(l) - if res.isErr: - return failure(res.error) - - builder.build() - -proc init*( - T: type MerkleTree, - cids: openArray[Cid] -): ?!MerkleTree = - var leaves = newSeq[MultiHash]() - - for cid in cids: - let res = cid.mhash.mapFailure - if res.isErr: - return failure(res.error) - else: - leaves.add(res.value) - - MerkleTree.init(leaves) - -########################################################### -# MerkleProof -########################################################### - -proc verifyLeaf*(self: MerkleProof, leaf: MultiHash, treeRoot: MultiHash): ?!bool = - if leaf.mcodec != self.mcodec: - return failure("Leaf mcodec was " & $leaf.mcodec & ", but " & $self.mcodec & " expected") - - if leaf.mcodec != self.mcodec: - return failure("Tree root mcodec was " & $treeRoot.mcodec & ", but " & $treeRoot.mcodec & " expected") - - var digestBuf = newSeq[byte](self.digestSize) - digestBuf[0..^1] = leaf.data.buffer[leaf.dpos..<(leaf.dpos + self.digestSize)] - - let proofLen = self.nodesBuffer.len div self.digestSize - var concatBuf = newSeq[byte](2 * self.digestSize) - for i in 0..