Merge branch 'next' into draft/multisig-order-independence

This commit is contained in:
Jude Nelson
2024-04-03 14:35:59 +00:00
committed by GitHub
38 changed files with 979 additions and 338 deletions

View File

@@ -92,6 +92,8 @@ struct SignerTest {
pub signer_stacks_private_keys: Vec<StacksPrivateKey>,
// link to the stacks node
pub stacks_client: StacksClient,
// Unique number used to isolate files created during the test
pub run_stamp: u16,
}
impl SignerTest {
@@ -107,6 +109,8 @@ impl SignerTest {
let password = "12345";
naka_conf.connection_options.block_proposal_token = Some(password.to_string());
let run_stamp = rand::random();
// Setup the signer and coordinator configurations
let signer_configs = build_signer_config_tomls(
&signer_stacks_private_keys,
@@ -114,6 +118,8 @@ impl SignerTest {
Some(Duration::from_millis(128)), // Timeout defaults to 5 seconds. Let's override it to 128 milliseconds.
&Network::Testnet,
password,
run_stamp,
3000,
);
let mut running_signers = Vec::new();
@@ -144,6 +150,7 @@ impl SignerTest {
running_signers,
signer_stacks_private_keys,
stacks_client,
run_stamp,
}
}
@@ -426,22 +433,11 @@ impl SignerTest {
.expect("failed to recv dkg results");
for result in results {
match result {
OperationResult::Sign(sig) => {
panic!("Received Signature ({},{})", &sig.R, &sig.z);
}
OperationResult::SignTaproot(proof) => {
panic!("Received SchnorrProof ({},{})", &proof.r, &proof.s);
}
OperationResult::DkgError(dkg_error) => {
panic!("Received DkgError {:?}", dkg_error);
}
OperationResult::SignError(sign_error) => {
panic!("Received SignError {}", sign_error);
}
OperationResult::Dkg(point) => {
info!("Received aggregate_group_key {point}");
aggregate_public_key = Some(point);
}
other => panic!("{}", operation_panic_message(&other)),
}
}
if aggregate_public_key.is_some() || dkg_now.elapsed() > timeout {
@@ -703,6 +699,46 @@ impl SignerTest {
]
}
/// Kills the signer runloop at index `signer_idx`
/// and returns the private key of the killed signer.
///
/// # Panics
/// Panics if `signer_idx` is out of bounds
fn stop_signer(&mut self, signer_idx: usize) -> StacksPrivateKey {
let running_signer = self.running_signers.remove(signer_idx);
self.signer_cmd_senders.remove(signer_idx);
self.result_receivers.remove(signer_idx);
let signer_key = self.signer_stacks_private_keys.remove(signer_idx);
running_signer.stop();
signer_key
}
/// (Re)starts a new signer runloop with the given private key
fn restart_signer(&mut self, signer_idx: usize, signer_private_key: StacksPrivateKey) {
let signer_config = build_signer_config_tomls(
&[signer_private_key],
&self.running_nodes.conf.node.rpc_bind,
Some(Duration::from_millis(128)), // Timeout defaults to 5 seconds. Let's override it to 128 milliseconds.
&Network::Testnet,
"12345", // It worked sir, we have the combination! -Great, what's the combination?
self.run_stamp,
3000 + signer_idx,
)
.pop()
.unwrap();
let (cmd_send, cmd_recv) = channel();
let (res_send, res_recv) = channel();
info!("Restarting signer");
let signer = spawn_signer(&signer_config, cmd_recv, res_send);
self.result_receivers.insert(signer_idx, res_recv);
self.signer_cmd_senders.insert(signer_idx, cmd_send);
self.running_signers.insert(signer_idx, signer);
}
fn shutdown(self) {
self.running_nodes
.coord_channel
@@ -851,6 +887,26 @@ fn setup_stx_btc_node(
}
}
fn operation_panic_message(result: &OperationResult) -> String {
match result {
OperationResult::Sign(sig) => {
format!("Received Signature ({},{})", sig.R, sig.z)
}
OperationResult::SignTaproot(proof) => {
format!("Received SchnorrProof ({},{})", proof.r, proof.s)
}
OperationResult::DkgError(dkg_error) => {
format!("Received DkgError {:?}", dkg_error)
}
OperationResult::SignError(sign_error) => {
format!("Received SignError {}", sign_error)
}
OperationResult::Dkg(point) => {
format!("Received aggregate_group_key {point}")
}
}
}
#[test]
#[ignore]
/// Test the signer can respond to external commands to perform DKG
@@ -1266,3 +1322,72 @@ fn stackerdb_filter_bad_transactions() {
}
signer_test.shutdown();
}
#[test]
#[ignore]
/// Test that signers will be able to continue their operations even if one signer is restarted.
///
/// Test Setup:
/// The test spins up three stacks signers, one miner Nakamoto node, and a corresponding bitcoind.
/// The stacks node is advanced to epoch 2.5, triggering a DKG round. The stacks node is then advanced
/// to Epoch 3.0 boundary to allow block signing.
///
/// Test Execution:
/// The signers sign one block as usual.
/// Then, one of the signers is restarted.
/// Finally, the signers sign another block with the restarted signer.
///
/// Test Assertion:
/// The signers are able to produce a valid signature after one of them is restarted.
fn stackerdb_sign_after_signer_reboot() {
if env::var("BITCOIND_TEST") != Ok("1".into()) {
return;
}
tracing_subscriber::registry()
.with(fmt::layer())
.with(EnvFilter::from_default_env())
.init();
info!("------------------------- Test Setup -------------------------");
let mut signer_test = SignerTest::new(3);
let timeout = Duration::from_secs(200);
let short_timeout = Duration::from_secs(30);
let key = signer_test.boot_to_epoch_3(timeout);
info!("------------------------- Test Mine Block -------------------------");
signer_test.mine_nakamoto_block(timeout);
let proposed_signer_signature_hash = signer_test.wait_for_validate_ok_response(short_timeout);
let signature =
signer_test.wait_for_confirmed_block(&proposed_signer_signature_hash, short_timeout);
assert!(
signature.verify(&key, proposed_signer_signature_hash.0.as_slice()),
"Signature verification failed"
);
info!("------------------------- Restart one Signer -------------------------");
let signer_key = signer_test.stop_signer(2);
debug!(
"Removed signer 2 with key: {:?}, {}",
signer_key,
signer_key.to_hex()
);
signer_test.restart_signer(2, signer_key);
info!("------------------------- Test Mine Block after restart -------------------------");
signer_test.mine_nakamoto_block(timeout);
let proposed_signer_signature_hash = signer_test.wait_for_validate_ok_response(short_timeout);
let frost_signature =
signer_test.wait_for_confirmed_block(&proposed_signer_signature_hash, short_timeout);
assert!(
frost_signature.verify(&key, proposed_signer_signature_hash.0.as_slice()),
"Signature verification failed"
);
signer_test.shutdown();
}