@@ -1183,8 +1183,11 @@ impl PartialEq for PackageTemplate {
1183
1183
}
1184
1184
1185
1185
impl PackageTemplate {
1186
+ fn weight ( & self ) -> u64 {
1187
+ self . inputs . iter ( ) . map ( |( _, solving_data) | solving_data. weight ( ) ) . sum :: < usize > ( ) as u64
1188
+ }
1186
1189
#[ rustfmt:: skip]
1187
- pub ( crate ) fn can_merge_with ( & self , other : & PackageTemplate , cur_height : u32 ) -> bool {
1190
+ pub ( crate ) fn can_merge_with ( & self , other : & PackageTemplate , cur_height : u32 , is_0fc_channel : bool ) -> bool {
1188
1191
match ( self . malleability , other. malleability ) {
1189
1192
( PackageMalleability :: Untractable , _) => false ,
1190
1193
( _, PackageMalleability :: Untractable ) => false ,
@@ -1235,16 +1238,30 @@ impl PackageTemplate {
1235
1238
self . counterparty_spendable_height <= cur_height + COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE ;
1236
1239
let other_pinnable = other_cluster == AggregationCluster :: Pinnable ||
1237
1240
other. counterparty_spendable_height <= cur_height + COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE ;
1238
- if self_pinnable && other_pinnable {
1239
- return true ;
1240
- }
1241
1241
1242
1242
let self_unpinnable = self_cluster == AggregationCluster :: Unpinnable &&
1243
1243
self . counterparty_spendable_height > cur_height + COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE ;
1244
1244
let other_unpinnable = other_cluster == AggregationCluster :: Unpinnable &&
1245
1245
other. counterparty_spendable_height > cur_height + COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE ;
1246
- if self_unpinnable && other_unpinnable {
1247
- return true ;
1246
+
1247
+ if self_pinnable && other_pinnable || self_unpinnable && other_unpinnable {
1248
+ if is_0fc_channel && self . inputs . iter ( ) . any ( |( _, solving_data) | matches ! ( solving_data, PackageSolvingData :: HolderHTLCOutput ( _) ) ) {
1249
+ // MUST be true, otherwise we are aggregating V2 tx claims with V3 tx claims
1250
+ debug_assert ! ( self . inputs. iter( ) . all( |( _, solving_data) | matches!( solving_data, PackageSolvingData :: HolderHTLCOutput ( _) ) ) ) ;
1251
+ debug_assert ! ( other. inputs. iter( ) . all( |( _, solving_data) | matches!( solving_data, PackageSolvingData :: HolderHTLCOutput ( _) ) ) ) ;
1252
+ // See rust-bitcoin to_vbytes_ceil
1253
+ let self_vbytes = ( self . weight ( ) + 3 ) / 4 ; // This is the weight of the witnesses alone, we need to add more here
1254
+ let other_vbytes = ( other. weight ( ) + 3 ) / 4 ;
1255
+ // What is a good offset to use here to leave room for the user-provided input-output pair?
1256
+ // How much validation to do at coin-selection time in bump_transaction mod ?
1257
+ // Just warn users in the docs not to use some really heavy witnesses to fee-bump their transactions?
1258
+ // A 1-input-1-output p2wpkh-input p2wpkh-input transaction is 109.25vB.
1259
+ if self_vbytes + other_vbytes < 10_000 - 200 {
1260
+ return true ;
1261
+ }
1262
+ } else {
1263
+ return true ;
1264
+ }
1248
1265
}
1249
1266
false
1250
1267
} ,
@@ -1310,9 +1327,9 @@ impl PackageTemplate {
1310
1327
}
1311
1328
}
1312
1329
pub ( crate ) fn merge_package (
1313
- & mut self , mut merge_from : PackageTemplate , cur_height : u32 ,
1330
+ & mut self , mut merge_from : PackageTemplate , cur_height : u32 , is_0fc_channel : bool ,
1314
1331
) -> Result < ( ) , PackageTemplate > {
1315
- if !self . can_merge_with ( & merge_from, cur_height) {
1332
+ if !self . can_merge_with ( & merge_from, cur_height, is_0fc_channel ) {
1316
1333
return Err ( merge_from) ;
1317
1334
}
1318
1335
for ( k, v) in merge_from. inputs . drain ( ..) {
@@ -1985,11 +2002,11 @@ mod tests {
1985
2002
let mut untractable_package = PackageTemplate :: build_package ( fake_txid ( 1 ) , 0 , funding_outp. clone ( ) , 0 ) ;
1986
2003
let mut malleable_package = PackageTemplate :: build_package ( fake_txid ( 2 ) , 0 , htlc_outp. clone ( ) , 1100 ) ;
1987
2004
1988
- assert ! ( !untractable_package. can_merge_with( & malleable_package, 1000 ) ) ;
1989
- assert ! ( untractable_package. merge_package( malleable_package. clone( ) , 1000 ) . is_err( ) ) ;
2005
+ assert ! ( !untractable_package. can_merge_with( & malleable_package, 1000 , false ) ) ;
2006
+ assert ! ( untractable_package. merge_package( malleable_package. clone( ) , 1000 , false ) . is_err( ) ) ;
1990
2007
1991
- assert ! ( !malleable_package. can_merge_with( & untractable_package, 1000 ) ) ;
1992
- assert ! ( malleable_package. merge_package( untractable_package. clone( ) , 1000 ) . is_err( ) ) ;
2008
+ assert ! ( !malleable_package. can_merge_with( & untractable_package, 1000 , false ) ) ;
2009
+ assert ! ( malleable_package. merge_package( untractable_package. clone( ) , 1000 , false ) . is_err( ) ) ;
1993
2010
}
1994
2011
1995
2012
#[ test]
@@ -2000,8 +2017,8 @@ mod tests {
2000
2017
let mut empty_package = PackageTemplate :: build_package ( fake_txid ( 1 ) , 0 , revk_outp. clone ( ) , 0 ) ;
2001
2018
empty_package. inputs = vec ! [ ] ;
2002
2019
let mut package = PackageTemplate :: build_package ( fake_txid ( 1 ) , 1 , revk_outp. clone ( ) , 1100 ) ;
2003
- assert ! ( empty_package. merge_package( package. clone( ) , 1000 ) . is_err( ) ) ;
2004
- assert ! ( package. merge_package( empty_package. clone( ) , 1000 ) . is_err( ) ) ;
2020
+ assert ! ( empty_package. merge_package( package. clone( ) , 1000 , false ) . is_err( ) ) ;
2021
+ assert ! ( package. merge_package( empty_package. clone( ) , 1000 , false ) . is_err( ) ) ;
2005
2022
}
2006
2023
2007
2024
#[ test]
@@ -2017,15 +2034,15 @@ mod tests {
2017
2034
let mut offered_htlc_2_package = PackageTemplate :: build_package ( fake_txid ( 1 ) , 1 , offered_htlc_2. clone ( ) , 0 ) ;
2018
2035
let mut accepted_htlc_package = PackageTemplate :: build_package ( fake_txid ( 1 ) , 2 , accepted_htlc. clone ( ) , 1001 ) ;
2019
2036
2020
- assert ! ( !offered_htlc_2_package. can_merge_with( & offered_htlc_1_package, 1000 ) ) ;
2021
- assert ! ( offered_htlc_2_package. merge_package( offered_htlc_1_package. clone( ) , 1000 ) . is_err( ) ) ;
2022
- assert ! ( !offered_htlc_1_package. can_merge_with( & offered_htlc_2_package, 1000 ) ) ;
2023
- assert ! ( offered_htlc_1_package. merge_package( offered_htlc_2_package. clone( ) , 1000 ) . is_err( ) ) ;
2037
+ assert ! ( !offered_htlc_2_package. can_merge_with( & offered_htlc_1_package, 1000 , false ) ) ;
2038
+ assert ! ( offered_htlc_2_package. merge_package( offered_htlc_1_package. clone( ) , 1000 , false ) . is_err( ) ) ;
2039
+ assert ! ( !offered_htlc_1_package. can_merge_with( & offered_htlc_2_package, 1000 , false ) ) ;
2040
+ assert ! ( offered_htlc_1_package. merge_package( offered_htlc_2_package. clone( ) , 1000 , false ) . is_err( ) ) ;
2024
2041
2025
- assert ! ( !accepted_htlc_package. can_merge_with( & offered_htlc_1_package, 1000 ) ) ;
2026
- assert ! ( accepted_htlc_package. merge_package( offered_htlc_1_package. clone( ) , 1000 ) . is_err( ) ) ;
2027
- assert ! ( !offered_htlc_1_package. can_merge_with( & accepted_htlc_package, 1000 ) ) ;
2028
- assert ! ( offered_htlc_1_package. merge_package( accepted_htlc_package. clone( ) , 1000 ) . is_err( ) ) ;
2042
+ assert ! ( !accepted_htlc_package. can_merge_with( & offered_htlc_1_package, 1000 , false ) ) ;
2043
+ assert ! ( accepted_htlc_package. merge_package( offered_htlc_1_package. clone( ) , 1000 , false ) . is_err( ) ) ;
2044
+ assert ! ( !offered_htlc_1_package. can_merge_with( & accepted_htlc_package, 1000 , false ) ) ;
2045
+ assert ! ( offered_htlc_1_package. merge_package( accepted_htlc_package. clone( ) , 1000 , false ) . is_err( ) ) ;
2029
2046
}
2030
2047
2031
2048
#[ test]
@@ -2043,15 +2060,15 @@ mod tests {
2043
2060
let future_outp_1_package = PackageTemplate :: build_package ( fake_txid ( 1 ) , 2 , future_outp_1. clone ( ) , 0 ) ;
2044
2061
let future_outp_2_package = PackageTemplate :: build_package ( fake_txid ( 1 ) , 3 , future_outp_2. clone ( ) , 0 ) ;
2045
2062
2046
- assert ! ( old_outp_1_package. can_merge_with( & old_outp_2_package, 1000 ) ) ;
2047
- assert ! ( old_outp_2_package. can_merge_with( & old_outp_1_package, 1000 ) ) ;
2048
- assert ! ( old_outp_1_package. clone( ) . merge_package( old_outp_2_package. clone( ) , 1000 ) . is_ok( ) ) ;
2049
- assert ! ( old_outp_2_package. clone( ) . merge_package( old_outp_1_package. clone( ) , 1000 ) . is_ok( ) ) ;
2063
+ assert ! ( old_outp_1_package. can_merge_with( & old_outp_2_package, 1000 , false ) ) ;
2064
+ assert ! ( old_outp_2_package. can_merge_with( & old_outp_1_package, 1000 , false ) ) ;
2065
+ assert ! ( old_outp_1_package. clone( ) . merge_package( old_outp_2_package. clone( ) , 1000 , false ) . is_ok( ) ) ;
2066
+ assert ! ( old_outp_2_package. clone( ) . merge_package( old_outp_1_package. clone( ) , 1000 , false ) . is_ok( ) ) ;
2050
2067
2051
- assert ! ( !future_outp_1_package. can_merge_with( & future_outp_2_package, 1000 ) ) ;
2052
- assert ! ( !future_outp_2_package. can_merge_with( & future_outp_1_package, 1000 ) ) ;
2053
- assert ! ( future_outp_1_package. clone( ) . merge_package( future_outp_2_package. clone( ) , 1000 ) . is_err( ) ) ;
2054
- assert ! ( future_outp_2_package. clone( ) . merge_package( future_outp_1_package. clone( ) , 1000 ) . is_err( ) ) ;
2068
+ assert ! ( !future_outp_1_package. can_merge_with( & future_outp_2_package, 1000 , false ) ) ;
2069
+ assert ! ( !future_outp_2_package. can_merge_with( & future_outp_1_package, 1000 , false ) ) ;
2070
+ assert ! ( future_outp_1_package. clone( ) . merge_package( future_outp_2_package. clone( ) , 1000 , false ) . is_err( ) ) ;
2071
+ assert ! ( future_outp_2_package. clone( ) . merge_package( future_outp_1_package. clone( ) , 1000 , false ) . is_err( ) ) ;
2055
2072
}
2056
2073
2057
2074
#[ test]
@@ -2087,10 +2104,10 @@ mod tests {
2087
2104
for i in 0 ..clusters[ a] . len ( ) {
2088
2105
for j in 0 ..clusters[ b] . len ( ) {
2089
2106
if a != b {
2090
- assert ! ( !clusters[ a] [ i] . can_merge_with( clusters[ b] [ j] , 1000 ) ) ;
2107
+ assert ! ( !clusters[ a] [ i] . can_merge_with( clusters[ b] [ j] , 1000 , false ) ) ;
2091
2108
} else {
2092
2109
if i != j {
2093
- assert ! ( clusters[ a] [ i] . can_merge_with( clusters[ b] [ j] , 1000 ) ) ;
2110
+ assert ! ( clusters[ a] [ i] . can_merge_with( clusters[ b] [ j] , 1000 , false ) ) ;
2094
2111
}
2095
2112
}
2096
2113
}
@@ -2104,9 +2121,9 @@ mod tests {
2104
2121
] ;
2105
2122
for i in ( 1 ..packages. len ( ) ) . rev ( ) {
2106
2123
for j in 0 ..i {
2107
- if packages[ i] . can_merge_with ( & packages[ j] , 1000 ) {
2124
+ if packages[ i] . can_merge_with ( & packages[ j] , 1000 , false ) {
2108
2125
let merge = packages. remove ( i) ;
2109
- assert ! ( packages[ j] . merge_package( merge, 1000 ) . is_ok( ) ) ;
2126
+ assert ! ( packages[ j] . merge_package( merge, 1000 , false ) . is_ok( ) ) ;
2110
2127
}
2111
2128
}
2112
2129
}
@@ -2122,8 +2139,8 @@ mod tests {
2122
2139
let counterparty_received_htlc = dumb_counterparty_received_output ! ( 1_000_000 , 900 , ChannelTypeFeatures :: only_static_remote_key( ) ) ;
2123
2140
let counterparty_received_htlc_package = PackageTemplate :: build_package ( fake_txid ( 2 ) , 0 , counterparty_received_htlc. clone ( ) , 0 ) ;
2124
2141
2125
- assert ! ( !offered_htlc_package. can_merge_with( & counterparty_received_htlc_package, 1000 ) ) ;
2126
- assert ! ( offered_htlc_package. merge_package( counterparty_received_htlc_package. clone( ) , 1000 ) . is_err( ) ) ;
2142
+ assert ! ( !offered_htlc_package. can_merge_with( & counterparty_received_htlc_package, 1000 , false ) ) ;
2143
+ assert ! ( offered_htlc_package. merge_package( counterparty_received_htlc_package. clone( ) , 1000 , false ) . is_err( ) ) ;
2127
2144
}
2128
2145
2129
2146
#[ test]
@@ -2137,8 +2154,8 @@ mod tests {
2137
2154
let package_two = PackageTemplate :: build_package ( fake_txid ( 1 ) , 1 , revk_outp_two, 1100 ) ;
2138
2155
let package_three = PackageTemplate :: build_package ( fake_txid ( 1 ) , 2 , revk_outp_three, 1100 ) ;
2139
2156
2140
- assert ! ( package_one. merge_package( package_two, 1000 ) . is_ok( ) ) ;
2141
- assert ! ( package_one. merge_package( package_three, 1000 ) . is_ok( ) ) ;
2157
+ assert ! ( package_one. merge_package( package_two, 1000 , false ) . is_ok( ) ) ;
2158
+ assert ! ( package_one. merge_package( package_three, 1000 , false ) . is_ok( ) ) ;
2142
2159
assert_eq ! ( package_one. outpoints( ) . len( ) , 3 ) ;
2143
2160
2144
2161
if let Some ( split_package) = package_one. split_package ( & BitcoinOutPoint { txid : fake_txid ( 1 ) , vout : 1 } ) {
0 commit comments