1 // This file is Copyright its original authors, visible in version control
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
10 //! ChannelId definition.
12 use crate::chain::transaction::OutPoint;
14 use crate::ln::msgs::DecodeError;
15 use crate::sign::EntropySource;
16 use crate::util::ser::{Readable, Writeable, Writer};
18 use bitcoin::hashes::Hash as _;
22 /// A unique 32-byte identifier for a channel.
23 /// Depending on how the ID is generated, several varieties are distinguished
24 /// (but all are stored as 32 bytes):
25 /// _v1_ and _temporary_.
26 /// A _v1_ channel ID is generated based on funding tx outpoint (txid & index).
27 /// A _temporary_ ID is generated randomly.
28 /// (Later revocation-point-based _v2_ is a possibility.)
29 /// The variety (context) is not stored, it is relevant only at creation.
31 /// This is not exported to bindings users as we just use [u8; 32] directly.
32 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
33 pub struct ChannelId(pub [u8; 32]);
36 /// Create _v1_ channel ID based on a funding TX ID and output index
37 pub fn v1_from_funding_txid(txid: &[u8; 32], output_index: u16) -> Self {
38 let mut res = [0; 32];
39 res[..].copy_from_slice(&txid[..]);
40 res[30] ^= ((output_index >> 8) & 0xff) as u8;
41 res[31] ^= ((output_index >> 0) & 0xff) as u8;
45 /// Create _v1_ channel ID from a funding tx outpoint
46 pub fn v1_from_funding_outpoint(outpoint: OutPoint) -> Self {
47 Self::v1_from_funding_txid(outpoint.txid.as_byte_array(), outpoint.index)
50 /// Create a _temporary_ channel ID randomly, based on an entropy source.
51 pub fn temporary_from_entropy_source<ES: Deref>(entropy_source: &ES) -> Self
52 where ES::Target: EntropySource {
53 Self(entropy_source.get_secure_random_bytes())
56 /// Generic constructor; create a new channel ID from the provided data.
57 /// Use a more specific `*_from_*` constructor when possible.
58 pub fn from_bytes(data: [u8; 32]) -> Self {
62 /// Create a channel ID consisting of all-zeros data (e.g. when uninitialized or a placeholder).
63 pub fn new_zero() -> Self {
67 /// Check whether ID is consisting of all zeros (uninitialized)
68 pub fn is_zero(&self) -> bool {
73 impl Writeable for ChannelId {
74 fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
79 impl Readable for ChannelId {
80 fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
81 let buf: [u8; 32] = Readable::read(r)?;
86 impl fmt::Display for ChannelId {
87 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
88 crate::util::logger::DebugBytes(&self.0).fmt(f)
96 use crate::ln::ChannelId;
97 use crate::util::ser::{Readable, Writeable};
98 use crate::util::test_utils;
99 use crate::prelude::*;
103 fn test_channel_id_v1_from_funding_txid() {
104 let channel_id = ChannelId::v1_from_funding_txid(&[2; 32], 1);
105 assert_eq!(channel_id.0.as_hex().to_string(), "0202020202020202020202020202020202020202020202020202020202020203");
109 fn test_channel_id_new_from_data() {
110 let data: [u8; 32] = [2; 32];
111 let channel_id = ChannelId::from_bytes(data.clone());
112 assert_eq!(channel_id.0, data);
116 fn test_channel_id_equals() {
117 let channel_id11 = ChannelId::v1_from_funding_txid(&[2; 32], 2);
118 let channel_id12 = ChannelId::v1_from_funding_txid(&[2; 32], 2);
119 let channel_id21 = ChannelId::v1_from_funding_txid(&[2; 32], 42);
120 assert_eq!(channel_id11, channel_id12);
121 assert_ne!(channel_id11, channel_id21);
125 fn test_channel_id_write_read() {
126 let data: [u8; 32] = [2; 32];
127 let channel_id = ChannelId::from_bytes(data.clone());
129 let mut w = test_utils::TestVecWriter(Vec::new());
130 channel_id.write(&mut w).unwrap();
132 let channel_id_2 = ChannelId::read(&mut io::Cursor::new(&w.0)).unwrap();
133 assert_eq!(channel_id_2, channel_id);
134 assert_eq!(channel_id_2.0, data);
138 fn test_channel_id_display() {
139 let channel_id = ChannelId::v1_from_funding_txid(&[2; 32], 1);
140 assert_eq!(format!("{}", &channel_id), "0202020202020202020202020202020202020202020202020202020202020203");