sapling2.prf 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. # You will need this repo:
  2. # https://github.com/zcash/librustzcash/
  3. # Then compare this code to the file:
  4. # librustzcash/zcash_proofs/src/circuit/sapling.rs
  5. # What is the LC stuff?
  6. # Difference between AllocatedNum and Num
  7. # Why BlsScalar vs JJScalar?
  8. const:
  9. G_VCV: Point
  10. G_VCR: Point
  11. G_SPEND: Point
  12. G_PROOF: Point
  13. G_NOTE_COMMIT_R: Point
  14. G_NULL: Point
  15. CRH_IVK: Blake2sPersonalization
  16. NOTE_COMMIT: PedersenPersonalization
  17. MERKLE: list<PedersenPersonalization>
  18. PRF_NF: Blake2sPersonalization
  19. def value_commit(value: u64, randomness: Scalar) -> (Point, list<bool>):
  20. let value_bits: list<bool> = value as list<bool>
  21. let value: Point = value * G_VCV
  22. let rcv: list<bool> = randomness as list<bool>
  23. let rcv: Point = rcv * G_VCR
  24. let cv: Point = value + rcv
  25. emit cv
  26. return value_bits
  27. # The parameters to this function are the same as in:
  28. # struct Spend
  29. proof input_burn:
  30. private:
  31. value: u64 # ValueCommitment.value
  32. randomness: Scalar # ValueCommitment.randomness
  33. ak: Point # from ProofGenerationKey
  34. ar: Scalar
  35. nsk: Scalar # from ProofGenerationKey
  36. g_d: Point # Computed from payment_address
  37. commitment_randomness: Scalar
  38. auth_path: list<(Scalar, bool)>
  39. anchor: Scalar
  40. contract -> (Point, Point, Point, list<bool>):
  41. let ak = witness(ak)
  42. ak.assert_not_small_order()
  43. let ar: list<bool> = ar as list<bool>
  44. let ar: Point = ar * G_SPEND
  45. let rk: Point = ak + ar
  46. emit rk
  47. let nsk: list<bool> = nsk as list<bool>
  48. let nk: Point = nsk * G_PROOF
  49. let mut ivk_preimage: list<bool> = []
  50. # Must be list<bool> as well
  51. ivk_preimage.extend(ak.repr())
  52. let mut nf_preimage: list<bool> = []
  53. let nk_repr: list<bool> = nk.repr()
  54. ivk_preimage.extend(nk_repr)
  55. nf_preimage.extend(nk_repr)
  56. assert len(ivk_preimage) == 512
  57. assert len(nf_preimage) == 256
  58. let mut ivk: list<bool> = blake2s(ivk_preimage, CRH_IVK)
  59. ivk.truncate(Scalar::CAPACITY)
  60. let g_d: Point = witness g_d
  61. g_d.assert_not_small_order()
  62. let pk_d: Point = ivk * g_d
  63. let mut note_contents: list<bool> = []
  64. let (cv: Point, value_bits: list<bool>) = value_commit(value, randomness)
  65. let mut value_num: Num = Num.zero()
  66. let mut coeff: Scalar = Scalar.one()
  67. for bit in value_bits:
  68. value_num = value_num.add_bool_with_coeff(bit, coeff)
  69. coeff = coeff.double()
  70. # Is this equivalent?
  71. let value_num = value_bits as Num
  72. note_contents.extend(value_bits)
  73. note_contents.extend(g_d)
  74. note_contents.extend(pk_d)
  75. assert len(note_contents) == 64 + 256 + 256
  76. let mut cm: Point = pedersen_hash(NOTE_COMMIT, note_contents)
  77. let rcm: list<bool> = commitment_randomness as list<bool>
  78. let rcm: Point = rcm * G_NOTE_COMMIT_R
  79. cm += rcm
  80. let mut position_bits: list<bool> = []
  81. let mut cur: Scalar = cm.u
  82. for i, (node, is_right) in enumerate(auth_path):
  83. position_bits.push(is_right)
  84. let node: EncryptedNum = EncryptedNum.from(node)
  85. print(node)
  86. let (left: list<bool>, right: list<bool>) = Num.swap_if(is_right, cur, node)
  87. let mut preimage: list<bool> = []
  88. preimage.extend(left)
  89. preimage.extend(right)
  90. cur = pedersen_hash(MERKLE_TREE[i], preimage).u
  91. let rt: Point = EncryptedNum.from(anchor)
  92. enforce (cur - rt) * value_num == 0
  93. emit rt
  94. let position: Point = position_bits * G_NULL
  95. let rho: Point = cm + position
  96. nf_preimage.extend(rho)
  97. assert len(nf_preimage) == 512
  98. let nf: list<bool> = blake2s(nf_preimage, PRF_NF)
  99. emit nf
  100. def output_mint(
  101. value: u64,
  102. randomness: Scalar,
  103. g_d: Point,
  104. esk: Scalar,
  105. pk_d: Point,
  106. commitment_randomness: Scalar
  107. ) -> (Point, Point, Scalar):
  108. let (cv: Point, value_bits: list<bool>) = value_commit(value, randomness)
  109. let mut note_contents: list<bool> = []
  110. note_contents.extend(value_bits)
  111. let g_d: Point = witness g_d
  112. assert is_not_small_order(g_d)
  113. let esk: list<bool> = esk as list<bool>
  114. let epk: Point = esk * g_d
  115. let v_contents: list<bool> = pk_d.v as list<bool>
  116. let sign_bit: bool = pk_d.u.is_odd() as bool
  117. note_contents.extend(v_contents)
  118. note_contents.push(sign_bit)
  119. assert len(note_contents) == 64 + 256 + 256
  120. let mut cm: Point = pedersen_hash(NOTE_COMMIT, note_contents)
  121. let rcm: list<bool> = commitment_randomness as list<bool>
  122. let rcm: Point = rcm * G_NOTE_COMMIT_R
  123. cm += rcm
  124. let cmu: Scalar = cm.u
  125. return (cv, epk, cmu)