pub const BOLT_MAGIC: [u8; 4] = [0x60, 0x60, 0xB0, 0x17];
pub const SUPPORTED_VERSIONS: [(u8, u8); 4] = [
(5, 4), (5, 3),
(5, 2),
(5, 1), ];
pub fn negotiate_version(proposals: &[u8; 16]) -> Option<(u8, u8)> {
for chunk in proposals.chunks_exact(4) {
let range = chunk[1];
let minor = chunk[2];
let major = chunk[3];
if major == 0 && minor == 0 {
continue;
}
for &(sup_major, sup_minor) in &SUPPORTED_VERSIONS {
if sup_major == major && sup_minor <= minor && sup_minor >= minor.saturating_sub(range)
{
return Some((sup_major, sup_minor));
}
}
}
None
}
pub fn encode_version(major: u8, minor: u8) -> [u8; 4] {
[0, 0, minor, major]
}
pub const NO_VERSION: [u8; 4] = [0, 0, 0, 0];
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn negotiate_exact_match() {
let mut proposals = [0u8; 16];
proposals[2] = 4; proposals[3] = 5; assert_eq!(negotiate_version(&proposals), Some((5, 4)));
}
#[test]
fn negotiate_range_match() {
let mut proposals = [0u8; 16];
proposals[1] = 3; proposals[2] = 6; proposals[3] = 5; assert_eq!(negotiate_version(&proposals), Some((5, 4)));
}
#[test]
fn negotiate_no_match() {
let mut proposals = [0u8; 16];
proposals[2] = 4; proposals[3] = 4; assert_eq!(negotiate_version(&proposals), None);
}
#[test]
fn negotiate_second_proposal() {
let mut proposals = [0u8; 16];
proposals[2] = 0;
proposals[3] = 6;
proposals[6] = 2; proposals[7] = 5; assert_eq!(negotiate_version(&proposals), Some((5, 2)));
}
#[test]
fn negotiate_all_zeros() {
let proposals = [0u8; 16];
assert_eq!(negotiate_version(&proposals), None);
}
#[test]
fn encode_version_54() {
assert_eq!(encode_version(5, 4), [0, 0, 4, 5]);
}
}