Skip to content

Commit a50f955

Browse files
authored
Merge pull request #5243 from stacks-network/chore/remove-v1-signer
Chore/remove v1 signer
2 parents 9c90c5c + 8c0137c commit a50f955

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+405
-8451
lines changed

Cargo.lock

Lines changed: 14 additions & 459 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,11 @@ members = [
1515
# Dependencies we want to keep the same between workspace members
1616
[workspace.dependencies]
1717
ed25519-dalek = { version = "2.1.1", features = ["serde", "rand_core"] }
18-
hashbrown = "0.14.3"
18+
hashbrown = { version = "0.14.3", features = ["serde"] }
1919
rand_core = "0.6"
2020
rand = "0.8"
2121
rand_chacha = "0.3.1"
2222
tikv-jemallocator = "0.5.4"
23-
wsts = { version = "9.0.0", default-features = false }
2423
rusqlite = { version = "0.31.0", features = ["blob", "serde_json", "i128_blob", "bundled", "trace"] }
2524

2625
# Use a bit more than default optimization for

libsigner/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ stacks-common = { path = "../stacks-common" }
3232
stackslib = { path = "../stackslib"}
3333
thiserror = "1.0"
3434
tiny_http = "0.12"
35-
wsts = { workspace = true }
3635

3736
[dev-dependencies]
3837
mutants = "0.0.3"

libsigner/src/events.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use std::time::SystemTime;
2525
use blockstack_lib::chainstate::nakamoto::NakamotoBlock;
2626
use blockstack_lib::chainstate::stacks::boot::{MINERS_NAME, SIGNERS_NAME};
2727
use blockstack_lib::chainstate::stacks::events::StackerDBChunksEvent;
28-
use blockstack_lib::chainstate::stacks::{StacksTransaction, ThresholdSignature};
28+
use blockstack_lib::chainstate::stacks::StacksTransaction;
2929
use blockstack_lib::net::api::postblock_proposal::{
3030
BlockValidateReject, BlockValidateResponse, ValidateRejectCode,
3131
};
@@ -48,12 +48,6 @@ use stacks_common::util::HexError;
4848
use tiny_http::{
4949
Method as HttpMethod, Request as HttpRequest, Response as HttpResponse, Server as HttpServer,
5050
};
51-
use wsts::common::Signature;
52-
use wsts::net::{
53-
DkgBegin, DkgEnd, DkgEndBegin, DkgPrivateBegin, DkgPrivateShares, DkgPublicShares, DkgStatus,
54-
Message, NonceRequest, NonceResponse, Packet, SignatureShareRequest, SignatureShareResponse,
55-
};
56-
use wsts::state_machine::signer;
5751

5852
use crate::http::{decode_http_body, decode_http_request};
5953
use crate::EventError;

libsigner/src/libsigner.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ mod session;
4444
mod signer_set;
4545
/// v0 signer related code
4646
pub mod v0;
47-
/// v1 signer related code
48-
pub mod v1;
4947

5048
use std::cmp::Eq;
5149
use std::fmt::Debug;

libsigner/src/runloop.rs

Lines changed: 9 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -41,20 +41,15 @@ const STDERR: i32 = 2;
4141
/// Trait describing the needful components of a top-level runloop.
4242
/// This is where the signer business logic would go.
4343
/// Implement this, and you get all the multithreaded setup for free.
44-
pub trait SignerRunLoop<R: Send, CMD: Send, T: SignerEventTrait> {
44+
pub trait SignerRunLoop<R: Send, T: SignerEventTrait> {
4545
/// Hint to set how long to wait for new events
4646
fn set_event_timeout(&mut self, timeout: Duration);
4747
/// Getter for the event poll timeout
4848
fn get_event_timeout(&self) -> Duration;
4949
/// Run one pass of the event loop, given new Signer events discovered since the last pass.
5050
/// Returns Some(R) if this is the final pass -- the runloop evaluated to R
5151
/// Returns None to keep running.
52-
fn run_one_pass(
53-
&mut self,
54-
event: Option<SignerEvent<T>>,
55-
cmd: Option<CMD>,
56-
res: &Sender<R>,
57-
) -> Option<R>;
52+
fn run_one_pass(&mut self, event: Option<SignerEvent<T>>, res: &Sender<R>) -> Option<R>;
5853

5954
/// This is the main loop body for the signer. It continuously receives events from
6055
/// `event_recv`, polling for up to `self.get_event_timeout()` units of time. Once it has
@@ -66,7 +61,6 @@ pub trait SignerRunLoop<R: Send, CMD: Send, T: SignerEventTrait> {
6661
fn main_loop<EVST: EventStopSignaler>(
6762
&mut self,
6863
event_recv: Receiver<SignerEvent<T>>,
69-
command_recv: Receiver<CMD>,
7064
result_send: Sender<R>,
7165
mut event_stop_signaler: EVST,
7266
) -> Option<R> {
@@ -81,11 +75,7 @@ pub trait SignerRunLoop<R: Send, CMD: Send, T: SignerEventTrait> {
8175
return None;
8276
}
8377
};
84-
// Do not block for commands
85-
let next_command_opt = command_recv.try_recv().ok();
86-
if let Some(final_state) =
87-
self.run_one_pass(next_event_opt, next_command_opt, &result_send)
88-
{
78+
if let Some(final_state) = self.run_one_pass(next_event_opt, &result_send) {
8979
info!("Runloop exit; signaling event-receiver to stop");
9080
event_stop_signaler.send();
9181
return Some(final_state);
@@ -95,13 +85,11 @@ pub trait SignerRunLoop<R: Send, CMD: Send, T: SignerEventTrait> {
9585
}
9686

9787
/// The top-level signer implementation
98-
pub struct Signer<CMD, R, SL, EV, T> {
88+
pub struct Signer<R, SL, EV, T> {
9989
/// the runloop itself
10090
signer_loop: Option<SL>,
10191
/// the event receiver to use
10292
event_receiver: Option<EV>,
103-
/// the command receiver to use
104-
command_receiver: Option<Receiver<CMD>>,
10593
/// the result sender to use
10694
result_sender: Option<Sender<R>>,
10795
/// phantom data for the codec
@@ -193,31 +181,24 @@ pub fn set_runloop_signal_handler<ST: EventStopSignaler + Send + 'static>(mut st
193181
}).expect("FATAL: failed to set signal handler");
194182
}
195183

196-
impl<CMD, R, SL, EV, T> Signer<CMD, R, SL, EV, T> {
184+
impl<R, SL, EV, T> Signer<R, SL, EV, T> {
197185
/// Create a new signer with the given runloop and event receiver.
198-
pub fn new(
199-
runloop: SL,
200-
event_receiver: EV,
201-
command_receiver: Receiver<CMD>,
202-
result_sender: Sender<R>,
203-
) -> Signer<CMD, R, SL, EV, T> {
186+
pub fn new(runloop: SL, event_receiver: EV, result_sender: Sender<R>) -> Signer<R, SL, EV, T> {
204187
Signer {
205188
signer_loop: Some(runloop),
206189
event_receiver: Some(event_receiver),
207-
command_receiver: Some(command_receiver),
208190
result_sender: Some(result_sender),
209191
phantom_data: PhantomData,
210192
}
211193
}
212194
}
213195

214196
impl<
215-
CMD: Send + 'static,
216197
R: Send + 'static,
217198
T: SignerEventTrait + 'static,
218-
SL: SignerRunLoop<R, CMD, T> + Send + 'static,
199+
SL: SignerRunLoop<R, T> + Send + 'static,
219200
EV: EventReceiver<T> + Send + 'static,
220-
> Signer<CMD, R, SL, EV, T>
201+
> Signer<R, SL, EV, T>
221202
{
222203
/// This is a helper function to spawn both the runloop and event receiver in their own
223204
/// threads. Advanced signers may not need this method, and instead opt to run the receiver
@@ -234,10 +215,6 @@ impl<
234215
.event_receiver
235216
.take()
236217
.ok_or(EventError::AlreadyRunning)?;
237-
let command_receiver = self
238-
.command_receiver
239-
.take()
240-
.ok_or(EventError::AlreadyRunning)?;
241218
let result_sender = self
242219
.result_sender
243220
.take()
@@ -266,9 +243,7 @@ impl<
266243
let runloop_thread = thread::Builder::new()
267244
.name(format!("signer_runloop:{bind_port}"))
268245
.stack_size(THREAD_STACK_SIZE)
269-
.spawn(move || {
270-
signer_loop.main_loop(event_recv, command_receiver, result_sender, stop_signaler)
271-
})
246+
.spawn(move || signer_loop.main_loop(event_recv, result_sender, stop_signaler))
272247
.map_err(|e| {
273248
error!("SignerRunLoop failed to start: {:?}", &e);
274249
ret_stop_signaler.send();

libsigner/src/signer_set.rs

Lines changed: 42 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -13,125 +13,77 @@
1313
// You should have received a copy of the GNU General Public License
1414
// along with this program. If not, see <http://www.gnu.org/licenses/>.
1515

16+
use std::collections::{BTreeMap, HashMap};
17+
1618
use blockstack_lib::chainstate::stacks::boot::NakamotoSignerEntry;
17-
use hashbrown::{HashMap, HashSet};
1819
use stacks_common::types::chainstate::{StacksAddress, StacksPublicKey};
19-
use wsts::curve::ecdsa;
20-
use wsts::curve::point::{Compressed, Point};
21-
use wsts::state_machine::PublicKeys;
2220

23-
/// A reward set parsed into the structures required by WSTS party members and coordinators.
21+
/// A reward set parsed into relevant structures
2422
#[derive(Debug, Clone)]
2523
pub struct SignerEntries {
26-
/// The signer addresses mapped to signer id
27-
pub signer_ids: HashMap<StacksAddress, u32>,
28-
/// The signer ids mapped to public key and key ids mapped to public keys
29-
pub public_keys: PublicKeys,
30-
/// The signer ids mapped to key ids
31-
pub signer_key_ids: HashMap<u32, Vec<u32>>,
32-
/// The signer ids mapped to wsts public keys
33-
pub signer_public_keys: HashMap<u32, Point>,
34-
/// The signer ids mapped to a hash set of key ids
35-
/// The wsts coordinator uses a hash set for each signer since it needs to do lots of lookups
36-
pub coordinator_key_ids: HashMap<u32, HashSet<u32>>,
24+
/// The signer addresses mapped to signer ID
25+
pub signer_addr_to_id: HashMap<StacksAddress, u32>,
26+
/// The signer IDs mapped to addresses. Uses a BTreeMap to ensure *reward cycle order*
27+
pub signer_id_to_addr: BTreeMap<u32, StacksAddress>,
28+
/// signer ID mapped to public key
29+
pub signer_id_to_pk: HashMap<u32, StacksPublicKey>,
30+
/// public_key mapped to signer ID
31+
pub signer_pk_to_id: HashMap<StacksPublicKey, u32>,
32+
/// The signer public keys
33+
pub signer_pks: Vec<StacksPublicKey>,
34+
/// The signer addresses
35+
pub signer_addresses: Vec<StacksAddress>,
36+
/// The signer address mapped to signing weight
37+
pub signer_addr_to_weight: HashMap<StacksAddress, u32>,
3738
}
3839

3940
/// Parsing errors for `SignerEntries`
4041
#[derive(Debug)]
4142
pub enum Error {
4243
/// A member of the signing set has a signing key buffer
43-
/// which does not represent a ecdsa public key.
44+
/// which does not represent a valid Stacks public key
4445
BadSignerPublicKey(String),
4546
/// The number of signers was greater than u32::MAX
4647
SignerCountOverflow,
4748
}
4849

4950
impl SignerEntries {
50-
/// Try to parse the reward set defined by `NakamotoSignEntry` into the structures required
51-
/// by WSTS party members and coordinators.
51+
/// Try to parse the reward set defined by `NakamotoSignEntry` into the SignerEntries struct
5252
pub fn parse(is_mainnet: bool, reward_set: &[NakamotoSignerEntry]) -> Result<Self, Error> {
53-
let mut weight_end = 1;
54-
let mut signer_key_ids = HashMap::with_capacity(reward_set.len());
55-
let mut signer_public_keys = HashMap::with_capacity(reward_set.len());
56-
let mut coordinator_key_ids = HashMap::with_capacity(4000);
57-
let mut signer_ids = HashMap::with_capacity(reward_set.len());
58-
let mut wsts_signers = HashMap::new();
59-
let mut wsts_key_ids = HashMap::new();
53+
let mut signer_pk_to_id = HashMap::with_capacity(reward_set.len());
54+
let mut signer_id_to_pk = HashMap::with_capacity(reward_set.len());
55+
let mut signer_addr_to_id = HashMap::with_capacity(reward_set.len());
56+
let mut signer_pks = Vec::with_capacity(reward_set.len());
57+
let mut signer_id_to_addr = BTreeMap::new();
58+
let mut signer_addr_to_weight = HashMap::new();
59+
let mut signer_addresses = Vec::with_capacity(reward_set.len());
6060
for (i, entry) in reward_set.iter().enumerate() {
6161
let signer_id = u32::try_from(i).map_err(|_| Error::SignerCountOverflow)?;
62-
let ecdsa_pk =
63-
ecdsa::PublicKey::try_from(entry.signing_key.as_slice()).map_err(|e| {
64-
Error::BadSignerPublicKey(format!(
65-
"Failed to convert signing key to ecdsa::PublicKey: {e}"
66-
))
67-
})?;
68-
let signer_public_key = Point::try_from(&Compressed::from(ecdsa_pk.to_bytes()))
69-
.map_err(|e| {
70-
Error::BadSignerPublicKey(format!(
71-
"Failed to convert signing key to wsts::Point: {e}"
72-
))
73-
})?;
74-
let stacks_public_key = StacksPublicKey::from_slice(entry.signing_key.as_slice())
62+
let signer_public_key = StacksPublicKey::from_slice(entry.signing_key.as_slice())
7563
.map_err(|e| {
7664
Error::BadSignerPublicKey(format!(
7765
"Failed to convert signing key to StacksPublicKey: {e}"
7866
))
7967
})?;
8068

81-
let stacks_address = StacksAddress::p2pkh(is_mainnet, &stacks_public_key);
82-
signer_ids.insert(stacks_address, signer_id);
83-
84-
signer_public_keys.insert(signer_id, signer_public_key);
85-
let weight_start = weight_end;
86-
weight_end = weight_start + entry.weight;
87-
let key_ids: HashSet<u32> = (weight_start..weight_end).collect();
88-
for key_id in key_ids.iter() {
89-
wsts_key_ids.insert(*key_id, ecdsa_pk);
90-
}
91-
signer_key_ids.insert(signer_id, (weight_start..weight_end).collect());
92-
coordinator_key_ids.insert(signer_id, key_ids);
93-
wsts_signers.insert(signer_id, ecdsa_pk);
69+
let stacks_address = StacksAddress::p2pkh(is_mainnet, &signer_public_key);
70+
signer_addr_to_id.insert(stacks_address, signer_id);
71+
signer_id_to_pk.insert(signer_id, signer_public_key);
72+
signer_pk_to_id.insert(signer_public_key, signer_id);
73+
signer_pks.push(signer_public_key);
74+
signer_id_to_addr.insert(signer_id, stacks_address);
75+
signer_addr_to_weight.insert(stacks_address, entry.weight);
76+
signer_addresses.push(stacks_address);
9477
}
9578

9679
Ok(Self {
97-
signer_ids,
98-
public_keys: PublicKeys {
99-
signers: wsts_signers,
100-
key_ids: wsts_key_ids,
101-
},
102-
signer_key_ids,
103-
signer_public_keys,
104-
coordinator_key_ids,
80+
signer_addr_to_id,
81+
signer_id_to_pk,
82+
signer_pk_to_id,
83+
signer_pks,
84+
signer_id_to_addr,
85+
signer_addr_to_weight,
86+
signer_addresses,
10587
})
10688
}
107-
108-
/// Return the number of Key IDs in the WSTS group signature
109-
pub fn count_keys(&self) -> Result<u32, Error> {
110-
self.public_keys
111-
.key_ids
112-
.len()
113-
.try_into()
114-
.map_err(|_| Error::SignerCountOverflow)
115-
}
116-
117-
/// Return the number of Key IDs in the WSTS group signature
118-
pub fn count_signers(&self) -> Result<u32, Error> {
119-
self.public_keys
120-
.signers
121-
.len()
122-
.try_into()
123-
.map_err(|_| Error::SignerCountOverflow)
124-
}
125-
126-
/// Return the number of Key IDs required to sign a message with the WSTS group signature
127-
pub fn get_signing_threshold(&self) -> Result<u32, Error> {
128-
let num_keys = self.count_keys()?;
129-
Ok((num_keys as f64 * 7_f64 / 10_f64).ceil() as u32)
130-
}
131-
132-
/// Return the number of Key IDs required to sign a message with the WSTS group signature
133-
pub fn get_dkg_threshold(&self) -> Result<u32, Error> {
134-
let num_keys = self.count_keys()?;
135-
Ok((num_keys as f64 * 9_f64 / 10_f64).ceil() as u32)
136-
}
13789
}

libsigner/src/tests/http.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use crate::http::{decode_http_body, decode_http_request, decode_http_response, r
2525

2626
#[test]
2727
fn test_decode_http_request_ok() {
28-
let tests = vec![
28+
let tests = [
2929
("GET /foo HTTP/1.1\r\nHost: localhost:6270\r\n\r\n",
3030
("GET", "/foo", vec![("host", "localhost:6270")])),
3131
("POST asdf HTTP/1.1\r\nHost: core.blockstack.org\r\nFoo: Bar\r\n\r\n",
@@ -61,7 +61,7 @@ fn test_decode_http_request_ok() {
6161

6262
#[test]
6363
fn test_decode_http_request_err() {
64-
let tests = vec![
64+
let tests = [
6565
(
6666
"GET /foo HTTP/1.1\r\n",
6767
EventError::Deserialize("".to_string()),
@@ -99,7 +99,7 @@ fn test_decode_http_request_err() {
9999

100100
#[test]
101101
fn test_decode_http_response_ok() {
102-
let tests = vec![
102+
let tests = [
103103
("HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream\r\nContent-Length: 123\r\nX-Request-ID: 0\r\n\r\n",
104104
vec![("content-type", "application/octet-stream"), ("content-length", "123"), ("x-request-id", "0")]),
105105
("HTTP/1.1 200 Ok\r\nContent-Type: application/octet-stream\r\nTransfer-encoding: chunked\r\nX-Request-ID: 0\r\n\r\n",
@@ -123,7 +123,7 @@ fn test_decode_http_response_ok() {
123123

124124
#[test]
125125
fn test_decode_http_response_err() {
126-
let tests = vec![
126+
let tests = [
127127
("HTTP/1.1 400 Bad Request\r\nContent-Type: application/json\r\nContent-Length: 456\r\nFoo: Bar\r\nX-Request-ID: 0\r\n\r\n",
128128
RPCError::HttpError(400)),
129129
("HTTP/1.1 200",
@@ -223,7 +223,7 @@ impl Write for MockHTTPSocket {
223223

224224
#[test]
225225
fn test_run_http_request_with_body() {
226-
let tests = vec![
226+
let tests = [
227227
("GET", "/test-no-content-type-and-no-body", None, vec![]),
228228
(
229229
"GET",
@@ -288,7 +288,7 @@ fn test_run_http_request_with_body() {
288288

289289
#[test]
290290
fn test_run_http_request_no_body() {
291-
let tests = vec![
291+
let tests = [
292292
("GET", "/test-no-content-type-and-no-body", None, vec![]),
293293
(
294294
"GET",

0 commit comments

Comments
 (0)