Create short_channel_id utils
[rust-lightning] / lightning / src / util / scid_utils.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 /// A `short_channel_id` construction error
11 #[derive(Debug, PartialEq)]
12 pub enum ShortChannelIdError {
13         BlockOverflow,
14         TxIndexOverflow,
15 }
16
17 /// Extracts the block height (most significant 3-bytes) from the `short_channel_id`
18 #[allow(dead_code)]
19 pub fn block_from_scid(short_channel_id: &u64) -> u32 {
20         return (short_channel_id >> 40) as u32;
21 }
22
23 /// Constructs a `short_channel_id` using the components pieces. Results in an error
24 /// if the block height or tx index overflow the 3-bytes for each component.
25 #[allow(dead_code)]
26 pub fn scid_from_parts(block: u32, tx_index: u32, vout_index: u16) -> Result<u64, ShortChannelIdError> {
27         if block > 0x00ffffff {
28                 return Err(ShortChannelIdError::BlockOverflow);
29         }
30
31         if      tx_index > 0x00ffffff {
32                 return Err(ShortChannelIdError::TxIndexOverflow);
33         }
34
35         Ok(((block as u64) << 40) | ((tx_index as u64) << 16) | (vout_index as u64))
36 }
37
38 #[cfg(test)]
39 mod tests {
40         use super::*;
41
42         #[test]
43         fn test_block_from_scid() {
44                 assert_eq!(block_from_scid(&0x000000_000000_0000), 0);
45                 assert_eq!(block_from_scid(&0x000001_000000_0000), 1);
46                 assert_eq!(block_from_scid(&0x000001_ffffff_ffff), 1);
47                 assert_eq!(block_from_scid(&0x800000_ffffff_ffff), 0x800000);
48                 assert_eq!(block_from_scid(&0xffffff_ffffff_ffff), 0xffffff);
49         }
50
51         #[test]
52         fn test_scid_from_parts() {
53                 assert_eq!(scid_from_parts(0x00000000, 0x00000000, 0x0000).unwrap(), 0x000000_000000_0000);
54                 assert_eq!(scid_from_parts(0x00000001, 0x00000002, 0x0003).unwrap(), 0x000001_000002_0003);
55                 assert_eq!(scid_from_parts(0x00111111, 0x00222222, 0x3333).unwrap(), 0x111111_222222_3333);
56                 assert_eq!(scid_from_parts(0x00ffffff, 0x00ffffff, 0xffff).unwrap(), 0xffffff_ffffff_ffff);
57                 assert_eq!(scid_from_parts(0x01ffffff, 0x00000000, 0x0000).err().unwrap(), ShortChannelIdError::BlockOverflow);
58                 assert_eq!(scid_from_parts(0x00000000, 0x01ffffff, 0x0000).err().unwrap(), ShortChannelIdError::TxIndexOverflow);
59         }
60 }