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

+ 6 - 8
src/contract/dao/src/dao_client.rs

@@ -26,6 +26,7 @@ use darkfi_sdk::{
         coin::Coin, constants::MERKLE_DEPTH, poseidon_hash, MerkleNode, PublicKey, SecretKey,
         TokenId,
     },
+    incrementalmerkletree,
     incrementalmerkletree::{bridgetree::BridgeTree, Tree},
     pasta::pallas,
 };
@@ -33,17 +34,15 @@ use halo2_proofs::circuit::Value;
 use log::debug;
 use rand::rngs::OsRng;
 
-use crate::{
-    note::EncryptedNote2,
-    state::{DaoBulla, DaoMintParams},
-};
+use darkfi_money_contract::client::{EncryptedNote, Note};
+
+use crate::state::{DaoBulla, DaoMintParams};
 
 pub type MerkleTree = BridgeTree<MerkleNode, { MERKLE_DEPTH }>;
 
-/*
 pub struct OwnCoin {
     pub coin: Coin,
-    pub note: money::transfer::wallet::Note,
+    pub note: Note,
     pub leaf_position: incrementalmerkletree::Position,
 }
 
@@ -83,7 +82,7 @@ impl WalletCache {
         panic!("you forget to track() this secret!");
     }
 
-    pub fn try_decrypt_note(&mut self, coin: Coin, ciphertext: &EncryptedNote2) {
+    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);
@@ -98,7 +97,6 @@ impl WalletCache {
         }
     }
 }
-*/
 
 struct DaoMintRevealed {
     pub bulla: DaoBulla,

+ 8 - 5
src/contract/dao/src/money_client.rs

@@ -258,13 +258,16 @@ impl Builder {
                 memo: Vec::new(),
             };
 
-            //let encrypted_note = note.encrypt(&output.public)?;
-            /*
-            let encrypted_note = note::encrypt(&note, &output.public)?;
+            let encrypted_note = note.encrypt(&output.public)?;
 
-            let output = Output { revealed, enc_note: encrypted_note };
+            let output = Output {
+                value_commit: revealed.value_commit,
+                token_commit: revealed.token_commit,
+                coin: revealed.coin.inner(),
+                ciphertext: encrypted_note.ciphertext,
+                ephem_public: encrypted_note.ephem_public,
+            };
             outputs.push(output);
-            */
         }
 
         Ok((MoneyTransferParams { clear_inputs, inputs, outputs }, proofs))

+ 115 - 16
src/contract/dao/tests/integration.rs

@@ -18,22 +18,29 @@
 
 use darkfi::{tx::Transaction, Result};
 use darkfi_sdk::{
-    crypto::{constants::MERKLE_DEPTH, MerkleNode, TokenId},
+    crypto::{
+        coin::Coin, constants::MERKLE_DEPTH, contract_id::MONEY_CONTRACT_ID, poseidon_hash,
+        MerkleNode, TokenId,
+    },
     incrementalmerkletree::{bridgetree::BridgeTree, Tree},
-    pasta::{group::ff::Field, pallas},
+    pasta::{
+        arithmetic::CurveAffine,
+        group::{ff::Field, Curve},
+        pallas,
+    },
     tx::ContractCall,
 };
-use darkfi_serial::Encodable;
+use darkfi_serial::{Decodable, Encodable};
 use log::{debug, info};
 use rand::rngs::OsRng;
 
 use darkfi_dao_contract::{
-    dao_client::{build_dao_mint_tx, MerkleTree},
-    DaoFunction,
+    dao_client::{build_dao_mint_tx, MerkleTree, WalletCache},
+    money_client, DaoFunction,
 };
 
 use darkfi_money_contract::{
-    client::{build_half_swap_tx, build_transfer_tx, Coin, EncryptedNote, OwnCoin},
+    client::{build_half_swap_tx, build_transfer_tx, EncryptedNote, OwnCoin},
     state::MoneyTransferParams,
     MoneyFunction,
 };
@@ -57,11 +64,12 @@ use money_harness::{init_logger, MoneyTestHarness};
 async fn integration_test() -> Result<()> {
     init_logger()?;
 
-    let mut th = DaoTestHarness::new().await?;
+    let mut dao_th = DaoTestHarness::new().await?;
+    let mut money_th = MoneyTestHarness::new().await?;
 
     // Money parameters
     let xdrk_supply = 1_000_000;
-    let xrdk_token_id = TokenId::from(pallas::Base::random(&mut OsRng));
+    let xdrk_token_id = TokenId::from(pallas::Base::random(&mut OsRng));
 
     // Governance token parameters
     let gdrk_supply = 1_000_000;
@@ -73,6 +81,9 @@ async fn integration_test() -> Result<()> {
     let dao_approval_ratio_quot = 1;
     let dao_approval_ratio_base = 2;
 
+    // We use this to receive coins
+    let mut cache = WalletCache::new();
+
     // =======================================================
     // Dao::Mint
     //
@@ -91,11 +102,11 @@ async fn integration_test() -> Result<()> {
         dao_approval_ratio_quot,
         dao_approval_ratio_base,
         gdrk_token_id,
-        &th.dao_kp.public,
+        &dao_th.dao_kp.public,
         dao_bulla_blind,
-        &th.dao_kp.secret,
-        &th.dao_mint_zkbin,
-        &th.dao_mint_pk,
+        &dao_th.dao_kp.secret,
+        &dao_th.dao_mint_zkbin,
+        &dao_th.dao_mint_pk,
     )?;
 
     info!("[Alice] ==========================================");
@@ -103,7 +114,7 @@ async fn integration_test() -> Result<()> {
     info!("[Alice] ==========================================");
     let mut data = vec![DaoFunction::Mint as u8];
     params.encode(&mut data)?;
-    let calls = vec![ContractCall { contract_id: th.dao_contract_id, data }];
+    let calls = vec![ContractCall { contract_id: dao_th.dao_contract_id, data }];
     let proofs = vec![proofs];
     let mut tx = Transaction { calls, proofs, signatures: vec![] };
     let sigs = tx.create_sigs(&mut OsRng, &[])?;
@@ -112,7 +123,7 @@ async fn integration_test() -> Result<()> {
     info!("[Alice] ===============================");
     info!("[Alice] Executing Dao::Mint transaction");
     info!("[Alice] ===============================");
-    th.alice_state.read().await.verify_transactions(&[tx.clone()], true).await?;
+    dao_th.alice_state.read().await.verify_transactions(&[tx.clone()], true).await?;
     // TODO: Witness and add to wallet merkle tree?
 
     let mut dao_tree = MerkleTree::new(100);
@@ -121,7 +132,8 @@ async fn integration_test() -> Result<()> {
         dao_tree.append(&node);
         dao_tree.witness().unwrap()
     };
-    debug!(target: "demo", "Created DAO bulla: {:?}", params.dao_bulla.inner());
+    let dao_bulla = params.dao_bulla;
+    debug!(target: "demo", "Created DAO bulla: {:?}", dao_bulla.inner());
 
     // =======================================================
     // Money::Transfer
@@ -131,11 +143,98 @@ async fn integration_test() -> Result<()> {
     // =======================================================
     debug!(target: "demo", "Stage 2. Minting treasury token");
 
+    cache.track(dao_th.dao_kp.secret);
+
     // We use this to receive coins
     //let mut cache = WalletCache::new();
 
-    let mut th = MoneyTestHarness::new().await?;
     //let (params, proofs) = builder.build(&zk_bins)?;
+    // TODO: this should be the contract/func ID
+    let spend_hook = pallas::Base::from(110);
+    let user_data = dao_bulla.inner();
+
+    let builder = money_client::Builder {
+        clear_inputs: vec![money_client::BuilderClearInputInfo {
+            value: xdrk_supply,
+            token_id: xdrk_token_id,
+            signature_secret: money_th.faucet_kp.secret,
+        }],
+        inputs: vec![],
+        outputs: vec![money_client::BuilderOutputInfo {
+            value: xdrk_supply,
+            token_id: xdrk_token_id,
+            public: dao_th.dao_kp.public,
+            serial: pallas::Base::random(&mut OsRng),
+            coin_blind: pallas::Base::random(&mut OsRng),
+            spend_hook,
+            user_data,
+        }],
+    };
+    let (params, proofs) = builder.build(
+        &money_th.mint_zkbin,
+        &money_th.mint_pk,
+        &money_th.burn_zkbin,
+        &money_th.burn_pk,
+    )?;
+
+    let contract_id = *MONEY_CONTRACT_ID;
+
+    let mut data = vec![MoneyFunction::Transfer as u8];
+    params.encode(&mut data)?;
+    let calls = vec![ContractCall { contract_id, data }];
+    let proofs = vec![proofs];
+    let mut tx = Transaction { calls, proofs, signatures: vec![] };
+    let sigs = tx.create_sigs(&mut OsRng, &vec![money_th.faucet_kp.secret])?;
+    tx.signatures = vec![sigs];
+
+    money_th.faucet_state.read().await.verify_transactions(&[tx.clone()], true).await?;
+    money_th.faucet_merkle_tree.append(&MerkleNode::from(params.outputs[0].coin));
+
+    // Wallet stuff
+
+    // DAO reads the money received from the encrypted note
+    {
+        assert_eq!(tx.calls.len(), 1);
+        let calldata = &tx.calls[0].data;
+        let params_data = &calldata[1..];
+        let params: MoneyTransferParams = Decodable::decode(params_data)?;
+
+        for output in params.outputs {
+            let coin = output.coin;
+            let enc_note =
+                EncryptedNote { ciphertext: output.ciphertext, ephem_public: output.ephem_public };
+
+            let coin = Coin(coin);
+            cache.try_decrypt_note(coin, &enc_note);
+        }
+    }
+
+    let mut recv_coins = cache.get_received(&dao_th.dao_kp.secret);
+    assert_eq!(recv_coins.len(), 1);
+    let dao_recv_coin = recv_coins.pop().unwrap();
+    let treasury_note = dao_recv_coin.note;
+
+    // Check the actual coin received is valid before accepting it
+
+    let coords = dao_th.dao_kp.public.inner().to_affine().coordinates().unwrap();
+    let coin = poseidon_hash::<8>([
+        *coords.x(),
+        *coords.y(),
+        pallas::Base::from(treasury_note.value),
+        treasury_note.token_id.inner(),
+        treasury_note.serial,
+        treasury_note.spend_hook,
+        treasury_note.user_data,
+        treasury_note.coin_blind,
+    ]);
+    assert_eq!(coin, dao_recv_coin.coin.0);
+
+    assert_eq!(treasury_note.spend_hook, spend_hook);
+    assert_eq!(treasury_note.user_data, dao_bulla.inner());
+
+    debug!("DAO received a coin worth {} xDRK", treasury_note.value);
+
+    ///////////////////////////////////////////////////
 
     Ok(())
 }

+ 1 - 0
src/contract/dao/tests/money_harness.rs

@@ -0,0 +1 @@
+../../money/tests/harness.rs

+ 1 - 1
src/contract/money/src/client.rs

@@ -98,7 +98,7 @@ pub const AEAD_TAG_SIZE: usize = 16;
 
 /// The `Coin` is represented as a base field element.
 #[derive(Debug, Clone, Copy, Eq, PartialEq, SerialEncodable, SerialDecodable)]
-pub struct Coin(pallas::Base);
+pub struct Coin(pub pallas::Base);
 
 impl Coin {
     /// Reference the raw inner base field element

+ 1 - 1
src/sdk/src/crypto/coin.rs

@@ -25,7 +25,7 @@ use pasta_curves::{group::ff::PrimeField, pallas};
 /// The `Coin` is represented as a base field element.
 #[repr(C)]
 #[derive(Debug, Clone, Copy, Eq, PartialEq, SerialEncodable, SerialDecodable)]
-pub struct Coin(pallas::Base);
+pub struct Coin(pub pallas::Base);
 
 impl Coin {
     /// Reference the raw inner base field element