Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "dlccryptlib"
version = "1.0.0"
version = "1.9.0"
edition = "2021"
description = "Library for working with DLC's with adaptor signatures (Discrete Log Contracts), by Cadena Bitcoin"
license = "MIT"
Expand Down
4 changes: 2 additions & 2 deletions lib-py/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "dlccryptlib-py"
version = "1.0.0"
version = "1.9.0"
edition = "2021"
description = "Python-wrapped library for working with DLC's with adaptor signatures (Discrete Log Contracts), by Cadena Bitcoin"
license = "MIT"
Expand All @@ -9,6 +9,6 @@ license = "MIT"
name = "dlccryptlib_py"

[dependencies]
#dlccryptlib = "1.0.0"
#dlccryptlib = "1.9.0"
dlccryptlib = { path = "../" }
pyo3 = { version = "0.23.1" }
36 changes: 20 additions & 16 deletions lib-py/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,26 @@ pub fn get_xpub() -> PyResult<String> {

/// Return a child public key (specified by its index).
#[pyfunction]
pub fn get_public_key(index: u32) -> PyResult<String> {
dlccryptlib::get_public_key(index).map_err(|e| PyErr::new::<PyException, _>(e))
pub fn get_public_key(index4: u32, index5: u32) -> PyResult<String> {
dlccryptlib::get_public_key(index4, index5).map_err(|e| PyErr::new::<PyException, _>(e))
}

/// Return a child address (specified by index).
#[pyfunction]
pub fn get_address(index: u32) -> PyResult<String> {
dlccryptlib::get_address(index).map_err(|e| PyErr::new::<PyException, _>(e))
pub fn get_address(index4: u32, index5: u32) -> PyResult<String> {
dlccryptlib::get_address(index4, index5).map_err(|e| PyErr::new::<PyException, _>(e))
}

/// Verify a child public key.
#[pyfunction]
pub fn verify_public_key(index: u32, pubkey: String) -> PyResult<bool> {
dlccryptlib::verify_public_key(index, &pubkey).map_err(|e| PyErr::new::<PyException, _>(e))
pub fn verify_public_key(index4: u32, index5: u32, pubkey: String) -> PyResult<bool> {
dlccryptlib::verify_public_key(index4, index5, &pubkey).map_err(|e| PyErr::new::<PyException, _>(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<String> {
dlccryptlib::sign_hash_ecdsa(&hash, signer_index, &signer_pubkey)
pub fn sign_hash_ecdsa(hash: String, signer_index4: u32, signer_index5: u32, signer_pubkey: String) -> PyResult<String> {
dlccryptlib::sign_hash_ecdsa(&hash, signer_index4, signer_index5, &signer_pubkey)
.map_err(|e| PyErr::new::<PyException, _>(e))
}

Expand All @@ -73,15 +73,15 @@ pub fn create_deterministic_nonce(

/// 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<String> {
dlccryptlib::sign_schnorr_with_nonce(&msg, &nonce_sec_hex, index)
pub fn sign_schnorr_with_nonce(msg: String, nonce_sec_hex: String, index4: u32, index5: u32) -> PyResult<String> {
dlccryptlib::sign_schnorr_with_nonce(&msg, &nonce_sec_hex, index4, index5)
.map_err(|e| PyErr::new::<PyException, _>(e))
}

/// Verify a Schnorr signature over a message, using a child key
#[pyfunction]
pub fn verify_schnorr(msg: String, signature_hex: String, index: u32) -> PyResult<bool> {
dlccryptlib::verify_schnorr(&msg, &signature_hex, index)
pub fn verify_schnorr(msg: String, signature_hex: String, index4: u32, index5: u32) -> PyResult<bool> {
dlccryptlib::verify_schnorr(&msg, &signature_hex, index4, index5)
.map_err(|e| PyErr::new::<PyException, _>(e))
}

Expand All @@ -105,7 +105,8 @@ pub fn create_cet_adaptor_sigs(
num_cets: u64,
digit_string_template: String,
oracle_pubkey: String,
signing_key_index: u32,
signing_key_index4: u32,
signing_key_index5: u32,
signing_pubkey: String,
nonces: String,
interval_wildcards: String,
Expand All @@ -116,7 +117,8 @@ pub fn create_cet_adaptor_sigs(
num_cets,
&digit_string_template,
&oracle_pubkey,
signing_key_index,
signing_key_index4,
signing_key_index5,
&signing_pubkey,
&nonces,
&interval_wildcards,
Expand Down Expand Up @@ -155,7 +157,8 @@ pub fn verify_cet_adaptor_sigs(
/// Perform final signing of a CET
#[pyfunction]
pub fn create_final_cet_sigs(
signing_key_index: u32,
signing_key_index4: u32,
signing_key_index5: u32,
signing_pubkey: String,
other_pubkey: String,
num_digits: u8,
Expand All @@ -165,7 +168,8 @@ pub fn create_final_cet_sigs(
other_adaptor_signature: String,
) -> PyResult<String> {
dlccryptlib::create_final_cet_sigs(
signing_key_index,
signing_key_index4,
signing_key_index5,
&signing_pubkey,
&other_pubkey,
num_digits,
Expand Down
4 changes: 2 additions & 2 deletions samples/python/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ def sample():
xpub = dlccryptlib_py.init_with_entropy(entropy_hex, network)
print(f"Library initialized, xpub {xpub}")

pubkey0 = dlccryptlib_py.get_public_key(0)
pubkey0 = dlccryptlib_py.get_public_key(0, 0)
print(f"pubkey 0: {pubkey0}")

hash = "0001020300000000000000000000000000000000000000000000000000010203"
sig = dlccryptlib_py.sign_hash_ecdsa(hash, 0, pubkey0)
sig = dlccryptlib_py.sign_hash_ecdsa(hash, 0, 0, pubkey0)
print(f"signature: {sig}")

if __name__ == "__main__":
Expand Down
10 changes: 5 additions & 5 deletions samples/python/test_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@

xpub = dlccryptlib_py.get_xpub()
print('Xpub', xpub)
pubkey0 = dlccryptlib_py.get_public_key(0)
pubkey0 = dlccryptlib_py.get_public_key(0, 0)
print('Pubkey 0', pubkey0)
address0 = dlccryptlib_py.get_address(0)
address0 = dlccryptlib_py.get_address(0, 0)
print('Address 0', address0)

event_id = "event001"
Expand All @@ -25,11 +25,11 @@
nonce2_arr = dlccryptlib_py.create_deterministic_nonce(event_id, 2)

# Sign the event id with nonce1
sig = dlccryptlib_py.sign_schnorr_with_nonce(event_id, nonce1_sec, 0)
sig = dlccryptlib_py.sign_schnorr_with_nonce(event_id, nonce1_sec, 0, 0)
print('Signature: ', sig)

# Sign again (same nonce)
print('Sign again: ', dlccryptlib_py.sign_schnorr_with_nonce(event_id, nonce1_sec, 0))
print('Sign again: ', dlccryptlib_py.sign_schnorr_with_nonce(event_id, nonce1_sec, 0, 0))

# Sign with different nonce
print('Sign with other nonce: ', dlccryptlib_py.sign_schnorr_with_nonce(event_id, nonce2_arr[0], 0))
print('Sign with other nonce: ', dlccryptlib_py.sign_schnorr_with_nonce(event_id, nonce2_arr[0], 0, 0))
26 changes: 13 additions & 13 deletions samples/python/test_lib_c.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ def __init__(self):
# Define Rust method signatures
self.lib.init_with_entropy_c.argtypes = [c_char_p, c_char_p]
self.lib.init_with_entropy_c.restype = c_char_p
self.lib.get_public_key_c.argtypes = [c_uint32]
self.lib.get_public_key_c.argtypes = [c_uint32, c_uint32]
self.lib.get_public_key_c.restype = c_char_p
self.lib.sign_hash_ecdsa_c.argtypes = [c_char_p, c_uint32, c_char_p]
self.lib.sign_hash_ecdsa_c.argtypes = [c_char_p, c_uint32, c_uint32, c_char_p]
self.lib.sign_hash_ecdsa_c.restype = c_char_p
self.lib.create_cet_adaptor_sigs_c.argtypes = [c_uint8, c_uint32, c_char_p, c_char_p, c_uint32, c_char_p, c_char_p, c_char_p, c_char_p]
self.lib.create_cet_adaptor_sigs_c.argtypes = [c_uint8, c_uint32, c_char_p, c_char_p, c_uint32, c_uint32, c_char_p, c_char_p, c_char_p, c_char_p]
self.lib.create_cet_adaptor_sigs_c.restype = c_char_p
self.lib.create_deterministic_nonce_c.argtypes = [c_char_p, c_char_p]
self.lib.create_deterministic_nonce_c.restype = c_char_p
Expand All @@ -43,19 +43,19 @@ def init_with_entropy(self, entropy, network):
return self.lib.init_with_entropy_c(entropy.encode('utf-8'), network.encode('utf-8')).decode("utf-8")

# Sign a hash with a child private key (specified by index).
def sign_hash_ecdsa(self, hash, signer_index, signer_pubkey):
def sign_hash_ecdsa(self, hash, signer_index4, signer_index5, signer_pubkey):
# Call the Rust function (sign_hash_ecdsa_c) from the .so library
return self.lib.sign_hash_ecdsa_c(hash.encode('utf-8'), signer_index, signer_pubkey.encode('utf-8')).decode('utf-8')
return self.lib.sign_hash_ecdsa_c(hash.encode('utf-8'), signer_index4, signer_index5, signer_pubkey.encode('utf-8')).decode('utf-8')

# Create adaptor signatures for a number of CETs
def create_cet_adaptor_sigs(self, num_digits: int, num_cets: int, digit_string_template: str, oracle_pubkey: str, signing_key_index: int, signing_pubkey: str, nonces: str, interval_wildcards: str, sighashes: str):
def create_cet_adaptor_sigs(self, num_digits: int, num_cets: int, digit_string_template: str, oracle_pubkey: str, signing_key_index4: int, signing_key_index5, signing_pubkey: str, nonces: str, interval_wildcards: str, sighashes: str):
# Call the Rust function (create_cet_adaptor_sigs_c) from the .so library
return self.lib.create_cet_adaptor_sigs_c(num_digits, num_cets, digit_string_template.encode('utf-8'), oracle_pubkey.encode('utf-8'), signing_key_index, signing_pubkey.encode('utf-8'), nonces.encode('utf-8'), interval_wildcards.encode('utf-8'), sighashes.encode('utf-8')).decode('utf-8')
return self.lib.create_cet_adaptor_sigs_c(num_digits, num_cets, digit_string_template.encode('utf-8'), oracle_pubkey.encode('utf-8'), signing_key_index4, signing_key_index5, signing_pubkey.encode('utf-8'), nonces.encode('utf-8'), interval_wildcards.encode('utf-8'), sighashes.encode('utf-8')).decode('utf-8')

# Return a child public key.
def get_public_key(self, index):
def get_public_key(self, index4, index5):
# Call the Rust function (get_public_key_c) from the .so library
return self.lib.get_public_key_c(index).decode("utf-8")
return self.lib.get_public_key_c(index4, index5).decode("utf-8")

def create_deterministic_nonce(self, event_id, index):
# Call the Rust function (create_deterministic_nonce_c) from the .so library
Expand All @@ -75,12 +75,12 @@ def create_deterministic_nonce(self, event_id, index):
print("xpub:", xpub)
assert(xpub == "tpubDCxVvuZwEu4oZypCT3pzos1MUoVJyjTHjfrhKFXNBkAEqBmkkzEb2dUgzpZmBWbd6wZnNmm3Ex2suMnEFUMmayH2a6S49R4pTnoQttGrxUm")

pubkey0 = rust_interface.get_public_key(0)
print("pubkey 0:", pubkey0)
pubkey0 = rust_interface.get_public_key(0, 0)
print("pubkey 0/0:", pubkey0)
assert(pubkey0 == "031941e84b8d111e094aefc46e7181757c93a1da87c93ab519a40d9d765176e704")

hash = "0001020300000000000000000000000000000000000000000000000000010203"
sig = rust_interface.sign_hash_ecdsa(hash, 0, pubkey0)
sig = rust_interface.sign_hash_ecdsa(hash, 0, 0, pubkey0)
print("sig:", sig)


Expand All @@ -89,7 +89,7 @@ def create_deterministic_nonce(self, event_id, index):
nonces = "03bf8272fd77ac83400e8b7f1af5899ab96ce81871ca26d31fa3b80db08bdc412e 03ec14b379b5db0c5305a452ee04d4b82b5a1db90f8eddc55f1f94d5947b341ed4 0325642feb3db37b3ffa88b0754d59ad1c3116e035ee9e5557e107fd3d914fb3fb 02d597f9bd84cb925ade7efa04edf46c33a7d96cc4252647204a6961a34838d00d 03d11c778b1c4f1f7710a4b17816f02d049325220b2fb8007efd84248f08fd75dc 038fb0dbd6eb0e970c75c28ca02b614523fe59b5da000f815fcfbfcf4a4ecdd192 023f0eadc3b9c3337d31e38a9238a3c59505cc8004fa7ca6facdd3c853d824ca0d"
interval_wildcards = "0000*** 0001*** 0002***"
sighashes = "0001020300000000000000000000000000000000000000000000000000010200 0001020300000000000000000000000000000000000000000000000000010201 0001020300000000000000000000000000000000000000000000000000010202"
sigs = rust_interface.create_cet_adaptor_sigs(7, 3, digit_string_template, oracle_pubkey, 0, pubkey0, nonces, interval_wildcards, sighashes)
sigs = rust_interface.create_cet_adaptor_sigs(7, 3, digit_string_template, oracle_pubkey, 0, 0, pubkey0, nonces, interval_wildcards, sighashes)
print("signatures:", sigs)


Expand Down
4 changes: 2 additions & 2 deletions samples/rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[package]
name = "rust"
version = "0.1.0"
version = "1.9.0"
edition = "2021"

[dependencies]
#dlccryptlib = "1.0.0"
#dlccryptlib = "1.9.0"
dlccryptlib = { path = "../../" }
4 changes: 2 additions & 2 deletions samples/rust/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ fn main() {
let xpub = dlccryptlib::init_with_entropy(entropy_hex, network).unwrap();
println!("xpub: {xpub}");

let pubkey0 = dlccryptlib::get_public_key(0).unwrap();
let pubkey0 = dlccryptlib::get_public_key(0, 0).unwrap();
println!("pubkey 0: {pubkey0}");

let hash = "0001020300000000000000000000000000000000000000000000000000010203";
let sig = dlccryptlib::sign_hash_ecdsa(hash, 0, &pubkey0).unwrap();
let sig = dlccryptlib::sign_hash_ecdsa(hash, 0, 0, &pubkey0).unwrap();
println!("signature: {sig}");
}
21 changes: 14 additions & 7 deletions samples/rust/src/test_lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,34 +21,41 @@ fn test_init_with_entropy() {
fn test_get_public_key() {
let _xpub = dlccryptlib::init_with_entropy(DUMMY_ENTROPY_STR, DEFAULT_NETWORK).unwrap();

let pubkey0 = dlccryptlib::get_public_key(0).unwrap();
let pubkey00 = dlccryptlib::get_public_key(0, 0).unwrap();
assert_eq!(
pubkey0.to_string(),
pubkey00.to_string(),
"031941e84b8d111e094aefc46e7181757c93a1da87c93ab519a40d9d765176e704"
);

let pubkey3 = dlccryptlib::get_public_key(3).unwrap();
let pubkey03 = dlccryptlib::get_public_key(0, 3).unwrap();
assert_eq!(
pubkey3.to_string(),
pubkey03.to_string(),
"02a9569875400df2b7af9360fc5025de31fcd48ca8b658d61e535c3ff2f55aa128"
);

let pubkey10 = dlccryptlib::get_public_key(1, 0).unwrap();
assert_eq!(
pubkey10.to_string(),
"026f48799f8f6571a6b8d1f8737f4ca9f2b73aa7597ee8766120cac4cee222a603"
);
}

#[test]
fn test_sign_hash_ecdsa() {
let _xpub = dlccryptlib::init_with_entropy(DUMMY_ENTROPY_STR, DEFAULT_NETWORK).unwrap();

let pubkey3 = dlccryptlib::get_public_key(3).unwrap();
let pubkey3 = dlccryptlib::get_public_key(0, 3).unwrap();
assert_eq!(
pubkey3.to_string(),
"02a9569875400df2b7af9360fc5025de31fcd48ca8b658d61e535c3ff2f55aa128"
);

let hash = DUMMY_HASH07_STR;
let sig = dlccryptlib::sign_hash_ecdsa(&hash, 3, &pubkey3).unwrap();
let sig = dlccryptlib::sign_hash_ecdsa(&hash, 0, 3, &pubkey3).unwrap();

assert!(sig.len() >= 140 && sig.len() <= 146);

// negative test, wrong index
assert!(dlccryptlib::sign_hash_ecdsa(&hash, 31, &pubkey3).is_err());
assert!(dlccryptlib::sign_hash_ecdsa(&hash, 0, 31, &pubkey3).is_err());
assert!(dlccryptlib::sign_hash_ecdsa(&hash, 1, 3, &pubkey3).is_err());
}
28 changes: 17 additions & 11 deletions src/hd_wallet_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,11 @@ impl HDWalletStorage {
}

/// Return a child keypair
pub(crate) fn get_child_keypair(&self, index: u32) -> Result<Keypair, String> {
pub(crate) fn get_child_keypair(&self, index4: u32, index5: u32) -> Result<Keypair, String> {
let wallet = self.get_cached_hdwallet_info()?;
// derive
let index_4 = ChildNumber::from_normal_idx(0).unwrap();
let index_5 = ChildNumber::from_normal_idx(index).unwrap();
let index_4 = ChildNumber::from_normal_idx(index4).unwrap();
let index_5 = ChildNumber::from_normal_idx(index5).unwrap();
let xpriv_5 = wallet
.xpriv
.derive_priv(&self.secp, &vec![index_4, index_5])
Expand All @@ -120,32 +120,38 @@ impl HDWalletStorage {
}

/// Return a child public key
pub(crate) fn get_child_public_key(&self, index: u32) -> Result<PublicKey, String> {
let keypair = self.get_child_keypair(index)?;
pub(crate) fn get_child_public_key(
&self,
index4: u32,
index5: u32,
) -> Result<PublicKey, String> {
let keypair = self.get_child_keypair(index4, index5)?;
Ok(keypair.public_key())
}

/// Return a child address
pub(crate) fn get_address(&self, index: u32) -> Result<Address, String> {
let pubkey = self.get_child_public_key(index)?;
pub(crate) fn get_address(&self, index4: u32, index5: u32) -> Result<Address, String> {
let pubkey = self.get_child_public_key(index4, index5)?;
let ck = bitcoin::CompressedPublicKey(pubkey);
let address = Address::p2wpkh(&ck, self.network());
Ok(address)
}

pub(crate) fn verify_child_public_key_intern(
&self,
index: u32,
index4: u32,
index5: u32,
pubkey: &PublicKey,
print_entity: &str,
) -> Result<bool, String> {
let keypair = self.get_child_keypair(index)?;
let keypair = self.get_child_keypair(index4, index5)?;
// verify pubkey
if &keypair.public_key() != pubkey {
return Err(format!(
"{} mismatch, index {}, {} vs. {}",
"{} mismatch, index {}/{}, {} vs. {}",
print_entity,
index,
index4,
index5,
pubkey,
keypair.public_key()
));
Expand Down
Loading