Skip to content

Commit

Permalink
Merge pull request #48 from cryptogarageinc/features/sprint57
Browse files Browse the repository at this point in the history
update to v0.2.3
  • Loading branch information
k-matsuzawa authored Oct 28, 2020
2 parents 99d6235 + d0ccab4 commit ce4f6b9
Show file tree
Hide file tree
Showing 7 changed files with 270 additions and 17 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cfd-rust"
version = "0.2.2"
version = "0.2.3"
license = "MIT"
readme = "README.md"
keywords = ["build-dependencies"]
Expand Down
2 changes: 1 addition & 1 deletion cfd-sys/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cfd_sys"
version = "0.2.2"
version = "0.2.3"
license = "MIT"
readme = "../README.md"
keywords = ["build-dependencies"]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
CFDRUST_VERSION=0.2.2
CFD_TARGET_VERSION=refs/tags/v0.2.6
CFDCORE_TARGET_VERSION=refs/tags/v0.2.5
LIBWALLY_TARGET_VERSION=refs/tags/cfd-0.2.2
CFDRUST_VERSION=0.2.3
CFD_TARGET_VERSION=refs/tags/v0.2.7
CFDCORE_TARGET_VERSION=refs/tags/v0.2.6
LIBWALLY_TARGET_VERSION=refs/tags/cfd-0.2.3
CFD_TARGET_URL=cryptogarageinc/cfd.git
CFDCORE_TARGET_URL=cryptogarageinc/cfd-core.git
29 changes: 29 additions & 0 deletions cfd-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,35 @@ fns! {
handle: *const c_void,
privkey: *const i8,
pubkey: *mut *mut c_char,
parity: *mut bool,
) -> c_int;
pub fn CfdGetSchnorrPubkeyFromPubkey(
handle: *const c_void,
pubkey: *const i8,
schnorr_pubkey: *mut *mut c_char,
parity: *mut bool,
) -> c_int;
pub fn CfdSchnorrPubkeyTweakAdd(
handle: *const c_void,
pubkey: *const i8,
tweak: *const i8,
output: *mut *mut c_char,
parity: *mut bool,
) -> c_int;
pub fn CfdSchnorrKeyPairTweakAdd(
handle: *const c_void,
privkey: *const i8,
tweak: *const i8,
tweaked_pubkey: *mut *mut c_char,
tweaked_parity: *mut bool,
tweaked_privkey: *mut *mut c_char,
) -> c_int;
pub fn CfdCheckTweakAddFromSchnorrPubkey(
handle: *const c_void,
tweaked_pubkey: *const i8,
tweaked_parity: bool,
base_pubkey: *const i8,
tweak: *const i8,
) -> c_int;
pub fn CfdSignSchnorr(
handle: *const c_void,
Expand Down
190 changes: 184 additions & 6 deletions src/schnorr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ use std::result::Result::{Err, Ok};
use std::str::FromStr;

use self::cfd_sys::{
CfdAdaptEcdsaAdaptor, CfdComputeSchnorrSigPoint, CfdExtractEcdsaAdaptorSecret,
CfdSignEcdsaAdaptor, CfdSignSchnorr, CfdSignSchnorrWithNonce, CfdSplitSchnorrSignature,
CfdVerifyEcdsaAdaptor, CfdVerifySchnorr, CfdGetSchnorrPubkeyFromPrivkey,
CfdAdaptEcdsaAdaptor, CfdCheckTweakAddFromSchnorrPubkey, CfdComputeSchnorrSigPoint,
CfdExtractEcdsaAdaptorSecret, CfdGetSchnorrPubkeyFromPrivkey, CfdGetSchnorrPubkeyFromPubkey,
CfdSchnorrKeyPairTweakAdd, CfdSchnorrPubkeyTweakAdd, CfdSignEcdsaAdaptor, CfdSignSchnorr,
CfdSignSchnorrWithNonce, CfdSplitSchnorrSignature, CfdVerifyEcdsaAdaptor, CfdVerifySchnorr,
};

/// adaptor signature size.
Expand Down Expand Up @@ -590,23 +591,115 @@ impl SchnorrPubkey {
/// use cfd_rust::{SchnorrPubkey, Privkey};
/// use std::str::FromStr;
/// let key = Privkey::from_str("475697a71a74ff3f2a8f150534e9b67d4b0b6561fab86fcaa51f8c9d6c9db8c6").expect("Fail");
/// let pubkey = SchnorrPubkey::from_privkey(&key).expect("Fail");
/// let pubkey_ret = SchnorrPubkey::from_privkey(&key).expect("Fail");
/// let (pubkey, parity) = pubkey_ret;
/// ```
pub fn from_privkey(key: &Privkey) -> Result<SchnorrPubkey, CfdError> {
pub fn from_privkey(key: &Privkey) -> Result<(SchnorrPubkey, bool), CfdError> {
let key_hex = alloc_c_string(&key.to_hex())?;
let handle = ErrorHandle::new()?;
let mut pubkey_hex: *mut c_char = ptr::null_mut();
let mut parity = false;
let error_code = unsafe {
CfdGetSchnorrPubkeyFromPrivkey(
handle.as_handle(),
key_hex.as_ptr(),
&mut pubkey_hex,
&mut parity,
)
};
let result = match error_code {
0 => {
let pubkey = unsafe { collect_cstring_and_free(pubkey_hex) }?;
SchnorrPubkey::from_str(&pubkey)
let pubkey_obj = SchnorrPubkey::from_str(&pubkey)?;
Ok((pubkey_obj, parity))
}
_ => Err(handle.get_error(error_code)),
};
handle.free_handle();
result
}

/// Generate from pubkey.
///
/// # Arguments
/// * `key` - A public key.
///
/// # Example
///
/// ```
/// use cfd_rust::{SchnorrPubkey, Pubkey};
/// use std::str::FromStr;
/// let key = Pubkey::from_str("03b33cc9edc096d0a83416964bd3c6247b8fecd256e4efa7870d2c854bdeb33390").expect("Fail");
/// let pubkey_ret = SchnorrPubkey::from_pubkey(&key).expect("Fail");
/// let (pubkey, parity) = pubkey_ret;
/// ```
pub fn from_pubkey(key: &Pubkey) -> Result<(SchnorrPubkey, bool), CfdError> {
let key_hex = alloc_c_string(&key.to_hex())?;
let handle = ErrorHandle::new()?;
let mut pubkey_hex: *mut c_char = ptr::null_mut();
let mut parity = false;
let error_code = unsafe {
CfdGetSchnorrPubkeyFromPubkey(
handle.as_handle(),
key_hex.as_ptr(),
&mut pubkey_hex,
&mut parity,
)
};
let result = match error_code {
0 => {
let pubkey = unsafe { collect_cstring_and_free(pubkey_hex) }?;
let pubkey_obj = SchnorrPubkey::from_str(&pubkey)?;
Ok((pubkey_obj, parity))
}
_ => Err(handle.get_error(error_code)),
};
handle.free_handle();
result
}

/// Generate tweaked key pair from privkey.
///
/// # Arguments
/// * `key` - A private key.
/// * `data` - A tweaked 32 byte buffer.
///
/// # Example
///
/// ```
/// use cfd_rust::{SchnorrPubkey, Privkey, ByteData};
/// use std::str::FromStr;
/// let key = Privkey::from_str("475697a71a74ff3f2a8f150534e9b67d4b0b6561fab86fcaa51f8c9d6c9db8c6").expect("Fail");
/// let tweak = ByteData::from_str("e48441762fb75010b2aa31a512b62b4148aa3fb08eb0765d76b252559064a614").expect("Fail");
/// let pubkey_ret = SchnorrPubkey::get_tweak_add_from_privkey(&key, tweak.to_slice()).expect("Fail");
/// let (pubkey, parity, privkey) = pubkey_ret;
/// ```
pub fn get_tweak_add_from_privkey(
key: &Privkey,
data: &[u8],
) -> Result<(SchnorrPubkey, bool, Privkey), CfdError> {
let key_hex = alloc_c_string(&key.to_hex())?;
let tweak_hex = alloc_c_string(&hex_from_bytes(data))?;
let handle = ErrorHandle::new()?;
let mut pubkey_hex: *mut c_char = ptr::null_mut();
let mut privkey_hex: *mut c_char = ptr::null_mut();
let mut parity = false;
let error_code = unsafe {
CfdSchnorrKeyPairTweakAdd(
handle.as_handle(),
key_hex.as_ptr(),
tweak_hex.as_ptr(),
&mut pubkey_hex,
&mut parity,
&mut privkey_hex,
)
};
let result = match error_code {
0 => {
let str_list = unsafe { collect_multi_cstring_and_free(&[pubkey_hex, privkey_hex]) }?;
let pubkey_obj = SchnorrPubkey::from_str(&str_list[0])?;
let privkey_obj = Privkey::from_str(&str_list[1])?;
Ok((pubkey_obj, parity, privkey_obj))
}
_ => Err(handle.get_error(error_code)),
};
Expand All @@ -632,6 +725,91 @@ impl SchnorrPubkey {
pub fn as_key(&self) -> Result<Privkey, CfdError> {
Privkey::from_slice(&self.data)
}

/// Generate tweaked schnorr pubkey.
///
/// # Arguments
/// * `data` - A tweaked 32 byte buffer.
///
/// # Example
///
/// ```
/// use cfd_rust::{SchnorrPubkey, ByteData};
/// use std::str::FromStr;
/// let key = SchnorrPubkey::from_str("b33cc9edc096d0a83416964bd3c6247b8fecd256e4efa7870d2c854bdeb33390").expect("Fail");
/// let tweak = ByteData::from_str("e48441762fb75010b2aa31a512b62b4148aa3fb08eb0765d76b252559064a614").expect("Fail");
/// let pubkey_ret = key.tweak_add(tweak.to_slice()).expect("Fail");
/// let (pubkey, parity) = pubkey_ret;
/// ```
pub fn tweak_add(&self, data: &[u8]) -> Result<(SchnorrPubkey, bool), CfdError> {
let key_hex = alloc_c_string(&self.to_hex())?;
let tweak_hex = alloc_c_string(&hex_from_bytes(data))?;
let handle = ErrorHandle::new()?;
let mut pubkey_hex: *mut c_char = ptr::null_mut();
let mut parity = false;
let error_code = unsafe {
CfdSchnorrPubkeyTweakAdd(
handle.as_handle(),
key_hex.as_ptr(),
tweak_hex.as_ptr(),
&mut pubkey_hex,
&mut parity,
)
};
let result = match error_code {
0 => {
let pubkey = unsafe { collect_cstring_and_free(pubkey_hex) }?;
let pubkey_obj = SchnorrPubkey::from_str(&pubkey)?;
Ok((pubkey_obj, parity))
}
_ => Err(handle.get_error(error_code)),
};
handle.free_handle();
result
}

/// Generate tweaked schnorr pubkey.
///
/// # Arguments
/// * `data` - A tweaked 32 byte buffer.
///
/// # Example
///
/// ```
/// use cfd_rust::{SchnorrPubkey, ByteData};
/// use std::str::FromStr;
/// let key = SchnorrPubkey::from_str("b33cc9edc096d0a83416964bd3c6247b8fecd256e4efa7870d2c854bdeb33390").expect("Fail");
/// let tweak = ByteData::from_str("e48441762fb75010b2aa31a512b62b4148aa3fb08eb0765d76b252559064a614").expect("Fail");
/// let tweaked_key = SchnorrPubkey::from_str("1fc8e882e34cc7942a15f39ffaebcbdf58a19239bcb17b7f5aa88e0eb808f906").expect("Fail");
/// let is_valid = tweaked_key.is_tweaked(true, &key, tweak.to_slice()).expect("Fail");
/// ```
pub fn is_tweaked(
&self,
parity: bool,
base_pubkey: &SchnorrPubkey,
data: &[u8],
) -> Result<bool, CfdError> {
let key_hex = alloc_c_string(&self.to_hex())?;
let base_key_hex = alloc_c_string(&base_pubkey.to_hex())?;
let tweak_hex = alloc_c_string(&hex_from_bytes(data))?;
let handle = ErrorHandle::new()?;
let error_code = unsafe {
CfdCheckTweakAddFromSchnorrPubkey(
handle.as_handle(),
key_hex.as_ptr(),
parity,
base_key_hex.as_ptr(),
tweak_hex.as_ptr(),
)
};
let result = match error_code {
0 => Ok(true),
7 => Ok(false),
_ => Err(handle.get_error(error_code)),
};
handle.free_handle();
result
}
}

impl fmt::Display for SchnorrPubkey {
Expand Down
2 changes: 1 addition & 1 deletion tests/hdwallet_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ mod tests {
"0101010101010101010101010101010101010101010101010101010101010101",
ByteData::from_slice(&entropy).to_hex()
);

let wallet = HDWallet::from_mnemonic(
"absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter advice comic",
MnemonicLanguage::EN,
Expand Down
54 changes: 50 additions & 4 deletions tests/schnorr_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ mod tests {
}

#[test]
fn schnorr_test() {
fn schnorr_util_test() {
// default
let msg =
ByteData::from_str("e48441762fb75010b2aa31a512b62b4148aa3fb08eb0765d76b252559064a614")
Expand All @@ -79,9 +79,6 @@ mod tests {
SchnorrSignature::from_str("6470fd1303dda4fda717b9837153c24a6eab377183fc438f939e0ed2b620e9ee5077c4a8b8dca28963d772a94f5f0ddf598e1c47c137f91933274c7c3edadce8").expect("Fail");

let obj = SchnorrUtil::new();
let schnorr_pubkey = SchnorrPubkey::from_privkey(&sk).expect("Fail");
assert_eq!(pubkey.to_hex(), schnorr_pubkey.to_hex());

let sig1 = obj.sign(&msg, &sk, &aux_rand).expect("Fail");
assert_eq!(signature.to_hex(), sig1.to_hex());

Expand All @@ -106,4 +103,53 @@ mod tests {
assert_eq!(expected_nonce, sig1.as_nonce().to_hex());
assert_eq!(expected_privkey, sig1.as_key().to_hex());
}

#[test]
fn schnorr_pubkey_test() {
// default
let tweak =
ByteData::from_str("e48441762fb75010b2aa31a512b62b4148aa3fb08eb0765d76b252559064a614")
.expect("Fail");
let sk = Privkey::from_str("688c77bc2d5aaff5491cf309d4753b732135470d05b7b2cd21add0744fe97bef")
.expect("Fail");
let pk = Pubkey::from_str("03b33cc9edc096d0a83416964bd3c6247b8fecd256e4efa7870d2c854bdeb33390")
.expect("Fail");
let pubkey =
SchnorrPubkey::from_str("b33cc9edc096d0a83416964bd3c6247b8fecd256e4efa7870d2c854bdeb33390")
.expect("Fail");
let exp_tweaked_pk =
SchnorrPubkey::from_str("1fc8e882e34cc7942a15f39ffaebcbdf58a19239bcb17b7f5aa88e0eb808f906")
.expect("Fail");
let exp_tweaked_sk =
Privkey::from_str("7bf7c9ba025ca01b698d3e9b3e40efce2774f8a388f8c390550481e1407b2a25")
.expect("Fail");

let (schnorr_pubkey, parity) = SchnorrPubkey::from_privkey(&sk).expect("Fail");
assert_eq!(pubkey.to_hex(), schnorr_pubkey.to_hex());
assert_eq!(true, parity);

let (schnorr_pubkey, parity) = SchnorrPubkey::from_pubkey(&pk).expect("Fail");
assert_eq!(pubkey.to_hex(), schnorr_pubkey.to_hex());
assert_eq!(true, parity);

let (tweaked_pubkey, tweaked_parity) = pubkey.tweak_add(tweak.to_slice()).expect("Fail");
assert_eq!(exp_tweaked_pk.to_hex(), tweaked_pubkey.to_hex());
assert_eq!(true, tweaked_parity);

let gen_key_ret =
SchnorrPubkey::get_tweak_add_from_privkey(&sk, tweak.to_slice()).expect("Fail");
let (tweaked_pubkey, tweaked_parity, tweaked_privkey) = gen_key_ret;
assert_eq!(exp_tweaked_pk.to_hex(), tweaked_pubkey.to_hex());
assert_eq!(true, tweaked_parity);
assert_eq!(exp_tweaked_sk.to_hex(), tweaked_privkey.to_hex());

let is_valid = tweaked_pubkey
.is_tweaked(true, &pubkey, tweak.to_slice())
.expect("Fail");
assert_eq!(true, is_valid);
let is_valid = tweaked_pubkey
.is_tweaked(false, &pubkey, tweak.to_slice())
.expect("Fail");
assert_eq!(false, is_valid);
}
}

0 comments on commit ce4f6b9

Please sign in to comment.