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

split WalletCache into its own module

x 3 лет назад
Родитель
Сommit
a7751f4e18

+ 25 - 153
src/contract/dao/src/dao_client/mint.rs

@@ -22,81 +22,14 @@ use darkfi::{
     Result,
 };
 use darkfi_sdk::{
-    crypto::{
-        coin::Coin, constants::MERKLE_DEPTH, poseidon_hash, MerkleNode, PublicKey, SecretKey,
-        TokenId,
-    },
-    incrementalmerkletree,
-    incrementalmerkletree::{bridgetree::BridgeTree, Tree},
+    crypto::{poseidon_hash, PublicKey, TokenId},
     pasta::pallas,
 };
 use halo2_proofs::circuit::Value;
 use log::debug;
 use rand::rngs::OsRng;
 
-use darkfi_money_contract::client::{EncryptedNote, Note};
-
-use crate::dao_model::{DaoBulla, DaoMintParams};
-
-pub type MerkleTree = BridgeTree<MerkleNode, { MERKLE_DEPTH }>;
-
-pub struct OwnCoin {
-    pub coin: Coin,
-    pub note: Note,
-    pub leaf_position: incrementalmerkletree::Position,
-}
-
-pub struct WalletCache {
-    // Normally this would be a HashMap, but SecretKey is not Hash-able
-    // TODO: This can be HashableBase
-    cache: Vec<(SecretKey, Vec<OwnCoin>)>,
-    /// The entire Merkle tree state
-    pub tree: MerkleTree,
-}
-
-impl Default for WalletCache {
-    fn default() -> Self {
-        Self { cache: Vec::new(), tree: MerkleTree::new(100) }
-    }
-}
-
-impl WalletCache {
-    pub fn new() -> Self {
-        Self { cache: Vec::new(), tree: MerkleTree::new(100) }
-    }
-
-    /// Must be called at the start to begin tracking received coins for this secret.
-    pub fn track(&mut self, secret: SecretKey) {
-        self.cache.push((secret, Vec::new()));
-    }
-
-    /// Get all coins received by this secret key
-    /// track() must be called on this secret before calling this or the function will panic.
-    pub fn get_received(&mut self, secret: &SecretKey) -> Vec<OwnCoin> {
-        for (other_secret, own_coins) in self.cache.iter_mut() {
-            if *secret == *other_secret {
-                // clear own_coins vec, and return current contents
-                return std::mem::take(own_coins)
-            }
-        }
-        panic!("you forget to track() this secret!");
-    }
-
-    pub fn try_decrypt_note(&mut self, coin: Coin, ciphertext: &EncryptedNote) {
-        // Add the new coins to the Merkle tree
-        let node = MerkleNode::from(coin.inner());
-        self.tree.append(&node);
-
-        // Loop through all our secret keys...
-        for (secret, own_coins) in self.cache.iter_mut() {
-            // .. attempt to decrypt the note ...
-            if let Ok(note) = ciphertext.decrypt(secret) {
-                let leaf_position = self.tree.witness().expect("coin should be in tree");
-                own_coins.push(OwnCoin { coin, note, leaf_position });
-            }
-        }
-    }
-}
+use crate::dao_model::DaoMintParams;
 
 #[derive(Clone)]
 pub struct Dao {
@@ -109,63 +42,30 @@ pub struct Dao {
     pub bulla_blind: pallas::Base,
 }
 
-struct DaoMintRevealed {
-    pub bulla: DaoBulla,
-}
-
-impl DaoMintRevealed {
-    pub fn compute(
-        dao_proposer_limit: pallas::Base,
-        dao_quorum: pallas::Base,
-        dao_approval_ratio_quot: pallas::Base,
-        dao_approval_ratio_base: pallas::Base,
-        gov_token_id: TokenId,
-        dao_pubkey: &PublicKey,
-        dao_bulla_blind: pallas::Base,
-    ) -> Self {
-        let (pub_x, pub_y) = dao_pubkey.xy();
-
-        let dao_bulla = poseidon_hash([
-            dao_proposer_limit,
-            dao_quorum,
-            dao_approval_ratio_quot,
-            dao_approval_ratio_base,
-            gov_token_id.inner(),
-            pub_x,
-            pub_y,
-            dao_bulla_blind,
-        ]);
+pub fn make_mint_call(
+    dao: &Dao,
+    dao_mint_zkbin: &ZkBinary,
+    dao_mint_pk: &ProvingKey,
+) -> Result<(DaoMintParams, Vec<Proof>)> {
+    debug!(target: "dao", "Building DAO contract mint transaction");
 
-        Self { bulla: DaoBulla::from(dao_bulla) }
-    }
+    let dao_proposer_limit = pallas::Base::from(dao.proposer_limit);
+    let dao_quorum = pallas::Base::from(dao.quorum);
+    let dao_approval_ratio_quot = pallas::Base::from(dao.approval_ratio_quot);
+    let dao_approval_ratio_base = pallas::Base::from(dao.approval_ratio_base);
 
-    pub fn to_vec(&self) -> Vec<pallas::Base> {
-        vec![self.bulla.inner()]
-    }
-}
+    let (pub_x, pub_y) = dao.public_key.xy();
 
-fn create_dao_mint_proof(
-    zkbin: &ZkBinary,
-    pk: &ProvingKey,
-    dao_proposer_limit: pallas::Base,
-    dao_quorum: pallas::Base,
-    dao_approval_ratio_quot: pallas::Base,
-    dao_approval_ratio_base: pallas::Base,
-    gov_token_id: TokenId,
-    dao_pubkey: &PublicKey,
-    dao_bulla_blind: pallas::Base,
-) -> Result<(Proof, DaoMintRevealed)> {
-    let revealed = DaoMintRevealed::compute(
+    let dao_bulla = poseidon_hash([
         dao_proposer_limit,
         dao_quorum,
         dao_approval_ratio_quot,
         dao_approval_ratio_base,
-        gov_token_id,
-        dao_pubkey,
-        dao_bulla_blind,
-    );
-
-    let (pub_x, pub_y) = dao_pubkey.xy();
+        dao.gov_token_id.inner(),
+        pub_x,
+        pub_y,
+        dao.bulla_blind,
+    ]);
 
     // NOTE: It's important to keep these in the same order as the zkas code.
     let prover_witnesses = vec![
@@ -173,46 +73,18 @@ fn create_dao_mint_proof(
         Witness::Base(Value::known(dao_quorum)),
         Witness::Base(Value::known(dao_approval_ratio_quot)),
         Witness::Base(Value::known(dao_approval_ratio_base)),
-        Witness::Base(Value::known(gov_token_id.inner())),
+        Witness::Base(Value::known(dao.gov_token_id.inner())),
         Witness::Base(Value::known(pub_x)),
         Witness::Base(Value::known(pub_y)),
-        Witness::Base(Value::known(dao_bulla_blind)),
+        Witness::Base(Value::known(dao.bulla_blind)),
     ];
 
-    let circuit = ZkCircuit::new(prover_witnesses, zkbin.clone());
-    let proof = Proof::create(pk, &[circuit], &revealed.to_vec(), &mut OsRng)?;
-
-    Ok((proof, revealed))
-}
-
-pub fn build_dao_mint_tx(
-    dao_proposer_limit: u64,
-    dao_quorum: u64,
-    dao_approval_ratio_quot: u64,
-    dao_approval_ratio_base: u64,
-    gov_token_id: TokenId,
-    dao_pubkey: &PublicKey,
-    dao_bulla_blind: pallas::Base,
-    _signature_secret: &SecretKey,
-    dao_mint_zkbin: &ZkBinary,
-    dao_mint_pk: &ProvingKey,
-) -> Result<(DaoMintParams, Vec<Proof>)> {
-    debug!(target: "dao", "Building DAO contract mint transaction");
+    let public = vec![dao_bulla];
 
-    let (proof, revealed) = create_dao_mint_proof(
-        dao_mint_zkbin,
-        dao_mint_pk,
-        pallas::Base::from(dao_proposer_limit),
-        pallas::Base::from(dao_quorum),
-        pallas::Base::from(dao_approval_ratio_quot),
-        pallas::Base::from(dao_approval_ratio_base),
-        gov_token_id,
-        dao_pubkey,
-        dao_bulla_blind,
-    )?;
+    let circuit = ZkCircuit::new(prover_witnesses, dao_mint_zkbin.clone());
+    let proof = Proof::create(dao_mint_pk, &[circuit], &public, &mut OsRng)?;
 
-    let dao_bulla = revealed.bulla;
-    let dao_mint_params = DaoMintParams { dao_bulla };
+    let dao_mint_params = DaoMintParams { dao_bulla: dao_bulla.into() };
 
     Ok((dao_mint_params, vec![proof]))
 }

+ 0 - 1
src/contract/dao/src/dao_client/propose.rs

@@ -82,7 +82,6 @@ pub struct ProposeCall {
 }
 
 impl ProposeCall {
-    //pub fn build(self /*, zk_bins: &ZkContractTable */) -> Result<(DaoProposeParams, Vec<Proof>)> {
     pub fn make(
         self,
         burn_zkbin: &ZkBinary,

+ 4 - 12
src/contract/dao/src/lib.rs

@@ -30,22 +30,14 @@ pub mod dao_client;
 
 pub mod dao_model;
 
-//#[cfg(feature = "client")]
-///// Transaction building API for clients interacting with DAO contract
-//pub mod dao_propose_client;
-//
-//#[cfg(feature = "client")]
-///// Transaction building API for clients interacting with DAO contract
-//pub mod dao_vote_client;
-//
-//#[cfg(feature = "client")]
-///// Transaction building API for clients interacting with DAO contract
-//pub mod dao_exec_client;
-
 #[cfg(feature = "client")]
 /// Transaction building API for clients interacting with money contract
 pub mod money_client;
 
+#[cfg(feature = "client")]
+/// Decrypt incoming transaction notes to track coins sent to us
+pub mod wallet_cache;
+
 // These are the zkas circuit namespaces
 pub const DAO_CONTRACT_ZKAS_DAO_MINT_NS: &str = "DaoMint";
 pub const DAO_CONTRACT_ZKAS_DAO_EXEC_NS: &str = "DaoExec";

+ 21 - 40
src/contract/dao/tests/integration.rs

@@ -34,17 +34,15 @@ use darkfi_sdk::{
     tx::ContractCall,
 };
 use darkfi_serial::{Decodable, Encodable};
-use log::{debug, info};
+use log::debug;
 use rand::rngs::OsRng;
 
 use darkfi_dao_contract::{
     dao_client,
-    dao_client::{
-        exec as dao_exec_client,
-        mint::{build_dao_mint_tx, MerkleTree, WalletCache},
-        propose as dao_propose_client, vote as dao_vote_client,
-    },
-    money_client, note, DaoFunction,
+    dao_client::{exec as dao_exec_client, propose as dao_propose_client, vote as dao_vote_client},
+    money_client, note,
+    wallet_cache::{MerkleTree, WalletCache},
+    DaoFunction,
 };
 
 use darkfi_money_contract::{client::EncryptedNote, state::MoneyTransferParams, MoneyFunction};
@@ -75,10 +73,15 @@ async fn integration_test() -> Result<()> {
     let gdrk_token_id = TokenId::from(pallas::Base::random(&mut OsRng));
 
     // DAO parameters
-    let dao_proposer_limit = 110;
-    let dao_quorum = 110;
-    let dao_approval_ratio_quot = 1;
-    let dao_approval_ratio_base = 2;
+    let dao = dao_client::Dao {
+        proposer_limit: 110,
+        quorum: 110,
+        approval_ratio_base: 1,
+        approval_ratio_quot: 2,
+        gov_token_id: gdrk_token_id,
+        public_key: dao_th.dao_kp.public,
+        bulla_blind: pallas::Base::random(&mut OsRng),
+    };
 
     // We use this to receive coins
     let mut cache = WalletCache::new();
@@ -90,20 +93,8 @@ async fn integration_test() -> Result<()> {
     // =======================================================
     debug!(target: "dao", "Stage 1. Creating DAO bulla");
 
-    let dao_bulla_blind = pallas::Base::random(&mut OsRng);
-
-    let (params, proofs) = build_dao_mint_tx(
-        dao_proposer_limit,
-        dao_quorum,
-        dao_approval_ratio_quot,
-        dao_approval_ratio_base,
-        gdrk_token_id,
-        &dao_th.dao_kp.public,
-        dao_bulla_blind,
-        &dao_th.dao_kp.secret,
-        &dao_th.dao_mint_zkbin,
-        &dao_th.dao_mint_pk,
-    )?;
+    let (params, proofs) =
+        dao_client::make_mint_call(&dao, &dao_th.dao_mint_zkbin, &dao_th.dao_mint_pk)?;
 
     let mut data = vec![DaoFunction::Mint as u8];
     params.encode(&mut data)?;
@@ -408,16 +399,6 @@ async fn integration_test() -> Result<()> {
         (merkle_path, root)
     };
 
-    let dao_params = dao_client::Dao {
-        proposer_limit: dao_proposer_limit,
-        quorum: dao_quorum,
-        approval_ratio_base: dao_approval_ratio_base,
-        approval_ratio_quot: dao_approval_ratio_quot,
-        gov_token_id: gdrk_token_id,
-        public_key: dao_th.dao_kp.public,
-        bulla_blind: dao_bulla_blind,
-    };
-
     let proposal = dao_client::Proposal {
         dest: receiver_keypair.public,
         amount: 1000,
@@ -429,7 +410,7 @@ async fn integration_test() -> Result<()> {
     let call = dao_client::ProposeCall {
         inputs: vec![input],
         proposal,
-        dao: dao_params.clone(),
+        dao: dao.clone(),
         dao_leaf_position,
         dao_merkle_path,
         dao_merkle_root,
@@ -539,7 +520,7 @@ async fn integration_test() -> Result<()> {
         },
         vote_keypair: vote_keypair_1,
         proposal: proposal.clone(),
-        dao: dao_params.clone(),
+        dao: dao.clone(),
     };
     let (params, proofs) = builder.build(
         &dao_th.dao_vote_burn_zkbin,
@@ -610,7 +591,7 @@ async fn integration_test() -> Result<()> {
         },
         vote_keypair: vote_keypair_2,
         proposal: proposal.clone(),
-        dao: dao_params.clone(),
+        dao: dao.clone(),
     };
     let (params, proofs) = builder.build(
         &dao_th.dao_vote_burn_zkbin,
@@ -678,7 +659,7 @@ async fn integration_test() -> Result<()> {
         },
         vote_keypair: vote_keypair_3,
         proposal: proposal.clone(),
-        dao: dao_params.clone(),
+        dao: dao.clone(),
     };
     let (params, proofs) = builder.build(
         &dao_th.dao_vote_burn_zkbin,
@@ -855,7 +836,7 @@ async fn integration_test() -> Result<()> {
 
     let builder = dao_exec_client::Builder {
         proposal,
-        dao: dao_params.clone(),
+        dao,
         yes_votes_value,
         all_votes_value,
         yes_votes_blind,