use core::fmt;
use std::io;
use secp256k1_zkp::rand::{CryptoRng, RngCore};
use secp256k1_zkp::{self, PublicKey, Secp256k1, SecretKey, Signing};
#[cfg(feature = "serde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use super::CommitmentEncoder;
use crate::encode::{self, Decodable, Encodable};
use crate::encoding;
use crate::hashes::sha256d;
type ExplicitInner = [u8; 32];
type ConfInner = PublicKey;
const EXPLICIT_LEN: usize = 32;
const CONFIDENTIAL_LEN: usize = 33;
const CONFIDENTIAL_LEN_LESS_PREFIX: usize = CONFIDENTIAL_LEN - 1;
const CONF_PREFIX_1: u8 = 0x02;
const CONF_PREFIX_2: u8 = 0x03;
#[derive(Copy, Clone, Debug, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub enum Nonce {
#[default]
Null,
Explicit(ExplicitInner),
Confidential(ConfInner),
}
impl Nonce {
pub fn new_confidential<R: RngCore + CryptoRng, C: Signing>(
rng: &mut R,
secp: &Secp256k1<C>,
receiver_blinding_pk: &ConfInner,
) -> (Self, SecretKey) {
let ephemeral_sk = SecretKey::new(rng);
Self::with_ephemeral_sk(secp, ephemeral_sk, receiver_blinding_pk)
}
pub fn with_ephemeral_sk<C: Signing>(
secp: &Secp256k1<C>,
ephemeral_sk: SecretKey,
receiver_blinding_pk: &ConfInner,
) -> (Self, SecretKey) {
let sender_pk = ConfInner::from_secret_key(secp, &ephemeral_sk);
let shared_secret = Self::make_shared_secret(receiver_blinding_pk, &ephemeral_sk);
(Self::Confidential(sender_pk), shared_secret)
}
pub fn shared_secret(&self, receiver_blinding_sk: &SecretKey) -> Option<SecretKey> {
match self {
Self::Confidential(sender_pk) =>
Some(Self::make_shared_secret(sender_pk, receiver_blinding_sk)),
_ => None,
}
}
fn make_shared_secret(pk: &ConfInner, sk: &SecretKey) -> SecretKey {
let xy = secp256k1_zkp::ecdh::shared_secret_point(pk, sk);
let shared_secret = {
let mut dh_secret = [0u8; CONFIDENTIAL_LEN];
dh_secret[0] = if xy.last().unwrap() % 2 == 0 { CONF_PREFIX_1 } else { CONF_PREFIX_2 };
dh_secret[1..].copy_from_slice(&xy[0..32]);
sha256d::Hash::hash(&dh_secret).to_byte_array()
};
SecretKey::from_slice(&shared_secret[..32]).expect("always has exactly 32 bytes")
}
pub fn encoded_length(&self) -> usize {
match *self {
Self::Null => 1,
Self::Explicit(..) => 1 + EXPLICIT_LEN,
Self::Confidential(..) => CONFIDENTIAL_LEN,
}
}
pub fn from_commitment(bytes: &[u8]) -> Result<Self, encode::Error> {
Ok(Self::Confidential(
ConfInner::from_slice(bytes).map_err(secp256k1_zkp::Error::Upstream)?,
))
}
pub fn is_null(&self) -> bool { matches!(*self, Self::Null) }
pub fn is_explicit(&self) -> bool { matches!(*self, Self::Explicit(_)) }
pub fn is_confidential(&self) -> bool { matches!(*self, Self::Confidential(_)) }
pub fn explicit(&self) -> Option<ExplicitInner> {
match *self {
Self::Explicit(i) => Some(i),
_ => None,
}
}
pub fn commitment(&self) -> Option<ConfInner> {
match *self {
Self::Confidential(i) => Some(i),
_ => None,
}
}
}
impl From<ConfInner> for Nonce {
fn from(from: ConfInner) -> Self { Self::Confidential(from) }
}
impl fmt::Display for Nonce {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Self::Null => f.write_str("null"),
Self::Explicit(n) => {
for b in &n {
write!(f, "{:02x}", b)?;
}
Ok(())
}
Self::Confidential(pk) => write!(f, "{:02x}", pk),
}
}
}
impl Encodable for Nonce {
fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, encode::Error> {
match *self {
Self::Null => {
s.write_all(&[0u8])?;
Ok(1)
}
Self::Explicit(n) => {
s.write_all(&[1u8])?;
s.write_all(&n)?;
Ok(1 + EXPLICIT_LEN)
}
Self::Confidential(commitment) => {
s.write_all(&commitment.serialize())?;
Ok(CONFIDENTIAL_LEN)
}
}
}
}
impl Decodable for Nonce {
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
let mut buf = [0u8; CONFIDENTIAL_LEN];
d.read_exact(&mut buf[0..1])?;
match buf[0] {
0 => Ok(Self::Null),
1 => {
let mut buf = [0; EXPLICIT_LEN];
d.read_exact(&mut buf)?;
Ok(Self::Explicit(buf))
}
p if p == CONF_PREFIX_1 || p == CONF_PREFIX_2 => {
d.read_exact(&mut buf[1..])?;
Ok(Self::Confidential(ConfInner::from_slice(&buf)?))
}
p => Err(encode::Error::InvalidConfidentialPrefix(p)),
}
}
}
#[cfg(feature = "serde")]
impl Serialize for Nonce {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
use serde::ser::SerializeSeq;
let seq_len = match *self {
Self::Null => 1,
Self::Explicit(_) | Self::Confidential(_) => 2,
};
let mut seq = s.serialize_seq(Some(seq_len))?;
match *self {
Self::Null => seq.serialize_element(&0u8)?,
Self::Explicit(n) => {
seq.serialize_element(&1u8)?;
seq.serialize_element(&n)?;
}
Self::Confidential(commitment) => {
seq.serialize_element(&2u8)?;
seq.serialize_element(&commitment)?;
}
}
seq.end()
}
}
#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for Nonce {
fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
use serde::de::{Error, SeqAccess, Visitor};
struct CommitVisitor;
impl<'de> Visitor<'de> for CommitVisitor {
type Value = Nonce;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("a committed value")
}
fn visit_seq<A: SeqAccess<'de>>(self, mut access: A) -> Result<Nonce, A::Error> {
let prefix = access.next_element::<u8>()?;
match prefix {
Some(0) => Ok(Self::Value::Null),
Some(1) => match access.next_element()? {
Some(x) => Ok(Self::Value::Explicit(x)),
None => Err(A::Error::custom("missing explicit nonce")),
},
Some(2) => match access.next_element()? {
Some(x) => Ok(Self::Value::Confidential(x)),
None => Err(A::Error::custom("missing nonce")),
},
_ => Err(A::Error::custom("wrong or missing prefix")),
}
}
}
d.deserialize_seq(CommitVisitor)
}
}
encoding::encoder_newtype_exact! {
#[derive(Clone, Debug)]
pub struct Encoder<'e>(CommitmentEncoder<'e>);
}
impl encoding::Encode for Nonce {
type Encoder<'e> = Encoder<'e>;
fn encoder(&self) -> Self::Encoder<'_> {
Encoder::new(match *self {
Self::Null => CommitmentEncoder::Null(0),
Self::Explicit(ref id) => CommitmentEncoder::Explicit32(Some(1), id),
Self::Confidential(ref gen) => CommitmentEncoder::Explicit33(gen.serialize()),
})
}
}
decoder_state_machine! {
pub struct Decoder(enum DecoderInner {
Done(Nonce),
Errored,
DecodePrefix {
decoder: encoding::ArrayDecoder<1>,
=> transition_decode_prefix(prefix, ...) -> Result {
match prefix {
[0] => Ok(DecoderInner::Done(Nonce::Null)),
[1] => {
Ok(DecoderInner::DecodeExplicit { decoder: encoding::ArrayDecoder::default() })
},
[prefix @ (CONF_PREFIX_1 | CONF_PREFIX_2)] => {
Ok(DecoderInner::DecodeConfidential { decoder: encoding::ArrayDecoder::default(), prefix })
},
[prefix] => Err(DecoderErrorInner::InvalidConfidentialPrefix { prefix })
}
}
},
DecodeExplicit {
decoder: encoding::ArrayDecoder<EXPLICIT_LEN>
=> transition_decode_explicit(bytes, ...) -> Result {
Ok(DecoderInner::Done(Nonce::Explicit(bytes)))
}
},
DecodeConfidential {
decoder: encoding::ArrayDecoder<CONFIDENTIAL_LEN_LESS_PREFIX>,
prefix: u8
=> transition_decode_confidential(x_coord, ...) -> Result {
let mut bytes = [0; CONFIDENTIAL_LEN];
bytes[0] = prefix;
bytes[1..].copy_from_slice(&x_coord);
let gen = ConfInner::from_slice(&bytes)
.map_err(DecoderErrorInner::InvalidCommitment)?;
Ok(DecoderInner::Done(Nonce::Confidential(gen)))
}
},
});
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct DecoderError(enum DecoderErrorInner {
[macro-inserted decoder variants]
InvalidConfidentialPrefix {
prefix: u8,
},
InvalidCommitment(bitcoin::secp256k1::Error),
});
}
impl fmt::Display for DecoderError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use DecoderErrorInner as Inner;
match self.0 {
Inner::DecodePrefix(_) => f.write_str("failed to decode prefix"),
Inner::DecodeExplicit(_) => f.write_str("failed to decode explicit value"),
Inner::DecodeConfidential(_) => f.write_str("failed to decode confidential value"),
Inner::InvalidConfidentialPrefix { prefix, .. } => {
write!(
f,
"confidential prefix 0x{:02x} was not one of 0, 1, 0x{:02x} or 0x{:02x}",
prefix, CONF_PREFIX_1, CONF_PREFIX_2,
)
}
Inner::InvalidCommitment(_) => f.write_str("failed to parse confidential commitment"),
}
}
}
impl std::error::Error for DecoderError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use DecoderErrorInner as Inner;
match self.0 {
Inner::DecodePrefix(ref e) => Some(e),
Inner::DecodeExplicit(ref e) => Some(e),
Inner::DecodeConfidential(ref e) => Some(e),
Inner::InvalidConfidentialPrefix { .. } => None,
Inner::InvalidCommitment(ref e) => Some(e),
}
}
}
impl Default for Decoder {
fn default() -> Self {
Self(DecoderInner::DecodePrefix { decoder: encoding::ArrayDecoder::default() })
}
}