@@ -320,6 +320,11 @@ impl PackageTemplate {
320
320
None
321
321
} ,
322
322
_ => {
323
+ // Note, we may try to split on remote transaction for
324
+ // which we don't have a competing one (HTLC-Success before
325
+ // timelock expiration). This explain we don't panic!.
326
+ // We should refactor OnchainTxHandler::block_connected to
327
+ // only test equality on competing claims.
323
328
return None ;
324
329
}
325
330
}
@@ -559,6 +564,14 @@ impl PackageTemplate {
559
564
}
560
565
}
561
566
567
+ impl Default for PackageTemplate {
568
+ fn default ( ) -> Self {
569
+ PackageTemplate :: MalleableJusticeTx {
570
+ inputs : HashMap :: new ( ) ,
571
+ }
572
+ }
573
+ }
574
+
562
575
impl Writeable for PackageTemplate {
563
576
fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , :: std:: io:: Error > {
564
577
match self {
@@ -639,3 +652,152 @@ impl Readable for PackageTemplate {
639
652
Ok ( package)
640
653
}
641
654
}
655
+
656
+ /// BumpStrategy is a basic enum to encode a fee-committing strategy. We
657
+ /// may extend it in the future with other stategies like BYOF-input.
658
+ #[ derive( PartialEq , Clone ) ]
659
+ pub ( crate ) enum BumpStrategy {
660
+ RBF ,
661
+ CPFP
662
+ }
663
+
664
+ impl Writeable for BumpStrategy {
665
+ fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , :: std:: io:: Error > {
666
+ match self {
667
+ BumpStrategy :: RBF => {
668
+ writer. write_all ( & [ 0 ; 1 ] ) ?;
669
+ } ,
670
+ BumpStrategy :: CPFP => {
671
+ writer. write_all ( & [ 1 ; 1 ] ) ?;
672
+ }
673
+ }
674
+ Ok ( ( ) )
675
+ }
676
+ }
677
+
678
+ impl Readable for BumpStrategy {
679
+ fn read < R : :: std:: io:: Read > ( reader : & mut R ) -> Result < Self , DecodeError > {
680
+ let bump_strategy = match <u8 as Readable >:: read ( reader) ? {
681
+ 0 => {
682
+ BumpStrategy :: RBF
683
+ } ,
684
+ 1 => {
685
+ BumpStrategy :: CPFP
686
+ } ,
687
+ _ => return Err ( DecodeError :: InvalidValue ) ,
688
+ } ;
689
+ Ok ( bump_strategy)
690
+ }
691
+ }
692
+
693
+ /// A structure to describe a claim content and its metadatas which is generated
694
+ /// by ChannelMonitor and used by OnchainTxHandler to generate feerate-competive
695
+ /// transactions.
696
+ ///
697
+ /// Metadatas are related to multiple fields playing a role in packet lifetime.
698
+ /// Once issued, it may be aggregated with other requests if it's judged safe
699
+ /// and feerate opportunistic.
700
+ /// Current LN fees model, pre-committed fees with update_fee adjustement, means
701
+ /// that counter-signed transactions must be CPFP to be dynamically confirmed as a
702
+ /// bumping strategy. If transactions aren't lockdown (i.e justice transactions) we
703
+ /// may RBF them.
704
+ /// Feerate previous will serve as a feerate floor between different bumping attempts.
705
+ /// Height timer clocks these different bumping attempts.
706
+ /// Absolute timelock defines the block barrier at which claiming isn't exclusive
707
+ /// to us anymore and thus we MUST have get it solved before.
708
+ /// Height original serves as a packet timestamps to prune out claim in case of reorg.
709
+ /// Content embeds transactions elements to generate transaction. See PackageTemplate.
710
+ #[ derive( PartialEq , Clone ) ]
711
+ pub struct OnchainRequest {
712
+ // Timeout tx must have nLocktime set which means aggregating multiple
713
+ // ones must take the higher nLocktime among them to satisfy all of them.
714
+ // Sadly it has few pitfalls, a) it takes longuer to get fund back b) CLTV_DELTA
715
+ // of a sooner-HTLC could be swallowed by the highest nLocktime of the HTLC set.
716
+ // Do simplify we mark them as non-aggregable.
717
+ pub ( crate ) aggregation : bool ,
718
+ // Content may lockdown with counter-signature of our counterparty
719
+ // or fully-malleable by our own. Depending on this bumping strategy
720
+ // must be adapted.
721
+ pub ( crate ) bump_strategy : BumpStrategy ,
722
+ // Based feerate of previous broadcast. If resources available (either
723
+ // output value or utxo bumping).
724
+ pub ( crate ) feerate_previous : u64 ,
725
+ // At every block tick, used to check if pending claiming tx is taking too
726
+ // much time for confirmation and we need to bump it.
727
+ pub ( crate ) height_timer : Option < u32 > ,
728
+ // Block height before which claiming is exclusive to one party,
729
+ // after reaching it, claiming may be contentious.
730
+ pub ( crate ) absolute_timelock : u32 ,
731
+ // Tracked in case of reorg to wipe out now-superflous request.
732
+ pub ( crate ) height_original : u32 ,
733
+ // Content of request.
734
+ pub ( crate ) content : PackageTemplate ,
735
+ }
736
+
737
+ impl OnchainRequest {
738
+ pub ( crate ) fn request_merge ( & mut self , req : OnchainRequest ) {
739
+ // We init default onchain request with first merge content
740
+ if self . absolute_timelock == :: std:: u32:: MAX {
741
+ println ! ( "Init merging {}" , req. height_original) ;
742
+ self . height_original = req. height_original ;
743
+ self . content = req. content ;
744
+ self . absolute_timelock = req. absolute_timelock ;
745
+ return ;
746
+ }
747
+ assert_eq ! ( self . height_original, req. height_original) ;
748
+ if self . absolute_timelock > req. absolute_timelock {
749
+ self . absolute_timelock = req. absolute_timelock ;
750
+ }
751
+ self . content . package_merge ( req. content ) ;
752
+ }
753
+ }
754
+
755
+ impl Default for OnchainRequest {
756
+ fn default ( ) -> Self {
757
+ OnchainRequest {
758
+ aggregation : true ,
759
+ bump_strategy : BumpStrategy :: RBF ,
760
+ feerate_previous : 0 ,
761
+ height_timer : None ,
762
+ absolute_timelock : :: std:: u32:: MAX ,
763
+ height_original : 0 ,
764
+ content : PackageTemplate :: default ( )
765
+ }
766
+ }
767
+ }
768
+
769
+ impl Writeable for OnchainRequest {
770
+ fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , :: std:: io:: Error > {
771
+ self . aggregation . write ( writer) ?;
772
+ self . bump_strategy . write ( writer) ?;
773
+ self . feerate_previous . write ( writer) ?;
774
+ self . height_timer . write ( writer) ?;
775
+ self . absolute_timelock . write ( writer) ?;
776
+ self . height_original . write ( writer) ?;
777
+ self . content . write ( writer) ?;
778
+
779
+ Ok ( ( ) )
780
+ }
781
+ }
782
+
783
+ impl Readable for OnchainRequest {
784
+ fn read < R : :: std:: io:: Read > ( reader : & mut R ) -> Result < Self , DecodeError > {
785
+ let aggregation = Readable :: read ( reader) ?;
786
+ let bump_strategy = Readable :: read ( reader) ?;
787
+ let feerate_previous = Readable :: read ( reader) ?;
788
+ let height_timer = Readable :: read ( reader) ?;
789
+ let absolute_timelock = Readable :: read ( reader) ?;
790
+ let height_original = Readable :: read ( reader) ?;
791
+ let content = Readable :: read ( reader) ?;
792
+
793
+ Ok ( OnchainRequest {
794
+ aggregation,
795
+ bump_strategy,
796
+ feerate_previous,
797
+ height_timer,
798
+ absolute_timelock,
799
+ height_original,
800
+ content
801
+ } )
802
+ }
803
+ }
0 commit comments