add lp peer config

This commit is contained in:
Georgio Nicolas
2026-02-25 15:55:46 +01:00
committed by Jędrzej Stuczyński
parent 901557ad04
commit ef5d503692
2 changed files with 130 additions and 0 deletions
+1
View File
@@ -5,6 +5,7 @@ pub mod codec;
pub mod error;
pub mod packet;
pub mod peer;
pub mod peer_config;
pub mod psq;
pub mod replay;
pub mod session;
+129
View File
@@ -0,0 +1,129 @@
use std::char::MAX;
use rand09::{self, CryptoRng, Rng};
use crate::LpError;
pub const MAX_HOPS: u8 = 16;
pub const LP_PEER_CONFIG_SIZE: usize = 20;
// 20 bytes
pub struct LpPeerConfig {
// these 3 fields will be packed in one u8
// with 2 bits left at the end
hop_id: u8,
is_exit: bool,
censorship_resistance: bool,
// if we add config params later, we can use this
filler: [u8; 3],
seed: [u8; 16],
}
impl LpPeerConfig {
pub fn new<R>(
rng: &mut R,
hop_id: u8,
is_exit: bool,
censorship_resistance: bool,
) -> Result<Self, LpError>
where
R: Rng + CryptoRng,
{
let seed: [u8; 16] = rng.random();
let filler: [u8; 3] = rng.random();
Self::build(hop_id, is_exit, censorship_resistance, seed, filler)
}
fn build(
hop_id: u8,
is_exit: bool,
censorship_resistance: bool,
seed: [u8; 16],
filler: [u8; 3],
) -> Result<Self, LpError> {
if hop_id >= MAX_HOPS {
Err(LpError::Internal(format!(
"Requested hop index ({}) is greater than the allowed maximum {}.",
hop_id,
MAX_HOPS - 1
)))
} else if is_exit && hop_id == 0 {
Err(LpError::Internal(
"Hop index for exit node cannot be zero".into(),
))
} else {
Ok(Self {
hop_id,
is_exit,
censorship_resistance,
seed,
filler,
})
}
}
pub fn serialize(&self) -> [u8; LP_PEER_CONFIG_SIZE] {
let mut output_bytes: [u8; LP_PEER_CONFIG_SIZE] = [0u8; LP_PEER_CONFIG_SIZE];
output_bytes[0..4].copy_from_slice(self.pack_config().as_slice());
output_bytes[4..].copy_from_slice(&self.seed);
output_bytes
}
pub fn deserialize(bytes: &[u8]) -> Result<Self, LpError> {
if bytes.len() != LP_PEER_CONFIG_SIZE {
Err(LpError::DeserializationError(format!(
"Invalid Lp Config Length ({}), expected ({})",
bytes.len(),
LP_PEER_CONFIG_SIZE
)))
} else {
let (hop_id, is_exit, censorship_resistance) = Self::unpack_first_byte(bytes[0]);
let filler: [u8; 3] = [bytes[1], bytes[2], bytes[3]];
let mut seed: [u8; 16] = [0u8; 16];
seed.copy_from_slice(&bytes[4..LP_PEER_CONFIG_SIZE]);
Self::build(hop_id, is_exit, censorship_resistance, seed, filler)
}
}
fn pack_config(&self) -> [u8; 4] {
[
self.pack_first_byte(),
self.filler[0],
self.filler[1],
self.filler[2],
]
}
fn pack_first_byte(&self) -> u8 {
let mut byte = self.hop_id;
if self.is_exit {
byte |= 0b0001_0000;
}
if self.censorship_resistance {
byte |= 0b0010_0000;
}
// there will be 2 free bits at the end
byte
}
fn unpack_first_byte(byte: u8) -> (u8, bool, bool) {
// extract 4 bits
let hop_id = byte & 0b0000_1111;
// extract 5th bit
let is_exit = (byte & 0b0001_0000) >> 4 == 1;
// extract 6th bit
let censorship_resistance = (byte & 0b0010_0000) >> 5 == 1;
// if we need to use the last 2 bits, we can add something here
(hop_id, is_exit, censorship_resistance)
}
}