almost loop

This commit is contained in:
eschorn1 2024-01-21 18:15:52 -06:00
parent 6e9edb1ca5
commit b5a6545bb0
5 changed files with 167 additions and 30 deletions

View file

@ -13,6 +13,7 @@ zeroize = { version = "1.7.0", features = ["zeroize_derive"] }
rand_core = { version = "0.6.4", default-features = false }
sha3 = { version = "0.10.8", default-features = false }
generic-array = { version = "1.0.0", features=["const-default", "zeroize"] }
hex = "0.4.3"
[features]
default = ["default-rng", "slh_dsa_sha2_128s", "slh_dsa_shake_128s", "slh_dsa_sha2_128f", "slh_dsa_shake_128f",
@ -31,3 +32,7 @@ slh_dsa_sha2_256s = []
slh_dsa_shake_256s = []
slh_dsa_sha2_256f = []
slh_dsa_shake_256f = []
[dev-dependencies]
rand = "0.8.5"

View file

@ -166,6 +166,7 @@ pub(crate) fn chain<N: ArrayLength>(
// 4:
// 5: tmp ← X
//println!("cap x: {}", hex::encode(&cap_x));
let mut tmp = cap_x;
// 6:
@ -190,8 +191,15 @@ pub(crate) fn chain<N: ArrayLength>(
pub(crate) fn prf<N: ArrayLength>(
pk_seed: &[u8], sk_seed: &[u8], adrs: &[u8],
) -> GenericArray<u8, N> {
shake256(&[&pk_seed, &sk_seed, &adrs])
}
shake256(&[&pk_seed, &adrs, &sk_seed]) // note order
} // NOTE ORDER
#[allow(clippy::similar_names)]
pub(crate) fn prf2<N: ArrayLength>(
a0: &[u8], b1: &[u8], c2: &[u8],
) -> GenericArray<u8, N> {
shake256(&[&a0, &b1, &c2])
} // NOTE ORDER
pub(crate) fn tlen<LEN: ArrayLength, N: ArrayLength>(
@ -224,6 +232,7 @@ pub(crate) fn wots_pkgen<LEN: ArrayLength, N: ArrayLength>(
) -> WotsPk<N> {
let mut adrs = adrs.clone();
let mut tmp: GenericArray<GenericArray<u8, N>, LEN> = GenericArray::default();
//println!("pk_seed: {}", hex::encode(&pk_seed));
// 1: skADRS ← ADRS ▷ Copy address to create key generation key address
let mut sk_adrs = adrs.clone();
@ -244,6 +253,7 @@ pub(crate) fn wots_pkgen<LEN: ArrayLength, N: ArrayLength>(
// 6: sk ← PRF(PK.seed, SK.seed, skADRS) ▷ Compute secret value for chain i
let sk = prf(pk_seed, sk_seed, &sk_adrs.to_bytes());
//println!("sk wots pkgen: {}/n", hex::encode(&sk));
// 7: ADRS.setChainAddress(i)
adrs.set_chain_address(i);
@ -278,11 +288,11 @@ pub(crate) fn wots_pkgen<LEN: ArrayLength, N: ArrayLength>(
/// Input: Message `M`, secret seed `SK.seed`, public seed `PK.seed`, address `ADRS`. <br>
/// Output: WOTS+ signature sig.
#[allow(clippy::similar_names)]
pub(crate) fn wots_sign<N: ArrayLength, LEN: ArrayLength>(
pub(crate) fn wots_sign<LEN: ArrayLength, N: ArrayLength>(
m: &[u8], sk_seed: &[u8], pk_seed: &[u8], adrs: &Adrs,
) -> WotsSig<N, LEN> {
) -> WotsSig<LEN, N> {
let mut adrs = adrs.clone();
let mut sig: WotsSig<N, LEN> = WotsSig::default();
let mut sig: WotsSig<LEN, N> = WotsSig::default();
// 1: csum ← 0
let mut csum = 0u64;
@ -397,7 +407,7 @@ pub(crate) fn wots_pk_from_sig<LEN: ArrayLength, N: ArrayLength>(
adrs.set_chain_address(i as u32);
// 13: tmp[i] ← chain(sig[i], msg[i], w 1 msg[i], PK.seed, ADRS)
tmp[i] = chain(
tmp[i] = chain::<N>(
sig.data[i].clone(),
usize::try_from(msg[i]).unwrap(),
crate::W as usize - 1 - msg[i] as usize,
@ -405,6 +415,7 @@ pub(crate) fn wots_pk_from_sig<LEN: ArrayLength, N: ArrayLength>(
&adrs,
)
.expect("chain broke2!");
println!("wots_pk_from_sig tmp: [{}] {}", i, hex::encode(&tmp[i])); // TODO <<<========== BROKE b4 HERE!!!
// 14: end for
}
@ -469,16 +480,19 @@ pub(crate) fn xmss_node<H: ArrayLength, HP: ArrayLength, LEN: ArrayLength, N: Ar
adrs.set_type_and_clear(WOTS_HASH);
// 6: ADRS.setKeyPairAddress(i)
adrs.set_key_pair_address(i);
adrs.set_key_pair_address(i as u32);
// 7: node ← wots_PKgen(SK.seed, PK.seed, ADRS)
wots_pkgen::<LEN, N>(sk_seed, pk_seed, &adrs).0.clone() // TODO revisit (remove clone?)
let xx = wots_pkgen::<LEN, N>(sk_seed, pk_seed, &adrs).0.clone(); // TODO revisit (remove clone?)
//println!("wots_pkgen: {}", hex::encode(&xx));
xx //wots_pkgen
// 8: else
} else {
//
// 9: lnode ← xmss_node(SK.seed, 2 * i, z 1, PK.seed, ADRS)
let lnode = xmss_node::<H, HP, LEN, N>(sk_seed, 2 * i, z - 1, pk_seed, &adrs)?;
//println!("lnode: {}", hex::encode(&lnode));
// 10: rnode ← xmss_node(SK.seed, 2 * i + 1, z 1, PK.seed, ADRS)
let rnode = xmss_node::<H, HP, LEN, N>(sk_seed, 2 * i + 1, z - 1, pk_seed, &adrs)?;
@ -490,7 +504,7 @@ pub(crate) fn xmss_node<H: ArrayLength, HP: ArrayLength, LEN: ArrayLength, N: Ar
adrs.set_tree_height(z);
// 13: ADRS.setTreeIndex(i)
adrs.set_tree_index(i);
adrs.set_tree_index(i as u32);
// 14: node ← H(PK.seed, ADRS, lnode ∥ rnode)
h(pk_seed, &adrs.to_bytes(), &lnode, &rnode)
@ -532,7 +546,7 @@ pub(crate) fn xmss_sign<H: ArrayLength, HP: ArrayLength, LEN: ArrayLength, N: Ar
adrs.set_type_and_clear(WOTS_HASH);
// 7: ADRS.setKeyPairAddress(idx)
adrs.set_key_pair_address(idx);
adrs.set_key_pair_address(idx as u32);
// 8: sig ← wots_sign(M, SK.seed, PK.seed, ADRS)
sig_xmss.sig_wots = wots_sign(m, sk_seed, pk_seed, &adrs);
@ -560,7 +574,7 @@ pub(crate) fn xmss_pk_from_sig<HP: ArrayLength, LEN: ArrayLength, N: ArrayLength
adrs.set_type_and_clear(WOTS_HASH);
// 2: ADRS.setKeyPairAddress(idx)
adrs.set_chain_address(idx);
adrs.set_key_pair_address(idx);
// 3: sig ← SIG_XMSS.getWOTSSig() ▷ SIG_XMSS [0 : len · n]
let sig = sig_xmss.get_wots_sig();
@ -570,7 +584,10 @@ pub(crate) fn xmss_pk_from_sig<HP: ArrayLength, LEN: ArrayLength, N: ArrayLength
// 5: node[0] ← wots_PKFromSig(sig, M, PK.seed, ADRS)
let mut node_0 = wots_pk_from_sig::<LEN, N>(sig, m, pk_seed, &adrs).0.clone();
println!("verif node_0: {}", hex::encode(&node_0)); // TODO blah...3rd? time here
if node_0[0] == 0x9a {
println!("wogga");
}
// 6:
// 7: ADRS.setTypeAndClear(TREE) ▷ Compute root from WOTS+ pk and AUTH
adrs.set_type_and_clear(TREE);
@ -586,7 +603,7 @@ pub(crate) fn xmss_pk_from_sig<HP: ArrayLength, LEN: ArrayLength, N: ArrayLength
// 11: if idx/2^k is even then
#[allow(clippy::if_not_else)] // Follows the algorithm as written
let node_1 = if (idx >> k) % 2 == 0 {
let node_1 = if ((idx >> k) % 2) == 0 {
// 12: ADRS.setTreeIndex(ADRS.getTreeIndex()/2)
let tmp = adrs.get_tree_index() / 2;
adrs.set_tree_index(tmp);
@ -632,7 +649,7 @@ pub(crate) fn ht_sign<
LEN: ArrayLength,
N: ArrayLength,
>(
m: &[u8], sk_seed: &[u8], pk_seed: &[u8], idx_tree: u32, idx_leaf: u32,
m: &[u8], sk_seed: &[u8], pk_seed: &[u8], idx_tree: u64, idx_leaf: u32,
) -> Result<HtSig<D, HP, LEN, N>, &'static str> {
//
// 1: ADRS ← toByte(0, 32)
@ -656,7 +673,7 @@ pub(crate) fn ht_sign<
for j in 1..D::to_u32() {
//
// 8: idx_leaf ← idx_tree mod 2^{h} ▷ h least significant bits of idx_tree
let idx_leaf = idx_tree % 2u32.pow(HP::to_u32());
let idx_leaf = idx_tree % 2u64.pow(HP::to_u32());
// 9: idx_tree ← idx_tree ≫ h ▷ Remove least significant h bits from idx_tree
let idx_tree = idx_tree >> HP::to_u32();
@ -668,7 +685,7 @@ pub(crate) fn ht_sign<
adrs.set_tree_address(idx_tree);
// 12: SIG_tmp ← xmss_sign(root, SK.seed, idx_leaf, PK.seed, ADRS)
sig_tmp = xmss_sign::<H, HP, LEN, N>(&root, sk_seed, idx_leaf, pk_seed, &adrs)?;
sig_tmp = xmss_sign::<H, HP, LEN, N>(&root, sk_seed, idx_leaf as u32, pk_seed, &adrs)?;
// 13: SIG_HT ← SIG_HT ∥ SIG_tmp
sig_ht.xmss_sigs[j as usize] = sig_tmp.clone();
@ -677,7 +694,7 @@ pub(crate) fn ht_sign<
if j < (D::to_u32() - 1) {
//
// 15: root ← xmss_PKFromSig(idx_leaf, SIG_tmp, root, PK.seed, ADRS)
root = xmss_pk_from_sig::<HP, LEN, N>(idx_leaf, &sig_tmp, &root, pk_seed, &adrs);
root = xmss_pk_from_sig::<HP, LEN, N>(idx_leaf as u32, &sig_tmp, &root, pk_seed, &adrs);
// 16: end if
}
@ -696,7 +713,7 @@ pub(crate) fn ht_sign<
/// HT public key `PK.root`. <br>
/// Output: Boolean.
pub(crate) fn ht_verify<D: ArrayLength, HP: ArrayLength, LEN: ArrayLength, N: ArrayLength>(
m: &[u8], sig_ht: &HtSig<D, HP, LEN, N>, pk_seed: &[u8], idx_tree: u32, idx_leaf: u32,
m: &[u8], sig_ht: &HtSig<D, HP, LEN, N>, pk_seed: &[u8], idx_tree: u64, idx_leaf: u32,
pk_root: &GenericArray<u8, N>,
) -> bool {
//
@ -712,12 +729,13 @@ pub(crate) fn ht_verify<D: ArrayLength, HP: ArrayLength, LEN: ArrayLength, N: Ar
// 5: node ← xmss_PKFromSig(idx_leaf, SIG_tmp, M, PK.seed, ADRS)
let mut node = xmss_pk_from_sig(idx_leaf, &sig_tmp, m, pk_seed, &adrs);
println!("verif node: {}", hex::encode(&node));
// 6: for j from 1 to d 1 do
for j in 1..D::to_u32() {
//
// 7: idx_leaf ← idx_tree mod 2^{h} ▷ h least significant bits of idx_tree
let idx_leaf = idx_tree % 2u32.pow(HP::to_u32());
let idx_leaf = idx_tree % 2u64.pow(HP::to_u32());
// 8: idx_tree ← idx_tree ≫ h ▷ Remove least significant h bits from idx_tree
let idx_tree = idx_tree >> HP::to_u32();
@ -732,7 +750,7 @@ pub(crate) fn ht_verify<D: ArrayLength, HP: ArrayLength, LEN: ArrayLength, N: Ar
let sig_tmp = sig_ht.xmss_sigs[j as usize].clone();
// 12: node ← xmss_PKFromSig(idx_leaf, SIG_tmp, node, PK.seed, ADRS)
node = xmss_pk_from_sig(idx_leaf, &sig_tmp, &node, pk_seed, &adrs);
node = xmss_pk_from_sig(idx_leaf as u32, &sig_tmp, &node, pk_seed, &adrs);
// 13: end for
}
@ -930,7 +948,7 @@ pub(crate) fn fors_pk_from_sig<A: ArrayLength, K: ArrayLength, N: ArrayLength>(
adrs.set_tree_height(j + 1);
// 11: if indices[i]/2^j is even then
let node_1 = if indices[i as usize] >> j % 2 == 0 {
let node_1 = if ((indices[i as usize] >> j) % 2) == 0 {
//
// 12: ADRS.setTreeIndex(ADRS.getTreeIndex()/2)
let tmp = adrs.get_tree_index() / 2;
@ -1000,6 +1018,7 @@ pub(crate) fn slh_keygen_with_rng<
let mut sk_seed = GenericArray::default();
rng.try_fill_bytes(&mut sk_seed)
.map_err(|_| "Alg17: rng failed1")?;
println!("sk:seed: {}", hex::encode(&sk_seed));
// 2: SK.prf ←$ B^n ▷ strings using an approved random bit generator
let mut sk_prf = GenericArray::default();
@ -1020,6 +1039,7 @@ pub(crate) fn slh_keygen_with_rng<
// 7: PK.root ← xmss_node(SK.seed, 0, h, PK.seed, ADRS)
let pk_root = xmss_node::<H, HP, LEN, N>(&sk_seed, 0, HP::to_u32(), &pk_seed, &adrs)?;
println!("pk_root: {}", hex::encode(&pk_root));
// 8:
// 9: return ( (SK.seed, SK.prf, PK.seed, PK.root), (PK.seed, PK.root) )
@ -1062,18 +1082,22 @@ pub(crate) fn slh_sign_with_rng<
// 6: end if
}
println!("opt_rand: {}", hex::encode(&opt_rand.clone()));
// 7: R ← PRF_msg(SK.prf, opt_rand, M) ▷ Generate randomizer
let r = prf(&sk.sk_prf, &opt_rand, m);
let r = prf2(&sk.sk_prf, &opt_rand, m);
// 8: SIG ← R
let mut sig = SlhDsaSig::default();
sig.randomness = r.clone();
println!("r: {}", hex::encode(&r.clone()));
// 9:
// 10: digest ← H_msg(R, PK.seed, PK.root, M) ▷ Compute message digest
let digest = h::<M>(&r, &sk.pk_seed, &sk.pk_root, m);
println!("DIGEST: {}", hex::encode(&digest));
// 11: md ← digest[0 : ceil(k·a/8)] ▷ first ceil(k·a/8) bytes
let index1 = (K::to_usize() * A::to_usize()).div_ceil(8);
@ -1099,7 +1123,7 @@ pub(crate) fn slh_sign_with_rng<
// 17:
// 18: ADRS.setTreeAddress(idx_tree)
adrs.set_tree_address(idx_tree as u32); //TODO not u32
adrs.set_tree_address(idx_tree);
// 19: ADRS.setTypeAndClear(FORS_TREE)
adrs.set_type_and_clear(FORS_TREE);
@ -1107,14 +1131,21 @@ pub(crate) fn slh_sign_with_rng<
// 20: ADRS.setKeyPairAddress(idxleaf)
adrs.set_key_pair_address(idx_leaf as u32);
println!("adrs a: {}", hex::encode(&adrs.to_bytes()));
// 21: SIG_FORS ← fors_sign(md, SK.seed, PK.seed, ADRS)
// 22: SIG ← SIG ∥ SIG_FORS
sig.fors_sig = fors_sign(md, &sk.sk_seed, &adrs, &sk.pk_seed)?; // TODO: adrs swapped position?
println!("FORS {}", hex::encode(&sig.fors_sig.private_key_value[0]));
// 23:
// 24: PK_FORS ← fors_pkFromSig(SIG_FORS , md, PK.seed, ADRS) ▷ Get FORS key
let pk_fors = fors_pk_from_sig::<A, K, N>(&sig.fors_sig, md, &sk.pk_seed, &adrs);
println!("PK_FORS {}", hex::encode(&pk_fors.key));
// 25:
// 26: SIG_HT ← ht_sign(PK_FORS , SK.seed, PK.seed, idx_tree, idx_leaf)
// 27: SIG ← SIG ∥ SIG_HT
@ -1122,7 +1153,7 @@ pub(crate) fn slh_sign_with_rng<
&pk_fors.key,
&sk.sk_seed,
&sk.pk_seed,
idx_tree as u32,
idx_tree,
idx_leaf as u32,
)?;
// 28: return SIG
@ -1168,6 +1199,7 @@ pub(crate) fn slh_verify<
// 8:
// 9: digest ← Hmsg(R, PK.seed, PK.root, M) ▷ Compute message digest
let digest = h::<M>(r, &pk.pk_seed, &pk.pk_root, m);
println!("verify digest {}", hex::encode(&digest)); // good
// 10: md ← digest[0 : ceil(k·a/8)] ▷ first ceil(k·a/8) bytes
let index1 = (K::to_usize() * A::to_usize()).div_ceil(8);
@ -1183,7 +1215,7 @@ pub(crate) fn slh_verify<
// 13:
// 14: idx_tree ← toInt(tmp_idx_tree, ceil((h - h/d)/8)) mod 2^{hh/d}
let idx_tree = to_int(tmp_idx_tree, H::to_usize() - H::to_usize() / D::to_usize()).div_ceil(8)
let idx_tree = to_int(tmp_idx_tree, (H::to_usize() - H::to_usize() / D::to_usize()).div_ceil(8))
% 2u64.pow(H::to_u32() - H::to_u32() / D::to_u32());
// 15: idx_leaf ← toInt(tmp_idx_leaf, ceil(h/8d) mod 2^{h/d}
@ -1195,7 +1227,7 @@ pub(crate) fn slh_verify<
// 16:
// 17: ADRS.setTreeAddress(idx_tree) ▷ Compute FORS public key
adrs.set_tree_address(idx_tree as u32);
adrs.set_tree_address(idx_tree);
// 18: ADRS.setTypeAndClear(FORS_TREE)
adrs.set_type_and_clear(FORS_TREE);
@ -1206,6 +1238,9 @@ pub(crate) fn slh_verify<
// 20:
// 21: PK_FORS ← fors_pkFromSig(SIG_FORS, md, PK.seed, ADRS)
let pk_fors = fors_pk_from_sig::<A, K, N>(sig_fors, md, &pk.pk_seed, &adrs);
println!("verify pk_forst {}", hex::encode(&pk_fors.key));
// 22:
// 23: return ht_verify(PK_FORS, SIG_HT, PK.seed, idx_tree , idx_leaf, PK.root)
@ -1213,7 +1248,7 @@ pub(crate) fn slh_verify<
&pk_fors.key,
sig_ht,
&pk.pk_seed,
idx_tree as u32,
idx_tree,
idx_leaf as u32,
&pk.pk_root,
)

View file

@ -11,9 +11,11 @@
//! TKTK crate doc
extern crate alloc; // TODO: remove (with vecs)
extern crate alloc;
extern crate core; // TODO: remove (with vecs)
mod algs;
mod test;
mod traits;
mod types;
@ -24,6 +26,32 @@ const W: u32 = 16;
macro_rules! functionality {
() => {
use rand_core::CryptoRngCore;
use crate::types::{SlhPrivateKey, SlhPublicKey, SlhDsaSig};
use generic_array::typenum::{Prod, Sum, U2, U3};
/// blah
pub fn slh_keygen_with_rng(
rng: &mut impl CryptoRngCore,
) -> Result<(SlhPrivateKey<N>, SlhPublicKey<N>), &'static str> {
crate::algs::slh_keygen_with_rng::<D, H, HP, Sum<Prod<U2, N>, U3>, N>(rng)
}
/// blah
pub fn slh_sign_with_rng(
rng: &mut impl CryptoRngCore, m: &[u8], sk: &SlhPrivateKey<N>, randomize: bool,
) -> Result<SlhDsaSig<A, D, HP, K, Sum<Prod<U2, N>, U3>, N>, &'static str> {
crate::algs::slh_sign_with_rng::<A, D, H, HP, K, Sum<Prod<U2, N>, U3>, M, N>(
rng, &m, &sk, randomize)
}
/// blah
pub fn slh_verify(
m: &[u8], sig: &SlhDsaSig<A, D, HP, K, Sum<Prod<U2, N>, U3>, N>, pk: &SlhPublicKey<N>,
) -> bool {
crate::algs::slh_verify::<A, D, H, HP, K, Sum<Prod<U2, N>, U3>, M, N>(&m, &sig, &pk)
}
#[cfg(test)]
mod tests {
use super::*;
@ -31,6 +59,7 @@ macro_rules! functionality {
use generic_array::typenum::{Prod, Sum, U2, U3};
use rand_core::OsRng;
#[ignore]
#[test]
fn it_works1111() {
let m = [0u8, 1, 2, 3];

68
src/test.rs Normal file
View file

@ -0,0 +1,68 @@
#[cfg(test)]
mod tests {
extern crate alloc;
use hex::decode;
use alloc::vec::Vec;
//use rand::{Rng, SeedableRng};
use rand_core::{CryptoRng, RngCore};
struct TestRng {
data: Vec<Vec<u8>>,
}
impl RngCore for TestRng {
fn next_u32(&mut self) -> u32 { unimplemented!() }
fn next_u64(&mut self) -> u64 { unimplemented!() }
fn fill_bytes(&mut self, out: &mut [u8]) {
let x = self.data.pop().expect("TestRng problem");
out.copy_from_slice(&x)
}
fn try_fill_bytes(&mut self, out: &mut [u8]) -> Result<(), rand_core::Error> {
self.fill_bytes(out);
Ok(()) // panic on probs is OK
}
}
impl CryptoRng for TestRng {}
impl TestRng {
fn new() -> Self { TestRng { data: Vec::new() } }
fn push(&mut self, new_data: &[u8]) {
let x = new_data.to_vec();
self.data.push(x);
}
}
use crate::slh_dsa_sha2_128s::{slh_keygen_with_rng, slh_sign_with_rng, slh_verify};
#[test]
fn vector_debug() {
let m = decode("d81c4d8d734fcbfbeade3d3f8a039faa2a2c9957e835ad55b22e75bf57bb556ac8").unwrap();
let mut rnd = TestRng::new();
let sk_seed = "7c9935a0b07694aa0c6d10e4db6b1add";
let sk_prf = "2fd81a25ccb148032dcd739936737f2d";
let pk_seed = "b505d7cfad1b497499323c8686325e47";
let opt_rand = "33b3c07507e4201748494d832b6ee2a6";
rnd.push(&decode(opt_rand).unwrap());
rnd.push(&decode(pk_seed).unwrap());
rnd.push(&decode(sk_prf).unwrap());
rnd.push(&decode(sk_seed).unwrap());
let (sk, pk) = slh_keygen_with_rng (&mut rnd).unwrap();
assert_eq!(*decode("ac524902fc81f5032bc27b17d9261ebd").unwrap(), *sk.pk_root, "pk_root failed!!!!!!");
let sig = slh_sign_with_rng(&mut rnd, &m, &sk, true).unwrap();
assert_eq!(*decode("43f8eb75d58b652f779c5a0f5378709e").unwrap(), *sig.fors_sig.private_key_value[0], "fors_sig failed!!!");
assert_eq!(*decode("ad62955228fdf4c3be9c22f601397a11").unwrap(), *sig.ht_sig.xmss_sigs[0].sig_wots.data[0], "fors_sig failed!!!");
let result = slh_verify(&m, &sig, &pk);
assert_eq!(result, true, "Signature did not verify!");
}
}

View file

@ -114,7 +114,7 @@ impl Adrs {
self.f7 = 0u32.to_be_bytes();
}
pub(crate) fn set_tree_address(&mut self, t: u32) { self.f1 = t.to_be_bytes() }
pub(crate) fn set_tree_address(&mut self, t: u64) { self.f2 = ((t >> 32) as u32).to_be_bytes(); self.f3 = (t as u32).to_be_bytes() }
// TODO: revisit 16 bytes
@ -126,5 +126,5 @@ impl Adrs {
pub(crate) fn set_tree_index(&mut self, i: u32) { self.f7 = i.to_be_bytes() }
pub(crate) fn to_bytes(&self) -> Vec<u8> { [self.f0, self.f1, self.f2, self.f3].concat() }
pub(crate) fn to_bytes(&self) -> Vec<u8> { [self.f0, self.f1, self.f2, self.f3, self.f4, self.f5, self.f6, self.f7].concat() }
}