mirror of
https://github.com/codex-storage/nim-poseidon2.git
synced 2025-02-23 16:28:07 +00:00
Streaming API for merkle root calculation
This commit is contained in:
parent
16e20ee8f7
commit
fe3e3230f4
@ -1,4 +1,3 @@
|
|||||||
import std/sequtils
|
|
||||||
import constantine/math/arithmetic
|
import constantine/math/arithmetic
|
||||||
import constantine/math/io/io_fields
|
import constantine/math/io/io_fields
|
||||||
import ./types
|
import ./types
|
||||||
@ -10,39 +9,57 @@ const KeyBottomLayer = F.fromHex("0x1")
|
|||||||
const KeyOdd = F.fromHex("0x2")
|
const KeyOdd = F.fromHex("0x2")
|
||||||
const KeyOddAndBottomLayer = F.fromhex("0x3")
|
const KeyOddAndBottomLayer = F.fromhex("0x3")
|
||||||
|
|
||||||
func merkleRoot(xs: openArray[F], isBottomLayer: static bool) : F =
|
type Merkle* = object
|
||||||
let a = low(xs)
|
todo: seq[F] # nodes that haven't been combined yet
|
||||||
let b = high(xs)
|
width: int # width of the current subtree
|
||||||
let m = b-a+1
|
leafs: int # amount of leafs processed
|
||||||
|
|
||||||
when isBottomLayer:
|
func init*(_: type Merkle): Merkle =
|
||||||
assert m > 0, "merkle root of empty sequence is not defined"
|
Merkle(width: 2)
|
||||||
|
|
||||||
when not isBottomLayer:
|
func compress(merkle: var Merkle, odd: static bool) =
|
||||||
if m==1:
|
when odd:
|
||||||
return xs[a]
|
let a = merkle.todo.pop()
|
||||||
|
let b = zero
|
||||||
let halfn : int = m div 2
|
let key = if merkle.width == 2: KeyOddAndBottomLayer else: KeyOdd
|
||||||
let n : int = 2*halfn
|
merkle.todo.add(compress(a, b, key = key))
|
||||||
let isOdd : bool = (n != m)
|
merkle.leafs += merkle.width div 2 # zero node represents this many leafs
|
||||||
|
|
||||||
var ys : seq[F]
|
|
||||||
if not isOdd:
|
|
||||||
ys = newSeq[F](halfn)
|
|
||||||
else:
|
else:
|
||||||
ys = newSeq[F](halfn+1)
|
let b = merkle.todo.pop()
|
||||||
|
let a = merkle.todo.pop()
|
||||||
|
let key = if merkle.width == 2: KeyBottomLayer else: KeyNone
|
||||||
|
merkle.todo.add(compress(a, b, key = key))
|
||||||
|
merkle.width *= 2
|
||||||
|
|
||||||
for i in 0..<halfn:
|
func update*(merkle: var Merkle, element: F) =
|
||||||
const key = when isBottomLayer: KeyBottomLayer else: KeyNone
|
merkle.todo.add(element)
|
||||||
ys[i] = compress( xs[a+2*i], xs[a+2*i+1], key = key )
|
inc merkle.leafs
|
||||||
if isOdd:
|
merkle.width = 2
|
||||||
const key = when isBottomLayer: KeyOddAndBottomLayer else: KeyOdd
|
while merkle.width <= merkle.leafs and merkle.leafs mod merkle.width == 0:
|
||||||
ys[halfn] = compress( xs[n], zero, key = key )
|
merkle.compress(odd = false)
|
||||||
|
|
||||||
return merkleRoot(ys, isBottomLayer = false)
|
func finish*(merkle: var Merkle): F =
|
||||||
|
assert merkle.todo.len > 0, "merkle root of empty sequence is not defined"
|
||||||
|
|
||||||
func merkleRoot*(xs: openArray[F]) : F =
|
if merkle.leafs == 1:
|
||||||
merkleRoot(xs, isBottomLayer = true)
|
merkle.compress(odd = true)
|
||||||
|
|
||||||
func merkleRoot*(bytes: openArray[byte]): F =
|
while merkle.todo.len > 1:
|
||||||
merkleRoot(toSeq bytes.elements(F))
|
if merkle.leafs mod merkle.width == 0:
|
||||||
|
merkle.compress(odd = false)
|
||||||
|
else:
|
||||||
|
merkle.compress(odd = true)
|
||||||
|
|
||||||
|
return merkle.todo[0]
|
||||||
|
|
||||||
|
func digest*(_: type Merkle, elements: openArray[F]): F =
|
||||||
|
var merkle = Merkle.init()
|
||||||
|
for element in elements:
|
||||||
|
merkle.update(element)
|
||||||
|
return merkle.finish()
|
||||||
|
|
||||||
|
func digest*(_: type Merkle, bytes: openArray[byte]): F =
|
||||||
|
var merkle = Merkle.init()
|
||||||
|
for element in bytes.elements(F):
|
||||||
|
merkle.update(element)
|
||||||
|
return merkle.finish()
|
||||||
|
@ -25,7 +25,7 @@ suite "merkle root":
|
|||||||
for i in 1..n:
|
for i in 1..n:
|
||||||
xs.add( toF(i) )
|
xs.add( toF(i) )
|
||||||
|
|
||||||
let root = merkleRoot(xs)
|
let root = Merkle.digest(xs)
|
||||||
check root.toHex(littleEndian) == "0x593e01f200cb1aee4e75fe2a9206abc3abd2a1216ab75f1061965e97371e8623"
|
check root.toHex(littleEndian) == "0x593e01f200cb1aee4e75fe2a9206abc3abd2a1216ab75f1061965e97371e8623"
|
||||||
|
|
||||||
test "merkle root of even elements":
|
test "merkle root of even elements":
|
||||||
@ -34,7 +34,7 @@ suite "merkle root":
|
|||||||
compress(1.toF, 2.toF, key = isBottomLayer.toF),
|
compress(1.toF, 2.toF, key = isBottomLayer.toF),
|
||||||
compress(3.toF, 4.toF, key = isBottomLayer.toF),
|
compress(3.toF, 4.toF, key = isBottomLayer.toF),
|
||||||
)
|
)
|
||||||
check bool(merkleRoot(elements) == expected)
|
check bool(Merkle.digest(elements) == expected)
|
||||||
|
|
||||||
test "merkle root of odd elements":
|
test "merkle root of odd elements":
|
||||||
let elements = toSeq(1..3).mapIt(toF(it))
|
let elements = toSeq(1..3).mapIt(toF(it))
|
||||||
@ -42,40 +42,40 @@ suite "merkle root":
|
|||||||
compress(1.toF, 2.toF, key = isBottomLayer.toF),
|
compress(1.toF, 2.toF, key = isBottomLayer.toF),
|
||||||
compress(3.toF, 0.toF, key = (isBottomLayer + isOddNode).toF)
|
compress(3.toF, 0.toF, key = (isBottomLayer + isOddNode).toF)
|
||||||
)
|
)
|
||||||
check bool(merkleRoot(elements) == expected)
|
check bool(Merkle.digest(elements) == expected)
|
||||||
|
|
||||||
test "data ending with 0 differs from padded data":
|
test "data ending with 0 differs from padded data":
|
||||||
let a = toSeq(1..3).mapIt(it.toF)
|
let a = toSeq(1..3).mapIt(it.toF)
|
||||||
let b = a & @[0.toF]
|
let b = a & @[0.toF]
|
||||||
check not bool(merkleRoot(a) == merkleRoot(b))
|
check not bool(Merkle.digest(a) == Merkle.digest(b))
|
||||||
|
|
||||||
test "merkle root of single element does not equal the element":
|
test "merkle root of single element does not equal the element":
|
||||||
check not bool(merkleRoot([1.toF]) == 1.toF)
|
check not bool(Merkle.digest([1.toF]) == 1.toF)
|
||||||
|
|
||||||
test "merkle root differs from merkle root of merkle root":
|
test "merkle root differs from merkle root of merkle root":
|
||||||
let a = 1.toF
|
let a = 1.toF
|
||||||
let b = 2.toF
|
let b = 2.toF
|
||||||
check not bool(merkleRoot([a, b]) == merkleRoot([merkleRoot([a, b])]))
|
check not bool(Merkle.digest([a, b]) == Merkle.digest([Merkle.digest([a, b])]))
|
||||||
|
|
||||||
test "merkle root of bytes":
|
test "merkle root of bytes":
|
||||||
let bytes = toSeq 1'u8..80'u8
|
let bytes = toSeq 1'u8..80'u8
|
||||||
let root = merkleRoot(bytes)
|
let root = Merkle.digest(bytes)
|
||||||
check root.toHex(littleEndian) == "0x40989b63104f39e3331767883381085bcfc46e2202679123371f1ffe53521b16"
|
check root.toHex(littleEndian) == "0x40989b63104f39e3331767883381085bcfc46e2202679123371f1ffe53521b16"
|
||||||
|
|
||||||
test "merkle root of bytes converted to bytes":
|
test "merkle root of bytes converted to bytes":
|
||||||
let bytes = toSeq 1'u8..80'u8
|
let bytes = toSeq 1'u8..80'u8
|
||||||
let rootAsBytes = merkleRoot(bytes).toBytes()
|
let rootAsBytes = Merkle.digest(bytes).toBytes()
|
||||||
check rootAsBytes.toHex == "0x40989b63104f39e3331767883381085bcfc46e2202679123371f1ffe53521b16"
|
check rootAsBytes.toHex == "0x40989b63104f39e3331767883381085bcfc46e2202679123371f1ffe53521b16"
|
||||||
|
|
||||||
test "merkle root of empty sequence of elements":
|
test "merkle root of empty sequence of elements":
|
||||||
let empty = seq[F].default
|
let empty = seq[F].default
|
||||||
expect Exception:
|
expect Exception:
|
||||||
discard merkleRoot(empty)
|
discard Merkle.digest(empty)
|
||||||
|
|
||||||
test "merkle root of empty sequency of bytes":
|
test "merkle root of empty sequency of bytes":
|
||||||
# merkle root of empty sequence of bytes is uniquely defined through padding
|
# merkle root of empty sequence of bytes is uniquely defined through padding
|
||||||
let empty = seq[byte].default
|
let empty = seq[byte].default
|
||||||
check merkleRoot(empty).toBytes.toHex == "0xcc8da1d157900e611b89e258d95450e707f4f9eec169422d7c26aba54f803c08"
|
check Merkle.digest(empty).toBytes.toHex == "0xcc8da1d157900e611b89e258d95450e707f4f9eec169422d7c26aba54f803c08"
|
||||||
|
|
||||||
suite "merkle root test vectors":
|
suite "merkle root test vectors":
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ suite "merkle root test vectors":
|
|||||||
|
|
||||||
for n in 1..40:
|
for n in 1..40:
|
||||||
let input = collect(newSeq, (for i in 1..n: i.toF))
|
let input = collect(newSeq, (for i in 1..n: i.toF))
|
||||||
let root = merkleRoot(input)
|
let root = Merkle.digest(input)
|
||||||
check root.toDecimal == expected[n-1]
|
check root.toDecimal == expected[n-1]
|
||||||
|
|
||||||
test "byte sequences":
|
test "byte sequences":
|
||||||
@ -217,5 +217,5 @@ suite "merkle root test vectors":
|
|||||||
|
|
||||||
for n in 0..80:
|
for n in 0..80:
|
||||||
let input = collect(newSeq, (for i in 1..n: byte(i)))
|
let input = collect(newSeq, (for i in 1..n: byte(i)))
|
||||||
let root = merkleRoot(input)
|
let root = Merkle.digest(input)
|
||||||
check root.toDecimal == expected[n]
|
check root.toDecimal == expected[n]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user