fix: fix tests and add Makefile
This commit is contained in:
		
							
								
								
									
										23
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| # Makefile to run all browser (WASM) tests for kvstore, vault, and evm_client | ||||
|  | ||||
| BROWSER ?= firefox | ||||
|  | ||||
| .PHONY: test-browser-all test-browser-kvstore test-browser-vault test-browser-evm-client | ||||
|  | ||||
| test-browser-all: test-browser-kvstore test-browser-vault test-browser-evm-client | ||||
|  | ||||
| # Run browser tests for kvstore | ||||
|  | ||||
| test-browser-kvstore: | ||||
| 	cd kvstore && wasm-pack test --headless --$(BROWSER) | ||||
|  | ||||
| # Run browser tests for vault | ||||
|  | ||||
| test-browser-vault: | ||||
| 	cd vault && wasm-pack test --headless --$(BROWSER) | ||||
|  | ||||
| # Run browser tests for evm_client | ||||
|  | ||||
| test-browser-evm-client: | ||||
| 	cd evm_client && wasm-pack test --headless --$(BROWSER) | ||||
|  | ||||
							
								
								
									
										76
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										76
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,24 +1,80 @@ | ||||
| # Modular Rust System: Key-Value Store, Vault, and EVM Client | ||||
|  | ||||
| This repository implements a modular, async, and cross-platform cryptographic stack in Rust. It is designed for use in both native (desktop/server) and WASM (browser) environments, supporting secure storage, cryptographic operations, and EVM (Ethereum) client functionality. | ||||
| A modular, async, and cross-platform cryptographic stack in Rust. Built for both native (desktop/server) and WASM (browser) environments, this system provides secure storage, cryptographic operations, and Ethereum (EVM) client functionality—all with a focus on extensibility, testability, and scripting. | ||||
|  | ||||
| ## Crate Overview | ||||
|  | ||||
| - **kvstore/**: Async key-value store trait and implementations (native: `sled`, WASM: IndexedDB). | ||||
| - **vault/**: Cryptographic vault for managing encrypted keyspaces and key operations. Uses `kvstore` for persistence. | ||||
| - **evm_client/**: EVM RPC client, integrates with `vault` for signing and secure key management. | ||||
| - **cli_app/**: (Planned) Command-line interface for scripting and automation. | ||||
| - **web_app/**: (Planned) WASM web app exposing the same APIs to JavaScript or browser scripting. | ||||
| - **kvstore/**: Async key-value store trait and implementations (native: `sled`, WASM: IndexedDB) | ||||
| - **vault/**: Cryptographic vault for encrypted keyspaces, key management, and signing; uses `kvstore` for persistence | ||||
| - **evm_client/**: Async EVM RPC client, integrates with `vault` for secure signing; supports trait-based signers and modular providers | ||||
| - **cli_app/** _(planned)_: Command-line interface for scripting, automation, and Rhai scripting | ||||
| - **web_app/** _(planned)_: WASM web app exposing APIs to JavaScript/browser scripting | ||||
| - **wasm/** _(planned)_: WebAssembly module for browser/extension integration | ||||
| - **browser_extension/** _(planned)_: Browser extension for secure scripting and automation | ||||
| - **rhai scripting** _(planned)_: Unified scripting API for both CLI and browser (see [`docs/rhai_architecture_plan.md`](docs/rhai_architecture_plan.md)) | ||||
|  | ||||
| ## Directory Structure | ||||
| > **Note:** Some directories are planned for future extensibility and scripting, and may not exist yet in the current workspace. | ||||
|  | ||||
| ``` | ||||
| . | ||||
| ├── kvstore/            # Key-value store trait and backends | ||||
| ├── vault/              # Cryptographic vault (shared core) | ||||
| ├── evm_client/         # EVM RPC client (shared core) | ||||
| ├── cli_app/            # Command-line tool for Rhai scripts (planned) | ||||
| ├── web_app/            # WASM web app exposing APIs (planned) | ||||
| ├── wasm/               # WebAssembly module for browser/extension (planned) | ||||
| ├── browser_extension/  # Extension source (planned) | ||||
| ├── docs/               # Architecture & usage docs | ||||
| └── README.md | ||||
| ``` | ||||
|  | ||||
| ## Architecture Highlights | ||||
| - **Async everywhere:** All APIs are async and runtime-agnostic. | ||||
| - **Conditional backends:** Uses Cargo features and `cfg` to select the appropriate backend for each environment. | ||||
| - **Secure by design:** Vault encrypts all key material at rest and leverages modern cryptography. | ||||
| - **Tested natively and in browser:** WASM and native backends are both covered by tests. | ||||
| - **Modular and async:** All APIs are async and runtime-agnostic (works with both native and WASM targets) | ||||
| - **Conditional backends:** Uses Cargo features and `cfg` for platform-specific storage/networking | ||||
| - **Secure by design:** Vault encrypts all key material at rest using modern cryptography | ||||
| - **Extensible:** Trait-based APIs for signers and providers, ready for scripting and new integrations | ||||
| - **Tested everywhere:** Native and browser (WASM) backends are covered by automated tests and a unified Makefile | ||||
|  | ||||
| ## Building and Testing | ||||
|  | ||||
| ### Prerequisites | ||||
| - Rust (latest stable recommended) | ||||
| - wasm-pack (for browser tests) | ||||
| - Firefox or Chrome (for browser testing) | ||||
|  | ||||
| ### Native Build & Test | ||||
| ```sh | ||||
| cargo build | ||||
| cargo test | ||||
| ``` | ||||
|  | ||||
| ### Browser (WASM) Tests | ||||
| Run all browser tests for all modules: | ||||
| ```sh | ||||
| make test-browser-all | ||||
| ``` | ||||
| Or run for a specific module: | ||||
| ```sh | ||||
| make test-browser-kvstore | ||||
| make test-browser-vault | ||||
| make test-browser-evm-client | ||||
| ``` | ||||
| Set `BROWSER=chrome` to use Chrome instead of Firefox. | ||||
|  | ||||
| ## Scripting & Extensibility | ||||
| - **Rhai scripting**: The architecture is ready for ergonomic scripting via Rhai, both in CLI and browser (see [`docs/rhai_architecture_plan.md`](docs/rhai_architecture_plan.md)) | ||||
| - **Browser extension**: Planned support for browser extension scripting and secure key usage | ||||
|  | ||||
| ## Documentation | ||||
| - [Architecture Overview](docs/architecture.md) | ||||
| - [EVM Client Plan](docs/evm_client_architecture_plan.md) | ||||
| - [Rhai Scripting Plan](docs/rhai_architecture_plan.md) | ||||
|  | ||||
| --- | ||||
|  | ||||
| For questions, contributions, or more details, see the architecture docs or open an issue! | ||||
|  | ||||
| - Rust (latest stable recommended) | ||||
| - For WASM: `wasm-pack`, Firefox or Chrome (for browser tests) | ||||
|  | ||||
|   | ||||
| @@ -25,6 +25,8 @@ k256 = { version = "0.13", features = ["ecdsa"] } | ||||
| [dev-dependencies] | ||||
| wasm-bindgen-test = "0.3" | ||||
| web-sys = { version = "0.3", features = ["console"] } | ||||
| tempfile = "3" | ||||
| kvstore = { path = "../kvstore" } | ||||
|  | ||||
| [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] | ||||
| tokio = { version = "1", features = ["macros", "rt-multi-thread"] } | ||||
|   | ||||
| @@ -1,7 +1,47 @@ | ||||
| use evm_client::provider::Transaction; | ||||
| use evm_client::provider::{parse_signature_rs_v, get_balance}; | ||||
| // All native (non-WASM) balance and signature tests are in this file. | ||||
| use ethers_core::types::{U256, Address, Bytes}; | ||||
| use ethers_core::types::{Address, U256}; | ||||
|  | ||||
| #[cfg(not(target_arch = "wasm32"))] | ||||
| mod native_tests { | ||||
|     use super::*; | ||||
|     use vault::{SessionManager, KeyType}; | ||||
|     use tempfile::TempDir; | ||||
|     use kvstore::native::NativeStore; | ||||
|     use alloy_primitives::keccak256; | ||||
|  | ||||
|     #[tokio::test] | ||||
|     async fn test_vault_sessionmanager_balance_for_new_keypair() { | ||||
|         let tmp_dir = TempDir::new().expect("create temp dir"); | ||||
|         let store = NativeStore::open(tmp_dir.path().to_str().unwrap()).expect("Failed to open native store"); | ||||
|         let mut vault = vault::Vault::new(store.clone()); | ||||
|         let keyspace = "testspace"; | ||||
|         let password = b"testpass"; | ||||
|         // 1. Create keyspace | ||||
|         vault.create_keyspace(keyspace, password, None).await.expect("create keyspace"); | ||||
|         // 2. Add secp256k1 keypair | ||||
|         let key_id = vault.add_keypair(keyspace, password, Some(KeyType::Secp256k1), None).await.expect("add keypair"); | ||||
|         // 3. Create SessionManager and unlock keyspace | ||||
|         let mut session = SessionManager::new(vault); | ||||
|         session.unlock_keyspace(keyspace, password).await.expect("unlock keyspace"); | ||||
|         session.select_keyspace(keyspace).expect("select keyspace"); | ||||
|         session.select_keypair(&key_id).expect("select keypair"); | ||||
|         let kp = session.current_keypair().expect("current keypair"); | ||||
|         // 4. Derive Ethereum address from public key (same as in evm_client) | ||||
|         let pubkey = &kp.public_key; | ||||
|         // Remove leading 0x04 if present (uncompressed SEC1) | ||||
|         let pubkey = if pubkey.len() == 65 && pubkey[0] == 0x04 { &pubkey[1..] } else { pubkey.as_slice() }; | ||||
|         let hash = keccak256(pubkey); | ||||
|         let address = Address::from_slice(&hash[12..]); | ||||
|         // 5. Query balance | ||||
|         let url = "https://ethereum.blockpi.network/v1/rpc/public"; | ||||
|         let balance = get_balance(url, address).await.expect("Failed to get balance"); | ||||
|         assert_eq!(balance, ethers_core::types::U256::zero(), "New keypair should have zero balance"); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| use ethers_core::types::Bytes; | ||||
|  | ||||
| #[test] | ||||
| fn test_rlp_encode_unsigned() { | ||||
|   | ||||
| @@ -34,6 +34,39 @@ pub async fn test_get_balance_real_address_wasm_unique() { | ||||
|     assert!(balance > U256::zero(), "Vitalik's balance should be greater than zero"); | ||||
| } | ||||
|  | ||||
| #[wasm_bindgen_test(async)] | ||||
| pub async fn test_vault_sessionmanager_balance_for_new_keypair_wasm() { | ||||
|     use vault::{SessionManager, KeyType}; | ||||
|     use ethers_core::types::Address; | ||||
|     use evm_client::provider::get_balance; | ||||
|     use alloy_primitives::keccak256; | ||||
|     web_sys::console::log_1(&"WASM vault-session balance test running!".into()); | ||||
|     let store = kvstore::wasm::WasmStore::open("test-db").await.expect("open"); | ||||
|     let mut vault = vault::Vault::new(store); | ||||
|     let keyspace = "testspace-wasm"; | ||||
|     let password = b"testpass"; | ||||
|     // 1. Create keyspace | ||||
|     vault.create_keyspace(keyspace, password, None).await.expect("create keyspace"); | ||||
|     // 2. Add secp256k1 keypair | ||||
|     let key_id = vault.add_keypair(keyspace, password, Some(KeyType::Secp256k1), None).await.expect("add keypair"); | ||||
|     // 3. Create SessionManager and unlock keyspace | ||||
|     let mut session = SessionManager::new(vault); | ||||
|     session.unlock_keyspace(keyspace, password).await.expect("unlock keyspace"); | ||||
|     session.select_keyspace(keyspace).expect("select keyspace"); | ||||
|     session.select_keypair(&key_id).expect("select keypair"); | ||||
|     let kp = session.current_keypair().expect("current keypair"); | ||||
|     // 4. Derive Ethereum address from public key | ||||
|     let pubkey = &kp.public_key; | ||||
|     let pubkey = if pubkey.len() == 65 && pubkey[0] == 0x04 { &pubkey[1..] } else { pubkey.as_slice() }; | ||||
|     let hash = keccak256(pubkey); | ||||
|     let address = Address::from_slice(&hash[12..]); | ||||
|     // 5. Query balance | ||||
|     let url = "https://ethereum.blockpi.network/v1/rpc/public"; | ||||
|     let balance = get_balance(url, address).await.expect("Failed to get balance"); | ||||
|     web_sys::console::log_1(&format!("Balance: {balance:?}").into()); | ||||
|     assert_eq!(balance, ethers_core::types::U256::zero(), "New keypair should have zero balance"); | ||||
| } | ||||
|  | ||||
| #[wasm_bindgen_test] | ||||
| fn test_parse_signature_rs_v() { | ||||
|     let mut sig = [0u8; 65]; | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| //! WASM integration test for SessionManager using kvstore::WasmStore | ||||
|  | ||||
| use vault::Vault; | ||||
|  | ||||
| use vault::{Vault, KeyType, KeyMetadata, SessionManager}; | ||||
| #[cfg(target_arch = "wasm32")] | ||||
| use kvstore::WasmStore; | ||||
| use wasm_bindgen_test::*; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user