Skip to content

Commit

Permalink
Merge pull request #2244 from b-zee/feat-autonomi-wasm-file-vault
Browse files Browse the repository at this point in the history
feat(autonomi): file/vault API in wasm
  • Loading branch information
b-zee authored Oct 17, 2024
2 parents 189aaa7 + 2e32497 commit 6c4ad11
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 42 deletions.
35 changes: 27 additions & 8 deletions autonomi/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,26 @@
<body>
<!-- credits: https://rustwasm.github.io/docs/wasm-bindgen/examples/without-a-bundler.html -->
<script type="module">
import init, { Client, getFundedWallet, logInit } from './pkg/autonomi.js';
import init, * as aut from './pkg/autonomi.js';

async function run() {
document.getElementById("btn-run").disabled = true;
const peer_addr = document.getElementById('peer_id').value;

await init();

logInit("sn_networking=debug,autonomi=trace");
aut.logInit("sn_networking=warn,autonomi=trace");

console.log("connecting...");
const client = await new Client([peer_addr]);
const client = await new aut.Client([peer_addr]);
console.log("connected");

console.log("getting wallet...");
const wallet = getFundedWallet();
const wallet = aut.getFundedWallet();
console.log("wallet retrieved");

const data = new Uint8Array([1, 2, 3]);
// Random 32 byte data
const data = [...Array(16)].map(() => Math.floor(Math.random() * 9));
console.log("our data: ", data);

console.log("calculating cost...");
Expand All @@ -33,10 +34,28 @@
console.log("putting...");
const dataAddr = await client.dataPut(data, wallet);
console.log("put done: ", dataAddr.toString());

let archive = new Map([["README.md", dataAddr]]);
console.log("putting data as archive... ", archive);
let archiveAddr = await client.archivePut(archive, wallet);
console.log("archive put done: ", archiveAddr);

console.log("getting...");
const data_get = await client.dataGet(dataAddr);
console.log("get done: ", data_get, " (original data: ", data, ")");
console.log("fetching archive...");
let archiveFetched = await client.archiveGet(archiveAddr);
console.log("archive fetched: ", archiveFetched);
for (const [path, addr] of archiveFetched) {
console.log("fetching data: ", path, ", addr: ", addr);
const dataFetched = await client.dataGet(addr);
console.log("data fetched: ", dataFetched);
}

// Generate random secret key
const secretKey = [...Array(32)].map(() => Math.floor(Math.random() * 9));

await client.writeBytesToVault(data, wallet, secretKey);

const vault = await client.fetchAndDecryptVault(secretKey);
console.log("vault: ", vault);
}

document.getElementById ("btn-run").addEventListener("click", run, false);
Expand Down
4 changes: 2 additions & 2 deletions autonomi/src/client/vault.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ impl Client {
/// Pays for a new VaultPacket if none yet created for the client. Returns the current version
/// of the data on success.
pub async fn write_bytes_to_vault(
&mut self,
&self,
data: Bytes,
wallet: &mut EvmWallet,
wallet: &EvmWallet,
secret_key: &SecretKey,
) -> Result<u64, PutError> {
let client_pk = secret_key.public_key();
Expand Down
128 changes: 99 additions & 29 deletions autonomi/src/client/wasm.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,10 @@
use libp2p::Multiaddr;
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub struct Client(super::Client);

#[wasm_bindgen]
pub struct ChunkAddr(xor_name::XorName);
use super::address::{addr_to_str, str_to_addr};

#[wasm_bindgen]
pub struct DataAddr(xor_name::XorName);
#[wasm_bindgen]
impl DataAddr {
#[wasm_bindgen(js_name = toString)]
pub fn to_string(&self) -> String {
crate::client::address::addr_to_str(self.0)
}
}
#[wasm_bindgen(js_name = Client)]
pub struct JsClient(super::Client);

#[wasm_bindgen]
pub struct AttoTokens(sn_evm::AttoTokens);
Expand All @@ -27,41 +16,46 @@ impl AttoTokens {
}
}

#[wasm_bindgen]
impl Client {
#[wasm_bindgen(js_class = Client)]
impl JsClient {
#[wasm_bindgen(constructor)]
pub async fn connect(peers: Vec<String>) -> Result<Client, JsError> {
pub async fn connect(peers: Vec<String>) -> Result<JsClient, JsError> {
let peers = peers
.into_iter()
.map(|peer| peer.parse())
.collect::<Result<Vec<Multiaddr>, _>>()?;

let client = super::Client::connect(&peers).await?;

Ok(Client(client))
Ok(JsClient(client))
}

#[wasm_bindgen(js_name = chunkPut)]
pub async fn chunk_put(&self, _data: Vec<u8>, _wallet: Wallet) -> Result<ChunkAddr, JsError> {
pub async fn chunk_put(&self, _data: Vec<u8>, _wallet: &JsWallet) -> Result<String, JsError> {
async { unimplemented!() }.await
}

#[wasm_bindgen(js_name = chunkGet)]
pub async fn chunk_get(&self, addr: ChunkAddr) -> Result<Vec<u8>, JsError> {
let chunk = self.0.chunk_get(addr.0).await?;
pub async fn chunk_get(&self, addr: String) -> Result<Vec<u8>, JsError> {
let addr = str_to_addr(&addr)?;
let chunk = self.0.chunk_get(addr).await?;

Ok(chunk.value().to_vec())
}

#[wasm_bindgen(js_name = dataPut)]
pub async fn data_put(&self, data: Vec<u8>, wallet: Wallet) -> Result<DataAddr, JsError> {
pub async fn data_put(&self, data: Vec<u8>, wallet: &JsWallet) -> Result<String, JsError> {
let data = crate::Bytes::from(data);
let xorname = self.0.data_put(data, &wallet.0).await?;
Ok(DataAddr(xorname))

Ok(addr_to_str(xorname))
}

#[wasm_bindgen(js_name = dataGet)]
pub async fn data_get(&self, addr: DataAddr) -> Result<Vec<u8>, JsError> {
let data = self.0.data_get(addr.0).await?;
pub async fn data_get(&self, addr: String) -> Result<Vec<u8>, JsError> {
let addr = str_to_addr(&addr)?;
let data = self.0.data_get(addr).await?;

Ok(data.to_vec())
}

Expand All @@ -74,14 +68,90 @@ impl Client {
}
}

#[wasm_bindgen]
pub struct Wallet(evmlib::wallet::Wallet);
mod archive {
use super::*;
use crate::client::{address::str_to_addr, archive::Archive};
use std::{collections::HashMap, path::PathBuf};
use xor_name::XorName;

#[wasm_bindgen(js_class = Client)]
impl JsClient {
#[wasm_bindgen(js_name = archiveGet)]
pub async fn archive_get(&self, addr: String) -> Result<js_sys::Map, JsError> {
let addr = str_to_addr(&addr)?;
let data = self.0.archive_get(addr).await?;

// To `Map<K, V>` (JS)
let data = serde_wasm_bindgen::to_value(&data.map)?;
Ok(data.into())
}

#[wasm_bindgen(js_name = archivePut)]
pub async fn archive_put(
&self,
map: JsValue,
wallet: &JsWallet,
) -> Result<String, JsError> {
// From `Map<K, V>` or `Iterable<[K, V]>` (JS)
let map: HashMap<PathBuf, XorName> = serde_wasm_bindgen::from_value(map)?;
let archive = Archive { map };

let addr = self.0.archive_put(archive, &wallet.0).await?;

Ok(addr_to_str(addr))
}
}
}

#[cfg(feature = "vault")]
mod vault {
use super::*;
use bls::SecretKey;

#[wasm_bindgen(js_class = Client)]
impl JsClient {
#[wasm_bindgen(js_name = fetchAndDecryptVault)]
pub async fn fetch_and_decrypt_vault(
&self,
secret_key: Vec<u8>,
) -> Result<Option<Vec<u8>>, JsError> {
let secret_key: [u8; 32] = secret_key[..].try_into()?;
let secret_key = SecretKey::from_bytes(secret_key)?;

let vault = self.0.fetch_and_decrypt_vault(&secret_key).await?;
let vault = vault.map(|v| v.to_vec());

Ok(vault)
}

#[wasm_bindgen(js_name = writeBytesToVault)]
pub async fn write_bytes_to_vault(
&self,
vault: Vec<u8>,
wallet: &mut JsWallet,
secret_key: Vec<u8>,
) -> Result<(), JsError> {
let secret_key: [u8; 32] = secret_key[..].try_into()?;
let secret_key = SecretKey::from_bytes(secret_key)?;

let vault = bytes::Bytes::from(vault);
self.0
.write_bytes_to_vault(vault, &mut wallet.0, &secret_key)
.await?;

Ok(())
}
}
}

#[wasm_bindgen(js_name = Wallet)]
pub struct JsWallet(evmlib::wallet::Wallet);

/// Get a funded wallet for testing. This either uses a default private key or the `EVM_PRIVATE_KEY`
/// environment variable that was used during the build process of this library.
#[wasm_bindgen(js_name = getFundedWallet)]
pub fn funded_wallet() -> Wallet {
Wallet(test_utils::evm::get_funded_wallet())
pub fn funded_wallet() -> JsWallet {
JsWallet(test_utils::evm::get_funded_wallet())
}

/// Enable tracing logging in the console.
Expand Down
6 changes: 3 additions & 3 deletions autonomi/tests/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ fn compute_dir_sha256(dir: &str) -> Result<String> {
async fn file_into_vault() -> Result<()> {
let _log_appender_guard = LogBuilder::init_single_threaded_tokio_test("file", false);

let mut client = Client::connect(&peers_from_env()?).await?;
let mut wallet = get_funded_wallet();
let client = Client::connect(&peers_from_env()?).await?;
let wallet = get_funded_wallet();
let client_sk = bls::SecretKey::random();

let addr = client
Expand All @@ -92,7 +92,7 @@ async fn file_into_vault() -> Result<()> {

let archive = client.archive_get(addr).await?;
client
.write_bytes_to_vault(archive.into_bytes()?, &mut wallet, &client_sk)
.write_bytes_to_vault(archive.into_bytes()?, &wallet, &client_sk)
.await?;

// now assert over the stored account packet
Expand Down

0 comments on commit 6c4ad11

Please sign in to comment.