mirror of
https://github.com/alexgo-io/stacks-puppet-node.git
synced 2026-01-13 08:40:45 +08:00
Add pox contract ID option to config to overwrite node result
Signed-off-by: Jacinta Ferrant <jacinta@trustmachines.co>
This commit is contained in:
@@ -105,6 +105,8 @@ pub struct Config {
|
||||
pub endpoint: SocketAddr,
|
||||
/// smart contract that controls the target stackerdb
|
||||
pub stackerdb_contract_id: QualifiedContractIdentifier,
|
||||
/// smart contract that controls the target stackerdb
|
||||
pub pox_contract_id: Option<QualifiedContractIdentifier>,
|
||||
/// The Scalar representation of the private key for signer communication
|
||||
pub message_private_key: Scalar,
|
||||
/// The signer's Stacks private key
|
||||
@@ -137,8 +139,11 @@ struct RawConfigFile {
|
||||
pub node_host: String,
|
||||
/// endpoint to stackerdb receiver
|
||||
pub endpoint: String,
|
||||
/// contract identifier
|
||||
// FIXME: these contract's should go away in non testing scenarios. Make them both optionals.
|
||||
/// Stacker db contract identifier
|
||||
pub stackerdb_contract_id: String,
|
||||
/// pox contract identifier
|
||||
pub pox_contract_id: Option<String>,
|
||||
/// the 32 byte ECDSA private key used to sign blocks, chunks, and transactions
|
||||
pub message_private_key: String,
|
||||
/// The hex representation of the signer's Stacks private key used for communicating
|
||||
@@ -218,6 +223,17 @@ impl TryFrom<RawConfigFile> for Config {
|
||||
)
|
||||
})?;
|
||||
|
||||
let pox_contract_id = if let Some(id) = raw_data.pox_contract_id.as_ref() {
|
||||
Some(QualifiedContractIdentifier::parse(id).map_err(|_| {
|
||||
ConfigError::BadField(
|
||||
"pox_contract_id".to_string(),
|
||||
raw_data.pox_contract_id.unwrap_or("".to_string()),
|
||||
)
|
||||
})?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let message_private_key =
|
||||
Scalar::try_from(raw_data.message_private_key.as_str()).map_err(|_| {
|
||||
ConfigError::BadField(
|
||||
@@ -269,6 +285,7 @@ impl TryFrom<RawConfigFile> for Config {
|
||||
node_host,
|
||||
endpoint,
|
||||
stackerdb_contract_id,
|
||||
pox_contract_id,
|
||||
message_private_key,
|
||||
stacks_private_key,
|
||||
stacks_address,
|
||||
|
||||
@@ -269,6 +269,7 @@ fn handle_generate_files(args: GenerateFilesArgs) {
|
||||
args.num_keys,
|
||||
&args.db_args.host.to_string(),
|
||||
&args.db_args.contract.to_string(),
|
||||
None,
|
||||
args.timeout.map(Duration::from_millis),
|
||||
);
|
||||
debug!("Built {:?} signer config tomls.", signer_config_tomls.len());
|
||||
|
||||
@@ -36,7 +36,7 @@ pub enum RunLoopCommand {
|
||||
/// The RunLoop state
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum State {
|
||||
// TODO: add a state for startup: such as Unitialized where it indicates we need to replay events/configure the signer
|
||||
// TODO: Unitialized should indicate we need to replay events/configure the signer
|
||||
/// The runloop signer is unitialized
|
||||
Unitialized,
|
||||
/// The runloop is idle
|
||||
@@ -180,7 +180,7 @@ impl<C: Coordinatable> RunLoop<C> {
|
||||
self.state = State::Idle;
|
||||
}
|
||||
Err(e) => {
|
||||
// TODO: is this a fatal error? If we fail at startup to access the stacks client to see if DKG was set...this seems pretty fatal..
|
||||
// TODO:do a backoff retry here. This could fail because of node spinning up.
|
||||
panic!(
|
||||
"Failed to load aggregate public key from stacks client: {:?}",
|
||||
e
|
||||
@@ -355,7 +355,7 @@ impl<C: Coordinatable> SignerRunLoop<Vec<OperationResult>, RunLoopCommand> for R
|
||||
if self.should_run_dkg() {
|
||||
// Add it to the front of the queue so it is set before any other commands get processed!
|
||||
debug!("DKG has not run and needs to be queued. Adding it to the front of the queue.");
|
||||
self.commands.push_back(RunLoopCommand::Dkg);
|
||||
self.commands.push_front(RunLoopCommand::Dkg);
|
||||
}
|
||||
// The process the next command
|
||||
// Must be called AFTER processing the event as the state may update to IDLE due to said event.
|
||||
|
||||
@@ -126,6 +126,8 @@ pub struct StacksClient {
|
||||
chain_id: u32,
|
||||
/// The Client used to make HTTP connects
|
||||
stacks_node_client: reqwest::blocking::Client,
|
||||
/// The pox contract ID
|
||||
pox_contract_id: Option<QualifiedContractIdentifier>,
|
||||
}
|
||||
|
||||
impl From<&Config> for StacksClient {
|
||||
@@ -142,6 +144,7 @@ impl From<&Config> for StacksClient {
|
||||
tx_version: config.network.to_transaction_version(),
|
||||
chain_id: config.network.to_chain_id(),
|
||||
stacks_node_client: reqwest::blocking::Client::new(),
|
||||
pox_contract_id: config.pox_contract_id.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -267,6 +270,10 @@ impl StacksClient {
|
||||
|
||||
/// Helper function to retrieve the pox contract address and name from the stacks node
|
||||
fn get_pox_contract(&self) -> Result<(StacksAddress, ContractName), ClientError> {
|
||||
// Check if we have overwritten the pox contract ID in the config
|
||||
if let Some(pox_contract) = self.pox_contract_id.clone() {
|
||||
return Ok((pox_contract.issuer.into(), pox_contract.name));
|
||||
}
|
||||
debug!("Retrieving pox contract ID...");
|
||||
// TODO: we may want to cache the pox contract inside the client itself (calling this function once on init)
|
||||
let send_request = || {
|
||||
|
||||
@@ -14,7 +14,8 @@ pub fn build_signer_config_tomls(
|
||||
signer_stacks_private_keys: &[StacksPrivateKey],
|
||||
num_keys: u32,
|
||||
node_host: &str,
|
||||
contract_id: &str,
|
||||
stackerdb_contract_id: &str,
|
||||
pox_contract_id: Option<&str>,
|
||||
timeout: Option<Duration>,
|
||||
) -> Vec<String> {
|
||||
let num_signers = signer_stacks_private_keys.len() as u32;
|
||||
@@ -73,7 +74,7 @@ stacks_private_key = "{stacks_private_key}"
|
||||
node_host = "{node_host}"
|
||||
endpoint = "{endpoint}"
|
||||
network = "testnet"
|
||||
stackerdb_contract_id = "{contract_id}"
|
||||
stackerdb_contract_id = "{stackerdb_contract_id}"
|
||||
signer_id = {id}
|
||||
{signers_array}
|
||||
"#
|
||||
@@ -88,8 +89,18 @@ event_timeout = {event_timeout_ms}
|
||||
"#
|
||||
)
|
||||
}
|
||||
if let Some(pox_contract_id) = pox_contract_id {
|
||||
signer_config_toml = format!(
|
||||
r#"
|
||||
{signer_config_toml}
|
||||
pox_contract_id = "{pox_contract_id}"
|
||||
"#
|
||||
);
|
||||
}
|
||||
|
||||
signer_config_tomls.push(signer_config_toml);
|
||||
}
|
||||
|
||||
signer_config_tomls
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ fn setup_stx_btc_node(
|
||||
num_signers: u32,
|
||||
signer_stacks_private_keys: &[StacksPrivateKey],
|
||||
stackerdb_contract: &str,
|
||||
pox_contract: &str,
|
||||
signer_config_tomls: &Vec<String>,
|
||||
) -> RunningNodes {
|
||||
for toml in signer_config_tomls {
|
||||
@@ -133,7 +134,21 @@ fn setup_stx_btc_node(
|
||||
submit_tx(&http_origin, &tx);
|
||||
|
||||
// mine it
|
||||
info!("Mine it...");
|
||||
info!("Mining stackerdb contract...");
|
||||
next_block_and_wait(&mut btc_regtest_controller, &blocks_processed);
|
||||
next_block_and_wait(&mut btc_regtest_controller, &blocks_processed);
|
||||
|
||||
let tx = make_contract_publish(
|
||||
&signer_stacks_private_keys[0],
|
||||
1,
|
||||
10_000,
|
||||
"pox-4",
|
||||
pox_contract,
|
||||
);
|
||||
submit_tx(&http_origin, &tx);
|
||||
|
||||
// mine it
|
||||
info!("Mining pox contract...");
|
||||
next_block_and_wait(&mut btc_regtest_controller, &blocks_processed);
|
||||
next_block_and_wait(&mut btc_regtest_controller, &blocks_processed);
|
||||
|
||||
@@ -145,6 +160,52 @@ fn setup_stx_btc_node(
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function for building our fake pox contract
|
||||
pub fn build_pox_contract(num_signers: u32) -> String {
|
||||
let mut pox_contract = String::new(); // "
|
||||
pox_contract += r#"
|
||||
;; data vars
|
||||
;;
|
||||
(define-data-var bitcoin-wallet-public-key (optional (buff 33)) none)
|
||||
"#;
|
||||
pox_contract += &format!("(define-data-var num-signers uint u{num_signers})\n");
|
||||
pox_contract += r#"
|
||||
(define-data-var num-voted uint u0)
|
||||
|
||||
;; data maps
|
||||
;;
|
||||
(define-map vote-per-signer {signer: (principal)} {candidate: (buff 33) })
|
||||
|
||||
|
||||
;; read only functions
|
||||
;;
|
||||
|
||||
(define-read-only (get-bitcoin-wallet-public-key (reward-cycle uint))
|
||||
(var-get bitcoin-wallet-public-key)
|
||||
)
|
||||
|
||||
(define-read-only (get-bitcoin-wallet-public-key-vote (signer principal) (reward-cycle uint))
|
||||
(map-get? vote-per-signer signer)
|
||||
)
|
||||
|
||||
;; public functions
|
||||
;;
|
||||
(define-public (cast-bitcoin-wallet-public-key-vote (public-key (buff 33) (reward-cycle uint)))
|
||||
(begin
|
||||
(var-set num-voted (+ (var-get num-voted) 1))
|
||||
(map-set vote-per-signer {public_key: tx-sender} {candidate: public-key})
|
||||
(if (is-eq (var-get num-voted) num-signers)
|
||||
(begin
|
||||
(var-set bitcoin-wallet-public-key (some public-key))
|
||||
(var-get bitcoin-wallet-public-key)
|
||||
(ok none))
|
||||
(ok none))
|
||||
)
|
||||
)
|
||||
"#;
|
||||
pox_contract
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stackerdb_dkg() {
|
||||
if env::var("BITCOIND_TEST") != Ok("1".into()) {
|
||||
@@ -170,9 +231,15 @@ fn test_stackerdb_dkg() {
|
||||
// Setup the neon node
|
||||
let (mut conf, _) = neon_integration_test_conf();
|
||||
|
||||
// Build our simulated pox-4 stacks contract TODO: replace this with the real deal?
|
||||
let pox_contract = build_pox_contract(num_signers);
|
||||
let pox_contract_id = QualifiedContractIdentifier::new(
|
||||
to_addr(&signer_stacks_private_keys[0]).into(),
|
||||
"pox-4".into(),
|
||||
);
|
||||
// Build the stackerdb contract
|
||||
let stackerdb_contract = build_stackerdb_contract(&signer_stacks_addresses);
|
||||
let contract_id =
|
||||
let stacker_db_contract_id =
|
||||
QualifiedContractIdentifier::new(signer_stacks_addresses[0].into(), "hello-world".into());
|
||||
|
||||
// Setup the signer and coordinator configurations
|
||||
@@ -180,7 +247,8 @@ fn test_stackerdb_dkg() {
|
||||
&signer_stacks_private_keys,
|
||||
num_keys,
|
||||
&conf.node.rpc_bind,
|
||||
&contract_id.to_string(),
|
||||
&stacker_db_contract_id.to_string(),
|
||||
Some(&pox_contract_id.to_string()),
|
||||
Some(Duration::from_millis(128)), // Timeout defaults to 5 seconds. Let's override it to 128 milliseconds.
|
||||
);
|
||||
|
||||
@@ -216,6 +284,7 @@ fn test_stackerdb_dkg() {
|
||||
num_signers,
|
||||
&signer_stacks_private_keys,
|
||||
&stackerdb_contract,
|
||||
&pox_contract,
|
||||
&signer_configs,
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user