cli fixes
This commit is contained in:
parent
e80a3d3063
commit
1c8ecab2b6
@ -187,8 +187,14 @@ reply - reply to an AppCall not handled directly by the server
|
|||||||
let ui = self.ui_sender();
|
let ui = self.ui_sender();
|
||||||
spawn_detached_local(async move {
|
spawn_detached_local(async move {
|
||||||
match capi.server_debug(rest.unwrap_or_default()).await {
|
match capi.server_debug(rest.unwrap_or_default()).await {
|
||||||
Ok(output) => ui.display_string_dialog("Debug Output", output, callback),
|
Ok(output) => {
|
||||||
Err(e) => ui.display_string_dialog("Debug Error", e.to_string(), callback),
|
ui.add_node_event(Level::Debug, output);
|
||||||
|
ui.send_callback(callback);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
ui.add_node_event(Level::Error, e.to_string());
|
||||||
|
ui.send_callback(callback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -14,8 +14,8 @@ use cursive::CursiveRunnable;
|
|||||||
use cursive_flexi_logger_view::{CursiveLogWriter, FlexiLoggerView};
|
use cursive_flexi_logger_view::{CursiveLogWriter, FlexiLoggerView};
|
||||||
// use cursive_multiplex::*;
|
// use cursive_multiplex::*;
|
||||||
use std::collections::{HashMap, VecDeque};
|
use std::collections::{HashMap, VecDeque};
|
||||||
|
use std::io::Write;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////
|
||||||
///
|
///
|
||||||
struct Dirty<T> {
|
struct Dirty<T> {
|
||||||
@ -454,20 +454,52 @@ impl UI {
|
|||||||
Self::command_processor(s).start_connection();
|
Self::command_processor(s).start_connection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn copy_to_clipboard<S: AsRef<str>>(s: &mut Cursive, text: S) {
|
||||||
|
if let Ok(mut clipboard) = arboard::Clipboard::new() {
|
||||||
|
// X11/Wayland/other system copy
|
||||||
|
if clipboard.set_text(text.as_ref()).is_ok() {
|
||||||
|
let color = *Self::inner_mut(s).log_colors.get(&Level::Info).unwrap();
|
||||||
|
cursive_flexi_logger_view::push_to_log(StyledString::styled(
|
||||||
|
format!(">> Copied: {}", text.as_ref()),
|
||||||
|
color,
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
let color = *Self::inner_mut(s).log_colors.get(&Level::Warn).unwrap();
|
||||||
|
cursive_flexi_logger_view::push_to_log(StyledString::styled(
|
||||||
|
format!(">> Could not copy to clipboard"),
|
||||||
|
color,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// OSC52 clipboard copy for terminals
|
||||||
|
if std::io::stdout()
|
||||||
|
.write_all(
|
||||||
|
format!(
|
||||||
|
"\x1B]52;c;{}\x07",
|
||||||
|
data_encoding::BASE64.encode(text.as_ref().as_bytes()),
|
||||||
|
)
|
||||||
|
.as_bytes(),
|
||||||
|
)
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
if std::io::stdout().flush().is_ok() {
|
||||||
|
let color = *Self::inner_mut(s).log_colors.get(&Level::Info).unwrap();
|
||||||
|
cursive_flexi_logger_view::push_to_log(StyledString::styled(
|
||||||
|
format!(">> Copied: {}", text.as_ref()),
|
||||||
|
color,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn on_submit_peers_table_view(s: &mut Cursive, _row: usize, index: usize) {
|
fn on_submit_peers_table_view(s: &mut Cursive, _row: usize, index: usize) {
|
||||||
let peers_table_view = UI::peers(s);
|
let peers_table_view = UI::peers(s);
|
||||||
let node_id = peers_table_view
|
let node_id = peers_table_view
|
||||||
.borrow_item(index)
|
.borrow_item(index)
|
||||||
.map(|j| j["node_ids"][0].to_string());
|
.map(|j| j["node_ids"][0].to_string());
|
||||||
if let Some(node_id) = node_id {
|
if let Some(node_id) = node_id {
|
||||||
let mut clipboard = arboard::Clipboard::new().unwrap();
|
Self::copy_to_clipboard(s, node_id);
|
||||||
clipboard.set_text(node_id.clone()).unwrap();
|
|
||||||
|
|
||||||
let color = *Self::inner_mut(s).log_colors.get(&Level::Info).unwrap();
|
|
||||||
cursive_flexi_logger_view::push_to_log(StyledString::styled(
|
|
||||||
format!(">> NodeId Copied: {}", node_id),
|
|
||||||
color,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -967,10 +999,18 @@ impl UISender {
|
|||||||
pub fn set_config(&mut self, config: &json::JsonValue) {
|
pub fn set_config(&mut self, config: &json::JsonValue) {
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
|
|
||||||
inner
|
let node_ids = &config["network"]["routing_table"]["node_id"];
|
||||||
.ui_state
|
|
||||||
.node_id
|
let mut node_id_str = String::new();
|
||||||
.set(config["network"]["routing_table"]["node_id"].to_string());
|
for l in 0..node_ids.len() {
|
||||||
|
let nid = &node_ids[l];
|
||||||
|
if !node_id_str.is_empty() {
|
||||||
|
node_id_str.push_str(" ");
|
||||||
|
}
|
||||||
|
node_id_str.push_str(nid.to_string().as_ref());
|
||||||
|
}
|
||||||
|
|
||||||
|
inner.ui_state.node_id.set(node_id_str);
|
||||||
}
|
}
|
||||||
pub fn set_connection_state(&mut self, state: ConnectionState) {
|
pub fn set_connection_state(&mut self, state: ConnectionState) {
|
||||||
{
|
{
|
||||||
|
@ -130,6 +130,7 @@ macro_rules! byte_array_type {
|
|||||||
Self { bytes }
|
Self { bytes }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Big endian bit ordering
|
||||||
pub fn bit(&self, index: usize) -> bool {
|
pub fn bit(&self, index: usize) -> bool {
|
||||||
assert!(index < ($size * 8));
|
assert!(index < ($size * 8));
|
||||||
let bi = index / 8;
|
let bi = index / 8;
|
||||||
@ -152,6 +153,7 @@ macro_rules! byte_array_type {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Big endian nibble ordering
|
||||||
pub fn nibble(&self, index: usize) -> u8 {
|
pub fn nibble(&self, index: usize) -> u8 {
|
||||||
assert!(index < ($size * 2));
|
assert!(index < ($size * 2));
|
||||||
let bi = index / 2;
|
let bi = index / 2;
|
||||||
|
@ -353,10 +353,40 @@ async fn test_operations(vcrypto: CryptoSystemVersion) {
|
|||||||
assert_eq!(d4.first_nonzero_bit(), Some(0));
|
assert_eq!(d4.first_nonzero_bit(), Some(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn test_crypto_key_ordering() {
|
||||||
|
let k1 = CryptoKey::new([
|
||||||
|
128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0,
|
||||||
|
]);
|
||||||
|
let k2 = CryptoKey::new([
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0,
|
||||||
|
]);
|
||||||
|
let k3 = CryptoKey::new([
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 128,
|
||||||
|
]);
|
||||||
|
let k4 = CryptoKey::new([
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 1,
|
||||||
|
]);
|
||||||
|
let k5 = CryptoKey::new([
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
assert!(k2 < k1);
|
||||||
|
assert!(k3 < k2);
|
||||||
|
assert!(k4 < k3);
|
||||||
|
assert!(k5 < k4);
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn test_all() {
|
pub async fn test_all() {
|
||||||
let api = crypto_tests_startup().await;
|
let api = crypto_tests_startup().await;
|
||||||
let crypto = api.crypto().unwrap();
|
let crypto = api.crypto().unwrap();
|
||||||
|
|
||||||
|
test_crypto_key_ordering().await;
|
||||||
|
|
||||||
// Test versions
|
// Test versions
|
||||||
for v in VALID_CRYPTO_KINDS {
|
for v in VALID_CRYPTO_KINDS {
|
||||||
let vcrypto = crypto.get(v).unwrap();
|
let vcrypto = crypto.get(v).unwrap();
|
||||||
|
@ -51,6 +51,7 @@ impl RoutingTable {
|
|||||||
return NetworkResult::invalid_message("unsupported cryptosystem");
|
return NetworkResult::invalid_message("unsupported cryptosystem");
|
||||||
};
|
};
|
||||||
let own_distance = vcrypto.distance(&own_node_id.value, &key.value);
|
let own_distance = vcrypto.distance(&own_node_id.value, &key.value);
|
||||||
|
let vcrypto2 = vcrypto.clone();
|
||||||
|
|
||||||
let filter = Box::new(
|
let filter = Box::new(
|
||||||
move |rti: &RoutingTableInner, opt_entry: Option<Arc<BucketEntry>>| {
|
move |rti: &RoutingTableInner, opt_entry: Option<Arc<BucketEntry>>| {
|
||||||
@ -98,6 +99,46 @@ impl RoutingTable {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// xxx test
|
||||||
|
// Validate peers returned are, in fact, closer to the key than the node we sent this to
|
||||||
|
let valid = match Self::verify_peers_closer(vcrypto2, own_node_id, key, &closest_nodes) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
panic!("missing cryptosystem in peers node ids: {}", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if !valid {
|
||||||
|
panic!("non-closer peers returned");
|
||||||
|
}
|
||||||
|
|
||||||
NetworkResult::value(closest_nodes)
|
NetworkResult::value(closest_nodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Determine if set of peers is closer to key_near than key_far
|
||||||
|
pub(crate) fn verify_peers_closer(
|
||||||
|
vcrypto: CryptoSystemVersion,
|
||||||
|
key_far: TypedKey,
|
||||||
|
key_near: TypedKey,
|
||||||
|
peers: &[PeerInfo],
|
||||||
|
) -> EyreResult<bool> {
|
||||||
|
let kind = vcrypto.kind();
|
||||||
|
|
||||||
|
if key_far.kind != kind || key_near.kind != kind {
|
||||||
|
bail!("keys all need the same cryptosystem");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut closer = true;
|
||||||
|
for peer in peers {
|
||||||
|
let Some(key_peer) = peer.node_ids().get(kind) else {
|
||||||
|
bail!("peers need to have a key with the same cryptosystem");
|
||||||
|
};
|
||||||
|
let d_near = vcrypto.distance(&key_near.value, &key_peer.value);
|
||||||
|
let d_far = vcrypto.distance(&key_far.value, &key_peer.value);
|
||||||
|
if d_far < d_near {
|
||||||
|
closer = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(closer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -404,37 +404,6 @@ impl RPCProcessor {
|
|||||||
routing_table.signed_node_info_is_valid_in_routing_domain(routing_domain, &signed_node_info)
|
routing_table.signed_node_info_is_valid_in_routing_domain(routing_domain, &signed_node_info)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determine if set of peers is closer to key_near than key_far
|
|
||||||
fn verify_peers_closer(
|
|
||||||
&self,
|
|
||||||
vcrypto: CryptoSystemVersion,
|
|
||||||
key_far: TypedKey,
|
|
||||||
key_near: TypedKey,
|
|
||||||
peers: &[PeerInfo],
|
|
||||||
) -> Result<bool, RPCError> {
|
|
||||||
let kind = vcrypto.kind();
|
|
||||||
|
|
||||||
if key_far.kind != kind || key_near.kind != kind {
|
|
||||||
return Err(RPCError::internal("keys all need the same cryptosystem"));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut closer = true;
|
|
||||||
for peer in peers {
|
|
||||||
let Some(key_peer) = peer.node_ids().get(kind) else {
|
|
||||||
return Err(RPCError::invalid_format(
|
|
||||||
"peers need to have a key with the same cryptosystem",
|
|
||||||
));
|
|
||||||
};
|
|
||||||
let d_near = vcrypto.distance(&key_near.value, &key_peer.value);
|
|
||||||
let d_far = vcrypto.distance(&key_far.value, &key_peer.value);
|
|
||||||
if d_far < d_near {
|
|
||||||
closer = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(closer)
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/// Search the DHT for a single node closest to a key and add it to the routing table and return the node reference
|
/// Search the DHT for a single node closest to a key and add it to the routing table and return the node reference
|
||||||
|
@ -76,15 +76,13 @@ impl RPCProcessor {
|
|||||||
let (value, peers, descriptor) = get_value_a.destructure();
|
let (value, peers, descriptor) = get_value_a.destructure();
|
||||||
|
|
||||||
// Validate peers returned are, in fact, closer to the key than the node we sent this to
|
// Validate peers returned are, in fact, closer to the key than the node we sent this to
|
||||||
let valid = match self.verify_peers_closer(vcrypto, target_node_id, key, &peers) {
|
let valid = match RoutingTable::verify_peers_closer(vcrypto, target_node_id, key, &peers) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if matches!(e, RPCError::Internal(_)) {
|
return Ok(NetworkResult::invalid_message(format!(
|
||||||
return Err(e);
|
"missing cryptosystem in peers node ids: {}",
|
||||||
}
|
e
|
||||||
return Ok(NetworkResult::invalid_message(
|
)));
|
||||||
"missing cryptosystem in peers node ids",
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if !valid {
|
if !valid {
|
||||||
|
@ -83,15 +83,13 @@ impl RPCProcessor {
|
|||||||
let (set, value, peers) = set_value_a.destructure();
|
let (set, value, peers) = set_value_a.destructure();
|
||||||
|
|
||||||
// Validate peers returned are, in fact, closer to the key than the node we sent this to
|
// Validate peers returned are, in fact, closer to the key than the node we sent this to
|
||||||
let valid = match self.verify_peers_closer(vcrypto, target_node_id, key, &peers) {
|
let valid = match RoutingTable::verify_peers_closer(vcrypto, target_node_id, key, &peers) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if matches!(e, RPCError::Internal(_)) {
|
return Ok(NetworkResult::invalid_message(format!(
|
||||||
return Err(e);
|
"missing cryptosystem in peers node ids: {}",
|
||||||
}
|
e
|
||||||
return Ok(NetworkResult::invalid_message(
|
)));
|
||||||
"missing cryptosystem in peers node ids",
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if !valid {
|
if !valid {
|
||||||
|
@ -341,7 +341,6 @@ impl StorageManager {
|
|||||||
} else {
|
} else {
|
||||||
ValueData::new(data, writer.key)
|
ValueData::new(data, writer.key)
|
||||||
};
|
};
|
||||||
let seq = value_data.seq();
|
|
||||||
|
|
||||||
// Validate with schema
|
// Validate with schema
|
||||||
if !schema.check_subkey_value_data(descriptor.owner(), subkey, &value_data) {
|
if !schema.check_subkey_value_data(descriptor.owner(), subkey, &value_data) {
|
||||||
@ -374,7 +373,6 @@ impl StorageManager {
|
|||||||
drop(inner);
|
drop(inner);
|
||||||
|
|
||||||
// Use the safety selection we opened the record with
|
// Use the safety selection we opened the record with
|
||||||
|
|
||||||
let final_signed_value_data = self
|
let final_signed_value_data = self
|
||||||
.outbound_set_value(
|
.outbound_set_value(
|
||||||
rpc_processor,
|
rpc_processor,
|
||||||
@ -386,13 +384,12 @@ impl StorageManager {
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// If we got a new value back then write it to the opened record
|
// Whatever record we got back, store it locally, might be newer than the one we asked to save
|
||||||
if final_signed_value_data.value_data().seq() != seq {
|
let mut inner = self.lock().await?;
|
||||||
let mut inner = self.lock().await?;
|
inner
|
||||||
inner
|
.handle_set_local_value(key, subkey, final_signed_value_data.clone())
|
||||||
.handle_set_local_value(key, subkey, final_signed_value_data.clone())
|
.await?;
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
Ok(Some(final_signed_value_data.into_value_data()))
|
Ok(Some(final_signed_value_data.into_value_data()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +67,9 @@ async def test_set_get_dht_value(api_connection: veilid.VeilidAPI):
|
|||||||
vd2 = await rc.get_dht_value(rec.key, 0, False)
|
vd2 = await rc.get_dht_value(rec.key, 0, False)
|
||||||
assert vd2 != None
|
assert vd2 != None
|
||||||
|
|
||||||
|
print("vd: {}", vd.__dict__)
|
||||||
|
print("vd2: {}", vd2.__dict__)
|
||||||
|
|
||||||
assert vd == vd2
|
assert vd == vd2
|
||||||
|
|
||||||
await rc.close_dht_record(rec.key)
|
await rc.close_dht_record(rec.key)
|
||||||
|
@ -2,6 +2,7 @@ import base64
|
|||||||
import json
|
import json
|
||||||
from enum import StrEnum
|
from enum import StrEnum
|
||||||
from typing import Any, Optional, Self, Tuple
|
from typing import Any, Optional, Self, Tuple
|
||||||
|
from functools import total_ordering
|
||||||
|
|
||||||
####################################################################
|
####################################################################
|
||||||
|
|
||||||
@ -323,6 +324,7 @@ class DHTRecordDescriptor:
|
|||||||
return self.__dict__
|
return self.__dict__
|
||||||
|
|
||||||
|
|
||||||
|
# @total_ordering
|
||||||
class ValueData:
|
class ValueData:
|
||||||
seq: ValueSeqNum
|
seq: ValueSeqNum
|
||||||
data: bytes
|
data: bytes
|
||||||
@ -333,6 +335,21 @@ class ValueData:
|
|||||||
self.data = data
|
self.data = data
|
||||||
self.writer = writer
|
self.writer = writer
|
||||||
|
|
||||||
|
# def __lt__(self, other):
|
||||||
|
# return self.data < other.data
|
||||||
|
|
||||||
|
# def __eq__(self, other):
|
||||||
|
# return self.cgpa == other.cgpa
|
||||||
|
|
||||||
|
# def __le__(self, other):
|
||||||
|
# return self.cgpa<= other.cgpa
|
||||||
|
|
||||||
|
# def __ge__(self, other):
|
||||||
|
# return self.cgpa>= other.cgpa
|
||||||
|
|
||||||
|
# def __ne__(self, other):
|
||||||
|
# return self.cgpa != other.cgpa
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_json(cls, j: dict) -> Self:
|
def from_json(cls, j: dict) -> Self:
|
||||||
return cls(
|
return cls(
|
||||||
|
Loading…
Reference in New Issue
Block a user