@@ -1308,6 +1308,7 @@ pub struct CommitmentTransaction {
1308
1308
commitment_number : u64 ,
1309
1309
to_broadcaster_value_sat : u64 ,
1310
1310
to_countersignatory_value_sat : u64 ,
1311
+ to_self_delay : Option < u16 > , // Added in <TODO: expected version>
1311
1312
feerate_per_kw : u32 ,
1312
1313
htlcs : Vec < HTLCOutputInCommitment > ,
1313
1314
// Note that on upgrades, some features of existing outputs may be missed.
@@ -1341,6 +1342,7 @@ impl Writeable for CommitmentTransaction {
1341
1342
let legacy_deserialization_prevention_marker = legacy_deserialization_prevention_marker_for_channel_type_features ( & self . channel_type_features ) ;
1342
1343
write_tlv_fields ! ( writer, {
1343
1344
( 0 , self . commitment_number, required) ,
1345
+ ( 1 , self . to_self_delay, option) ,
1344
1346
( 2 , self . to_broadcaster_value_sat, required) ,
1345
1347
( 4 , self . to_countersignatory_value_sat, required) ,
1346
1348
( 6 , self . feerate_per_kw, required) ,
@@ -1359,6 +1361,7 @@ impl Readable for CommitmentTransaction {
1359
1361
let mut commitment_number = RequiredWrapper ( None ) ;
1360
1362
let mut to_broadcaster_value_sat = RequiredWrapper ( None ) ;
1361
1363
let mut to_countersignatory_value_sat = RequiredWrapper ( None ) ;
1364
+ let mut to_self_delay = None ;
1362
1365
let mut feerate_per_kw = RequiredWrapper ( None ) ;
1363
1366
let mut keys = RequiredWrapper ( None ) ;
1364
1367
let mut built = RequiredWrapper ( None ) ;
@@ -1368,6 +1371,7 @@ impl Readable for CommitmentTransaction {
1368
1371
1369
1372
read_tlv_fields ! ( reader, {
1370
1373
( 0 , commitment_number, required) ,
1374
+ ( 1 , to_self_delay, option) ,
1371
1375
( 2 , to_broadcaster_value_sat, required) ,
1372
1376
( 4 , to_countersignatory_value_sat, required) ,
1373
1377
( 6 , feerate_per_kw, required) ,
@@ -1386,6 +1390,7 @@ impl Readable for CommitmentTransaction {
1386
1390
commitment_number : commitment_number. 0 . unwrap ( ) ,
1387
1391
to_broadcaster_value_sat : to_broadcaster_value_sat. 0 . unwrap ( ) ,
1388
1392
to_countersignatory_value_sat : to_countersignatory_value_sat. 0 . unwrap ( ) ,
1393
+ to_self_delay,
1389
1394
feerate_per_kw : feerate_per_kw. 0 . unwrap ( ) ,
1390
1395
keys : keys. 0 . unwrap ( ) ,
1391
1396
built : built. 0 . unwrap ( ) ,
@@ -1417,6 +1422,7 @@ impl CommitmentTransaction {
1417
1422
commitment_number,
1418
1423
to_broadcaster_value_sat,
1419
1424
to_countersignatory_value_sat,
1425
+ to_self_delay : Some ( channel_parameters. contest_delay ( ) ) ,
1420
1426
feerate_per_kw,
1421
1427
htlcs,
1422
1428
channel_type_features : channel_parameters. channel_type_features ( ) . clone ( ) ,
@@ -1617,6 +1623,52 @@ impl CommitmentTransaction {
1617
1623
& self . htlcs
1618
1624
}
1619
1625
1626
+ /// Returns the index of the revokeable output in the built transaction, if any exists.
1627
+ /// There are two cases where this may return `None`:
1628
+ /// - The balance of the revokeable output is below the dust limit (only found on commitments
1629
+ /// early in the channel's lifetime, i.e. before the channel reserve is met).
1630
+ /// - This commitment was created before <TODO: expected version>. In this case, the
1631
+ /// commitment transaction previously didn't contain enough information to locate the
1632
+ /// revokeable output.
1633
+ pub fn revokeable_output_index ( & self ) -> Option < usize > {
1634
+ let revokeable_redeemscript = get_revokeable_redeemscript (
1635
+ & self . keys . revocation_key ,
1636
+ self . to_self_delay ?,
1637
+ & self . keys . broadcaster_delayed_payment_key ,
1638
+ ) ;
1639
+ let revokeable_p2wsh = revokeable_redeemscript. to_v0_p2wsh ( ) ;
1640
+ let outputs = & self . built . transaction . output ;
1641
+ outputs. iter ( ) . enumerate ( )
1642
+ . find ( |( _, out) | out. script_pubkey == revokeable_p2wsh)
1643
+ . map ( |( idx, _) | idx)
1644
+ }
1645
+
1646
+ /// Helper method to build a basic justice transaction spending `value` sats from an output
1647
+ /// on this transaction to a destination script. Use [`Self::revokeable_output_index`] to get
1648
+ /// the index of the output to spend to create a valid justice transaction.
1649
+ pub fn build_justice_tx ( & self , output_idx : u32 , value : u64 , destination_script : Script )
1650
+ -> Transaction {
1651
+ let input = vec ! [ TxIn {
1652
+ previous_output: OutPoint {
1653
+ txid: self . trust( ) . txid( ) ,
1654
+ vout: output_idx,
1655
+ } ,
1656
+ script_sig: Script :: new( ) ,
1657
+ sequence: Sequence :: ENABLE_RBF_NO_LOCKTIME ,
1658
+ witness: Witness :: new( ) ,
1659
+ } ] ;
1660
+ let output = vec ! [ TxOut {
1661
+ script_pubkey: destination_script,
1662
+ value,
1663
+ } ] ;
1664
+ Transaction {
1665
+ version : 2 ,
1666
+ lock_time : bitcoin:: PackedLockTime :: ZERO ,
1667
+ input,
1668
+ output,
1669
+ }
1670
+ }
1671
+
1620
1672
/// Trust our pre-built transaction and derived transaction creation public keys.
1621
1673
///
1622
1674
/// Applies a wrapper which allows access to these fields.
@@ -1768,7 +1820,7 @@ pub fn get_commitment_transaction_number_obscure_factor(
1768
1820
1769
1821
#[ cfg( test) ]
1770
1822
mod tests {
1771
- use super :: CounterpartyCommitmentSecrets ;
1823
+ use super :: { CounterpartyCommitmentSecrets , ChannelPublicKeys } ;
1772
1824
use crate :: { hex, chain} ;
1773
1825
use crate :: prelude:: * ;
1774
1826
use crate :: ln:: chan_utils:: { get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, CommitmentTransaction , TxCreationKeys , ChannelTransactionParameters , CounterpartyChannelTransactionParameters , HTLCOutputInCommitment } ;
@@ -1783,74 +1835,86 @@ mod tests {
1783
1835
use bitcoin:: PublicKey as BitcoinPublicKey ;
1784
1836
use crate :: ln:: features:: ChannelTypeFeatures ;
1785
1837
1786
- #[ test]
1787
- fn test_anchors ( ) {
1788
- let secp_ctx = Secp256k1 :: new ( ) ;
1838
+ struct TestCommitmentTxBuilder {
1839
+ commitment_number : u64 ,
1840
+ holder_funding_pubkey : PublicKey ,
1841
+ counterparty_funding_pubkey : PublicKey ,
1842
+ keys : TxCreationKeys ,
1843
+ feerate_per_kw : u32 ,
1844
+ htlcs_with_aux : Vec < ( HTLCOutputInCommitment , ( ) ) > ,
1845
+ channel_parameters : ChannelTransactionParameters ,
1846
+ counterparty_pubkeys : ChannelPublicKeys ,
1847
+ }
1848
+
1849
+ impl TestCommitmentTxBuilder {
1850
+ fn new ( ) -> Self {
1851
+ let secp_ctx = Secp256k1 :: new ( ) ;
1852
+ let seed = [ 42 ; 32 ] ;
1853
+ let network = Network :: Testnet ;
1854
+ let keys_provider = test_utils:: TestKeysInterface :: new ( & seed, network) ;
1855
+ let signer = keys_provider. derive_channel_signer ( 3000 , keys_provider. generate_channel_keys_id ( false , 1_000_000 , 0 ) ) ;
1856
+ let counterparty_signer = keys_provider. derive_channel_signer ( 3000 , keys_provider. generate_channel_keys_id ( true , 1_000_000 , 1 ) ) ;
1857
+ let delayed_payment_base = & signer. pubkeys ( ) . delayed_payment_basepoint ;
1858
+ let per_commitment_secret = SecretKey :: from_slice ( & hex:: decode ( "1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100" ) . unwrap ( ) [ ..] ) . unwrap ( ) ;
1859
+ let per_commitment_point = PublicKey :: from_secret_key ( & secp_ctx, & per_commitment_secret) ;
1860
+ let htlc_basepoint = & signer. pubkeys ( ) . htlc_basepoint ;
1861
+ let holder_pubkeys = signer. pubkeys ( ) ;
1862
+ let counterparty_pubkeys = counterparty_signer. pubkeys ( ) . clone ( ) ;
1863
+ let keys = TxCreationKeys :: derive_new ( & secp_ctx, & per_commitment_point, delayed_payment_base, htlc_basepoint, & counterparty_pubkeys. revocation_basepoint , & counterparty_pubkeys. htlc_basepoint ) ;
1864
+ let channel_parameters = ChannelTransactionParameters {
1865
+ holder_pubkeys : holder_pubkeys. clone ( ) ,
1866
+ holder_selected_contest_delay : 0 ,
1867
+ is_outbound_from_holder : false ,
1868
+ counterparty_parameters : Some ( CounterpartyChannelTransactionParameters { pubkeys : counterparty_pubkeys. clone ( ) , selected_contest_delay : 0 } ) ,
1869
+ funding_outpoint : Some ( chain:: transaction:: OutPoint { txid : Txid :: all_zeros ( ) , index : 0 } ) ,
1870
+ channel_type_features : ChannelTypeFeatures :: only_static_remote_key ( ) ,
1871
+ } ;
1872
+ let htlcs_with_aux = Vec :: new ( ) ;
1873
+
1874
+ Self {
1875
+ commitment_number : 0 ,
1876
+ holder_funding_pubkey : holder_pubkeys. funding_pubkey ,
1877
+ counterparty_funding_pubkey : counterparty_pubkeys. funding_pubkey ,
1878
+ keys,
1879
+ feerate_per_kw : 1 ,
1880
+ htlcs_with_aux,
1881
+ channel_parameters,
1882
+ counterparty_pubkeys,
1883
+ }
1884
+ }
1789
1885
1790
- let seed = [ 42 ; 32 ] ;
1791
- let network = Network :: Testnet ;
1792
- let keys_provider = test_utils:: TestKeysInterface :: new ( & seed, network) ;
1793
- let signer = keys_provider. derive_channel_signer ( 3000 , keys_provider. generate_channel_keys_id ( false , 1_000_000 , 0 ) ) ;
1794
- let counterparty_signer = keys_provider. derive_channel_signer ( 3000 , keys_provider. generate_channel_keys_id ( true , 1_000_000 , 1 ) ) ;
1795
- let delayed_payment_base = & signer. pubkeys ( ) . delayed_payment_basepoint ;
1796
- let per_commitment_secret = SecretKey :: from_slice ( & hex:: decode ( "1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100" ) . unwrap ( ) [ ..] ) . unwrap ( ) ;
1797
- let per_commitment_point = PublicKey :: from_secret_key ( & secp_ctx, & per_commitment_secret) ;
1798
- let htlc_basepoint = & signer. pubkeys ( ) . htlc_basepoint ;
1799
- let holder_pubkeys = signer. pubkeys ( ) ;
1800
- let counterparty_pubkeys = counterparty_signer. pubkeys ( ) ;
1801
- let keys = TxCreationKeys :: derive_new ( & secp_ctx, & per_commitment_point, delayed_payment_base, htlc_basepoint, & counterparty_pubkeys. revocation_basepoint , & counterparty_pubkeys. htlc_basepoint ) ;
1802
- let mut channel_parameters = ChannelTransactionParameters {
1803
- holder_pubkeys : holder_pubkeys. clone ( ) ,
1804
- holder_selected_contest_delay : 0 ,
1805
- is_outbound_from_holder : false ,
1806
- counterparty_parameters : Some ( CounterpartyChannelTransactionParameters { pubkeys : counterparty_pubkeys. clone ( ) , selected_contest_delay : 0 } ) ,
1807
- funding_outpoint : Some ( chain:: transaction:: OutPoint { txid : Txid :: all_zeros ( ) , index : 0 } ) ,
1808
- channel_type_features : ChannelTypeFeatures :: only_static_remote_key ( ) ,
1809
- } ;
1886
+ fn build ( & mut self , to_broadcaster_sats : u64 , to_countersignatory_sats : u64 ) -> CommitmentTransaction {
1887
+ CommitmentTransaction :: new_with_auxiliary_htlc_data (
1888
+ self . commitment_number , to_broadcaster_sats, to_countersignatory_sats,
1889
+ self . holder_funding_pubkey . clone ( ) ,
1890
+ self . counterparty_funding_pubkey . clone ( ) ,
1891
+ self . keys . clone ( ) , self . feerate_per_kw ,
1892
+ & mut self . htlcs_with_aux , & self . channel_parameters . as_holder_broadcastable ( )
1893
+ )
1894
+ }
1895
+ }
1810
1896
1811
- let mut htlcs_with_aux: Vec < ( _ , ( ) ) > = Vec :: new ( ) ;
1897
+ #[ test]
1898
+ fn test_anchors ( ) {
1899
+ let mut builder = TestCommitmentTxBuilder :: new ( ) ;
1812
1900
1813
1901
// Generate broadcaster and counterparty outputs
1814
- let tx = CommitmentTransaction :: new_with_auxiliary_htlc_data (
1815
- 0 , 1000 , 2000 ,
1816
- holder_pubkeys. funding_pubkey ,
1817
- counterparty_pubkeys. funding_pubkey ,
1818
- keys. clone ( ) , 1 ,
1819
- & mut htlcs_with_aux, & channel_parameters. as_holder_broadcastable ( )
1820
- ) ;
1902
+ let tx = builder. build ( 1000 , 2000 ) ;
1821
1903
assert_eq ! ( tx. built. transaction. output. len( ) , 2 ) ;
1822
- assert_eq ! ( tx. built. transaction. output[ 1 ] . script_pubkey, Payload :: p2wpkh( & BitcoinPublicKey :: new( counterparty_pubkeys. payment_point) ) . unwrap( ) . script_pubkey( ) ) ;
1904
+ assert_eq ! ( tx. built. transaction. output[ 1 ] . script_pubkey, Payload :: p2wpkh( & BitcoinPublicKey :: new( builder . counterparty_pubkeys. payment_point) ) . unwrap( ) . script_pubkey( ) ) ;
1823
1905
1824
1906
// Generate broadcaster and counterparty outputs as well as two anchors
1825
- channel_parameters. channel_type_features = ChannelTypeFeatures :: anchors_zero_htlc_fee_and_dependencies ( ) ;
1826
- let tx = CommitmentTransaction :: new_with_auxiliary_htlc_data (
1827
- 0 , 1000 , 2000 ,
1828
- holder_pubkeys. funding_pubkey ,
1829
- counterparty_pubkeys. funding_pubkey ,
1830
- keys. clone ( ) , 1 ,
1831
- & mut htlcs_with_aux, & channel_parameters. as_holder_broadcastable ( )
1832
- ) ;
1907
+ builder. channel_parameters . channel_type_features = ChannelTypeFeatures :: anchors_zero_htlc_fee_and_dependencies ( ) ;
1908
+ let tx = builder. build ( 1000 , 2000 ) ;
1833
1909
assert_eq ! ( tx. built. transaction. output. len( ) , 4 ) ;
1834
- assert_eq ! ( tx. built. transaction. output[ 3 ] . script_pubkey, get_to_countersignatory_with_anchors_redeemscript( & counterparty_pubkeys. payment_point) . to_v0_p2wsh( ) ) ;
1910
+ assert_eq ! ( tx. built. transaction. output[ 3 ] . script_pubkey, get_to_countersignatory_with_anchors_redeemscript( & builder . counterparty_pubkeys. payment_point) . to_v0_p2wsh( ) ) ;
1835
1911
1836
1912
// Generate broadcaster output and anchor
1837
- let tx = CommitmentTransaction :: new_with_auxiliary_htlc_data (
1838
- 0 , 3000 , 0 ,
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
- ) ;
1913
+ let tx = builder. build ( 3000 , 0 ) ;
1844
1914
assert_eq ! ( tx. built. transaction. output. len( ) , 2 ) ;
1845
1915
1846
1916
// Generate counterparty output and anchor
1847
- let tx = CommitmentTransaction :: new_with_auxiliary_htlc_data (
1848
- 0 , 0 , 3000 ,
1849
- holder_pubkeys. funding_pubkey ,
1850
- counterparty_pubkeys. funding_pubkey ,
1851
- keys. clone ( ) , 1 ,
1852
- & mut htlcs_with_aux, & channel_parameters. as_holder_broadcastable ( )
1853
- ) ;
1917
+ let tx = builder. build ( 0 , 3000 ) ;
1854
1918
assert_eq ! ( tx. built. transaction. output. len( ) , 2 ) ;
1855
1919
1856
1920
let received_htlc = HTLCOutputInCommitment {
@@ -1870,15 +1934,10 @@ mod tests {
1870
1934
} ;
1871
1935
1872
1936
// Generate broadcaster output and received and offered HTLC outputs, w/o anchors
1873
- channel_parameters. channel_type_features = ChannelTypeFeatures :: only_static_remote_key ( ) ;
1874
- let tx = CommitmentTransaction :: new_with_auxiliary_htlc_data (
1875
- 0 , 3000 , 0 ,
1876
- holder_pubkeys. funding_pubkey ,
1877
- counterparty_pubkeys. funding_pubkey ,
1878
- keys. clone ( ) , 1 ,
1879
- & mut vec ! [ ( received_htlc. clone( ) , ( ) ) , ( offered_htlc. clone( ) , ( ) ) ] ,
1880
- & channel_parameters. as_holder_broadcastable ( )
1881
- ) ;
1937
+ builder. channel_parameters . channel_type_features = ChannelTypeFeatures :: only_static_remote_key ( ) ;
1938
+ builder. htlcs_with_aux = vec ! [ ( received_htlc. clone( ) , ( ) ) , ( offered_htlc. clone( ) , ( ) ) ] ;
1939
+ let tx = builder. build ( 3000 , 0 ) ;
1940
+ let keys = & builder. keys . clone ( ) ;
1882
1941
assert_eq ! ( tx. built. transaction. output. len( ) , 3 ) ;
1883
1942
assert_eq ! ( tx. built. transaction. output[ 0 ] . script_pubkey, get_htlc_redeemscript( & received_htlc, & ChannelTypeFeatures :: only_static_remote_key( ) , & keys) . to_v0_p2wsh( ) ) ;
1884
1943
assert_eq ! ( tx. built. transaction. output[ 1 ] . script_pubkey, get_htlc_redeemscript( & offered_htlc, & ChannelTypeFeatures :: only_static_remote_key( ) , & keys) . to_v0_p2wsh( ) ) ;
@@ -1888,15 +1947,9 @@ mod tests {
1888
1947
"0020215d61bba56b19e9eadb6107f5a85d7f99c40f65992443f69229c290165bc00d" ) ;
1889
1948
1890
1949
// Generate broadcaster output and received and offered HTLC outputs, with anchors
1891
- channel_parameters. channel_type_features = ChannelTypeFeatures :: anchors_zero_htlc_fee_and_dependencies ( ) ;
1892
- let tx = CommitmentTransaction :: new_with_auxiliary_htlc_data (
1893
- 0 , 3000 , 0 ,
1894
- holder_pubkeys. funding_pubkey ,
1895
- counterparty_pubkeys. funding_pubkey ,
1896
- keys. clone ( ) , 1 ,
1897
- & mut vec ! [ ( received_htlc. clone( ) , ( ) ) , ( offered_htlc. clone( ) , ( ) ) ] ,
1898
- & channel_parameters. as_holder_broadcastable ( )
1899
- ) ;
1950
+ builder. channel_parameters . channel_type_features = ChannelTypeFeatures :: anchors_zero_htlc_fee_and_dependencies ( ) ;
1951
+ builder. htlcs_with_aux = vec ! [ ( received_htlc. clone( ) , ( ) ) , ( offered_htlc. clone( ) , ( ) ) ] ;
1952
+ let tx = builder. build ( 3000 , 0 ) ;
1900
1953
assert_eq ! ( tx. built. transaction. output. len( ) , 5 ) ;
1901
1954
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( ) ) ;
1902
1955
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( ) ) ;
@@ -1906,6 +1959,26 @@ mod tests {
1906
1959
"002087a3faeb1950a469c0e2db4a79b093a41b9526e5a6fc6ef5cb949bde3be379c7" ) ;
1907
1960
}
1908
1961
1962
+ #[ test]
1963
+ fn test_finding_revokeable_output_index ( ) {
1964
+ let mut builder = TestCommitmentTxBuilder :: new ( ) ;
1965
+
1966
+ // Revokeable output present
1967
+ let tx = builder. build ( 1000 , 2000 ) ;
1968
+ assert_eq ! ( tx. built. transaction. output. len( ) , 2 ) ;
1969
+ assert_eq ! ( tx. revokeable_output_index( ) , Some ( 0 ) ) ;
1970
+
1971
+ // Revokeable output present (but to_self_delay missing)
1972
+ let tx = CommitmentTransaction { to_self_delay : None , ..tx } ;
1973
+ assert_eq ! ( tx. built. transaction. output. len( ) , 2 ) ;
1974
+ assert_eq ! ( tx. revokeable_output_index( ) , None ) ;
1975
+
1976
+ // Revokeable output not present (our balance is dust)
1977
+ let tx = builder. build ( 0 , 2000 ) ;
1978
+ assert_eq ! ( tx. built. transaction. output. len( ) , 1 ) ;
1979
+ assert_eq ! ( tx. revokeable_output_index( ) , None ) ;
1980
+ }
1981
+
1909
1982
#[ test]
1910
1983
fn test_per_commitment_storage ( ) {
1911
1984
// Test vectors from BOLT 3:
0 commit comments