mirror of
https://github.com/alexgo-io/stacks-puppet-node.git
synced 2026-01-12 22:43:42 +08:00
Merge branch 'develop' of https://github.com/stacks-network/stacks-core into chore/block-signature-message-type
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
use std::io::{Read, Write};
|
||||
|
||||
use clarity::vm::costs::ExecutionCost;
|
||||
use regex::{Captures, Regex};
|
||||
use stacks_common::types::chainstate::{
|
||||
BlockHeaderHash, ConsensusHash, StacksBlockId, StacksPublicKey,
|
||||
@@ -23,6 +24,7 @@ use stacks_common::types::chainstate::{
|
||||
use stacks_common::types::net::PeerHost;
|
||||
use stacks_common::types::StacksPublicKeyBuffer;
|
||||
use stacks_common::util::hash::{Hash160, Sha256Sum};
|
||||
use url::form_urlencoded;
|
||||
|
||||
use crate::burnchains::affirmation::AffirmationMap;
|
||||
use crate::burnchains::Txid;
|
||||
@@ -30,19 +32,23 @@ use crate::chainstate::burn::db::sortdb::SortitionDB;
|
||||
use crate::chainstate::stacks::db::blocks::MINIMUM_TX_FEE_RATE_PER_BYTE;
|
||||
use crate::chainstate::stacks::db::StacksChainState;
|
||||
use crate::core::mempool::MemPoolDB;
|
||||
use crate::net::api::postfeerate::RPCPostFeeRateRequestHandler;
|
||||
use crate::net::http::{
|
||||
parse_json, Error, HttpRequest, HttpRequestContents, HttpRequestPreamble, HttpResponse,
|
||||
HttpResponseContents, HttpResponsePayload, HttpResponsePreamble,
|
||||
parse_json, Error, HttpBadRequest, HttpRequest, HttpRequestContents, HttpRequestPreamble,
|
||||
HttpResponse, HttpResponseContents, HttpResponsePayload, HttpResponsePreamble,
|
||||
};
|
||||
use crate::net::httpcore::{
|
||||
HttpPreambleExtensions, RPCRequestHandler, StacksHttpRequest, StacksHttpResponse,
|
||||
};
|
||||
use crate::net::p2p::PeerNetwork;
|
||||
use crate::net::{Error as NetError, StacksNodeState};
|
||||
use crate::net::{Error as NetError, HttpServerError, StacksNodeState};
|
||||
use crate::version_string;
|
||||
|
||||
pub(crate) const SINGLESIG_TX_TRANSFER_LEN: u64 = 180;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RPCGetStxTransferCostRequestHandler {}
|
||||
|
||||
impl RPCGetStxTransferCostRequestHandler {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
@@ -74,7 +80,7 @@ impl HttpRequest for RPCGetStxTransferCostRequestHandler {
|
||||
) -> Result<HttpRequestContents, Error> {
|
||||
if preamble.get_content_length() != 0 {
|
||||
return Err(Error::DecodeError(
|
||||
"Invalid Http request: expected 0-length body for GetInfo".to_string(),
|
||||
"Invalid Http request: expected 0-length body".to_string(),
|
||||
));
|
||||
}
|
||||
Ok(HttpRequestContents::new().query_string(query))
|
||||
@@ -92,9 +98,57 @@ impl RPCRequestHandler for RPCGetStxTransferCostRequestHandler {
|
||||
_contents: HttpRequestContents,
|
||||
node: &mut StacksNodeState,
|
||||
) -> Result<(HttpResponsePreamble, HttpResponseContents), NetError> {
|
||||
// todo -- need to actually estimate the cost / length for token transfers
|
||||
// right now, it just uses the minimum.
|
||||
let fee = MINIMUM_TX_FEE_RATE_PER_BYTE;
|
||||
// NOTE: The estimated length isn't needed per se because we're returning a fee rate, but
|
||||
// we do need an absolute length to use the estimator (so supply a common one).
|
||||
let estimated_len = SINGLESIG_TX_TRANSFER_LEN;
|
||||
|
||||
let fee_resp = node.with_node_state(|_network, sortdb, _chainstate, _mempool, rpc_args| {
|
||||
let tip = self.get_canonical_burn_chain_tip(&preamble, sortdb)?;
|
||||
let stacks_epoch = self.get_stacks_epoch(&preamble, sortdb, tip.block_height)?;
|
||||
|
||||
if let Some((_, fee_estimator, metric)) = rpc_args.get_estimators_ref() {
|
||||
// STX transfer transactions have zero runtime cost
|
||||
let estimated_cost = ExecutionCost::zero();
|
||||
let estimations =
|
||||
RPCPostFeeRateRequestHandler::estimate_tx_fee_from_cost_and_length(
|
||||
&preamble,
|
||||
fee_estimator,
|
||||
metric,
|
||||
estimated_cost,
|
||||
estimated_len,
|
||||
stacks_epoch,
|
||||
)?
|
||||
.estimations;
|
||||
if estimations.len() != 3 {
|
||||
// logic bug, but treat as runtime error
|
||||
return Err(StacksHttpResponse::new_error(
|
||||
&preamble,
|
||||
&HttpServerError::new(
|
||||
"Logic error in fee estimation: did not get three estimates".into(),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
// safety -- checked estimations.len() == 3 above
|
||||
let median_estimation = &estimations[1];
|
||||
|
||||
// NOTE: this returns the fee _rate_
|
||||
Ok(median_estimation.fee / estimated_len)
|
||||
} else {
|
||||
// unlike `POST /v2/fees/transaction`, this method can't fail due to the
|
||||
// unavailability of cost estimation, so just assume the minimum fee.
|
||||
debug!("Fee and cost estimation not configured on this stacks node");
|
||||
Ok(MINIMUM_TX_FEE_RATE_PER_BYTE)
|
||||
}
|
||||
});
|
||||
|
||||
let fee = match fee_resp {
|
||||
Ok(fee) => fee,
|
||||
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(&fee)?;
|
||||
@@ -116,13 +170,9 @@ impl HttpResponse for RPCGetStxTransferCostRequestHandler {
|
||||
|
||||
impl StacksHttpRequest {
|
||||
pub fn new_get_stx_transfer_cost(host: PeerHost) -> StacksHttpRequest {
|
||||
StacksHttpRequest::new_for_peer(
|
||||
host,
|
||||
"GET".into(),
|
||||
"/v2/fees/transfer".into(),
|
||||
HttpRequestContents::new(),
|
||||
)
|
||||
.expect("FATAL: failed to construct request from infallible data")
|
||||
let mut contents = HttpRequestContents::new();
|
||||
StacksHttpRequest::new_for_peer(host, "GET".into(), "/v2/fees/transfer".into(), contents)
|
||||
.expect("FATAL: failed to construct request from infallible data")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,9 @@ use crate::chainstate::stacks::db::blocks::MINIMUM_TX_FEE_RATE_PER_BYTE;
|
||||
use crate::chainstate::stacks::db::StacksChainState;
|
||||
use crate::chainstate::stacks::TransactionPayload;
|
||||
use crate::core::mempool::MemPoolDB;
|
||||
use crate::cost_estimates::FeeRateEstimate;
|
||||
use crate::core::StacksEpoch;
|
||||
use crate::cost_estimates::metrics::CostMetric;
|
||||
use crate::cost_estimates::{CostEstimator, FeeEstimator, FeeRateEstimate};
|
||||
use crate::net::http::{
|
||||
parse_json, Error, HttpBadRequest, HttpContentType, HttpNotFound, HttpRequest,
|
||||
HttpRequestContents, HttpRequestPreamble, HttpResponse, HttpResponseContents,
|
||||
@@ -92,6 +94,7 @@ pub struct RPCPostFeeRateRequestHandler {
|
||||
pub estimated_len: Option<u64>,
|
||||
pub transaction_payload: Option<TransactionPayload>,
|
||||
}
|
||||
|
||||
impl RPCPostFeeRateRequestHandler {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
@@ -99,6 +102,48 @@ impl RPCPostFeeRateRequestHandler {
|
||||
transaction_payload: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Estimate a transaction fee, given its execution cost estimation and length estimation
|
||||
/// and cost estimators.
|
||||
/// Returns Ok(fee structure) on success
|
||||
/// Returns Err(HTTP response) on error
|
||||
pub fn estimate_tx_fee_from_cost_and_length(
|
||||
preamble: &HttpRequestPreamble,
|
||||
fee_estimator: &dyn FeeEstimator,
|
||||
metric: &dyn CostMetric,
|
||||
estimated_cost: ExecutionCost,
|
||||
estimated_len: u64,
|
||||
stacks_epoch: StacksEpoch,
|
||||
) -> Result<RPCFeeEstimateResponse, StacksHttpResponse> {
|
||||
let scalar_cost =
|
||||
metric.from_cost_and_len(&estimated_cost, &stacks_epoch.block_limit, estimated_len);
|
||||
let fee_rates = fee_estimator.get_rate_estimates().map_err(|e| {
|
||||
StacksHttpResponse::new_error(
|
||||
&preamble,
|
||||
&HttpBadRequest::new(format!(
|
||||
"Estimator RPC endpoint failed to estimate fees for tx: {:?}",
|
||||
&e
|
||||
)),
|
||||
)
|
||||
})?;
|
||||
|
||||
let mut estimations = RPCFeeEstimate::estimate_fees(scalar_cost, fee_rates).to_vec();
|
||||
|
||||
let minimum_fee = estimated_len * MINIMUM_TX_FEE_RATE_PER_BYTE;
|
||||
|
||||
for estimate in estimations.iter_mut() {
|
||||
if estimate.fee < minimum_fee {
|
||||
estimate.fee = minimum_fee;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(RPCFeeEstimateResponse {
|
||||
estimated_cost,
|
||||
estimations,
|
||||
estimated_cost_scalar: scalar_cost,
|
||||
cost_scalar_change_by_byte: metric.change_per_byte(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Decode the HTTP request
|
||||
@@ -206,39 +251,14 @@ impl RPCRequestHandler for RPCPostFeeRateRequestHandler {
|
||||
)
|
||||
})?;
|
||||
|
||||
let scalar_cost = metric.from_cost_and_len(
|
||||
&estimated_cost,
|
||||
&stacks_epoch.block_limit,
|
||||
estimated_len,
|
||||
);
|
||||
let fee_rates = fee_estimator.get_rate_estimates().map_err(|e| {
|
||||
StacksHttpResponse::new_error(
|
||||
&preamble,
|
||||
&HttpBadRequest::new(format!(
|
||||
"Estimator RPC endpoint failed to estimate fees for tx {}: {:?}",
|
||||
&tx.name(),
|
||||
&e
|
||||
)),
|
||||
)
|
||||
})?;
|
||||
|
||||
let mut estimations =
|
||||
RPCFeeEstimate::estimate_fees(scalar_cost, fee_rates).to_vec();
|
||||
|
||||
let minimum_fee = estimated_len * MINIMUM_TX_FEE_RATE_PER_BYTE;
|
||||
|
||||
for estimate in estimations.iter_mut() {
|
||||
if estimate.fee < minimum_fee {
|
||||
estimate.fee = minimum_fee;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(RPCFeeEstimateResponse {
|
||||
Self::estimate_tx_fee_from_cost_and_length(
|
||||
&preamble,
|
||||
fee_estimator,
|
||||
metric,
|
||||
estimated_cost,
|
||||
estimations,
|
||||
estimated_cost_scalar: scalar_cost,
|
||||
cost_scalar_change_by_byte: metric.change_per_byte(),
|
||||
})
|
||||
estimated_len,
|
||||
stacks_epoch,
|
||||
)
|
||||
} else {
|
||||
debug!("Fee and cost estimation not configured on this stacks node");
|
||||
Err(StacksHttpResponse::new_error(
|
||||
|
||||
@@ -25,6 +25,7 @@ use stacks_common::types::Address;
|
||||
use super::test_rpc;
|
||||
use crate::chainstate::stacks::db::blocks::MINIMUM_TX_FEE_RATE_PER_BYTE;
|
||||
use crate::core::BLOCK_LIMIT_MAINNET_21;
|
||||
use crate::net::api::getstxtransfercost::SINGLESIG_TX_TRANSFER_LEN;
|
||||
use crate::net::api::*;
|
||||
use crate::net::connection::ConnectionOptions;
|
||||
use crate::net::httpcore::{
|
||||
@@ -67,6 +68,7 @@ fn test_try_make_response() {
|
||||
|
||||
let mut responses = test_rpc(function_name!(), vec![request]);
|
||||
assert_eq!(responses.len(), 1);
|
||||
responses.reverse();
|
||||
|
||||
let response = responses.pop().unwrap();
|
||||
debug!(
|
||||
@@ -80,5 +82,6 @@ fn test_try_make_response() {
|
||||
);
|
||||
|
||||
let fee_rate = response.decode_stx_transfer_fee().unwrap();
|
||||
debug!("fee_rate = {:?}", &fee_rate);
|
||||
assert_eq!(fee_rate, MINIMUM_TX_FEE_RATE_PER_BYTE);
|
||||
}
|
||||
|
||||
@@ -646,6 +646,24 @@ impl PeerNetwork {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Call `bind()` only if not already bound
|
||||
/// Returns:
|
||||
/// - `Ok(true)` if `bind()` call was successful
|
||||
/// - `Ok(false)` if `bind()` call was skipped
|
||||
/// - `Err()` if `bind()`` failed
|
||||
#[cfg_attr(test, mutants::skip)]
|
||||
pub fn try_bind(
|
||||
&mut self,
|
||||
my_addr: &SocketAddr,
|
||||
http_addr: &SocketAddr,
|
||||
) -> Result<bool, net_error> {
|
||||
if self.network.is_some() {
|
||||
// Already bound
|
||||
return Ok(false);
|
||||
}
|
||||
self.bind(my_addr, http_addr).map(|()| true)
|
||||
}
|
||||
|
||||
/// Get bound neighbor key. This is how this PeerNetwork appears to other nodes.
|
||||
pub fn bound_neighbor_key(&self) -> &NeighborKey {
|
||||
&self.bind_nk
|
||||
|
||||
@@ -25,6 +25,7 @@ use stacks::chainstate::stacks::Error as ChainstateError;
|
||||
use stacks::monitoring;
|
||||
use stacks::monitoring::update_active_miners_count_gauge;
|
||||
use stacks::net::atlas::AtlasConfig;
|
||||
use stacks::net::p2p::PeerNetwork;
|
||||
use stacks::net::relay::Relayer;
|
||||
use stacks::net::stackerdb::StackerDBs;
|
||||
use stacks_common::types::chainstate::SortitionId;
|
||||
@@ -132,6 +133,7 @@ impl StacksNode {
|
||||
globals: Globals,
|
||||
// relay receiver endpoint for the p2p thread, so the relayer can feed it data to push
|
||||
relay_recv: Receiver<RelayerDirective>,
|
||||
peer_network: Option<PeerNetwork>,
|
||||
) -> StacksNode {
|
||||
let config = runloop.config().clone();
|
||||
let is_miner = runloop.is_miner();
|
||||
@@ -157,7 +159,8 @@ impl StacksNode {
|
||||
.connect_mempool_db()
|
||||
.expect("FATAL: database failure opening mempool");
|
||||
|
||||
let mut p2p_net = NeonNode::setup_peer_network(&config, &atlas_config, burnchain);
|
||||
let mut p2p_net = peer_network
|
||||
.unwrap_or_else(|| NeonNode::setup_peer_network(&config, &atlas_config, burnchain));
|
||||
|
||||
let stackerdbs = StackerDBs::connect(&config.get_stacker_db_file_path(), true)
|
||||
.expect("FATAL: failed to connect to stacker DB");
|
||||
|
||||
@@ -182,8 +182,13 @@ impl PeerThread {
|
||||
.parse()
|
||||
.unwrap_or_else(|_| panic!("Failed to parse socket: {}", &config.node.rpc_bind));
|
||||
|
||||
net.bind(&p2p_sock, &rpc_sock)
|
||||
.expect("BUG: PeerNetwork could not bind or is already bound");
|
||||
let did_bind = net
|
||||
.try_bind(&p2p_sock, &rpc_sock)
|
||||
.expect("BUG: PeerNetwork could not bind");
|
||||
|
||||
if !did_bind {
|
||||
info!("`PeerNetwork::bind()` skipped, already bound");
|
||||
}
|
||||
|
||||
let poll_timeout = cmp::min(5000, config.miner.first_attempt_time_ms / 2);
|
||||
|
||||
|
||||
@@ -298,7 +298,7 @@ pub struct StacksNode {
|
||||
/// True if we're a miner
|
||||
is_miner: bool,
|
||||
/// handle to the p2p thread
|
||||
pub p2p_thread_handle: JoinHandle<()>,
|
||||
pub p2p_thread_handle: JoinHandle<Option<PeerNetwork>>,
|
||||
/// handle to the relayer thread
|
||||
pub relayer_thread_handle: JoinHandle<()>,
|
||||
}
|
||||
@@ -4655,7 +4655,10 @@ impl StacksNode {
|
||||
/// Main loop of the p2p thread.
|
||||
/// Runs in a separate thread.
|
||||
/// Continuously receives, until told otherwise.
|
||||
pub fn p2p_main(mut p2p_thread: PeerThread, event_dispatcher: EventDispatcher) {
|
||||
pub fn p2p_main(
|
||||
mut p2p_thread: PeerThread,
|
||||
event_dispatcher: EventDispatcher,
|
||||
) -> Option<PeerNetwork> {
|
||||
let should_keep_running = p2p_thread.globals.should_keep_running.clone();
|
||||
let (mut dns_resolver, mut dns_client) = DNSResolver::new(10);
|
||||
|
||||
@@ -4718,6 +4721,7 @@ impl StacksNode {
|
||||
thread::sleep(Duration::from_secs(5));
|
||||
}
|
||||
info!("P2P thread exit!");
|
||||
p2p_thread.net
|
||||
}
|
||||
|
||||
/// This function sets the global var `GLOBAL_BURNCHAIN_SIGNER`.
|
||||
@@ -4814,7 +4818,7 @@ impl StacksNode {
|
||||
))
|
||||
.spawn(move || {
|
||||
debug!("p2p thread ID is {:?}", thread::current().id());
|
||||
Self::p2p_main(p2p_thread, p2p_event_dispatcher);
|
||||
Self::p2p_main(p2p_thread, p2p_event_dispatcher)
|
||||
})
|
||||
.expect("FATAL: failed to start p2p thread");
|
||||
|
||||
@@ -5017,8 +5021,8 @@ impl StacksNode {
|
||||
}
|
||||
|
||||
/// Join all inner threads
|
||||
pub fn join(self) {
|
||||
pub fn join(self) -> Option<PeerNetwork> {
|
||||
self.relayer_thread_handle.join().unwrap();
|
||||
self.p2p_thread_handle.join().unwrap();
|
||||
self.p2p_thread_handle.join().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ impl BootRunLoop {
|
||||
let InnerLoops::Epoch3(ref mut naka_loop) = self.active_loop else {
|
||||
panic!("FATAL: unexpectedly invoked start_from_naka when active loop wasn't nakamoto");
|
||||
};
|
||||
naka_loop.start(burnchain_opt, mine_start)
|
||||
naka_loop.start(burnchain_opt, mine_start, None)
|
||||
}
|
||||
|
||||
fn start_from_neon(&mut self, burnchain_opt: Option<Burnchain>, mine_start: u64) {
|
||||
@@ -120,7 +120,7 @@ impl BootRunLoop {
|
||||
|
||||
let boot_thread = Self::spawn_stopper(&self.config, neon_loop)
|
||||
.expect("FATAL: failed to spawn epoch-2/3-boot thread");
|
||||
neon_loop.start(burnchain_opt.clone(), mine_start);
|
||||
let peer_network = neon_loop.start(burnchain_opt.clone(), mine_start);
|
||||
|
||||
let monitoring_thread = neon_loop.take_monitoring_thread();
|
||||
// did we exit because of the epoch-3.0 transition, or some other reason?
|
||||
@@ -150,7 +150,7 @@ impl BootRunLoop {
|
||||
let InnerLoops::Epoch3(ref mut naka_loop) = self.active_loop else {
|
||||
panic!("FATAL: unexpectedly found epoch2 loop after setting epoch3 active");
|
||||
};
|
||||
naka_loop.start(burnchain_opt, mine_start)
|
||||
naka_loop.start(burnchain_opt, mine_start, peer_network)
|
||||
}
|
||||
|
||||
fn spawn_stopper(
|
||||
|
||||
@@ -31,6 +31,7 @@ use stacks::chainstate::stacks::db::{ChainStateBootData, StacksChainState};
|
||||
use stacks::chainstate::stacks::miner::{signal_mining_blocked, signal_mining_ready, MinerStatus};
|
||||
use stacks::core::StacksEpochId;
|
||||
use stacks::net::atlas::{AtlasConfig, AtlasDB, Attachment};
|
||||
use stacks::net::p2p::PeerNetwork;
|
||||
use stacks_common::types::PublicKey;
|
||||
use stacks_common::util::hash::Hash160;
|
||||
use stx_genesis::GenesisData;
|
||||
@@ -392,7 +393,12 @@ impl RunLoop {
|
||||
/// It will start the burnchain (separate thread), set-up a channel in
|
||||
/// charge of coordinating the new blocks coming from the burnchain and
|
||||
/// the nodes, taking turns on tenures.
|
||||
pub fn start(&mut self, burnchain_opt: Option<Burnchain>, mut mine_start: u64) {
|
||||
pub fn start(
|
||||
&mut self,
|
||||
burnchain_opt: Option<Burnchain>,
|
||||
mut mine_start: u64,
|
||||
peer_network: Option<PeerNetwork>,
|
||||
) {
|
||||
let (coordinator_receivers, coordinator_senders) = self
|
||||
.coordinator_channels
|
||||
.take()
|
||||
@@ -475,7 +481,7 @@ impl RunLoop {
|
||||
|
||||
// Boot up the p2p network and relayer, and figure out how many sortitions we have so far
|
||||
// (it could be non-zero if the node is resuming from chainstate)
|
||||
let mut node = StacksNode::spawn(self, globals.clone(), relay_recv);
|
||||
let mut node = StacksNode::spawn(self, globals.clone(), relay_recv, peer_network);
|
||||
|
||||
// Wait for all pending sortitions to process
|
||||
let burnchain_db = burnchain_config
|
||||
|
||||
@@ -21,6 +21,7 @@ use stacks::chainstate::stacks::db::{ChainStateBootData, StacksChainState};
|
||||
use stacks::chainstate::stacks::miner::{signal_mining_blocked, signal_mining_ready, MinerStatus};
|
||||
use stacks::core::StacksEpochId;
|
||||
use stacks::net::atlas::{AtlasConfig, AtlasDB, Attachment};
|
||||
use stacks::net::p2p::PeerNetwork;
|
||||
use stacks::util_lib::db::Error as db_error;
|
||||
use stacks_common::deps_common::ctrlc as termination;
|
||||
use stacks_common::deps_common::ctrlc::SignalId;
|
||||
@@ -999,7 +1000,11 @@ impl RunLoop {
|
||||
/// It will start the burnchain (separate thread), set-up a channel in
|
||||
/// charge of coordinating the new blocks coming from the burnchain and
|
||||
/// the nodes, taking turns on tenures.
|
||||
pub fn start(&mut self, burnchain_opt: Option<Burnchain>, mut mine_start: u64) {
|
||||
pub fn start(
|
||||
&mut self,
|
||||
burnchain_opt: Option<Burnchain>,
|
||||
mut mine_start: u64,
|
||||
) -> Option<PeerNetwork> {
|
||||
let (coordinator_receivers, coordinator_senders) = self
|
||||
.coordinator_channels
|
||||
.take()
|
||||
@@ -1018,12 +1023,12 @@ impl RunLoop {
|
||||
Ok(burnchain_controller) => burnchain_controller,
|
||||
Err(burnchain_error::ShutdownInitiated) => {
|
||||
info!("Exiting stacks-node");
|
||||
return;
|
||||
return None;
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Error initializing burnchain: {}", e);
|
||||
info!("Exiting stacks-node");
|
||||
return;
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1142,11 +1147,11 @@ impl RunLoop {
|
||||
|
||||
globals.coord().stop_chains_coordinator();
|
||||
coordinator_thread_handle.join().unwrap();
|
||||
node.join();
|
||||
let peer_network = node.join();
|
||||
liveness_thread.join().unwrap();
|
||||
|
||||
info!("Exiting stacks-node");
|
||||
break;
|
||||
break peer_network;
|
||||
}
|
||||
|
||||
let remote_chain_height = burnchain.get_headers_height() - 1;
|
||||
@@ -1269,7 +1274,7 @@ impl RunLoop {
|
||||
if !node.relayer_sortition_notify() {
|
||||
// relayer hung up, exit.
|
||||
error!("Runloop: Block relayer and miner hung up, exiting.");
|
||||
return;
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1343,7 +1348,7 @@ impl RunLoop {
|
||||
if !node.relayer_issue_tenure(ibd) {
|
||||
// relayer hung up, exit.
|
||||
error!("Runloop: Block relayer and miner hung up, exiting.");
|
||||
break;
|
||||
break None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user