Skip to content

Commit

Permalink
psbt: fix taproot key-only signing
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-orlovsky committed Jul 16, 2024
1 parent 5666fb9 commit fbdc3e8
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 15 deletions.
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 15 additions & 3 deletions derive/src/sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
// limitations under the License.

use bc::secp256k1::{ecdsa, schnorr as bip340};
use bc::{LegacyPk, Sighash, TapLeafHash, TapMerklePath, TapSighash, XOnlyPk};
use bc::{
InternalPk, LegacyPk, Sighash, TapLeafHash, TapMerklePath, TapNodeHash, TapSighash, XOnlyPk,
};

use crate::KeyOrigin;

Expand All @@ -36,9 +38,19 @@ pub trait Sign {
origin: Option<&KeyOrigin>,
) -> Option<ecdsa::Signature>;

/// Create signature with a given key for inputs using Schnorr signatures with BIP-340 signing
/// Create signature with a given internal key using Schnorr signatures with BIP-340 signing
/// scheme (taproot).
fn sign_bip340(
fn sign_bip340_key_only(
&self,
message: TapSighash,
pk: InternalPk,
origin: Option<&KeyOrigin>,
merkle_root: Option<TapNodeHash>,
) -> Option<bip340::Signature>;

/// Create signature with a given script path and x-only public key using Schnorr signatures
/// with BIP-340 signing scheme (taproot).
fn sign_bip340_script_path(
&self,
message: TapSighash,
pk: XOnlyPk,
Expand Down
16 changes: 10 additions & 6 deletions psbt/src/sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

use std::borrow::Borrow;

use derive::{Bip340Sig, LegacySig, SighashCache, SighashError, Sign, Tx, TxOut, Txid, XOnlyPk};
use derive::{Bip340Sig, LegacySig, SighashCache, SighashError, Sign, Tx, TxOut, Txid};

use crate::{Input, Psbt};

Expand Down Expand Up @@ -183,7 +183,8 @@ impl Input {
if !tap.leaf_hashes.contains(&tapleaf_hash) {
continue;
}
let Some(sig) = signer.sign_bip340(sighash, *pk, Some(&tap.origin)) else {
let Some(sig) = signer.sign_bip340_script_path(sighash, *pk, Some(&tap.origin))
else {
continue;
};
let sig = Bip340Sig { sig, sighash_type };
Expand All @@ -199,11 +200,14 @@ impl Input {
let Some(internal_key) = self.tap_internal_key else {
return Ok(signature_count);
};
let xonly_key = XOnlyPk::from(internal_key);
let derivation = self.tap_bip32_derivation.get(&xonly_key);
let derivation = self.tap_bip32_derivation.get(&internal_key.to_xonly_pk());
let sighash = sig_hasher.tap_sighash_key(self.index, sighash_type)?;
let Some(sig) = signer.sign_bip340(sighash, xonly_key, derivation.map(|d| &d.origin))
else {
let Some(sig) = signer.sign_bip340_key_only(
sighash,
internal_key,
derivation.map(|d| &d.origin),
self.tap_merkle_root,
) else {
return Ok(signature_count);
};
let sig = Bip340Sig { sig, sighash_type };
Expand Down
25 changes: 23 additions & 2 deletions src/signers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ use std::collections::HashMap;

use amplify::Wrapper;
use bc::secp256k1::{ecdsa, schnorr as bip340, SECP256K1};
use bc::{LegacyPk, Sighash, TapLeafHash, TapMerklePath, TapSighash, XOnlyPk};
use bc::{
InternalKeypair, InternalPk, LegacyPk, Sighash, TapLeafHash, TapMerklePath,
TapNodeHash, TapSighash, XOnlyPk,
};
use derive::{KeyOrigin, Sign, XkeyOrigin, Xpriv, XprivAccount};
use psbt::{Psbt, Rejected, Signer};

Expand Down Expand Up @@ -113,7 +116,25 @@ impl<'a> Sign for TestnetRefSigner<'a> {
Some(sk.sign_ecdsa(message.into()))
}

fn sign_bip340(
fn sign_bip340_key_only(
&self,
message: TapSighash,
pk: InternalPk,
origin: Option<&KeyOrigin>,
merkle_root: Option<TapNodeHash>,
) -> Option<bip340::Signature> {
let xpriv = self.get(origin)?;
let output_pair =
InternalKeypair::from(xpriv.to_keypair_bip340()).to_output_keypair(merkle_root).0;
if output_pair.x_only_public_key().0.serialize()
!= pk.to_output_pk(merkle_root).0.to_byte_array()
{
return None;
}
Some(output_pair.sign_schnorr(message.into()))
}

fn sign_bip340_script_path(
&self,
message: TapSighash,
pk: XOnlyPk,
Expand Down

0 comments on commit fbdc3e8

Please sign in to comment.