wasm_utils/
types.rs

1#![allow(clippy::unused_unit)]
2use core::convert::{TryFrom, TryInto};
3use core::fmt;
4use core::ops::Deref;
5use core::str::FromStr;
6
7use arkworks_setups::Curve as ArkCurve;
8use js_sys::{JsString, Uint8Array};
9use wasm_bindgen::__rt::core::fmt::Formatter;
10use wasm_bindgen::prelude::*;
11
12/// Final Operation Error
13#[cfg(not(test))]
14#[wasm_bindgen]
15#[derive(PartialEq, Eq, Debug)]
16pub struct OperationError {
17	#[wasm_bindgen(skip)]
18	pub code: OpStatusCode,
19	#[wasm_bindgen(skip)]
20	pub error_message: String,
21	#[wasm_bindgen(skip)]
22	pub data: Option<String>,
23}
24
25#[allow(clippy::unused_unit)]
26#[cfg(not(test))]
27#[wasm_bindgen]
28impl OperationError {
29	#[wasm_bindgen(js_name = code)]
30	#[wasm_bindgen(getter)]
31	pub fn code(&self) -> JsValue {
32		JsValue::from(self.code.clone() as u32)
33	}
34
35	// For backward compatibility
36	#[wasm_bindgen(js_name = error_message)]
37	#[wasm_bindgen(getter)]
38	pub fn error_message(&self) -> JsString {
39		JsString::from(self.error_message.clone())
40	}
41
42	#[wasm_bindgen(js_name = message)]
43	#[wasm_bindgen(getter)]
44	pub fn message(&self) -> JsString {
45		JsString::from(self.error_message.clone())
46	}
47
48	#[wasm_bindgen(js_name = data)]
49	#[wasm_bindgen(getter)]
50	pub fn data(&self) -> JsString {
51		match self.data.clone() {
52			None => JsString::from("{}"),
53			Some(e) => JsString::from(e),
54		}
55	}
56}
57/// For tests this will have a custom JsValue conversion
58#[cfg(test)]
59#[derive(PartialEq, Eq, Debug)]
60pub struct OperationError {
61	pub code: OpStatusCode,
62	pub error_message: String,
63	pub data: Option<String>,
64}
65#[cfg(test)]
66impl OperationError {
67	pub fn code(&self) -> JsValue {
68		JsValue::from(self.code.clone() as u32)
69	}
70
71	pub fn error_message(&self) -> JsString {
72		JsString::from(self.error_message.clone())
73	}
74
75	pub fn data(&self) -> JsString {
76		match self.data.clone() {
77			None => JsString::from("{}"),
78			Some(e) => JsString::from(e),
79		}
80	}
81}
82
83#[cfg(test)]
84impl From<OperationError> for JsValue {
85	fn from(e: OperationError) -> Self {
86		JsValue::from(e.to_string())
87	}
88}
89
90impl fmt::Display for OperationError {
91	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
92		write!(
93			f,
94			"Code {}, message {}, data {}",
95			self.code.clone() as u32,
96			self.error_message.clone(),
97			self.data()
98		)
99	}
100}
101
102impl OperationError {
103	pub fn new_with_message(code: OpStatusCode, message: String) -> Self {
104		let mut oe: Self = code.into();
105		oe.error_message = message;
106		oe
107	}
108}
109#[derive(Clone, Copy, PartialEq, Eq, Debug)]
110pub enum NoteVersion {
111	V1,
112}
113
114#[derive(Clone, Copy, PartialEq, Eq, Debug)]
115pub enum Chain {
116	Edgeware,
117	Ganache,
118	Beresheet,
119	HarmonyTestShard1,
120	Rinkeby,
121}
122
123#[derive(Clone, Copy, PartialEq, Eq, Debug)]
124pub enum Backend {
125	Arkworks,
126	Circom,
127}
128
129#[derive(Clone, Copy, PartialEq, Eq, Debug)]
130pub enum Curve {
131	Bls381,
132	Bn254,
133}
134
135#[derive(Clone, Copy, PartialEq, Eq, Debug)]
136pub enum HashFunction {
137	Poseidon,
138	MiMCTornado,
139}
140
141#[derive(Clone, Copy, PartialEq, Eq, Debug)]
142pub enum NoteProtocol {
143	Mixer,
144	VAnchor,
145}
146
147impl fmt::Display for NoteVersion {
148	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
149		match self {
150			NoteVersion::V1 => write!(f, "v1"),
151		}
152	}
153}
154
155impl FromStr for NoteVersion {
156	type Err = OpStatusCode;
157
158	fn from_str(s: &str) -> Result<Self, Self::Err> {
159		match s {
160			"v1" => Ok(NoteVersion::V1),
161			_ => Err(OpStatusCode::InvalidNoteVersion),
162		}
163	}
164}
165
166impl fmt::Display for Backend {
167	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168		match self {
169			Backend::Arkworks => write!(f, "Arkworks"),
170			Backend::Circom => write!(f, "Circom"),
171		}
172	}
173}
174
175impl FromStr for Backend {
176	type Err = OpStatusCode;
177
178	fn from_str(s: &str) -> Result<Self, Self::Err> {
179		match s {
180			"Arkworks" => Ok(Backend::Arkworks),
181			"Circom" => Ok(Backend::Circom),
182			_ => Err(OpStatusCode::InvalidBackend),
183		}
184	}
185}
186
187impl fmt::Display for Curve {
188	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
189		match self {
190			Curve::Bls381 => write!(f, "Bls381"),
191			Curve::Bn254 => write!(f, "Bn254"),
192		}
193	}
194}
195
196impl FromStr for Curve {
197	type Err = OpStatusCode;
198
199	fn from_str(s: &str) -> Result<Self, Self::Err> {
200		match s {
201			"Bls381" => Ok(Curve::Bls381),
202			"Bn254" => Ok(Curve::Bn254),
203			_ => Err(OpStatusCode::InvalidCurve),
204		}
205	}
206}
207
208impl fmt::Display for HashFunction {
209	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
210		match self {
211			HashFunction::Poseidon => write!(f, "Poseidon"),
212			HashFunction::MiMCTornado => write!(f, "MiMCTornado"),
213		}
214	}
215}
216
217impl FromStr for NoteProtocol {
218	type Err = OpStatusCode;
219
220	fn from_str(s: &str) -> Result<Self, Self::Err> {
221		match s {
222			"mixer" => Ok(NoteProtocol::Mixer),
223			"vanchor" => Ok(NoteProtocol::VAnchor),
224			_ => Err(OpStatusCode::InvalidNoteProtocol),
225		}
226	}
227}
228
229impl fmt::Display for NoteProtocol {
230	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
231		match self {
232			NoteProtocol::Mixer => write!(f, "mixer"),
233			NoteProtocol::VAnchor => write!(f, "vanchor"),
234		}
235	}
236}
237
238impl FromStr for HashFunction {
239	type Err = OpStatusCode;
240
241	fn from_str(s: &str) -> Result<Self, Self::Err> {
242		match s {
243			"Poseidon" => Ok(HashFunction::Poseidon),
244			"MiMCTornado" => Ok(HashFunction::MiMCTornado),
245			_ => Err(OpStatusCode::InvalidHasFunction),
246		}
247	}
248}
249
250impl From<Curve> for ArkCurve {
251	fn from(curve: Curve) -> Self {
252		match curve {
253			Curve::Bls381 => ArkCurve::Bls381,
254			Curve::Bn254 => ArkCurve::Bn254,
255		}
256	}
257}
258
259#[derive(Debug, Eq, PartialEq, Clone)]
260#[repr(u32)]
261pub enum OpStatusCode {
262	Unknown = 0,
263	/// Invalid hex string length when decoding
264	InvalidHexLength = 1,
265	/// Failed to parse hex string
266	HexParsingFailed = 2,
267	/// Invalid number of note parts when decoding
268	InvalidNoteLength = 3,
269	/// Invalid note protocol
270	InvalidNoteProtocol = 4,
271	/// Invalid note version
272	InvalidNoteVersion = 5,
273	/// Invalid note id when parsing
274	InvalidNoteId = 6,
275	/// Invalid note block number when parsing
276	InvalidNoteBlockNumber = 7,
277	/// Invalid note secrets
278	InvalidNoteSecrets = 8,
279	/// Unable to find merkle tree
280	MerkleTreeNotFound = 9,
281	/// Failed serialization of passed params
282	/// Error for failing to parse rust type into JsValue
283	SerializationFailed = 10,
284	/// Failed deserialization of JsValue into rust type
285	DeserializationFailed = 11,
286	/// Invalid Array of 32 bytes.
287	InvalidArrayLength = 12,
288	/// Invalid curve  when parsing
289	InvalidCurve = 13,
290	/// Invalid hashFunction id when parsing
291	InvalidHasFunction = 14,
292	/// Invalid backend id when parsing
293	InvalidBackend = 15,
294	/// Invalid denomination id when parsing
295	InvalidDenomination = 16,
296	/// Failed to generate secrets
297	SecretGenFailed = 17,
298	/// Invalid Source chain
299	InvalidSourceChain = 18,
300	/// Invalid target chain
301	InvalidTargetChain = 19,
302	/// Invalid Token Symbol
303	InvalidTokenSymbol = 20,
304	/// Invalid Exponentiation
305	InvalidExponentiation = 21,
306	/// Invalid Width
307	InvalidWidth = 22,
308	/// Invalid Amount
309	InvalidAmount = 23,
310	/// Invalid proof parameters
311	InvalidProofParameters = 24,
312	/// Invalid Proving key
313	InvalidProvingKey = 25,
314	/// Invalid Recipient
315	InvalidRecipient = 26,
316	/// Invalid Relayer
317	InvalidRelayer = 27,
318	/// Invalid LeafIndex
319	InvalidLeafIndex = 28,
320	/// Invalid Fee
321	InvalidFee = 29,
322	/// Invalid Refund
323	InvalidRefund = 30,
324	/// Invalid InvalidLeaves
325	InvalidLeaves = 31,
326	/// Failed to  Generating Leaf
327	FailedToGenerateTheLeaf = 32,
328	/// Note not set
329	ProofBuilderNoteNotSet = 33,
330	/// Commitment not set
331	CommitmentNotSet = 34,
332	/// Neighbour Roots aren't set
333	RootsNotSet = 35,
334	/// Invalid note misc data
335	InvalidNoteMiscData = 36,
336	/// Invalid Source IdentifyingData
337	InvalidSourceIdentifyingData = 37,
338	/// Invalid target IdentifyingData
339	InvalidTargetIdentifyingData = 38,
340	/// Unsupported combination of parameters
341	UnsupportedParameterCombination = 39,
342	/// Invalid proof on verification
343	InvalidProof = 40,
344	/// Invalid index
345	InvalidUTXOIndex = 41,
346	/// Unsupported Backend
347	UnsupportedBackend = 42,
348	/// Public amount not set
349	PublicAmountNotSet = 43,
350	/// VAnchor Proof Chain Id not set
351	VAnchorProofChainId = 44,
352	/// VAnchor proof not set
353	VAnchorNotesNotSet = 45,
354	/// VAnchor proof indices
355	VAnchorProofIndices = 46,
356	/// VAnchor proof leaves map not defined
357	VAnchorProofLeavesMap = 47,
358	/// Generic error while trying to instantiate proof input field
359	ProofInputFieldInstantiationError = 48,
360	/// Invalid filed for the proof input protocol
361	ProofInputFieldInstantiationProtocolInvalid = 49,
362	InvalidNullifer = 50,
363	InvalidRoots = 51,
364	InvalidChainId = 52,
365	InvalidIndices = 53,
366	InvalidPublicAmount = 54,
367	InvalidOutputUtxoConfig = 55,
368	InvalidExtDataHash = 56,
369}
370
371#[wasm_bindgen]
372extern "C" {
373	// Use `js_namespace` here to bind `console.log(..)` instead of just
374	// `log(..)`
375	#[wasm_bindgen(js_namespace = console)]
376	pub fn log(s: &str);
377
378	#[wasm_bindgen(typescript_type = "NoteProtocol")]
379	pub type Protocol;
380
381	#[wasm_bindgen(typescript_type = "Curve")]
382	#[derive(Clone)]
383	pub type WasmCurve;
384
385	#[wasm_bindgen(typescript_type = "HashFunction")]
386	pub type HF;
387
388	#[wasm_bindgen(typescript_type = "Version")]
389	pub type Version;
390
391	#[wasm_bindgen(typescript_type = "Backend")]
392	#[derive(Clone)]
393	pub type BE;
394
395	#[wasm_bindgen(typescript_type = "Leaves")]
396	pub type Leaves;
397
398	#[wasm_bindgen(typescript_type = "Indices")]
399	pub type Indices;
400
401}
402
403#[wasm_bindgen(typescript_custom_section)]
404const NOTE_PROTOCOL: &str = "type NoteProtocol = 'mixer' | 'vanchor' ";
405
406#[wasm_bindgen(typescript_custom_section)]
407const LEAVES: &str = "type Leaves = Array<Uint8Array>;";
408
409#[wasm_bindgen(typescript_custom_section)]
410const INDICES: &str = "type Indices = Array<number>;";
411
412#[wasm_bindgen(typescript_custom_section)]
413const HF: &str = "type HashFunction = 'Poseidon' | 'MiMCTornado'";
414
415#[wasm_bindgen(typescript_custom_section)]
416const CURVE: &str = "type Curve = 'Bls381' | 'Bn254'";
417
418#[wasm_bindgen(typescript_custom_section)]
419const VERSION: &str = "type Version = 'v1'";
420
421#[wasm_bindgen(typescript_custom_section)]
422const BE: &str = "type Backend = 'Arkworks' | 'Circom'";
423
424pub struct Uint8Arrayx32(pub [u8; 32]);
425
426impl Deref for Uint8Arrayx32 {
427	type Target = [u8; 32];
428
429	fn deref(&self) -> &Self::Target {
430		&self.0
431	}
432}
433
434impl TryFrom<Uint8Array> for Uint8Arrayx32 {
435	type Error = OpStatusCode;
436
437	fn try_from(value: Uint8Array) -> Result<Self, Self::Error> {
438		let bytes: [u8; 32] = value
439			.to_vec()
440			.try_into()
441			.map_err(|_| OpStatusCode::InvalidArrayLength)?;
442		Ok(Self(bytes))
443	}
444}
445impl From<OpStatusCode> for String {
446	fn from(e: OpStatusCode) -> Self {
447		match e {
448			OpStatusCode::Unknown => "Unknown error",
449			OpStatusCode::InvalidHexLength => "Invalid hex length",
450			OpStatusCode::HexParsingFailed => "Failed to parse hex",
451			OpStatusCode::InvalidNoteLength => "Invalid note length",
452			OpStatusCode::InvalidNoteProtocol => "Invalid note protocol",
453			OpStatusCode::InvalidNoteVersion => "Invalid note version",
454			OpStatusCode::InvalidNoteId => "Invalid note id",
455			OpStatusCode::InvalidNoteBlockNumber => "Invalid block number",
456			OpStatusCode::InvalidNoteSecrets => "Invalid note secrets",
457			OpStatusCode::MerkleTreeNotFound => "Merkle tree not found",
458			OpStatusCode::SerializationFailed => "Failed to serialize",
459			OpStatusCode::DeserializationFailed => "Failed to deserialize",
460			OpStatusCode::InvalidArrayLength => "Invalid array length",
461			OpStatusCode::InvalidCurve => "Invalid curve",
462			OpStatusCode::InvalidHasFunction => "Invalid hash function",
463			OpStatusCode::InvalidBackend => "Invalid backend",
464			OpStatusCode::InvalidDenomination => "Invalid denomination",
465			OpStatusCode::SecretGenFailed => "Failed to generate secrets",
466			OpStatusCode::InvalidSourceChain => "Invalid source chain id",
467			OpStatusCode::InvalidTargetChain => "Invalid target chain id",
468			OpStatusCode::InvalidTokenSymbol => "Invalid token symbol",
469			OpStatusCode::InvalidExponentiation => "Invalid exponentiation",
470			OpStatusCode::InvalidWidth => "Invalid width",
471			OpStatusCode::InvalidAmount => "Invalid amount",
472			OpStatusCode::InvalidProofParameters => "Invalid proof parameters",
473			OpStatusCode::InvalidProvingKey => "Invalid proving key",
474			OpStatusCode::InvalidRecipient => "Invalid recipient address",
475			OpStatusCode::InvalidRelayer => "Invalid relayer address",
476			OpStatusCode::InvalidLeafIndex => "Invalid leaf index",
477			OpStatusCode::InvalidFee => "Invalid fee",
478			OpStatusCode::InvalidRefund => "Invalid refund",
479			OpStatusCode::InvalidLeaves => "Invalid leaves",
480			OpStatusCode::FailedToGenerateTheLeaf => "Failed to generate the leaf",
481			OpStatusCode::ProofBuilderNoteNotSet => "Proof building failed note isn't set",
482			OpStatusCode::CommitmentNotSet => "Proof building failed refresh commitment isn't set",
483			OpStatusCode::RootsNotSet => "Proof building failed roots array isn't set",
484			OpStatusCode::InvalidNoteMiscData => "Invalid note misc data",
485			OpStatusCode::InvalidSourceIdentifyingData => "Invalid source identifying data",
486			OpStatusCode::InvalidTargetIdentifyingData => "Invalid target identifying data",
487			OpStatusCode::UnsupportedParameterCombination => "Unsupported Paramater combination to generate proof",
488			OpStatusCode::InvalidProof => "Proof verification failed",
489			OpStatusCode::InvalidUTXOIndex => "Invalid UTXO Index value",
490			OpStatusCode::UnsupportedBackend => "Unsupported backend",
491			OpStatusCode::PublicAmountNotSet => "VAnchor proof input requires public amount field",
492			OpStatusCode::VAnchorProofChainId => "VAnchor proof input requires chain id",
493			OpStatusCode::VAnchorNotesNotSet => "VAnchor proof input requires list of notes",
494			OpStatusCode::VAnchorProofIndices => "VAnchor proof input require list of indices",
495			OpStatusCode::VAnchorProofLeavesMap => "VAnchor proof input require leaves  map",
496			OpStatusCode::ProofInputFieldInstantiationError => "The proof input field installation failed",
497			OpStatusCode::ProofInputFieldInstantiationProtocolInvalid => {
498				"The proof input field installation failed wrong protocol or field"
499			}
500			OpStatusCode::InvalidNullifer => "Invalid nullifer value",
501			OpStatusCode::InvalidRoots => "Invalid roots value",
502			OpStatusCode::InvalidChainId => "Invalid chain id",
503			OpStatusCode::InvalidIndices => "Invalid indices value",
504			OpStatusCode::InvalidPublicAmount => "Invalid public amount",
505			OpStatusCode::InvalidOutputUtxoConfig => "Invalid output UTXO config",
506			OpStatusCode::InvalidExtDataHash => "Invalid external data hash",
507		}
508		.to_string()
509	}
510}
511impl From<OpStatusCode> for OperationError {
512	fn from(e: OpStatusCode) -> Self {
513		OperationError {
514			code: e.clone(),
515			data: None,
516			error_message: e.into(),
517		}
518	}
519}
520
521impl From<OpStatusCode> for JsValue {
522	fn from(e: OpStatusCode) -> Self {
523		let op: OperationError = e.into();
524		op.into()
525	}
526}
527
528impl From<Backend> for JsString {
529	fn from(e: Backend) -> Self {
530		JsString::from(e.to_string())
531	}
532}
533
534impl From<Curve> for JsString {
535	fn from(e: Curve) -> Self {
536		JsString::from(e.to_string())
537	}
538}
539
540impl From<HashFunction> for JsString {
541	fn from(e: HashFunction) -> Self {
542		JsString::from(e.to_string())
543	}
544}
545
546impl From<NoteVersion> for JsString {
547	fn from(e: NoteVersion) -> Self {
548		JsString::from(e.to_string())
549	}
550}
551
552impl From<NoteProtocol> for JsString {
553	fn from(e: NoteProtocol) -> Self {
554		JsString::from(e.to_string())
555	}
556}
557
558impl From<Curve> for WasmCurve {
559	fn from(curve: Curve) -> Self {
560		let js_str = curve.to_string();
561		JsValue::from(&js_str).try_into().unwrap()
562	}
563}
564
565impl From<HashFunction> for HF {
566	fn from(hash_function: HashFunction) -> Self {
567		let js_str = hash_function.to_string();
568		JsValue::from(&js_str).try_into().unwrap()
569	}
570}
571
572impl From<NoteVersion> for Version {
573	fn from(version: NoteVersion) -> Self {
574		let js_str = version.to_string();
575		JsValue::from(&js_str).try_into().unwrap()
576	}
577}
578
579impl From<Backend> for BE {
580	fn from(backend: Backend) -> Self {
581		let js_str = backend.to_string();
582		JsValue::from(&js_str).try_into().unwrap()
583	}
584}
585
586impl From<NoteProtocol> for Protocol {
587	fn from(proto: NoteProtocol) -> Self {
588		let js_str = proto.to_string();
589		JsValue::from(&js_str).try_into().unwrap()
590	}
591}
592
593#[cfg(not(test))]
594#[allow(clippy::unused_unit)]
595#[wasm_bindgen(start)]
596pub fn main() {
597	console_error_panic_hook::set_once();
598}