Prechádzať zdrojové kódy

contract/test-harness: Add a generate_block() function.

This is supposed to be used whenever we want a Holder to produce
a block and receive the mining reward.

As part of the integration test, it will test PoWReward functionality.
parazyd 2 rokov pred
rodič
commit
09e7475d58

+ 1 - 0
.gitignore

@@ -5,6 +5,7 @@
 *.wasm
 *.zk.bin
 
+witness.json
 *_circuit_layout.png
 
 /bin/zkas/zkas

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

@@ -61,7 +61,7 @@ impl TokenFreezeCallBuilder {
         let token_id = self.token_attrs.to_token_id();
 
         let public_inputs = vec![mint_pubkey.x(), mint_pubkey.y(), token_id.inner()];
-        darkfi::zk::export_witness_json("witness.json", &prover_witnesses, &public_inputs);
+        //darkfi::zk::export_witness_json("witness.json", &prover_witnesses, &public_inputs);
 
         let circuit = ZkCircuit::new(prover_witnesses, &self.freeze_zkbin);
         let proof = Proof::create(&self.freeze_pk, &[circuit], &public_inputs, &mut OsRng)?;

+ 3 - 42
src/contract/money/tests/integration.rs

@@ -18,7 +18,6 @@
 
 use darkfi::Result;
 use darkfi_contract_test_harness::{init_logger, Holder, TestHarness};
-use darkfi_sdk::blockchain::expected_reward;
 use log::info;
 
 #[test]
@@ -32,50 +31,12 @@ fn money_integration() -> Result<()> {
         // Initialize harness
         let mut th = TestHarness::new(&HOLDERS, true).await?;
 
+        // Generate a new block mined by Alice
+        th.generate_block(&Holder::Alice, &HOLDERS).await?;
+
         // Block height to verify against
         let current_block_height = 1;
 
-        // Drop some money to Alice
-        info!("[Alice] Building block proposal");
-        let (alice_proposal_tx, alice_proposal_params) =
-            th.pow_reward(&Holder::Alice, None, None).await?;
-
-        for holder in HOLDERS {
-            info!("[{holder:?}] Executing Alice's block proposal");
-            th.execute_pow_reward_tx(
-                &holder,
-                &alice_proposal_tx,
-                &alice_proposal_params,
-                current_block_height,
-            )
-            .await?;
-        }
-
-        let alice_owncoins = th.holders.get(&Holder::Alice).unwrap().unspent_money_coins.clone();
-        assert!(alice_owncoins[0].note.value == expected_reward(current_block_height));
-
-        th.assert_trees(&HOLDERS);
-
-        // And some to Bob
-        info!("[Bob] Building block proposal");
-        let (bob_proposal_tx, bob_proposal_params) =
-            th.pow_reward(&Holder::Bob, None, None).await?;
-
-        for holder in HOLDERS {
-            info!("[{holder:?}] Executing Alice's block proposal");
-            th.execute_pow_reward_tx(
-                &holder,
-                &bob_proposal_tx,
-                &bob_proposal_params,
-                current_block_height,
-            )
-            .await?;
-        }
-
-        th.assert_trees(&HOLDERS);
-
-        // Alice sends a payment of some DRK to Bob.
-
         // Thanks for reading
         Ok(())
     })

+ 58 - 23
src/contract/test-harness/src/money_pow_reward.rs

@@ -17,6 +17,7 @@
  */
 
 use darkfi::{
+    blockchain::{BlockInfo, Header},
     tx::{ContractCallLeaf, Transaction, TransactionBuilder},
     zk::halo2::Field,
     Result,
@@ -32,6 +33,7 @@ use darkfi_sdk::{
     ContractCall,
 };
 use darkfi_serial::AsyncEncodable;
+use log::info;
 use rand::rngs::OsRng;
 
 use super::{Holder, TestHarness};
@@ -41,7 +43,7 @@ impl TestHarness {
     ///
     /// Optionally takes a specific reward recipient and a nonstandard reward value.
     /// Returns the created [`Transaction`] and [`MoneyPoWRewardParamsV1`].
-    pub async fn pow_reward(
+    async fn pow_reward(
         &mut self,
         holder: &Holder,
         recipient: Option<&Holder>,
@@ -94,34 +96,67 @@ impl TestHarness {
         Ok((tx, debris.params))
     }
 
-    /// Execute the transaction created by `pow_reward()` for a given [`Holder`].
+    /// Generate and add an empty block to the given [`Holder`]s blockchains.
+    /// The `miner` holder will produce the block and receive the reward.
     ///
-    /// Returns any gathered [`OwnCoin`]s from the transaction.
-    pub async fn execute_pow_reward_tx(
+    /// Returns any found [`OwnCoin`]s.
+    pub async fn generate_block(
         &mut self,
-        holder: &Holder,
-        tx: &Transaction,
-        params: &MoneyPoWRewardParamsV1,
-        block_height: u64,
+        miner: &Holder,
+        holders: &[Holder],
     ) -> Result<Vec<OwnCoin>> {
-        let wallet = self.holders.get_mut(holder).unwrap();
+        // Build the POW reward transaction
+        info!("Building PoWReward transaction for {:?}", miner);
+        let (tx, params) = self.pow_reward(miner, None, None).await?;
 
-        wallet.validator.add_test_producer_transaction(tx, block_height, true).await?;
-        wallet.money_merkle_tree.append(MerkleNode::from(params.output.coin.inner()));
+        // Fetch the last block in the blockchain
+        let wallet = self.holders.get(miner).unwrap();
+        let previous = wallet.validator.blockchain.last_block()?;
 
-        // Attempt to decrypt the output note to see if this is a coin for the holder.
-        let Ok(note) = params.output.note.decrypt::<MoneyNote>(&wallet.keypair.secret) else {
-            return Ok(vec![])
-        };
+        // We increment timestamp so we don't have to use sleep
+        let mut timestamp = previous.header.timestamp;
+        timestamp.add(1);
 
-        let owncoin = OwnCoin {
-            coin: params.output.coin,
-            note: note.clone(),
-            secret: wallet.keypair.secret,
-            leaf_position: wallet.money_merkle_tree.mark().unwrap(),
-        };
+        // Generate block header
+        let header = Header::new(
+            previous.hash()?,
+            previous.header.height + 1,
+            timestamp,
+            previous.header.nonce,
+        );
+
+        // Generate the block
+        let mut block = BlockInfo::new_empty(header);
+
+        // Add producer transaction to the block
+        block.append_txs(vec![tx])?;
+
+        // Attach signature
+        block.sign(&wallet.keypair.secret)?;
+
+        // For all holders, append the block
+        let mut found_owncoins = vec![];
+        for holder in holders {
+            let wallet = self.holders.get_mut(holder).unwrap();
+            wallet.validator.add_blocks(&[block.clone()]).await?;
+            wallet.money_merkle_tree.append(MerkleNode::from(params.output.coin.inner()));
+
+            // Attempt to decrypt the note to see if this is a coin for the holder
+            let Ok(note) = params.output.note.decrypt::<MoneyNote>(&wallet.keypair.secret) else {
+                continue
+            };
+
+            let owncoin = OwnCoin {
+                coin: params.output.coin,
+                note: note.clone(),
+                secret: wallet.keypair.secret,
+                leaf_position: wallet.money_merkle_tree.mark().unwrap(),
+            };
+
+            wallet.unspent_money_coins.push(owncoin.clone());
+            found_owncoins.push(owncoin);
+        }
 
-        wallet.unspent_money_coins.push(owncoin.clone());
-        Ok(vec![owncoin])
+        Ok(found_owncoins)
     }
 }