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

View File

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

View File

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

View File

@@ -2,7 +2,6 @@ use crate::xx::*;
use crate::*;
use data_encoding::BASE64URL_NOPAD;
use keyring_manager::*;
use serde::{Deserialize, Serialize};
use std::path::Path;
pub struct ProtectedStoreInner {
@@ -144,18 +143,31 @@ impl ProtectedStore {
}
#[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
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
}
#[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
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 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))
}

View File

@@ -85,12 +85,25 @@ impl TableDB {
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.
pub fn store_cbor<T>(&self, col: u32, key: &[u8], value: &T) -> EyreResult<()>
/// Store a key in rkyv format with a value in a column in the TableDB. Performs a single transaction immediately.
pub fn store_rkyv<T>(&self, col: u32, key: &[u8], value: &T) -> EyreResult<()>
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 mut dbt = db.transaction();
@@ -104,10 +117,14 @@ impl TableDB {
db.get(col, key).wrap_err("failed to get key")
}
/// Read a key from a column in the TableDB immediately, in CBOR format.
pub fn load_cbor<T>(&self, col: u32, key: &[u8]) -> EyreResult<Option<T>>
/// Read an rkyv key from a column in the TableDB immediately
pub fn load_rkyv<T>(&self, col: u32, key: &[u8]) -> EyreResult<Option<T>>
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 out = db.get(col, key).wrap_err("failed to get key")?;
@@ -117,7 +134,24 @@ impl TableDB {
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))
}
@@ -176,12 +210,22 @@ impl<'a> TableDBTransaction<'a> {
self.dbt.as_mut().unwrap().put(col, key, value);
}
/// Store a key in CBOR format with a value in a column in the TableDB
pub fn store_cbor<T>(&mut self, col: u32, key: &[u8], value: &T) -> EyreResult<()>
/// Store a key in rkyv format with a value in a column in the TableDB
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
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());
Ok(())
}

View File

@@ -136,18 +136,22 @@ impl ProtectedStore {
}
#[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
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
}
#[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
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 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))
}

View File

@@ -295,7 +295,7 @@ impl NetworkManager {
if let Some(nr) = routing_table.register_node_with_signed_node_info(
RoutingDomain::PublicInternet,
k,
SignedNodeInfo::with_no_signature(NodeInfo {
SignedDirectNodeInfo::with_no_signature(NodeInfo {
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
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>>;
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 {
match state {
@@ -27,29 +39,33 @@ impl Bucket {
}
}
pub(super) fn load_bucket(&mut self, data: &[u8]) -> EyreResult<()> {
let bucket_data: BucketData =
serde_cbor::from_slice::<BucketData>(data).wrap_err("failed to deserialize bucket")?;
pub(super) fn load_bucket(&mut self, data: Vec<u8>) -> EyreResult<()> {
let bucket_data: BucketData = from_rkyv(data)?;
for (k, d) in bucket_data.0 {
let entryinner = serde_cbor::from_slice::<BucketEntryInner>(&d)
.wrap_err("failed to deserialize bucket entry")?;
for e in bucket_data.entries {
let entryinner = from_rkyv(e.value).wrap_err("failed to deserialize bucket entry")?;
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(())
}
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 {
let entry_bytes = v.with_mut_inner(|e| serde_cbor::to_vec(e))?;
entry_vec.push((*k, entry_bytes));
let entry_bytes = v.with_inner(|e| to_rkyv(e))?;
entries.push(BucketEntryData {
key: *k,
value: entry_bytes,
});
}
let bucket_data: BucketData = (entry_vec, self.newest_entry.clone());
let out = serde_cbor::to_vec(&bucket_data)?;
let bucket_data = BucketData {
entries,
newest_entry: self.newest_entry.clone(),
};
let out = to_rkyv(&bucket_data)?;
Ok(out)
}

View File

@@ -64,22 +64,44 @@ pub struct BucketEntryLocalNetwork {
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)]
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,
/// The last connection descriptors used to contact this node, per protocol type
#[serde(skip)]
last_connections: BTreeMap<LastConnectionKey, (ConnectionDescriptor, u64)>,
/// The node info for this entry on the publicinternet routing domain
public_internet: BucketEntryPublicInternet,
/// The node info for this entry on the localnetwork routing domain
local_network: BucketEntryLocalNetwork,
/// Statistics gathered for the peer
peer_stats: PeerStats,
/// The accounting for the latency statistics
#[serde(skip)]
latency_stats_accounting: LatencyStatsAccounting,
/// The accounting for the transfer statistics
#[serde(skip)]
transfer_stats_accounting: TransferStatsAccounting,
/// Tracking identifier for NodeRef debugging
#[cfg(feature = "tracking")]
#[serde(skip)]
next_track_id: usize,
/// Backtraces for NodeRef debugging
#[cfg(feature = "tracking")]
#[serde(skip)]
node_ref_tracks: HashMap<usize, backtrace::Backtrace>,
@@ -190,12 +212,12 @@ impl BucketEntryInner {
// Always allow overwriting invalid/unsigned node
if current_sni.has_valid_signature() {
// 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
// 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
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
// Touch the node and let it try to live again
@@ -207,11 +229,22 @@ impl BucketEntryInner {
}
}
// Update the protocol min/max version we have
self.min_max_version = Some((
signed_node_info.node_info.min_version,
signed_node_info.node_info.max_version,
));
// Update the protocol min/max version we have to use, to include relay requirements if needed
let mut version_range = VersionRange {
min: signed_node_info.node_info().min_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
*opt_current_sni = Some(Box::new(signed_node_info));
@@ -238,7 +271,7 @@ impl BucketEntryInner {
RoutingDomain::LocalNetwork => &self.local_network.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> {
@@ -338,11 +371,11 @@ impl BucketEntryInner {
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);
}
pub fn min_max_version(&self) -> Option<(u8, u8)> {
pub fn min_max_version(&self) -> Option<VersionRange> {
self.min_max_version
}

View File

@@ -163,7 +163,7 @@ impl RoutingTable {
// Load bucket entries from table db if possible
debug!("loading routing table entries");
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();
inner.init_buckets(self.clone());
}
@@ -173,7 +173,7 @@ impl RoutingTable {
let route_spec_store = match RouteSpecStore::load(self.clone()).await {
Ok(v) => v,
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())
}
};
@@ -239,7 +239,7 @@ impl RoutingTable {
let tdb = table_store.open("routing_table", 1).await?;
let bucket_count = bucketvec.len();
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();
return Err(e);
}
@@ -253,14 +253,13 @@ impl RoutingTable {
async fn load_buckets(&self) -> EyreResult<()> {
// Deserialize all entries
let inner = &mut *self.inner.write();
let tstore = self.network_manager().table_store();
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");
return Ok(());
};
let inner = &mut *self.inner.write();
if bucket_count != inner.buckets.len() {
// Must have the same number of buckets
warn!("bucket count is different, not loading routing table");
@@ -275,8 +274,8 @@ impl RoutingTable {
};
bucketdata_vec.push(bucketdata);
}
for n in 0..bucket_count {
inner.buckets[n].load_bucket(&bucketdata_vec[n])?;
for (n, bucketdata) in bucketdata_vec.into_iter().enumerate() {
inner.buckets[n].load_bucket(bucketdata)?;
}
Ok(())
@@ -383,7 +382,7 @@ impl RoutingTable {
}
/// 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)
}
@@ -526,7 +525,7 @@ impl RoutingTable {
&self,
routing_domain: RoutingDomain,
node_id: DHTKey,
signed_node_info: SignedNodeInfo,
signed_node_info: SignedDirectNodeInfo,
allow_invalid: bool,
) -> Option<NodeRef> {
self.inner.write().register_node_with_signed_node_info(

View File

@@ -385,9 +385,12 @@ impl NodeRef {
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())
}
pub fn locked_mut<'a>(&self, rti: &'a mut RoutingTableInner) -> NodeRefLockedMut<'a> {
NodeRefLockedMut::new(rti, self.clone())
}
}
impl NodeRefBase for NodeRef {
@@ -480,12 +483,12 @@ impl Drop for NodeRef {
/// already locked a RoutingTableInner
/// Keeps entry in the routing table until all references are gone
pub struct NodeRefLocked<'a> {
inner: Mutex<&'a mut RoutingTableInner>,
inner: Mutex<&'a RoutingTableInner>,
nr: NodeRef,
}
impl<'a> NodeRefLocked<'a> {
pub fn new(inner: &'a mut RoutingTableInner, nr: NodeRef) -> Self {
pub fn new(inner: &'a RoutingTableInner, nr: NodeRef) -> Self {
Self {
inner: Mutex::new(inner),
nr,
@@ -510,6 +513,65 @@ impl<'a> NodeRefBase for NodeRefLocked<'a> {
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
where
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 {
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 {
f.debug_struct("NodeRefLocked")
f.debug_struct("NodeRefLockedMut")
.field("nr", &self.nr)
.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 rsstdb = table_store.open("RouteSpecStore", 1).await?;
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
let mut dead_keys = Vec::new();
@@ -246,7 +246,7 @@ impl RouteSpecStore {
// Load secrets from pstore
let pstore = routing_table.network_manager().protected_store();
let out: Vec<(DHTKey, DHTKeySecret)> = pstore
.load_user_secret_cbor("RouteSpecStore")
.load_user_secret_rkyv("RouteSpecStore")
.await?
.unwrap_or_default();
@@ -289,14 +289,14 @@ impl RouteSpecStore {
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
.unlocked_inner
.routing_table
.network_manager()
.table_store();
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
let pstore = self
@@ -310,7 +310,9 @@ impl RouteSpecStore {
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(())
}

View File

@@ -101,6 +101,45 @@ impl RoutingDomainDetailCommon {
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
where
F: FnOnce(&PeerInfo) -> R,
@@ -110,7 +149,7 @@ impl RoutingDomainDetailCommon {
// Regenerate peer info
let pi = PeerInfo::new(
NodeId::new(rti.unlocked_inner.node_id),
SignedNodeInfo::with_secret(
SignedDirectNodeInfo::with_secret(
NodeInfo {
network_class: self.network_class.unwrap_or(NetworkClass::Invalid),
outbound_protocols: self.outbound_protocols,
@@ -118,10 +157,11 @@ impl RoutingDomainDetailCommon {
min_version: MIN_CRYPTO_VERSION,
max_version: MAX_CRYPTO_VERSION,
dial_info_detail_list: self.dial_info_details.clone(),
relay_peer_info: self
.relay_node
.as_ref()
.and_then(|rn| rn.make_peer_info(self.routing_domain).map(Box::new)),
relay_peer_info: self.relay_node.as_ref().and_then(|rn| {
rn.locked(rti)
.make_peer_info(self.routing_domain)
.map(Box::new)
}),
},
NodeId::new(rti.unlocked_inner.node_id),
&rti.unlocked_inner.node_id_secret,

View File

@@ -253,7 +253,7 @@ impl RoutingTableInner {
}
/// 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| {
rdd.common()
.with_peer_info(self, |pi| pi.signed_node_info.clone())
@@ -662,7 +662,7 @@ impl RoutingTableInner {
outer_self: RoutingTable,
routing_domain: RoutingDomain,
node_id: DHTKey,
signed_node_info: SignedNodeInfo,
signed_node_info: SignedDirectNodeInfo,
allow_invalid: bool,
) -> Option<NodeRef> {
// validate signed node info is not something malicious
@@ -717,7 +717,8 @@ impl RoutingTableInner {
});
if let Some(nr) = &out {
// 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
}

View File

@@ -17,7 +17,9 @@ mod public_key;
mod sender_info;
mod signal_info;
mod signature;
mod signed_direct_node_info;
mod signed_node_info;
mod signed_relayed_node_info;
mod socket_address;
mod tunnel;
mod value_data;
@@ -42,7 +44,9 @@ pub use public_key::*;
pub use sender_info::*;
pub use signal_info::*;
pub use signature::*;
pub use signed_direct_node_info::*;
pub use signed_node_info::*;
pub use signed_relayed_node_info::*;
pub use socket_address::*;
pub use tunnel::*;
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::OutboundOnly => veilid_capnp::NetworkClass::OutboundOnly,
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::OutboundOnly => NetworkClass::OutboundOnly,
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)?;
}
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(())
}
pub fn decode_node_info(
reader: &veilid_capnp::node_info::Reader,
allow_relay_peer_info: bool,
) -> Result<NodeInfo, RPCError> {
pub fn decode_node_info(reader: &veilid_capnp::node_info::Reader) -> Result<NodeInfo, RPCError> {
let network_class = decode_network_class(
reader
.reborrow()
@@ -81,22 +73,6 @@ pub fn decode_node_info(
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 {
network_class,
outbound_protocols,
@@ -104,6 +80,5 @@ pub fn decode_node_info(
min_version,
max_version,
dial_info_detail_list,
relay_peer_info,
})
}

View File

@@ -120,7 +120,7 @@ impl RPCOperation {
let sni_reader = operation_reader
.get_sender_node_info()
.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)
} else {
None

View File

@@ -47,7 +47,7 @@ impl RPCOperationFindBlockA {
.map_err(RPCError::map_internal("too many suppliers"))?,
);
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);
}
@@ -59,7 +59,7 @@ impl RPCOperationFindBlockA {
.map_err(RPCError::map_internal("too many peers"))?,
);
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);
}

View File

@@ -41,7 +41,7 @@ impl RPCOperationFindNodeA {
.map_err(RPCError::map_internal("too many peers"))?,
);
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);
}

View File

@@ -48,7 +48,7 @@ impl RPCOperationGetValueA {
.map_err(RPCError::map_internal("too many peers"))?,
);
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);
}

View File

@@ -18,7 +18,7 @@ impl RPCOperationNodeInfoUpdate {
}
let sender_node_id = opt_sender_node_id.unwrap();
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 })
}

View File

@@ -53,7 +53,7 @@ impl RPCOperationSetValueA {
.map_err(RPCError::map_internal("too many peers"))?,
);
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);
}

View File

@@ -49,7 +49,7 @@ impl RPCOperationSupplyBlockA {
.map_err(RPCError::map_internal("too many peers"))?,
);
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);
}

View File

@@ -43,7 +43,7 @@ impl RPCOperationWatchValueA {
.map_err(RPCError::map_internal("too many peers"))?,
);
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);
}

View File

@@ -14,10 +14,7 @@ pub fn encode_peer_info(
Ok(())
}
pub fn decode_peer_info(
reader: &veilid_capnp::peer_info::Reader,
allow_relay_peer_info: bool,
) -> Result<PeerInfo, RPCError> {
pub fn decode_peer_info(reader: &veilid_capnp::peer_info::Reader) -> Result<PeerInfo, RPCError> {
let nid_reader = reader
.reborrow()
.get_node_id()
@@ -27,8 +24,7 @@ pub fn decode_peer_info(
.get_signed_node_info()
.map_err(RPCError::protocol)?;
let node_id = NodeId::new(decode_public_key(&nid_reader));
let signed_node_info =
decode_signed_node_info(&sni_reader, &node_id.key, allow_relay_peer_info)?;
let signed_node_info = decode_signed_node_info(&sni_reader, &node_id.key)?;
Ok(PeerInfo {
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) => {
let pi_reader = pi.map_err(RPCError::protocol)?;
RouteNode::PeerInfo(
decode_peer_info(&pi_reader, true)
decode_peer_info(&pi_reader)
.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(
"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 }
}
@@ -69,7 +69,7 @@ pub fn decode_signal_info(
let pi_reader = r.get_peer_info().map_err(RPCError::map_protocol(
"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 }
}

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

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
// 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
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
// Otherwise we would be attaching the original sender's identity to the final destination,
// thus defeating the purpose of the safety route entirely :P
@@ -682,7 +682,7 @@ impl RPCProcessor {
let op_id = operation.op_id();
// 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
let RenderedOperation {
@@ -745,7 +745,7 @@ impl RPCProcessor {
let operation = RPCOperation::new_statement(statement, opt_sender_info);
// 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
let RenderedOperation {
@@ -865,7 +865,7 @@ impl RPCProcessor {
let operation = RPCOperation::new_answer(&request.operation, answer, opt_sender_info);
// 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
let RenderedOperation {
@@ -997,7 +997,7 @@ impl RPCProcessor {
};
// 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
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()));
}
pub async fn test_cbor(ts: TableStore) {
trace!("test_cbor");
pub async fn test_frozen(ts: TableStore) {
trace!("test_frozen");
let _ = ts.delete("test");
let db = ts.open("test", 3).await.expect("should have opened");
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,
Err(e) => {
panic!("couldn't decode cbor: {}", e);
panic!("couldn't decode: {}", e);
}
};
assert_eq!(d, Some(dht_key), "keys should be equal");
@@ -147,8 +147,8 @@ pub async fn test_cbor(ts: TableStore) {
);
assert!(
db.load_cbor::<DHTKey>(1, b"foo").is_err(),
"should fail to load cbor"
db.load_rkyv::<DHTKey>(1, b"foo").is_err(),
"should fail to unfreeze"
);
}
@@ -157,7 +157,7 @@ pub async fn test_all() {
let ts = api.table_store().unwrap();
test_delete_open_delete(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;

View File

@@ -43,7 +43,78 @@ pub async fn test_attach_detach() {
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() {
test_startup_shutdown().await;
test_attach_detach().await;
test_signed_node_info().await;
}

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,9 @@
use super::*;
pub use bytecheck::CheckBytes;
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!
@@ -128,3 +132,79 @@ pub mod arc_serialize {
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())
}
}