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

working spends (minus signatures)

narodnik 5 лет назад
Родитель
Сommit
04cc96ad69
2 измененных файлов с 64 добавлено и 67 удалено
  1. 14 4
      src/bin/tx.rs
  2. 50 63
      src/tx.rs

+ 14 - 4
src/bin/tx.rs

@@ -38,11 +38,9 @@ fn txbuilding() {
         outputs: vec![tx::TransactionBuilderOutputInfo { value: 110, public }],
     };
 
-    let mut coin_look = tx::CoinHashMap::new();
-
     let mut tx_data = vec![];
     {
-        let tx = builder.build(&mut coin_look, &mint_params, &spend_params);
+        let tx = builder.build(&mint_params, &spend_params);
         tx.encode(&mut tx_data).expect("encode tx");
     }
     let mut tree = CommitmentTree::empty();
@@ -53,7 +51,7 @@ fn txbuilding() {
     let note =
     {
         let tx = tx::Transaction::decode(&tx_data[..]).unwrap();
-        assert!(tx.verify(&mint_pvk));
+        assert!(tx.verify(&mint_pvk, &spend_pvk));
         tree.append(Coin::new(tx.outputs[0].revealed.coin))
             .expect("append merkle");
 
@@ -91,9 +89,21 @@ fn txbuilding() {
         inputs: vec![tx::TransactionBuilderInputInfo {
             coin,
             merkle_path: auth_path,
+            merkle_root: tree,
+            secret,
+            note
         }],
         outputs: vec![tx::TransactionBuilderOutputInfo { value: 110, public }],
     };
+    let mut tx_data = vec![];
+    {
+        let tx = builder.build(&mint_params, &spend_params);
+        tx.encode(&mut tx_data).expect("encode tx");
+    }
+    {
+        let tx = tx::Transaction::decode(&tx_data[..]).unwrap();
+        assert!(tx.verify(&mint_pvk, &spend_pvk));
+    }
 
     /*let note = Note {
         serial: jubjub::Fr::random(&mut OsRng),

+ 50 - 63
src/tx.rs

@@ -10,45 +10,13 @@ use crate::crypto::{
     create_mint_proof, create_spend_proof, load_params, note::{Note, EncryptedNote}, save_params, schnorr,
     setup_mint_prover, setup_spend_prover, verify_mint_proof, verify_spend_proof,
     MintRevealedValues, SpendRevealedValues,
+    merkle::CommitmentTree,
+    coin::Coin
 };
 use crate::error::{Error, Result};
 use crate::impl_vec;
 use crate::serial::{Decodable, Encodable, VarInt};
 
-pub trait CoinLookup {
-    fn lookup(&self, coin: &[u8; 32]) -> CoinAttributes;
-    fn add(&mut self, coin: [u8; 32], attrs: CoinAttributes);
-}
-
-#[derive(Clone)]
-pub struct CoinAttributes {
-    serial: jubjub::Fr,
-    coin_blind: jubjub::Fr,
-    value: u64,
-}
-
-pub struct CoinHashMap {
-    map: HashMap<[u8; 32], CoinAttributes>,
-}
-
-impl CoinHashMap {
-    pub fn new() -> Self {
-        Self {
-            map: HashMap::new(),
-        }
-    }
-}
-
-impl CoinLookup for CoinHashMap {
-    fn lookup(&self, coin: &[u8; 32]) -> CoinAttributes {
-        self.map[coin].clone()
-    }
-
-    fn add(&mut self, coin: [u8; 32], attrs: CoinAttributes) {
-        self.map.insert(coin, attrs);
-    }
-}
-
 pub struct TransactionBuilder {
     pub clear_inputs: Vec<TransactionBuilderClearInputInfo>,
     pub inputs: Vec<TransactionBuilderInputInfo>,
@@ -58,24 +26,28 @@ pub struct TransactionBuilder {
 impl TransactionBuilder {
     fn compute_remainder_blind(
         clear_inputs: &Vec<TransactionClearInput>,
+        input_blinds: &Vec<jubjub::Fr>,
         output_blinds: &Vec<jubjub::Fr>,
     ) -> jubjub::Fr {
-        let mut lhs_total = jubjub::Fr::zero();
+        let mut total = jubjub::Fr::zero();
+
         for input in clear_inputs {
-            lhs_total += input.valcom_blind;
+            total += input.valcom_blind;
+        }
+
+        for input_blind in input_blinds {
+            total += input_blind;
         }
 
-        let mut rhs_total = jubjub::Fr::zero();
         for output_blind in output_blinds {
-            rhs_total += output_blind;
+            total -= output_blind;
         }
 
-        lhs_total - rhs_total
+        total
     }
 
-    pub fn build<C: CoinLookup>(
+    pub fn build(
         self,
-        coin_look: &mut C,
         mint_params: &groth16::Parameters<Bls12>,
         spend_params: &groth16::Parameters<Bls12>,
     ) -> Transaction {
@@ -90,36 +62,44 @@ impl TransactionBuilder {
         }
 
         let mut inputs = vec![];
+        let mut input_blinds = vec![];
         for input in &self.inputs {
-            let valcom_blind: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
+            input_blinds.push(input.note.valcom_blind.clone());
 
             let signature_secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
             let signature_public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * signature_secret;
 
             // make proof
-            let attrs = coin_look.lookup(&input.coin);
 
-            /*
             let (proof, revealed) = create_spend_proof(
                 &spend_params,
-                attrs.value,
-                valcom_blind.clone(),
-                attrs.serial,
-                attrs.coin_blind,
-                secret,
-                merkle_path,
-                signature_secret,
+                input.note.value,
+                input.note.valcom_blind,
+                input.note.serial,
+                input.note.coin_blind,
+                input.secret,
+                input.merkle_path.clone(),
+                signature_secret.clone(),
             );
-            */
 
             // make signature
+            // TODO...
+            let signature_secret = schnorr::SecretKey(signature_secret);
+            let signature = signature_secret.sign(b"XYZ");
+
+            let input = TransactionInput {
+                spend_proof: proof,
+                revealed,
+                signature
+            };
+            inputs.push(input);
         }
 
         let mut outputs = vec![];
         let mut output_blinds = vec![];
         for (i, output) in self.outputs.iter().enumerate() {
             let valcom_blind = if i == self.outputs.len() - 1 {
-                Self::compute_remainder_blind(&clear_inputs, &output_blinds)
+                Self::compute_remainder_blind(&clear_inputs, &input_blinds, &output_blinds)
             } else {
                 jubjub::Fr::random(&mut OsRng)
             };
@@ -128,12 +108,6 @@ impl TransactionBuilder {
             let serial: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
             let coin_blind: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
 
-            let coin_attrs = CoinAttributes {
-                serial: serial.clone(),
-                coin_blind: coin_blind.clone(),
-                value: output.value,
-            };
-
             let (mint_proof, revealed) = create_mint_proof(
                 mint_params,
                 output.value,
@@ -143,8 +117,6 @@ impl TransactionBuilder {
                 output.public.clone(),
             );
 
-            coin_look.add(revealed.coin.clone(), coin_attrs);
-
             // Encrypted note
 
             let note = Note {
@@ -179,6 +151,9 @@ pub struct TransactionBuilderClearInputInfo {
 pub struct TransactionBuilderInputInfo {
     pub coin: [u8; 32],
     pub merkle_path: Vec<(bls12_381::Scalar, bool)>,
+    pub merkle_root: CommitmentTree<Coin>,
+    pub secret: jubjub::Fr,
+    pub note: Note,
 }
 
 pub struct TransactionBuilderOutputInfo {
@@ -220,17 +195,29 @@ impl Transaction {
         value_commit
     }
 
-    pub fn verify(&self, pvk: &groth16::PreparedVerifyingKey<Bls12>) -> bool {
+    pub fn verify(&self,
+                  mint_pvk: &groth16::PreparedVerifyingKey<Bls12>,
+                  spend_pvk: &groth16::PreparedVerifyingKey<Bls12>,
+
+                  ) -> bool {
         let mut valcom_total = jubjub::SubgroupPoint::identity();
         for input in &self.clear_inputs {
             valcom_total += Self::compute_value_commit(input.value, &input.valcom_blind);
         }
+        for input in &self.inputs {
+            if !verify_spend_proof(spend_pvk, &input.spend_proof, &input.revealed) {
+                return false;
+            }
+            valcom_total += &input.revealed.value_commit;
+        }
         for output in &self.outputs {
-            if !verify_mint_proof(pvk, &output.mint_proof, &output.revealed) {
+            if !verify_mint_proof(mint_pvk, &output.mint_proof, &output.revealed) {
+                println!("mint fail");
                 return false;
             }
             valcom_total -= &output.revealed.value_commit;
         }
+        // TODO: Verify signatures
 
         valcom_total == jubjub::SubgroupPoint::identity()
     }