Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove dead CLI commands including Sign, DKG, and generate Files comm… #4772

Merged
merged 2 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 0 additions & 84 deletions stacks-signer/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
// 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::io::{self, Read};
use std::net::SocketAddr;
use std::path::PathBuf;

use blockstack_lib::chainstate::stacks::address::PoxAddress;
Expand All @@ -28,8 +27,6 @@ use stacks_common::address::{
};
use stacks_common::types::chainstate::StacksPrivateKey;

use crate::config::Network;

extern crate alloc;

#[derive(Parser, Debug)]
Expand All @@ -52,16 +49,8 @@ pub enum Command {
ListChunks(StackerDBArgs),
/// Upload a chunk to the stacker-db instance
PutChunk(PutChunkArgs),
/// Run DKG and sign the message through the stacker-db instance
DkgSign(SignArgs),
/// Sign the message through the stacker-db instance
Sign(SignArgs),
/// Run a DKG round through the stacker-db instance
Dkg(RunDkgArgs),
/// Run the signer, waiting for events from the stacker-db instance
Run(RunSignerArgs),
/// Generate necessary files for running a collection of signers
GenerateFiles(GenerateFilesArgs),
/// Generate a signature for Stacking transactions
GenerateStackingSignature(GenerateStackingSignatureArgs),
/// Check a configuration file and output config information
Expand Down Expand Up @@ -126,34 +115,6 @@ pub struct PutChunkArgs {
pub data: alloc::vec::Vec<u8>,
}

#[derive(Parser, Debug, Clone)]
/// Arguments for the dkg-sign and sign command
pub struct SignArgs {
/// Path to config file
#[arg(long, short, value_name = "FILE")]
pub config: PathBuf,
/// The reward cycle the signer is registered for and wants to sign for
/// Note: this must be the current reward cycle of the node
#[arg(long, short)]
pub reward_cycle: u64,
/// The data to sign
#[arg(required = false, value_parser = parse_data)]
// Note this weirdness is due to https://github.com/clap-rs/clap/discussions/4695
// Need to specify the long name here due to invalid parsing in Clap which looks at the NAME rather than the TYPE which causes issues in how it handles Vec's.
pub data: alloc::vec::Vec<u8>,
}

#[derive(Parser, Debug, Clone)]
/// Arguments for the Dkg command
pub struct RunDkgArgs {
/// Path to config file
#[arg(long, short, value_name = "FILE")]
pub config: PathBuf,
/// The reward cycle the signer is registered for and wants to peform DKG for
#[arg(long, short)]
pub reward_cycle: u64,
}

#[derive(Parser, Debug, Clone)]
/// Arguments for the Run command
pub struct RunSignerArgs {
Expand All @@ -162,36 +123,6 @@ pub struct RunSignerArgs {
pub config: PathBuf,
}

#[derive(Parser, Debug, Clone)]
/// Arguments for the generate-files command
pub struct GenerateFilesArgs {
/// The Stacks node to connect to
#[arg(long)]
pub host: SocketAddr,
#[arg(
long,
required_unless_present = "private_keys",
conflicts_with = "private_keys"
)]
/// The number of signers to generate
pub num_signers: Option<u32>,
#[clap(long, value_name = "FILE")]
/// A path to a file containing a list of hexadecimal Stacks private keys of the signers
pub private_keys: Option<PathBuf>,
#[arg(long, value_parser = parse_network)]
/// The network to use. One of "mainnet", "testnet", or "mocknet".
pub network: Network,
/// The directory to write the test data files to
#[arg(long, default_value = ".")]
pub dir: PathBuf,
/// The number of milliseconds to wait when polling for events from the stacker-db instance.
#[arg(long)]
pub timeout: Option<u64>,
#[arg(long)]
/// The authorization password to use to connect to the validate block proposal node endpoint
pub password: String,
}

#[derive(Clone, Debug)]
/// Wrapper around `Pox4SignatureTopic` to implement `ValueEnum`
pub struct StackingSignatureMethod(Pox4SignatureTopic);
Expand Down Expand Up @@ -312,21 +243,6 @@ fn parse_data(data: &str) -> Result<Vec<u8>, String> {
Ok(data)
}

/// Parse the network. Must be one of "mainnet", "testnet", or "mocknet".
fn parse_network(network: &str) -> Result<Network, String> {
Ok(match network.to_lowercase().as_str() {
"mainnet" => Network::Mainnet,
"testnet" => Network::Testnet,
"mocknet" => Network::Mocknet,
_ => {
return Err(format!(
"Invalid network: {}. Must be one of \"mainnet\", \"testnet\", or \"mocknet\".",
network
))
}
})
}

#[cfg(test)]
mod tests {
use blockstack_lib::chainstate::stacks::address::{PoxAddressType20, PoxAddressType32};
Expand Down
214 changes: 8 additions & 206 deletions stacks-signer/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,33 +26,25 @@ extern crate serde;
extern crate serde_json;
extern crate toml;

use std::fs::File;
use std::io::{self, BufRead, Write};
use std::path::{Path, PathBuf};
use std::io::{self, Write};
use std::path::PathBuf;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::time::Duration;

use blockstack_lib::util_lib::signed_structured_data::pox4::make_pox_4_signer_key_signature;
use clap::Parser;
use clarity::vm::types::QualifiedContractIdentifier;
use libsigner::{
BlockProposalSigners, RunningSigner, Signer, SignerEventReceiver, SignerSession,
StackerDBSession,
};
use libsigner::{RunningSigner, Signer, SignerEventReceiver, SignerSession, StackerDBSession};
use libstackerdb::StackerDBChunkData;
use slog::{slog_debug, slog_error, slog_info};
use stacks_common::codec::read_next;
use stacks_common::types::chainstate::StacksPrivateKey;
use slog::{slog_debug, slog_info};
use stacks_common::util::hash::to_hex;
use stacks_common::util::secp256k1::{MessageSignature, Secp256k1PublicKey};
use stacks_common::{debug, error, info};
use stacks_common::{debug, info};
use stacks_signer::cli::{
Cli, Command, GenerateFilesArgs, GenerateStackingSignatureArgs, GetChunkArgs,
GetLatestChunkArgs, PutChunkArgs, RunDkgArgs, RunSignerArgs, SignArgs, StackerDBArgs,
Cli, Command, GenerateStackingSignatureArgs, GetChunkArgs, GetLatestChunkArgs, PutChunkArgs,
RunSignerArgs, StackerDBArgs,
};
use stacks_signer::config::{build_signer_config_tomls, GlobalConfig};
use stacks_signer::config::GlobalConfig;
use stacks_signer::runloop::{RunLoop, RunLoopCommand};
use stacks_signer::signer::Command as SignerCommand;
use tracing_subscriber::prelude::*;
use tracing_subscriber::{fmt, EnvFilter};
use wsts::state_machine::OperationResult;
Expand Down Expand Up @@ -108,64 +100,6 @@ fn spawn_running_signer(path: &PathBuf) -> SpawnedSigner {
}
}

// Process a DKG result
fn process_dkg_result(dkg_res: &[OperationResult]) {
assert!(dkg_res.len() == 1, "Received unexpected number of results");
let dkg = dkg_res.first().unwrap();
match dkg {
OperationResult::Dkg(aggregate_key) => {
println!("Received aggregate group key: {aggregate_key}");
}
OperationResult::Sign(signature) => {
panic!(
"Received unexpected signature ({},{})",
&signature.R, &signature.z,
);
}
OperationResult::SignTaproot(schnorr_proof) => {
panic!(
"Received unexpected schnorr proof ({},{})",
&schnorr_proof.r, &schnorr_proof.s,
);
}
OperationResult::DkgError(dkg_error) => {
panic!("Received DkgError {}", dkg_error);
}
OperationResult::SignError(sign_error) => {
panic!("Received SignError {}", sign_error);
}
}
}

// Process a Sign result
fn process_sign_result(sign_res: &[OperationResult]) {
assert!(sign_res.len() == 1, "Received unexpected number of results");
let sign = sign_res.first().unwrap();
match sign {
OperationResult::Dkg(aggregate_key) => {
panic!("Received unexpected aggregate group key: {aggregate_key}");
}
OperationResult::Sign(signature) => {
panic!(
"Received bood signature ({},{})",
&signature.R, &signature.z,
);
}
OperationResult::SignTaproot(schnorr_proof) => {
panic!(
"Received unexpected schnorr proof ({},{})",
&schnorr_proof.r, &schnorr_proof.s,
);
}
OperationResult::DkgError(dkg_error) => {
panic!("Received DkgError {}", dkg_error);
}
OperationResult::SignError(sign_error) => {
panic!("Received SignError {}", sign_error);
}
}
}

fn handle_get_chunk(args: GetChunkArgs) {
debug!("Getting chunk...");
let mut session = stackerdb_session(&args.db_args.host, args.db_args.contract);
Expand Down Expand Up @@ -198,73 +132,6 @@ fn handle_put_chunk(args: PutChunkArgs) {
println!("{}", serde_json::to_string(&chunk_ack).unwrap());
}

fn handle_dkg(args: RunDkgArgs) {
debug!("Running DKG...");
let spawned_signer = spawn_running_signer(&args.config);
let dkg_command = RunLoopCommand {
reward_cycle: args.reward_cycle,
command: SignerCommand::Dkg,
};
spawned_signer.cmd_send.send(dkg_command).unwrap();
let dkg_res = spawned_signer.res_recv.recv().unwrap();
process_dkg_result(&dkg_res);
spawned_signer.running_signer.stop();
}

fn handle_sign(args: SignArgs) {
debug!("Signing message...");
let spawned_signer = spawn_running_signer(&args.config);
let Some(block_proposal) = read_next::<BlockProposalSigners, _>(&mut &args.data[..]).ok()
else {
error!("Unable to parse provided message as a BlockProposalSigners.");
spawned_signer.running_signer.stop();
return;
};
let sign_command = RunLoopCommand {
reward_cycle: args.reward_cycle,
command: SignerCommand::Sign {
block_proposal,
is_taproot: false,
merkle_root: None,
},
};
spawned_signer.cmd_send.send(sign_command).unwrap();
let sign_res = spawned_signer.res_recv.recv().unwrap();
process_sign_result(&sign_res);
spawned_signer.running_signer.stop();
}

fn handle_dkg_sign(args: SignArgs) {
debug!("Running DKG and signing message...");
let spawned_signer = spawn_running_signer(&args.config);
let Some(block_proposal) = read_next::<BlockProposalSigners, _>(&mut &args.data[..]).ok()
else {
error!("Unable to parse provided message as a BlockProposalSigners.");
spawned_signer.running_signer.stop();
return;
};
let dkg_command = RunLoopCommand {
reward_cycle: args.reward_cycle,
command: SignerCommand::Dkg,
};
let sign_command = RunLoopCommand {
reward_cycle: args.reward_cycle,
command: SignerCommand::Sign {
block_proposal,
is_taproot: false,
merkle_root: None,
},
};
// First execute DKG, then sign
spawned_signer.cmd_send.send(dkg_command).unwrap();
spawned_signer.cmd_send.send(sign_command).unwrap();
let dkg_res = spawned_signer.res_recv.recv().unwrap();
process_dkg_result(&dkg_res);
let sign_res = spawned_signer.res_recv.recv().unwrap();
process_sign_result(&sign_res);
spawned_signer.running_signer.stop();
}

fn handle_run(args: RunSignerArgs) {
debug!("Running signer...");
let spawned_signer = spawn_running_signer(&args.config);
Expand All @@ -273,50 +140,6 @@ fn handle_run(args: RunSignerArgs) {
let _ = spawned_signer.running_signer.join();
}

fn handle_generate_files(args: GenerateFilesArgs) {
debug!("Generating files...");
let signer_stacks_private_keys = if let Some(path) = args.private_keys {
let file = File::open(path).unwrap();
let reader = io::BufReader::new(file);

let private_keys: Vec<String> = reader.lines().collect::<Result<_, _>>().unwrap();
println!("{}", StacksPrivateKey::new().to_hex());
let private_keys = private_keys
.iter()
.map(|key| StacksPrivateKey::from_hex(key).expect("Failed to parse private key."))
.collect::<Vec<StacksPrivateKey>>();
if private_keys.is_empty() {
panic!("Private keys file is empty.");
}
private_keys
} else {
let num_signers = args.num_signers.unwrap();
if num_signers == 0 {
panic!("--num-signers must be non-zero.");
}
(0..num_signers)
.map(|_| StacksPrivateKey::new())
.collect::<Vec<StacksPrivateKey>>()
};

let signer_config_tomls = build_signer_config_tomls(
&signer_stacks_private_keys,
&args.host.to_string(),
args.timeout.map(Duration::from_millis),
&args.network,
&args.password,
rand::random(),
3000,
None,
None,
None,
);
debug!("Built {:?} signer config tomls.", signer_config_tomls.len());
for (i, file_contents) in signer_config_tomls.iter().enumerate() {
write_file(&args.dir, &format!("signer-{}.toml", i), file_contents);
}
}

fn handle_generate_stacking_signature(
args: GenerateStackingSignatureArgs,
do_print: bool,
Expand Down Expand Up @@ -370,15 +193,6 @@ fn handle_check_config(args: RunSignerArgs) {
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);
let filename = file_path.to_str().unwrap();
let mut file = File::create(filename).unwrap();
file.write_all(contents.as_bytes()).unwrap();
println!("Created file: {}", filename);
}

fn main() {
let cli = Cli::parse();

Expand All @@ -400,21 +214,9 @@ fn main() {
Command::PutChunk(args) => {
handle_put_chunk(args);
}
Command::Dkg(args) => {
handle_dkg(args);
}
Command::DkgSign(args) => {
handle_dkg_sign(args);
}
Command::Sign(args) => {
handle_sign(args);
}
Command::Run(args) => {
handle_run(args);
}
Command::GenerateFiles(args) => {
handle_generate_files(args);
}
Command::GenerateStackingSignature(args) => {
handle_generate_stacking_signature(args, true);
}
Expand Down