Skip to main content

keymaster_multisig/
lib.rs

1mod error;
2mod multisig;
3mod types;
4mod version;
5
6pub use error::{MultisigError, Result};
7pub use multisig::Multisig;
8pub use types::*;
9pub use version::{PROTOCOL, PROTOCOL_VERSION, RELEASE_VERSION, VERSION};
10
11use serde_wasm_bindgen as swbg;
12use wasm_bindgen::prelude::*;
13
14#[wasm_bindgen]
15pub fn create_multisig(
16    private_keys: JsValue,
17    public_keys: JsValue,
18    m: usize,
19) -> std::result::Result<MultisigWasm, JsValue> {
20    let pub_keys: Vec<PublicKey> = swbg::from_value(public_keys)?;
21    let priv_keys: Option<Vec<PrivateKey>> = swbg::from_value(private_keys).ok();
22
23    let multisig =
24        Multisig::new(priv_keys, pub_keys, m).map_err(|e| JsValue::from_str(&e.to_string()))?;
25
26    Ok(MultisigWasm { multisig })
27}
28
29#[wasm_bindgen]
30pub fn create_locking_script(
31    public_keys: JsValue,
32    m: usize,
33) -> std::result::Result<JsValue, JsValue> {
34    let pub_keys: Vec<PublicKey> = swbg::from_value(public_keys)?;
35
36    if m == 0 || m > pub_keys.len() {
37        return Err(JsValue::from_str("Invalid m value"));
38    }
39    if pub_keys.is_empty() || pub_keys.len() > 20 {
40        return Err(JsValue::from_str("Invalid public keys"));
41    }
42
43    let mut script = vec![0x01 + (m as u8) - 1];
44
45    for pub_key in &pub_keys {
46        script.push(pub_key.key.len() as u8);
47        script.extend(&pub_key.key);
48    }
49
50    script.push(0x01 + (pub_keys.len() as u8) - 1);
51    script.push(0xae);
52
53    Ok(swbg::to_value(&script)?)
54}
55
56#[wasm_bindgen]
57pub fn estimate_multisig_length(m: usize) -> usize {
58    1 + m * (71 + 1)
59}
60
61#[wasm_bindgen]
62pub struct MultisigWasm {
63    multisig: Multisig,
64}
65
66#[wasm_bindgen]
67impl MultisigWasm {
68    #[wasm_bindgen(constructor)]
69    pub fn new(
70        private_keys: JsValue,
71        public_keys: JsValue,
72        m: usize,
73    ) -> std::result::Result<MultisigWasm, JsValue> {
74        create_multisig(private_keys, public_keys, m)
75    }
76
77    pub fn lock(&self) -> std::result::Result<JsValue, JsValue> {
78        let script = self
79            .multisig
80            .lock()
81            .map_err(|e| JsValue::from_str(&e.to_string()))?;
82        Ok(swbg::to_value(&script)?)
83    }
84
85    pub fn sign(
86        &self,
87        transaction: JsValue,
88        input_index: usize,
89    ) -> std::result::Result<JsValue, JsValue> {
90        let tx: Transaction = swbg::from_value(transaction)?;
91        let signatures = self
92            .multisig
93            .sign(&tx, input_index)
94            .map_err(|e| JsValue::from_str(&e.to_string()))?;
95        Ok(swbg::to_value(&signatures)?)
96    }
97
98    pub fn sign_one(
99        &self,
100        transaction: JsValue,
101        input_index: usize,
102        private_key: JsValue,
103    ) -> std::result::Result<JsValue, JsValue> {
104        let tx: Transaction = swbg::from_value(transaction)?;
105        let priv_key: PrivateKey = swbg::from_value(private_key)?;
106
107        let signature = self
108            .multisig
109            .sign_one(&tx, input_index, &priv_key)
110            .map_err(|e| JsValue::from_str(&e.to_string()))?;
111        Ok(swbg::to_value(&signature)?)
112    }
113
114    pub fn estimate_length(&self) -> usize {
115        self.multisig.estimate_length()
116    }
117
118    pub fn create_fake_sign(&self) -> std::result::Result<JsValue, JsValue> {
119        let script = self
120            .multisig
121            .create_fake_sign()
122            .map_err(|e| JsValue::from_str(&e.to_string()))?;
123        Ok(swbg::to_value(&script)?)
124    }
125
126    pub fn build_sign_script(&self, signatures: JsValue) -> std::result::Result<JsValue, JsValue> {
127        let sigs: Vec<Vec<u8>> = swbg::from_value(signatures)?;
128        let script = self
129            .multisig
130            .build_sign_script(&sigs)
131            .map_err(|e| JsValue::from_str(&e.to_string()))?;
132        Ok(swbg::to_value(&script)?)
133    }
134
135    pub fn get_m(&self) -> usize {
136        self.multisig.get_m()
137    }
138
139    pub fn get_n(&self) -> usize {
140        self.multisig.get_n()
141    }
142
143    pub fn get_sig_hash_type(&self) -> u8 {
144        self.multisig.get_sig_hash_type()
145    }
146}
147
148#[wasm_bindgen(start)]
149pub fn main() {
150    console_error_panic_hook::set_once();
151}
152
153#[wasm_bindgen]
154extern "C" {
155    #[wasm_bindgen(js_namespace = console)]
156    fn error(s: &str);
157}