secp256k1_zkp/
lib.rs

1// Bitcoin secp256k1 bindings
2// Written in 2014 by
3//   Dawid Ciężarkiewicz
4//   Andrew Poelstra
5//
6// To the extent possible under law, the author(s) have dedicated all
7// copyright and related and neighboring rights to this software to
8// the public domain worldwide. This software is distributed without
9// any warranty.
10//
11// You should have received a copy of the CC0 Public Domain Dedication
12// along with this software.
13// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
14//
15
16//! # Secp256k1-zkp
17//!
18//! Rust bindings for libsecp256k1-zkp, a fork of Pieter Wuille's secp256k1 library.
19//!
20//! This library re-exports everything from `secp256k1` and adds bindings for the following modules:
21//!
22//! - generators
23//! - range proofs
24//! - pedersen commitments
25//!
26//! As such, it can be used as a drop-in replacement for `secp256k1`. All types are interoperable
27//! (as long as you are dependening on the correct version) which means [`SecretKey`]s and the [`Context`]
28//! are interoperable.
29//!
30
31// Coding conventions
32#![cfg_attr(docsrs, feature(doc_auto_cfg))]
33#![warn(missing_docs)]
34#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
35
36/// Re-export of the internal FFI bindings crate
37pub extern crate secp256k1_zkp_sys;
38/// Re-export of the internal FFI bindings crate under the alternate name `ffi`
39pub use secp256k1_zkp_sys as ffi;
40
41extern crate secp256k1;
42
43#[cfg(feature = "hashes")]
44pub use secp256k1::hashes;
45/// Re-export of the `rand` crate
46#[cfg(feature = "actual-rand")]
47pub extern crate actual_rand as rand;
48/// Re-export of the `serde` crate
49#[cfg(feature = "serde")]
50pub extern crate actual_serde as serde;
51#[cfg(any(test, feature = "std"))]
52extern crate core;
53#[cfg(all(test, feature = "serde"))]
54extern crate serde_test;
55#[cfg(all(test, target_arch = "wasm32"))]
56#[macro_use]
57extern crate wasm_bindgen_test;
58
59use core::{fmt, str};
60
61pub use secp256k1::constants;
62pub use secp256k1::ecdh;
63pub use secp256k1::ecdsa;
64pub use secp256k1::schnorr;
65
66pub use crate::{PublicKey, SecretKey};
67
68pub use secp256k1::*;
69
70#[cfg(feature = "serde")]
71mod serde_util;
72mod zkp;
73pub use crate::zkp::*;
74
75pub use secp256k1::Error as UpstreamError;
76
77/// An ECDSA error
78#[derive(Copy, PartialEq, Eq, Clone, Debug)]
79pub enum Error {
80    /// Calling through to `secp256k1` resulted in an error.
81    Upstream(UpstreamError),
82    /// Failed to produce a surjection proof because of an internal error within `libsecp256k1-zkp`
83    CannotProveSurjection,
84    /// Given bytes don't represent a valid surjection proof
85    InvalidSurjectionProof,
86    /// Given bytes don't represent a valid pedersen commitment
87    InvalidPedersenCommitment,
88    /// Failed to produce a range proof because of an internal error within `libsecp256k1-zkp`
89    CannotMakeRangeProof,
90    /// Given range proof does not prove that the commitment is within a range
91    InvalidRangeProof,
92    /// Bad generator
93    InvalidGenerator,
94    /// Tweak must of len 32
95    InvalidTweakLength,
96    /// Tweak must be less than secp curve order
97    TweakOutOfBounds,
98    /// Given bytes don't represent a valid adaptor signature
99    InvalidEcdsaAdaptorSignature,
100    /// Failed to decrypt an adaptor signature because of an internal error within `libsecp256k1-zkp`
101    CannotDecryptAdaptorSignature,
102    /// Failed to recover an adaptor secret from an adaptor signature because of an internal error within `libsecp256k1-zkp`
103    CannotRecoverAdaptorSecret,
104    /// Given adaptor signature is not valid for the provided combination of public key, encryption key and message
105    CannotVerifyAdaptorSignature,
106    /// Given bytes don't represent a valid whitelist signature
107    InvalidWhitelistSignature,
108    /// Invalid PAK list
109    InvalidPakList,
110    /// Couldn't create whitelist signature with the given data.
111    CannotCreateWhitelistSignature,
112    /// The given whitelist signature doesn't correctly prove inclusion in the whitelist.
113    InvalidWhitelistProof,
114}
115
116// Passthrough Debug to Display, since errors should be user-visible
117impl fmt::Display for Error {
118    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
119        let str = match *self {
120            Error::CannotProveSurjection => "failed to prove surjection",
121            Error::InvalidSurjectionProof => "malformed surjection proof",
122            Error::InvalidPedersenCommitment => "malformed pedersen commitment",
123            Error::CannotMakeRangeProof => "failed to generate range proof",
124            Error::InvalidRangeProof => "failed to verify range proof",
125            Error::InvalidGenerator => "malformed generator",
126            Error::InvalidEcdsaAdaptorSignature => "malformed ecdsa adaptor signature",
127            Error::CannotDecryptAdaptorSignature => "failed to decrypt adaptor signature",
128            Error::CannotRecoverAdaptorSecret => "failed to recover adaptor secret",
129            Error::CannotVerifyAdaptorSignature => "failed to verify adaptor signature",
130            Error::Upstream(inner) => return write!(f, "{}", inner),
131            Error::InvalidTweakLength => "Tweak must of size 32",
132            Error::TweakOutOfBounds => "Tweak must be less than secp curve order",
133            Error::InvalidWhitelistSignature => "malformed whitelist signature",
134            Error::InvalidPakList => "invalid PAK list",
135            Error::CannotCreateWhitelistSignature => {
136                "cannot create whitelist signature with the given data"
137            }
138            Error::InvalidWhitelistProof => {
139                "given whitelist signature doesn't correctly prove inclusion in the whitelist"
140            }
141        };
142
143        f.write_str(str)
144    }
145}
146
147#[cfg(feature = "std")]
148impl std::error::Error for Error {}
149
150impl From<UpstreamError> for Error {
151    fn from(e: UpstreamError) -> Self {
152        Error::Upstream(e)
153    }
154}
155
156/// Utility function used to parse hex into a target u8 buffer. Returns
157/// the number of bytes converted or an error if it encounters an invalid
158/// character or unexpected end of string.
159fn from_hex(hex: &str, target: &mut [u8]) -> Result<usize, ()> {
160    if hex.len() % 2 == 1 || hex.len() > target.len() * 2 {
161        return Err(());
162    }
163
164    let mut b = 0;
165    let mut idx = 0;
166    for c in hex.bytes() {
167        b <<= 4;
168        match c {
169            b'A'..=b'F' => b |= c - b'A' + 10,
170            b'a'..=b'f' => b |= c - b'a' + 10,
171            b'0'..=b'9' => b |= c - b'0',
172            _ => return Err(()),
173        }
174        if (idx & 1) == 1 {
175            target[idx / 2] = b;
176            b = 0;
177        }
178        idx += 1;
179    }
180    Ok(idx / 2)
181}