From 8ba60ccca0ba6bf2d799023ad8209ce1939d06ea Mon Sep 17 00:00:00 2001 From: Duddino Date: Sun, 27 Oct 2024 15:07:29 +0100 Subject: [PATCH] Add ability to use different URL than duddino.com for sapling params --- Cargo.lock | 8 ------- Cargo.toml | 2 -- js/pivx_shield.ts | 8 +++++-- src/lib.rs | 1 + src/prover.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++++ src/transaction.rs | 59 +++++---------------------------------------- 6 files changed, 73 insertions(+), 65 deletions(-) create mode 100644 src/prover.rs diff --git a/Cargo.lock b/Cargo.lock index 57ea7ac..e403fbb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,12 +77,6 @@ dependencies = [ "syn 2.0.79", ] -[[package]] -name = "async_once" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ce4f10ea3abcd6617873bae9f91d1c5332b4a778bd9ce34d0cd517474c1de82" - [[package]] name = "atomic-waker" version = "1.1.2" @@ -1382,14 +1376,12 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" name = "pivx-shield-rust" version = "1.1.6" dependencies = [ - "async_once", "atomic_float", "console_error_panic_hook", "either", "getrandom", "hex", "jubjub", - "lazy_static", "pivx_client_backend", "pivx_primitives", "pivx_proofs", diff --git a/Cargo.toml b/Cargo.toml index 6d5b1a7..099f413 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,8 +17,6 @@ multicore = ["pivx_proofs/multicore", "wasm-bindgen-rayon"] [dependencies] tokio = { version = "1.40.0", default-features = false, features = ["sync", "macros"] } rayon = "1.10.0" -lazy_static = "1.5.0" -async_once = "0.2.6" sha256 = { version = "1.5.0", default-features = false } getrandom = { version = "0.2.15", features = ["js"] } reqwest = { version = "0.12.0", features = ["blocking"] } diff --git a/js/pivx_shield.ts b/js/pivx_shield.ts index 18b5619..0766c31 100644 --- a/js/pivx_shield.ts +++ b/js/pivx_shield.ts @@ -542,8 +542,12 @@ export class PIVXShield { * But will be done lazily if note called explicitally. * @returns resolves when the sapling prover is loaded */ - async loadSaplingProver() { - return await this.callWorker("load_prover"); + async loadSaplingProver(url?: string) { + if (url) { + return await this.callWorker("load_prover_with_url", url); + } else { + return await this.callWorker("load_prover"); + } } /** diff --git a/src/lib.rs b/src/lib.rs index 8d93dc4..a81152d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ mod checkpoint; mod keys; mod mainnet_checkpoints; +mod prover; mod testnet_checkpoints; mod transaction; mod utils; diff --git a/src/prover.rs b/src/prover.rs new file mode 100644 index 0000000..8c7eeaf --- /dev/null +++ b/src/prover.rs @@ -0,0 +1,60 @@ +use pivx_proofs::prover::LocalTxProver; +use reqwest::Client; +use std::error::Error; +use tokio::sync::OnceCell; +use wasm_bindgen::prelude::*; + +static PROVER: OnceCell = OnceCell::const_new(); + +pub async fn get_prover() -> &'static LocalTxProver { + let default_urls = &["https://https://pivxla.bz", "https://duddino.com"]; + for url in default_urls { + if let Ok(prover) = get_with_url(url).await { + return prover; + } + } + panic!("Failed to download prover"); +} + +/** + * gets prover using the specified url. If the prover has already been downloaded + * no request will be made + */ +pub async fn get_with_url(url: &str) -> Result<&'static LocalTxProver, Box> { + PROVER + .get_or_try_init(|| async { + let c = Client::new(); + let out_url = format!("{}/sapling-output.params", url); + let spend_url = format!("{}/sapling-spend.params", url); + let sapling_output_bytes = c.get(&out_url).send().await?.bytes().await?; + let sapling_spend_bytes = c.get(&spend_url).send().await?.bytes().await?; + + if sha256::digest(&*sapling_output_bytes) + != "2f0ebbcbb9bb0bcffe95a397e7eba89c29eb4dde6191c339db88570e3f3fb0e4" + { + Err("Sha256 does not match for sapling output")?; + } + + if sha256::digest(&*sapling_spend_bytes) + != "8e48ffd23abb3a5fd9c5589204f32d9c31285a04b78096ba40a79b75677efc13" + { + Err("Sha256 does not match for sapling spend")?; + } + Ok(LocalTxProver::from_bytes( + &sapling_spend_bytes, + &sapling_output_bytes, + )) + }) + .await +} + +#[wasm_bindgen] +pub async fn load_prover() -> bool { + get_prover().await; + true +} + +#[wasm_bindgen] +pub async fn load_prover_with_url(url: &str) -> bool { + get_with_url(url).await.is_ok() +} diff --git a/src/transaction.rs b/src/transaction.rs index 9a50bb8..7b5f8ca 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -1,5 +1,6 @@ pub use crate::keys::decode_extended_full_viewing_key; pub use crate::keys::decode_extsk; +use crate::prover::get_prover; pub use pivx_client_backend::decrypt_transaction; pub use pivx_client_backend::keys::UnifiedFullViewingKey; use pivx_primitives::consensus::Network; @@ -13,11 +14,9 @@ pub use pivx_primitives::transaction::builder::Progress; use crate::keys::decode_generic_address; use crate::keys::GenericAddress; -use async_once::AsyncOnce; #[cfg(feature = "multicore")] use atomic_float::AtomicF32; pub use either::Either; -use lazy_static::lazy_static; pub use pivx_primitives::sapling::{note::Note, Node, Nullifier}; pub use pivx_primitives::transaction::builder::Builder; pub use pivx_primitives::transaction::components::Amount; @@ -30,7 +29,7 @@ pub use pivx_primitives::zip32::ExtendedSpendingKey; pub use pivx_primitives::zip32::Scope; pub use pivx_proofs::prover::LocalTxProver; use rand_core::OsRng; -pub use reqwest::Client; + use secp256k1::SecretKey; pub use serde::{Deserialize, Serialize}; use std::convert::TryInto; @@ -43,13 +42,6 @@ use tokio::{join, sync::mpsc::Receiver, sync::mpsc::Sender}; pub use wasm_bindgen::prelude::*; mod test; -lazy_static! { - static ref PROVER: AsyncOnce = AsyncOnce::new(async { - let (sapling_spend_bytes, sapling_output_bytes): (Vec, Vec) = - fetch_params().await.expect("Cannot fetch params"); - LocalTxProver::from_bytes(&sapling_spend_bytes, &sapling_output_bytes) - }); -} #[cfg(feature = "multicore")] static TX_PROGRESS_LOCK: AtomicF32 = AtomicF32::new(0.0); @@ -72,35 +64,7 @@ fn fee_calculator( + transparent_output_count * transparent_output_size + tx_offset_size) } -async fn fetch_params() -> Result<(Vec, Vec), Box> { - let c = Client::new(); - let sapling_output_bytes = c - .get("https://duddino.com/sapling-output.params") - .send() - .await? - .bytes() - .await?; - let sapling_spend_bytes = c - .get("https://duddino.com/sapling-spend.params") - .send() - .await? - .bytes() - .await?; - - if sha256::digest(&*sapling_output_bytes) - != "2f0ebbcbb9bb0bcffe95a397e7eba89c29eb4dde6191c339db88570e3f3fb0e4" - { - Err("Sha256 does not match for sapling output")?; - } - if sha256::digest(&*sapling_spend_bytes) - != "8e48ffd23abb3a5fd9c5589204f32d9c31285a04b78096ba40a79b75677efc13" - { - Err("Sha256 does not match for sapling spend")?; - } - - Ok((sapling_spend_bytes.to_vec(), sapling_output_bytes.to_vec())) -} #[wasm_bindgen] #[cfg(feature = "multicore")] pub fn read_tx_progress() -> f32 { @@ -117,11 +81,6 @@ pub fn read_tx_progress() -> f32 { pub fn set_tx_status(val: f32) { TX_PROGRESS_LOCK.store(val, Ordering::Relaxed); } -#[wasm_bindgen] -pub async fn load_prover() -> bool { - PROVER.get().await; - true -} #[derive(Serialize, Deserialize)] pub struct JSTxSaplingData { @@ -158,15 +117,9 @@ pub fn handle_transaction( }) .collect::>(); let mut new_comp_note: Vec<(Note, IncrementalWitness)> = vec![]; - let nullifiers = handle_transaction_internal( - &mut tree, - tx, - key, - true, - &mut comp_note, - &mut new_comp_note, - ) - .map_err(|_| "Cannot decode tx")?; + let nullifiers = + handle_transaction_internal(&mut tree, tx, key, true, &mut comp_note, &mut new_comp_note) + .map_err(|_| "Cannot decode tx")?; let ser_comp_note: Vec<(Note, String)> = serialize_comp_note(comp_note).map_err(|_| "Cannot serialize notes")?; let ser_new_comp_note: Vec<(Note, String)> = @@ -449,7 +402,7 @@ pub async fn create_transaction_internal( } } - let prover = PROVER.get().await; + let prover = get_prover().await; #[cfg(feature = "multicore")] { let (transmitter, mut receiver): (Sender, Receiver) =