From b9c57bb1589422fb5a4ca9d56e852b02c8cbcd65 Mon Sep 17 00:00:00 2001 From: optout <13562139+optout21@users.noreply.github.com> Date: Tue, 16 Dec 2025 19:20:44 +0100 Subject: [PATCH 1/7] Provide Python library; WIP --- README.md | 14 +++ lib-py/Cargo.toml | 13 +++ lib-py/requirements.txt | 2 + lib-py/src/lib.rs | 192 ++++++++++++++++++++++++++++++++ samples/python/main.py | 21 ++++ samples/python/requirements.txt | 2 + src/lib.rs | 2 +- 7 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 lib-py/Cargo.toml create mode 100644 lib-py/requirements.txt create mode 100644 lib-py/src/lib.rs create mode 100644 samples/python/main.py create mode 100644 samples/python/requirements.txt diff --git a/README.md b/README.md index 703c66c..158e905 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,20 @@ To build and test in Rust: cargo build && cargo test ``` +Publish the library: + +``` +cargo publish +``` + +To build the Python-wrapper library: + +``` +cd lib-py +./venv/bin/pip install -r requirements.txt +VIRTUAL_ENV="./venv" ./venv/bin/maturin develop +``` + ## Samples ``` diff --git a/lib-py/Cargo.toml b/lib-py/Cargo.toml new file mode 100644 index 0000000..7463c8a --- /dev/null +++ b/lib-py/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "dlccryptlib-py" +version = "0.3.2" +edition = "2021" +description = "Python-wrapped library for working with DLC's with adaptor signatures (Discrete Log Contracts), by Cadena Bitcoin" +license = "MIT" + +[lib] +name = "dlccryptlib_py" + +[dependencies] +dlccryptlib = { path = "../" } +pyo3 = { version = "0.23.1" } diff --git a/lib-py/requirements.txt b/lib-py/requirements.txt new file mode 100644 index 0000000..b8be672 --- /dev/null +++ b/lib-py/requirements.txt @@ -0,0 +1,2 @@ +# for Rust +maturin diff --git a/lib-py/src/lib.rs b/lib-py/src/lib.rs new file mode 100644 index 0000000..9062261 --- /dev/null +++ b/lib-py/src/lib.rs @@ -0,0 +1,192 @@ +use dlccryptlib; + +use pyo3::prelude::*; +use pyo3::exceptions::PyException; +use pyo3::wrap_pyfunction; + + +// ##### Facade functions for easy Python invocations (pyo3/maturin) + +/// Initialize the library, load secret from encrypted file. Return the XPUB. +#[pyfunction] +pub fn init(path_for_secret_file: String, encryption_password: String) -> PyResult { + dlccryptlib::init_intern(&path_for_secret_file, &encryption_password, false) + .map_err(|e| PyErr::new::(e)) +} + +#[pyfunction] +pub fn reinit_for_testing( + path_for_secret_file: String, + encryption_password: String, +) -> PyResult { + dlccryptlib::init_intern(&path_for_secret_file, &encryption_password, true) + .map_err(|e| PyErr::new::(e)) +} + +/// network: "bitcoin", or "signet". +// #[cfg(test)] +#[pyfunction] +pub fn init_with_entropy(entropy: String, network: String) -> PyResult { + dlccryptlib::init_with_entropy_intern(&entropy, &network).map_err(|e| PyErr::new::(e)) +} + +/// Return the XPUB +#[pyfunction] +pub fn get_xpub() -> PyResult { + dlccryptlib::get_xpub_intern().map_err(|e| PyErr::new::(e)) +} + +/// Return a child public key (specified by its index). +#[pyfunction] +pub fn get_public_key(index: u32) -> PyResult { + dlccryptlib::get_public_key_intern(index).map_err(|e| PyErr::new::(e)) +} + +/// Return a child address (specified by index). +#[pyfunction] +pub fn get_address(index: u32) -> PyResult { + dlccryptlib::get_address_intern(index).map_err(|e| PyErr::new::(e)) +} + +/// Verify a child public key. +#[pyfunction] +pub fn verify_public_key(index: u32, pubkey: String) -> PyResult { + dlccryptlib::verify_public_key_intern(index, &pubkey).map_err(|e| PyErr::new::(e)) +} + +/// Sign a hash with a child private key (specified by index). +#[pyfunction] +pub fn sign_hash_ecdsa(hash: String, signer_index: u32, signer_pubkey: String) -> PyResult { + dlccryptlib::sign_hash_ecdsa_intern(&hash, signer_index, &signer_pubkey) + .map_err(|e| PyErr::new::(e)) +} + +/// Create a nonce value deterministically +#[pyfunction] +pub fn create_deterministic_nonce( + event_id: String, + nonce_index: u32, +) -> PyResult<(String, String)> { + dlccryptlib::create_deterministic_nonce_intern(&event_id, nonce_index) + .map_err(|e| PyErr::new::(e)) +} + +/// Sign a message using Schnorr, with a nonce, using a child key +#[pyfunction] +pub fn sign_schnorr_with_nonce(msg: String, nonce_sec_hex: String, index: u32) -> PyResult { + dlccryptlib::sign_schnorr_with_nonce_intern(&msg, &nonce_sec_hex, index) + .map_err(|e| PyErr::new::(e)) +} + +/// Combine a number of public keys into one +#[pyfunction] +pub fn combine_pubkeys(keys_hex: String) -> PyResult { + dlccryptlib::combine_pubkeys_intern(&keys_hex).map_err(|e| PyErr::new::(e)) +} + +/// Combine a number of secret keys into one. +/// Warning: Handle secret keys with caution! +#[pyfunction] +pub fn combine_seckeys(keys_hex: String) -> PyResult { + dlccryptlib::combine_seckeys_intern(&keys_hex).map_err(|e| PyErr::new::(e)) +} + +/// Create adaptor signatures for a number of CETs +#[pyfunction] +pub fn create_cet_adaptor_sigs( + num_digits: u8, + num_cets: u64, + digit_string_template: String, + oracle_pubkey: String, + signing_key_index: u32, + signing_pubkey: String, + nonces: String, + interval_wildcards: String, + sighashes: String, +) -> PyResult { + dlccryptlib::create_cet_adaptor_sigs_intern( + num_digits, + num_cets, + &digit_string_template, + &oracle_pubkey, + signing_key_index, + &signing_pubkey, + &nonces, + &interval_wildcards, + &sighashes, + ) + .map_err(|e| PyErr::new::(e)) +} + +/// Verify adaptor signatures for a number of CETs +#[pyfunction] +pub fn verify_cet_adaptor_sigs( + num_digits: u8, + num_cets: u64, + digit_string_template: String, + oracle_pubkey: String, + signing_pubkey: String, + nonces: String, + interval_wildcards: String, + sighashes: String, + signatures: String, +) -> PyResult { + dlccryptlib::verify_cet_adaptor_sigs_intern( + num_digits, + num_cets, + &digit_string_template, + &oracle_pubkey, + &signing_pubkey, + &nonces, + &interval_wildcards, + &sighashes, + &signatures, + ) + .map_err(|e| PyErr::new::(e)) +} + +/// Perform final signing of a CET +#[pyfunction] +pub fn create_final_cet_sigs( + signing_key_index: u32, + signing_pubkey: String, + other_pubkey: String, + num_digits: u8, + oracle_signatures: String, + cet_value_wildcard: String, + cet_sighash: String, + other_adaptor_signature: String, +) -> PyResult { + dlccryptlib::create_final_cet_sigs_intern( + signing_key_index, + &signing_pubkey, + &other_pubkey, + num_digits, + &oracle_signatures, + &cet_value_wildcard, + &cet_sighash, + &other_adaptor_signature, + ) + .map_err(|e| PyErr::new::(e)) +} + +#[pymodule] +fn dlccryptlib_py(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { + m.add_function(wrap_pyfunction!(init, m)?)?; + m.add_function(wrap_pyfunction!(reinit_for_testing, m)?)?; + m.add_function(wrap_pyfunction!(init_with_entropy, m)?)?; + m.add_function(wrap_pyfunction!(get_xpub, m)?)?; + m.add_function(wrap_pyfunction!(get_public_key, m)?)?; + m.add_function(wrap_pyfunction!(get_address, m)?)?; + m.add_function(wrap_pyfunction!(verify_public_key, m)?)?; + m.add_function(wrap_pyfunction!(sign_hash_ecdsa, m)?)?; + m.add_function(wrap_pyfunction!(create_deterministic_nonce, m)?)?; + m.add_function(wrap_pyfunction!(sign_schnorr_with_nonce, m)?)?; + m.add_function(wrap_pyfunction!(combine_pubkeys, m)?)?; + m.add_function(wrap_pyfunction!(combine_seckeys, m)?)?; + m.add_function(wrap_pyfunction!(create_cet_adaptor_sigs, m)?)?; + m.add_function(wrap_pyfunction!(verify_cet_adaptor_sigs, m)?)?; + m.add_function(wrap_pyfunction!(create_final_cet_sigs, m)?)?; + Ok(()) +} + diff --git a/samples/python/main.py b/samples/python/main.py new file mode 100644 index 0000000..f46aa7d --- /dev/null +++ b/samples/python/main.py @@ -0,0 +1,21 @@ +import dlccryptlib + +def sample(): + print("Dlccryptlib sample app, Python") + + entropy_hex = "99d33a674ce99d33a674ce99d33a674c" # oil x 12 + network = "signet"; + + xpub = dlccryptlib.init_with_entropy(entropy_hex, network) + print(f"Library initialized, xpub {xpub}") + + pubkey0 = dlccryptlib.get_public_key(0) + print(f"pubkey 0: {pubkey0}") + + hash = "0001020300000000000000000000000000000000000000000000000000010203" + sig = dlccryptlib.sign_hash_ecdsa(hash, 0, pubkey0) + print(f"signature: {sig}") + +if __name__ == "__main__": + sample() + diff --git a/samples/python/requirements.txt b/samples/python/requirements.txt new file mode 100644 index 0000000..0956260 --- /dev/null +++ b/samples/python/requirements.txt @@ -0,0 +1,2 @@ +dlccryptlib-py + diff --git a/src/lib.rs b/src/lib.rs index c86c533..e7c495c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -749,7 +749,7 @@ pub fn create_final_cet_sigs( #[cfg(feature = "with-pyo3")] #[pymodule] -fn dlcplazacryptlib(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { +fn dlccryptlib(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(init, m)?)?; m.add_function(wrap_pyfunction!(reinit_for_testing, m)?)?; m.add_function(wrap_pyfunction!(init_with_entropy, m)?)?; From 9c66849664bd25e1239f23dc08a0f36794220cd8 Mon Sep 17 00:00:00 2001 From: optout <13562139+optout21@users.noreply.github.com> Date: Tue, 16 Dec 2025 19:22:06 +0100 Subject: [PATCH 2/7] Cleanup --- Cargo.toml | 3 - src/lib.rs | 210 ----------------------------------------------------- 2 files changed, 213 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 231c067..4d0fb64 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,12 +13,9 @@ crate-type = ["cdylib", "rlib"] [dependencies] bip39 = "2.1.0" bitcoin = "0.32.4" -pyo3 = { version = "0.23.1", optional = true } secp256k1-sys = "0.10.1" secp256k1-zkp = "0.11.0" [features] default = ["std"] std = ["bitcoin/std", "secp256k1-zkp/rand-std"] -# To compile with Python interfacing methods -with-pyo3 = ["pyo3"] diff --git a/src/lib.rs b/src/lib.rs index e7c495c..7bfc2f8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -558,213 +558,3 @@ fn error_as_cstr_prefix(error: String) -> *mut c_char { .into_raw() } -// Conditional compilation to exclude PyO3-related code for Android -#[cfg(feature = "with-pyo3")] -use pyo3::prelude::*; -#[cfg(feature = "with-pyo3")] -use pyo3::exceptions::PyException; -#[cfg(feature = "with-pyo3")] -use pyo3::wrap_pyfunction; - - -// ##### Facade functions for easy Python invocations (pyo3/maturin) - -/// Initialize the library, load secret from encrypted file. Return the XPUB. -#[cfg(feature = "with-pyo3")] -#[pyfunction] -pub fn init(path_for_secret_file: String, encryption_password: String) -> PyResult { - init_intern(&path_for_secret_file, &encryption_password, false) - .map_err(|e| PyErr::new::(e)) -} - -#[cfg(feature = "with-pyo3")] -#[pyfunction] -pub fn reinit_for_testing( - path_for_secret_file: String, - encryption_password: String, -) -> PyResult { - init_intern(&path_for_secret_file, &encryption_password, true) - .map_err(|e| PyErr::new::(e)) -} - -/// network: "bitcoin", or "signet". -// #[cfg(test)] -#[cfg(feature = "with-pyo3")] -#[pyfunction] -pub fn init_with_entropy(entropy: String, network: String) -> PyResult { - init_with_entropy_intern(&entropy, &network).map_err(|e| PyErr::new::(e)) -} - -/// Return the XPUB -#[cfg(feature = "with-pyo3")] -#[pyfunction] -pub fn get_xpub() -> PyResult { - get_xpub_intern().map_err(|e| PyErr::new::(e)) -} - -/// Return a child public key (specified by its index). -#[cfg(feature = "with-pyo3")] -#[pyfunction] -pub fn get_public_key(index: u32) -> PyResult { - get_public_key_intern(index).map_err(|e| PyErr::new::(e)) -} - -/// Return a child address (specified by index). -#[cfg(feature = "with-pyo3")] -#[pyfunction] -pub fn get_address(index: u32) -> PyResult { - get_address_intern(index).map_err(|e| PyErr::new::(e)) -} - -/// Verify a child public key. -#[cfg(feature = "with-pyo3")] -#[pyfunction] -pub fn verify_public_key(index: u32, pubkey: String) -> PyResult { - verify_public_key_intern(index, &pubkey).map_err(|e| PyErr::new::(e)) -} - -/// Sign a hash with a child private key (specified by index). -#[cfg(feature = "with-pyo3")] -#[pyfunction] -pub fn sign_hash_ecdsa(hash: String, signer_index: u32, signer_pubkey: String) -> PyResult { - sign_hash_ecdsa_intern(&hash, signer_index, &signer_pubkey) - .map_err(|e| PyErr::new::(e)) -} - -/// Create a nonce value deterministically -#[cfg(feature = "with-pyo3")] -#[pyfunction] -pub fn create_deterministic_nonce( - event_id: String, - nonce_index: u32, -) -> PyResult<(String, String)> { - create_deterministic_nonce_intern(&event_id, nonce_index) - .map_err(|e| PyErr::new::(e)) -} - -/// Sign a message using Schnorr, with a nonce, using a child key -#[cfg(feature = "with-pyo3")] -#[pyfunction] -pub fn sign_schnorr_with_nonce(msg: String, nonce_sec_hex: String, index: u32) -> PyResult { - sign_schnorr_with_nonce_intern(&msg, &nonce_sec_hex, index) - .map_err(|e| PyErr::new::(e)) -} - -/// Combine a number of public keys into one -#[cfg(feature = "with-pyo3")] -#[pyfunction] -pub fn combine_pubkeys(keys_hex: String) -> PyResult { - combine_pubkeys_intern(&keys_hex).map_err(|e| PyErr::new::(e)) -} - -/// Combine a number of secret keys into one. -/// Warning: Handle secret keys with caution! -#[cfg(feature = "with-pyo3")] -#[pyfunction] -pub fn combine_seckeys(keys_hex: String) -> PyResult { - combine_seckeys_intern(&keys_hex).map_err(|e| PyErr::new::(e)) -} - -/// Create adaptor signatures for a number of CETs -#[cfg(feature = "with-pyo3")] -#[pyfunction] -pub fn create_cet_adaptor_sigs( - num_digits: u8, - num_cets: u64, - digit_string_template: String, - oracle_pubkey: String, - signing_key_index: u32, - signing_pubkey: String, - nonces: String, - interval_wildcards: String, - sighashes: String, -) -> PyResult { - create_cet_adaptor_sigs_intern( - num_digits, - num_cets, - &digit_string_template, - &oracle_pubkey, - signing_key_index, - &signing_pubkey, - &nonces, - &interval_wildcards, - &sighashes, - ) - .map_err(|e| PyErr::new::(e)) -} - -/// Verify adaptor signatures for a number of CETs -#[cfg(feature = "with-pyo3")] -#[pyfunction] -pub fn verify_cet_adaptor_sigs( - num_digits: u8, - num_cets: u64, - digit_string_template: String, - oracle_pubkey: String, - signing_pubkey: String, - nonces: String, - interval_wildcards: String, - sighashes: String, - signatures: String, -) -> PyResult { - verify_cet_adaptor_sigs_intern( - num_digits, - num_cets, - &digit_string_template, - &oracle_pubkey, - &signing_pubkey, - &nonces, - &interval_wildcards, - &sighashes, - &signatures, - ) - .map_err(|e| PyErr::new::(e)) -} - -/// Perform final signing of a CET -#[cfg(feature = "with-pyo3")] -#[pyfunction] -pub fn create_final_cet_sigs( - signing_key_index: u32, - signing_pubkey: String, - other_pubkey: String, - num_digits: u8, - oracle_signatures: String, - cet_value_wildcard: String, - cet_sighash: String, - other_adaptor_signature: String, -) -> PyResult { - create_final_cet_sigs_intern( - signing_key_index, - &signing_pubkey, - &other_pubkey, - num_digits, - &oracle_signatures, - &cet_value_wildcard, - &cet_sighash, - &other_adaptor_signature, - ) - .map_err(|e| PyErr::new::(e)) -} - -#[cfg(feature = "with-pyo3")] -#[pymodule] -fn dlccryptlib(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { - m.add_function(wrap_pyfunction!(init, m)?)?; - m.add_function(wrap_pyfunction!(reinit_for_testing, m)?)?; - m.add_function(wrap_pyfunction!(init_with_entropy, m)?)?; - m.add_function(wrap_pyfunction!(get_xpub, m)?)?; - m.add_function(wrap_pyfunction!(get_public_key, m)?)?; - m.add_function(wrap_pyfunction!(get_address, m)?)?; - m.add_function(wrap_pyfunction!(verify_public_key, m)?)?; - m.add_function(wrap_pyfunction!(sign_hash_ecdsa, m)?)?; - m.add_function(wrap_pyfunction!(create_deterministic_nonce, m)?)?; - m.add_function(wrap_pyfunction!(sign_schnorr_with_nonce, m)?)?; - m.add_function(wrap_pyfunction!(combine_pubkeys, m)?)?; - m.add_function(wrap_pyfunction!(combine_seckeys, m)?)?; - m.add_function(wrap_pyfunction!(create_cet_adaptor_sigs, m)?)?; - m.add_function(wrap_pyfunction!(verify_cet_adaptor_sigs, m)?)?; - m.add_function(wrap_pyfunction!(create_final_cet_sigs, m)?)?; - Ok(()) -} - From f8d565f55fdc65929d238390b5d339ec582a8e41 Mon Sep 17 00:00:00 2001 From: optout <13562139+optout21@users.noreply.github.com> Date: Tue, 16 Dec 2025 19:27:20 +0100 Subject: [PATCH 3/7] Python CI --- .github/workflows/build_python.yml | 28 ++++++++++++++++++++++++++++ .github/workflows/build_test.yml | 4 +--- 2 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/build_python.yml diff --git a/.github/workflows/build_python.yml b/.github/workflows/build_python.yml new file mode 100644 index 0000000..fe9d021 --- /dev/null +++ b/.github/workflows/build_python.yml @@ -0,0 +1,28 @@ +name: Rust + +on: + push: + branches: [ "main", "develop", "staging" ] + pull_request: + branches: [ "main", "develop", "staging" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - name: Set up Rust + run: sudo apt-get install cargo && rustup override set 1.81 + - name: Set up Python + run: sudo apt-get install python3 python3-dev + - uses: actions/checkout@v4 + - name: Set up a Python virtual environment (needed for maturin) + run: python3 -m venv ./venv + - name: Install Python deps + run: ./venv/bin/pip3 install -r ./lib-py/requirements.txt + - name: Build the Rust library, install it as a Python module + run: cd lib-py && VIRTUAL_ENV='../venv' ../venv/bin/maturin develop && cd .. diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml index 2c96b9d..4bc2845 100644 --- a/.github/workflows/build_test.yml +++ b/.github/workflows/build_test.yml @@ -1,4 +1,4 @@ -name: Rust +name: Rust-Python on: push: @@ -20,8 +20,6 @@ jobs: - uses: actions/checkout@v4 - name: Build the library run: cargo build - - name: Build with pyo3 - run: cargo build --features with-pyo3 - name: Run unit tests run: cargo test - name: Build and run sample/rust From 96e109c608416769972530a56d0bd953ed320884 Mon Sep 17 00:00:00 2001 From: optout <13562139+optout21@users.noreply.github.com> Date: Tue, 16 Dec 2025 19:30:00 +0100 Subject: [PATCH 4/7] Name fix --- .github/workflows/build_python.yml | 2 +- .github/workflows/build_test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_python.yml b/.github/workflows/build_python.yml index fe9d021..9d5521d 100644 --- a/.github/workflows/build_python.yml +++ b/.github/workflows/build_python.yml @@ -1,4 +1,4 @@ -name: Rust +name: Rust-Python on: push: diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml index 4bc2845..ba7611e 100644 --- a/.github/workflows/build_test.yml +++ b/.github/workflows/build_test.yml @@ -1,4 +1,4 @@ -name: Rust-Python +name: Rust on: push: From 9eb0e3250dc4b751e780f33028c19f3a830580f1 Mon Sep 17 00:00:00 2001 From: optout <13562139+optout21@users.noreply.github.com> Date: Tue, 16 Dec 2025 19:32:35 +0100 Subject: [PATCH 5/7] Python CI: run sample app --- .github/workflows/build_python.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build_python.yml b/.github/workflows/build_python.yml index 9d5521d..7090768 100644 --- a/.github/workflows/build_python.yml +++ b/.github/workflows/build_python.yml @@ -26,3 +26,5 @@ jobs: run: ./venv/bin/pip3 install -r ./lib-py/requirements.txt - name: Build the Rust library, install it as a Python module run: cd lib-py && VIRTUAL_ENV='../venv' ../venv/bin/maturin develop && cd .. + - name: Run the Python sample app + run: cd samples/python && ../../venv/bin/python main.py && cd ../.. From 5b8a1986124092796dec692d91eaf326924d7722 Mon Sep 17 00:00:00 2001 From: optout <13562139+optout21@users.noreply.github.com> Date: Tue, 16 Dec 2025 19:34:26 +0100 Subject: [PATCH 6/7] Python sample app fix --- samples/python/main.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/samples/python/main.py b/samples/python/main.py index f46aa7d..df8fcb9 100644 --- a/samples/python/main.py +++ b/samples/python/main.py @@ -1,4 +1,4 @@ -import dlccryptlib +import dlccryptlib_py def sample(): print("Dlccryptlib sample app, Python") @@ -6,14 +6,14 @@ def sample(): entropy_hex = "99d33a674ce99d33a674ce99d33a674c" # oil x 12 network = "signet"; - xpub = dlccryptlib.init_with_entropy(entropy_hex, network) + xpub = dlccryptlib_py.init_with_entropy(entropy_hex, network) print(f"Library initialized, xpub {xpub}") - pubkey0 = dlccryptlib.get_public_key(0) + pubkey0 = dlccryptlib_py.get_public_key(0) print(f"pubkey 0: {pubkey0}") hash = "0001020300000000000000000000000000000000000000000000000000010203" - sig = dlccryptlib.sign_hash_ecdsa(hash, 0, pubkey0) + sig = dlccryptlib_py.sign_hash_ecdsa(hash, 0, pubkey0) print(f"signature: {sig}") if __name__ == "__main__": From 0150ca36997b1e3c01eecae407e171373bac93bd Mon Sep 17 00:00:00 2001 From: optout <13562139+optout21@users.noreply.github.com> Date: Tue, 16 Dec 2025 22:58:20 +0100 Subject: [PATCH 7/7] Set lib versions, 0.9.0 --- Cargo.toml | 2 +- lib-py/Cargo.toml | 3 ++- samples/rust/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4d0fb64..1e81773 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dlccryptlib" -version = "0.3.2" +version = "0.9.0" edition = "2021" description = "Library for working with DLC's with adaptor signatures (Discrete Log Contracts), by Cadena Bitcoin" license = "MIT" diff --git a/lib-py/Cargo.toml b/lib-py/Cargo.toml index 7463c8a..a92ac30 100644 --- a/lib-py/Cargo.toml +++ b/lib-py/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dlccryptlib-py" -version = "0.3.2" +version = "0.9.0" edition = "2021" description = "Python-wrapped library for working with DLC's with adaptor signatures (Discrete Log Contracts), by Cadena Bitcoin" license = "MIT" @@ -9,5 +9,6 @@ license = "MIT" name = "dlccryptlib_py" [dependencies] +#dlccryptlib = "0.9.0" dlccryptlib = { path = "../" } pyo3 = { version = "0.23.1" } diff --git a/samples/rust/Cargo.toml b/samples/rust/Cargo.toml index f1d86f4..57767ab 100644 --- a/samples/rust/Cargo.toml +++ b/samples/rust/Cargo.toml @@ -4,5 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies] -#dlccryptlib = "0.3.2" +#dlccryptlib = "0.9.0" dlccryptlib = { path = "../../" }