diff --git a/Cargo.lock b/Cargo.lock index d3f89cb3d..b5fa3ff5a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2442,6 +2442,7 @@ dependencies = [ "entropy-shared", "futures", "hex", + "js-sys", "num", "rand_core 0.6.4", "reqwest 0.12.4", diff --git a/crates/client/Cargo.toml b/crates/client/Cargo.toml index 2074c138f..57bd8c837 100644 --- a/crates/client/Cargo.toml +++ b/crates/client/Cargo.toml @@ -25,14 +25,17 @@ blake2 ={ version="0.10.4", optional=true } rand_core ={ version="0.6.4", optional=true } serde_json ={ version="1.0", optional=true } x25519-dalek ={ version="2.0.1", features=["static_secrets"], optional=true } -entropy-protocol={ version="0.0.12", path="../protocol", optional=true } +entropy-protocol={ version="0.0.12", path="../protocol", optional=true, default-features=false } reqwest ={ version="0.12.4", features=["json", "stream"], optional=true } base64 ={ version="0.22.0", optional=true } synedrion ={ version="0.1", optional=true } hex ={ version="0.4.3", optional=true } +# Only for the browser +js-sys={ version="0.3.68", optional=true } + [features] -default=["native", "full-client"] +default=["native", "full-client-native"] native=[ "entropy-shared/std", "entropy-shared/user-native", @@ -55,3 +58,5 @@ full-client=[ "dep:synedrion", "dep:hex", ] +full-client-native=["full-client", "entropy-protocol/server"] +full-client-wasm=["full-client", "entropy-protocol/wasm", "dep:js-sys"] diff --git a/crates/client/src/client.rs b/crates/client/src/client.rs index 6f773e053..3f76f3d07 100644 --- a/crates/client/src/client.rs +++ b/crates/client/src/client.rs @@ -30,7 +30,7 @@ use crate::{ }, EntropyConfig, }, - substrate::{query_chain, submit_transaction}, + substrate::{query_chain, submit_transaction_with_pair}, user::{get_current_subgroup_signers, UserSignatureRequest}, Hasher, }; @@ -41,13 +41,12 @@ use entropy_protocol::{ RecoverableSignature, ValidatorInfo, }; use entropy_shared::HashingAlgorithm; -use futures::future; -use sp_core::{crypto::AccountId32, sr25519, Pair}; +use futures::{future, stream::StreamExt}; +use sp_core::{sr25519, Pair}; use std::time::SystemTime; use subxt::{ backend::legacy::LegacyRpcMethods, events::EventsClient, - tx::PairSigner, utils::{AccountId32 as SubxtAccountId32, Static, H256}, Config, OnlineClient, }; @@ -124,21 +123,22 @@ pub async fn register( _ => None, }; - let account_id32: AccountId32 = signature_request_keypair.public().into(); - let account_id: ::AccountId = account_id32.into(); + let account_id: ::AccountId = + SubxtAccountId32(signature_request_keypair.public().0); for _ in 0..50 { - let block_hash = rpc.chain_get_block_hash(None).await.unwrap(); - let events = EventsClient::new(api.clone()).at(block_hash.unwrap()).await.unwrap(); + let block_hash = rpc.chain_get_block_hash(None).await?; + let events = EventsClient::new(api.clone()) + .at(block_hash.ok_or(anyhow!("Cannot get block hash"))?) + .await?; let registered_event = events.find::(); for event in registered_event.flatten() { if event.0 == account_id { let registered_query = entropy::storage().registry().registered(&event.1); - let registered_status = - query_chain(api, rpc, registered_query, block_hash).await.unwrap(); - if registered_status.is_some() { + let registered_status = query_chain(api, rpc, registered_query, block_hash).await?; + if let Some(status) = registered_status { // check if the event belongs to this user - return Ok((registered_status.unwrap(), keyshare_option)); + return Ok((status, keyshare_option)); } } } @@ -176,7 +176,7 @@ pub async fn sign( message: hex::encode(message), auxilary_data: Some(vec![auxilary_data.map(hex::encode)]), validators_info: validators_info.clone(), - timestamp: SystemTime::now(), + timestamp: get_current_time(), hash: HashingAlgorithm::Keccak, signature_verifying_key: signature_verifying_key.to_vec(), }; @@ -229,10 +229,11 @@ pub async fn sign( // Get the first result if let Some(res) = results.into_iter().next() { - let mut output = res?; + let output = res?; ensure!(output.status() == 200, "Signing failed: {}", output.text().await?); - let chunk = output.chunk().await?.ok_or(anyhow!("No response"))?; + let mut bytes_stream = output.bytes_stream(); + let chunk = bytes_stream.next().await.ok_or(anyhow!("No response"))??; let signing_result: Result<(String, sr25519::Signature), String> = serde_json::from_slice(&chunk)?; let (signature_base64, signature_of_signature) = @@ -251,12 +252,14 @@ pub async fn sign( ); let recovery_digit = decoded_sig.pop().ok_or(anyhow!("Cannot get recovery digit"))?; - let signature = k256Signature::from_slice(&decoded_sig)?; + let signature = k256Signature::from_slice(&decoded_sig) + .map_err(|_| anyhow!("Cannot parse signature"))?; let recovery_id = RecoveryId::from_byte(recovery_digit).ok_or(anyhow!("Cannot create recovery id"))?; let verifying_key_of_signature = - VerifyingKey::recover_from_prehash(&message_hash, &signature, recovery_id)?; + VerifyingKey::recover_from_prehash(&message_hash, &signature, recovery_id) + .map_err(|e| anyhow!(e.to_string()))?; tracing::debug!("Verifying Key {:?}", verifying_key_of_signature); return Ok(RecoverableSignature { signature, recovery_id }); @@ -287,9 +290,8 @@ pub async fn store_program( auxiliary_data_interface, oracle_data_pointer, ); - let deployer = PairSigner::::new(deployer_pair.clone()); - - let in_block = submit_transaction(api, rpc, &deployer, &update_program_tx, None).await?; + let in_block = + submit_transaction_with_pair(api, rpc, deployer_pair, &update_program_tx, None).await?; let result_event = in_block.find_first::()?; Ok(result_event.ok_or(anyhow!("Error getting program created event"))?.program_hash) } @@ -305,8 +307,7 @@ pub async fn update_programs( let update_pointer_tx = entropy::tx() .registry() .change_program_instance(BoundedVec(verifying_key.to_vec()), program_instance); - let deployer = PairSigner::::new(deployer_pair.clone()); - submit_transaction(entropy_api, rpc, &deployer, &update_pointer_tx, None).await?; + submit_transaction_with_pair(entropy_api, rpc, deployer_pair, &update_pointer_tx, None).await?; Ok(()) } /// Get info on all registered accounts @@ -354,13 +355,11 @@ pub async fn put_register_request_on_chain( key_visibility: KeyVisibility, program_instance: BoundedVec, ) -> anyhow::Result<()> { - let signature_request_pair_signer = - PairSigner::::new(signature_request_keypair); - let registering_tx = entropy::tx().registry().register(deployer, Static(key_visibility), program_instance); - submit_transaction(api, rpc, &signature_request_pair_signer, ®istering_tx, None).await?; + submit_transaction_with_pair(api, rpc, &signature_request_keypair, ®istering_tx, None) + .await?; Ok(()) } @@ -437,3 +436,13 @@ async fn select_validator_from_subgroup( }; Ok(address.clone()) } + +#[cfg(feature = "full-client-wasm")] +fn get_current_time() -> SystemTime { + use std::time::{Duration, UNIX_EPOCH}; + UNIX_EPOCH + Duration::from_secs(js_sys::Date::now() as u64) +} +#[cfg(not(feature = "full-client-wasm"))] +fn get_current_time() -> SystemTime { + SystemTime::now() +} diff --git a/crates/threshold-signature-server/Cargo.toml b/crates/threshold-signature-server/Cargo.toml index d2c1a78de..ffbc4489f 100644 --- a/crates/threshold-signature-server/Cargo.toml +++ b/crates/threshold-signature-server/Cargo.toml @@ -81,7 +81,7 @@ entropy-protocol ={ version="0.0.12", path="../protocol", features=["unsafe" blake3 ="1.5.1" ethers-core ="2.0.14" schnorrkel ={ version="0.11.4", default-features=false, features=["std"] } -entropy-client ={ path="../client", features=["full-client"] } +entropy-client ={ path="../client", features=["full-client-native"] } schemars ={ version="0.8.17" } [build-dependencies]