mirror of
https://github.com/mimblewimble/grin.git
synced 2025-02-01 08:51:08 +03:00
Update secp256k1zlp to serde 1.0
This commit is contained in:
parent
1ae2e905d8
commit
da41120293
8 changed files with 2067 additions and 1999 deletions
|
@ -29,6 +29,5 @@ clippy = {version = "0.0", optional = true}
|
|||
rand = "0.3"
|
||||
libc = "0.1"
|
||||
rustc-serialize = "0.3"
|
||||
serde = "0.6"
|
||||
serde_json = "0.6"
|
||||
|
||||
serde = "~1.0.8"
|
||||
serde_json = "~1.0.2"
|
||||
|
|
|
@ -26,106 +26,106 @@ use ffi;
|
|||
pub struct SharedSecret(ffi::SharedSecret);
|
||||
|
||||
impl SharedSecret {
|
||||
/// Creates a new shared secret from a pubkey and secret key
|
||||
#[inline]
|
||||
pub fn new(secp: &Secp256k1, point: &PublicKey, scalar: &SecretKey) -> SharedSecret {
|
||||
unsafe {
|
||||
let mut ss = ffi::SharedSecret::blank();
|
||||
let res = ffi::secp256k1_ecdh(secp.ctx, &mut ss, point.as_ptr(), scalar.as_ptr());
|
||||
debug_assert_eq!(res, 1);
|
||||
SharedSecret(ss)
|
||||
}
|
||||
}
|
||||
/// Creates a new shared secret from a pubkey and secret key
|
||||
#[inline]
|
||||
pub fn new(secp: &Secp256k1, point: &PublicKey, scalar: &SecretKey) -> SharedSecret {
|
||||
unsafe {
|
||||
let mut ss = ffi::SharedSecret::blank();
|
||||
let res = ffi::secp256k1_ecdh(secp.ctx, &mut ss, point.as_ptr(), scalar.as_ptr());
|
||||
debug_assert_eq!(res, 1);
|
||||
SharedSecret(ss)
|
||||
}
|
||||
}
|
||||
|
||||
/// Obtains a raw pointer suitable for use with FFI functions
|
||||
#[inline]
|
||||
pub fn as_ptr(&self) -> *const ffi::SharedSecret {
|
||||
&self.0 as *const _
|
||||
}
|
||||
/// Obtains a raw pointer suitable for use with FFI functions
|
||||
#[inline]
|
||||
pub fn as_ptr(&self) -> *const ffi::SharedSecret {
|
||||
&self.0 as *const _
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new shared secret from a FFI shared secret
|
||||
impl From<ffi::SharedSecret> for SharedSecret {
|
||||
#[inline]
|
||||
fn from(ss: ffi::SharedSecret) -> SharedSecret {
|
||||
SharedSecret(ss)
|
||||
}
|
||||
#[inline]
|
||||
fn from(ss: ffi::SharedSecret) -> SharedSecret {
|
||||
SharedSecret(ss)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl ops::Index<usize> for SharedSecret {
|
||||
type Output = u8;
|
||||
type Output = u8;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: usize) -> &u8 {
|
||||
&self.0[index]
|
||||
}
|
||||
#[inline]
|
||||
fn index(&self, index: usize) -> &u8 {
|
||||
&self.0[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Index<ops::Range<usize>> for SharedSecret {
|
||||
type Output = [u8];
|
||||
type Output = [u8];
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: ops::Range<usize>) -> &[u8] {
|
||||
&self.0[index]
|
||||
}
|
||||
#[inline]
|
||||
fn index(&self, index: ops::Range<usize>) -> &[u8] {
|
||||
&self.0[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Index<ops::RangeFrom<usize>> for SharedSecret {
|
||||
type Output = [u8];
|
||||
type Output = [u8];
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: ops::RangeFrom<usize>) -> &[u8] {
|
||||
&self.0[index.start..]
|
||||
}
|
||||
#[inline]
|
||||
fn index(&self, index: ops::RangeFrom<usize>) -> &[u8] {
|
||||
&self.0[index.start..]
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Index<ops::RangeFull> for SharedSecret {
|
||||
type Output = [u8];
|
||||
type Output = [u8];
|
||||
|
||||
#[inline]
|
||||
fn index(&self, _: ops::RangeFull) -> &[u8] {
|
||||
&self.0[..]
|
||||
}
|
||||
#[inline]
|
||||
fn index(&self, _: ops::RangeFull) -> &[u8] {
|
||||
&self.0[..]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rand::thread_rng;
|
||||
use super::SharedSecret;
|
||||
use super::super::Secp256k1;
|
||||
use rand::thread_rng;
|
||||
use super::SharedSecret;
|
||||
use super::super::Secp256k1;
|
||||
|
||||
#[test]
|
||||
fn ecdh() {
|
||||
let s = Secp256k1::with_caps(::ContextFlag::SignOnly);
|
||||
let (sk1, pk1) = s.generate_keypair(&mut thread_rng()).unwrap();
|
||||
let (sk2, pk2) = s.generate_keypair(&mut thread_rng()).unwrap();
|
||||
#[test]
|
||||
fn ecdh() {
|
||||
let s = Secp256k1::with_caps(::ContextFlag::SignOnly);
|
||||
let (sk1, pk1) = s.generate_keypair(&mut thread_rng()).unwrap();
|
||||
let (sk2, pk2) = s.generate_keypair(&mut thread_rng()).unwrap();
|
||||
|
||||
let sec1 = SharedSecret::new(&s, &pk1, &sk2);
|
||||
let sec2 = SharedSecret::new(&s, &pk2, &sk1);
|
||||
let sec_odd = SharedSecret::new(&s, &pk1, &sk1);
|
||||
assert_eq!(sec1, sec2);
|
||||
assert!(sec_odd != sec2);
|
||||
}
|
||||
let sec1 = SharedSecret::new(&s, &pk1, &sk2);
|
||||
let sec2 = SharedSecret::new(&s, &pk2, &sk1);
|
||||
let sec_odd = SharedSecret::new(&s, &pk1, &sk1);
|
||||
assert_eq!(sec1, sec2);
|
||||
assert!(sec_odd != sec2);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(test, feature = "unstable"))]
|
||||
mod benches {
|
||||
use rand::thread_rng;
|
||||
use test::{Bencher, black_box};
|
||||
use rand::thread_rng;
|
||||
use test::{Bencher, black_box};
|
||||
|
||||
use super::SharedSecret;
|
||||
use super::super::Secp256k1;
|
||||
use super::SharedSecret;
|
||||
use super::super::Secp256k1;
|
||||
|
||||
#[bench]
|
||||
pub fn bench_ecdh(bh: &mut Bencher) {
|
||||
let s = Secp256k1::with_caps(::ContextFlag::SignOnly);
|
||||
let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap();
|
||||
#[bench]
|
||||
pub fn bench_ecdh(bh: &mut Bencher) {
|
||||
let s = Secp256k1::with_caps(::ContextFlag::SignOnly);
|
||||
let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap();
|
||||
|
||||
let s = Secp256k1::new();
|
||||
bh.iter(|| {
|
||||
let res = SharedSecret::new(&s, &pk, &sk);
|
||||
black_box(res);
|
||||
});
|
||||
}
|
||||
let s = Secp256k1::new();
|
||||
bh.iter(|| {
|
||||
let res = SharedSecret::new(&s, &pk, &sk);
|
||||
black_box(res);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,14 +61,14 @@ impl_array_newtype!(PublicKey, c_uchar, 64);
|
|||
impl_raw_debug!(PublicKey);
|
||||
|
||||
impl PublicKey {
|
||||
/// Create a new (zeroed) public key usable for the FFI interface
|
||||
pub fn new() -> PublicKey {
|
||||
PublicKey([0; 64])
|
||||
}
|
||||
/// Create a new (uninitialized) public key usable for the FFI interface
|
||||
pub unsafe fn blank() -> PublicKey {
|
||||
mem::uninitialized()
|
||||
}
|
||||
/// Create a new (zeroed) public key usable for the FFI interface
|
||||
pub fn new() -> PublicKey {
|
||||
PublicKey([0; 64])
|
||||
}
|
||||
/// Create a new (uninitialized) public key usable for the FFI interface
|
||||
pub unsafe fn blank() -> PublicKey {
|
||||
mem::uninitialized()
|
||||
}
|
||||
}
|
||||
|
||||
/// Library-internal representation of a Secp256k1 signature
|
||||
|
@ -84,25 +84,25 @@ impl_array_newtype!(RecoverableSignature, c_uchar, 65);
|
|||
impl_raw_debug!(RecoverableSignature);
|
||||
|
||||
impl Signature {
|
||||
/// Create a new (zeroed) signature usable for the FFI interface
|
||||
pub fn new() -> Signature {
|
||||
Signature([0; 64])
|
||||
}
|
||||
/// Create a new (uninitialized) signature usable for the FFI interface
|
||||
pub unsafe fn blank() -> Signature {
|
||||
mem::uninitialized()
|
||||
}
|
||||
/// Create a new (zeroed) signature usable for the FFI interface
|
||||
pub fn new() -> Signature {
|
||||
Signature([0; 64])
|
||||
}
|
||||
/// Create a new (uninitialized) signature usable for the FFI interface
|
||||
pub unsafe fn blank() -> Signature {
|
||||
mem::uninitialized()
|
||||
}
|
||||
}
|
||||
|
||||
impl RecoverableSignature {
|
||||
/// Create a new (zeroed) signature usable for the FFI interface
|
||||
pub fn new() -> RecoverableSignature {
|
||||
RecoverableSignature([0; 65])
|
||||
}
|
||||
/// Create a new (uninitialized) signature usable for the FFI interface
|
||||
pub unsafe fn blank() -> RecoverableSignature {
|
||||
mem::uninitialized()
|
||||
}
|
||||
/// Create a new (zeroed) signature usable for the FFI interface
|
||||
pub fn new() -> RecoverableSignature {
|
||||
RecoverableSignature([0; 65])
|
||||
}
|
||||
/// Create a new (uninitialized) signature usable for the FFI interface
|
||||
pub unsafe fn blank() -> RecoverableSignature {
|
||||
mem::uninitialized()
|
||||
}
|
||||
}
|
||||
|
||||
/// Library-internal representation of an ECDH shared secret
|
||||
|
@ -112,263 +112,263 @@ impl_array_newtype!(SharedSecret, c_uchar, 32);
|
|||
impl_raw_debug!(SharedSecret);
|
||||
|
||||
impl SharedSecret {
|
||||
/// Create a new (zeroed) signature usable for the FFI interface
|
||||
pub fn new() -> SharedSecret {
|
||||
SharedSecret([0; 32])
|
||||
}
|
||||
/// Create a new (uninitialized) signature usable for the FFI interface
|
||||
pub unsafe fn blank() -> SharedSecret {
|
||||
mem::uninitialized()
|
||||
}
|
||||
/// Create a new (zeroed) signature usable for the FFI interface
|
||||
pub fn new() -> SharedSecret {
|
||||
SharedSecret([0; 32])
|
||||
}
|
||||
/// Create a new (uninitialized) signature usable for the FFI interface
|
||||
pub unsafe fn blank() -> SharedSecret {
|
||||
mem::uninitialized()
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub static secp256k1_nonce_function_rfc6979: NonceFn;
|
||||
pub static secp256k1_nonce_function_rfc6979: NonceFn;
|
||||
|
||||
pub static secp256k1_nonce_function_default: NonceFn;
|
||||
pub static secp256k1_nonce_function_default: NonceFn;
|
||||
|
||||
// Contexts
|
||||
pub fn secp256k1_context_create(flags: c_uint) -> *mut Context;
|
||||
// Contexts
|
||||
pub fn secp256k1_context_create(flags: c_uint) -> *mut Context;
|
||||
|
||||
pub fn secp256k1_context_clone(cx: *mut Context) -> *mut Context;
|
||||
pub fn secp256k1_context_clone(cx: *mut Context) -> *mut Context;
|
||||
|
||||
pub fn secp256k1_context_destroy(cx: *mut Context);
|
||||
pub fn secp256k1_context_destroy(cx: *mut Context);
|
||||
|
||||
pub fn secp256k1_context_randomize(cx: *mut Context, seed32: *const c_uchar) -> c_int;
|
||||
pub fn secp256k1_context_randomize(cx: *mut Context, seed32: *const c_uchar) -> c_int;
|
||||
|
||||
pub fn secp256k1_pedersen_context_initialize(ctx: *mut Context);
|
||||
pub fn secp256k1_rangeproof_context_initialize(ctx: *mut Context);
|
||||
pub fn secp256k1_pedersen_context_initialize(ctx: *mut Context);
|
||||
pub fn secp256k1_rangeproof_context_initialize(ctx: *mut Context);
|
||||
|
||||
// TODO secp256k1_context_set_illegal_callback
|
||||
// TODO secp256k1_context_set_error_callback
|
||||
// (Actually, I don't really want these exposed; if either of these
|
||||
// are ever triggered it indicates a bug in rust-secp256k1, since
|
||||
// one goal is to use Rust's type system to eliminate all possible
|
||||
// bad inputs.)
|
||||
// TODO secp256k1_context_set_illegal_callback
|
||||
// TODO secp256k1_context_set_error_callback
|
||||
// (Actually, I don't really want these exposed; if either of these
|
||||
// are ever triggered it indicates a bug in rust-secp256k1, since
|
||||
// one goal is to use Rust's type system to eliminate all possible
|
||||
// bad inputs.)
|
||||
|
||||
// Pubkeys
|
||||
pub fn secp256k1_ec_pubkey_parse(cx: *const Context,
|
||||
pk: *mut PublicKey,
|
||||
input: *const c_uchar,
|
||||
in_len: size_t)
|
||||
-> c_int;
|
||||
// Pubkeys
|
||||
pub fn secp256k1_ec_pubkey_parse(cx: *const Context,
|
||||
pk: *mut PublicKey,
|
||||
input: *const c_uchar,
|
||||
in_len: size_t)
|
||||
-> c_int;
|
||||
|
||||
pub fn secp256k1_ec_pubkey_serialize(cx: *const Context,
|
||||
output: *const c_uchar,
|
||||
out_len: *mut size_t,
|
||||
pk: *const PublicKey,
|
||||
compressed: c_uint)
|
||||
-> c_int;
|
||||
pub fn secp256k1_ec_pubkey_serialize(cx: *const Context,
|
||||
output: *const c_uchar,
|
||||
out_len: *mut size_t,
|
||||
pk: *const PublicKey,
|
||||
compressed: c_uint)
|
||||
-> c_int;
|
||||
|
||||
// Signatures
|
||||
pub fn secp256k1_ecdsa_signature_parse_der(cx: *const Context,
|
||||
sig: *mut Signature,
|
||||
input: *const c_uchar,
|
||||
in_len: size_t)
|
||||
-> c_int;
|
||||
// Signatures
|
||||
pub fn secp256k1_ecdsa_signature_parse_der(cx: *const Context,
|
||||
sig: *mut Signature,
|
||||
input: *const c_uchar,
|
||||
in_len: size_t)
|
||||
-> c_int;
|
||||
|
||||
pub fn ecdsa_signature_parse_der_lax(cx: *const Context,
|
||||
sig: *mut Signature,
|
||||
input: *const c_uchar,
|
||||
in_len: size_t)
|
||||
-> c_int;
|
||||
pub fn ecdsa_signature_parse_der_lax(cx: *const Context,
|
||||
sig: *mut Signature,
|
||||
input: *const c_uchar,
|
||||
in_len: size_t)
|
||||
-> c_int;
|
||||
|
||||
pub fn secp256k1_ecdsa_signature_serialize_der(cx: *const Context,
|
||||
output: *const c_uchar,
|
||||
out_len: *mut size_t,
|
||||
sig: *const Signature)
|
||||
-> c_int;
|
||||
pub fn secp256k1_ecdsa_signature_serialize_der(cx: *const Context,
|
||||
output: *const c_uchar,
|
||||
out_len: *mut size_t,
|
||||
sig: *const Signature)
|
||||
-> c_int;
|
||||
|
||||
pub fn secp256k1_ecdsa_recoverable_signature_parse_compact(cx: *const Context,
|
||||
sig: *mut RecoverableSignature,
|
||||
input64: *const c_uchar,
|
||||
recid: c_int)
|
||||
-> c_int;
|
||||
pub fn secp256k1_ecdsa_recoverable_signature_parse_compact(cx: *const Context,
|
||||
sig: *mut RecoverableSignature,
|
||||
input64: *const c_uchar,
|
||||
recid: c_int)
|
||||
-> c_int;
|
||||
|
||||
pub fn secp256k1_ecdsa_recoverable_signature_serialize_compact(cx: *const Context, output64: *const c_uchar,
|
||||
pub fn secp256k1_ecdsa_recoverable_signature_serialize_compact(cx: *const Context, output64: *const c_uchar,
|
||||
recid: *mut c_int, sig: *const RecoverableSignature)
|
||||
-> c_int;
|
||||
|
||||
pub fn secp256k1_ecdsa_recoverable_signature_convert(cx: *const Context,
|
||||
sig: *mut Signature,
|
||||
input: *const RecoverableSignature)
|
||||
-> c_int;
|
||||
pub fn secp256k1_ecdsa_recoverable_signature_convert(cx: *const Context,
|
||||
sig: *mut Signature,
|
||||
input: *const RecoverableSignature)
|
||||
-> c_int;
|
||||
|
||||
pub fn secp256k1_ecdsa_signature_normalize(cx: *const Context,
|
||||
out_sig: *mut Signature,
|
||||
in_sig: *const Signature)
|
||||
-> c_int;
|
||||
pub fn secp256k1_ecdsa_signature_normalize(cx: *const Context,
|
||||
out_sig: *mut Signature,
|
||||
in_sig: *const Signature)
|
||||
-> c_int;
|
||||
|
||||
// ECDSA
|
||||
pub fn secp256k1_ecdsa_verify(cx: *const Context,
|
||||
sig: *const Signature,
|
||||
msg32: *const c_uchar,
|
||||
pk: *const PublicKey)
|
||||
-> c_int;
|
||||
// ECDSA
|
||||
pub fn secp256k1_ecdsa_verify(cx: *const Context,
|
||||
sig: *const Signature,
|
||||
msg32: *const c_uchar,
|
||||
pk: *const PublicKey)
|
||||
-> c_int;
|
||||
|
||||
pub fn secp256k1_ecdsa_sign(cx: *const Context,
|
||||
sig: *mut Signature,
|
||||
msg32: *const c_uchar,
|
||||
sk: *const c_uchar,
|
||||
noncefn: NonceFn,
|
||||
noncedata: *const c_void)
|
||||
-> c_int;
|
||||
pub fn secp256k1_ecdsa_sign(cx: *const Context,
|
||||
sig: *mut Signature,
|
||||
msg32: *const c_uchar,
|
||||
sk: *const c_uchar,
|
||||
noncefn: NonceFn,
|
||||
noncedata: *const c_void)
|
||||
-> c_int;
|
||||
|
||||
pub fn secp256k1_ecdsa_sign_recoverable(cx: *const Context,
|
||||
sig: *mut RecoverableSignature,
|
||||
msg32: *const c_uchar,
|
||||
sk: *const c_uchar,
|
||||
noncefn: NonceFn,
|
||||
noncedata: *const c_void)
|
||||
-> c_int;
|
||||
pub fn secp256k1_ecdsa_sign_recoverable(cx: *const Context,
|
||||
sig: *mut RecoverableSignature,
|
||||
msg32: *const c_uchar,
|
||||
sk: *const c_uchar,
|
||||
noncefn: NonceFn,
|
||||
noncedata: *const c_void)
|
||||
-> c_int;
|
||||
|
||||
pub fn secp256k1_ecdsa_recover(cx: *const Context,
|
||||
pk: *mut PublicKey,
|
||||
sig: *const RecoverableSignature,
|
||||
msg32: *const c_uchar)
|
||||
-> c_int;
|
||||
pub fn secp256k1_ecdsa_recover(cx: *const Context,
|
||||
pk: *mut PublicKey,
|
||||
sig: *const RecoverableSignature,
|
||||
msg32: *const c_uchar)
|
||||
-> c_int;
|
||||
|
||||
// Schnorr
|
||||
pub fn secp256k1_schnorr_sign(cx: *const Context,
|
||||
sig64: *mut c_uchar,
|
||||
msg32: *const c_uchar,
|
||||
sk: *const c_uchar,
|
||||
noncefn: NonceFn,
|
||||
noncedata: *const c_void)
|
||||
-> c_int;
|
||||
// Schnorr
|
||||
pub fn secp256k1_schnorr_sign(cx: *const Context,
|
||||
sig64: *mut c_uchar,
|
||||
msg32: *const c_uchar,
|
||||
sk: *const c_uchar,
|
||||
noncefn: NonceFn,
|
||||
noncedata: *const c_void)
|
||||
-> c_int;
|
||||
|
||||
pub fn secp256k1_schnorr_verify(cx: *const Context,
|
||||
sig64: *const c_uchar,
|
||||
msg32: *const c_uchar,
|
||||
pk: *const PublicKey)
|
||||
-> c_int;
|
||||
pub fn secp256k1_schnorr_verify(cx: *const Context,
|
||||
sig64: *const c_uchar,
|
||||
msg32: *const c_uchar,
|
||||
pk: *const PublicKey)
|
||||
-> c_int;
|
||||
|
||||
pub fn secp256k1_schnorr_recover(cx: *const Context,
|
||||
pk: *mut PublicKey,
|
||||
sig64: *const c_uchar,
|
||||
msg32: *const c_uchar)
|
||||
-> c_int;
|
||||
pub fn secp256k1_schnorr_recover(cx: *const Context,
|
||||
pk: *mut PublicKey,
|
||||
sig64: *const c_uchar,
|
||||
msg32: *const c_uchar)
|
||||
-> c_int;
|
||||
|
||||
// EC
|
||||
pub fn secp256k1_ec_seckey_verify(cx: *const Context, sk: *const c_uchar) -> c_int;
|
||||
// EC
|
||||
pub fn secp256k1_ec_seckey_verify(cx: *const Context, sk: *const c_uchar) -> c_int;
|
||||
|
||||
pub fn secp256k1_ec_pubkey_create(cx: *const Context,
|
||||
pk: *mut PublicKey,
|
||||
sk: *const c_uchar)
|
||||
-> c_int;
|
||||
pub fn secp256k1_ec_pubkey_create(cx: *const Context,
|
||||
pk: *mut PublicKey,
|
||||
sk: *const c_uchar)
|
||||
-> c_int;
|
||||
|
||||
// TODO secp256k1_ec_privkey_export
|
||||
// TODO secp256k1_ec_privkey_import
|
||||
// TODO secp256k1_ec_privkey_export
|
||||
// TODO secp256k1_ec_privkey_import
|
||||
|
||||
pub fn secp256k1_ec_privkey_tweak_add(cx: *const Context,
|
||||
sk: *mut c_uchar,
|
||||
tweak: *const c_uchar)
|
||||
-> c_int;
|
||||
pub fn secp256k1_ec_privkey_tweak_add(cx: *const Context,
|
||||
sk: *mut c_uchar,
|
||||
tweak: *const c_uchar)
|
||||
-> c_int;
|
||||
|
||||
pub fn secp256k1_ec_pubkey_tweak_add(cx: *const Context,
|
||||
pk: *mut PublicKey,
|
||||
tweak: *const c_uchar)
|
||||
-> c_int;
|
||||
pub fn secp256k1_ec_pubkey_tweak_add(cx: *const Context,
|
||||
pk: *mut PublicKey,
|
||||
tweak: *const c_uchar)
|
||||
-> c_int;
|
||||
|
||||
pub fn secp256k1_ec_privkey_tweak_mul(cx: *const Context,
|
||||
sk: *mut c_uchar,
|
||||
tweak: *const c_uchar)
|
||||
-> c_int;
|
||||
pub fn secp256k1_ec_privkey_tweak_mul(cx: *const Context,
|
||||
sk: *mut c_uchar,
|
||||
tweak: *const c_uchar)
|
||||
-> c_int;
|
||||
|
||||
pub fn secp256k1_ec_pubkey_tweak_mul(cx: *const Context,
|
||||
pk: *mut PublicKey,
|
||||
tweak: *const c_uchar)
|
||||
-> c_int;
|
||||
pub fn secp256k1_ec_pubkey_tweak_mul(cx: *const Context,
|
||||
pk: *mut PublicKey,
|
||||
tweak: *const c_uchar)
|
||||
-> c_int;
|
||||
|
||||
pub fn secp256k1_ec_pubkey_combine(cx: *const Context,
|
||||
out: *mut PublicKey,
|
||||
ins: *const *const PublicKey,
|
||||
n: c_int)
|
||||
-> c_int;
|
||||
pub fn secp256k1_ec_pubkey_combine(cx: *const Context,
|
||||
out: *mut PublicKey,
|
||||
ins: *const *const PublicKey,
|
||||
n: c_int)
|
||||
-> c_int;
|
||||
|
||||
pub fn secp256k1_ecdh(cx: *const Context,
|
||||
out: *mut SharedSecret,
|
||||
point: *const PublicKey,
|
||||
scalar: *const c_uchar)
|
||||
-> c_int;
|
||||
pub fn secp256k1_ecdh(cx: *const Context,
|
||||
out: *mut SharedSecret,
|
||||
point: *const PublicKey,
|
||||
scalar: *const c_uchar)
|
||||
-> c_int;
|
||||
|
||||
// Generates a pedersen commitment: *commit = blind * G + value * G2.
|
||||
// The commitment is 33 bytes, the blinding factor is 32 bytes.
|
||||
pub fn secp256k1_pedersen_commit(ctx: *const Context,
|
||||
commit: *mut c_uchar,
|
||||
blind: *const c_uchar,
|
||||
value: uint64_t)
|
||||
-> c_int;
|
||||
// Generates a pedersen commitment: *commit = blind * G + value * G2.
|
||||
// The commitment is 33 bytes, the blinding factor is 32 bytes.
|
||||
pub fn secp256k1_pedersen_commit(ctx: *const Context,
|
||||
commit: *mut c_uchar,
|
||||
blind: *const c_uchar,
|
||||
value: uint64_t)
|
||||
-> c_int;
|
||||
|
||||
// Takes a list of n pointers to 32 byte blinding values, the first negs
|
||||
// of which are treated with positive sign and the rest negative, then
|
||||
// calculates an additional blinding value that adds to zero.
|
||||
pub fn secp256k1_pedersen_blind_sum(ctx: *const Context,
|
||||
blind_out: *const c_uchar,
|
||||
blinds: *const *const c_uchar,
|
||||
n: c_int,
|
||||
npositive: c_int)
|
||||
-> c_int;
|
||||
// Takes a list of n pointers to 32 byte blinding values, the first negs
|
||||
// of which are treated with positive sign and the rest negative, then
|
||||
// calculates an additional blinding value that adds to zero.
|
||||
pub fn secp256k1_pedersen_blind_sum(ctx: *const Context,
|
||||
blind_out: *const c_uchar,
|
||||
blinds: *const *const c_uchar,
|
||||
n: c_int,
|
||||
npositive: c_int)
|
||||
-> c_int;
|
||||
|
||||
// Takes two list of 33-byte commitments and sums the first set, subtracts
|
||||
// the second and returns the resulting commitment.
|
||||
pub fn secp256k1_pedersen_commit_sum(ctx: *const Context,
|
||||
commit_out: *const c_uchar,
|
||||
commits: *const *const c_uchar,
|
||||
pcnt: c_int,
|
||||
ncommits: *const *const c_uchar,
|
||||
ncnt: c_int)
|
||||
-> c_int;
|
||||
// Takes two list of 33-byte commitments and sums the first set, subtracts
|
||||
// the second and returns the resulting commitment.
|
||||
pub fn secp256k1_pedersen_commit_sum(ctx: *const Context,
|
||||
commit_out: *const c_uchar,
|
||||
commits: *const *const c_uchar,
|
||||
pcnt: c_int,
|
||||
ncommits: *const *const c_uchar,
|
||||
ncnt: c_int)
|
||||
-> c_int;
|
||||
|
||||
// Takes two list of 33-byte commitments and sums the first set and
|
||||
// subtracts the second and verifies that they sum to excess.
|
||||
pub fn secp256k1_pedersen_verify_tally(ctx: *const Context,
|
||||
commits: *const *const c_uchar,
|
||||
pcnt: c_int,
|
||||
ncommits: *const *const c_uchar,
|
||||
ncnt: c_int,
|
||||
excess: int64_t)
|
||||
-> c_int;
|
||||
// Takes two list of 33-byte commitments and sums the first set and
|
||||
// subtracts the second and verifies that they sum to excess.
|
||||
pub fn secp256k1_pedersen_verify_tally(ctx: *const Context,
|
||||
commits: *const *const c_uchar,
|
||||
pcnt: c_int,
|
||||
ncommits: *const *const c_uchar,
|
||||
ncnt: c_int,
|
||||
excess: int64_t)
|
||||
-> c_int;
|
||||
|
||||
pub fn secp256k1_rangeproof_info(ctx: *const Context,
|
||||
exp: *mut c_int,
|
||||
mantissa: *mut c_int,
|
||||
min_value: *mut uint64_t,
|
||||
max_value: *mut uint64_t,
|
||||
proof: *const c_uchar,
|
||||
plen: c_int)
|
||||
-> c_int;
|
||||
pub fn secp256k1_rangeproof_info(ctx: *const Context,
|
||||
exp: *mut c_int,
|
||||
mantissa: *mut c_int,
|
||||
min_value: *mut uint64_t,
|
||||
max_value: *mut uint64_t,
|
||||
proof: *const c_uchar,
|
||||
plen: c_int)
|
||||
-> c_int;
|
||||
|
||||
pub fn secp256k1_rangeproof_rewind(ctx: *const Context,
|
||||
blind_out: *mut c_uchar,
|
||||
value_out: *mut uint64_t,
|
||||
message_out: *mut c_uchar,
|
||||
outlen: *mut c_int,
|
||||
nonce: *const c_uchar,
|
||||
min_value: *mut uint64_t,
|
||||
max_value: *mut uint64_t,
|
||||
commit: *const c_uchar,
|
||||
proof: *const c_uchar,
|
||||
plen: c_int)
|
||||
-> c_int;
|
||||
pub fn secp256k1_rangeproof_rewind(ctx: *const Context,
|
||||
blind_out: *mut c_uchar,
|
||||
value_out: *mut uint64_t,
|
||||
message_out: *mut c_uchar,
|
||||
outlen: *mut c_int,
|
||||
nonce: *const c_uchar,
|
||||
min_value: *mut uint64_t,
|
||||
max_value: *mut uint64_t,
|
||||
commit: *const c_uchar,
|
||||
proof: *const c_uchar,
|
||||
plen: c_int)
|
||||
-> c_int;
|
||||
|
||||
pub fn secp256k1_rangeproof_verify(ctx: *const Context,
|
||||
min_value: &mut uint64_t,
|
||||
max_value: &mut uint64_t,
|
||||
commit: *const c_uchar,
|
||||
proof: *const c_uchar,
|
||||
plen: c_int)
|
||||
-> c_int;
|
||||
pub fn secp256k1_rangeproof_verify(ctx: *const Context,
|
||||
min_value: &mut uint64_t,
|
||||
max_value: &mut uint64_t,
|
||||
commit: *const c_uchar,
|
||||
proof: *const c_uchar,
|
||||
plen: c_int)
|
||||
-> c_int;
|
||||
|
||||
pub fn secp256k1_rangeproof_sign(ctx: *const Context,
|
||||
proof: *mut c_uchar,
|
||||
plen: *mut c_int,
|
||||
min_value: uint64_t,
|
||||
commit: *const c_uchar,
|
||||
blind: *const c_uchar,
|
||||
nonce: *const c_uchar,
|
||||
exp: c_int,
|
||||
min_bits: c_int,
|
||||
value: uint64_t)
|
||||
-> c_int;
|
||||
pub fn secp256k1_rangeproof_sign(ctx: *const Context,
|
||||
proof: *mut c_uchar,
|
||||
plen: *mut c_int,
|
||||
min_value: uint64_t,
|
||||
commit: *const c_uchar,
|
||||
blind: *const c_uchar,
|
||||
nonce: *const c_uchar,
|
||||
exp: c_int,
|
||||
min_bits: c_int,
|
||||
value: uint64_t)
|
||||
-> c_int;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -20,25 +20,25 @@ macro_rules! impl_array_newtype {
|
|||
|
||||
impl $thing {
|
||||
#[inline]
|
||||
/// Converts the object to a raw pointer for FFI interfacing
|
||||
/// Converts the object to a raw pointer for FFI interfacing
|
||||
pub fn as_ptr(&self) -> *const $ty {
|
||||
let &$thing(ref dat) = self;
|
||||
dat.as_ptr()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Converts the object to a mutable raw pointer for FFI interfacing
|
||||
/// Converts the object to a mutable raw pointer for FFI interfacing
|
||||
pub fn as_mut_ptr(&mut self) -> *mut $ty {
|
||||
let &mut $thing(ref mut dat) = self;
|
||||
dat.as_mut_ptr()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Returns the length of the object as an array
|
||||
/// Returns the length of the object as an array
|
||||
pub fn len(&self) -> usize { $len }
|
||||
|
||||
#[inline]
|
||||
/// Returns whether the object as an array is empty
|
||||
/// Returns whether the object as an array is empty
|
||||
pub fn is_empty(&self) -> bool { false }
|
||||
}
|
||||
|
||||
|
@ -125,9 +125,9 @@ macro_rules! impl_array_newtype {
|
|||
impl ::std::hash::Hash for $thing {
|
||||
fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
|
||||
state.write(&self.0)
|
||||
// for n in 0..self.len() {
|
||||
// state.write_u8(self.0[n]);
|
||||
// }
|
||||
// for n in 0..self.len() {
|
||||
// state.write_u8(self.0[n]);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,45 +159,48 @@ macro_rules! impl_array_newtype {
|
|||
}
|
||||
}
|
||||
|
||||
impl ::serde::Deserialize for $thing {
|
||||
fn deserialize<D>(d: &mut D) -> Result<$thing, D::Error>
|
||||
where D: ::serde::Deserializer
|
||||
impl<'de> ::serde::Deserialize<'de> for $thing {
|
||||
fn deserialize<D>(d: D) -> Result<$thing, D::Error>
|
||||
where D: ::serde::Deserializer<'de>
|
||||
{
|
||||
// We have to define the Visitor struct inside the function
|
||||
// to make it local ... all we really need is that it's
|
||||
// local to the macro, but this works too :)
|
||||
struct Visitor {
|
||||
marker: ::std::marker::PhantomData<$thing>,
|
||||
}
|
||||
impl ::serde::de::Visitor for Visitor {
|
||||
struct Visitor;
|
||||
|
||||
impl<'di> ::serde::de::Visitor<'di> for Visitor {
|
||||
type Value = $thing;
|
||||
|
||||
fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
formatter.write_str("an array of bytes")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_seq<V>(&mut self, mut v: V) -> Result<$thing, V::Error>
|
||||
where V: ::serde::de::SeqVisitor
|
||||
fn visit_seq<V>(self, mut v: V) -> Result<$thing, V::Error>
|
||||
where V: ::serde::de::SeqAccess<'di>
|
||||
{
|
||||
unsafe {
|
||||
use std::mem;
|
||||
let mut ret: [$ty; $len] = mem::uninitialized();
|
||||
for i in 0..$len {
|
||||
ret[i] = match try!(v.visit()) {
|
||||
ret[i] = match try!(v.next_element()) {
|
||||
Some(c) => c,
|
||||
None => return Err(::serde::de::Error::end_of_stream())
|
||||
None => return Err(::serde::de::Error::invalid_length(i, &self))
|
||||
};
|
||||
}
|
||||
try!(v.end());
|
||||
Ok($thing(ret))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Begin actual function
|
||||
d.visit(Visitor { marker: ::std::marker::PhantomData })
|
||||
// d.visit(Visitor { marker: ::std::marker::PhantomData })
|
||||
d.deserialize_seq(Visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::serde::Serialize for $thing {
|
||||
fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
|
||||
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
|
||||
where S: ::serde::Serializer
|
||||
{
|
||||
(&self.0[..]).serialize(s)
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
//! # Pedersen commitments and related range proofs
|
||||
|
||||
use std::cmp::min;
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
|
||||
use ContextFlag;
|
||||
|
@ -26,6 +28,7 @@ use ffi;
|
|||
use key;
|
||||
use key::SecretKey;
|
||||
use rand::{Rng, OsRng};
|
||||
use serde::{ser, de};
|
||||
|
||||
/// A Pedersen commitment
|
||||
pub struct Commitment(pub [u8; constants::PEDERSEN_COMMITMENT_SIZE]);
|
||||
|
@ -34,327 +37,392 @@ impl_pretty_debug!(Commitment);
|
|||
|
||||
|
||||
impl Commitment {
|
||||
/// Uninitialized commitment, use with caution
|
||||
unsafe fn blank() -> Commitment {
|
||||
mem::uninitialized()
|
||||
}
|
||||
/// Converts a commitment to a public key
|
||||
pub fn to_pubkey(&self, secp: &Secp256k1) -> Result<key::PublicKey, Error> {
|
||||
key::PublicKey::from_slice(secp, &self.0)
|
||||
/// Builds a Hash from a byte vector. If the vector is too short, it will be
|
||||
/// completed by zeroes. If it's too long, it will be truncated.
|
||||
pub fn from_vec(v: Vec<u8>) -> Commitment {
|
||||
let mut h = [0; constants::PEDERSEN_COMMITMENT_SIZE];
|
||||
for i in 0..min(v.len(), constants::PEDERSEN_COMMITMENT_SIZE) {
|
||||
h[i] = v[i];
|
||||
}
|
||||
Commitment(h)
|
||||
}
|
||||
/// Uninitialized commitment, use with caution
|
||||
unsafe fn blank() -> Commitment {
|
||||
mem::uninitialized()
|
||||
}
|
||||
/// Converts a commitment to a public key
|
||||
pub fn to_pubkey(&self, secp: &Secp256k1) -> Result<key::PublicKey, Error> {
|
||||
key::PublicKey::from_slice(secp, &self.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// A range proof. Typically much larger in memory that the above (~5k).
|
||||
#[derive(Copy)]
|
||||
pub struct RangeProof {
|
||||
/// The proof itself, at most 5134 bytes long
|
||||
pub proof: [u8; constants::MAX_PROOF_SIZE],
|
||||
/// The length of the proof
|
||||
pub plen: usize,
|
||||
/// The proof itself, at most 5134 bytes long
|
||||
pub proof: [u8; constants::MAX_PROOF_SIZE],
|
||||
/// The length of the proof
|
||||
pub plen: usize,
|
||||
}
|
||||
|
||||
impl PartialEq for RangeProof {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.proof.as_ref() == other.proof.as_ref()
|
||||
}
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.proof.as_ref() == other.proof.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for RangeProof {
|
||||
#[inline]
|
||||
fn clone(&self) -> RangeProof {
|
||||
unsafe {
|
||||
use std::intrinsics::copy_nonoverlapping;
|
||||
use std::mem;
|
||||
let mut ret: [u8; constants::MAX_PROOF_SIZE] = mem::uninitialized();
|
||||
copy_nonoverlapping(self.proof.as_ptr(),
|
||||
ret.as_mut_ptr(),
|
||||
mem::size_of::<RangeProof>());
|
||||
RangeProof {
|
||||
proof: ret,
|
||||
plen: self.plen,
|
||||
}
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn clone(&self) -> RangeProof {
|
||||
unsafe {
|
||||
use std::intrinsics::copy_nonoverlapping;
|
||||
use std::mem;
|
||||
let mut ret: [u8; constants::MAX_PROOF_SIZE] = mem::uninitialized();
|
||||
copy_nonoverlapping(self.proof.as_ptr(),
|
||||
ret.as_mut_ptr(),
|
||||
mem::size_of::<RangeProof>());
|
||||
RangeProof {
|
||||
proof: ret,
|
||||
plen: self.plen,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ser::Serialize for RangeProof {
|
||||
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
|
||||
where S: ser::Serializer
|
||||
{
|
||||
(&self.proof[..self.plen]).serialize(s)
|
||||
}
|
||||
}
|
||||
|
||||
struct Visitor;
|
||||
|
||||
impl<'di> de::Visitor<'di> for Visitor {
|
||||
type Value = RangeProof;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("an array of bytes")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_seq<V>(self, mut v: V) -> Result<RangeProof, V::Error>
|
||||
where V: de::SeqAccess<'di>
|
||||
{
|
||||
unsafe {
|
||||
use std::mem;
|
||||
let mut ret: [u8; constants::MAX_PROOF_SIZE] = mem::uninitialized();
|
||||
let mut i = 0;
|
||||
while let Some(val) = v.next_element()? {
|
||||
ret[i] = val;
|
||||
i += 1;
|
||||
}
|
||||
Ok(RangeProof {
|
||||
proof: ret,
|
||||
plen: i,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> de::Deserialize<'de> for RangeProof {
|
||||
fn deserialize<D>(d: D) -> Result<RangeProof, D::Error>
|
||||
where D: de::Deserializer<'de>
|
||||
{
|
||||
|
||||
// Begin actual function
|
||||
d.deserialize_seq(Visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for RangeProof {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.proof[..self.plen as usize]
|
||||
}
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.proof[..self.plen as usize]
|
||||
}
|
||||
}
|
||||
|
||||
impl RangeProof {
|
||||
/// The range proof as a byte slice.
|
||||
pub fn bytes(&self) -> &[u8] {
|
||||
&self.proof[..self.plen as usize]
|
||||
}
|
||||
/// Length of the range proof in bytes.
|
||||
pub fn len(&self) -> usize {
|
||||
self.plen
|
||||
}
|
||||
pub fn zero() -> RangeProof {
|
||||
RangeProof {
|
||||
proof: [0; constants::MAX_PROOF_SIZE],
|
||||
plen: 0,
|
||||
}
|
||||
}
|
||||
/// The range proof as a byte slice.
|
||||
pub fn bytes(&self) -> &[u8] {
|
||||
&self.proof[..self.plen as usize]
|
||||
}
|
||||
/// Length of the range proof in bytes.
|
||||
pub fn len(&self) -> usize {
|
||||
self.plen
|
||||
}
|
||||
}
|
||||
|
||||
/// The range that was proven
|
||||
pub struct ProofRange {
|
||||
/// Min value that was proven
|
||||
pub min: u64,
|
||||
/// Max value that was proven
|
||||
pub max: u64,
|
||||
/// Min value that was proven
|
||||
pub min: u64,
|
||||
/// Max value that was proven
|
||||
pub max: u64,
|
||||
}
|
||||
|
||||
/// Information about a valid proof after rewinding it.
|
||||
pub struct ProofInfo {
|
||||
/// Whether the proof is valid or not
|
||||
pub success: bool,
|
||||
/// Value that was used by the commitment
|
||||
pub value: u64,
|
||||
/// Message embedded in the proof
|
||||
pub message: [u8; constants::PROOF_MSG_SIZE],
|
||||
/// Length of the embedded message
|
||||
pub mlen: i32,
|
||||
/// Min value that was proven
|
||||
pub min: u64,
|
||||
/// Max value that was proven
|
||||
pub max: u64,
|
||||
/// Exponent used by the proof
|
||||
pub exp: i32,
|
||||
/// Mantissa used by the proof
|
||||
pub mantissa: i32,
|
||||
/// Whether the proof is valid or not
|
||||
pub success: bool,
|
||||
/// Value that was used by the commitment
|
||||
pub value: u64,
|
||||
/// Message embedded in the proof
|
||||
pub message: [u8; constants::PROOF_MSG_SIZE],
|
||||
/// Length of the embedded message
|
||||
pub mlen: i32,
|
||||
/// Min value that was proven
|
||||
pub min: u64,
|
||||
/// Max value that was proven
|
||||
pub max: u64,
|
||||
/// Exponent used by the proof
|
||||
pub exp: i32,
|
||||
/// Mantissa used by the proof
|
||||
pub mantissa: i32,
|
||||
}
|
||||
|
||||
impl ::std::fmt::Debug for RangeProof {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
try!(write!(f, "{}(", stringify!(RangeProof)));
|
||||
for i in self.proof[..self.plen].iter().cloned() {
|
||||
try!(write!(f, "{:02x}", i));
|
||||
}
|
||||
write!(f, ")[{}]", self.plen)
|
||||
}
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
try!(write!(f, "{}(", stringify!(RangeProof)));
|
||||
for i in self.proof[..self.plen].iter().cloned() {
|
||||
try!(write!(f, "{:02x}", i));
|
||||
}
|
||||
write!(f, ")[{}]", self.plen)
|
||||
}
|
||||
}
|
||||
|
||||
impl Secp256k1 {
|
||||
/// Creates a pedersen commitment from a value and a blinding factor
|
||||
pub fn commit(&self, value: u64, blind: SecretKey) -> Result<Commitment, Error> {
|
||||
/// Creates a pedersen commitment from a value and a blinding factor
|
||||
pub fn commit(&self, value: u64, blind: SecretKey) -> Result<Commitment, Error> {
|
||||
|
||||
if self.caps != ContextFlag::Commit {
|
||||
return Err(Error::IncapableContext);
|
||||
}
|
||||
let mut commit = [0; 33];
|
||||
unsafe {
|
||||
ffi::secp256k1_pedersen_commit(self.ctx, commit.as_mut_ptr(), blind.as_ptr(), value)
|
||||
};
|
||||
Ok(Commitment(commit))
|
||||
}
|
||||
if self.caps != ContextFlag::Commit {
|
||||
return Err(Error::IncapableContext);
|
||||
}
|
||||
let mut commit = [0; 33];
|
||||
unsafe {
|
||||
ffi::secp256k1_pedersen_commit(self.ctx, commit.as_mut_ptr(), blind.as_ptr(), value)
|
||||
};
|
||||
Ok(Commitment(commit))
|
||||
}
|
||||
|
||||
/// Convenience method to Create a pedersen commitment only from a value, with a zero blinding factor
|
||||
pub fn commit_value(&self, value: u64) -> Result<Commitment, Error> {
|
||||
/// Convenience method to Create a pedersen commitment only from a value,
|
||||
/// with a zero blinding factor
|
||||
pub fn commit_value(&self, value: u64) -> Result<Commitment, Error> {
|
||||
|
||||
if self.caps != ContextFlag::Commit {
|
||||
return Err(Error::IncapableContext);
|
||||
}
|
||||
let mut commit = [0; 33];
|
||||
let zblind = [0; 32];
|
||||
unsafe {
|
||||
ffi::secp256k1_pedersen_commit(self.ctx, commit.as_mut_ptr(), zblind.as_ptr(), value)
|
||||
};
|
||||
Ok(Commitment(commit))
|
||||
}
|
||||
if self.caps != ContextFlag::Commit {
|
||||
return Err(Error::IncapableContext);
|
||||
}
|
||||
let mut commit = [0; 33];
|
||||
let zblind = [0; 32];
|
||||
unsafe {
|
||||
ffi::secp256k1_pedersen_commit(self.ctx, commit.as_mut_ptr(), zblind.as_ptr(), value)
|
||||
};
|
||||
Ok(Commitment(commit))
|
||||
}
|
||||
|
||||
/// Taking vectors of positive and negative commitments as well as an
|
||||
/// expected excess, verifies that it all sums to zero.
|
||||
pub fn verify_commit_sum(&self,
|
||||
positive: Vec<Commitment>,
|
||||
negative: Vec<Commitment>,
|
||||
excess: i64)
|
||||
-> bool {
|
||||
let pos = map_vec!(positive, |p| p.0.as_ptr());
|
||||
let neg = map_vec!(negative, |n| n.0.as_ptr());
|
||||
unsafe {
|
||||
ffi::secp256k1_pedersen_verify_tally(self.ctx,
|
||||
pos.as_ptr(),
|
||||
pos.len() as i32,
|
||||
neg.as_ptr(),
|
||||
neg.len() as i32,
|
||||
excess) == 1
|
||||
}
|
||||
}
|
||||
/// Taking vectors of positive and negative commitments as well as an
|
||||
/// expected excess, verifies that it all sums to zero.
|
||||
pub fn verify_commit_sum(&self,
|
||||
positive: Vec<Commitment>,
|
||||
negative: Vec<Commitment>,
|
||||
excess: i64)
|
||||
-> bool {
|
||||
let pos = map_vec!(positive, |p| p.0.as_ptr());
|
||||
let neg = map_vec!(negative, |n| n.0.as_ptr());
|
||||
unsafe {
|
||||
ffi::secp256k1_pedersen_verify_tally(self.ctx,
|
||||
pos.as_ptr(),
|
||||
pos.len() as i32,
|
||||
neg.as_ptr(),
|
||||
neg.len() as i32,
|
||||
excess) == 1
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the sum of multiple positive and negative pedersen commitments.
|
||||
pub fn commit_sum(&self,
|
||||
positive: Vec<Commitment>,
|
||||
negative: Vec<Commitment>)
|
||||
-> Result<Commitment, Error> {
|
||||
let pos = map_vec!(positive, |p| p.0.as_ptr());
|
||||
let neg = map_vec!(negative, |n| n.0.as_ptr());
|
||||
let mut ret = unsafe { Commitment::blank() };
|
||||
let err = unsafe {
|
||||
ffi::secp256k1_pedersen_commit_sum(self.ctx,
|
||||
ret.as_mut_ptr(),
|
||||
pos.as_ptr(),
|
||||
pos.len() as i32,
|
||||
neg.as_ptr(),
|
||||
neg.len() as i32)
|
||||
};
|
||||
if err == 1 {
|
||||
Ok(ret)
|
||||
} else {
|
||||
Err(Error::IncorrectCommitSum)
|
||||
}
|
||||
}
|
||||
/// Computes the sum of multiple positive and negative pedersen commitments.
|
||||
pub fn commit_sum(&self,
|
||||
positive: Vec<Commitment>,
|
||||
negative: Vec<Commitment>)
|
||||
-> Result<Commitment, Error> {
|
||||
let pos = map_vec!(positive, |p| p.0.as_ptr());
|
||||
let neg = map_vec!(negative, |n| n.0.as_ptr());
|
||||
let mut ret = unsafe { Commitment::blank() };
|
||||
let err = unsafe {
|
||||
ffi::secp256k1_pedersen_commit_sum(self.ctx,
|
||||
ret.as_mut_ptr(),
|
||||
pos.as_ptr(),
|
||||
pos.len() as i32,
|
||||
neg.as_ptr(),
|
||||
neg.len() as i32)
|
||||
};
|
||||
if err == 1 {
|
||||
Ok(ret)
|
||||
} else {
|
||||
Err(Error::IncorrectCommitSum)
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the sum of multiple positive and negative blinding factors.
|
||||
pub fn blind_sum(&self,
|
||||
positive: Vec<SecretKey>,
|
||||
negative: Vec<SecretKey>)
|
||||
-> Result<SecretKey, Error> {
|
||||
let mut neg = map_vec!(negative, |n| n.as_ptr());
|
||||
let mut all = map_vec!(positive, |p| p.as_ptr());
|
||||
all.append(&mut neg);
|
||||
let mut ret: [u8; 32] = unsafe { mem::uninitialized() };
|
||||
unsafe {
|
||||
assert_eq!(ffi::secp256k1_pedersen_blind_sum(self.ctx,
|
||||
/// Computes the sum of multiple positive and negative blinding factors.
|
||||
pub fn blind_sum(&self,
|
||||
positive: Vec<SecretKey>,
|
||||
negative: Vec<SecretKey>)
|
||||
-> Result<SecretKey, Error> {
|
||||
let mut neg = map_vec!(negative, |n| n.as_ptr());
|
||||
let mut all = map_vec!(positive, |p| p.as_ptr());
|
||||
all.append(&mut neg);
|
||||
let mut ret: [u8; 32] = unsafe { mem::uninitialized() };
|
||||
unsafe {
|
||||
assert_eq!(ffi::secp256k1_pedersen_blind_sum(self.ctx,
|
||||
ret.as_mut_ptr(),
|
||||
all.as_ptr(),
|
||||
all.len() as i32,
|
||||
positive.len() as i32),
|
||||
1)
|
||||
}
|
||||
// secp256k1 should never return an invalid private
|
||||
SecretKey::from_slice(self, &ret)
|
||||
}
|
||||
}
|
||||
// secp256k1 should never return an invalid private
|
||||
SecretKey::from_slice(self, &ret)
|
||||
}
|
||||
|
||||
/// Produces a range proof for the provided value, using min and max bounds, relying
|
||||
/// on the blinding factor and commitment.
|
||||
pub fn range_proof(&self,
|
||||
min: u64,
|
||||
value: u64,
|
||||
blind: SecretKey,
|
||||
commit: Commitment)
|
||||
-> RangeProof {
|
||||
/// Produces a range proof for the provided value, using min and max
|
||||
/// bounds, relying
|
||||
/// on the blinding factor and commitment.
|
||||
pub fn range_proof(&self,
|
||||
min: u64,
|
||||
value: u64,
|
||||
blind: SecretKey,
|
||||
commit: Commitment)
|
||||
-> RangeProof {
|
||||
|
||||
let mut rng = OsRng::new().unwrap();
|
||||
let mut nonce = [0u8; 32];
|
||||
rng.fill_bytes(&mut nonce);
|
||||
let mut rng = OsRng::new().unwrap();
|
||||
let mut nonce = [0u8; 32];
|
||||
rng.fill_bytes(&mut nonce);
|
||||
|
||||
let mut retried = false;
|
||||
let mut proof = [0; constants::MAX_PROOF_SIZE];
|
||||
let mut plen = constants::MAX_PROOF_SIZE as i32;
|
||||
loop {
|
||||
let err = unsafe {
|
||||
// because: "This can randomly fail with probability around one in 2^100.
|
||||
// If this happens, buy a lottery ticket and retry."
|
||||
ffi::secp256k1_rangeproof_sign(self.ctx,
|
||||
proof.as_mut_ptr(),
|
||||
&mut plen,
|
||||
min,
|
||||
commit.as_ptr(),
|
||||
blind.as_ptr(),
|
||||
nonce.as_ptr(),
|
||||
0,
|
||||
64,
|
||||
value)
|
||||
};
|
||||
if retried {
|
||||
break;
|
||||
}
|
||||
if err == 1 {
|
||||
retried = true;
|
||||
}
|
||||
}
|
||||
RangeProof {
|
||||
proof: proof,
|
||||
plen: plen as usize,
|
||||
}
|
||||
}
|
||||
let mut retried = false;
|
||||
let mut proof = [0; constants::MAX_PROOF_SIZE];
|
||||
let mut plen = constants::MAX_PROOF_SIZE as i32;
|
||||
loop {
|
||||
let err = unsafe {
|
||||
// because: "This can randomly fail with probability around one in 2^100.
|
||||
// If this happens, buy a lottery ticket and retry."
|
||||
ffi::secp256k1_rangeproof_sign(self.ctx,
|
||||
proof.as_mut_ptr(),
|
||||
&mut plen,
|
||||
min,
|
||||
commit.as_ptr(),
|
||||
blind.as_ptr(),
|
||||
nonce.as_ptr(),
|
||||
0,
|
||||
64,
|
||||
value)
|
||||
};
|
||||
if retried {
|
||||
break;
|
||||
}
|
||||
if err == 1 {
|
||||
retried = true;
|
||||
}
|
||||
}
|
||||
RangeProof {
|
||||
proof: proof,
|
||||
plen: plen as usize,
|
||||
}
|
||||
}
|
||||
|
||||
/// Verify a proof that a committed value is within a range.
|
||||
pub fn verify_range_proof(&self,
|
||||
commit: Commitment,
|
||||
proof: RangeProof)
|
||||
-> Result<ProofRange, Error> {
|
||||
let mut min: u64 = 0;
|
||||
let mut max: u64 = 0;
|
||||
/// Verify a proof that a committed value is within a range.
|
||||
pub fn verify_range_proof(&self,
|
||||
commit: Commitment,
|
||||
proof: RangeProof)
|
||||
-> Result<ProofRange, Error> {
|
||||
let mut min: u64 = 0;
|
||||
let mut max: u64 = 0;
|
||||
|
||||
let success = unsafe {
|
||||
ffi::secp256k1_rangeproof_verify(self.ctx,
|
||||
&mut min,
|
||||
&mut max,
|
||||
commit.as_ptr(),
|
||||
proof.proof.as_ptr(),
|
||||
proof.plen as i32) == 1
|
||||
};
|
||||
if success {
|
||||
Ok(ProofRange {
|
||||
min: min,
|
||||
max: max,
|
||||
})
|
||||
} else {
|
||||
Err(Error::InvalidRangeProof)
|
||||
}
|
||||
}
|
||||
let success = unsafe {
|
||||
ffi::secp256k1_rangeproof_verify(self.ctx,
|
||||
&mut min,
|
||||
&mut max,
|
||||
commit.as_ptr(),
|
||||
proof.proof.as_ptr(),
|
||||
proof.plen as i32) == 1
|
||||
};
|
||||
if success {
|
||||
Ok(ProofRange {
|
||||
min: min,
|
||||
max: max,
|
||||
})
|
||||
} else {
|
||||
Err(Error::InvalidRangeProof)
|
||||
}
|
||||
}
|
||||
|
||||
/// Verify a range proof proof and rewind the proof to recover information sent by its author.
|
||||
pub fn rewind_range_proof(&self,
|
||||
commit: Commitment,
|
||||
proof: RangeProof,
|
||||
nonce: [u8; 32])
|
||||
-> ProofInfo {
|
||||
let mut value: u64 = 0;
|
||||
let mut blind: [u8; 32] = unsafe { mem::uninitialized() };
|
||||
let mut message = [0u8; constants::PROOF_MSG_SIZE];
|
||||
let mut mlen: i32 = 0;
|
||||
let mut min: u64 = 0;
|
||||
let mut max: u64 = 0;
|
||||
let success = unsafe {
|
||||
ffi::secp256k1_rangeproof_rewind(self.ctx,
|
||||
blind.as_mut_ptr(),
|
||||
&mut value,
|
||||
message.as_mut_ptr(),
|
||||
&mut mlen,
|
||||
nonce.as_ptr(),
|
||||
&mut min,
|
||||
&mut max,
|
||||
commit.as_ptr(),
|
||||
proof.proof.as_ptr(),
|
||||
proof.plen as i32) == 1
|
||||
};
|
||||
ProofInfo {
|
||||
success: success,
|
||||
value: value,
|
||||
message: message,
|
||||
mlen: mlen,
|
||||
min: min,
|
||||
max: max,
|
||||
exp: 0,
|
||||
mantissa: 0,
|
||||
}
|
||||
}
|
||||
/// Verify a range proof proof and rewind the proof to recover information
|
||||
/// sent by its author.
|
||||
pub fn rewind_range_proof(&self,
|
||||
commit: Commitment,
|
||||
proof: RangeProof,
|
||||
nonce: [u8; 32])
|
||||
-> ProofInfo {
|
||||
let mut value: u64 = 0;
|
||||
let mut blind: [u8; 32] = unsafe { mem::uninitialized() };
|
||||
let mut message = [0u8; constants::PROOF_MSG_SIZE];
|
||||
let mut mlen: i32 = 0;
|
||||
let mut min: u64 = 0;
|
||||
let mut max: u64 = 0;
|
||||
let success = unsafe {
|
||||
ffi::secp256k1_rangeproof_rewind(self.ctx,
|
||||
blind.as_mut_ptr(),
|
||||
&mut value,
|
||||
message.as_mut_ptr(),
|
||||
&mut mlen,
|
||||
nonce.as_ptr(),
|
||||
&mut min,
|
||||
&mut max,
|
||||
commit.as_ptr(),
|
||||
proof.proof.as_ptr(),
|
||||
proof.plen as i32) == 1
|
||||
};
|
||||
ProofInfo {
|
||||
success: success,
|
||||
value: value,
|
||||
message: message,
|
||||
mlen: mlen,
|
||||
min: min,
|
||||
max: max,
|
||||
exp: 0,
|
||||
mantissa: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// General information extracted from a range proof. Does not provide any
|
||||
/// information about the value or the message (see rewind).
|
||||
pub fn range_proof_info(&self, proof: RangeProof) -> ProofInfo {
|
||||
let mut exp: i32 = 0;
|
||||
let mut mantissa: i32 = 0;
|
||||
let mut min: u64 = 0;
|
||||
let mut max: u64 = 0;
|
||||
let success = unsafe {
|
||||
ffi::secp256k1_rangeproof_info(self.ctx,
|
||||
&mut exp,
|
||||
&mut mantissa,
|
||||
&mut min,
|
||||
&mut max,
|
||||
proof.proof.as_ptr(),
|
||||
proof.plen as i32) == 1
|
||||
};
|
||||
ProofInfo {
|
||||
success: success,
|
||||
value: 0,
|
||||
message: [0; 4096],
|
||||
mlen: 0,
|
||||
min: min,
|
||||
max: max,
|
||||
exp: exp,
|
||||
mantissa: mantissa,
|
||||
}
|
||||
}
|
||||
/// General information extracted from a range proof. Does not provide any
|
||||
/// information about the value or the message (see rewind).
|
||||
pub fn range_proof_info(&self, proof: RangeProof) -> ProofInfo {
|
||||
let mut exp: i32 = 0;
|
||||
let mut mantissa: i32 = 0;
|
||||
let mut min: u64 = 0;
|
||||
let mut max: u64 = 0;
|
||||
let success = unsafe {
|
||||
ffi::secp256k1_rangeproof_info(self.ctx,
|
||||
&mut exp,
|
||||
&mut mantissa,
|
||||
&mut min,
|
||||
&mut max,
|
||||
proof.proof.as_ptr(),
|
||||
proof.plen as i32) == 1
|
||||
};
|
||||
ProofInfo {
|
||||
success: success,
|
||||
value: 0,
|
||||
message: [0; 4096],
|
||||
mlen: 0,
|
||||
min: min,
|
||||
max: max,
|
||||
exp: exp,
|
||||
mantissa: mantissa,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,166 +32,166 @@ impl_array_newtype!(Signature, u8, constants::SCHNORR_SIGNATURE_SIZE);
|
|||
impl_pretty_debug!(Signature);
|
||||
|
||||
impl Signature {
|
||||
/// Deserializes a signature from a 64-byte vector
|
||||
pub fn deserialize(data: &[u8]) -> Signature {
|
||||
assert_eq!(data.len(), constants::SCHNORR_SIGNATURE_SIZE);
|
||||
unsafe {
|
||||
let mut ret: Signature = mem::uninitialized();
|
||||
ptr::copy_nonoverlapping(data.as_ptr(),
|
||||
ret.as_mut_ptr(),
|
||||
constants::SCHNORR_SIGNATURE_SIZE);
|
||||
ret
|
||||
}
|
||||
}
|
||||
/// Deserializes a signature from a 64-byte vector
|
||||
pub fn deserialize(data: &[u8]) -> Signature {
|
||||
assert_eq!(data.len(), constants::SCHNORR_SIGNATURE_SIZE);
|
||||
unsafe {
|
||||
let mut ret: Signature = mem::uninitialized();
|
||||
ptr::copy_nonoverlapping(data.as_ptr(),
|
||||
ret.as_mut_ptr(),
|
||||
constants::SCHNORR_SIGNATURE_SIZE);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
/// Serializes a signature to a 64-byte vector
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut ret = Vec::with_capacity(constants::SCHNORR_SIGNATURE_SIZE);
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(self.as_ptr(),
|
||||
ret.as_mut_ptr(),
|
||||
constants::SCHNORR_SIGNATURE_SIZE);
|
||||
ret.set_len(constants::SCHNORR_SIGNATURE_SIZE);
|
||||
}
|
||||
ret
|
||||
}
|
||||
/// Serializes a signature to a 64-byte vector
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut ret = Vec::with_capacity(constants::SCHNORR_SIGNATURE_SIZE);
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(self.as_ptr(),
|
||||
ret.as_mut_ptr(),
|
||||
constants::SCHNORR_SIGNATURE_SIZE);
|
||||
ret.set_len(constants::SCHNORR_SIGNATURE_SIZE);
|
||||
}
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl Secp256k1 {
|
||||
/// Create a Schnorr signature
|
||||
pub fn sign_schnorr(&self, msg: &Message, sk: &SecretKey) -> Result<Signature, Error> {
|
||||
if self.caps == ContextFlag::VerifyOnly || self.caps == ContextFlag::None {
|
||||
return Err(Error::IncapableContext);
|
||||
}
|
||||
/// Create a Schnorr signature
|
||||
pub fn sign_schnorr(&self, msg: &Message, sk: &SecretKey) -> Result<Signature, Error> {
|
||||
if self.caps == ContextFlag::VerifyOnly || self.caps == ContextFlag::None {
|
||||
return Err(Error::IncapableContext);
|
||||
}
|
||||
|
||||
let mut ret: Signature = unsafe { mem::uninitialized() };
|
||||
unsafe {
|
||||
// We can assume the return value because it's not possible to construct
|
||||
// an invalid signature from a valid `Message` and `SecretKey`
|
||||
let err = ffi::secp256k1_schnorr_sign(self.ctx,
|
||||
ret.as_mut_ptr(),
|
||||
msg.as_ptr(),
|
||||
sk.as_ptr(),
|
||||
ffi::secp256k1_nonce_function_rfc6979,
|
||||
ptr::null());
|
||||
debug_assert_eq!(err, 1);
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
let mut ret: Signature = unsafe { mem::uninitialized() };
|
||||
unsafe {
|
||||
// We can assume the return value because it's not possible to construct
|
||||
// an invalid signature from a valid `Message` and `SecretKey`
|
||||
let err = ffi::secp256k1_schnorr_sign(self.ctx,
|
||||
ret.as_mut_ptr(),
|
||||
msg.as_ptr(),
|
||||
sk.as_ptr(),
|
||||
ffi::secp256k1_nonce_function_rfc6979,
|
||||
ptr::null());
|
||||
debug_assert_eq!(err, 1);
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
/// Verify a Schnorr signature
|
||||
pub fn verify_schnorr(&self,
|
||||
msg: &Message,
|
||||
sig: &Signature,
|
||||
pk: &PublicKey)
|
||||
-> Result<(), Error> {
|
||||
if self.caps == ContextFlag::SignOnly || self.caps == ContextFlag::None {
|
||||
return Err(Error::IncapableContext);
|
||||
}
|
||||
/// Verify a Schnorr signature
|
||||
pub fn verify_schnorr(&self,
|
||||
msg: &Message,
|
||||
sig: &Signature,
|
||||
pk: &PublicKey)
|
||||
-> Result<(), Error> {
|
||||
if self.caps == ContextFlag::SignOnly || self.caps == ContextFlag::None {
|
||||
return Err(Error::IncapableContext);
|
||||
}
|
||||
|
||||
if !pk.is_valid() {
|
||||
Err(Error::InvalidPublicKey)
|
||||
} else if unsafe {
|
||||
ffi::secp256k1_schnorr_verify(self.ctx, sig.as_ptr(), msg.as_ptr(), pk.as_ptr())
|
||||
} == 0 {
|
||||
Err(Error::IncorrectSignature)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
if !pk.is_valid() {
|
||||
Err(Error::InvalidPublicKey)
|
||||
} else if unsafe {
|
||||
ffi::secp256k1_schnorr_verify(self.ctx, sig.as_ptr(), msg.as_ptr(), pk.as_ptr())
|
||||
} == 0 {
|
||||
Err(Error::IncorrectSignature)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the public key for which `sig` is a valid signature for `msg`.
|
||||
/// Requires a verify-capable context.
|
||||
pub fn recover_schnorr(&self, msg: &Message, sig: &Signature) -> Result<PublicKey, Error> {
|
||||
if self.caps == ContextFlag::SignOnly || self.caps == ContextFlag::None {
|
||||
return Err(Error::IncapableContext);
|
||||
}
|
||||
/// Retrieves the public key for which `sig` is a valid signature for `msg`.
|
||||
/// Requires a verify-capable context.
|
||||
pub fn recover_schnorr(&self, msg: &Message, sig: &Signature) -> Result<PublicKey, Error> {
|
||||
if self.caps == ContextFlag::SignOnly || self.caps == ContextFlag::None {
|
||||
return Err(Error::IncapableContext);
|
||||
}
|
||||
|
||||
let mut pk = unsafe { ffi::PublicKey::blank() };
|
||||
unsafe {
|
||||
if ffi::secp256k1_schnorr_recover(self.ctx, &mut pk, sig.as_ptr(), msg.as_ptr()) != 1 {
|
||||
return Err(Error::InvalidSignature);
|
||||
}
|
||||
};
|
||||
Ok(PublicKey::from(pk))
|
||||
}
|
||||
let mut pk = unsafe { ffi::PublicKey::blank() };
|
||||
unsafe {
|
||||
if ffi::secp256k1_schnorr_recover(self.ctx, &mut pk, sig.as_ptr(), msg.as_ptr()) != 1 {
|
||||
return Err(Error::InvalidSignature);
|
||||
}
|
||||
};
|
||||
Ok(PublicKey::from(pk))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rand::{Rng, thread_rng};
|
||||
use ContextFlag;
|
||||
use Message;
|
||||
use Secp256k1;
|
||||
use Error::IncapableContext;
|
||||
use super::Signature;
|
||||
use rand::{Rng, thread_rng};
|
||||
use ContextFlag;
|
||||
use Message;
|
||||
use Secp256k1;
|
||||
use Error::IncapableContext;
|
||||
use super::Signature;
|
||||
|
||||
#[test]
|
||||
fn capabilities() {
|
||||
let none = Secp256k1::with_caps(ContextFlag::None);
|
||||
let sign = Secp256k1::with_caps(ContextFlag::SignOnly);
|
||||
let vrfy = Secp256k1::with_caps(ContextFlag::VerifyOnly);
|
||||
let full = Secp256k1::with_caps(ContextFlag::Full);
|
||||
#[test]
|
||||
fn capabilities() {
|
||||
let none = Secp256k1::with_caps(ContextFlag::None);
|
||||
let sign = Secp256k1::with_caps(ContextFlag::SignOnly);
|
||||
let vrfy = Secp256k1::with_caps(ContextFlag::VerifyOnly);
|
||||
let full = Secp256k1::with_caps(ContextFlag::Full);
|
||||
|
||||
let mut msg = [0u8; 32];
|
||||
thread_rng().fill_bytes(&mut msg);
|
||||
let msg = Message::from_slice(&msg).unwrap();
|
||||
let mut msg = [0u8; 32];
|
||||
thread_rng().fill_bytes(&mut msg);
|
||||
let msg = Message::from_slice(&msg).unwrap();
|
||||
|
||||
let (sk, pk) = full.generate_keypair(&mut thread_rng()).unwrap();
|
||||
let (sk, pk) = full.generate_keypair(&mut thread_rng()).unwrap();
|
||||
|
||||
// Try signing
|
||||
assert_eq!(none.sign_schnorr(&msg, &sk), Err(IncapableContext));
|
||||
assert_eq!(vrfy.sign_schnorr(&msg, &sk), Err(IncapableContext));
|
||||
assert!(sign.sign_schnorr(&msg, &sk).is_ok());
|
||||
assert!(full.sign_schnorr(&msg, &sk).is_ok());
|
||||
assert_eq!(sign.sign_schnorr(&msg, &sk), full.sign_schnorr(&msg, &sk));
|
||||
let sig = full.sign_schnorr(&msg, &sk).unwrap();
|
||||
// Try signing
|
||||
assert_eq!(none.sign_schnorr(&msg, &sk), Err(IncapableContext));
|
||||
assert_eq!(vrfy.sign_schnorr(&msg, &sk), Err(IncapableContext));
|
||||
assert!(sign.sign_schnorr(&msg, &sk).is_ok());
|
||||
assert!(full.sign_schnorr(&msg, &sk).is_ok());
|
||||
assert_eq!(sign.sign_schnorr(&msg, &sk), full.sign_schnorr(&msg, &sk));
|
||||
let sig = full.sign_schnorr(&msg, &sk).unwrap();
|
||||
|
||||
// Try verifying
|
||||
assert_eq!(none.verify_schnorr(&msg, &sig, &pk), Err(IncapableContext));
|
||||
assert_eq!(sign.verify_schnorr(&msg, &sig, &pk), Err(IncapableContext));
|
||||
assert!(vrfy.verify_schnorr(&msg, &sig, &pk).is_ok());
|
||||
assert!(full.verify_schnorr(&msg, &sig, &pk).is_ok());
|
||||
// Try verifying
|
||||
assert_eq!(none.verify_schnorr(&msg, &sig, &pk), Err(IncapableContext));
|
||||
assert_eq!(sign.verify_schnorr(&msg, &sig, &pk), Err(IncapableContext));
|
||||
assert!(vrfy.verify_schnorr(&msg, &sig, &pk).is_ok());
|
||||
assert!(full.verify_schnorr(&msg, &sig, &pk).is_ok());
|
||||
|
||||
// Try pk recovery
|
||||
assert_eq!(none.recover_schnorr(&msg, &sig), Err(IncapableContext));
|
||||
assert_eq!(sign.recover_schnorr(&msg, &sig), Err(IncapableContext));
|
||||
assert!(vrfy.recover_schnorr(&msg, &sig).is_ok());
|
||||
assert!(full.recover_schnorr(&msg, &sig).is_ok());
|
||||
// Try pk recovery
|
||||
assert_eq!(none.recover_schnorr(&msg, &sig), Err(IncapableContext));
|
||||
assert_eq!(sign.recover_schnorr(&msg, &sig), Err(IncapableContext));
|
||||
assert!(vrfy.recover_schnorr(&msg, &sig).is_ok());
|
||||
assert!(full.recover_schnorr(&msg, &sig).is_ok());
|
||||
|
||||
assert_eq!(vrfy.recover_schnorr(&msg, &sig),
|
||||
assert_eq!(vrfy.recover_schnorr(&msg, &sig),
|
||||
full.recover_schnorr(&msg, &sig));
|
||||
assert_eq!(full.recover_schnorr(&msg, &sig), Ok(pk));
|
||||
}
|
||||
assert_eq!(full.recover_schnorr(&msg, &sig), Ok(pk));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sign_verify() {
|
||||
let mut s = Secp256k1::new();
|
||||
s.randomize(&mut thread_rng());
|
||||
#[test]
|
||||
fn sign_verify() {
|
||||
let mut s = Secp256k1::new();
|
||||
s.randomize(&mut thread_rng());
|
||||
|
||||
let mut msg = [0u8; 32];
|
||||
thread_rng().fill_bytes(&mut msg);
|
||||
let msg = Message::from_slice(&msg).unwrap();
|
||||
let mut msg = [0u8; 32];
|
||||
thread_rng().fill_bytes(&mut msg);
|
||||
let msg = Message::from_slice(&msg).unwrap();
|
||||
|
||||
let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap();
|
||||
let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap();
|
||||
|
||||
let sig = s.sign_schnorr(&msg, &sk).unwrap();
|
||||
assert!(s.verify_schnorr(&msg, &sig, &pk).is_ok());
|
||||
}
|
||||
let sig = s.sign_schnorr(&msg, &sk).unwrap();
|
||||
assert!(s.verify_schnorr(&msg, &sig, &pk).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize() {
|
||||
let mut s = Secp256k1::new();
|
||||
s.randomize(&mut thread_rng());
|
||||
#[test]
|
||||
fn deserialize() {
|
||||
let mut s = Secp256k1::new();
|
||||
s.randomize(&mut thread_rng());
|
||||
|
||||
let mut msg = [0u8; 32];
|
||||
thread_rng().fill_bytes(&mut msg);
|
||||
let msg = Message::from_slice(&msg).unwrap();
|
||||
let mut msg = [0u8; 32];
|
||||
thread_rng().fill_bytes(&mut msg);
|
||||
let msg = Message::from_slice(&msg).unwrap();
|
||||
|
||||
let (sk, _) = s.generate_keypair(&mut thread_rng()).unwrap();
|
||||
let (sk, _) = s.generate_keypair(&mut thread_rng()).unwrap();
|
||||
|
||||
let sig1 = s.sign_schnorr(&msg, &sk).unwrap();
|
||||
let sig2 = Signature::deserialize(&sig1.serialize());
|
||||
assert_eq!(sig1, sig2);
|
||||
}
|
||||
let sig1 = s.sign_schnorr(&msg, &sk).unwrap();
|
||||
let sig2 = Signature::deserialize(&sig1.serialize());
|
||||
assert_eq!(sig1, sig2);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue