tx.rs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. use bellman::groth16;
  2. use bls12_381::Bls12;
  3. use ff::{Field, PrimeField};
  4. use group::Group;
  5. use rand::rngs::OsRng;
  6. use std::io;
  7. use std::path::Path;
  8. use sapvi::crypto::{
  9. coin::Coin,
  10. create_mint_proof, create_spend_proof, load_params,
  11. merkle::{CommitmentTree, IncrementalWitness},
  12. note::Note,
  13. save_params, setup_mint_prover, setup_spend_prover, verify_mint_proof, verify_spend_proof,
  14. MintRevealedValues, SpendRevealedValues,
  15. };
  16. use sapvi::error::{Error, Result};
  17. use sapvi::serial::{Decodable, Encodable, VarInt};
  18. use sapvi::state::{state_transition, ProgramState, StateUpdates};
  19. use sapvi::tx;
  20. struct MemoryState {
  21. mint_pvk: groth16::PreparedVerifyingKey<Bls12>,
  22. spend_pvk: groth16::PreparedVerifyingKey<Bls12>,
  23. cashier_public: jubjub::SubgroupPoint,
  24. }
  25. impl ProgramState for MemoryState {
  26. fn is_valid_cashier_public_key(&self, public: &jubjub::SubgroupPoint) -> bool {
  27. public == &self.cashier_public
  28. }
  29. fn mint_pvk(&self) -> &groth16::PreparedVerifyingKey<Bls12> {
  30. &self.mint_pvk
  31. }
  32. fn spend_pvk(&self) -> &groth16::PreparedVerifyingKey<Bls12> {
  33. &self.spend_pvk
  34. }
  35. }
  36. impl MemoryState {
  37. fn apply(updates: StateUpdates) {}
  38. }
  39. fn main() {
  40. // Auto create trusted ceremony parameters if they don't exist
  41. if !Path::new("mint.params").exists() {
  42. let params = setup_mint_prover();
  43. save_params("mint.params", &params);
  44. }
  45. if !Path::new("spend.params").exists() {
  46. let params = setup_spend_prover();
  47. save_params("spend.params", &params);
  48. }
  49. // Load trusted setup parameters
  50. let (mint_params, mint_pvk) = load_params("mint.params").expect("params should load");
  51. let (spend_params, spend_pvk) = load_params("spend.params").expect("params should load");
  52. // Cashier creates a secret key
  53. let cashier_secret = jubjub::Fr::random(&mut OsRng);
  54. // This is their public key
  55. let cashier_public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * cashier_secret;
  56. let state = MemoryState {
  57. mint_pvk,
  58. spend_pvk,
  59. cashier_public,
  60. };
  61. // Wallet 1 creates a secret key
  62. let secret = jubjub::Fr::random(&mut OsRng);
  63. // This is their public key
  64. let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
  65. // Step 1: Cashier deposits to wallet1's address
  66. // Create the deposit for 110 BTC
  67. // Clear inputs are visible to everyone on the network
  68. let builder = tx::TransactionBuilder {
  69. clear_inputs: vec![tx::TransactionBuilderClearInputInfo {
  70. value: 110,
  71. signature_secret: cashier_secret,
  72. }],
  73. inputs: vec![],
  74. outputs: vec![tx::TransactionBuilderOutputInfo { value: 110, public }],
  75. };
  76. // We will 'compile' the tx, and then serialize it to this Vec<u8>
  77. let mut tx_data = vec![];
  78. {
  79. // Build the tx
  80. let tx = builder.build(&mint_params, &spend_params);
  81. // Now serialize it
  82. tx.encode(&mut tx_data).expect("encode tx");
  83. }
  84. // Step 1 is completed.
  85. // Tx data is posted to the blockchain
  86. // Step 2: wallet1 receive's payment from the cashier
  87. // Wallet1 is receiving tx, and for every new coin it finds, it adds to its merkle tree
  88. let mut tree = CommitmentTree::empty();
  89. // Here we simulate 5 fake random coins, adding them to our tree.
  90. for i in 0..5 {
  91. let cmu = Coin::new(bls12_381::Scalar::random(&mut OsRng).to_repr());
  92. tree.append(cmu);
  93. }
  94. // Now we receive the tx data
  95. let note = {
  96. let txx = tx::Transaction::decode(&tx_data[..]).unwrap();
  97. let tx = tx::Transaction::decode(&tx_data[..]).unwrap();
  98. let update = state_transition(&state, txx).expect("step 2 state transition failed");
  99. // Check the tx verifies correctly
  100. //assert!(tx.verify(&mint_pvk, &spend_pvk));
  101. // Add the new coins to the merkle tree
  102. tree.append(Coin::new(tx.outputs[0].revealed.coin))
  103. .expect("append merkle");
  104. // Now for every new tx we receive, the wallets should iterate over all outputs
  105. // and try to decrypt the coin's note.
  106. // If they can successfully decrypt it, then it's a coin destined for us.
  107. // Try to decrypt output note
  108. let note = tx.outputs[0]
  109. .enc_note
  110. .decrypt(&secret)
  111. .expect("note should be destined for us");
  112. // This contains the secret attributes so we can spend the coin
  113. note
  114. };
  115. // Wallet1 has received payment from the cashier.
  116. // Step 2 is complete.
  117. // We need to keep track of the witness for this coin.
  118. // This allows us to prove inclusion of the coin in the merkle tree with ZK.
  119. // Just as we update the merkle tree with every new coin, so we do the same with the witness.
  120. // Derive the current witness from the current tree.
  121. // This is done right after we add our coin to the tree (but before any other coins are added)
  122. let mut witness = IncrementalWitness::from_tree(&tree);
  123. // Check this is the 6th coin we added
  124. assert_eq!(witness.position(), 5);
  125. assert_eq!(tree.root(), witness.root());
  126. // Add some more random coins in
  127. for i in 0..10 {
  128. let cmu = Coin::new(bls12_381::Scalar::random(&mut OsRng).to_repr());
  129. tree.append(cmu);
  130. witness.append(cmu);
  131. assert_eq!(tree.root(), witness.root());
  132. }
  133. // TODO: Some stupid glue code. Need to put this somewhere else.
  134. let merkle_path = witness.path().unwrap();
  135. let auth_path: Vec<(bls12_381::Scalar, bool)> = merkle_path
  136. .auth_path
  137. .iter()
  138. .map(|(node, b)| ((*node).into(), *b))
  139. .collect();
  140. // Step 3: wallet1 sends payment to wallet2
  141. // Wallet1 now wishes to send the coin to wallet2
  142. let secret2 = jubjub::Fr::random(&mut OsRng);
  143. // This is their public key
  144. let public2 = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret2;
  145. // Make a spend tx
  146. // Get the coin we're spending from the previous tx
  147. let coin = {
  148. let tx = tx::Transaction::decode(&tx_data[..]).unwrap();
  149. tx.outputs[0].revealed.coin
  150. };
  151. // Construct a new tx spending the coin
  152. // We need the decrypted note and our private key
  153. let builder = tx::TransactionBuilder {
  154. clear_inputs: vec![],
  155. inputs: vec![tx::TransactionBuilderInputInfo {
  156. coin,
  157. merkle_path: auth_path,
  158. merkle_root: tree,
  159. secret,
  160. note,
  161. }],
  162. // We can add more outputs to this list.
  163. // The only constraint is that sum(value in) == sum(value out)
  164. outputs: vec![tx::TransactionBuilderOutputInfo {
  165. value: 110,
  166. public: public2,
  167. }],
  168. };
  169. // Build the tx
  170. let mut tx_data = vec![];
  171. {
  172. let tx = builder.build(&mint_params, &spend_params);
  173. tx.encode(&mut tx_data).expect("encode tx");
  174. }
  175. // Verify it's valid
  176. {
  177. let tx = tx::Transaction::decode(&tx_data[..]).unwrap();
  178. //assert!(tx.verify(&mint_pvk, &spend_pvk));
  179. }
  180. }