mirror of
https://github.com/alexgo-io/stacks-puppet-node.git
synced 2026-05-28 23:20:55 +08:00
Merge branch 'develop' into draft/multisig-order-independence
This commit is contained in:
@@ -62,7 +62,7 @@ name = "stacks-events"
|
||||
path = "src/stacks_events.rs"
|
||||
|
||||
[features]
|
||||
monitoring_prom = ["stacks/monitoring_prom"]
|
||||
monitoring_prom = ["stacks/monitoring_prom", "libsigner/monitoring_prom"]
|
||||
slog_json = ["stacks/slog_json", "stacks-common/slog_json", "clarity/slog_json"]
|
||||
prod-genesis-chainstate = []
|
||||
default = []
|
||||
|
||||
@@ -704,7 +704,7 @@ impl BitcoinRegtestController {
|
||||
block_height: u64,
|
||||
) -> Option<UTXOSet> {
|
||||
// if mock mining, do not even bother requesting UTXOs
|
||||
if self.config.get_node_config().mock_mining {
|
||||
if self.config.get_node_config(false).mock_mining {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
||||
@@ -163,6 +163,11 @@ impl MinerStats {
|
||||
// calculate the burn distribution from these operations.
|
||||
// The resulting distribution will contain the user burns that match block commits
|
||||
let burn_dist = BurnSamplePoint::make_min_median_distribution(
|
||||
if burnchain.is_in_prepare_phase(burn_block_height) {
|
||||
1
|
||||
} else {
|
||||
MINING_COMMITMENT_WINDOW
|
||||
},
|
||||
windowed_block_commits,
|
||||
windowed_missed_commits,
|
||||
burn_blocks,
|
||||
@@ -647,6 +652,7 @@ pub mod tests {
|
||||
};
|
||||
let burn_dist = vec![
|
||||
BurnSamplePoint {
|
||||
frequency: 10,
|
||||
burns: block_commit_1.burn_fee.into(),
|
||||
median_burn: block_commit_2.burn_fee.into(),
|
||||
range_start: Uint256::zero(),
|
||||
@@ -659,6 +665,7 @@ pub mod tests {
|
||||
candidate: block_commit_1.clone(),
|
||||
},
|
||||
BurnSamplePoint {
|
||||
frequency: 10,
|
||||
burns: block_commit_2.burn_fee.into(),
|
||||
median_burn: block_commit_2.burn_fee.into(),
|
||||
range_start: Uint256([
|
||||
@@ -676,6 +683,7 @@ pub mod tests {
|
||||
candidate: block_commit_2.clone(),
|
||||
},
|
||||
BurnSamplePoint {
|
||||
frequency: 10,
|
||||
burns: (block_commit_3.burn_fee).into(),
|
||||
median_burn: block_commit_3.burn_fee.into(),
|
||||
range_start: Uint256([
|
||||
|
||||
@@ -101,7 +101,8 @@ mod tests {
|
||||
seed = "invalid-hex-value"
|
||||
"#,
|
||||
)
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
false
|
||||
)
|
||||
.unwrap_err()
|
||||
);
|
||||
@@ -115,7 +116,8 @@ mod tests {
|
||||
local_peer_seed = "invalid-hex-value"
|
||||
"#,
|
||||
)
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
false
|
||||
)
|
||||
.unwrap_err()
|
||||
);
|
||||
@@ -130,6 +132,7 @@ mod tests {
|
||||
"#,
|
||||
)
|
||||
.unwrap(),
|
||||
false,
|
||||
)
|
||||
.unwrap_err();
|
||||
assert_eq!(
|
||||
@@ -137,7 +140,7 @@ mod tests {
|
||||
&actual_err_msg[..expected_err_prefix.len()]
|
||||
);
|
||||
|
||||
assert!(Config::from_config_file(ConfigFile::from_str("").unwrap()).is_ok());
|
||||
assert!(Config::from_config_file(ConfigFile::from_str("").unwrap(), false).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -195,6 +198,7 @@ mod tests {
|
||||
"#,
|
||||
)
|
||||
.unwrap(),
|
||||
false,
|
||||
)
|
||||
.expect("Expected to be able to parse block proposal token from file");
|
||||
|
||||
@@ -218,6 +222,7 @@ mod tests {
|
||||
"#
|
||||
))
|
||||
.expect("Expected to be able to parse config file from string"),
|
||||
false,
|
||||
)
|
||||
.expect("Expected to be able to parse affirmation map from file");
|
||||
|
||||
@@ -241,7 +246,7 @@ mod tests {
|
||||
))
|
||||
.expect("Expected to be able to parse config file from string");
|
||||
|
||||
assert!(Config::from_config_file(file).is_err());
|
||||
assert!(Config::from_config_file(file, false).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -249,6 +254,7 @@ mod tests {
|
||||
let config = Config::from_config_file(
|
||||
ConfigFile::from_str(r#""#)
|
||||
.expect("Expected to be able to parse config file from string"),
|
||||
false,
|
||||
)
|
||||
.expect("Expected to be able to parse affirmation map from file");
|
||||
|
||||
@@ -266,6 +272,7 @@ mod tests {
|
||||
"#,
|
||||
)
|
||||
.expect("Expected to be able to parse config file from string"),
|
||||
false,
|
||||
)
|
||||
.expect("Expected to be able to parse affirmation map from file");
|
||||
// Should default add xenon affirmation overrides
|
||||
@@ -291,6 +298,7 @@ mod tests {
|
||||
"#,
|
||||
))
|
||||
.expect("Expected to be able to parse config file from string"),
|
||||
false,
|
||||
)
|
||||
.expect("Expected to be able to parse affirmation map from file");
|
||||
// Should default add xenon affirmation overrides, but overwrite with the configured one above
|
||||
@@ -537,7 +545,7 @@ impl Config {
|
||||
let Ok(config_file) = ConfigFile::from_path(path.as_str()) else {
|
||||
return self.burnchain.clone();
|
||||
};
|
||||
let Ok(config) = Config::from_config_file(config_file) else {
|
||||
let Ok(config) = Config::from_config_file(config_file, false) else {
|
||||
return self.burnchain.clone();
|
||||
};
|
||||
config.burnchain
|
||||
@@ -552,20 +560,20 @@ impl Config {
|
||||
let Ok(config_file) = ConfigFile::from_path(path.as_str()) else {
|
||||
return self.miner.clone();
|
||||
};
|
||||
let Ok(config) = Config::from_config_file(config_file) else {
|
||||
let Ok(config) = Config::from_config_file(config_file, false) else {
|
||||
return self.miner.clone();
|
||||
};
|
||||
return config.miner;
|
||||
}
|
||||
|
||||
pub fn get_node_config(&self) -> NodeConfig {
|
||||
pub fn get_node_config(&self, resolve_bootstrap_nodes: bool) -> NodeConfig {
|
||||
let Some(path) = &self.config_path else {
|
||||
return self.node.clone();
|
||||
};
|
||||
let Ok(config_file) = ConfigFile::from_path(path.as_str()) else {
|
||||
return self.node.clone();
|
||||
};
|
||||
let Ok(config) = Config::from_config_file(config_file) else {
|
||||
let Ok(config) = Config::from_config_file(config_file, resolve_bootstrap_nodes) else {
|
||||
return self.node.clone();
|
||||
};
|
||||
return config.node;
|
||||
@@ -941,11 +949,18 @@ impl Config {
|
||||
Ok(out_epochs)
|
||||
}
|
||||
|
||||
pub fn from_config_file(config_file: ConfigFile) -> Result<Config, String> {
|
||||
Self::from_config_default(config_file, Config::default())
|
||||
pub fn from_config_file(
|
||||
config_file: ConfigFile,
|
||||
resolve_bootstrap_nodes: bool,
|
||||
) -> Result<Config, String> {
|
||||
Self::from_config_default(config_file, Config::default(), resolve_bootstrap_nodes)
|
||||
}
|
||||
|
||||
fn from_config_default(config_file: ConfigFile, default: Config) -> Result<Config, String> {
|
||||
fn from_config_default(
|
||||
config_file: ConfigFile,
|
||||
default: Config,
|
||||
resolve_bootstrap_nodes: bool,
|
||||
) -> Result<Config, String> {
|
||||
let Config {
|
||||
node: default_node_config,
|
||||
burnchain: default_burnchain_config,
|
||||
@@ -996,9 +1011,15 @@ impl Config {
|
||||
};
|
||||
|
||||
if let Some(bootstrap_node) = bootstrap_node {
|
||||
node.set_bootstrap_nodes(bootstrap_node, burnchain.chain_id, burnchain.peer_version);
|
||||
if resolve_bootstrap_nodes {
|
||||
node.set_bootstrap_nodes(
|
||||
bootstrap_node,
|
||||
burnchain.chain_id,
|
||||
burnchain.peer_version,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if is_mainnet {
|
||||
if is_mainnet && resolve_bootstrap_nodes {
|
||||
let bootstrap_node = ConfigFile::mainnet().node.unwrap().bootstrap_node.unwrap();
|
||||
node.set_bootstrap_nodes(
|
||||
bootstrap_node,
|
||||
|
||||
@@ -65,7 +65,7 @@ static GLOBAL: Jemalloc = Jemalloc;
|
||||
fn cli_pick_best_tip(config_path: &str, at_stacks_height: Option<u64>) -> TipCandidate {
|
||||
info!("Loading config at path {}", config_path);
|
||||
let config = match ConfigFile::from_path(config_path) {
|
||||
Ok(config_file) => Config::from_config_file(config_file).unwrap(),
|
||||
Ok(config_file) => Config::from_config_file(config_file, true).unwrap(),
|
||||
Err(e) => {
|
||||
warn!("Invalid config file: {}", e);
|
||||
process::exit(1);
|
||||
@@ -105,7 +105,7 @@ fn cli_get_miner_spend(
|
||||
) -> u64 {
|
||||
info!("Loading config at path {}", config_path);
|
||||
let config = match ConfigFile::from_path(&config_path) {
|
||||
Ok(config_file) => Config::from_config_file(config_file).unwrap(),
|
||||
Ok(config_file) => Config::from_config_file(config_file, true).unwrap(),
|
||||
Err(e) => {
|
||||
warn!("Invalid config file: {}", e);
|
||||
process::exit(1);
|
||||
@@ -334,7 +334,7 @@ fn main() {
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
match Config::from_config_file(config_file) {
|
||||
match Config::from_config_file(config_file, true) {
|
||||
Ok(_) => {
|
||||
info!("Loaded config!");
|
||||
process::exit(0);
|
||||
@@ -365,9 +365,11 @@ fn main() {
|
||||
let seed = {
|
||||
let config_path: Option<String> = args.opt_value_from_str("--config").unwrap();
|
||||
if let Some(config_path) = config_path {
|
||||
let conf =
|
||||
Config::from_config_file(ConfigFile::from_path(&config_path).unwrap())
|
||||
.unwrap();
|
||||
let conf = Config::from_config_file(
|
||||
ConfigFile::from_path(&config_path).unwrap(),
|
||||
true,
|
||||
)
|
||||
.unwrap();
|
||||
args.finish();
|
||||
conf.node.seed
|
||||
} else {
|
||||
@@ -416,7 +418,7 @@ fn main() {
|
||||
}
|
||||
};
|
||||
|
||||
let conf = match Config::from_config_file(config_file) {
|
||||
let conf = match Config::from_config_file(config_file, true) {
|
||||
Ok(conf) => conf,
|
||||
Err(e) => {
|
||||
warn!("Invalid config: {}", e);
|
||||
|
||||
@@ -167,7 +167,7 @@ impl StacksNode {
|
||||
let local_peer = p2p_net.local_peer.clone();
|
||||
|
||||
// setup initial key registration
|
||||
let leader_key_registration_state = if config.get_node_config().mock_mining {
|
||||
let leader_key_registration_state = if config.get_node_config(false).mock_mining {
|
||||
// mock mining, pretend to have a registered key
|
||||
let (vrf_public_key, _) = keychain.make_vrf_keypair(VRF_MOCK_MINER_KEY);
|
||||
LeaderKeyRegistrationState::Active(RegisteredKey {
|
||||
|
||||
@@ -656,7 +656,7 @@ impl BlockMinerThread {
|
||||
fn make_vrf_proof(&mut self) -> Option<VRFProof> {
|
||||
// if we're a mock miner, then make sure that the keychain has a keypair for the mocked VRF
|
||||
// key
|
||||
let vrf_proof = if self.config.get_node_config().mock_mining {
|
||||
let vrf_proof = if self.config.get_node_config(false).mock_mining {
|
||||
self.keychain.generate_proof(
|
||||
VRF_MOCK_MINER_KEY,
|
||||
self.burn_block.sortition_hash.as_bytes(),
|
||||
|
||||
@@ -1712,7 +1712,7 @@ impl BlockMinerThread {
|
||||
fn make_vrf_proof(&mut self) -> Option<VRFProof> {
|
||||
// if we're a mock miner, then make sure that the keychain has a keypair for the mocked VRF
|
||||
// key
|
||||
let vrf_proof = if self.config.get_node_config().mock_mining {
|
||||
let vrf_proof = if self.config.get_node_config(false).mock_mining {
|
||||
self.keychain.generate_proof(
|
||||
VRF_MOCK_MINER_KEY,
|
||||
self.burn_block.sortition_hash.as_bytes(),
|
||||
@@ -2535,7 +2535,7 @@ impl BlockMinerThread {
|
||||
let res = bitcoin_controller.submit_operation(target_epoch_id, op, &mut op_signer, attempt);
|
||||
if res.is_none() {
|
||||
self.failed_to_submit_last_attempt = true;
|
||||
if !self.config.get_node_config().mock_mining {
|
||||
if !self.config.get_node_config(false).mock_mining {
|
||||
warn!("Relayer: Failed to submit Bitcoin transaction");
|
||||
return None;
|
||||
}
|
||||
@@ -3518,7 +3518,7 @@ impl RelayerThread {
|
||||
return false;
|
||||
}
|
||||
|
||||
if !self.config.get_node_config().mock_mining {
|
||||
if !self.config.get_node_config(false).mock_mining {
|
||||
// mock miner can't mine microblocks yet, so don't stop it from trying multiple
|
||||
// anchored blocks
|
||||
if self.mined_stacks_block && self.config.node.mine_microblocks {
|
||||
@@ -4777,7 +4777,7 @@ impl StacksNode {
|
||||
let local_peer = p2p_net.local_peer.clone();
|
||||
|
||||
// setup initial key registration
|
||||
let leader_key_registration_state = if config.get_node_config().mock_mining {
|
||||
let leader_key_registration_state = if config.get_node_config(false).mock_mining {
|
||||
// mock mining, pretend to have a registered key
|
||||
let (vrf_public_key, _) = keychain.make_vrf_keypair(VRF_MOCK_MINER_KEY);
|
||||
LeaderKeyRegistrationState::Active(RegisteredKey {
|
||||
|
||||
@@ -195,7 +195,7 @@ impl RunLoop {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if self.config.get_node_config().mock_mining {
|
||||
if self.config.get_node_config(false).mock_mining {
|
||||
info!("No UTXOs found, but configured to mock mine");
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@@ -373,7 +373,7 @@ impl RunLoop {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if self.config.get_node_config().mock_mining {
|
||||
if self.config.get_node_config(false).mock_mining {
|
||||
info!("No UTXOs found, but configured to mock mine");
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@@ -149,7 +149,7 @@ fn inner_neon_integration_test_conf(seed: Option<Vec<u8>>) -> (Config, StacksAdd
|
||||
burnchain.peer_host = Some("127.0.0.1".to_string());
|
||||
}
|
||||
|
||||
let magic_bytes = Config::from_config_file(cfile)
|
||||
let magic_bytes = Config::from_config_file(cfile, false)
|
||||
.unwrap()
|
||||
.burnchain
|
||||
.magic_bytes;
|
||||
|
||||
@@ -125,6 +125,7 @@ impl SignerTest {
|
||||
3000,
|
||||
Some(100_000),
|
||||
None,
|
||||
Some(9000),
|
||||
);
|
||||
|
||||
let mut running_signers = Vec::new();
|
||||
@@ -511,6 +512,23 @@ impl SignerTest {
|
||||
entries.public_keys
|
||||
}
|
||||
|
||||
fn get_signer_metrics(&self) -> String {
|
||||
#[cfg(feature = "monitoring_prom")]
|
||||
{
|
||||
let client = reqwest::blocking::Client::new();
|
||||
let res = client
|
||||
.get("http://localhost:9000/metrics")
|
||||
.send()
|
||||
.unwrap()
|
||||
.text()
|
||||
.unwrap();
|
||||
|
||||
return res;
|
||||
}
|
||||
#[cfg(not(feature = "monitoring_prom"))]
|
||||
return String::new();
|
||||
}
|
||||
|
||||
fn generate_invalid_transactions(&self) -> Vec<StacksTransaction> {
|
||||
let host = self
|
||||
.running_nodes
|
||||
@@ -741,6 +759,7 @@ impl SignerTest {
|
||||
3000 + signer_idx,
|
||||
Some(100_000),
|
||||
None,
|
||||
Some(9000 + signer_idx),
|
||||
)
|
||||
.pop()
|
||||
.unwrap();
|
||||
@@ -782,6 +801,10 @@ fn spawn_signer(
|
||||
let config = SignerConfig::load_from_str(data).unwrap();
|
||||
let ev = SignerEventReceiver::new(config.network.is_mainnet());
|
||||
let endpoint = config.endpoint;
|
||||
#[cfg(feature = "monitoring_prom")]
|
||||
{
|
||||
stacks_signer::monitoring::start_serving_monitoring_metrics(config.clone()).ok();
|
||||
}
|
||||
let runloop: stacks_signer::runloop::RunLoop = stacks_signer::runloop::RunLoop::from(config);
|
||||
let mut signer: Signer<
|
||||
RunLoopCommand,
|
||||
@@ -1329,7 +1352,8 @@ fn stackerdb_block_proposal() {
|
||||
.init();
|
||||
|
||||
info!("------------------------- Test Setup -------------------------");
|
||||
let mut signer_test = SignerTest::new(5);
|
||||
let num_signers = 5;
|
||||
let mut signer_test = SignerTest::new(num_signers);
|
||||
let timeout = Duration::from_secs(200);
|
||||
let short_timeout = Duration::from_secs(30);
|
||||
|
||||
@@ -1347,6 +1371,17 @@ fn stackerdb_block_proposal() {
|
||||
.0
|
||||
.verify(&key, proposed_signer_signature_hash.as_bytes()));
|
||||
|
||||
// Test prometheus metrics response
|
||||
#[cfg(feature = "monitoring_prom")]
|
||||
{
|
||||
let metrics_response = signer_test.get_signer_metrics();
|
||||
|
||||
// Because 5 signers are running in the same process, the prometheus metrics
|
||||
// are incremented once for every signer. This is why we expect the metric to be
|
||||
// `5`, even though there is only one block proposed.
|
||||
let expected_result = format!("stacks_signer_block_proposals_received {}", num_signers);
|
||||
assert!(metrics_response.contains(&expected_result));
|
||||
}
|
||||
signer_test.shutdown();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user