diff --git a/crates/testing-utils/src/lib.rs b/crates/testing-utils/src/lib.rs index eaca4f553..8da2a5cda 100644 --- a/crates/testing-utils/src/lib.rs +++ b/crates/testing-utils/src/lib.rs @@ -21,6 +21,8 @@ pub mod constants; pub mod create_test_keyshares; mod node_proc; pub mod substrate_context; -pub use entropy_tss::helpers::tests::spawn_testing_validators; +pub use entropy_tss::helpers::tests::{ + jump_start_network_with_signer as jump_start_network, spawn_testing_validators, +}; pub use node_proc::TestNodeProcess; pub use substrate_context::*; diff --git a/crates/threshold-signature-server/src/helpers/tests.rs b/crates/threshold-signature-server/src/helpers/tests.rs index bb5906f41..72b1c5557 100644 --- a/crates/threshold-signature-server/src/helpers/tests.rs +++ b/crates/threshold-signature-server/src/helpers/tests.rs @@ -32,6 +32,7 @@ use crate::{ }, logger::{Instrumentation, Logger}, substrate::{query_chain, submit_transaction}, + validator::get_signer_and_x25519_secret_from_mnemonic, }, signing_client::ListenerState, AppState, @@ -264,3 +265,25 @@ pub async fn unsafe_get(client: &reqwest::Client, query_key: String, port: u32) get_result.bytes().await.unwrap().into() } + +/// Mock the network being jump started by confirming a jump start even though no DKG took place, +/// so that we can use pre-store parent keyshares for testing +pub async fn jump_start_network_with_signer( + api: &OnlineClient, + rpc: &LegacyRpcMethods, + signer: &PairSigner, +) { + let jump_start_request = entropy::tx().registry().jump_start_network(); + let _result = submit_transaction(api, rpc, signer, &jump_start_request, None).await.unwrap(); + + let validators_names = vec![ValidatorName::Bob, ValidatorName::Charlie, ValidatorName::Dave]; + for validator_name in validators_names { + let mnemonic = development_mnemonic(&Some(validator_name)); + let (tss_signer, _static_secret) = + get_signer_and_x25519_secret_from_mnemonic(&mnemonic.to_string()).unwrap(); + let jump_start_confirm_request = + entropy::tx().registry().confirm_jump_start(BoundedVec(EVE_VERIFYING_KEY.to_vec())); + + submit_transaction(api, rpc, &tss_signer, &jump_start_confirm_request, None).await.unwrap(); + } +} diff --git a/crates/threshold-signature-server/src/user/tests.rs b/crates/threshold-signature-server/src/user/tests.rs index b6c68a6f3..b141ee641 100644 --- a/crates/threshold-signature-server/src/user/tests.rs +++ b/crates/threshold-signature-server/src/user/tests.rs @@ -121,7 +121,8 @@ use crate::{ substrate::{get_oracle_data, query_chain, submit_transaction}, tests::{ check_has_confirmation, check_if_confirmation, create_clients, initialize_test_logger, - remove_program, run_to_block, setup_client, spawn_testing_validators, unsafe_get, + jump_start_network_with_signer, remove_program, run_to_block, setup_client, + spawn_testing_validators, unsafe_get, }, user::compute_hash, validator::get_signer_and_x25519_secret_from_mnemonic, @@ -1555,80 +1556,6 @@ async fn test_new_registration_flow() { clean_tests(); } -#[tokio::test] -#[serial] -async fn test_client_register_and_sign() { - clean_tests(); - let account_owner = AccountKeyring::Ferdie.pair(); - let signature_request_author = AccountKeyring::One; - - let add_parent_key = true; - let (_validator_ips, _validator_ids) = spawn_testing_validators(add_parent_key).await; - - let force_authoring = true; - let substrate_context = test_node_process_testing_state(force_authoring).await; - let api = get_api(&substrate_context.ws_url).await.unwrap(); - let rpc = get_rpc(&substrate_context.ws_url).await.unwrap(); - - // Jumpstart the network - jump_start_network(&api, &rpc).await; - - // Store a program - let program_pointer = store_program( - &api, - &rpc, - &account_owner, - TEST_PROGRAM_WASM_BYTECODE.to_owned(), - vec![], - vec![], - vec![], - ) - .await - .unwrap(); - - // Register, using that program - let (verifying_key, _registered_info) = { - let register_on_chain = true; - let mut registrations = register( - &api, - &rpc, - account_owner.clone(), - subxtAccountId32(account_owner.public().0), - BoundedVec(vec![ProgramInstance { program_pointer, program_config: vec![] }]), - register_on_chain, - ) - .await - .unwrap(); - - registrations.pop().unwrap() - }; - - // Sign a message - let recoverable_signature = sign( - &api, - &rpc, - signature_request_author.pair(), - verifying_key, - PREIMAGE_SHOULD_SUCCEED.to_vec(), - Some(AUXILARY_DATA_SHOULD_SUCCEED.to_vec()), - ) - .await - .unwrap(); - - // Check the signature - let message_should_succeed_hash = Hasher::keccak(PREIMAGE_SHOULD_SUCCEED); - let recovery_key_from_sig = VerifyingKey::recover_from_prehash( - &message_should_succeed_hash, - &recoverable_signature.signature, - recoverable_signature.recovery_id, - ) - .unwrap(); - assert_eq!( - verifying_key.to_vec(), - recovery_key_from_sig.to_encoded_point(true).to_bytes().to_vec() - ); -} - #[tokio::test] #[serial] async fn test_mutiple_confirm_done() { @@ -1825,24 +1752,12 @@ pub async fn get_sign_tx_data( (validators_info, generic_msg, validator_ips_and_keys) } +/// Mock jump starting the network pub async fn jump_start_network( api: &OnlineClient, rpc: &LegacyRpcMethods, ) { let alice = AccountKeyring::Alice; let signer = PairSigner::::new(alice.clone().into()); - - let jump_start_request = entropy::tx().registry().jump_start_network(); - let _result = submit_transaction(api, rpc, &signer, &jump_start_request, None).await.unwrap(); - - let validators_names = vec![ValidatorName::Bob, ValidatorName::Charlie, ValidatorName::Dave]; - for validator_name in validators_names { - let mnemonic = development_mnemonic(&Some(validator_name)); - let (tss_signer, _static_secret) = - get_signer_and_x25519_secret_from_mnemonic(&mnemonic.to_string()).unwrap(); - let jump_start_confirm_request = - entropy::tx().registry().confirm_jump_start(BoundedVec(EVE_VERIFYING_KEY.to_vec())); - - submit_transaction(api, rpc, &tss_signer, &jump_start_confirm_request, None).await.unwrap(); - } + jump_start_network_with_signer(api, rpc, &signer).await; } diff --git a/crates/threshold-signature-server/tests/register_and_sign.rs b/crates/threshold-signature-server/tests/register_and_sign.rs new file mode 100644 index 000000000..454ff701e --- /dev/null +++ b/crates/threshold-signature-server/tests/register_and_sign.rs @@ -0,0 +1,107 @@ +// Copyright (C) 2023 Entropy Cryptography Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +use entropy_client::{ + chain_api::{ + entropy::runtime_types::bounded_collections::bounded_vec::BoundedVec, + entropy::runtime_types::pallet_registry::pallet::ProgramInstance, get_api, get_rpc, + EntropyConfig, + }, + client as test_client, Hasher, +}; +use entropy_kvdb::clean_tests; +use entropy_testing_utils::{ + constants::{ + AUXILARY_DATA_SHOULD_SUCCEED, PREIMAGE_SHOULD_SUCCEED, TEST_PROGRAM_WASM_BYTECODE, + }, + jump_start_network, spawn_testing_validators, test_node_process_testing_state, +}; +use serial_test::serial; +use sp_core::{sr25519, Pair}; +use sp_keyring::AccountKeyring; +use subxt::{tx::PairSigner, utils::AccountId32}; +use synedrion::k256::ecdsa::VerifyingKey; + +#[tokio::test] +#[serial] +async fn integration_test_register_and_sign() { + clean_tests(); + let account_owner = AccountKeyring::Ferdie.pair(); + let signature_request_author = AccountKeyring::One; + + let add_parent_key = true; + let (_validator_ips, _validator_ids) = spawn_testing_validators(add_parent_key).await; + + let force_authoring = true; + let substrate_context = test_node_process_testing_state(force_authoring).await; + let api = get_api(&substrate_context.ws_url).await.unwrap(); + let rpc = get_rpc(&substrate_context.ws_url).await.unwrap(); + + // Jumpstart the network + let alice = AccountKeyring::Alice; + let signer = PairSigner::::new(alice.clone().into()); + jump_start_network(&api, &rpc, &signer).await; + + // Store a program + let program_pointer = test_client::store_program( + &api, + &rpc, + &account_owner, + TEST_PROGRAM_WASM_BYTECODE.to_owned(), + vec![], + vec![], + vec![], + ) + .await + .unwrap(); + + // Register, using that program + let register_on_chain = true; + let (verifying_key, _registered_info) = test_client::register( + &api, + &rpc, + account_owner.clone(), + AccountId32(account_owner.public().0), + BoundedVec(vec![ProgramInstance { program_pointer, program_config: vec![] }]), + register_on_chain, + ) + .await + .unwrap(); + + // Sign a message + let recoverable_signature = test_client::sign( + &api, + &rpc, + signature_request_author.pair(), + verifying_key, + PREIMAGE_SHOULD_SUCCEED.to_vec(), + Some(AUXILARY_DATA_SHOULD_SUCCEED.to_vec()), + ) + .await + .unwrap(); + + // Check the signature + let message_should_succeed_hash = Hasher::keccak(PREIMAGE_SHOULD_SUCCEED); + let recovery_key_from_sig = VerifyingKey::recover_from_prehash( + &message_should_succeed_hash, + &recoverable_signature.signature, + recoverable_signature.recovery_id, + ) + .unwrap(); + assert_eq!( + verifying_key.to_vec(), + recovery_key_from_sig.to_encoded_point(true).to_bytes().to_vec() + ); +}