fix: fix tests and add Makefile
This commit is contained in:
parent
85a15edaec
commit
19f46d6edb
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
|
# 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
|
## Crate Overview
|
||||||
|
|
||||||
- **kvstore/**: Async key-value store trait and implementations (native: `sled`, WASM: IndexedDB).
|
- **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.
|
- **vault/**: Cryptographic vault for encrypted keyspaces, key management, and signing; uses `kvstore` for persistence
|
||||||
- **evm_client/**: EVM RPC client, integrates with `vault` for signing and secure key management.
|
- **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 and automation.
|
- **cli_app/** _(planned)_: Command-line interface for scripting, automation, and Rhai scripting
|
||||||
- **web_app/**: (Planned) WASM web app exposing the same APIs to JavaScript or browser 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
|
## Architecture Highlights
|
||||||
- **Async everywhere:** All APIs are async and runtime-agnostic.
|
- **Modular and async:** All APIs are async and runtime-agnostic (works with both native and WASM targets)
|
||||||
- **Conditional backends:** Uses Cargo features and `cfg` to select the appropriate backend for each environment.
|
- **Conditional backends:** Uses Cargo features and `cfg` for platform-specific storage/networking
|
||||||
- **Secure by design:** Vault encrypts all key material at rest and leverages modern cryptography.
|
- **Secure by design:** Vault encrypts all key material at rest using modern cryptography
|
||||||
- **Tested natively and in browser:** WASM and native backends are both covered by tests.
|
- **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
|
## Building and Testing
|
||||||
|
|
||||||
### Prerequisites
|
### 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)
|
- Rust (latest stable recommended)
|
||||||
- For WASM: `wasm-pack`, Firefox or Chrome (for browser tests)
|
- For WASM: `wasm-pack`, Firefox or Chrome (for browser tests)
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@ k256 = { version = "0.13", features = ["ecdsa"] }
|
|||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
wasm-bindgen-test = "0.3"
|
wasm-bindgen-test = "0.3"
|
||||||
web-sys = { version = "0.3", features = ["console"] }
|
web-sys = { version = "0.3", features = ["console"] }
|
||||||
|
tempfile = "3"
|
||||||
|
kvstore = { path = "../kvstore" }
|
||||||
|
|
||||||
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
|
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
|
||||||
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
|
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
|
||||||
|
@ -1,7 +1,47 @@
|
|||||||
use evm_client::provider::Transaction;
|
use evm_client::provider::Transaction;
|
||||||
use evm_client::provider::{parse_signature_rs_v, get_balance};
|
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::{Address, U256};
|
||||||
use ethers_core::types::{U256, Address, Bytes};
|
|
||||||
|
#[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]
|
#[test]
|
||||||
fn test_rlp_encode_unsigned() {
|
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");
|
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]
|
#[wasm_bindgen_test]
|
||||||
fn test_parse_signature_rs_v() {
|
fn test_parse_signature_rs_v() {
|
||||||
let mut sig = [0u8; 65];
|
let mut sig = [0u8; 65];
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//! WASM integration test for SessionManager using kvstore::WasmStore
|
//! WASM integration test for SessionManager using kvstore::WasmStore
|
||||||
|
|
||||||
use vault::Vault;
|
|
||||||
|
use vault::{Vault, KeyType, KeyMetadata, SessionManager};
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use kvstore::WasmStore;
|
use kvstore::WasmStore;
|
||||||
use wasm_bindgen_test::*;
|
use wasm_bindgen_test::*;
|
||||||
|
Loading…
Reference in New Issue
Block a user