Merge branch 'release/2.5.0.0.0' into fix/2.5-changelog_btc-height

This commit is contained in:
wileyj
2024-04-15 18:22:30 -07:00
committed by GitHub
7 changed files with 152 additions and 8 deletions

View File

@@ -23,5 +23,5 @@ RUN case ${TARGETPLATFORM} in \
&& unzip ${BIN_ARCH}.zip -d /out
FROM --platform=${TARGETPLATFORM} alpine
COPY --from=builder /out/stacks-node /bin/
COPY --from=builder /out/stacks-node /out/stacks-signer /bin/
CMD ["stacks-node", "mainnet"]

View File

@@ -23,5 +23,5 @@ RUN case ${TARGETPLATFORM} in \
&& unzip ${BIN_ARCH}.zip -d /out
FROM --platform=${TARGETPLATFORM} debian:bookworm
COPY --from=builder /out/stacks-node /bin/
COPY --from=builder /out/stacks-node /out/stacks-signer /bin/
CMD ["stacks-node", "mainnet"]

View File

@@ -64,6 +64,8 @@ pub enum Command {
GenerateFiles(GenerateFilesArgs),
/// Generate a signature for Stacking transactions
GenerateStackingSignature(GenerateStackingSignatureArgs),
/// Check a configuration file and output config information
CheckConfig(RunSignerArgs),
}
/// Basic arguments for all cyrptographic and stacker-db functionality

View File

@@ -14,6 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
use std::fmt::Display;
use std::fs;
use std::net::{SocketAddr, ToSocketAddrs};
use std::path::PathBuf;
@@ -329,6 +330,39 @@ impl GlobalConfig {
pub fn load_from_file(path: &str) -> Result<Self, ConfigError> {
Self::try_from(&PathBuf::from(path))
}
/// Return a string with non-sensitive configuration
/// information for logging purposes
pub fn config_to_log_string(&self) -> String {
let tx_fee = match self.tx_fee_ustx {
0 => "default".to_string(),
_ => (self.tx_fee_ustx as f64 / 1_000_000.0).to_string(),
};
format!(
r#"
Stacks node host: {node_host}
Signer endpoint: {endpoint}
Stacks address: {stacks_address}
Public key: {public_key}
Network: {network}
Database path: {db_path}
DKG transaction fee: {tx_fee} uSTX
"#,
node_host = self.node_host,
endpoint = self.endpoint,
stacks_address = self.stacks_address.to_string(),
public_key = StacksPublicKey::from_private(&self.stacks_private_key).to_hex(),
network = self.network,
db_path = self.db_path.to_str().unwrap_or_default(),
tx_fee = tx_fee
)
}
}
impl Display for GlobalConfig {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.config_to_log_string())
}
}
/// Helper function for building a signer config for each provided signer private key
@@ -412,4 +446,24 @@ mod tests {
assert_eq!(config.auth_password, "melon");
}
#[test]
fn test_config_to_string() {
let config = GlobalConfig::load_from_file("./src/tests/conf/signer-0.toml").unwrap();
let config_str = config.config_to_log_string();
assert_eq!(
config_str,
format!(
r#"
Stacks node host: 127.0.0.1:20443
Signer endpoint: [::1]:30000
Stacks address: ST3FPN8KBZ3YPBP0ZJGAAHTVFMQDTJCR5QPS7VTNJ
Public key: 03bc489f27da3701d9f9e577c88de5567cf4023111b7577042d55cde4d823a3505
Network: testnet
Database path: :memory:
DKG transaction fee: 0.01 uSTX
"#
)
);
}
}

View File

@@ -38,12 +38,12 @@ use clap::Parser;
use clarity::vm::types::QualifiedContractIdentifier;
use libsigner::{RunningSigner, Signer, SignerEventReceiver, SignerSession, StackerDBSession};
use libstackerdb::StackerDBChunkData;
use slog::{slog_debug, slog_error};
use slog::{slog_debug, slog_error, slog_info};
use stacks_common::codec::read_next;
use stacks_common::types::chainstate::StacksPrivateKey;
use stacks_common::util::hash::to_hex;
use stacks_common::util::secp256k1::{MessageSignature, Secp256k1PublicKey};
use stacks_common::{debug, error};
use stacks_common::{debug, error, info};
use stacks_signer::cli::{
Cli, Command, GenerateFilesArgs, GenerateStackingSignatureArgs, GetChunkArgs,
GetLatestChunkArgs, PutChunkArgs, RunDkgArgs, RunSignerArgs, SignArgs, StackerDBArgs,
@@ -85,6 +85,7 @@ fn write_chunk_to_stdout(chunk_opt: Option<Vec<u8>>) {
fn spawn_running_signer(path: &PathBuf) -> SpawnedSigner {
let config = GlobalConfig::try_from(path).unwrap();
let endpoint = config.endpoint;
info!("Starting signer with config: {}", config);
let (cmd_send, cmd_recv) = channel();
let (res_send, res_recv) = channel();
let ev = SignerEventReceiver::new(config.network.is_mainnet());
@@ -349,6 +350,11 @@ fn handle_generate_stacking_signature(
signature
}
fn handle_check_config(args: RunSignerArgs) {
let config = GlobalConfig::try_from(&args.config).unwrap();
println!("Config: {}", config);
}
/// Helper function for writing the given contents to filename in the given directory
fn write_file(dir: &Path, filename: &str, contents: &str) {
let file_path = dir.join(filename);
@@ -397,6 +403,9 @@ fn main() {
Command::GenerateStackingSignature(args) => {
handle_generate_stacking_signature(args, true);
}
Command::CheckConfig(args) => {
handle_check_config(args);
}
}
}

View File

@@ -271,6 +271,32 @@ mod tests {
// Should default add xenon affirmation overrides
assert_eq!(config.burnchain.affirmation_overrides.len(), 5);
}
#[test]
fn should_override_xenon_default_affirmation_overrides() {
let affirmation_string = "aaapnnnnnnnnnnnnnnnnnnnnnnnnnnnnppnnnnnnnnnnnnnnnnnnnnnnnnpppppnnnnnnnnnnnnnnnnnnnnnnnpppppppppppppppnnnnnnnnnnnnnnnnnnnnnnnppppppppppnnnnnnnnnnnnnnnnnnnppppnnnnnnnnnnnnnnnnnnnnnnnppppppppnnnnnnnnnnnnnnnnnnnnnnnppnppnnnnnnnnnnnnnnnnnnnnnnnppppnnnnnnnnnnnnnnnnnnnnnnnnnppppppnnnnnnnnnnnnnnnnnnnnnnnnnppnnnnnnnnnnnnnnnnnnnnnnnnnpppppppnnnnnnnnnnnnnnnnnnnnnnnnnnpnnnnnnnnnnnnnnnnnnnnnnnnnpppnppppppppppppppnnppppnpa";
let affirmation =
AffirmationMap::decode(affirmation_string).expect("Failed to decode affirmation map");
let config = Config::from_config_file(
ConfigFile::from_str(&format!(
r#"
[burnchain]
chain = "bitcoin"
mode = "xenon"
[[burnchain.affirmation_overrides]]
reward_cycle = 413
affirmation = "{affirmation_string}"
"#,
))
.expect("Expected to be able to parse config file from string"),
)
.expect("Expected to be able to parse affirmation map from file");
// Should default add xenon affirmation overrides, but overwrite with the configured one above
assert_eq!(config.burnchain.affirmation_overrides.len(), 5);
assert_eq!(config.burnchain.affirmation_overrides[&413], affirmation);
}
}
impl ConfigFile {
@@ -1470,7 +1496,6 @@ impl BurnchainConfigFile {
BITCOIN_TESTNET_STACKS_25_BURN_HEIGHT,
)
.unwrap();
eprintln!("last_present_cycle = {last_present_cycle}");
assert_eq!(
u64::try_from(affirmations_pre_2_5.len()).unwrap(),
last_present_cycle - 1
@@ -1481,10 +1506,12 @@ impl BurnchainConfigFile {
BITCOIN_TESTNET_STACKS_25_REORGED_HEIGHT,
)
.unwrap();
eprintln!("last_present_cycle = {last_present_cycle}, last_override = {last_override}");
let override_values = ["a", "n"];
for (override_index, reward_cycle) in (last_present_cycle + 1..=last_override).enumerate() {
let affirmation = format!("{affirmations_pre_2_5}{}", "a".repeat(override_index + 1));
assert!(override_values.len() > override_index);
let overrides = override_values[..(override_index + 1)].join("");
let affirmation = format!("{affirmations_pre_2_5}{overrides}");
default_overrides.push(AffirmationOverride {
reward_cycle,
affirmation,
@@ -1493,7 +1520,10 @@ impl BurnchainConfigFile {
if let Some(affirmation_overrides) = self.affirmation_overrides.as_mut() {
for affirmation in default_overrides {
affirmation_overrides.push(affirmation);
// insert at front, so that the hashmap uses the configured overrides
// instead of the defaults (the configured overrides will write over the
// the defaults because they come later in the list).
affirmation_overrides.insert(0, affirmation);
}
} else {
self.affirmation_overrides = Some(default_overrides);

View File

@@ -1169,6 +1169,55 @@ impl BlockMinerThread {
return vec![];
}
let sortdb_tip_handle = burn_db.index_handle_at_tip();
let stacks_tips: Vec<_> = stacks_tips
.into_iter()
.filter(|candidate| {
let candidate_ch = &candidate.consensus_hash;
let candidate_burn_ht = match SortitionDB::get_block_snapshot_consensus(
sortdb_tip_handle.conn(),
candidate_ch
) {
Ok(Some(x)) => x.block_height,
Ok(None) => {
warn!("Tried to evaluate potential chain tip with an unknown consensus hash";
"consensus_hash" => %candidate_ch,
"stacks_block_hash" => %candidate.anchored_block_hash);
return false;
},
Err(e) => {
warn!("Error while trying to evaluate potential chain tip with an unknown consensus hash";
"consensus_hash" => %candidate_ch,
"stacks_block_hash" => %candidate.anchored_block_hash,
"err" => ?e);
return false;
},
};
let tip_ch = match sortdb_tip_handle.get_consensus_at(candidate_burn_ht) {
Ok(Some(x)) => x,
Ok(None) => {
warn!("Tried to evaluate potential chain tip with a consensus hash ahead of canonical tip";
"consensus_hash" => %candidate_ch,
"stacks_block_hash" => %candidate.anchored_block_hash);
return false;
},
Err(e) => {
warn!("Error while trying to evaluate potential chain tip with an unknown consensus hash";
"consensus_hash" => %candidate_ch,
"stacks_block_hash" => %candidate.anchored_block_hash,
"err" => ?e);
return false;
},
};
if &tip_ch != candidate_ch {
false
} else {
true
}
})
.collect();
let mut considered = HashSet::new();
let mut candidates = vec![];
let end_height = stacks_tips[0].height;