@@ -21,6 +21,8 @@ use bitcoin::hashes::sha256::Hash as Sha256;
2121use bitcoin:: hashes:: ripemd160:: Hash as Ripemd160 ;
2222use bitcoin:: hash_types:: { Txid , PubkeyHash } ;
2323
24+ use crate :: chain:: chaininterface:: fee_for_weight;
25+ use crate :: chain:: package:: WEIGHT_REVOKED_OUTPUT ;
2426use crate :: sign:: EntropySource ;
2527use crate :: ln:: { PaymentHash , PaymentPreimage } ;
2628use crate :: ln:: msgs:: DecodeError ;
@@ -1308,6 +1310,7 @@ pub struct CommitmentTransaction {
13081310 commitment_number : u64 ,
13091311 to_broadcaster_value_sat : u64 ,
13101312 to_countersignatory_value_sat : u64 ,
1313+ to_broadcaster_delay : Option < u16 > , // Added in 0.0.117
13111314 feerate_per_kw : u32 ,
13121315 htlcs : Vec < HTLCOutputInCommitment > ,
13131316 // Note that on upgrades, some features of existing outputs may be missed.
@@ -1341,6 +1344,7 @@ impl Writeable for CommitmentTransaction {
13411344 let legacy_deserialization_prevention_marker = legacy_deserialization_prevention_marker_for_channel_type_features ( & self . channel_type_features ) ;
13421345 write_tlv_fields ! ( writer, {
13431346 ( 0 , self . commitment_number, required) ,
1347+ ( 1 , self . to_broadcaster_delay, option) ,
13441348 ( 2 , self . to_broadcaster_value_sat, required) ,
13451349 ( 4 , self . to_countersignatory_value_sat, required) ,
13461350 ( 6 , self . feerate_per_kw, required) ,
@@ -1358,6 +1362,7 @@ impl Readable for CommitmentTransaction {
13581362 fn read < R : io:: Read > ( reader : & mut R ) -> Result < Self , DecodeError > {
13591363 _init_and_read_tlv_fields ! ( reader, {
13601364 ( 0 , commitment_number, required) ,
1365+ ( 1 , to_broadcaster_delay, option) ,
13611366 ( 2 , to_broadcaster_value_sat, required) ,
13621367 ( 4 , to_countersignatory_value_sat, required) ,
13631368 ( 6 , feerate_per_kw, required) ,
@@ -1376,6 +1381,7 @@ impl Readable for CommitmentTransaction {
13761381 commitment_number : commitment_number. 0 . unwrap ( ) ,
13771382 to_broadcaster_value_sat : to_broadcaster_value_sat. 0 . unwrap ( ) ,
13781383 to_countersignatory_value_sat : to_countersignatory_value_sat. 0 . unwrap ( ) ,
1384+ to_broadcaster_delay,
13791385 feerate_per_kw : feerate_per_kw. 0 . unwrap ( ) ,
13801386 keys : keys. 0 . unwrap ( ) ,
13811387 built : built. 0 . unwrap ( ) ,
@@ -1407,6 +1413,7 @@ impl CommitmentTransaction {
14071413 commitment_number,
14081414 to_broadcaster_value_sat,
14091415 to_countersignatory_value_sat,
1416+ to_broadcaster_delay : Some ( channel_parameters. contest_delay ( ) ) ,
14101417 feerate_per_kw,
14111418 htlcs,
14121419 channel_type_features : channel_parameters. channel_type_features ( ) . clone ( ) ,
@@ -1724,6 +1731,69 @@ impl<'a> TrustedCommitmentTransaction<'a> {
17241731 ) ;
17251732 htlc_tx
17261733 }
1734+
1735+ /// Returns the index of the revokeable output, i.e. the `to_local` output sending funds to
1736+ /// the broadcaster, in the built transaction, if any exists.
1737+ ///
1738+ /// There are two cases where this may return `None`:
1739+ /// - The balance of the revokeable output is below the dust limit (only found on commitments
1740+ /// early in the channel's lifetime, i.e. before the channel reserve is met).
1741+ /// - This commitment was created before LDK 0.0.117. In this case, the
1742+ /// commitment transaction previously didn't contain enough information to locate the
1743+ /// revokeable output.
1744+ pub fn revokeable_output_index ( & self ) -> Option < usize > {
1745+ let revokeable_redeemscript = get_revokeable_redeemscript (
1746+ & self . keys . revocation_key ,
1747+ self . to_broadcaster_delay ?,
1748+ & self . keys . broadcaster_delayed_payment_key ,
1749+ ) ;
1750+ let revokeable_p2wsh = revokeable_redeemscript. to_v0_p2wsh ( ) ;
1751+ let outputs = & self . inner . built . transaction . output ;
1752+ outputs. iter ( ) . enumerate ( )
1753+ . find ( |( _, out) | out. script_pubkey == revokeable_p2wsh)
1754+ . map ( |( idx, _) | idx)
1755+ }
1756+
1757+ /// Helper method to build an unsigned justice transaction spending the revokeable
1758+ /// `to_local` output to a destination script. Fee estimation accounts for the expected
1759+ /// revocation witness data that will be added when signed.
1760+ ///
1761+ /// This method will error if the given fee rate results in a fee greater than the value
1762+ /// of the output being spent, or if there exists no revokeable `to_local` output on this
1763+ /// commitment transaction. See [`Self::revokeable_output_index`] for more details.
1764+ ///
1765+ /// The built transaction will allow fee bumping with RBF, and this method takes
1766+ /// `feerate_per_kw` as an input such that multiple copies of a justice transaction at different
1767+ /// fee rates may be built.
1768+ pub fn build_to_local_justice_tx ( & self , feerate_per_kw : u64 , destination_script : Script )
1769+ -> Result < Transaction , ( ) > {
1770+ let output_idx = self . revokeable_output_index ( ) . ok_or ( ( ) ) ?;
1771+ let input = vec ! [ TxIn {
1772+ previous_output: OutPoint {
1773+ txid: self . trust( ) . txid( ) ,
1774+ vout: output_idx as u32 ,
1775+ } ,
1776+ script_sig: Script :: new( ) ,
1777+ sequence: Sequence :: ENABLE_RBF_NO_LOCKTIME ,
1778+ witness: Witness :: new( ) ,
1779+ } ] ;
1780+ let value = self . inner . built . transaction . output [ output_idx] . value ;
1781+ let output = vec ! [ TxOut {
1782+ script_pubkey: destination_script,
1783+ value,
1784+ } ] ;
1785+ let mut justice_tx = Transaction {
1786+ version : 2 ,
1787+ lock_time : PackedLockTime :: ZERO ,
1788+ input,
1789+ output,
1790+ } ;
1791+ let weight = justice_tx. weight ( ) as u64 + WEIGHT_REVOKED_OUTPUT ;
1792+ let fee = fee_for_weight ( feerate_per_kw as u32 , weight) ;
1793+ justice_tx. output [ 0 ] . value = value. checked_sub ( fee) . ok_or ( ( ) ) ?;
1794+ Ok ( justice_tx)
1795+ }
1796+
17271797}
17281798
17291799/// Commitment transaction numbers which appear in the transactions themselves are XOR'd with a
@@ -1758,89 +1828,101 @@ pub fn get_commitment_transaction_number_obscure_factor(
17581828
17591829#[ cfg( test) ]
17601830mod tests {
1761- use super :: CounterpartyCommitmentSecrets ;
1831+ use super :: { CounterpartyCommitmentSecrets , ChannelPublicKeys } ;
17621832 use crate :: { hex, chain} ;
17631833 use crate :: prelude:: * ;
17641834 use crate :: ln:: chan_utils:: { get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, CommitmentTransaction , TxCreationKeys , ChannelTransactionParameters , CounterpartyChannelTransactionParameters , HTLCOutputInCommitment } ;
17651835 use bitcoin:: secp256k1:: { PublicKey , SecretKey , Secp256k1 } ;
17661836 use crate :: util:: test_utils;
17671837 use crate :: sign:: { ChannelSigner , SignerProvider } ;
1768- use bitcoin:: { Network , Txid } ;
1838+ use bitcoin:: { Network , Txid , Script } ;
17691839 use bitcoin:: hashes:: Hash ;
17701840 use crate :: ln:: PaymentHash ;
17711841 use bitcoin:: hashes:: hex:: ToHex ;
17721842 use bitcoin:: util:: address:: Payload ;
17731843 use bitcoin:: PublicKey as BitcoinPublicKey ;
17741844 use crate :: ln:: features:: ChannelTypeFeatures ;
17751845
1776- #[ test]
1777- fn test_anchors ( ) {
1778- let secp_ctx = Secp256k1 :: new ( ) ;
1846+ struct TestCommitmentTxBuilder {
1847+ commitment_number : u64 ,
1848+ holder_funding_pubkey : PublicKey ,
1849+ counterparty_funding_pubkey : PublicKey ,
1850+ keys : TxCreationKeys ,
1851+ feerate_per_kw : u32 ,
1852+ htlcs_with_aux : Vec < ( HTLCOutputInCommitment , ( ) ) > ,
1853+ channel_parameters : ChannelTransactionParameters ,
1854+ counterparty_pubkeys : ChannelPublicKeys ,
1855+ }
1856+
1857+ impl TestCommitmentTxBuilder {
1858+ fn new ( ) -> Self {
1859+ let secp_ctx = Secp256k1 :: new ( ) ;
1860+ let seed = [ 42 ; 32 ] ;
1861+ let network = Network :: Testnet ;
1862+ let keys_provider = test_utils:: TestKeysInterface :: new ( & seed, network) ;
1863+ let signer = keys_provider. derive_channel_signer ( 3000 , keys_provider. generate_channel_keys_id ( false , 1_000_000 , 0 ) ) ;
1864+ let counterparty_signer = keys_provider. derive_channel_signer ( 3000 , keys_provider. generate_channel_keys_id ( true , 1_000_000 , 1 ) ) ;
1865+ let delayed_payment_base = & signer. pubkeys ( ) . delayed_payment_basepoint ;
1866+ let per_commitment_secret = SecretKey :: from_slice ( & hex:: decode ( "1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100" ) . unwrap ( ) [ ..] ) . unwrap ( ) ;
1867+ let per_commitment_point = PublicKey :: from_secret_key ( & secp_ctx, & per_commitment_secret) ;
1868+ let htlc_basepoint = & signer. pubkeys ( ) . htlc_basepoint ;
1869+ let holder_pubkeys = signer. pubkeys ( ) ;
1870+ let counterparty_pubkeys = counterparty_signer. pubkeys ( ) . clone ( ) ;
1871+ let keys = TxCreationKeys :: derive_new ( & secp_ctx, & per_commitment_point, delayed_payment_base, htlc_basepoint, & counterparty_pubkeys. revocation_basepoint , & counterparty_pubkeys. htlc_basepoint ) ;
1872+ let channel_parameters = ChannelTransactionParameters {
1873+ holder_pubkeys : holder_pubkeys. clone ( ) ,
1874+ holder_selected_contest_delay : 0 ,
1875+ is_outbound_from_holder : false ,
1876+ counterparty_parameters : Some ( CounterpartyChannelTransactionParameters { pubkeys : counterparty_pubkeys. clone ( ) , selected_contest_delay : 0 } ) ,
1877+ funding_outpoint : Some ( chain:: transaction:: OutPoint { txid : Txid :: all_zeros ( ) , index : 0 } ) ,
1878+ channel_type_features : ChannelTypeFeatures :: only_static_remote_key ( ) ,
1879+ } ;
1880+ let htlcs_with_aux = Vec :: new ( ) ;
1881+
1882+ Self {
1883+ commitment_number : 0 ,
1884+ holder_funding_pubkey : holder_pubkeys. funding_pubkey ,
1885+ counterparty_funding_pubkey : counterparty_pubkeys. funding_pubkey ,
1886+ keys,
1887+ feerate_per_kw : 1 ,
1888+ htlcs_with_aux,
1889+ channel_parameters,
1890+ counterparty_pubkeys,
1891+ }
1892+ }
17791893
1780- let seed = [ 42 ; 32 ] ;
1781- let network = Network :: Testnet ;
1782- let keys_provider = test_utils:: TestKeysInterface :: new ( & seed, network) ;
1783- let signer = keys_provider. derive_channel_signer ( 3000 , keys_provider. generate_channel_keys_id ( false , 1_000_000 , 0 ) ) ;
1784- let counterparty_signer = keys_provider. derive_channel_signer ( 3000 , keys_provider. generate_channel_keys_id ( true , 1_000_000 , 1 ) ) ;
1785- let delayed_payment_base = & signer. pubkeys ( ) . delayed_payment_basepoint ;
1786- let per_commitment_secret = SecretKey :: from_slice ( & hex:: decode ( "1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100" ) . unwrap ( ) [ ..] ) . unwrap ( ) ;
1787- let per_commitment_point = PublicKey :: from_secret_key ( & secp_ctx, & per_commitment_secret) ;
1788- let htlc_basepoint = & signer. pubkeys ( ) . htlc_basepoint ;
1789- let holder_pubkeys = signer. pubkeys ( ) ;
1790- let counterparty_pubkeys = counterparty_signer. pubkeys ( ) ;
1791- let keys = TxCreationKeys :: derive_new ( & secp_ctx, & per_commitment_point, delayed_payment_base, htlc_basepoint, & counterparty_pubkeys. revocation_basepoint , & counterparty_pubkeys. htlc_basepoint ) ;
1792- let mut channel_parameters = ChannelTransactionParameters {
1793- holder_pubkeys : holder_pubkeys. clone ( ) ,
1794- holder_selected_contest_delay : 0 ,
1795- is_outbound_from_holder : false ,
1796- counterparty_parameters : Some ( CounterpartyChannelTransactionParameters { pubkeys : counterparty_pubkeys. clone ( ) , selected_contest_delay : 0 } ) ,
1797- funding_outpoint : Some ( chain:: transaction:: OutPoint { txid : Txid :: all_zeros ( ) , index : 0 } ) ,
1798- channel_type_features : ChannelTypeFeatures :: only_static_remote_key ( ) ,
1799- } ;
1894+ fn build ( & mut self , to_broadcaster_sats : u64 , to_countersignatory_sats : u64 ) -> CommitmentTransaction {
1895+ CommitmentTransaction :: new_with_auxiliary_htlc_data (
1896+ self . commitment_number , to_broadcaster_sats, to_countersignatory_sats,
1897+ self . holder_funding_pubkey . clone ( ) ,
1898+ self . counterparty_funding_pubkey . clone ( ) ,
1899+ self . keys . clone ( ) , self . feerate_per_kw ,
1900+ & mut self . htlcs_with_aux , & self . channel_parameters . as_holder_broadcastable ( )
1901+ )
1902+ }
1903+ }
18001904
1801- let mut htlcs_with_aux: Vec < ( _ , ( ) ) > = Vec :: new ( ) ;
1905+ #[ test]
1906+ fn test_anchors ( ) {
1907+ let mut builder = TestCommitmentTxBuilder :: new ( ) ;
18021908
18031909 // Generate broadcaster and counterparty outputs
1804- let tx = CommitmentTransaction :: new_with_auxiliary_htlc_data (
1805- 0 , 1000 , 2000 ,
1806- holder_pubkeys. funding_pubkey ,
1807- counterparty_pubkeys. funding_pubkey ,
1808- keys. clone ( ) , 1 ,
1809- & mut htlcs_with_aux, & channel_parameters. as_holder_broadcastable ( )
1810- ) ;
1910+ let tx = builder. build ( 1000 , 2000 ) ;
18111911 assert_eq ! ( tx. built. transaction. output. len( ) , 2 ) ;
1812- assert_eq ! ( tx. built. transaction. output[ 1 ] . script_pubkey, Payload :: p2wpkh( & BitcoinPublicKey :: new( counterparty_pubkeys. payment_point) ) . unwrap( ) . script_pubkey( ) ) ;
1912+ assert_eq ! ( tx. built. transaction. output[ 1 ] . script_pubkey, Payload :: p2wpkh( & BitcoinPublicKey :: new( builder . counterparty_pubkeys. payment_point) ) . unwrap( ) . script_pubkey( ) ) ;
18131913
18141914 // Generate broadcaster and counterparty outputs as well as two anchors
1815- channel_parameters. channel_type_features = ChannelTypeFeatures :: anchors_zero_htlc_fee_and_dependencies ( ) ;
1816- let tx = CommitmentTransaction :: new_with_auxiliary_htlc_data (
1817- 0 , 1000 , 2000 ,
1818- holder_pubkeys. funding_pubkey ,
1819- counterparty_pubkeys. funding_pubkey ,
1820- keys. clone ( ) , 1 ,
1821- & mut htlcs_with_aux, & channel_parameters. as_holder_broadcastable ( )
1822- ) ;
1915+ builder. channel_parameters . channel_type_features = ChannelTypeFeatures :: anchors_zero_htlc_fee_and_dependencies ( ) ;
1916+ let tx = builder. build ( 1000 , 2000 ) ;
18231917 assert_eq ! ( tx. built. transaction. output. len( ) , 4 ) ;
1824- assert_eq ! ( tx. built. transaction. output[ 3 ] . script_pubkey, get_to_countersignatory_with_anchors_redeemscript( & counterparty_pubkeys. payment_point) . to_v0_p2wsh( ) ) ;
1918+ assert_eq ! ( tx. built. transaction. output[ 3 ] . script_pubkey, get_to_countersignatory_with_anchors_redeemscript( & builder . counterparty_pubkeys. payment_point) . to_v0_p2wsh( ) ) ;
18251919
18261920 // Generate broadcaster output and anchor
1827- let tx = CommitmentTransaction :: new_with_auxiliary_htlc_data (
1828- 0 , 3000 , 0 ,
1829- holder_pubkeys. funding_pubkey ,
1830- counterparty_pubkeys. funding_pubkey ,
1831- keys. clone ( ) , 1 ,
1832- & mut htlcs_with_aux, & channel_parameters. as_holder_broadcastable ( )
1833- ) ;
1921+ let tx = builder. build ( 3000 , 0 ) ;
18341922 assert_eq ! ( tx. built. transaction. output. len( ) , 2 ) ;
18351923
18361924 // Generate counterparty output and anchor
1837- let tx = CommitmentTransaction :: new_with_auxiliary_htlc_data (
1838- 0 , 0 , 3000 ,
1839- holder_pubkeys. funding_pubkey ,
1840- counterparty_pubkeys. funding_pubkey ,
1841- keys. clone ( ) , 1 ,
1842- & mut htlcs_with_aux, & channel_parameters. as_holder_broadcastable ( )
1843- ) ;
1925+ let tx = builder. build ( 0 , 3000 ) ;
18441926 assert_eq ! ( tx. built. transaction. output. len( ) , 2 ) ;
18451927
18461928 let received_htlc = HTLCOutputInCommitment {
@@ -1860,15 +1942,10 @@ mod tests {
18601942 } ;
18611943
18621944 // Generate broadcaster output and received and offered HTLC outputs, w/o anchors
1863- channel_parameters. channel_type_features = ChannelTypeFeatures :: only_static_remote_key ( ) ;
1864- let tx = CommitmentTransaction :: new_with_auxiliary_htlc_data (
1865- 0 , 3000 , 0 ,
1866- holder_pubkeys. funding_pubkey ,
1867- counterparty_pubkeys. funding_pubkey ,
1868- keys. clone ( ) , 1 ,
1869- & mut vec ! [ ( received_htlc. clone( ) , ( ) ) , ( offered_htlc. clone( ) , ( ) ) ] ,
1870- & channel_parameters. as_holder_broadcastable ( )
1871- ) ;
1945+ builder. channel_parameters . channel_type_features = ChannelTypeFeatures :: only_static_remote_key ( ) ;
1946+ builder. htlcs_with_aux = vec ! [ ( received_htlc. clone( ) , ( ) ) , ( offered_htlc. clone( ) , ( ) ) ] ;
1947+ let tx = builder. build ( 3000 , 0 ) ;
1948+ let keys = & builder. keys . clone ( ) ;
18721949 assert_eq ! ( tx. built. transaction. output. len( ) , 3 ) ;
18731950 assert_eq ! ( tx. built. transaction. output[ 0 ] . script_pubkey, get_htlc_redeemscript( & received_htlc, & ChannelTypeFeatures :: only_static_remote_key( ) , & keys) . to_v0_p2wsh( ) ) ;
18741951 assert_eq ! ( tx. built. transaction. output[ 1 ] . script_pubkey, get_htlc_redeemscript( & offered_htlc, & ChannelTypeFeatures :: only_static_remote_key( ) , & keys) . to_v0_p2wsh( ) ) ;
@@ -1878,15 +1955,9 @@ mod tests {
18781955 "0020215d61bba56b19e9eadb6107f5a85d7f99c40f65992443f69229c290165bc00d" ) ;
18791956
18801957 // Generate broadcaster output and received and offered HTLC outputs, with anchors
1881- channel_parameters. channel_type_features = ChannelTypeFeatures :: anchors_zero_htlc_fee_and_dependencies ( ) ;
1882- let tx = CommitmentTransaction :: new_with_auxiliary_htlc_data (
1883- 0 , 3000 , 0 ,
1884- holder_pubkeys. funding_pubkey ,
1885- counterparty_pubkeys. funding_pubkey ,
1886- keys. clone ( ) , 1 ,
1887- & mut vec ! [ ( received_htlc. clone( ) , ( ) ) , ( offered_htlc. clone( ) , ( ) ) ] ,
1888- & channel_parameters. as_holder_broadcastable ( )
1889- ) ;
1958+ builder. channel_parameters . channel_type_features = ChannelTypeFeatures :: anchors_zero_htlc_fee_and_dependencies ( ) ;
1959+ builder. htlcs_with_aux = vec ! [ ( received_htlc. clone( ) , ( ) ) , ( offered_htlc. clone( ) , ( ) ) ] ;
1960+ let tx = builder. build ( 3000 , 0 ) ;
18901961 assert_eq ! ( tx. built. transaction. output. len( ) , 5 ) ;
18911962 assert_eq ! ( tx. built. transaction. output[ 2 ] . script_pubkey, get_htlc_redeemscript( & received_htlc, & ChannelTypeFeatures :: anchors_zero_htlc_fee_and_dependencies( ) , & keys) . to_v0_p2wsh( ) ) ;
18921963 assert_eq ! ( tx. built. transaction. output[ 3 ] . script_pubkey, get_htlc_redeemscript( & offered_htlc, & ChannelTypeFeatures :: anchors_zero_htlc_fee_and_dependencies( ) , & keys) . to_v0_p2wsh( ) ) ;
@@ -1896,6 +1967,61 @@ mod tests {
18961967 "002087a3faeb1950a469c0e2db4a79b093a41b9526e5a6fc6ef5cb949bde3be379c7" ) ;
18971968 }
18981969
1970+ #[ test]
1971+ fn test_finding_revokeable_output_index ( ) {
1972+ let mut builder = TestCommitmentTxBuilder :: new ( ) ;
1973+
1974+ // Revokeable output present
1975+ let tx = builder. build ( 1000 , 2000 ) ;
1976+ assert_eq ! ( tx. built. transaction. output. len( ) , 2 ) ;
1977+ assert_eq ! ( tx. trust( ) . revokeable_output_index( ) , Some ( 0 ) ) ;
1978+
1979+ // Revokeable output present (but to_broadcaster_delay missing)
1980+ let tx = CommitmentTransaction { to_broadcaster_delay : None , ..tx } ;
1981+ assert_eq ! ( tx. built. transaction. output. len( ) , 2 ) ;
1982+ assert_eq ! ( tx. trust( ) . revokeable_output_index( ) , None ) ;
1983+
1984+ // Revokeable output not present (our balance is dust)
1985+ let tx = builder. build ( 0 , 2000 ) ;
1986+ assert_eq ! ( tx. built. transaction. output. len( ) , 1 ) ;
1987+ assert_eq ! ( tx. trust( ) . revokeable_output_index( ) , None ) ;
1988+ }
1989+
1990+ #[ test]
1991+ fn test_building_to_local_justice_tx ( ) {
1992+ let mut builder = TestCommitmentTxBuilder :: new ( ) ;
1993+
1994+ // Revokeable output not present (our balance is dust)
1995+ let tx = builder. build ( 0 , 2000 ) ;
1996+ assert_eq ! ( tx. built. transaction. output. len( ) , 1 ) ;
1997+ assert ! ( tx. trust( ) . build_to_local_justice_tx( 253 , Script :: new( ) ) . is_err( ) ) ;
1998+
1999+ // Revokeable output present
2000+ let tx = builder. build ( 1000 , 2000 ) ;
2001+ assert_eq ! ( tx. built. transaction. output. len( ) , 2 ) ;
2002+
2003+ // Too high feerate
2004+ assert ! ( tx. trust( ) . build_to_local_justice_tx( 100_000 , Script :: new( ) ) . is_err( ) ) ;
2005+
2006+ // Generate a random public key for destination script
2007+ let secret_key = SecretKey :: from_slice (
2008+ & hex:: decode ( "1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100" )
2009+ . unwrap ( ) [ ..] ) . unwrap ( ) ;
2010+ let pubkey_hash = BitcoinPublicKey :: new (
2011+ PublicKey :: from_secret_key ( & Secp256k1 :: new ( ) , & secret_key) ) . wpubkey_hash ( ) . unwrap ( ) ;
2012+ let destination_script = Script :: new_v0_p2wpkh ( & pubkey_hash) ;
2013+
2014+ let justice_tx = tx. trust ( ) . build_to_local_justice_tx ( 253 , destination_script. clone ( ) ) . unwrap ( ) ;
2015+ assert_eq ! ( justice_tx. input. len( ) , 1 ) ;
2016+ assert_eq ! ( justice_tx. input[ 0 ] . previous_output. txid, tx. built. transaction. txid( ) ) ;
2017+ assert_eq ! ( justice_tx. input[ 0 ] . previous_output. vout, tx. trust( ) . revokeable_output_index( ) . unwrap( ) as u32 ) ;
2018+ assert ! ( justice_tx. input[ 0 ] . sequence. is_rbf( ) ) ;
2019+
2020+ assert_eq ! ( justice_tx. output. len( ) , 1 ) ;
2021+ assert ! ( justice_tx. output[ 0 ] . value < 1000 ) ;
2022+ assert_eq ! ( justice_tx. output[ 0 ] . script_pubkey, destination_script) ;
2023+ }
2024+
18992025 #[ test]
19002026 fn test_per_commitment_storage ( ) {
19012027 // Test vectors from BOLT 3:
0 commit comments