From fe641cfb52a61d79cfb5e82a77154966f98f0749 Mon Sep 17 00:00:00 2001 From: driemworks Date: Thu, 24 Oct 2024 09:06:56 -0500 Subject: [PATCH] feat: move idn_connect, fix feature gating --- Cargo.lock | 1 - core/src/murmur.rs | 8 ++++-- lib/Cargo.toml | 1 - lib/src/bin/murmur/main.rs | 46 ++++++++++++++++++++++++----- lib/src/lib.rs | 59 +++++++++++--------------------------- 5 files changed, 61 insertions(+), 54 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 140e30f..35c7d29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2610,7 +2610,6 @@ dependencies = [ "ark-std", "ckb-merkle-mountain-range", "clap", - "hkdf", "murmur-core", "murmur-test-utils", "parity-scale-codec", diff --git a/core/src/murmur.rs b/core/src/murmur.rs index 55fa094..e37dd7c 100644 --- a/core/src/murmur.rs +++ b/core/src/murmur.rs @@ -243,6 +243,7 @@ impl MurmurStore { /// * `seed`: The value written to the transcript /// * `rng`: A CSPRNG /// +#[cfg(feature = "client")] fn generate_witness(mut seed: Vec, mut rng: R) -> [u8; 32] { let mut transcript = Transcript::new_labeled(MURMUR_PROTO); transcript.write_bytes(&seed); @@ -259,6 +260,7 @@ fn generate_witness(mut seed: Vec, mut rng: R) - /// * `message`: The message to be timelock encrypted /// * `rng`: A CSPRNG /// +#[cfg(feature = "client")] fn timelock_encrypt( identity: Identity, pk: E::PublicKeyGroup, @@ -335,17 +337,19 @@ pub mod verifier { /// * `nonce`: A nonce value /// pub fn verify_update( - serialized_proof: Vec, + serialized_proof: Vec, serialized_pubkey: Vec, nonce: u64, ) -> Result { // build transcript let mut transcript = Transcript::new_labeled(MURMUR_PROTO); transcript.write_bytes(&nonce.to_be_bytes()); - // deserialize proof and pubkey + + // deserialize proof and pubkey let proof = ThinVrfProof::<::Affine>:: deserialize_compressed(&mut &serialized_proof[..]) .map_err(|_| VerificationError::UnserializableProof)?; + let pk = PublicKey::<::Affine>:: deserialize_compressed(&mut &serialized_pubkey[..]) .map_err(|_| VerificationError::UnserializablePubkey)?; diff --git a/lib/Cargo.toml b/lib/Cargo.toml index ee2b399..80ffe1f 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -45,7 +45,6 @@ ark-serialize = "0.4.0" w3f-bls = "0.1.3" murmur-core = { path = "../core/", features = ["client"] } zeroize = "1.8.1" -hkdf = "0.12.4" [dev-dependencies] diff --git a/lib/src/bin/murmur/main.rs b/lib/src/bin/murmur/main.rs index b163d99..f6d9ad4 100644 --- a/lib/src/bin/murmur/main.rs +++ b/lib/src/bin/murmur/main.rs @@ -16,12 +16,16 @@ use clap::{Parser, Subcommand}; use murmur_lib::{ - create, etf, idn_connect, prepare_execute, BlockNumber, BoundedVec, MurmurStore, RuntimeCall, + create, etf, prepare_execute, BlockNumber, BoundedVec, MurmurStore, RuntimeCall, }; + use rand_core::{OsRng, SeedableRng}; use rand_chacha::ChaCha20Rng; use sp_core::crypto::Ss58Codec; use std::{fs::File, time::Instant}; +use subxt::{ + backend::rpc::RpcClient, client::OnlineClient, config::SubstrateConfig, +}; use subxt_signer::sr25519::dev; use thiserror::Error; @@ -105,22 +109,21 @@ async fn main() -> Result<(), Box> { } // 2. create mmr - let create_data = create( + let mmr_store = create( args.seed.as_bytes().to_vec(), 0, schedule, round_pubkey_bytes, &mut rng, - ) - .map_err(|_| CLIError::MurmurCreationFailed)?; + ).map_err(|_| CLIError::MurmurCreationFailed)?; // 3. add to storage - write_mmr_store(create_data.mmr_store.clone(), MMR_STORE_FILEPATH); + write_mmr_store(mmr_store.clone(), MMR_STORE_FILEPATH); // 4. build the call let call = etf::tx().murmur().create( - create_data.root, - create_data.size, + mmr_store.root.0, + mmr_store.metadata.keys().len() as u64, BoundedVec(args.name.as_bytes().to_vec()), ); @@ -175,6 +178,35 @@ async fn main() -> Result<(), Box> { Ok(()) } +/// Async connection to the Ideal Network +/// if successful then fetch data +/// else error if unreachable +async fn idn_connect( +) -> Result<(OnlineClient, BlockNumber, Vec), Box> { + println!("🎲 Connecting to Ideal network (local node)"); + let ws_url = std::env::var("WS_URL").unwrap_or_else(|_| { + let fallback_url = "ws://localhost:9944".to_string(); + println!("⚠️ WS_URL environment variable not set. Using fallback URL: {}", fallback_url); + fallback_url + }); + + let rpc_client = RpcClient::from_url(&ws_url).await?; + let client = OnlineClient::::from_rpc_client(rpc_client.clone()).await?; + println!("🔗 RPC Client: connection established"); + + // fetch the round public key from etf runtime storage + let round_key_query = subxt::dynamic::storage("Etf", "RoundPublic", ()); + let result = client.storage().at_latest().await?.fetch(&round_key_query).await?; + let round_pubkey_bytes = result.unwrap().as_type::>()?; + + println!("🔑 Successfully retrieved the round public key."); + + let current_block = client.blocks().at_latest().await?; + let current_block_number: BlockNumber = current_block.header().number; + println!("🧊 Current block number: #{:?}", current_block_number); + Ok((client, current_block_number, round_pubkey_bytes)) +} + /// read an MMR from a file fn load_mmr_store(path: &str) -> Result { let mmr_store_file = File::open(path).expect("Unable to open file"); diff --git a/lib/src/lib.rs b/lib/src/lib.rs index a66e986..53f2d9d 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -15,12 +15,8 @@ */ use beefy::{known_payloads, Commitment, Payload}; -use hkdf::Hkdf; use murmur_core::types::{Identity, IdentityBuilder}; use serde::Serialize; -use subxt::{ - backend::rpc::RpcClient, client::OnlineClient, config::SubstrateConfig, ext::codec::Encode, -}; use w3f_bls::{DoublePublicKey, SerializableToBytes, TinyBLS377}; use zeroize::Zeroize; @@ -32,6 +28,7 @@ pub use murmur_core::{ types::BlockNumber, }; use rand_chacha::ChaCha20Rng; +use subxt::ext::codec::Encode; // Generate an interface that we can use from the node's metadata. #[subxt::subxt(runtime_metadata_path = "artifacts/metadata.scale")] @@ -60,7 +57,12 @@ pub struct CreateData { pub root: Vec, /// The size of the MMR pub size: u64, + /// The murmur store (map of block nubmer to ciphertext) pub mmr_store: MurmurStore, + /// The serialized VRF public key + pub public_key_bytes: Vec, + /// The serialized Schnorr signature + pub proof_bytes: Vec, } #[derive(Serialize)] @@ -69,8 +71,11 @@ pub struct ProxyData { pub position: u64, /// The hash of the commitment pub hash: Vec, + /// The timelocked ciphertext pub ciphertext: Vec, + /// The Merkle proof items pub proof_items: Vec>, + /// The size of the Merkle proof pub size: u64, } @@ -85,7 +90,7 @@ pub fn create( block_schedule: Vec, round_pubkey_bytes: Vec, rng: &mut ChaCha20Rng, -) -> Result { +) -> Result { let round_pubkey = DoublePublicKey::::from_bytes(&round_pubkey_bytes) .map_err(|_| Error::InvalidPubkey)?; @@ -97,10 +102,7 @@ pub fn create( rng, )?; seed.zeroize(); - - let root = mmr_store.root.clone(); - - Ok(CreateData { root: root.0, size: mmr_store.metadata.len() as u64, mmr_store }) + Ok(mmr_store) } /// Return the data needed for the immediate execution of the proxied call. @@ -133,35 +135,6 @@ pub fn prepare_execute( Ok(ProxyData { position: pos, hash: commitment, ciphertext, proof_items, size }) } -/// Async connection to the Ideal Network -/// if successful then fetch data -/// else error if unreachable -pub async fn idn_connect( -) -> Result<(OnlineClient, BlockNumber, Vec), Box> { - println!("🎲 Connecting to Ideal network (local node)"); - let ws_url = std::env::var("WS_URL").unwrap_or_else(|_| { - let fallback_url = "ws://localhost:9944".to_string(); - println!("⚠️ WS_URL environment variable not set. Using fallback URL: {}", fallback_url); - fallback_url - }); - - let rpc_client = RpcClient::from_url(&ws_url).await?; - let client = OnlineClient::::from_rpc_client(rpc_client.clone()).await?; - println!("🔗 RPC Client: connection established"); - - // fetch the round public key from etf runtime storage - let round_key_query = subxt::dynamic::storage("Etf", "RoundPublic", ()); - let result = client.storage().at_latest().await?.fetch(&round_key_query).await?; - let round_pubkey_bytes = result.unwrap().as_type::>()?; - - println!("🔑 Successfully retrieved the round public key."); - - let current_block = client.blocks().at_latest().await?; - let current_block_number: BlockNumber = current_block.header().number; - println!("🧊 Current block number: #{:?}", current_block_number); - Ok((client, current_block_number, round_pubkey_bytes)) -} - #[cfg(test)] mod tests { use super::*; @@ -176,7 +149,7 @@ mod tests { let block_schedule = vec![1, 2, 3, 4, 5, 6, 7]; let double_public_bytes = murmur_test_utils::get_dummy_beacon_pubkey(); let mut rng = ChaCha20Rng::from_rng(&mut OsRng).unwrap(); - let create_data = + let mmr_store = create(seed.clone(), 0, block_schedule.clone(), double_public_bytes.clone(), &mut rng) .unwrap(); @@ -188,8 +161,8 @@ mod tests { // &mut rng, // ).unwrap(); - assert_eq!(create_data.mmr_store.root.0.len(), 32); - assert_eq!(create_data.size, 7); + assert_eq!(mmr_store.root.0.len(), 32); + assert_eq!(mmr_store.size, 7); } #[test] @@ -199,7 +172,7 @@ mod tests { let block_schedule = vec![1, 2, 3, 4, 5, 6, 7]; let double_public_bytes = murmur_test_utils::get_dummy_beacon_pubkey(); let mut rng = ChaCha20Rng::from_rng(&mut OsRng).unwrap(); - let create_data = create( + let mmr_store = create( seed.clone(), 0, block_schedule, @@ -234,7 +207,7 @@ mod tests { let proxy_data = prepare_execute( seed.clone(), when, - create_data.mmr_store.clone(), + mmr_store.clone(), &balance_transfer_call, &mut rng, )