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

daod: move signature verification and signing to Transaction level. at this point, encoding is still unimplemented

lunar-mining 3 лет назад
Родитель
Сommit
2349eaab43

+ 5 - 4
bin/daod/src/dao_contract/exec/validate.rs

@@ -5,7 +5,7 @@ use pasta_curves::{
 };
 
 use darkfi::{
-    crypto::{coin::Coin, types::DrkCircuitField},
+    crypto::{coin::Coin, keypair::PublicKey, types::DrkCircuitField},
     Error as DarkFiError,
 };
 
@@ -95,6 +95,10 @@ impl CallDataBase for CallData {
     fn as_any(&self) -> &dyn Any {
         self
     }
+
+    fn signature_public_keys(&self) -> Vec<PublicKey> {
+        vec![]
+    }
 }
 
 pub fn state_transition(
@@ -189,7 +193,4 @@ impl UpdateBase for Update {
             .expect("Return type is not of type State");
         state.proposal_votes.remove(&HashableBase(self.proposal)).unwrap();
     }
-    //fn as_any(&self) -> &dyn Any {
-    //    self
-    //}
 }

+ 2 - 0
bin/daod/src/dao_contract/exec/wallet.rs

@@ -6,6 +6,7 @@ use pasta_curves::{arithmetic::CurveAffine, group::Curve, pallas};
 
 use darkfi::{
     crypto::{
+        keypair::{PublicKey, SecretKey},
         util::{pedersen_commitment_u64, poseidon_hash},
         Proof,
     },
@@ -34,6 +35,7 @@ pub struct Builder {
     pub input_value: u64,
     pub input_value_blind: pallas::Scalar,
     pub hook_dao_exec: pallas::Base,
+    pub signature_secret: SecretKey,
 }
 
 impl Builder {

+ 5 - 4
bin/daod/src/dao_contract/mint/validate.rs

@@ -1,6 +1,6 @@
 use std::any::{Any, TypeId};
 
-use darkfi::crypto::types::DrkCircuitField;
+use darkfi::crypto::{keypair::PublicKey, types::DrkCircuitField};
 
 use crate::{
     dao_contract::{DaoBulla, State},
@@ -36,9 +36,6 @@ impl UpdateBase for Update {
         // Add dao_bulla to state.dao_bullas
         state.add_dao_bulla(self.dao_bulla);
     }
-    //fn as_any(&self) -> &dyn Any {
-    //    self
-    //}
 }
 
 #[derive(Debug, Clone, thiserror::Error)]
@@ -58,4 +55,8 @@ impl CallDataBase for CallData {
     fn as_any(&self) -> &dyn Any {
         self
     }
+
+    fn signature_public_keys(&self) -> Vec<PublicKey> {
+        vec![]
+    }
 }

+ 8 - 1
bin/daod/src/dao_contract/mint/wallet.rs

@@ -1,7 +1,11 @@
 use crate::dao_contract::state::DaoBulla;
 
 use darkfi::{
-    crypto::{keypair::PublicKey, util::poseidon_hash, Proof},
+    crypto::{
+        keypair::{PublicKey, SecretKey},
+        util::poseidon_hash,
+        Proof,
+    },
     zk::vm::{Witness, ZkCircuit},
 };
 use halo2_proofs::circuit::Value;
@@ -20,6 +24,7 @@ pub struct Builder {
     gov_token_id: pallas::Base,
     dao_pubkey: PublicKey,
     dao_bulla_blind: pallas::Base,
+    signature_secret: SecretKey,
 }
 
 impl Builder {
@@ -30,6 +35,7 @@ impl Builder {
         gov_token_id: pallas::Base,
         dao_pubkey: PublicKey,
         dao_bulla_blind: pallas::Base,
+        signature_secret: SecretKey,
     ) -> Self {
         Self {
             dao_proposer_limit,
@@ -38,6 +44,7 @@ impl Builder {
             gov_token_id,
             dao_pubkey,
             dao_bulla_blind,
+            signature_secret,
         }
     }
 

+ 9 - 19
bin/daod/src/dao_contract/propose/validate.rs

@@ -49,7 +49,7 @@ impl From<DarkFiError> for Error {
 pub struct CallData {
     pub header: Header,
     pub inputs: Vec<Input>,
-    pub signatures: Vec<schnorr::Signature>,
+    pub signature_publics: Vec<PublicKey>,
 }
 
 impl CallDataBase for CallData {
@@ -95,6 +95,14 @@ impl CallDataBase for CallData {
     fn as_any(&self) -> &dyn Any {
         self
     }
+
+    fn signature_public_keys(&self) -> Vec<PublicKey> {
+        let mut signature_public_keys = vec![];
+        for pub_key in self.signature_publics.clone() {
+            signature_public_keys.push(pub_key);
+        }
+        signature_public_keys
+    }
 }
 
 #[derive(Clone, SerialEncodable, SerialDecodable)]
@@ -141,21 +149,6 @@ pub fn state_transition(
         return Err(Error::InvalidDaoMerkleRoot)
     }
 
-    // Verify the available signatures
-    let mut unsigned_tx_data = vec![];
-    call_data.header.encode(&mut unsigned_tx_data).expect("failed to encode data");
-    call_data.inputs.encode(&mut unsigned_tx_data).expect("failed to encode inputs");
-    func_call.proofs.encode(&mut unsigned_tx_data).expect("failed to encode proofs");
-
-    for (_i, (input, signature)) in
-        call_data.inputs.iter().zip(call_data.signatures.iter()).enumerate()
-    {
-        let public = &input.signature_public;
-        if !public.verify(&unsigned_tx_data[..], signature) {
-            return Err(Error::SignatureVerifyFailed)
-        }
-    }
-
     // TODO: look at gov tokens avoid using already spent ones
     // Need to spend original coin and generate 2 nullifiers?
 
@@ -172,7 +165,4 @@ impl UpdateBase for Update {
         let state = states.lookup_mut::<DaoState>(&"DAO".to_string()).unwrap();
         state.add_proposal_bulla(self.proposal_bulla);
     }
-    //fn as_any(&self) -> &dyn Any {
-    //    self
-    //}
 }

+ 8 - 19
bin/daod/src/dao_contract/propose/wallet.rs

@@ -37,6 +37,7 @@ pub struct BuilderInput {
     pub note: money_contract::transfer::wallet::Note,
     pub leaf_position: incrementalmerkletree::Position,
     pub merkle_path: Vec<MerkleNode>,
+    pub signature_secret: SecretKey,
 }
 
 #[derive(SerialEncodable, SerialDecodable, Clone)]
@@ -65,6 +66,7 @@ pub struct Builder {
     pub dao_leaf_position: incrementalmerkletree::Position,
     pub dao_merkle_path: Vec<MerkleNode>,
     pub dao_merkle_root: MerkleNode,
+    //pub signature_secrets: Vec<SecretKey>,
 }
 
 impl Builder {
@@ -76,14 +78,15 @@ impl Builder {
         let mut inputs = vec![];
         let mut total_funds = 0;
         let mut total_funds_blinds = pallas::Scalar::from(0);
-        let mut signature_secrets = vec![];
+        //let mut signature_secrets = vec![];
+        let mut signature_publics = vec![];
         for input in self.inputs {
             let funds_blind = pallas::Scalar::random(&mut OsRng);
             total_funds += input.note.value;
             total_funds_blinds += funds_blind;
 
-            let signature_secret = SecretKey::random(&mut OsRng);
-            let signature_public = PublicKey::from_secret(signature_secret);
+            let signature_public = PublicKey::from_secret(input.signature_secret);
+            signature_publics.push(signature_public);
 
             let zk_info = zk_bins.lookup(&"dao-propose-burn".to_string()).unwrap();
             let zk_info = if let ZkContractInfo::Binary(info) = zk_info {
@@ -109,7 +112,7 @@ impl Builder {
                 Witness::Base(Value::known(gov_token_blind)),
                 Witness::Uint32(Value::known(leaf_pos.try_into().unwrap())),
                 Witness::MerklePath(Value::known(input.merkle_path.clone().try_into().unwrap())),
-                Witness::Base(Value::known(signature_secret.0)),
+                Witness::Base(Value::known(input.signature_secret.0)),
             ];
 
             let public_key = PublicKey::from_secret(input.secret);
@@ -167,9 +170,6 @@ impl Builder {
                 .expect("DAO::propose() proving error!");
             proofs.push(input_proof);
 
-            // First we make the tx then sign after
-            signature_secrets.push(signature_secret);
-
             let input = Input { value_commit, merkle_root, signature_public };
             inputs.push(input);
         }
@@ -272,18 +272,7 @@ impl Builder {
             enc_note,
         };
 
-        let mut unsigned_tx_data = vec![];
-        header.encode(&mut unsigned_tx_data).expect("failed to encode data");
-        inputs.encode(&mut unsigned_tx_data).expect("failed to encode inputs");
-        proofs.encode(&mut unsigned_tx_data).expect("failed to encode proofs");
-
-        let mut signatures = vec![];
-        for signature_secret in &signature_secrets {
-            let signature = signature_secret.sign(&unsigned_tx_data[..]);
-            signatures.push(signature);
-        }
-
-        let call_data = CallData { header, inputs, signatures };
+        let call_data = CallData { header, inputs, signature_publics };
 
         FuncCall {
             contract_id: "DAO".to_string(),

+ 9 - 21
bin/daod/src/dao_contract/vote/validate.rs

@@ -52,7 +52,7 @@ impl From<DarkFiError> for Error {
 pub struct CallData {
     pub header: Header,
     pub inputs: Vec<Input>,
-    pub signatures: Vec<schnorr::Signature>,
+    pub signature_publics: Vec<PublicKey>,
 }
 
 impl CallDataBase for CallData {
@@ -103,6 +103,14 @@ impl CallDataBase for CallData {
     fn as_any(&self) -> &dyn Any {
         self
     }
+
+    fn signature_public_keys(&self) -> Vec<PublicKey> {
+        let mut signature_public_keys = vec![];
+        for pub_key in self.signature_publics.clone() {
+            signature_public_keys.push(pub_key);
+        }
+        signature_public_keys
+    }
 }
 
 #[derive(Clone, SerialEncodable, SerialDecodable)]
@@ -166,23 +174,6 @@ pub fn state_transition(
         vote_nulls.push(input.nullifier);
     }
 
-    // Verify the available signatures
-    let mut unsigned_tx_data = vec![];
-    call_data.header.encode(&mut unsigned_tx_data).expect("failed to encode data");
-    call_data.inputs.encode(&mut unsigned_tx_data).expect("failed to encode inputs");
-    func_call.proofs.encode(&mut unsigned_tx_data).expect("failed to encode proofs");
-
-    //debug!("unsigned_tx_data: {:?}", unsigned_tx_data);
-
-    for (_i, (input, signature)) in
-        call_data.inputs.iter().zip(call_data.signatures.iter()).enumerate()
-    {
-        let public = &input.signature_public;
-        if !public.verify(&unsigned_tx_data[..], signature) {
-            return Err(Error::SignatureVerifyFailed)
-        }
-    }
-
     Ok(Box::new(Update {
         proposal_bulla: call_data.header.proposal_bulla,
         vote_nulls,
@@ -207,7 +198,4 @@ impl UpdateBase for Update {
         votes_info.value_commits += self.value_commit;
         votes_info.vote_nulls.append(&mut self.vote_nulls);
     }
-    //fn as_any(&self) -> &dyn Any {
-    //    self
-    //}
 }

+ 6 - 26
bin/daod/src/dao_contract/vote/wallet.rs

@@ -49,6 +49,7 @@ pub struct BuilderInput {
     pub note: money_contract::transfer::wallet::Note,
     pub leaf_position: incrementalmerkletree::Position,
     pub merkle_path: Vec<MerkleNode>,
+    pub signature_secret: SecretKey,
 }
 
 // TODO: should be token locking voting?
@@ -71,7 +72,7 @@ impl Builder {
         let mut inputs = vec![];
         let mut value = 0;
         let mut value_blind = pallas::Scalar::from(0);
-        let mut signature_secrets = vec![];
+        let mut signature_publics = vec![];
 
         for input in self.inputs {
             let input_value_blind = pallas::Scalar::random(&mut OsRng);
@@ -79,8 +80,8 @@ impl Builder {
             value += input.note.value;
             value_blind += input_value_blind;
 
-            let signature_secret = SecretKey::random(&mut OsRng);
-            let signature_public = PublicKey::from_secret(signature_secret);
+            let signature_public = PublicKey::from_secret(input.signature_secret);
+            signature_publics.push(signature_public);
 
             let zk_info = zk_bins.lookup(&"dao-vote-burn".to_string()).unwrap();
 
@@ -107,7 +108,7 @@ impl Builder {
                 Witness::Base(Value::known(gov_token_blind)),
                 Witness::Uint32(Value::known(leaf_pos.try_into().unwrap())),
                 Witness::MerklePath(Value::known(input.merkle_path.clone().try_into().unwrap())),
-                Witness::Base(Value::known(signature_secret.0)),
+                Witness::Base(Value::known(input.signature_secret.0)),
             ];
 
             let public_key = PublicKey::from_secret(input.secret);
@@ -169,9 +170,6 @@ impl Builder {
                 .expect("DAO::vote() proving error!");
             proofs.push(input_proof);
 
-            // First we make the tx then sign after
-            signature_secrets.push(signature_secret);
-
             let input = Input {
                 nullifier: Nullifier(nullifier),
                 value_commit,
@@ -289,25 +287,7 @@ impl Builder {
 
         let header = Header { token_commit, proposal_bulla, vote_commit, enc_note };
 
-        let mut unsigned_tx_data = vec![];
-        header.encode(&mut unsigned_tx_data).expect("failed to encode data");
-        inputs.encode(&mut unsigned_tx_data).expect("failed to encode inputs");
-        proofs.encode(&mut unsigned_tx_data).expect("failed to encode proofs");
-
-        //debug!("unsigned_tx_data: {:?}", unsigned_tx_data);
-
-        let mut signatures = vec![];
-        assert_eq!(
-            signature_secrets.len(),
-            inputs.len(),
-            "non matching signature_secrets and inputs length!"
-        );
-        for signature_secret in &signature_secrets {
-            let signature = signature_secret.sign(&unsigned_tx_data[..]);
-            signatures.push(signature);
-        }
-
-        let call_data = CallData { header, inputs, signatures };
+        let call_data = CallData { header, inputs, signature_publics };
 
         FuncCall {
             contract_id: "DAO".to_string(),

+ 86 - 25
bin/daod/src/demo.rs

@@ -16,10 +16,12 @@ use darkfi::{
     crypto::{
         keypair::{Keypair, PublicKey, SecretKey},
         proof::{ProvingKey, VerifyingKey},
+        schnorr::{SchnorrPublic, SchnorrSecret, Signature},
         types::{DrkCircuitField, DrkSpendHook, DrkUserData, DrkValue},
         util::{pedersen_commitment_u64, poseidon_hash},
         Proof,
     },
+    util::serial::{Encodable, SerialDecodable, SerialEncodable},
     zk::{
         circuit::{BurnContract, MintContract},
         vm::ZkCircuit,
@@ -92,8 +94,10 @@ impl ZkContractTable {
     }
 }
 
+//#[derive(Clone, SerialEncodable, SerialDecodable)]
 pub struct Transaction {
     pub func_calls: Vec<FuncCall>,
+    pub signatures: Vec<Signature>,
 }
 
 impl Transaction {
@@ -130,6 +134,32 @@ impl Transaction {
             }
         }
     }
+
+    fn verify_sigs(&self) {
+        let mut unsigned_tx_data = vec![];
+        for (i, (func_call, signature)) in
+            self.func_calls.iter().zip(self.signatures.clone()).enumerate()
+        {
+            let signature_pub_keys = func_call.call_data.signature_public_keys();
+            for signature_pub_key in signature_pub_keys {
+                let verify_result = signature_pub_key.verify(&unsigned_tx_data[..], &signature);
+                assert!(verify_result, "verify sigs[{}] failed", i);
+            }
+            debug!(target: "demo", "verify_sigs({}) passed", i);
+        }
+    }
+}
+
+fn sign(signature_secrets: Vec<SecretKey>) -> Vec<Signature> {
+    let mut signatures = vec![];
+    let mut unsigned_tx_data = vec![];
+    // TODO:
+    //tx.encode(&mut unsigned_tx_data).expect("failed to encode data");
+    for (i, signature_secret) in signature_secrets.iter().enumerate() {
+        let signature = signature_secret.sign(&unsigned_tx_data[..]);
+        signatures.push(signature);
+    }
+    signatures
 }
 
 // These would normally be a hash or sth
@@ -150,6 +180,9 @@ pub trait CallDataBase {
 
     // For upcasting to CallData itself so it can be read in state_transition()
     fn as_any(&self) -> &dyn Any;
+
+    // Public keys we will use to verify transaction signatures.
+    fn signature_public_keys(&self) -> Vec<PublicKey>;
 }
 
 type GenericContractState = Box<dyn Any>;
@@ -179,9 +212,6 @@ impl StateRegistry {
 
 pub trait UpdateBase {
     fn apply(self: Box<Self>, states: &mut StateRegistry);
-
-    // For upcasting to Update. Used for testing.
-    // fn as_any(&self) -> &dyn Any;
 }
 
 ///////////////////////////////////////////////////
@@ -205,10 +235,13 @@ pub async fn example() -> Result<()> {
     //// Wallet
 
     let foo = example_contract::foo::wallet::Foo { a: 5, b: 10 };
+    let signature_secret = SecretKey::random(&mut OsRng);
 
-    let builder = example_contract::foo::wallet::Builder { foo };
+    let builder = example_contract::foo::wallet::Builder { foo, signature_secret };
     let func_call = builder.build(&zk_bins);
-    let tx = Transaction { func_calls: vec![func_call] };
+
+    let signatures = sign(vec![signature_secret]);
+    let tx = Transaction { func_calls: vec![func_call], signatures };
 
     //// Validator
 
@@ -230,6 +263,7 @@ pub async fn example() -> Result<()> {
     }
 
     tx.zk_verify(&zk_bins);
+    tx.verify_sigs();
 
     Ok(())
 }
@@ -329,6 +363,7 @@ pub async fn demo() -> Result<()> {
     let dao_keypair = Keypair::random(&mut OsRng);
     let dao_bulla_blind = pallas::Base::random(&mut OsRng);
 
+    let signature_secret = SecretKey::random(&mut OsRng);
     // Create DAO mint tx
     let builder = dao_contract::mint::wallet::Builder::new(
         dao_proposer_limit,
@@ -337,10 +372,12 @@ pub async fn demo() -> Result<()> {
         gdrk_token_id,
         dao_keypair.public,
         dao_bulla_blind,
+        signature_secret,
     );
     let func_call = builder.build(&zk_bins);
 
-    let tx = Transaction { func_calls: vec![func_call] };
+    let signatures = sign(vec![signature_secret]);
+    let tx = Transaction { func_calls: vec![func_call], signatures };
 
     //// Validator
 
@@ -434,7 +471,8 @@ pub async fn demo() -> Result<()> {
 
     let func_call = builder.build(&zk_bins)?;
 
-    let tx = Transaction { func_calls: vec![func_call] };
+    let signatures = sign(vec![cashier_signature_secret]);
+    let tx = Transaction { func_calls: vec![func_call], signatures };
 
     //// Validator
 
@@ -458,6 +496,7 @@ pub async fn demo() -> Result<()> {
     }
 
     tx.zk_verify(&zk_bins);
+    tx.verify_sigs();
 
     //// Wallet
     // DAO reads the money received from the encrypted note
@@ -510,9 +549,6 @@ pub async fn demo() -> Result<()> {
 
     let gov_keypairs = vec![gov_keypair_1, gov_keypair_2, gov_keypair_3];
 
-    // We don't use this because money-transfer expects a cashier.
-    // let signature_secret = SecretKey::random(&mut OsRng);
-
     // Spend hook and user data disabled
     let spend_hook = DrkSpendHook::from(0);
     let user_data = DrkUserData::from(0);
@@ -561,7 +597,8 @@ pub async fn demo() -> Result<()> {
 
     let func_call = builder.build(&zk_bins)?;
 
-    let tx = Transaction { func_calls: vec![func_call] };
+    let signatures = sign(vec![cashier_signature_secret]);
+    let tx = Transaction { func_calls: vec![func_call], signatures };
 
     //// Validator
 
@@ -585,6 +622,7 @@ pub async fn demo() -> Result<()> {
     }
 
     tx.zk_verify(&zk_bins);
+    tx.verify_sigs();
 
     //// Wallet
 
@@ -660,11 +698,13 @@ pub async fn demo() -> Result<()> {
 
     // TODO: is it possible for an invalid transfer() to be constructed on exec()?
     //       need to look into this
+    let signature_secret = SecretKey::random(&mut OsRng);
     let input = dao_contract::propose::wallet::BuilderInput {
         secret: gov_keypair_1.secret,
         note: gov_recv[0].note.clone(),
         leaf_position: money_leaf_position,
         merkle_path: money_merkle_path,
+        signature_secret,
     };
 
     let (dao_merkle_path, dao_merkle_root) = {
@@ -703,7 +743,8 @@ pub async fn demo() -> Result<()> {
 
     let func_call = builder.build(&zk_bins);
 
-    let tx = Transaction { func_calls: vec![func_call] };
+    let signatures = sign(vec![signature_secret]);
+    let tx = Transaction { func_calls: vec![func_call], signatures };
 
     //// Validator
 
@@ -725,6 +766,7 @@ pub async fn demo() -> Result<()> {
     }
 
     tx.zk_verify(&zk_bins);
+    tx.verify_sigs();
 
     //// Wallet
 
@@ -793,11 +835,13 @@ pub async fn demo() -> Result<()> {
         (leaf_position, merkle_path)
     };
 
+    let signature_secret = SecretKey::random(&mut OsRng);
     let input = dao_contract::vote::wallet::BuilderInput {
         secret: gov_keypair_1.secret,
         note: gov_recv[0].note.clone(),
         leaf_position: money_leaf_position,
         merkle_path: money_merkle_path,
+        signature_secret,
     };
 
     let vote_option: bool = true;
@@ -820,7 +864,8 @@ pub async fn demo() -> Result<()> {
     debug!(target: "demo", "build()...");
     let func_call = builder.build(&zk_bins);
 
-    let tx = Transaction { func_calls: vec![func_call] };
+    let signatures = sign(vec![signature_secret]);
+    let tx = Transaction { func_calls: vec![func_call], signatures };
 
     //// Validator
 
@@ -842,6 +887,7 @@ pub async fn demo() -> Result<()> {
     }
 
     tx.zk_verify(&zk_bins);
+    tx.verify_sigs();
 
     //// Wallet
 
@@ -875,11 +921,13 @@ pub async fn demo() -> Result<()> {
         (leaf_position, merkle_path)
     };
 
+    let signature_secret = SecretKey::random(&mut OsRng);
     let input = dao_contract::vote::wallet::BuilderInput {
         secret: gov_keypair_2.secret,
         note: gov_recv[1].note.clone(),
         leaf_position: money_leaf_position,
         merkle_path: money_merkle_path,
+        signature_secret,
     };
 
     let vote_option: bool = false;
@@ -902,7 +950,8 @@ pub async fn demo() -> Result<()> {
     debug!(target: "demo", "build()...");
     let func_call = builder.build(&zk_bins);
 
-    let tx = Transaction { func_calls: vec![func_call] };
+    let signatures = sign(vec![signature_secret]);
+    let tx = Transaction { func_calls: vec![func_call], signatures };
 
     //// Validator
 
@@ -924,6 +973,7 @@ pub async fn demo() -> Result<()> {
     }
 
     tx.zk_verify(&zk_bins);
+    tx.verify_sigs();
 
     //// Wallet
 
@@ -957,11 +1007,13 @@ pub async fn demo() -> Result<()> {
         (leaf_position, merkle_path)
     };
 
+    let signature_secret = SecretKey::random(&mut OsRng);
     let input = dao_contract::vote::wallet::BuilderInput {
         secret: gov_keypair_3.secret,
         note: gov_recv[2].note.clone(),
         leaf_position: money_leaf_position,
         merkle_path: money_merkle_path,
+        signature_secret,
     };
 
     let vote_option: bool = true;
@@ -984,7 +1036,8 @@ pub async fn demo() -> Result<()> {
     debug!(target: "demo", "build()...");
     let func_call = builder.build(&zk_bins);
 
-    let tx = Transaction { func_calls: vec![func_call] };
+    let signatures = sign(vec![signature_secret]);
+    let tx = Transaction { func_calls: vec![func_call], signatures };
 
     //// Validator
 
@@ -1006,6 +1059,7 @@ pub async fn demo() -> Result<()> {
     }
 
     tx.zk_verify(&zk_bins);
+    tx.verify_sigs();
 
     //// Wallet
 
@@ -1102,6 +1156,8 @@ pub async fn demo() -> Result<()> {
     let dao_coin_blind = pallas::Base::random(&mut OsRng);
     let input_value = treasury_note.value;
     let input_value_blind = pallas::Scalar::random(&mut OsRng);
+    let tx_signature_secret = SecretKey::random(&mut OsRng);
+    let exec_signature_secret = SecretKey::random(&mut OsRng);
 
     let (treasury_leaf_position, treasury_merkle_path) = {
         let state = states.lookup::<money_contract::State>(&"Money".to_string()).unwrap();
@@ -1112,16 +1168,19 @@ pub async fn demo() -> Result<()> {
         (leaf_position, merkle_path)
     };
 
+    let input = money_contract::transfer::wallet::BuilderInputInfo {
+        leaf_position: treasury_leaf_position,
+        merkle_path: treasury_merkle_path,
+        secret: dao_keypair.secret,
+        note: treasury_note,
+        user_data_blind,
+        value_blind: input_value_blind,
+        signature_secret: tx_signature_secret,
+    };
+
     let builder = money_contract::transfer::wallet::Builder {
         clear_inputs: vec![],
-        inputs: vec![money_contract::transfer::wallet::BuilderInputInfo {
-            leaf_position: treasury_leaf_position,
-            merkle_path: treasury_merkle_path,
-            secret: dao_keypair.secret,
-            note: treasury_note,
-            user_data_blind,
-            value_blind: input_value_blind,
-        }],
+        inputs: vec![input],
         outputs: vec![
             // Sending money
             money_contract::transfer::wallet::BuilderOutputInfo {
@@ -1162,10 +1221,12 @@ pub async fn demo() -> Result<()> {
         input_value,
         input_value_blind,
         hook_dao_exec: *dao_contract::exec::FUNC_ID,
+        signature_secret: exec_signature_secret,
     };
     let exec_func_call = builder.build(&zk_bins);
 
-    let tx = Transaction { func_calls: vec![transfer_func_call, exec_func_call] };
+    let signatures = sign(vec![tx_signature_secret, exec_signature_secret]);
+    let tx = Transaction { func_calls: vec![transfer_func_call, exec_func_call], signatures };
 
     {
         // Now the spend_hook field specifies the function DAO::exec()
@@ -1217,7 +1278,7 @@ pub async fn demo() -> Result<()> {
 
     // Other stuff
     tx.zk_verify(&zk_bins);
-    // TODO: signature verification
+    tx.verify_sigs();
 
     //// Wallet
 

+ 5 - 4
bin/daod/src/example_contract/foo/validate.rs

@@ -32,7 +32,7 @@ impl From<DarkFiError> for Error {
 
 pub struct CallData {
     pub public_value: pallas::Base,
-    //pub signature_public: PublicKey,
+    pub signature_public: PublicKey,
 }
 
 impl CallDataBase for CallData {
@@ -43,6 +43,10 @@ impl CallDataBase for CallData {
     fn as_any(&self) -> &dyn Any {
         self
     }
+
+    fn signature_public_keys(&self) -> Vec<PublicKey> {
+        vec![self.signature_public]
+    }
 }
 
 pub fn state_transition(
@@ -78,7 +82,4 @@ impl UpdateBase for Update {
         let example_state = states.lookup_mut::<State>(&"Example".to_string()).unwrap();
         example_state.add_public_value(self.public_value);
     }
-    //fn as_any(&self) -> &dyn Any {
-    //    self
-    //}
 }

+ 7 - 2
bin/daod/src/example_contract/foo/wallet.rs

@@ -5,7 +5,10 @@ use halo2_proofs::circuit::Value;
 use pasta_curves::pallas;
 
 use darkfi::{
-    crypto::{keypair::SecretKey, Proof},
+    crypto::{
+        keypair::{PublicKey, SecretKey},
+        Proof,
+    },
     zk::vm::{Witness, ZkCircuit},
 };
 
@@ -57,7 +60,9 @@ impl Builder {
             .expect("Example::foo() proving error!)");
         proofs.push(input_proof);
 
-        let call_data = CallData { public_value: c };
+        let signature_public = PublicKey::from_secret(self.signature_secret);
+
+        let call_data = CallData { public_value: c, signature_public };
 
         FuncCall {
             contract_id: "Example".to_string(),

+ 10 - 31
bin/daod/src/money_contract/transfer/validate.rs

@@ -60,9 +60,6 @@ impl UpdateBase for Update {
             state.wallet_cache.try_decrypt_note(coin, enc_note, &mut state.tree);
         }
     }
-    //fn as_any(&self) -> &dyn Any {
-    //    self
-    //}
 }
 
 pub fn state_transition(
@@ -183,10 +180,8 @@ pub struct CallData {
     pub inputs: Vec<Input>,
     /// Anonymous outputs
     pub outputs: Vec<Output>,
-    /// Clear input signatures
-    pub clear_signatures: Vec<schnorr::Signature>,
-    /// Input signatures
-    pub signatures: Vec<schnorr::Signature>,
+    /// Signature public keys
+    pub signature_publics: Vec<PublicKey>,
 }
 
 impl CallDataBase for CallData {
@@ -204,6 +199,14 @@ impl CallDataBase for CallData {
     fn as_any(&self) -> &dyn Any {
         self
     }
+
+    fn signature_public_keys(&self) -> Vec<PublicKey> {
+        let mut signature_public_keys = Vec::new();
+        for pub_key in self.signature_publics.clone() {
+            signature_public_keys.push(pub_key);
+        }
+        signature_public_keys
+    }
 }
 impl CallData {
     /// Verify the transaction
@@ -247,30 +250,6 @@ impl CallData {
             return Err(VerifyFailed::TokenMismatch)
         }
 
-        // Verify the available signatures
-        let mut unsigned_tx_data = vec![];
-        self.clear_inputs.encode(&mut unsigned_tx_data)?;
-        self.inputs.encode(&mut unsigned_tx_data)?;
-        self.outputs.encode(&mut unsigned_tx_data)?;
-
-        for (i, (input, signature)) in
-            self.clear_inputs.iter().zip(self.clear_signatures.iter()).enumerate()
-        {
-            let public = &input.signature_public;
-            if !public.verify(&unsigned_tx_data[..], signature) {
-                error!("tx::verify(): Failed to verify Clear Input signature {}", i);
-                return Err(VerifyFailed::ClearInputSignature(i))
-            }
-        }
-
-        for (i, (input, signature)) in self.inputs.iter().zip(self.signatures.iter()).enumerate() {
-            let public = &input.revealed.signature_public;
-            if !public.verify(&unsigned_tx_data[..], signature) {
-                error!("tx::verify(): Failed to verify Input signature {}", i);
-                return Err(VerifyFailed::InputSignature(i))
-            }
-        }
-
         Ok(())
     }
 

+ 9 - 31
bin/daod/src/money_contract/transfer/wallet.rs

@@ -54,6 +54,7 @@ pub struct BuilderInputInfo {
     pub note: Note,
     pub user_data_blind: DrkUserDataBlind,
     pub value_blind: DrkValueBlind,
+    pub signature_secret: SecretKey,
 }
 
 pub struct BuilderOutputInfo {
@@ -109,15 +110,16 @@ impl Builder {
         }
 
         let mut proofs = vec![];
-
         let mut inputs = vec![];
         let mut input_blinds = vec![];
-        let mut signature_secrets = vec![];
+        let mut signature_publics = vec![];
+
         for input in self.inputs {
             let value_blind = input.value_blind;
             input_blinds.push(value_blind);
 
-            let signature_secret = SecretKey::random(&mut OsRng);
+            let signature_public = PublicKey::from_secret(input.signature_secret);
+            signature_publics.push(signature_public);
 
             let zk_info = zk_bins.lookup(&"money-transfer-burn".to_string()).unwrap();
             let zk_info = if let ZkContractInfo::Native(info) = zk_info {
@@ -128,7 +130,7 @@ impl Builder {
             let burn_pk = &zk_info.proving_key;
 
             // Note from the previous output
-            let note = input.note;
+            let note = input.note.clone();
 
             let (burn_proof, revealed) = create_burn_proof(
                 burn_pk,
@@ -143,14 +145,11 @@ impl Builder {
                 note.coin_blind,
                 input.secret,
                 input.leaf_position,
-                input.merkle_path,
-                signature_secret,
+                input.merkle_path.clone(),
+                input.signature_secret,
             )?;
             proofs.push(burn_proof);
 
-            // First we make the tx then sign after
-            signature_secrets.push(signature_secret);
-
             let input = Input { revealed };
             inputs.push(input);
         }
@@ -193,7 +192,6 @@ impl Builder {
             )?;
             proofs.push(mint_proof);
 
-            // Encrypted note
             let note = Note {
                 serial,
                 value: output.value,
@@ -211,27 +209,7 @@ impl Builder {
             outputs.push(output);
         }
 
-        //let partial = Partial { clear_inputs, inputs, outputs, proofs };
-
-        let mut unsigned_tx_data = vec![];
-        clear_inputs.encode(&mut unsigned_tx_data)?;
-        inputs.encode(&mut unsigned_tx_data)?;
-        outputs.encode(&mut unsigned_tx_data)?;
-
-        let mut clear_signatures = vec![];
-        for clear_input in self.clear_inputs {
-            let secret = clear_input.signature_secret;
-            let signature = secret.sign(&unsigned_tx_data[..]);
-            clear_signatures.push(signature);
-        }
-
-        let mut signatures = vec![];
-        for signature_secret in signature_secrets {
-            let signature = signature_secret.sign(&unsigned_tx_data[..]);
-            signatures.push(signature);
-        }
-
-        let call_data = CallData { clear_inputs, inputs, outputs, clear_signatures, signatures };
+        let call_data = CallData { clear_inputs, inputs, outputs, signature_publics };
 
         Ok(FuncCall {
             contract_id: "Money".to_string(),

+ 1 - 1
script/research/fud/localnet/lilith_config.toml

@@ -10,7 +10,7 @@
 #rpc_listen = "tcp://127.0.0.1:18927"
 
 # Daemon published url, common for all enabled networks
-url = ["tcp://127.0.0.1"]
+url = ["tls://127.0.0.1"]
 
 ## Per-network settings
 #[network."darkfid_sync"]