Skip to main content

dlccryptlib_py/
lib.rs

1use dlccryptlib;
2
3use pyo3::exceptions::PyException;
4use pyo3::prelude::*;
5use pyo3::wrap_pyfunction;
6
7// ##### Facade functions for easy Python invocations (pyo3/maturin)
8
9/// Initialize the library, load secret from encrypted file. Return the XPUB.
10#[pyfunction]
11pub fn init(path_for_secret_file: String, encryption_password: String) -> PyResult<String> {
12    dlccryptlib::init(&path_for_secret_file, &encryption_password, false)
13        .map_err(|e| PyErr::new::<PyException, _>(e))
14}
15
16#[pyfunction]
17pub fn reinit_for_testing(
18    path_for_secret_file: String,
19    encryption_password: String,
20) -> PyResult<String> {
21    dlccryptlib::init(&path_for_secret_file, &encryption_password, true)
22        .map_err(|e| PyErr::new::<PyException, _>(e))
23}
24
25/// network: "bitcoin", or "signet".
26// #[cfg(test)]
27#[pyfunction]
28pub fn init_with_entropy(entropy: String, network: String) -> PyResult<String> {
29    dlccryptlib::init_with_entropy(&entropy, &network).map_err(|e| PyErr::new::<PyException, _>(e))
30}
31
32/// Return the XPUB
33#[pyfunction]
34pub fn get_xpub() -> PyResult<String> {
35    dlccryptlib::get_xpub().map_err(|e| PyErr::new::<PyException, _>(e))
36}
37
38/// Return a child public key (specified by its index).
39#[pyfunction]
40pub fn get_public_key(index4: u32, index5: u32) -> PyResult<String> {
41    dlccryptlib::get_public_key(index4, index5).map_err(|e| PyErr::new::<PyException, _>(e))
42}
43
44/// Return a child address (specified by index).
45#[pyfunction]
46pub fn get_address(index4: u32, index5: u32) -> PyResult<String> {
47    dlccryptlib::get_address(index4, index5).map_err(|e| PyErr::new::<PyException, _>(e))
48}
49
50/// Verify a child public key.
51#[pyfunction]
52pub fn verify_public_key(index4: u32, index5: u32, pubkey: String) -> PyResult<bool> {
53    dlccryptlib::verify_public_key(index4, index5, &pubkey)
54        .map_err(|e| PyErr::new::<PyException, _>(e))
55}
56
57/// Sign a hash with a child private key (specified by index).
58#[pyfunction]
59pub fn sign_hash_ecdsa(
60    hash: String,
61    signer_index4: u32,
62    signer_index5: u32,
63    signer_pubkey: String,
64) -> PyResult<String> {
65    dlccryptlib::sign_hash_ecdsa(&hash, signer_index4, signer_index5, &signer_pubkey)
66        .map_err(|e| PyErr::new::<PyException, _>(e))
67}
68
69/// Create a nonce value deterministically
70#[pyfunction]
71pub fn create_deterministic_nonce(
72    event_id: String,
73    nonce_index: u32,
74) -> PyResult<(String, String)> {
75    dlccryptlib::create_deterministic_nonce(&event_id, nonce_index)
76        .map_err(|e| PyErr::new::<PyException, _>(e))
77}
78
79/// Sign a message using Schnorr, with a nonce, using a child key
80#[pyfunction]
81pub fn sign_schnorr_with_nonce(
82    msg: String,
83    nonce_sec_hex: String,
84    index4: u32,
85    index5: u32,
86) -> PyResult<String> {
87    dlccryptlib::sign_schnorr_with_nonce(&msg, &nonce_sec_hex, index4, index5)
88        .map_err(|e| PyErr::new::<PyException, _>(e))
89}
90
91/// Verify a Schnorr signature over a message, using a child key
92#[pyfunction]
93pub fn verify_schnorr(
94    msg: String,
95    signature_hex: String,
96    index4: u32,
97    index5: u32,
98) -> PyResult<bool> {
99    dlccryptlib::verify_schnorr(&msg, &signature_hex, index4, index5)
100        .map_err(|e| PyErr::new::<PyException, _>(e))
101}
102
103/// Combine a number of public keys into one
104#[pyfunction]
105pub fn combine_pubkeys(keys_hex: String) -> PyResult<String> {
106    dlccryptlib::combine_pubkeys(&keys_hex).map_err(|e| PyErr::new::<PyException, _>(e))
107}
108
109/// Combine a number of secret keys into one.
110/// Warning: Handle secret keys with caution!
111#[pyfunction]
112pub fn combine_seckeys(keys_hex: String) -> PyResult<String> {
113    dlccryptlib::combine_seckeys(&keys_hex).map_err(|e| PyErr::new::<PyException, _>(e))
114}
115
116/// Create adaptor signatures for a number of CETs
117#[pyfunction]
118pub fn create_cet_adaptor_sigs(
119    num_digits: u8,
120    num_cets: u64,
121    digit_string_template: String,
122    oracle_pubkey: String,
123    signing_key_index4: u32,
124    signing_key_index5: u32,
125    signing_pubkey: String,
126    nonces: String,
127    interval_wildcards: String,
128    sighashes: String,
129) -> PyResult<String> {
130    dlccryptlib::create_cet_adaptor_sigs(
131        num_digits,
132        num_cets,
133        &digit_string_template,
134        &oracle_pubkey,
135        signing_key_index4,
136        signing_key_index5,
137        &signing_pubkey,
138        &nonces,
139        &interval_wildcards,
140        &sighashes,
141    )
142    .map_err(|e| PyErr::new::<PyException, _>(e))
143}
144
145/// Verify adaptor signatures for a number of CETs
146#[pyfunction]
147pub fn verify_cet_adaptor_sigs(
148    num_digits: u8,
149    num_cets: u64,
150    digit_string_template: String,
151    oracle_pubkey: String,
152    signing_pubkey: String,
153    nonces: String,
154    interval_wildcards: String,
155    sighashes: String,
156    signatures: String,
157) -> PyResult<bool> {
158    dlccryptlib::verify_cet_adaptor_sigs(
159        num_digits,
160        num_cets,
161        &digit_string_template,
162        &oracle_pubkey,
163        &signing_pubkey,
164        &nonces,
165        &interval_wildcards,
166        &sighashes,
167        &signatures,
168    )
169    .map_err(|e| PyErr::new::<PyException, _>(e))
170}
171
172/// Perform final signing of a CET
173#[pyfunction]
174pub fn create_final_cet_sigs(
175    signing_key_index4: u32,
176    signing_key_index5: u32,
177    signing_pubkey: String,
178    other_pubkey: String,
179    num_digits: u8,
180    oracle_signatures: String,
181    cet_value_wildcard: String,
182    cet_sighash: String,
183    other_adaptor_signature: String,
184) -> PyResult<String> {
185    dlccryptlib::create_final_cet_sigs(
186        signing_key_index4,
187        signing_key_index5,
188        &signing_pubkey,
189        &other_pubkey,
190        num_digits,
191        &oracle_signatures,
192        &cet_value_wildcard,
193        &cet_sighash,
194        &other_adaptor_signature,
195    )
196    .map_err(|e| PyErr::new::<PyException, _>(e))
197}
198
199/// Perform final signing of a CET, decrypt a signature when outcome signatures are available.
200/// Return the decrypted signature.
201#[pyfunction]
202pub fn create_final_cet_sig(
203    pubkey: String,
204    num_digits: u8,
205    oracle_signatures: String,
206    cet_value_wildcard: String,
207    cet_sighash: String,
208    adaptor_signature: String,
209) -> PyResult<String> {
210    dlccryptlib::create_final_cet_sig(
211        &pubkey,
212        num_digits,
213        &oracle_signatures,
214        &cet_value_wildcard,
215        &cet_sighash,
216        &adaptor_signature,
217    )
218    .map_err(|e| PyErr::new::<PyException, _>(e))
219}
220
221#[pymodule]
222fn dlccryptlib_py(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
223    m.add_function(wrap_pyfunction!(init, m)?)?;
224    m.add_function(wrap_pyfunction!(reinit_for_testing, m)?)?;
225    m.add_function(wrap_pyfunction!(init_with_entropy, m)?)?;
226    m.add_function(wrap_pyfunction!(get_xpub, m)?)?;
227    m.add_function(wrap_pyfunction!(get_public_key, m)?)?;
228    m.add_function(wrap_pyfunction!(get_address, m)?)?;
229    m.add_function(wrap_pyfunction!(verify_public_key, m)?)?;
230    m.add_function(wrap_pyfunction!(sign_hash_ecdsa, m)?)?;
231    m.add_function(wrap_pyfunction!(create_deterministic_nonce, m)?)?;
232    m.add_function(wrap_pyfunction!(sign_schnorr_with_nonce, m)?)?;
233    m.add_function(wrap_pyfunction!(verify_schnorr, m)?)?;
234    m.add_function(wrap_pyfunction!(combine_pubkeys, m)?)?;
235    m.add_function(wrap_pyfunction!(combine_seckeys, m)?)?;
236    m.add_function(wrap_pyfunction!(create_cet_adaptor_sigs, m)?)?;
237    m.add_function(wrap_pyfunction!(verify_cet_adaptor_sigs, m)?)?;
238    m.add_function(wrap_pyfunction!(create_final_cet_sigs, m)?)?;
239    m.add_function(wrap_pyfunction!(create_final_cet_sig, m)?)?;
240    Ok(())
241}