diff --git a/Cargo.lock b/Cargo.lock index 7a8502fa3..5bc70b146 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2353,9 +2353,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "p256k1" -version = "5.5.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e81c2cb5a1936d3f26278f9d698932239d03ddf0d5818392d91cd5f98ffc79" +checksum = "5afcf536d20c074ef45371ee9a654dcfc46fb2dde18ecc54ec30c936eb850fa2" dependencies = [ "bindgen", "bitvec", @@ -3548,7 +3548,6 @@ dependencies = [ "lazy_static", "libc", "libsigner", - "p256k1", "pico-args", "rand 0.7.3", "regex", @@ -3582,7 +3581,6 @@ dependencies = [ "hashbrown 0.14.0", "libsigner", "libstackerdb", - "p256k1", "rand_core 0.6.4", "reqwest", "secp256k1", @@ -3618,7 +3616,6 @@ dependencies = [ "libstackerdb", "mio 0.6.23", "nix", - "p256k1", "percent-encoding", "pox-locking", "prometheus", @@ -4711,9 +4708,9 @@ dependencies = [ [[package]] name = "wsts" -version = "4.0.0" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a0c0ec44cbd35be82490c8c566ad4971f7b41ffe8508f1c9938140df7fe18b2" +checksum = "2c250118354755b4abb091a83cb8d659b511c0ae211ccdb3b1254e3db199cb86" dependencies = [ "aes-gcm 0.10.2", "bs58 0.5.0", diff --git a/Cargo.toml b/Cargo.toml index df81990bc..a861f143e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,10 @@ members = [ "stacks-signer", "testnet/stacks-node"] +# Dependencies we want to keep the same between workspace members +[workspace.dependencies] +wsts = "5.0" + # Use a bit more than default optimization for # dev builds to speed up test execution [profile.dev] diff --git a/stacks-signer/Cargo.toml b/stacks-signer/Cargo.toml index 50f501b51..cd5571657 100644 --- a/stacks-signer/Cargo.toml +++ b/stacks-signer/Cargo.toml @@ -27,7 +27,6 @@ clap = { version = "4.1.1", features = ["derive", "env"] } hashbrown = "0.14" libsigner = { path = "../libsigner" } libstackerdb = { path = "../libstackerdb" } -p256k1 = "5.5" rand_core = "0.6" reqwest = { version = "0.11.22", features = ["blocking", "json"] } serde = "1" @@ -42,7 +41,7 @@ thiserror = "1.0" toml = "0.5.6" tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } -wsts = "4.0.0" +wsts = { workspace = true } [dependencies.serde_json] version = "1.0" diff --git a/stacks-signer/src/config.rs b/stacks-signer/src/config.rs index d634dd0cd..4991fb3ff 100644 --- a/stacks-signer/src/config.rs +++ b/stacks-signer/src/config.rs @@ -23,14 +23,14 @@ use std::time::Duration; use blockstack_lib::chainstate::stacks::TransactionVersion; use clarity::vm::types::QualifiedContractIdentifier; use hashbrown::HashMap; -use p256k1::ecdsa; -use p256k1::scalar::Scalar; use serde::Deserialize; use stacks_common::address::{ AddressHashMode, C32_ADDRESS_VERSION_MAINNET_SINGLESIG, C32_ADDRESS_VERSION_TESTNET_SINGLESIG, }; use stacks_common::consts::{CHAIN_ID_MAINNET, CHAIN_ID_TESTNET}; use stacks_common::types::chainstate::{StacksAddress, StacksPrivateKey, StacksPublicKey}; +use wsts::curve::ecdsa; +use wsts::curve::scalar::Scalar; use wsts::state_machine::PublicKeys; /// List of key_ids for each signer_id diff --git a/stacks-signer/src/main.rs b/stacks-signer/src/main.rs index dce30b8d4..a2fdac84e 100644 --- a/stacks-signer/src/main.rs +++ b/stacks-signer/src/main.rs @@ -124,6 +124,9 @@ fn process_dkg_result(dkg_res: &[OperationResult]) { &schnorr_proof.r, &schnorr_proof.s, ); } + OperationResult::DkgError(..) | OperationResult::SignError(..) => { + todo!() + } } } @@ -147,6 +150,9 @@ fn process_sign_result(sign_res: &[OperationResult]) { &schnorr_proof.r, &schnorr_proof.s, ); } + OperationResult::DkgError(..) | OperationResult::SignError(..) => { + todo!() + } } } diff --git a/stacks-signer/src/runloop.rs b/stacks-signer/src/runloop.rs index 7d6bf54d1..e4a6e5c01 100644 --- a/stacks-signer/src/runloop.rs +++ b/stacks-signer/src/runloop.rs @@ -2,15 +2,16 @@ use std::collections::VecDeque; use std::sync::mpsc::Sender; use std::time::Duration; +use backoff::default; use libsigner::{SignerRunLoop, StackerDBChunksEvent}; -use p256k1::ecdsa; use slog::{slog_debug, slog_error, slog_info, slog_warn}; use stacks_common::{debug, error, info, warn}; use wsts::common::MerkleRoot; +use wsts::curve::ecdsa; use wsts::net::{Message, Packet, Signable}; use wsts::state_machine::coordinator::frost::Coordinator as FrostCoordinator; -use wsts::state_machine::coordinator::Coordinatable; -use wsts::state_machine::signer::SigningRound; +use wsts::state_machine::coordinator::{Config as CoordinatorConfig, Coordinator}; +use wsts::state_machine::signer::Signer; use wsts::state_machine::{OperationResult, PublicKeys}; use wsts::v2; @@ -56,7 +57,7 @@ pub struct RunLoop { /// The signing round used to sign messages // TODO: update this to use frost_signer directly instead of the frost signing round // See: https://github.com/stacks-network/stacks-blockchain/issues/3913 - pub signing_round: SigningRound, + pub signing_round: Signer, /// The stacks client pub stacks_client: StacksClient, /// Received Commands that need to be processed @@ -65,7 +66,7 @@ pub struct RunLoop { pub state: State, } -impl RunLoop { +impl RunLoop { /// Initialize the signer, reading the stacker-db state and setting the aggregate public key fn initialize(&mut self) -> Result<(), ClientError> { // TODO: update to read stacker db to get state. @@ -92,7 +93,7 @@ impl RunLoop { match command { RunLoopCommand::Dkg => { info!("Starting DKG"); - match self.coordinator.start_distributed_key_generation() { + match self.coordinator.start_dkg_round() { Ok(msg) => { let ack = self .stacks_client @@ -117,7 +118,7 @@ impl RunLoop { info!("Signing message: {:?}", message); match self .coordinator - .start_signing_message(message, *is_taproot, *merkle_root) + .start_signing_round(message, *is_taproot, *merkle_root) { Ok(msg) => { let ack = self @@ -231,15 +232,17 @@ impl From<&Config> for RunLoop> { .get(&config.signer_id) .unwrap() .iter() - .map(|i| i - 1) // SigningRound::new (unlike SigningRound::from) doesn't do this + .map(|i| i - 1) // Signer::new (unlike Signer::from) doesn't do this .collect::>(); - let coordinator = FrostCoordinator::new( - total_signers, - total_keys, + let coordinator_config = CoordinatorConfig { threshold, - config.message_private_key, - ); - let signing_round = SigningRound::new( + num_signers: total_signers, + num_keys: total_keys, + message_private_key: config.message_private_key, + ..Default::default() + }; + let coordinator = FrostCoordinator::new(coordinator_config); + let signing_round = Signer::new( threshold, total_signers, total_keys, @@ -260,7 +263,7 @@ impl From<&Config> for RunLoop> { } } -impl SignerRunLoop, RunLoopCommand> for RunLoop { +impl SignerRunLoop, RunLoopCommand> for RunLoop { fn set_event_timeout(&mut self, timeout: Duration) { self.event_timeout = timeout; } diff --git a/stacks-signer/src/stacks_client.rs b/stacks-signer/src/stacks_client.rs index 0621df4b0..cc70a0b8c 100644 --- a/stacks-signer/src/stacks_client.rs +++ b/stacks-signer/src/stacks_client.rs @@ -18,8 +18,9 @@ use slog::{slog_debug, slog_warn}; use stacks_common::codec::StacksMessageCodec; use stacks_common::types::chainstate::{StacksAddress, StacksPrivateKey, StacksPublicKey}; use stacks_common::{debug, warn}; +use wsts::curve::point::Point; +use wsts::curve::scalar::Scalar; use wsts::net::{Message, Packet}; -use wsts::{Point, Scalar}; use crate::config::Config; diff --git a/stacks-signer/src/utils.rs b/stacks-signer/src/utils.rs index 86436f09a..5664fd707 100644 --- a/stacks-signer/src/utils.rs +++ b/stacks-signer/src/utils.rs @@ -1,11 +1,11 @@ use std::time::Duration; -use p256k1::ecdsa; use rand_core::OsRng; use slog::slog_debug; use stacks_common::debug; use stacks_common::types::chainstate::{StacksAddress, StacksPrivateKey}; -use wsts::Scalar; +use wsts::curve::ecdsa; +use wsts::curve::scalar::Scalar; use crate::stacks_client::SLOTS_PER_USER; diff --git a/stackslib/Cargo.toml b/stackslib/Cargo.toml index bc114d205..54a87b22c 100644 --- a/stackslib/Cargo.toml +++ b/stackslib/Cargo.toml @@ -55,8 +55,7 @@ stacks-common = { path = "../stacks-common" } pox-locking = { path = "../pox-locking" } libstackerdb = { path = "../libstackerdb" } siphasher = "0.3.7" -wsts = "4.0.0" -p256k1 = "5.5.0" +wsts = {workspace = true} [target.'cfg(unix)'.dependencies] nix = "0.23" diff --git a/stackslib/src/chainstate/stacks/mod.rs b/stackslib/src/chainstate/stacks/mod.rs index a822ea540..defeb01ea 100644 --- a/stackslib/src/chainstate/stacks/mod.rs +++ b/stackslib/src/chainstate/stacks/mod.rs @@ -658,10 +658,7 @@ pub enum TenureChangeError { /// Schnorr threshold signature using types from `wsts` #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct ThresholdSignature { - R: wsts::Point, - z: wsts::Scalar, -} +pub struct ThresholdSignature(pub wsts::common::Signature); /// A transaction from Stackers to signal new mining tenure #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] diff --git a/stackslib/src/chainstate/stacks/transaction.rs b/stackslib/src/chainstate/stacks/transaction.rs index 06a738730..60c58b985 100644 --- a/stackslib/src/chainstate/stacks/transaction.rs +++ b/stackslib/src/chainstate/stacks/transaction.rs @@ -29,6 +29,7 @@ use stacks_common::types::StacksPublicKeyBuffer; use stacks_common::util::hash::{to_hex, MerkleHashFunc, MerkleTree, Sha512Trunc256Sum}; use stacks_common::util::retry::BoundReader; use stacks_common::util::secp256k1::MessageSignature; +use wsts::curve as p256k1; use crate::burnchains::Txid; use crate::chainstate::stacks::{TransactionPayloadID, *}; @@ -151,17 +152,18 @@ impl StacksMessageCodec for TenureChangeCause { impl StacksMessageCodec for ThresholdSignature { fn consensus_serialize(&self, fd: &mut W) -> Result<(), codec_error> { - let compressed = self.R.compress(); + let compressed = self.0.R.compress(); let bytes = compressed.as_bytes(); fd.write_all(bytes) .map_err(crate::codec::Error::WriteError)?; - write_next(fd, &self.z.to_bytes())?; + write_next(fd, &self.0.z.to_bytes())?; Ok(()) } fn consensus_deserialize(fd: &mut R) -> Result { - use p256k1::point::Compressed; - use wsts::{Point, Scalar}; + use p256k1::point::{Compressed, Point}; + use p256k1::scalar::Scalar; + use wsts::common::Signature; // Read curve point let mut buf = [0u8; 33]; @@ -177,17 +179,25 @@ impl StacksMessageCodec for ThresholdSignature { .map_err(crate::codec::Error::ReadError)?; let z = Scalar::from(buf); - Ok(Self { R, z }) + Ok(Self(Signature { R, z })) } } impl ThresholdSignature { + pub fn verify(&self, public_key: &p256k1::point::Point, msg: &[u8]) -> bool { + self.0.verify(public_key, msg) + } + /// Create mock data for testing. Not valid data pub fn mock() -> Self { - Self { - R: wsts::Point::G(), - z: wsts::Scalar::new(), - } + use p256k1::point::Point; + use p256k1::scalar::Scalar; + use wsts::common::Signature; + + Self(Signature { + R: Point::G(), + z: Scalar::new(), + }) } } diff --git a/testnet/stacks-node/Cargo.toml b/testnet/stacks-node/Cargo.toml index f75d2c422..7e0e7387e 100644 --- a/testnet/stacks-node/Cargo.toml +++ b/testnet/stacks-node/Cargo.toml @@ -38,10 +38,9 @@ clarity = { path = "../../clarity", features = ["default", "testing"]} stacks-common = { path = "../../stacks-common", features = ["default", "testing"] } stacks = { package = "stackslib", path = "../../stackslib", features = ["default", "testing"] } stacks-signer = { path = "../../stacks-signer" } -p256k1 = "5.5" tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } -wsts = "4.0" +wsts = {workspace = true} [dependencies.rusqlite] version = "=0.24.2" diff --git a/testnet/stacks-node/src/tests/signer.rs b/testnet/stacks-node/src/tests/signer.rs index f064c5ed8..f2c44c483 100644 --- a/testnet/stacks-node/src/tests/signer.rs +++ b/testnet/stacks-node/src/tests/signer.rs @@ -310,6 +310,9 @@ fn test_stackerdb_dkg() { info!("Received SchnorrProof ({},{})", &proof.r, &proof.s); schnorr_proof = Some(proof); } + OperationResult::DkgError(..) | OperationResult::SignError(..) => { + todo!() + } } } if aggregate_group_key.is_some() && frost_signature.is_some() && schnorr_proof.is_some()