mirror of
https://github.com/alexgo-io/stacks-puppet-node.git
synced 2026-04-28 11:46:07 +08:00
Merge branch 'release/2.5.0.0.0' into fix/2.5-changelog_btc-height
This commit is contained in:
@@ -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"]
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
"#
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user