checkpoint

This commit is contained in:
John Smith 2022-11-09 17:11:35 -05:00
parent a54da97393
commit e672ae0319
39 changed files with 1676 additions and 423 deletions

94
Cargo.lock generated
View File

@ -672,6 +672,27 @@ version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c"
[[package]]
name = "bytecheck"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d11cac2c12b5adc6570dad2ee1b87eff4955dac476fe12d81e5fdd352e52406f"
dependencies = [
"bytecheck_derive",
"ptr_meta",
]
[[package]]
name = "bytecheck_derive"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13e576ebe98e605500b3c8041bb888e966653577172df6dd97398714eb30b9bf"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.4.3" version = "1.4.3"
@ -3871,6 +3892,26 @@ version = "2.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94"
[[package]]
name = "ptr_meta"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1"
dependencies = [
"ptr_meta_derive",
]
[[package]]
name = "ptr_meta_derive"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "quick-error" name = "quick-error"
version = "1.2.3" version = "1.2.3"
@ -4051,6 +4092,15 @@ dependencies = [
"winapi 0.3.9", "winapi 0.3.9",
] ]
[[package]]
name = "rend"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79af64b4b6362ffba04eef3a4e10829718a4896dac19daa741851c86781edf95"
dependencies = [
"bytecheck",
]
[[package]] [[package]]
name = "resolv-conf" name = "resolv-conf"
version = "0.7.0" version = "0.7.0"
@ -4076,6 +4126,31 @@ dependencies = [
"winapi 0.3.9", "winapi 0.3.9",
] ]
[[package]]
name = "rkyv"
version = "0.7.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cec2b3485b07d96ddfd3134767b8a447b45ea4eb91448d0a35180ec0ffd5ed15"
dependencies = [
"bytecheck",
"hashbrown",
"ptr_meta",
"rend",
"rkyv_derive",
"seahash",
]
[[package]]
name = "rkyv_derive"
version = "0.7.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6eaedadc88b53e36dd32d940ed21ae4d850d5916f2581526921f553a72ac34c4"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "rlp" name = "rlp"
version = "0.5.2" version = "0.5.2"
@ -4274,6 +4349,12 @@ dependencies = [
"untrusted", "untrusted",
] ]
[[package]]
name = "seahash"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
[[package]] [[package]]
name = "secrecy" name = "secrecy"
version = "0.7.0" version = "0.7.0"
@ -4371,6 +4452,15 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "serde_bytes"
version = "0.11.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfc50e8183eeeb6178dcb167ae34a8051d63535023ae38b5d8d12beae193d37b"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "serde_cbor" name = "serde_cbor"
version = "0.11.2" version = "0.11.2"
@ -5477,6 +5567,7 @@ dependencies = [
"backtrace", "backtrace",
"blake3", "blake3",
"bugsalot", "bugsalot",
"bytecheck",
"capnp", "capnp",
"capnpc", "capnpc",
"cfg-if 1.0.0", "cfg-if 1.0.0",
@ -5520,6 +5611,7 @@ dependencies = [
"owo-colors", "owo-colors",
"parking_lot 0.12.1", "parking_lot 0.12.1",
"rand 0.7.3", "rand 0.7.3",
"rkyv",
"rtnetlink", "rtnetlink",
"rusqlite", "rusqlite",
"rust-fsm", "rust-fsm",
@ -5529,7 +5621,7 @@ dependencies = [
"send_wrapper 0.6.0", "send_wrapper 0.6.0",
"serde", "serde",
"serde-big-array", "serde-big-array",
"serde_cbor", "serde_bytes",
"serde_json", "serde_json",
"serial_test", "serial_test",
"simplelog 0.12.0", "simplelog 0.12.0",

View File

@ -59,6 +59,9 @@ rtnetlink = { version = "^0", default-features = false, optional = true }
async-std-resolver = { version = "^0", optional = true } async-std-resolver = { version = "^0", optional = true }
trust-dns-resolver = { version = "^0", optional = true } trust-dns-resolver = { version = "^0", optional = true }
keyvaluedb = { path = "../external/keyvaluedb/keyvaluedb" } keyvaluedb = { path = "../external/keyvaluedb/keyvaluedb" }
serde_bytes = { version = "^0" }
rkyv = { version = "^0", default_features = false, features = ["std", "alloc", "strict", "size_64", "archive_le", "validation"] }
bytecheck = "^0"
# Dependencies for native builds only # Dependencies for native builds only
# Linux, Windows, Mac, iOS, Android # Linux, Windows, Mac, iOS, Android
@ -82,7 +85,6 @@ futures-util = { version = "^0", default-features = false, features = ["async-aw
keyvaluedb-sqlite = { path = "../external/keyvaluedb/keyvaluedb-sqlite" } keyvaluedb-sqlite = { path = "../external/keyvaluedb/keyvaluedb-sqlite" }
data-encoding = { version = "^2" } data-encoding = { version = "^2" }
serde = { version = "^1", features = ["derive" ] } serde = { version = "^1", features = ["derive" ] }
serde_cbor = { version = "^0" }
serde_json = { version = "^1" } serde_json = { version = "^1" }
socket2 = "^0" socket2 = "^0"
bugsalot = "^0" bugsalot = "^0"
@ -99,7 +101,6 @@ no-std-net = { path = "../external/no-std-net", features = ["serde"] }
keyvaluedb-web = { path = "../external/keyvaluedb/keyvaluedb-web" } keyvaluedb-web = { path = "../external/keyvaluedb/keyvaluedb-web" }
data-encoding = { version = "^2", default_features = false, features = ["alloc"] } data-encoding = { version = "^2", default_features = false, features = ["alloc"] }
serde = { version = "^1", default-features = false, features = ["derive", "alloc"] } serde = { version = "^1", default-features = false, features = ["derive", "alloc"] }
serde_cbor = { version = "^0", default-features = false, features = ["alloc"] }
serde_json = { version = "^1", default-features = false, features = ["alloc"] } serde_json = { version = "^1", default-features = false, features = ["alloc"] }
getrandom = { version = "^0", features = ["js"] } getrandom = { version = "^0", features = ["js"] }
ws_stream_wasm = "^0" ws_stream_wasm = "^0"

View File

@ -173,7 +173,7 @@ struct ValueKey {
# } # }
struct ValueData { struct ValueData {
data @0 :Data; # value or subvalue contents in CBOR format data @0 :Data; # value or subvalue contents
seq @1 :ValueSeqNum; # sequence number of value seq @1 :ValueSeqNum; # sequence number of value
} }
@ -181,9 +181,10 @@ struct ValueData {
############################## ##############################
enum NetworkClass { enum NetworkClass {
inboundCapable @0; # I = Inbound capable without relay, may require signal invalid @0; # X = Invalid network class, network is not yet set up
outboundOnly @1; # O = Outbound only, inbound relay required except with reverse connect signal inboundCapable @1; # I = Inbound capable without relay, may require signal
webApp @2; # W = PWA, outbound relay is required in most cases outboundOnly @2; # O = Outbound only, inbound relay required except with reverse connect signal
webApp @3; # W = PWA, outbound relay is required in most cases
} }
enum DialInfoClass { enum DialInfoClass {
@ -232,6 +233,10 @@ struct AddressTypeSet {
ipv6 @1 :Bool; ipv6 @1 :Bool;
} }
struct SenderInfo {
socketAddress @0 :SocketAddress; # socket address that for the sending peer
}
struct NodeInfo { struct NodeInfo {
networkClass @0 :NetworkClass; # network class of this node networkClass @0 :NetworkClass; # network class of this node
outboundProtocols @1 :ProtocolTypeSet; # protocols that can go outbound outboundProtocols @1 :ProtocolTypeSet; # protocols that can go outbound
@ -239,17 +244,27 @@ struct NodeInfo {
minVersion @3 :UInt8; # minimum protocol version for rpc minVersion @3 :UInt8; # minimum protocol version for rpc
maxVersion @4 :UInt8; # maximum protocol version for rpc maxVersion @4 :UInt8; # maximum protocol version for rpc
dialInfoDetailList @5 :List(DialInfoDetail); # inbound dial info details for this node dialInfoDetailList @5 :List(DialInfoDetail); # inbound dial info details for this node
relayPeerInfo @6 :PeerInfo; # (optional) relay peer info for this node }
struct SignedDirectNodeInfo {
nodeInfo @0 :NodeInfo; # node info
timestamp @1 :UInt64; # when signed node info was generated
signature @2 :Signature; # signature
}
struct SignedRelayedNodeInfo {
nodeInfo @0 :NodeInfo; # node info
relayId @1 :NodeID; # node id for relay
relayInfo @2 :SignedDirectNodeInfo; # signed node info for relay
timestamp @3 :UInt64; # when signed node info was generated
signature @4 :Signature; # signature
} }
struct SignedNodeInfo { struct SignedNodeInfo {
nodeInfo @0 :NodeInfo; # node info union {
signature @1 :Signature; # signature direct @0 :SignedDirectNodeInfo; # node info for nodes reachable without a relay
timestamp @2 :UInt64; # when signed node info was generated relayed @1 :SignedRelayedNodeInfo; # node info for nodes requiring a relay
} }
struct SenderInfo {
socketAddress @0 :SocketAddress; # socket address that for the sending peer
} }
struct PeerInfo { struct PeerInfo {
@ -326,7 +341,7 @@ struct OperationGetValueA {
struct OperationSetValueQ { struct OperationSetValueQ {
key @0 :ValueKey; # key for value to update key @0 :ValueKey; # key for value to update
value @1 :ValueData; # value or subvalue contents in CBOR format (older or equal seq number gets dropped) value @1 :ValueData; # value or subvalue contents (older or equal seq number gets dropped)
} }
struct OperationSetValueA { struct OperationSetValueA {
@ -347,7 +362,7 @@ struct OperationWatchValueA {
struct OperationValueChanged { struct OperationValueChanged {
key @0 :ValueKey; # key for value that changed key @0 :ValueKey; # key for value that changed
value @1 :ValueData; # value or subvalue contents in CBOR format with sequence number value @1 :ValueData; # value or subvalue contents with sequence number
} }
struct OperationSupplyBlockQ { struct OperationSupplyBlockQ {

View File

@ -9,7 +9,7 @@ use core::fmt;
use serde::*; use serde::*;
state_machine! { state_machine! {
derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize) derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize, RkyvArchive, RkyvSerialize, RkyvDeserialize,)
pub Attachment(Detached) pub Attachment(Detached)
//--- //---
Detached(AttachRequested) => Attaching [StartAttachment], Detached(AttachRequested) => Attaching [StartAttachment],

View File

@ -12,7 +12,6 @@ use digest::generic_array::typenum::U64;
use digest::{Digest, Output}; use digest::{Digest, Output};
use ed25519_dalek::{Keypair, PublicKey, Signature}; use ed25519_dalek::{Keypair, PublicKey, Signature};
use generic_array::GenericArray; use generic_array::GenericArray;
use serde::{Deserialize, Serialize};
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -39,13 +38,14 @@ pub const DHT_SIGNATURE_LENGTH_ENCODED: usize = 86;
macro_rules! byte_array_type { macro_rules! byte_array_type {
($name:ident, $size:expr) => { ($name:ident, $size:expr) => {
#[derive(Clone, Copy)] #[derive(Clone, Copy, RkyvArchive, RkyvSerialize, RkyvDeserialize)]
#[archive_attr(repr(C), derive(CheckBytes))]
pub struct $name { pub struct $name {
pub bytes: [u8; $size], pub bytes: [u8; $size],
pub valid: bool, pub valid: bool,
} }
impl Serialize for $name { impl serde::Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where where
S: serde::Serializer, S: serde::Serializer,
@ -56,16 +56,16 @@ macro_rules! byte_array_type {
} else { } else {
s = "".to_owned(); s = "".to_owned();
} }
s.serialize(serializer) serde::Serialize::serialize(&s, serializer)
} }
} }
impl<'de> Deserialize<'de> for $name { impl<'de> serde::Deserialize<'de> for $name {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: serde::Deserializer<'de>, D: serde::Deserializer<'de>,
{ {
let s = String::deserialize(deserializer)?; let s = <String as serde::Deserialize>::deserialize(deserializer)?;
if s == "" { if s == "" {
return Ok($name::default()); return Ok($name::default());
} }

View File

@ -2,7 +2,6 @@ use crate::xx::*;
use crate::*; use crate::*;
use data_encoding::BASE64URL_NOPAD; use data_encoding::BASE64URL_NOPAD;
use keyring_manager::*; use keyring_manager::*;
use serde::{Deserialize, Serialize};
use std::path::Path; use std::path::Path;
pub struct ProtectedStoreInner { pub struct ProtectedStoreInner {
@ -144,18 +143,31 @@ impl ProtectedStore {
} }
#[instrument(level = "trace", skip(self, value))] #[instrument(level = "trace", skip(self, value))]
pub async fn save_user_secret_cbor<T>(&self, key: &str, value: &T) -> EyreResult<bool> pub async fn save_user_secret_rkyv<T>(&self, key: &str, value: &T) -> EyreResult<bool>
where where
T: Serialize, T: RkyvSerialize<rkyv::ser::serializers::AllocSerializer<1024>>,
{ {
let v = serde_cbor::to_vec(value).wrap_err("couldn't store as CBOR")?; let v = to_rkyv(value)?;
self.save_user_secret(&key, &v).await
}
#[instrument(level = "trace", skip(self, value))]
pub async fn save_user_secret_json<T>(&self, key: &str, value: &T) -> EyreResult<bool>
where
T: serde::Serialize,
{
let v = serde_json::to_vec(value)?;
self.save_user_secret(&key, &v).await self.save_user_secret(&key, &v).await
} }
#[instrument(level = "trace", skip(self))] #[instrument(level = "trace", skip(self))]
pub async fn load_user_secret_cbor<T>(&self, key: &str) -> EyreResult<Option<T>> pub async fn load_user_secret_rkyv<T>(&self, key: &str) -> EyreResult<Option<T>>
where where
T: for<'de> Deserialize<'de>, T: RkyvArchive,
<T as RkyvArchive>::Archived:
for<'t> bytecheck::CheckBytes<rkyv::validation::validators::DefaultValidator<'t>>,
<T as RkyvArchive>::Archived:
rkyv::Deserialize<T, rkyv::de::deserializers::SharedDeserializeMap>,
{ {
let out = self.load_user_secret(key).await?; let out = self.load_user_secret(key).await?;
let b = match out { let b = match out {
@ -165,7 +177,24 @@ impl ProtectedStore {
} }
}; };
let obj = serde_cbor::from_slice::<T>(&b).wrap_err("failed to deserialize")?; let obj = from_rkyv(b)?;
Ok(Some(obj))
}
#[instrument(level = "trace", skip(self))]
pub async fn load_user_secret_json<T>(&self, key: &str) -> EyreResult<Option<T>>
where
T: for<'de> serde::de::Deserialize<'de>,
{
let out = self.load_user_secret(key).await?;
let b = match out {
Some(v) => v,
None => {
return Ok(None);
}
};
let obj = serde_json::from_slice(&b)?;
Ok(Some(obj)) Ok(Some(obj))
} }

View File

@ -85,12 +85,25 @@ impl TableDB {
db.write(dbt).wrap_err("failed to store key") db.write(dbt).wrap_err("failed to store key")
} }
/// Store a key in CBOR format with a value in a column in the TableDB. Performs a single transaction immediately. /// Store a key in rkyv format with a value in a column in the TableDB. Performs a single transaction immediately.
pub fn store_cbor<T>(&self, col: u32, key: &[u8], value: &T) -> EyreResult<()> pub fn store_rkyv<T>(&self, col: u32, key: &[u8], value: &T) -> EyreResult<()>
where where
T: Serialize, T: RkyvSerialize<rkyv::ser::serializers::AllocSerializer<1024>>,
{ {
let v = serde_cbor::to_vec(value).wrap_err("couldn't store as CBOR")?; let v = to_rkyv(value)?;
let db = &self.inner.lock().database;
let mut dbt = db.transaction();
dbt.put(col, key, v.as_slice());
db.write(dbt).wrap_err("failed to store key")
}
/// Store a key in json format with a value in a column in the TableDB. Performs a single transaction immediately.
pub fn store_json<T>(&self, col: u32, key: &[u8], value: &T) -> EyreResult<()>
where
T: serde::Serialize,
{
let v = serde_json::to_vec(value)?;
let db = &self.inner.lock().database; let db = &self.inner.lock().database;
let mut dbt = db.transaction(); let mut dbt = db.transaction();
@ -104,10 +117,14 @@ impl TableDB {
db.get(col, key).wrap_err("failed to get key") db.get(col, key).wrap_err("failed to get key")
} }
/// Read a key from a column in the TableDB immediately, in CBOR format. /// Read an rkyv key from a column in the TableDB immediately
pub fn load_cbor<T>(&self, col: u32, key: &[u8]) -> EyreResult<Option<T>> pub fn load_rkyv<T>(&self, col: u32, key: &[u8]) -> EyreResult<Option<T>>
where where
T: for<'de> Deserialize<'de>, T: RkyvArchive,
<T as RkyvArchive>::Archived:
for<'t> bytecheck::CheckBytes<rkyv::validation::validators::DefaultValidator<'t>>,
<T as RkyvArchive>::Archived:
rkyv::Deserialize<T, rkyv::de::deserializers::SharedDeserializeMap>,
{ {
let db = &self.inner.lock().database; let db = &self.inner.lock().database;
let out = db.get(col, key).wrap_err("failed to get key")?; let out = db.get(col, key).wrap_err("failed to get key")?;
@ -117,7 +134,24 @@ impl TableDB {
return Ok(None); return Ok(None);
} }
}; };
let obj = serde_cbor::from_slice::<T>(&b).wrap_err("failed to deserialize")?; let obj = from_rkyv(b)?;
Ok(Some(obj))
}
/// Read an serde-json key from a column in the TableDB immediately
pub fn load_json<T>(&self, col: u32, key: &[u8]) -> EyreResult<Option<T>>
where
T: for<'de> serde::Deserialize<'de>,
{
let db = &self.inner.lock().database;
let out = db.get(col, key).wrap_err("failed to get key")?;
let b = match out {
Some(v) => v,
None => {
return Ok(None);
}
};
let obj = serde_json::from_slice(&b)?;
Ok(Some(obj)) Ok(Some(obj))
} }
@ -176,12 +210,22 @@ impl<'a> TableDBTransaction<'a> {
self.dbt.as_mut().unwrap().put(col, key, value); self.dbt.as_mut().unwrap().put(col, key, value);
} }
/// Store a key in CBOR format with a value in a column in the TableDB /// Store a key in rkyv format with a value in a column in the TableDB
pub fn store_cbor<T>(&mut self, col: u32, key: &[u8], value: &T) -> EyreResult<()> pub fn store_rkyv<T>(&mut self, col: u32, key: &[u8], value: &T) -> EyreResult<()>
where
T: RkyvSerialize<rkyv::ser::serializers::AllocSerializer<1024>>,
{
let v = to_rkyv(value)?;
self.dbt.as_mut().unwrap().put(col, key, v.as_slice());
Ok(())
}
/// Store a key in rkyv format with a value in a column in the TableDB
pub fn store_json<T>(&mut self, col: u32, key: &[u8], value: &T) -> EyreResult<()>
where where
T: Serialize, T: Serialize,
{ {
let v = serde_cbor::to_vec(value).wrap_err("couldn't store as CBOR")?; let v = serde_json::to_vec(value)?;
self.dbt.as_mut().unwrap().put(col, key, v.as_slice()); self.dbt.as_mut().unwrap().put(col, key, v.as_slice());
Ok(()) Ok(())
} }

View File

@ -136,18 +136,22 @@ impl ProtectedStore {
} }
#[instrument(level = "trace", skip(self, value))] #[instrument(level = "trace", skip(self, value))]
pub async fn save_user_secret_cbor<T>(&self, key: &str, value: &T) -> EyreResult<bool> pub async fn save_user_secret_frozen<T>(&self, key: &str, value: &T) -> EyreResult<bool>
where where
T: Serialize, T: RkyvSerialize<rkyv::ser::serializers::AllocSerializer<1024>>,
{ {
let v = serde_cbor::to_vec(value).wrap_err("couldn't store as CBOR")?; let v = to_frozen(value)?;
self.save_user_secret(&key, &v).await self.save_user_secret(&key, &v).await
} }
#[instrument(level = "trace", skip(self))] #[instrument(level = "trace", skip(self))]
pub async fn load_user_secret_cbor<T>(&self, key: &str) -> EyreResult<Option<T>> pub async fn load_user_secret_frozen<T>(&self, key: &str) -> EyreResult<Option<T>>
where where
T: for<'de> Deserialize<'de>, T: RkyvArchive,
<T as RkyvArchive>::Archived:
for<'t> bytecheck::CheckBytes<rkyv::validation::validators::DefaultValidator<'t>>,
<T as RkyvArchive>::Archived:
rkyv::Deserialize<T, rkyv::de::deserializers::SharedDeserializeMap>,
{ {
let out = self.load_user_secret(key).await?; let out = self.load_user_secret(key).await?;
let b = match out { let b = match out {
@ -157,7 +161,7 @@ impl ProtectedStore {
} }
}; };
let obj = serde_cbor::from_slice::<T>(&b).wrap_err("failed to deserialize")?; let obj = from_frozen(&b)?;
Ok(Some(obj)) Ok(Some(obj))
} }

View File

@ -295,7 +295,7 @@ impl NetworkManager {
if let Some(nr) = routing_table.register_node_with_signed_node_info( if let Some(nr) = routing_table.register_node_with_signed_node_info(
RoutingDomain::PublicInternet, RoutingDomain::PublicInternet,
k, k,
SignedNodeInfo::with_no_signature(NodeInfo { SignedDirectNodeInfo::with_no_signature(NodeInfo {
network_class: NetworkClass::InboundCapable, // Bootstraps are always inbound capable network_class: NetworkClass::InboundCapable, // Bootstraps are always inbound capable
outbound_protocols: ProtocolTypeSet::only(ProtocolType::UDP), // Bootstraps do not participate in relaying and will not make outbound requests, but will have UDP enabled outbound_protocols: ProtocolTypeSet::only(ProtocolType::UDP), // Bootstraps do not participate in relaying and will not make outbound requests, but will have UDP enabled
address_types: AddressTypeSet::all(), // Bootstraps are always IPV4 and IPV6 capable address_types: AddressTypeSet::all(), // Bootstraps are always IPV4 and IPV6 capable

View File

@ -8,7 +8,19 @@ pub struct Bucket {
} }
pub(super) type EntriesIter<'a> = alloc::collections::btree_map::Iter<'a, DHTKey, Arc<BucketEntry>>; pub(super) type EntriesIter<'a> = alloc::collections::btree_map::Iter<'a, DHTKey, Arc<BucketEntry>>;
type BucketData = (Vec<(DHTKey, Vec<u8>)>, Option<DHTKey>); #[derive(Debug, RkyvArchive, RkyvSerialize, RkyvDeserialize)]
#[archive_attr(repr(C), derive(CheckBytes))]
struct BucketEntryData {
key: DHTKey,
value: Vec<u8>,
}
#[derive(Debug, RkyvArchive, RkyvSerialize, RkyvDeserialize)]
#[archive_attr(repr(C), derive(CheckBytes))]
struct BucketData {
entries: Vec<BucketEntryData>,
newest_entry: Option<DHTKey>,
}
fn state_ordering(state: BucketEntryState) -> usize { fn state_ordering(state: BucketEntryState) -> usize {
match state { match state {
@ -27,29 +39,33 @@ impl Bucket {
} }
} }
pub(super) fn load_bucket(&mut self, data: &[u8]) -> EyreResult<()> { pub(super) fn load_bucket(&mut self, data: Vec<u8>) -> EyreResult<()> {
let bucket_data: BucketData = let bucket_data: BucketData = from_rkyv(data)?;
serde_cbor::from_slice::<BucketData>(data).wrap_err("failed to deserialize bucket")?;
for (k, d) in bucket_data.0 { for e in bucket_data.entries {
let entryinner = serde_cbor::from_slice::<BucketEntryInner>(&d) let entryinner = from_rkyv(e.value).wrap_err("failed to deserialize bucket entry")?;
.wrap_err("failed to deserialize bucket entry")?;
self.entries self.entries
.insert(k, Arc::new(BucketEntry::new_with_inner(entryinner))); .insert(e.key, Arc::new(BucketEntry::new_with_inner(entryinner)));
} }
self.newest_entry = bucket_data.1; self.newest_entry = bucket_data.newest_entry;
Ok(()) Ok(())
} }
pub(super) fn save_bucket(&self) -> EyreResult<Vec<u8>> { pub(super) fn save_bucket(&self) -> EyreResult<Vec<u8>> {
let mut entry_vec = Vec::new(); let mut entries = Vec::new();
for (k, v) in &self.entries { for (k, v) in &self.entries {
let entry_bytes = v.with_mut_inner(|e| serde_cbor::to_vec(e))?; let entry_bytes = v.with_inner(|e| to_rkyv(e))?;
entry_vec.push((*k, entry_bytes)); entries.push(BucketEntryData {
key: *k,
value: entry_bytes,
});
} }
let bucket_data: BucketData = (entry_vec, self.newest_entry.clone()); let bucket_data = BucketData {
let out = serde_cbor::to_vec(&bucket_data)?; entries,
newest_entry: self.newest_entry.clone(),
};
let out = to_rkyv(&bucket_data)?;
Ok(out) Ok(out)
} }

View File

@ -64,22 +64,44 @@ pub struct BucketEntryLocalNetwork {
node_status: Option<LocalNetworkNodeStatus>, node_status: Option<LocalNetworkNodeStatus>,
} }
/// A range of cryptography versions supported by this entry
#[derive(Debug, Serialize, Deserialize)]
pub struct VersionRange {
/// The minimum cryptography version supported by this entry
min: u8,
/// The maximum cryptography version supported by this entry
max: u8,
}
/// The data associated with each bucket entry
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct BucketEntryInner { pub struct BucketEntryInner {
min_max_version: Option<(u8, u8)>, /// The minimum and maximum range of cryptography versions supported by the node,
/// inclusive of the requirements of any relay the node may be using
min_max_version: Option<VersionRange>,
/// Whether or not we have updated this peer with our node info since our network
/// and dial info has last changed, for example when our IP address changes
updated_since_last_network_change: bool, updated_since_last_network_change: bool,
/// The last connection descriptors used to contact this node, per protocol type
#[serde(skip)] #[serde(skip)]
last_connections: BTreeMap<LastConnectionKey, (ConnectionDescriptor, u64)>, last_connections: BTreeMap<LastConnectionKey, (ConnectionDescriptor, u64)>,
/// The node info for this entry on the publicinternet routing domain
public_internet: BucketEntryPublicInternet, public_internet: BucketEntryPublicInternet,
/// The node info for this entry on the localnetwork routing domain
local_network: BucketEntryLocalNetwork, local_network: BucketEntryLocalNetwork,
/// Statistics gathered for the peer
peer_stats: PeerStats, peer_stats: PeerStats,
/// The accounting for the latency statistics
#[serde(skip)] #[serde(skip)]
latency_stats_accounting: LatencyStatsAccounting, latency_stats_accounting: LatencyStatsAccounting,
/// The accounting for the transfer statistics
#[serde(skip)] #[serde(skip)]
transfer_stats_accounting: TransferStatsAccounting, transfer_stats_accounting: TransferStatsAccounting,
/// Tracking identifier for NodeRef debugging
#[cfg(feature = "tracking")] #[cfg(feature = "tracking")]
#[serde(skip)] #[serde(skip)]
next_track_id: usize, next_track_id: usize,
/// Backtraces for NodeRef debugging
#[cfg(feature = "tracking")] #[cfg(feature = "tracking")]
#[serde(skip)] #[serde(skip)]
node_ref_tracks: HashMap<usize, backtrace::Backtrace>, node_ref_tracks: HashMap<usize, backtrace::Backtrace>,
@ -190,12 +212,12 @@ impl BucketEntryInner {
// Always allow overwriting invalid/unsigned node // Always allow overwriting invalid/unsigned node
if current_sni.has_valid_signature() { if current_sni.has_valid_signature() {
// If the timestamp hasn't changed or is less, ignore this update // If the timestamp hasn't changed or is less, ignore this update
if signed_node_info.timestamp <= current_sni.timestamp { if signed_node_info.timestamp() <= current_sni.timestamp() {
// If we received a node update with the same timestamp // If we received a node update with the same timestamp
// we can make this node live again, but only if our network has recently changed // we can make this node live again, but only if our network has recently changed
// which may make nodes that were unreachable now reachable with the same dialinfo // which may make nodes that were unreachable now reachable with the same dialinfo
if !self.updated_since_last_network_change if !self.updated_since_last_network_change
&& signed_node_info.timestamp == current_sni.timestamp && signed_node_info.timestamp() == current_sni.timestamp()
{ {
// No need to update the signednodeinfo though since the timestamp is the same // No need to update the signednodeinfo though since the timestamp is the same
// Touch the node and let it try to live again // Touch the node and let it try to live again
@ -207,11 +229,22 @@ impl BucketEntryInner {
} }
} }
// Update the protocol min/max version we have // Update the protocol min/max version we have to use, to include relay requirements if needed
self.min_max_version = Some(( let mut version_range = VersionRange {
signed_node_info.node_info.min_version, min: signed_node_info.node_info().min_version,
signed_node_info.node_info.max_version, max: signed_node_info.node_info().max_version,
)); };
if let Some(relay_info) = signed_node_info.relay_info() {
version_range.min.max_assign(relay_info.min_version);
version_range.max.min_assign(relay_info.max_version);
}
if version_range.min <= version_range.max {
// Can be reached with at least one crypto version
self.min_max_version = Some(version_range);
} else {
// No valid crypto version in range
self.min_max_version = None;
}
// Update the signed node info // Update the signed node info
*opt_current_sni = Some(Box::new(signed_node_info)); *opt_current_sni = Some(Box::new(signed_node_info));
@ -238,7 +271,7 @@ impl BucketEntryInner {
RoutingDomain::LocalNetwork => &self.local_network.signed_node_info, RoutingDomain::LocalNetwork => &self.local_network.signed_node_info,
RoutingDomain::PublicInternet => &self.public_internet.signed_node_info, RoutingDomain::PublicInternet => &self.public_internet.signed_node_info,
}; };
opt_current_sni.as_ref().map(|s| &s.node_info) opt_current_sni.as_ref().map(|s| s.node_info())
} }
pub fn signed_node_info(&self, routing_domain: RoutingDomain) -> Option<&SignedNodeInfo> { pub fn signed_node_info(&self, routing_domain: RoutingDomain) -> Option<&SignedNodeInfo> {
@ -338,11 +371,11 @@ impl BucketEntryInner {
out out
} }
pub fn set_min_max_version(&mut self, min_max_version: (u8, u8)) { pub fn set_min_max_version(&mut self, min_max_version: VersionRange) {
self.min_max_version = Some(min_max_version); self.min_max_version = Some(min_max_version);
} }
pub fn min_max_version(&self) -> Option<(u8, u8)> { pub fn min_max_version(&self) -> Option<VersionRange> {
self.min_max_version self.min_max_version
} }

View File

@ -163,7 +163,7 @@ impl RoutingTable {
// Load bucket entries from table db if possible // Load bucket entries from table db if possible
debug!("loading routing table entries"); debug!("loading routing table entries");
if let Err(e) = self.load_buckets().await { if let Err(e) = self.load_buckets().await {
log_rtab!(warn "Error loading buckets from storage: {}. Resetting.", e); log_rtab!(debug "Error loading buckets from storage: {:#?}. Resetting.", e);
let mut inner = self.inner.write(); let mut inner = self.inner.write();
inner.init_buckets(self.clone()); inner.init_buckets(self.clone());
} }
@ -173,7 +173,7 @@ impl RoutingTable {
let route_spec_store = match RouteSpecStore::load(self.clone()).await { let route_spec_store = match RouteSpecStore::load(self.clone()).await {
Ok(v) => v, Ok(v) => v,
Err(e) => { Err(e) => {
log_rtab!(warn "Error loading route spec store: {}. Resetting.", e); log_rtab!(debug "Error loading route spec store: {:#?}. Resetting.", e);
RouteSpecStore::new(self.clone()) RouteSpecStore::new(self.clone())
} }
}; };
@ -239,7 +239,7 @@ impl RoutingTable {
let tdb = table_store.open("routing_table", 1).await?; let tdb = table_store.open("routing_table", 1).await?;
let bucket_count = bucketvec.len(); let bucket_count = bucketvec.len();
let mut dbx = tdb.transact(); let mut dbx = tdb.transact();
if let Err(e) = dbx.store_cbor(0, b"bucket_count", &bucket_count) { if let Err(e) = dbx.store_frozen(0, b"bucket_count", &bucket_count) {
dbx.rollback(); dbx.rollback();
return Err(e); return Err(e);
} }
@ -253,14 +253,13 @@ impl RoutingTable {
async fn load_buckets(&self) -> EyreResult<()> { async fn load_buckets(&self) -> EyreResult<()> {
// Deserialize all entries // Deserialize all entries
let inner = &mut *self.inner.write();
let tstore = self.network_manager().table_store(); let tstore = self.network_manager().table_store();
let tdb = tstore.open("routing_table", 1).await?; let tdb = tstore.open("routing_table", 1).await?;
let Some(bucket_count): Option<usize> = tdb.load_cbor(0, b"bucket_count")? else { let Some(bucket_count): Option<usize> = tdb.load_rkyv(0, b"bucket_count")? else {
log_rtab!(debug "no bucket count in saved routing table"); log_rtab!(debug "no bucket count in saved routing table");
return Ok(()); return Ok(());
}; };
let inner = &mut *self.inner.write();
if bucket_count != inner.buckets.len() { if bucket_count != inner.buckets.len() {
// Must have the same number of buckets // Must have the same number of buckets
warn!("bucket count is different, not loading routing table"); warn!("bucket count is different, not loading routing table");
@ -275,8 +274,8 @@ impl RoutingTable {
}; };
bucketdata_vec.push(bucketdata); bucketdata_vec.push(bucketdata);
} }
for n in 0..bucket_count { for (n, bucketdata) in bucketdata_vec.into_iter().enumerate() {
inner.buckets[n].load_bucket(&bucketdata_vec[n])?; inner.buckets[n].load_bucket(bucketdata)?;
} }
Ok(()) Ok(())
@ -383,7 +382,7 @@ impl RoutingTable {
} }
/// Return a copy of our node's signednodeinfo /// Return a copy of our node's signednodeinfo
pub fn get_own_signed_node_info(&self, routing_domain: RoutingDomain) -> SignedNodeInfo { pub fn get_own_signed_node_info(&self, routing_domain: RoutingDomain) -> SignedDirectNodeInfo {
self.inner.read().get_own_signed_node_info(routing_domain) self.inner.read().get_own_signed_node_info(routing_domain)
} }
@ -526,7 +525,7 @@ impl RoutingTable {
&self, &self,
routing_domain: RoutingDomain, routing_domain: RoutingDomain,
node_id: DHTKey, node_id: DHTKey,
signed_node_info: SignedNodeInfo, signed_node_info: SignedDirectNodeInfo,
allow_invalid: bool, allow_invalid: bool,
) -> Option<NodeRef> { ) -> Option<NodeRef> {
self.inner.write().register_node_with_signed_node_info( self.inner.write().register_node_with_signed_node_info(

View File

@ -385,9 +385,12 @@ impl NodeRef {
out out
} }
pub fn locked<'a>(&self, rti: &'a mut RoutingTableInner) -> NodeRefLocked<'a> { pub fn locked<'a>(&self, rti: &'a RoutingTableInner) -> NodeRefLocked<'a> {
NodeRefLocked::new(rti, self.clone()) NodeRefLocked::new(rti, self.clone())
} }
pub fn locked_mut<'a>(&self, rti: &'a mut RoutingTableInner) -> NodeRefLockedMut<'a> {
NodeRefLockedMut::new(rti, self.clone())
}
} }
impl NodeRefBase for NodeRef { impl NodeRefBase for NodeRef {
@ -480,12 +483,12 @@ impl Drop for NodeRef {
/// already locked a RoutingTableInner /// already locked a RoutingTableInner
/// Keeps entry in the routing table until all references are gone /// Keeps entry in the routing table until all references are gone
pub struct NodeRefLocked<'a> { pub struct NodeRefLocked<'a> {
inner: Mutex<&'a mut RoutingTableInner>, inner: Mutex<&'a RoutingTableInner>,
nr: NodeRef, nr: NodeRef,
} }
impl<'a> NodeRefLocked<'a> { impl<'a> NodeRefLocked<'a> {
pub fn new(inner: &'a mut RoutingTableInner, nr: NodeRef) -> Self { pub fn new(inner: &'a RoutingTableInner, nr: NodeRef) -> Self {
Self { Self {
inner: Mutex::new(inner), inner: Mutex::new(inner),
nr, nr,
@ -510,6 +513,65 @@ impl<'a> NodeRefBase for NodeRefLocked<'a> {
self.nr.common.entry.with(inner, f) self.nr.common.entry.with(inner, f)
} }
fn operate_mut<T, F>(&self, _f: F) -> T
where
F: FnOnce(&mut RoutingTableInner, &mut BucketEntryInner) -> T,
{
panic!("need to locked_mut() for this operation")
}
}
impl<'a> fmt::Display for NodeRefLocked<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.nr)
}
}
impl<'a> fmt::Debug for NodeRefLocked<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("NodeRefLocked")
.field("nr", &self.nr)
.finish()
}
}
////////////////////////////////////////////////////////////////////////////////////
/// Mutable locked reference to a routing table entry
/// For internal use inside the RoutingTable module where you have
/// already locked a RoutingTableInner
/// Keeps entry in the routing table until all references are gone
pub struct NodeRefLockedMut<'a> {
inner: Mutex<&'a mut RoutingTableInner>,
nr: NodeRef,
}
impl<'a> NodeRefLockedMut<'a> {
pub fn new(inner: &'a mut RoutingTableInner, nr: NodeRef) -> Self {
Self {
inner: Mutex::new(inner),
nr,
}
}
}
impl<'a> NodeRefBase for NodeRefLockedMut<'a> {
fn common(&self) -> &NodeRefBaseCommon {
&self.nr.common
}
fn common_mut(&mut self) -> &mut NodeRefBaseCommon {
&mut self.nr.common
}
fn operate<T, F>(&self, f: F) -> T
where
F: FnOnce(&RoutingTableInner, &BucketEntryInner) -> T,
{
let inner = &*self.inner.lock();
self.nr.common.entry.with(inner, f)
}
fn operate_mut<T, F>(&self, f: F) -> T fn operate_mut<T, F>(&self, f: F) -> T
where where
F: FnOnce(&mut RoutingTableInner, &mut BucketEntryInner) -> T, F: FnOnce(&mut RoutingTableInner, &mut BucketEntryInner) -> T,
@ -519,15 +581,15 @@ impl<'a> NodeRefBase for NodeRefLocked<'a> {
} }
} }
impl<'a> fmt::Display for NodeRefLocked<'a> { impl<'a> fmt::Display for NodeRefLockedMut<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.nr) write!(f, "{}", self.nr)
} }
} }
impl<'a> fmt::Debug for NodeRefLocked<'a> { impl<'a> fmt::Debug for NodeRefLockedMut<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("NodeRefLocked") f.debug_struct("NodeRefLockedMut")
.field("nr", &self.nr) .field("nr", &self.nr)
.finish() .finish()
} }

View File

@ -221,11 +221,11 @@ impl RouteSpecStore {
) )
}; };
// Get cbor blob from table store // Get frozen blob from table store
let table_store = routing_table.network_manager().table_store(); let table_store = routing_table.network_manager().table_store();
let rsstdb = table_store.open("RouteSpecStore", 1).await?; let rsstdb = table_store.open("RouteSpecStore", 1).await?;
let mut content: RouteSpecStoreContent = let mut content: RouteSpecStoreContent =
rsstdb.load_cbor(0, b"content")?.unwrap_or_default(); rsstdb.load_json(0, b"content")?.unwrap_or_default();
// Look up all route hop noderefs since we can't serialize those // Look up all route hop noderefs since we can't serialize those
let mut dead_keys = Vec::new(); let mut dead_keys = Vec::new();
@ -246,7 +246,7 @@ impl RouteSpecStore {
// Load secrets from pstore // Load secrets from pstore
let pstore = routing_table.network_manager().protected_store(); let pstore = routing_table.network_manager().protected_store();
let out: Vec<(DHTKey, DHTKeySecret)> = pstore let out: Vec<(DHTKey, DHTKeySecret)> = pstore
.load_user_secret_cbor("RouteSpecStore") .load_user_secret_rkyv("RouteSpecStore")
.await? .await?
.unwrap_or_default(); .unwrap_or_default();
@ -289,14 +289,14 @@ impl RouteSpecStore {
inner.content.clone() inner.content.clone()
}; };
// Save all the fields we care about to the cbor blob in table storage // Save all the fields we care about to the frozen blob in table storage
let table_store = self let table_store = self
.unlocked_inner .unlocked_inner
.routing_table .routing_table
.network_manager() .network_manager()
.table_store(); .table_store();
let rsstdb = table_store.open("RouteSpecStore", 1).await?; let rsstdb = table_store.open("RouteSpecStore", 1).await?;
rsstdb.store_cbor(0, b"content", &content)?; rsstdb.store_json(0, b"content", &content)?;
// // Keep secrets in protected store as well // // Keep secrets in protected store as well
let pstore = self let pstore = self
@ -310,7 +310,9 @@ impl RouteSpecStore {
out.push((*k, v.secret_key)); out.push((*k, v.secret_key));
} }
let _ = pstore.save_user_secret_cbor("RouteSpecStore", &out).await?; // ignore if this previously existed or not let _ = pstore
.save_user_secret_frozen("RouteSpecStore", &out)
.await?; // ignore if this previously existed or not
Ok(()) Ok(())
} }

View File

@ -101,6 +101,45 @@ impl RoutingDomainDetailCommon {
self.network_class.unwrap_or(NetworkClass::Invalid) != NetworkClass::Invalid self.network_class.unwrap_or(NetworkClass::Invalid) != NetworkClass::Invalid
} }
fn make_peer_info(&self, rti: &RoutingTableInner) -> PeerInfo {
let node_info = NodeInfo {
network_class: self.network_class.unwrap_or(NetworkClass::Invalid),
outbound_protocols: self.outbound_protocols,
address_types: self.address_types,
min_version: MIN_CRYPTO_VERSION,
max_version: MAX_CRYPTO_VERSION,
dial_info_detail_list: self.dial_info_details.clone(),
};
let relay_peer_info = self
.relay_node
.as_ref()
.and_then(|rn| rn.locked(rti).make_peer_info(self.routing_domain));
let signed_node_info = match relay_peer_info {
Some(relay_pi) => SignedNodeInfo::Relayed(
SignedRelayedNodeInfo::with_secret(
NodeId::new(rti.unlocked_inner.node_id),
node_info,
relay_pi.node_id,
relay_pi.signed_node_info,
&rti.unlocked_inner.node_id_secret,
)
.unwrap(),
),
None => SignedNodeInfo::Direct(
SignedDirectNodeInfo::with_secret(
NodeId::new(rti.unlocked_inner.node_id),
node_info,
&rti.unlocked_inner.node_id_secret,
)
.unwrap(),
),
};
PeerInfo::new(NodeId::new(rti.unlocked_inner.node_id), signed_node_info)
}
pub fn with_peer_info<F, R>(&self, rti: &RoutingTableInner, f: F) -> R pub fn with_peer_info<F, R>(&self, rti: &RoutingTableInner, f: F) -> R
where where
F: FnOnce(&PeerInfo) -> R, F: FnOnce(&PeerInfo) -> R,
@ -110,7 +149,7 @@ impl RoutingDomainDetailCommon {
// Regenerate peer info // Regenerate peer info
let pi = PeerInfo::new( let pi = PeerInfo::new(
NodeId::new(rti.unlocked_inner.node_id), NodeId::new(rti.unlocked_inner.node_id),
SignedNodeInfo::with_secret( SignedDirectNodeInfo::with_secret(
NodeInfo { NodeInfo {
network_class: self.network_class.unwrap_or(NetworkClass::Invalid), network_class: self.network_class.unwrap_or(NetworkClass::Invalid),
outbound_protocols: self.outbound_protocols, outbound_protocols: self.outbound_protocols,
@ -118,10 +157,11 @@ impl RoutingDomainDetailCommon {
min_version: MIN_CRYPTO_VERSION, min_version: MIN_CRYPTO_VERSION,
max_version: MAX_CRYPTO_VERSION, max_version: MAX_CRYPTO_VERSION,
dial_info_detail_list: self.dial_info_details.clone(), dial_info_detail_list: self.dial_info_details.clone(),
relay_peer_info: self relay_peer_info: self.relay_node.as_ref().and_then(|rn| {
.relay_node rn.locked(rti)
.as_ref() .make_peer_info(self.routing_domain)
.and_then(|rn| rn.make_peer_info(self.routing_domain).map(Box::new)), .map(Box::new)
}),
}, },
NodeId::new(rti.unlocked_inner.node_id), NodeId::new(rti.unlocked_inner.node_id),
&rti.unlocked_inner.node_id_secret, &rti.unlocked_inner.node_id_secret,

View File

@ -253,7 +253,7 @@ impl RoutingTableInner {
} }
/// Return a copy of our node's signednodeinfo /// Return a copy of our node's signednodeinfo
pub fn get_own_signed_node_info(&self, routing_domain: RoutingDomain) -> SignedNodeInfo { pub fn get_own_signed_node_info(&self, routing_domain: RoutingDomain) -> SignedDirectNodeInfo {
self.with_routing_domain(routing_domain, |rdd| { self.with_routing_domain(routing_domain, |rdd| {
rdd.common() rdd.common()
.with_peer_info(self, |pi| pi.signed_node_info.clone()) .with_peer_info(self, |pi| pi.signed_node_info.clone())
@ -662,7 +662,7 @@ impl RoutingTableInner {
outer_self: RoutingTable, outer_self: RoutingTable,
routing_domain: RoutingDomain, routing_domain: RoutingDomain,
node_id: DHTKey, node_id: DHTKey,
signed_node_info: SignedNodeInfo, signed_node_info: SignedDirectNodeInfo,
allow_invalid: bool, allow_invalid: bool,
) -> Option<NodeRef> { ) -> Option<NodeRef> {
// validate signed node info is not something malicious // validate signed node info is not something malicious
@ -717,7 +717,8 @@ impl RoutingTableInner {
}); });
if let Some(nr) = &out { if let Some(nr) = &out {
// set the most recent node address for connection finding and udp replies // set the most recent node address for connection finding and udp replies
nr.locked(self).set_last_connection(descriptor, timestamp); nr.locked_mut(self)
.set_last_connection(descriptor, timestamp);
} }
out out
} }

View File

@ -17,7 +17,9 @@ mod public_key;
mod sender_info; mod sender_info;
mod signal_info; mod signal_info;
mod signature; mod signature;
mod signed_direct_node_info;
mod signed_node_info; mod signed_node_info;
mod signed_relayed_node_info;
mod socket_address; mod socket_address;
mod tunnel; mod tunnel;
mod value_data; mod value_data;
@ -42,7 +44,9 @@ pub use public_key::*;
pub use sender_info::*; pub use sender_info::*;
pub use signal_info::*; pub use signal_info::*;
pub use signature::*; pub use signature::*;
pub use signed_direct_node_info::*;
pub use signed_node_info::*; pub use signed_node_info::*;
pub use signed_relayed_node_info::*;
pub use socket_address::*; pub use socket_address::*;
pub use tunnel::*; pub use tunnel::*;
pub use value_data::*; pub use value_data::*;

View File

@ -5,7 +5,7 @@ pub fn encode_network_class(network_class: NetworkClass) -> veilid_capnp::Networ
NetworkClass::InboundCapable => veilid_capnp::NetworkClass::InboundCapable, NetworkClass::InboundCapable => veilid_capnp::NetworkClass::InboundCapable,
NetworkClass::OutboundOnly => veilid_capnp::NetworkClass::OutboundOnly, NetworkClass::OutboundOnly => veilid_capnp::NetworkClass::OutboundOnly,
NetworkClass::WebApp => veilid_capnp::NetworkClass::WebApp, NetworkClass::WebApp => veilid_capnp::NetworkClass::WebApp,
NetworkClass::Invalid => panic!("invalid network class should not be encoded"), NetworkClass::Invalid => veilid_capnp::NetworkClass::Invalid,
} }
} }
@ -14,5 +14,6 @@ pub fn decode_network_class(network_class: veilid_capnp::NetworkClass) -> Networ
veilid_capnp::NetworkClass::InboundCapable => NetworkClass::InboundCapable, veilid_capnp::NetworkClass::InboundCapable => NetworkClass::InboundCapable,
veilid_capnp::NetworkClass::OutboundOnly => NetworkClass::OutboundOnly, veilid_capnp::NetworkClass::OutboundOnly => NetworkClass::OutboundOnly,
veilid_capnp::NetworkClass::WebApp => NetworkClass::WebApp, veilid_capnp::NetworkClass::WebApp => NetworkClass::WebApp,
veilid_capnp::NetworkClass::Invalid => NetworkClass::Invalid,
} }
} }

View File

@ -31,18 +31,10 @@ pub fn encode_node_info(
encode_dial_info_detail(&node_info.dial_info_detail_list[idx], &mut did_builder)?; encode_dial_info_detail(&node_info.dial_info_detail_list[idx], &mut did_builder)?;
} }
if let Some(rpi) = &node_info.relay_peer_info {
let mut rpi_builder = builder.reborrow().init_relay_peer_info();
encode_peer_info(rpi, &mut rpi_builder)?;
}
Ok(()) Ok(())
} }
pub fn decode_node_info( pub fn decode_node_info(reader: &veilid_capnp::node_info::Reader) -> Result<NodeInfo, RPCError> {
reader: &veilid_capnp::node_info::Reader,
allow_relay_peer_info: bool,
) -> Result<NodeInfo, RPCError> {
let network_class = decode_network_class( let network_class = decode_network_class(
reader reader
.reborrow() .reborrow()
@ -81,22 +73,6 @@ pub fn decode_node_info(
dial_info_detail_list.push(decode_dial_info_detail(&did)?) dial_info_detail_list.push(decode_dial_info_detail(&did)?)
} }
let relay_peer_info = if allow_relay_peer_info {
if reader.has_relay_peer_info() {
Some(Box::new(decode_peer_info(
&reader
.reborrow()
.get_relay_peer_info()
.map_err(RPCError::protocol)?,
false,
)?))
} else {
None
}
} else {
None
};
Ok(NodeInfo { Ok(NodeInfo {
network_class, network_class,
outbound_protocols, outbound_protocols,
@ -104,6 +80,5 @@ pub fn decode_node_info(
min_version, min_version,
max_version, max_version,
dial_info_detail_list, dial_info_detail_list,
relay_peer_info,
}) })
} }

View File

@ -120,7 +120,7 @@ impl RPCOperation {
let sni_reader = operation_reader let sni_reader = operation_reader
.get_sender_node_info() .get_sender_node_info()
.map_err(RPCError::protocol)?; .map_err(RPCError::protocol)?;
let sni = decode_signed_node_info(&sni_reader, sender_node_id, true)?; let sni = decode_signed_node_info(&sni_reader, sender_node_id)?;
Some(sni) Some(sni)
} else { } else {
None None

View File

@ -47,7 +47,7 @@ impl RPCOperationFindBlockA {
.map_err(RPCError::map_internal("too many suppliers"))?, .map_err(RPCError::map_internal("too many suppliers"))?,
); );
for s in suppliers_reader.iter() { for s in suppliers_reader.iter() {
let peer_info = decode_peer_info(&s, true)?; let peer_info = decode_peer_info(&s)?;
suppliers.push(peer_info); suppliers.push(peer_info);
} }
@ -59,7 +59,7 @@ impl RPCOperationFindBlockA {
.map_err(RPCError::map_internal("too many peers"))?, .map_err(RPCError::map_internal("too many peers"))?,
); );
for p in peers_reader.iter() { for p in peers_reader.iter() {
let peer_info = decode_peer_info(&p, true)?; let peer_info = decode_peer_info(&p)?;
peers.push(peer_info); peers.push(peer_info);
} }

View File

@ -41,7 +41,7 @@ impl RPCOperationFindNodeA {
.map_err(RPCError::map_internal("too many peers"))?, .map_err(RPCError::map_internal("too many peers"))?,
); );
for p in peers_reader.iter() { for p in peers_reader.iter() {
let peer_info = decode_peer_info(&p, true)?; let peer_info = decode_peer_info(&p)?;
peers.push(peer_info); peers.push(peer_info);
} }

View File

@ -48,7 +48,7 @@ impl RPCOperationGetValueA {
.map_err(RPCError::map_internal("too many peers"))?, .map_err(RPCError::map_internal("too many peers"))?,
); );
for p in peers_reader.iter() { for p in peers_reader.iter() {
let peer_info = decode_peer_info(&p, true)?; let peer_info = decode_peer_info(&p)?;
peers.push(peer_info); peers.push(peer_info);
} }

View File

@ -18,7 +18,7 @@ impl RPCOperationNodeInfoUpdate {
} }
let sender_node_id = opt_sender_node_id.unwrap(); let sender_node_id = opt_sender_node_id.unwrap();
let sni_reader = reader.get_signed_node_info().map_err(RPCError::protocol)?; let sni_reader = reader.get_signed_node_info().map_err(RPCError::protocol)?;
let signed_node_info = decode_signed_node_info(&sni_reader, sender_node_id, true)?; let signed_node_info = decode_signed_node_info(&sni_reader, sender_node_id)?;
Ok(RPCOperationNodeInfoUpdate { signed_node_info }) Ok(RPCOperationNodeInfoUpdate { signed_node_info })
} }

View File

@ -53,7 +53,7 @@ impl RPCOperationSetValueA {
.map_err(RPCError::map_internal("too many peers"))?, .map_err(RPCError::map_internal("too many peers"))?,
); );
for p in peers_reader.iter() { for p in peers_reader.iter() {
let peer_info = decode_peer_info(&p, true)?; let peer_info = decode_peer_info(&p)?;
peers.push(peer_info); peers.push(peer_info);
} }

View File

@ -49,7 +49,7 @@ impl RPCOperationSupplyBlockA {
.map_err(RPCError::map_internal("too many peers"))?, .map_err(RPCError::map_internal("too many peers"))?,
); );
for p in peers_reader.iter() { for p in peers_reader.iter() {
let peer_info = decode_peer_info(&p, true)?; let peer_info = decode_peer_info(&p)?;
peers.push(peer_info); peers.push(peer_info);
} }

View File

@ -43,7 +43,7 @@ impl RPCOperationWatchValueA {
.map_err(RPCError::map_internal("too many peers"))?, .map_err(RPCError::map_internal("too many peers"))?,
); );
for p in peers_reader.iter() { for p in peers_reader.iter() {
let peer_info = decode_peer_info(&p, true)?; let peer_info = decode_peer_info(&p)?;
peers.push(peer_info); peers.push(peer_info);
} }

View File

@ -14,10 +14,7 @@ pub fn encode_peer_info(
Ok(()) Ok(())
} }
pub fn decode_peer_info( pub fn decode_peer_info(reader: &veilid_capnp::peer_info::Reader) -> Result<PeerInfo, RPCError> {
reader: &veilid_capnp::peer_info::Reader,
allow_relay_peer_info: bool,
) -> Result<PeerInfo, RPCError> {
let nid_reader = reader let nid_reader = reader
.reborrow() .reborrow()
.get_node_id() .get_node_id()
@ -27,8 +24,7 @@ pub fn decode_peer_info(
.get_signed_node_info() .get_signed_node_info()
.map_err(RPCError::protocol)?; .map_err(RPCError::protocol)?;
let node_id = NodeId::new(decode_public_key(&nid_reader)); let node_id = NodeId::new(decode_public_key(&nid_reader));
let signed_node_info = let signed_node_info = decode_signed_node_info(&sni_reader, &node_id.key)?;
decode_signed_node_info(&sni_reader, &node_id.key, allow_relay_peer_info)?;
Ok(PeerInfo { Ok(PeerInfo {
node_id, node_id,

View File

@ -77,7 +77,7 @@ pub fn decode_route_hop(reader: &veilid_capnp::route_hop::Reader) -> Result<Rout
veilid_capnp::route_hop::node::Which::PeerInfo(pi) => { veilid_capnp::route_hop::node::Which::PeerInfo(pi) => {
let pi_reader = pi.map_err(RPCError::protocol)?; let pi_reader = pi.map_err(RPCError::protocol)?;
RouteNode::PeerInfo( RouteNode::PeerInfo(
decode_peer_info(&pi_reader, true) decode_peer_info(&pi_reader)
.map_err(RPCError::map_protocol("invalid peer info in route hop"))?, .map_err(RPCError::map_protocol("invalid peer info in route hop"))?,
) )
} }

View File

@ -53,7 +53,7 @@ pub fn decode_signal_info(
let pi_reader = r.get_peer_info().map_err(RPCError::map_protocol( let pi_reader = r.get_peer_info().map_err(RPCError::map_protocol(
"invalid peer info in hole punch signal info", "invalid peer info in hole punch signal info",
))?; ))?;
let peer_info = decode_peer_info(&pi_reader, true)?; let peer_info = decode_peer_info(&pi_reader)?;
SignalInfo::HolePunch { receipt, peer_info } SignalInfo::HolePunch { receipt, peer_info }
} }
@ -69,7 +69,7 @@ pub fn decode_signal_info(
let pi_reader = r.get_peer_info().map_err(RPCError::map_protocol( let pi_reader = r.get_peer_info().map_err(RPCError::map_protocol(
"invalid peer info in reverse connect signal info", "invalid peer info in reverse connect signal info",
))?; ))?;
let peer_info = decode_peer_info(&pi_reader, true)?; let peer_info = decode_peer_info(&pi_reader)?;
SignalInfo::ReverseConnect { receipt, peer_info } SignalInfo::ReverseConnect { receipt, peer_info }
} }

View File

@ -0,0 +1,43 @@
use crate::*;
use rpc_processor::*;
pub fn encode_signed_direct_node_info(
signed_direct_node_info: &SignedDirectNodeInfo,
builder: &mut veilid_capnp::signed_direct_node_info::Builder,
) -> Result<(), RPCError> {
//
let mut ni_builder = builder.reborrow().init_node_info();
encode_node_info(&signed_direct_node_info.node_info, &mut ni_builder)?;
builder
.reborrow()
.set_timestamp(signed_direct_node_info.timestamp);
let mut sig_builder = builder.reborrow().init_signature();
encode_signature(&signed_direct_node_info.signature, &mut sig_builder);
Ok(())
}
pub fn decode_signed_direct_node_info(
reader: &veilid_capnp::signed_direct_node_info::Reader,
node_id: &DHTKey,
) -> Result<SignedDirectNodeInfo, RPCError> {
let ni_reader = reader
.reborrow()
.get_node_info()
.map_err(RPCError::protocol)?;
let node_info = decode_node_info(&ni_reader)?;
let sig_reader = reader
.reborrow()
.get_signature()
.map_err(RPCError::protocol)?;
let timestamp = reader.reborrow().get_timestamp();
let signature = decode_signature(&sig_reader);
SignedDirectNodeInfo::new(NodeId::new(*node_id), node_info, timestamp, signature)
.map_err(RPCError::protocol)
}

View File

@ -5,14 +5,16 @@ pub fn encode_signed_node_info(
signed_node_info: &SignedNodeInfo, signed_node_info: &SignedNodeInfo,
builder: &mut veilid_capnp::signed_node_info::Builder, builder: &mut veilid_capnp::signed_node_info::Builder,
) -> Result<(), RPCError> { ) -> Result<(), RPCError> {
// match signed_node_info {
let mut ni_builder = builder.reborrow().init_node_info(); SignedNodeInfo::Direct(d) => {
encode_node_info(&signed_node_info.node_info, &mut ni_builder)?; let mut d_builder = builder.reborrow().init_direct();
encode_signed_direct_node_info(d, &mut d_builder)?;
let mut sig_builder = builder.reborrow().init_signature(); }
encode_signature(&signed_node_info.signature, &mut sig_builder); SignedNodeInfo::Relayed(r) => {
let mut r_builder = builder.reborrow().init_relayed();
builder.reborrow().set_timestamp(signed_node_info.timestamp); encode_signed_relayed_node_info(r, &mut r_builder)?;
}
}
Ok(()) Ok(())
} }
@ -20,22 +22,20 @@ pub fn encode_signed_node_info(
pub fn decode_signed_node_info( pub fn decode_signed_node_info(
reader: &veilid_capnp::signed_node_info::Reader, reader: &veilid_capnp::signed_node_info::Reader,
node_id: &DHTKey, node_id: &DHTKey,
allow_relay_peer_info: bool,
) -> Result<SignedNodeInfo, RPCError> { ) -> Result<SignedNodeInfo, RPCError> {
let ni_reader = reader match reader
.reborrow() .which()
.get_node_info() .map_err(RPCError::map_internal("invalid signal operation"))?
.map_err(RPCError::protocol)?; {
let node_info = decode_node_info(&ni_reader, allow_relay_peer_info)?; veilid_capnp::signed_node_info::Direct(d) => {
let d_reader = d.map_err(RPCError::protocol)?;
let sig_reader = reader let sdni = decode_signed_direct_node_info(&d_reader, node_id)?;
.reborrow() Ok(SignedNodeInfo::Direct(sdni))
.get_signature() }
.map_err(RPCError::protocol)?; veilid_capnp::signed_node_info::Relayed(r) => {
let signature = decode_signature(&sig_reader); let r_reader = r.map_err(RPCError::protocol)?;
let srni = decode_signed_relayed_node_info(&r_reader, node_id)?;
let timestamp = reader.reborrow().get_timestamp(); Ok(SignedNodeInfo::Relayed(srni))
}
SignedNodeInfo::new(node_info, NodeId::new(*node_id), signature, timestamp) }
.map_err(RPCError::protocol)
} }

View File

@ -0,0 +1,67 @@
use crate::*;
use rpc_processor::*;
pub fn encode_signed_relayed_node_info(
signed_relayed_node_info: &SignedRelayedNodeInfo,
builder: &mut veilid_capnp::signed_relayed_node_info::Builder,
) -> Result<(), RPCError> {
//
let mut ni_builder = builder.reborrow().init_node_info();
encode_node_info(&signed_relayed_node_info.node_info, &mut ni_builder)?;
let mut rid_builder = builder.reborrow().init_relay_id();
encode_public_key(&signed_relayed_node_info.relay_id.key, &mut rid_builder)?;
let mut ri_builder = builder.reborrow().init_relay_info();
encode_signed_direct_node_info(&signed_relayed_node_info.relay_info, &mut ri_builder)?;
builder
.reborrow()
.set_timestamp(signed_relayed_node_info.timestamp);
let mut sig_builder = builder.reborrow().init_signature();
encode_signature(&signed_relayed_node_info.signature, &mut sig_builder);
Ok(())
}
pub fn decode_signed_relayed_node_info(
reader: &veilid_capnp::signed_relayed_node_info::Reader,
node_id: &DHTKey,
) -> Result<SignedRelayedNodeInfo, RPCError> {
let ni_reader = reader
.reborrow()
.get_node_info()
.map_err(RPCError::protocol)?;
let node_info = decode_node_info(&ni_reader)?;
let rid_reader = reader
.reborrow()
.get_relay_id()
.map_err(RPCError::protocol)?;
let relay_id = decode_public_key(&rid_reader);
let ri_reader = reader
.reborrow()
.get_relay_info()
.map_err(RPCError::protocol)?;
let relay_info = decode_signed_direct_node_info(&ri_reader, &relay_id)?;
let sig_reader = reader
.reborrow()
.get_signature()
.map_err(RPCError::protocol)?;
let timestamp = reader.reborrow().get_timestamp();
let signature = decode_signature(&sig_reader);
SignedRelayedNodeInfo::new(
NodeId::new(*node_id),
node_info,
NodeId::new(relay_id),
relay_info,
timestamp,
signature,
)
.map_err(RPCError::protocol)
}

View File

@ -619,7 +619,7 @@ impl RPCProcessor {
// routing table caching when it is okay to do so // routing table caching when it is okay to do so
// This is only done in the PublicInternet routing domain because // This is only done in the PublicInternet routing domain because
// as far as we can tell this is the only domain that will really benefit // as far as we can tell this is the only domain that will really benefit
fn get_sender_signed_node_info(&self, dest: &Destination) -> Option<SignedNodeInfo> { fn get_sender_signed_node_info(&self, dest: &Destination) -> Option<SignedDirectNodeInfo> {
// Don't do this if the sender is to remain private // Don't do this if the sender is to remain private
// Otherwise we would be attaching the original sender's identity to the final destination, // Otherwise we would be attaching the original sender's identity to the final destination,
// thus defeating the purpose of the safety route entirely :P // thus defeating the purpose of the safety route entirely :P
@ -682,7 +682,7 @@ impl RPCProcessor {
let op_id = operation.op_id(); let op_id = operation.op_id();
// Log rpc send // Log rpc send
debug!(target: "rpc_message", dir = "send", kind = "question", op_id, desc = operation.kind().desc(), ?dest); trace!(target: "rpc_message", dir = "send", kind = "question", op_id, desc = operation.kind().desc(), ?dest);
// Produce rendered operation // Produce rendered operation
let RenderedOperation { let RenderedOperation {
@ -745,7 +745,7 @@ impl RPCProcessor {
let operation = RPCOperation::new_statement(statement, opt_sender_info); let operation = RPCOperation::new_statement(statement, opt_sender_info);
// Log rpc send // Log rpc send
debug!(target: "rpc_message", dir = "send", kind = "statement", op_id = operation.op_id(), desc = operation.kind().desc(), ?dest); trace!(target: "rpc_message", dir = "send", kind = "statement", op_id = operation.op_id(), desc = operation.kind().desc(), ?dest);
// Produce rendered operation // Produce rendered operation
let RenderedOperation { let RenderedOperation {
@ -865,7 +865,7 @@ impl RPCProcessor {
let operation = RPCOperation::new_answer(&request.operation, answer, opt_sender_info); let operation = RPCOperation::new_answer(&request.operation, answer, opt_sender_info);
// Log rpc send // Log rpc send
debug!(target: "rpc_message", dir = "send", kind = "answer", op_id = operation.op_id(), desc = operation.kind().desc(), ?dest); trace!(target: "rpc_message", dir = "send", kind = "answer", op_id = operation.op_id(), desc = operation.kind().desc(), ?dest);
// Produce rendered operation // Produce rendered operation
let RenderedOperation { let RenderedOperation {
@ -997,7 +997,7 @@ impl RPCProcessor {
}; };
// Log rpc receive // Log rpc receive
debug!(target: "rpc_message", dir = "recv", kind, op_id = msg.operation.op_id(), desc = msg.operation.kind().desc(), header = ?msg.header); trace!(target: "rpc_message", dir = "recv", kind, op_id = msg.operation.op_id(), desc = msg.operation.kind().desc(), header = ?msg.header);
// Process specific message kind // Process specific message kind
match msg.operation.kind() { match msg.operation.kind() {

View File

@ -122,21 +122,21 @@ pub async fn test_store_delete_load(ts: TableStore) {
assert_eq!(db.load(2, b"baz").unwrap(), Some(b"QWERTY".to_vec())); assert_eq!(db.load(2, b"baz").unwrap(), Some(b"QWERTY".to_vec()));
} }
pub async fn test_cbor(ts: TableStore) { pub async fn test_frozen(ts: TableStore) {
trace!("test_cbor"); trace!("test_frozen");
let _ = ts.delete("test"); let _ = ts.delete("test");
let db = ts.open("test", 3).await.expect("should have opened"); let db = ts.open("test", 3).await.expect("should have opened");
let (dht_key, _) = generate_secret(); let (dht_key, _) = generate_secret();
assert!(db.store_cbor(0, b"asdf", &dht_key).is_ok()); assert!(db.store_rkyv(0, b"asdf", &dht_key).is_ok());
assert_eq!(db.load_cbor::<DHTKey>(0, b"qwer").unwrap(), None); assert_eq!(db.load_rkyv::<DHTKey>(0, b"qwer").unwrap(), None);
let d = match db.load_cbor::<DHTKey>(0, b"asdf") { let d = match db.load_rkyv::<DHTKey>(0, b"asdf") {
Ok(x) => x, Ok(x) => x,
Err(e) => { Err(e) => {
panic!("couldn't decode cbor: {}", e); panic!("couldn't decode: {}", e);
} }
}; };
assert_eq!(d, Some(dht_key), "keys should be equal"); assert_eq!(d, Some(dht_key), "keys should be equal");
@ -147,8 +147,8 @@ pub async fn test_cbor(ts: TableStore) {
); );
assert!( assert!(
db.load_cbor::<DHTKey>(1, b"foo").is_err(), db.load_rkyv::<DHTKey>(1, b"foo").is_err(),
"should fail to load cbor" "should fail to unfreeze"
); );
} }
@ -157,7 +157,7 @@ pub async fn test_all() {
let ts = api.table_store().unwrap(); let ts = api.table_store().unwrap();
test_delete_open_delete(ts.clone()).await; test_delete_open_delete(ts.clone()).await;
test_store_delete_load(ts.clone()).await; test_store_delete_load(ts.clone()).await;
test_cbor(ts.clone()).await; test_frozen(ts.clone()).await;
let _ = ts.delete("test").await; let _ = ts.delete("test").await;

View File

@ -43,7 +43,78 @@ pub async fn test_attach_detach() {
api.shutdown().await; api.shutdown().await;
} }
pub async fn test_signed_node_info() {
info!("--- test_signed_node_info ---");
let (update_callback, config_callback) = setup_veilid_core();
let api = api_startup(update_callback, config_callback)
.await
.expect("startup failed");
// Test direct
let node_info = NodeInfo {
network_class: NetworkClass::InboundCapable,
outbound_protocols: ProtocolTypeSet::all(),
address_types: AddressTypeSet::all(),
min_version: 0,
max_version: 0,
dial_info_detail_list: vec![DialInfoDetail {
class: DialInfoClass::Mapped,
dial_info: DialInfo::udp(SocketAddress::default()),
}],
};
let (pkey, skey) = generate_secret();
let sni =
SignedDirectNodeInfo::with_secret(NodeId::new(pkey.clone()), node_info.clone(), &skey)
.unwrap();
let _ = SignedDirectNodeInfo::new(
NodeId::new(pkey),
node_info.clone(),
sni.timestamp,
sni.signature,
)
.unwrap();
// Test relayed
let node_info2 = NodeInfo {
network_class: NetworkClass::OutboundOnly,
outbound_protocols: ProtocolTypeSet::all(),
address_types: AddressTypeSet::all(),
min_version: 0,
max_version: 0,
dial_info_detail_list: vec![DialInfoDetail {
class: DialInfoClass::Blocked,
dial_info: DialInfo::udp(SocketAddress::default()),
}],
};
let (pkey2, skey2) = generate_secret();
let sni2 = SignedRelayedNodeInfo::with_secret(
NodeId::new(pkey2.clone()),
node_info2.clone(),
NodeId::new(pkey.clone()),
sni.clone(),
&skey2,
)
.unwrap();
let _ = SignedRelayedNodeInfo::new(
NodeId::new(pkey2),
node_info2,
NodeId::new(pkey),
sni,
sni2.timestamp,
sni2.signature,
)
.unwrap();
api.shutdown().await;
}
pub async fn test_all() { pub async fn test_all() {
test_startup_shutdown().await; test_startup_shutdown().await;
test_attach_detach().await; test_attach_detach().await;
test_signed_node_info().await;
} }

View File

@ -4,7 +4,6 @@
use super::*; use super::*;
use data_encoding::BASE64URL_NOPAD; use data_encoding::BASE64URL_NOPAD;
use routing_table::*; use routing_table::*;
use rpc_processor::*;
#[derive(Default, Debug)] #[derive(Default, Debug)]
struct DebugCache { struct DebugCache {

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,9 @@
use super::*; use super::*;
pub use bytecheck::CheckBytes;
use core::fmt::Debug; use core::fmt::Debug;
pub use rkyv::Archive as RkyvArchive;
pub use rkyv::Deserialize as RkyvDeserialize;
pub use rkyv::Serialize as RkyvSerialize;
// XXX: Don't trace these functions as they are used in the transfer of API logs, which will recurse! // XXX: Don't trace these functions as they are used in the transfer of API logs, which will recurse!
@ -128,3 +132,79 @@ pub mod arc_serialize {
Ok(Arc::new(T::deserialize(d)?)) Ok(Arc::new(T::deserialize(d)?))
} }
} }
pub fn to_rkyv<T>(v: &T) -> EyreResult<Vec<u8>>
where
T: RkyvSerialize<rkyv::ser::serializers::AllocSerializer<1024>>,
{
Ok(rkyv::to_bytes::<T, 1024>(v)
.wrap_err("failed to freeze object")?
.to_vec())
}
pub fn from_rkyv<T>(v: Vec<u8>) -> EyreResult<T>
where
T: RkyvArchive,
<T as RkyvArchive>::Archived:
for<'t> bytecheck::CheckBytes<rkyv::validation::validators::DefaultValidator<'t>>,
<T as RkyvArchive>::Archived:
rkyv::Deserialize<T, rkyv::de::deserializers::SharedDeserializeMap>,
{
match rkyv::from_bytes::<T>(&v) {
Ok(v) => Ok(v),
Err(e) => {
bail!("failed to deserialize frozen object: {}", e);
}
}
}
pub struct RkyvEnumSet;
impl<T> rkyv::with::ArchiveWith<EnumSet<T>> for RkyvEnumSet
where
T: EnumSetType + EnumSetTypeWithRepr,
<T as EnumSetTypeWithRepr>::Repr: rkyv::Archive,
{
type Archived = rkyv::Archived<<T as EnumSetTypeWithRepr>::Repr>;
type Resolver = rkyv::Resolver<<T as EnumSetTypeWithRepr>::Repr>;
#[inline]
unsafe fn resolve_with(
field: &EnumSet<T>,
pos: usize,
resolver: Self::Resolver,
out: *mut Self::Archived,
) {
let r = field.as_repr();
r.resolve(pos, resolver, out);
}
}
impl<T, S> rkyv::with::SerializeWith<EnumSet<T>, S> for RkyvEnumSet
where
S: rkyv::Fallible + ?Sized,
T: EnumSetType + EnumSetTypeWithRepr,
<T as EnumSetTypeWithRepr>::Repr: rkyv::Serialize<S>,
{
fn serialize_with(field: &EnumSet<T>, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
let r = field.as_repr();
r.serialize(serializer)
}
}
impl<T, D>
rkyv::with::DeserializeWith<rkyv::Archived<<T as EnumSetTypeWithRepr>::Repr>, EnumSet<T>, D>
for RkyvEnumSet
where
D: rkyv::Fallible + ?Sized,
T: EnumSetType + EnumSetTypeWithRepr,
<T as EnumSetTypeWithRepr>::Repr: rkyv::Archive,
rkyv::Archived<<T as EnumSetTypeWithRepr>::Repr>: rkyv::Deserialize<EnumSet<T>, D>,
{
fn deserialize_with(
field: &rkyv::Archived<<T as EnumSetTypeWithRepr>::Repr>,
deserializer: &mut D,
) -> Result<EnumSet<T>, D::Error> {
Ok(field.deserialize(deserializer)?.into())
}
}