Skip to content

Commit

Permalink
Jumpstart network (#918)
Browse files Browse the repository at this point in the history
* Jumpstart network

* some tests

* add confirmation check

* fix jump start details test

* test jump start

* jump start threshold side test

* jumpstart test

* test master key sign

* fmt

* fmt

* add benchmarks to register

* clean

* changelog

* clean

* Apply suggestions from code review

Co-authored-by: Hernando Castano <[email protected]>

* fixes

* add comment

* fix

* Apply suggestions from code review

Co-authored-by: Hernando Castano <[email protected]>

* fix

* change master to parent

* fix build

* fix build

* fix

* Update crates/threshold-signature-server/src/user/errors.rs

Co-authored-by: Hernando Castano <[email protected]>

* fix

---------

Co-authored-by: Hernando Castano <[email protected]>
  • Loading branch information
JesseAbram and HCastano authored Jul 11, 2024
1 parent 5a39fc6 commit 314849f
Show file tree
Hide file tree
Showing 11 changed files with 617 additions and 60 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ At the moment this project **does not** adhere to

## [Unreleased](https://github.com/entropyxyz/entropy-core/compare/release/v0.2.0...master)

### Added
- Jumpstart network ([#918](https://github.com/entropyxyz/entropy-core/pull/918))

## [0.2.0](https://github.com/entropyxyz/entropy-core/compare/release/v0.1.0...release/v0.2.0) - 2024-07-11

### Breaking Changes
Expand Down
Binary file modified crates/client/entropy_metadata.scale
Binary file not shown.
2 changes: 2 additions & 0 deletions crates/shared/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ lazy_static! {
pub static ref DEVICE_KEY_CONFIG_TYPE: Vec<u8> = vec![123, 34, 36, 115, 99, 104, 101, 109, 97, 34, 58, 34, 104, 116, 116, 112, 58, 47, 47, 106, 115, 111, 110, 45, 115, 99, 104, 101, 109, 97, 46, 111, 114, 103, 47, 100, 114, 97, 102, 116, 45, 48, 55, 47, 115, 99, 104, 101, 109, 97, 35, 34, 44, 34, 116, 105, 116, 108, 101, 34, 58, 34, 85, 115, 101, 114, 67, 111, 110, 102, 105, 103, 34, 44, 34, 100, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 58, 34, 74, 83, 79, 78, 45, 100, 101, 115, 101, 114, 105, 97, 108, 105, 122, 97, 98, 108, 101, 32, 115, 116, 114, 117, 99, 116, 32, 116, 104, 97, 116, 32, 119, 105, 108, 108, 32, 98, 101, 32, 117, 115, 101, 100, 32, 116, 111, 32, 100, 101, 114, 105, 118, 101, 32, 116, 104, 101, 32, 112, 114, 111, 103, 114, 97, 109, 45, 74, 83, 79, 78, 32, 105, 110, 116, 101, 114, 102, 97, 99, 101, 46, 32, 78, 111, 116, 101, 32, 104, 111, 119, 32, 116, 104, 105, 115, 32, 117, 115, 101, 115, 32, 74, 83, 79, 78, 45, 110, 97, 116, 105, 118, 101, 32, 116, 121, 112, 101, 115, 32, 111, 110, 108, 121, 46, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 111, 98, 106, 101, 99, 116, 34, 44, 34, 112, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 58, 123, 34, 101, 99, 100, 115, 97, 95, 112, 117, 98, 108, 105, 99, 95, 107, 101, 121, 115, 34, 58, 123, 34, 100, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 58, 34, 98, 97, 115, 101, 54, 52, 45, 101, 110, 99, 111, 100, 101, 100, 32, 99, 111, 109, 112, 114, 101, 115, 115, 101, 100, 32, 112, 111, 105, 110, 116, 32, 40, 51, 51, 45, 98, 121, 116, 101, 41, 32, 69, 67, 68, 83, 65, 32, 112, 117, 98, 108, 105, 99, 32, 107, 101, 121, 115, 44, 32, 40, 101, 103, 46, 32, 92, 34, 65, 53, 55, 50, 100, 113, 111, 117, 101, 53, 79, 121, 119, 89, 47, 52, 56, 100, 116, 121, 116, 81, 105, 109, 76, 57, 87, 79, 48, 100, 112, 83, 79, 98, 97, 70, 98, 65, 120, 111, 69, 87, 87, 57, 92, 34, 41, 34, 44, 34, 116, 121, 112, 101, 34, 58, 91, 34, 97, 114, 114, 97, 121, 34, 44, 34, 110, 117, 108, 108, 34, 93, 44, 34, 105, 116, 101, 109, 115, 34, 58, 123, 34, 116, 121, 112, 101, 34, 58, 34, 115, 116, 114, 105, 110, 103, 34, 125, 125, 44, 34, 101, 100, 50, 53, 53, 49, 57, 95, 112, 117, 98, 108, 105, 99, 95, 107, 101, 121, 115, 34, 58, 123, 34, 116, 121, 112, 101, 34, 58, 91, 34, 97, 114, 114, 97, 121, 34, 44, 34, 110, 117, 108, 108, 34, 93, 44, 34, 105, 116, 101, 109, 115, 34, 58, 123, 34, 116, 121, 112, 101, 34, 58, 34, 115, 116, 114, 105, 110, 103, 34, 125, 125, 44, 34, 115, 114, 50, 53, 53, 49, 57, 95, 112, 117, 98, 108, 105, 99, 95, 107, 101, 121, 115, 34, 58, 123, 34, 116, 121, 112, 101, 34, 58, 91, 34, 97, 114, 114, 97, 121, 34, 44, 34, 110, 117, 108, 108, 34, 93, 44, 34, 105, 116, 101, 109, 115, 34, 58, 123, 34, 116, 121, 112, 101, 34, 58, 34, 115, 116, 114, 105, 110, 103, 34, 125, 125, 125, 125];
// Device key aux data struct seralized by generate types in programs repo
pub static ref DEVICE_KEY_AUX_DATA_TYPE: Vec<u8> = vec![123, 34, 36, 115, 99, 104, 101, 109, 97, 34, 58, 34, 104, 116, 116, 112, 58, 47, 47, 106, 115, 111, 110, 45, 115, 99, 104, 101, 109, 97, 46, 111, 114, 103, 47, 100, 114, 97, 102, 116, 45, 48, 55, 47, 115, 99, 104, 101, 109, 97, 35, 34, 44, 34, 116, 105, 116, 108, 101, 34, 58, 34, 65, 117, 120, 68, 97, 116, 97, 34, 44, 34, 100, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 58, 34, 74, 83, 79, 78, 32, 114, 101, 112, 114, 101, 115, 101, 110, 116, 97, 116, 105, 111, 110, 32, 111, 102, 32, 116, 104, 101, 32, 97, 117, 120, 105, 108, 105, 97, 114, 121, 32, 100, 97, 116, 97, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 111, 98, 106, 101, 99, 116, 34, 44, 34, 114, 101, 113, 117, 105, 114, 101, 100, 34, 58, 91, 34, 99, 111, 110, 116, 101, 120, 116, 34, 44, 34, 112, 117, 98, 108, 105, 99, 95, 107, 101, 121, 34, 44, 34, 112, 117, 98, 108, 105, 99, 95, 107, 101, 121, 95, 116, 121, 112, 101, 34, 44, 34, 115, 105, 103, 110, 97, 116, 117, 114, 101, 34, 93, 44, 34, 112, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 58, 123, 34, 99, 111, 110, 116, 101, 120, 116, 34, 58, 123, 34, 100, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 58, 34, 84, 104, 101, 32, 99, 111, 110, 116, 101, 120, 116, 32, 102, 111, 114, 32, 116, 104, 101, 32, 115, 105, 103, 110, 97, 116, 117, 114, 101, 32, 111, 110, 108, 121, 32, 110, 101, 101, 100, 101, 100, 32, 105, 110, 32, 115, 114, 50, 53, 53, 49, 57, 32, 115, 105, 103, 110, 97, 116, 117, 114, 101, 32, 116, 121, 112, 101, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 115, 116, 114, 105, 110, 103, 34, 125, 44, 34, 112, 117, 98, 108, 105, 99, 95, 107, 101, 121, 34, 58, 123, 34, 100, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 58, 34, 98, 97, 115, 101, 54, 52, 45, 101, 110, 99, 111, 100, 101, 100, 32, 112, 117, 98, 108, 105, 99, 32, 107, 101, 121, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 115, 116, 114, 105, 110, 103, 34, 125, 44, 34, 112, 117, 98, 108, 105, 99, 95, 107, 101, 121, 95, 116, 121, 112, 101, 34, 58, 123, 34, 100, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 58, 34, 92, 34, 101, 99, 100, 115, 97, 92, 34, 44, 32, 92, 34, 101, 100, 50, 53, 53, 49, 57, 92, 34, 44, 32, 92, 34, 115, 114, 50, 53, 53, 49, 57, 92, 34, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 115, 116, 114, 105, 110, 103, 34, 125, 44, 34, 115, 105, 103, 110, 97, 116, 117, 114, 101, 34, 58, 123, 34, 100, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 58, 34, 98, 97, 115, 101, 54, 52, 45, 101, 110, 99, 111, 100, 101, 100, 32, 115, 105, 103, 110, 97, 116, 117, 114, 101, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 115, 116, 114, 105, 110, 103, 34, 125, 125, 125];
// Network parent key
pub static ref NETWORK_PARENT_KEY: H256 = H256::zero();
}

pub const SIGNING_PARTY_SIZE: usize = 2;
Expand Down
49 changes: 36 additions & 13 deletions crates/threshold-signature-server/src/user/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ use entropy_programs_runtime::{Config as ProgramConfig, Runtime, SignatureReques
use entropy_protocol::ValidatorInfo;
use entropy_protocol::{KeyParams, SigningSessionInfo};
use entropy_shared::{
types::KeyVisibility, HashingAlgorithm, OcwMessageDkg, X25519PublicKey, SIGNING_PARTY_SIZE,
types::KeyVisibility, HashingAlgorithm, OcwMessageDkg, X25519PublicKey, NETWORK_PARENT_KEY,
SIGNING_PARTY_SIZE,
};
use futures::{
channel::mpsc,
Expand All @@ -46,7 +47,7 @@ use futures::{
use num::{bigint::BigInt, FromPrimitive, Num, ToPrimitive};
use parity_scale_codec::{Decode, DecodeAll, Encode};
use serde::{Deserialize, Serialize};
use sp_core::crypto::AccountId32;
use sp_core::{crypto::AccountId32, H256};
use subxt::{
backend::legacy::LegacyRpcMethods,
ext::sp_core::{crypto::Ss58Codec, sr25519, sr25519::Signature, Pair},
Expand Down Expand Up @@ -142,6 +143,11 @@ pub async fn sign_tx(
.number;

check_stale(user_sig_req.block_number, block_number).await?;
// Probably impossible but block signing from parent key anyways
if user_sig_req.signature_verifying_key == NETWORK_PARENT_KEY.encode() {
return Err(UserErr::NoSigningFromParentKey);
}

let user_details =
get_registered_details(&api, &rpc, user_sig_req.signature_verifying_key.clone()).await?;
check_hash_pointer_out_of_bounds(&user_sig_req.hash, user_details.programs_data.0.len())?;
Expand Down Expand Up @@ -307,7 +313,6 @@ async fn setup_dkg(
app_state: AppState,
) -> Result<(), UserErr> {
tracing::debug!("Preparing to execute DKG");

let subgroup = get_subgroup(&api, rpc, signer.account_id()).await?;
let stash_address = get_stash_address(&api, rpc, signer.account_id()).await?;
let mut addresses_in_subgroup = return_all_addresses_of_subgroup(&api, rpc, subgroup).await?;
Expand All @@ -325,21 +330,32 @@ async fn setup_dkg(
.try_into()
.map_err(|_| UserErr::AddressConversionError("Invalid Length".to_string()))?;
let sig_request_address = SubxtAccountId32(*address_slice);
let user_details =
get_registering_user_details(&api, &sig_request_address.clone(), rpc).await?;
let key_visibility = if sig_request_account == NETWORK_PARENT_KEY.encode() {
KeyVisibility::Public
} else {
let user_details =
get_registering_user_details(&api, &sig_request_address.clone(), rpc).await?;
user_details.key_visibility.0
};

let key_share = do_dkg(
&data.validators_info,
&signer,
x25519_secret_key,
&app_state.listener_state,
sig_request_address.clone(),
*user_details.key_visibility,
key_visibility,
data.block_number,
)
.await?;
let verifying_key = key_share.verifying_key().to_encoded_point(true).as_bytes().to_vec();
let string_verifying_key = hex::encode(verifying_key.clone()).to_string();
let string_verifying_key = if sig_request_account == NETWORK_PARENT_KEY.encode() {
hex::encode(*NETWORK_PARENT_KEY)
} else {
hex::encode(verifying_key.clone())
}
.to_string();

let serialized_key_share = key_serialize(&key_share)
.map_err(|_| UserErr::KvSerialize("Kv Serialize Error".to_string()))?;

Expand Down Expand Up @@ -505,12 +521,19 @@ pub async fn confirm_registered(
// TODO fire and forget, or wait for in block maybe Ddos error
// TODO: Understand this better, potentially use sign_and_submit_default
// or other method under sign_and_*
let registration_tx = entropy::tx().registry().confirm_register(
who,
subgroup,
entropy::runtime_types::bounded_collections::bounded_vec::BoundedVec(verifying_key),
);
submit_transaction(api, rpc, signer, &registration_tx, Some(nonce)).await?;

if who.encode() == NETWORK_PARENT_KEY.encode() {
let jump_start_request = entropy::tx().registry().confirm_jump_start(subgroup);
submit_transaction(api, rpc, signer, &jump_start_request, Some(nonce)).await?;
} else {
let confirm_register_request = entropy::tx().registry().confirm_register(
who,
subgroup,
entropy::runtime_types::bounded_collections::bounded_vec::BoundedVec(verifying_key),
);
submit_transaction(api, rpc, signer, &confirm_register_request, Some(nonce)).await?;
}

Ok(())
}

Expand Down
2 changes: 2 additions & 0 deletions crates/threshold-signature-server/src/user/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ pub enum UserErr {
EncryptionOrAuthentication(#[from] EncryptedSignedMessageErr),
#[error("Custom hash choice out of bounds")]
CustomHashOutOfBounds,
#[error("No signing from parent key")]
NoSigningFromParentKey,
#[error("Listener: {0}")]
Listener(#[from] entropy_protocol::errors::ListenerErr),
#[error("Error creating sr25519 keypair from seed: {0}")]
Expand Down
100 changes: 100 additions & 0 deletions crates/threshold-signature-server/src/user/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use entropy_protocol::{
use entropy_shared::{
HashingAlgorithm, KeyVisibility, OcwMessageDkg, DAVE_VERIFYING_KEY, DEFAULT_VERIFYING_KEY,
DEFAULT_VERIFYING_KEY_NOT_REGISTERED, DEVICE_KEY_HASH, EVE_VERIFYING_KEY, FERDIE_VERIFYING_KEY,
NETWORK_PARENT_KEY,
};
use entropy_testing_utils::{
chain_api::{
Expand Down Expand Up @@ -362,6 +363,18 @@ async fn test_sign_tx_no_chain() {
for res in test_user_custom_hash_out_of_bounds {
assert_eq!(res.unwrap().text().await.unwrap(), "Custom hash choice out of bounds");
}

generic_msg.block_number = rpc.chain_get_header(None).await.unwrap().unwrap().number;
generic_msg.signature_verifying_key = NETWORK_PARENT_KEY.0.to_vec();
let test_user_sign_with_parent_key = submit_transaction_requests(
vec![validator_ips_and_keys[1].clone()],
generic_msg.clone(),
one,
)
.await;
for res in test_user_sign_with_parent_key {
assert_eq!(res.unwrap().text().await.unwrap(), "No signing from parent key");
}
clean_tests();
}

Expand Down Expand Up @@ -774,6 +787,81 @@ async fn test_store_share() {
clean_tests();
}

#[tokio::test]
#[serial]
async fn test_jumpstart_network() {
initialize_test_logger().await;
clean_tests();

let alice = AccountKeyring::Alice;

let cxt = test_context_stationary().await;
let (_validator_ips, _validator_ids, _) =
spawn_testing_validators(Some(DEFAULT_VERIFYING_KEY.to_vec()), false, false).await;
let api = get_api(&cxt.node_proc.ws_url).await.unwrap();
let rpc = get_rpc(&cxt.node_proc.ws_url).await.unwrap();

let client = reqwest::Client::new();

let block_number = rpc.chain_get_header(None).await.unwrap().unwrap().number + 1;
let validators_info = vec![
entropy_shared::ValidatorInfo {
ip_address: b"127.0.0.1:3001".to_vec(),
x25519_public_key: X25519_PUBLIC_KEYS[0],
tss_account: TSS_ACCOUNTS[0].clone().encode(),
},
entropy_shared::ValidatorInfo {
ip_address: b"127.0.0.1:3002".to_vec(),
x25519_public_key: X25519_PUBLIC_KEYS[1],
tss_account: TSS_ACCOUNTS[1].clone().encode(),
},
];
let onchain_user_request = OcwMessageDkg {
sig_request_accounts: vec![H256::zero().encode()],
block_number,
validators_info,
};

put_jumpstart_request_on_chain(&api, &rpc, &alice).await;

run_to_block(&rpc, block_number + 1).await;

// succeeds
let user_registration_response = client
.post("http://127.0.0.1:3002/user/new")
.body(onchain_user_request.clone().encode())
.send()
.await
.unwrap();

assert_eq!(user_registration_response.text().await.unwrap(), "");
// wait for jump start event check that key exists in kvdb
for _ in 0..45 {
std::thread::sleep(std::time::Duration::from_millis(1000));
let block_hash = rpc.chain_get_block_hash(None).await.unwrap();
let events = EventsClient::new(api.clone()).at(block_hash.unwrap()).await.unwrap();
let jump_start_event = events.find::<entropy::registry::events::FinishedNetworkJumpStart>();
for _event in jump_start_event.flatten() {
break;
}
}

let get_query = UnsafeQuery::new(hex::encode(H256::zero()), [].to_vec()).to_json();
// check get key before registration to see if key gets replaced
let response_key = client
.post("http://127.0.0.1:3001/unsafe/get")
.header("Content-Type", "application/json")
.body(get_query.clone())
.send()
.await
.unwrap();
// check to make sure keyshare is correct
let key_share: Option<KeyShare<KeyParams>> =
entropy_kvdb::kv_manager::helpers::deserialize(&response_key.bytes().await.unwrap());
assert_eq!(key_share.is_some(), true);
clean_tests();
}

#[tokio::test]
#[serial]
async fn test_return_addresses_of_subgroup() {
Expand Down Expand Up @@ -1053,6 +1141,18 @@ pub async fn put_register_request_on_chain(
submit_transaction(api, rpc, &sig_req_account, &registering_tx, None).await.unwrap();
}

pub async fn put_jumpstart_request_on_chain(
api: &OnlineClient<EntropyConfig>,
rpc: &LegacyRpcMethods<EntropyConfig>,
sig_req_keyring: &Sr25519Keyring,
) {
let sig_req_account =
PairSigner::<EntropyConfig, sp_core::sr25519::Pair>::new(sig_req_keyring.pair());

let registering_tx = entropy::tx().registry().jump_start_network();
submit_transaction(api, rpc, &sig_req_account, &registering_tx, None).await.unwrap();
}

#[tokio::test]
#[serial]
async fn test_sign_tx_user_participates() {
Expand Down
61 changes: 61 additions & 0 deletions pallets/registry/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,67 @@ pub fn add_non_syncing_validators<T: Config>(
}

benchmarks! {
jump_start_network {

let sig_req_account: T::AccountId = whitelisted_caller();
let balance = <T as pallet_staking_extension::Config>::Currency::minimum_balance() * 100u32.into();
let _ = <T as pallet_staking_extension::Config>::Currency::make_free_balance_be(&sig_req_account, balance);

}: _(RawOrigin::Signed(sig_req_account.clone()))
verify {
assert_last_event::<T>(Event::StartedNetworkJumpStart().into());
}

confirm_jump_start_done {
let c in 0 .. SIG_PARTIES as u32;
let sig_req_account: T::AccountId = whitelisted_caller();
let validator_account: T::AccountId = whitelisted_caller();
let threshold_account: T::AccountId = whitelisted_caller();

let sig_party_size = MaxValidators::<T>::get() / SIG_PARTIES as u32;
// add validators and a registering user
for i in 0..SIG_PARTIES {
let validators = add_non_syncing_validators::<T>(sig_party_size, 0, i as u8);
<ThresholdToStash<T>>::insert(&threshold_account, &validators[i]);
}
<JumpStartProgress<T>>::put(JumpStartDetails {
jump_start_status: JumpStartStatus::InProgress(0),
confirmations: vec![1],
});


let balance = <T as pallet_staking_extension::Config>::Currency::minimum_balance() * 100u32.into();
let _ = <T as pallet_staking_extension::Config>::Currency::make_free_balance_be(&threshold_account, balance);
}: confirm_jump_start(RawOrigin::Signed(threshold_account), 0)
verify {
assert_last_event::<T>(Event::<T>::FinishedNetworkJumpStart().into());
}

confirm_jump_start_confirm {
let c in 0 .. SIG_PARTIES as u32;
let sig_req_account: T::AccountId = whitelisted_caller();
let validator_account: T::AccountId = whitelisted_caller();
let threshold_account: T::AccountId = whitelisted_caller();

let sig_party_size = MaxValidators::<T>::get() / SIG_PARTIES as u32;
// add validators and a registering user
for i in 0..SIG_PARTIES {
let validators = add_non_syncing_validators::<T>(sig_party_size, 0, i as u8);
<ThresholdToStash<T>>::insert(&threshold_account, &validators[i]);
}
<JumpStartProgress<T>>::put(JumpStartDetails {
jump_start_status: JumpStartStatus::InProgress(0),
confirmations: vec![],
});


let balance = <T as pallet_staking_extension::Config>::Currency::minimum_balance() * 100u32.into();
let _ = <T as pallet_staking_extension::Config>::Currency::make_free_balance_be(&threshold_account, balance);
}: confirm_jump_start(RawOrigin::Signed(threshold_account), 0)
verify {
assert_last_event::<T>(Event::<T>::JumpStartConfirmation(0).into());
}

register {
let p in 1 .. T::MaxProgramHashes::get();
let program = vec![0u8];
Expand Down
Loading

0 comments on commit 314849f

Please sign in to comment.