From db5435f93b719b96eb51b96d4f6b173332917e70 Mon Sep 17 00:00:00 2001 From: sword_smith Date: Thu, 2 Jan 2025 16:44:46 +0100 Subject: [PATCH] refactor(mine_loop): Create state-less versions of tx-generators Better for tests and for facilitating #294. Co-authored-by: Alan Szepieniec --- src/mine_loop.rs | 338 +++++++++++++++++------------ src/models/blockchain/block/mod.rs | 8 +- src/models/state/archival_state.rs | 6 +- src/models/state/mempool.rs | 6 +- src/models/state/mod.rs | 10 +- src/models/state/wallet/mod.rs | 6 +- src/tests/shared.rs | 30 ++- 7 files changed, 236 insertions(+), 168 deletions(-) diff --git a/src/mine_loop.rs b/src/mine_loop.rs index ac1a02254..75bf56bc6 100644 --- a/src/mine_loop.rs +++ b/src/mine_loop.rs @@ -26,7 +26,7 @@ use tracing::*; use twenty_first::math::digest::Digest; use crate::job_queue::triton_vm::TritonVmJobPriority; -use crate::mine_loop::prover_job::ProverJobSettings; +use crate::job_queue::JobQueue; use crate::models::blockchain::block::block_height::BlockHeight; use crate::models::blockchain::block::difficulty_control::difficulty_control; use crate::models::blockchain::block::*; @@ -41,9 +41,11 @@ use crate::models::proof_abstractions::timestamp::Timestamp; use crate::models::shared::SIZE_20MB_IN_BYTES; use crate::models::state::transaction_details::TransactionDetails; use crate::models::state::tx_proving_capability::TxProvingCapability; +use crate::models::state::wallet::address::ReceivingAddress; use crate::models::state::wallet::expected_utxo::ExpectedUtxo; use crate::models::state::wallet::expected_utxo::UtxoNotifier; use crate::models::state::wallet::transaction_output::TxOutput; +use crate::models::state::wallet::transaction_output::TxOutputList; use crate::models::state::wallet::utxo_notification::UtxoNotifyMethod; use crate::models::state::GlobalState; use crate::models::state::GlobalStateLock; @@ -345,35 +347,18 @@ fn guess_nonce_iteration( } } -/// Produce a transaction that allocates the given fraction of the block -/// subsidy to the wallet in two UTXOs, one time-locked and one liquid. -pub(crate) async fn make_coinbase_transaction( +/// Make a coinbase transaction rewarding the composer identified by receiving +/// address with the block subsidy minus the guesser fee. The rest, including +/// transaction fees, goes to the guesser. +pub(crate) async fn make_coinbase_transaction_stateless( latest_block: &Block, - global_state_lock: &GlobalStateLock, + receiving_address: ReceivingAddress, + sender_randomness: Digest, guesser_block_subsidy_fraction: f64, timestamp: Timestamp, proving_power: TxProvingCapability, -) -> Result<(Transaction, Vec)> { - // note: it is Ok to always use the same key here because: - // 1. if we find a block, the utxo will go to our wallet - // and notification occurs offchain, so there is no privacy issue. - // 2. if we were to derive a new addr for each block then we would - // have large gaps since an address only receives funds when - // we actually win the mining lottery. - // 3. also this way we do not have to modify global/wallet state. - - // It's important to use the input `latest_block` here instead of - // reading it from state, since that could, because of a race condition - // lead to an inconsistent witness higher up in the call graph. This is - // done to avoid holding a read-lock throughout this function. - - let coinbase_recipient_spending_key = global_state_lock - .lock_guard() - .await - .wallet_state - .wallet_secret - .nth_generation_spending_key(0); - let receiving_address = coinbase_recipient_spending_key.to_address(); + vm_job_queue: &JobQueue, +) -> Result<(Transaction, TxOutputList)> { let mutator_set_accumulator = latest_block.mutator_set_accumulator_after().clone(); let next_block_height: BlockHeight = latest_block.header().height.next(); @@ -390,9 +375,6 @@ pub(crate) async fn make_coinbase_transaction( info!("Setting guesser_fee to {guesser_fee}."); - // There is no reason to put coinbase UTXO notifications on chain, because: - // Both sender randomness and receiver preimage are derived - // deterministically from the wallet's seed. let Some(amount_to_composer) = coinbase_amount.checked_sub(&guesser_fee) else { bail!( "Guesser fee may not exceed coinbase amount. coinbase_amount: {}; guesser_fee: {}.", @@ -412,18 +394,11 @@ pub(crate) async fn make_coinbase_transaction( .checked_sub(&liquid_composer_amount) .expect("Amount to composer must be larger than liquid amount to composer."); - let sender_randomness: Digest = global_state_lock - .lock_guard() - .await - .wallet_state - .wallet_secret - .generate_sender_randomness(next_block_height, receiving_address.privacy_digest()); - let owned = true; let liquid_coinbase_output = TxOutput::offchain_native_currency( liquid_composer_amount, sender_randomness, - receiving_address.into(), + receiving_address.clone(), owned, ); @@ -432,18 +407,19 @@ pub(crate) async fn make_coinbase_transaction( let timelocked_coinbase_output = TxOutput::offchain_native_currency( timelocked_composer_amount, sender_randomness, - receiving_address.into(), + receiving_address, owned, ) .with_time_lock(timestamp + MINING_REWARD_TIME_LOCK_PERIOD + Timestamp::minutes(30)); + let composer_outputs: TxOutputList = vec![ + liquid_coinbase_output.clone(), + timelocked_coinbase_output.clone(), + ] + .into(); let transaction_details = TransactionDetails::new_with_coinbase( vec![], - vec![ - liquid_coinbase_output.clone(), - timelocked_coinbase_output.clone(), - ] - .into(), + composer_outputs.clone(), coinbase_amount, guesser_fee, timestamp, @@ -454,112 +430,67 @@ pub(crate) async fn make_coinbase_transaction( and tx must be balanced because the one output receives exactly the coinbase amount", ); - // 2. Create the transaction - // The transaction is supported by a PrimitiveWitness. Upgrading this proof - // must be done by the caller. - - // It's important to not hold any locks (not even read-locks) here. Since - // we, depending on the specified proof quality, might use *very* long time - // here. Read: minutes. info!("Start: generate single proof for coinbase transaction"); - let vm_job_queue = global_state_lock.vm_job_queue(); let transaction = GlobalState::create_raw_transaction( transaction_details, proving_power, vm_job_queue, - ( - TritonVmJobPriority::High, - global_state_lock.cli().max_log2_padded_height_for_proofs, - ) - .into(), + TritonVmProofJobOptions { + job_priority: TritonVmJobPriority::High, + job_settings: Default::default(), + }, ) .await?; info!("Done: generating single proof for coinbase transaction"); - let composer_utxo_not_timelocked = ExpectedUtxo::new( - liquid_coinbase_output.utxo(), - liquid_coinbase_output.sender_randomness(), - coinbase_recipient_spending_key.privacy_preimage(), - UtxoNotifier::OwnMinerComposeBlock, - ); - let composer_utxo_timelocked = ExpectedUtxo::new( - timelocked_coinbase_output.utxo(), - timelocked_coinbase_output.sender_randomness(), - coinbase_recipient_spending_key.privacy_preimage(), - UtxoNotifier::OwnMinerComposeBlock, - ); - - Ok(( - transaction, - vec![composer_utxo_not_timelocked, composer_utxo_timelocked], - )) + Ok((transaction, composer_outputs)) } -/// Create the transaction that goes into the block template. The transaction is -/// built from the mempool and from the coinbase transaction. Also returns the -/// "sender randomness" used in the coinbase transaction. -pub(crate) async fn create_block_transaction( +/// Create a transaction with a coinbase for the indicated address. +/// +/// If no mempool transactions are included, a nop transaction will be merged in +/// such that the resulting transaction is valid for block inclusion. +pub(crate) async fn create_block_transaction_stateless( predecessor_block: &Block, - global_state_lock: &GlobalStateLock, + receiving_address: ReceivingAddress, + sender_randomness_for_composer: Digest, + shuffle_seed: [u8; 32], timestamp: Timestamp, guesser_fee_fraction: f64, -) -> Result<(Transaction, Vec)> { - let block_capacity_for_transactions = SIZE_20MB_IN_BYTES; - + vm_job_queue: &JobQueue, + mut selected_mempool_txs: Vec, +) -> Result<(Transaction, TxOutputList)> { // A coinbase transaction implies mining. So you *must* // be able to create a SingleProof. - let (coinbase_transaction, composer_utxos) = make_coinbase_transaction( + let (coinbase_transaction, composer_txos) = make_coinbase_transaction_stateless( predecessor_block, - global_state_lock, + receiving_address, + sender_randomness_for_composer, guesser_fee_fraction, timestamp, TxProvingCapability::SingleProof, + vm_job_queue, ) .await?; - let predecessor_block_ms = predecessor_block.mutator_set_accumulator_after(); - debug!( - "Creating block transaction with mutator set hash: {}", - predecessor_block_ms.hash() - ); - - let mut rng: StdRng = - SeedableRng::from_seed(global_state_lock.lock_guard().await.shuffle_seed()); - - // Get most valuable transactions from mempool. - // TODO: Change this const to be defined through CLI arguments. - const MAX_NUM_TXS_TO_MERGE: usize = 7; - let only_merge_single_proofs = true; - let mut transactions_to_include = global_state_lock - .lock_guard() - .await - .mempool - .get_transactions_for_block( - block_capacity_for_transactions, - Some(MAX_NUM_TXS_TO_MERGE), - only_merge_single_proofs, - ); + let mut rng = StdRng::from_seed(shuffle_seed); - let vm_job_queue = global_state_lock.vm_job_queue(); - let proof_job_options = TritonVmProofJobOptions { - job_priority: TritonVmJobPriority::High, - job_settings: ProverJobSettings { - max_log2_padded_height_for_proofs: global_state_lock - .cli() - .max_log2_padded_height_for_proofs, - }, - }; - if transactions_to_include.is_empty() { + let mut block_transaction = coinbase_transaction; + if selected_mempool_txs.is_empty() { // create the nop-gobbler and merge into the coinbase transaction to - // set the merge bit and allow the tx to be included in a block. + // set the merge bit to allow the tx to be included in a block. let nop_gobbler = TransactionDetails::fee_gobbler( NeptuneCoins::zero(), rng.gen(), - predecessor_block_ms, + predecessor_block.mutator_set_accumulator_after(), timestamp, UtxoNotifyMethod::None, ); let nop_gobbler = PrimitiveWitness::from_transaction_details(nop_gobbler); + let proof_job_options = TritonVmProofJobOptions { + job_priority: TritonVmJobPriority::High, + job_settings: Default::default(), + }; let nop_gobbler_proof = SingleProof::produce(&nop_gobbler, vm_job_queue, proof_job_options).await?; let nop_gobbler = Transaction { @@ -567,30 +498,104 @@ pub(crate) async fn create_block_transaction( proof: TransactionProof::SingleProof(nop_gobbler_proof), }; - transactions_to_include = vec![nop_gobbler]; + selected_mempool_txs = vec![nop_gobbler]; } - // Merge incoming transactions with the coinbase transaction - let num_transactions_to_include = transactions_to_include.len(); - let mut block_transaction = coinbase_transaction; - for (i, transaction_to_include) in transactions_to_include.into_iter().enumerate() { - info!( - "Merging transaction {} / {}", - i + 1, - num_transactions_to_include - ); + let num_merges = selected_mempool_txs.len(); + for (i, tx_to_include) in selected_mempool_txs.into_iter().enumerate() { + info!("Merging transaction {} / {}", i + 1, num_merges); block_transaction = Transaction::merge_with( block_transaction, - transaction_to_include, + tx_to_include, rng.gen(), vm_job_queue, - proof_job_options, + TritonVmProofJobOptions { + job_priority: TritonVmJobPriority::High, + job_settings: Default::default(), + }, ) .await .expect("Must be able to merge transactions in mining context"); } - Ok((block_transaction, composer_utxos)) + Ok((block_transaction, composer_txos)) +} + +/// Create the transaction that goes into the block template. The transaction is +/// built from the mempool and from the coinbase transaction. Also returns the +/// "sender randomness" used in the coinbase transaction. +pub(crate) async fn create_block_transaction( + predecessor_block: &Block, + global_state_lock: &GlobalStateLock, + timestamp: Timestamp, + guesser_fee_fraction: f64, +) -> Result<(Transaction, Vec)> { + let block_capacity_for_transactions = SIZE_20MB_IN_BYTES; + + let predecessor_block_ms = predecessor_block.mutator_set_accumulator_after(); + debug!( + "Creating block transaction with mutator set hash: {}", + predecessor_block_ms.hash() + ); + + let mut rng: StdRng = + SeedableRng::from_seed(global_state_lock.lock_guard().await.shuffle_seed()); + + // Get most valuable transactions from mempool. + // TODO: Change this const to be defined through CLI arguments. + const MAX_NUM_TXS_TO_MERGE: usize = 7; + let only_merge_single_proofs = true; + let mempool_txs_to_mine = global_state_lock + .lock_guard() + .await + .mempool + .get_transactions_for_block( + block_capacity_for_transactions, + Some(MAX_NUM_TXS_TO_MERGE), + only_merge_single_proofs, + ); + + let coinbase_recipient_spending_key = global_state_lock + .lock_guard() + .await + .wallet_state + .wallet_secret + .nth_generation_spending_key(0); + let receiving_address = coinbase_recipient_spending_key.to_address(); + let next_block_height: BlockHeight = predecessor_block.header().height.next(); + let sender_randomness_for_composer = global_state_lock + .lock_guard() + .await + .wallet_state + .wallet_secret + .generate_sender_randomness(next_block_height, receiving_address.privacy_digest()); + let vm_job_queue = global_state_lock.vm_job_queue(); + + let (transaction, composer_txos) = create_block_transaction_stateless( + predecessor_block, + receiving_address.into(), + sender_randomness_for_composer, + rng.gen(), + timestamp, + guesser_fee_fraction, + vm_job_queue, + mempool_txs_to_mine, + ) + .await?; + + let own_expected_utxos = composer_txos + .iter() + .map(|txo| { + ExpectedUtxo::new( + txo.utxo(), + txo.sender_randomness(), + coinbase_recipient_spending_key.privacy_preimage(), + UtxoNotifier::OwnMinerComposeBlock, + ) + }) + .collect(); + + Ok((transaction, own_expected_utxos)) } /// @@ -880,6 +885,69 @@ pub(crate) mod mine_loop_tests { use crate::util_types::test_shared::mutator_set::random_mutator_set_accumulator; use crate::WalletSecret; + /// Produce a transaction that allocates the given fraction of the block + /// subsidy to the wallet in two UTXOs, one time-locked and one liquid. + pub(crate) async fn make_coinbase_transaction_from_state( + latest_block: &Block, + global_state_lock: &GlobalStateLock, + guesser_block_subsidy_fraction: f64, + timestamp: Timestamp, + proving_power: TxProvingCapability, + ) -> Result<(Transaction, Vec)> { + // note: it is Ok to always use the same key here because: + // 1. if we find a block, the utxo will go to our wallet + // and notification occurs offchain, so there is no privacy issue. + // 2. if we were to derive a new addr for each block then we would + // have large gaps since an address only receives funds when + // we actually win the mining lottery. + // 3. also this way we do not have to modify global/wallet state. + + // It's important to use the input `latest_block` here instead of + // reading it from state, since that could, because of a race condition + // lead to an inconsistent witness higher up in the call graph. This is + // done to avoid holding a read-lock throughout this function. + + let coinbase_recipient_spending_key = global_state_lock + .lock_guard() + .await + .wallet_state + .wallet_secret + .nth_generation_spending_key(0); + let receiving_address = coinbase_recipient_spending_key.to_address(); + let next_block_height: BlockHeight = latest_block.header().height.next(); + let sender_randomness: Digest = global_state_lock + .lock_guard() + .await + .wallet_state + .wallet_secret + .generate_sender_randomness(next_block_height, receiving_address.privacy_digest()); + let vm_job_queue = global_state_lock.vm_job_queue(); + let (transaction, composer_outputs) = make_coinbase_transaction_stateless( + latest_block, + receiving_address.into(), + sender_randomness, + guesser_block_subsidy_fraction, + timestamp, + proving_power, + vm_job_queue, + ) + .await?; + + let own_expected_utxos = composer_outputs + .iter() + .map(|txo| { + ExpectedUtxo::new( + txo.utxo(), + txo.sender_randomness(), + coinbase_recipient_spending_key.privacy_preimage(), + UtxoNotifier::OwnMinerComposeBlock, + ) + }) + .collect(); + + Ok((transaction, own_expected_utxos)) + } + /// Similar to [mine_iteration] function but intended for tests. /// /// Does *not* update the timestamp of the block and therefore also does not @@ -994,7 +1062,7 @@ pub(crate) mod mine_loop_tests { ) .await; let tick = std::time::SystemTime::now(); - let (transaction, _coinbase_utxo_info) = make_coinbase_transaction( + let (transaction, _coinbase_utxo_info) = make_coinbase_transaction_from_state( &genesis_block, &global_state_lock, 0f64, @@ -1078,7 +1146,7 @@ pub(crate) mod mine_loop_tests { "Mempool must be empty at start of loop" ); let (transaction_empty_mempool, _coinbase_utxo_info) = { - make_coinbase_transaction( + make_coinbase_transaction_from_state( &genesis_block, &alice, guesser_fee_fraction, @@ -1233,7 +1301,7 @@ pub(crate) mod mine_loop_tests { let launch_date = tip_block_orig.header().timestamp; let (worker_task_tx, worker_task_rx) = oneshot::channel::(); - let (transaction, coinbase_utxo_info) = make_coinbase_transaction( + let (transaction, coinbase_utxo_info) = make_coinbase_transaction_from_state( &tip_block_orig, &global_state_lock, 0f64, @@ -1301,7 +1369,7 @@ pub(crate) mod mine_loop_tests { // pretend/simulate that it takes at least 10 seconds to mine the block. let ten_seconds_ago = now - Timestamp::seconds(10); - let (transaction, coinbase_utxo_info) = make_coinbase_transaction( + let (transaction, coinbase_utxo_info) = make_coinbase_transaction_from_state( &tip_block_orig, &global_state_lock, 0f64, @@ -1581,7 +1649,7 @@ pub(crate) mod mine_loop_tests { let genesis_block = Block::genesis_block(network); let launch_date = genesis_block.header().timestamp; - let (transaction, coinbase_utxo_info) = make_coinbase_transaction( + let (transaction, coinbase_utxo_info) = make_coinbase_transaction_from_state( &genesis_block, &global_state_lock, 0f64, diff --git a/src/models/blockchain/block/mod.rs b/src/models/blockchain/block/mod.rs index 40269d94a..201526dd5 100644 --- a/src/models/blockchain/block/mod.rs +++ b/src/models/blockchain/block/mod.rs @@ -273,6 +273,10 @@ impl Block { ), "Transaction proof must be valid to generate a block" ); + assert!( + transaction.kernel.merge_bit, + "Merge-bit must be set in transactions before they can be included in blocks." + ); let primitive_witness = BlockPrimitiveWitness::new(predecessor.to_owned(), transaction); Self::block_template_from_block_primitive_witness( primitive_witness, @@ -1026,7 +1030,7 @@ mod block_tests { use crate::config_models::network::Network; use crate::database::storage::storage_schema::SimpleRustyStorage; use crate::database::NeptuneLevelDb; - use crate::mine_loop::make_coinbase_transaction; + use crate::mine_loop::mine_loop_tests::make_coinbase_transaction_from_state; use crate::models::blockchain::transaction::lock_script::LockScriptAndWitness; use crate::models::state::tx_proving_capability::TxProvingCapability; use crate::models::state::wallet::transaction_output::TxOutput; @@ -1237,7 +1241,7 @@ mod block_tests { mock_genesis_global_state(network, 0, wallet, cli_args::Args::default()).await; let guesser_fraction = 0f64; - let (block_tx, _expected_utxo) = make_coinbase_transaction( + let (block_tx, _expected_utxo) = make_coinbase_transaction_from_state( &genesis_block, &genesis_state, guesser_fraction, diff --git a/src/models/state/archival_state.rs b/src/models/state/archival_state.rs index 7a494a4f5..a92f19bf7 100644 --- a/src/models/state/archival_state.rs +++ b/src/models/state/archival_state.rs @@ -1164,7 +1164,7 @@ mod archival_state_tests { use crate::database::storage::storage_vec::traits::*; use crate::job_queue::triton_vm::TritonVmJobPriority; use crate::job_queue::triton_vm::TritonVmJobQueue; - use crate::mine_loop::make_coinbase_transaction; + use crate::mine_loop::mine_loop_tests::make_coinbase_transaction_from_state; use crate::models::blockchain::block::block_header::MINIMUM_BLOCK_TIME; use crate::models::blockchain::transaction::lock_script::LockScript; use crate::models::blockchain::transaction::utxo::Utxo; @@ -1855,7 +1855,7 @@ mod archival_state_tests { println!("Generated transaction for Alice and Bob."); let guesser_fraction = 0f64; - let (cbtx, composer_expected_utxos) = make_coinbase_transaction( + let (cbtx, composer_expected_utxos) = make_coinbase_transaction_from_state( &premine_rec .global_state_lock .lock_guard() @@ -2108,7 +2108,7 @@ mod archival_state_tests { // Make block_2 with tx that contains: // - 4 inputs: 2 from Alice and 2 from Bob // - 7 outputs: 2 from Alice to premine rec, 3 from Bob to premine rec, and 2 coinbases to premine rec - let (cbtx2, expected_composer_utxos2) = make_coinbase_transaction( + let (cbtx2, expected_composer_utxos2) = make_coinbase_transaction_from_state( &premine_rec .global_state_lock .lock_guard() diff --git a/src/models/state/mempool.rs b/src/models/state/mempool.rs index 3f121cfb6..a294399ec 100644 --- a/src/models/state/mempool.rs +++ b/src/models/state/mempool.rs @@ -810,7 +810,7 @@ mod tests { use crate::config_models::cli_args; use crate::config_models::network::Network; use crate::job_queue::triton_vm::TritonVmJobPriority; - use crate::mine_loop::make_coinbase_transaction; + use crate::mine_loop::mine_loop_tests::make_coinbase_transaction_from_state; use crate::models::blockchain::block::block_height::BlockHeight; use crate::models::blockchain::transaction::primitive_witness::PrimitiveWitness; use crate::models::blockchain::transaction::validity::single_proof::SingleProof; @@ -1202,7 +1202,7 @@ mod tests { // Create next block which includes Bob's, but not Alice's, transaction. let guesser_fraction = 0f64; - let (coinbase_transaction, _expected_utxo) = make_coinbase_transaction( + let (coinbase_transaction, _expected_utxo) = make_coinbase_transaction_from_state( &bob.global_state_lock .lock_guard() .await @@ -1282,7 +1282,7 @@ mod tests { tx_by_alice_updated = mempool.get_transactions_for_block(usize::MAX, None, true)[0].clone(); let block_5_timestamp = previous_block.header().timestamp + Timestamp::hours(1); - let (cbtx, _eutxo) = make_coinbase_transaction( + let (cbtx, _eutxo) = make_coinbase_transaction_from_state( &alice .global_state_lock .lock_guard() diff --git a/src/models/state/mod.rs b/src/models/state/mod.rs index 33622431e..c80602962 100644 --- a/src/models/state/mod.rs +++ b/src/models/state/mod.rs @@ -1507,7 +1507,7 @@ mod global_state_tests { use super::*; use crate::config_models::network::Network; - use crate::mine_loop::make_coinbase_transaction; + use crate::mine_loop::mine_loop_tests::make_coinbase_transaction_from_state; use crate::models::blockchain::block::Block; use crate::tests::shared::make_mock_block; use crate::tests::shared::mock_genesis_global_state; @@ -2205,7 +2205,7 @@ mod global_state_tests { let in_eight_months = in_seven_months + Timestamp::months(1); let guesser_fraction = 0f64; - let (coinbase_transaction, coinbase_expected_utxos) = make_coinbase_transaction( + let (coinbase_transaction, coinbase_expected_utxos) = make_coinbase_transaction_from_state( &genesis_block, &premine_receiver, guesser_fraction, @@ -2492,7 +2492,7 @@ mod global_state_tests { // Make block_2 with tx that contains: // - 4 inputs: 2 from Alice and 2 from Bob // - 7 outputs: 2 from Alice to Genesis, 3 from Bob to Genesis, and 2 coinbases - let (coinbase_transaction2, _expected_utxo) = make_coinbase_transaction( + let (coinbase_transaction2, _expected_utxo) = make_coinbase_transaction_from_state( &premine_receiver .global_state_lock .lock_guard() @@ -2559,7 +2559,7 @@ mod global_state_tests { let now = genesis_block.kernel.header.timestamp + Timestamp::hours(1); let guesser_fraction = 0f64; - let (cb, _) = make_coinbase_transaction( + let (cb, _) = make_coinbase_transaction_from_state( &genesis_block, &global_state_lock, guesser_fraction, @@ -2612,7 +2612,7 @@ mod global_state_tests { ) -> Block { let genesis_block = Block::genesis_block(global_state_lock.cli().network); let timestamp = genesis_block.header().timestamp + Timestamp::hours(1); - let (cb, _) = make_coinbase_transaction( + let (cb, _) = make_coinbase_transaction_from_state( &genesis_block, global_state_lock, guesser_fraction, diff --git a/src/models/state/wallet/mod.rs b/src/models/state/wallet/mod.rs index 18fbb9ed1..b8d978257 100644 --- a/src/models/state/wallet/mod.rs +++ b/src/models/state/wallet/mod.rs @@ -426,7 +426,7 @@ mod wallet_tests { use crate::database::storage::storage_vec::traits::*; use crate::job_queue::triton_vm::TritonVmJobPriority; use crate::job_queue::triton_vm::TritonVmJobQueue; - use crate::mine_loop::make_coinbase_transaction; + use crate::mine_loop::mine_loop_tests::make_coinbase_transaction_from_state; use crate::models::blockchain::block::block_header::MINIMUM_BLOCK_TIME; use crate::models::blockchain::block::block_height::BlockHeight; use crate::models::blockchain::block::Block; @@ -1215,7 +1215,7 @@ mod wallet_tests { .unwrap(); let guesser_fraction = 0f64; - let (coinbase_tx, expected_composer_utxos) = make_coinbase_transaction( + let (coinbase_tx, expected_composer_utxos) = make_coinbase_transaction_from_state( &alice .global_state_lock .lock_guard() @@ -1396,7 +1396,7 @@ mod wallet_tests { let mut rng = StdRng::seed_from_u64(87255549301u64); let guesser_fraction = 0f64; - let (cbtx, _cb_expected) = make_coinbase_transaction( + let (cbtx, _cb_expected) = make_coinbase_transaction_from_state( &bob.global_state_lock .lock_guard() .await diff --git a/src/tests/shared.rs b/src/tests/shared.rs index 5956d7e37..f997e5740 100644 --- a/src/tests/shared.rs +++ b/src/tests/shared.rs @@ -49,7 +49,8 @@ use crate::config_models::network::Network; use crate::database::NeptuneLevelDb; use crate::job_queue::triton_vm::TritonVmJobPriority; use crate::job_queue::triton_vm::TritonVmJobQueue; -use crate::mine_loop::make_coinbase_transaction; +use crate::mine_loop::create_block_transaction_stateless; +use crate::mine_loop::mine_loop_tests::make_coinbase_transaction_from_state; use crate::mine_loop::mine_loop_tests::mine_iteration_for_tests; use crate::models::blockchain::block::block_appendix::BlockAppendix; use crate::models::blockchain::block::block_body::BlockBody; @@ -85,15 +86,13 @@ use crate::models::state::blockchain_state::BlockchainState; use crate::models::state::light_state::LightState; use crate::models::state::mempool::Mempool; use crate::models::state::networking_state::NetworkingState; -use crate::models::state::transaction_details::TransactionDetails; use crate::models::state::tx_proving_capability::TxProvingCapability; use crate::models::state::wallet::address::generation_address; +use crate::models::state::wallet::address::generation_address::GenerationReceivingAddress; use crate::models::state::wallet::expected_utxo::ExpectedUtxo; use crate::models::state::wallet::expected_utxo::UtxoNotifier; -use crate::models::state::wallet::transaction_output::TxOutputList; use crate::models::state::wallet::wallet_state::WalletState; use crate::models::state::wallet::WalletSecret; -use crate::models::state::GlobalState; use crate::models::state::GlobalStateLock; use crate::prelude::twenty_first; use crate::util_types::mutator_set::addition_record::AdditionRecord; @@ -847,24 +846,21 @@ pub(crate) async fn valid_successor_for_tests( timestamp: Timestamp, seed: [u8; 32], ) -> Block { - let tx_details = TransactionDetails::new_without_coinbase( - vec![], - TxOutputList::default(), - NeptuneCoins::zero(), + let mut rng = StdRng::from_seed(seed); + let (block_tx, _) = create_block_transaction_stateless( + predecessor, + GenerationReceivingAddress::derive_from_seed(rng.gen()).into(), + rng.gen(), + rng.gen(), timestamp, - predecessor.mutator_set_accumulator_after().clone(), - ) - .unwrap(); - let tx = GlobalState::create_raw_transaction( - tx_details, - TxProvingCapability::SingleProof, + 0.5f64, &TritonVmJobQueue::dummy(), - TritonVmJobPriority::default().into(), + vec![], ) .await .unwrap(); - valid_block_from_tx_for_tests(predecessor, tx, seed).await + valid_block_from_tx_for_tests(predecessor, block_tx, rng.gen()).await } /// Create a valid block with coinbase going to self. For testing purposes. @@ -878,7 +874,7 @@ pub(crate) async fn valid_block_for_tests( guesser_fraction: f64, ) -> Block { let current_tip = state_lock.lock_guard().await.chain.light_state().clone(); - let (cb, _) = make_coinbase_transaction( + let (cb, _) = make_coinbase_transaction_from_state( ¤t_tip, state_lock, guesser_fraction,