Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add bip340 schnorr #237

Merged
merged 5 commits into from Nov 27, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Expand Up @@ -34,7 +34,7 @@ external-symbols = ["secp256k1-sys/external-symbols"]
fuzztarget = ["secp256k1-sys/fuzztarget"]

[dependencies]
secp256k1-sys = { version = "0.3.0", default-features = false, path = "./secp256k1-sys" }
secp256k1-sys = { version = "0.3.1", default-features = false, path = "./secp256k1-sys" }
bitcoin_hashes = { version = "0.9", optional = true }
rand = { version = "0.6", default-features = false, optional = true }
serde = { version = "1.0", default-features = false, optional = true }
Expand Down
2 changes: 1 addition & 1 deletion secp256k1-sys/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "secp256k1-sys"
version = "0.3.0"
version = "0.3.1"
authors = [ "Dawid Ciężarkiewicz <dpc@ucore.info>",
"Andrew Poelstra <apoelstra@wpsoftware.net>",
"Steven Roose <steven@stevenroose.org>" ]
Expand Down
2 changes: 2 additions & 0 deletions secp256k1-sys/build.rs
Expand Up @@ -39,6 +39,8 @@ fn main() {
.flag_if_supported("-Wno-unused-function") // some ecmult stuff is defined but not used upstream
.define("SECP256K1_BUILD", Some("1"))
.define("ENABLE_MODULE_ECDH", Some("1"))
.define("ENABLE_MODULE_SCHNORRSIG", Some("1"))
.define("ENABLE_MODULE_EXTRAKEYS", Some("1"))
.define("ECMULT_GEN_PREC_BITS", Some("4"))
// TODO these three should be changed to use libgmp, at least until secp PR 290 is merged
.define("USE_NUM_NONE", Some("1"))
Expand Down
241 changes: 241 additions & 0 deletions secp256k1-sys/src/lib.rs
Expand Up @@ -71,6 +71,20 @@ pub type EcdhHashFn = unsafe extern "C" fn(
data: *mut c_void,
) -> c_int;

/// Same as secp256k1_nonce function with the exception of accepting an
/// additional pubkey argument and not requiring an attempt argument. The pubkey
/// argument can protect signature schemes with key-prefixed challenge hash
/// inputs against reusing the nonce when signing with the wrong precomputed
/// pubkey.
pub type SchnorrNonceFn = unsafe extern "C" fn(
nonce32: *mut c_uchar,
msg32: *const c_uchar,
key32: *const c_uchar,
xonly_pk32: *const c_uchar,
algo16: *const c_uchar,
data: *mut c_void,
) -> c_int;

/// A Secp256k1 context, containing various precomputed values and such
/// needed to do elliptic curve computations. If you create one of these
/// with `secp256k1_context_create` you MUST destroy it with
Expand Down Expand Up @@ -125,6 +139,55 @@ impl Default for Signature {
}
}

#[repr(C)]
pub struct XOnlyPublicKey([c_uchar; 64]);
impl_array_newtype!(XOnlyPublicKey, c_uchar, 64);
impl_raw_debug!(XOnlyPublicKey);

impl XOnlyPublicKey {
/// Create a new (zeroed) x-only public key usable for the FFI interface
pub fn new() -> XOnlyPublicKey { XOnlyPublicKey([0; 64]) }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't have this function, as it creates an invalid public key which will trigger assertation failures in upstream.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll fix this in a followup commit/PR. It's a bit subtle because we do need (temporarily) uninitialized values to use the FFI interface.

pub fn from_array(data: [c_uchar; 64]) -> XOnlyPublicKey {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should rename this to from_array_unchecked for similar reasons.

XOnlyPublicKey(data)
}
}

impl hash::Hash for XOnlyPublicKey {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
state.write(&self.0)
}
}

impl Default for XOnlyPublicKey {
fn default() -> Self {
XOnlyPublicKey::new()
}
}

#[repr(C)]
pub struct KeyPair([c_uchar; 96]);
impl_array_newtype!(KeyPair, c_uchar, 96);
impl_raw_debug!(KeyPair);

impl KeyPair {
/// Create a new (zeroed) key pair usable for the FFI interface
pub fn new() -> KeyPair { KeyPair([0; 96]) }
pub fn from_array(data: [c_uchar; 96]) -> KeyPair {
KeyPair(data)
}
}

impl hash::Hash for KeyPair {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
state.write(&self.0)
}
}

impl Default for KeyPair {
fn default() -> Self {
KeyPair::new()
}
}

#[cfg(not(feature = "fuzztarget"))]
extern "C" {
Expand Down Expand Up @@ -301,6 +364,92 @@ extern "C" {
hashfp: EcdhHashFn,
data: *mut c_void,
) -> c_int;


// Schnorr Signatures
#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_3_1_nonce_function_bip340")]
pub static secp256k1_nonce_function_bip340: SchnorrNonceFn;

#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_3_1_schnorrsig_sign")]
pub fn secp256k1_schnorrsig_sign(
cx: *const Context,
sig: *mut c_uchar,
msg32: *const c_uchar,
keypair: *const KeyPair,
noncefp: SchnorrNonceFn,
noncedata: *const c_void
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

upstream this is a *mut c_void

) -> c_int;

#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_3_1_schnorrsig_verify")]
pub fn secp256k1_schnorrsig_verify(
cx: *const Context,
sig64: *const c_uchar,
msg32: *const c_uchar,
pubkey: *const XOnlyPublicKey,
) -> c_int;

// Extra keys

#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_3_1_keypair_create")]
pub fn secp256k1_keypair_create(
cx: *const Context,
keypair: *mut KeyPair,
seckey: *const c_uchar,
) -> c_int;

#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_3_1_xonly_pubkey_parse")]
pub fn secp256k1_xonly_pubkey_parse(
cx: *const Context,
pubkey: *mut XOnlyPublicKey,
input32: *const c_uchar,
) -> c_int;

#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_3_1_xonly_pubkey_serialize")]
pub fn secp256k1_xonly_pubkey_serialize(
cx: *const Context,
output32: *mut c_uchar,
pubkey: *const XOnlyPublicKey,
) -> c_int;

#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_3_1_xonly_pubkey_from_pubkey")]
pub fn secp256k1_xonly_pubkey_from_pubkey(
cx: *const Context,
xonly_pubkey: *mut XOnlyPublicKey,
pk_parity: *mut c_int,
pubkey: *const PublicKey,
) -> c_int;

#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_3_1_xonly_pubkey_tweak_add")]
pub fn secp256k1_xonly_pubkey_tweak_add(
cx: *const Context,
output_pubkey: *mut PublicKey,
internal_pubkey: *const XOnlyPublicKey,
tweak32: *const c_uchar,
) -> c_int;

#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_3_1_keypair_xonly_pub")]
pub fn secp256k1_keypair_xonly_pub(
cx: *const Context,
pubkey: *mut XOnlyPublicKey,
pk_parity: *mut c_int,
keypair: *const KeyPair
) -> c_int;

#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_3_1_keypair_xonly_tweak_add")]
pub fn secp256k1_keypair_xonly_tweak_add(
cx: *const Context,
keypair: *mut KeyPair,
tweak32: *const c_uchar,
) -> c_int;

#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_3_1_xonly_pubkey_tweak_add_check")]
pub fn secp256k1_xonly_pubkey_tweak_add_check(
cx: *const Context,
tweaked_pubkey32: *const c_uchar,
tweaked_pubkey_parity: c_int,
internal_pubkey: *const XOnlyPublicKey,
tweak32: *const c_uchar,
) -> c_int;
}


Expand Down Expand Up @@ -459,6 +608,7 @@ mod fuzz_dummy {
use self::std::boxed::Box;
use types::*;
use {Signature, Context, NonceFn, EcdhHashFn, PublicKey,
SchnorrNonceFn, XOnlyPublicKey, KeyPair,
SECP256K1_START_NONE, SECP256K1_START_VERIFY, SECP256K1_START_SIGN,
SECP256K1_SER_COMPRESSED, SECP256K1_SER_UNCOMPRESSED};

Expand All @@ -470,6 +620,8 @@ mod fuzz_dummy {
pub static secp256k1_ecdh_hash_function_default: EcdhHashFn;
#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_3_1_nonce_function_rfc6979")]
pub static secp256k1_nonce_function_rfc6979: NonceFn;
#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_3_1_nonce_function_bip340")]
pub static secp256k1_nonce_function_bip340: SchnorrNonceFn;
}

// Contexts
Expand Down Expand Up @@ -841,6 +993,95 @@ mod fuzz_dummy {
(*out.offset(16)) = 0x00; // result should always be a valid secret key
1
}

pub unsafe fn secp256k1_schnorrsig_sign(
_cx: *const Context,
_sig: *mut c_uchar,
_msg32: *const c_uchar,
_keypair: *const KeyPair,
_noncefp: SchnorrNonceFn,
_noncedata: *const c_void
) -> c_int {
unimplemented!();
}

pub unsafe fn secp256k1_schnorrsig_verify(
_cx: *const Context,
_sig64: *const c_uchar,
_msg32: *const c_uchar,
_pubkey: *const XOnlyPublicKey,
) -> c_int {
unimplemented!();
}

pub fn secp256k1_xonly_pubkey_parse(
_cx: *const Context,
_pubkey: *mut XOnlyPublicKey,
_input32: *const c_uchar,
) -> c_int {
unimplemented!();
}

pub fn secp256k1_xonly_pubkey_serialize(
_cx: *const Context,
_output32: *mut c_uchar,
_pubkey: *const XOnlyPublicKey,
) -> c_int {
unimplemented!();
}

pub unsafe fn secp256k1_xonly_pubkey_from_pubkey(
_cx: *const Context,
_xonly_pubkey: *mut XOnlyPublicKey,
_pk_parity: *mut c_int,
_pubkey: *const PublicKey,
) -> c_int {
unimplemented!();
}

pub unsafe fn secp256k1_keypair_create(
_cx: *const Context,
_keypair: *mut KeyPair,
_seckey: *const c_uchar,
) -> c_int {
unimplemented!();
}

pub unsafe fn secp256k1_xonly_pubkey_tweak_add(
_cx: *const Context,
_output_pubkey: *mut PublicKey,
_internal_pubkey: *const XOnlyPublicKey,
_tweak32: *const c_uchar,
) -> c_int {
unimplemented!();
}

pub unsafe fn secp256k1_keypair_xonly_pub(
_cx: *const Context,
_pubkey: *mut XOnlyPublicKey,
_pk_parity: *mut c_int,
_keypair: *const KeyPair
) -> c_int {
unimplemented!();
}

pub unsafe fn secp256k1_keypair_xonly_tweak_add(
_cx: *const Context,
_keypair: *mut KeyPair,
_tweak32: *const c_uchar,
) -> c_int {
unimplemented!();
}

pub unsafe fn secp256k1_xonly_pubkey_tweak_add_check(
_cx: *const Context,
_tweaked_pubkey32: *const c_uchar,
_tweaked_pubkey_parity: c_int,
_internal_pubkey: *const XOnlyPublicKey,
_tweak32: *const c_uchar,
) -> c_int {
unimplemented!();
}
}
#[cfg(feature = "fuzztarget")]
pub use self::fuzz_dummy::*;
Expand Down