Procházet zdrojové kódy

contract/dao: Integration test port

parazyd před 2 roky
rodič
revize
98521da0de

+ 180 - 124
src/contract/dao/tests/integration.rs

@@ -31,7 +31,7 @@ use darkfi_sdk::{
         pasta_prelude::*,
         pedersen_commitment_u64, poseidon_hash,
         util::{fp_mod_fv, fp_to_u64},
-        Blind, FuncId, FuncRef, DAO_CONTRACT_ID, MONEY_CONTRACT_ID,
+        BaseBlind, Blind, FuncId, FuncRef, DAO_CONTRACT_ID, MONEY_CONTRACT_ID,
     },
     pasta::pallas,
 };
@@ -44,26 +44,19 @@ fn integration_test() -> Result<()> {
         init_logger();
 
         // Holders this test will use:
-        // * Faucet airdrops DRK
         // * Alice, Bob, and Charlie are members of the DAO.
-        // * Rachel is the proposal recipient.
         // * Dao is the DAO wallet
-        const HOLDERS: [Holder; 6] = [
-            Holder::Faucet,
-            Holder::Alice,
-            Holder::Bob,
-            Holder::Charlie,
-            Holder::Rachel,
-            Holder::Dao,
-        ];
+        // * Rachel is the proposal recipient.
+        const HOLDERS: [Holder; 5] =
+            [Holder::Alice, Holder::Bob, Holder::Charlie, Holder::Dao, Holder::Rachel];
 
         // Initialize harness
-        let mut th = TestHarness::new(&["money".to_string(), "dao".to_string()], false).await?;
+        let mut th = TestHarness::new(&HOLDERS, false).await?;
 
         // We'll use the ALICE token as the DAO governance token
         let wallet = th.holders.get(&Holder::Alice).unwrap();
         let mint_authority = wallet.token_mint_authority;
-        let token_blind = wallet.token_blind;
+        let gov_token_blind = BaseBlind::random(&mut OsRng);
 
         let auth_func_id = FuncRef {
             contract_id: *MONEY_CONTRACT_ID,
@@ -73,7 +66,7 @@ fn integration_test() -> Result<()> {
         let token_attrs = TokenAttributes {
             auth_parent: auth_func_id,
             user_data: poseidon_hash([mint_authority.public.x(), mint_authority.public.y()]),
-            blind: token_blind,
+            blind: gov_token_blind,
         };
         let gov_token_id = token_attrs.to_token_id();
 
@@ -108,12 +101,20 @@ fn integration_test() -> Result<()> {
         info!("Stage 1. Creating DAO bulla");
 
         info!("[Dao] Building DAO mint tx");
-        let (dao_mint_tx, dao_mint_params) = th.dao_mint(&dao, &dao_keypair)?;
+        let (dao_mint_tx, dao_mint_params, fee_params) =
+            th.dao_mint(&Holder::Alice, &dao, &dao_keypair, current_block_height).await?;
 
         for holder in &HOLDERS {
             info!("[{holder:?}] Executing DAO Mint tx");
-            th.execute_dao_mint_tx(holder, &dao_mint_tx, &dao_mint_params, current_block_height)
-                .await?;
+            th.execute_dao_mint_tx(
+                holder,
+                dao_mint_tx.clone(),
+                &dao_mint_params,
+                &fee_params,
+                current_block_height,
+                true,
+            )
+            .await?;
         }
 
         th.assert_trees(&HOLDERS);
@@ -121,35 +122,37 @@ fn integration_test() -> Result<()> {
         // =======================================
         // Airdrop some treasury tokens to the DAO
         // =======================================
-        info!("Stage 2. Send Treasury token");
-
-        info!("[Faucet] Building DAO airdrop tx");
+        info!("[Dao] Building DAO airdrop tx");
         let spend_hook =
             FuncRef { contract_id: *DAO_CONTRACT_ID, func_code: DaoFunction::Exec as u8 }
                 .to_func_id();
 
-        let (airdrop_tx, airdrop_params) = th.airdrop_native(
-            DRK_TOKEN_SUPPLY,
-            &Holder::Dao,
-            Some(spend_hook),                        // spend_hook
-            Some(dao_mint_params.dao_bulla.inner()), // user_data
-        )?;
+        let (genesis_mint_tx, genesis_mint_params) = th
+            .genesis_mint(
+                &Holder::Dao,
+                DRK_TOKEN_SUPPLY,
+                Some(spend_hook),
+                Some(dao_mint_params.dao_bulla.inner()),
+            )
+            .await?;
 
         for holder in &HOLDERS {
-            info!("[{holder:?}] Executing DAO airdrop tx");
-            th.execute_airdrop_native_tx(
+            th.execute_genesis_mint_tx(
                 holder,
-                &airdrop_tx,
-                &airdrop_params,
+                genesis_mint_tx.clone(),
+                &genesis_mint_params,
                 current_block_height,
+                true,
             )
             .await?;
         }
 
         th.assert_trees(&HOLDERS);
 
-        // Gather the DAO owncoin
-        th.gather_owncoin_from_output(&Holder::Dao, &airdrop_params.outputs[0], None)?;
+        let _dao_tokens = &th.holders.get(&Holder::Dao).unwrap().unspent_money_coins;
+        assert!(_dao_tokens.len() == 1);
+        assert!(_dao_tokens[0].note.token_id == *DARK_TOKEN_ID);
+        assert!(_dao_tokens[0].note.value == DRK_TOKEN_SUPPLY);
 
         // ======================================
         // Mint the governance token to 3 holders
@@ -157,79 +160,106 @@ fn integration_test() -> Result<()> {
         info!("Stage 3. Minting governance token");
 
         info!("[Alice] Building governance token mint tx for Alice");
-        let (a_token_mint_tx, a_token_mint_params, a_auth_token_mint_params) =
-            th.token_mint(ALICE_GOV_SUPPLY, &Holder::Alice, &Holder::Alice, None, None)?;
+        let (a_token_mint_tx, a_token_mint_params, a_auth_token_mint_params, a_fee_params) = th
+            .token_mint(
+                ALICE_GOV_SUPPLY,
+                &Holder::Alice,
+                &Holder::Alice,
+                gov_token_blind,
+                None,
+                None,
+                current_block_height,
+            )
+            .await?;
 
         for holder in &HOLDERS {
             info!("[{holder:?}] Executing governance token mint tx for Alice");
             th.execute_token_mint_tx(
                 holder,
-                &a_token_mint_tx,
+                a_token_mint_tx.clone(),
                 &a_token_mint_params,
+                &a_auth_token_mint_params,
+                &a_fee_params,
                 current_block_height,
+                true,
             )
             .await?;
         }
 
         th.assert_trees(&HOLDERS);
 
-        // Gather owncoin
-        th.gather_owncoin(
-            &Holder::Alice,
-            &a_token_mint_params.coin,
-            &a_auth_token_mint_params.enc_note,
-            None,
-        )?;
+        let _alice_tokens = &th.holders.get(&Holder::Alice).unwrap().unspent_money_coins;
+        assert!(_alice_tokens.len() == 1);
+        assert!(_alice_tokens[0].note.token_id == gov_token_id);
+        assert!(_alice_tokens[0].note.value == ALICE_GOV_SUPPLY);
 
         info!("[Alice] Building governance token mint tx for Bob");
-        let (b_token_mint_tx, b_token_mint_params, b_auth_token_mint_params) =
-            th.token_mint(BOB_GOV_SUPPLY, &Holder::Alice, &Holder::Bob, None, None)?;
+        let (b_token_mint_tx, b_token_mint_params, b_auth_token_mint_params, b_fee_params) = th
+            .token_mint(
+                BOB_GOV_SUPPLY,
+                &Holder::Alice,
+                &Holder::Bob,
+                gov_token_blind,
+                None,
+                None,
+                current_block_height,
+            )
+            .await?;
 
         for holder in &HOLDERS {
             info!("[{holder:?}] Executing governance token mint tx for Bob");
             th.execute_token_mint_tx(
                 holder,
-                &b_token_mint_tx,
+                b_token_mint_tx.clone(),
                 &b_token_mint_params,
+                &b_auth_token_mint_params,
+                &b_fee_params,
                 current_block_height,
+                true,
             )
             .await?;
         }
 
         th.assert_trees(&HOLDERS);
 
-        // Gather owncoin
-        th.gather_owncoin(
-            &Holder::Bob,
-            &b_token_mint_params.coin,
-            &b_auth_token_mint_params.enc_note,
-            None,
-        )?;
+        let _bob_tokens = &th.holders.get(&Holder::Bob).unwrap().unspent_money_coins;
+        assert!(_bob_tokens.len() == 1);
+        assert!(_bob_tokens[0].note.token_id == gov_token_id);
+        assert!(_bob_tokens[0].note.value == BOB_GOV_SUPPLY);
 
         info!("[Alice] Building governance token mint tx for Charlie");
-        let (c_token_mint_tx, c_token_mint_params, c_auth_token_mint_params) =
-            th.token_mint(CHARLIE_GOV_SUPPLY, &Holder::Alice, &Holder::Charlie, None, None)?;
+        let (c_token_mint_tx, c_token_mint_params, c_auth_token_mint_params, c_fee_params) = th
+            .token_mint(
+                CHARLIE_GOV_SUPPLY,
+                &Holder::Alice,
+                &Holder::Charlie,
+                gov_token_blind,
+                None,
+                None,
+                current_block_height,
+            )
+            .await?;
 
         for holder in &HOLDERS {
             info!("[{holder:?}] Executing governance token mint tx for Charlie");
             th.execute_token_mint_tx(
                 holder,
-                &c_token_mint_tx,
+                c_token_mint_tx.clone(),
                 &c_token_mint_params,
+                &c_auth_token_mint_params,
+                &c_fee_params,
                 current_block_height,
+                true,
             )
             .await?;
         }
 
         th.assert_trees(&HOLDERS);
 
-        // Gather owncoin
-        th.gather_owncoin(
-            &Holder::Charlie,
-            &c_token_mint_params.coin,
-            &c_auth_token_mint_params.enc_note,
-            None,
-        )?;
+        let _charlie_tokens = &th.holders.get(&Holder::Charlie).unwrap().unspent_money_coins;
+        assert!(_charlie_tokens.len() == 1);
+        assert!(_charlie_tokens[0].note.token_id == gov_token_id);
+        assert!(_charlie_tokens[0].note.value == CHARLIE_GOV_SUPPLY);
 
         // ================
         // Dao::Propose
@@ -255,19 +285,28 @@ fn integration_test() -> Result<()> {
         // It's up to the auth module to decide what to do with it.
         let user_data = pallas::Base::ZERO;
 
-        let (propose_tx, propose_params, propose_info) = th.dao_propose(
-            &Holder::Alice,
-            &proposal_coinattrs,
-            user_data,
-            &dao,
-            &dao_mint_params.dao_bulla,
-            current_block_height,
-        )?;
+        let (propose_tx, (propose_params, fee_params), propose_info) = th
+            .dao_propose(
+                &Holder::Alice,
+                &proposal_coinattrs,
+                user_data,
+                &dao,
+                &dao_mint_params.dao_bulla,
+                current_block_height,
+            )
+            .await?;
 
         for holder in &HOLDERS {
             info!("[{holder:?}] Executing DAO proposal tx");
-            th.execute_dao_propose_tx(holder, &propose_tx, &propose_params, current_block_height)
-                .await?;
+            th.execute_dao_propose_tx(
+                holder,
+                propose_tx.clone(),
+                &propose_params,
+                &fee_params,
+                current_block_height,
+                true,
+            )
+            .await?;
         }
 
         th.assert_trees(&HOLDERS);
@@ -279,56 +318,75 @@ fn integration_test() -> Result<()> {
         info!("Stage 5. Start voting");
 
         info!("[Alice] Building vote tx (yes)");
-        let (alice_vote_tx, alice_vote_params) = th.dao_vote(
-            &Holder::Alice,
-            true,
-            &dao,
-            &dao_keypair,
-            &propose_info,
-            &propose_params.proposal_bulla,
-            current_block_height,
-        )?;
+        let (alice_vote_tx, alice_vote_params, alice_vote_fee_params) = th
+            .dao_vote(
+                &Holder::Alice,
+                true,
+                &dao,
+                &dao_keypair,
+                &propose_info,
+                &propose_params.proposal_bulla,
+                current_block_height,
+            )
+            .await?;
 
         info!("[Bob] Building vote tx (no)");
-        let (bob_vote_tx, bob_vote_params) = th.dao_vote(
-            &Holder::Bob,
-            false,
-            &dao,
-            &dao_keypair,
-            &propose_info,
-            &propose_params.proposal_bulla,
-            current_block_height,
-        )?;
+        let (bob_vote_tx, bob_vote_params, bob_vote_fee_params) = th
+            .dao_vote(
+                &Holder::Bob,
+                false,
+                &dao,
+                &dao_keypair,
+                &propose_info,
+                &propose_params.proposal_bulla,
+                current_block_height,
+            )
+            .await?;
 
         info!("[Charlie] Building vote tx (yes)");
-        let (charlie_vote_tx, charlie_vote_params) = th.dao_vote(
-            &Holder::Charlie,
-            true,
-            &dao,
-            &dao_keypair,
-            &propose_info,
-            &propose_params.proposal_bulla,
-            current_block_height,
-        )?;
+        let (charlie_vote_tx, charlie_vote_params, charlie_vote_fee_params) = th
+            .dao_vote(
+                &Holder::Charlie,
+                true,
+                &dao,
+                &dao_keypair,
+                &propose_info,
+                &propose_params.proposal_bulla,
+                current_block_height,
+            )
+            .await?;
 
         for holder in &HOLDERS {
             info!("[{holder:?}] Executing Alice vote tx");
             th.execute_dao_vote_tx(
                 holder,
-                &alice_vote_tx,
+                alice_vote_tx.clone(),
                 &alice_vote_params,
+                &alice_vote_fee_params,
                 current_block_height,
+                true,
             )
             .await?;
+
             info!("[{holder:?}] Executing Bob vote tx");
-            th.execute_dao_vote_tx(holder, &bob_vote_tx, &bob_vote_params, current_block_height)
-                .await?;
+            th.execute_dao_vote_tx(
+                holder,
+                bob_vote_tx.clone(),
+                &bob_vote_params,
+                &bob_vote_fee_params,
+                current_block_height,
+                true,
+            )
+            .await?;
+
             info!("[{holder:?}] Executing Charlie vote tx");
             th.execute_dao_vote_tx(
                 holder,
-                &charlie_vote_tx,
+                charlie_vote_tx.clone(),
                 &charlie_vote_params,
+                &charlie_vote_fee_params,
                 current_block_height,
+                true,
             )
             .await?;
         }
@@ -407,46 +465,44 @@ fn integration_test() -> Result<()> {
         info!("Stage 6. Execute the vote");
 
         info!("[Dao] Building Dao::Exec tx");
-        let (exec_tx, xfer_params, exec_params) = th.dao_exec(
-            &dao,
-            &dao_mint_params.dao_bulla,
-            &propose_info,
-            proposal_coinattrs,
-            total_yes_vote_value,
-            total_all_vote_value,
-            total_yes_vote_blind,
-            total_all_vote_blind,
-        )?;
+        let (exec_tx, xfer_params, exec_params, exec_fee_params) = th
+            .dao_exec(
+                &Holder::Alice,
+                &dao,
+                &dao_mint_params.dao_bulla,
+                &propose_info,
+                proposal_coinattrs,
+                total_yes_vote_value,
+                total_all_vote_value,
+                total_yes_vote_blind,
+                total_all_vote_blind,
+                current_block_height,
+            )
+            .await?;
 
         for holder in &HOLDERS {
             info!("[{holder:?}] Executing Dao::Exec tx");
             th.execute_dao_exec_tx(
                 holder,
-                &exec_tx,
+                exec_tx.clone(),
                 &xfer_params,
                 &exec_params,
+                &exec_fee_params,
                 current_block_height,
+                true,
             )
             .await?;
         }
 
         th.assert_trees(&HOLDERS);
 
-        // Gather the coins
-        th.gather_owncoin_from_output(&Holder::Rachel, &xfer_params.outputs[0], None)?;
-        th.gather_owncoin_from_output(&Holder::Dao, &xfer_params.outputs[1], None)?;
-
         let rachel_wallet = th.holders.get(&Holder::Rachel).unwrap();
         assert!(rachel_wallet.unspent_money_coins[0].note.value == PROPOSAL_AMOUNT);
         assert!(rachel_wallet.unspent_money_coins[0].note.token_id == drk_token_id);
 
-        // FIXME: The harness doesn't register that we spent the first coin on the proposal.
         let dao_wallet = th.holders.get(&Holder::Dao).unwrap();
-        assert!(dao_wallet.unspent_money_coins[1].note.value == DRK_TOKEN_SUPPLY - PROPOSAL_AMOUNT);
-        assert!(dao_wallet.unspent_money_coins[1].note.token_id == drk_token_id);
-
-        // Stats
-        th.statistics();
+        assert!(dao_wallet.unspent_money_coins[0].note.value == DRK_TOKEN_SUPPLY - PROPOSAL_AMOUNT);
+        assert!(dao_wallet.unspent_money_coins[0].note.token_id == drk_token_id);
 
         // Thanks for reading
         Ok(())

+ 1 - 0
src/contract/test-harness/src/lib.rs

@@ -101,6 +101,7 @@ pub enum Holder {
     Bob,
     Charlie,
     Dao,
+    Rachel,
 }
 
 /// Wallet instance for a single [`Holder`]

+ 4 - 2
src/contract/test-harness/src/money_genesis_mint.rs

@@ -45,6 +45,8 @@ impl TestHarness {
         &mut self,
         holder: &Holder,
         amount: u64,
+        spend_hook: Option<FuncId>,
+        user_data: Option<pallas::Base>,
     ) -> Result<(Transaction, MoneyGenesisMintParamsV1)> {
         let wallet = self.holders.get(holder).unwrap();
 
@@ -55,8 +57,8 @@ impl TestHarness {
         let builder = GenesisMintCallBuilder {
             keypair: wallet.keypair,
             amount,
-            spend_hook: FuncId::none(),
-            user_data: pallas::Base::ZERO,
+            spend_hook: spend_hook.unwrap_or(FuncId::none()),
+            user_data: user_data.unwrap_or(pallas::Base::ZERO),
             mint_zkbin: mint_zkbin.clone(),
             mint_pk: mint_pk.clone(),
         };

+ 1 - 1
src/contract/test-harness/src/money_token.rs

@@ -52,6 +52,7 @@ impl TestHarness {
         amount: u64,
         holder: &Holder,
         recipient: &Holder,
+        token_blind: BaseBlind,
         spend_hook: Option<FuncId>,
         user_data: Option<pallas::Base>,
         block_height: u64,
@@ -79,7 +80,6 @@ impl TestHarness {
         .to_func_id();
 
         let (mint_auth_x, mint_auth_y) = mint_authority.public.xy();
-        let token_blind = BaseBlind::random(&mut OsRng);
 
         let token_attrs = TokenAttributes {
             auth_parent: auth_func_id,