pub const WOTS_HASH: u32 = 0;
pub const WOTS_PK: u32 = 1;
pub const TREE: u32 = 2;
pub const FORS_TREE: u32 = 3;
pub const FORS_ROOTS: u32 = 4;
pub const WOTS_PRF: u32 = 5;
pub const FORS_PRF: u32 = 6;
#[derive(Clone, Debug)]
pub struct Adrs {
data: [u8; 32],
}
impl Default for Adrs {
fn default() -> Self {
Self::new()
}
}
impl Adrs {
pub fn new() -> Self {
Self { data: [0u8; 32] }
}
pub fn as_bytes(&self) -> &[u8; 32] {
&self.data
}
pub fn as_bytes_compressed(&self) -> [u8; 22] {
let mut c = [0u8; 22];
c[0] = self.data[3]; c[1..9].copy_from_slice(&self.data[8..16]); c[9] = self.data[19]; c[10..22].copy_from_slice(&self.data[20..32]); c
}
fn get_word(&self, offset: usize) -> u32 {
u32::from_be_bytes([
self.data[offset],
self.data[offset + 1],
self.data[offset + 2],
self.data[offset + 3],
])
}
fn set_word(&mut self, offset: usize, val: u32) {
let bytes = val.to_be_bytes();
self.data[offset..offset + 4].copy_from_slice(&bytes);
}
pub fn get_layer_address(&self) -> u32 {
self.get_word(0)
}
pub fn set_layer_address(&mut self, val: u32) {
self.set_word(0, val);
}
pub fn set_tree_address(&mut self, val: u64) {
self.set_word(4, 0);
self.set_word(8, (val >> 32) as u32);
self.set_word(12, val as u32);
}
pub fn get_tree_address(&self) -> u64 {
let hi = self.get_word(8) as u64;
let lo = self.get_word(12) as u64;
(hi << 32) | lo
}
pub fn set_type_and_clear(&mut self, addr_type: u32) {
self.set_word(16, addr_type);
for i in 20..32 {
self.data[i] = 0;
}
}
pub fn get_type(&self) -> u32 {
self.get_word(16)
}
pub fn get_key_pair_address(&self) -> u32 {
self.get_word(20)
}
pub fn set_key_pair_address(&mut self, val: u32) {
self.set_word(20, val);
}
pub fn get_chain_address(&self) -> u32 {
self.get_word(24)
}
pub fn set_chain_address(&mut self, val: u32) {
self.set_word(24, val);
}
pub fn get_hash_address(&self) -> u32 {
self.get_word(28)
}
pub fn set_hash_address(&mut self, val: u32) {
self.set_word(28, val);
}
pub fn get_tree_height(&self) -> u32 {
self.get_word(24)
}
pub fn set_tree_height(&mut self, val: u32) {
self.set_word(24, val);
}
pub fn get_tree_index(&self) -> u32 {
self.get_word(28)
}
pub fn set_tree_index(&mut self, val: u32) {
self.set_word(28, val);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn compressed_address_layout() {
let mut a = Adrs::new();
a.set_layer_address(0x11); a.set_tree_address(0x2233_4455_6677_8899); a.set_type_and_clear(0x06); a.set_key_pair_address(0xaabb_ccdd); a.set_tree_height(0x01020304); a.set_tree_index(0x05060708);
let c = a.as_bytes_compressed();
assert_eq!(c.len(), 22);
assert_eq!(c[0], 0x11); assert_eq!(&c[1..9], &0x2233_4455_6677_8899u64.to_be_bytes()); assert_eq!(c[9], 0x06); assert_eq!(&c[10..14], &0xaabb_ccddu32.to_be_bytes()); assert_eq!(&c[14..18], &0x0102_0304u32.to_be_bytes()); assert_eq!(&c[18..22], &0x0506_0708u32.to_be_bytes()); }
}