diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index b7142740..a3fc1c78 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -68,7 +68,7 @@ pub(super) const MAINNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)] (block::Height(653_600), Blossom), (block::Height(903_000), Heartwood), (block::Height(1_046_400), Canopy), - // TODO: Add Nu5 mainnet activation height (#4115) + (block::Height(1_687_104), Nu5), ]; /// Fake mainnet network upgrade activation heights, used in tests. diff --git a/zebra-consensus/src/transaction/tests.rs b/zebra-consensus/src/transaction/tests.rs index f4806048..db7c3eb8 100644 --- a/zebra-consensus/src/transaction/tests.rs +++ b/zebra-consensus/src/transaction/tests.rs @@ -279,9 +279,6 @@ async fn v5_transaction_is_rejected_before_nu5_activation() { } #[tokio::test] -// TODO: Remove `should_panic` once the NU5 activation height for mainnet has been -// defined. -#[should_panic] async fn v5_transaction_is_accepted_after_nu5_activation_mainnet() { v5_transaction_is_accepted_after_nu5_activation_for_network(Network::Mainnet).await } @@ -571,7 +568,15 @@ async fn v4_coinbase_transaction_with_exceeding_expiry_height() { service_fn(|_| async { unreachable!("State service should not be called") }); let verifier = Verifier::new(Network::Mainnet, state_service); - let block_height = block::Height::MAX; + // Use an arbitrary pre-NU5 block height. + // It can't be NU5-onward because the expiry height limit is not enforced + // for coinbase transactions (it needs to match the block height instead), + // which is what is used in this test. + let block_height = (NetworkUpgrade::Nu5 + .activation_height(Network::Mainnet) + .expect("NU5 height must be set") + - 1) + .expect("will not underflow"); let (input, output) = mock_coinbase_transparent_output(block_height); @@ -1059,6 +1064,7 @@ async fn v5_coinbase_transaction_expiry_height() { *new_transaction.expiry_height_mut() = new_expiry_height; let result = verifier + .clone() .oneshot(Request::Block { transaction: Arc::new(new_transaction.clone()), known_utxos: Arc::new(HashMap::new()), @@ -1075,6 +1081,29 @@ async fn v5_coinbase_transaction_expiry_height() { transaction_hash: new_transaction.hash(), }) ); + + // Test with matching heights again, but using a very high value + // that is greater than the limit for non-coinbase transactions, + // to ensure the limit is not being enforced for coinbase transactions. + let new_expiry_height = Height::MAX; + let mut new_transaction = transaction.clone(); + + *new_transaction.expiry_height_mut() = new_expiry_height; + + let result = verifier + .clone() + .oneshot(Request::Block { + transaction: Arc::new(new_transaction.clone()), + known_utxos: Arc::new(HashMap::new()), + height: new_expiry_height, + time: chrono::MAX_DATETIME, + }) + .await; + + assert_eq!( + result.expect("unexpected error response").tx_id(), + new_transaction.unmined_id() + ); } /// Tests if an expired non-coinbase V5 transaction is rejected. @@ -1170,52 +1199,6 @@ async fn v5_transaction_with_exceeding_expiry_height() { ); } -/// Tests if a coinbase V5 transaction with an expiry height exceeding the -/// maximum is rejected. -#[tokio::test] -async fn v5_coinbase_transaction_with_exceeding_expiry_height() { - let state_service = - service_fn(|_| async { unreachable!("State service should not be called") }); - let verifier = Verifier::new(Network::Mainnet, state_service); - - let block_height = block::Height::MAX; - - let (input, output) = mock_coinbase_transparent_output(block_height); - - // This expiry height exceeds the maximum defined by the specification. - let expiry_height = block::Height(500_000_000); - - // Create a coinbase V4 tx. - let transaction = Transaction::V5 { - inputs: vec![input], - outputs: vec![output], - lock_time: LockTime::unlocked(), - expiry_height, - sapling_shielded_data: None, - orchard_shielded_data: None, - network_upgrade: NetworkUpgrade::Nu5, - }; - - let result = verifier - .oneshot(Request::Block { - transaction: Arc::new(transaction.clone()), - known_utxos: Arc::new(HashMap::new()), - height: block_height, - time: chrono::MAX_DATETIME, - }) - .await; - - assert_eq!( - result, - Err(TransactionError::MaximumExpiryHeight { - expiry_height, - is_coinbase: true, - block_height, - transaction_hash: transaction.hash(), - }) - ); -} - /// Test if V5 coinbase transaction is accepted. #[tokio::test] async fn v5_coinbase_transaction_is_accepted() { diff --git a/zebra-network/src/constants.rs b/zebra-network/src/constants.rs index eb633023..5a15ceaa 100644 --- a/zebra-network/src/constants.rs +++ b/zebra-network/src/constants.rs @@ -249,9 +249,7 @@ pub const USER_AGENT: &str = "/Zebra:1.0.0-beta.9/"; /// /// The current protocol version typically changes before Mainnet and Testnet /// network upgrades. -// -// TODO: update to Nu5 mainnet (#4115) -pub const CURRENT_NETWORK_PROTOCOL_VERSION: Version = Version(170_050); +pub const CURRENT_NETWORK_PROTOCOL_VERSION: Version = Version(170_100); /// The default RTT estimate for peer responses. /// diff --git a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap index d1312835..d81c2efc 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap @@ -1,6 +1,5 @@ --- source: zebra-rpc/src/methods/tests/snapshot.rs -assertion_line: 177 expression: info --- { @@ -33,6 +32,11 @@ expression: info "name": "Canopy", "activationheight": 1046400, "status": "pending" + }, + "c2d6d0b4": { + "name": "Nu5", + "activationheight": 1687104, + "status": "pending" } }, "consensus": {