@@ -21,6 +21,8 @@ use bitcoin::hashes::sha256::Hash as Sha256;
21
21
use bitcoin:: hashes:: ripemd160:: Hash as Ripemd160 ;
22
22
use bitcoin:: hash_types:: { Txid , PubkeyHash } ;
23
23
24
+ use crate :: chain:: chaininterface:: fee_for_weight;
25
+ use crate :: chain:: package:: WEIGHT_REVOKED_OUTPUT ;
24
26
use crate :: sign:: EntropySource ;
25
27
use crate :: ln:: { PaymentHash , PaymentPreimage } ;
26
28
use crate :: ln:: msgs:: DecodeError ;
@@ -1308,6 +1310,7 @@ pub struct CommitmentTransaction {
1308
1310
commitment_number : u64 ,
1309
1311
to_broadcaster_value_sat : u64 ,
1310
1312
to_countersignatory_value_sat : u64 ,
1313
+ to_broadcaster_delay : Option < u16 > , // Added in 0.0.117
1311
1314
feerate_per_kw : u32 ,
1312
1315
htlcs : Vec < HTLCOutputInCommitment > ,
1313
1316
// Note that on upgrades, some features of existing outputs may be missed.
@@ -1341,6 +1344,7 @@ impl Writeable for CommitmentTransaction {
1341
1344
let legacy_deserialization_prevention_marker = legacy_deserialization_prevention_marker_for_channel_type_features ( & self . channel_type_features ) ;
1342
1345
write_tlv_fields ! ( writer, {
1343
1346
( 0 , self . commitment_number, required) ,
1347
+ ( 1 , self . to_broadcaster_delay, option) ,
1344
1348
( 2 , self . to_broadcaster_value_sat, required) ,
1345
1349
( 4 , self . to_countersignatory_value_sat, required) ,
1346
1350
( 6 , self . feerate_per_kw, required) ,
@@ -1358,6 +1362,7 @@ impl Readable for CommitmentTransaction {
1358
1362
fn read < R : io:: Read > ( reader : & mut R ) -> Result < Self , DecodeError > {
1359
1363
_init_and_read_tlv_fields ! ( reader, {
1360
1364
( 0 , commitment_number, required) ,
1365
+ ( 1 , to_broadcaster_delay, option) ,
1361
1366
( 2 , to_broadcaster_value_sat, required) ,
1362
1367
( 4 , to_countersignatory_value_sat, required) ,
1363
1368
( 6 , feerate_per_kw, required) ,
@@ -1376,6 +1381,7 @@ impl Readable for CommitmentTransaction {
1376
1381
commitment_number : commitment_number. 0 . unwrap ( ) ,
1377
1382
to_broadcaster_value_sat : to_broadcaster_value_sat. 0 . unwrap ( ) ,
1378
1383
to_countersignatory_value_sat : to_countersignatory_value_sat. 0 . unwrap ( ) ,
1384
+ to_broadcaster_delay,
1379
1385
feerate_per_kw : feerate_per_kw. 0 . unwrap ( ) ,
1380
1386
keys : keys. 0 . unwrap ( ) ,
1381
1387
built : built. 0 . unwrap ( ) ,
@@ -1407,6 +1413,7 @@ impl CommitmentTransaction {
1407
1413
commitment_number,
1408
1414
to_broadcaster_value_sat,
1409
1415
to_countersignatory_value_sat,
1416
+ to_broadcaster_delay : Some ( channel_parameters. contest_delay ( ) ) ,
1410
1417
feerate_per_kw,
1411
1418
htlcs,
1412
1419
channel_type_features : channel_parameters. channel_type_features ( ) . clone ( ) ,
@@ -1724,6 +1731,69 @@ impl<'a> TrustedCommitmentTransaction<'a> {
1724
1731
) ;
1725
1732
htlc_tx
1726
1733
}
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
+
1727
1797
}
1728
1798
1729
1799
/// 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(
1758
1828
1759
1829
#[ cfg( test) ]
1760
1830
mod tests {
1761
- use super :: CounterpartyCommitmentSecrets ;
1831
+ use super :: { CounterpartyCommitmentSecrets , ChannelPublicKeys } ;
1762
1832
use crate :: { hex, chain} ;
1763
1833
use crate :: prelude:: * ;
1764
1834
use crate :: ln:: chan_utils:: { get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, CommitmentTransaction , TxCreationKeys , ChannelTransactionParameters , CounterpartyChannelTransactionParameters , HTLCOutputInCommitment } ;
1765
1835
use bitcoin:: secp256k1:: { PublicKey , SecretKey , Secp256k1 } ;
1766
1836
use crate :: util:: test_utils;
1767
1837
use crate :: sign:: { ChannelSigner , SignerProvider } ;
1768
- use bitcoin:: { Network , Txid } ;
1838
+ use bitcoin:: { Network , Txid , Script } ;
1769
1839
use bitcoin:: hashes:: Hash ;
1770
1840
use crate :: ln:: PaymentHash ;
1771
1841
use bitcoin:: hashes:: hex:: ToHex ;
1772
1842
use bitcoin:: util:: address:: Payload ;
1773
1843
use bitcoin:: PublicKey as BitcoinPublicKey ;
1774
1844
use crate :: ln:: features:: ChannelTypeFeatures ;
1775
1845
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
+ }
1779
1893
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
+ }
1800
1904
1801
- let mut htlcs_with_aux: Vec < ( _ , ( ) ) > = Vec :: new ( ) ;
1905
+ #[ test]
1906
+ fn test_anchors ( ) {
1907
+ let mut builder = TestCommitmentTxBuilder :: new ( ) ;
1802
1908
1803
1909
// 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 ) ;
1811
1911
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( ) ) ;
1813
1913
1814
1914
// 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 ) ;
1823
1917
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( ) ) ;
1825
1919
1826
1920
// 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 ) ;
1834
1922
assert_eq ! ( tx. built. transaction. output. len( ) , 2 ) ;
1835
1923
1836
1924
// 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 ) ;
1844
1926
assert_eq ! ( tx. built. transaction. output. len( ) , 2 ) ;
1845
1927
1846
1928
let received_htlc = HTLCOutputInCommitment {
@@ -1860,15 +1942,10 @@ mod tests {
1860
1942
} ;
1861
1943
1862
1944
// 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 ( ) ;
1872
1949
assert_eq ! ( tx. built. transaction. output. len( ) , 3 ) ;
1873
1950
assert_eq ! ( tx. built. transaction. output[ 0 ] . script_pubkey, get_htlc_redeemscript( & received_htlc, & ChannelTypeFeatures :: only_static_remote_key( ) , & keys) . to_v0_p2wsh( ) ) ;
1874
1951
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 {
1878
1955
"0020215d61bba56b19e9eadb6107f5a85d7f99c40f65992443f69229c290165bc00d" ) ;
1879
1956
1880
1957
// 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 ) ;
1890
1961
assert_eq ! ( tx. built. transaction. output. len( ) , 5 ) ;
1891
1962
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( ) ) ;
1892
1963
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 {
1896
1967
"002087a3faeb1950a469c0e2db4a79b093a41b9526e5a6fc6ef5cb949bde3be379c7" ) ;
1897
1968
}
1898
1969
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
+
1899
2025
#[ test]
1900
2026
fn test_per_commitment_storage ( ) {
1901
2027
// Test vectors from BOLT 3:
0 commit comments