Skip to content

Commit

Permalink
Merge pull request #3633 from stacks-network/feat/peer-pub-key
Browse files Browse the repository at this point in the history
Feat: Add `peer-pub-key` command to `stacks-inspect`
  • Loading branch information
kantai committed Apr 4, 2023
2 parents 0e026ba + f6f4ea6 commit 995ea8f
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 39 deletions.
15 changes: 15 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ use blockstack_lib::util::get_epoch_time_ms;
use blockstack_lib::util::hash::{hex_bytes, to_hex};
use blockstack_lib::util::log;
use blockstack_lib::util::retry::LogReader;
use blockstack_lib::util::secp256k1::Secp256k1PrivateKey;
use blockstack_lib::util::secp256k1::Secp256k1PublicKey;
use blockstack_lib::util::sleep_ms;
use blockstack_lib::util_lib::strings::UrlString;
use blockstack_lib::{
Expand Down Expand Up @@ -116,6 +118,19 @@ fn main() {
process::exit(0);
}

if argv[1] == "peer-pub-key" {
if argv.len() < 3 {
eprintln!("Usage: {} peer-pub-key <local-peer-seed>", argv[0]);
process::exit(1);
}

let local_seed = hex_bytes(&argv[2]).expect("Failed to parse hex input local-peer-seed");
let node_privkey = Secp256k1PrivateKey::from_seed(&local_seed);
let pubkey = Secp256k1PublicKey::from_private(&node_privkey).to_hex();
println!("{}", pubkey);
process::exit(0);
}

if argv[1] == "decode-bitcoin-header" {
if argv.len() < 4 {
eprintln!(
Expand Down
47 changes: 47 additions & 0 deletions stacks-common/src/util/secp256k1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ use serde::Serialize;
use rand::thread_rng;
use rand::RngCore;

use super::hash::Sha256Sum;

// per-thread Secp256k1 context
thread_local!(static _secp256k1: Secp256k1<secp256k1::All> = Secp256k1::new());

Expand Down Expand Up @@ -268,6 +270,27 @@ impl Secp256k1PrivateKey {
}
}

/// Create a Secp256k1PrivateKey from seed bytes by repeatedly
/// SHA256 hashing the seed bytes until a private key is found.
///
/// If `seed` is a valid private key, it will be returned without hashing.
/// The returned private key's compress_public flag will be `true`
pub fn from_seed(seed: &[u8]) -> Secp256k1PrivateKey {
let mut re_hashed_seed = Vec::from(seed);
loop {
if let Ok(mut sk) = Secp256k1PrivateKey::from_slice(&re_hashed_seed[..]) {
// set this to true: LocalPeer will be doing this anyways,
// and that's currently the only way this method is used
sk.set_compress_public(true);
return sk;
} else {
re_hashed_seed = Sha256Sum::from_data(&re_hashed_seed[..])
.as_bytes()
.to_vec()
}
}
}

pub fn from_hex(hex_string: &str) -> Result<Secp256k1PrivateKey, &'static str> {
let data = hex_bytes(hex_string).map_err(|_e| "Failed to decode hex private key")?;
Secp256k1PrivateKey::from_slice(&data[..]).map_err(|_e| "Invalid private key hex string")
Expand Down Expand Up @@ -458,6 +481,30 @@ mod tests {
assert_eq!(Secp256k1PrivateKey::from_hex(&h_comp), Ok(t1));
}

#[test]
/// Test the behavior of from_seed using hard-coded values from previous existing integration tests
fn sk_from_seed() {
let sk = Secp256k1PrivateKey::from_seed(&[2; 32]);
assert_eq!(
Secp256k1PublicKey::from_private(&sk).to_hex(),
"024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d0766"
);
assert_eq!(
sk.to_hex(),
"020202020202020202020202020202020202020202020202020202020202020201"
);

let sk = Secp256k1PrivateKey::from_seed(&[0]);
assert_eq!(
Secp256k1PublicKey::from_private(&sk).to_hex(),
"0243311589af63c2adda04fcd7792c038a05c12a4fe40351b3eb1612ff6b2e5a0e"
);
assert_eq!(
sk.to_hex(),
"6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d01"
);
}

#[test]
fn test_parse_serialize() {
let ctx: Secp256k1<secp256k1::All> = Secp256k1::new();
Expand Down
23 changes: 1 addition & 22 deletions testnet/stacks-node/src/neon_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,6 @@ use crate::syncctl::PoxSyncWatchdogComms;
use stacks::monitoring;

use stacks_common::types::chainstate::StacksBlockId;
use stacks_common::types::chainstate::StacksPrivateKey;
use stacks_common::util::vrf::VRFProof;

use clarity::vm::ast::ASTRules;
Expand Down Expand Up @@ -3808,25 +3807,6 @@ impl PeerThread {
}

impl StacksNode {
/// Create a StacksPrivateKey from a given seed buffer
pub fn make_node_private_key_from_seed(seed: &[u8]) -> StacksPrivateKey {
let node_privkey = {
let mut re_hashed_seed = seed.to_vec();
let my_private_key = loop {
match Secp256k1PrivateKey::from_slice(&re_hashed_seed[..]) {
Ok(sk) => break sk,
Err(_) => {
re_hashed_seed = Sha256Sum::from_data(&re_hashed_seed[..])
.as_bytes()
.to_vec()
}
}
};
my_private_key
};
node_privkey
}

/// Set up the AST size-precheck height, if configured
fn setup_ast_size_precheck(config: &Config, sortdb: &mut SortitionDB) {
if let Some(ast_precheck_size_height) = config.burnchain.ast_precheck_size_height {
Expand Down Expand Up @@ -3898,8 +3878,7 @@ impl StacksNode {
"Failed to parse socket: {}",
&config.node.p2p_address
));
let node_privkey =
StacksNode::make_node_private_key_from_seed(&config.node.local_peer_seed);
let node_privkey = Secp256k1PrivateKey::from_seed(&config.node.local_peer_seed);

let mut peerdb = PeerDB::connect(
&config.get_peer_db_file_path(),
Expand Down
20 changes: 7 additions & 13 deletions testnet/stacks-node/src/tests/epoch_21.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use stacks::burnchains::Burnchain;
use stacks::chainstate::stacks::db::StacksChainState;
use stacks::chainstate::stacks::StacksBlockHeader;
use stacks::types::chainstate::StacksAddress;
use stacks::util::secp256k1::Secp256k1PrivateKey;

use crate::config::Config;
use crate::config::EventKeyType;
Expand Down Expand Up @@ -62,7 +63,6 @@ use clarity::vm::ClarityVersion;
use stacks::core::BURNCHAIN_TX_SEARCH_WINDOW;

use crate::burnchains::bitcoin_regtest_controller::UTXO;
use crate::neon_node::StacksNode;
use crate::operations::BurnchainOpSigner;
use crate::Keychain;

Expand Down Expand Up @@ -2132,8 +2132,7 @@ fn test_pox_reorgs_three_flaps() {
confs.push(conf);
}

let node_privkey_1 =
StacksNode::make_node_private_key_from_seed(&confs[0].node.local_peer_seed);
let node_privkey_1 = Secp256k1PrivateKey::from_seed(&confs[0].node.local_peer_seed);
for i in 1..num_miners {
let chain_id = confs[0].burnchain.chain_id;
let peer_version = confs[0].burnchain.peer_version;
Expand Down Expand Up @@ -2667,8 +2666,7 @@ fn test_pox_reorg_one_flap() {
confs.push(conf);
}

let node_privkey_1 =
StacksNode::make_node_private_key_from_seed(&confs[0].node.local_peer_seed);
let node_privkey_1 = Secp256k1PrivateKey::from_seed(&confs[0].node.local_peer_seed);
for i in 1..num_miners {
let chain_id = confs[0].burnchain.chain_id;
let peer_version = confs[0].burnchain.peer_version;
Expand Down Expand Up @@ -3090,8 +3088,7 @@ fn test_pox_reorg_flap_duel() {
confs.push(conf);
}

let node_privkey_1 =
StacksNode::make_node_private_key_from_seed(&confs[0].node.local_peer_seed);
let node_privkey_1 = Secp256k1PrivateKey::from_seed(&confs[0].node.local_peer_seed);
for i in 1..num_miners {
let chain_id = confs[0].burnchain.chain_id;
let peer_version = confs[0].burnchain.peer_version;
Expand Down Expand Up @@ -3523,8 +3520,7 @@ fn test_pox_reorg_flap_reward_cycles() {
confs.push(conf);
}

let node_privkey_1 =
StacksNode::make_node_private_key_from_seed(&confs[0].node.local_peer_seed);
let node_privkey_1 = Secp256k1PrivateKey::from_seed(&confs[0].node.local_peer_seed);
for i in 1..num_miners {
let chain_id = confs[0].burnchain.chain_id;
let peer_version = confs[0].burnchain.peer_version;
Expand Down Expand Up @@ -3950,8 +3946,7 @@ fn test_pox_missing_five_anchor_blocks() {
confs.push(conf);
}

let node_privkey_1 =
StacksNode::make_node_private_key_from_seed(&confs[0].node.local_peer_seed);
let node_privkey_1 = Secp256k1PrivateKey::from_seed(&confs[0].node.local_peer_seed);
for i in 1..num_miners {
let chain_id = confs[0].burnchain.chain_id;
let peer_version = confs[0].burnchain.peer_version;
Expand Down Expand Up @@ -4349,8 +4344,7 @@ fn test_sortition_divergence_pre_21() {
confs.push(conf);
}

let node_privkey_1 =
StacksNode::make_node_private_key_from_seed(&confs[0].node.local_peer_seed);
let node_privkey_1 = Secp256k1PrivateKey::from_seed(&confs[0].node.local_peer_seed);
for i in 1..num_miners {
let chain_id = confs[0].burnchain.chain_id;
let peer_version = confs[0].burnchain.peer_version;
Expand Down
6 changes: 2 additions & 4 deletions testnet/stacks-node/src/tests/neon_integrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ use stacks::types::chainstate::{
};
use stacks::util::hash::Hash160;
use stacks::util::hash::{bytes_to_hex, hex_bytes, to_hex};
use stacks::util::secp256k1::Secp256k1PrivateKey;
use stacks::util::secp256k1::Secp256k1PublicKey;
use stacks::util::{get_epoch_time_ms, get_epoch_time_secs, sleep_ms};
use stacks::util_lib::boot::boot_code_id;
Expand Down Expand Up @@ -77,8 +78,6 @@ use crate::{
use crate::util::hash::{MerkleTree, Sha512Trunc256Sum};
use crate::util::secp256k1::MessageSignature;

use crate::neon_node::StacksNode;

use rand::Rng;

use super::bitcoin_regtest::BitcoinCoreController;
Expand Down Expand Up @@ -10492,8 +10491,7 @@ fn test_competing_miners_build_on_same_chain(
confs.push(conf);
}

let node_privkey_1 =
StacksNode::make_node_private_key_from_seed(&confs[0].node.local_peer_seed);
let node_privkey_1 = Secp256k1PrivateKey::from_seed(&confs[0].node.local_peer_seed);
for i in 1..num_miners {
let chain_id = confs[0].burnchain.chain_id;
let peer_version = confs[0].burnchain.peer_version;
Expand Down

0 comments on commit 995ea8f

Please sign in to comment.