|
@@ -22,81 +22,14 @@ use darkfi::{
|
|
|
Result,
|
|
Result,
|
|
|
};
|
|
};
|
|
|
use darkfi_sdk::{
|
|
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,
|
|
pasta::pallas,
|
|
|
};
|
|
};
|
|
|
use halo2_proofs::circuit::Value;
|
|
use halo2_proofs::circuit::Value;
|
|
|
use log::debug;
|
|
use log::debug;
|
|
|
use rand::rngs::OsRng;
|
|
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)]
|
|
#[derive(Clone)]
|
|
|
pub struct Dao {
|
|
pub struct Dao {
|
|
@@ -109,63 +42,30 @@ pub struct Dao {
|
|
|
pub bulla_blind: pallas::Base,
|
|
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_proposer_limit,
|
|
|
dao_quorum,
|
|
dao_quorum,
|
|
|
dao_approval_ratio_quot,
|
|
dao_approval_ratio_quot,
|
|
|
dao_approval_ratio_base,
|
|
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.
|
|
// NOTE: It's important to keep these in the same order as the zkas code.
|
|
|
let prover_witnesses = vec![
|
|
let prover_witnesses = vec![
|
|
@@ -173,46 +73,18 @@ fn create_dao_mint_proof(
|
|
|
Witness::Base(Value::known(dao_quorum)),
|
|
Witness::Base(Value::known(dao_quorum)),
|
|
|
Witness::Base(Value::known(dao_approval_ratio_quot)),
|
|
Witness::Base(Value::known(dao_approval_ratio_quot)),
|
|
|
Witness::Base(Value::known(dao_approval_ratio_base)),
|
|
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_x)),
|
|
|
Witness::Base(Value::known(pub_y)),
|
|
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]))
|
|
Ok((dao_mint_params, vec![proof]))
|
|
|
}
|
|
}
|