mirror of
https://github.com/aljazceru/cdk.git
synced 2026-01-12 01:15:44 +01:00
feat: nut11 p2pk
This commit is contained in:
@@ -168,15 +168,19 @@ impl Client for HttpClient {
|
||||
async fn post_swap(
|
||||
&self,
|
||||
mint_url: Url,
|
||||
split_request: SwapRequest,
|
||||
swap_request: SwapRequest,
|
||||
) -> Result<SwapResponse, Error> {
|
||||
let url = join_url(mint_url, &["v1", "swap"])?;
|
||||
|
||||
let res = minreq::post(url).with_json(&split_request)?.send()?;
|
||||
println!("{}", serde_json::to_string(&swap_request).unwrap());
|
||||
|
||||
let res = minreq::post(url).with_json(&swap_request)?.send()?;
|
||||
|
||||
let value = res.json::<Value>()?;
|
||||
println!("{}", value);
|
||||
let response: Result<SwapResponse, serde_json::Error> =
|
||||
serde_json::from_value(value.clone());
|
||||
println!("{:?}", response);
|
||||
|
||||
match response {
|
||||
Ok(res) => Ok(res),
|
||||
|
||||
@@ -311,6 +311,7 @@ impl Mint {
|
||||
amount,
|
||||
b,
|
||||
keyset_id,
|
||||
..
|
||||
} = blinded_message;
|
||||
|
||||
let keyset = self
|
||||
|
||||
@@ -9,7 +9,7 @@ use cashu::nuts::nut07::ProofState;
|
||||
use cashu::nuts::nut11::SigningKey;
|
||||
use cashu::nuts::{
|
||||
BlindedSignature, CurrencyUnit, Id, KeySetInfo, Keys, MintInfo, P2PKConditions, PreMintSecrets,
|
||||
PreSwap, Proof, Proofs, SwapRequest, Token,
|
||||
PreSwap, Proof, Proofs, SigFlag, SwapRequest, Token,
|
||||
};
|
||||
#[cfg(feature = "nut07")]
|
||||
use cashu::secret::Secret;
|
||||
@@ -234,6 +234,7 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
|
||||
}
|
||||
|
||||
let keysets = self.client.get_mint_keysets(mint_url.try_into()?).await?;
|
||||
println!("{:?}", keysets);
|
||||
|
||||
self.localstore
|
||||
.add_mint_keysets(
|
||||
@@ -353,7 +354,17 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
|
||||
|
||||
// TODO: if none fetch keyset for mint
|
||||
|
||||
let keys = self.localstore.get_keys(&active_keyset_id.unwrap()).await?;
|
||||
let keys =
|
||||
if let Some(keys) = self.localstore.get_keys(&active_keyset_id.unwrap()).await? {
|
||||
keys
|
||||
} else {
|
||||
self.get_mint_keys(&token.mint, active_keyset_id.unwrap())
|
||||
.await?;
|
||||
self.localstore
|
||||
.get_keys(&active_keyset_id.unwrap())
|
||||
.await?
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
// Sum amount of all proofs
|
||||
let amount: Amount = token.proofs.iter().map(|p| p.amount).sum();
|
||||
@@ -372,15 +383,20 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
|
||||
swap_response.signatures,
|
||||
pre_swap.pre_mint_secrets.rs(),
|
||||
pre_swap.pre_mint_secrets.secrets(),
|
||||
&keys.unwrap(),
|
||||
&keys,
|
||||
)?;
|
||||
// println!("{:?}", p);
|
||||
let mint_proofs = proofs.entry(token.mint).or_default();
|
||||
|
||||
mint_proofs.extend(p);
|
||||
}
|
||||
//println!("{:?}", proofs);
|
||||
|
||||
for (mint, proofs) in proofs {
|
||||
self.localstore.add_proofs(mint, proofs).await?;
|
||||
for (mint, p) in proofs {
|
||||
println!("{:?}", serde_json::to_string(&p));
|
||||
println!("{:?}", mint);
|
||||
self.add_mint(mint.clone()).await?;
|
||||
self.localstore.add_proofs(mint, p).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -408,9 +424,9 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
|
||||
desired_messages.sort_secrets();
|
||||
desired_messages
|
||||
} else {
|
||||
let value = proofs.iter().map(|p| p.amount).sum();
|
||||
let amount = proofs.iter().map(|p| p.amount).sum();
|
||||
|
||||
PreMintSecrets::random(active_keyset_id, value)?
|
||||
PreMintSecrets::random(active_keyset_id, amount)?
|
||||
};
|
||||
|
||||
let swap_request = SwapRequest::new(proofs, pre_mint_secrets.blinded_messages());
|
||||
@@ -420,7 +436,51 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
|
||||
swap_request,
|
||||
})
|
||||
}
|
||||
/*
|
||||
/// Create Swap Payload
|
||||
async fn create_swap_signed(
|
||||
&mut self,
|
||||
mint_url: &UncheckedUrl,
|
||||
unit: &CurrencyUnit,
|
||||
amount: Option<Amount>,
|
||||
proofs: Proofs,
|
||||
signing_key: Option<SigningKey>,
|
||||
) -> Result<PreSwap, Error> {
|
||||
let active_keyset_id = self.active_mint_keyset(mint_url, unit).await?.unwrap();
|
||||
|
||||
let pre_mint_secrets = if let Some(amount) = amount {
|
||||
let mut desired_messages = PreMintSecrets::random(active_keyset_id, amount)?;
|
||||
|
||||
let change_amount = proofs.iter().map(|p| p.amount).sum::<Amount>() - amount;
|
||||
|
||||
let change_messages = if let Some(signing_key) = signing_key {
|
||||
PreMintSecrets::random_signed(active_keyset_id, change_amount, signing_key)?
|
||||
} else {
|
||||
PreMintSecrets::random(active_keyset_id, change_amount)?
|
||||
};
|
||||
// Combine the BlindedMessages totoalling the desired amount with change
|
||||
desired_messages.combine(change_messages);
|
||||
// Sort the premint secrets to avoid finger printing
|
||||
desired_messages.sort_secrets();
|
||||
desired_messages
|
||||
} else {
|
||||
let amount = proofs.iter().map(|p| p.amount).sum();
|
||||
|
||||
if let Some(signing_key) = signing_key {
|
||||
PreMintSecrets::random_signed(active_keyset_id, amount, signing_key)?
|
||||
} else {
|
||||
PreMintSecrets::random(active_keyset_id, amount)?
|
||||
}
|
||||
};
|
||||
|
||||
let swap_request = SwapRequest::new(proofs, pre_mint_secrets.blinded_messages());
|
||||
|
||||
Ok(PreSwap {
|
||||
pre_mint_secrets,
|
||||
swap_request,
|
||||
})
|
||||
}
|
||||
*/
|
||||
pub async fn process_swap_response(
|
||||
&self,
|
||||
blinded_messages: PreMintSecrets,
|
||||
@@ -752,6 +812,7 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
|
||||
encoded_token: &str,
|
||||
signing_keys: Vec<SigningKey>,
|
||||
) -> Result<(), Error> {
|
||||
let signing_key = signing_keys[0].clone();
|
||||
let pubkey_secret_key: HashMap<String, SigningKey> = signing_keys
|
||||
.into_iter()
|
||||
.map(|s| (s.public_key().to_string(), s))
|
||||
@@ -778,6 +839,8 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
|
||||
|
||||
let mut proofs = token.proofs;
|
||||
|
||||
let mut sig_flag = None;
|
||||
|
||||
for proof in &mut proofs {
|
||||
if let Ok(secret) =
|
||||
<cashu::secret::Secret as TryInto<cashu::nuts::nut10::Secret>>::try_into(
|
||||
@@ -786,21 +849,36 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
|
||||
{
|
||||
let conditions: Result<P2PKConditions, _> = secret.try_into();
|
||||
if let Ok(conditions) = conditions {
|
||||
println!("{:?}", conditions);
|
||||
let pubkeys = conditions.pubkeys;
|
||||
|
||||
for pubkey in pubkeys {
|
||||
if let Some(signing) = pubkey_secret_key.get(&pubkey.to_string()) {
|
||||
proof.sign_p2pk_proof(signing.clone()).ok();
|
||||
proof.sign_p2pk_proof(signing.clone()).unwrap();
|
||||
proof.verify_p2pk().unwrap();
|
||||
println!("v");
|
||||
}
|
||||
}
|
||||
|
||||
sig_flag = Some(conditions.sig_flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let pre_swap = self
|
||||
let mut pre_swap = self
|
||||
.create_swap(&token.mint, &unit, Some(amount), proofs)
|
||||
.await?;
|
||||
|
||||
if let Some(sigflag) = sig_flag {
|
||||
if sigflag.eq(&SigFlag::SigAll) {
|
||||
for blinded_message in &mut pre_swap.swap_request.outputs {
|
||||
blinded_message
|
||||
.sign_p2pk_blinded_message(signing_key.clone())
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let swap_response = self
|
||||
.client
|
||||
.post_swap(token.mint.clone().try_into()?, pre_swap.swap_request)
|
||||
@@ -824,54 +902,70 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
/*
|
||||
pub async fn claim_p2pk_locked_proofs(
|
||||
&mut self,
|
||||
sigflag: SigFlag,
|
||||
mint_url: &UncheckedUrl,
|
||||
unit: &CurrencyUnit,
|
||||
signing_key: SigningKey,
|
||||
proofs: Proofs,
|
||||
) -> Result<(), Error> {
|
||||
let active_keyset_id = self.active_mint_keyset(&mint_url, &unit).await?;
|
||||
|
||||
pub async fn claim_p2pk_locked_proofs(
|
||||
&mut self,
|
||||
mint_url: &UncheckedUrl,
|
||||
unit: &CurrencyUnit,
|
||||
signing_key: SigningKey,
|
||||
proofs: Proofs,
|
||||
) -> Result<(), Error> {
|
||||
let active_keyset_id = self.active_mint_keyset(&mint_url, &unit).await?;
|
||||
let keys = self.localstore.get_keys(&active_keyset_id.unwrap()).await?;
|
||||
|
||||
let keys = self.localstore.get_keys(&active_keyset_id.unwrap()).await?;
|
||||
let mut signed_proofs: Proofs = Vec::with_capacity(proofs.len());
|
||||
|
||||
let mut signed_proofs: Proofs = Vec::with_capacity(proofs.len());
|
||||
// Sum amount of all proofs
|
||||
let amount: Amount = proofs.iter().map(|p| p.amount).sum();
|
||||
|
||||
// Sum amount of all proofs
|
||||
let amount: Amount = proofs.iter().map(|p| p.amount).sum();
|
||||
for p in proofs.clone() {
|
||||
let mut p = p;
|
||||
p.sign_p2pk_proof(signing_key.clone()).unwrap();
|
||||
signed_proofs.push(p);
|
||||
}
|
||||
|
||||
for p in proofs.clone() {
|
||||
let mut p = p;
|
||||
p.sign_p2pk_proof(signing_key.clone()).unwrap();
|
||||
signed_proofs.push(p);
|
||||
let pre_swap = match sigflag {
|
||||
SigFlag::SigInputs => {
|
||||
self.create_swap(mint_url, &unit, Some(amount), signed_proofs)
|
||||
.await?
|
||||
}
|
||||
SigFlag::SigAll => {
|
||||
self.create_swap_signed(
|
||||
mint_url,
|
||||
unit,
|
||||
Some(amount),
|
||||
signed_proofs,
|
||||
Some(signing_key),
|
||||
)
|
||||
.await?
|
||||
}
|
||||
_ => todo!(),
|
||||
};
|
||||
|
||||
let swap_response = self
|
||||
.client
|
||||
.post_swap(mint_url.clone().try_into()?, pre_swap.swap_request)
|
||||
.await?;
|
||||
|
||||
// Proof to keep
|
||||
let p = construct_proofs(
|
||||
swap_response.signatures,
|
||||
pre_swap.pre_mint_secrets.rs(),
|
||||
pre_swap.pre_mint_secrets.secrets(),
|
||||
&keys.unwrap(),
|
||||
)?;
|
||||
|
||||
self.localstore
|
||||
.remove_proofs(mint_url.clone(), &proofs)
|
||||
.await?;
|
||||
|
||||
self.localstore.add_proofs(mint_url.clone(), p).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
let pre_swap = self
|
||||
.create_swap(mint_url, &unit, Some(amount), signed_proofs)
|
||||
.await?;
|
||||
|
||||
let swap_response = self
|
||||
.client
|
||||
.post_swap(mint_url.clone().try_into()?, pre_swap.swap_request)
|
||||
.await?;
|
||||
|
||||
// Proof to keep
|
||||
let p = construct_proofs(
|
||||
swap_response.signatures,
|
||||
pre_swap.pre_mint_secrets.rs(),
|
||||
pre_swap.pre_mint_secrets.secrets(),
|
||||
&keys.unwrap(),
|
||||
)?;
|
||||
|
||||
self.localstore
|
||||
.remove_proofs(mint_url.clone(), &proofs)
|
||||
.await?;
|
||||
|
||||
self.localstore.add_proofs(mint_url.clone(), p).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
*/
|
||||
|
||||
pub fn proofs_to_token(
|
||||
&self,
|
||||
|
||||
@@ -64,7 +64,15 @@ pub struct ErrorResponse {
|
||||
|
||||
impl ErrorResponse {
|
||||
pub fn from_json(json: &str) -> Result<Self, serde_json::Error> {
|
||||
serde_json::from_str(json)
|
||||
if let Ok(res) = serde_json::from_str::<ErrorResponse>(json) {
|
||||
Ok(res)
|
||||
} else {
|
||||
Ok(Self {
|
||||
code: 999,
|
||||
error: Some(json.to_string()),
|
||||
detail: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
// https://github.com/cashubtc/nuts/blob/main/00.md
|
||||
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::hash::{self, Hasher};
|
||||
use std::str::FromStr;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{Id, Proofs, PublicKey};
|
||||
use super::{Id, Proofs, PublicKey, Signatures, SigningKey};
|
||||
use crate::error::Error;
|
||||
use crate::nuts::nut11::{witness_deserialize, witness_serialize};
|
||||
use crate::secret::Secret;
|
||||
use crate::url::UncheckedUrl;
|
||||
use crate::Amount;
|
||||
@@ -24,9 +25,39 @@ pub struct BlindedMessage {
|
||||
/// encrypted secret message (B_)
|
||||
#[serde(rename = "B_")]
|
||||
pub b: PublicKey,
|
||||
/// Witness
|
||||
#[serde(default)]
|
||||
#[serde(skip_serializing_if = "Signatures::is_empty")]
|
||||
#[serde(serialize_with = "witness_serialize")]
|
||||
#[serde(deserialize_with = "witness_deserialize")]
|
||||
pub witness: Signatures,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, Hash)]
|
||||
impl BlindedMessage {
|
||||
pub fn new(amount: Amount, keyset_id: Id, b: PublicKey) -> Self {
|
||||
Self {
|
||||
amount,
|
||||
keyset_id,
|
||||
b,
|
||||
witness: Signatures::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sign_p2pk_blinded_message(&mut self, secret_key: SigningKey) -> Result<(), Error> {
|
||||
let msg_to_sign = hex::decode(self.b.to_string())?;
|
||||
|
||||
println!("{:?}", msg_to_sign);
|
||||
|
||||
let signature = secret_key.sign(&msg_to_sign);
|
||||
|
||||
self.witness
|
||||
.signatures
|
||||
.push(hex::encode(signature.to_bytes()));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, hash::Hash)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum CurrencyUnit {
|
||||
#[default]
|
||||
@@ -145,11 +176,7 @@ pub mod wallet {
|
||||
let secret = Secret::new();
|
||||
let (blinded, r) = blind_message(&secret.to_bytes()?, None)?;
|
||||
|
||||
let blinded_message = BlindedMessage {
|
||||
amount,
|
||||
b: blinded,
|
||||
keyset_id,
|
||||
};
|
||||
let blinded_message = BlindedMessage::new(amount, keyset_id, blinded);
|
||||
|
||||
output.push(PreMint {
|
||||
secret,
|
||||
@@ -172,11 +199,7 @@ pub mod wallet {
|
||||
for (secret, amount) in secrets.into_iter().zip(amounts) {
|
||||
let (blinded, r) = blind_message(&secret.to_bytes()?, None)?;
|
||||
|
||||
let blinded_message = BlindedMessage {
|
||||
amount,
|
||||
b: blinded,
|
||||
keyset_id,
|
||||
};
|
||||
let blinded_message = BlindedMessage::new(amount, keyset_id, blinded);
|
||||
|
||||
output.push(PreMint {
|
||||
secret,
|
||||
@@ -199,11 +222,7 @@ pub mod wallet {
|
||||
let secret = Secret::new();
|
||||
let (blinded, r) = blind_message(&secret.to_bytes()?, None)?;
|
||||
|
||||
let blinded_message = BlindedMessage {
|
||||
amount: Amount::ZERO,
|
||||
b: blinded,
|
||||
keyset_id,
|
||||
};
|
||||
let blinded_message = BlindedMessage::new(Amount::ZERO, keyset_id, blinded);
|
||||
|
||||
output.push(PreMint {
|
||||
secret,
|
||||
@@ -236,11 +255,7 @@ pub mod wallet {
|
||||
let (blinded, r) =
|
||||
blind_message(&secret.to_bytes()?, Some(blinding_factor.into()))?;
|
||||
|
||||
let blinded_message = BlindedMessage {
|
||||
keyset_id,
|
||||
amount,
|
||||
b: blinded,
|
||||
};
|
||||
let blinded_message = BlindedMessage::new(amount, keyset_id, blinded);
|
||||
|
||||
let pre_mint = PreMint {
|
||||
blinded_message,
|
||||
@@ -270,11 +285,7 @@ pub mod wallet {
|
||||
let secret: Secret = conditions.clone().try_into().unwrap();
|
||||
let (blinded, r) = blind_message(&secret.to_bytes()?, None)?;
|
||||
|
||||
let blinded_message = BlindedMessage {
|
||||
amount,
|
||||
b: blinded,
|
||||
keyset_id,
|
||||
};
|
||||
let blinded_message = BlindedMessage::new(amount, keyset_id, blinded);
|
||||
|
||||
output.push(PreMint {
|
||||
secret,
|
||||
@@ -480,7 +491,7 @@ impl Proof {
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Proof {
|
||||
impl hash::Hash for Proof {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.secret.hash(state);
|
||||
}
|
||||
|
||||
@@ -64,6 +64,12 @@ impl From<VerifyingKey> for PublicKey {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<super::VerifyingKey> for PublicKey {
|
||||
fn from(value: super::VerifyingKey) -> PublicKey {
|
||||
let v: VerifyingKey = value.into();
|
||||
PublicKey(v.into())
|
||||
}
|
||||
}
|
||||
impl PublicKey {
|
||||
pub fn to_bytes(&self) -> Box<[u8]> {
|
||||
self.0.to_sec1_bytes()
|
||||
|
||||
@@ -6,12 +6,11 @@ use std::fmt;
|
||||
use std::hash::{self, Hasher};
|
||||
use std::str::FromStr;
|
||||
|
||||
use bitcoin::hashes::{sha256, Hash};
|
||||
use k256::schnorr::signature::{Signer, Verifier};
|
||||
use k256::schnorr::Signature;
|
||||
use serde::de::Error as DeserializerError;
|
||||
use serde::ser::SerializeSeq;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use serde::{de, ser, Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
use super::nut01::PublicKey;
|
||||
use super::nut02::Id;
|
||||
@@ -25,7 +24,7 @@ use crate::Amount;
|
||||
pub struct Signatures {
|
||||
#[serde(default)]
|
||||
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||
signatures: Vec<String>,
|
||||
pub signatures: Vec<String>,
|
||||
}
|
||||
|
||||
impl Signatures {
|
||||
@@ -50,9 +49,26 @@ pub struct Proof {
|
||||
/// Witness
|
||||
#[serde(default)]
|
||||
#[serde(skip_serializing_if = "Signatures::is_empty")]
|
||||
#[serde(serialize_with = "witness_serialize")]
|
||||
#[serde(deserialize_with = "witness_deserialize")]
|
||||
pub witness: Signatures,
|
||||
}
|
||||
|
||||
pub fn witness_serialize<S>(x: &Signatures, s: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
s.serialize_str(&serde_json::to_string(x).map_err(ser::Error::custom)?)
|
||||
}
|
||||
|
||||
pub fn witness_deserialize<'de, D>(deserializer: D) -> Result<Signatures, D::Error>
|
||||
where
|
||||
D: de::Deserializer<'de>,
|
||||
{
|
||||
let s: String = String::deserialize(deserializer)?;
|
||||
serde_json::from_str(&s).map_err(de::Error::custom)
|
||||
}
|
||||
|
||||
impl Proof {
|
||||
pub fn new(amount: Amount, keyset_id: Id, secret: crate::secret::Secret, c: PublicKey) -> Self {
|
||||
Proof {
|
||||
@@ -136,7 +152,9 @@ impl TryFrom<P2PKConditions> for Secret {
|
||||
return Err(Error::Amount);
|
||||
}
|
||||
|
||||
let data = pubkeys[0].to_string();
|
||||
let data: PublicKey = pubkeys[0].clone().into();
|
||||
|
||||
let data = data.to_string();
|
||||
|
||||
let mut tags = vec![];
|
||||
|
||||
@@ -259,7 +277,13 @@ impl Proof {
|
||||
|
||||
let mut valid_sigs = 0;
|
||||
|
||||
let msg = sha256::Hash::hash(&self.secret.to_bytes().unwrap());
|
||||
println!("{:?}", self.secret.to_string());
|
||||
println!(
|
||||
"sec bytes: {:?}",
|
||||
self.secret.to_string().into_bytes().len()
|
||||
);
|
||||
|
||||
let msg = &self.secret.to_bytes().unwrap();
|
||||
|
||||
for signature in &self.witness.signatures {
|
||||
let mut pubkeys = spending_conditions.pubkeys.clone();
|
||||
@@ -268,31 +292,30 @@ impl Proof {
|
||||
for v in &spending_conditions.pubkeys {
|
||||
let sig = Signature::try_from(hex::decode(signature).unwrap().as_slice()).unwrap();
|
||||
|
||||
if v.verify(&msg.to_byte_array(), &sig).is_ok() {
|
||||
if v.verify(msg, &sig).is_ok() {
|
||||
valid_sigs += 1;
|
||||
} else {
|
||||
println!("{:?}", v.verify(&msg.to_byte_array(), &sig).unwrap());
|
||||
println!("{:?}", v.verify(msg, &sig).unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if valid_sigs.ge(&spending_conditions.num_sigs.unwrap_or(1)) {
|
||||
println!("valid sigs: {}", valid_sigs);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Some(locktime) = spending_conditions.locktime {
|
||||
// If lock time has passed check if refund witness signature is valid
|
||||
if locktime.lt(&unix_time()) {
|
||||
if !spending_conditions.refund_keys.is_empty() {
|
||||
for s in &self.witness.signatures {
|
||||
for v in &spending_conditions.refund_keys {
|
||||
let sig = Signature::try_from(s.as_bytes())
|
||||
.map_err(|_| Error::InvalidSignature)?;
|
||||
if locktime.lt(&unix_time()) && !spending_conditions.refund_keys.is_empty() {
|
||||
for s in &self.witness.signatures {
|
||||
for v in &spending_conditions.refund_keys {
|
||||
let sig = Signature::try_from(s.as_bytes())
|
||||
.map_err(|_| Error::InvalidSignature)?;
|
||||
|
||||
// As long as there is one valid refund signature it can be spent
|
||||
if v.verify(&msg.to_byte_array(), &sig).is_ok() {
|
||||
return Ok(());
|
||||
}
|
||||
// As long as there is one valid refund signature it can be spent
|
||||
if v.verify(msg, &sig).is_ok() {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -303,13 +326,14 @@ impl Proof {
|
||||
}
|
||||
|
||||
pub fn sign_p2pk_proof(&mut self, secret_key: SigningKey) -> Result<(), Error> {
|
||||
let msg_to_sign = sha256::Hash::hash(&self.secret.to_bytes().unwrap());
|
||||
let msg_to_sign = &self.secret.to_bytes().unwrap();
|
||||
|
||||
let signature = secret_key.sign(msg_to_sign.as_byte_array());
|
||||
let signature = secret_key.sign(msg_to_sign);
|
||||
|
||||
self.witness
|
||||
.signatures
|
||||
.push(hex::encode(signature.to_bytes()));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -476,6 +500,7 @@ impl From<Tag> for Vec<String> {
|
||||
let mut tag = vec![TagKind::Pubkeys.to_string()];
|
||||
|
||||
for pubkey in pubkeys {
|
||||
let pubkey: PublicKey = pubkey.into();
|
||||
tag.push(pubkey.to_string())
|
||||
}
|
||||
tag
|
||||
@@ -529,7 +554,10 @@ impl VerifyingKey {
|
||||
}
|
||||
|
||||
pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), Error> {
|
||||
Ok(self.0.verify(msg, signature).unwrap())
|
||||
self.0
|
||||
.verify(msg, signature)
|
||||
.map_err(|_| Error::InvalidSignature)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -622,7 +650,7 @@ impl From<SecretKey> for SigningKey {
|
||||
|
||||
impl SigningKey {
|
||||
pub fn public_key(&self) -> VerifyingKey {
|
||||
self.0.verifying_key().clone().into()
|
||||
(*self.0.verifying_key()).into()
|
||||
}
|
||||
|
||||
pub fn sign(&self, msg: &[u8]) -> Signature {
|
||||
@@ -630,7 +658,7 @@ impl SigningKey {
|
||||
}
|
||||
|
||||
pub fn verifying_key(&self) -> VerifyingKey {
|
||||
VerifyingKey(self.0.verifying_key().clone())
|
||||
VerifyingKey(*self.0.verifying_key())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -701,15 +729,6 @@ mod tests {
|
||||
assert_eq!(secret_der, secret);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verify() {
|
||||
let proof_str = r#"{"amount":0,"secret":"[\"P2PK\",{\"nonce\":\"190badde56afcbf67937e228744ea896bb3e48bcb60efa412799e1518618c287\",\"data\":\"0249098aa8b9d2fbec49ff8598feb17b592b986e62319a4fa488a3dc36387157a7\",\"tags\":[[\"sigflag\",\"SIG_INPUTS\"]]}]","C":"02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904","id": "009a1f293253e41e","witness":{"signatures":["2b117c29a0e405fcbcac4c632b5862eb3ace0d67c681e8209d3aa2f52d5198471629b1ec6bce75d3879c47725be89d28938e31236307b40bc6c89491fa540e35"]}}"#;
|
||||
|
||||
let proof: Proof = serde_json::from_str(proof_str).unwrap();
|
||||
|
||||
assert!(proof.verify_p2pk().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sign_proof() {
|
||||
let secret_key = SigningKey::from_str(
|
||||
@@ -721,7 +740,7 @@ mod tests {
|
||||
|
||||
let conditions = P2PKConditions {
|
||||
locktime: None,
|
||||
pubkeys: vec![v_key.into()],
|
||||
pubkeys: vec![v_key],
|
||||
refund_keys: vec![],
|
||||
num_sigs: None,
|
||||
sig_flag: SigFlag::SigInputs,
|
||||
@@ -732,7 +751,7 @@ mod tests {
|
||||
let mut proof = Proof {
|
||||
keyset_id: Id::from_str("009a1f293253e41e").unwrap(),
|
||||
amount: Amount::ZERO,
|
||||
secret: secret.try_into().unwrap(),
|
||||
secret: secret.clone().try_into().unwrap(),
|
||||
c: PublicKey::from_str(
|
||||
"02698c4e2b5f9534cd0687d87513c759790cf829aa5739184a3e3735471fbda904",
|
||||
)
|
||||
@@ -740,9 +759,7 @@ mod tests {
|
||||
witness: Signatures { signatures: vec![] },
|
||||
};
|
||||
|
||||
let signing_key: SigningKey = secret_key.try_into().unwrap();
|
||||
|
||||
proof.sign_p2pk_proof(signing_key).unwrap();
|
||||
proof.sign_p2pk_proof(secret_key).unwrap();
|
||||
|
||||
assert!(proof.verify_p2pk().is_ok());
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ impl Secret {
|
||||
serde_json::from_str(&self.0);
|
||||
|
||||
match secret {
|
||||
Ok(_) => Ok(self.0.clone().into_bytes()),
|
||||
Ok(_) => Ok(self.0.clone().replace('\\', "").into_bytes()),
|
||||
Err(_) => Ok(hex::decode(&self.0)?),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user