lnp/channel/bolt/
util.rs

1// LNP/BP Core Library implementing LNPBP specifications & standards
2// Written in 2020-2022 by
3//     Dr. Maxim Orlovsky <orlovsky@pandoracore.com>
4//
5// To the extent possible under law, the author(s) have dedicated all
6// copyright and related and neighboring rights to this software to
7// the public domain worldwide. This software is distributed without
8// any warranty.
9//
10// You should have received a copy of the MIT License
11// along with this software.
12// If not, see <https://opensource.org/licenses/MIT>.
13
14use std::collections::BTreeMap;
15use std::convert::TryFrom;
16use std::fmt::Debug;
17
18use internet2::presentation::sphinx::Hop;
19use lnp2p::bolt::Messages;
20use lnpbp::chain::AssetId;
21use p2p::bolt::PaymentOnion;
22use strict_encoding::{
23    self, strict_deserialize, strict_serialize, StrictDecode, StrictEncode,
24};
25
26use super::{AnchorOutputs, BoltChannel, ChannelState, Error, Htlc};
27use crate::channel::shared_ext::Bip96;
28use crate::channel::tx_graph::TxRole;
29use crate::channel::{self, Channel};
30use crate::{extension, ChannelExtension};
31
32/// Shorthand for representing asset - amount pairs
33pub type AssetsBalance = BTreeMap<AssetId, u64>;
34
35#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display)]
36#[derive(StrictEncode, StrictDecode)]
37#[display(Debug)]
38pub enum BoltExt {
39    /// The channel itself
40    Channel = 0,
41
42    /// Main channel constructor
43    Bolt3 = 1,
44    /// HTLC payments
45    Htlc = 2,
46
47    /// BOLT-9 feature: shutdown script
48    ShutdownScript = 10,
49    /// BOLT-9 feature: anchor
50    AnchorOutputs = 11,
51
52    /// The role of policy extension is to make sure that aggregate properties
53    /// of the transaction (no of HTLCs, fees etc) does not violate channel
54    /// policies – and adjust to these policies if needed
55    ///
56    /// NB: Policy must always be applied after other extenders
57    Policy = 100,
58
59    /// Deterministic transaction ordering
60    Bip96 = 1000,
61}
62
63impl Default for BoltExt {
64    fn default() -> Self {
65        BoltExt::Channel
66    }
67}
68
69impl From<BoltExt> for u16 {
70    fn from(id: BoltExt) -> Self {
71        let mut buf = [0u8; 2];
72        buf.copy_from_slice(
73            &strict_serialize(&id)
74                .expect("Enum in-memory strict encoding can't fail"),
75        );
76        u16::from_be_bytes(buf)
77    }
78}
79
80impl TryFrom<u16> for BoltExt {
81    type Error = strict_encoding::Error;
82
83    fn try_from(value: u16) -> Result<Self, Self::Error> {
84        strict_deserialize(value.to_be_bytes())
85    }
86}
87
88impl extension::Nomenclature for BoltExt {
89    type State = ChannelState;
90    type Error = Error;
91    type PeerMessage = lnp2p::bolt::Messages;
92    type UpdateMessage = ();
93    type UpdateRequest = UpdateReq;
94}
95
96impl channel::Nomenclature for BoltExt {
97    type Constructor = BoltChannel;
98
99    #[inline]
100    fn default_extenders() -> Vec<Box<dyn ChannelExtension<Self>>> {
101        vec![Htlc::new()]
102    }
103
104    #[inline]
105    fn default_modifiers() -> Vec<Box<dyn ChannelExtension<Self>>> {
106        vec![Bip96::new()]
107    }
108
109    fn update_from_peer(
110        channel: &mut Channel<Self>,
111        message: &Messages,
112    ) -> Result<(), Error> {
113        #[allow(clippy::single_match)] // We'll add more code in the future
114        match message {
115            Messages::OpenChannel(open_channel) => {
116                if open_channel.has_anchor_outputs() {
117                    channel.add_extender(AnchorOutputs::new())
118                }
119            }
120            _ => {}
121        }
122        Ok(())
123    }
124}
125
126#[derive(Clone, PartialEq, Eq, Hash, Debug)]
127pub enum UpdateReq {
128    PayBolt(Vec<Hop<PaymentOnion>>),
129}
130
131#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display)]
132#[derive(StrictEncode, StrictDecode)]
133#[display(Debug)]
134pub enum TxType {
135    HtlcSuccess,
136    HtlcTimeout,
137    Unknown(u16),
138}
139
140impl From<TxType> for u16 {
141    fn from(ty: TxType) -> Self {
142        match ty {
143            TxType::HtlcSuccess => 0x0,
144            TxType::HtlcTimeout => 0x1,
145            TxType::Unknown(x) => x,
146        }
147    }
148}
149
150impl From<u16> for TxType {
151    fn from(ty: u16) -> Self {
152        match ty {
153            0x00 => TxType::HtlcSuccess,
154            0x01 => TxType::HtlcTimeout,
155            x => TxType::Unknown(x),
156        }
157    }
158}
159
160impl TxRole for TxType {}
161
162/// Channel lifecycle: states of the channel state machine
163#[cfg_attr(
164    feature = "serde",
165    derive(Serialize, Deserialize),
166    serde(crate = "serde_crate")
167)]
168#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display)]
169#[derive(StrictEncode, StrictDecode)]
170#[repr(u8)]
171pub enum Lifecycle {
172    /// Channel is initialized, communications with the remote peer has not
173    /// started yet
174    #[display("INIT")]
175    Initial,
176
177    /// Sent or received `open_channel`
178    #[display("PROPOSED")]
179    Proposed,
180
181    /// Sent or received `accept_channel`
182    #[display("ACCEPTED")]
183    Accepted,
184
185    /// Producing signature for the refund transaction internally
186    #[display("SIGNING")]
187    Signing,
188
189    /// Local party signed funding tx
190    #[display("FUNDING")]
191    Funding,
192
193    /// Other peer signed funding tx
194    #[display("SIGNED")]
195    Signed,
196
197    /// Funding tx is published but not mined
198    #[display("FUNDED")]
199    Funded,
200
201    /// Funding tx mining confirmed by one peer
202    #[display("LOCKED")]
203    Locked,
204
205    /// Both peers confirmed lock, channel active
206    #[display("ACTIVE")]
207    Active,
208
209    /// Reestablishing connectivity
210    #[display("REESTABLISHING")]
211    Reestablishing,
212
213    /// Shutdown proposed but not yet accepted
214    #[display("SHUTDOWN")]
215    Shutdown,
216
217    /// Shutdown agreed, exchanging `closing_signed`
218    #[display("CLOSING-{round}")]
219    Closing { round: usize },
220
221    /// Non-cooperative unilateral closing initialized from the self
222    #[display("ABORTING")]
223    Aborting,
224
225    /// Reacting to an uncooperative channel close from remote
226    #[display("PENALIZE")]
227    Penalize,
228
229    /// Channel non-operational and closed
230    #[display("CLOSED")]
231    Closed,
232}
233
234impl Default for Lifecycle {
235    fn default() -> Self {
236        Lifecycle::Initial
237    }
238}