|
|
@@ -18,6 +18,7 @@
|
|
|
|
|
|
use darkfi::{
|
|
|
tx::{ContractCallLeaf, Transaction, TransactionBuilder},
|
|
|
+ validator::consensus::Fork,
|
|
|
Result,
|
|
|
};
|
|
|
use darkfi_contract_test_harness::{init_logger, Holder, TestHarness};
|
|
|
@@ -146,8 +147,7 @@ async fn converge_fee_tx(
|
|
|
let mut burned_fee = 0;
|
|
|
|
|
|
for _ in 0..64 {
|
|
|
- let (tx, params, fee_params) =
|
|
|
- fee_tx(th, from, to, coin, paid_fee, burned_fee).await?;
|
|
|
+ let (tx, params, fee_params) = fee_tx(th, from, to, coin, paid_fee, burned_fee).await?;
|
|
|
let required = measure_required_fee(th, from, &tx, block_height).await?;
|
|
|
let mandatory = burn_fee(required)?;
|
|
|
|
|
|
@@ -182,6 +182,61 @@ async fn execute_on_all(
|
|
|
Ok(())
|
|
|
}
|
|
|
|
|
|
+/// Confirm the mempool reward claim matches the fee accumulator:
|
|
|
+/// `unproposed_txs` must report the miner-claimable fees (`paid -
|
|
|
+/// burned`) that `Money::FeeV1` accumulates for the height, since the
|
|
|
+/// block template's `PoWRewardV1` claim is checked against exactly
|
|
|
+/// that value.
|
|
|
+#[test]
|
|
|
+fn fees_reward_claim() -> Result<()> {
|
|
|
+ smol::block_on(async {
|
|
|
+ init_logger();
|
|
|
+
|
|
|
+ use Holder::{Alice, Bob};
|
|
|
+
|
|
|
+ let mut th = TestHarness::new(&[Alice, Bob], true).await?;
|
|
|
+
|
|
|
+ // Alice mines two blocks so she holds coins to pay fees with
|
|
|
+ th.generate_block_all(&Alice).await?;
|
|
|
+ th.generate_block_all(&Alice).await?;
|
|
|
+ let height = 3;
|
|
|
+
|
|
|
+ // Build a fee-paying transaction and read back its declared
|
|
|
+ // public fee values
|
|
|
+ let coin = th.coins(&Alice).last().unwrap().clone();
|
|
|
+ let (tx, _, _, paid, burned) =
|
|
|
+ converge_fee_tx(&mut th, &Alice, &Bob, &coin, height, 0, 0).await?;
|
|
|
+ let fee_values = tx
|
|
|
+ .calls
|
|
|
+ .iter()
|
|
|
+ .find(|call| call.data.is_money_fee())
|
|
|
+ .unwrap()
|
|
|
+ .data
|
|
|
+ .money_fee_values()?;
|
|
|
+ assert_eq!(fee_values.paid_fee, paid);
|
|
|
+ assert_eq!(fee_values.burned_fee, burned);
|
|
|
+
|
|
|
+ // Put it in the mempool without applying it to the chain, like
|
|
|
+ // the real node flow does
|
|
|
+ let validator = th.wallet(&Alice).validator.read().await;
|
|
|
+ validator.blockchain.transactions.insert_pending(std::slice::from_ref(&tx))?;
|
|
|
+ let blockchain = validator.blockchain.clone();
|
|
|
+ let module = validator.consensus.module.clone();
|
|
|
+ drop(validator);
|
|
|
+
|
|
|
+ // Retrieve unproposed transactions the way the block template
|
|
|
+ // does, and check the reported fees against the accumulator
|
|
|
+ let mut fork = Fork::new(blockchain, module).await?;
|
|
|
+ let (unproposed, _, fees) = fork.unproposed_txs(height, true).await?;
|
|
|
+
|
|
|
+ assert_eq!(unproposed.len(), 1);
|
|
|
+ assert_eq!(fees, paid - burned);
|
|
|
+
|
|
|
+ // Thanks for reading
|
|
|
+ Ok(())
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
#[test]
|
|
|
fn fees() -> Result<()> {
|
|
|
smol::block_on(async {
|
|
|
@@ -239,8 +294,9 @@ fn fees() -> Result<()> {
|
|
|
// 3. Over-declared burn is valid: only paid - burned is
|
|
|
// miner-claimable, the excess burn is not re-minted.
|
|
|
let coin = th.coins(&Alice).last().unwrap().clone();
|
|
|
- let (tx, params, fee_params, required, mandatory_burn) = converge_fee_tx(&mut th, &Alice, &Bob, &coin, height, TIP as i64, EXTRA_BURN as i64)
|
|
|
- .await?;
|
|
|
+ let (tx, params, fee_params, required, mandatory_burn) =
|
|
|
+ converge_fee_tx(&mut th, &Alice, &Bob, &coin, height, TIP as i64, EXTRA_BURN as i64)
|
|
|
+ .await?;
|
|
|
execute_on_all(&mut th, &holders, &tx, ¶ms, &fee_params, height).await?;
|
|
|
let inclusion_fee = required - mandatory_burn;
|
|
|
th.generate_block_with_fees(&Bob, &holders, inclusion_fee + TIP - EXTRA_BURN).await?;
|
|
|
@@ -280,8 +336,7 @@ fn fees() -> Result<()> {
|
|
|
.is_err());
|
|
|
|
|
|
// 7. Declaring burned_fee > paid_fee is rejected.
|
|
|
- let (tx, params, fee_params) =
|
|
|
- fee_tx(&mut th, &Alice, &Bob, &coin, 1000, 1001).await?;
|
|
|
+ let (tx, params, fee_params) = fee_tx(&mut th, &Alice, &Bob, &coin, 1000, 1001).await?;
|
|
|
assert!(th
|
|
|
.execute_transfer_tx(&Alice, tx, ¶ms, &fee_params, height, true)
|
|
|
.await
|