/ reference / nim / proof_input / src / merkle / goldilocks / poseidon2.nim
poseidon2.nim
 1  
 2  import std/sequtils
 3  
 4  import goldilocks_hash/types
 5  import goldilocks_hash/poseidon2/compress
 6  import goldilocks_hash/poseidon2/merkle
 7  import goldilocks_hash/poseidon2/sponge
 8  
 9  import ../../types
10  import ../../types/goldilocks
11  
12  #-------------------------------------------------------------------------------
13  
14  func compressWithkey*(key: int, x, y: Digest): Digest = compress(x,y, key=uint64(key))
15  
16  func merkleDigestPoseidon2*(xs: openArray[Digest]): Digest = Merkle.digest(xs)
17  
18  # TODO: move these somewhere else
19  func digestFeltsPoseidon2*(xs: openArray[F]   ): Digest = digestFeltsC( rate=8, xs )
20  func digestBytesPoseidon2*(xs: openArray[byte]): Digest = digestBytesC( rate=8, xs )
21  
22  #-------------------------------------------------------------------------------
23  
24  const KeyNone              : uint64 = 0x00
25  const KeyBottomLayer       : uint64 = 0x01
26  const KeyOdd               : uint64 = 0x02
27  const KeyOddAndBottomLayer : uint64 = 0x03
28  
29  func merkleTreeWorker(xs: openArray[Digest], isBottomLayer: static bool) : seq[seq[Digest]] =
30    let a = low(xs)
31    let b = high(xs)
32    let m = b-a+1
33  
34    when not isBottomLayer:
35      if m==1:
36        return @[ xs.toSeq() ]
37  
38    let halfn  : int  = m div 2
39    let n      : int  = 2*halfn
40    let isOdd : bool = (n != m)
41  
42    var ys : seq[Digest]
43    if not isOdd:
44      ys = newSeq[Digest](halfn)
45    else:
46      ys = newSeq[Digest](halfn+1)
47  
48    for i in 0..<halfn:
49      const key = when isBottomLayer: KeyBottomLayer else: KeyNone
50      ys[i] = compress( xs[a+2*i], xs[a+2*i+1], key = key )
51    if isOdd:
52      const key = when isBottomLayer: KeyOddAndBottomLayer else: KeyOdd
53      ys[halfn] = compress( xs[n], zeroDigest, key = key )
54  
55    var ls : seq[seq[Digest]] 
56    ls = @[ xs.toSeq() ] 
57    ls = ls & merkleTreeWorker(ys, isBottomLayer = false)
58    return ls
59  
60  #-------------------------------------------------------------------------------
61  
62  func merkleTreeGoldilocksPoseidon2*(xs: openArray[Digest]) : MerkleTree[Digest] =
63    return MerkleTree[Digest](layers: merkleTreeWorker(xs, isBottomLayer = true))
64  
65  #-------------------------------------------------------------------------------