@@ -1183,8 +1183,11 @@ impl PartialEq for PackageTemplate {
11831183}
11841184
11851185impl PackageTemplate {
1186+ fn weight ( & self ) -> u64 {
1187+ self . inputs . iter ( ) . map ( |( _, solving_data) | solving_data. weight ( ) ) . sum :: < usize > ( ) as u64
1188+ }
11861189 #[ 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 {
11881191 match ( self . malleability , other. malleability ) {
11891192 ( PackageMalleability :: Untractable , _) => false ,
11901193 ( _, PackageMalleability :: Untractable ) => false ,
@@ -1235,16 +1238,30 @@ impl PackageTemplate {
12351238 self . counterparty_spendable_height <= cur_height + COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE ;
12361239 let other_pinnable = other_cluster == AggregationCluster :: Pinnable ||
12371240 other. counterparty_spendable_height <= cur_height + COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE ;
1238- if self_pinnable && other_pinnable {
1239- return true ;
1240- }
12411241
12421242 let self_unpinnable = self_cluster == AggregationCluster :: Unpinnable &&
12431243 self . counterparty_spendable_height > cur_height + COUNTERPARTY_CLAIMABLE_WITHIN_BLOCKS_PINNABLE ;
12441244 let other_unpinnable = other_cluster == AggregationCluster :: Unpinnable &&
12451245 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+ }
12481265 }
12491266 false
12501267 } ,
@@ -1310,9 +1327,9 @@ impl PackageTemplate {
13101327 }
13111328 }
13121329 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 ,
13141331 ) -> 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 ) {
13161333 return Err ( merge_from) ;
13171334 }
13181335 for ( k, v) in merge_from. inputs . drain ( ..) {
@@ -1985,11 +2002,11 @@ mod tests {
19852002 let mut untractable_package = PackageTemplate :: build_package ( fake_txid ( 1 ) , 0 , funding_outp. clone ( ) , 0 ) ;
19862003 let mut malleable_package = PackageTemplate :: build_package ( fake_txid ( 2 ) , 0 , htlc_outp. clone ( ) , 1100 ) ;
19872004
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( ) ) ;
19902007
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( ) ) ;
19932010 }
19942011
19952012 #[ test]
@@ -2000,8 +2017,8 @@ mod tests {
20002017 let mut empty_package = PackageTemplate :: build_package ( fake_txid ( 1 ) , 0 , revk_outp. clone ( ) , 0 ) ;
20012018 empty_package. inputs = vec ! [ ] ;
20022019 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( ) ) ;
20052022 }
20062023
20072024 #[ test]
@@ -2017,15 +2034,15 @@ mod tests {
20172034 let mut offered_htlc_2_package = PackageTemplate :: build_package ( fake_txid ( 1 ) , 1 , offered_htlc_2. clone ( ) , 0 ) ;
20182035 let mut accepted_htlc_package = PackageTemplate :: build_package ( fake_txid ( 1 ) , 2 , accepted_htlc. clone ( ) , 1001 ) ;
20192036
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( ) ) ;
20242041
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( ) ) ;
20292046 }
20302047
20312048 #[ test]
@@ -2043,15 +2060,15 @@ mod tests {
20432060 let future_outp_1_package = PackageTemplate :: build_package ( fake_txid ( 1 ) , 2 , future_outp_1. clone ( ) , 0 ) ;
20442061 let future_outp_2_package = PackageTemplate :: build_package ( fake_txid ( 1 ) , 3 , future_outp_2. clone ( ) , 0 ) ;
20452062
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( ) ) ;
20502067
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( ) ) ;
20552072 }
20562073
20572074 #[ test]
@@ -2087,10 +2104,10 @@ mod tests {
20872104 for i in 0 ..clusters[ a] . len ( ) {
20882105 for j in 0 ..clusters[ b] . len ( ) {
20892106 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 ) ) ;
20912108 } else {
20922109 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 ) ) ;
20942111 }
20952112 }
20962113 }
@@ -2104,9 +2121,9 @@ mod tests {
21042121 ] ;
21052122 for i in ( 1 ..packages. len ( ) ) . rev ( ) {
21062123 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 ) {
21082125 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( ) ) ;
21102127 }
21112128 }
21122129 }
@@ -2122,8 +2139,8 @@ mod tests {
21222139 let counterparty_received_htlc = dumb_counterparty_received_output ! ( 1_000_000 , 900 , ChannelTypeFeatures :: only_static_remote_key( ) ) ;
21232140 let counterparty_received_htlc_package = PackageTemplate :: build_package ( fake_txid ( 2 ) , 0 , counterparty_received_htlc. clone ( ) , 0 ) ;
21242141
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( ) ) ;
21272144 }
21282145
21292146 #[ test]
@@ -2137,8 +2154,8 @@ mod tests {
21372154 let package_two = PackageTemplate :: build_package ( fake_txid ( 1 ) , 1 , revk_outp_two, 1100 ) ;
21382155 let package_three = PackageTemplate :: build_package ( fake_txid ( 1 ) , 2 , revk_outp_three, 1100 ) ;
21392156
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( ) ) ;
21422159 assert_eq ! ( package_one. outpoints( ) . len( ) , 3 ) ;
21432160
21442161 if let Some ( split_package) = package_one. split_package ( & BitcoinOutPoint { txid : fake_txid ( 1 ) , vout : 1 } ) {
0 commit comments