mirror of
https://github.com/aljazceru/cdk.git
synced 2026-02-06 21:56:13 +01:00
feat: verify p2pk on blinded message
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user