@@ -14,7 +14,7 @@ use bitcoin::constants::ChainHash;
14
14
use bitcoin::script::{Builder, Script, ScriptBuf, WScriptHash};
15
15
use bitcoin::sighash::EcdsaSighashType;
16
16
use bitcoin::transaction::{Transaction, TxIn, TxOut};
17
- use bitcoin::{Weight, Witness};
17
+ use bitcoin::{TapSighashType, Weight, Witness};
18
18
19
19
use bitcoin::hash_types::{BlockHash, Txid};
20
20
use bitcoin::hashes::sha256::Hash as Sha256;
@@ -7586,11 +7586,54 @@ where
7586
7586
}
7587
7587
}
7588
7588
7589
- fn verify_interactive_tx_signatures(&mut self, _witnesses: &Vec<Witness>) {
7590
- if let Some(ref mut _signing_session) = self.interactive_tx_signing_session {
7591
- // Check that sighash_all was used:
7592
- // TODO(dual_funding): Check sig for sighash
7589
+ // A very basic check that anything resembling a signature in provided witnesses uses the
7590
+ // SIGHASH_ALL sighash type.
7591
+ //
7592
+ // May have false positives for elements that have the same length as Schnorr signatures.
7593
+ // If the length is 64 bytes, this doesn't matter as it's implicitly treated as SIGHASH_DEFAULT
7594
+ // (= SIGHASH_ALL). If it is instead 65 bytes and the last byte could be interpreted as a real
7595
+ // sighash type, then this function would return an error if it is not equal to SIGHASH_ALL.
7596
+ fn verify_interactive_tx_signatures(
7597
+ &mut self, witnesses: &Vec<Witness>,
7598
+ ) -> Result<(), APIError> {
7599
+ for witness in witnesses {
7600
+ for element in witness {
7601
+ match element.len() {
7602
+ // Possibly a DER-encoded ECDSA signature with a sighash type byte assuming low-S
7603
+ 70..=72 => {
7604
+ if bitcoin::ecdsa::Signature::from_slice(element)
7605
+ .map(|sig| matches!(sig.sighash_type, EcdsaSighashType::All))
7606
+ .unwrap_or(true)
7607
+ {
7608
+ continue;
7609
+ }
7610
+
7611
+ return Err(APIError::APIMisuseError {
7612
+ err: format!(
7613
+ "An ECDSA signature in a provided witness does not use SIGHASH_ALL"
7614
+ ),
7615
+ });
7616
+ },
7617
+ // Schnorr sig + sighash type byte.
7618
+ // If this were just 64 bytes, it would implicitly be SIGHASH_DEFAULT (= SIGHASH_ALL)
7619
+ 65 => {
7620
+ if bitcoin::taproot::Signature::from_slice(element)
7621
+ .map(|sig| matches!(sig.sighash_type, TapSighashType::All))
7622
+ .unwrap_or(true)
7623
+ {
7624
+ continue;
7625
+ }
7626
+
7627
+ return Err(APIError::APIMisuseError {
7628
+ err:
7629
+ format!("A Schnorr signature in a provided witness does not use SIGHASH_DEFAULT or SIGHASH_ALL")
7630
+ });
7631
+ },
7632
+ _ => continue,
7633
+ }
7634
+ }
7593
7635
}
7636
+ Ok(())
7594
7637
}
7595
7638
7596
7639
pub fn funding_transaction_signed<L: Deref>(
@@ -7599,7 +7642,7 @@ where
7599
7642
where
7600
7643
L::Target: Logger,
7601
7644
{
7602
- self.verify_interactive_tx_signatures(&witnesses);
7645
+ self.verify_interactive_tx_signatures(&witnesses)? ;
7603
7646
if let Some(ref mut signing_session) = self.interactive_tx_signing_session {
7604
7647
let logger = WithChannelContext::from(logger, &self.context, None);
7605
7648
if let Some(holder_tx_signatures) = signing_session
0 commit comments