Merge branch 'develop' into draft/multisig-order-independence

This commit is contained in:
Jude Nelson
2024-05-10 21:23:16 +00:00
committed by GitHub
51 changed files with 3634 additions and 555 deletions

View File

@@ -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 = []

View File

@@ -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;
}

View File

@@ -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([

View File

@@ -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,

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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(),

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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();
}