Explorar o código

contract/deployooor/tests/integration: fully test all contract logic

skoupidi hai 9 meses
pai
achega
2e60e3ca3b

+ 69 - 2
src/contract/deployooor/tests/integration.rs

@@ -34,11 +34,11 @@ fn deploy_integration() -> Result<()> {
         // WASM bincode to deploy
         let wasm_bincode = include_bytes!("../../dao/darkfi_dao_contract.wasm");
 
-        info!("[Alice] Building deploy tx");
+        info!(target: "deploy", "[Alice] Building deploy tx");
         let (deploy_tx, deploy_params, fee_params) =
             th.deploy_contract(&Holder::Alice, wasm_bincode.to_vec(), current_block_height).await?;
 
-        info!("[Alice] Executing deploy tx");
+        info!(target: "deploy", "[Alice] Executing deploy tx");
         th.execute_deploy_tx(
             &Holder::Alice,
             deploy_tx,
@@ -49,6 +49,73 @@ fn deploy_integration() -> Result<()> {
         )
         .await?;
 
+        // WASM bincode to deploy as a replacement
+        let wasm_bincode = include_bytes!("../../money/darkfi_money_contract.wasm");
+
+        info!(target: "deploy", "[Alice] Building deploy replacement tx");
+        let (deploy_tx, deploy_params, fee_params) =
+            th.deploy_contract(&Holder::Alice, wasm_bincode.to_vec(), current_block_height).await?;
+
+        info!(target: "deploy", "[Alice] Executing deploy replacement tx");
+        th.execute_deploy_tx(
+            &Holder::Alice,
+            deploy_tx,
+            &deploy_params,
+            &fee_params,
+            current_block_height,
+            true,
+        )
+        .await?;
+
+        info!(target: "deploy", "[Alice] Building deploy lock tx");
+        let (lock_tx, lock_params, fee_params) =
+            th.lock_contract(&Holder::Alice, current_block_height).await?;
+
+        info!(target: "deploy", "[Alice] Executing deploy lock tx");
+        th.execute_lock_tx(
+            &Holder::Alice,
+            lock_tx,
+            &lock_params,
+            &fee_params,
+            current_block_height,
+            true,
+        )
+        .await?;
+
+        info!(target: "deploy", "[Malicious] ===============================");
+        info!(target: "deploy", "[Malicious] Checking locking contract again");
+        info!(target: "deploy", "[Malicious] ===============================");
+        let (lock_tx, lock_params, fee_params) =
+            th.lock_contract(&Holder::Alice, current_block_height).await?;
+        assert!(th
+            .execute_lock_tx(
+                &Holder::Alice,
+                lock_tx,
+                &lock_params,
+                &fee_params,
+                current_block_height,
+                true,
+            )
+            .await
+            .is_err());
+
+        info!(target: "deploy", "[Malicious] ====================================");
+        info!(target: "deploy", "[Malicious] Checking deploy on a locked contract");
+        info!(target: "deploy", "[Malicious] ====================================");
+        let (deploy_tx, deploy_params, fee_params) =
+            th.deploy_contract(&Holder::Alice, wasm_bincode.to_vec(), current_block_height).await?;
+        assert!(th
+            .execute_deploy_tx(
+                &Holder::Alice,
+                deploy_tx,
+                &deploy_params,
+                &fee_params,
+                current_block_height,
+                true,
+            )
+            .await
+            .is_err());
+
         // Thanks for reading
         Ok(())
     })

+ 152 - 0
src/contract/test-harness/src/contract_lock.rs

@@ -0,0 +1,152 @@
+/* This file is part of DarkFi (https://dark.fi)
+ *
+ * Copyright (C) 2020-2025 Dyne.org foundation
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+use darkfi::{
+    tx::{ContractCallLeaf, Transaction, TransactionBuilder},
+    Result,
+};
+use darkfi_deployooor_contract::{
+    client::lock_v1::LockCallBuilder, model::LockParamsV1, DeployFunction,
+};
+use darkfi_money_contract::{
+    client::{MoneyNote, OwnCoin},
+    model::MoneyFeeParamsV1,
+};
+use darkfi_sdk::{
+    crypto::{contract_id::DEPLOYOOOR_CONTRACT_ID, MerkleNode},
+    //deploy::LockParamsV1,
+    ContractCall,
+};
+use darkfi_serial::AsyncEncodable;
+use log::debug;
+
+use super::{Holder, TestHarness};
+
+impl TestHarness {
+    /// Create a `Deployooor::Lock` transaction with the given WASM bincode.
+    ///
+    /// Returns the [`Transaction`], and necessary parameters.
+    pub async fn lock_contract(
+        &mut self,
+        holder: &Holder,
+        block_height: u32,
+    ) -> Result<(Transaction, LockParamsV1, Option<MoneyFeeParamsV1>)> {
+        let wallet = self.holders.get(holder).unwrap();
+        let deploy_keypair = wallet.contract_deploy_authority;
+
+        // Build the contract call
+        let builder = LockCallBuilder { deploy_keypair };
+        let debris = builder.build()?;
+
+        // Encode the call
+        let mut data = vec![DeployFunction::LockV1 as u8];
+        debris.params.encode_async(&mut data).await?;
+        let call = ContractCall { contract_id: *DEPLOYOOOR_CONTRACT_ID, data };
+        let mut tx_builder =
+            TransactionBuilder::new(ContractCallLeaf { call, proofs: vec![] }, vec![])?;
+
+        // If we have tx fees enabled, make an offering
+        let mut fee_params = None;
+        let mut fee_signature_secrets = None;
+        if self.verify_fees {
+            let mut tx = tx_builder.build()?;
+            let sigs = tx.create_sigs(&[deploy_keypair.secret])?;
+            tx.signatures = vec![sigs];
+
+            let (fee_call, fee_proofs, fee_secrets, _spent_fee_coins, fee_call_params) =
+                self.append_fee_call(holder, tx, block_height, &[]).await?;
+
+            // Append the fee call to the transaction
+            tx_builder.append(ContractCallLeaf { call: fee_call, proofs: fee_proofs }, vec![])?;
+            fee_signature_secrets = Some(fee_secrets);
+            fee_params = Some(fee_call_params);
+        }
+
+        // Now build the actual transaction and sign it with necessary keys.
+        let mut tx = tx_builder.build()?;
+        let sigs = tx.create_sigs(&[deploy_keypair.secret])?;
+        tx.signatures = vec![sigs];
+        if let Some(fee_signature_secrets) = fee_signature_secrets {
+            let sigs = tx.create_sigs(&fee_signature_secrets)?;
+            tx.signatures.push(sigs);
+        }
+
+        Ok((tx, debris.params, fee_params))
+    }
+
+    /// Execute the transaction created by `lock_contract()` for a given [`Holder`].
+    ///
+    /// Returns any found [`OwnCoin`]s.
+    pub async fn execute_lock_tx(
+        &mut self,
+        holder: &Holder,
+        tx: Transaction,
+        _params: &LockParamsV1,
+        fee_params: &Option<MoneyFeeParamsV1>,
+        block_height: u32,
+        append: bool,
+    ) -> Result<Vec<OwnCoin>> {
+        let wallet = self.holders.get_mut(holder).unwrap();
+
+        // Execute the transaction
+        wallet.add_transaction("deploy::lock", tx, block_height).await?;
+
+        if !append {
+            return Ok(vec![])
+        }
+
+        if let Some(ref fee_params) = fee_params {
+            let nullifier = fee_params.input.nullifier.inner();
+            wallet
+                .money_null_smt
+                .insert_batch(vec![(nullifier, nullifier)])
+                .expect("smt.insert_batch()");
+
+            if let Some(spent_coin) = wallet
+                .unspent_money_coins
+                .iter()
+                .find(|x| x.nullifier() == fee_params.input.nullifier)
+                .cloned()
+            {
+                debug!("Found spent OwnCoin({}) for {:?}", spent_coin.coin, holder);
+                wallet.unspent_money_coins.retain(|x| x.nullifier() != fee_params.input.nullifier);
+                wallet.spent_money_coins.push(spent_coin.clone());
+            }
+
+            wallet.money_merkle_tree.append(MerkleNode::from(fee_params.output.coin.inner()));
+
+            let Ok(note) = fee_params.output.note.decrypt::<MoneyNote>(&wallet.keypair.secret)
+            else {
+                return Ok(vec![])
+            };
+
+            let owncoin = OwnCoin {
+                coin: fee_params.output.coin,
+                note: note.clone(),
+                secret: wallet.keypair.secret,
+                leaf_position: wallet.money_merkle_tree.mark().unwrap(),
+            };
+
+            debug!("Found new OwnCoin({}) for {:?}", owncoin.coin, holder);
+            wallet.unspent_money_coins.push(owncoin.clone());
+            return Ok(vec![owncoin])
+        }
+
+        Ok(vec![])
+    }
+}

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

@@ -70,6 +70,9 @@ mod money_otc_swap;
 /// `Deployooor::Deploy` functionality
 mod contract_deploy;
 
+/// `Deployooor::Lock` functionality
+mod contract_lock;
+
 /// `Dao::Mint` functionality
 mod dao_mint;
 

+ 0 - 1
tests/network_transports.rs

@@ -26,7 +26,6 @@ use darkfi::net::transport::{Dialer, Listener};
 fn tcp_transport() {
     let executor = LocalExecutor::new();
 
-
     smol::block_on(executor.run(async {
         let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
         let port = listener.local_addr().unwrap().port();