@@ -23,7 +23,7 @@ use bitcoin::hash_types::{Txid, PubkeyHash};
2323use ln:: { PaymentHash , PaymentPreimage } ;
2424use ln:: msgs:: DecodeError ;
2525use util:: ser:: { Readable , Writeable , Writer } ;
26- use util:: byte_utils;
26+ use util:: { byte_utils, transaction_utils } ;
2727
2828use bitcoin:: hash_types:: WPubkeyHash ;
2929use bitcoin:: secp256k1:: key:: { SecretKey , PublicKey } ;
@@ -80,6 +80,50 @@ pub fn build_commitment_secret(commitment_seed: &[u8; 32], idx: u64) -> [u8; 32]
8080 res
8181}
8282
83+ /// Build a closing transaction
84+ pub fn build_closing_transaction ( to_holder_value_sat : u64 , to_counterparty_value_sat : u64 , to_holder_script : Script , to_counterparty_script : Script , funding_outpoint : OutPoint ) -> Transaction {
85+ let txins = {
86+ let mut ins: Vec < TxIn > = Vec :: new ( ) ;
87+ ins. push ( TxIn {
88+ previous_output : funding_outpoint,
89+ script_sig : Script :: new ( ) ,
90+ sequence : 0xffffffff ,
91+ witness : Vec :: new ( ) ,
92+ } ) ;
93+ ins
94+ } ;
95+
96+ let mut txouts: Vec < ( TxOut , ( ) ) > = Vec :: new ( ) ;
97+
98+ if to_counterparty_value_sat > 0 {
99+ txouts. push ( ( TxOut {
100+ script_pubkey : to_counterparty_script,
101+ value : to_counterparty_value_sat
102+ } , ( ) ) ) ;
103+ }
104+
105+ if to_holder_value_sat > 0 {
106+ txouts. push ( ( TxOut {
107+ script_pubkey : to_holder_script,
108+ value : to_holder_value_sat
109+ } , ( ) ) ) ;
110+ }
111+
112+ transaction_utils:: sort_outputs ( & mut txouts, |_, _| { cmp:: Ordering :: Equal } ) ; // Ordering doesnt matter if they used our pubkey...
113+
114+ let mut outputs: Vec < TxOut > = Vec :: new ( ) ;
115+ for out in txouts. drain ( ..) {
116+ outputs. push ( out. 0 ) ;
117+ }
118+
119+ Transaction {
120+ version : 2 ,
121+ lock_time : 0 ,
122+ input : txins,
123+ output : outputs,
124+ }
125+ }
126+
83127/// Implements the per-commitment secret storage scheme from
84128/// [BOLT 3](https://github.com/lightningnetwork/lightning-rfc/blob/dcbf8583976df087c79c3ce0b535311212e6812d/03-transactions.md#efficient-per-commitment-secret-storage).
85129///
@@ -846,7 +890,130 @@ impl BuiltCommitmentTransaction {
846890 }
847891}
848892
849- /// This class tracks the per-transaction information needed to build a commitment transaction and to
893+ /// This class tracks the per-transaction information needed to build a closing transaction and will
894+ /// actually build it and sign.
895+ ///
896+ /// This class can be used inside a signer implementation to generate a signature given the relevant
897+ /// secret key.
898+ pub struct ClosingTransaction {
899+ to_holder_value_sat : u64 ,
900+ to_counterparty_value_sat : u64 ,
901+ to_holder_script : Script ,
902+ to_counterparty_script : Script ,
903+ built : Transaction ,
904+ }
905+
906+ impl ClosingTransaction {
907+ /// Construct an object of the class
908+ pub fn new (
909+ to_holder_value_sat : u64 ,
910+ to_counterparty_value_sat : u64 ,
911+ to_holder_script : Script ,
912+ to_counterparty_script : Script ,
913+ funding_outpoint : OutPoint ,
914+ ) -> Self {
915+ let built = build_closing_transaction (
916+ to_holder_value_sat, to_counterparty_value_sat,
917+ to_holder_script. clone ( ) , to_counterparty_script. clone ( ) ,
918+ funding_outpoint
919+ ) ;
920+ ClosingTransaction {
921+ to_holder_value_sat,
922+ to_counterparty_value_sat,
923+ to_holder_script,
924+ to_counterparty_script,
925+ built
926+ }
927+ }
928+
929+ /// Trust our pre-built transaction.
930+ ///
931+ /// Applies a wrapper which allows access to the transaction.
932+ ///
933+ /// This should only be used if you fully trust the builder of this object. It should not
934+ /// be used by an external signer - instead use the verify function.
935+ pub fn trust ( & self ) -> TrustedClosingTransaction {
936+ TrustedClosingTransaction { inner : self }
937+ }
938+
939+ /// Verify our pre-built transaction.
940+ ///
941+ /// Applies a wrapper which allows access to the transaction.
942+ ///
943+ /// An external validating signer must call this method before signing
944+ /// or using the built transaction.
945+ pub fn verify ( & self , funding_outpoint : OutPoint ) -> Result < TrustedClosingTransaction , ( ) > {
946+ let built = build_closing_transaction (
947+ self . to_holder_value_sat , self . to_counterparty_value_sat ,
948+ self . to_holder_script . clone ( ) , self . to_counterparty_script . clone ( ) ,
949+ funding_outpoint
950+ ) ;
951+ if self . built != built {
952+ return Err ( ( ) )
953+ }
954+ Ok ( TrustedClosingTransaction { inner : self } )
955+ }
956+
957+ /// The value to be sent to the holder, or zero if the output will be omitted
958+ pub fn to_holder_value_sat ( & self ) -> u64 {
959+ self . to_holder_value_sat
960+ }
961+
962+ /// The value to be sent to the counterparty, or zero if the output will be omitted
963+ pub fn to_counterparty_value_sat ( & self ) -> u64 {
964+ self . to_counterparty_value_sat
965+ }
966+
967+ /// The destination of the holder's output
968+ pub fn to_holder_script ( & self ) -> & Script {
969+ & self . to_holder_script
970+ }
971+
972+ /// The destination of the counterparty's output
973+ pub fn to_counterparty_script ( & self ) -> & Script {
974+ & self . to_counterparty_script
975+ }
976+ }
977+
978+ /// A wrapper on ClosingTransaction indicating that the built bitcoin
979+ /// transaction is trusted.
980+ ///
981+ /// See trust() and verify() functions on CommitmentTransaction.
982+ ///
983+ /// This structure implements Deref.
984+ pub struct TrustedClosingTransaction < ' a > {
985+ inner : & ' a ClosingTransaction ,
986+ }
987+
988+ impl < ' a > Deref for TrustedClosingTransaction < ' a > {
989+ type Target = ClosingTransaction ;
990+
991+ fn deref ( & self ) -> & Self :: Target { self . inner }
992+ }
993+
994+ impl < ' a > TrustedClosingTransaction < ' a > {
995+ /// The pre-built Bitcoin commitment transaction
996+ pub fn built_transaction ( & self ) -> & Transaction {
997+ & self . inner . built
998+ }
999+
1000+ /// Get the SIGHASH_ALL sighash value of the transaction.
1001+ ///
1002+ /// This can be used to verify a signature.
1003+ pub fn get_sighash_all ( & self , funding_redeemscript : & Script , channel_value_satoshis : u64 ) -> Message {
1004+ let sighash = & bip143:: SigHashCache :: new ( & self . inner . built ) . signature_hash ( 0 , funding_redeemscript, channel_value_satoshis, SigHashType :: All ) [ ..] ;
1005+ hash_to_message ! ( sighash)
1006+ }
1007+
1008+ /// Sign a transaction, either because we are counter-signing the counterparty's transaction or
1009+ /// because we are about to broadcast a holder transaction.
1010+ pub fn sign < T : secp256k1:: Signing > ( & self , funding_key : & SecretKey , funding_redeemscript : & Script , channel_value_satoshis : u64 , secp_ctx : & Secp256k1 < T > ) -> Signature {
1011+ let sighash = self . get_sighash_all ( funding_redeemscript, channel_value_satoshis) ;
1012+ secp_ctx. sign ( & sighash, funding_key)
1013+ }
1014+ }
1015+
1016+ /// This class tracks the per-transaction information needed to build a commitment transaction and will
8501017/// actually build it and sign. It is used for holder transactions that we sign only when needed
8511018/// and for transactions we sign for the counterparty.
8521019///
@@ -1110,7 +1277,7 @@ impl CommitmentTransaction {
11101277 /// Applies a wrapper which allows access to these fields.
11111278 ///
11121279 /// This should only be used if you fully trust the builder of this object. It should not
1113- /// be used by an external signer - instead use the verify function.
1280+ /// be used by an external signer - instead use the verify function.
11141281 pub fn trust ( & self ) -> TrustedCommitmentTransaction {
11151282 TrustedCommitmentTransaction { inner : self }
11161283 }
0 commit comments