diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ccb9b5cac..eeb514f6b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE - `get-tenure-info?` added - `get-block-info?` removed - Added `/v3/signer/{signer_pubkey}/{reward_cycle}` endpoint +- Added `tenure_height` to `/v2/info` endpoint - Added optional `timeout_ms` to `events_observer` configuration ## [2.5.0.0.7] diff --git a/docs/rpc/api/core-node/get-info.example.json b/docs/rpc/api/core-node/get-info.example.json index afc42e6f68..77ece128c3 100644 --- a/docs/rpc/api/core-node/get-info.example.json +++ b/docs/rpc/api/core-node/get-info.example.json @@ -11,6 +11,7 @@ "stacks_tip": "b1807a2d3f7f8c7922f7c1d60d7c34145ade05d789640dc7dc9ec1021e07bb54", "stacks_tip_consensus_hash": "17f76e597bab45646956f38dd39573085d72cbc0", "unanchored_tip": "0000000000000000000000000000000000000000000000000000000000000000", + "tenure_height": 523, "exit_at_block_height": null, "is_fully_synced": false } diff --git a/docs/rpc/api/core-node/get-info.schema.json b/docs/rpc/api/core-node/get-info.schema.json index 16b560ed5e..e997a2d19c 100644 --- a/docs/rpc/api/core-node/get-info.schema.json +++ b/docs/rpc/api/core-node/get-info.schema.json @@ -17,6 +17,7 @@ "stacks_tip", "stacks_tip_consensus_hash", "unanchored_tip", + "tenure_height", "exit_at_block_height", "is_fully_synced" ], @@ -69,6 +70,10 @@ "type": "string", "description": "the latest microblock hash if any microblocks were processed. if no microblock has been processed for the current block, a 000.., hex array is returned" }, + "tenure_height": { + "type": "integer", + "description": "the latest Stacks tenure height" + }, "exit_at_block_height": { "type": "integer", "description": "the block height at which the testnet network will be reset. not applicable for mainnet" diff --git a/stacks-signer/src/client/mod.rs b/stacks-signer/src/client/mod.rs index 3fe9f09354..9885182d98 100644 --- a/stacks-signer/src/client/mod.rs +++ b/stacks-signer/src/client/mod.rs @@ -322,6 +322,7 @@ pub(crate) mod tests { stacks_tip_consensus_hash: generate_random_consensus_hash(), unanchored_tip: None, unanchored_seq: Some(0), + tenure_height: thread_rng().next_u64(), exit_at_block_height: None, is_fully_synced: false, genesis_chainstate_hash: Sha256Sum::zero(), diff --git a/stackslib/src/net/api/getinfo.rs b/stackslib/src/net/api/getinfo.rs index 237205f63a..d95b94803a 100644 --- a/stackslib/src/net/api/getinfo.rs +++ b/stackslib/src/net/api/getinfo.rs @@ -27,11 +27,12 @@ use stacks_common::util::hash::{Hash160, Sha256Sum}; use crate::burnchains::affirmation::AffirmationMap; use crate::burnchains::Txid; use crate::chainstate::burn::db::sortdb::SortitionDB; +use crate::chainstate::nakamoto::NakamotoChainState; use crate::chainstate::stacks::db::StacksChainState; use crate::core::mempool::MemPoolDB; use crate::net::http::{ parse_json, Error, HttpRequest, HttpRequestContents, HttpRequestPreamble, HttpResponse, - HttpResponseContents, HttpResponsePayload, HttpResponsePreamble, + HttpResponseContents, HttpResponsePayload, HttpResponsePreamble, HttpServerError, }; use crate::net::httpcore::{ HttpPreambleExtensions, RPCRequestHandler, StacksHttpRequest, StacksHttpResponse, @@ -81,6 +82,7 @@ pub struct RPCPeerInfoData { pub genesis_chainstate_hash: Sha256Sum, pub unanchored_tip: Option, pub unanchored_seq: Option, + pub tenure_height: u64, pub exit_at_block_height: Option, pub is_fully_synced: bool, #[serde(default)] @@ -106,6 +108,7 @@ impl RPCPeerInfoData { chainstate: &StacksChainState, exit_at_block_height: Option, genesis_chainstate_hash: &Sha256Sum, + coinbase_height: u64, ibd: bool, ) -> RPCPeerInfoData { let server_version = version_string( @@ -148,7 +151,7 @@ impl RPCPeerInfoData { stacks_tip_consensus_hash: network.stacks_tip.consensus_hash.clone(), unanchored_tip: unconfirmed_tip, unanchored_seq: unconfirmed_seq, - exit_at_block_height: exit_at_block_height, + exit_at_block_height, is_fully_synced, genesis_chainstate_hash: genesis_chainstate_hash.clone(), node_public_key: Some(public_key_buf), @@ -169,6 +172,7 @@ impl RPCPeerInfoData { .map(|cid| format!("{}", cid)) .collect(), ), + tenure_height: coinbase_height, } } } @@ -217,16 +221,28 @@ impl RPCRequestHandler for RPCPeerInfoRequestHandler { node: &mut StacksNodeState, ) -> Result<(HttpResponsePreamble, HttpResponseContents), NetError> { let ibd = node.ibd; - let rpc_peer_info = + + let rpc_peer_info: Result = node.with_node_state(|network, _sortdb, chainstate, _mempool, rpc_args| { - RPCPeerInfoData::from_network( + let coinbase_height = network.stacks_tip.coinbase_height; + + Ok(RPCPeerInfoData::from_network( network, chainstate, rpc_args.exit_at_block_height.clone(), &rpc_args.genesis_chainstate_hash, + coinbase_height, ibd, - ) + )) }); + + let rpc_peer_info = match rpc_peer_info { + Ok(rpc_peer_info) => rpc_peer_info, + Err(response) => { + return response.try_into_contents().map_err(NetError::from); + } + }; + let mut preamble = HttpResponsePreamble::ok_json(&preamble); preamble.set_canonical_stacks_tip_height(Some(node.canonical_stacks_tip_height())); let body = HttpResponseContents::try_from_json(&rpc_peer_info)?; diff --git a/stackslib/src/net/api/postmempoolquery.rs b/stackslib/src/net/api/postmempoolquery.rs index 2155863220..25da52a66d 100644 --- a/stackslib/src/net/api/postmempoolquery.rs +++ b/stackslib/src/net/api/postmempoolquery.rs @@ -116,9 +116,9 @@ impl StacksMemPoolStream { Self { tx_query, - last_randomized_txid: last_randomized_txid, + last_randomized_txid, num_txs: 0, - max_txs: max_txs, + max_txs, coinbase_height, corked: false, finished: false, @@ -275,14 +275,8 @@ impl RPCRequestHandler for RPCMempoolQueryRequestHandler { .ok_or(NetError::SendError("`mempool_query` not set".into()))?; let page_id = self.page_id.take(); - let stream_res = node.with_node_state(|network, sortdb, chainstate, mempool, _rpc_args| { - let header = self.get_stacks_chain_tip(&preamble, sortdb, chainstate) - .map_err(|e| StacksHttpResponse::new_error(&preamble, &HttpServerError::new(format!("Failed to load chain tip: {:?}", &e))))?; - - let coinbase_height = NakamotoChainState::get_coinbase_height(&mut chainstate.index_conn(), &header.index_block_hash()) - .map_err(|e| StacksHttpResponse::new_error(&preamble, &HttpServerError::new(format!("Failed to load coinbase height: {:?}", &e))))? - .unwrap_or(0); - + let stream_res = node.with_node_state(|network, _sortdb, _chainstate, mempool, _rpc_args| { + let coinbase_height = network.stacks_tip.coinbase_height; let max_txs = network.connection_opts.mempool_max_tx_query; debug!( "Begin mempool query"; diff --git a/stackslib/src/net/api/tests/getinfo.rs b/stackslib/src/net/api/tests/getinfo.rs index 7d8aeff01c..89054e3453 100644 --- a/stackslib/src/net/api/tests/getinfo.rs +++ b/stackslib/src/net/api/tests/getinfo.rs @@ -50,7 +50,7 @@ fn test_try_parse_request() { .try_parse_request(&parsed_preamble.expect_request(), &bytes[offset..]) .unwrap(); - // parsed request consumes headers that would not be in a constructed reqeuest + // parsed request consumes headers that would not be in a constructed request parsed_request.clear_headers(); parsed_request.add_header( "X-Canonical-Stacks-Tip-Height".to_string(), @@ -63,10 +63,10 @@ fn test_try_parse_request() { #[test] fn test_getinfo_compat() { - let old_getinfo_json = r#"{"peer_version":402653189,"pox_consensus":"b712eb731b613eebae814a8f416c5c15bc8391ec","burn_block_height":727631,"stable_pox_consensus":"53b5ed79842080500d7d83daa36aa1069dedf983","stable_burn_block_height":727624,"server_version":"stacks-node 0.0.1 (feat/faster-inv-generation:68f33190a, release build, linux [x86_64])","network_id":1,"parent_network_id":3652501241,"stacks_tip_height":52537,"stacks_tip":"b3183f2ac588e12319ff0fde78f97e62c92a218d87828c35710c29aaf7adbedc","stacks_tip_consensus_hash":"b712eb731b613eebae814a8f416c5c15bc8391ec","genesis_chainstate_hash":"74237aa39aa50a83de11a4f53e9d3bb7d43461d1de9873f402e5453ae60bc59b","unanchored_tip":"e76f68d607480e9984b4062b2691fb60a88423177898f5780b40ace17ae8982a","unanchored_seq":0,"exit_at_block_height":null,"is_fully_synced":false}"#; - let getinfo_no_pubkey_hash_json = r#"{"peer_version":402653189,"pox_consensus":"b712eb731b613eebae814a8f416c5c15bc8391ec","burn_block_height":727631,"stable_pox_consensus":"53b5ed79842080500d7d83daa36aa1069dedf983","stable_burn_block_height":727624,"server_version":"stacks-node 0.0.1 (feat/faster-inv-generation:68f33190a, release build, linux [x86_64])","network_id":1,"parent_network_id":3652501241,"stacks_tip_height":52537,"stacks_tip":"b3183f2ac588e12319ff0fde78f97e62c92a218d87828c35710c29aaf7adbedc","stacks_tip_consensus_hash":"b712eb731b613eebae814a8f416c5c15bc8391ec","genesis_chainstate_hash":"74237aa39aa50a83de11a4f53e9d3bb7d43461d1de9873f402e5453ae60bc59b","unanchored_tip":"e76f68d607480e9984b4062b2691fb60a88423177898f5780b40ace17ae8982a","unanchored_seq":0,"exit_at_block_height":null,"is_fully_synced":false,"node_public_key":"029b27d345e7bd2a6627262cefe6e97d9bc482f41ec32ec76a7bec391bb441798d"}"#; - let getinfo_no_pubkey_json = r#"{"peer_version":402653189,"pox_consensus":"b712eb731b613eebae814a8f416c5c15bc8391ec","burn_block_height":727631,"stable_pox_consensus":"53b5ed79842080500d7d83daa36aa1069dedf983","stable_burn_block_height":727624,"server_version":"stacks-node 0.0.1 (feat/faster-inv-generation:68f33190a, release build, linux [x86_64])","network_id":1,"parent_network_id":3652501241,"stacks_tip_height":52537,"stacks_tip":"b3183f2ac588e12319ff0fde78f97e62c92a218d87828c35710c29aaf7adbedc","stacks_tip_consensus_hash":"b712eb731b613eebae814a8f416c5c15bc8391ec","genesis_chainstate_hash":"74237aa39aa50a83de11a4f53e9d3bb7d43461d1de9873f402e5453ae60bc59b","unanchored_tip":"e76f68d607480e9984b4062b2691fb60a88423177898f5780b40ace17ae8982a","unanchored_seq":0,"exit_at_block_height":null,"is_fully_synced":false,"node_public_key_hash":"046e6f832a83ff0da4a550907d3a44412cc1e4bf"}"#; - let getinfo_full_json = r#"{"peer_version":402653189,"pox_consensus":"b712eb731b613eebae814a8f416c5c15bc8391ec","burn_block_height":727631,"stable_pox_consensus":"53b5ed79842080500d7d83daa36aa1069dedf983","stable_burn_block_height":727624,"server_version":"stacks-node 0.0.1 (feat/faster-inv-generation:68f33190a, release build, linux [x86_64])","network_id":1,"parent_network_id":3652501241,"stacks_tip_height":52537,"stacks_tip":"b3183f2ac588e12319ff0fde78f97e62c92a218d87828c35710c29aaf7adbedc","stacks_tip_consensus_hash":"b712eb731b613eebae814a8f416c5c15bc8391ec","genesis_chainstate_hash":"74237aa39aa50a83de11a4f53e9d3bb7d43461d1de9873f402e5453ae60bc59b","unanchored_tip":"e76f68d607480e9984b4062b2691fb60a88423177898f5780b40ace17ae8982a","unanchored_seq":0,"exit_at_block_height":null,"is_fully_synced":false,"node_public_key":"029b27d345e7bd2a6627262cefe6e97d9bc482f41ec32ec76a7bec391bb441798d","node_public_key_hash":"046e6f832a83ff0da4a550907d3a44412cc1e4bf"}"#; + let old_getinfo_json = r#"{"peer_version":402653189,"pox_consensus":"b712eb731b613eebae814a8f416c5c15bc8391ec","burn_block_height":727631,"stable_pox_consensus":"53b5ed79842080500d7d83daa36aa1069dedf983","stable_burn_block_height":727624,"server_version":"stacks-node 0.0.1 (feat/faster-inv-generation:68f33190a, release build, linux [x86_64])","network_id":1,"parent_network_id":3652501241,"stacks_tip_height":52537,"stacks_tip":"b3183f2ac588e12319ff0fde78f97e62c92a218d87828c35710c29aaf7adbedc","stacks_tip_consensus_hash":"b712eb731b613eebae814a8f416c5c15bc8391ec","genesis_chainstate_hash":"74237aa39aa50a83de11a4f53e9d3bb7d43461d1de9873f402e5453ae60bc59b","unanchored_tip":"e76f68d607480e9984b4062b2691fb60a88423177898f5780b40ace17ae8982a","unanchored_seq":0,"exit_at_block_height":null,"is_fully_synced":false, "tenure_height": 42}"#; + let getinfo_no_pubkey_hash_json = r#"{"peer_version":402653189,"pox_consensus":"b712eb731b613eebae814a8f416c5c15bc8391ec","burn_block_height":727631,"stable_pox_consensus":"53b5ed79842080500d7d83daa36aa1069dedf983","stable_burn_block_height":727624,"server_version":"stacks-node 0.0.1 (feat/faster-inv-generation:68f33190a, release build, linux [x86_64])","network_id":1,"parent_network_id":3652501241,"stacks_tip_height":52537,"stacks_tip":"b3183f2ac588e12319ff0fde78f97e62c92a218d87828c35710c29aaf7adbedc","stacks_tip_consensus_hash":"b712eb731b613eebae814a8f416c5c15bc8391ec","genesis_chainstate_hash":"74237aa39aa50a83de11a4f53e9d3bb7d43461d1de9873f402e5453ae60bc59b","unanchored_tip":"e76f68d607480e9984b4062b2691fb60a88423177898f5780b40ace17ae8982a","unanchored_seq":0,"exit_at_block_height":null,"is_fully_synced":false,"node_public_key":"029b27d345e7bd2a6627262cefe6e97d9bc482f41ec32ec76a7bec391bb441798d", "tenure_height": 42}"#; + let getinfo_no_pubkey_json = r#"{"peer_version":402653189,"pox_consensus":"b712eb731b613eebae814a8f416c5c15bc8391ec","burn_block_height":727631,"stable_pox_consensus":"53b5ed79842080500d7d83daa36aa1069dedf983","stable_burn_block_height":727624,"server_version":"stacks-node 0.0.1 (feat/faster-inv-generation:68f33190a, release build, linux [x86_64])","network_id":1,"parent_network_id":3652501241,"stacks_tip_height":52537,"stacks_tip":"b3183f2ac588e12319ff0fde78f97e62c92a218d87828c35710c29aaf7adbedc","stacks_tip_consensus_hash":"b712eb731b613eebae814a8f416c5c15bc8391ec","genesis_chainstate_hash":"74237aa39aa50a83de11a4f53e9d3bb7d43461d1de9873f402e5453ae60bc59b","unanchored_tip":"e76f68d607480e9984b4062b2691fb60a88423177898f5780b40ace17ae8982a","unanchored_seq":0,"exit_at_block_height":null,"is_fully_synced":false,"node_public_key_hash":"046e6f832a83ff0da4a550907d3a44412cc1e4bf", "tenure_height": 0}"#; + let getinfo_full_json = r#"{"peer_version":402653189,"pox_consensus":"b712eb731b613eebae814a8f416c5c15bc8391ec","burn_block_height":727631,"stable_pox_consensus":"53b5ed79842080500d7d83daa36aa1069dedf983","stable_burn_block_height":727624,"server_version":"stacks-node 0.0.1 (feat/faster-inv-generation:68f33190a, release build, linux [x86_64])","network_id":1,"parent_network_id":3652501241,"stacks_tip_height":52537,"stacks_tip":"b3183f2ac588e12319ff0fde78f97e62c92a218d87828c35710c29aaf7adbedc","stacks_tip_consensus_hash":"b712eb731b613eebae814a8f416c5c15bc8391ec","genesis_chainstate_hash":"74237aa39aa50a83de11a4f53e9d3bb7d43461d1de9873f402e5453ae60bc59b","unanchored_tip":"e76f68d607480e9984b4062b2691fb60a88423177898f5780b40ace17ae8982a","unanchored_seq":0,"exit_at_block_height":null,"is_fully_synced":false,"node_public_key":"029b27d345e7bd2a6627262cefe6e97d9bc482f41ec32ec76a7bec391bb441798d","node_public_key_hash":"046e6f832a83ff0da4a550907d3a44412cc1e4bf", "tenure_height": 2423}"#; // they all parse for json_obj in &[ @@ -102,4 +102,6 @@ fn test_try_make_response() { Some(1) ); let resp = response.decode_peer_info().unwrap(); + + assert_eq!(resp.tenure_height, 1); } diff --git a/stackslib/src/net/api/tests/gettenureinfo.rs b/stackslib/src/net/api/tests/gettenureinfo.rs index db53a5daca..51a8a11785 100644 --- a/stackslib/src/net/api/tests/gettenureinfo.rs +++ b/stackslib/src/net/api/tests/gettenureinfo.rs @@ -25,7 +25,6 @@ use stacks_common::types::net::PeerHost; use stacks_common::types::Address; use super::test_rpc; -use crate::net::api::getinfo::RPCPeerInfoData; use crate::net::api::tests::TestRPC; use crate::net::api::*; use crate::net::connection::ConnectionOptions; diff --git a/stackslib/src/net/p2p.rs b/stackslib/src/net/p2p.rs index eb224f3e80..054fefaf1d 100644 --- a/stackslib/src/net/p2p.rs +++ b/stackslib/src/net/p2p.rs @@ -105,7 +105,7 @@ struct NetworkHandleServer { impl NetworkHandle { pub fn new(chan_in: SyncSender) -> NetworkHandle { - NetworkHandle { chan_in: chan_in } + NetworkHandle { chan_in } } /// Send out a command to the p2p thread. Do not bother waiting for the response. @@ -175,7 +175,7 @@ impl NetworkHandle { impl NetworkHandleServer { pub fn new(chan_in: Receiver) -> NetworkHandleServer { - NetworkHandleServer { chan_in: chan_in } + NetworkHandleServer { chan_in } } pub fn pair(bufsz: usize) -> (NetworkHandleServer, NetworkHandle) { @@ -246,6 +246,7 @@ pub struct StacksTipInfo { pub consensus_hash: ConsensusHash, pub block_hash: BlockHeaderHash, pub height: u64, + pub coinbase_height: u64, pub is_nakamoto: bool, } @@ -255,6 +256,7 @@ impl StacksTipInfo { consensus_hash: ConsensusHash([0u8; 20]), block_hash: BlockHeaderHash([0u8; 32]), height: 0, + coinbase_height: 0, is_nakamoto: false, } } @@ -481,11 +483,11 @@ impl PeerNetwork { } let mut network = PeerNetwork { - peer_version: peer_version, - epochs: epochs, + peer_version, + epochs, - local_peer: local_peer, - chain_view: chain_view, + local_peer, + chain_view, chain_view_stable_consensus_hash: ConsensusHash([0u8; 20]), ast_rules: ASTRules::Typical, heaviest_affirmation_map: AffirmationMap::empty(), @@ -504,8 +506,8 @@ impl PeerNetwork { tenure_start_block_id: StacksBlockId([0x00; 32]), current_reward_sets: BTreeMap::new(), - peerdb: peerdb, - atlasdb: atlasdb, + peerdb, + atlasdb, peers: PeerMap::new(), sockets: HashMap::new(), @@ -521,8 +523,8 @@ impl PeerNetwork { p2p_network_handle: 0, http_network_handle: 0, - burnchain: burnchain, - connection_opts: connection_opts, + burnchain, + connection_opts, work_state: PeerNetworkWorkState::GetPublicIP, nakamoto_work_state: PeerNetworkWorkState::GetPublicIP, @@ -553,8 +555,8 @@ impl PeerNetwork { attachments_downloader: None, stacker_db_syncs: Some(stacker_db_sync_map), - stacker_db_configs: stacker_db_configs, - stackerdbs: stackerdbs, + stacker_db_configs, + stackerdbs, prune_outbound_counts: HashMap::new(), prune_inbound_counts: HashMap::new(), @@ -3491,7 +3493,7 @@ impl PeerNetwork { } let microblocks_data = MicroblocksData { index_anchor_block: anchor_block_id.clone(), - microblocks: microblocks, + microblocks, }; debug!( @@ -4039,7 +4041,7 @@ impl PeerNetwork { peer_version: nk.peer_version, network_id: nk.network_id, ts: get_epoch_time_secs(), - pubkey: pubkey, + pubkey, }, ); @@ -4218,14 +4220,39 @@ impl PeerNetwork { let parent_tenure_start_header = NakamotoChainState::get_tenure_start_block_header(&mut chainstate.index_conn(), stacks_tip_block_id, &parent_header.consensus_hash)? .ok_or_else(|| { - debug!("{:?}: get_parent_stacks_tip: No tenure-start block for parent tenure {} off of child {} (parnet {})", self.get_local_peer(), &parent_header.consensus_hash, stacks_tip_block_id, &parent_block_id); + debug!("{:?}: get_parent_stacks_tip: No tenure-start block for parent tenure {} off of child {} (parent {})", self.get_local_peer(), &parent_header.consensus_hash, stacks_tip_block_id, &parent_block_id); net_error::DBError(db_error::NotFoundError) })?; + let parent_stacks_tip_block_hash = parent_tenure_start_header.anchored_header.block_hash(); + let parent_stacks_tip_block_id = StacksBlockId::new( + &parent_tenure_start_header.consensus_hash, + &parent_stacks_tip_block_hash, + ); + let parent_coinbase_height = NakamotoChainState::get_coinbase_height( + &mut chainstate.index_conn(), + &parent_stacks_tip_block_id, + )?; + + let coinbase_height = match parent_coinbase_height { + Some(cbh) => cbh, + None => { + if parent_tenure_start_header.is_epoch_2_block() { + // The coinbase height is the same as the stacks block height as + // every block contains a coinbase in epoch 2.x + parent_tenure_start_header.stacks_block_height + } else { + debug!("{:?}: get_parent_stacks_tip: No coinbase height found for nakamoto block {parent_stacks_tip_block_id}", self.get_local_peer()); + return Err(net_error::DBError(db_error::NotFoundError)); + } + } + }; + let parent_stacks_tip = StacksTipInfo { consensus_hash: parent_tenure_start_header.consensus_hash, - block_hash: parent_tenure_start_header.anchored_header.block_hash(), + block_hash: parent_stacks_tip_block_hash, height: parent_tenure_start_header.anchored_header.height(), + coinbase_height, is_nakamoto: parent_tenure_start_header .anchored_header .as_stacks_nakamoto() @@ -4377,6 +4404,25 @@ impl PeerNetwork { self.stacks_tip.is_nakamoto }; + let stacks_tip_cbh = NakamotoChainState::get_coinbase_height( + &mut chainstate.index_conn(), + &new_stacks_tip_block_id, + )?; + + let coinbase_height = match stacks_tip_cbh { + Some(cbh) => cbh, + None => { + if !stacks_tip_is_nakamoto { + // The coinbase height is the same as the stacks block height as + // every block contains a coinbase in epoch 2.x + stacks_tip_height + } else { + debug!("{:?}: No coinbase height found for nakamoto block {new_stacks_tip_block_id}", self.get_local_peer()); + return Err(net_error::DBError(db_error::NotFoundError)); + } + } + }; + let need_stackerdb_refresh = canonical_sn.canonical_stacks_tip_consensus_hash != self.burnchain_tip.canonical_stacks_tip_consensus_hash || burnchain_tip_changed @@ -4415,6 +4461,7 @@ impl PeerNetwork { consensus_hash: FIRST_BURNCHAIN_CONSENSUS_HASH.clone(), block_hash: FIRST_STACKS_BLOCK_HASH.clone(), height: 0, + coinbase_height: 0, is_nakamoto: false, } } @@ -4610,6 +4657,7 @@ impl PeerNetwork { consensus_hash: stacks_tip_ch, block_hash: stacks_tip_bhh, height: stacks_tip_height, + coinbase_height, is_nakamoto: stacks_tip_is_nakamoto, }; self.parent_stacks_tip = parent_stacks_tip; @@ -5184,7 +5232,7 @@ mod test { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x01, ]), - port: port, + port, }, public_key: Secp256k1PublicKey::from_hex( "02fa66b66f8971a8cd4d20ffded09674e030f0f33883f337f34b95ad4935bac0e3", diff --git a/stackslib/src/net/tests/relay/nakamoto.rs b/stackslib/src/net/tests/relay/nakamoto.rs index fb9db70d5b..606f1f3fb2 100644 --- a/stackslib/src/net/tests/relay/nakamoto.rs +++ b/stackslib/src/net/tests/relay/nakamoto.rs @@ -54,7 +54,6 @@ use crate::chainstate::stacks::tests::{ use crate::chainstate::stacks::{Error as ChainstateError, *}; use crate::clarity_vm::clarity::ClarityConnection; use crate::core::*; -use crate::net::api::getinfo::RPCPeerInfoData; use crate::net::asn::*; use crate::net::chat::*; use crate::net::codec::*; diff --git a/testnet/stacks-node/src/tests/nakamoto_integrations.rs b/testnet/stacks-node/src/tests/nakamoto_integrations.rs index 009797a376..37b7a6c329 100644 --- a/testnet/stacks-node/src/tests/nakamoto_integrations.rs +++ b/testnet/stacks-node/src/tests/nakamoto_integrations.rs @@ -5399,6 +5399,11 @@ fn check_block_heights() { let info = get_chain_info_result(&naka_conf).unwrap(); info!("Chain info: {:?}", info); + + // With the first Nakamoto block, the chain tip and the number of tenures + // must be the same (before Nakamoto every block counts as a tenure) + assert_eq!(info.tenure_height, info.stacks_tip_height); + let mut last_burn_block_height; let mut last_stacks_block_height = info.stacks_tip_height as u128; let mut last_tenure_height = last_stacks_block_height as u128; @@ -5532,6 +5537,9 @@ fn check_block_heights() { ); last_tenure_height = bh1; + let info = get_chain_info_result(&naka_conf).unwrap(); + assert_eq!(info.tenure_height, bh3 as u64); + let sbh = heights3 .get("stacks-block-height") .unwrap() @@ -5640,6 +5648,9 @@ fn check_block_heights() { "Tenure height should not have changed" ); + let info = get_chain_info_result(&naka_conf).unwrap(); + assert_eq!(info.tenure_height, bh3 as u64); + let sbh = heights3 .get("stacks-block-height") .unwrap() @@ -5680,6 +5691,9 @@ fn check_block_heights() { "Should have mined 1 + (1 + interim_blocks_per_tenure) * tenure_count nakamoto blocks" ); + let info = get_chain_info_result(&naka_conf).unwrap(); + assert_eq!(info.tenure_height, block_height_pre_3_0 + tenure_count); + coord_channel .lock() .expect("Mutex poisoned")