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

working signatures for clear inputs (deposits)

narodnik 5 лет назад
Родитель
Сommit
07eb99c465
2 измененных файлов с 118 добавлено и 45 удалено
  1. 21 27
      src/bin/tx.rs
  2. 97 18
      src/tx.rs

+ 21 - 27
src/bin/tx.rs

@@ -4,6 +4,7 @@ use ff::{Field, PrimeField};
 use group::Group;
 use group::Group;
 use rand::rngs::OsRng;
 use rand::rngs::OsRng;
 use std::io;
 use std::io;
+use std::path::Path;
 
 
 use sapvi::crypto::{
 use sapvi::crypto::{
     coin::Coin,
     coin::Coin,
@@ -17,23 +18,33 @@ use sapvi::error::{Error, Result};
 use sapvi::serial::{Decodable, Encodable, VarInt};
 use sapvi::serial::{Decodable, Encodable, VarInt};
 use sapvi::tx;
 use sapvi::tx;
 
 
-fn txbuilding() {
-    //{
-    //    let params = setup_mint_prover();
-    //    save_params("mint.params", &params);
-    //}
-    //{
-    //    let params = setup_spend_prover();
-    //    save_params("spend.params", &params);
-    //}
+fn main() {
+    // Auto create trusted ceremony parameters if they don't exist
+    if !Path::new("mint.params").exists() {
+        let params = setup_mint_prover();
+        save_params("mint.params", &params);
+    }
+    if !Path::new("spend.params").exists() {
+        let params = setup_spend_prover();
+        save_params("spend.params", &params);
+    }
+
+    // Load trusted setup parameters
     let (mint_params, mint_pvk) = load_params("mint.params").expect("params should load");
     let (mint_params, mint_pvk) = load_params("mint.params").expect("params should load");
     let (spend_params, spend_pvk) = load_params("spend.params").expect("params should load");
     let (spend_params, spend_pvk) = load_params("spend.params").expect("params should load");
 
 
+    // Cashier creates a secret key
+    let cashier_secret = jubjub::Fr::random(&mut OsRng);
+    // This is their public key
+    let cashier_public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * cashier_secret;
+
+    // Wallet 1 creates a secret key
     let secret = jubjub::Fr::random(&mut OsRng);
     let secret = jubjub::Fr::random(&mut OsRng);
+    // This is their public key
     let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
     let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
 
 
     let builder = tx::TransactionBuilder {
     let builder = tx::TransactionBuilder {
-        clear_inputs: vec![tx::TransactionBuilderClearInputInfo { value: 110 }],
+        clear_inputs: vec![tx::TransactionBuilderClearInputInfo { value: 110, signature_secret: cashier_secret }],
         inputs: vec![],
         inputs: vec![],
         outputs: vec![tx::TransactionBuilderOutputInfo { value: 110, public }],
         outputs: vec![tx::TransactionBuilderOutputInfo { value: 110, public }],
     };
     };
@@ -106,22 +117,5 @@ fn txbuilding() {
         let tx = tx::Transaction::decode(&tx_data[..]).unwrap();
         let tx = tx::Transaction::decode(&tx_data[..]).unwrap();
         assert!(tx.verify(&mint_pvk, &spend_pvk));
         assert!(tx.verify(&mint_pvk, &spend_pvk));
     }
     }
-
-    /*let note = Note {
-        serial: jubjub::Fr::random(&mut OsRng),
-        value: 110,
-        coin_blind: jubjub::Fr::random(&mut OsRng),
-        valcom_blind: jubjub::Fr::random(&mut OsRng),
-    };
-
-    let secret = jubjub::Fr::random(&mut OsRng);
-    let public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * secret;
-
-    let encrypted_note = note.encrypt(&public).unwrap();
-    let note2 = encrypted_note.decrypt(&secret).unwrap();
-    assert_eq!(note.value, note2.value);*/
 }
 }
 
 
-fn main() {
-    txbuilding();
-}

+ 97 - 18
src/tx.rs

@@ -26,7 +26,7 @@ pub struct TransactionBuilder {
 
 
 impl TransactionBuilder {
 impl TransactionBuilder {
     fn compute_remainder_blind(
     fn compute_remainder_blind(
-        clear_inputs: &Vec<TransactionClearInput>,
+        clear_inputs: &Vec<PartialTransactionClearInput>,
         input_blinds: &Vec<jubjub::Fr>,
         input_blinds: &Vec<jubjub::Fr>,
         output_blinds: &Vec<jubjub::Fr>,
         output_blinds: &Vec<jubjub::Fr>,
     ) -> jubjub::Fr {
     ) -> jubjub::Fr {
@@ -54,10 +54,14 @@ impl TransactionBuilder {
     ) -> Transaction {
     ) -> Transaction {
         let mut clear_inputs = vec![];
         let mut clear_inputs = vec![];
         for input in &self.clear_inputs {
         for input in &self.clear_inputs {
+            let signature_public =
+                zcash_primitives::constants::SPENDING_KEY_GENERATOR * input.signature_secret;
+
             let valcom_blind: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
             let valcom_blind: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
-            let clear_input = TransactionClearInput {
+            let clear_input = PartialTransactionClearInput {
                 value: input.value,
                 value: input.value,
                 valcom_blind,
                 valcom_blind,
+                signature_public
             };
             };
             clear_inputs.push(clear_input);
             clear_inputs.push(clear_input);
         }
         }
@@ -69,8 +73,6 @@ impl TransactionBuilder {
             input_blinds.push(input.note.valcom_blind.clone());
             input_blinds.push(input.note.valcom_blind.clone());
 
 
             let signature_secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
             let signature_secret: jubjub::Fr = jubjub::Fr::random(&mut OsRng);
-            let signature_public =
-                zcash_primitives::constants::SPENDING_KEY_GENERATOR * signature_secret;
 
 
             // make proof
             // make proof
 
 
@@ -148,6 +150,14 @@ impl TransactionBuilder {
             .encode(&mut unsigned_tx_data)
             .encode(&mut unsigned_tx_data)
             .expect("TODO handle this");
             .expect("TODO handle this");
 
 
+        let mut clear_inputs = vec![];
+        for (input, info) in partial_tx.clear_inputs.into_iter().zip(self.clear_inputs) {
+            let secret = schnorr::SecretKey(info.signature_secret.clone());
+            let signature = secret.sign(&unsigned_tx_data[..]);
+            let input = TransactionClearInput::from_partial(input, signature);
+            clear_inputs.push(input);
+        }
+
         let mut inputs = vec![];
         let mut inputs = vec![];
         for (input, signature_secret) in partial_tx
         for (input, signature_secret) in partial_tx
             .inputs
             .inputs
@@ -160,7 +170,7 @@ impl TransactionBuilder {
         }
         }
 
 
         Transaction {
         Transaction {
-            clear_inputs: partial_tx.clear_inputs,
+            clear_inputs,
             inputs,
             inputs,
             outputs: partial_tx.outputs,
             outputs: partial_tx.outputs,
         }
         }
@@ -169,6 +179,7 @@ impl TransactionBuilder {
 
 
 pub struct TransactionBuilderClearInputInfo {
 pub struct TransactionBuilderClearInputInfo {
     pub value: u64,
     pub value: u64,
+    pub signature_secret: jubjub::Fr,
 }
 }
 
 
 pub struct TransactionBuilderInputInfo {
 pub struct TransactionBuilderInputInfo {
@@ -185,7 +196,7 @@ pub struct TransactionBuilderOutputInfo {
 }
 }
 
 
 pub struct PartialTransaction {
 pub struct PartialTransaction {
-    pub clear_inputs: Vec<TransactionClearInput>,
+    pub clear_inputs: Vec<PartialTransactionClearInput>,
     pub inputs: Vec<PartialTransactionInput>,
     pub inputs: Vec<PartialTransactionInput>,
     pub outputs: Vec<TransactionOutput>,
     pub outputs: Vec<TransactionOutput>,
 }
 }
@@ -239,7 +250,7 @@ impl Decodable for Transaction {
 impl Transaction {
 impl Transaction {
     fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
     fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
         let mut len = 0;
         let mut len = 0;
-        len += self.clear_inputs.encode(&mut s)?;
+        len += self.clear_inputs.encode_without_signature(&mut s)?;
         len += self.inputs.encode_without_signature(&mut s)?;
         len += self.inputs.encode_without_signature(&mut s)?;
         len += self.outputs.encode(s)?;
         len += self.outputs.encode(s)?;
         Ok(len)
         Ok(len)
@@ -280,6 +291,12 @@ impl Transaction {
         self
         self
             .encode_without_signature(&mut unsigned_tx_data)
             .encode_without_signature(&mut unsigned_tx_data)
             .expect("TODO handle this");
             .expect("TODO handle this");
+        for input in &self.clear_inputs {
+            let public = schnorr::PublicKey(input.signature_public.clone());
+            if !public.verify(&unsigned_tx_data[..], &input.signature) {
+                return false;
+            }
+        }
         for input in &self.inputs {
         for input in &self.inputs {
             let public = schnorr::PublicKey(input.revealed.signature_public.clone());
             let public = schnorr::PublicKey(input.revealed.signature_public.clone());
             if !public.verify(&unsigned_tx_data[..], &input.signature) {
             if !public.verify(&unsigned_tx_data[..], &input.signature) {
@@ -294,8 +311,47 @@ impl Transaction {
 pub struct TransactionClearInput {
 pub struct TransactionClearInput {
     pub value: u64,
     pub value: u64,
     pub valcom_blind: jubjub::Fr,
     pub valcom_blind: jubjub::Fr,
+    pub signature_public: jubjub::SubgroupPoint,
+    pub signature: schnorr::Signature,
+}
+
+impl TransactionClearInput {
+    fn from_partial(partial: PartialTransactionClearInput, signature: schnorr::Signature) -> Self {
+        Self {
+            value: partial.value,
+            valcom_blind: partial.valcom_blind,
+            signature_public: partial.signature_public,
+            signature
+        }
+    }
+
+    fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
+        let mut len = 0;
+        len += self.value.encode(&mut s)?;
+        len += self.valcom_blind.encode(&mut s)?;
+        len += self.signature_public.encode(s)?;
+        Ok(len)
+    }
+}
+
+macro_rules! impl_vec_without_signature {
+    ($type: ty) => {
+        impl EncodableWithoutSignature for Vec<$type> {
+            #[inline]
+            fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
+                let mut len = 0;
+                len += VarInt(self.len() as u64).encode(&mut s)?;
+                for c in self.iter() {
+                    len += c.encode_without_signature(&mut s)?;
+                }
+                Ok(len)
+            }
+        }
+    };
 }
 }
 
 
+impl_vec_without_signature!(TransactionClearInput);
+
 impl_vec!(TransactionClearInput);
 impl_vec!(TransactionClearInput);
 
 
 impl Encodable for TransactionClearInput {
 impl Encodable for TransactionClearInput {
@@ -303,6 +359,8 @@ impl Encodable for TransactionClearInput {
         let mut len = 0;
         let mut len = 0;
         len += self.value.encode(&mut s)?;
         len += self.value.encode(&mut s)?;
         len += self.valcom_blind.encode(&mut s)?;
         len += self.valcom_blind.encode(&mut s)?;
+        len += self.signature_public.encode(&mut s)?;
+        len += self.signature.encode(s)?;
         Ok(len)
         Ok(len)
     }
     }
 }
 }
@@ -311,7 +369,37 @@ impl Decodable for TransactionClearInput {
     fn decode<D: io::Read>(mut d: D) -> Result<Self> {
     fn decode<D: io::Read>(mut d: D) -> Result<Self> {
         Ok(Self {
         Ok(Self {
             value: Decodable::decode(&mut d)?,
             value: Decodable::decode(&mut d)?,
-            valcom_blind: Decodable::decode(d)?,
+            valcom_blind: Decodable::decode(&mut d)?,
+            signature_public: Decodable::decode(&mut d)?,
+            signature: Decodable::decode(d)?,
+        })
+    }
+}
+
+pub struct PartialTransactionClearInput {
+    pub value: u64,
+    pub valcom_blind: jubjub::Fr,
+    pub signature_public: jubjub::SubgroupPoint,
+}
+
+impl_vec!(PartialTransactionClearInput);
+
+impl Encodable for PartialTransactionClearInput {
+    fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
+        let mut len = 0;
+        len += self.value.encode(&mut s)?;
+        len += self.valcom_blind.encode(&mut s)?;
+        len += self.signature_public.encode(&mut s)?;
+        Ok(len)
+    }
+}
+
+impl Decodable for PartialTransactionClearInput {
+    fn decode<D: io::Read>(mut d: D) -> Result<Self> {
+        Ok(Self {
+            value: Decodable::decode(&mut d)?,
+            valcom_blind: Decodable::decode(&mut d)?,
+            signature_public: Decodable::decode(&mut d)?,
         })
         })
     }
     }
 }
 }
@@ -368,16 +456,7 @@ trait EncodableWithoutSignature {
     fn encode_without_signature<S: io::Write>(&self, s: S) -> Result<usize>;
     fn encode_without_signature<S: io::Write>(&self, s: S) -> Result<usize>;
 }
 }
 
 
-impl EncodableWithoutSignature for Vec<TransactionInput> {
-    fn encode_without_signature<S: io::Write>(&self, mut s: S) -> Result<usize> {
-        let mut len = 0;
-        len += VarInt(self.len() as u64).encode(&mut s)?;
-        for c in self.iter() {
-            len += c.encode_without_signature(&mut s)?;
-        }
-        Ok(len)
-    }
-}
+impl_vec_without_signature!(TransactionInput);
 
 
 impl Encodable for TransactionInput {
 impl Encodable for TransactionInput {
     fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
     fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {