mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-04-28 03:00:18 -04:00
split WalletCache into its own module
This commit is contained in:
@@ -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,
|
||||
}
|
||||
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");
|
||||
|
||||
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_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);
|
||||
|
||||
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,
|
||||
]);
|
||||
let (pub_x, pub_y) = dao.public_key.xy();
|
||||
|
||||
Self { bulla: DaoBulla::from(dao_bulla) }
|
||||
}
|
||||
|
||||
pub fn to_vec(&self) -> Vec<pallas::Base> {
|
||||
vec![self.bulla.inner()]
|
||||
}
|
||||
}
|
||||
|
||||
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)?;
|
||||
let public = vec![dao_bulla];
|
||||
|
||||
Ok((proof, revealed))
|
||||
}
|
||||
let circuit = ZkCircuit::new(prover_witnesses, dao_mint_zkbin.clone());
|
||||
let proof = Proof::create(dao_mint_pk, &[circuit], &public, &mut OsRng)?;
|
||||
|
||||
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 (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 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]))
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user