diff --git a/codex/merkletree/merkletree.nim b/codex/merkletree/merkletree.nim new file mode 100644 index 00000000..6fcb4682 --- /dev/null +++ b/codex/merkletree/merkletree.nim @@ -0,0 +1,189 @@ +## Nim-Codex +## Copyright (c) 2022 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/sequtils +import std/math +import std/bitops +import std/sugar + +import pkg/libp2p +import pkg/stew/byteutils +import pkg/questionable +import pkg/questionable/results + +type + MerkleHash* = MultiHash + MerkleTree* = object + leavesCount: int + nodes: seq[MerkleHash] + MerkleProof* = object + index: int + path: seq[MerkleHash] + +# Tree constructed from leaves H0..H2 is +# H5=H(H3 & H4) +# / \ +# H3=H(H0 & H1) H4=H(H2 & H2) +# / \ / +# H0=H(A) H1=H(B) H2=H(C) +# | | | +# A B C +# +# Memory layout is [H0, H1, H2, H3, H4, H5] +# +# Proofs of inclusion are +# - [H1, H4] for A +# - [H0, H4] for B +# - [H2, H3] for C + + +func computeTreeHeight(leavesCount: int): int = + if isPowerOfTwo(leavesCount): + fastLog2(leavesCount) + 1 + else: + fastLog2(leavesCount) + 2 + +func getLowHigh(leavesCount, level: int): (int, int) = + var width = leavesCount + var low = 0 + for _ in 0..= self.leavesCount or index < 0: + return failure("Index " & $index & " out of range [0.." & $self.leaves.high & "]" ) + + var path = newSeq[MerkleHash](self.height - 1) + for level in 0.. newException(CatchableError, "Error calculating hash using codec " & $mcodec & ": " & $c) + ) + + # copy leaves + for i in 0..