You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add util fn for creating a Transaction from spendable outputs
This adds a utility method, `KeysManager::spend_spendable_outputs`,
which constructs a Transaction from a given set of
`SpendableOutputDescriptor`s, deriving relevant keys as needed.
It also adds methods which can sign individual inputs where
channel-specific key derivation is required to
`InMemoryChannelKeys`, making it easy to sign transaction inputs
when a custom `KeysInterface` is used with `InMemoryChannelKeys`.
Copy file name to clipboardExpand all lines: lightning/src/chain/keysinterface.rs
+178-3Lines changed: 178 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -11,7 +11,7 @@
11
11
//! spendable on-chain outputs which the user owns and is responsible for using just as any other
12
12
//! on-chain output which is theirs.
13
13
14
-
use bitcoin::blockdata::transaction::{Transaction,TxOut,SigHashType};
14
+
use bitcoin::blockdata::transaction::{Transaction,TxOut,TxIn,SigHashType};
15
15
use bitcoin::blockdata::script::{Script,Builder};
16
16
use bitcoin::blockdata::opcodes;
17
17
use bitcoin::network::constants::Network;
@@ -28,17 +28,18 @@ use bitcoin::secp256k1::key::{SecretKey, PublicKey};
28
28
use bitcoin::secp256k1::{Secp256k1,Signature,Signing};
29
29
use bitcoin::secp256k1;
30
30
31
-
use util::byte_utils;
31
+
use util::{byte_utils, transaction_utils};
32
32
use util::ser::{Writeable,Writer,Readable};
33
33
34
34
use chain::transaction::OutPoint;
35
35
use ln::chan_utils;
36
36
use ln::chan_utils::{HTLCOutputInCommitment, make_funding_redeemscript,ChannelPublicKeys,HolderCommitmentTransaction,ChannelTransactionParameters,CommitmentTransaction};
37
37
use ln::msgs::UnsignedChannelAnnouncement;
38
38
39
+
use std::collections::HashSet;
39
40
use std::sync::atomic::{AtomicUsize,Ordering};
40
41
use std::io::Error;
41
-
use ln::msgs::DecodeError;
42
+
use ln::msgs::{DecodeError,MAX_VALUE_MSAT};
42
43
43
44
/// Information about a spendable output to a P2WSH script. See
44
45
/// SpendableOutputDescriptor::DynamicOutputP2WSH for more details on how to spend this.
// TODO: We really should be taking the SigHashCache as a parameter here instead of
510
+
// spend_tx, but ideally the SigHashCache would expose the transaction's inputs read-only
511
+
// so that we can check them. This requires upstream rust-bitcoin changes (as well as
512
+
// bindings updates to support SigHashCache objects).
513
+
if spend_tx.input.len() <= input_idx {returnErr(());}
514
+
if !spend_tx.input[input_idx].script_sig.is_empty(){returnErr(());}
515
+
if spend_tx.input[input_idx].previous_output != descriptor.outpoint.into_bitcoin_outpoint(){returnErr(());}
516
+
517
+
let remotepubkey = self.pubkeys().payment_point;
518
+
let witness_script = bitcoin::Address::p2pkh(&::bitcoin::PublicKey{compressed:true,key: remotepubkey},Network::Testnet).script_pubkey();
519
+
let sighash = hash_to_message!(&bip143::SigHashCache::new(spend_tx).signature_hash(input_idx,&witness_script, descriptor.output.value,SigHashType::All)[..]);
520
+
let remotesig = secp_ctx.sign(&sighash,&self.payment_key);
521
+
522
+
letmut witness = Vec::with_capacity(2);
523
+
witness.push(remotesig.serialize_der().to_vec());
524
+
witness[0].push(SigHashType::Allasu8);
525
+
witness.push(remotepubkey.serialize().to_vec());
526
+
Ok(witness)
527
+
}
528
+
529
+
/// Sign the single input of spend_tx at index `input_idx` which spends the output
530
+
/// described by descriptor, returning the witness stack for the input.
531
+
///
532
+
/// Returns an Err if the input at input_idx does not exist, has a non-empty script_sig,
533
+
/// is not spending the outpoint described by `descriptor.outpoint`, or does not have a
// TODO: We really should be taking the SigHashCache as a parameter here instead of
537
+
// spend_tx, but ideally the SigHashCache would expose the transaction's inputs read-only
538
+
// so that we can check them. This requires upstream rust-bitcoin changes (as well as
539
+
// bindings updates to support SigHashCache objects).
540
+
if spend_tx.input.len() <= input_idx {returnErr(());}
541
+
if !spend_tx.input[input_idx].script_sig.is_empty(){returnErr(());}
542
+
if spend_tx.input[input_idx].previous_output != descriptor.outpoint.into_bitcoin_outpoint(){returnErr(());}
543
+
if spend_tx.input[input_idx].sequence != descriptor.to_self_delayasu32{returnErr(());}
544
+
545
+
let delayed_payment_key = chan_utils::derive_private_key(&secp_ctx,&descriptor.per_commitment_point,&self.delayed_payment_base_key)
546
+
.expect("We constructed the payment_base_key, so we can only fail here if the RNG is busted.");
547
+
let delayed_payment_pubkey = PublicKey::from_secret_key(&secp_ctx,&delayed_payment_key);
548
+
let witness_script = chan_utils::get_revokeable_redeemscript(&descriptor.revocation_pubkey, descriptor.to_self_delay,&delayed_payment_pubkey);
549
+
let sighash = hash_to_message!(&bip143::SigHashCache::new(spend_tx).signature_hash(input_idx,&witness_script, descriptor.output.value,SigHashType::All)[..]);
550
+
let local_delayedsig = secp_ctx.sign(&sighash,&delayed_payment_key);
0 commit comments