Skip to main content

blvm_protocol/
service_flags.rs

1//! Service flags for Bitcoin P2P protocol
2//!
3//! Defines service flags used in Version messages to indicate node capabilities.
4//! Includes standard Bitcoin flags and Commons-specific extensions.
5
6/// Standard Bitcoin service flags (from Bitcoin Core)
7pub mod standard {
8    /// Node network (always set)
9    pub const NODE_NETWORK: u64 = 1 << 0;
10
11    /// Node GetUTXO (deprecated)
12    pub const NODE_GETUTXO: u64 = 1 << 1;
13
14    /// Node Bloom (deprecated)
15    pub const NODE_BLOOM: u64 = 1 << 2;
16
17    /// Node Witness (SegWit support)
18    pub const NODE_WITNESS: u64 = 1 << 3;
19
20    /// Node Xthin (deprecated)
21    pub const NODE_XTHIN: u64 = 1 << 4;
22
23    /// Node Compact Filters (BIP157)
24    pub const NODE_COMPACT_FILTERS: u64 = 1 << 6;
25
26    /// Node Network Limited (pruned node)
27    pub const NODE_NETWORK_LIMITED: u64 = 1 << 10;
28
29    /// Node supports BIP324 v2 encrypted transport
30    #[cfg(feature = "bip324")]
31    pub const NODE_V2_TRANSPORT: u64 = 1 << 11;
32}
33
34/// Commons-specific service flags
35pub mod commons {
36    /// Node supports Dandelion++ privacy relay
37    pub const NODE_DANDELION: u64 = 1 << 24;
38
39    /// Node supports Package Relay (BIP331)
40    pub const NODE_PACKAGE_RELAY: u64 = 1 << 25;
41
42    /// Node supports FIBRE (Fast Internet Bitcoin Relay Engine)
43    pub const NODE_FIBRE: u64 = 1 << 26;
44
45    /// Node supports UTXO Commitments protocol
46    #[cfg(feature = "utxo-commitments")]
47    pub const NODE_UTXO_COMMITMENTS: u64 = 1 << 27;
48
49    /// Node supports Ban List Sharing
50    pub const NODE_BAN_LIST_SHARING: u64 = 1 << 28;
51
52    /// Node supports governance-related P2P capability (advertised via Version.services)
53    pub const NODE_GOVERNANCE: u64 = 1 << 29;
54
55    /// Erlay (BIP330) transaction relay
56    pub const NODE_ERLAY: u64 = 1 << 30;
57}
58
59pub use commons::*;
60/// Re-export commonly used flags
61pub use standard::*;
62
63/// Check if a service flag is set
64#[inline]
65pub fn has_flag(services: u64, flag: u64) -> bool {
66    (services & flag) != 0
67}
68
69/// Set a service flag
70#[inline]
71pub fn set_flag(services: &mut u64, flag: u64) {
72    *services |= flag;
73}
74
75/// Clear a service flag
76#[inline]
77pub fn clear_flag(services: &mut u64, flag: u64) -> bool {
78    let had_flag = has_flag(*services, flag);
79    *services &= !flag;
80    had_flag
81}
82
83/// Get all Commons-specific flags
84pub fn get_commons_flags() -> u64 {
85    let mut flags = 0u64;
86    #[cfg(feature = "utxo-commitments")]
87    {
88        flags |= commons::NODE_UTXO_COMMITMENTS;
89    }
90    flags |= commons::NODE_DANDELION
91        | commons::NODE_PACKAGE_RELAY
92        | commons::NODE_FIBRE
93        | commons::NODE_BAN_LIST_SHARING;
94    flags
95}
96
97/// Check if node supports Commons features
98pub fn supports_commons(services: u64) -> bool {
99    has_flag(services, commons::NODE_FIBRE)
100        || has_flag(services, commons::NODE_BAN_LIST_SHARING)
101        || {
102            #[cfg(feature = "utxo-commitments")]
103            {
104                has_flag(services, commons::NODE_UTXO_COMMITMENTS)
105            }
106            #[cfg(not(feature = "utxo-commitments"))]
107            {
108                false
109            }
110        }
111}
112
113#[cfg(test)]
114mod tests {
115    use super::*;
116
117    #[test]
118    fn test_has_flag() {
119        let services = standard::NODE_NETWORK | standard::NODE_WITNESS;
120        assert!(has_flag(services, standard::NODE_NETWORK));
121        assert!(has_flag(services, standard::NODE_WITNESS));
122        assert!(!has_flag(services, standard::NODE_BLOOM));
123    }
124
125    #[test]
126    fn test_set_flag() {
127        let mut services = 0u64;
128        set_flag(&mut services, standard::NODE_NETWORK);
129        assert!(has_flag(services, standard::NODE_NETWORK));
130    }
131
132    #[test]
133    fn test_clear_flag() {
134        let mut services = standard::NODE_NETWORK | standard::NODE_WITNESS;
135        assert!(clear_flag(&mut services, standard::NODE_NETWORK));
136        assert!(!has_flag(services, standard::NODE_NETWORK));
137        assert!(has_flag(services, standard::NODE_WITNESS));
138    }
139
140    #[test]
141    fn test_commons_flags() {
142        let flags = get_commons_flags();
143        assert!(has_flag(flags, commons::NODE_DANDELION));
144        assert!(has_flag(flags, commons::NODE_PACKAGE_RELAY));
145        assert!(has_flag(flags, commons::NODE_FIBRE));
146        assert!(has_flag(flags, commons::NODE_BAN_LIST_SHARING));
147    }
148
149    #[test]
150    fn test_supports_commons() {
151        let services = commons::NODE_FIBRE | standard::NODE_NETWORK;
152        assert!(supports_commons(services));
153    }
154}