Skip to content

Commit b8e17c8

Browse files
authored
Merge pull request #5070 from stacks-network/feat/mock-signature-aggregation
Feat/mock signing revamp
2 parents 02fdee4 + 1610ce3 commit b8e17c8

File tree

8 files changed

+509
-259
lines changed

8 files changed

+509
-259
lines changed

libsigner/src/v0/messages.rs

Lines changed: 200 additions & 111 deletions
Large diffs are not rendered by default.

stacks-signer/src/v0/signer.rs

Lines changed: 23 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,12 @@ use std::sync::mpsc::Sender;
1818

1919
use blockstack_lib::chainstate::nakamoto::NakamotoBlockHeader;
2020
use blockstack_lib::net::api::postblock_proposal::BlockValidateResponse;
21-
use clarity::consts::{CHAIN_ID_MAINNET, CHAIN_ID_TESTNET};
2221
use clarity::types::chainstate::StacksPrivateKey;
2322
use clarity::types::{PrivateKey, StacksEpochId};
2423
use clarity::util::hash::MerkleHashFunc;
2524
use clarity::util::secp256k1::Secp256k1PublicKey;
2625
use libsigner::v0::messages::{
27-
BlockResponse, MessageSlotID, MockSignature, RejectCode, SignerMessage,
26+
BlockResponse, MessageSlotID, MockProposal, MockSignature, RejectCode, SignerMessage,
2827
};
2928
use libsigner::{BlockProposal, SignerEvent};
3029
use slog::{slog_debug, slog_error, slog_info, slog_warn};
@@ -159,6 +158,25 @@ impl SignerTrait<SignerMessage> for Signer {
159158
"push_result" => ?block_push_result,
160159
);
161160
}
161+
SignerMessage::MockProposal(mock_proposal) => {
162+
let epoch = match stacks_client.get_node_epoch() {
163+
Ok(epoch) => epoch,
164+
Err(e) => {
165+
warn!("{self}: Failed to determine node epoch. Cannot mock sign: {e}");
166+
return;
167+
}
168+
};
169+
info!("{self}: received a mock block proposal.";
170+
"current_reward_cycle" => current_reward_cycle,
171+
"epoch" => ?epoch
172+
);
173+
if epoch == StacksEpochId::Epoch25
174+
&& self.reward_cycle == current_reward_cycle
175+
{
176+
// We are in epoch 2.5, so we should mock sign to prove we are still alive.
177+
self.mock_sign(mock_proposal.clone());
178+
}
179+
}
162180
_ => {}
163181
}
164182
}
@@ -184,22 +202,6 @@ impl SignerTrait<SignerMessage> for Signer {
184202
);
185203
}
186204
*sortition_state = None;
187-
let epoch = match stacks_client.get_node_epoch() {
188-
Ok(epoch) => epoch,
189-
Err(e) => {
190-
warn!("{self}: Failed to determine node epoch. Cannot mock sign: {e}");
191-
return;
192-
}
193-
};
194-
debug!("{self}: Epoch 2.5 signer received a new burn block event.";
195-
"burn_height" => burn_height,
196-
"current_reward_cycle" => current_reward_cycle,
197-
"epoch" => ?epoch
198-
);
199-
if epoch == StacksEpochId::Epoch25 && self.reward_cycle == current_reward_cycle {
200-
// We are in epoch 2.5, so we should mock mine to prove we are still alive.
201-
self.mock_sign(*burn_height, stacks_client);
202-
}
203205
}
204206
}
205207
}
@@ -720,26 +722,9 @@ impl Signer {
720722
}
721723

722724
/// Send a mock signature to stackerdb to prove we are still alive
723-
fn mock_sign(&mut self, burn_block_height: u64, stacks_client: &StacksClient) {
724-
let Ok(peer_info) = stacks_client.get_peer_info() else {
725-
warn!("{self}: Failed to get peer info. Cannot mock sign.");
726-
return;
727-
};
728-
let chain_id = if self.mainnet {
729-
CHAIN_ID_MAINNET
730-
} else {
731-
CHAIN_ID_TESTNET
732-
};
733-
info!("Mock signing for burn block {burn_block_height:?}";
734-
"stacks_tip_consensus_hash" => ?peer_info.stacks_tip_consensus_hash.clone(),
735-
"stacks_tip" => ?peer_info.stacks_tip.clone(),
736-
"peer_burn_block_height" => peer_info.burn_block_height,
737-
"pox_consensus" => ?peer_info.pox_consensus.clone(),
738-
"server_version" => peer_info.server_version.clone(),
739-
"chain_id" => chain_id
740-
);
741-
let mock_signature =
742-
MockSignature::new(burn_block_height, peer_info, chain_id, &self.private_key);
725+
fn mock_sign(&mut self, mock_proposal: MockProposal) {
726+
info!("{self}: Mock signing mock proposal: {mock_proposal:?}");
727+
let mock_signature = MockSignature::new(mock_proposal, &self.private_key);
743728
let message = SignerMessage::MockSignature(mock_signature);
744729
if let Err(e) = self
745730
.stackerdb

stackslib/src/chainstate/nakamoto/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4191,7 +4191,6 @@ impl NakamotoChainState {
41914191
"stackerdb_slots" => ?stackerdb_config.signers,
41924192
"queried_sortition" => %election_sortition,
41934193
"sortition_hashes" => ?miners_info.get_sortitions());
4194-
41954194
return Ok(None);
41964195
}
41974196
let slot_id_range = signer_ranges.swap_remove(signer_ix);

testnet/stacks-node/src/config.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,6 +1168,10 @@ impl Config {
11681168
.validate()
11691169
.map_err(|e| format!("Atlas config error: {e}"))?;
11701170

1171+
if miner.mining_key.is_none() && miner.pre_nakamoto_mock_signing {
1172+
return Err("Cannot use pre_nakamoto_mock_signing without a mining_key".to_string());
1173+
}
1174+
11711175
Ok(Config {
11721176
config_path: config_file.__path,
11731177
node,
@@ -2352,6 +2356,8 @@ pub struct MinerConfig {
23522356
pub max_reorg_depth: u64,
23532357
/// Amount of time while mining in nakamoto to wait for signers to respond to a proposed block
23542358
pub wait_on_signers: Duration,
2359+
/// Whether to mock sign in Epoch 2.5 through the .miners and .signers contracts. This is used for testing purposes in Epoch 2.5 only.
2360+
pub pre_nakamoto_mock_signing: bool,
23552361
}
23562362

23572363
impl Default for MinerConfig {
@@ -2382,6 +2388,7 @@ impl Default for MinerConfig {
23822388
max_reorg_depth: 3,
23832389
// TODO: update to a sane value based on stackerdb benchmarking
23842390
wait_on_signers: Duration::from_secs(200),
2391+
pre_nakamoto_mock_signing: false, // Should only default true if mining key is set
23852392
}
23862393
}
23872394
}
@@ -2731,10 +2738,17 @@ pub struct MinerConfigFile {
27312738
pub filter_origins: Option<String>,
27322739
pub max_reorg_depth: Option<u64>,
27332740
pub wait_on_signers_ms: Option<u64>,
2741+
pub pre_nakamoto_mock_signing: Option<bool>,
27342742
}
27352743

27362744
impl MinerConfigFile {
27372745
fn into_config_default(self, miner_default_config: MinerConfig) -> Result<MinerConfig, String> {
2746+
let mining_key = self
2747+
.mining_key
2748+
.as_ref()
2749+
.map(|x| Secp256k1PrivateKey::from_hex(x))
2750+
.transpose()?;
2751+
let pre_nakamoto_mock_signing = mining_key.is_some();
27382752
Ok(MinerConfig {
27392753
first_attempt_time_ms: self
27402754
.first_attempt_time_ms
@@ -2833,6 +2847,9 @@ impl MinerConfigFile {
28332847
.wait_on_signers_ms
28342848
.map(Duration::from_millis)
28352849
.unwrap_or(miner_default_config.wait_on_signers),
2850+
pre_nakamoto_mock_signing: self
2851+
.pre_nakamoto_mock_signing
2852+
.unwrap_or(pre_nakamoto_mock_signing), // Should only default true if mining key is set
28362853
})
28372854
}
28382855
}

testnet/stacks-node/src/nakamoto_node/sign_coordinator.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -860,8 +860,10 @@ impl SignCoordinator {
860860
debug!("Received block pushed message. Ignoring.");
861861
continue;
862862
}
863-
SignerMessageV0::MockSignature(_) => {
864-
debug!("Received mock signature message. Ignoring.");
863+
SignerMessageV0::MockSignature(_)
864+
| SignerMessageV0::MockProposal(_)
865+
| SignerMessageV0::MockBlock(_) => {
866+
debug!("Received mock message. Ignoring.");
865867
continue;
866868
}
867869
};

0 commit comments

Comments
 (0)