use std::{
fmt::{self, Display},
str::FromStr,
};
use nostr::{FromBech32, PublicKey};
use serde::{Deserialize, Serialize};
use crate::error::CarbonadoError;
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct EncodeInfo {
pub input_len: u32,
pub output_len: u32,
pub bytes_compressed: u32,
pub compression_factor: f32,
pub bytes_encrypted: u32,
pub bytes_ecc: u32,
pub bytes_verifiable: u32,
pub amplification_factor: f32,
pub padding_len: u32,
pub chunk_len: u32,
pub verifiable_slice_count: u16,
pub chunk_slice_count: u16,
}
pub struct Encoded(pub Vec<u8>, pub bao::Hash, pub EncodeInfo);
pub struct Secp256k1PubKey {
pub pk: secp256k1::PublicKey,
pub x_only_pk: [u8; 32],
}
impl TryFrom<&str> for Secp256k1PubKey {
type Error = CarbonadoError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
let pk = match (
value.get(0..2).expect("key is at least 2 characters long"),
value.len(),
) {
("+n", _) => secp256k1::PublicKey::from_x_only_public_key(
secp256k1::XOnlyPublicKey::from_slice(
&PublicKey::from_bech32(value.get(1..).unwrap())?.to_bytes(),
)?,
secp256k1::Parity::Even,
),
("-n", _) => secp256k1::PublicKey::from_x_only_public_key(
secp256k1::XOnlyPublicKey::from_slice(
&PublicKey::from_bech32(value.get(1..).unwrap())?.to_bytes(),
)?,
secp256k1::Parity::Odd,
),
("np", _) => secp256k1::PublicKey::from_x_only_public_key(
secp256k1::XOnlyPublicKey::from_slice(&PublicKey::from_bech32(value)?.to_bytes())?,
secp256k1::Parity::Odd,
),
("02", 66) => secp256k1::PublicKey::from_str(value)?,
("03", 66) => secp256k1::PublicKey::from_str(value)?,
(_, 64) => {
let value = "03".to_owned() + value;
secp256k1::PublicKey::from_str(&value)?
}
_ => {
return Err(CarbonadoError::IncorrectPubKeyFormat);
}
};
let (x_only_pk, _) = pk.x_only_public_key();
let x_only_pk = x_only_pk.serialize();
Ok(Self { pk, x_only_pk })
}
}
impl Display for Secp256k1PubKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { pk, .. } = self;
f.write_str(&pk.to_string())
}
}
impl AsRef<[u8; 32]> for Secp256k1PubKey {
fn as_ref(&self) -> &[u8; 32] {
&self.x_only_pk
}
}
impl Secp256k1PubKey {
pub fn new(pk: secp256k1::PublicKey) -> Self {
let (x_only_pk, _) = pk.x_only_public_key();
let x_only_pk = x_only_pk.serialize();
Self { pk, x_only_pk }
}
pub fn to_bytes(&self) -> Vec<u8> {
let Self { pk, .. } = self;
pk.serialize().to_vec()
}
pub fn into_inner(&self) -> secp256k1::PublicKey {
let Self { pk, .. } = self;
pk.to_owned()
}
}
#[test]
fn test_pubkey_decode() {
let result = Secp256k1PubKey::try_from(
"+npub14rnkcwkw0q5lnmjye7ffxvy7yxscyjl3u4mrr5qxsks76zctmz3qvuftjz",
);
assert!(result.is_ok());
assert_eq!(
result.unwrap().to_string(),
"02a8e76c3ace7829f9ee44cf9293309e21a1824bf1e57631d00685a1ed0b0bd8a2"
);
let result = Secp256k1PubKey::try_from(
"-npub14rnkcwkw0q5lnmjye7ffxvy7yxscyjl3u4mrr5qxsks76zctmz3qvuftjz",
);
assert!(result.is_ok());
assert_eq!(
result.unwrap().to_string(),
"03a8e76c3ace7829f9ee44cf9293309e21a1824bf1e57631d00685a1ed0b0bd8a2"
);
let result = Secp256k1PubKey::try_from(
"a8e76c3ace7829f9ee44cf9293309e21a1824bf1e57631d00685a1ed0b0bd8a2",
);
assert!(result.is_ok());
assert_eq!(
result.unwrap().to_string(),
"03a8e76c3ace7829f9ee44cf9293309e21a1824bf1e57631d00685a1ed0b0bd8a2"
);
let result = Secp256k1PubKey::try_from(
"npub1qqqqqqqrxtrcx8vut2vlrqa0c2qn5mmf59hdmflkls8dsyg9vmnqsclxwk",
);
assert!(result.is_ok());
assert_eq!(
result.unwrap().to_string(),
"03000000000332c7831d9c5a99f183afc2813a6f69a16edda7f6fc0ed8110566e6"
);
}