Skip to content

Commit 151e06e

Browse files
author
Aaron Blankstein
authored
Merge pull request #2052 from blockstack/fix/1934
Fix 1934: mix burn block height into microblock pubkey
2 parents 0b96be3 + bcc602b commit 151e06e

File tree

6 files changed

+36
-12
lines changed

6 files changed

+36
-12
lines changed

src/vm/docs/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ const PRINT_API: SpecialAPI = SpecialAPI {
545545
input_type: "A",
546546
output_type: "A",
547547
signature: "(print expr)",
548-
description: "The `print` function evaluates and returns its input expression. On Blockstack Core
548+
description: "The `print` function evaluates and returns its input expression. On Stacks Core
549549
nodes configured for development (as opposed to production mining nodes), this function prints the resulting value to `STDOUT` (standard output).",
550550
example: "(print (+ 1 2 3)) ;; Returns 6",
551551
};

testnet/stacks-node/src/keychain.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use stacks::burnchains::{BurnchainSigner, PrivateKey};
77
use stacks::chainstate::stacks::{
88
StacksAddress, StacksPrivateKey, StacksPublicKey, StacksTransactionSigner, TransactionAuth,
99
};
10-
use stacks::util::hash::Sha256Sum;
10+
use stacks::util::hash::{Hash160, Sha256Sum};
1111
use stacks::util::vrf::{VRFPrivateKey, VRFProof, VRFPublicKey, VRF};
1212

1313
#[derive(Clone)]
@@ -97,14 +97,18 @@ impl Keychain {
9797
pk
9898
}
9999

100-
pub fn rotate_microblock_keypair(&mut self) -> StacksPrivateKey {
101-
let mut seed = match self.microblocks_secret_keys.last() {
100+
pub fn rotate_microblock_keypair(&mut self, burn_block_height: u64) -> StacksPrivateKey {
101+
let mut secret_state = match self.microblocks_secret_keys.last() {
102102
// First key is the hash of the secret state
103-
None => self.hashed_secret_state,
103+
None => self.hashed_secret_state.to_bytes().to_vec(),
104104
// Next key is the hash of the last
105-
Some(last_sk) => Sha256Sum::from_data(&last_sk.to_bytes()[..]),
105+
Some(last_sk) => last_sk.to_bytes().to_vec(),
106106
};
107107

108+
secret_state.extend_from_slice(&burn_block_height.to_be_bytes());
109+
110+
let mut seed = Sha256Sum::from_data(&secret_state);
111+
108112
// Not every 256-bit number is a valid secp256k1 secret key.
109113
// As such, we continuously generate seeds through re-hashing until one works.
110114
let mut sk = loop {
@@ -116,6 +120,10 @@ impl Keychain {
116120
sk.set_compress_public(true);
117121
self.microblocks_secret_keys.push(sk.clone());
118122

123+
debug!("Microblock keypair rotated";
124+
"burn_block_height" => %burn_block_height,
125+
"pubkey_hash" => %Hash160::from_node_public_key(&StacksPublicKey::from_private(&sk)).to_string(),);
126+
119127
sk
120128
}
121129

testnet/stacks-node/src/neon_node.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1033,7 +1033,20 @@ impl InitializedNeonNode {
10331033

10341034
// Generates a new secret key for signing the trail of microblocks
10351035
// of the upcoming tenure.
1036-
let microblock_secret_key = keychain.rotate_microblock_keypair();
1036+
let microblock_secret_key = if attempt > 1 {
1037+
match keychain.get_microblock_key() {
1038+
Some(k) => k,
1039+
None => {
1040+
error!(
1041+
"Failed to obtain microblock key for mining attempt";
1042+
"attempt" => %attempt
1043+
);
1044+
return None;
1045+
}
1046+
}
1047+
} else {
1048+
keychain.rotate_microblock_keypair(burn_block.block_height)
1049+
};
10371050
let mblock_pubkey_hash =
10381051
Hash160::from_node_public_key(&StacksPublicKey::from_private(&microblock_secret_key));
10391052

testnet/stacks-node/src/node.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,9 @@ impl Node {
475475

476476
// Generates a new secret key for signing the trail of microblocks
477477
// of the upcoming tenure.
478-
let microblock_secret_key = self.keychain.rotate_microblock_keypair();
478+
let microblock_secret_key = self
479+
.keychain
480+
.rotate_microblock_keypair(block_to_build_upon.block_snapshot.block_height);
479481

480482
// Get the stack's chain tip
481483
let chain_tip = match self.bootstraping_chain {

testnet/stacks-node/src/tests/mempool.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -637,8 +637,8 @@ fn mempool_setup_chainstate() {
637637
conf.node.seed = vec![0x00];
638638

639639
let mut keychain = Keychain::default(conf.node.seed.clone());
640-
for _i in 0..4 {
641-
let microblock_secret_key = keychain.rotate_microblock_keypair();
640+
for i in 0..4 {
641+
let microblock_secret_key = keychain.rotate_microblock_keypair(1 + i);
642642
let mut microblock_pubkey =
643643
Secp256k1PublicKey::from_private(&microblock_secret_key);
644644
microblock_pubkey.set_compressed(true);

testnet/stacks-node/src/tests/neon_integrations.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,9 @@ fn find_microblock_privkey(
197197
max_tries: u64,
198198
) -> Option<StacksPrivateKey> {
199199
let mut keychain = Keychain::default(conf.node.seed.clone());
200-
for _ in 0..max_tries {
201-
let privk = keychain.rotate_microblock_keypair();
200+
for ix in 0..max_tries {
201+
// the first rotation occurs at 203.
202+
let privk = keychain.rotate_microblock_keypair(203 + ix);
202203
let pubkh = Hash160::from_node_public_key(&StacksPublicKey::from_private(&privk));
203204
if pubkh == *pubkey_hash {
204205
return Some(privk);

0 commit comments

Comments
 (0)