alto_types/
wasm.rs

1use crate::{
2    leader_index as compute_leader_index, Block, Finalized, Identity, Notarized, Seed, NAMESPACE,
3};
4use commonware_codec::{DecodeExt, Encode};
5use commonware_consensus::Viewable;
6use commonware_cryptography::Digestible;
7use serde::Serialize;
8use wasm_bindgen::prelude::*;
9
10#[derive(Serialize)]
11pub struct SeedJs {
12    pub view: u64,
13    pub signature: Vec<u8>,
14}
15
16#[derive(Serialize)]
17pub struct ProofJs {
18    pub view: u64,
19    pub parent: u64,
20    pub payload: Vec<u8>,
21    pub signature: Vec<u8>,
22}
23
24#[derive(Serialize)]
25pub struct BlockJs {
26    pub parent: Vec<u8>,
27    pub height: u64,
28    pub timestamp: u64,
29    pub digest: Vec<u8>,
30}
31
32#[derive(Serialize)]
33pub struct NotarizedJs {
34    pub proof: ProofJs,
35    pub block: BlockJs,
36}
37
38#[derive(Serialize)]
39pub struct FinalizedJs {
40    pub proof: ProofJs,
41    pub block: BlockJs,
42}
43
44#[wasm_bindgen]
45pub fn parse_seed(identity: Vec<u8>, bytes: Vec<u8>) -> JsValue {
46    let identity = Identity::decode(identity.as_ref()).expect("invalid identity");
47    let Ok(seed) = Seed::decode(bytes.as_ref()) else {
48        return JsValue::NULL;
49    };
50    if !seed.verify(NAMESPACE, &identity) {
51        return JsValue::NULL;
52    }
53    let seed_js = SeedJs {
54        view: seed.view(),
55        signature: seed.signature.encode().to_vec(),
56    };
57    serde_wasm_bindgen::to_value(&seed_js).unwrap_or(JsValue::NULL)
58}
59
60#[wasm_bindgen]
61pub fn parse_notarized(identity: Vec<u8>, bytes: Vec<u8>) -> JsValue {
62    let identity = Identity::decode(identity.as_ref()).expect("invalid identity");
63    let Ok(notarized) = Notarized::decode(bytes.as_ref()) else {
64        return JsValue::NULL;
65    };
66    if !notarized.verify(NAMESPACE, &identity) {
67        return JsValue::NULL;
68    }
69    let notarized_js = NotarizedJs {
70        proof: ProofJs {
71            view: notarized.proof.view(),
72            parent: notarized.proof.proposal.parent,
73            payload: notarized.proof.proposal.payload.to_vec(),
74            signature: notarized.proof.proposal_signature.encode().to_vec(),
75        },
76        block: BlockJs {
77            parent: notarized.block.parent.to_vec(),
78            height: notarized.block.height,
79            timestamp: notarized.block.timestamp,
80            digest: notarized.block.digest().to_vec(),
81        },
82    };
83    serde_wasm_bindgen::to_value(&notarized_js).unwrap_or(JsValue::NULL)
84}
85
86#[wasm_bindgen]
87pub fn parse_finalized(identity: Vec<u8>, bytes: Vec<u8>) -> JsValue {
88    let identity = Identity::decode(identity.as_ref()).expect("invalid identity");
89    let Ok(finalized) = Finalized::decode(bytes.as_ref()) else {
90        return JsValue::NULL;
91    };
92    if !finalized.verify(NAMESPACE, &identity) {
93        return JsValue::NULL;
94    }
95    let finalized_js = FinalizedJs {
96        proof: ProofJs {
97            view: finalized.proof.view(),
98            parent: finalized.proof.proposal.parent,
99            payload: finalized.proof.proposal.payload.to_vec(),
100            signature: finalized.proof.proposal_signature.encode().to_vec(),
101        },
102        block: BlockJs {
103            parent: finalized.block.parent.to_vec(),
104            height: finalized.block.height,
105            timestamp: finalized.block.timestamp,
106            digest: finalized.block.digest().to_vec(),
107        },
108    };
109    serde_wasm_bindgen::to_value(&finalized_js).unwrap_or(JsValue::NULL)
110}
111
112#[wasm_bindgen]
113pub fn parse_block(bytes: Vec<u8>) -> JsValue {
114    let Ok(block) = Block::decode(bytes.as_ref()) else {
115        return JsValue::NULL;
116    };
117    let block_js = BlockJs {
118        parent: block.parent.to_vec(),
119        height: block.height,
120        timestamp: block.timestamp,
121        digest: block.digest().to_vec(),
122    };
123    serde_wasm_bindgen::to_value(&block_js).unwrap_or(JsValue::NULL)
124}
125
126#[wasm_bindgen]
127pub fn leader_index(signature: Vec<u8>, participants: usize) -> usize {
128    compute_leader_index(&signature, participants)
129}