Bläddra i källkod

document src/bin/tx.rs

narodnik 5 år sedan
förälder
incheckning
6041fca23a
4 ändrade filer med 67 tillägg och 23 borttagningar
  1. 43 16
      src/bin/tx.rs
  2. 15 0
      src/crypto/node.rs
  3. 5 3
      src/crypto/spend_proof.rs
  4. 4 4
      src/state.rs

+ 43 - 16
src/bin/tx.rs

@@ -14,17 +14,32 @@ use sapvi::crypto::{
     save_params, setup_mint_prover, setup_spend_prover,
 };
 use sapvi::serial::{Decodable, Encodable};
-use sapvi::state::{state_transition, ProgramState, StateUpdates};
+use sapvi::state::{state_transition, ProgramState, StateUpdate};
 use sapvi::tx;
 
 struct MemoryState {
+    // The entire merkle tree state
     tree: CommitmentTree<Node>,
-    merkle_roots: Vec<bls12_381::Scalar>,
+    // List of all previous and the current merkle roots
+    // This is the hashed value of all the children.
+    merkle_roots: Vec<Node>,
+    // Nullifiers prevent double spending
     nullifiers: Vec<Nullifier>,
+    // All received coins
+    // NOTE: we need maybe a flag to keep track of which ones are spent
+    // Maybe the spend field links to a tx hash:input index
+    // We should also keep track of the tx hash:output index where this
+    // coin was received
     own_coins: Vec<(Coin, Note, jubjub::Fr, IncrementalWitness<Node>)>,
+
+    // Mint verifying key used by ZK
     mint_pvk: groth16::PreparedVerifyingKey<Bls12>,
+    // Spend verifying key used by ZK
     spend_pvk: groth16::PreparedVerifyingKey<Bls12>,
+
+    // Public key of the cashier
     cashier_public: jubjub::SubgroupPoint,
+    // List of all our secret keys
     secrets: Vec<jubjub::Fr>,
 }
 
@@ -32,8 +47,8 @@ impl ProgramState for MemoryState {
     fn is_valid_cashier_public_key(&self, public: &jubjub::SubgroupPoint) -> bool {
         public == &self.cashier_public
     }
-    fn is_valid_merkle(&self, merkle: &bls12_381::Scalar) -> bool {
-        self.merkle_roots.iter().any(|m| *m == *merkle)
+    fn is_valid_merkle(&self, merkle_root: &Node) -> bool {
+        self.merkle_roots.iter().any(|m| *m == *merkle_root)
     }
     fn nullifier_exists(&self, nullifier: &Nullifier) -> bool {
         self.nullifiers.iter().any(|n| n.repr == nullifier.repr)
@@ -48,20 +63,22 @@ impl ProgramState for MemoryState {
 }
 
 impl MemoryState {
-    fn apply(&mut self, mut updates: StateUpdates) {
-        self.nullifiers.append(&mut updates.nullifiers);
+    fn apply(&mut self, mut update: StateUpdate) {
+        // Extend our list of nullifiers with the ones from the update
+        self.nullifiers.append(&mut update.nullifiers);
 
         // Update merkle tree and witnesses
-        for (coin, enc_note) in updates.coins.into_iter().zip(updates.enc_notes.into_iter()) {
-            let node = Node::from_coin(&coin);
-
+        for (coin, enc_note) in update.coins.into_iter().zip(update.enc_notes.into_iter()) {
             // Add the new coins to the merkle tree
+            let node = Node::from_coin(&coin);
             self.tree
                 .append(node)
                 .expect("Append to merkle tree");
 
-            let root = self.tree.root();
-            self.merkle_roots.push(root.into());
+            // Keep track of all merkle roots that have existed
+            self.merkle_roots.push(self.tree.root());
+
+            // Also update all the coin witnesses
             for (_, _, _, witness) in self.own_coins.iter_mut() {
                 witness
                     .append(node)
@@ -171,6 +188,8 @@ fn main() {
         // Here we simulate 5 fake random coins, adding them to our tree.
         let tree = &mut state.tree;
         for i in 0..5 {
+            // Don't worry about any of the code in this block
+            // We're just filling the tree with fake coins
             let cmu = Node::new(bls12_381::Scalar::random(&mut OsRng).to_repr());
             tree.append(cmu);
 
@@ -197,8 +216,6 @@ fn main() {
 
     let merkle_path = {
         let tree = &mut state.tree;
-        //let coin: &Coin = &state.own_coins[0].0;
-        //let witness = &mut state.own_coins[0].3;
         let (coin, _, _, witness) = &mut state.own_coins[0];
         // Check this is the 6th coin we added
         assert_eq!(witness.position(), 5);
@@ -206,6 +223,8 @@ fn main() {
 
         // Add some more random coins in
         for i in 0..10 {
+            // Don't worry about any of the code in this block
+            // We're just filling the tree with fake coins
             let cmu = Node::new(bls12_381::Scalar::random(&mut OsRng).to_repr());
             tree.append(cmu);
             witness.append(cmu);
@@ -217,8 +236,15 @@ fn main() {
 
         assert_eq!(state.merkle_roots.len(), 16);
 
-        // Just test the path is good
+        // This is the value we need to spend the coin
+        // We use the witness and the merkle root (both in sync with each other)
+        // to prove our coin exists inside the tree.
+        // The coin is not revealed publicly but is proved to exist inside
+        // a merkle tree. Only the root will be revealed, and then the
+        // verifier checks that merkle root actually existed before.
         let merkle_path = witness.path().unwrap();
+
+        // Just test the path is good because we just added a bunch of fake coins
         let node = Node::from_coin(&coin);
         let root = tree.root();
         drop(tree);
@@ -234,8 +260,9 @@ fn main() {
 
     // Wallet1 now wishes to send the coin to wallet2
 
+    // The receiving wallet has a secret key
     let secret2 = jubjub::Fr::random(&mut OsRng);
-    // This is their public key
+    // This is their public key to receive payment
     let public2 = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret2;
 
     // Make a spend tx
@@ -265,8 +292,8 @@ fn main() {
     // Verify it's valid
     {
         let tx = tx::Transaction::decode(&tx_data[..]).unwrap();
-        assert!(state.is_valid_merkle(&tx.inputs[0].revealed.merkle_root));
         let update = state_transition(&state, tx).expect("step 3 state transition failed");
         state.apply(update);
     }
 }
+

+ 15 - 0
src/crypto/node.rs

@@ -5,6 +5,7 @@ use lazy_static::lazy_static;
 use std::io;
 
 use super::{coin::Coin, merkle::Hashable};
+use crate::{error::Result, serial::{Decodable, Encodable}};
 
 pub const SAPLING_COMMITMENT_TREE_DEPTH: usize = 6;
 
@@ -112,6 +113,20 @@ impl From<Node> for bls12_381::Scalar {
     }
 }
 
+impl Encodable for Node {
+    fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
+        Ok(self.repr.encode(s)?)
+    }
+}
+
+impl Decodable for Node {
+    fn decode<D: io::Read>(mut d: D) -> Result<Self> {
+        Ok(Self {
+            repr: Decodable::decode(d)?,
+        })
+    }
+}
+
 lazy_static! {
     static ref EMPTY_ROOTS: Vec<Node> = {
         let mut v = vec![Node::blank()];

+ 5 - 3
src/crypto/spend_proof.rs

@@ -8,7 +8,7 @@ use rand::rngs::OsRng;
 use std::io;
 use std::time::Instant;
 
-use super::node::{SAPLING_COMMITMENT_TREE_DEPTH, merkle_hash};
+use super::node::{SAPLING_COMMITMENT_TREE_DEPTH, merkle_hash, Node};
 use crate::circuit::spend_contract::SpendContract;
 use crate::error::Result;
 use crate::serial::{Decodable, Encodable};
@@ -19,7 +19,7 @@ pub struct SpendRevealedValues {
     pub nullifier: Nullifier,
     // This should not be here, we just have it for debugging
     //coin: [u8; 32],
-    pub merkle_root: bls12_381::Scalar,
+    pub merkle_root: Node,
     pub signature_public: jubjub::SubgroupPoint,
 }
 
@@ -85,6 +85,8 @@ impl SpendRevealedValues {
             }
         }
 
+        let merkle_root = Node::new(merkle_root.to_repr());
+
         SpendRevealedValues {
             value_commit,
             nullifier,
@@ -134,7 +136,7 @@ impl SpendRevealedValues {
             public_input[5] = hash[1];
         }*/
 
-        public_input[4] = self.merkle_root;
+        public_input[4] = self.merkle_root.into();
 
         {
             let result = jubjub::ExtendedPoint::from(self.signature_public);

+ 4 - 4
src/state.rs

@@ -9,14 +9,14 @@ use crate::{
 
 pub trait ProgramState {
     fn is_valid_cashier_public_key(&self, public: &jubjub::SubgroupPoint) -> bool;
-    fn is_valid_merkle(&self, merkle: &bls12_381::Scalar) -> bool;
+    fn is_valid_merkle(&self, merkle: &Node) -> bool;
     fn nullifier_exists(&self, nullifier: &Nullifier) -> bool;
 
     fn mint_pvk(&self) -> &groth16::PreparedVerifyingKey<Bls12>;
     fn spend_pvk(&self) -> &groth16::PreparedVerifyingKey<Bls12>;
 }
 
-pub struct StateUpdates {
+pub struct StateUpdate {
     pub nullifiers: Vec<Nullifier>,
     pub coins: Vec<Coin>,
     pub enc_notes: Vec<EncryptedNote>,
@@ -66,7 +66,7 @@ impl fmt::Display for VerifyFailed {
 pub fn state_transition<S: ProgramState>(
     state: &S,
     tx: tx::Transaction,
-) -> VerifyResult<StateUpdates> {
+) -> VerifyResult<StateUpdate> {
     // Check deposits are legit
     for (i, input) in tx.clear_inputs.iter().enumerate() {
         // Check the public key in the clear inputs
@@ -112,7 +112,7 @@ pub fn state_transition<S: ProgramState>(
         enc_notes.push(output.enc_note);
     }
 
-    Ok(StateUpdates {
+    Ok(StateUpdate {
         nullifiers,
         coins,
         enc_notes,