From 30fd6bb3531890df90df3c0b114f83e9fe98784c Mon Sep 17 00:00:00 2001 From: Gregory Coppola <60008382+gregorycoppola@users.noreply.github.com> Date: Tue, 16 Nov 2021 11:39:57 -0500 Subject: [PATCH] Stacks 2.05: Add Epoch to Cost Estimate Key (#2923) * added bunch of things * moving the stuff * test compiles * added a test * fixed typo * added two tests * updated code/tests in stacks-node * replaced indexed conn with unindexed one --- src/chainstate/coordinator/mod.rs | 7 +- src/chainstate/stacks/miner.rs | 31 ++- src/core/mempool.rs | 7 + src/cost_estimates/mod.rs | 41 ++- src/cost_estimates/pessimistic.rs | 44 ++- src/cost_estimates/tests/cost_estimators.rs | 254 ++++++++++++++++-- src/net/p2p.rs | 1 + src/net/rpc.rs | 24 +- testnet/stacks-node/src/neon_node.rs | 1 + testnet/stacks-node/src/node.rs | 6 +- .../stacks-node/src/tests/bitcoin_regtest.rs | 16 +- testnet/stacks-node/src/tests/integrations.rs | 25 ++ testnet/stacks-node/src/tests/mempool.rs | 6 + testnet/stacks-node/src/tests/mod.rs | 28 +- 14 files changed, 422 insertions(+), 69 deletions(-) diff --git a/src/chainstate/coordinator/mod.rs b/src/chainstate/coordinator/mod.rs index a8e6cdfef6..e0dde49871 100644 --- a/src/chainstate/coordinator/mod.rs +++ b/src/chainstate/coordinator/mod.rs @@ -776,8 +776,11 @@ impl< .index_conn() .get_stacks_epoch_by_epoch_id(&block_receipt.evaluated_epoch) .expect("Could not find a stacks epoch."); - estimator - .notify_block(&block_receipt.tx_receipts, &stacks_epoch.block_limit); + estimator.notify_block( + &block_receipt.tx_receipts, + &stacks_epoch.block_limit, + &stacks_epoch.epoch_id, + ); } if let Some(ref mut estimator) = self.fee_estimator { diff --git a/src/chainstate/stacks/miner.rs b/src/chainstate/stacks/miner.rs index 6c72a53634..4be02ec472 100644 --- a/src/chainstate/stacks/miner.rs +++ b/src/chainstate/stacks/miner.rs @@ -472,10 +472,11 @@ impl<'a> StacksMicroblockBuilder<'a> { let deadline = get_epoch_time_ms() + (self.settings.max_miner_time_ms as u128); mem_pool.reset_last_known_nonces()?; + let stacks_epoch_id = clarity_tx.get_epoch(); let block_limit = clarity_tx .block_limit() .expect("No block limit found for clarity_tx."); - mem_pool.estimate_tx_rates(100, &block_limit)?; + mem_pool.estimate_tx_rates(100, &block_limit, &stacks_epoch_id)?; debug!( "Microblock transaction selection begins (child of {}), bytes so far: {}", @@ -516,6 +517,7 @@ impl<'a> StacksMicroblockBuilder<'a> { &mempool_tx.tx.payload, &receipt.execution_cost, &block_limit, + &stacks_epoch_id, ) { warn!("Error updating estimator"; "txid" => %mempool_tx.metadata.txid, @@ -1534,6 +1536,8 @@ impl StacksBlockBuilder { let (mut epoch_tx, confirmed_mblock_cost) = builder.epoch_begin(&mut chainstate, burn_dbconn)?; + let stacks_epoch_id = epoch_tx.get_epoch(); + let block_limit = epoch_tx .block_limit() .expect("Failed to obtain block limit from miner's block connection"); @@ -1542,7 +1546,7 @@ impl StacksBlockBuilder { mempool.reset_last_known_nonces()?; - mempool.estimate_tx_rates(100, &block_limit)?; + mempool.estimate_tx_rates(100, &block_limit, &stacks_epoch_id)?; let mut considered = HashSet::new(); // txids of all transactions we looked at let mut mined_origin_nonces: HashMap = HashMap::new(); // map addrs of mined transaction origins to the nonces we used @@ -1614,6 +1618,7 @@ impl StacksBlockBuilder { &txinfo.tx.payload, &tx_receipt.execution_cost, &block_limit, + &stacks_epoch_id, ) { warn!("Error updating estimator"; "txid" => %txinfo.metadata.txid, @@ -6660,6 +6665,7 @@ pub mod test { &stx_transfer, None, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } @@ -6800,6 +6806,7 @@ pub mod test { &stx_transfer, None, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } @@ -6937,6 +6944,7 @@ pub mod test { &stx_transfer, None, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } @@ -6961,6 +6969,7 @@ pub mod test { &stx_transfer, None, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } @@ -7664,6 +7673,7 @@ pub mod test { &tx, None, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } @@ -7867,6 +7877,7 @@ pub mod test { &stx_transfer, None, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); @@ -7887,6 +7898,7 @@ pub mod test { &contract_tx, None, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); @@ -7906,6 +7918,7 @@ pub mod test { &stx_transfer, None, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); @@ -8060,6 +8073,7 @@ pub mod test { &contract_tx, None, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } @@ -8217,6 +8231,7 @@ pub mod test { &contract_tx, None, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } @@ -8352,6 +8367,7 @@ pub mod test { &parent_header_hash, contract_tx_bytes, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); @@ -8378,6 +8394,7 @@ pub mod test { &parent_header_hash, contract_tx_bytes, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); @@ -8723,6 +8740,7 @@ pub mod test { &parent_header_hash, contract_tx_bytes, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); @@ -8750,6 +8768,7 @@ pub mod test { &parent_header_hash, contract_tx_bytes, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); @@ -8785,6 +8804,7 @@ pub mod test { &parent_header_hash, contract_tx_bytes, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); @@ -8812,6 +8832,7 @@ pub mod test { &parent_header_hash, contract_tx_bytes, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); @@ -9078,6 +9099,7 @@ pub mod test { &parent_header_hash, tx_bytes, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } @@ -9409,6 +9431,7 @@ pub mod test { &parent_header_hash, tx_bytes, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } @@ -9483,6 +9506,7 @@ pub mod test { &parent_header_hash, tx_bytes, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } @@ -9514,6 +9538,7 @@ pub mod test { &parent_header_hash, tx_bytes, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } @@ -9890,6 +9915,7 @@ pub mod test { &tx, None, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap() } @@ -9914,6 +9940,7 @@ pub mod test { &tx, None, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap() } diff --git a/src/core/mempool.rs b/src/core/mempool.rs index e040330bd2..9cf12b7693 100644 --- a/src/core/mempool.rs +++ b/src/core/mempool.rs @@ -40,6 +40,7 @@ use chainstate::stacks::{ Error as ChainstateError, StacksTransaction, }; use core::ExecutionCost; +use core::StacksEpochId; use core::FIRST_BURNCHAIN_CONSENSUS_HASH; use core::FIRST_STACKS_BLOCK_HASH; use monitoring::increment_stx_mempool_gc; @@ -663,6 +664,7 @@ impl MemPoolDB { &mut self, max_updates: u32, block_limit: &ExecutionCost, + stacks_epoch_id: &StacksEpochId, ) -> Result { let sql_tx = tx_begin_immediate(&mut self.db)?; let txs: Vec = query_rows( @@ -679,6 +681,7 @@ impl MemPoolDB { self.cost_estimator.as_ref(), self.metric.as_ref(), block_limit, + stacks_epoch_id, ); let fee_rate_f64 = match estimator_result { Ok(x) => Some(x), @@ -1234,12 +1237,14 @@ impl MemPoolDB { tx: &StacksTransaction, event_observer: Option<&dyn MemPoolEventDispatcher>, block_limit: &ExecutionCost, + stacks_epoch_id: &StacksEpochId, ) -> Result<(), MemPoolRejection> { let estimator_result = cost_estimates::estimate_fee_rate( tx, self.cost_estimator.as_ref(), self.metric.as_ref(), block_limit, + stacks_epoch_id, ); let mut mempool_tx = self.tx_begin().map_err(MemPoolRejection::DBError)?; @@ -1279,6 +1284,7 @@ impl MemPoolDB { block_hash: &BlockHeaderHash, tx_bytes: Vec, block_limit: &ExecutionCost, + stacks_epoch_id: &StacksEpochId, ) -> Result<(), MemPoolRejection> { let tx = StacksTransaction::consensus_deserialize(&mut &tx_bytes[..]) .map_err(MemPoolRejection::DeserializationFailure)?; @@ -1288,6 +1294,7 @@ impl MemPoolDB { self.cost_estimator.as_ref(), self.metric.as_ref(), block_limit, + stacks_epoch_id, ); let mut mempool_tx = self.tx_begin().map_err(MemPoolRejection::DBError)?; diff --git a/src/cost_estimates/mod.rs b/src/cost_estimates/mod.rs index 129cfd05ab..fd481de13c 100644 --- a/src/cost_estimates/mod.rs +++ b/src/cost_estimates/mod.rs @@ -21,6 +21,7 @@ pub mod pessimistic; pub mod tests; use crate::chainstate::stacks::StacksTransaction; +use core::StacksEpochId; use self::metrics::CostMetric; pub use self::pessimistic::PessimisticEstimator; @@ -106,8 +107,9 @@ pub fn estimate_fee_rate( estimator: &CE, metric: &CM, block_limit: &ExecutionCost, + stacks_epoch_id: &StacksEpochId, ) -> Result { - let cost_estimate = estimator.estimate_cost(&tx.payload)?; + let cost_estimate = estimator.estimate_cost(&tx.payload, stacks_epoch_id)?; let metric_estimate = metric.from_cost_and_len(&cost_estimate, block_limit, tx.tx_len()); Ok(tx.get_tx_fee() as f64 / metric_estimate as f64) } @@ -128,19 +130,29 @@ pub trait CostEstimator: Send { tx: &TransactionPayload, actual_cost: &ExecutionCost, block_limit: &ExecutionCost, + evaluated_epoch: &StacksEpochId, ) -> Result<(), EstimatorError>; /// This method is used by a stacks-node to obtain an estimate for a given transaction payload. /// If the estimator cannot provide an accurate estimate for a given payload, it should return /// `EstimatorError::NoEstimateAvailable` - fn estimate_cost(&self, tx: &TransactionPayload) -> Result; + fn estimate_cost( + &self, + tx: &TransactionPayload, + evaluated_epoch: &StacksEpochId, + ) -> Result; /// This method is invoked by the `stacks-node` to notify the estimator of all the transaction /// receipts in a given block. /// /// A default implementation is provided to implementing structs that processes the transaction /// receipts by feeding them into `CostEstimator::notify_event()` - fn notify_block(&mut self, receipts: &[StacksTransactionReceipt], block_limit: &ExecutionCost) { + fn notify_block( + &mut self, + receipts: &[StacksTransactionReceipt], + block_limit: &ExecutionCost, + stacks_epoch_id: &StacksEpochId, + ) { // iterate over receipts, and for all the tx receipts, notify the event for current_receipt in receipts.iter() { let current_txid = match current_receipt.transaction { @@ -152,9 +164,12 @@ pub trait CostEstimator: Send { TransactionOrigin::Stacks(ref tx) => &tx.payload, }; - if let Err(e) = - self.notify_event(tx_payload, ¤t_receipt.execution_cost, block_limit) - { + if let Err(e) = self.notify_event( + tx_payload, + ¤t_receipt.execution_cost, + block_limit, + stacks_epoch_id, + ) { info!("CostEstimator failed to process event"; "txid" => %current_txid, "error" => %e, @@ -225,11 +240,16 @@ impl CostEstimator for () { _tx: &TransactionPayload, _actual_cost: &ExecutionCost, _block_limit: &ExecutionCost, + _evaluated_epoch: &StacksEpochId, ) -> Result<(), EstimatorError> { Ok(()) } - fn estimate_cost(&self, _tx: &TransactionPayload) -> Result { + fn estimate_cost( + &self, + _tx: &TransactionPayload, + _evaluated_epoch: &StacksEpochId, + ) -> Result { Err(EstimatorError::NoEstimateAvailable) } } @@ -261,11 +281,16 @@ impl CostEstimator for UnitEstimator { _tx: &TransactionPayload, _actual_cost: &ExecutionCost, _block_limit: &ExecutionCost, + _evaluated_epoch: &StacksEpochId, ) -> Result<(), EstimatorError> { Ok(()) } - fn estimate_cost(&self, _tx: &TransactionPayload) -> Result { + fn estimate_cost( + &self, + _tx: &TransactionPayload, + _evaluated_epoch: &StacksEpochId, + ) -> Result { Ok(ExecutionCost { write_length: 1, write_count: 1, diff --git a/src/cost_estimates/pessimistic.rs b/src/cost_estimates/pessimistic.rs index 325577b871..3467ceef3d 100644 --- a/src/cost_estimates/pessimistic.rs +++ b/src/cost_estimates/pessimistic.rs @@ -18,6 +18,8 @@ use crate::util::db::sql_pragma; use crate::util::db::table_exists; use crate::util::db::tx_begin_immediate_sqlite; +use crate::core::StacksEpochId; + use super::{CostEstimator, EstimatorError}; /// This struct pessimistically estimates the `ExecutionCost` of transaction payloads. @@ -215,11 +217,24 @@ impl PessimisticEstimator { Ok(()) } - fn get_estimate_key(tx: &TransactionPayload, field: &CostField) -> String { + fn get_estimate_key( + tx: &TransactionPayload, + field: &CostField, + evaluated_epoch: &StacksEpochId, + ) -> String { let tx_descriptor = match tx { TransactionPayload::TokenTransfer(..) => "stx-transfer".to_string(), TransactionPayload::ContractCall(cc) => { - format!("cc:{}.{}", cc.contract_name, cc.function_name) + // Epoch key is "" before Epoch2_05 for backwards compatibility. + let epoch_marker = match evaluated_epoch { + StacksEpochId::Epoch10 => "", + StacksEpochId::Epoch20 => "", + StacksEpochId::Epoch2_05 => ":2.05", + }; + format!( + "cc{}:{}.{}", + epoch_marker, cc.contract_name, cc.function_name + ) } TransactionPayload::SmartContract(_sc) => "contract-publish".to_string(), TransactionPayload::PoisonMicroblock(_, _) => "poison-ublock".to_string(), @@ -242,23 +257,24 @@ impl CostEstimator for PessimisticEstimator { tx: &TransactionPayload, actual_cost: &ExecutionCost, block_limit: &ExecutionCost, + evaluated_epoch: &StacksEpochId, ) -> Result<(), EstimatorError> { if self.log_error { // only log the estimate error if an estimate could be constructed - if let Ok(estimated_cost) = self.estimate_cost(tx) { + if let Ok(estimated_cost) = self.estimate_cost(tx, evaluated_epoch) { let estimated_scalar = estimated_cost.proportion_dot_product(&block_limit, PROPORTION_RESOLUTION); let actual_scalar = actual_cost.proportion_dot_product(&block_limit, PROPORTION_RESOLUTION); info!("PessimisticEstimator received event"; - "key" => %PessimisticEstimator::get_estimate_key(tx, &CostField::RuntimeCost), + "key" => %PessimisticEstimator::get_estimate_key(tx, &CostField::RuntimeCost, evaluated_epoch), "estimate" => estimated_scalar, "actual" => actual_scalar, "estimate_err" => (estimated_scalar as i64 - actual_scalar as i64), "estimate_err_pct" => (estimated_scalar as i64 - actual_scalar as i64)/(cmp::max(1, actual_scalar as i64)),); for field in CostField::ALL.iter() { info!("New data event received"; - "key" => %PessimisticEstimator::get_estimate_key(tx, field), + "key" => %PessimisticEstimator::get_estimate_key(tx, field, evaluated_epoch), "value" => field.select_key(actual_cost)); } } @@ -266,7 +282,7 @@ impl CostEstimator for PessimisticEstimator { let sql_tx = tx_begin_immediate_sqlite(&mut self.db)?; for field in CostField::ALL.iter() { - let key = PessimisticEstimator::get_estimate_key(tx, field); + let key = PessimisticEstimator::get_estimate_key(tx, field, evaluated_epoch); let field_cost = field.select_key(actual_cost); let mut current_sample = Samples::get_sqlite(&sql_tx, &key); current_sample.update_with(field_cost); @@ -276,30 +292,34 @@ impl CostEstimator for PessimisticEstimator { Ok(()) } - fn estimate_cost(&self, tx: &TransactionPayload) -> Result { + fn estimate_cost( + &self, + tx: &TransactionPayload, + evaluated_epoch: &StacksEpochId, + ) -> Result { let runtime = Samples::get_estimate_sqlite( &self.db, - &PessimisticEstimator::get_estimate_key(tx, &CostField::RuntimeCost), + &PessimisticEstimator::get_estimate_key(tx, &CostField::RuntimeCost, evaluated_epoch), ) .ok_or_else(|| EstimatorError::NoEstimateAvailable)?; let read_count = Samples::get_estimate_sqlite( &self.db, - &PessimisticEstimator::get_estimate_key(tx, &CostField::ReadCount), + &PessimisticEstimator::get_estimate_key(tx, &CostField::ReadCount, evaluated_epoch), ) .ok_or_else(|| EstimatorError::NoEstimateAvailable)?; let read_length = Samples::get_estimate_sqlite( &self.db, - &PessimisticEstimator::get_estimate_key(tx, &CostField::ReadLength), + &PessimisticEstimator::get_estimate_key(tx, &CostField::ReadLength, evaluated_epoch), ) .ok_or_else(|| EstimatorError::NoEstimateAvailable)?; let write_count = Samples::get_estimate_sqlite( &self.db, - &PessimisticEstimator::get_estimate_key(tx, &CostField::WriteCount), + &PessimisticEstimator::get_estimate_key(tx, &CostField::WriteCount, evaluated_epoch), ) .ok_or_else(|| EstimatorError::NoEstimateAvailable)?; let write_length = Samples::get_estimate_sqlite( &self.db, - &PessimisticEstimator::get_estimate_key(tx, &CostField::WriteLength), + &PessimisticEstimator::get_estimate_key(tx, &CostField::WriteLength, evaluated_epoch), ) .ok_or_else(|| EstimatorError::NoEstimateAvailable)?; diff --git a/src/cost_estimates/tests/cost_estimators.rs b/src/cost_estimates/tests/cost_estimators.rs index d8cfb56c49..d6e7203cd3 100644 --- a/src/cost_estimates/tests/cost_estimators.rs +++ b/src/cost_estimates/tests/cost_estimators.rs @@ -67,7 +67,7 @@ fn test_empty_pessimistic_estimator() { let estimator = instantiate_test_db(); assert_eq!( estimator - .estimate_cost(&make_dummy_transfer_payload()) + .estimate_cost(&make_dummy_transfer_payload(), &StacksEpochId::Epoch20) .expect_err("Empty pessimistic estimator should error."), EstimatorError::NoEstimateAvailable ); @@ -191,11 +191,14 @@ fn test_cost_estimator_notify_block() { }, ), ]; - estimator.notify_block(&block, &BLOCK_LIMIT_MAINNET_20); + estimator.notify_block(&block, &BLOCK_LIMIT_MAINNET_20, &StacksEpochId::Epoch20); assert_eq!( estimator - .estimate_cost(&make_dummy_cc_payload("contract-1", "func1")) + .estimate_cost( + &make_dummy_cc_payload("contract-1", "func1"), + &StacksEpochId::Epoch20 + ) .expect("Should be able to provide cost estimate now"), ExecutionCost { write_length: 10, @@ -227,12 +230,16 @@ fn test_pessimistic_cost_estimator_declining_average() { runtime: 10, }, &BLOCK_LIMIT_MAINNET_20, + &StacksEpochId::Epoch20, ) .expect("Should be able to process event"); assert_eq!( estimator - .estimate_cost(&make_dummy_cc_payload("contract-1", "func1")) + .estimate_cost( + &make_dummy_cc_payload("contract-1", "func1"), + &StacksEpochId::Epoch20 + ) .expect("Should be able to provide cost estimate now"), ExecutionCost { write_length: 10, @@ -254,12 +261,16 @@ fn test_pessimistic_cost_estimator_declining_average() { runtime: 1, }, &BLOCK_LIMIT_MAINNET_20, + &StacksEpochId::Epoch20, ) .expect("Should be able to process event"); assert_eq!( estimator - .estimate_cost(&make_dummy_cc_payload("contract-1", "func1")) + .estimate_cost( + &make_dummy_cc_payload("contract-1", "func1"), + &StacksEpochId::Epoch20, + ) .expect("Should be able to provide cost estimate now"), ExecutionCost { write_length: 5, @@ -290,12 +301,16 @@ fn test_pessimistic_cost_estimator() { runtime: 1, }, &BLOCK_LIMIT_MAINNET_20, + &StacksEpochId::Epoch20, ) .expect("Should be able to process event"); assert_eq!( estimator - .estimate_cost(&make_dummy_cc_payload("contract-1", "func1")) + .estimate_cost( + &make_dummy_cc_payload("contract-1", "func1"), + &StacksEpochId::Epoch20, + ) .expect("Should be able to provide cost estimate now"), ExecutionCost { write_length: 1, @@ -319,12 +334,16 @@ fn test_pessimistic_cost_estimator() { &make_dummy_cc_payload("contract-1", "func1"), &repeated_cost, &BLOCK_LIMIT_MAINNET_20, + &StacksEpochId::Epoch20, ) .expect("Should be able to process event"); assert_eq!( estimator - .estimate_cost(&make_dummy_cc_payload("contract-1", "func1")) + .estimate_cost( + &make_dummy_cc_payload("contract-1", "func1"), + &StacksEpochId::Epoch20, + ) .expect("Should be able to provide cost estimate now"), ExecutionCost { write_length: 5, @@ -340,6 +359,7 @@ fn test_pessimistic_cost_estimator() { &make_dummy_cc_payload("contract-1", "func1"), &repeated_cost, &BLOCK_LIMIT_MAINNET_20, + &StacksEpochId::Epoch20, ) .expect("Should be able to process event"); @@ -349,7 +369,10 @@ fn test_pessimistic_cost_estimator() { // 3 * 2 + 1 = 7 / 3 assert_eq!( estimator - .estimate_cost(&make_dummy_cc_payload("contract-1", "func1")) + .estimate_cost( + &make_dummy_cc_payload("contract-1", "func1"), + &StacksEpochId::Epoch20, + ) .expect("Should be able to provide cost estimate now"), ExecutionCost { write_length: 6, @@ -365,6 +388,7 @@ fn test_pessimistic_cost_estimator() { &make_dummy_cc_payload("contract-1", "func1"), &repeated_cost, &BLOCK_LIMIT_MAINNET_20, + &StacksEpochId::Epoch20, ) .expect("Should be able to process event"); @@ -374,7 +398,10 @@ fn test_pessimistic_cost_estimator() { // 3 * 3 + 1 = 10 / 4 assert_eq!( estimator - .estimate_cost(&make_dummy_cc_payload("contract-1", "func1")) + .estimate_cost( + &make_dummy_cc_payload("contract-1", "func1"), + &StacksEpochId::Epoch20, + ) .expect("Should be able to provide cost estimate now"), ExecutionCost { write_length: 7, @@ -390,6 +417,7 @@ fn test_pessimistic_cost_estimator() { &make_dummy_cc_payload("contract-1", "func1"), &repeated_cost, &BLOCK_LIMIT_MAINNET_20, + &StacksEpochId::Epoch20, ) .expect("Should be able to process event"); @@ -399,7 +427,10 @@ fn test_pessimistic_cost_estimator() { // 3 * 4 + 1 = 13 / 5 assert_eq!( estimator - .estimate_cost(&make_dummy_cc_payload("contract-1", "func1")) + .estimate_cost( + &make_dummy_cc_payload("contract-1", "func1"), + &StacksEpochId::Epoch20, + ) .expect("Should be able to provide cost estimate now"), ExecutionCost { write_length: 7, @@ -415,6 +446,7 @@ fn test_pessimistic_cost_estimator() { &make_dummy_cc_payload("contract-1", "func1"), &repeated_cost, &BLOCK_LIMIT_MAINNET_20, + &StacksEpochId::Epoch20, ) .expect("Should be able to process event"); @@ -424,7 +456,10 @@ fn test_pessimistic_cost_estimator() { // 3 * 5 + 1 = 16 / 6 assert_eq!( estimator - .estimate_cost(&make_dummy_cc_payload("contract-1", "func1")) + .estimate_cost( + &make_dummy_cc_payload("contract-1", "func1"), + &StacksEpochId::Epoch20, + ) .expect("Should be able to provide cost estimate now"), ExecutionCost { write_length: 7, @@ -440,6 +475,7 @@ fn test_pessimistic_cost_estimator() { &make_dummy_cc_payload("contract-1", "func1"), &repeated_cost, &BLOCK_LIMIT_MAINNET_20, + &StacksEpochId::Epoch20, ) .expect("Should be able to process event"); @@ -449,7 +485,10 @@ fn test_pessimistic_cost_estimator() { // 3 * 6 + 1 = 19 / 7 assert_eq!( estimator - .estimate_cost(&make_dummy_cc_payload("contract-1", "func1")) + .estimate_cost( + &make_dummy_cc_payload("contract-1", "func1"), + &StacksEpochId::Epoch20, + ) .expect("Should be able to provide cost estimate now"), ExecutionCost { write_length: 7, @@ -465,6 +504,7 @@ fn test_pessimistic_cost_estimator() { &make_dummy_cc_payload("contract-1", "func1"), &repeated_cost, &BLOCK_LIMIT_MAINNET_20, + &StacksEpochId::Epoch20, ) .expect("Should be able to process event"); @@ -474,7 +514,10 @@ fn test_pessimistic_cost_estimator() { // 3 * 7 + 1 = 22 / 8 assert_eq!( estimator - .estimate_cost(&make_dummy_cc_payload("contract-1", "func1")) + .estimate_cost( + &make_dummy_cc_payload("contract-1", "func1"), + &StacksEpochId::Epoch20, + ) .expect("Should be able to provide cost estimate now"), ExecutionCost { write_length: 8, @@ -490,6 +533,7 @@ fn test_pessimistic_cost_estimator() { &make_dummy_cc_payload("contract-1", "func1"), &repeated_cost, &BLOCK_LIMIT_MAINNET_20, + &StacksEpochId::Epoch20, ) .expect("Should be able to process event"); @@ -499,7 +543,10 @@ fn test_pessimistic_cost_estimator() { // 3 * 8 + 1 = 25 / 9 assert_eq!( estimator - .estimate_cost(&make_dummy_cc_payload("contract-1", "func1")) + .estimate_cost( + &make_dummy_cc_payload("contract-1", "func1"), + &StacksEpochId::Epoch20, + ) .expect("Should be able to provide cost estimate now"), ExecutionCost { write_length: 8, @@ -515,6 +562,7 @@ fn test_pessimistic_cost_estimator() { &make_dummy_cc_payload("contract-1", "func1"), &repeated_cost, &BLOCK_LIMIT_MAINNET_20, + &StacksEpochId::Epoch20, ) .expect("Should be able to process event"); @@ -524,7 +572,10 @@ fn test_pessimistic_cost_estimator() { // 3 * 9 + 1 = 28 / 10 assert_eq!( estimator - .estimate_cost(&make_dummy_cc_payload("contract-1", "func1")) + .estimate_cost( + &make_dummy_cc_payload("contract-1", "func1"), + &StacksEpochId::Epoch20, + ) .expect("Should be able to provide cost estimate now"), ExecutionCost { write_length: 8, @@ -543,13 +594,17 @@ fn test_pessimistic_cost_estimator() { &make_dummy_cc_payload("contract-1", "func1"), &repeated_cost, &BLOCK_LIMIT_MAINNET_20, + &StacksEpochId::Epoch20, ) .expect("Should be able to process event"); // should just be equal to the repeated cost, because all of the costs in the window are equal assert_eq!( estimator - .estimate_cost(&make_dummy_cc_payload("contract-1", "func1")) + .estimate_cost( + &make_dummy_cc_payload("contract-1", "func1"), + &StacksEpochId::Epoch20, + ) .expect("Should be able to provide cost estimate now"), ExecutionCost { write_length: 9, @@ -571,6 +626,7 @@ fn test_pessimistic_cost_estimator() { runtime: 1, }, &BLOCK_LIMIT_MAINNET_20, + &StacksEpochId::Epoch20, ) .expect("Should be able to process event"); @@ -578,7 +634,10 @@ fn test_pessimistic_cost_estimator() { // by the pessimistic estimator assert_eq!( estimator - .estimate_cost(&make_dummy_cc_payload("contract-1", "func1")) + .estimate_cost( + &make_dummy_cc_payload("contract-1", "func1"), + &StacksEpochId::Epoch20, + ) .expect("Should be able to provide cost estimate now"), ExecutionCost { write_length: 9, @@ -589,3 +648,164 @@ fn test_pessimistic_cost_estimator() { } ); } + +/// Test that we forget the "learnings" from previous Stacks epoch on next epoch. +#[test] +fn test_cost_estimator_forget_previous() { + // Setup: Do "notify" in Epoch20. + let mut estimator = instantiate_test_db(); + let block = vec![make_dummy_cc_tx( + "contract-1", + "func1", + ExecutionCost { + write_length: 10, + write_count: 10, + read_length: 10, + read_count: 10, + runtime: 10, + }, + )]; + estimator.notify_block(&block, &BLOCK_LIMIT_MAINNET_20, &StacksEpochId::Epoch20); + + // Test 1: We should get *non-zero* estimates back when we test in Epoch20. + assert_eq!( + estimator + .estimate_cost( + &make_dummy_cc_payload("contract-1", "func1"), + &StacksEpochId::Epoch20 + ) + .expect("Should be able to provide cost estimate now"), + ExecutionCost { + write_length: 10, + write_count: 10, + read_length: 10, + read_count: 10, + runtime: 10, + } + ); + + // Test 2: We should get *zero* estimates back when we test in Epoch2_05. + assert_eq!( + estimator + .estimate_cost( + &make_dummy_cc_payload("contract-1", "func1"), + &StacksEpochId::Epoch2_05 + ) + .unwrap_err(), + EstimatorError::NoEstimateAvailable + ); +} + +/// Test that data from a later epoch doesn't affect an earlier one. +#[test] +fn test_cost_estimator_dont_affect_previous() { + // Setup: Do "notify" in Epoch2_05. + let mut estimator = instantiate_test_db(); + let block = vec![make_dummy_cc_tx( + "contract-1", + "func1", + ExecutionCost { + write_length: 10, + write_count: 10, + read_length: 10, + read_count: 10, + runtime: 10, + }, + )]; + estimator.notify_block(&block, &BLOCK_LIMIT_MAINNET_20, &StacksEpochId::Epoch2_05); + + // Test 1: We should get *non-zero* estimates back when we test in Epoch2_05. + assert_eq!( + estimator + .estimate_cost( + &make_dummy_cc_payload("contract-1", "func1"), + &StacksEpochId::Epoch2_05 + ) + .expect("Should be able to provide cost estimate now"), + ExecutionCost { + write_length: 10, + write_count: 10, + read_length: 10, + read_count: 10, + runtime: 10, + } + ); + + // Test 2: We should get *zero* estimates back when we test in Epoch20. + assert_eq!( + estimator + .estimate_cost( + &make_dummy_cc_payload("contract-1", "func1"), + &StacksEpochId::Epoch20 + ) + .unwrap_err(), + EstimatorError::NoEstimateAvailable + ); +} + +/// Test that updates to Stacks 2.0 and Stacks 2.05 can be recorded and recovered independently. +#[test] +fn test_cost_estimator_epochs_independent() { + let contract_name = "contract-1"; + let func_name = "func1"; + let cost_200 = ExecutionCost { + write_length: 200, + write_count: 200, + read_length: 200, + read_count: 200, + runtime: 200, + }; + let cost_205 = ExecutionCost { + write_length: 205, + write_count: 205, + read_length: 205, + read_count: 205, + runtime: 205, + }; + let mut estimator = instantiate_test_db(); + + // Setup: "notify" cost_200 in Epoch20. + estimator.notify_block( + &vec![make_dummy_cc_tx( + &contract_name, + &func_name, + cost_200.clone(), + )], + &BLOCK_LIMIT_MAINNET_20, + &StacksEpochId::Epoch20, + ); + + // Setup: "notify" cost_205 in Epoch2_05. + estimator.notify_block( + &vec![ + make_dummy_coinbase_tx(), + make_dummy_transfer_tx(), + make_dummy_transfer_tx(), + make_dummy_cc_tx(&contract_name, &func_name, cost_205.clone()), + ], + &BLOCK_LIMIT_MAINNET_20, + &StacksEpochId::Epoch2_05, + ); + + // Check: We get back cost_200 for Epoch20. + assert_eq!( + estimator + .estimate_cost( + &make_dummy_cc_payload("contract-1", "func1"), + &StacksEpochId::Epoch20 + ) + .expect("Should be able to provide cost estimate now"), + cost_200.clone(), + ); + + // Check: We get back cost_205 for Epoch2_05. + assert_eq!( + estimator + .estimate_cost( + &make_dummy_cc_payload("contract-1", "func1"), + &StacksEpochId::Epoch2_05 + ) + .expect("Should be able to provide cost estimate now"), + cost_205.clone(), + ); +} diff --git a/src/net/p2p.rs b/src/net/p2p.rs index cb0699b430..072d22d134 100644 --- a/src/net/p2p.rs +++ b/src/net/p2p.rs @@ -4427,6 +4427,7 @@ impl PeerNetwork { &tx, event_observer, &stacks_epoch.block_limit, + &stacks_epoch.epoch_id, ) { warn!("Transaction rejected from mempool, {}", &e.into_json(&txid)); return false; diff --git a/src/net/rpc.rs b/src/net/rpc.rs index 160d017fed..8af14bed49 100644 --- a/src/net/rpc.rs +++ b/src/net/rpc.rs @@ -1609,8 +1609,17 @@ impl ConversationHttp { estimated_len: u64, ) -> Result<(), net_error> { let response_metadata = HttpResponseMetadata::from(req); + let tip = SortitionDB::get_canonical_burn_chain_tip(sortdb.conn())?; + let stacks_epoch = SortitionDB::get_stacks_epoch(sortdb.conn(), tip.block_height)? + .ok_or_else(|| { + warn!( + "Failed to get fee rate estimate because could not load Stacks epoch for canonical burn height = {}", + tip.block_height + ); + net_error::ChainstateError("Could not load Stacks epoch for canonical burn height".into()) + })?; if let Some((cost_estimator, fee_estimator, metric)) = handler_args.get_estimators_ref() { - let estimated_cost = match cost_estimator.estimate_cost(tx) { + let estimated_cost = match cost_estimator.estimate_cost(tx, &stacks_epoch.epoch_id) { Ok(x) => x, Err(e) => { debug!( @@ -1622,18 +1631,6 @@ impl ConversationHttp { } }; - let tip = SortitionDB::get_canonical_burn_chain_tip(sortdb.conn())?; - let stacks_epoch = sortdb - .index_conn() - .get_stacks_epoch(tip.block_height as u32) - .ok_or_else(|| { - warn!( - "Failed to get fee rate estimate because could not load Stacks epoch for canonical burn height = {}", - tip.block_height - ); - net_error::ChainstateError("Could not load Stacks epoch for canonical burn height".into()) - })?; - let scalar_cost = metric.from_cost_and_len(&estimated_cost, &stacks_epoch.block_limit, estimated_len); let fee_rates = match fee_estimator.get_rate_estimates() { @@ -1727,6 +1724,7 @@ impl ConversationHttp { &tx, event_observer, &stacks_epoch.block_limit, + &stacks_epoch.epoch_id, ) { Ok(_) => { debug!("Mempool accepted POSTed transaction {}", &txid); diff --git a/testnet/stacks-node/src/neon_node.rs b/testnet/stacks-node/src/neon_node.rs index 221a60d9a3..d463b114bc 100644 --- a/testnet/stacks-node/src/neon_node.rs +++ b/testnet/stacks-node/src/neon_node.rs @@ -1852,6 +1852,7 @@ impl InitializedNeonNode { &poison_microblock_tx, Some(event_observer), &stacks_epoch.block_limit, + &stacks_epoch.epoch_id, ) { warn!( "Detected but failed to mine poison-microblock transaction: {:?}", diff --git a/testnet/stacks-node/src/node.rs b/testnet/stacks-node/src/node.rs index d8281c2a78..25140fb326 100644 --- a/testnet/stacks-node/src/node.rs +++ b/testnet/stacks-node/src/node.rs @@ -888,7 +888,11 @@ impl Node { .get_stacks_epoch_by_epoch_id(&processed_block.evaluated_epoch) .expect("Could not find a stacks epoch."); if let Some(estimator) = cost_estimator.as_mut() { - estimator.notify_block(&processed_block.tx_receipts, &stacks_epoch.block_limit); + estimator.notify_block( + &processed_block.tx_receipts, + &stacks_epoch.block_limit, + &stacks_epoch.epoch_id, + ); } if let Some(estimator) = fee_estimator.as_mut() { diff --git a/testnet/stacks-node/src/tests/bitcoin_regtest.rs b/testnet/stacks-node/src/tests/bitcoin_regtest.rs index 17db2ac45e..b13d07fa81 100644 --- a/testnet/stacks-node/src/tests/bitcoin_regtest.rs +++ b/testnet/stacks-node/src/tests/bitcoin_regtest.rs @@ -9,6 +9,7 @@ use stacks::chainstate::burn::operations::BlockstackOperationType::{ LeaderBlockCommit, LeaderKeyRegister, }; use stacks::chainstate::stacks::StacksPrivateKey; +use stacks::core::StacksEpochId; use stacks::util::hash::hex_bytes; use super::PUBLISH_CONTRACT; @@ -328,7 +329,8 @@ fn bitcoind_integration_test() { // ./blockstack-cli --testnet publish 043ff5004e3d695060fa48ac94c96049b8c14ef441c50a184a6a3875d2a000f3 0 0 store /tmp/out.clar let header_hash = chain_tip.block.block_hash(); let consensus_hash = chain_tip.metadata.consensus_hash; - tenure.mem_pool.submit_raw(&mut chainstate_copy, &consensus_hash, &header_hash, PUBLISH_CONTRACT.to_owned(), &ExecutionCost::max_value()).unwrap(); + tenure.mem_pool.submit_raw(&mut chainstate_copy, &consensus_hash, &header_hash, PUBLISH_CONTRACT.to_owned(), &ExecutionCost::max_value(), + &StacksEpochId::Epoch20,).unwrap(); }, 2 => { // On round 2, publish a "get:foo" transaction @@ -336,7 +338,8 @@ fn bitcoind_integration_test() { let header_hash = chain_tip.block.block_hash(); let consensus_hash = chain_tip.metadata.consensus_hash; let get_foo = "8080000000040021a3c334fc0ee50359353799e8b2605ac6be1fe40000000000000001000000000000000a0100b7ff8b6c20c427b4f4f09c1ad7e50027e2b076b2ddc0ab55e64ef5ea3771dd4763a79bc5a2b1a79b72ce03dd146ccf24b84942d675a815819a8b85aa8065dfaa030200000000021a21a3c334fc0ee50359353799e8b2605ac6be1fe40573746f7265096765742d76616c7565000000010d00000003666f6f"; - tenure.mem_pool.submit_raw(&mut chainstate_copy, &consensus_hash, &header_hash,hex_bytes(get_foo).unwrap().to_vec(), &ExecutionCost::max_value()).unwrap(); + tenure.mem_pool.submit_raw(&mut chainstate_copy, &consensus_hash, &header_hash,hex_bytes(get_foo).unwrap().to_vec(), &ExecutionCost::max_value(), + &StacksEpochId::Epoch20,).unwrap(); }, 3 => { // On round 3, publish a "set:foo=bar" transaction @@ -344,7 +347,8 @@ fn bitcoind_integration_test() { let header_hash = chain_tip.block.block_hash(); let consensus_hash = chain_tip.metadata.consensus_hash; let set_foo_bar = "8080000000040021a3c334fc0ee50359353799e8b2605ac6be1fe40000000000000002000000000000000a010142a01caf6a32b367664869182f0ebc174122a5a980937ba259d44cc3ebd280e769a53dd3913c8006ead680a6e1c98099fcd509ce94b0a4e90d9f4603b101922d030200000000021a21a3c334fc0ee50359353799e8b2605ac6be1fe40573746f7265097365742d76616c7565000000020d00000003666f6f0d00000003626172"; - tenure.mem_pool.submit_raw(&mut chainstate_copy, &consensus_hash, &header_hash,hex_bytes(set_foo_bar).unwrap().to_vec(), &ExecutionCost::max_value()).unwrap(); + tenure.mem_pool.submit_raw(&mut chainstate_copy, &consensus_hash, &header_hash,hex_bytes(set_foo_bar).unwrap().to_vec(), &ExecutionCost::max_value(), + &StacksEpochId::Epoch20,).unwrap(); }, 4 => { // On round 4, publish a "get:foo" transaction @@ -352,7 +356,8 @@ fn bitcoind_integration_test() { let header_hash = chain_tip.block.block_hash(); let consensus_hash = chain_tip.metadata.consensus_hash; let get_foo = "8080000000040021a3c334fc0ee50359353799e8b2605ac6be1fe40000000000000003000000000000000a010046c2c1c345231443fef9a1f64fccfef3e1deacc342b2ab5f97612bb3742aa799038b20aea456789aca6b883e52f84a31adfee0bc2079b740464877af8f2f87d2030200000000021a21a3c334fc0ee50359353799e8b2605ac6be1fe40573746f7265096765742d76616c7565000000010d00000003666f6f"; - tenure.mem_pool.submit_raw(&mut chainstate_copy, &consensus_hash, &header_hash,hex_bytes(get_foo).unwrap().to_vec(), &ExecutionCost::max_value()).unwrap(); + tenure.mem_pool.submit_raw(&mut chainstate_copy, &consensus_hash, &header_hash,hex_bytes(get_foo).unwrap().to_vec(), &ExecutionCost::max_value(), + &StacksEpochId::Epoch20,).unwrap(); }, 5 => { // On round 5, publish a stacks transaction @@ -360,7 +365,8 @@ fn bitcoind_integration_test() { let header_hash = chain_tip.block.block_hash(); let consensus_hash = chain_tip.metadata.consensus_hash; let transfer_1000_stx = "80800000000400b71a091b4b8b7661a661c620966ab6573bc2dcd30000000000000000000000000000000a0000393810832bacd44cfc4024980876135de6b95429bdb610d5ce96a92c9ee9bfd81ec77ea0f1748c8515fc9a1589e51d8b92bf028e3e84ade1249682c05271d5b803020000000000051a525b8a36ef8a73548cd0940c248d3b71ecf4a45100000000000003e800000000000000000000000000000000000000000000000000000000000000000000"; - tenure.mem_pool.submit_raw(&mut chainstate_copy, &consensus_hash, &header_hash,hex_bytes(transfer_1000_stx).unwrap().to_vec(), &ExecutionCost::max_value()).unwrap(); + tenure.mem_pool.submit_raw(&mut chainstate_copy, &consensus_hash, &header_hash,hex_bytes(transfer_1000_stx).unwrap().to_vec(), &ExecutionCost::max_value(), + &StacksEpochId::Epoch20,).unwrap(); }, _ => {} }; diff --git a/testnet/stacks-node/src/tests/integrations.rs b/testnet/stacks-node/src/tests/integrations.rs index 4bdae86f69..7b56fbfb92 100644 --- a/testnet/stacks-node/src/tests/integrations.rs +++ b/testnet/stacks-node/src/tests/integrations.rs @@ -219,6 +219,7 @@ fn integration_test_get_info() { &header_hash, publish_tx, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); let publish_tx = @@ -231,6 +232,7 @@ fn integration_test_get_info() { &header_hash, publish_tx, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); let publish_tx = @@ -243,6 +245,7 @@ fn integration_test_get_info() { &header_hash, publish_tx, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } else if round == 2 { @@ -263,6 +266,7 @@ fn integration_test_get_info() { &header_hash, publish_tx, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } else if round >= 3 { @@ -285,6 +289,7 @@ fn integration_test_get_info() { &header_hash, tx, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } @@ -305,6 +310,7 @@ fn integration_test_get_info() { &header_hash, tx_xfer, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } @@ -1066,6 +1072,7 @@ fn contract_stx_transfer() { &header_hash, xfer_to_contract, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } else if round == 2 { @@ -1080,6 +1087,7 @@ fn contract_stx_transfer() { &header_hash, publish_tx, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } else if round == 3 { @@ -1099,6 +1107,7 @@ fn contract_stx_transfer() { block_hash, publish_tx, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); @@ -1119,6 +1128,7 @@ fn contract_stx_transfer() { &header_hash, tx, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } else if round == 4 { @@ -1143,6 +1153,7 @@ fn contract_stx_transfer() { &xfer_to_contract, None, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } @@ -1160,6 +1171,7 @@ fn contract_stx_transfer() { &xfer_to_contract, None, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap_err() { @@ -1376,6 +1388,7 @@ fn mine_transactions_out_of_order() { &header_hash, xfer_to_contract, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } else if round == 2 { @@ -1389,6 +1402,7 @@ fn mine_transactions_out_of_order() { &header_hash, publish_tx, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } else if round == 3 { @@ -1402,6 +1416,7 @@ fn mine_transactions_out_of_order() { &header_hash, xfer_to_contract, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } else if round == 4 { @@ -1415,6 +1430,7 @@ fn mine_transactions_out_of_order() { &header_hash, xfer_to_contract, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } @@ -1517,6 +1533,7 @@ fn mine_contract_twice() { block_hash, publish_tx, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); @@ -1612,6 +1629,7 @@ fn bad_contract_tx_rollback() { block_hash, xfer_to_contract, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } else if round == 2 { @@ -1629,6 +1647,7 @@ fn bad_contract_tx_rollback() { block_hash, xfer_to_contract, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); @@ -1642,6 +1661,7 @@ fn bad_contract_tx_rollback() { block_hash, xfer_to_contract, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); @@ -1655,6 +1675,7 @@ fn bad_contract_tx_rollback() { block_hash, publish_tx, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); @@ -1668,6 +1689,7 @@ fn bad_contract_tx_rollback() { block_hash, publish_tx, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } @@ -1871,6 +1893,7 @@ fn block_limit_runtime_test() { block_hash, publish_tx, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } else if round > 1 { @@ -1899,6 +1922,7 @@ fn block_limit_runtime_test() { block_hash, tx, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } @@ -1984,6 +2008,7 @@ fn mempool_errors() { &header_hash, publish_tx, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } diff --git a/testnet/stacks-node/src/tests/mempool.rs b/testnet/stacks-node/src/tests/mempool.rs index 24f2d6888a..ba917a72cb 100644 --- a/testnet/stacks-node/src/tests/mempool.rs +++ b/testnet/stacks-node/src/tests/mempool.rs @@ -26,6 +26,7 @@ use stacks::{address::AddressHashMode, chainstate::stacks::TransactionAnchorMode use crate::helium::RunLoop; use crate::Keychain; +use stacks::core::StacksEpochId; use stacks::vm::costs::ExecutionCost; use super::{ @@ -123,6 +124,7 @@ fn mempool_setup_chainstate() { &header_hash, publish_tx1, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); @@ -136,6 +138,7 @@ fn mempool_setup_chainstate() { &header_hash, publish_tx2, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); @@ -154,6 +157,7 @@ fn mempool_setup_chainstate() { &header_hash, publish_tx3, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); @@ -172,6 +176,7 @@ fn mempool_setup_chainstate() { &header_hash, publish_tx4, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); @@ -190,6 +195,7 @@ fn mempool_setup_chainstate() { &header_hash, publish_tx4, &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ) .unwrap(); } diff --git a/testnet/stacks-node/src/tests/mod.rs b/testnet/stacks-node/src/tests/mod.rs index c3ec812a8f..582eb4090f 100644 --- a/testnet/stacks-node/src/tests/mod.rs +++ b/testnet/stacks-node/src/tests/mod.rs @@ -25,6 +25,7 @@ use stacks::vm::{ClarityName, ContractName, Value}; use stacks::{address::AddressHashMode, util::hash::to_hex}; use crate::helium::RunLoop; +use stacks::core::StacksEpochId; use super::burnchains::bitcoin_regtest_controller::ParsedUTXO; use super::Config; @@ -469,7 +470,8 @@ fn should_succeed_mining_valid_txs() { 1 => { // On round 1, publish the KV contract tenure.mem_pool.submit_raw(&mut chainstate_copy, &consensus_hash, &header_hash, PUBLISH_CONTRACT.to_owned(), - &ExecutionCost::max_value() + &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ).unwrap(); }, 2 => { @@ -477,7 +479,8 @@ fn should_succeed_mining_valid_txs() { // ./blockstack-cli --testnet contract-call 043ff5004e3d695060fa48ac94c96049b8c14ef441c50a184a6a3875d2a000f3 10 1 STGT7GSMZG7EA0TS6MVSKT5JC1DCDFGZWJJZXN8A store get-value -e \"foo\" let get_foo = "8080000000040021a3c334fc0ee50359353799e8b2605ac6be1fe40000000000000001000000000000000a0100b7ff8b6c20c427b4f4f09c1ad7e50027e2b076b2ddc0ab55e64ef5ea3771dd4763a79bc5a2b1a79b72ce03dd146ccf24b84942d675a815819a8b85aa8065dfaa030200000000021a21a3c334fc0ee50359353799e8b2605ac6be1fe40573746f7265096765742d76616c7565000000010d00000003666f6f"; tenure.mem_pool.submit_raw(&mut chainstate_copy, &consensus_hash, &header_hash,hex_bytes(get_foo).unwrap().to_vec(), - &ExecutionCost::max_value() + &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ).unwrap(); }, 3 => { @@ -485,7 +488,8 @@ fn should_succeed_mining_valid_txs() { // ./blockstack-cli --testnet contract-call 043ff5004e3d695060fa48ac94c96049b8c14ef441c50a184a6a3875d2a000f3 10 2 STGT7GSMZG7EA0TS6MVSKT5JC1DCDFGZWJJZXN8A store set-value -e \"foo\" -e \"bar\" let set_foo_bar = "8080000000040021a3c334fc0ee50359353799e8b2605ac6be1fe40000000000000002000000000000000a010142a01caf6a32b367664869182f0ebc174122a5a980937ba259d44cc3ebd280e769a53dd3913c8006ead680a6e1c98099fcd509ce94b0a4e90d9f4603b101922d030200000000021a21a3c334fc0ee50359353799e8b2605ac6be1fe40573746f7265097365742d76616c7565000000020d00000003666f6f0d00000003626172"; tenure.mem_pool.submit_raw(&mut chainstate_copy, &consensus_hash, &header_hash,hex_bytes(set_foo_bar).unwrap().to_vec(), - &ExecutionCost::max_value() + &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ).unwrap(); }, 4 => { @@ -493,7 +497,8 @@ fn should_succeed_mining_valid_txs() { // ./blockstack-cli --testnet contract-call 043ff5004e3d695060fa48ac94c96049b8c14ef441c50a184a6a3875d2a000f3 10 3 STGT7GSMZG7EA0TS6MVSKT5JC1DCDFGZWJJZXN8A store get-value -e \"foo\" let get_foo = "8080000000040021a3c334fc0ee50359353799e8b2605ac6be1fe40000000000000003000000000000000a010046c2c1c345231443fef9a1f64fccfef3e1deacc342b2ab5f97612bb3742aa799038b20aea456789aca6b883e52f84a31adfee0bc2079b740464877af8f2f87d2030200000000021a21a3c334fc0ee50359353799e8b2605ac6be1fe40573746f7265096765742d76616c7565000000010d00000003666f6f"; tenure.mem_pool.submit_raw(&mut chainstate_copy, &consensus_hash, &header_hash,hex_bytes(get_foo).unwrap().to_vec(), - &ExecutionCost::max_value() + &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ).unwrap(); }, 5 => { @@ -501,7 +506,8 @@ fn should_succeed_mining_valid_txs() { // ./blockstack-cli --testnet token-transfer b1cf9cee5083f421c84d7cb53be5edf2801c3c78d63d53917aee0bdc8bd160ee01 10 0 ST195Q2HPXY576N4CT2A0R94D7DRYSX54A5X3YZTH 1000 let transfer_1000_stx = "80800000000400b71a091b4b8b7661a661c620966ab6573bc2dcd30000000000000000000000000000000a0000393810832bacd44cfc4024980876135de6b95429bdb610d5ce96a92c9ee9bfd81ec77ea0f1748c8515fc9a1589e51d8b92bf028e3e84ade1249682c05271d5b803020000000000051a525b8a36ef8a73548cd0940c248d3b71ecf4a45100000000000003e800000000000000000000000000000000000000000000000000000000000000000000"; tenure.mem_pool.submit_raw(&mut chainstate_copy, &consensus_hash, &header_hash,hex_bytes(transfer_1000_stx).unwrap().to_vec(), - &ExecutionCost::max_value() + &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ).unwrap(); }, _ => {} @@ -758,7 +764,8 @@ fn should_succeed_handling_malformed_and_valid_txs() { let contract_sk = StacksPrivateKey::from_hex(SK_1).unwrap(); let publish_contract = make_contract_publish(&contract_sk, 0, 10, "store", STORE_CONTRACT); tenure.mem_pool.submit_raw(&mut chainstate_copy, &consensus_hash, &header_hash,publish_contract, - &ExecutionCost::max_value() + &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ).unwrap(); }, 2 => { @@ -767,7 +774,8 @@ fn should_succeed_handling_malformed_and_valid_txs() { // ./blockstack-cli contract-call 043ff5004e3d695060fa48ac94c96049b8c14ef441c50a184a6a3875d2a000f3 10 1 STGT7GSMZG7EA0TS6MVSKT5JC1DCDFGZWJJZXN8A store get-value -e \"foo\" let get_foo = "0000000001040021a3c334fc0ee50359353799e8b2605ac6be1fe40000000000000001000000000000000a0101ef2b00e7e55ee5cb7684d5313c7c49680c97e60cb29f0166798e6ffabd984a030cf0a7b919bcf5fa052efd5d9efd96b927213cb3af1cfb8d9c5a0be0fccda64d030200000000021a21a3c334fc0ee50359353799e8b2605ac6be1fe40573746f7265096765742d76616c7565000000010d00000003666f6f"; tenure.mem_pool.submit_raw(&mut chainstate_copy, &consensus_hash, &header_hash,hex_bytes(get_foo).unwrap().to_vec(), - &ExecutionCost::max_value() + &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ).unwrap(); }, 3 => { @@ -776,7 +784,8 @@ fn should_succeed_handling_malformed_and_valid_txs() { // ./blockstack-cli --testnet contract-call 043ff5004e3d695060fa48ac94c96049b8c14ef441c50a184a6a3875d2a000f3 10 1 STGT7GSMZG7EA0TS6MVSKT5JC1DCDFGZWJJZXN8A store set-value -e \"foo\" -e \"bar\" let set_foo_bar = "8080000000040021a3c334fc0ee50359353799e8b2605ac6be1fe40000000000000001000000000000000a010093f733efcebe2b239bb22e2e1ed25612547403af66b29282ed1f6fdfbbbf8f7f6ef107256d07947cbb72e165d723af99c447d6e25e7fbb6a92fd9a51c5ef7ee9030200000000021a21a3c334fc0ee50359353799e8b2605ac6be1fe40573746f7265097365742d76616c7565000000020d00000003666f6f0d00000003626172"; tenure.mem_pool.submit_raw(&mut chainstate_copy, &consensus_hash, &header_hash,hex_bytes(set_foo_bar).unwrap().to_vec(), - &ExecutionCost::max_value() + &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ).unwrap(); }, 4 => { @@ -784,7 +793,8 @@ fn should_succeed_handling_malformed_and_valid_txs() { // ./blockstack-cli --testnet contract-call 043ff5004e3d695060fa48ac94c96049b8c14ef441c50a184a6a3875d2a000f3 10 1 STGT7GSMZG7EA0TS6MVSKT5JC1DCDFGZWJJZXN8A store get-value -e \"foo\" let get_foo = "8080000000040021a3c334fc0ee50359353799e8b2605ac6be1fe40000000000000001000000000000000a0100b7ff8b6c20c427b4f4f09c1ad7e50027e2b076b2ddc0ab55e64ef5ea3771dd4763a79bc5a2b1a79b72ce03dd146ccf24b84942d675a815819a8b85aa8065dfaa030200000000021a21a3c334fc0ee50359353799e8b2605ac6be1fe40573746f7265096765742d76616c7565000000010d00000003666f6f"; tenure.mem_pool.submit_raw(&mut chainstate_copy, &consensus_hash, &header_hash,hex_bytes(get_foo).unwrap().to_vec(), - &ExecutionCost::max_value() + &ExecutionCost::max_value(), + &StacksEpochId::Epoch20, ).unwrap(); }, _ => {}