Преглед изворни кода

* `Cryptotext` was identified as being harmful,
and was replaced by `Ciphertext`.
* Improvements to the creation of test data in `test_helpers`.

Matthew Carr пре 2 година
родитељ
комит
84b516d6d4

+ 1 - 0
Cargo.lock

@@ -134,6 +134,7 @@ dependencies = [
  "env_logger",
  "foreign-types",
  "harness",
+ "lazy_static",
  "log",
  "nix",
  "openssl",

+ 1 - 0
crates/btlib/Cargo.toml

@@ -28,3 +28,4 @@ tempdir = "0.3.7"
 ctor = "0.1.22"
 nix = "0.25.0"
 env_logger = "0.9.0"
+lazy_static = "1.4.0"

+ 76 - 69
crates/btlib/src/crypto/mod.rs

@@ -8,6 +8,7 @@ use super::{
     Path, Principal, Read, Sectored, Seek, Serialize, TryCompose, Write, Writecap,
 };
 
+use btserde::{self, from_vec, to_vec, write_to};
 use foreign_types::ForeignType;
 use openssl::{
     encrypt::{Decrypter as OsslDecrypter, Encrypter as OsslEncrypter},
@@ -23,7 +24,6 @@ use serde::{
     de::{self, DeserializeOwned, Deserializer, SeqAccess, Visitor},
     ser::{SerializeStruct, Serializer},
 };
-use btserde::{self, from_vec, to_vec, write_to};
 use std::{
     convert::Infallible,
     io::{ErrorKind, SeekFrom},
@@ -34,13 +34,19 @@ use std::{
 use strum_macros::{Display, EnumDiscriminants, EnumString};
 use zeroize::ZeroizeOnDrop;
 
-/// Data that may or may not be encrypted.
 #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
-pub(crate) enum Cryptotext<T: Serialize> {
-    /// The inner value of `T` is plaintext.
-    Plain(T),
-    /// The inner value is ciphertext.
-    Cipher(Vec<u8>),
+pub struct Ciphertext<T> {
+    data: Vec<u8>,
+    phantom: PhantomData<T>,
+}
+
+impl<T> Ciphertext<T> {
+    pub fn new(data: Vec<u8>) -> Ciphertext<T> {
+        Ciphertext {
+            data,
+            phantom: PhantomData,
+        }
+    }
 }
 
 /// Errors that can occur during cryptographic operations.
@@ -320,9 +326,9 @@ impl AsMut<[u8]> for Signature {
 }
 
 #[derive(Serialize, Deserialize)]
-struct TaggedCiphertext<T: Serialize, U: Serialize> {
+struct TaggedCiphertext<T, U> {
     aad: U,
-    ciphertext: Cryptotext<T>,
+    ciphertext: Ciphertext<T>,
     tag: Vec<u8>,
 }
 
@@ -408,7 +414,7 @@ impl AeadKey {
 
         Ok(TaggedCiphertext {
             aad,
-            ciphertext: Cryptotext::Cipher(ciphertext),
+            ciphertext: Ciphertext::new(ciphertext),
             tag,
         })
     }
@@ -417,11 +423,7 @@ impl AeadKey {
         &self,
         tagged: &TaggedCiphertext<T, U>,
     ) -> Result<T> {
-        let ciphertext = match &tagged.ciphertext {
-            Cryptotext::Plain(_) => return Err(Error::custom("already decrypted")),
-            Cryptotext::Cipher(ciphertext) => ciphertext,
-        };
-
+        let ciphertext = &tagged.ciphertext.data;
         let (cipher, key, iv) = match self {
             AeadKey::AesGcm256 { key, iv } => {
                 (Cipher::aes_256_gcm(), key.as_slice(), iv.as_slice())
@@ -502,6 +504,16 @@ impl SymKey {
         let SymParams { cipher, key, iv } = self.params();
         Ok(Crypter::new(cipher, Mode::Decrypt, key, iv)?)
     }
+
+    fn key_slice(&self) -> &[u8] {
+        let SymParams { key, .. } = self.params();
+        key
+    }
+
+    fn iv_slice(&self) -> Option<&[u8]> {
+        let SymParams { iv, .. } = self.params();
+        iv
+    }
 }
 
 impl Encrypter for SymKey {
@@ -794,6 +806,7 @@ impl KeyPrivacy for Public {}
 
 unsafe impl HasPublic for Public {}
 
+#[derive(Debug, Clone)]
 /// Represents keys which must be kept confidential.
 pub enum Private {}
 
@@ -978,6 +991,7 @@ impl Verifier for AsymKey<Public, Sign> {
     }
 }
 
+#[derive(Clone)]
 pub struct AsymKeyPair<S: Scheme> {
     public: AsymKey<Public, S>,
     private: AsymKey<Private, S>,
@@ -1021,6 +1035,7 @@ impl Verifier for AsymKeyPair<Sign> {
     }
 }
 
+#[derive(Clone)]
 pub struct ConcreteCreds {
     sign: AsymKeyPair<Sign>,
     encrypt: AsymKeyPair<Encrypt>,
@@ -1797,61 +1812,60 @@ impl<T: Seek> Seek for SecretStream<T> {
     }
 }
 
-pub(crate) fn unveil<T: Read + Write + Seek, C: Encrypter + Decrypter>(
-    mut block: Block<T>,
+pub(crate) fn unveil<T: Read + Write + Seek, C: Encrypter + Decrypter, D>(
+    block: Block<T, D>,
     principal: &Principal,
     creds: &C,
-) -> Result<Block<impl Read + Write + Seek>> {
-    let (principal_owned, read_cap) = block
-        .header
-        .readcaps
-        .remove_entry(principal)
-        .ok_or(Error::NoReadCap)?;
-    let block_key = decrypt(read_cap, creds)?;
-    let mut block = block
+) -> Result<Block<impl Read + Write + Seek, D>> {
+    let readcap = {
+        let shared = block.shared.read()?;
+        let readcap_ct = shared
+            .header
+            .readcaps
+            .get(principal)
+            .ok_or(Error::NoReadCap)?;
+        decrypt(readcap_ct, creds)?
+    };
+    let block = block
+        // TODO: The merkle tree needs to be supplied in some other way.
         .compose_body(MerkleStream::new(MerkleTree::<Sha2_256>::empty(
             SECTOR_SZ_DEFAULT,
         )))
-        .try_compose_body(SecretStream::new(block_key.clone()))?
+        .try_compose_body(SecretStream::new(readcap))?
         .try_compose_body(SectoredBuf::new())?;
-    block
-        .header
-        .readcaps
-        .insert(principal_owned, encrypt(&block_key, creds)?);
     Ok(block)
 }
 
-fn encrypt<T: Serialize, K: Encrypter>(value: &T, key: &K) -> Result<Cryptotext<T>> {
+pub(crate) fn encrypt<T: Serialize, K: Encrypter>(value: &T, key: &K) -> Result<Ciphertext<T>> {
     let data = to_vec(value)?;
-    let vec = key.encrypt(&data);
-    Ok(Cryptotext::Cipher(vec?))
+    let data = key.encrypt(&data)?;
+    Ok(Ciphertext::new(data))
 }
 
-fn decrypt<T: Serialize + DeserializeOwned, K: Decrypter>(
-    cryptotext: Cryptotext<T>,
+pub(crate) fn decrypt<T: Serialize + DeserializeOwned, K: Decrypter>(
+    ciphertext: &Ciphertext<T>,
     key: &K,
 ) -> Result<T> {
-    let data = match cryptotext {
-        Cryptotext::Plain(value) => return Ok(value),
-        Cryptotext::Cipher(data) => data,
-    };
-    let vec = key.decrypt(&data);
-    Ok(from_vec(&vec?)?)
+    let Ciphertext { data, .. } = ciphertext;
+    let plaintext = key.decrypt(data)?;
+    Ok(from_vec(&plaintext)?)
 }
 
-pub(crate) fn sign_block<T, K: Signer>(block: &mut Block<T>, priv_key: &K) -> Result<()> {
-    let header = to_vec(&block.header)?;
+pub(crate) fn sign_block<T, K: Signer, C>(block: &Block<T, C>, priv_key: &K) -> Result<()> {
+    let mut shared = block.shared.write()?;
+    let header = to_vec(&shared.header)?;
     let signature = priv_key.sign(std::iter::once(header.as_slice()))?;
-    block.sig = signature;
+    shared.sig = signature;
     Ok(())
 }
 
-pub(crate) fn verify_block<T>(block: &Block<T>) -> Result<()> {
-    verify_writecap(&block.header.writecap, &block.header.path)?;
-    let header_data = to_vec(&block.header)?;
-    block.header.writecap.signing_key.verify(
+pub(crate) fn verify_block<T, C>(block: &Block<T, C>) -> Result<()> {
+    let shared = block.shared.read()?;
+    verify_writecap(&shared.header.writecap, &shared.header.path)?;
+    let header_data = to_vec(&shared.header)?;
+    shared.header.writecap.signing_key.verify(
         std::iter::once(header_data.as_slice()),
-        block.sig.as_slice(),
+        shared.sig.as_slice(),
     )
 }
 
@@ -1956,8 +1970,8 @@ mod tests {
         time::Duration,
     };
 
-    fn encrypt_decrypt_block_test_case<T: Read + Write + Seek, C: Creds>(
-        mut block: Block<T>,
+    fn encrypt_decrypt_block_test_case<T: Read + Write + Seek, C: Creds, D>(
+        mut block: Block<T, D>,
         principal: &Principal,
         creds: &C,
     ) {
@@ -1987,10 +2001,10 @@ mod tests {
 
     #[test]
     fn encrypt_decrypt_block() {
-        let readcap = make_readcap();
+        let key = make_key_pair();
+        let readcap = make_readcap_for(&key);
         let principal = readcap.issued_to.clone();
         let block = make_block_with(readcap);
-        let key = make_key_pair();
         encrypt_decrypt_block_test_case(block, &principal, &key)
     }
 
@@ -2088,11 +2102,10 @@ mod tests {
         let (mut root_writecap, root_key) = make_self_signed_writecap();
         root_writecap.issued_to = Principal(Hash::Sha2_256([0; 32]));
         sign_writecap(&mut root_writecap, &root_key)?;
-        let node_key = AsymKeyPub::new(Sign::RSA_PSS_3072_SHA_256, NODE_PUBLIC_KEY.as_slice())?;
-        let node_principal = node_key.owner();
+        let node_principal = NODE_CREDS.owner();
         let writecap = make_writecap_trusted_by(
             root_writecap,
-            root_key,
+            &root_key,
             node_principal,
             vec!["apps", "contacts"],
         );
@@ -2106,11 +2119,10 @@ mod tests {
         let owner = Principal(Hash::Sha2_256([0; 32]));
         root_writecap.path = make_path_with_owner(owner, vec![]);
         sign_writecap(&mut root_writecap, &root_key)?;
-        let node_key = AsymKeyPub::new(Sign::RSA_PSS_3072_SHA_256, NODE_PUBLIC_KEY.as_slice())?;
-        let node_owner = node_key.owner();
+        let node_owner = NODE_CREDS.owner();
         let writecap = make_writecap_trusted_by(
             root_writecap,
-            root_key,
+            &root_key,
             node_owner,
             vec!["apps", "contacts"],
         );
@@ -2134,14 +2146,7 @@ mod tests {
         let aad = [0u8; 16];
         let expected = [0u8; 32];
         let mut tagged = key.encrypt(aad, &expected).expect("encrypt failed");
-        {
-            let ct = match &mut tagged.ciphertext {
-                Cryptotext::Cipher(ct) => Some(ct),
-                Cryptotext::Plain(_) => None,
-            }
-            .expect("failed to extract cipher text");
-            ct[0] += 1;
-        }
+        tagged.ciphertext.data[0] += 1;
         let result = key.decrypt(&tagged);
         assert!(result.is_err())
     }
@@ -2530,8 +2535,10 @@ mod tests {
             let expected = b"We attack at the crack of noon!";
             let cipher = Cipher::aes_256_cbc();
 
-            let ciphertext = openssl_encrypt(cipher, &KEY, Some(&IV), expected).unwrap();
-            let actual = openssl_decrypt(cipher, &KEY, Some(&IV), ciphertext.as_slice()).unwrap();
+            let key = BLOCK_KEY.key_slice();
+            let iv = BLOCK_KEY.iv_slice();
+            let ciphertext = openssl_encrypt(cipher, key, iv, expected).unwrap();
+            let actual = openssl_decrypt(cipher, key, iv, ciphertext.as_slice()).unwrap();
 
             assert_eq!(expected, actual.as_slice());
         }

+ 1 - 1
crates/btlib/src/crypto/tpm.rs

@@ -1,5 +1,6 @@
 use super::*;
 
+use btserde::read_from;
 use log::error;
 use openssl::{
     bn::{BigNum, BigNumRef},
@@ -8,7 +9,6 @@ use openssl::{
     pkcs5::pbkdf2_hmac,
 };
 use serde::ser;
-use btserde::read_from;
 use std::{
     ffi::CStr,
     fs::OpenOptions,

+ 38 - 25
crates/btlib/src/lib.rs

@@ -11,10 +11,14 @@ mod serde_tests;
 #[macro_use]
 extern crate static_assertions;
 
+#[cfg(test)]
+#[macro_use]
+extern crate lazy_static;
+
 use brotli::{CompressorWriter, Decompressor};
 use btserde::{self, read_from, write_to};
 mod crypto;
-use crypto::{AsymKeyPub, Cryptotext, Hash, HashKind, Sign, Signature, SymKey};
+use crypto::{AsymKeyPub, Ciphertext, Hash, HashKind, Sign, Signature, SymKey};
 
 use log::error;
 use serde::{Deserialize, Serialize};
@@ -27,6 +31,7 @@ use std::{
     hash::Hash as Hashable,
     io::{self, Read, Seek, SeekFrom, Write},
     ops::{Add, Sub},
+    sync::{Arc, RwLock},
     time::{Duration, SystemTime},
 };
 
@@ -96,9 +101,9 @@ type Result<T> = std::result::Result<T, Error>;
 /// A Block tagged with its version number. When a block of a previous version is received over
 /// the network or read from the filesystem, it is upgraded to the current version before being
 /// processed.
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-enum VersionedBlock<T> {
-    V0(Block<T>),
+#[derive(Debug)]
+enum VersionedBlock<T, C> {
+    V0(Block<T, C>),
 }
 
 const SECTOR_SZ_DEFAULT: usize = 4096;
@@ -121,56 +126,64 @@ trait Sectored {
 #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
 pub struct Header {
     path: Path,
-    readcaps: HashMap<Principal, Cryptotext<SymKey>>,
+    readcaps: HashMap<Principal, Ciphertext<SymKey>>,
     writecap: Writecap,
     merkle_root: Hash,
 }
 
-/// A container which binds together ciphertext along with the metadata needed to identify,
-/// verify and decrypt it.
 #[derive(Debug, PartialEq, Serialize, Deserialize)]
-struct Block<T> {
+struct BlockShared<C> {
     header: Header,
     sig: Signature,
+    creds: C,
+}
+
+struct BlockStream<T, C> {
+    shared: Arc<RwLock<BlockShared<C>>>,
+    inner: T,
+}
+
+/// A container which binds together ciphertext along with the metadata needed to identify,
+/// verify and decrypt it.
+#[derive(Debug)]
+struct Block<T, C> {
+    shared: Arc<RwLock<BlockShared<C>>>,
     body: T,
 }
 
-impl<T> Block<T> {
+impl<T, C> Block<T, C> {
     fn try_compose_body<E: Into<Error>, U: Decompose<T>, V: TryCompose<T, U, Error = E>>(
         self,
         new_body: V,
-    ) -> Result<Block<U>> {
+    ) -> Result<Block<U, C>> {
         Ok(Block {
-            header: self.header,
-            sig: self.sig,
+            shared: self.shared,
             body: new_body.try_compose(self.body).map_err(|err| err.into())?,
         })
     }
 
-    fn compose_body<U: Decompose<T>, V: Compose<T, U>>(self, new_body: V) -> Block<U> {
+    fn compose_body<U: Decompose<T>, V: Compose<T, U>>(self, new_body: V) -> Block<U, C> {
         Block {
-            header: self.header,
-            sig: self.sig,
+            shared: self.shared,
             body: new_body.compose(self.body),
         }
     }
 }
 
-impl Block<File> {
-    fn new<P: AsRef<std::path::Path>>(path: P) -> Result<Block<File>> {
+impl<C> Block<File, C> {
+    fn new<P: AsRef<std::path::Path>>(creds: C, path: P) -> Result<Block<File, C>> {
         let mut file = OpenOptions::new().read(true).write(true).open(path)?;
         let header: Header = read_from(&mut file)?;
         let sig: Signature = read_from(&mut file)?;
         crypto::verify_header(&header, &sig)?;
         Ok(Block {
-            header,
-            sig,
+            shared: Arc::new(RwLock::new(BlockShared { header, sig, creds })),
             body: file,
         })
     }
 }
 
-impl<T: Write> Write for Block<T> {
+impl<T: Write, C> Write for Block<T, C> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.body.write(buf)
     }
@@ -180,13 +193,13 @@ impl<T: Write> Write for Block<T> {
     }
 }
 
-impl<T: Read> Read for Block<T> {
+impl<T: Read, C> Read for Block<T, C> {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         self.body.read(buf)
     }
 }
 
-impl<T: Seek> Seek for Block<T> {
+impl<T: Seek, C> Seek for Block<T, C> {
     fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
         self.body.seek(pos)
     }
@@ -592,16 +605,16 @@ impl<T: Seek + Read + Write> Seek for SectoredBuf<T> {
 }
 
 /// An envelopment of a key, which is tagged with the principal who the key is meant for.
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
 struct Readcap {
     /// The principal this `Readcap` was issued to.
     issued_to: Principal,
     /// An encipherment of a block key using the public key of the principal.
-    key: Cryptotext<SymKey>,
+    key: Ciphertext<SymKey>,
 }
 
 impl Readcap {
-    fn new(issued_to: Hash, key: Cryptotext<SymKey>) -> Readcap {
+    fn new(issued_to: Hash, key: Ciphertext<SymKey>) -> Readcap {
         Readcap {
             issued_to: Principal(issued_to),
             key,

+ 1 - 9
crates/btlib/src/serde_tests.rs

@@ -1,7 +1,7 @@
 /// Tests which ensure that the main data structures can be round-tripped faithfully.
 use super::*;
-use crypto::Hash;
 use btserde::{from_vec, to_vec, Error, Result};
+use crypto::Hash;
 use test_helpers::*;
 
 #[test]
@@ -57,11 +57,3 @@ fn roundtrip_read_cap() {
     let actual = from_vec(&ser_result).expect("from_vec failed");
     assert_eq!(expected, actual);
 }
-
-#[test]
-fn roundtrip_versioned_block() {
-    let expected = VersionedBlock::V0(make_block());
-    let ser_result = to_vec(&expected).expect("to_vec failed");
-    let actual = from_vec(&ser_result).expect("from_vec failed");
-    assert_eq!(expected, actual);
-}

+ 53 - 344
crates/btlib/src/test_helpers.rs

@@ -1,7 +1,7 @@
 /// Test data and functions to help with testing.
 use super::*;
-use crypto::*;
 use btserde::{Error, Result};
+use crypto::*;
 use std::{
     cell::RefCell,
     fmt::Write as FmtWrite,
@@ -57,318 +57,25 @@ pub const SIGNATURE: [u8; 384] = [
     0x42, 0xD7, 0xFE, 0x7D, 0x10, 0x02, 0xBD, 0x31, 0x21, 0xCD, 0xD1, 0x32, 0x04, 0x22, 0xE2, 0x36,
 ];
 
-pub const KEY: [u8; 32] = [
-    0xB2, 0xB3, 0xDA, 0x5A, 0x1A, 0xF6, 0xB3, 0x78, 0x30, 0xAB, 0x1D, 0x33, 0x33, 0xE7, 0xE3, 0x5B,
-    0xBB, 0xF9, 0xFE, 0xD0, 0xC1, 0xF7, 0x90, 0x34, 0x69, 0xB7, 0xE7, 0xC6, 0x1C, 0x46, 0x85, 0x48,
-];
-
-pub const ROOT_PUBLIC_KEY: [u8; 422] = [
-    0x30, 0x82, 0x01, 0xA2, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01,
-    0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x8F, 0x00, 0x30, 0x82, 0x01, 0x8A, 0x02, 0x82, 0x01, 0x81,
-    0x00, 0xCA, 0x69, 0x8F, 0x00, 0x0E, 0x09, 0xA0, 0x9A, 0x2D, 0xE6, 0xFC, 0xAC, 0x02, 0x46, 0xB7,
-    0x5C, 0xFB, 0xAE, 0x59, 0x9F, 0x3F, 0xAD, 0xE7, 0x72, 0x9C, 0x7D, 0xC5, 0x48, 0x9A, 0x8F, 0x4C,
-    0x33, 0x0B, 0x4E, 0x1A, 0x97, 0x95, 0xBF, 0x59, 0xA9, 0x4F, 0xB7, 0x9A, 0x43, 0x00, 0xD1, 0x80,
-    0x52, 0xC7, 0x2A, 0x5B, 0xA1, 0xE2, 0x7E, 0x58, 0x14, 0xF8, 0x39, 0x5E, 0xD1, 0x31, 0x54, 0xC0,
-    0xBF, 0xF7, 0x46, 0x33, 0x7B, 0xF1, 0x48, 0x85, 0x6E, 0xE0, 0x68, 0xD0, 0xCC, 0x74, 0x0F, 0x7D,
-    0x9B, 0xF5, 0x21, 0xCA, 0xB2, 0xB6, 0x99, 0x64, 0x20, 0x6F, 0xB7, 0x71, 0xA4, 0xBA, 0x89, 0xB9,
-    0xDA, 0x38, 0xC5, 0x2A, 0x7F, 0x44, 0x3F, 0xDA, 0xA5, 0x6A, 0x32, 0x67, 0xBA, 0x56, 0x67, 0x65,
-    0xF4, 0xAB, 0xDF, 0xD3, 0xC8, 0x11, 0xC5, 0xAB, 0x31, 0x61, 0xFB, 0x25, 0xA7, 0x05, 0xBE, 0x2E,
-    0xA9, 0x45, 0x80, 0x85, 0xA7, 0x19, 0xC3, 0xBD, 0x2F, 0x18, 0xD1, 0xD9, 0x08, 0xC0, 0xBE, 0xA5,
-    0xCD, 0x8F, 0xF9, 0x36, 0x71, 0x38, 0x70, 0xD7, 0xF2, 0x10, 0x64, 0xFE, 0x9A, 0xB6, 0x98, 0xCB,
-    0xB0, 0x16, 0x1C, 0xFE, 0x45, 0x26, 0x71, 0x5E, 0x7C, 0x99, 0x0C, 0xDD, 0xB2, 0x80, 0xE4, 0xE5,
-    0xA6, 0x46, 0x40, 0x73, 0xDA, 0xB0, 0xF9, 0xB6, 0xFD, 0x5D, 0xD6, 0x03, 0x25, 0x1B, 0x0F, 0xD6,
-    0x03, 0x3F, 0x5D, 0xDA, 0xDE, 0xA3, 0x23, 0xC1, 0x93, 0x71, 0x92, 0x92, 0xAE, 0xB3, 0x68, 0x25,
-    0x83, 0x7B, 0x3F, 0x1D, 0xFD, 0x05, 0xDB, 0xA3, 0xDB, 0xB6, 0x57, 0xD8, 0x3E, 0x03, 0x83, 0xD3,
-    0x0B, 0x0F, 0xE3, 0xEF, 0x3A, 0xBE, 0x6F, 0x92, 0x9B, 0x99, 0x1E, 0xA7, 0xB7, 0x82, 0xD4, 0x38,
-    0x4B, 0x09, 0xF3, 0xD3, 0xF5, 0x77, 0x82, 0x6A, 0x19, 0xBD, 0x79, 0x8A, 0x96, 0x66, 0x58, 0xE9,
-    0xBF, 0x65, 0x15, 0xB9, 0x01, 0xFD, 0x34, 0xC4, 0x42, 0x8F, 0x3A, 0x90, 0xCF, 0x6C, 0xA2, 0xC3,
-    0xD7, 0xBB, 0xD5, 0x0C, 0x67, 0x10, 0xDA, 0x1C, 0xAC, 0x30, 0xDA, 0x50, 0xBD, 0x5D, 0x85, 0x4A,
-    0x47, 0xAC, 0xB1, 0xB2, 0x27, 0xE8, 0xC9, 0x75, 0x1C, 0x3B, 0x93, 0xD4, 0x93, 0x5A, 0x51, 0x82,
-    0xF2, 0x66, 0x96, 0x5F, 0x24, 0xB0, 0x30, 0x45, 0x5B, 0x9D, 0xD1, 0xE4, 0x66, 0xDF, 0xA6, 0xED,
-    0x59, 0x1F, 0x58, 0x52, 0x05, 0x8B, 0x45, 0xD1, 0x9A, 0x3D, 0x08, 0x2E, 0x95, 0x1B, 0x08, 0x22,
-    0x0D, 0xAA, 0x49, 0xFB, 0x85, 0x01, 0xBF, 0x83, 0x62, 0xFE, 0x21, 0x45, 0xFE, 0x73, 0x06, 0x85,
-    0x20, 0x06, 0x77, 0x3D, 0x9B, 0x05, 0x0C, 0x2B, 0xB5, 0x89, 0x5A, 0x99, 0x4B, 0xAE, 0x4A, 0xDD,
-    0x93, 0x2F, 0xF9, 0x1D, 0xE4, 0x6C, 0xB3, 0xF7, 0x0C, 0x42, 0x00, 0x02, 0x3E, 0x2D, 0x78, 0x01,
-    0xA9, 0x02, 0x03, 0x01, 0x00, 0x01,
-];
-
-pub const ROOT_PRIVATE_KEY: [u8; 1769] = [
-    0x30, 0x82, 0x06, 0xE5, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x81, 0x00, 0xCA, 0x69, 0x8F, 0x00,
-    0x0E, 0x09, 0xA0, 0x9A, 0x2D, 0xE6, 0xFC, 0xAC, 0x02, 0x46, 0xB7, 0x5C, 0xFB, 0xAE, 0x59, 0x9F,
-    0x3F, 0xAD, 0xE7, 0x72, 0x9C, 0x7D, 0xC5, 0x48, 0x9A, 0x8F, 0x4C, 0x33, 0x0B, 0x4E, 0x1A, 0x97,
-    0x95, 0xBF, 0x59, 0xA9, 0x4F, 0xB7, 0x9A, 0x43, 0x00, 0xD1, 0x80, 0x52, 0xC7, 0x2A, 0x5B, 0xA1,
-    0xE2, 0x7E, 0x58, 0x14, 0xF8, 0x39, 0x5E, 0xD1, 0x31, 0x54, 0xC0, 0xBF, 0xF7, 0x46, 0x33, 0x7B,
-    0xF1, 0x48, 0x85, 0x6E, 0xE0, 0x68, 0xD0, 0xCC, 0x74, 0x0F, 0x7D, 0x9B, 0xF5, 0x21, 0xCA, 0xB2,
-    0xB6, 0x99, 0x64, 0x20, 0x6F, 0xB7, 0x71, 0xA4, 0xBA, 0x89, 0xB9, 0xDA, 0x38, 0xC5, 0x2A, 0x7F,
-    0x44, 0x3F, 0xDA, 0xA5, 0x6A, 0x32, 0x67, 0xBA, 0x56, 0x67, 0x65, 0xF4, 0xAB, 0xDF, 0xD3, 0xC8,
-    0x11, 0xC5, 0xAB, 0x31, 0x61, 0xFB, 0x25, 0xA7, 0x05, 0xBE, 0x2E, 0xA9, 0x45, 0x80, 0x85, 0xA7,
-    0x19, 0xC3, 0xBD, 0x2F, 0x18, 0xD1, 0xD9, 0x08, 0xC0, 0xBE, 0xA5, 0xCD, 0x8F, 0xF9, 0x36, 0x71,
-    0x38, 0x70, 0xD7, 0xF2, 0x10, 0x64, 0xFE, 0x9A, 0xB6, 0x98, 0xCB, 0xB0, 0x16, 0x1C, 0xFE, 0x45,
-    0x26, 0x71, 0x5E, 0x7C, 0x99, 0x0C, 0xDD, 0xB2, 0x80, 0xE4, 0xE5, 0xA6, 0x46, 0x40, 0x73, 0xDA,
-    0xB0, 0xF9, 0xB6, 0xFD, 0x5D, 0xD6, 0x03, 0x25, 0x1B, 0x0F, 0xD6, 0x03, 0x3F, 0x5D, 0xDA, 0xDE,
-    0xA3, 0x23, 0xC1, 0x93, 0x71, 0x92, 0x92, 0xAE, 0xB3, 0x68, 0x25, 0x83, 0x7B, 0x3F, 0x1D, 0xFD,
-    0x05, 0xDB, 0xA3, 0xDB, 0xB6, 0x57, 0xD8, 0x3E, 0x03, 0x83, 0xD3, 0x0B, 0x0F, 0xE3, 0xEF, 0x3A,
-    0xBE, 0x6F, 0x92, 0x9B, 0x99, 0x1E, 0xA7, 0xB7, 0x82, 0xD4, 0x38, 0x4B, 0x09, 0xF3, 0xD3, 0xF5,
-    0x77, 0x82, 0x6A, 0x19, 0xBD, 0x79, 0x8A, 0x96, 0x66, 0x58, 0xE9, 0xBF, 0x65, 0x15, 0xB9, 0x01,
-    0xFD, 0x34, 0xC4, 0x42, 0x8F, 0x3A, 0x90, 0xCF, 0x6C, 0xA2, 0xC3, 0xD7, 0xBB, 0xD5, 0x0C, 0x67,
-    0x10, 0xDA, 0x1C, 0xAC, 0x30, 0xDA, 0x50, 0xBD, 0x5D, 0x85, 0x4A, 0x47, 0xAC, 0xB1, 0xB2, 0x27,
-    0xE8, 0xC9, 0x75, 0x1C, 0x3B, 0x93, 0xD4, 0x93, 0x5A, 0x51, 0x82, 0xF2, 0x66, 0x96, 0x5F, 0x24,
-    0xB0, 0x30, 0x45, 0x5B, 0x9D, 0xD1, 0xE4, 0x66, 0xDF, 0xA6, 0xED, 0x59, 0x1F, 0x58, 0x52, 0x05,
-    0x8B, 0x45, 0xD1, 0x9A, 0x3D, 0x08, 0x2E, 0x95, 0x1B, 0x08, 0x22, 0x0D, 0xAA, 0x49, 0xFB, 0x85,
-    0x01, 0xBF, 0x83, 0x62, 0xFE, 0x21, 0x45, 0xFE, 0x73, 0x06, 0x85, 0x20, 0x06, 0x77, 0x3D, 0x9B,
-    0x05, 0x0C, 0x2B, 0xB5, 0x89, 0x5A, 0x99, 0x4B, 0xAE, 0x4A, 0xDD, 0x93, 0x2F, 0xF9, 0x1D, 0xE4,
-    0x6C, 0xB3, 0xF7, 0x0C, 0x42, 0x00, 0x02, 0x3E, 0x2D, 0x78, 0x01, 0xA9, 0x02, 0x03, 0x01, 0x00,
-    0x01, 0x02, 0x82, 0x01, 0x81, 0x00, 0x86, 0x24, 0xC8, 0xF1, 0xA7, 0x5B, 0xF8, 0x04, 0xD6, 0x10,
-    0xF4, 0x39, 0x66, 0xD4, 0xC8, 0xE6, 0xA5, 0xA1, 0x99, 0xA1, 0xB1, 0x89, 0x26, 0x0F, 0x4D, 0xE9,
-    0x08, 0x5B, 0x22, 0x9B, 0x7F, 0x4B, 0x80, 0xDD, 0x85, 0x40, 0x1A, 0xAD, 0x12, 0xD5, 0xE3, 0x8F,
-    0xF1, 0x7B, 0x20, 0x4A, 0xB7, 0xB9, 0xA4, 0x66, 0xCD, 0x0D, 0x8F, 0x56, 0x5E, 0x37, 0x9F, 0x7E,
-    0x1D, 0xF9, 0x93, 0xB0, 0xF0, 0x81, 0x08, 0x76, 0x8C, 0xDE, 0x42, 0x3C, 0xE6, 0xB9, 0x61, 0x9D,
-    0xF5, 0x6A, 0xDA, 0x2B, 0xFD, 0xF9, 0xE2, 0xCE, 0x3F, 0x50, 0x8B, 0x35, 0x43, 0x27, 0x40, 0x02,
-    0x9A, 0x1D, 0x2A, 0xC6, 0xE5, 0xD5, 0xDA, 0xB3, 0xC8, 0x83, 0x49, 0x8E, 0xEB, 0xEF, 0x9E, 0x5E,
-    0xC3, 0x61, 0xB9, 0xAB, 0x92, 0xE5, 0x41, 0x16, 0xF8, 0x7A, 0xEA, 0x54, 0x4F, 0x2D, 0x4E, 0x1B,
-    0x2C, 0x8B, 0xF1, 0x81, 0x65, 0xD9, 0x26, 0xC7, 0x93, 0x4B, 0xF8, 0x06, 0x42, 0x15, 0xB9, 0x64,
-    0x31, 0x6A, 0xDC, 0x9A, 0x3C, 0xB5, 0xEC, 0x09, 0xA4, 0x6C, 0x0A, 0x94, 0xB6, 0x78, 0xA5, 0x26,
-    0xD9, 0x99, 0x5D, 0x14, 0x0C, 0x41, 0xA9, 0x96, 0x13, 0x69, 0x6E, 0x9D, 0xC9, 0x99, 0xD7, 0xB0,
-    0xB0, 0x28, 0x81, 0xC5, 0xB0, 0xF0, 0xAE, 0x34, 0x3E, 0xD3, 0x9B, 0x60, 0x13, 0x46, 0xFC, 0xEE,
-    0x3D, 0x6D, 0x54, 0xEE, 0xFC, 0xCC, 0x41, 0xE5, 0x7B, 0xF6, 0xBA, 0x30, 0x64, 0x3A, 0x1D, 0xAC,
-    0xF2, 0x3E, 0x60, 0x81, 0xAB, 0xDF, 0x61, 0x75, 0x5C, 0xB6, 0x24, 0x27, 0xE4, 0x32, 0xA3, 0x60,
-    0x6B, 0x96, 0xFA, 0xE5, 0xC8, 0xBE, 0x8C, 0xED, 0x48, 0xBD, 0x8B, 0xFB, 0x9C, 0x80, 0x3E, 0xAF,
-    0x01, 0xFB, 0x82, 0x98, 0xC2, 0x08, 0x11, 0xAB, 0x71, 0x9A, 0xE1, 0xC3, 0xA8, 0x27, 0xBC, 0xFF,
-    0x11, 0x9A, 0x05, 0xBC, 0x9B, 0xE6, 0xE0, 0x79, 0x8E, 0xC9, 0x76, 0x56, 0x42, 0x78, 0x6F, 0x24,
-    0x5E, 0x9C, 0x81, 0x0D, 0x5E, 0xAD, 0x4C, 0x33, 0x25, 0x24, 0x70, 0x89, 0x9E, 0xD5, 0xD3, 0xB1,
-    0x81, 0x2F, 0xBA, 0xAC, 0x9F, 0xA6, 0x6B, 0xEC, 0x2D, 0xDB, 0xDD, 0x4F, 0x97, 0x05, 0x6B, 0x77,
-    0x55, 0xCF, 0xE2, 0x91, 0xE8, 0x67, 0xE3, 0xA2, 0x99, 0x53, 0xC3, 0xD6, 0x83, 0xF8, 0x0E, 0xAC,
-    0xE0, 0x2E, 0x61, 0xF4, 0x64, 0x0A, 0x20, 0x35, 0xEB, 0x5B, 0x60, 0x43, 0x2F, 0x33, 0x6F, 0xEC,
-    0x93, 0xA7, 0x92, 0x7A, 0xC6, 0xB7, 0x55, 0xB3, 0x46, 0x21, 0x8B, 0x47, 0x83, 0x84, 0xF1, 0x39,
-    0xF7, 0xB3, 0xC7, 0x7E, 0xD8, 0x65, 0x52, 0xA5, 0x6A, 0x4B, 0xE6, 0x92, 0x8B, 0x32, 0x7A, 0xBD,
-    0x64, 0xD3, 0xC0, 0xA6, 0x25, 0x32, 0xF8, 0x6A, 0xEE, 0xF3, 0xCE, 0x18, 0xAA, 0x48, 0x5D, 0x20,
-    0xFB, 0x02, 0x8B, 0x69, 0x05, 0xD1, 0x02, 0x81, 0xC1, 0x00, 0xF1, 0xE9, 0x9B, 0x56, 0x65, 0x41,
-    0xEF, 0x74, 0x0E, 0xF9, 0xF2, 0xD3, 0x28, 0xA6, 0xC7, 0xB9, 0x22, 0x61, 0x29, 0x2F, 0x8A, 0x39,
-    0xF8, 0xAE, 0x5C, 0x7F, 0xCC, 0xAA, 0x9A, 0x4B, 0x94, 0x02, 0xF8, 0x05, 0xC3, 0x27, 0x18, 0x0E,
-    0x2B, 0x81, 0x61, 0x87, 0x58, 0xF3, 0xC2, 0x40, 0xFB, 0x2A, 0xAA, 0x78, 0x8D, 0x75, 0x97, 0xA3,
-    0xB9, 0xFD, 0xFA, 0x60, 0x95, 0x69, 0xC4, 0xF8, 0xED, 0xD4, 0xBA, 0x5D, 0xEC, 0x81, 0x78, 0x0B,
-    0x48, 0xB2, 0xB5, 0x96, 0x18, 0xA2, 0xC2, 0xFD, 0xD3, 0x22, 0x15, 0xCD, 0xD5, 0xD9, 0xF9, 0x4A,
-    0x45, 0x48, 0xA3, 0x85, 0x8C, 0xED, 0x75, 0x3B, 0x60, 0xB5, 0x03, 0x53, 0x44, 0x7A, 0x01, 0x3E,
-    0xA0, 0x50, 0x8F, 0xA5, 0x63, 0x28, 0xEA, 0xD0, 0x8C, 0xB1, 0xAF, 0xB5, 0xAE, 0x21, 0x80, 0x9F,
-    0x66, 0x40, 0x65, 0x64, 0x34, 0x6A, 0xE1, 0xC1, 0x24, 0x0A, 0x71, 0xA4, 0x02, 0xD8, 0x34, 0xA9,
-    0xA4, 0x3E, 0x5E, 0x12, 0x56, 0x8D, 0x37, 0xF4, 0x96, 0xCB, 0xA6, 0xD3, 0x89, 0xF3, 0x49, 0xB8,
-    0x01, 0xB6, 0x72, 0xB6, 0xD6, 0x1F, 0xB2, 0xBF, 0x94, 0x78, 0x30, 0x6F, 0xB8, 0x03, 0x61, 0x56,
-    0x0E, 0xFA, 0x88, 0x73, 0x30, 0x13, 0x6B, 0xDD, 0x33, 0x11, 0x15, 0x3B, 0x01, 0x60, 0x7F, 0xF4,
-    0xFE, 0xF5, 0x5E, 0xB4, 0x82, 0xC7, 0xBE, 0xD8, 0xCD, 0x85, 0x02, 0x81, 0xC1, 0x00, 0xD6, 0x33,
-    0x16, 0xDE, 0x07, 0xAC, 0x4C, 0xB1, 0xAD, 0x9C, 0x49, 0x01, 0x6E, 0x55, 0x62, 0x31, 0x6A, 0x7A,
-    0xEF, 0x0C, 0x09, 0xC6, 0x38, 0xD5, 0x6C, 0xBB, 0xFA, 0x40, 0x27, 0x4A, 0x0F, 0x76, 0xC6, 0x77,
-    0x05, 0x57, 0x6C, 0x1D, 0xB3, 0x29, 0x43, 0x87, 0xF4, 0x96, 0x54, 0x20, 0x9B, 0x1D, 0x88, 0xA4,
-    0xA6, 0x8D, 0xE8, 0x00, 0x27, 0xC1, 0xCF, 0x90, 0x91, 0xDD, 0x0E, 0xBB, 0x23, 0x94, 0xD2, 0x8C,
-    0x47, 0xE8, 0x4D, 0xAA, 0x1C, 0x8C, 0xDD, 0x37, 0x28, 0x82, 0x93, 0xDC, 0x3D, 0x9B, 0x3E, 0x59,
-    0x04, 0x0A, 0x74, 0xD0, 0x09, 0xC0, 0x6A, 0xBE, 0x0B, 0xF1, 0x75, 0x26, 0x8D, 0x33, 0x21, 0xC8,
-    0x52, 0xE2, 0x62, 0x85, 0x51, 0x79, 0x64, 0x7A, 0x6E, 0xD9, 0xBB, 0x76, 0x73, 0xEC, 0x40, 0x4B,
-    0xED, 0xF9, 0x2D, 0x34, 0xE3, 0x86, 0x07, 0xB8, 0x3F, 0xC5, 0x2F, 0xF3, 0xB2, 0x51, 0x31, 0xA0,
-    0x69, 0xC9, 0x92, 0x0E, 0x15, 0xA3, 0x1F, 0xD9, 0x4A, 0x0D, 0x4F, 0x0F, 0x8D, 0x70, 0x23, 0x79,
-    0xDC, 0xFC, 0x2A, 0x1F, 0x2C, 0x34, 0xD3, 0x0C, 0x38, 0x3B, 0x20, 0xF2, 0xF4, 0x85, 0x6B, 0x81,
-    0x96, 0xF8, 0xE7, 0xC1, 0xAD, 0x89, 0x97, 0xE6, 0x92, 0x19, 0xC2, 0xAA, 0xEE, 0x3B, 0x2D, 0x3B,
-    0xAC, 0x06, 0xFC, 0x8B, 0x9D, 0xFD, 0xD1, 0x53, 0xDA, 0xDF, 0x26, 0x97, 0x9A, 0xD5, 0x02, 0x81,
-    0xC1, 0x00, 0xF1, 0x7C, 0xEF, 0xD2, 0x48, 0xF6, 0x8F, 0x20, 0xDE, 0x2A, 0x69, 0x5A, 0x9D, 0x44,
-    0x10, 0x30, 0x21, 0xBF, 0xB8, 0x2B, 0x7A, 0xE2, 0xEF, 0xFA, 0xAE, 0xDF, 0xEC, 0xE1, 0x89, 0x71,
-    0x54, 0xE9, 0xB9, 0xC9, 0x96, 0xCC, 0x99, 0xD8, 0xDB, 0x59, 0x26, 0x90, 0xC4, 0x1D, 0x61, 0x97,
-    0x18, 0xA3, 0xB8, 0xD4, 0xEA, 0xF1, 0xAE, 0x54, 0x84, 0xC0, 0xA2, 0x86, 0x73, 0xE0, 0xC7, 0xFE,
-    0x6E, 0xFC, 0x62, 0xA6, 0x8C, 0x07, 0x9A, 0x5C, 0x39, 0x50, 0x1C, 0xB1, 0x1F, 0x1A, 0xAB, 0x68,
-    0x52, 0xB1, 0xBD, 0xEE, 0x62, 0x42, 0x5B, 0xF6, 0xE6, 0x3E, 0xE2, 0xED, 0xD8, 0x86, 0xDA, 0xF6,
-    0x51, 0x4D, 0xA1, 0x6A, 0x27, 0xFB, 0x5A, 0xEE, 0xB7, 0x7E, 0x74, 0x46, 0xF7, 0x3B, 0xCB, 0x5C,
-    0x30, 0x76, 0xD8, 0x1E, 0x97, 0x1B, 0x5E, 0x98, 0xC0, 0xAC, 0x1C, 0x0A, 0xF1, 0xC0, 0x98, 0x68,
-    0x03, 0xA0, 0x61, 0x5D, 0x06, 0x71, 0xE9, 0xF0, 0x46, 0xC2, 0xF3, 0x89, 0x7E, 0xD9, 0x2E, 0x38,
-    0x7D, 0xA8, 0x02, 0x7B, 0x3D, 0x44, 0x9E, 0x1C, 0x8F, 0xA9, 0x1F, 0xCE, 0xA0, 0xE5, 0xB7, 0xBC,
-    0x43, 0x6B, 0xCF, 0x7E, 0x56, 0xC5, 0x19, 0x0F, 0x9D, 0x98, 0x3F, 0x4A, 0x2D, 0x7D, 0xD5, 0xB9,
-    0x54, 0xD7, 0x02, 0xC8, 0x8A, 0x51, 0x58, 0xAA, 0xAB, 0x31, 0x2A, 0x3F, 0x2C, 0x26, 0x55, 0xBF,
-    0x7B, 0x39, 0x02, 0x81, 0xC0, 0x0C, 0x68, 0xF7, 0x59, 0x33, 0xCE, 0x9A, 0xBE, 0xEC, 0x95, 0x12,
-    0x71, 0xBF, 0xC7, 0xB8, 0xA1, 0xAE, 0x4E, 0xA3, 0x0C, 0xEA, 0x80, 0x0E, 0x88, 0xE6, 0xFC, 0xD9,
-    0x19, 0xE0, 0x6C, 0xDD, 0x0A, 0x7F, 0xA3, 0x23, 0xAF, 0x15, 0xF7, 0x7E, 0x8A, 0xD4, 0x7B, 0xCB,
-    0x02, 0xEE, 0xAA, 0xD8, 0xF1, 0xD4, 0x19, 0xDE, 0x00, 0x78, 0xC1, 0x91, 0x8C, 0x1C, 0x0F, 0x7F,
-    0x33, 0xF4, 0x87, 0x89, 0x1F, 0x35, 0x37, 0xA5, 0x6E, 0xE3, 0x19, 0x09, 0x00, 0x6C, 0x4C, 0xA6,
-    0xCF, 0x31, 0xEB, 0xDF, 0xB1, 0xDF, 0xE1, 0xDE, 0x67, 0x10, 0xAF, 0x80, 0xF1, 0x21, 0xFE, 0x12,
-    0xC9, 0x11, 0x85, 0x83, 0x46, 0xC4, 0x1D, 0x4C, 0x18, 0x0B, 0xA7, 0x37, 0xBA, 0x35, 0xC5, 0x16,
-    0x29, 0x0D, 0x40, 0x66, 0xA4, 0xF8, 0x70, 0xAD, 0xBF, 0xF3, 0x0B, 0x8E, 0x67, 0x14, 0x89, 0x6B,
-    0x40, 0x6C, 0x6F, 0xCD, 0x14, 0x01, 0x31, 0x0F, 0x0F, 0xFB, 0xA3, 0x4F, 0x43, 0x9D, 0x33, 0xC4,
-    0xA3, 0x92, 0xC2, 0x0E, 0xEA, 0xC1, 0x53, 0x6D, 0x27, 0x3A, 0xF5, 0x85, 0x65, 0x26, 0x19, 0x1E,
-    0x24, 0xE6, 0xDA, 0xCC, 0xA9, 0xF2, 0x39, 0x96, 0xDA, 0xA2, 0xEA, 0xC8, 0xB8, 0x21, 0x11, 0xDD,
-    0xC3, 0x1A, 0x51, 0x36, 0xEE, 0x3C, 0xC7, 0xA9, 0x46, 0xDA, 0x58, 0xE8, 0x75, 0x6D, 0x2C, 0x53,
-    0x90, 0xFC, 0x36, 0x6A, 0x65, 0x02, 0x81, 0xC1, 0x00, 0x90, 0x17, 0x57, 0x12, 0x83, 0x17, 0xC8,
-    0x4C, 0x8E, 0xF7, 0x72, 0x9A, 0x8E, 0xC8, 0x6B, 0x73, 0x1A, 0x73, 0x43, 0x8A, 0x11, 0xBD, 0x76,
-    0xC6, 0x56, 0xEE, 0xE9, 0xCF, 0xFA, 0x20, 0x67, 0x8C, 0x20, 0xEF, 0x7E, 0xDF, 0x0B, 0x7A, 0xF9,
-    0xA8, 0x43, 0x62, 0xE1, 0x94, 0x4D, 0xB4, 0x47, 0xDF, 0xBD, 0xD8, 0x4E, 0xF8, 0x12, 0xCF, 0x9D,
-    0x4B, 0x24, 0x64, 0x90, 0x79, 0xA3, 0xF6, 0x8C, 0x5A, 0xDA, 0xBC, 0x97, 0x1A, 0x2B, 0xBF, 0x61,
-    0x6D, 0x21, 0xBB, 0xAB, 0xD0, 0x03, 0x9A, 0xA4, 0x38, 0x9B, 0x1A, 0x92, 0x36, 0xA4, 0xAA, 0xB0,
-    0x70, 0x05, 0x2D, 0x90, 0x00, 0x60, 0x09, 0x3C, 0x0C, 0x00, 0xA1, 0xFE, 0x36, 0x39, 0x29, 0x15,
-    0x8B, 0xC1, 0x34, 0x82, 0x4E, 0x36, 0xAB, 0xF3, 0x73, 0x1C, 0x68, 0x7D, 0x5D, 0x1A, 0x18, 0xA1,
-    0x53, 0x31, 0xD0, 0x22, 0x14, 0xF6, 0x22, 0x3A, 0xB5, 0x8D, 0xDC, 0x3C, 0x24, 0x56, 0x38, 0x34,
-    0x01, 0xA2, 0x1F, 0x57, 0x05, 0xC3, 0x84, 0xBD, 0xFC, 0xED, 0xB1, 0xAA, 0x37, 0xA0, 0x86, 0xFA,
-    0x45, 0x74, 0x87, 0x9F, 0xC0, 0x16, 0xAD, 0x8E, 0x65, 0xA0, 0x37, 0x00, 0x09, 0x52, 0x6A, 0x38,
-    0x65, 0x6B, 0xB1, 0xE4, 0xAE, 0xCC, 0xD4, 0xC9, 0xEB, 0x9D, 0x34, 0x72, 0x72, 0xAE, 0xB5, 0xC8,
-    0xF6, 0x50, 0x85, 0xF7, 0x8C, 0xCE, 0x16, 0xE1, 0x09,
-];
-
-pub const NODE_PUBLIC_KEY: [u8; 422] = [
-    0x30, 0x82, 0x01, 0xA2, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01,
-    0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x8F, 0x00, 0x30, 0x82, 0x01, 0x8A, 0x02, 0x82, 0x01, 0x81,
-    0x00, 0xCB, 0x0E, 0x66, 0x6E, 0xF3, 0x55, 0x59, 0x8E, 0x58, 0x1A, 0x85, 0x60, 0x7D, 0x2D, 0x54,
-    0x4D, 0x48, 0xD4, 0xEC, 0x68, 0xF0, 0xF0, 0x86, 0x68, 0xDC, 0x9B, 0xBF, 0xCC, 0xE9, 0xCA, 0x84,
-    0xE5, 0x4D, 0x67, 0xBA, 0x24, 0xB2, 0x89, 0xA1, 0x6A, 0x8D, 0xD9, 0x53, 0xA3, 0xB5, 0xF9, 0xF1,
-    0x09, 0x97, 0xE3, 0xA2, 0x5E, 0x91, 0x7E, 0x9B, 0xD5, 0xDB, 0xA8, 0x32, 0xB3, 0x4F, 0xE8, 0x41,
-    0x49, 0x2E, 0x62, 0x69, 0xB3, 0xC5, 0x56, 0xD9, 0xB3, 0x75, 0x4B, 0xF9, 0x09, 0xA6, 0xE9, 0xBD,
-    0xD0, 0x87, 0xDA, 0x20, 0xF7, 0x6A, 0x8D, 0x93, 0x02, 0x6F, 0x51, 0xB8, 0x65, 0x1B, 0x77, 0xCA,
-    0xE2, 0x75, 0x15, 0x9E, 0x94, 0x45, 0x69, 0x15, 0x94, 0xF3, 0x9F, 0x7C, 0xBD, 0x90, 0xB3, 0x27,
-    0x8C, 0xBA, 0x38, 0x32, 0x5E, 0xDD, 0x84, 0x1C, 0x7F, 0x18, 0xA9, 0x93, 0x88, 0x5A, 0x1B, 0x3E,
-    0x96, 0xA3, 0x69, 0x7C, 0x82, 0xFD, 0x73, 0x17, 0xC3, 0x65, 0x1C, 0xA3, 0x4D, 0x6D, 0x3F, 0x4E,
-    0x81, 0x73, 0x3C, 0x47, 0x64, 0x34, 0xD7, 0xC9, 0x32, 0xA7, 0x9C, 0xD8, 0xC9, 0x78, 0xE5, 0xB9,
-    0x65, 0xBD, 0x95, 0xD4, 0xF2, 0x4B, 0xB5, 0xD5, 0xCA, 0x44, 0xD9, 0x04, 0x7B, 0xCF, 0x77, 0x32,
-    0x5F, 0xAF, 0xD4, 0x64, 0x32, 0x97, 0x8E, 0x06, 0x61, 0x0A, 0xCD, 0xD5, 0xA0, 0x50, 0x8D, 0xD1,
-    0xA8, 0xBF, 0x15, 0xB8, 0x81, 0xA8, 0x40, 0xBC, 0x6D, 0x82, 0x6B, 0x69, 0xA9, 0x70, 0x4D, 0xA3,
-    0x42, 0x53, 0x6A, 0xD3, 0xE7, 0x47, 0xDD, 0x46, 0x9F, 0xA8, 0xA4, 0x0A, 0x5D, 0xC6, 0x4F, 0x1C,
-    0x38, 0xFF, 0xC7, 0x94, 0xAD, 0xB8, 0xB6, 0x7F, 0x25, 0xA1, 0x21, 0x5A, 0x97, 0x6E, 0x06, 0x39,
-    0xDF, 0xEB, 0x8F, 0xF4, 0x43, 0x64, 0xCD, 0xB4, 0x1C, 0xDD, 0x2B, 0xC9, 0x6D, 0x5F, 0xAC, 0x83,
-    0xD8, 0x0C, 0xB0, 0x9F, 0x2A, 0xDA, 0xC0, 0xC3, 0x4E, 0x04, 0xC2, 0xF0, 0x09, 0x0B, 0x10, 0xBD,
-    0x19, 0x00, 0x24, 0x32, 0xD1, 0xF4, 0x0A, 0x50, 0x44, 0xCB, 0xBE, 0x70, 0xD4, 0xDA, 0x63, 0xBC,
-    0xFC, 0xDC, 0xAD, 0x24, 0x63, 0x07, 0x66, 0x96, 0xE6, 0xA3, 0x86, 0xB9, 0xDD, 0xDE, 0x4B, 0xF1,
-    0xB5, 0x49, 0x94, 0x10, 0xE2, 0xF5, 0xD0, 0xF1, 0xAE, 0xDC, 0xCB, 0x22, 0xE8, 0xAE, 0x26, 0xFF,
-    0xD6, 0xFE, 0xE4, 0xDA, 0x5F, 0x70, 0xD4, 0xF7, 0x9A, 0xA0, 0x78, 0xFB, 0x84, 0x69, 0x0B, 0xB7,
-    0x71, 0xAD, 0xEC, 0x18, 0xB4, 0xA7, 0x38, 0x9A, 0xC8, 0xCB, 0x9A, 0x1C, 0x30, 0x44, 0xFB, 0xF3,
-    0xB5, 0xFF, 0x95, 0x53, 0x16, 0x50, 0xE8, 0x94, 0x06, 0xCF, 0xA2, 0x94, 0xB6, 0x48, 0x83, 0xA0,
-    0xAF, 0xA7, 0x87, 0x8C, 0xCA, 0xE7, 0x1F, 0xEA, 0x4A, 0x5B, 0x14, 0x54, 0x6A, 0x55, 0xDF, 0x3E,
-    0xCF, 0x02, 0x03, 0x01, 0x00, 0x01,
-];
-
-pub const NODE_PRIVATE_KEY: [u8; 1768] = [
-    0x30, 0x82, 0x06, 0xE4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x81, 0x00, 0xCB, 0x0E, 0x66, 0x6E,
-    0xF3, 0x55, 0x59, 0x8E, 0x58, 0x1A, 0x85, 0x60, 0x7D, 0x2D, 0x54, 0x4D, 0x48, 0xD4, 0xEC, 0x68,
-    0xF0, 0xF0, 0x86, 0x68, 0xDC, 0x9B, 0xBF, 0xCC, 0xE9, 0xCA, 0x84, 0xE5, 0x4D, 0x67, 0xBA, 0x24,
-    0xB2, 0x89, 0xA1, 0x6A, 0x8D, 0xD9, 0x53, 0xA3, 0xB5, 0xF9, 0xF1, 0x09, 0x97, 0xE3, 0xA2, 0x5E,
-    0x91, 0x7E, 0x9B, 0xD5, 0xDB, 0xA8, 0x32, 0xB3, 0x4F, 0xE8, 0x41, 0x49, 0x2E, 0x62, 0x69, 0xB3,
-    0xC5, 0x56, 0xD9, 0xB3, 0x75, 0x4B, 0xF9, 0x09, 0xA6, 0xE9, 0xBD, 0xD0, 0x87, 0xDA, 0x20, 0xF7,
-    0x6A, 0x8D, 0x93, 0x02, 0x6F, 0x51, 0xB8, 0x65, 0x1B, 0x77, 0xCA, 0xE2, 0x75, 0x15, 0x9E, 0x94,
-    0x45, 0x69, 0x15, 0x94, 0xF3, 0x9F, 0x7C, 0xBD, 0x90, 0xB3, 0x27, 0x8C, 0xBA, 0x38, 0x32, 0x5E,
-    0xDD, 0x84, 0x1C, 0x7F, 0x18, 0xA9, 0x93, 0x88, 0x5A, 0x1B, 0x3E, 0x96, 0xA3, 0x69, 0x7C, 0x82,
-    0xFD, 0x73, 0x17, 0xC3, 0x65, 0x1C, 0xA3, 0x4D, 0x6D, 0x3F, 0x4E, 0x81, 0x73, 0x3C, 0x47, 0x64,
-    0x34, 0xD7, 0xC9, 0x32, 0xA7, 0x9C, 0xD8, 0xC9, 0x78, 0xE5, 0xB9, 0x65, 0xBD, 0x95, 0xD4, 0xF2,
-    0x4B, 0xB5, 0xD5, 0xCA, 0x44, 0xD9, 0x04, 0x7B, 0xCF, 0x77, 0x32, 0x5F, 0xAF, 0xD4, 0x64, 0x32,
-    0x97, 0x8E, 0x06, 0x61, 0x0A, 0xCD, 0xD5, 0xA0, 0x50, 0x8D, 0xD1, 0xA8, 0xBF, 0x15, 0xB8, 0x81,
-    0xA8, 0x40, 0xBC, 0x6D, 0x82, 0x6B, 0x69, 0xA9, 0x70, 0x4D, 0xA3, 0x42, 0x53, 0x6A, 0xD3, 0xE7,
-    0x47, 0xDD, 0x46, 0x9F, 0xA8, 0xA4, 0x0A, 0x5D, 0xC6, 0x4F, 0x1C, 0x38, 0xFF, 0xC7, 0x94, 0xAD,
-    0xB8, 0xB6, 0x7F, 0x25, 0xA1, 0x21, 0x5A, 0x97, 0x6E, 0x06, 0x39, 0xDF, 0xEB, 0x8F, 0xF4, 0x43,
-    0x64, 0xCD, 0xB4, 0x1C, 0xDD, 0x2B, 0xC9, 0x6D, 0x5F, 0xAC, 0x83, 0xD8, 0x0C, 0xB0, 0x9F, 0x2A,
-    0xDA, 0xC0, 0xC3, 0x4E, 0x04, 0xC2, 0xF0, 0x09, 0x0B, 0x10, 0xBD, 0x19, 0x00, 0x24, 0x32, 0xD1,
-    0xF4, 0x0A, 0x50, 0x44, 0xCB, 0xBE, 0x70, 0xD4, 0xDA, 0x63, 0xBC, 0xFC, 0xDC, 0xAD, 0x24, 0x63,
-    0x07, 0x66, 0x96, 0xE6, 0xA3, 0x86, 0xB9, 0xDD, 0xDE, 0x4B, 0xF1, 0xB5, 0x49, 0x94, 0x10, 0xE2,
-    0xF5, 0xD0, 0xF1, 0xAE, 0xDC, 0xCB, 0x22, 0xE8, 0xAE, 0x26, 0xFF, 0xD6, 0xFE, 0xE4, 0xDA, 0x5F,
-    0x70, 0xD4, 0xF7, 0x9A, 0xA0, 0x78, 0xFB, 0x84, 0x69, 0x0B, 0xB7, 0x71, 0xAD, 0xEC, 0x18, 0xB4,
-    0xA7, 0x38, 0x9A, 0xC8, 0xCB, 0x9A, 0x1C, 0x30, 0x44, 0xFB, 0xF3, 0xB5, 0xFF, 0x95, 0x53, 0x16,
-    0x50, 0xE8, 0x94, 0x06, 0xCF, 0xA2, 0x94, 0xB6, 0x48, 0x83, 0xA0, 0xAF, 0xA7, 0x87, 0x8C, 0xCA,
-    0xE7, 0x1F, 0xEA, 0x4A, 0x5B, 0x14, 0x54, 0x6A, 0x55, 0xDF, 0x3E, 0xCF, 0x02, 0x03, 0x01, 0x00,
-    0x01, 0x02, 0x82, 0x01, 0x80, 0x19, 0x44, 0x5A, 0x74, 0xB5, 0xEC, 0xC9, 0xEF, 0x0F, 0x81, 0x85,
-    0x55, 0x43, 0x5E, 0x4F, 0x9E, 0x2A, 0x50, 0xEC, 0x76, 0x06, 0x7D, 0x37, 0x8C, 0x76, 0xDF, 0x1E,
-    0x97, 0xC6, 0x03, 0xC0, 0x53, 0xB4, 0x35, 0x13, 0x11, 0x9B, 0xF1, 0xCA, 0x57, 0x32, 0xFD, 0x77,
-    0x0D, 0xE9, 0x08, 0x07, 0xF9, 0x54, 0xA0, 0x2B, 0xC5, 0x2E, 0xBF, 0x9D, 0x6E, 0x98, 0x1D, 0xAE,
-    0xE9, 0x67, 0x29, 0x14, 0x6E, 0xA1, 0xC9, 0xF7, 0x33, 0x3A, 0x7C, 0x1B, 0x2C, 0xDC, 0x8C, 0xAE,
-    0x99, 0x87, 0xDE, 0x90, 0x13, 0x11, 0xC4, 0x8F, 0xD3, 0x99, 0xBB, 0xB2, 0x2E, 0x5C, 0x61, 0xC3,
-    0xDB, 0x38, 0xF6, 0xC8, 0x15, 0x33, 0xD2, 0x93, 0xE0, 0x09, 0x5F, 0x11, 0x23, 0x6E, 0xC9, 0x4A,
-    0xC1, 0x5F, 0xEF, 0x1B, 0x1D, 0xC4, 0xD2, 0x57, 0x5A, 0x3C, 0xA0, 0x42, 0xD7, 0x81, 0xDF, 0x20,
-    0x0F, 0x98, 0x7E, 0xC9, 0x63, 0xFF, 0x43, 0x92, 0x0D, 0xCE, 0xB1, 0xF2, 0xA4, 0x0A, 0xC1, 0xEC,
-    0x84, 0x26, 0xF2, 0xF8, 0xB6, 0xDC, 0xFB, 0x04, 0x3B, 0x30, 0xE4, 0x25, 0x12, 0x1B, 0x8F, 0x45,
-    0xDE, 0x94, 0x1F, 0xA9, 0xD9, 0x42, 0x25, 0x11, 0xD1, 0x70, 0xA0, 0x58, 0xD1, 0x09, 0x8E, 0x23,
-    0xA3, 0xB0, 0x66, 0x39, 0xAB, 0x74, 0x7A, 0xAE, 0x59, 0x29, 0x48, 0xAF, 0xFC, 0x85, 0x56, 0xA5,
-    0x9D, 0x84, 0x48, 0x91, 0x6D, 0x00, 0x4F, 0x35, 0xEA, 0xAC, 0xC9, 0x0C, 0x20, 0x06, 0x07, 0x72,
-    0xAB, 0x53, 0x12, 0x3D, 0x9A, 0xE7, 0x5E, 0x86, 0x86, 0xBF, 0xAF, 0x54, 0xFF, 0x61, 0xB6, 0x6F,
-    0xEC, 0x6C, 0xAB, 0xDD, 0xEC, 0x9C, 0x07, 0xD7, 0x44, 0x02, 0xE7, 0xF3, 0x38, 0x8B, 0x2C, 0x7B,
-    0x29, 0x10, 0x50, 0xF3, 0xE2, 0x45, 0x9A, 0x37, 0xB1, 0x80, 0xE1, 0xD7, 0x8F, 0xAC, 0x5D, 0x44,
-    0xEF, 0xC8, 0x54, 0x54, 0x08, 0x7F, 0x63, 0x91, 0xB3, 0x15, 0xE0, 0xAD, 0x1A, 0xA3, 0xB4, 0xB2,
-    0xFB, 0x2F, 0x5F, 0xD8, 0x7E, 0xAD, 0x6D, 0x05, 0x20, 0x5E, 0x16, 0x5C, 0xF9, 0x03, 0x43, 0x45,
-    0x46, 0xF3, 0x0F, 0xEA, 0x1F, 0x00, 0x2D, 0x5A, 0x3B, 0x62, 0xE6, 0xCD, 0xB5, 0xED, 0x35, 0x24,
-    0xA7, 0xB6, 0xA2, 0x16, 0xD9, 0xF3, 0xA9, 0x5D, 0x32, 0xBE, 0x2D, 0x97, 0xBC, 0x4A, 0x1A, 0x37,
-    0x79, 0xE7, 0x7A, 0xDE, 0x1A, 0xFE, 0x70, 0x01, 0x54, 0x95, 0x02, 0xE9, 0x1A, 0xD7, 0x72, 0xD8,
-    0x1E, 0xB4, 0xD3, 0x59, 0xB5, 0x22, 0x0B, 0x31, 0x55, 0x7F, 0xF6, 0x0F, 0xED, 0x1C, 0x55, 0x48,
-    0x81, 0x6E, 0xA4, 0xF5, 0x9D, 0x9B, 0x58, 0xED, 0x42, 0x6D, 0xE6, 0xBE, 0x2C, 0x10, 0xD7, 0x06,
-    0x7D, 0x63, 0x4E, 0xA5, 0x0B, 0x39, 0x5E, 0x1B, 0xE5, 0x85, 0x92, 0x89, 0xC7, 0xC8, 0xBB, 0x4F,
-    0x59, 0xF8, 0xC1, 0x78, 0xB9, 0x02, 0x81, 0xC1, 0x00, 0xEA, 0x11, 0x29, 0x0E, 0x92, 0xFD, 0x82,
-    0x3B, 0x89, 0x5E, 0x07, 0x07, 0x29, 0x67, 0x40, 0xDC, 0xC3, 0x64, 0x9E, 0xD0, 0x9C, 0x02, 0x61,
-    0x42, 0xBE, 0xFE, 0xC7, 0x6E, 0x77, 0x47, 0xA0, 0x2F, 0x85, 0xD6, 0x78, 0xF6, 0x2D, 0x34, 0x89,
-    0x8A, 0x56, 0x5C, 0xFF, 0x4B, 0x53, 0x92, 0xBD, 0xE5, 0x04, 0x88, 0x2A, 0x0D, 0x61, 0x7C, 0xA0,
-    0xBA, 0x5E, 0x95, 0x9A, 0x8B, 0x9D, 0x65, 0xD2, 0x8F, 0x10, 0x87, 0x5D, 0x61, 0xAE, 0x22, 0xC1,
-    0x1C, 0x88, 0x1E, 0xC2, 0xA9, 0x0F, 0x6C, 0xAA, 0x35, 0x80, 0x6C, 0x50, 0xF3, 0x03, 0xBA, 0x68,
-    0x9F, 0xE4, 0x0C, 0x0E, 0xC6, 0x7E, 0xBA, 0xC9, 0xE1, 0x6F, 0x9C, 0xA0, 0xD1, 0xD9, 0xE5, 0x2D,
-    0x75, 0xE0, 0x73, 0x4A, 0x00, 0x47, 0x26, 0x4D, 0x7D, 0x15, 0xF1, 0x7E, 0xEA, 0xA0, 0xB2, 0x5F,
-    0xE9, 0xCC, 0x61, 0xB0, 0x06, 0x70, 0xC1, 0x0E, 0xD0, 0xCA, 0x91, 0x1C, 0xAC, 0xD0, 0x0D, 0x16,
-    0xC0, 0x19, 0x90, 0xD2, 0xBE, 0x15, 0xE4, 0x6E, 0xF1, 0x1F, 0x48, 0xA5, 0x6D, 0xFF, 0x13, 0xA4,
-    0xEB, 0x58, 0x7B, 0x2F, 0x09, 0x67, 0x01, 0xBA, 0xF4, 0x2E, 0x4F, 0x29, 0x8F, 0x48, 0x2F, 0xC4,
-    0x17, 0xE5, 0x5B, 0x4F, 0x77, 0x62, 0x06, 0x6A, 0xCA, 0x1D, 0x47, 0x6B, 0xA3, 0x25, 0x07, 0xA7,
-    0x39, 0x16, 0x3E, 0xAB, 0xE6, 0xCD, 0xB6, 0x40, 0x33, 0x02, 0x81, 0xC1, 0x00, 0xDE, 0x15, 0x59,
-    0x0D, 0x19, 0xBA, 0x9C, 0xF3, 0x97, 0xB1, 0x0A, 0x45, 0xEE, 0x33, 0x4D, 0xEC, 0xBC, 0x86, 0x39,
-    0xF2, 0x17, 0xDF, 0x24, 0xD0, 0x91, 0xB1, 0x03, 0x6E, 0xFD, 0xE7, 0x5A, 0x1E, 0x72, 0x8C, 0xF5,
-    0x8C, 0x98, 0x79, 0x42, 0x88, 0x49, 0xA2, 0xD9, 0xE2, 0x1C, 0x15, 0x3D, 0x68, 0xC2, 0x29, 0x3E,
-    0x86, 0xBC, 0x0B, 0xE7, 0xDC, 0x0B, 0xB9, 0xD5, 0xB2, 0x39, 0x2F, 0x4B, 0x54, 0x7E, 0x16, 0xF3,
-    0xE9, 0xE5, 0xD6, 0x13, 0x2A, 0x96, 0x2F, 0x00, 0x64, 0xE6, 0x7B, 0x5C, 0xDC, 0xD8, 0xA9, 0x24,
-    0x68, 0xC5, 0xF9, 0x1A, 0xCD, 0x0C, 0x3A, 0x5A, 0xF4, 0x62, 0xEA, 0x6D, 0x59, 0x72, 0x63, 0xD8,
-    0xA5, 0xA4, 0x19, 0x03, 0xD5, 0x70, 0x22, 0xFA, 0xEF, 0x89, 0x97, 0x8C, 0x0B, 0xEC, 0x55, 0x9A,
-    0x18, 0xDF, 0xBC, 0x28, 0xAC, 0x7D, 0x4B, 0x4B, 0x63, 0x9B, 0x54, 0x60, 0x07, 0xA9, 0xAB, 0x6C,
-    0xF0, 0x8D, 0xA5, 0xD0, 0x89, 0xA4, 0xF5, 0x6B, 0x8F, 0x23, 0xC8, 0x0E, 0x21, 0x32, 0x5E, 0x28,
-    0x22, 0x3B, 0xAB, 0x09, 0xCB, 0x1B, 0xD6, 0xDB, 0x1C, 0x48, 0x8A, 0x4D, 0x45, 0x01, 0x41, 0x5F,
-    0x22, 0x2A, 0xCE, 0xD8, 0xD2, 0xB9, 0x96, 0x3D, 0xEB, 0x1F, 0x3E, 0x92, 0xA9, 0xD9, 0xF1, 0x9C,
-    0x41, 0x0B, 0x94, 0xC0, 0x2F, 0x5B, 0x87, 0x25, 0x11, 0x4B, 0x36, 0xFA, 0xF5, 0x02, 0x81, 0xC0,
-    0x40, 0xE9, 0x97, 0x68, 0x4A, 0x4D, 0x71, 0xD3, 0x8F, 0x09, 0xFB, 0x8A, 0xF9, 0xE9, 0x7F, 0xAC,
-    0x79, 0xA7, 0xAA, 0xFF, 0x91, 0x74, 0x7B, 0x82, 0xA6, 0x33, 0x44, 0x1D, 0x97, 0x88, 0xCE, 0x9C,
-    0xBF, 0x52, 0x36, 0x63, 0x97, 0x2F, 0xCD, 0xC1, 0x06, 0xA8, 0x6D, 0xC8, 0x77, 0x19, 0xE7, 0xFD,
-    0xDE, 0x5E, 0xE0, 0xC2, 0xAB, 0x39, 0x83, 0xDD, 0x8B, 0xA3, 0x93, 0xA3, 0x8A, 0x78, 0x15, 0x87,
-    0xC5, 0x7E, 0xB4, 0xE0, 0x05, 0x09, 0xF0, 0x62, 0x38, 0x41, 0xC7, 0x9C, 0x59, 0x01, 0xBA, 0xC6,
-    0x71, 0xA2, 0x18, 0x64, 0xFC, 0xB0, 0xB2, 0x99, 0x3D, 0x06, 0x37, 0x06, 0xC7, 0x58, 0x87, 0xEA,
-    0x34, 0x28, 0xCC, 0xD4, 0xC5, 0xC7, 0xEF, 0xEE, 0x93, 0xDB, 0x85, 0x37, 0x44, 0x84, 0x13, 0xD3,
-    0x4F, 0xC5, 0x94, 0x7B, 0xFF, 0x2A, 0xD8, 0xBC, 0x9F, 0x08, 0xAC, 0x67, 0x6C, 0xD7, 0xAD, 0x83,
-    0x2B, 0xDA, 0x48, 0x88, 0x88, 0x7E, 0x48, 0xC3, 0xE7, 0x93, 0x29, 0x4E, 0xBC, 0x05, 0x88, 0xDA,
-    0xE7, 0xE1, 0x1E, 0xB7, 0xBD, 0x98, 0xB6, 0x10, 0xEA, 0x8D, 0xE7, 0x02, 0x85, 0x85, 0x8E, 0x52,
-    0x6F, 0x91, 0x56, 0xA6, 0x3C, 0xCF, 0xBA, 0x63, 0x22, 0x21, 0x4B, 0x8D, 0x81, 0x2A, 0xE4, 0x6C,
-    0xBE, 0xE7, 0xF2, 0xAA, 0xE0, 0xF7, 0x19, 0x62, 0x14, 0x90, 0x36, 0xDE, 0x20, 0x48, 0x9D, 0xCF,
-    0x02, 0x81, 0xC1, 0x00, 0xA6, 0xF9, 0x31, 0xFD, 0x11, 0x8D, 0x27, 0x18, 0x56, 0xC2, 0xBB, 0x50,
-    0x9C, 0xA9, 0x62, 0x3B, 0x4D, 0xFB, 0x35, 0x71, 0xF9, 0xD4, 0xC2, 0x1F, 0x36, 0x8A, 0xFA, 0x63,
-    0xE6, 0xEE, 0x9C, 0xE9, 0x2B, 0x83, 0x23, 0xD3, 0x53, 0x88, 0x48, 0x27, 0xA4, 0x05, 0x96, 0xFF,
-    0xD3, 0xD1, 0x7C, 0x5C, 0x59, 0x2F, 0x1D, 0x5D, 0xBB, 0xE0, 0xCF, 0xB0, 0xB7, 0xF8, 0x3E, 0xDD,
-    0x42, 0xF5, 0x76, 0x13, 0xCE, 0xC1, 0x7F, 0x1E, 0x2A, 0xB9, 0xEB, 0xAB, 0x27, 0x43, 0xAB, 0x6E,
-    0x31, 0x84, 0x2A, 0xEB, 0xB8, 0xD2, 0x63, 0x17, 0x8B, 0x51, 0xA1, 0x7E, 0xED, 0x64, 0xAA, 0xA1,
-    0xF8, 0x04, 0xFD, 0xB6, 0x34, 0xB5, 0x31, 0x5C, 0x48, 0xA6, 0xAE, 0x25, 0x39, 0xAC, 0x73, 0x32,
-    0xCA, 0x26, 0x71, 0x1B, 0x3D, 0xD3, 0x96, 0x8A, 0x81, 0x1D, 0x3D, 0x0F, 0x83, 0x1C, 0xAB, 0x4F,
-    0xF6, 0xA7, 0x57, 0x94, 0x2B, 0x53, 0x42, 0x13, 0x12, 0xCC, 0xCA, 0x9F, 0xD2, 0xB0, 0xDA, 0xEF,
-    0xC2, 0x1D, 0x55, 0xD2, 0x4B, 0xC6, 0x53, 0x32, 0x79, 0xDE, 0x3C, 0xFC, 0xC2, 0xAF, 0xA6, 0x09,
-    0xFB, 0xD8, 0x50, 0x04, 0x43, 0xCF, 0x5C, 0xB1, 0x99, 0xB1, 0xEF, 0x7F, 0x70, 0x1D, 0xAF, 0xEC,
-    0x29, 0x8F, 0xA8, 0x41, 0xA0, 0x25, 0x72, 0x2F, 0xCD, 0x7F, 0x47, 0x87, 0xD3, 0xAF, 0x26, 0x85,
-    0x7C, 0x21, 0x98, 0x49, 0x02, 0x81, 0xC1, 0x00, 0xE6, 0xDC, 0x27, 0xAF, 0x9C, 0x39, 0x82, 0xD2,
-    0x36, 0x51, 0xCC, 0x5A, 0xE5, 0x15, 0x1A, 0x16, 0x31, 0x50, 0xBA, 0x67, 0xA6, 0x15, 0x1F, 0x1B,
-    0x5B, 0x9C, 0x40, 0x18, 0xEC, 0x18, 0x1C, 0xEA, 0xB0, 0x7D, 0x30, 0xF9, 0xBA, 0x6A, 0x68, 0x00,
-    0xDC, 0x69, 0x70, 0xDD, 0x2C, 0xBD, 0xBF, 0xBF, 0xBC, 0xEB, 0x8F, 0x00, 0x8A, 0x71, 0x39, 0xE0,
-    0xEC, 0x09, 0xEB, 0xAC, 0x85, 0x44, 0xC4, 0xF4, 0x43, 0x0F, 0xA3, 0x63, 0x76, 0xD3, 0x36, 0x4A,
-    0xB9, 0x86, 0x13, 0x3A, 0x2A, 0x16, 0xD4, 0x44, 0x4E, 0xF7, 0x0A, 0x7C, 0xDC, 0x86, 0x94, 0x5D,
-    0xB8, 0x0C, 0xBF, 0xE3, 0x78, 0xB5, 0x52, 0xF8, 0x62, 0x57, 0xE7, 0x8B, 0x50, 0x23, 0x32, 0x83,
-    0xAF, 0x7E, 0xAD, 0xAB, 0x4E, 0xFC, 0x4B, 0x87, 0xEF, 0x3A, 0xC3, 0x00, 0xBF, 0x4D, 0x56, 0xFF,
-    0x01, 0x08, 0x89, 0xBC, 0x02, 0x4F, 0x37, 0x1E, 0xE2, 0x39, 0xEE, 0xBA, 0xDA, 0xBA, 0x44, 0x8A,
-    0x35, 0x5D, 0x49, 0xEC, 0x0F, 0xD7, 0x54, 0x20, 0x61, 0xA9, 0x63, 0x17, 0xF2, 0x57, 0xFC, 0x57,
-    0x91, 0x34, 0xE3, 0x14, 0x9B, 0x54, 0x7B, 0xC3, 0x3C, 0x97, 0x16, 0x8E, 0x90, 0x0D, 0x0C, 0x80,
-    0xA3, 0x31, 0x6C, 0x31, 0x28, 0x5B, 0x25, 0x2C, 0x12, 0x1E, 0x41, 0xEA, 0x58, 0x69, 0xC4, 0x1E,
-    0x0F, 0x5A, 0xC2, 0x7B, 0x01, 0x2C, 0xB7, 0xFA,
-];
-
-pub const BLOCK_KEY: [u8; 32] = [
-    0xEE, 0x76, 0xD6, 0xDC, 0x6D, 0x94, 0x1D, 0x95, 0xC2, 0x57, 0x94, 0x46, 0xA2, 0x97, 0x8F, 0x5B,
-    0x59, 0xE1, 0x7E, 0xE4, 0x3B, 0xB1, 0x69, 0x88, 0x5D, 0x16, 0x30, 0x5A, 0x50, 0xDB, 0x58, 0x65,
-];
-
-pub const LONG_KEY: [u8; 64] = [
-    0x65, 0x4E, 0x78, 0x5C, 0x8E, 0xEE, 0x9E, 0x57, 0x58, 0x8D, 0xDE, 0x9E, 0x6D, 0x84, 0xF4, 0x68,
-    0x7F, 0x9E, 0x48, 0xC4, 0x6F, 0x1F, 0x4F, 0x83, 0x46, 0x68, 0xB2, 0xC1, 0x46, 0xD0, 0x06, 0xF2,
-    0x23, 0xB9, 0xD4, 0x66, 0x4B, 0xED, 0x65, 0x92, 0xF1, 0xA2, 0x04, 0x1A, 0xD9, 0xF6, 0xA2, 0xAE,
-    0x87, 0x3E, 0xBF, 0x10, 0x4A, 0x29, 0x28, 0x83, 0x2A, 0x8F, 0xC5, 0x30, 0x86, 0x11, 0x48, 0x52,
-];
-
-pub const IV: [u8; 16] = [
-    0x60, 0xE0, 0xBE, 0x45, 0xA9, 0xAB, 0x5D, 0x99, 0x3B, 0x3A, 0x1E, 0x54, 0x18, 0xE0, 0x46, 0xDE,
-];
+pub(crate) static BLOCK_KEY: SymKey = {
+    const KEY: [u8; 32] = [
+        0xB2, 0xB3, 0xDA, 0x5A, 0x1A, 0xF6, 0xB3, 0x78, 0x30, 0xAB, 0x1D, 0x33, 0x33, 0xE7, 0xE3,
+        0x5B, 0xBB, 0xF9, 0xFE, 0xD0, 0xC1, 0xF7, 0x90, 0x34, 0x69, 0xB7, 0xE7, 0xC6, 0x1C, 0x46,
+        0x85, 0x48,
+    ];
+    const IV: [u8; 16] = [
+        0xEC, 0x19, 0x59, 0x3A, 0x1D, 0x1E, 0x4A, 0x58, 0x66, 0xC1, 0xD1, 0x9A, 0x61, 0x6E, 0xBA,
+        0x16,
+    ];
+    SymKey::Aes256Cbc { key: KEY, iv: IV }
+};
 
-pub const BLOCK_IV: [u8; 16] = [
-    0xF2, 0xB5, 0x64, 0xF3, 0x82, 0xC6, 0xEC, 0x1E, 0x35, 0xAA, 0x34, 0xD1, 0x40, 0xA3, 0xA8, 0xB3,
-];
+lazy_static! {
+    pub static ref ROOT_CREDS: ConcreteCreds =
+        ConcreteCreds::generate().expect("root cred generation failed");
+    pub static ref NODE_CREDS: ConcreteCreds =
+        ConcreteCreds::generate().expect("node cred generation failed");
+}
 
 /// Converts the given error to a serde_block_tree error by turning it into a message.
 fn convert_err<E: Display>(err: E) -> Error {
@@ -392,15 +99,23 @@ pub(crate) fn make_path(rel_components: Vec<&str>) -> Path {
     make_path_with_owner(make_principal(), rel_components)
 }
 
-pub(crate) fn make_writecap(rel_components: Vec<&str>) -> Writecap {
+pub(crate) fn make_writecap_and_creds(rel_components: Vec<&str>) -> (Writecap, impl Creds) {
     let (root_writecap, root_key) = make_self_signed_writecap();
     let issued_to = Principal(Hash::Sha2_256(PRINCIPAL));
-    make_writecap_trusted_by(root_writecap, root_key, issued_to, rel_components)
+    (
+        make_writecap_trusted_by(root_writecap, &root_key, issued_to, rel_components),
+        root_key,
+    )
+}
+
+pub(crate) fn make_writecap(rel_components: Vec<&str>) -> Writecap {
+    let (writecap, ..) = make_writecap_and_creds(rel_components);
+    writecap
 }
 
 pub(crate) fn make_writecap_trusted_by<C: Creds>(
     next: Writecap,
-    trusting_creds: C,
+    trusting_creds: &C,
     issued_to: Principal,
     path_components: Vec<&str>,
 ) -> Writecap {
@@ -413,27 +128,14 @@ pub(crate) fn make_writecap_trusted_by<C: Creds>(
         signature: Signature::empty(Sign::RSA_PSS_3072_SHA_256),
         next: Some(Box::from(next)),
     };
-    crypto::sign_writecap(&mut writecap, &trusting_creds)
+    crypto::sign_writecap(&mut writecap, trusting_creds)
         .map_err(convert_err)
         .expect("failed to sign writecap");
     writecap
 }
 
 pub(crate) fn make_key_pair() -> impl Creds {
-    let sign = AsymKeyPair::new(
-        Sign::RSA_PSS_3072_SHA_256,
-        ROOT_PUBLIC_KEY.as_slice(),
-        ROOT_PRIVATE_KEY.as_slice(),
-    )
-    .unwrap();
-    // Using the same key pair is terrible in production, but fine for testing.
-    let encrypt = AsymKeyPair::new(
-        Encrypt::RSA_OAEP_3072_SHA_256,
-        ROOT_PUBLIC_KEY.as_slice(),
-        ROOT_PRIVATE_KEY.as_slice(),
-    )
-    .unwrap();
-    ConcreteCreds::new(sign, encrypt)
+    ROOT_CREDS.clone()
 }
 
 pub(crate) fn make_self_signed_writecap() -> (Writecap, impl Creds) {
@@ -459,31 +161,38 @@ pub(crate) fn make_self_signed_writecap_with<C: Creds>(key: &C) -> Writecap {
 }
 
 pub(crate) fn make_readcap() -> Readcap {
-    Readcap::new(
-        Hash::Sha2_256(PRINCIPAL),
-        Cryptotext::Plain(SymKey::Aes256Ctr { key: KEY, iv: IV }),
-    )
+    make_readcap_for(&*ROOT_CREDS)
+}
+
+pub(crate) fn make_readcap_for<C: Encrypter + Owned>(creds: &C) -> Readcap {
+    Readcap {
+        issued_to: creds.owner(),
+        key: crypto::encrypt(&BLOCK_KEY, creds).expect("failed to encrypt block key"),
+    }
 }
 
-pub(crate) fn make_block() -> Block<SerdeCursor<Vec<u8>>> {
+pub(crate) fn make_block() -> Block<SerdeCursor<Vec<u8>>, impl Creds> {
     make_block_with(make_readcap())
 }
 
-pub(crate) fn make_block_with(readcap: Readcap) -> Block<SerdeCursor<Vec<u8>>> {
+pub(crate) fn make_block_with(readcap: Readcap) -> Block<SerdeCursor<Vec<u8>>, impl Creds> {
     let mut readcaps = HashMap::new();
     readcaps.insert(readcap.issued_to, readcap.key);
     // Notice that the writecap path contains the block path. If this were not the case, the block
     // would be invalid.
-    let writecap = make_writecap(vec!["apps"]);
+    let (writecap, creds) = make_writecap_and_creds(vec!["apps"]);
     let root_writecap = writecap.next.as_ref().unwrap();
     Block {
-        header: Header {
-            path: make_path_with_owner(root_writecap.issued_to.clone(), vec!["apps", "verse"]),
-            readcaps,
-            writecap,
-            merkle_root: Hash::Sha2_256([0u8; HashKind::Sha2_256.len()]),
-        },
-        sig: Signature::copy_from(Sign::RSA_PSS_3072_SHA_256, &SIGNATURE),
+        shared: Arc::new(RwLock::new(BlockShared {
+            header: Header {
+                path: make_path_with_owner(root_writecap.issued_to.clone(), vec!["apps", "verse"]),
+                readcaps,
+                writecap,
+                merkle_root: Hash::Sha2_256([0u8; HashKind::Sha2_256.len()]),
+            },
+            sig: Signature::copy_from(Sign::RSA_PSS_3072_SHA_256, &SIGNATURE),
+            creds,
+        })),
         body: SerdeCursor::new(Vec::new()),
     }
 }

+ 69 - 55
crates/btserde/src/de.rs

@@ -1,15 +1,8 @@
+use super::error::{Error, Result};
+use serde::de::{self, Deserialize, DeserializeOwned, DeserializeSeed, IntoDeserializer, Visitor};
 use std::convert::TryFrom;
-use std::str;
 use std::io::Read;
-use super::error::{Error, Result};
-use serde::de::{
-    self,
-    Deserialize,
-    DeserializeOwned,
-    Visitor,
-    DeserializeSeed,
-    IntoDeserializer
-};
+use std::str;
 
 // This lint is disabled because deserializing from a `&[u8]` is handled by `read_from`.
 #[allow(clippy::ptr_arg)]
@@ -36,7 +29,7 @@ fn try_from<TSource, TDest: TryFrom<TSource>>(value: TSource) -> Result<TDest> {
 /// encoding begins with the given byte. If the given byte is not valid as the first byte
 /// for any character, then a failed result with Error::InvalidUtf8Char is returned.
 fn num_bytes_for_char(first_byte: u8) -> Result<usize> {
-    if first_byte & 128u8 == 0  {
+    if first_byte & 128u8 == 0 {
         return Ok(1);
     }
     for bit in 2..5 {
@@ -59,7 +52,7 @@ fn u32_from_utf8(buf: &[u8]) -> Result<u32> {
     }
 
     fn two_bytes(buf: &[u8]) -> u32 {
-       mask(buf[0], 0b0001_1111) << 6 | mask(buf[1], MASK)
+        mask(buf[0], 0b0001_1111) << 6 | mask(buf[1], MASK)
     }
 
     fn three_bytes(buf: &[u8]) -> u32 {
@@ -67,7 +60,9 @@ fn u32_from_utf8(buf: &[u8]) -> Result<u32> {
     }
 
     fn four_bytes(buf: &[u8]) -> u32 {
-        mask(buf[0], 0b0000_0111) << 18 | mask(buf[1], MASK) << 12 | mask(buf[2], MASK) << 6
+        mask(buf[0], 0b0000_0111) << 18
+            | mask(buf[1], MASK) << 12
+            | mask(buf[2], MASK) << 6
             | mask(buf[3], MASK)
     }
 
@@ -76,7 +71,7 @@ fn u32_from_utf8(buf: &[u8]) -> Result<u32> {
         2 => Some(two_bytes(buf)),
         3 => Some(three_bytes(buf)),
         4 => Some(four_bytes(buf)),
-        _ => None
+        _ => None,
     };
     code_point.ok_or(Error::InvalidUtf8Char)
 }
@@ -159,7 +154,9 @@ impl<'de, 'a, T: Read> de::Deserializer<'de> for &'a mut Deserializer<'de, T> {
     type Error = Error;
 
     fn deserialize_any<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value> {
-        Err(Error::Message("deserialize_any is not supported".to_string()))
+        Err(Error::Message(
+            "deserialize_any is not supported".to_string(),
+        ))
     }
 
     fn deserialize_bool<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
@@ -256,8 +253,7 @@ impl<'de, 'a, T: Read> de::Deserializer<'de> for &'a mut Deserializer<'de, T> {
         let some = self.read_bool()?;
         if some {
             visitor.visit_some(self)
-        } 
-        else {
+        } else {
             visitor.visit_none()
         }
     }
@@ -267,45 +263,67 @@ impl<'de, 'a, T: Read> de::Deserializer<'de> for &'a mut Deserializer<'de, T> {
     }
 
     fn deserialize_unit_struct<V: Visitor<'de>>(
-        self, _name: &'static str, visitor: V
+        self,
+        _name: &'static str,
+        visitor: V,
     ) -> Result<V::Value> {
         visitor.visit_unit()
     }
 
     fn deserialize_newtype_struct<V: Visitor<'de>>(
-        self, _name: &'static str, visitor: V
+        self,
+        _name: &'static str,
+        visitor: V,
     ) -> Result<V::Value> {
         visitor.visit_newtype_struct(self)
     }
 
     fn deserialize_seq<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
         let len = self.read_u32()?;
-        visitor.visit_seq(SeqAccess { elements_left: len, deserializer: self})
+        visitor.visit_seq(SeqAccess {
+            elements_left: len,
+            deserializer: self,
+        })
     }
 
     fn deserialize_tuple<V: Visitor<'de>>(self, len: usize, visitor: V) -> Result<V::Value> {
-        visitor.visit_seq(SeqAccess { elements_left: try_from(len)?, deserializer: self})
+        visitor.visit_seq(SeqAccess {
+            elements_left: try_from(len)?,
+            deserializer: self,
+        })
     }
 
     fn deserialize_tuple_struct<V: Visitor<'de>>(
-        self, _name: &'static str, len: usize, visitor: V
+        self,
+        _name: &'static str,
+        len: usize,
+        visitor: V,
     ) -> Result<V::Value> {
         self.deserialize_tuple(len, visitor)
     }
 
     fn deserialize_map<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
         let len = self.read_u32()?;
-        visitor.visit_map(SeqAccess { elements_left: len, deserializer: self})
+        visitor.visit_map(SeqAccess {
+            elements_left: len,
+            deserializer: self,
+        })
     }
 
     fn deserialize_struct<V: Visitor<'de>>(
-        self, _name: &'static str, fields: &'static [&'static str], visitor: V
+        self,
+        _name: &'static str,
+        fields: &'static [&'static str],
+        visitor: V,
     ) -> Result<V::Value> {
         self.deserialize_tuple(fields.len(), visitor)
     }
 
     fn deserialize_enum<V: Visitor<'de>>(
-        self, _name: &'static str, _variants: &'static [&'static str], visitor: V
+        self,
+        _name: &'static str,
+        _variants: &'static [&'static str],
+        visitor: V,
     ) -> Result<V::Value> {
         visitor.visit_enum(self)
     }
@@ -325,7 +343,7 @@ impl<'de, 'a, T: Read> de::Deserializer<'de> for &'a mut Deserializer<'de, T> {
 
 struct SeqAccess<'a, 'de, T: Read> {
     elements_left: u32,
-    deserializer: &'a mut Deserializer<'de, T>
+    deserializer: &'a mut Deserializer<'de, T>,
 }
 
 impl<'a, 'de, T: Read> de::SeqAccess<'de> for SeqAccess<'a, 'de, T> {
@@ -333,7 +351,7 @@ impl<'a, 'de, T: Read> de::SeqAccess<'de> for SeqAccess<'a, 'de, T> {
 
     fn next_element_seed<S: DeserializeSeed<'de>>(&mut self, seed: S) -> Result<Option<S::Value>> {
         if 0 == self.elements_left {
-            return Ok(None)
+            return Ok(None);
         }
 
         self.elements_left -= 1;
@@ -346,7 +364,7 @@ impl<'a, 'de, T: Read> de::MapAccess<'de> for SeqAccess<'a, 'de, T> {
 
     fn next_key_seed<S: DeserializeSeed<'de>>(&mut self, seed: S) -> Result<Option<S::Value>> {
         if 0 == self.elements_left {
-            return Ok(None)
+            return Ok(None);
         }
 
         self.elements_left -= 1;
@@ -374,7 +392,9 @@ impl<'de, T: Read> de::VariantAccess<'de> for &mut Deserializer<'de, T> {
     }
 
     fn struct_variant<V: Visitor<'de>>(
-        self, fields: &'static [&'static str], visitor: V
+        self,
+        fields: &'static [&'static str],
+        visitor: V,
     ) -> Result<V::Value> {
         de::Deserializer::deserialize_struct(self, "", fields, visitor)
     }
@@ -383,7 +403,7 @@ impl<'de, T: Read> de::VariantAccess<'de> for &mut Deserializer<'de, T> {
 impl<'de, T: Read> de::EnumAccess<'de> for &mut Deserializer<'de, T> {
     type Error = Error;
     type Variant = Self;
-    
+
     fn variant_seed<S: DeserializeSeed<'de>>(self, seed: S) -> Result<(S::Value, Self::Variant)> {
         let int = self.read_u16()?;
         let index: u32 = try_from(int)?;
@@ -394,15 +414,10 @@ impl<'de, T: Read> de::EnumAccess<'de> for &mut Deserializer<'de, T> {
 
 #[cfg(test)]
 mod test {
+    use super::{from_vec, num_bytes_for_char, Deserializer, Result};
     use serde::Deserialize;
-    use super::{
-        from_vec,
-        num_bytes_for_char,
-        Result,
-        Deserializer
-    };
     use std::collections::HashMap;
-    
+
     #[test]
     fn new() -> Result<()> {
         let vec: Vec<u8> = vec![0xA1, 0x42, 0x71, 0xAC];
@@ -544,8 +559,8 @@ mod test {
     #[test]
     fn deserialize_string() -> Result<()> {
         let vec: Vec<u8> = vec![
-            0x06, 0x00, 0x00, 0x00,
-            'l' as u8, 'o' as u8, 'c' as u8, 'a' as u8, 's' as u8, 'h' as u8
+            0x06, 0x00, 0x00, 0x00, 'l' as u8, 'o' as u8, 'c' as u8, 'a' as u8, 's' as u8,
+            'h' as u8,
         ];
         let result: Result<String> = from_vec(&vec);
         assert_eq!("locash", result?);
@@ -580,8 +595,7 @@ mod test {
     fn deserialize_tuple() -> Result<()> {
         let expected = ("orb".to_string(), 12u16);
         let vec: Vec<u8> = vec![
-            0x03, 0x00, 0x00, 0x00, 'o' as u8, 'r' as u8, 'b' as u8,
-            0x0C, 0x00
+            0x03, 0x00, 0x00, 0x00, 'o' as u8, 'r' as u8, 'b' as u8, 0x0C, 0x00,
         ];
         let result = from_vec(&vec);
         assert_eq!(expected, result?);
@@ -590,15 +604,14 @@ mod test {
 
     #[test]
     fn deserialize_map() -> Result<()> {
-        let expected: HashMap<String, u8> = HashMap::from([
-            ("blue".to_string(), 5), ("red".to_string(), 7)
-        ]);
+        let expected: HashMap<String, u8> =
+            HashMap::from([("blue".to_string(), 5), ("red".to_string(), 7)]);
         let vec: Vec<u8> = vec![
             0x02, 0x00, 0x00, 0x00, // Number of entries in the map.
             0x04, 0x00, 0x00, 0x00, 'b' as u8, 'l' as u8, 'u' as u8, 'e' as u8, // First key.
-            0x05, // First value.
+            0x05,      // First value.
             0x03, 0x00, 0x00, 0x00, 'r' as u8, 'e' as u8, 'd' as u8, // Second key.
-            0x07, // Second value.
+            0x07,      // Second value.
         ];
         let result = from_vec(&vec);
         assert_eq!(expected, result?);
@@ -611,17 +624,15 @@ mod test {
         struct Order {
             customer: String,
             item_id: u16,
-            quantity: u8
+            quantity: u8,
         }
         let expected = Order {
             customer: "Bob".to_string(),
             item_id: 256,
-            quantity: 255
+            quantity: 255,
         };
         let vec: Vec<u8> = vec![
-            0x03, 0x00, 0x00, 0x00, 'B' as u8, 'o' as u8, 'b' as u8,
-            0x00, 0x01,
-            0xFF 
+            0x03, 0x00, 0x00, 0x00, 'B' as u8, 'o' as u8, 'b' as u8, 0x00, 0x01, 0xFF,
         ];
         let result = from_vec(&vec);
         assert_eq!(expected, result?);
@@ -631,7 +642,10 @@ mod test {
     #[test]
     fn deserialize_enum() -> Result<()> {
         #[derive(Debug, PartialEq, Deserialize)]
-        enum Emotions { Anguish, Catharsis }
+        enum Emotions {
+            Anguish,
+            Catharsis,
+        }
         let vec: Vec<u8> = vec![0x01, 0x00];
         let result = from_vec(&vec);
         assert_eq!(Emotions::Catharsis, result?);
@@ -643,17 +657,17 @@ mod test {
         #[derive(Debug, PartialEq, Deserialize)]
         enum Vector {
             Dim2(i32, i32),
-            Dim3(i32, i32, i32)
+            Dim3(i32, i32, i32),
         }
         let expected = Vector::Dim3(1, -1, -2);
         let vec: Vec<u8> = vec![
             0x01, 0x00, // The variant index.
             0x01, 0x00, 0x00, 0x00, // The first entry.
             0xFF, 0xFF, 0xFF, 0xFF, // The second entry.
-            0xFE, 0xFF, 0xFF, 0xFF // The last entry.
+            0xFE, 0xFF, 0xFF, 0xFF, // The last entry.
         ];
         let result = from_vec(&vec);
         assert_eq!(expected, result?);
         Ok(())
     }
-}
+}

+ 23 - 19
crates/btserde/src/dependency_tests.rs

@@ -1,5 +1,5 @@
-use super::{to_vec, from_vec, Result};
-use serde::{Serialize, Deserialize};
+use super::{from_vec, to_vec, Result};
+use serde::{Deserialize, Serialize};
 use serde_big_array::BigArray;
 
 #[test]
@@ -8,7 +8,7 @@ fn test_empty_array_deserialization() -> Result<()> {
     struct Vacuous {
         // Of course you would never actually do this, but it should handle it properly regardless.
         #[serde(with = "BigArray")]
-        nothing: [u8; 0]
+        nothing: [u8; 0],
     }
     let expected = Vacuous { nothing: [0u8; 0] };
     let vec = vec![];
@@ -20,18 +20,20 @@ fn test_empty_array_deserialization() -> Result<()> {
 #[derive(Serialize, Deserialize, Debug, PartialEq)]
 struct S {
     #[serde(with = "BigArray")]
-    array: [u8; 0x40]
+    array: [u8; 0x40],
 }
 
 #[test]
 fn test_big_array_deserialization() -> Result<()> {
-    let expected = S {  array: [
-        0x81, 0xc0, 0xf, 0x3e, 0x2f, 0x11, 0xae, 0xc9, 0x48, 0x68, 0xc4, 0x66, 0x67, 0x1e, 0xda,
-        0x4e, 0xde, 0xf, 0x84, 0x23, 0x4d, 0x24, 0x0, 0x23, 0xe8, 0x84, 0xac, 0xc6, 0x7c, 0xb0,
-        0x34, 0x5, 0xa3, 0xc3, 0x4b, 0x59, 0xaa, 0x96, 0x9f, 0xc6, 0x2d, 0x31, 0x5a, 0xb5, 0x61,
-        0xfd, 0xad, 0x9b, 0x7a, 0xf8, 0xf3, 0xd7, 0xee, 0x4a, 0x86, 0xd7, 0x87, 0x20, 0x33, 0x32,
-        0x12, 0xc9, 0x55, 0x1e
-    ] };
+    let expected = S {
+        array: [
+            0x81, 0xc0, 0xf, 0x3e, 0x2f, 0x11, 0xae, 0xc9, 0x48, 0x68, 0xc4, 0x66, 0x67, 0x1e,
+            0xda, 0x4e, 0xde, 0xf, 0x84, 0x23, 0x4d, 0x24, 0x0, 0x23, 0xe8, 0x84, 0xac, 0xc6, 0x7c,
+            0xb0, 0x34, 0x5, 0xa3, 0xc3, 0x4b, 0x59, 0xaa, 0x96, 0x9f, 0xc6, 0x2d, 0x31, 0x5a,
+            0xb5, 0x61, 0xfd, 0xad, 0x9b, 0x7a, 0xf8, 0xf3, 0xd7, 0xee, 0x4a, 0x86, 0xd7, 0x87,
+            0x20, 0x33, 0x32, 0x12, 0xc9, 0x55, 0x1e,
+        ],
+    };
     let mut vec = vec![0; 0x40];
     vec.copy_from_slice(expected.array.as_slice());
     let result = from_vec(&vec);
@@ -41,16 +43,18 @@ fn test_big_array_deserialization() -> Result<()> {
 
 #[test]
 fn test_big_array_serialization() -> Result<()> {
-    let value = S {  array: [
-        0x81, 0xc0, 0xf, 0x3e, 0x2f, 0x11, 0xae, 0xc9, 0x48, 0x68, 0xc4, 0x66, 0x67, 0x1e, 0xda,
-        0x4e, 0xde, 0xf, 0x84, 0x23, 0x4d, 0x24, 0x0, 0x23, 0xe8, 0x84, 0xac, 0xc6, 0x7c, 0xb0,
-        0x34, 0x5, 0xa3, 0xc3, 0x4b, 0x59, 0xaa, 0x96, 0x9f, 0xc6, 0x2d, 0x31, 0x5a, 0xb5, 0x61,
-        0xfd, 0xad, 0x9b, 0x7a, 0xf8, 0xf3, 0xd7, 0xee, 0x4a, 0x86, 0xd7, 0x87, 0x20, 0x33, 0x32,
-        0x12, 0xc9, 0x55, 0x1e
-    ] };
+    let value = S {
+        array: [
+            0x81, 0xc0, 0xf, 0x3e, 0x2f, 0x11, 0xae, 0xc9, 0x48, 0x68, 0xc4, 0x66, 0x67, 0x1e,
+            0xda, 0x4e, 0xde, 0xf, 0x84, 0x23, 0x4d, 0x24, 0x0, 0x23, 0xe8, 0x84, 0xac, 0xc6, 0x7c,
+            0xb0, 0x34, 0x5, 0xa3, 0xc3, 0x4b, 0x59, 0xaa, 0x96, 0x9f, 0xc6, 0x2d, 0x31, 0x5a,
+            0xb5, 0x61, 0xfd, 0xad, 0x9b, 0x7a, 0xf8, 0xf3, 0xd7, 0xee, 0x4a, 0x86, 0xd7, 0x87,
+            0x20, 0x33, 0x32, 0x12, 0xc9, 0x55, 0x1e,
+        ],
+    };
     let mut expected = vec![0; 0x40];
     expected.copy_from_slice(value.array.as_slice());
     let result = to_vec(&value);
     assert_eq!(expected, result?);
     Ok(())
-}
+}

+ 14 - 11
crates/btserde/src/error.rs

@@ -1,5 +1,5 @@
+use serde::{de, ser};
 use std::fmt::{self, Display};
-use serde::{ser, de};
 
 pub type Result<T> = std::result::Result<T, Error>;
 
@@ -14,7 +14,7 @@ pub enum Error {
     TypeConversion,
     NotSupported(&'static str),
     InvalidUtf8Char,
-    Format(std::fmt::Error)
+    Format(std::fmt::Error),
 }
 
 impl std::error::Error for Error {}
@@ -26,15 +26,18 @@ impl Display for Error {
             Error::Io(io_error) => io_error.fmt(formatter),
             Error::Eof => formatter.write_str("unexpected end of input"),
             Error::UnknownLength => formatter.write_str("sequence had an unknown length"),
-            Error::SequenceTooLong(length) => formatter.write_fmt(
-                format_args!("sequence was longer than 2**32 - 1: {}", length)
-            ),
-            Error::TooManyVariants(length) => formatter.write_fmt(
-                format_args!("too many variants to be serialized, the limit is 2**16: {}", length)
-            ),
+            Error::SequenceTooLong(length) => formatter.write_fmt(format_args!(
+                "sequence was longer than 2**32 - 1: {}",
+                length
+            )),
+            Error::TooManyVariants(length) => formatter.write_fmt(format_args!(
+                "too many variants to be serialized, the limit is 2**16: {}",
+                length
+            )),
             Error::TypeConversion => formatter.write_str("type conversion failed"),
-            Error::NotSupported(message) => formatter.write_fmt(format_args!(
-                "Operation is not supported: {}", message)),
+            Error::NotSupported(message) => {
+                formatter.write_fmt(format_args!("Operation is not supported: {}", message))
+            }
             Error::InvalidUtf8Char => formatter.write_str("Invalid UTF-8 character encountered."),
             Error::Format(fmt_error) => fmt_error.fmt(formatter),
         }
@@ -62,4 +65,4 @@ impl<T> MapError<T> for std::io::Result<T> {
     fn map_error(self) -> Result<T> {
         self.map_err(Error::Io)
     }
-}
+}

+ 2 - 3
crates/btserde/src/lib.rs

@@ -1,8 +1,7 @@
+mod de;
 /// This crate defines a compact binary serialization format for use in the Block Tree system.
-
 mod error;
 mod ser;
-mod de;
 
 #[cfg(test)]
 mod dependency_tests;
@@ -11,4 +10,4 @@ pub use error::{Error, Result};
 
 pub use ser::{to_vec, write_to, Serializer};
 
-pub use de::{from_vec, read_from, Deserializer};
+pub use de::{from_vec, read_from, Deserializer};

+ 96 - 37
crates/btserde/src/ser.rs

@@ -1,20 +1,14 @@
-use std::io::Write;
-use std::convert::TryFrom;
 use serde::{
     ser::{
-        self,
-        SerializeSeq,
-        SerializeTuple,
-        SerializeTupleStruct,
-        SerializeTupleVariant,
-        SerializeMap,
-        SerializeStruct,
-        SerializeStructVariant,       
+        self, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple,
+        SerializeTupleStruct, SerializeTupleVariant,
     },
     Serialize,
 };
+use std::convert::TryFrom;
+use std::io::Write;
 
-use super::error::{Error, Result, MapError};
+use super::error::{Error, MapError, Result};
 
 type Ok = ();
 
@@ -45,7 +39,7 @@ fn try_convert(len: Option<usize>) -> Result<u32> {
         Some(count) => {
             let length = u32::try_from(count).map_err(|_| Error::SequenceTooLong(count))?;
             Ok(length)
-        },
+        }
         None => Err(Error::UnknownLength),
     }
 }
@@ -67,7 +61,9 @@ impl<'a, 'w, T: Write> ser::Serializer for &'a mut Serializer<'w, T> {
 
     /// A bool is serialized by writing the byte 1 if true and 0 if false.
     fn serialize_bool(self, v: bool) -> Result<Self::Ok> {
-        self.output.write_all(&[if v { 1 } else { 0 }]).map_error()?;
+        self.output
+            .write_all(&[if v { 1 } else { 0 }])
+            .map_error()?;
         Ok(())
     }
 
@@ -199,7 +195,10 @@ impl<'a, 'w, T: Write> ser::Serializer for &'a mut Serializer<'w, T> {
 
     /// The index of the unit variant is written to the output.
     fn serialize_unit_variant(
-        self, _name: &'static str, variant_index: u32, _variant: &'static str
+        self,
+        _name: &'static str,
+        variant_index: u32,
+        _variant: &'static str,
     ) -> Result<Self::Ok> {
         let index = convert_variant_index(variant_index)?;
         self.serialize_u16(index)?;
@@ -208,7 +207,9 @@ impl<'a, 'w, T: Write> ser::Serializer for &'a mut Serializer<'w, T> {
 
     /// The value of the newtype struct is serialized and its name is ignored.
     fn serialize_newtype_struct<U: ?Sized + Serialize>(
-        self, _name: &'static str, value: &U
+        self,
+        _name: &'static str,
+        value: &U,
     ) -> Result<Self::Ok> {
         value.serialize(self)?;
         Ok(())
@@ -217,7 +218,11 @@ impl<'a, 'w, T: Write> ser::Serializer for &'a mut Serializer<'w, T> {
     /// The index of the variant is serialized and written out, followed by the serialization of
     /// its value.
     fn serialize_newtype_variant<U: ?Sized + Serialize>(
-        self, _name: &'static str, variant_index: u32, _variant: &'static str, value: &U
+        self,
+        _name: &'static str,
+        variant_index: u32,
+        _variant: &'static str,
+        value: &U,
     ) -> Result<Self::Ok> {
         let index = convert_variant_index(variant_index)?;
         self.serialize_u16(index)?;
@@ -238,14 +243,20 @@ impl<'a, 'w, T: Write> ser::Serializer for &'a mut Serializer<'w, T> {
 
     /// A tuple struct is serialized the same way as a tuple, its name is ignore.
     fn serialize_tuple_struct(
-        self, _name: &'static str, _len: usize
+        self,
+        _name: &'static str,
+        _len: usize,
     ) -> Result<Self::SerializeTupleStruct> {
         Ok(self)
     }
 
     /// The variant index is stored before the tuples values.
     fn serialize_tuple_variant(
-        self, _name: &'static str, variant_index: u32, _variant: &'static str, _len: usize
+        self,
+        _name: &'static str,
+        variant_index: u32,
+        _variant: &'static str,
+        _len: usize,
     ) -> Result<Self::SerializeTupleStruct> {
         let index = convert_variant_index(variant_index)?;
         self.serialize_u16(index)?;
@@ -268,7 +279,11 @@ impl<'a, 'w, T: Write> ser::Serializer for &'a mut Serializer<'w, T> {
 
     /// The variant index is stored before the struct's members.
     fn serialize_struct_variant(
-        self, _name: &'static str, variant_index: u32, _variant: &'static str, _len: usize
+        self,
+        _name: &'static str,
+        variant_index: u32,
+        _variant: &'static str,
+        _len: usize,
     ) -> Result<Self::SerializeStructVariant> {
         let index = convert_variant_index(variant_index)?;
         self.serialize_u16(index)?;
@@ -357,7 +372,10 @@ impl<'a, 'w, W: Write> SerializeStruct for &'a mut Serializer<'w, W> {
     type Error = Error;
 
     fn serialize_field<U: ?Sized + Serialize>(
-        &mut self, _key: &'static str, value: &U) -> Result<Ok> {
+        &mut self,
+        _key: &'static str,
+        value: &U,
+    ) -> Result<Ok> {
         value.serialize(&mut **self)?;
         Ok(())
     }
@@ -372,7 +390,10 @@ impl<'a, 'w, W: Write> SerializeStructVariant for &'a mut Serializer<'w, W> {
     type Error = Error;
 
     fn serialize_field<U: ?Sized + Serialize>(
-        &mut self, _key: &'static str, value: &U) -> Result<Ok> {
+        &mut self,
+        _key: &'static str,
+        value: &U,
+    ) -> Result<Ok> {
         value.serialize(&mut **self)?;
         Ok(())
     }
@@ -462,12 +483,24 @@ mod test {
     fn serialize_i128() -> Result<()> {
         {
             let buffer = super::to_vec(&1i128)?;
-            assert_eq!(vec![0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buffer);
+            assert_eq!(
+                vec![
+                    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                    0x00, 0x00, 0x00
+                ],
+                buffer
+            );
         }
         {
             let value: i128 = -2;
             let buffer = super::to_vec(&value)?;
-            assert_eq!(vec![0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], buffer);
+            assert_eq!(
+                vec![
+                    0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+                    0xFF, 0xFF, 0xFF
+                ],
+                buffer
+            );
         }
         Ok(())
     }
@@ -504,7 +537,13 @@ mod test {
     #[test]
     fn serialize_u128() -> Result<()> {
         let buffer = super::to_vec(&1u128)?;
-        assert_eq!(vec![0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buffer);
+        assert_eq!(
+            vec![
+                0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00
+            ],
+            buffer
+        );
         Ok(())
     }
 
@@ -545,7 +584,10 @@ mod test {
     fn serialize_str() -> Result<()> {
         let message = "vapid 😑";
         let buffer = super::to_vec(message)?;
-        assert_eq!(vec![10, 0, 0, 0, 118, 97, 112, 105, 100, 32, 240, 159, 152, 145], buffer);
+        assert_eq!(
+            vec![10, 0, 0, 0, 118, 97, 112, 105, 100, 32, 240, 159, 152, 145],
+            buffer
+        );
         Ok(())
     }
 
@@ -622,13 +664,13 @@ mod test {
             Usd(i32),
             Btc(i32),
             Fil(i32),
-            Eth(i32)
+            Eth(i32),
         }
         let value = Currency::Fil(1024);
         let buffer = super::to_vec(&value)?;
         let expected = vec![
             0x02, 0x00, // The variant index.
-            0x00, 0x04, 0x00, 0x00  // The value contained within.
+            0x00, 0x04, 0x00, 0x00, // The value contained within.
         ];
         assert_eq!(expected, buffer);
         Ok(())
@@ -642,7 +684,7 @@ mod test {
             Zeroth {},
             First {},
             Second {},
-            Third {}
+            Third {},
         }
         let test = UnitStructVariant::Second {};
         let buffer = super::to_vec(&test)?;
@@ -667,7 +709,7 @@ mod test {
         let expected = vec![
             0xFE, // The value -2.
             0x02, 0x00, 0x00, 0x00, // The length of the string.
-            0x2D, 0x32 // The characters '-' and '2'.
+            0x2D, 0x32, // The characters '-' and '2'.
         ];
         assert_eq!(expected, buffer);
         Ok(())
@@ -698,7 +740,10 @@ mod test {
         use std::collections::HashMap;
 
         #[derive(PartialEq, Eq, Hash, Serialize)]
-        enum Color { Red, Blue }
+        enum Color {
+            Red,
+            Blue,
+        }
         let mut map: HashMap<Color, u16> = HashMap::new();
         map.insert(Color::Red, 5);
         map.insert(Color::Blue, 256);
@@ -721,14 +766,18 @@ mod test {
         struct Bag {
             name: &'static str,
             weight: u16,
-            value: i8
+            value: i8,
         }
-        let value = Bag { name: "box", weight: 10, value: -1 };
+        let value = Bag {
+            name: "box",
+            weight: 10,
+            value: -1,
+        };
         let buffer = super::to_vec(&value)?;
         let expected = vec![
             0x03, 0x00, 0x00, 0x00, 'b' as u8, 'o' as u8, 'x' as u8, // name
             0x0A, 0x00, // weight
-            0xFF // value
+            0xFF, // value
         ];
         assert_eq!(expected, buffer);
         Ok(())
@@ -739,10 +788,20 @@ mod test {
         #[derive(Serialize)]
         #[allow(dead_code)]
         enum Shape {
-            Rectangle { upper_left_corner: (u16, u16), width: u16, height: u16 },
-            Circle { center: (u16, u16), radius: u16 },
+            Rectangle {
+                upper_left_corner: (u16, u16),
+                width: u16,
+                height: u16,
+            },
+            Circle {
+                center: (u16, u16),
+                radius: u16,
+            },
         }
-        let value = Shape::Circle { center: (0x1D42, 0x9FE0), radius: 0xA100 };
+        let value = Shape::Circle {
+            center: (0x1D42, 0x9FE0),
+            radius: 0xA100,
+        };
         let buffer = super::to_vec(&value)?;
         let expected = vec![
             0x01, 0x00, // The variant index.
@@ -752,4 +811,4 @@ mod test {
         assert_eq!(expected, buffer);
         Ok(())
     }
-}
+}

+ 17 - 16
crates/harness/src/lib.rs

@@ -1,12 +1,12 @@
-use serde::{Serialize, Deserialize};
+use btserde::{self, read_from, write_to};
+use log::error;
+use serde::{Deserialize, Serialize};
 use std::{
-    io::{BufWriter, BufReader, prelude::*},
+    io::{prelude::*, BufReader, BufWriter},
     process::{Child, ChildStdin, Command, Stdio},
     sync::mpsc::{channel, Receiver},
-    time::{Duration},
+    time::Duration,
 };
-use btserde::{self, write_to, read_from};
-use log::{error};
 
 #[derive(Serialize, Deserialize, Debug)]
 pub enum Message {
@@ -32,7 +32,7 @@ impl Node {
         let stdin = BufWriter::new(child.stdin.take().unwrap());
         let mut stdout = BufReader::new(child.stdout.take().unwrap());
         let (message_tx, message_rx) = channel();
-        std::thread::spawn(move ||  loop {
+        std::thread::spawn(move || loop {
             match read_from(&mut stdout) {
                 Ok(msg) => {
                     match message_tx.send(msg) {
@@ -40,19 +40,21 @@ impl Node {
                         // Break if the receiver is dead.
                         Err(_) => break,
                     }
-                },
+                }
                 // Break if the child is has exited.
                 Err(btserde::Error::Eof) => break,
-                Err(btserde::Error::Io(io_err)) => {
-                    match io_err.kind() {
-                        std::io::ErrorKind::UnexpectedEof => break,
-                        _ => error!("IO error ocurred: {:?}", io_err),
-                    }
+                Err(btserde::Error::Io(io_err)) => match io_err.kind() {
+                    std::io::ErrorKind::UnexpectedEof => break,
+                    _ => error!("IO error ocurred: {:?}", io_err),
                 },
                 Err(err) => error!("Failed to deserialize child message {:?}", err),
             };
         });
-        Ok(Node { child, stdin, message_rx })
+        Ok(Node {
+            child,
+            stdin,
+            message_rx,
+        })
     }
 
     pub fn send(&mut self, msg: &Message) -> btserde::Result<()> {
@@ -78,11 +80,10 @@ impl Node {
                 let code = status.code();
                 if code == Some(0) {
                     Ok(())
-                }
-                else {
+                } else {
                     Err(NodeHaltError::NonZeroExitCode(code))
                 }
-            },
+            }
             Err(err) => Err(NodeHaltError::Io(err)),
         }
     }

+ 1 - 0
crates/test-harness/src/lib.rs

@@ -0,0 +1 @@
+