witness_gen.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #!/usr/bin/env python3
  2. # This file is part of DarkFi (https://dark.fi)
  3. #
  4. # Copyright (C) 2020-2026 Dyne.org foundation
  5. #
  6. # This program is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU Affero General Public License as
  8. # published by the Free Software Foundation, either version 3 of the
  9. # License, or (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU Affero General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU Affero General Public License
  17. # along with this program. If not, see <https://www.gnu.org/licenses/>.
  18. """
  19. Example witness generation for some circuit.
  20. Here we generate them for opcodes.zk
  21. This reflects /darkfi/tests/zkvm_opcodes.rs
  22. """
  23. import json
  24. from darkfi_sdk.pasta import Ep, Fp, Fq, nullifier_k, EpAffine, fp_mod_fv
  25. from darkfi_sdk.crypto import poseidon_hash, pedersen_commitment_u64
  26. from darkfi_sdk.merkle import MerkleTree
  27. # Creating base elements and scalars
  28. value = 666
  29. value_blind = Fq.random()
  30. blind = Fp.random()
  31. secret = Fp.random()
  32. a = Fp.from_u64(42)
  33. b = Fp.from_u64(69)
  34. # Creating a Merkle tree (internally using bridgetree)
  35. tree = MerkleTree()
  36. c0 = Fp.random()
  37. c1 = Fp.random()
  38. c2 = poseidon_hash([Fp.one(), Fp.from_u64(2), blind])
  39. c3 = Fp.random()
  40. # Appending and marking leaves in the Merkle tree
  41. tree.append(c0)
  42. tree.mark()
  43. tree.append(c1)
  44. tree.append(c2)
  45. leaf_pos = tree.mark()
  46. tree.append(c3)
  47. tree.mark()
  48. # Calculating the tree root and authentication path
  49. root = tree.root(0)
  50. path = tree.witness(leaf_pos, 0)
  51. # Elliptic curve multiplication
  52. ephem_secret = Fp.random()
  53. pubkey = Ep.from_affine(nullifier_k()) * fp_mod_fv(ephem_secret)
  54. ephem_public = pubkey * fp_mod_fv(ephem_secret)
  55. ephem_x, ephem_y = EpAffine.from_projective(ephem_public).coordinates()
  56. value_commit = pedersen_commitment_u64(value, value_blind)
  57. value_coords = EpAffine.from_projective(value_commit).coordinates()
  58. d = poseidon_hash([Fp.one(), blind, value_coords[0], value_coords[1]])
  59. public = Ep.from_affine(nullifier_k()) * fp_mod_fv(secret)
  60. pub_x, pub_y = EpAffine.from_projective(public).coordinates()
  61. # Create the object representing the JSON witnesses file.
  62. w = {}
  63. # Private witnesses for the proof
  64. # yapf: disable
  65. w["witnesses"] = [
  66. {"Base": str(Fp.from_u64(value))},
  67. {"Scalar": str(value_blind)},
  68. {"Base": str(blind)},
  69. {"Base": str(a)},
  70. {"Base": str(b)},
  71. {"Base": str(secret)},
  72. {"EcNiPoint": EpAffine.from_projective(pubkey).coordinates_str()},
  73. {"Base": str(ephem_secret)},
  74. {"Uint32": leaf_pos},
  75. {"MerklePath": [str(i) for i in path]},
  76. {"Base": str(Fp.one())},
  77. ]
  78. # Public inputs for the proof
  79. # yapf: disable
  80. w["instances"] = [
  81. str(value_coords[0]),
  82. str(value_coords[1]),
  83. str(c2),
  84. str(d),
  85. str(root),
  86. str(pub_x),
  87. str(pub_y),
  88. str(ephem_x),
  89. str(ephem_y),
  90. str(a),
  91. str(Fp.zero()),
  92. ]
  93. # Printing the expected JSON file used by zkrunner.
  94. print(json.dumps(w, indent=2))