tx.rs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  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::{EncryptedNote, 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. tree: CommitmentTree<Coin>,
  22. nullifiers: Vec<[u8; 32]>,
  23. own_coins: Vec<([u8; 32], Note, jubjub::Fr, IncrementalWitness<Coin>)>,
  24. mint_pvk: groth16::PreparedVerifyingKey<Bls12>,
  25. spend_pvk: groth16::PreparedVerifyingKey<Bls12>,
  26. cashier_public: jubjub::SubgroupPoint,
  27. secrets: Vec<jubjub::Fr>,
  28. }
  29. impl ProgramState for MemoryState {
  30. fn is_valid_cashier_public_key(&self, public: &jubjub::SubgroupPoint) -> bool {
  31. public == &self.cashier_public
  32. }
  33. fn is_valid_merkle(&self, merkle: &bls12_381::Scalar) -> bool {
  34. true
  35. }
  36. fn nullifier_exists(&self, nullifier: &[u8; 32]) -> bool {
  37. false
  38. }
  39. fn mint_pvk(&self) -> &groth16::PreparedVerifyingKey<Bls12> {
  40. &self.mint_pvk
  41. }
  42. fn spend_pvk(&self) -> &groth16::PreparedVerifyingKey<Bls12> {
  43. &self.spend_pvk
  44. }
  45. }
  46. impl MemoryState {
  47. async fn apply(&mut self, mut updates: StateUpdates) {
  48. self.nullifiers.append(&mut updates.nullifiers);
  49. // Update merkle tree and witnesses
  50. for (coin, enc_note) in updates.coins.into_iter().zip(updates.enc_notes.into_iter()) {
  51. // Add the new coins to the merkle tree
  52. self.tree
  53. .append(Coin::new(coin.clone()))
  54. .expect("Append to merkle tree");
  55. if let Some((note, secret)) = self.try_decrypt_note(enc_note) {
  56. // We need to keep track of the witness for this coin.
  57. // This allows us to prove inclusion of the coin in the merkle tree with ZK.
  58. // Just as we update the merkle tree with every new coin, so we do the same with the witness.
  59. // Derive the current witness from the current tree.
  60. // This is done right after we add our coin to the tree (but before any other coins are added)
  61. // Make a new witness for this coin
  62. let witness = IncrementalWitness::from_tree(&self.tree);
  63. self.own_coins.push((coin, note, secret, witness));
  64. }
  65. }
  66. }
  67. fn try_decrypt_note(&self, ciphertext: EncryptedNote) -> Option<(Note, jubjub::Fr)> {
  68. // Loop through all our secret keys...
  69. for secret in &self.secrets {
  70. // ... attempt to decrypt the note ...
  71. match ciphertext.decrypt(secret) {
  72. Ok(note) => {
  73. // ... and return the decrypted note for this coin.
  74. return Some((note, secret.clone()));
  75. }
  76. Err(_) => {}
  77. }
  78. }
  79. // We weren't able to decrypt the note with any of our keys.
  80. None
  81. }
  82. }
  83. fn main() {
  84. // Auto create trusted ceremony parameters if they don't exist
  85. if !Path::new("mint.params").exists() {
  86. let params = setup_mint_prover();
  87. save_params("mint.params", &params);
  88. }
  89. if !Path::new("spend.params").exists() {
  90. let params = setup_spend_prover();
  91. save_params("spend.params", &params);
  92. }
  93. // Load trusted setup parameters
  94. let (mint_params, mint_pvk) = load_params("mint.params").expect("params should load");
  95. let (spend_params, spend_pvk) = load_params("spend.params").expect("params should load");
  96. // Cashier creates a secret key
  97. let cashier_secret = jubjub::Fr::random(&mut OsRng);
  98. // This is their public key
  99. let cashier_public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * cashier_secret;
  100. // Wallet 1 creates a secret key
  101. let secret = jubjub::Fr::random(&mut OsRng);
  102. // This is their public key
  103. let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
  104. let mut state = MemoryState {
  105. tree: CommitmentTree::empty(),
  106. nullifiers: vec![],
  107. own_coins: vec![],
  108. mint_pvk,
  109. spend_pvk,
  110. cashier_public,
  111. secrets: vec![secret.clone()],
  112. };
  113. // Step 1: Cashier deposits to wallet1's address
  114. // Create the deposit for 110 BTC
  115. // Clear inputs are visible to everyone on the network
  116. let builder = tx::TransactionBuilder {
  117. clear_inputs: vec![tx::TransactionBuilderClearInputInfo {
  118. value: 110,
  119. signature_secret: cashier_secret,
  120. }],
  121. inputs: vec![],
  122. outputs: vec![tx::TransactionBuilderOutputInfo { value: 110, public }],
  123. };
  124. // We will 'compile' the tx, and then serialize it to this Vec<u8>
  125. let mut tx_data = vec![];
  126. {
  127. // Build the tx
  128. let tx = builder.build(&mint_params, &spend_params);
  129. // Now serialize it
  130. tx.encode(&mut tx_data).expect("encode tx");
  131. }
  132. // Step 1 is completed.
  133. // Tx data is posted to the blockchain
  134. // Step 2: wallet1 receive's payment from the cashier
  135. // Wallet1 is receiving tx, and for every new coin it finds, it adds to its merkle tree
  136. {
  137. // Here we simulate 5 fake random coins, adding them to our tree.
  138. let tree = &mut state.tree;
  139. for i in 0..5 {
  140. let cmu = Coin::new(bls12_381::Scalar::random(&mut OsRng).to_repr());
  141. tree.append(cmu);
  142. }
  143. }
  144. // Now we receive the tx data
  145. {
  146. let tx = tx::Transaction::decode(&tx_data[..]).unwrap();
  147. let update = state_transition(&state, tx).expect("step 2 state transition failed");
  148. smol::block_on(state.apply(update));
  149. }
  150. // Wallet1 has received payment from the cashier.
  151. // Step 2 is complete.
  152. assert_eq!(state.own_coins.len(), 1);
  153. //let (coin, note, secret, witness) = &mut state.own_coins[0];
  154. let auth_path =
  155. {
  156. let tree = &mut state.tree;
  157. let witness = &mut state.own_coins[0].3;
  158. // Check this is the 6th coin we added
  159. assert_eq!(witness.position(), 5);
  160. assert_eq!(tree.root(), witness.root());
  161. // Add some more random coins in
  162. for i in 0..10 {
  163. let cmu = Coin::new(bls12_381::Scalar::random(&mut OsRng).to_repr());
  164. tree.append(cmu);
  165. witness.append(cmu);
  166. assert_eq!(tree.root(), witness.root());
  167. }
  168. // TODO: Some stupid glue code. Need to put this somewhere else.
  169. let merkle_path = witness.path().unwrap();
  170. let auth_path: Vec<(bls12_381::Scalar, bool)> = merkle_path
  171. .auth_path
  172. .iter()
  173. .map(|(node, b)| ((*node).into(), *b))
  174. .collect();
  175. auth_path
  176. };
  177. // Step 3: wallet1 sends payment to wallet2
  178. // Wallet1 now wishes to send the coin to wallet2
  179. let secret2 = jubjub::Fr::random(&mut OsRng);
  180. // This is their public key
  181. let public2 = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret2;
  182. // Make a spend tx
  183. // Get the coin we're spending from the previous tx
  184. let coin = {
  185. let tx = tx::Transaction::decode(&tx_data[..]).unwrap();
  186. tx.outputs[0].revealed.coin
  187. };
  188. // Construct a new tx spending the coin
  189. // We need the decrypted note and our private key
  190. let builder = tx::TransactionBuilder {
  191. clear_inputs: vec![],
  192. inputs: vec![tx::TransactionBuilderInputInfo {
  193. coin,
  194. merkle_path: auth_path,
  195. merkle_root: state.tree.clone(),
  196. secret: secret.clone(),
  197. note: state.own_coins[0].1.clone(),
  198. }],
  199. // We can add more outputs to this list.
  200. // The only constraint is that sum(value in) == sum(value out)
  201. outputs: vec![tx::TransactionBuilderOutputInfo {
  202. value: 110,
  203. public: public2,
  204. }],
  205. };
  206. // Build the tx
  207. let mut tx_data = vec![];
  208. {
  209. let tx = builder.build(&mint_params, &spend_params);
  210. tx.encode(&mut tx_data).expect("encode tx");
  211. }
  212. // Verify it's valid
  213. {
  214. let tx = tx::Transaction::decode(&tx_data[..]).unwrap();
  215. let update = state_transition(&state, tx).expect("step 3 state transition failed");
  216. }
  217. }