feat: verify p2pk on blinded message

This commit is contained in:
thesimplekid
2024-03-03 18:56:12 +00:00
parent ed1f034a9a
commit 1bc9ad3528
2 changed files with 104 additions and 79 deletions

View File

@@ -795,7 +795,7 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
for pubkey in pubkeys {
if let Some(signing) = pubkey_secret_key.get(&pubkey.to_string()) {
proof.sign_p2pk_proof(signing.clone()).unwrap();
proof.sign_p2pk(signing.clone()).unwrap();
proof.verify_p2pk().unwrap();
}
}
@@ -812,9 +812,7 @@ impl<C: Client, L: LocalStore> Wallet<C, L> {
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();
blinded_message.sign_p2pk(signing_key.clone()).unwrap();
}
}
}

View File

@@ -80,6 +80,76 @@ impl Proof {
witness: Signatures::default(),
}
}
pub fn verify_p2pk(&self) -> Result<(), Error> {
if !self.secret.is_p2pk() {
return Err(Error::IncorrectSecretKind);
}
let secret: Secret = self.secret.clone().try_into()?;
let spending_conditions: P2PKConditions = secret.clone().try_into()?;
let mut valid_sigs = 0;
let msg = &self.secret.to_bytes();
for signature in &self.witness.signatures {
let mut pubkeys = spending_conditions.pubkeys.clone();
let data_key = VerifyingKey::from_str(&secret.secret_data.data)?;
pubkeys.push(data_key);
for v in &spending_conditions.pubkeys {
let sig = Signature::try_from(hex::decode(signature)?.as_slice())?;
if v.verify(msg, &sig).is_ok() {
valid_sigs += 1;
} else {
debug!(
"Could not verify signature: {} on message: {}",
hex::encode(sig.to_bytes()),
self.secret.to_string()
)
}
}
}
if valid_sigs.ge(&spending_conditions.num_sigs.unwrap_or(1)) {
return Ok(());
}
println!("{:?}", spending_conditions.refund_keys);
if let Some(locktime) = spending_conditions.locktime {
// If lock time has passed check if refund witness signature is valid
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(hex::decode(s)?.as_slice())
.map_err(|_| Error::InvalidSignature)?;
// As long as there is one valid refund signature it can be spent
if v.verify(msg, &sig).is_ok() {
return Ok(());
}
}
}
}
}
Err(Error::SpendConditionsNotMet)
}
pub fn sign_p2pk(&mut self, secret_key: SigningKey) -> Result<(), Error> {
let msg_to_sign = &self.secret.to_bytes();
let signature = secret_key.sign(msg_to_sign);
self.witness
.signatures
.push(hex::encode(signature.to_bytes()));
Ok(())
}
}
impl hash::Hash for Proof {
@@ -129,8 +199,7 @@ impl BlindedMessage {
}
}
#[cfg(feature = "nut11")]
pub fn sign_p2pk_blinded_message(&mut self, secret_key: SigningKey) -> Result<(), Error> {
pub fn sign_p2pk(&mut self, secret_key: SigningKey) -> Result<(), Error> {
let msg_to_sign = hex::decode(self.b.to_string())?;
let signature = secret_key.sign(&msg_to_sign);
@@ -140,6 +209,36 @@ impl BlindedMessage {
.push(hex::encode(signature.to_bytes()));
Ok(())
}
pub fn verify_p2pk(
&self,
pubkeys: &Vec<VerifyingKey>,
required_sigs: u64,
) -> Result<(), Error> {
let mut valid_sigs = 0;
for signature in &self.witness.signatures {
for v in pubkeys {
let msg = &self.b.to_bytes();
let sig = Signature::try_from(hex::decode(signature)?.as_slice())?;
if v.verify(msg, &sig).is_ok() {
valid_sigs += 1;
} else {
debug!(
"Could not verify signature: {} on message: {}",
hex::encode(sig.to_bytes()),
self.b.to_string()
)
}
}
}
if valid_sigs.ge(&required_sigs) {
Ok(())
} else {
Err(Error::SpendConditionsNotMet)
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
@@ -307,78 +406,6 @@ impl TryFrom<Secret> for P2PKConditions {
}
}
impl Proof {
pub fn verify_p2pk(&self) -> Result<(), Error> {
if !self.secret.is_p2pk() {
return Err(Error::IncorrectSecretKind);
}
let secret: Secret = self.secret.clone().try_into()?;
let spending_conditions: P2PKConditions = secret.clone().try_into()?;
let mut valid_sigs = 0;
let msg = &self.secret.to_bytes();
for signature in &self.witness.signatures {
let mut pubkeys = spending_conditions.pubkeys.clone();
let data_key = VerifyingKey::from_str(&secret.secret_data.data)?;
pubkeys.push(data_key);
for v in &spending_conditions.pubkeys {
let sig = Signature::try_from(hex::decode(signature)?.as_slice())?;
if v.verify(msg, &sig).is_ok() {
valid_sigs += 1;
} else {
debug!(
"Could not verify signature: {} on message: {}",
hex::encode(sig.to_bytes()),
self.secret.to_string()
)
}
}
}
if valid_sigs.ge(&spending_conditions.num_sigs.unwrap_or(1)) {
return Ok(());
}
println!("{:?}", spending_conditions.refund_keys);
if let Some(locktime) = spending_conditions.locktime {
// If lock time has passed check if refund witness signature is valid
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(hex::decode(s)?.as_slice())
.map_err(|_| Error::InvalidSignature)?;
// As long as there is one valid refund signature it can be spent
if v.verify(msg, &sig).is_ok() {
return Ok(());
}
}
}
}
}
Err(Error::SpendConditionsNotMet)
}
pub fn sign_p2pk_proof(&mut self, secret_key: SigningKey) -> Result<(), Error> {
let msg_to_sign = &self.secret.to_bytes();
let signature = secret_key.sign(msg_to_sign);
self.witness
.signatures
.push(hex::encode(signature.to_bytes()));
Ok(())
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[serde(rename_all = "lowercase")]
pub enum TagKind {
@@ -802,7 +829,7 @@ mod tests {
witness: Signatures { signatures: vec![] },
};
proof.sign_p2pk_proof(secret_key).unwrap();
proof.sign_p2pk(secret_key).unwrap();
assert!(proof.verify_p2pk().is_ok());
}