spend.pism 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. constant G_VCV FixedGenerator
  2. constant G_VCR FixedGenerator
  3. constant G_SPEND FixedGenerator
  4. constant PRF_NF BlakePersonalization
  5. constant CRH_IVK BlakePersonalization
  6. constant NOTE_COMMIT PedersenPersonalization
  7. {% for i in range(32) %}
  8. constant MERKLE_{{ i }} PedersenPersonalization
  9. {% endfor %}
  10. contract spend_contract
  11. # Value commitment
  12. param value U64
  13. param asset_id U64
  14. param randomness_value Fr
  15. param randomness_asset Fr
  16. param serial Fr
  17. param randomness_coin Fr
  18. param secret Fr
  19. param signature_secret Fr
  20. {% for i in range(32) %}
  21. param branch_{{ i }} Scalar
  22. param is_right_{{ i }} Bool
  23. {% endfor %}
  24. start
  25. # Witness input values
  26. u64_as_binary_le value param:value
  27. u64_as_binary_le asset_id param:asset_id
  28. fr_as_binary_le randomness_value param:randomness_value
  29. fr_as_binary_le randomness_asset param:randomness_asset
  30. # Make value commitment
  31. # V = v * G_VCV + r * G_VCR
  32. ec_mul_const vcv value G_VCV
  33. ec_mul_const rcv randomness_value G_VCR
  34. ec_add cv vcv rcv
  35. # emit cv
  36. emit_ec cv
  37. # Make asset_id commitment
  38. # A = a * G_VCV + r * G_VCR
  39. ec_mul_const vca asset_id G_VCV
  40. ec_mul_const rca randomness_asset G_VCR
  41. ec_add ca vca rca
  42. # emit ca
  43. emit_ec ca
  44. # Make the nullifier
  45. # N = Hash(secret, serial)
  46. fr_as_binary_le serial param:serial
  47. fr_as_binary_le secret param:secret
  48. alloc_binary nf_preimage
  49. # Fr values are 252 bits so we need to pad it with extra 0s
  50. # to match the Rust values which are 256 bits
  51. {% macro binary_put_fr(binary, var) -%}
  52. binary_extend {{ binary }} {{ var }}
  53. {% for n in range(4) %}
  54. alloc_const_bit zero_bit false
  55. binary_push {{ binary }} zero_bit
  56. {% endfor %}
  57. {%- endmacro %}
  58. # secret
  59. binary_clone secret2 secret
  60. {{ binary_put_fr("nf_preimage", "secret2") }}
  61. # serial
  62. binary_clone serial2 serial
  63. {{ binary_put_fr("nf_preimage", "serial2") }}
  64. # Secret: Fr = 252 + 4 bits padding
  65. # Serial: Fr = 252 + 4 bits padding
  66. # TOTAL: 512 bits for preimage
  67. static_assert_binary_size nf_preimage 512
  68. blake2s nf nf_preimage PRF_NF
  69. emit_binary nf
  70. # Derive the public key
  71. # P = secret * G
  72. ec_mul_const public secret G_SPEND
  73. # Make the coin (same as mint contract)
  74. # C = Hash(public_key, value, asset_id, serial, randomness_coin)
  75. fr_as_binary_le randomness_coin param:randomness_coin
  76. # Build the preimage to hash
  77. alloc_binary preimage
  78. # public_key
  79. ec_repr repr_public public
  80. binary_extend preimage repr_public
  81. # value
  82. binary_extend preimage value
  83. # asset_id
  84. binary_extend preimage asset_id
  85. # serial
  86. {{ binary_put_fr("preimage", "serial") }}
  87. # randomness_coin
  88. {{ binary_put_fr("preimage", "randomness_coin") }}
  89. # Public key: SubgroupPoint = 256 bits
  90. # Value: u64 = 64 bits
  91. # Serial: Fr = 252 + 4 bits padding
  92. # Randomness coin Fr = 252 + 4 bits padding
  93. # TOTAL: 896 bits for preimage
  94. static_assert_binary_size preimage 896
  95. blake2s coin preimage CRH_IVK
  96. # Debug stuff. Normally we don't reveal the coin in the spend proof.
  97. #binary_clone coin2 coin
  98. #emit_binary coin2
  99. # coin_commit = PedersenHash(coin)
  100. pedersen_hash cm coin NOTE_COMMIT
  101. # left = coin_commit.u
  102. ec_get_u current cm
  103. # Our merkle tree has a height of 32
  104. {% for i in range(32) %}
  105. # left = current
  106. # right = branch[{{ i }}]
  107. alloc_scalar branch param:branch_{{ i }}
  108. # is_right = is_right[{{ i }}]
  109. alloc_bit is_right param:is_right_{{ i }}
  110. # reverse(a, b, condition) = if condition (b, a) else (a, b)
  111. conditionally_reverse left right current branch is_right
  112. # coin_commit = PedersenHash(left || right)
  113. scalar_as_binary left left
  114. scalar_as_binary right right
  115. alloc_binary preimage
  116. binary_extend preimage left
  117. binary_extend preimage right
  118. pedersen_hash cm preimage MERKLE_{{ i }}
  119. # current = coin_commit.u
  120. ec_get_u current cm
  121. {% endfor %}
  122. # Reveal the merkle root
  123. emit_scalar current
  124. # Emit the signature public key
  125. fr_as_binary_le signature_secret param:signature_secret
  126. ec_mul_const signature_public signature_secret G_SPEND
  127. emit_ec signature_public
  128. end