cdbcd302929c70b1a2a5c59dd51da2d22df39e2e
[rust-lightning] / lightning / src / ln / channel_id.rs
1 // This file is Copyright its original authors, visible in version control
2 // history.
3 //
4 // This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
5 // or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
7 // You may not use this file except in accordance with one or both of these
8 // licenses.
9
10 //! ChannelId definition.
11
12 use crate::ln::msgs::DecodeError;
13 use crate::sign::EntropySource;
14 use crate::util::ser::{Readable, Writeable, Writer};
15
16 use bitcoin::hashes::hex::ToHex;
17
18 use crate::io;
19 use crate::prelude::*;
20 use core::fmt;
21 use core::ops::Deref;
22
23 /// A unique 32-byte identifier for a channel.
24 /// Depending on how the ID is generated, several varieties are distinguished
25 /// (but all are stored as 32 bytes):
26 ///   _v1_ and _temporary_.
27 /// A _v1_ channel ID is generated based on funding tx outpoint (txid & index).
28 /// A _temporary_ ID is generated randomly.
29 /// (Later revocation-point-based _v2_ is a possibility.)
30 /// The variety (context) is not stored, it is relevant only at creation.
31 ///
32 /// This is not exported to bindings users as we just use [u8; 32] directly.
33 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
34 pub struct ChannelId(pub [u8; 32]);
35
36 impl ChannelId {
37         /// Create _v1_ channel ID based on a funding TX ID and output index
38         pub fn v1_from_funding_txid(txid: &[u8; 32], output_index: u16) -> Self {
39                 let mut res = [0; 32];
40                 res[..].copy_from_slice(&txid[..]);
41                 res[30] ^= ((output_index >> 8) & 0xff) as u8;
42                 res[31] ^= ((output_index >> 0) & 0xff) as u8;
43                 Self(res)
44         }
45
46         /// Create a _temporary_ channel ID randomly, based on an entropy source.
47         pub fn temporary_from_entropy_source<ES: Deref>(entropy_source: &ES) -> Self
48         where ES::Target: EntropySource {
49                 Self(entropy_source.get_secure_random_bytes())
50         }
51
52         /// Generic constructor; create a new channel ID from the provided data.
53         /// Use a more specific `*_from_*` constructor when possible.
54         pub fn from_bytes(data: [u8; 32]) -> Self {
55                 Self(data)
56         }
57
58         /// Create a channel ID consisting of all-zeros data (e.g. when uninitialized or a placeholder).
59         pub fn new_zero() -> Self {
60                 Self([0; 32])
61         }
62
63         /// Check whether ID is consisting of all zeros (uninitialized)
64         pub fn is_zero(&self) -> bool {
65                 self.0[..] == [0; 32]
66         }
67 }
68
69 impl Writeable for ChannelId {
70         fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
71                 self.0.write(w)
72         }
73 }
74
75 impl Readable for ChannelId {
76         fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
77                 let buf: [u8; 32] = Readable::read(r)?;
78                 Ok(ChannelId(buf))
79         }
80 }
81
82 impl ToHex for ChannelId {
83         fn to_hex(&self) -> String {
84                 self.0.to_hex()
85         }
86 }
87
88 impl fmt::Display for ChannelId {
89         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90                 crate::util::logger::DebugBytes(&self.0).fmt(f)
91         }
92 }
93
94 #[cfg(test)]
95 mod tests {
96         use crate::ln::ChannelId;
97         use crate::util::ser::{Readable, Writeable};
98         use crate::util::test_utils;
99         use bitcoin::hashes::hex::ToHex;
100         use crate::prelude::*;
101         use crate::io;
102
103         #[test]
104         fn test_channel_id_v1_from_funding_txid() {
105                 let channel_id = ChannelId::v1_from_funding_txid(&[2; 32], 1);
106                 assert_eq!(channel_id.to_hex(), "0202020202020202020202020202020202020202020202020202020202020203");
107         }
108
109         #[test]
110         fn test_channel_id_new_from_data() {
111                 let data: [u8; 32] = [2; 32];
112                 let channel_id = ChannelId::from_bytes(data.clone());
113                 assert_eq!(channel_id.0, data);
114         }
115
116         #[test]
117         fn test_channel_id_equals() {
118                 let channel_id11 = ChannelId::v1_from_funding_txid(&[2; 32], 2);
119                 let channel_id12 = ChannelId::v1_from_funding_txid(&[2; 32], 2);
120                 let channel_id21 = ChannelId::v1_from_funding_txid(&[2; 32], 42);
121                 assert_eq!(channel_id11, channel_id12);
122                 assert_ne!(channel_id11, channel_id21);
123         }
124
125         #[test]
126         fn test_channel_id_write_read() {
127                 let data: [u8; 32] = [2; 32];
128                 let channel_id = ChannelId::from_bytes(data.clone());
129
130                 let mut w = test_utils::TestVecWriter(Vec::new());
131                 channel_id.write(&mut w).unwrap();
132
133                 let channel_id_2 = ChannelId::read(&mut io::Cursor::new(&w.0)).unwrap();
134                 assert_eq!(channel_id_2, channel_id);
135                 assert_eq!(channel_id_2.0, data);
136         }
137
138         #[test]
139         fn test_channel_id_display() {
140                 let channel_id = ChannelId::v1_from_funding_txid(&[2; 32], 1);
141                 assert_eq!(format!("{}", &channel_id), "0202020202020202020202020202020202020202020202020202020202020203");
142         }
143 }