Skip to content

Commit 82be35a

Browse files
committed
Remove wsts from testnet/stacks-node
Signed-off-by: Jacinta Ferrant <[email protected]>
1 parent 447bb15 commit 82be35a

File tree

19 files changed

+121
-4337
lines changed

19 files changed

+121
-4337
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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
}

stacks-signer/src/client/mod.rs

Lines changed: 39 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ where
123123

124124
#[cfg(test)]
125125
pub(crate) mod tests {
126+
use std::collections::{BTreeMap, HashMap};
126127
use std::io::{Read, Write};
127128
use std::net::{SocketAddr, TcpListener};
128129

@@ -138,20 +139,16 @@ pub(crate) mod tests {
138139
use clarity::vm::costs::ExecutionCost;
139140
use clarity::vm::types::TupleData;
140141
use clarity::vm::Value as ClarityValue;
141-
use hashbrown::{HashMap, HashSet};
142142
use libsigner::SignerEntries;
143143
use rand::distributions::Standard;
144144
use rand::{thread_rng, Rng};
145-
use rand_core::{OsRng, RngCore};
145+
use rand_core::RngCore;
146146
use stacks_common::types::chainstate::{
147147
BlockHeaderHash, ConsensusHash, StacksAddress, StacksPrivateKey, StacksPublicKey,
148148
};
149149
use stacks_common::types::{StacksEpochId, StacksPublicKeyBuffer};
150150
use stacks_common::util::hash::{Hash160, Sha256Sum};
151-
use wsts::curve::ecdsa;
152-
use wsts::curve::point::{Compressed, Point};
153-
use wsts::curve::scalar::Scalar;
154-
use wsts::state_machine::PublicKeys;
151+
use wsts::curve::point::Point;
155152

156153
use super::*;
157154
use crate::config::{GlobalConfig, SignerConfig};
@@ -456,112 +453,59 @@ pub(crate) mod tests {
456453

457454
/// Generate a signer config with the given number of signers and keys where the first signer is
458455
/// obtained from the provided global config
459-
pub fn generate_signer_config(
460-
config: &GlobalConfig,
461-
num_signers: u32,
462-
num_keys: u32,
463-
) -> SignerConfig {
456+
pub fn generate_signer_config(config: &GlobalConfig, num_signers: u32) -> SignerConfig {
464457
assert!(
465458
num_signers > 0,
466459
"Cannot generate 0 signers...Specify at least 1 signer."
467460
);
468-
assert!(
469-
num_keys > 0,
470-
"Cannot generate 0 keys for the provided signers...Specify at least 1 key."
471-
);
472-
let mut public_keys = PublicKeys {
473-
signers: HashMap::new(),
474-
key_ids: HashMap::new(),
475-
};
461+
462+
let weight_per_signer = 100 / num_signers;
463+
let mut remaining_weight = 100 % num_signers;
464+
476465
let reward_cycle = thread_rng().next_u64();
477-
let rng = &mut OsRng;
478-
let num_keys = num_keys / num_signers;
479-
let remaining_keys = num_keys % num_signers;
480-
let mut coordinator_key_ids = HashMap::new();
481-
let mut signer_key_ids = HashMap::new();
482-
let mut signer_ids = HashMap::new();
483-
let mut start_key_id = 1u32;
484-
let mut end_key_id = start_key_id;
485-
let mut signer_public_keys = HashMap::new();
486-
let mut signer_slot_ids = vec![];
487-
let ecdsa_private_key = config.ecdsa_private_key;
488-
let ecdsa_public_key =
489-
ecdsa::PublicKey::new(&ecdsa_private_key).expect("Failed to create ecdsa public key");
490-
// Key ids start from 1 hence the wrapping adds everywhere
466+
467+
let mut signer_pk_to_id = HashMap::new();
468+
let mut signer_id_to_pk = HashMap::new();
469+
let mut signer_addr_to_id = HashMap::new();
470+
let mut signer_pks = Vec::new();
471+
let mut signer_slot_ids = Vec::new();
472+
let mut signer_id_to_addr = BTreeMap::new();
473+
let mut signer_addr_to_weight = HashMap::new();
474+
let mut signer_addresses = Vec::new();
475+
491476
for signer_id in 0..num_signers {
492-
end_key_id = if signer_id.wrapping_add(1) == num_signers {
493-
end_key_id.wrapping_add(remaining_keys)
477+
let private_key = if signer_id == 0 {
478+
config.stacks_private_key
494479
} else {
495-
end_key_id.wrapping_add(num_keys)
480+
StacksPrivateKey::new()
496481
};
497-
if signer_id == 0 {
498-
public_keys.signers.insert(signer_id, ecdsa_public_key);
499-
let signer_public_key =
500-
Point::try_from(&Compressed::from(ecdsa_public_key.to_bytes())).unwrap();
501-
signer_public_keys.insert(signer_id, signer_public_key);
502-
public_keys.signers.insert(signer_id, ecdsa_public_key);
503-
for k in start_key_id..end_key_id {
504-
public_keys.key_ids.insert(k, ecdsa_public_key);
505-
coordinator_key_ids
506-
.entry(signer_id)
507-
.or_insert(HashSet::new())
508-
.insert(k);
509-
signer_key_ids
510-
.entry(signer_id)
511-
.or_insert(Vec::new())
512-
.push(k);
513-
}
514-
start_key_id = end_key_id;
515-
let address = StacksAddress::p2pkh(
516-
false,
517-
&StacksPublicKey::from_slice(ecdsa_public_key.to_bytes().as_slice())
518-
.expect("Failed to create stacks public key"),
519-
);
520-
signer_slot_ids.push(SignerSlotID(signer_id));
521-
signer_ids.insert(address, signer_id);
522-
523-
continue;
524-
}
525-
let private_key = Scalar::random(rng);
526-
let public_key = ecdsa::PublicKey::new(&private_key).unwrap();
527-
let signer_public_key =
528-
Point::try_from(&Compressed::from(public_key.to_bytes())).unwrap();
529-
signer_public_keys.insert(signer_id, signer_public_key);
530-
public_keys.signers.insert(signer_id, public_key);
531-
for k in start_key_id..end_key_id {
532-
public_keys.key_ids.insert(k, public_key);
533-
coordinator_key_ids
534-
.entry(signer_id)
535-
.or_insert(HashSet::new())
536-
.insert(k);
537-
signer_key_ids
538-
.entry(signer_id)
539-
.or_insert(Vec::new())
540-
.push(k);
541-
}
542-
let address = StacksAddress::p2pkh(
543-
false,
544-
&StacksPublicKey::from_slice(public_key.to_bytes().as_slice())
545-
.expect("Failed to create stacks public key"),
546-
);
482+
let public_key = StacksPublicKey::from_private(&private_key);
483+
484+
signer_id_to_pk.insert(signer_id, public_key);
485+
signer_pk_to_id.insert(public_key, signer_id);
486+
let address = StacksAddress::p2pkh(false, &public_key);
487+
signer_addr_to_id.insert(address, signer_id);
488+
signer_pks.push(public_key);
547489
signer_slot_ids.push(SignerSlotID(signer_id));
548-
signer_ids.insert(address, signer_id);
549-
start_key_id = end_key_id;
490+
signer_id_to_addr.insert(signer_id, address);
491+
signer_addr_to_weight.insert(address, weight_per_signer + remaining_weight);
492+
signer_addresses.push(address);
493+
remaining_weight = 0; // The first signer gets the extra weight if there is any. All other signers only get the weight_per_signer
550494
}
551495
SignerConfig {
552496
reward_cycle,
553497
signer_id: 0,
554498
signer_slot_id: SignerSlotID(rand::thread_rng().gen_range(0..num_signers)), // Give a random signer slot id between 0 and num_signers
555-
key_ids: signer_key_ids.get(&0).cloned().unwrap_or_default(),
556499
signer_entries: SignerEntries {
557-
public_keys,
558-
coordinator_key_ids,
559-
signer_key_ids,
560-
signer_ids,
561-
signer_public_keys,
500+
signer_addr_to_id,
501+
signer_id_to_pk,
502+
signer_pk_to_id,
503+
signer_pks,
504+
signer_id_to_addr,
505+
signer_addr_to_weight,
506+
signer_addresses,
562507
},
563508
signer_slot_ids,
564-
ecdsa_private_key: config.ecdsa_private_key,
565509
stacks_private_key: config.stacks_private_key,
566510
node_host: config.node_host.to_string(),
567511
mainnet: config.network.is_mainnet(),

stacks-signer/src/client/stackerdb.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ mod tests {
257257
Some(9000),
258258
);
259259
let config = GlobalConfig::load_from_str(&signer_config[0]).unwrap();
260-
let signer_config = generate_signer_config(&config, 5, 20);
260+
let signer_config = generate_signer_config(&config, 5);
261261
let mut stackerdb = StackerDB::from(&signer_config);
262262

263263
let header = NakamotoBlockHeader::empty();

0 commit comments

Comments
 (0)