diff --git a/Cargo.lock b/Cargo.lock index cdbccf5..3d9ed9b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -385,22 +385,10 @@ version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f542548a609dca89fcd72b3b9f355928cf844d4363c5eed9c5273a3dd225e097" dependencies = [ - "alloy-rlp-derive", "arrayvec", "bytes", ] -[[package]] -name = "alloy-rlp-derive" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a833d97bf8a5f0f878daf2c8451fff7de7f9de38baa5a45d936ec718d81255a" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - [[package]] name = "android-tzdata" version = "0.1.1" @@ -970,15 +958,6 @@ dependencies = [ "uuid 1.11.1", ] -[[package]] -name = "block-padding" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" -dependencies = [ - "generic-array", -] - [[package]] name = "brotli" version = "6.0.0" @@ -1322,6 +1301,16 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + [[package]] name = "const-hex" version = "1.14.0" @@ -1861,23 +1850,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "enr" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "972070166c68827e64bd1ebc8159dd8e32d9bc2da7ebe8f20b61308f7974ad30" -dependencies = [ - "alloy-rlp", - "base64 0.21.7", - "bytes", - "hex", - "log", - "rand", - "secp256k1", - "sha3", - "zeroize", -] - [[package]] name = "enum-ordinalize" version = "4.3.0" @@ -2208,7 +2180,7 @@ dependencies = [ "base64 0.21.7", "bytes", "const-hex", - "enr 0.10.0", + "enr", "ethers-core", "futures-core", "futures-timer", @@ -3252,7 +3224,6 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" dependencies = [ - "block-padding", "generic-array", ] @@ -3359,17 +3330,18 @@ dependencies = [ "ark-std 0.5.0", "async-trait", "bincode", + "cfg-if", "concat-kdf", "ctr", "hashbrown 0.15.2", "hmac", "intmax2-zkp", + "js-sys", "num-traits", "plonky2", "plonky2_bn254 0.1.0 (git+https://github.com/InternetMaximalism/plonky2_bn254)", "plonky2_keccak", "rand", - "reth-ecies", "serde", "serde_bytes", "serde_json", @@ -3379,6 +3351,32 @@ dependencies = [ "tokio", ] +[[package]] +name = "intmax2-wasm-lib" +version = "0.1.5" +dependencies = [ + "anyhow", + "console_error_panic_hook", + "ethers", + "getrandom", + "hex", + "intmax2-client-sdk", + "intmax2-interfaces", + "intmax2-zkp", + "log", + "num-bigint 0.4.6", + "plonky2", + "rand", + "reqwest 0.12.12", + "serde", + "serde_json", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test", + "wasm-logger", + "web-sys", +] + [[package]] name = "intmax2-zkp" version = "0.1.0" @@ -3717,6 +3715,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minicov" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27fe9f1cc3c22e1687f9446c2083c4c5fc7f0bcf1c7a86bdbded14985895b4b" +dependencies = [ + "cc", + "walkdir", +] + [[package]] name = "miniz_oxide" version = "0.8.2" @@ -4829,51 +4837,6 @@ dependencies = [ "windows-registry", ] -[[package]] -name = "reth-ecies" -version = "1.1.5" -source = "git+https://github.com/paradigmxyz/reth.git?rev=v1.1.5#3212af2d85a54eb207661361ac9fe1d7de4b5b8e" -dependencies = [ - "aes", - "alloy-primitives", - "alloy-rlp", - "block-padding", - "byteorder", - "cipher", - "concat-kdf", - "ctr", - "digest 0.10.7", - "futures", - "generic-array", - "hmac", - "pin-project", - "rand", - "reth-network-peers", - "secp256k1", - "sha2", - "sha3", - "thiserror 2.0.11", - "tokio", - "tokio-stream", - "tokio-util", - "tracing", - "typenum", -] - -[[package]] -name = "reth-network-peers" -version = "1.1.5" -source = "git+https://github.com/paradigmxyz/reth.git?rev=v1.1.5#3212af2d85a54eb207661361ac9fe1d7de4b5b8e" -dependencies = [ - "alloy-primitives", - "alloy-rlp", - "enr 0.12.1", - "secp256k1", - "serde_with", - "thiserror 2.0.11", - "url", -] - [[package]] name = "rfc6979" version = "0.4.0" @@ -5217,6 +5180,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" @@ -5259,25 +5228,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "secp256k1" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" -dependencies = [ - "rand", - "secp256k1-sys", -] - -[[package]] -name = "secp256k1-sys" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" -dependencies = [ - "cc", -] - [[package]] name = "security-framework" version = "2.11.1" @@ -6960,6 +6910,8 @@ checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if", "once_cell", + "serde", + "serde_json", "wasm-bindgen-macro", ] @@ -7019,6 +6971,42 @@ version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" +[[package]] +name = "wasm-bindgen-test" +version = "0.3.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d44563646eb934577f2772656c7ad5e9c90fac78aa8013d776fcdaf24625d" +dependencies = [ + "js-sys", + "minicov", + "scoped-tls", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test-macro", +] + +[[package]] +name = "wasm-bindgen-test-macro" +version = "0.3.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54171416ce73aa0b9c377b51cc3cb542becee1cd678204812e8392e5b0e4a031" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "wasm-logger" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "074649a66bb306c8f2068c9016395fa65d8e08d2affcbf95acf3c24c3ab19718" +dependencies = [ + "log", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "web-sys" version = "0.3.76" diff --git a/Cargo.toml b/Cargo.toml index 384333d..a80ca21 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = [ "cli", "client-sdk", "interfaces", - # "wasm", + "wasm", "balance-prover", "store-vault-server", "validity-prover", diff --git a/interfaces/Cargo.toml b/interfaces/Cargo.toml index b8f3018..0ba6827 100644 --- a/interfaces/Cargo.toml +++ b/interfaces/Cargo.toml @@ -20,14 +20,17 @@ ark-ec = { workspace = true } ark-bn254 = { workspace = true } rand = "0.8.5" num-traits = "0.2.19" -reth-ecies = { package="reth-ecies", git = "https://github.com/paradigmxyz/reth.git", rev = "v1.1.5" } concat-kdf = "0.1.0" sha2 = "0.10.8" ark-ff = "0.5.0" hmac = "0.12.1" -alloy-primitives = "0.8.18" +alloy-primitives = { version = "0.8.18", features = ["rand"] } aes = "0.8.4" ctr = "0.9.2" ark-std = "0.5.0" serde_bytes = "0.11.15" serde_with = { version = "3.12.0", features = ["base64"] } +cfg-if = "1.0.0" + +[target.'cfg(target_arch = "wasm32")'.dependencies] +js-sys = "0.3" diff --git a/interfaces/src/data/encryption/algorithm.rs b/interfaces/src/data/encryption/algorithm.rs index bed4762..5f001d9 100644 --- a/interfaces/src/data/encryption/algorithm.rs +++ b/interfaces/src/data/encryption/algorithm.rs @@ -10,9 +10,9 @@ use intmax2_zkp::{ ethereum_types::{u256::U256, u32limb_trait::U32LimbTrait}, }; use rand::Rng; -use reth_ecies::ECIESError; use super::{ + errors::ECIESError, message::EncryptedMessage, utils::{ecdh_x, hmac_sha256, kdf, sha256, U256_SIZE}, }; diff --git a/interfaces/src/data/encryption/errors.rs b/interfaces/src/data/encryption/errors.rs new file mode 100644 index 0000000..2cfedfd --- /dev/null +++ b/interfaces/src/data/encryption/errors.rs @@ -0,0 +1,12 @@ +use thiserror::Error; + +/// An error that occurs while reading or writing to an ECIES stream. +#[derive(Debug, Error)] +pub enum ECIESError { + /// Error when checking the HMAC tag against the tag on the message being decrypted + #[error("tag check failure in read_header")] + TagCheckDecryptFailed, + /// The encrypted data is not large enough for all fields + #[error("encrypted data is not large enough for all fields")] + EncryptedDataTooSmall, +} diff --git a/interfaces/src/data/encryption/message.rs b/interfaces/src/data/encryption/message.rs index b9d801d..0a74c31 100644 --- a/interfaces/src/data/encryption/message.rs +++ b/interfaces/src/data/encryption/message.rs @@ -9,9 +9,23 @@ use alloy_primitives::{B128, B256}; use ark_bn254::Fr; use ctr::Ctr64BE; use intmax2_zkp::ethereum_types::{u256::U256, u32limb_trait::U32LimbTrait}; -use reth_ecies::{algorithm::RLPxSymmetricKeys, ECIESError, ECIESErrorImpl}; -use super::utils::{ecdh_x, hmac_sha256, kdf, sha256, U256_SIZE}; +use super::{ + errors::ECIESError, + utils::{ecdh_x, hmac_sha256, kdf, sha256, U256_SIZE}, +}; + +/// The symmetric keys derived from an ECIES message. +#[derive(Debug)] +pub struct RLPxSymmetricKeys { + /// The key used for decryption, specifically with AES-128 in CTR mode, using a 64-bit big + /// endian counter. + pub enc_key: B128, + + /// The key used for verifying message integrity, specifically with the NIST SP 800-56A Concat + /// KDF. + pub mac_key: B256, +} #[derive(Debug)] pub struct EncryptedMessage<'a> { @@ -38,7 +52,7 @@ impl<'a> EncryptedMessage<'a> { pub fn parse(data: &mut [u8]) -> Result, ECIESError> { // Auth data is 2 bytes, public key is 65 bytes if data.len() < U256_SIZE + 2 { - return Err(ECIESErrorImpl::EncryptedDataTooSmall.into()); + return Err(ECIESError::EncryptedDataTooSmall); } let (auth_data, encrypted) = data.split_at_mut(2); @@ -54,7 +68,7 @@ impl<'a> EncryptedMessage<'a> { let tag_index = encrypted .len() .checked_sub(32) - .ok_or(ECIESErrorImpl::EncryptedDataTooSmall)?; + .ok_or(ECIESError::EncryptedDataTooSmall)?; // NOTE: we've already checked that the encrypted data is long enough to contain the // encrypted data and tag @@ -66,7 +80,7 @@ impl<'a> EncryptedMessage<'a> { // now we can check if the encrypted data is long enough to contain the IV if data_iv.len() < 16 { - return Err(ECIESErrorImpl::EncryptedDataTooSmall.into()); + return Err(ECIESError::EncryptedDataTooSmall); } let (iv, encrypted_data) = data_iv.split_at_mut(16); @@ -142,7 +156,7 @@ impl<'a> EncryptedMessage<'a> { &self.auth_data, ); if check_tag != self.tag { - return Err(ECIESErrorImpl::TagCheckDecryptFailed.into()); + return Err(ECIESError::TagCheckDecryptFailed); } Ok(()) diff --git a/interfaces/src/data/encryption/mod.rs b/interfaces/src/data/encryption/mod.rs index d812c4a..098fa42 100644 --- a/interfaces/src/data/encryption/mod.rs +++ b/interfaces/src/data/encryption/mod.rs @@ -1,3 +1,4 @@ pub mod algorithm; +pub mod errors; pub mod message; pub mod utils; diff --git a/interfaces/src/utils/signature.rs b/interfaces/src/utils/signature.rs index 73fbfde..48d38a2 100644 --- a/interfaces/src/utils/signature.rs +++ b/interfaces/src/utils/signature.rs @@ -103,11 +103,22 @@ pub fn verify_signature(signature: FlatG2, pubkey: U256, hash: Bytes32) -> anyho Ok(()) } -fn current_time() -> u64 { - std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .unwrap() - .as_secs() +// WASM compatible time function +cfg_if::cfg_if! { + if #[cfg(target_arch = "wasm32")] { + use js_sys::Date; + + pub fn current_time() -> u64 { + (Date::now() / 1000.0) as u64 + } + } else { + pub fn current_time() -> u64 { + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_secs() + } + } } fn hash_to_message_point(hash: Bytes32) -> G2Affine { diff --git a/wasm/js-test/src/main.ts b/wasm/js-test/src/main.ts index 9a51c2f..22308b3 100644 --- a/wasm/js-test/src/main.ts +++ b/wasm/js-test/src/main.ts @@ -84,7 +84,7 @@ async function main() { const balance = await getEthBalance(ethKey, env.L1_RPC_URL); console.log("balance: ", balance); - const depositResult = await prepare_deposit(config, publicKey, amount, tokenType, tokenAddress, tokenId); + const depositResult = await prepare_deposit(config, ethAddress, publicKey, amount, tokenType, tokenAddress, tokenId); const pubkeySaltHash = depositResult.deposit_data.pubkey_salt_hash; console.log("pubkeySaltHash: ", pubkeySaltHash); diff --git a/wasm/src/js_types/data.rs b/wasm/src/js_types/data.rs index 28a9b09..6b89f45 100644 --- a/wasm/src/js_types/data.rs +++ b/wasm/src/js_types/data.rs @@ -3,15 +3,10 @@ use intmax2_interfaces::data::{ deposit_data::DepositData, transfer_data::TransferData, tx_data::TxData, user_data::UserData, }; use intmax2_zkp::ethereum_types::u32limb_trait::U32LimbTrait as _; -use plonky2::{field::goldilocks_field::GoldilocksField, plonk::config::PoseidonGoldilocksConfig}; use wasm_bindgen::prelude::wasm_bindgen; use super::common::{JsTransfer, JsTx}; -type F = GoldilocksField; -type C = PoseidonGoldilocksConfig; -const D: usize = 2; - #[derive(Debug, Clone)] #[wasm_bindgen(getter_with_clone)] pub struct JsDepositData { @@ -44,7 +39,7 @@ pub struct JsTransferData { } impl JsTransferData { - pub fn from_transfer_data(transfer_data: &TransferData) -> Self { + pub fn from_transfer_data(transfer_data: &TransferData) -> Self { Self { sender: transfer_data.sender.to_hex(), transfer: JsTransfer::from_transfer(&transfer_data.transfer), @@ -60,8 +55,8 @@ pub struct JsTxData { } impl JsTxData { - pub fn from_tx_data(tx_data: &TxData) -> Self { - let tx = JsTx::from_tx(&tx_data.common.tx); + pub fn from_tx_data(tx_data: &TxData) -> Self { + let tx = JsTx::from_tx(&tx_data.spent_witness.tx); let transfers = tx_data .spent_witness .transfers @@ -92,8 +87,6 @@ impl JsDepositResult { #[wasm_bindgen(getter_with_clone)] pub struct JsTxResult { pub tx_tree_root: String, - pub transfer_data_vec: Vec, - pub withdrawal_data_vec: Vec, pub transfer_uuids: Vec, pub withdrawal_uuids: Vec, } @@ -101,21 +94,8 @@ pub struct JsTxResult { impl JsTxResult { pub fn from_tx_result(tx_result: &TxResult) -> Self { let tx_tree_root = tx_result.tx_tree_root.to_hex(); - let transfer_data_vec = tx_result - .transfer_data_vec - .iter() - .map(JsTransferData::from_transfer_data) - .collect::>(); - let withdrawal_data_vec = tx_result - .withdrawal_data_vec - .iter() - .map(JsTransferData::from_transfer_data) - .collect::>(); - Self { tx_tree_root, - transfer_data_vec, - withdrawal_data_vec, transfer_uuids: tx_result.transfer_uuids.clone(), withdrawal_uuids: tx_result.withdrawal_uuids.clone(), } @@ -128,9 +108,6 @@ pub struct JsUserData { /// The user public key pub pubkey: String, - /// The block number of the user data - pub block_number: u32, - /// The token balances of the user pub balances: Vec, @@ -195,7 +172,6 @@ impl JsUserData { Self { pubkey: user_data.pubkey.to_hex(), - block_number: user_data.block_number, balances, private_commitment: user_data .full_private_state diff --git a/wasm/src/lib.rs b/wasm/src/lib.rs index e597d7d..c1a90d9 100644 --- a/wasm/src/lib.rs +++ b/wasm/src/lib.rs @@ -222,7 +222,7 @@ pub async fn get_user_data(config: &Config, private_key: &str) -> Result