Quellcode durchsuchen

money: test burned fees excluded from reward

brid vor 1 Woche
Ursprung
Commit
1dfd8b94a0

+ 55 - 0
src/contract/money/tests/integration.rs

@@ -60,3 +60,58 @@ fn money_integration() -> Result<()> {
         Ok(())
     })
 }
+
+#[test]
+fn money_fee_burn_is_excluded_from_reward() -> Result<()> {
+    smol::block_on(async {
+        init_logger();
+
+        use Holder::{Alice, Bob};
+
+        let mut th = TestHarness::new(&[Alice, Bob], true).await?;
+
+        th.generate_block_all(&Alice).await?;
+        th.generate_block_all(&Alice).await?;
+
+        let block_height = 3;
+        let native_token = th.coins(&Alice)[0].note.token_id;
+        let owncoins = vec![th.coins_by_token(&Alice, native_token)[0].clone()];
+        let transfer_amount = 100_000_000;
+        let (tx, _, _) = th
+            .transfer(transfer_amount, &Alice, &Bob, &owncoins, native_token, block_height, false)
+            .await?;
+
+        let paid_fee = tx
+            .calls
+            .iter()
+            .find(|call| call.data.is_money_fee())
+            .unwrap()
+            .data
+            .money_fee_value()
+            .unwrap();
+
+        let validator = th.wallet(&Alice).validator().read().await;
+        let (_, miner_claimable_fee) = validator
+            .add_test_transactions(
+                std::slice::from_ref(&tx),
+                block_height,
+                validator.consensus.module.target,
+                false,
+                true,
+            )
+            .await?;
+        drop(validator);
+
+        assert!(miner_claimable_fee < paid_fee);
+
+        let reward_coins = th
+            .generate_block_with_txs(&Alice, &[Alice, Bob], vec![tx], miner_claimable_fee)
+            .await?;
+
+        assert_eq!(reward_coins.len(), 1);
+        assert_eq!(reward_coins[0].note.value, expected_reward(block_height) + miner_claimable_fee);
+        assert_ne!(reward_coins[0].note.value, expected_reward(block_height) + paid_fee);
+
+        Ok(())
+    })
+}

+ 69 - 1
src/contract/test-harness/src/money_pow_reward.rs

@@ -21,7 +21,9 @@ use std::slice;
 use darkfi::{
     blockchain::{BlockInfo, BlockchainOverlay, Header},
     tx::{ContractCallLeaf, Transaction, TransactionBuilder},
-    validator::verification::apply_producer_transaction,
+    validator::verification::{
+        apply_producer_transaction, verify_producer_transaction, verify_transactions,
+    },
     Result,
 };
 use darkfi_money_contract::{
@@ -157,4 +159,70 @@ impl TestHarness {
 
         Ok(found_owncoins)
     }
+
+    /// Generate and add a block containing non-producer transactions.
+    ///
+    /// The caller must provide the block's accumulated miner-claimable fees.
+    /// Returns any found miner reward [`OwnCoin`]s.
+    pub async fn generate_block_with_txs(
+        &mut self,
+        miner: &Holder,
+        holders: &[Holder],
+        txs: Vec<Transaction>,
+        fees: u64,
+    ) -> Result<Vec<OwnCoin>> {
+        info!("Building PoWReward transaction for {miner:?}");
+        let (producer_tx, params) = self.pow_reward(miner, None, None, Some(fees)).await?;
+
+        let wallet = self.wallet(miner);
+        let validator = wallet.validator.read().await;
+        let previous = validator.blockchain.last_block()?;
+        let timestamp = previous.header.timestamp.checked_add(1.into())?;
+
+        let header = Header::new(
+            previous.hash(),
+            previous.header.height + 1,
+            previous.header.nonce,
+            timestamp,
+        );
+        let mut block = BlockInfo::new_empty(header);
+
+        block.append_txs(txs);
+        block.append_txs(vec![producer_tx]);
+
+        let overlay = BlockchainOverlay::new(&validator.blockchain)?;
+        let mut tree = MerkleTree::new(1);
+        let non_producer_txs = &block.txs[..block.txs.len() - 1];
+        verify_transactions(
+            &overlay,
+            block.header.height,
+            validator.consensus.module.target,
+            non_producer_txs,
+            &mut tree,
+            validator.verify_fees,
+        )
+        .await?;
+        verify_producer_transaction(
+            &overlay,
+            block.header.height,
+            validator.consensus.module.target,
+            block.txs.last().unwrap(),
+            &mut tree,
+        )
+        .await?;
+        drop(validator);
+
+        let diff = overlay.lock().unwrap().overlay.lock().unwrap().diff(&[])?;
+        block.header.state_root = overlay.lock().unwrap().contracts.update_state_monotree(&diff)?;
+        block.sign(&wallet.keypair.secret);
+
+        let mut found_owncoins = vec![];
+        for holder in holders {
+            let wallet = self.wallet_mut(holder);
+            wallet.validator.write().await.add_test_blocks(&[block.clone()]).await?;
+            found_owncoins.extend(wallet.process_outputs(slice::from_ref(&params.output), holder));
+        }
+
+        Ok(found_owncoins)
+    }
 }