tx.rs 9.4 KB

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