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(¬arized_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}