|  | @@ -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());
 | 
	
		
			
				|  |  |      }
 |