1use crate::crate_time::SystemTime;
4use crate::gen::fiber as molecule_fiber;
5use crate::invoice::HashAlgorithm;
6use crate::onion::PaymentOnionPacket;
7use crate::onion::TlcErrPacket;
8use crate::protocol::{ChannelAnnouncement, ChannelUpdate, EcdsaSignature};
9use crate::serde_utils::PartialSignatureAsBytes;
10use crate::serde_utils::PubNonceAsBytes;
11use crate::EntityHex;
12use crate::Hash256;
13use crate::Privkey;
14use crate::Pubkey;
15use bitflags::bitflags;
16use ckb_types::packed::Byte32 as MByte32;
17use ckb_types::packed::Script;
18use ckb_types::packed::Transaction;
19use ckb_types::prelude::{Pack, Unpack};
20use ckb_types::H256;
21use molecule::prelude::{Builder, Entity};
22use musig2::BinaryEncoding;
23use musig2::PartialSignature;
24use musig2::PubNonce;
25use musig2::{SecNonce, SecNonceBuilder};
26use serde::{Deserialize, Serialize};
27use serde_with::serde_as;
28use std::collections::{HashMap, VecDeque};
29use std::fmt::{Debug, Formatter};
30
31bitflags! {
32 #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
33 #[serde(transparent)]
34 pub struct ChannelFlags: u8 {
35 const PUBLIC = 1;
36 const ONE_WAY = 1 << 1;
37 const EXTERNAL_FUNDING = 1 << 2;
38 }
39
40 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
41 #[serde(transparent)]
42 pub struct ChannelUpdateChannelFlags: u32 {
43 const DISABLED = 1;
44 }
45
46 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
47 #[serde(transparent)]
48 pub struct ChannelUpdateMessageFlags: u32 {
49 const UPDATE_OF_NODE1 = 0;
50 const UPDATE_OF_NODE2 = 1;
51 }
52
53 #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
54 #[serde(transparent)]
55 pub struct NegotiatingFundingFlags: u32 {
56 const OUR_INIT_SENT = 1;
57 const THEIR_INIT_SENT = 1 << 1;
58 const INIT_SENT = NegotiatingFundingFlags::OUR_INIT_SENT.bits() | NegotiatingFundingFlags::THEIR_INIT_SENT.bits();
59 const AWAITING_EXTERNAL_FUNDING = 1 << 2;
60 }
61
62 #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
63 #[serde(transparent)]
64 pub struct CollaboratingFundingTxFlags: u32 {
65 const AWAITING_REMOTE_TX_COLLABORATION_MSG = 1;
66 const PREPARING_LOCAL_TX_COLLABORATION_MSG = 1 << 1;
67 const OUR_TX_COMPLETE_SENT = 1 << 2;
68 const THEIR_TX_COMPLETE_SENT = 1 << 3;
69 const COLLABORATION_COMPLETED = CollaboratingFundingTxFlags::OUR_TX_COMPLETE_SENT.bits() | CollaboratingFundingTxFlags::THEIR_TX_COMPLETE_SENT.bits();
70 }
71
72 #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
73 #[serde(transparent)]
74 pub struct SigningCommitmentFlags: u32 {
75 const OUR_COMMITMENT_SIGNED_SENT = 1;
76 const THEIR_COMMITMENT_SIGNED_SENT = 1 << 1;
77 const COMMITMENT_SIGNED_SENT = SigningCommitmentFlags::OUR_COMMITMENT_SIGNED_SENT.bits() | SigningCommitmentFlags::THEIR_COMMITMENT_SIGNED_SENT.bits();
78 }
79
80 #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
81 #[serde(transparent)]
82 pub struct AwaitingTxSignaturesFlags: u32 {
83 const OUR_TX_SIGNATURES_SENT = 1;
84 const THEIR_TX_SIGNATURES_SENT = 1 << 1;
85 const TX_SIGNATURES_SENT = AwaitingTxSignaturesFlags::OUR_TX_SIGNATURES_SENT.bits() | AwaitingTxSignaturesFlags::THEIR_TX_SIGNATURES_SENT.bits();
86 }
87
88 #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
89 #[serde(transparent)]
90 pub struct AwaitingChannelReadyFlags: u32 {
91 const OUR_CHANNEL_READY = 1;
92 const THEIR_CHANNEL_READY = 1 << 1;
93 const CHANNEL_READY = AwaitingChannelReadyFlags::OUR_CHANNEL_READY.bits() | AwaitingChannelReadyFlags::THEIR_CHANNEL_READY.bits();
94 }
95
96 #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
97 #[serde(transparent)]
98 pub struct ShuttingDownFlags: u32 {
99 const OUR_SHUTDOWN_SENT = 1;
100 const THEIR_SHUTDOWN_SENT = 1 << 1;
101 const AWAITING_PENDING_TLCS = ShuttingDownFlags::OUR_SHUTDOWN_SENT.bits() | ShuttingDownFlags::THEIR_SHUTDOWN_SENT.bits();
102 const DROPPING_PENDING = 1 << 2;
103 const WAITING_COMMITMENT_CONFIRMATION = 1 << 3;
104 }
105
106 #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
107 #[serde(transparent)]
108 pub struct CloseFlags: u32 {
109 const COOPERATIVE = 1;
110 const UNCOOPERATIVE_LOCAL = 1 << 1;
111 const ABANDONED = 1 << 2;
112 const FUNDING_ABORTED = 1 << 3;
113 const UNCOOPERATIVE_REMOTE = 1 << 4;
114 const WAITING_ONCHAIN_SETTLEMENT = 1 << 5;
115 }
116
117 #[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
118 #[serde(transparent)]
119 pub struct AppliedFlags: u8 {
120 const ADD = 1;
121 const REMOVE = 1 << 1;
122 }
123}
124
125#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord, Hash)]
127pub enum TLCId {
128 Offered(u64),
130 Received(u64),
132}
133
134impl From<TLCId> for u64 {
135 fn from(id: TLCId) -> u64 {
136 match id {
137 TLCId::Offered(id) => id,
138 TLCId::Received(id) => id,
139 }
140 }
141}
142
143impl TLCId {
144 pub fn is_offered(&self) -> bool {
145 matches!(self, TLCId::Offered(_))
146 }
147
148 pub fn is_received(&self) -> bool {
149 !self.is_offered()
150 }
151
152 pub fn flip(&self) -> Self {
153 match self {
154 TLCId::Offered(id) => TLCId::Received(*id),
155 TLCId::Received(id) => TLCId::Offered(*id),
156 }
157 }
158
159 pub fn flip_mut(&mut self) {
160 *self = self.flip();
161 }
162}
163
164#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
166pub enum OutboundTlcStatus {
167 LocalAnnounced,
169 Committed,
171 RemoteRemoved,
173 RemoveWaitPrevAck,
176 RemoveWaitAck,
178 RemoveAckConfirmed,
180}
181
182#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
184pub enum InboundTlcStatus {
185 RemoteAnnounced,
187 AnnounceWaitPrevAck,
190 AnnounceWaitAck,
192 Committed,
194 LocalRemoved,
196 RemoveAckConfirmed,
198}
199
200#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
202pub enum TlcStatus {
203 Outbound(OutboundTlcStatus),
205 Inbound(InboundTlcStatus),
207}
208
209impl TlcStatus {
210 pub fn as_outbound_status(&self) -> OutboundTlcStatus {
211 match self {
212 TlcStatus::Outbound(status) => status.clone(),
213 _ => {
214 unreachable!("unexpected status")
215 }
216 }
217 }
218
219 pub fn as_inbound_status(&self) -> InboundTlcStatus {
220 match self {
221 TlcStatus::Inbound(status) => status.clone(),
222 _ => {
223 unreachable!("unexpected status ")
224 }
225 }
226 }
227}
228
229#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
236pub enum ChannelState {
237 NegotiatingFunding(NegotiatingFundingFlags),
242 CollaboratingFundingTx(CollaboratingFundingTxFlags),
244 SigningCommitment(SigningCommitmentFlags),
246 AwaitingTxSignatures(AwaitingTxSignaturesFlags),
249 AwaitingChannelReady(AwaitingChannelReadyFlags),
252 ChannelReady,
255 ShuttingDown(ShuttingDownFlags),
257 Closed(CloseFlags),
259}
260
261impl ChannelState {
262 pub fn is_awaiting_external_funding(&self) -> bool {
263 matches!(
264 self,
265 ChannelState::NegotiatingFunding(flags)
266 if flags.contains(NegotiatingFundingFlags::AWAITING_EXTERNAL_FUNDING)
267 )
268 }
269
270 pub fn is_closed(&self) -> bool {
271 matches!(
272 self,
273 ChannelState::Closed(_)
274 | ChannelState::ShuttingDown(ShuttingDownFlags::WAITING_COMMITMENT_CONFIRMATION)
275 )
276 }
277
278 pub fn can_abort_funding(&self) -> bool {
279 match self {
280 ChannelState::NegotiatingFunding(_)
281 | ChannelState::CollaboratingFundingTx(_)
282 | ChannelState::SigningCommitment(_) => true,
283 ChannelState::AwaitingTxSignatures(flags)
284 if !flags.contains(AwaitingTxSignaturesFlags::OUR_TX_SIGNATURES_SENT) =>
285 {
286 true
287 }
288 _ => false,
289 }
290 }
291}
292
293impl ShuttingDownFlags {
294 pub fn is_ok_for_commitment_operation(&self) -> bool {
295 !self.contains(ShuttingDownFlags::DROPPING_PENDING)
296 && !self.contains(ShuttingDownFlags::WAITING_COMMITMENT_CONFIRMATION)
297 }
298}
299
300pub const INITIAL_COMMITMENT_NUMBER: u64 = 0;
302
303#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
305pub struct CommitmentNumbers {
306 pub local: u64,
307 pub remote: u64,
308}
309
310impl Default for CommitmentNumbers {
311 fn default() -> Self {
312 Self::new()
313 }
314}
315
316impl CommitmentNumbers {
317 pub fn new() -> Self {
318 Self {
319 local: INITIAL_COMMITMENT_NUMBER,
320 remote: INITIAL_COMMITMENT_NUMBER,
321 }
322 }
323
324 pub fn get_local(&self) -> u64 {
325 self.local
326 }
327
328 pub fn get_remote(&self) -> u64 {
329 self.remote
330 }
331
332 pub fn increment_local(&mut self) {
333 self.local += 1;
334 }
335
336 pub fn increment_remote(&mut self) {
337 self.remote += 1;
338 }
339}
340
341#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Default)]
343pub struct ChannelConstraints {
344 pub max_tlc_value_in_flight: u128,
346 pub max_tlc_number_in_flight: u64,
348}
349
350impl ChannelConstraints {
351 pub fn new(max_tlc_value_in_flight: u128, max_tlc_number_in_flight: u64) -> Self {
352 Self {
353 max_tlc_value_in_flight,
354 max_tlc_number_in_flight,
355 }
356 }
357}
358
359#[derive(Default, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
362pub struct ChannelTlcInfo {
363 pub timestamp: u64,
365
366 pub enabled: bool,
368
369 pub tlc_fee_proportional_millionths: u128,
375
376 pub tlc_expiry_delta: u64,
378
379 pub tlc_minimum_value: u128,
381}
382
383impl ChannelTlcInfo {
384 pub fn new(
386 tlc_minimum_value: u128,
387 tlc_expiry_delta: u64,
388 tlc_fee_proportional_millionths: u128,
389 timestamp: u64,
390 ) -> Self {
391 Self {
392 tlc_minimum_value,
393 tlc_expiry_delta,
394 tlc_fee_proportional_millionths,
395 enabled: true,
396 timestamp,
397 }
398 }
399}
400
401#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
403pub struct ChannelBasePublicKeys {
404 pub funding_pubkey: Pubkey,
407 pub tlc_base_key: Pubkey,
410}
411
412#[derive(Debug, Copy, Clone, Serialize, Deserialize, Eq, PartialEq, Hash)]
415pub struct PrevTlcInfo {
416 pub prev_channel_id: Hash256,
417 pub prev_tlc_id: u64,
419 pub forwarding_fee: u128,
420 pub shared_secret: Option<[u8; 32]>,
421}
422
423impl PrevTlcInfo {
424 pub fn new(prev_channel_id: Hash256, prev_tlc_id: u64, forwarding_fee: u128) -> Self {
425 Self {
426 prev_channel_id,
427 prev_tlc_id,
428 forwarding_fee,
429 shared_secret: None,
430 }
431 }
432
433 pub fn new_with_shared_secret(
434 prev_channel_id: Hash256,
435 prev_tlc_id: u64,
436 forwarding_fee: u128,
437 shared_secret: [u8; 32],
438 ) -> Self {
439 Self {
440 prev_channel_id,
441 prev_tlc_id,
442 forwarding_fee,
443 shared_secret: Some(shared_secret),
444 }
445 }
446}
447
448#[derive(Clone, Serialize, Deserialize, Eq, PartialEq)]
449pub struct TlcInfo {
450 pub status: TlcStatus,
451 pub tlc_id: TLCId,
452 pub amount: u128,
453 pub payment_hash: Hash256,
454 pub total_amount: Option<u128>,
456 pub payment_secret: Option<Hash256>,
458 pub attempt_id: Option<u64>,
461 pub expiry: u64,
462 pub hash_algorithm: HashAlgorithm,
463 pub onion_packet: Option<PaymentOnionPacket>,
465 pub shared_secret: [u8; 32],
469 #[serde(default)]
470 pub is_trampoline_hop: bool,
471 pub created_at: CommitmentNumbers,
472 pub removed_reason: Option<RemoveTlcReason>,
473
474 pub forwarding_tlc: Option<(Hash256, u64)>,
500 pub removed_confirmed_at: Option<u64>,
501 pub applied_flags: AppliedFlags,
502}
503
504use std::fmt;
505use std::time::Duration;
506
507impl fmt::Debug for TlcInfo {
508 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
509 f.debug_struct("TlcInfo")
510 .field("status", &self.status)
511 .field("tlc_id", &self.tlc_id)
512 .field("amount", &self.amount)
513 .field("payment_hash", &self.payment_hash)
514 .field("expiry", &self.expiry)
515 .field("created_at", &self.created_at)
516 .field("removed_reason", &self.removed_reason)
517 .field("applied_flags", &self.applied_flags)
518 .finish()
519 }
520}
521
522impl TlcInfo {
523 pub fn log(&self) -> String {
524 format!(
525 "id: {:?} status: {:?} amount: {:?} removed: {:?} hash: {:?} ",
526 &self.tlc_id, self.status, self.amount, self.removed_reason, self.payment_hash,
527 )
528 }
529
530 pub fn id(&self) -> u64 {
531 self.tlc_id.into()
532 }
533
534 pub fn is_offered(&self) -> bool {
535 self.tlc_id.is_offered()
536 }
537
538 pub fn is_received(&self) -> bool {
539 !self.is_offered()
540 }
541
542 pub fn get_commitment_numbers(&self) -> CommitmentNumbers {
543 self.created_at
544 }
545
546 pub fn flip_mut(&mut self) {
547 self.tlc_id.flip_mut();
548 }
549
550 pub fn outbound_status(&self) -> OutboundTlcStatus {
551 self.status.as_outbound_status()
552 }
553
554 pub fn inbound_status(&self) -> InboundTlcStatus {
555 self.status.as_inbound_status()
556 }
557
558 pub fn is_fail_remove_confirmed(&self) -> bool {
559 matches!(self.removed_reason, Some(RemoveTlcReason::RemoveTlcFail(_)))
560 && matches!(
561 self.status,
562 TlcStatus::Outbound(OutboundTlcStatus::RemoveAckConfirmed)
563 | TlcStatus::Outbound(OutboundTlcStatus::RemoveWaitAck)
564 | TlcStatus::Inbound(InboundTlcStatus::RemoveAckConfirmed)
565 )
566 }
567
568 pub fn get_htlc_type(&self) -> u8 {
574 let offered_flag = if self.is_offered() { 0u8 } else { 1u8 };
575 ((self.hash_algorithm as u8) << 1) + offered_flag
576 }
577}
578
579#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Default)]
581pub struct PendingTlcs {
582 pub tlcs: Vec<TlcInfo>,
583 pub next_tlc_id: u64,
584}
585
586impl PendingTlcs {
587 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut TlcInfo> {
588 self.tlcs.iter_mut()
589 }
590
591 pub fn get_next_id(&self) -> u64 {
592 self.next_tlc_id
593 }
594
595 pub fn increment_next_id(&mut self) {
596 self.next_tlc_id += 1;
597 }
598
599 pub fn add_tlc(&mut self, tlc: TlcInfo) {
600 self.tlcs.push(tlc);
601 }
602}
603
604#[derive(Default, Clone, Debug, Serialize, Deserialize)]
606pub struct TlcState {
607 pub offered_tlcs: PendingTlcs,
608 pub received_tlcs: PendingTlcs,
609 pub waiting_ack: bool,
610}
611
612impl TlcState {
613 pub fn info(&self) -> String {
614 format!(
615 "offer_tlcs: {:?} received_tlcs: {:?}",
616 self.offered_tlcs.tlcs.len(),
617 self.received_tlcs.tlcs.len(),
618 )
619 }
620
621 #[cfg(debug_assertions)]
622 pub fn debug(&self) {
623 let format_tlc_list = |tlcs: &[TlcInfo]| -> String {
624 if tlcs.is_empty() {
625 " <none>".to_string()
626 } else {
627 tlcs.iter()
628 .map(|tlc| format!(" {}", tlc.log()))
629 .collect::<Vec<_>>()
630 .join("\n")
631 }
632 };
633
634 let offered_str = format_tlc_list(&self.offered_tlcs.tlcs);
635 let received_str = format_tlc_list(&self.received_tlcs.tlcs);
636
637 if offered_str.contains("<none>") && received_str.contains("<none>") {
638 tracing::info!("TlcState: <none>");
639 } else {
640 tracing::info!(
641 "TlcState:\n Offered:\n{}\n Received:\n{}",
642 offered_str,
643 received_str
644 );
645 }
646 }
647
648 pub fn get_mut(&mut self, tlc_id: &TLCId) -> Option<&mut TlcInfo> {
649 self.offered_tlcs
650 .tlcs
651 .iter_mut()
652 .find(|tlc| tlc.tlc_id == *tlc_id)
653 .or_else(|| {
654 self.received_tlcs
655 .tlcs
656 .iter_mut()
657 .find(|tlc| tlc.tlc_id == *tlc_id)
658 })
659 }
660
661 pub fn get(&self, tlc_id: &TLCId) -> Option<&TlcInfo> {
662 if tlc_id.is_offered() {
663 self.offered_tlcs
664 .tlcs
665 .iter()
666 .find(|tlc| tlc.tlc_id == *tlc_id)
667 } else {
668 self.received_tlcs
669 .tlcs
670 .iter()
671 .find(|tlc| tlc.tlc_id == *tlc_id)
672 }
673 }
674
675 pub fn get_committed_received_tlcs(&self) -> impl Iterator<Item = &TlcInfo> + '_ {
676 self.received_tlcs.tlcs.iter().filter(|tlc| {
677 debug_assert!(tlc.is_received());
678 matches!(tlc.inbound_status(), InboundTlcStatus::Committed)
679 })
680 }
681
682 pub fn get_expired_offered_tlcs(
683 &self,
684 expect_expiry: u64,
685 ) -> impl Iterator<Item = &TlcInfo> + '_ {
686 self.offered_tlcs.tlcs.iter().filter(move |tlc| {
687 tlc.outbound_status() != OutboundTlcStatus::LocalAnnounced
688 && tlc.removed_confirmed_at.is_none()
689 && tlc.expiry < expect_expiry
690 })
691 }
692
693 pub fn get_next_offering(&self) -> u64 {
694 self.offered_tlcs.get_next_id()
695 }
696
697 pub fn get_next_received(&self) -> u64 {
698 self.received_tlcs.get_next_id()
699 }
700
701 pub fn increment_offering(&mut self) {
702 self.offered_tlcs.increment_next_id();
703 }
704
705 pub fn increment_received(&mut self) {
706 self.received_tlcs.increment_next_id();
707 }
708
709 pub fn set_waiting_ack(&mut self, waiting_ack: bool) {
710 self.waiting_ack = waiting_ack;
711 }
712
713 pub fn all_tlcs(&self) -> impl Iterator<Item = &TlcInfo> + '_ {
714 self.offered_tlcs
715 .tlcs
716 .iter()
717 .chain(self.received_tlcs.tlcs.iter())
718 }
719
720 pub fn apply_remove_tlc(&mut self, tlc_id: TLCId) {
721 if tlc_id.is_offered() {
722 self.offered_tlcs.tlcs.retain(|tlc| tlc.tlc_id != tlc_id);
723 } else {
724 self.received_tlcs.tlcs.retain(|tlc| tlc.tlc_id != tlc_id);
725 }
726 }
727
728 pub fn add_offered_tlc(&mut self, tlc: TlcInfo) {
729 self.offered_tlcs.add_tlc(tlc);
730 }
731
732 pub fn add_received_tlc(&mut self, tlc: TlcInfo) {
733 self.received_tlcs.add_tlc(tlc);
734 }
735
736 pub fn set_received_tlc_removed(&mut self, tlc_id: u64, reason: RemoveTlcReason) -> Hash256 {
737 let tlc = self.get_mut(&TLCId::Received(tlc_id)).expect("get tlc");
738 assert_eq!(tlc.inbound_status(), InboundTlcStatus::Committed);
739 tlc.removed_reason = Some(reason);
740 tlc.status = TlcStatus::Inbound(InboundTlcStatus::LocalRemoved);
741 tlc.payment_hash
742 }
743
744 pub fn set_offered_tlc_removed(&mut self, tlc_id: u64, reason: RemoveTlcReason) -> Hash256 {
745 let tlc = self.get_mut(&TLCId::Offered(tlc_id)).expect("get tlc");
746 assert_eq!(tlc.outbound_status(), OutboundTlcStatus::Committed);
747 tlc.removed_reason = Some(reason);
748 tlc.status = TlcStatus::Outbound(OutboundTlcStatus::RemoteRemoved);
749 tlc.payment_hash
750 }
751
752 pub fn commitment_signed_tlcs(&self, for_remote: bool) -> impl Iterator<Item = &TlcInfo> + '_ {
753 self.offered_tlcs
754 .tlcs
755 .iter()
756 .filter(move |tlc| match tlc.outbound_status() {
757 OutboundTlcStatus::LocalAnnounced => for_remote,
758 OutboundTlcStatus::Committed => true,
759 OutboundTlcStatus::RemoteRemoved => for_remote,
760 OutboundTlcStatus::RemoveWaitPrevAck => for_remote,
761 OutboundTlcStatus::RemoveWaitAck => false,
762 OutboundTlcStatus::RemoveAckConfirmed => false,
763 })
764 .chain(
765 self.received_tlcs
766 .tlcs
767 .iter()
768 .filter(move |tlc| match tlc.inbound_status() {
769 InboundTlcStatus::RemoteAnnounced => !for_remote,
770 InboundTlcStatus::AnnounceWaitPrevAck => !for_remote,
771 InboundTlcStatus::AnnounceWaitAck => true,
772 InboundTlcStatus::Committed => true,
773 InboundTlcStatus::LocalRemoved => !for_remote,
774 InboundTlcStatus::RemoveAckConfirmed => false,
775 }),
776 )
777 }
778
779 pub fn update_for_commitment_signed(&mut self) -> bool {
780 for tlc in self.offered_tlcs.tlcs.iter_mut() {
781 if tlc.outbound_status() == OutboundTlcStatus::RemoteRemoved {
782 let status = if self.waiting_ack {
783 OutboundTlcStatus::RemoveWaitPrevAck
784 } else {
785 OutboundTlcStatus::RemoveWaitAck
786 };
787 tlc.status = TlcStatus::Outbound(status);
788 }
789 }
790 for tlc in self.received_tlcs.tlcs.iter_mut() {
791 if tlc.inbound_status() == InboundTlcStatus::RemoteAnnounced {
792 let status = if self.waiting_ack {
793 InboundTlcStatus::AnnounceWaitPrevAck
794 } else {
795 InboundTlcStatus::AnnounceWaitAck
796 };
797 tlc.status = TlcStatus::Inbound(status)
798 }
799 }
800 self.need_another_commitment_signed()
801 }
802
803 pub fn update_for_revoke_and_ack(&mut self, commitment_number: CommitmentNumbers) {
804 for tlc in self.offered_tlcs.tlcs.iter_mut() {
805 match tlc.outbound_status() {
806 OutboundTlcStatus::LocalAnnounced => {
807 tlc.status = TlcStatus::Outbound(OutboundTlcStatus::Committed);
808 }
809 OutboundTlcStatus::RemoveWaitPrevAck => {
810 tlc.status = TlcStatus::Outbound(OutboundTlcStatus::RemoveWaitAck);
811 }
812 OutboundTlcStatus::RemoveWaitAck => {
813 tlc.status = TlcStatus::Outbound(OutboundTlcStatus::RemoveAckConfirmed);
814 tlc.removed_confirmed_at = Some(commitment_number.get_local());
815 }
816 _ => {}
817 }
818 }
819
820 for tlc in self.received_tlcs.tlcs.iter_mut() {
821 match tlc.inbound_status() {
822 InboundTlcStatus::AnnounceWaitPrevAck => {
823 tlc.status = TlcStatus::Inbound(InboundTlcStatus::AnnounceWaitAck);
824 }
825 InboundTlcStatus::AnnounceWaitAck => {
826 tlc.status = TlcStatus::Inbound(InboundTlcStatus::Committed);
827 }
828 InboundTlcStatus::LocalRemoved => {
829 tlc.status = TlcStatus::Inbound(InboundTlcStatus::RemoveAckConfirmed);
830 tlc.removed_confirmed_at = Some(commitment_number.get_remote());
831 }
832 _ => {}
833 }
834 }
835 }
836
837 pub fn need_another_commitment_signed(&self) -> bool {
838 self.offered_tlcs.tlcs.iter().any(|tlc| {
839 let status = tlc.outbound_status();
840 matches!(
841 status,
842 OutboundTlcStatus::LocalAnnounced
843 | OutboundTlcStatus::RemoteRemoved
844 | OutboundTlcStatus::RemoveWaitPrevAck
845 | OutboundTlcStatus::RemoveWaitAck
846 )
847 }) || self.received_tlcs.tlcs.iter().any(|tlc| {
848 let status = tlc.inbound_status();
849 matches!(
850 status,
851 InboundTlcStatus::RemoteAnnounced
852 | InboundTlcStatus::AnnounceWaitPrevAck
853 | InboundTlcStatus::AnnounceWaitAck
854 )
855 })
856 }
857}
858
859#[derive(Clone, Serialize, Deserialize, Eq, PartialEq, Hash)]
861pub struct AddTlcCommand {
862 pub amount: u128,
863 pub payment_hash: Hash256,
864 pub attempt_id: Option<u64>,
866 pub expiry: u64,
867 pub hash_algorithm: HashAlgorithm,
868 pub onion_packet: Option<PaymentOnionPacket>,
870 pub shared_secret: [u8; 32],
874 pub is_trampoline_hop: bool,
876 pub previous_tlc: Option<PrevTlcInfo>,
877}
878
879impl fmt::Debug for AddTlcCommand {
880 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
881 f.debug_struct("AddTlcCommand")
882 .field("amount", &self.amount)
883 .field("payment_hash", &self.payment_hash)
884 .field("attempt_id", &self.attempt_id)
885 .field("expiry", &self.expiry)
886 .field("hash_algorithm", &self.hash_algorithm)
887 .field("is_trampoline_hop", &self.is_trampoline_hop)
888 .field("previous_tlc", &self.previous_tlc)
889 .finish()
890 }
891}
892
893#[derive(Clone, Serialize, Deserialize, Eq, PartialEq, Debug, Hash)]
895pub enum RetryableTlcOperation {
896 RemoveTlc(TLCId, RemoveTlcReason),
897 AddTlc(AddTlcCommand),
898}
899
900#[derive(Clone, Serialize, Deserialize, Eq, PartialEq, Hash)]
902pub struct AddTlc {
903 pub channel_id: Hash256,
904 pub tlc_id: u64,
905 pub amount: u128,
906 pub payment_hash: Hash256,
907 pub expiry: u64,
908 pub hash_algorithm: HashAlgorithm,
909 pub onion_packet: Option<PaymentOnionPacket>,
910}
911
912impl fmt::Debug for AddTlc {
913 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
914 f.debug_struct("AddTlc")
915 .field("channel_id", &self.channel_id)
916 .field("tlc_id", &self.tlc_id)
917 .field("amount", &self.amount)
918 .field("payment_hash", &self.payment_hash)
919 .field("expiry", &self.expiry)
920 .field("hash_algorithm", &self.hash_algorithm)
921 .finish()
922 }
923}
924
925impl From<AddTlc> for molecule_fiber::AddTlc {
926 fn from(add_tlc: AddTlc) -> Self {
927 molecule_fiber::AddTlc::new_builder()
928 .channel_id(add_tlc.channel_id.into())
929 .tlc_id(add_tlc.tlc_id.pack())
930 .amount(add_tlc.amount.pack())
931 .payment_hash(add_tlc.payment_hash.into())
932 .expiry(add_tlc.expiry.pack())
933 .hash_algorithm(molecule::prelude::Byte::new(add_tlc.hash_algorithm as u8))
934 .onion_packet(
935 add_tlc
936 .onion_packet
937 .map(|p| p.into_bytes())
938 .unwrap_or_default()
939 .pack(),
940 )
941 .build()
942 }
943}
944
945impl TryFrom<molecule_fiber::AddTlc> for AddTlc {
946 type Error = anyhow::Error;
947
948 fn try_from(add_tlc: molecule_fiber::AddTlc) -> Result<Self, Self::Error> {
949 let onion_packet_bytes: Vec<u8> = add_tlc.onion_packet().unpack();
950 let onion_packet =
951 (!onion_packet_bytes.is_empty()).then(|| PaymentOnionPacket::new(onion_packet_bytes));
952 Ok(AddTlc {
953 onion_packet,
954 channel_id: add_tlc.channel_id().into(),
955 tlc_id: add_tlc.tlc_id().unpack(),
956 amount: add_tlc.amount().unpack(),
957 payment_hash: add_tlc.payment_hash().into(),
958 expiry: add_tlc.expiry().unpack(),
959 hash_algorithm: add_tlc
960 .hash_algorithm()
961 .try_into()
962 .map_err(|e: crate::invoice::UnknownHashAlgorithmError| anyhow::anyhow!(e))?,
963 })
964 }
965}
966
967#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Hash)]
969pub struct RemoveTlc {
970 pub channel_id: Hash256,
971 pub tlc_id: u64,
972 pub reason: RemoveTlcReason,
973}
974
975impl From<RemoveTlc> for molecule_fiber::RemoveTlc {
976 fn from(remove_tlc: RemoveTlc) -> Self {
977 molecule_fiber::RemoveTlc::new_builder()
978 .channel_id(remove_tlc.channel_id.into())
979 .tlc_id(remove_tlc.tlc_id.pack())
980 .reason(
981 molecule_fiber::RemoveTlcReason::new_builder()
982 .set(remove_tlc.reason)
983 .build(),
984 )
985 .build()
986 }
987}
988
989impl TryFrom<molecule_fiber::RemoveTlc> for RemoveTlc {
990 type Error = anyhow::Error;
991
992 fn try_from(remove_tlc: molecule_fiber::RemoveTlc) -> Result<Self, Self::Error> {
993 Ok(RemoveTlc {
994 channel_id: remove_tlc.channel_id().into(),
995 tlc_id: remove_tlc.tlc_id().unpack(),
996 reason: remove_tlc.reason().into(),
997 })
998 }
999}
1000
1001#[derive(Clone, Serialize, Deserialize, Eq, PartialEq, Debug, Hash)]
1003pub enum TlcReplayUpdate {
1004 Add(AddTlc),
1005 Remove(RemoveTlc),
1006}
1007
1008pub const CURRENT_COMMIT_DIFF_VERSION: u8 = 2;
1010
1011fn default_commit_diff_version() -> u8 {
1012 CURRENT_COMMIT_DIFF_VERSION
1013}
1014
1015#[serde_as]
1017#[derive(Clone, Debug, Serialize, Deserialize)]
1018pub struct CommitmentSignedTemplate {
1019 #[serde_as(as = "PubNonceAsBytes")]
1020 pub next_commitment_nonce: PubNonce,
1021 #[serde(default)]
1022 #[serde_as(as = "Option<PartialSignatureAsBytes>")]
1023 pub funding_tx_partial_signature: Option<PartialSignature>,
1024}
1025
1026#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
1028pub enum ReplayOrderHint {
1029 RevokeThenCommit,
1030 CommitThenRevoke,
1031}
1032
1033#[serde_as]
1035#[derive(Clone, Debug, Serialize, Deserialize)]
1036pub struct CommitDiff {
1037 #[serde(default = "default_commit_diff_version")]
1039 pub version: u8,
1040 #[serde(default)]
1042 pub channel_id: Hash256,
1043 #[serde(default)]
1045 pub local_commitment_number_at_send: u64,
1046 #[serde(default)]
1047 pub remote_commitment_number_at_send: u64,
1048 #[serde_as(as = "EntityHex")]
1050 pub commit_tx: Transaction,
1051 #[serde(default, alias = "tlc_updates")]
1053 pub replay_updates: Vec<TlcReplayUpdate>,
1054 #[serde(default)]
1056 pub commitment_signed_template: Option<CommitmentSignedTemplate>,
1057 #[serde(default)]
1059 pub replay_order_hint: Option<ReplayOrderHint>,
1060 #[serde(default, alias = "created_at")]
1062 pub created_at_ms: u64,
1063}
1064
1065#[serde_as]
1067#[derive(Clone, Serialize, Deserialize, Eq, PartialEq, Debug)]
1068pub struct ShutdownInfo {
1069 #[serde_as(as = "EntityHex")]
1070 pub close_script: Script,
1071 pub fee_rate: u64,
1072 #[serde_as(as = "Option<PartialSignatureAsBytes>")]
1073 pub signature: Option<PartialSignature>,
1074}
1075
1076#[serde_as]
1078#[derive(Debug, Clone, Serialize, Deserialize)]
1079pub struct RevokeAndAck {
1080 pub channel_id: Hash256,
1081 #[serde_as(as = "PartialSignatureAsBytes")]
1082 pub revocation_partial_signature: PartialSignature,
1083 pub next_per_commitment_point: Pubkey,
1084 #[serde_as(as = "PubNonceAsBytes")]
1085 pub next_revocation_nonce: PubNonce,
1086}
1087#[serde_as]
1094#[derive(Default, Clone, Debug, Serialize, Deserialize)]
1095pub struct PublicChannelInfo {
1096 #[serde_as(as = "Option<(_, PartialSignatureAsBytes)>")]
1098 pub local_channel_announcement_signature: Option<(EcdsaSignature, PartialSignature)>,
1099 #[serde_as(as = "Option<(_, PartialSignatureAsBytes)>")]
1100 pub remote_channel_announcement_signature: Option<(EcdsaSignature, PartialSignature)>,
1101 #[serde_as(as = "Option<PubNonceAsBytes>")]
1102 pub remote_channel_announcement_nonce: Option<PubNonce>,
1103 pub channel_announcement: Option<ChannelAnnouncement>,
1104 pub channel_update: Option<ChannelUpdate>,
1105}
1106
1107impl PublicChannelInfo {
1108 pub fn new() -> Self {
1109 Default::default()
1110 }
1111}
1112
1113#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)]
1118pub struct InMemorySigner {
1119 pub funding_key: Privkey,
1121 pub tlc_base_key: Privkey,
1123 pub musig2_base_nonce: Privkey,
1125 pub commitment_seed: [u8; 32],
1127}
1128
1129impl fmt::Debug for InMemorySigner {
1130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1131 f.debug_struct("InMemorySigner")
1132 .field("funding_key", &"[REDACTED]")
1133 .field("tlc_base_key", &"[REDACTED]")
1134 .field("musig2_base_nonce", &"[REDACTED]")
1135 .field("commitment_seed", &"[REDACTED]")
1136 .finish()
1137 }
1138}
1139
1140pub fn blake2b_hash_with_salt(data: &[u8], salt: &[u8]) -> [u8; 32] {
1142 let mut hasher = ckb_hash::new_blake2b();
1143 hasher.update(salt);
1144 hasher.update(data);
1145 let mut result = [0u8; 32];
1146 hasher.finalize(&mut result);
1147 result
1148}
1149
1150pub fn get_tweak_by_commitment_point(commitment_point: &Pubkey) -> [u8; 32] {
1152 let mut hasher = ckb_hash::new_blake2b();
1153 hasher.update(&commitment_point.serialize());
1154 let mut result = [0u8; 32];
1155 hasher.finalize(&mut result);
1156 result
1157}
1158
1159pub fn derive_private_key(secret: &Privkey, commitment_point: &Pubkey) -> Privkey {
1161 secret.tweak(get_tweak_by_commitment_point(commitment_point))
1162}
1163
1164pub fn derive_public_key(base_key: &Pubkey, commitment_point: &Pubkey) -> Pubkey {
1166 base_key.tweak(get_tweak_by_commitment_point(commitment_point))
1167}
1168
1169pub fn derive_tlc_pubkey(base_key: &Pubkey, commitment_point: &Pubkey) -> Pubkey {
1171 derive_public_key(base_key, commitment_point)
1172}
1173
1174pub fn get_commitment_secret(commitment_seed: &[u8; 32], commitment_number: u64) -> [u8; 32] {
1178 let mut res: [u8; 32] = *commitment_seed;
1179 for i in 0..48 {
1180 let bitpos = 47 - i;
1181 if commitment_number & (1 << bitpos) == (1 << bitpos) {
1182 res[bitpos / 8] ^= 1 << (bitpos & 7);
1183 res = ckb_hash::blake2b_256(res);
1184 }
1185 }
1186 res
1187}
1188
1189pub fn get_commitment_point(commitment_seed: &[u8; 32], commitment_number: u64) -> Pubkey {
1191 Privkey::from(&get_commitment_secret(commitment_seed, commitment_number)).pubkey()
1192}
1193
1194pub enum Musig2Context {
1196 Commitment,
1198 Revoke,
1200}
1201
1202impl std::fmt::Display for Musig2Context {
1203 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1204 let context_str = match self {
1205 Musig2Context::Commitment => "COMMITMENT",
1206 Musig2Context::Revoke => "REVOKE",
1207 };
1208 write!(f, "{}", context_str)
1209 }
1210}
1211
1212impl InMemorySigner {
1213 pub fn generate_from_seed(params: &[u8]) -> InMemorySigner {
1215 let seed = ckb_hash::blake2b_256(params);
1216
1217 let commitment_seed = {
1218 let mut hasher = ckb_hash::new_blake2b();
1219 hasher.update(&seed);
1220 hasher.update(&b"commitment seed"[..]);
1221 let mut result = [0u8; 32];
1222 hasher.finalize(&mut result);
1223 result
1224 };
1225
1226 let key_derive = |seed: &[u8], info: &[u8]| {
1227 let result = blake2b_hash_with_salt(seed, info);
1228 Privkey::from_slice(&result)
1229 };
1230
1231 let funding_key = key_derive(&seed, b"funding key");
1232 let tlc_base_key = key_derive(funding_key.as_ref(), b"HTLC base key");
1233 let musig2_base_nonce = key_derive(tlc_base_key.as_ref(), b"musig nocne");
1234
1235 InMemorySigner {
1236 funding_key,
1237 tlc_base_key,
1238 musig2_base_nonce,
1239 commitment_seed,
1240 }
1241 }
1242
1243 pub fn get_base_public_keys(&self) -> ChannelBasePublicKeys {
1245 ChannelBasePublicKeys {
1246 funding_pubkey: self.funding_key.pubkey(),
1247 tlc_base_key: self.tlc_base_key.pubkey(),
1248 }
1249 }
1250
1251 pub fn get_commitment_point(&self, commitment_number: u64) -> Pubkey {
1257 get_commitment_point(&self.commitment_seed, commitment_number)
1258 }
1259
1260 pub fn get_commitment_secret(&self, commitment_number: u64) -> [u8; 32] {
1262 get_commitment_secret(&self.commitment_seed, commitment_number)
1263 }
1264
1265 pub fn derive_tlc_key(&self, new_commitment_number: u64) -> Privkey {
1267 let per_commitment_point = self.get_commitment_point(new_commitment_number);
1268 derive_private_key(&self.tlc_base_key, &per_commitment_point)
1269 }
1270
1271 pub fn derive_musig2_nonce(&self, commitment_number: u64, context: Musig2Context) -> SecNonce {
1273 let commitment_point = self.get_commitment_point(commitment_number);
1274 let seckey = derive_private_key(&self.musig2_base_nonce, &commitment_point);
1275
1276 SecNonceBuilder::new(seckey.as_ref())
1277 .with_extra_input(&context.to_string())
1278 .build()
1279 }
1280}
1281
1282#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
1284pub enum ChannelOpeningStatus {
1285 WaitingForPeer,
1288 FundingTxBuilding,
1290 FundingTxBroadcasted,
1292 ChannelReady,
1294 Failed,
1296}
1297
1298#[serde_as]
1304#[derive(Clone, Debug, Serialize, Deserialize)]
1305pub struct ChannelOpenRecord {
1306 pub channel_id: Hash256,
1311 pub pubkey: Pubkey,
1313 pub is_acceptor: bool,
1315 pub status: ChannelOpeningStatus,
1317 pub funding_amount: u128,
1321 pub failure_detail: Option<String>,
1323 pub created_at: u64,
1325 pub last_updated_at: u64,
1327}
1328
1329impl ChannelOpenRecord {
1330 pub fn new(channel_id: Hash256, pubkey: Pubkey, funding_amount: u128) -> Self {
1332 let now = crate::now_timestamp_as_millis_u64();
1333 Self {
1334 channel_id,
1335 pubkey,
1336 is_acceptor: false,
1337 status: ChannelOpeningStatus::WaitingForPeer,
1338 funding_amount,
1339 failure_detail: None,
1340 created_at: now,
1341 last_updated_at: now,
1342 }
1343 }
1344
1345 pub fn new_inbound(channel_id: Hash256, pubkey: Pubkey, remote_funding_amount: u128) -> Self {
1348 let mut record = Self::new(channel_id, pubkey, remote_funding_amount);
1349 record.is_acceptor = true;
1350 record
1351 }
1352
1353 pub fn update_status(&mut self, status: ChannelOpeningStatus) {
1355 self.status = status;
1356 self.last_updated_at = crate::now_timestamp_as_millis_u64();
1357 }
1358
1359 pub fn fail(&mut self, reason: String) {
1361 self.status = ChannelOpeningStatus::Failed;
1362 self.failure_detail = Some(reason);
1363 self.last_updated_at = crate::now_timestamp_as_millis_u64();
1364 }
1365}
1366
1367pub trait ChannelOpenRecordStore {
1369 fn get_channel_open_records(&self) -> Vec<ChannelOpenRecord>;
1371 fn get_channel_open_record(&self, channel_id: &Hash256) -> Option<ChannelOpenRecord>;
1373 fn insert_channel_open_record(&self, record: ChannelOpenRecord);
1375 fn delete_channel_open_record(&self, channel_id: &Hash256);
1377}
1378
1379#[derive(Clone, Serialize, Deserialize, Debug)]
1381pub struct PendingNotifySettleTlc {
1382 pub payment_hash: Hash256,
1383 pub tlc_id: u64,
1384 pub hold_expire_at: Option<u64>,
1386}
1387
1388impl PendingNotifySettleTlc {
1389 pub fn pending_notify_should_hold(&self) -> bool {
1391 self.hold_expire_at.is_some()
1392 }
1393
1394 pub fn pending_notify_hold_expiry_duration(
1396 &self,
1397 now_millis_since_unix_epoch: u64,
1398 ) -> Duration {
1399 Duration::from_millis(
1400 self.hold_expire_at
1401 .unwrap_or_default()
1402 .saturating_sub(now_millis_since_unix_epoch),
1403 )
1404 }
1405}
1406
1407#[serde_as]
1412#[derive(Clone, Serialize, Deserialize)]
1413pub struct ChannelActorData {
1414 pub state: ChannelState,
1415 pub public_channel_info: Option<PublicChannelInfo>,
1417
1418 pub local_tlc_info: ChannelTlcInfo,
1419 pub remote_tlc_info: Option<ChannelTlcInfo>,
1420
1421 pub local_pubkey: Pubkey,
1423 pub remote_pubkey: Pubkey,
1425
1426 pub id: Hash256,
1427 #[serde_as(as = "Option<EntityHex>")]
1428 pub funding_tx: Option<Transaction>,
1429
1430 pub funding_tx_confirmed_at: Option<(H256, u32, u64)>,
1431
1432 #[serde_as(as = "Option<EntityHex>")]
1433 pub funding_udt_type_script: Option<Script>,
1434
1435 pub is_acceptor: bool,
1438
1439 pub is_one_way: bool,
1442
1443 pub to_local_amount: u128,
1446 pub to_remote_amount: u128,
1449
1450 pub local_reserved_ckb_amount: u64,
1454 pub remote_reserved_ckb_amount: u64,
1455
1456 pub commitment_fee_rate: u64,
1459
1460 pub commitment_delay_epoch: u64,
1463
1464 pub funding_fee_rate: u64,
1467
1468 pub signer: InMemorySigner,
1470
1471 pub local_channel_public_keys: ChannelBasePublicKeys,
1473
1474 pub commitment_numbers: CommitmentNumbers,
1477
1478 pub local_constraints: ChannelConstraints,
1479 pub remote_constraints: ChannelConstraints,
1480
1481 pub tlc_state: TlcState,
1483
1484 pub retryable_tlc_operations: VecDeque<RetryableTlcOperation>,
1486 pub waiting_forward_tlc_tasks: HashMap<TLCId, [u8; 32]>,
1487
1488 #[serde_as(as = "Option<EntityHex>")]
1490 pub remote_shutdown_script: Option<Script>,
1491 #[serde_as(as = "EntityHex")]
1493 pub local_shutdown_script: Script,
1494
1495 #[serde_as(as = "Option<PubNonceAsBytes>")]
1498 pub last_committed_remote_nonce: Option<PubNonce>,
1499
1500 #[serde_as(as = "Option<PubNonceAsBytes>")]
1501 pub remote_revocation_nonce_for_verify: Option<PubNonce>,
1502 #[serde_as(as = "Option<PubNonceAsBytes>")]
1503 pub remote_revocation_nonce_for_send: Option<PubNonce>,
1504 #[serde_as(as = "Option<PubNonceAsBytes>")]
1505 pub remote_revocation_nonce_for_next: Option<PubNonce>,
1506
1507 #[serde_as(as = "Option<EntityHex>")]
1510 pub latest_commitment_transaction: Option<Transaction>,
1511
1512 pub remote_commitment_points: Vec<(u64, Pubkey)>,
1515 pub remote_channel_public_keys: Option<ChannelBasePublicKeys>,
1516
1517 pub local_shutdown_info: Option<ShutdownInfo>,
1519 pub remote_shutdown_info: Option<ShutdownInfo>,
1520
1521 pub shutdown_transaction_hash: Option<H256>,
1524
1525 pub reestablishing: bool,
1528 pub last_revoke_ack_msg: Option<RevokeAndAck>,
1529
1530 pub created_at: SystemTime,
1531
1532 #[serde(default)]
1535 pub pending_replay_updates: Vec<TlcReplayUpdate>,
1536
1537 #[serde(default)]
1539 pub last_was_revoke: bool,
1540}
1541
1542fn partial_signature_to_molecule(partial_signature: PartialSignature) -> MByte32 {
1543 MByte32::from_slice(partial_signature.serialize().as_ref()).expect("[Byte; 32] from [u8; 32]")
1544}
1545
1546fn pub_nonce_to_molecule(pub_nonce: PubNonce) -> molecule_fiber::PubNonce {
1547 molecule_fiber::PubNonce::from_slice(pub_nonce.to_bytes().as_ref())
1548 .expect("PubNonce from 66 bytes")
1549}
1550
1551impl From<PubNonce> for molecule_fiber::PubNonce {
1552 fn from(value: PubNonce) -> Self {
1553 molecule_fiber::PubNonce::from_slice(value.to_bytes().as_ref())
1554 .expect("valid pubnonce serialized to 66 bytes")
1555 }
1556}
1557
1558impl TryFrom<molecule_fiber::PubNonce> for PubNonce {
1559 type Error = musig2::errors::DecodeError<PubNonce>;
1560
1561 fn try_from(value: molecule_fiber::PubNonce) -> Result<Self, Self::Error> {
1562 PubNonce::from_bytes(value.as_slice())
1563 }
1564}
1565
1566impl From<RevokeAndAck> for molecule_fiber::RevokeAndAck {
1567 fn from(revoke_and_ack: RevokeAndAck) -> Self {
1568 molecule_fiber::RevokeAndAck::new_builder()
1569 .channel_id(revoke_and_ack.channel_id.into())
1570 .revocation_partial_signature(partial_signature_to_molecule(
1571 revoke_and_ack.revocation_partial_signature,
1572 ))
1573 .next_per_commitment_point(revoke_and_ack.next_per_commitment_point.into())
1574 .next_revocation_nonce(pub_nonce_to_molecule(revoke_and_ack.next_revocation_nonce))
1575 .build()
1576 }
1577}
1578
1579impl TryFrom<molecule_fiber::RevokeAndAck> for RevokeAndAck {
1580 type Error = anyhow::Error;
1581
1582 fn try_from(revoke_and_ack: molecule_fiber::RevokeAndAck) -> Result<Self, Self::Error> {
1583 Ok(RevokeAndAck {
1584 channel_id: revoke_and_ack.channel_id().into(),
1585 revocation_partial_signature: PartialSignature::from_slice(
1586 revoke_and_ack.revocation_partial_signature().as_slice(),
1587 )
1588 .map_err(|e| anyhow::anyhow!(e))?,
1589 next_per_commitment_point: revoke_and_ack
1590 .next_per_commitment_point()
1591 .try_into()
1592 .map_err(|e: secp256k1::Error| anyhow::anyhow!(e))?,
1593 next_revocation_nonce: PubNonce::from_bytes(
1594 revoke_and_ack.next_revocation_nonce().as_slice(),
1595 )
1596 .map_err(|e| anyhow::anyhow!("{}", e))?,
1597 })
1598 }
1599}
1600
1601#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
1603pub struct RemoveTlcFulfill {
1604 pub payment_preimage: Hash256,
1605}
1606
1607#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
1609pub enum RemoveTlcReason {
1610 RemoveTlcFulfill(RemoveTlcFulfill),
1611 RemoveTlcFail(TlcErrPacket),
1612}
1613
1614impl Debug for RemoveTlcReason {
1615 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1616 match self {
1617 RemoveTlcReason::RemoveTlcFulfill(_fulfill) => {
1618 write!(f, "RemoveTlcFulfill")
1619 }
1620 RemoveTlcReason::RemoveTlcFail(_fail) => {
1621 write!(f, "RemoveTlcFail")
1622 }
1623 }
1624 }
1625}
1626
1627impl RemoveTlcReason {
1628 pub fn backward(self, shared_secret: &[u8; 32]) -> Self {
1631 match self {
1632 RemoveTlcReason::RemoveTlcFulfill(remove_tlc_fulfill) => {
1633 RemoveTlcReason::RemoveTlcFulfill(remove_tlc_fulfill)
1634 }
1635 RemoveTlcReason::RemoveTlcFail(remove_tlc_fail) => {
1636 RemoveTlcReason::RemoveTlcFail(remove_tlc_fail.backward(shared_secret))
1637 }
1638 }
1639 }
1640}
1641
1642impl From<RemoveTlcReason> for molecule_fiber::RemoveTlcReasonUnion {
1643 fn from(remove_tlc_reason: RemoveTlcReason) -> Self {
1644 match remove_tlc_reason {
1645 RemoveTlcReason::RemoveTlcFulfill(remove_tlc_fulfill) => {
1646 molecule_fiber::RemoveTlcReasonUnion::RemoveTlcFulfill(remove_tlc_fulfill.into())
1647 }
1648 RemoveTlcReason::RemoveTlcFail(remove_tlc_fail) => {
1649 molecule_fiber::RemoveTlcReasonUnion::TlcErrPacket(remove_tlc_fail.into())
1650 }
1651 }
1652 }
1653}
1654
1655impl From<RemoveTlcReason> for molecule_fiber::RemoveTlcReason {
1656 fn from(remove_tlc_reason: RemoveTlcReason) -> Self {
1657 molecule_fiber::RemoveTlcReason::new_builder()
1658 .set(remove_tlc_reason)
1659 .build()
1660 }
1661}
1662
1663impl From<molecule_fiber::RemoveTlcReason> for RemoveTlcReason {
1664 fn from(remove_tlc_reason: molecule_fiber::RemoveTlcReason) -> Self {
1665 match remove_tlc_reason.to_enum() {
1666 molecule_fiber::RemoveTlcReasonUnion::RemoveTlcFulfill(remove_tlc_fulfill) => {
1667 RemoveTlcReason::RemoveTlcFulfill(remove_tlc_fulfill.into())
1668 }
1669 molecule_fiber::RemoveTlcReasonUnion::TlcErrPacket(remove_tlc_fail) => {
1670 RemoveTlcReason::RemoveTlcFail(remove_tlc_fail.into())
1671 }
1672 }
1673 }
1674}
1675
1676impl From<RemoveTlcFulfill> for molecule_fiber::RemoveTlcFulfill {
1677 fn from(remove_tlc_fulfill: RemoveTlcFulfill) -> Self {
1678 molecule_fiber::RemoveTlcFulfill::new_builder()
1679 .payment_preimage(remove_tlc_fulfill.payment_preimage.into())
1680 .build()
1681 }
1682}
1683
1684impl From<molecule_fiber::RemoveTlcFulfill> for RemoveTlcFulfill {
1685 fn from(remove_tlc_fulfill: molecule_fiber::RemoveTlcFulfill) -> Self {
1686 RemoveTlcFulfill {
1687 payment_preimage: remove_tlc_fulfill.payment_preimage().into(),
1688 }
1689 }
1690}
1691
1692#[serde_as]
1697#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
1698pub struct ChannelUpdateInfo {
1699 #[serde_as(as = "crate::U64Hex")]
1701 pub timestamp: u64,
1702 pub enabled: bool,
1704 #[serde_as(as = "Option<crate::U128Hex>")]
1706 pub outbound_liquidity: Option<u128>,
1707 #[serde_as(as = "crate::U64Hex")]
1709 pub tlc_expiry_delta: u64,
1710 #[serde_as(as = "crate::U128Hex")]
1712 pub tlc_minimum_value: u128,
1713 #[serde_as(as = "crate::U64Hex")]
1715 pub fee_rate: u64,
1716}
1717
1718impl From<&ChannelTlcInfo> for ChannelUpdateInfo {
1719 fn from(info: &ChannelTlcInfo) -> Self {
1720 Self {
1721 timestamp: info.timestamp,
1722 enabled: info.enabled,
1723 outbound_liquidity: None,
1724 tlc_expiry_delta: info.tlc_expiry_delta,
1725 tlc_minimum_value: info.tlc_minimum_value,
1726 fee_rate: info.tlc_fee_proportional_millionths as u64,
1727 }
1728 }
1729}
1730
1731impl From<ChannelTlcInfo> for ChannelUpdateInfo {
1732 fn from(info: ChannelTlcInfo) -> Self {
1733 Self::from(&info)
1734 }
1735}
1736
1737impl From<crate::protocol::ChannelUpdate> for ChannelUpdateInfo {
1738 fn from(update: crate::protocol::ChannelUpdate) -> Self {
1739 Self::from(&update)
1740 }
1741}
1742
1743impl From<&crate::protocol::ChannelUpdate> for ChannelUpdateInfo {
1744 fn from(update: &crate::protocol::ChannelUpdate) -> Self {
1745 Self {
1746 timestamp: update.timestamp,
1747 enabled: !update.is_disabled(),
1748 outbound_liquidity: None,
1749 tlc_expiry_delta: update.tlc_expiry_delta,
1750 tlc_minimum_value: update.tlc_minimum_value,
1751 fee_rate: update.tlc_fee_proportional_millionths as u64,
1752 }
1753 }
1754}