iuna

iuna

iuna - experimental devnet protocol
git clone https://getiuna.org/git/iuna.git
Log | Files | Refs | README | LICENSE

tests.rs (20055B)


      1 use std::collections::BTreeMap;
      2 
      3 use crate::{
      4     adapters::config_store::{DEFAULT_POW_MINING_WORKERS, MAX_POW_MINING_WORKERS},
      5     app::{GossipEnvelope, NodeConfig, NodeCore},
      6     domain::{
      7         FinalizerMode, GenesisBurn, Ledger, MICRO_IUNA, MINE_ACTIONS_PER_ANCHOR_LIMIT,
      8         MINE_FINALIZER_FEE, RECOVERY_BLOCK_DELAY_MS, Transaction, VDF_TARGET_BLOCK_MS, Wallet,
      9         run_vdf,
     10     },
     11 };
     12 
     13 #[test]
     14 fn same_height_verified_import_does_not_reset_auto_burn_guard() {
     15     let alice = Wallet::from_seed("same-height-import-alice");
     16     let mut allocations = BTreeMap::new();
     17     allocations.insert(alice.address().to_string(), MICRO_IUNA);
     18     let mut node = NodeCore::new(NodeConfig {
     19         wallet: alice,
     20         genesis_allocations: allocations,
     21         vdf_rounds: 10,
     22         burn_per_block: 1,
     23         burn_fee: 1,
     24         pow_mining_workers: 1,
     25         recovery_vdf_top_rank_percent: 100,
     26     });
     27 
     28     let first = node.prepare_automatic_mining(1);
     29     assert!(first.burned.is_some());
     30     assert_eq!(node.last_auto_burn_height, Some(0));
     31 
     32     let same_height_ledger = node.clone_ledger();
     33     assert!(!node.import_verified_ledger(same_height_ledger).unwrap());
     34     assert_eq!(node.last_auto_burn_height, Some(0));
     35 
     36     let second = node.prepare_automatic_mining(2);
     37     assert!(second.burned.is_none());
     38 }
     39 
     40 #[test]
     41 fn automatic_pow_mining_searches_bounded_nonce_batches_per_tip() {
     42     let wallet = Wallet::from_seed("automatic-pow-mining-wallet");
     43     let ledger = Ledger::new_with_genesis_burns(
     44         BTreeMap::from([(wallet.address().to_string(), 1)]),
     45         vec![GenesisBurn::new(wallet.address(), 1)],
     46         10,
     47     )
     48     .unwrap();
     49     let mut node = NodeCore::from_ledger(wallet.clone(), ledger, 0);
     50 
     51     let disabled = node.prepare_automatic_mining(1);
     52     assert!(disabled.pow_mined.is_none());
     53     assert_eq!(
     54         disabled.skipped_reason.as_deref(),
     55         Some("automatic mining is off")
     56     );
     57 
     58     node.set_pow_mining_enabled(true);
     59     let first = node.prepare_automatic_mining(2);
     60     assert!(node.ledger().pending_blinded_transactions().len() <= 1);
     61     let first = std::iter::once(first)
     62         .chain((3..10_000).map(|timestamp| node.prepare_automatic_mining(timestamp)))
     63         .find(|plan| plan.pow_mined.is_some())
     64         .expect("bounded PoW search should eventually find a proof");
     65     let first_mine = first.pow_mined.as_ref().expect("PoW should be queued");
     66     let Transaction::Mine {
     67         anchor,
     68         recipient,
     69         difficulty_bits,
     70         ..
     71     } = first_mine
     72     else {
     73         panic!("expected mine transaction");
     74     };
     75     assert_eq!(anchor, &node.chain().last().unwrap().hash);
     76     assert_eq!(recipient, wallet.address());
     77     assert_eq!(
     78         *difficulty_bits,
     79         node.ledger().current_mine_difficulty_bits()
     80     );
     81     let first_pending = node.ledger().pending().len();
     82     assert!(first_pending >= 1);
     83     assert!(node.ledger().pending_blinded_transactions().is_empty());
     84     assert!(node.drain_outbox().iter().any(|envelope| {
     85             matches!(envelope, GossipEnvelope::MineAction(tx) if tx.signature() == first_mine.signature())
     86         }));
     87     assert!(
     88         node.status()
     89             .mining
     90             .last_auto_pow_mine_status
     91             .as_deref()
     92             .unwrap_or_default()
     93             .contains("queued")
     94     );
     95 
     96     let second = (10_000..20_000)
     97         .map(|timestamp| node.prepare_automatic_mining(timestamp))
     98         .find(|plan| plan.pow_mined.is_some())
     99         .expect("automatic PoW should allow a second proof for the same tip");
    100     let second_mine = second.pow_mined.as_ref().expect("PoW should be queued");
    101     assert_ne!(second_mine.signature(), first_mine.signature());
    102     assert_eq!(node.ledger().pending().len(), first_pending + 1);
    103 
    104     for timestamp in 20_000..20_010 {
    105         assert!(node.prepare_automatic_mining(timestamp).pow_mined.is_none());
    106     }
    107     assert_eq!(node.ledger().pending().len(), first_pending + 1);
    108     assert_eq!(
    109         node.status().mining.last_auto_pow_mine_status.as_deref(),
    110         Some("waiting for next chain tip after queued mine actions")
    111     );
    112     assert!(node.ledger().pending_blinded_transactions().is_empty());
    113 }
    114 
    115 #[test]
    116 fn automatic_pow_mining_waits_after_queueing_anchor_limit_for_tip() {
    117     let wallet = Wallet::from_seed("automatic-pow-independent-wallet");
    118     let mut allocations = BTreeMap::new();
    119     allocations.insert(wallet.address().to_string(), 1);
    120     let mut node = NodeCore::new(NodeConfig {
    121         wallet,
    122         genesis_allocations: allocations,
    123         vdf_rounds: 10,
    124         burn_per_block: 0,
    125         burn_fee: 0,
    126         pow_mining_workers: 1,
    127         recovery_vdf_top_rank_percent: 100,
    128     });
    129 
    130     node.set_pow_mining_enabled(true);
    131     let first_mined = (1..10_000)
    132         .find_map(|_| node.prepare_automatic_pow_mining().unwrap())
    133         .expect("PoW should eventually queue a mine action");
    134     let anchor = match first_mined {
    135         Transaction::Mine { ref anchor, .. } => anchor.clone(),
    136         _ => panic!("expected mine action"),
    137     };
    138     assert_eq!(node.ledger().pending_mine_count_for_anchor(&anchor), 1);
    139 
    140     (1..10_000)
    141         .find_map(|_| node.prepare_automatic_pow_mining().unwrap())
    142         .expect("PoW should allow a second mine action for the same tip");
    143     assert_eq!(
    144         node.ledger().pending_mine_count_for_anchor(&anchor),
    145         MINE_ACTIONS_PER_ANCHOR_LIMIT
    146     );
    147     assert!(node.prepare_automatic_pow_mining().unwrap().is_none());
    148     assert!(node.auto_pow_mine_cursor.is_none());
    149 }
    150 
    151 #[test]
    152 fn disabling_automatic_pow_mining_clears_local_work() {
    153     let wallet = Wallet::from_seed("automatic-pow-disable-wallet");
    154     let mut allocations = BTreeMap::new();
    155     allocations.insert(wallet.address().to_string(), 1);
    156     let mut node = NodeCore::new(NodeConfig {
    157         wallet,
    158         genesis_allocations: allocations,
    159         vdf_rounds: 10,
    160         burn_per_block: 0,
    161         burn_fee: 0,
    162         pow_mining_workers: 1,
    163         recovery_vdf_top_rank_percent: 100,
    164     });
    165 
    166     node.set_pow_mining_enabled(true);
    167     assert!(node.pow_mining_enabled());
    168     node.prepare_automatic_pow_mining().unwrap();
    169     assert!(node.auto_pow_mine_cursor.is_some());
    170     assert!(node.status().mining.last_auto_pow_mine_status.is_some());
    171 
    172     node.set_pow_mining_enabled(false);
    173 
    174     assert!(!node.pow_mining_enabled());
    175     assert!(node.auto_pow_mine_cursor.is_none());
    176     assert!(node.status().mining.last_auto_pow_mine_status.is_none());
    177 }
    178 
    179 #[test]
    180 fn automatic_pow_mining_workers_are_clamped_and_reported() {
    181     let wallet = Wallet::from_seed("automatic-pow-workers-wallet");
    182     let mut node = NodeCore::new(NodeConfig {
    183         wallet,
    184         genesis_allocations: BTreeMap::new(),
    185         vdf_rounds: 10,
    186         burn_per_block: 0,
    187         burn_fee: 0,
    188         pow_mining_workers: 99,
    189         recovery_vdf_top_rank_percent: 100,
    190     });
    191 
    192     assert_eq!(node.pow_mining_workers(), MAX_POW_MINING_WORKERS);
    193     assert_eq!(
    194         node.status().mining.max_pow_mining_workers,
    195         MAX_POW_MINING_WORKERS
    196     );
    197 
    198     node.set_pow_mining_workers(0);
    199 
    200     assert_eq!(node.pow_mining_workers(), DEFAULT_POW_MINING_WORKERS);
    201     assert_eq!(
    202         node.status().mining.pow_mining_workers,
    203         DEFAULT_POW_MINING_WORKERS
    204     );
    205 }
    206 
    207 #[test]
    208 fn automatic_pow_mining_skips_unspendable_owned_blinded_payloads() {
    209     let alice = Wallet::from_seed("automatic-pow-stale-owned-blind-alice");
    210     let bob = Wallet::from_seed("automatic-pow-stale-owned-blind-bob");
    211     let mut allocations = BTreeMap::new();
    212     allocations.insert(alice.address().to_string(), 10 * MICRO_IUNA);
    213     allocations.insert(bob.address().to_string(), MICRO_IUNA);
    214     let ledger = Ledger::new_with_genesis_burns(
    215         allocations,
    216         vec![GenesisBurn::new(bob.address(), MICRO_IUNA)],
    217         10,
    218     )
    219     .unwrap();
    220     let mut node = NodeCore::from_ledger(alice.clone(), ledger, 0);
    221 
    222     let blinded = node
    223         .blinded_burn_with_fee(MICRO_IUNA / 10, 7, node.chain_height() + 4)
    224         .unwrap();
    225     let mut finalizer_ledger = node.ledger().clone();
    226     let leader_burn = finalizer_ledger.build_burn(&bob, 1, 0).unwrap();
    227     finalizer_ledger.submit_transaction(leader_burn).unwrap();
    228     let commit_block = finalizer_ledger.mine_next_block(&bob, 1).unwrap();
    229     assert!(
    230         commit_block
    231             .blinded_transactions
    232             .iter()
    233             .any(|tx| tx.commitment == blinded.commitment)
    234     );
    235     finalizer_ledger.apply_block(commit_block).unwrap();
    236     assert!(node.import_verified_ledger(finalizer_ledger).unwrap());
    237     assert!(
    238         node.ledger()
    239             .has_unrevealed_blinded_transaction(&blinded.commitment)
    240     );
    241 
    242     node.set_pow_mining_enabled(true);
    243 
    244     assert!(node.prepare_automatic_pow_mining().is_ok());
    245 }
    246 
    247 #[test]
    248 fn automatic_pow_mining_skips_stale_local_anchor_reservation() {
    249     let wallet = Wallet::from_seed("automatic-pow-stale-anchor-wallet");
    250     let mut stale_allocations = BTreeMap::new();
    251     stale_allocations.insert(wallet.address().to_string(), MICRO_IUNA);
    252     let stale_ledger = Ledger::new(stale_allocations, 10);
    253     let stale_anchor = stale_ledger.build_burn(&wallet, 1, 0).unwrap();
    254     let live_ledger = Ledger::new(BTreeMap::new(), 10);
    255     let mut node = NodeCore::from_ledger(wallet.clone(), live_ledger, 0);
    256     node.local_block_anchor_burn = Some((node.chain_height(), stale_anchor));
    257     node.set_pow_mining_enabled(true);
    258 
    259     assert!(node.prepare_automatic_pow_mining().is_ok());
    260 }
    261 
    262 #[test]
    263 fn automatic_finalization_does_not_tick_pow_mining() {
    264     let wallet = Wallet::from_seed("automatic-pow-separated-finalizer-wallet");
    265     let mut node = NodeCore::new(NodeConfig {
    266         wallet,
    267         genesis_allocations: BTreeMap::new(),
    268         vdf_rounds: 10,
    269         burn_per_block: 0,
    270         burn_fee: 0,
    271         pow_mining_workers: 1,
    272         recovery_vdf_top_rank_percent: 100,
    273     });
    274 
    275     node.set_pow_mining_enabled(true);
    276     let _ = node.prepare_automatic_finalization(1);
    277 
    278     assert!(node.auto_pow_mine_cursor.is_none());
    279 }
    280 
    281 #[test]
    282 fn automatic_finalization_prepares_recovery_after_ticket_timeout() {
    283     let alice = Wallet::from_seed("automatic-recovery-alice");
    284     let bob = Wallet::from_seed("automatic-recovery-bob");
    285     let mut allocations = BTreeMap::new();
    286     allocations.insert(alice.address().to_string(), 10 * MICRO_IUNA);
    287     allocations.insert(bob.address().to_string(), 10 * MICRO_IUNA);
    288     let ledger =
    289         Ledger::new_with_genesis_burns(allocations, vec![GenesisBurn::new(alice.address(), 1)], 10)
    290             .unwrap();
    291     let mut node = NodeCore::from_ledger(bob, ledger, 1);
    292 
    293     let early = node.prepare_automatic_finalization(RECOVERY_BLOCK_DELAY_MS - 1);
    294     assert!(early.work.is_none());
    295     assert!(
    296         early
    297             .skipped_reason
    298             .as_deref()
    299             .unwrap_or_default()
    300             .contains("waiting for selected finalizer")
    301     );
    302 
    303     let recovery = node.prepare_automatic_finalization(RECOVERY_BLOCK_DELAY_MS);
    304     let work = recovery.work.expect("recovery work should be prepared");
    305     let block = work.finish(
    306         node.wallet.unlocked().unwrap(),
    307         "preverified-vdf".to_string(),
    308     );
    309 
    310     assert_eq!(block.finalizer_mode, FinalizerMode::Recovery);
    311     assert!(block.leader_proof.is_none());
    312 }
    313 
    314 #[test]
    315 fn automatic_finalization_respects_zero_recovery_vdf_threshold() {
    316     let alice = Wallet::from_seed("automatic-recovery-zero-alice");
    317     let bob = Wallet::from_seed("automatic-recovery-zero-bob");
    318     let mut allocations = BTreeMap::new();
    319     allocations.insert(alice.address().to_string(), 10 * MICRO_IUNA);
    320     allocations.insert(bob.address().to_string(), 10 * MICRO_IUNA);
    321     let ledger =
    322         Ledger::new_with_genesis_burns(allocations, vec![GenesisBurn::new(alice.address(), 1)], 10)
    323             .unwrap();
    324     let mut node = NodeCore::from_ledger(bob, ledger, 1);
    325     node.set_recovery_vdf_top_rank_percent(0);
    326 
    327     let recovery = node.prepare_automatic_finalization(RECOVERY_BLOCK_DELAY_MS);
    328 
    329     assert!(recovery.work.is_none());
    330 }
    331 
    332 #[test]
    333 fn selected_finalizer_runs_vdf_with_zero_recovery_vdf_threshold() {
    334     let alice = Wallet::from_seed("automatic-selected-zero-alice");
    335     let mut allocations = BTreeMap::new();
    336     allocations.insert(alice.address().to_string(), 10 * MICRO_IUNA);
    337     let ledger =
    338         Ledger::new_with_genesis_burns(allocations, vec![GenesisBurn::new(alice.address(), 1)], 10)
    339             .unwrap();
    340     assert_eq!(
    341         ledger.expected_leader_for_next_block().as_deref(),
    342         Some(alice.address())
    343     );
    344     let mut node = NodeCore::from_ledger(alice.clone(), ledger, 1);
    345     node.set_recovery_vdf_top_rank_percent(0);
    346 
    347     let plan = node.prepare_automatic_finalization(1);
    348 
    349     assert!(plan.work.is_some());
    350     assert!(plan.skipped_reason.is_none());
    351 }
    352 
    353 #[test]
    354 fn automatic_non_leader_burn_is_queued_as_blinded() {
    355     let alice = Wallet::from_seed("auto-blinded-burn-alice");
    356     let bob = Wallet::from_seed("auto-blinded-burn-bob");
    357     let carol = Wallet::from_seed("auto-blinded-burn-carol");
    358     let finalizers = [alice.clone(), bob.clone()];
    359     let mut allocations = BTreeMap::new();
    360     allocations.insert(alice.address().to_string(), 10 * MICRO_IUNA);
    361     allocations.insert(bob.address().to_string(), 10 * MICRO_IUNA);
    362     allocations.insert(carol.address().to_string(), 10 * MICRO_IUNA);
    363     let ledger = Ledger::new_with_genesis_burns(
    364         allocations,
    365         finalizers
    366             .iter()
    367             .map(|wallet| GenesisBurn::new(wallet.address(), MICRO_IUNA))
    368             .collect(),
    369         1,
    370     )
    371     .unwrap();
    372     assert_eq!(ledger.finalizer_rank_for_next_block(carol.address()), None);
    373     let mut node =
    374         NodeCore::from_ledger_with_burn_fee_and_enabled(carol, ledger, true, MICRO_IUNA / 10, 1);
    375 
    376     let plan = node.prepare_automatic_finalization(1);
    377     let outbox = node.drain_outbox();
    378 
    379     assert!(plan.burned.is_some());
    380     assert!(node.ledger().pending().is_empty());
    381     assert_eq!(node.ledger().pending_blinded_transactions().len(), 1);
    382     assert!(
    383         outbox
    384             .iter()
    385             .any(|envelope| matches!(envelope, GossipEnvelope::BlindedTransaction(_)))
    386     );
    387 }
    388 
    389 #[test]
    390 fn automatic_fallback_finalizer_prepares_anchor_and_blinded_burn() {
    391     let alice = Wallet::from_seed("auto-fallback-burn-alice");
    392     let bob = Wallet::from_seed("auto-fallback-burn-bob");
    393     let finalizers = [alice.clone(), bob.clone()];
    394     let mut allocations = BTreeMap::new();
    395     allocations.insert(alice.address().to_string(), 10 * MICRO_IUNA);
    396     allocations.insert(bob.address().to_string(), 10 * MICRO_IUNA);
    397     let ledger = Ledger::new_with_genesis_burns(
    398         allocations,
    399         finalizers
    400             .iter()
    401             .map(|wallet| GenesisBurn::new(wallet.address(), MICRO_IUNA))
    402             .collect(),
    403         1,
    404     )
    405     .unwrap();
    406     let fallback = finalizers
    407         .iter()
    408         .find(|wallet| ledger.finalizer_rank_for_next_block(wallet.address()) == Some(1))
    409         .unwrap()
    410         .clone();
    411     let mut node =
    412         NodeCore::from_ledger_with_burn_fee_and_enabled(fallback, ledger, true, MICRO_IUNA / 10, 1);
    413 
    414     let plan = node.prepare_automatic_finalization(1);
    415     let outbox = node.drain_outbox();
    416 
    417     assert!(plan.burned.is_some());
    418     assert!(
    419         plan.skipped_reason.is_none(),
    420         "fallback should not be skipped: {:?}",
    421         plan.skipped_reason
    422     );
    423     assert!(node.ledger().pending().is_empty());
    424     assert_eq!(node.ledger().pending_blinded_transactions().len(), 1);
    425     let (_, anchor_burn) = node
    426         .local_block_anchor_burn
    427         .as_ref()
    428         .expect("fallback anchor burn should be held locally");
    429     let anchor_signature = anchor_burn.signature().to_string();
    430     assert_eq!(anchor_burn.amount(), super::AUTO_BLOCK_ANCHOR_BURN_AMOUNT);
    431     assert!(
    432         outbox
    433             .iter()
    434             .any(|envelope| matches!(envelope, GossipEnvelope::BlindedTransaction(_)))
    435     );
    436     let work = plan.work.expect("fallback work should be prepared");
    437     let vdf_output = run_vdf(work.vdf_seed(), work.vdf_rounds());
    438     let block = node
    439         .complete_prepared_block_at(work, vdf_output, VDF_TARGET_BLOCK_MS * 2)
    440         .unwrap();
    441 
    442     assert_eq!(block.finalizer_rank, 1);
    443     assert_eq!(block.finalizer_mode, FinalizerMode::Ticket);
    444     assert!(block.transactions.iter().any(|transaction| {
    445         transaction.is_burn() && transaction.amount() == super::AUTO_BLOCK_ANCHOR_BURN_AMOUNT
    446     }));
    447     assert_eq!(
    448         block
    449             .transactions
    450             .first()
    451             .map(|transaction| transaction.signature()),
    452         Some(anchor_signature.as_str())
    453     );
    454     assert!(!block.blinded_transactions.is_empty());
    455     assert_eq!(node.ledger().height(), 1);
    456 }
    457 
    458 #[test]
    459 fn automatic_leader_prepares_anchor_and_blinded_burn() {
    460     let alice = Wallet::from_seed("auto-plaintext-burn-alice");
    461     let bob = Wallet::from_seed("auto-plaintext-burn-bob");
    462     let finalizers = [alice.clone(), bob.clone()];
    463     let mut allocations = BTreeMap::new();
    464     allocations.insert(alice.address().to_string(), 10 * MICRO_IUNA);
    465     allocations.insert(bob.address().to_string(), 10 * MICRO_IUNA);
    466     let mut ledger = Ledger::new_with_genesis_burns(
    467         allocations,
    468         finalizers
    469             .iter()
    470             .map(|wallet| GenesisBurn::new(wallet.address(), MICRO_IUNA))
    471             .collect(),
    472         1,
    473     )
    474     .unwrap();
    475     let leader = ledger.expected_leader_for_next_block().unwrap();
    476     let leader_wallet = finalizers
    477         .iter()
    478         .find(|wallet| wallet.address() == leader)
    479         .unwrap()
    480         .clone();
    481     for wallet in &finalizers {
    482         let split = ledger
    483             .build_transfer(wallet, wallet.address(), MICRO_IUNA, 0)
    484             .unwrap();
    485         ledger.submit_transaction(split).unwrap();
    486     }
    487     let anchor = ledger.build_burn(&leader_wallet, 1, 0).unwrap();
    488     ledger.submit_transaction(anchor).unwrap();
    489     let split_block = ledger.mine_next_block(&leader_wallet, 1).unwrap();
    490     ledger.apply_block(split_block).unwrap();
    491     let leader = ledger.expected_leader_for_next_block().unwrap();
    492     let leader_wallet = finalizers
    493         .iter()
    494         .find(|wallet| wallet.address() == leader)
    495         .unwrap()
    496         .clone();
    497     let mut node = NodeCore::from_ledger_with_burn_fee_and_enabled(
    498         leader_wallet,
    499         ledger,
    500         true,
    501         MICRO_IUNA / 10,
    502         1,
    503     );
    504 
    505     let plan = node.prepare_automatic_finalization(1);
    506     let outbox = node.drain_outbox();
    507 
    508     assert!(plan.burned.is_some());
    509     assert!(node.ledger().pending().is_empty());
    510     assert_eq!(node.ledger().pending_blinded_transactions().len(), 1);
    511     let (_, anchor_burn) = node
    512         .local_block_anchor_burn
    513         .as_ref()
    514         .expect("leader anchor burn should be held locally");
    515     assert_eq!(anchor_burn.amount(), super::AUTO_BLOCK_ANCHOR_BURN_AMOUNT);
    516     assert!(
    517         outbox
    518             .iter()
    519             .any(|envelope| matches!(envelope, GossipEnvelope::BlindedTransaction(_)))
    520     );
    521     assert!(node.prepare_automatic_finalization(1).work.is_some());
    522 }
    523 
    524 #[test]
    525 fn automatic_pow_mining_uses_protocol_finalizer_fee() {
    526     let wallet = Wallet::from_seed("automatic-pow-mining-fee-wallet");
    527     let ledger = Ledger::new_with_genesis_burns(
    528         BTreeMap::from([(wallet.address().to_string(), MICRO_IUNA)]),
    529         vec![GenesisBurn::new(wallet.address(), 1)],
    530         10,
    531     )
    532     .unwrap();
    533     let mut node = NodeCore::from_ledger(wallet, ledger, 0);
    534 
    535     node.set_pow_mining_enabled(true);
    536     let plan = (1..10_000)
    537         .map(|timestamp| node.prepare_automatic_mining(timestamp))
    538         .find(|plan| plan.pow_mined.is_some())
    539         .expect("bounded PoW search should eventually find a proof");
    540     let mine = plan.pow_mined.expect("PoW should be queued");
    541 
    542     assert_eq!(mine.fee(), MINE_FINALIZER_FEE);
    543     assert_eq!(mine.amount(), crate::domain::MINE_REWARD);
    544     assert_eq!(
    545         node.status().mining.automatic_pow_mine_fee,
    546         MINE_FINALIZER_FEE
    547     );
    548 }