Просмотр исходного кода

bin/tx: bring state_transition function to tx.rs file

ghassmo 4 лет назад
Родитель
Сommit
56ef0af458
1 измененных файлов с 118 добавлено и 54 удалено
  1. 118 54
      src/bin/tx.rs

+ 118 - 54
src/bin/tx.rs

@@ -4,7 +4,6 @@ use ff::{Field, PrimeField};
 use rand::rngs::OsRng;
 use rand::rngs::OsRng;
 use std::path::Path;
 use std::path::Path;
 
 
-use async_std::sync::{Arc, Mutex};
 use drk::crypto::{
 use drk::crypto::{
     coin::Coin,
     coin::Coin,
     load_params,
     load_params,
@@ -15,7 +14,7 @@ use drk::crypto::{
     save_params, setup_mint_prover, setup_spend_prover,
     save_params, setup_mint_prover, setup_spend_prover,
 };
 };
 use drk::serial::{Decodable, Encodable};
 use drk::serial::{Decodable, Encodable};
-use drk::state::{state_transition, ProgramState, StateUpdate};
+use drk::state::{ProgramState, StateUpdate};
 use drk::tx;
 use drk::tx;
 
 
 struct MemoryState {
 struct MemoryState {
@@ -203,8 +202,6 @@ async fn main() {
         }
         }
     }
     }
 
 
-    let state = Mutex::new(state);
-    let mut state = state.lock().await;
     // Now we receive the tx data
     // Now we receive the tx data
     {
     {
         let tx = tx::Transaction::decode(&tx_data[..]).unwrap();
         let tx = tx::Transaction::decode(&tx_data[..]).unwrap();
@@ -221,47 +218,47 @@ async fn main() {
     assert_eq!(state.own_coins.len(), 1);
     assert_eq!(state.own_coins.len(), 1);
     ////let (coin, note, secret, witness) = &mut state.own_coins[0];
     ////let (coin, note, secret, witness) = &mut state.own_coins[0];
 
 
-    //let merkle_path = {
-    //    let tree = &mut state.tree;
-    //    let (coin, _, _, witness) = &mut state.own_coins[0];
-    //    // Check this is the 6th coin we added
-    //    assert_eq!(witness.position(), 5);
-    //    assert_eq!(tree.root(), witness.root());
-
-    //    // 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 = MerkleNode::new(bls12_381::Scalar::random(&mut OsRng).to_repr());
-    //        tree.append(cmu).unwrap();
-    //        witness.append(cmu).unwrap();
-    //        assert_eq!(tree.root(), witness.root());
-
-    //        let root = tree.root();
-    //        state.merkle_roots.push(root.into());
-    //    }
-
-    //    assert_eq!(state.merkle_roots.len(), 16);
-
-    //    // 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 = MerkleNode::from_coin(&coin);
-    //    let root = tree.root();
-    //    drop(tree);
-    //    drop(witness);
-    //    assert_eq!(merkle_path.root(node), root);
-    //    let root = root.into();
-    //    assert!(state.is_valid_merkle(&root));
-
-    //    merkle_path
-    //};
+    let merkle_path = {
+        let tree = &mut state.tree;
+        let (coin, _, _, witness) = &mut state.own_coins[0];
+        // Check this is the 6th coin we added
+        assert_eq!(witness.position(), 5);
+        assert_eq!(tree.root(), witness.root());
+
+        // 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 = MerkleNode::new(bls12_381::Scalar::random(&mut OsRng).to_repr());
+            tree.append(cmu).unwrap();
+            witness.append(cmu).unwrap();
+            assert_eq!(tree.root(), witness.root());
+
+            let root = tree.root();
+            state.merkle_roots.push(root.into());
+        }
+
+        assert_eq!(state.merkle_roots.len(), 16);
+
+        // 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 = MerkleNode::from_coin(&coin);
+        let root = tree.root();
+        drop(tree);
+        drop(witness);
+        assert_eq!(merkle_path.root(node), root);
+        let root = root.into();
+        assert!(state.is_valid_merkle(&root));
+
+        merkle_path
+    };
 
 
     // Step 3: wallet1 sends payment to wallet2
     // Step 3: wallet1 sends payment to wallet2
 
 
@@ -279,12 +276,11 @@ async fn main() {
     // We need the decrypted note and our private key
     // We need the decrypted note and our private key
     let builder = tx::TransactionBuilder {
     let builder = tx::TransactionBuilder {
         clear_inputs: vec![],
         clear_inputs: vec![],
-        inputs: vec![],
-        //inputs: vec![tx::TransactionBuilderInputInfo {
-        //    merkle_path,
-        //    secret: secret.clone(),
-        //    note: state.own_coins[0].1.clone(),
-        //}],
+        inputs: vec![tx::TransactionBuilderInputInfo {
+            merkle_path,
+            secret: secret.clone(),
+            note: state.own_coins[0].1.clone(),
+        }],
         // We can add more outputs to this list.
         // We can add more outputs to this list.
         // The only constraint is that sum(value in) == sum(value out)
         // The only constraint is that sum(value in) == sum(value out)
         outputs: vec![tx::TransactionBuilderOutputInfo {
         outputs: vec![tx::TransactionBuilderOutputInfo {
@@ -302,8 +298,76 @@ async fn main() {
     // Verify it's valid
     // Verify it's valid
     {
     {
         let tx = tx::Transaction::decode(&tx_data[..]).unwrap();
         let tx = tx::Transaction::decode(&tx_data[..]).unwrap();
-        //let state = state.lock().await;
-        //let update = state_transition(&state, tx).expect("step 3 state transition failed");
-        //state.apply(update);
+        let update = state_transition(&state, tx).expect("step 3 state transition failed");
+        state.apply(update);
     }
     }
 }
 }
+
+
+use log::*;
+use drk::state::{VerifyResult, VerifyFailed};
+
+pub fn state_transition<S: ProgramState>(
+    state: &S,
+    tx: tx::Transaction,
+) -> VerifyResult<StateUpdate> {
+    // Check deposits are legit
+
+    debug!(target: "STATE TRANSITION", "iterate clear_inputs");
+
+    for (i, input) in tx.clear_inputs.iter().enumerate() {
+        // Check the public key in the clear inputs
+        // It should be a valid public key for the cashier
+
+
+        if !state.is_valid_cashier_public_key(&input.signature_public) {
+            log::error!(target: "STATE TRANSITION", "Not valid cashier public key");
+            return Err(VerifyFailed::InvalidCashierKey(i));
+        }
+    }
+
+    debug!(target: "STATE TRANSITION", "iterate inputs");
+
+    for (i, input) in tx.inputs.iter().enumerate() {
+        // Check merkle roots
+        let merkle = &input.revealed.merkle_root;
+
+        // Merkle is used to know whether this is a coin that existed
+        // in a previous state.
+        if !state.is_valid_merkle(merkle) {
+            return Err(VerifyFailed::InvalidMerkle(i));
+        }
+
+        // The nullifiers should not already exist
+        // It is double spend protection.
+        let nullifier = &input.revealed.nullifier;
+
+        if state.nullifier_exists(nullifier) {
+            return Err(VerifyFailed::DuplicateNullifier(i));
+        }
+    }
+
+    debug!(target: "STATE TRANSITION", "Check the tx Verifies correctly");
+    // Check the tx verifies correctly
+    tx.verify(state.mint_pvk(), state.spend_pvk())?;
+
+    let mut nullifiers = vec![];
+    for input in tx.inputs {
+        nullifiers.push(input.revealed.nullifier);
+    }
+
+    // Newly created coins for this tx
+    let mut coins = vec![];
+    let mut enc_notes = vec![];
+    for output in tx.outputs {
+        // Gather all the coins
+        coins.push(Coin::new(output.revealed.coin));
+        enc_notes.push(output.enc_note);
+    }
+
+    Ok(StateUpdate {
+        nullifiers,
+        coins,
+        enc_notes,
+    })
+}