Skip to content

Commit bf0b1ae

Browse files
[types] Define WASM Bindings (#8)
* add WASM bindings * add WASM pack test * if publci key bytes are provided, force parse
1 parent 52aae01 commit bf0b1ae

File tree

5 files changed

+155
-4
lines changed

5 files changed

+155
-4
lines changed

.github/workflows/tests.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,7 @@ jobs:
7575
run: rustup target add wasm32-unknown-unknown
7676
- name: Build types
7777
run: cargo build --target wasm32-unknown-unknown --release --manifest-path types/Cargo.toml && du -h target/wasm32-unknown-unknown/release/alto_types.wasm
78+
- name: Install wasm-pack
79+
run: cargo install wasm-pack
80+
- name: Pack types
81+
run: wasm-pack build types --release --target web

Cargo.lock

Lines changed: 18 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

types/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ commonware-utils = { workspace = true }
1919
bytes = { workspace = true }
2020
rand = { workspace = true }
2121
thiserror = { workspace = true }
22+
wasm-bindgen = "0.2.100"
23+
serde = { version = "1.0.219", features = ["derive"] }
24+
serde-wasm-bindgen = "0.6.5"
2225

2326
# Enable "js" feature when WASM is target
2427
[target.'cfg(target_arch = "wasm32")'.dependencies.getrandom]

types/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod block;
44
pub use block::{Block, Finalized, Notarized};
55
mod consensus;
66
pub use consensus::{Finalization, Kind, Notarization, Nullification, Seed};
7+
pub mod wasm;
78

89
// We don't use functions here to guard against silent changes.
910
pub const NAMESPACE: &[u8] = b"_ALTO";

types/src/wasm.rs

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
use commonware_cryptography::bls12381::PublicKey;
2+
use serde::Serialize;
3+
use wasm_bindgen::prelude::*;
4+
5+
use crate::{Block, Finalized, Notarized, Seed};
6+
7+
#[derive(Serialize)]
8+
pub struct SeedJs {
9+
pub view: u64,
10+
pub signature: Vec<u8>,
11+
}
12+
13+
#[derive(Serialize)]
14+
pub struct ProofJs {
15+
pub view: u64,
16+
pub parent: u64,
17+
pub payload: Vec<u8>,
18+
pub signature: Vec<u8>,
19+
}
20+
21+
#[derive(Serialize)]
22+
pub struct BlockJs {
23+
pub parent: Vec<u8>,
24+
pub height: u64,
25+
pub timestamp: u64,
26+
pub digest: Vec<u8>,
27+
}
28+
29+
#[derive(Serialize)]
30+
pub struct NotarizedJs {
31+
pub proof: ProofJs,
32+
pub block: BlockJs,
33+
}
34+
35+
#[derive(Serialize)]
36+
pub struct FinalizedJs {
37+
pub proof: ProofJs,
38+
pub block: BlockJs,
39+
}
40+
41+
#[wasm_bindgen]
42+
pub fn parse_seed(public_key: Option<Vec<u8>>, bytes: Vec<u8>) -> JsValue {
43+
let mut public = None;
44+
if let Some(pk) = public_key {
45+
public = Some(PublicKey::try_from(pk).expect("invalid public key"));
46+
}
47+
match Seed::deserialize(public.as_ref(), &bytes) {
48+
Some(s) => {
49+
let seed_js = SeedJs {
50+
view: s.view,
51+
signature: s.signature.to_vec(),
52+
};
53+
serde_wasm_bindgen::to_value(&seed_js).unwrap_or(JsValue::NULL)
54+
}
55+
None => JsValue::NULL,
56+
}
57+
}
58+
59+
#[wasm_bindgen]
60+
pub fn parse_notarized(public_key: Option<Vec<u8>>, bytes: Vec<u8>) -> JsValue {
61+
let mut public = None;
62+
if let Some(pk) = public_key {
63+
public = Some(PublicKey::try_from(pk).expect("invalid public key"));
64+
}
65+
match Notarized::deserialize(public.as_ref(), &bytes) {
66+
Some(n) => {
67+
let notarized_js = NotarizedJs {
68+
proof: ProofJs {
69+
view: n.proof.view,
70+
parent: n.proof.parent,
71+
payload: n.proof.payload.to_vec(),
72+
signature: n.proof.signature.to_vec(),
73+
},
74+
block: BlockJs {
75+
parent: n.block.parent.to_vec(),
76+
height: n.block.height,
77+
timestamp: n.block.timestamp,
78+
digest: n.block.digest().to_vec(),
79+
},
80+
};
81+
serde_wasm_bindgen::to_value(&notarized_js).unwrap_or(JsValue::NULL)
82+
}
83+
None => JsValue::NULL,
84+
}
85+
}
86+
87+
#[wasm_bindgen]
88+
pub fn parse_finalized(public_key: Option<Vec<u8>>, bytes: Vec<u8>) -> JsValue {
89+
let mut public = None;
90+
if let Some(pk) = public_key {
91+
public = Some(PublicKey::try_from(pk).expect("invalid public key"));
92+
}
93+
match Finalized::deserialize(public.as_ref(), &bytes) {
94+
Some(f) => {
95+
let finalized_js = FinalizedJs {
96+
proof: ProofJs {
97+
view: f.proof.view,
98+
parent: f.proof.parent,
99+
payload: f.proof.payload.to_vec(),
100+
signature: f.proof.signature.to_vec(),
101+
},
102+
block: BlockJs {
103+
parent: f.block.parent.to_vec(),
104+
height: f.block.height,
105+
timestamp: f.block.timestamp,
106+
digest: f.block.digest().to_vec(),
107+
},
108+
};
109+
serde_wasm_bindgen::to_value(&finalized_js).unwrap_or(JsValue::NULL)
110+
}
111+
None => JsValue::NULL,
112+
}
113+
}
114+
115+
#[wasm_bindgen]
116+
pub fn parse_block(bytes: Vec<u8>) -> JsValue {
117+
match Block::deserialize(&bytes) {
118+
Some(b) => {
119+
let block_js = BlockJs {
120+
parent: b.parent.to_vec(),
121+
height: b.height,
122+
timestamp: b.timestamp,
123+
digest: b.digest().to_vec(),
124+
};
125+
serde_wasm_bindgen::to_value(&block_js).unwrap_or(JsValue::NULL)
126+
}
127+
None => JsValue::NULL,
128+
}
129+
}

0 commit comments

Comments
 (0)