xfer
This commit is contained in:
parent
cd9a3414cf
commit
f17c2f62cb
@ -29,6 +29,13 @@ pub enum Destination {
|
||||
}
|
||||
|
||||
impl Destination {
|
||||
pub fn target(&self) -> Option<NodeRef> {
|
||||
match self {
|
||||
Destination::Direct { target, safety_selection: _ } => Some(target.clone()),
|
||||
Destination::Relay { relay:_, target, safety_selection: _ } => Some(target.clone()),
|
||||
Destination::PrivateRoute { private_route:_, safety_selection:_ } => None,
|
||||
}
|
||||
}
|
||||
pub fn direct(target: NodeRef) -> Self {
|
||||
let sequencing = target.sequencing();
|
||||
Self::Direct {
|
||||
|
@ -88,6 +88,7 @@ where
|
||||
for cn in &ctx.closest_nodes {
|
||||
if cn.same_entry(&nn) {
|
||||
dup = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !dup {
|
||||
@ -125,6 +126,7 @@ where
|
||||
// New fanout call candidate found
|
||||
next_node = Some(cn.clone());
|
||||
ctx.called_nodes.add(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -395,7 +395,7 @@ impl RPCProcessor {
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Determine if a SignedNodeInfo can be placed into the specified routing domain
|
||||
fn filter_node_info(
|
||||
fn verify_node_info(
|
||||
&self,
|
||||
routing_domain: RoutingDomain,
|
||||
signed_node_info: &SignedNodeInfo,
|
||||
@ -404,6 +404,37 @@ impl RPCProcessor {
|
||||
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
|
||||
@ -1348,7 +1379,7 @@ impl RPCProcessor {
|
||||
// Ensure the sender peer info is for the actual sender specified in the envelope
|
||||
|
||||
// Sender PeerInfo was specified, update our routing table with it
|
||||
if !self.filter_node_info(routing_domain, sender_peer_info.signed_node_info()) {
|
||||
if !self.verify_node_info(routing_domain, sender_peer_info.signed_node_info()) {
|
||||
return Ok(NetworkResult::invalid_message(
|
||||
"sender peerinfo has invalid peer scope",
|
||||
));
|
||||
|
@ -29,9 +29,9 @@ impl RPCProcessor {
|
||||
let app_call_a = match kind {
|
||||
RPCOperationKind::Answer(a) => match a.destructure() {
|
||||
RPCAnswerDetail::AppCallA(a) => a,
|
||||
_ => return Err(RPCError::invalid_format("not an appcall answer")),
|
||||
_ => return Ok(NetworkResult::invalid_message("not an appcall answer")),
|
||||
},
|
||||
_ => return Err(RPCError::invalid_format("not an answer")),
|
||||
_ => return Ok(NetworkResult::invalid_message("not an answer")),
|
||||
};
|
||||
|
||||
let a_message = app_call_a.destructure();
|
||||
|
@ -46,17 +46,17 @@ impl RPCProcessor {
|
||||
let find_node_a = match kind {
|
||||
RPCOperationKind::Answer(a) => match a.destructure() {
|
||||
RPCAnswerDetail::FindNodeA(a) => a,
|
||||
_ => return Err(RPCError::invalid_format("not a find_node answer")),
|
||||
_ => return Ok(NetworkResult::invalid_message("not a find_node answer")),
|
||||
},
|
||||
_ => return Err(RPCError::invalid_format("not an answer")),
|
||||
_ => return Ok(NetworkResult::invalid_message("not an answer")),
|
||||
};
|
||||
|
||||
// Verify peers are in the correct peer scope
|
||||
let peers = find_node_a.destructure();
|
||||
|
||||
for peer_info in &peers {
|
||||
if !self.filter_node_info(RoutingDomain::PublicInternet, peer_info.signed_node_info()) {
|
||||
return Err(RPCError::invalid_format(
|
||||
if !self.verify_node_info(RoutingDomain::PublicInternet, peer_info.signed_node_info()) {
|
||||
return Ok(NetworkResult::invalid_message(
|
||||
"find_node response has invalid peer scope",
|
||||
));
|
||||
}
|
||||
|
@ -24,32 +24,32 @@ impl RPCProcessor {
|
||||
last_descriptor: Option<SignedValueDescriptor>,
|
||||
) -> Result<NetworkResult<Answer<GetValueAnswer>>, RPCError> {
|
||||
// Ensure destination never has a private route
|
||||
if matches!(
|
||||
dest,
|
||||
Destination::PrivateRoute {
|
||||
private_route: _,
|
||||
safety_selection: _
|
||||
}
|
||||
) {
|
||||
// and get the target noderef so we can validate the response
|
||||
let Some(target) = dest.target() else {
|
||||
return Err(RPCError::internal(
|
||||
"Never send get value requests over private routes",
|
||||
"Never send set value requests over private routes",
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
// Get the target node id
|
||||
let Some(vcrypto) = self.crypto.get(key.kind) else {
|
||||
return Err(RPCError::internal("unsupported cryptosystem"));
|
||||
};
|
||||
let Some(target_node_id) = target.node_ids().get(key.kind) else {
|
||||
return Err(RPCError::internal("No node id for crypto kind"));
|
||||
};
|
||||
|
||||
// Send the getvalue question
|
||||
let get_value_q = RPCOperationGetValueQ::new(key, subkey, last_descriptor.is_none());
|
||||
let question = RPCQuestion::new(
|
||||
network_result_try!(self.get_destination_respond_to(&dest)?),
|
||||
RPCQuestionDetail::GetValueQ(get_value_q),
|
||||
);
|
||||
let Some(vcrypto) = self.crypto.get(key.kind) else {
|
||||
return Err(RPCError::internal("unsupported cryptosystem"));
|
||||
};
|
||||
|
||||
// Send the getvalue question
|
||||
let question_context = QuestionContext::GetValue(ValidateGetValueContext {
|
||||
last_descriptor,
|
||||
subkey,
|
||||
vcrypto,
|
||||
vcrypto: vcrypto.clone(),
|
||||
});
|
||||
|
||||
let waitable_reply = network_result_try!(
|
||||
@ -68,13 +68,29 @@ impl RPCProcessor {
|
||||
let get_value_a = match kind {
|
||||
RPCOperationKind::Answer(a) => match a.destructure() {
|
||||
RPCAnswerDetail::GetValueA(a) => a,
|
||||
_ => return Err(RPCError::invalid_format("not a getvalue answer")),
|
||||
_ => return Ok(NetworkResult::invalid_message("not a getvalue answer")),
|
||||
},
|
||||
_ => return Err(RPCError::invalid_format("not an answer")),
|
||||
_ => return Ok(NetworkResult::invalid_message("not an answer")),
|
||||
};
|
||||
|
||||
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
|
||||
let valid = match self.verify_peers_closer(vcrypto, target_node_id, key, &peers) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
if matches!(e, RPCError::Internal(_)) {
|
||||
return Err(e);
|
||||
}
|
||||
return Ok(NetworkResult::invalid_message(
|
||||
"missing cryptosystem in peers node ids",
|
||||
));
|
||||
}
|
||||
};
|
||||
if !valid {
|
||||
return Ok(NetworkResult::invalid_message("non-closer peers returned"));
|
||||
}
|
||||
|
||||
Ok(NetworkResult::value(Answer::new(
|
||||
latency,
|
||||
GetValueAnswer {
|
||||
|
@ -62,7 +62,7 @@ impl RPCProcessor {
|
||||
) -> Result<NetworkResult<()>, RPCError> {
|
||||
// Make sure hop count makes sense
|
||||
if next_private_route.hop_count as usize > self.unlocked_inner.max_route_hop_count {
|
||||
return Err(RPCError::protocol(
|
||||
return Ok(NetworkResult::invalid_message(
|
||||
"Private route hop count too high to process",
|
||||
));
|
||||
}
|
||||
@ -110,9 +110,9 @@ impl RPCProcessor {
|
||||
// Now that things are valid, decrypt the routed operation with DEC(nonce, DH(the SR's public key, the PR's (or node's) secret)
|
||||
// xxx: punish nodes that send messages that fail to decrypt eventually? How to do this for safety routes?
|
||||
let node_id_secret = self.routing_table.node_id_secret_key(remote_sr_pubkey.kind);
|
||||
let dh_secret = vcrypto
|
||||
.cached_dh(&remote_sr_pubkey.value, &node_id_secret)
|
||||
.map_err(RPCError::protocol)?;
|
||||
let Ok(dh_secret) = vcrypto.cached_dh(&remote_sr_pubkey.value, &node_id_secret) else {
|
||||
return Ok(NetworkResult::invalid_message("dh failed for remote safety route for safety routed operation"));
|
||||
};
|
||||
let body = match vcrypto.decrypt_aead(
|
||||
routed_operation.data(),
|
||||
routed_operation.nonce(),
|
||||
@ -183,19 +183,18 @@ impl RPCProcessor {
|
||||
|
||||
// Now that things are valid, decrypt the routed operation with DEC(nonce, DH(the SR's public key, the PR's (or node's) secret)
|
||||
// xxx: punish nodes that send messages that fail to decrypt eventually. How to do this for private routes?
|
||||
let dh_secret = vcrypto
|
||||
.cached_dh(&remote_sr_pubkey.value, &secret_key)
|
||||
.map_err(RPCError::protocol)?;
|
||||
let body = vcrypto
|
||||
let Ok(dh_secret) = vcrypto.cached_dh(&remote_sr_pubkey.value, &secret_key) else {
|
||||
return Ok(NetworkResult::invalid_message("dh failed for remote safety route for private routed operation"));
|
||||
};
|
||||
let Ok(body) = vcrypto
|
||||
.decrypt_aead(
|
||||
routed_operation.data(),
|
||||
routed_operation.nonce(),
|
||||
&dh_secret,
|
||||
None,
|
||||
)
|
||||
.map_err(RPCError::map_internal(
|
||||
"decryption of routed operation failed",
|
||||
))?;
|
||||
) else {
|
||||
return Ok(NetworkResult::invalid_message("decryption of routed operation failed"));
|
||||
};
|
||||
|
||||
// Pass message to RPC system
|
||||
self.enqueue_private_routed_message(
|
||||
@ -401,37 +400,48 @@ impl RPCProcessor {
|
||||
SafetyRouteHops::Data(ref route_hop_data) => {
|
||||
// Decrypt the blob with DEC(nonce, DH(the SR's public key, this hop's secret)
|
||||
let node_id_secret = self.routing_table.node_id_secret_key(crypto_kind);
|
||||
let dh_secret = vcrypto
|
||||
.cached_dh(&safety_route.public_key.value, &node_id_secret)
|
||||
.map_err(RPCError::protocol)?;
|
||||
let mut dec_blob_data = vcrypto
|
||||
let Ok(dh_secret) = vcrypto
|
||||
.cached_dh(&safety_route.public_key.value, &node_id_secret) else {
|
||||
return Ok(NetworkResult::invalid_message("dh failed for safety route hop"));
|
||||
};
|
||||
let Ok(mut dec_blob_data) = vcrypto
|
||||
.decrypt_aead(
|
||||
&route_hop_data.blob,
|
||||
&route_hop_data.nonce,
|
||||
&dh_secret,
|
||||
None,
|
||||
)
|
||||
.map_err(RPCError::protocol)?;
|
||||
else {
|
||||
return Ok(NetworkResult::invalid_message("failed to decrypt route hop data for safety route hop"));
|
||||
};
|
||||
|
||||
// See if this is last hop in safety route, if so, we're decoding a PrivateRoute not a RouteHop
|
||||
let Some(dec_blob_tag) = dec_blob_data.pop() else {
|
||||
return Ok(NetworkResult::invalid_message("no bytes in blob"));
|
||||
};
|
||||
|
||||
let dec_blob_reader = RPCMessageData::new(dec_blob_data).get_reader()?;
|
||||
let Ok(dec_blob_reader) = RPCMessageData::new(dec_blob_data).get_reader() else {
|
||||
return Ok(NetworkResult::invalid_message("Failed to decode RPCMessageData from blob"));
|
||||
};
|
||||
|
||||
// Decode the blob appropriately
|
||||
if dec_blob_tag == 1 {
|
||||
// PrivateRoute
|
||||
let private_route = {
|
||||
let pr_reader = dec_blob_reader
|
||||
.get_root::<veilid_capnp::private_route::Reader>()
|
||||
.map_err(RPCError::protocol)?;
|
||||
decode_private_route(&pr_reader)?
|
||||
let Ok(pr_reader) = dec_blob_reader
|
||||
.get_root::<veilid_capnp::private_route::Reader>() else {
|
||||
return Ok(NetworkResult::invalid_message("failed to get private route reader for blob"));
|
||||
};
|
||||
let Ok(private_route) = decode_private_route(&pr_reader) else {
|
||||
return Ok(NetworkResult::invalid_message("failed to decode private route"));
|
||||
};
|
||||
private_route
|
||||
};
|
||||
|
||||
// Validate the private route
|
||||
private_route.validate(self.crypto.clone()).map_err(RPCError::protocol)?;
|
||||
if let Err(_) = private_route.validate(self.crypto.clone()) {
|
||||
return Ok(NetworkResult::invalid_message("failed to validate private route"));
|
||||
}
|
||||
|
||||
// Switching from full safety route to private route first hop
|
||||
network_result_try!(
|
||||
@ -445,14 +455,20 @@ impl RPCProcessor {
|
||||
} else if dec_blob_tag == 0 {
|
||||
// RouteHop
|
||||
let route_hop = {
|
||||
let rh_reader = dec_blob_reader
|
||||
.get_root::<veilid_capnp::route_hop::Reader>()
|
||||
.map_err(RPCError::protocol)?;
|
||||
decode_route_hop(&rh_reader)?
|
||||
let Ok(rh_reader) = dec_blob_reader
|
||||
.get_root::<veilid_capnp::route_hop::Reader>() else {
|
||||
return Ok(NetworkResult::invalid_message("failed to get route hop reader for blob"));
|
||||
};
|
||||
let Ok(route_hop) = decode_route_hop(&rh_reader) else {
|
||||
return Ok(NetworkResult::invalid_message("failed to decode route hop"));
|
||||
};
|
||||
route_hop
|
||||
};
|
||||
|
||||
// Validate the route hop
|
||||
route_hop.validate(self.crypto.clone()).map_err(RPCError::protocol)?;
|
||||
if let Err(_) = route_hop.validate(self.crypto.clone()) {
|
||||
return Ok(NetworkResult::invalid_message("failed to validate route hop"));
|
||||
}
|
||||
|
||||
// Continue the full safety route with another hop
|
||||
network_result_try!(
|
||||
|
@ -14,7 +14,6 @@ impl RPCProcessor {
|
||||
/// Because this leaks information about the identity of the node itself,
|
||||
/// replying to this request received over a private route will leak
|
||||
/// the identity of the node and defeat the private route.
|
||||
#[instrument(level = "trace", skip(self), ret, err)]
|
||||
pub async fn rpc_call_set_value(
|
||||
self,
|
||||
dest: Destination,
|
||||
@ -25,18 +24,22 @@ impl RPCProcessor {
|
||||
send_descriptor: bool,
|
||||
) -> Result<NetworkResult<Answer<SetValueAnswer>>, RPCError> {
|
||||
// Ensure destination never has a private route
|
||||
if matches!(
|
||||
dest,
|
||||
Destination::PrivateRoute {
|
||||
private_route: _,
|
||||
safety_selection: _
|
||||
}
|
||||
) {
|
||||
// and get the target noderef so we can validate the response
|
||||
let Some(target) = dest.target() else {
|
||||
return Err(RPCError::internal(
|
||||
"Never send set value requests over private routes",
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
// Get the target node id
|
||||
let Some(vcrypto) = self.crypto.get(key.kind) else {
|
||||
return Err(RPCError::internal("unsupported cryptosystem"));
|
||||
};
|
||||
let Some(target_node_id) = target.node_ids().get(key.kind) else {
|
||||
return Err(RPCError::internal("No node id for crypto kind"));
|
||||
};
|
||||
|
||||
// Send the setvalue question
|
||||
let set_value_q = RPCOperationSetValueQ::new(
|
||||
key,
|
||||
subkey,
|
||||
@ -51,17 +54,11 @@ impl RPCProcessor {
|
||||
network_result_try!(self.get_destination_respond_to(&dest)?),
|
||||
RPCQuestionDetail::SetValueQ(set_value_q),
|
||||
);
|
||||
let Some(vcrypto) = self.crypto.get(key.kind) else {
|
||||
return Err(RPCError::internal("unsupported cryptosystem"));
|
||||
};
|
||||
|
||||
// Send the setvalue question
|
||||
let question_context = QuestionContext::SetValue(ValidateSetValueContext {
|
||||
descriptor,
|
||||
subkey,
|
||||
vcrypto,
|
||||
vcrypto: vcrypto.clone(),
|
||||
});
|
||||
|
||||
let waitable_reply = network_result_try!(
|
||||
self.question(dest, question, Some(question_context))
|
||||
.await?
|
||||
@ -78,13 +75,29 @@ impl RPCProcessor {
|
||||
let set_value_a = match kind {
|
||||
RPCOperationKind::Answer(a) => match a.destructure() {
|
||||
RPCAnswerDetail::SetValueA(a) => a,
|
||||
_ => return Err(RPCError::invalid_format("not a setvalue answer")),
|
||||
_ => return Ok(NetworkResult::invalid_message("not a setvalue answer")),
|
||||
},
|
||||
_ => return Err(RPCError::invalid_format("not an answer")),
|
||||
_ => return Ok(NetworkResult::invalid_message("not an answer")),
|
||||
};
|
||||
|
||||
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
|
||||
let valid = match self.verify_peers_closer(vcrypto, target_node_id, key, &peers) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
if matches!(e, RPCError::Internal(_)) {
|
||||
return Err(e);
|
||||
}
|
||||
return Ok(NetworkResult::invalid_message(
|
||||
"missing cryptosystem in peers node ids",
|
||||
));
|
||||
}
|
||||
};
|
||||
if !valid {
|
||||
return Ok(NetworkResult::invalid_message("non-closer peers returned"));
|
||||
}
|
||||
|
||||
Ok(NetworkResult::value(Answer::new(
|
||||
latency,
|
||||
SetValueAnswer { set, value, peers },
|
||||
|
@ -119,9 +119,9 @@ impl RPCProcessor {
|
||||
let status_a = match kind {
|
||||
RPCOperationKind::Answer(a) => match a.destructure() {
|
||||
RPCAnswerDetail::StatusA(a) => a,
|
||||
_ => return Err(RPCError::invalid_format("not a status answer")),
|
||||
_ => return Ok(NetworkResult::invalid_message("not a status answer")),
|
||||
},
|
||||
_ => return Err(RPCError::invalid_format("not an answer")),
|
||||
_ => return Ok(NetworkResult::invalid_message("not an answer")),
|
||||
};
|
||||
let (a_node_status, sender_info) = status_a.destructure();
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::*;
|
||||
|
||||
/// The context of the do_get_value operation
|
||||
struct DoGetValueContext {
|
||||
/// The context of the outbound_get_value operation
|
||||
struct OutboundGetValueContext {
|
||||
/// The latest value of the subkey, may be the value passed in
|
||||
pub value: Option<SignedValueData>,
|
||||
/// The consensus count for the value we have received
|
||||
@ -42,7 +42,7 @@ impl StorageManager {
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let context = Arc::new(Mutex::new(DoGetValueContext {
|
||||
let context = Arc::new(Mutex::new(OutboundGetValueContext {
|
||||
value: last_subkey_result.value,
|
||||
value_count: 0,
|
||||
descriptor: last_subkey_result.descriptor.clone(),
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::*;
|
||||
|
||||
/// The context of the do_get_value operation
|
||||
struct DoSetValueContext {
|
||||
/// The context of the outbound_set_value operation
|
||||
struct OutboundSetValueContext {
|
||||
/// The latest value of the subkey, may be the value passed in
|
||||
pub value: SignedValueData,
|
||||
/// The consensus count for the value we have received
|
||||
@ -37,7 +37,7 @@ impl StorageManager {
|
||||
|
||||
// Make do-set-value answer context
|
||||
let schema = descriptor.schema()?;
|
||||
let context = Arc::new(Mutex::new(DoSetValueContext {
|
||||
let context = Arc::new(Mutex::new(OutboundSetValueContext {
|
||||
value,
|
||||
value_count: 0,
|
||||
schema,
|
||||
|
@ -1,74 +1,74 @@
|
||||
# # Routing context veilid tests
|
||||
# Routing context veilid tests
|
||||
|
||||
# import veilid
|
||||
# import pytest
|
||||
# import asyncio
|
||||
# import json
|
||||
# from . import *
|
||||
import veilid
|
||||
import pytest
|
||||
import asyncio
|
||||
import json
|
||||
from . import *
|
||||
|
||||
# ##################################################################
|
||||
# BOGUS_KEY = veilid.TypedKey.from_value(veilid.CryptoKind.CRYPTO_KIND_VLD0, veilid.PublicKey.from_bytes(b' '))
|
||||
##################################################################
|
||||
BOGUS_KEY = veilid.TypedKey.from_value(veilid.CryptoKind.CRYPTO_KIND_VLD0, veilid.PublicKey.from_bytes(b' '))
|
||||
|
||||
# @pytest.mark.asyncio
|
||||
# async def test_get_dht_value_unopened(api_connection: veilid.VeilidAPI):
|
||||
# rc = await api_connection.new_routing_context()
|
||||
# async with rc:
|
||||
# with pytest.raises(veilid.VeilidAPIError):
|
||||
# out = await rc.get_dht_value(BOGUS_KEY, veilid.ValueSubkey(0), False)
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_dht_value_unopened(api_connection: veilid.VeilidAPI):
|
||||
rc = await api_connection.new_routing_context()
|
||||
async with rc:
|
||||
with pytest.raises(veilid.VeilidAPIError):
|
||||
out = await rc.get_dht_value(BOGUS_KEY, veilid.ValueSubkey(0), False)
|
||||
|
||||
|
||||
# @pytest.mark.asyncio
|
||||
# async def test_open_dht_record_nonexistent_no_writer(api_connection: veilid.VeilidAPI):
|
||||
# rc = await api_connection.new_routing_context()
|
||||
# async with rc:
|
||||
# with pytest.raises(veilid.VeilidAPIError):
|
||||
# out = await rc.open_dht_record(BOGUS_KEY, None)
|
||||
@pytest.mark.asyncio
|
||||
async def test_open_dht_record_nonexistent_no_writer(api_connection: veilid.VeilidAPI):
|
||||
rc = await api_connection.new_routing_context()
|
||||
async with rc:
|
||||
with pytest.raises(veilid.VeilidAPIError):
|
||||
out = await rc.open_dht_record(BOGUS_KEY, None)
|
||||
|
||||
# @pytest.mark.asyncio
|
||||
# async def test_close_dht_record_nonexistent(api_connection: veilid.VeilidAPI):
|
||||
# rc = await api_connection.new_routing_context()
|
||||
# async with rc:
|
||||
# with pytest.raises(veilid.VeilidAPIError):
|
||||
# await rc.close_dht_record(BOGUS_KEY)
|
||||
@pytest.mark.asyncio
|
||||
async def test_close_dht_record_nonexistent(api_connection: veilid.VeilidAPI):
|
||||
rc = await api_connection.new_routing_context()
|
||||
async with rc:
|
||||
with pytest.raises(veilid.VeilidAPIError):
|
||||
await rc.close_dht_record(BOGUS_KEY)
|
||||
|
||||
# @pytest.mark.asyncio
|
||||
# async def test_delete_dht_record_nonexistent(api_connection: veilid.VeilidAPI):
|
||||
# rc = await api_connection.new_routing_context()
|
||||
# async with rc:
|
||||
# with pytest.raises(veilid.VeilidAPIError):
|
||||
# await rc.delete_dht_record(BOGUS_KEY)
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_dht_record_nonexistent(api_connection: veilid.VeilidAPI):
|
||||
rc = await api_connection.new_routing_context()
|
||||
async with rc:
|
||||
with pytest.raises(veilid.VeilidAPIError):
|
||||
await rc.delete_dht_record(BOGUS_KEY)
|
||||
|
||||
# @pytest.mark.asyncio
|
||||
# async def test_create_delete_dht_record_simple(api_connection: veilid.VeilidAPI):
|
||||
# rc = await api_connection.new_routing_context()
|
||||
# async with rc:
|
||||
# rec = await rc.create_dht_record(veilid.CryptoKind.CRYPTO_KIND_VLD0, veilid.DHTSchema.dflt(1))
|
||||
# await rc.close_dht_record(rec.key)
|
||||
# await rc.delete_dht_record(rec.key)
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_delete_dht_record_simple(api_connection: veilid.VeilidAPI):
|
||||
rc = await api_connection.new_routing_context()
|
||||
async with rc:
|
||||
rec = await rc.create_dht_record(veilid.CryptoKind.CRYPTO_KIND_VLD0, veilid.DHTSchema.dflt(1))
|
||||
await rc.close_dht_record(rec.key)
|
||||
await rc.delete_dht_record(rec.key)
|
||||
|
||||
# @pytest.mark.asyncio
|
||||
# async def test_get_dht_value_nonexistent(api_connection: veilid.VeilidAPI):
|
||||
# rc = await api_connection.new_routing_context()
|
||||
# async with rc:
|
||||
# rec = await rc.create_dht_record(veilid.CryptoKind.CRYPTO_KIND_VLD0, veilid.DHTSchema.dflt(1))
|
||||
# assert await rc.get_dht_value(rec.key, 0, False) == None
|
||||
# await rc.close_dht_record(rec.key)
|
||||
# await rc.delete_dht_record(rec.key)
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_dht_value_nonexistent(api_connection: veilid.VeilidAPI):
|
||||
rc = await api_connection.new_routing_context()
|
||||
async with rc:
|
||||
rec = await rc.create_dht_record(veilid.CryptoKind.CRYPTO_KIND_VLD0, veilid.DHTSchema.dflt(1))
|
||||
assert await rc.get_dht_value(rec.key, 0, False) == None
|
||||
await rc.close_dht_record(rec.key)
|
||||
await rc.delete_dht_record(rec.key)
|
||||
|
||||
# @pytest.mark.asyncio
|
||||
# async def test_set_get_dht_value(api_connection: veilid.VeilidAPI):
|
||||
# rc = await api_connection.new_routing_context()
|
||||
# async with rc:
|
||||
# rec = await rc.create_dht_record(veilid.CryptoKind.CRYPTO_KIND_VLD0, veilid.DHTSchema.dflt(1))
|
||||
@pytest.mark.asyncio
|
||||
async def test_set_get_dht_value(api_connection: veilid.VeilidAPI):
|
||||
rc = await api_connection.new_routing_context()
|
||||
async with rc:
|
||||
rec = await rc.create_dht_record(veilid.CryptoKind.CRYPTO_KIND_VLD0, veilid.DHTSchema.dflt(1))
|
||||
|
||||
# vd = await rc.set_dht_value(rec.key, 0, b"BLAH BLAH BLAH")
|
||||
# assert vd != None
|
||||
vd = await rc.set_dht_value(rec.key, 0, b"BLAH BLAH BLAH")
|
||||
assert vd != None
|
||||
|
||||
# vd2 = await rc.get_dht_value(rec.key, 0, False)
|
||||
# assert vd2 != None
|
||||
vd2 = await rc.get_dht_value(rec.key, 0, False)
|
||||
assert vd2 != None
|
||||
|
||||
# assert vd == vd2
|
||||
assert vd == vd2
|
||||
|
||||
# await rc.close_dht_record(rec.key)
|
||||
# await rc.delete_dht_record(rec.key)
|
||||
await rc.close_dht_record(rec.key)
|
||||
await rc.delete_dht_record(rec.key)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user