checkpoint, adding 'inspect value'

This commit is contained in:
Christien Rioux 2024-03-08 21:24:59 -05:00
parent 946d33ced6
commit ca65d12836
13 changed files with 1641 additions and 100 deletions

View File

@ -368,6 +368,18 @@ struct OperationWatchValueA @0xa726cab7064ba893 {
watchId @3 :UInt64; # (0 = id not allocated if rejecting new watch) random id for watch instance on this node
}
struct OperationInspectValueQ @0xdef712d2fd16f55a {
key @0 :TypedKey; # DHT Key = Hash(ownerKeyKind) of: [ ownerKeyValue, schema ]
subkeys @1 :List(SubkeyRange); # subkey range to inspect (up to 512 total subkeys), if empty this implies 0..=511
wantDescriptor @2 :Bool; # whether or not to include the descriptor for the key
}
struct OperationInspectValueA @0xb8b57faf960ee102 {
seqs @0 :List(ValueSeqNum); # the list of subkey value sequence numbers in ascending order for each subkey in the requested range. if a subkey has not been written to, it is given a value of UINT32_MAX. these are not signed, and may be immediately out of date, and must be verified by a GetValueQ request.
peers @1 :List(PeerInfo); # returned 'closer peer' information on either success or failure
descriptor @2 :SignedValueDescriptor; # optional: the descriptor if requested if the value is also returned
}
struct OperationValueChanged @0xd1c59ebdd8cc1bf6 {
key @0 :TypedKey; # key for value that changed
subkeys @1 :List(SubkeyRange); # subkey range that changed (up to 512 ranges at a time, if empty this is a watch expiration notice)
@ -487,15 +499,17 @@ struct Question @0xd8510bc33492ef70 {
getValueQ @5 :OperationGetValueQ;
setValueQ @6 :OperationSetValueQ;
watchValueQ @7 :OperationWatchValueQ;
inspectValueQ @8 :OperationInspectValueQ;
# #[cfg(feature="unstable-blockstore")]
# supplyBlockQ @8 :OperationSupplyBlockQ;
# findBlockQ @9 :OperationFindBlockQ;
# supplyBlockQ @9 :OperationSupplyBlockQ;
# findBlockQ @10 :OperationFindBlockQ;
# Tunnel operations
# #[cfg(feature="unstable-tunnels")]
# startTunnelQ @10 :OperationStartTunnelQ;
# completeTunnelQ @11 :OperationCompleteTunnelQ;
# cancelTunnelQ @12 :OperationCancelTunnelQ;
# startTunnelQ @11 :OperationStartTunnelQ;
# completeTunnelQ @12 :OperationCompleteTunnelQ;
# cancelTunnelQ @13 :OperationCancelTunnelQ;
}
}
@ -526,16 +540,17 @@ struct Answer @0xacacb8b6988c1058 {
getValueA @3 :OperationGetValueA;
setValueA @4 :OperationSetValueA;
watchValueA @5 :OperationWatchValueA;
inspectValueA @6 :OperationInspectValueA;
# #[cfg(feature="unstable-blockstore")]
#supplyBlockA @6 :OperationSupplyBlockA;
#findBlockA @7 :OperationFindBlockA;
#supplyBlockA @7 :OperationSupplyBlockA;
#findBlockA @8 :OperationFindBlockA;
# Tunnel operations
# #[cfg(feature="unstable-tunnels")]
# startTunnelA @8 :OperationStartTunnelA;
# completeTunnelA @9 :OperationCompleteTunnelA;
# cancelTunnelA @10 :OperationCancelTunnelA;
# startTunnelA @9 :OperationStartTunnelA;
# completeTunnelA @10 :OperationCompleteTunnelA;
# cancelTunnelA @11 :OperationCancelTunnelA;
}
}

View File

@ -14457,6 +14457,588 @@ pub mod operation_watch_value_a {
}
}
pub mod operation_inspect_value_q {
#[derive(Copy, Clone)]
pub struct Owned(());
impl ::capnp::introspect::Introspect for Owned { fn introspect() -> ::capnp::introspect::Type { ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } }
impl ::capnp::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; }
impl ::capnp::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; }
impl ::capnp::traits::Pipelined for Owned { type Pipeline = Pipeline; }
pub struct Reader<'a> { reader: ::capnp::private::layout::StructReader<'a> }
impl <'a,> ::core::marker::Copy for Reader<'a,> {}
impl <'a,> ::core::clone::Clone for Reader<'a,> {
fn clone(&self) -> Self { *self }
}
impl <'a,> ::capnp::traits::HasTypeId for Reader<'a,> {
const TYPE_ID: u64 = _private::TYPE_ID;
}
impl <'a,> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a,> {
fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self {
Self { reader, }
}
}
impl <'a,> ::core::convert::From<Reader<'a,>> for ::capnp::dynamic_value::Reader<'a> {
fn from(reader: Reader<'a,>) -> Self {
Self::Struct(::capnp::dynamic_struct::Reader::new(reader.reader, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>})))
}
}
impl <'a,> ::core::fmt::Debug for Reader<'a,> {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> {
core::fmt::Debug::fmt(&::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), f)
}
}
impl <'a,> ::capnp::traits::FromPointerReader<'a> for Reader<'a,> {
fn get_from_pointer(reader: &::capnp::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result<Self> {
::core::result::Result::Ok(reader.get_struct(default)?.into())
}
}
impl <'a,> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a,> {
fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> {
self.reader
}
}
impl <'a,> ::capnp::traits::Imbue<'a> for Reader<'a,> {
fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) {
self.reader.imbue(::capnp::private::layout::CapTableReader::Plain(cap_table))
}
}
impl <'a,> Reader<'a,> {
pub fn reborrow(&self) -> Reader<'_,> {
Self { .. *self }
}
pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> {
self.reader.total_size()
}
#[inline]
pub fn get_key(self) -> ::capnp::Result<crate::veilid_capnp::typed_key::Reader<'a>> {
::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None)
}
#[inline]
pub fn has_key(&self) -> bool {
!self.reader.get_pointer_field(0).is_null()
}
#[inline]
pub fn get_subkeys(self) -> ::capnp::Result<::capnp::struct_list::Reader<'a,crate::veilid_capnp::subkey_range::Owned>> {
::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None)
}
#[inline]
pub fn has_subkeys(&self) -> bool {
!self.reader.get_pointer_field(1).is_null()
}
#[inline]
pub fn get_want_descriptor(self) -> bool {
self.reader.get_bool_field(0)
}
}
pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> }
impl <'a,> ::capnp::traits::HasStructSize for Builder<'a,> {
const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 1, pointers: 2 };
}
impl <'a,> ::capnp::traits::HasTypeId for Builder<'a,> {
const TYPE_ID: u64 = _private::TYPE_ID;
}
impl <'a,> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a,> {
fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self {
Self { builder, }
}
}
impl <'a,> ::core::convert::From<Builder<'a,>> for ::capnp::dynamic_value::Builder<'a> {
fn from(builder: Builder<'a,>) -> Self {
Self::Struct(::capnp::dynamic_struct::Builder::new(builder.builder, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>})))
}
}
impl <'a,> ::capnp::traits::ImbueMut<'a> for Builder<'a,> {
fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) {
self.builder.imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table))
}
}
impl <'a,> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a,> {
fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self {
builder.init_struct(<Self as ::capnp::traits::HasStructSize>::STRUCT_SIZE).into()
}
fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result<Self> {
::core::result::Result::Ok(builder.get_struct(<Self as ::capnp::traits::HasStructSize>::STRUCT_SIZE, default)?.into())
}
}
impl <'a,> ::capnp::traits::SetPointerBuilder for Reader<'a,> {
fn set_pointer_builder(mut pointer: ::capnp::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> ::capnp::Result<()> { pointer.set_struct(&value.reader, canonicalize) }
}
impl <'a,> Builder<'a,> {
pub fn into_reader(self) -> Reader<'a,> {
self.builder.into_reader().into()
}
pub fn reborrow(&mut self) -> Builder<'_,> {
Builder { builder: self.builder.reborrow() }
}
pub fn reborrow_as_reader(&self) -> Reader<'_,> {
self.builder.as_reader().into()
}
pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> {
self.builder.as_reader().total_size()
}
#[inline]
pub fn get_key(self) -> ::capnp::Result<crate::veilid_capnp::typed_key::Builder<'a>> {
::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None)
}
#[inline]
pub fn set_key(&mut self, value: crate::veilid_capnp::typed_key::Reader<'_>) -> ::capnp::Result<()> {
::capnp::traits::SetPointerBuilder::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false)
}
#[inline]
pub fn init_key(self, ) -> crate::veilid_capnp::typed_key::Builder<'a> {
::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0)
}
#[inline]
pub fn has_key(&self) -> bool {
!self.builder.is_pointer_field_null(0)
}
#[inline]
pub fn get_subkeys(self) -> ::capnp::Result<::capnp::struct_list::Builder<'a,crate::veilid_capnp::subkey_range::Owned>> {
::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None)
}
#[inline]
pub fn set_subkeys(&mut self, value: ::capnp::struct_list::Reader<'_,crate::veilid_capnp::subkey_range::Owned>) -> ::capnp::Result<()> {
::capnp::traits::SetPointerBuilder::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false)
}
#[inline]
pub fn init_subkeys(self, size: u32) -> ::capnp::struct_list::Builder<'a,crate::veilid_capnp::subkey_range::Owned> {
::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), size)
}
#[inline]
pub fn has_subkeys(&self) -> bool {
!self.builder.is_pointer_field_null(1)
}
#[inline]
pub fn get_want_descriptor(self) -> bool {
self.builder.get_bool_field(0)
}
#[inline]
pub fn set_want_descriptor(&mut self, value: bool) {
self.builder.set_bool_field(0, value);
}
}
pub struct Pipeline { _typeless: ::capnp::any_pointer::Pipeline }
impl ::capnp::capability::FromTypelessPipeline for Pipeline {
fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self {
Self { _typeless: typeless, }
}
}
impl Pipeline {
pub fn get_key(&self) -> crate::veilid_capnp::typed_key::Pipeline {
::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0))
}
}
mod _private {
pub static ENCODED_NODE: [::capnp::Word; 70] = [
::capnp::word(0, 0, 0, 0, 5, 0, 6, 0),
::capnp::word(90, 245, 22, 253, 210, 18, 247, 222),
::capnp::word(19, 0, 0, 0, 1, 0, 1, 0),
::capnp::word(2, 171, 52, 55, 3, 232, 252, 143),
::capnp::word(2, 0, 7, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(21, 0, 0, 0, 82, 1, 0, 0),
::capnp::word(41, 0, 0, 0, 7, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(37, 0, 0, 0, 175, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(112, 114, 111, 116, 111, 47, 118, 101),
::capnp::word(105, 108, 105, 100, 46, 99, 97, 112),
::capnp::word(110, 112, 58, 79, 112, 101, 114, 97),
::capnp::word(116, 105, 111, 110, 73, 110, 115, 112),
::capnp::word(101, 99, 116, 86, 97, 108, 117, 101),
::capnp::word(81, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 1, 0, 1, 0),
::capnp::word(12, 0, 0, 0, 3, 0, 4, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 1, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(69, 0, 0, 0, 34, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(64, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(76, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(1, 0, 0, 0, 1, 0, 0, 0),
::capnp::word(0, 0, 1, 0, 1, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(73, 0, 0, 0, 66, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(68, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(96, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(2, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 1, 0, 2, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(93, 0, 0, 0, 122, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(92, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(104, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(107, 101, 121, 0, 0, 0, 0, 0),
::capnp::word(16, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(41, 27, 230, 241, 169, 103, 213, 226),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(16, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(115, 117, 98, 107, 101, 121, 115, 0),
::capnp::word(14, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(16, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(28, 23, 208, 164, 192, 218, 146, 245),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(14, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(119, 97, 110, 116, 68, 101, 115, 99),
::capnp::word(114, 105, 112, 116, 111, 114, 0, 0),
::capnp::word(1, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(1, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
];
pub fn get_field_types(index: u16) -> ::capnp::introspect::Type {
match index {
0 => <crate::veilid_capnp::typed_key::Owned as ::capnp::introspect::Introspect>::introspect(),
1 => <::capnp::struct_list::Owned<crate::veilid_capnp::subkey_range::Owned> as ::capnp::introspect::Introspect>::introspect(),
2 => <bool as ::capnp::introspect::Introspect>::introspect(),
_ => panic!("invalid field index {}", index),
}
}
pub fn get_annotation_types(child_index: Option<u16>, index: u32) -> ::capnp::introspect::Type {
panic!("invalid annotation indices ({:?}, {}) ", child_index, index)
}
pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = ::capnp::introspect::RawStructSchema {
encoded_node: &ENCODED_NODE,
nonunion_members: NONUNION_MEMBERS,
members_by_discriminant: MEMBERS_BY_DISCRIMINANT,
};
pub static NONUNION_MEMBERS : &[u16] = &[0,1,2];
pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[];
pub const TYPE_ID: u64 = 0xdef7_12d2_fd16_f55a;
}
}
pub mod operation_inspect_value_a {
#[derive(Copy, Clone)]
pub struct Owned(());
impl ::capnp::introspect::Introspect for Owned { fn introspect() -> ::capnp::introspect::Type { ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } }
impl ::capnp::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; }
impl ::capnp::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; }
impl ::capnp::traits::Pipelined for Owned { type Pipeline = Pipeline; }
pub struct Reader<'a> { reader: ::capnp::private::layout::StructReader<'a> }
impl <'a,> ::core::marker::Copy for Reader<'a,> {}
impl <'a,> ::core::clone::Clone for Reader<'a,> {
fn clone(&self) -> Self { *self }
}
impl <'a,> ::capnp::traits::HasTypeId for Reader<'a,> {
const TYPE_ID: u64 = _private::TYPE_ID;
}
impl <'a,> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a,> {
fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self {
Self { reader, }
}
}
impl <'a,> ::core::convert::From<Reader<'a,>> for ::capnp::dynamic_value::Reader<'a> {
fn from(reader: Reader<'a,>) -> Self {
Self::Struct(::capnp::dynamic_struct::Reader::new(reader.reader, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>})))
}
}
impl <'a,> ::core::fmt::Debug for Reader<'a,> {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> {
core::fmt::Debug::fmt(&::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), f)
}
}
impl <'a,> ::capnp::traits::FromPointerReader<'a> for Reader<'a,> {
fn get_from_pointer(reader: &::capnp::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result<Self> {
::core::result::Result::Ok(reader.get_struct(default)?.into())
}
}
impl <'a,> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a,> {
fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> {
self.reader
}
}
impl <'a,> ::capnp::traits::Imbue<'a> for Reader<'a,> {
fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) {
self.reader.imbue(::capnp::private::layout::CapTableReader::Plain(cap_table))
}
}
impl <'a,> Reader<'a,> {
pub fn reborrow(&self) -> Reader<'_,> {
Self { .. *self }
}
pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> {
self.reader.total_size()
}
#[inline]
pub fn get_seqs(self) -> ::capnp::Result<::capnp::primitive_list::Reader<'a,u32>> {
::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None)
}
#[inline]
pub fn has_seqs(&self) -> bool {
!self.reader.get_pointer_field(0).is_null()
}
#[inline]
pub fn get_peers(self) -> ::capnp::Result<::capnp::struct_list::Reader<'a,crate::veilid_capnp::peer_info::Owned>> {
::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None)
}
#[inline]
pub fn has_peers(&self) -> bool {
!self.reader.get_pointer_field(1).is_null()
}
#[inline]
pub fn get_descriptor(self) -> ::capnp::Result<crate::veilid_capnp::signed_value_descriptor::Reader<'a>> {
::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(2), ::core::option::Option::None)
}
#[inline]
pub fn has_descriptor(&self) -> bool {
!self.reader.get_pointer_field(2).is_null()
}
}
pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> }
impl <'a,> ::capnp::traits::HasStructSize for Builder<'a,> {
const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 0, pointers: 3 };
}
impl <'a,> ::capnp::traits::HasTypeId for Builder<'a,> {
const TYPE_ID: u64 = _private::TYPE_ID;
}
impl <'a,> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a,> {
fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self {
Self { builder, }
}
}
impl <'a,> ::core::convert::From<Builder<'a,>> for ::capnp::dynamic_value::Builder<'a> {
fn from(builder: Builder<'a,>) -> Self {
Self::Struct(::capnp::dynamic_struct::Builder::new(builder.builder, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>})))
}
}
impl <'a,> ::capnp::traits::ImbueMut<'a> for Builder<'a,> {
fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) {
self.builder.imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table))
}
}
impl <'a,> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a,> {
fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self {
builder.init_struct(<Self as ::capnp::traits::HasStructSize>::STRUCT_SIZE).into()
}
fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result<Self> {
::core::result::Result::Ok(builder.get_struct(<Self as ::capnp::traits::HasStructSize>::STRUCT_SIZE, default)?.into())
}
}
impl <'a,> ::capnp::traits::SetPointerBuilder for Reader<'a,> {
fn set_pointer_builder(mut pointer: ::capnp::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> ::capnp::Result<()> { pointer.set_struct(&value.reader, canonicalize) }
}
impl <'a,> Builder<'a,> {
pub fn into_reader(self) -> Reader<'a,> {
self.builder.into_reader().into()
}
pub fn reborrow(&mut self) -> Builder<'_,> {
Builder { builder: self.builder.reborrow() }
}
pub fn reborrow_as_reader(&self) -> Reader<'_,> {
self.builder.as_reader().into()
}
pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> {
self.builder.as_reader().total_size()
}
#[inline]
pub fn get_seqs(self) -> ::capnp::Result<::capnp::primitive_list::Builder<'a,u32>> {
::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None)
}
#[inline]
pub fn set_seqs(&mut self, value: ::capnp::primitive_list::Reader<'_,u32>) -> ::capnp::Result<()> {
::capnp::traits::SetPointerBuilder::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false)
}
#[inline]
pub fn init_seqs(self, size: u32) -> ::capnp::primitive_list::Builder<'a,u32> {
::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), size)
}
#[inline]
pub fn has_seqs(&self) -> bool {
!self.builder.is_pointer_field_null(0)
}
#[inline]
pub fn get_peers(self) -> ::capnp::Result<::capnp::struct_list::Builder<'a,crate::veilid_capnp::peer_info::Owned>> {
::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None)
}
#[inline]
pub fn set_peers(&mut self, value: ::capnp::struct_list::Reader<'_,crate::veilid_capnp::peer_info::Owned>) -> ::capnp::Result<()> {
::capnp::traits::SetPointerBuilder::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false)
}
#[inline]
pub fn init_peers(self, size: u32) -> ::capnp::struct_list::Builder<'a,crate::veilid_capnp::peer_info::Owned> {
::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), size)
}
#[inline]
pub fn has_peers(&self) -> bool {
!self.builder.is_pointer_field_null(1)
}
#[inline]
pub fn get_descriptor(self) -> ::capnp::Result<crate::veilid_capnp::signed_value_descriptor::Builder<'a>> {
::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(2), ::core::option::Option::None)
}
#[inline]
pub fn set_descriptor(&mut self, value: crate::veilid_capnp::signed_value_descriptor::Reader<'_>) -> ::capnp::Result<()> {
::capnp::traits::SetPointerBuilder::set_pointer_builder(self.builder.reborrow().get_pointer_field(2), value, false)
}
#[inline]
pub fn init_descriptor(self, ) -> crate::veilid_capnp::signed_value_descriptor::Builder<'a> {
::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(2), 0)
}
#[inline]
pub fn has_descriptor(&self) -> bool {
!self.builder.is_pointer_field_null(2)
}
}
pub struct Pipeline { _typeless: ::capnp::any_pointer::Pipeline }
impl ::capnp::capability::FromTypelessPipeline for Pipeline {
fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self {
Self { _typeless: typeless, }
}
}
impl Pipeline {
pub fn get_descriptor(&self) -> crate::veilid_capnp::signed_value_descriptor::Pipeline {
::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(2))
}
}
mod _private {
pub static ENCODED_NODE: [::capnp::Word; 74] = [
::capnp::word(0, 0, 0, 0, 5, 0, 6, 0),
::capnp::word(2, 225, 14, 150, 175, 127, 181, 184),
::capnp::word(19, 0, 0, 0, 1, 0, 0, 0),
::capnp::word(2, 171, 52, 55, 3, 232, 252, 143),
::capnp::word(3, 0, 7, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(21, 0, 0, 0, 82, 1, 0, 0),
::capnp::word(41, 0, 0, 0, 7, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(37, 0, 0, 0, 175, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(112, 114, 111, 116, 111, 47, 118, 101),
::capnp::word(105, 108, 105, 100, 46, 99, 97, 112),
::capnp::word(110, 112, 58, 79, 112, 101, 114, 97),
::capnp::word(116, 105, 111, 110, 73, 110, 115, 112),
::capnp::word(101, 99, 116, 86, 97, 108, 117, 101),
::capnp::word(65, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 1, 0, 1, 0),
::capnp::word(12, 0, 0, 0, 3, 0, 4, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 1, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(69, 0, 0, 0, 42, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(64, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(92, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(1, 0, 0, 0, 1, 0, 0, 0),
::capnp::word(0, 0, 1, 0, 1, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(89, 0, 0, 0, 50, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(84, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(112, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(2, 0, 0, 0, 2, 0, 0, 0),
::capnp::word(0, 0, 1, 0, 2, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(109, 0, 0, 0, 90, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(108, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(120, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(115, 101, 113, 115, 0, 0, 0, 0),
::capnp::word(14, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(8, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(14, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(112, 101, 101, 114, 115, 0, 0, 0),
::capnp::word(14, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(16, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(203, 75, 60, 93, 45, 114, 45, 254),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(14, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(100, 101, 115, 99, 114, 105, 112, 116),
::capnp::word(111, 114, 0, 0, 0, 0, 0, 0),
::capnp::word(16, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(231, 176, 225, 249, 211, 28, 145, 231),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(16, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
];
pub fn get_field_types(index: u16) -> ::capnp::introspect::Type {
match index {
0 => <::capnp::primitive_list::Owned<u32> as ::capnp::introspect::Introspect>::introspect(),
1 => <::capnp::struct_list::Owned<crate::veilid_capnp::peer_info::Owned> as ::capnp::introspect::Introspect>::introspect(),
2 => <crate::veilid_capnp::signed_value_descriptor::Owned as ::capnp::introspect::Introspect>::introspect(),
_ => panic!("invalid field index {}", index),
}
}
pub fn get_annotation_types(child_index: Option<u16>, index: u32) -> ::capnp::introspect::Type {
panic!("invalid annotation indices ({:?}, {}) ", child_index, index)
}
pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = ::capnp::introspect::RawStructSchema {
encoded_node: &ENCODED_NODE,
nonunion_members: NONUNION_MEMBERS,
members_by_discriminant: MEMBERS_BY_DISCRIMINANT,
};
pub static NONUNION_MEMBERS : &[u16] = &[0,1,2];
pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[];
pub const TYPE_ID: u64 = 0xb8b5_7faf_960e_e102;
}
}
pub mod operation_value_changed {
#[derive(Copy, Clone)]
pub struct Owned(());
@ -18995,7 +19577,7 @@ pub mod question {
}
pub mod detail {
pub use self::Which::{StatusQ,FindNodeQ,AppCallQ,GetValueQ,SetValueQ,WatchValueQ};
pub use self::Which::{StatusQ,FindNodeQ,AppCallQ,GetValueQ,SetValueQ,WatchValueQ,InspectValueQ};
#[derive(Copy, Clone)]
pub struct Owned(());
@ -19088,6 +19670,11 @@ pub mod question {
!self.reader.get_pointer_field(1).is_null()
}
#[inline]
pub fn has_inspect_value_q(&self) -> bool {
if self.reader.get_data_field::<u16>(1) != 6 { return false; }
!self.reader.get_pointer_field(1).is_null()
}
#[inline]
pub fn which(self) -> ::core::result::Result<WhichReader<'a,>, ::capnp::NotInSchema> {
match self.reader.get_data_field::<u16>(1) {
0 => {
@ -19120,6 +19707,11 @@ pub mod question {
::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None)
))
}
6 => {
::core::result::Result::Ok(InspectValueQ(
::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None)
))
}
x => ::core::result::Result::Err(::capnp::NotInSchema(x))
}
}
@ -19268,6 +19860,21 @@ pub mod question {
!self.builder.is_pointer_field_null(1)
}
#[inline]
pub fn set_inspect_value_q(&mut self, value: crate::veilid_capnp::operation_inspect_value_q::Reader<'_>) -> ::capnp::Result<()> {
self.builder.set_data_field::<u16>(1, 6);
::capnp::traits::SetPointerBuilder::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false)
}
#[inline]
pub fn init_inspect_value_q(self, ) -> crate::veilid_capnp::operation_inspect_value_q::Builder<'a> {
self.builder.set_data_field::<u16>(1, 6);
::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), 0)
}
#[inline]
pub fn has_inspect_value_q(&self) -> bool {
if self.builder.get_data_field::<u16>(1) != 6 { return false; }
!self.builder.is_pointer_field_null(1)
}
#[inline]
pub fn which(self) -> ::core::result::Result<WhichBuilder<'a,>, ::capnp::NotInSchema> {
match self.builder.get_data_field::<u16>(1) {
0 => {
@ -19300,6 +19907,11 @@ pub mod question {
::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None)
))
}
6 => {
::core::result::Result::Ok(InspectValueQ(
::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None)
))
}
x => ::core::result::Result::Err(::capnp::NotInSchema(x))
}
}
@ -19314,17 +19926,17 @@ pub mod question {
impl Pipeline {
}
mod _private {
pub static ENCODED_NODE: [::capnp::Word; 113] = [
pub static ENCODED_NODE: [::capnp::Word; 129] = [
::capnp::word(0, 0, 0, 0, 5, 0, 6, 0),
::capnp::word(178, 131, 145, 42, 21, 110, 131, 223),
::capnp::word(28, 0, 0, 0, 1, 0, 1, 0),
::capnp::word(112, 239, 146, 52, 195, 11, 81, 216),
::capnp::word(2, 0, 7, 0, 1, 0, 6, 0),
::capnp::word(2, 0, 7, 0, 1, 0, 7, 0),
::capnp::word(1, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(21, 0, 0, 0, 26, 1, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(29, 0, 0, 0, 87, 1, 0, 0),
::capnp::word(29, 0, 0, 0, 143, 1, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(112, 114, 111, 116, 111, 47, 118, 101),
@ -19332,49 +19944,56 @@ pub mod question {
::capnp::word(110, 112, 58, 81, 117, 101, 115, 116),
::capnp::word(105, 111, 110, 46, 100, 101, 116, 97),
::capnp::word(105, 108, 0, 0, 0, 0, 0, 0),
::capnp::word(24, 0, 0, 0, 3, 0, 4, 0),
::capnp::word(28, 0, 0, 0, 3, 0, 4, 0),
::capnp::word(0, 0, 255, 255, 1, 0, 0, 0),
::capnp::word(0, 0, 1, 0, 2, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(153, 0, 0, 0, 66, 0, 0, 0),
::capnp::word(181, 0, 0, 0, 66, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(148, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(160, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(176, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(188, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(1, 0, 254, 255, 1, 0, 0, 0),
::capnp::word(0, 0, 1, 0, 3, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(157, 0, 0, 0, 82, 0, 0, 0),
::capnp::word(185, 0, 0, 0, 82, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(156, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(168, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(184, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(196, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(2, 0, 253, 255, 1, 0, 0, 0),
::capnp::word(0, 0, 1, 0, 4, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(165, 0, 0, 0, 74, 0, 0, 0),
::capnp::word(193, 0, 0, 0, 74, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(164, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(176, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(192, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(204, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(3, 0, 252, 255, 1, 0, 0, 0),
::capnp::word(0, 0, 1, 0, 5, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(173, 0, 0, 0, 82, 0, 0, 0),
::capnp::word(201, 0, 0, 0, 82, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(172, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(184, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(200, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(212, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(4, 0, 251, 255, 1, 0, 0, 0),
::capnp::word(0, 0, 1, 0, 6, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(181, 0, 0, 0, 82, 0, 0, 0),
::capnp::word(209, 0, 0, 0, 82, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(180, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(192, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(208, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(220, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(5, 0, 250, 255, 1, 0, 0, 0),
::capnp::word(0, 0, 1, 0, 7, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(189, 0, 0, 0, 98, 0, 0, 0),
::capnp::word(217, 0, 0, 0, 98, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(188, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(200, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(216, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(228, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(6, 0, 249, 255, 1, 0, 0, 0),
::capnp::word(0, 0, 1, 0, 8, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(225, 0, 0, 0, 114, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(224, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(236, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(115, 116, 97, 116, 117, 115, 81, 0),
::capnp::word(16, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(74, 136, 13, 167, 206, 128, 93, 134),
@ -19428,6 +20047,15 @@ pub mod question {
::capnp::word(16, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(105, 110, 115, 112, 101, 99, 116, 86),
::capnp::word(97, 108, 117, 101, 81, 0, 0, 0),
::capnp::word(16, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(90, 245, 22, 253, 210, 18, 247, 222),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(16, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
];
pub fn get_field_types(index: u16) -> ::capnp::introspect::Type {
match index {
@ -19437,6 +20065,7 @@ pub mod question {
3 => <crate::veilid_capnp::operation_get_value_q::Owned as ::capnp::introspect::Introspect>::introspect(),
4 => <crate::veilid_capnp::operation_set_value_q::Owned as ::capnp::introspect::Introspect>::introspect(),
5 => <crate::veilid_capnp::operation_watch_value_q::Owned as ::capnp::introspect::Introspect>::introspect(),
6 => <crate::veilid_capnp::operation_inspect_value_q::Owned as ::capnp::introspect::Introspect>::introspect(),
_ => panic!("invalid field index {}", index),
}
}
@ -19449,19 +20078,20 @@ pub mod question {
members_by_discriminant: MEMBERS_BY_DISCRIMINANT,
};
pub static NONUNION_MEMBERS : &[u16] = &[];
pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[0,1,2,3,4,5];
pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[0,1,2,3,4,5,6];
pub const TYPE_ID: u64 = 0xdf83_6e15_2a91_83b2;
}
pub enum Which<A0,A1,A2,A3,A4,A5> {
pub enum Which<A0,A1,A2,A3,A4,A5,A6> {
StatusQ(A0),
FindNodeQ(A1),
AppCallQ(A2),
GetValueQ(A3),
SetValueQ(A4),
WatchValueQ(A5),
InspectValueQ(A6),
}
pub type WhichReader<'a,> = Which<::capnp::Result<crate::veilid_capnp::operation_status_q::Reader<'a>>,::capnp::Result<crate::veilid_capnp::operation_find_node_q::Reader<'a>>,::capnp::Result<crate::veilid_capnp::operation_app_call_q::Reader<'a>>,::capnp::Result<crate::veilid_capnp::operation_get_value_q::Reader<'a>>,::capnp::Result<crate::veilid_capnp::operation_set_value_q::Reader<'a>>,::capnp::Result<crate::veilid_capnp::operation_watch_value_q::Reader<'a>>>;
pub type WhichBuilder<'a,> = Which<::capnp::Result<crate::veilid_capnp::operation_status_q::Builder<'a>>,::capnp::Result<crate::veilid_capnp::operation_find_node_q::Builder<'a>>,::capnp::Result<crate::veilid_capnp::operation_app_call_q::Builder<'a>>,::capnp::Result<crate::veilid_capnp::operation_get_value_q::Builder<'a>>,::capnp::Result<crate::veilid_capnp::operation_set_value_q::Builder<'a>>,::capnp::Result<crate::veilid_capnp::operation_watch_value_q::Builder<'a>>>;
pub type WhichReader<'a,> = Which<::capnp::Result<crate::veilid_capnp::operation_status_q::Reader<'a>>,::capnp::Result<crate::veilid_capnp::operation_find_node_q::Reader<'a>>,::capnp::Result<crate::veilid_capnp::operation_app_call_q::Reader<'a>>,::capnp::Result<crate::veilid_capnp::operation_get_value_q::Reader<'a>>,::capnp::Result<crate::veilid_capnp::operation_set_value_q::Reader<'a>>,::capnp::Result<crate::veilid_capnp::operation_watch_value_q::Reader<'a>>,::capnp::Result<crate::veilid_capnp::operation_inspect_value_q::Reader<'a>>>;
pub type WhichBuilder<'a,> = Which<::capnp::Result<crate::veilid_capnp::operation_status_q::Builder<'a>>,::capnp::Result<crate::veilid_capnp::operation_find_node_q::Builder<'a>>,::capnp::Result<crate::veilid_capnp::operation_app_call_q::Builder<'a>>,::capnp::Result<crate::veilid_capnp::operation_get_value_q::Builder<'a>>,::capnp::Result<crate::veilid_capnp::operation_set_value_q::Builder<'a>>,::capnp::Result<crate::veilid_capnp::operation_watch_value_q::Builder<'a>>,::capnp::Result<crate::veilid_capnp::operation_inspect_value_q::Builder<'a>>>;
}
}
@ -20317,7 +20947,7 @@ pub mod answer {
}
pub mod detail {
pub use self::Which::{StatusA,FindNodeA,AppCallA,GetValueA,SetValueA,WatchValueA};
pub use self::Which::{StatusA,FindNodeA,AppCallA,GetValueA,SetValueA,WatchValueA,InspectValueA};
#[derive(Copy, Clone)]
pub struct Owned(());
@ -20410,6 +21040,11 @@ pub mod answer {
!self.reader.get_pointer_field(0).is_null()
}
#[inline]
pub fn has_inspect_value_a(&self) -> bool {
if self.reader.get_data_field::<u16>(0) != 6 { return false; }
!self.reader.get_pointer_field(0).is_null()
}
#[inline]
pub fn which(self) -> ::core::result::Result<WhichReader<'a,>, ::capnp::NotInSchema> {
match self.reader.get_data_field::<u16>(0) {
0 => {
@ -20442,6 +21077,11 @@ pub mod answer {
::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None)
))
}
6 => {
::core::result::Result::Ok(InspectValueA(
::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None)
))
}
x => ::core::result::Result::Err(::capnp::NotInSchema(x))
}
}
@ -20590,6 +21230,21 @@ pub mod answer {
!self.builder.is_pointer_field_null(0)
}
#[inline]
pub fn set_inspect_value_a(&mut self, value: crate::veilid_capnp::operation_inspect_value_a::Reader<'_>) -> ::capnp::Result<()> {
self.builder.set_data_field::<u16>(0, 6);
::capnp::traits::SetPointerBuilder::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false)
}
#[inline]
pub fn init_inspect_value_a(self, ) -> crate::veilid_capnp::operation_inspect_value_a::Builder<'a> {
self.builder.set_data_field::<u16>(0, 6);
::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0)
}
#[inline]
pub fn has_inspect_value_a(&self) -> bool {
if self.builder.get_data_field::<u16>(0) != 6 { return false; }
!self.builder.is_pointer_field_null(0)
}
#[inline]
pub fn which(self) -> ::core::result::Result<WhichBuilder<'a,>, ::capnp::NotInSchema> {
match self.builder.get_data_field::<u16>(0) {
0 => {
@ -20622,6 +21277,11 @@ pub mod answer {
::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None)
))
}
6 => {
::core::result::Result::Ok(InspectValueA(
::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None)
))
}
x => ::core::result::Result::Err(::capnp::NotInSchema(x))
}
}
@ -20636,17 +21296,17 @@ pub mod answer {
impl Pipeline {
}
mod _private {
pub static ENCODED_NODE: [::capnp::Word; 113] = [
pub static ENCODED_NODE: [::capnp::Word; 129] = [
::capnp::word(0, 0, 0, 0, 5, 0, 6, 0),
::capnp::word(181, 242, 159, 40, 61, 141, 102, 244),
::capnp::word(26, 0, 0, 0, 1, 0, 1, 0),
::capnp::word(88, 16, 140, 152, 182, 184, 172, 172),
::capnp::word(1, 0, 7, 0, 1, 0, 6, 0),
::capnp::word(1, 0, 7, 0, 1, 0, 7, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(21, 0, 0, 0, 10, 1, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(29, 0, 0, 0, 87, 1, 0, 0),
::capnp::word(29, 0, 0, 0, 143, 1, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(112, 114, 111, 116, 111, 47, 118, 101),
@ -20654,49 +21314,56 @@ pub mod answer {
::capnp::word(110, 112, 58, 65, 110, 115, 119, 101),
::capnp::word(114, 46, 100, 101, 116, 97, 105, 108),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(24, 0, 0, 0, 3, 0, 4, 0),
::capnp::word(28, 0, 0, 0, 3, 0, 4, 0),
::capnp::word(0, 0, 255, 255, 0, 0, 0, 0),
::capnp::word(0, 0, 1, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(153, 0, 0, 0, 66, 0, 0, 0),
::capnp::word(181, 0, 0, 0, 66, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(148, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(160, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(176, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(188, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(1, 0, 254, 255, 0, 0, 0, 0),
::capnp::word(0, 0, 1, 0, 1, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(157, 0, 0, 0, 82, 0, 0, 0),
::capnp::word(185, 0, 0, 0, 82, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(156, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(168, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(184, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(196, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(2, 0, 253, 255, 0, 0, 0, 0),
::capnp::word(0, 0, 1, 0, 2, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(165, 0, 0, 0, 74, 0, 0, 0),
::capnp::word(193, 0, 0, 0, 74, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(164, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(176, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(192, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(204, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(3, 0, 252, 255, 0, 0, 0, 0),
::capnp::word(0, 0, 1, 0, 3, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(173, 0, 0, 0, 82, 0, 0, 0),
::capnp::word(201, 0, 0, 0, 82, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(172, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(184, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(200, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(212, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(4, 0, 251, 255, 0, 0, 0, 0),
::capnp::word(0, 0, 1, 0, 4, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(181, 0, 0, 0, 82, 0, 0, 0),
::capnp::word(209, 0, 0, 0, 82, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(180, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(192, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(208, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(220, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(5, 0, 250, 255, 0, 0, 0, 0),
::capnp::word(0, 0, 1, 0, 5, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(189, 0, 0, 0, 98, 0, 0, 0),
::capnp::word(217, 0, 0, 0, 98, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(188, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(200, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(216, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(228, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(6, 0, 249, 255, 0, 0, 0, 0),
::capnp::word(0, 0, 1, 0, 6, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(225, 0, 0, 0, 114, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(224, 0, 0, 0, 3, 0, 1, 0),
::capnp::word(236, 0, 0, 0, 2, 0, 1, 0),
::capnp::word(115, 116, 97, 116, 117, 115, 65, 0),
::capnp::word(16, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(85, 42, 129, 250, 7, 244, 6, 179),
@ -20750,6 +21417,15 @@ pub mod answer {
::capnp::word(16, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(105, 110, 115, 112, 101, 99, 116, 86),
::capnp::word(97, 108, 117, 101, 65, 0, 0, 0),
::capnp::word(16, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(2, 225, 14, 150, 175, 127, 181, 184),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(16, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
::capnp::word(0, 0, 0, 0, 0, 0, 0, 0),
];
pub fn get_field_types(index: u16) -> ::capnp::introspect::Type {
match index {
@ -20759,6 +21435,7 @@ pub mod answer {
3 => <crate::veilid_capnp::operation_get_value_a::Owned as ::capnp::introspect::Introspect>::introspect(),
4 => <crate::veilid_capnp::operation_set_value_a::Owned as ::capnp::introspect::Introspect>::introspect(),
5 => <crate::veilid_capnp::operation_watch_value_a::Owned as ::capnp::introspect::Introspect>::introspect(),
6 => <crate::veilid_capnp::operation_inspect_value_a::Owned as ::capnp::introspect::Introspect>::introspect(),
_ => panic!("invalid field index {}", index),
}
}
@ -20771,19 +21448,20 @@ pub mod answer {
members_by_discriminant: MEMBERS_BY_DISCRIMINANT,
};
pub static NONUNION_MEMBERS : &[u16] = &[];
pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[0,1,2,3,4,5];
pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[0,1,2,3,4,5,6];
pub const TYPE_ID: u64 = 0xf466_8d3d_289f_f2b5;
}
pub enum Which<A0,A1,A2,A3,A4,A5> {
pub enum Which<A0,A1,A2,A3,A4,A5,A6> {
StatusA(A0),
FindNodeA(A1),
AppCallA(A2),
GetValueA(A3),
SetValueA(A4),
WatchValueA(A5),
InspectValueA(A6),
}
pub type WhichReader<'a,> = Which<::capnp::Result<crate::veilid_capnp::operation_status_a::Reader<'a>>,::capnp::Result<crate::veilid_capnp::operation_find_node_a::Reader<'a>>,::capnp::Result<crate::veilid_capnp::operation_app_call_a::Reader<'a>>,::capnp::Result<crate::veilid_capnp::operation_get_value_a::Reader<'a>>,::capnp::Result<crate::veilid_capnp::operation_set_value_a::Reader<'a>>,::capnp::Result<crate::veilid_capnp::operation_watch_value_a::Reader<'a>>>;
pub type WhichBuilder<'a,> = Which<::capnp::Result<crate::veilid_capnp::operation_status_a::Builder<'a>>,::capnp::Result<crate::veilid_capnp::operation_find_node_a::Builder<'a>>,::capnp::Result<crate::veilid_capnp::operation_app_call_a::Builder<'a>>,::capnp::Result<crate::veilid_capnp::operation_get_value_a::Builder<'a>>,::capnp::Result<crate::veilid_capnp::operation_set_value_a::Builder<'a>>,::capnp::Result<crate::veilid_capnp::operation_watch_value_a::Builder<'a>>>;
pub type WhichReader<'a,> = Which<::capnp::Result<crate::veilid_capnp::operation_status_a::Reader<'a>>,::capnp::Result<crate::veilid_capnp::operation_find_node_a::Reader<'a>>,::capnp::Result<crate::veilid_capnp::operation_app_call_a::Reader<'a>>,::capnp::Result<crate::veilid_capnp::operation_get_value_a::Reader<'a>>,::capnp::Result<crate::veilid_capnp::operation_set_value_a::Reader<'a>>,::capnp::Result<crate::veilid_capnp::operation_watch_value_a::Reader<'a>>,::capnp::Result<crate::veilid_capnp::operation_inspect_value_a::Reader<'a>>>;
pub type WhichBuilder<'a,> = Which<::capnp::Result<crate::veilid_capnp::operation_status_a::Builder<'a>>,::capnp::Result<crate::veilid_capnp::operation_find_node_a::Builder<'a>>,::capnp::Result<crate::veilid_capnp::operation_app_call_a::Builder<'a>>,::capnp::Result<crate::veilid_capnp::operation_get_value_a::Builder<'a>>,::capnp::Result<crate::veilid_capnp::operation_set_value_a::Builder<'a>>,::capnp::Result<crate::veilid_capnp::operation_watch_value_a::Builder<'a>>,::capnp::Result<crate::veilid_capnp::operation_inspect_value_a::Builder<'a>>>;
}
}
@ -21406,4 +22084,4 @@ pub mod operation {
}
}
//BUILDHASH:4ee16918900e322a0daa4bb0a11ca6094989c65936a653b0b78811e027d4d962
//BUILDHASH:6df0786a4485a9d0c25c177959fe1b2070c2a98884d20267eb70e129be95f2b0

View File

@ -63,6 +63,7 @@ use super::*;
pub(in crate::rpc_processor) enum QuestionContext {
GetValue(ValidateGetValueContext),
SetValue(ValidateSetValueContext),
InspectValue(ValidateInspectValueContext),
}
#[derive(Clone)]

View File

@ -38,6 +38,7 @@ pub(in crate::rpc_processor) enum RPCAnswerDetail {
GetValueA(Box<RPCOperationGetValueA>),
SetValueA(Box<RPCOperationSetValueA>),
WatchValueA(Box<RPCOperationWatchValueA>),
InspectValueA(Box<RPCOperationInspectValueA>),
#[cfg(feature = "unstable-blockstore")]
SupplyBlockA(Box<RPCOperationSupplyBlockA>),
#[cfg(feature = "unstable-blockstore")]
@ -60,6 +61,7 @@ impl RPCAnswerDetail {
RPCAnswerDetail::GetValueA(_) => "GetValueA",
RPCAnswerDetail::SetValueA(_) => "SetValueA",
RPCAnswerDetail::WatchValueA(_) => "WatchValueA",
RPCAnswerDetail::InspectValueA(_) => "InspectValueA",
#[cfg(feature = "unstable-blockstore")]
RPCAnswerDetail::SupplyBlockA(_) => "SupplyBlockA",
#[cfg(feature = "unstable-blockstore")]
@ -80,6 +82,7 @@ impl RPCAnswerDetail {
RPCAnswerDetail::GetValueA(r) => r.validate(validate_context),
RPCAnswerDetail::SetValueA(r) => r.validate(validate_context),
RPCAnswerDetail::WatchValueA(r) => r.validate(validate_context),
RPCAnswerDetail::InspectValueA(r) => r.validate(validate_context),
#[cfg(feature = "unstable-blockstore")]
RPCAnswerDetail::SupplyBlockA(r) => r.validate(validate_context),
#[cfg(feature = "unstable-blockstore")]
@ -127,6 +130,11 @@ impl RPCAnswerDetail {
let out = RPCOperationWatchValueA::decode(&op_reader)?;
RPCAnswerDetail::WatchValueA(Box::new(out))
}
veilid_capnp::answer::detail::InspectValueA(r) => {
let op_reader = r.map_err(RPCError::protocol)?;
let out = RPCOperationInspectValueA::decode(&op_reader)?;
RPCAnswerDetail::InspectValueA(Box::new(out))
}
#[cfg(feature = "unstable-blockstore")]
veilid_capnp::answer::detail::SupplyBlockA(r) => {
let op_reader = r.map_err(RPCError::protocol)?;
@ -173,6 +181,9 @@ impl RPCAnswerDetail {
RPCAnswerDetail::WatchValueA(d) => {
d.encode(&mut builder.reborrow().init_watch_value_a())
}
RPCAnswerDetail::InspectValueA(d) => {
d.encode(&mut builder.reborrow().init_inspect_value_a())
}
#[cfg(feature = "unstable-blockstore")]
RPCAnswerDetail::SupplyBlockA(d) => {
d.encode(&mut builder.reborrow().init_supply_block_a())

View File

@ -4,6 +4,7 @@ mod operation_app_call;
mod operation_app_message;
mod operation_find_node;
mod operation_get_value;
mod operation_inspect_value;
mod operation_return_receipt;
mod operation_route;
mod operation_set_value;
@ -35,6 +36,7 @@ pub(in crate::rpc_processor) use operation_app_call::*;
pub(in crate::rpc_processor) use operation_app_message::*;
pub(in crate::rpc_processor) use operation_find_node::*;
pub(in crate::rpc_processor) use operation_get_value::*;
pub(in crate::rpc_processor) use operation_inspect_value::*;
pub(in crate::rpc_processor) use operation_return_receipt::*;
pub(in crate::rpc_processor) use operation_route::*;
pub(in crate::rpc_processor) use operation_set_value::*;

View File

@ -111,29 +111,30 @@ impl RPCOperationGetValueA {
panic!("Wrong context type for GetValueA");
};
if let Some(value) = &self.value {
// Get descriptor to validate with
let descriptor = if let Some(descriptor) = &self.descriptor {
if let Some(last_descriptor) = &get_value_context.last_descriptor {
if descriptor.cmp_no_sig(last_descriptor) != cmp::Ordering::Equal {
return Err(RPCError::protocol(
"getvalue descriptor does not match last descriptor",
));
}
}
descriptor
} else {
let Some(descriptor) = &get_value_context.last_descriptor else {
// Validate descriptor
if let Some(descriptor) = &self.descriptor {
// Ensure descriptor matches last one
if let Some(last_descriptor) = &get_value_context.last_descriptor {
if descriptor.cmp_no_sig(last_descriptor) != cmp::Ordering::Equal {
return Err(RPCError::protocol(
"no last descriptor, requires a descriptor",
"GetValue descriptor does not match last descriptor",
));
};
descriptor
};
}
}
// Ensure the descriptor itself validates
descriptor
.validate(get_value_context.vcrypto.clone())
.map_err(RPCError::protocol)?;
}
// Ensure the value validates
if let Some(value) = &self.value {
// Get descriptor to validate with
let Some(descriptor) = self.descriptor.or(get_value_context.last_descriptor) else {
return Err(RPCError::protocol(
"no last descriptor, requires a descriptor",
));
};
// And the signed value data
value

View File

@ -0,0 +1,291 @@
use super::*;
use crate::storage_manager::SignedValueDescriptor;
const MAX_INSPECT_VALUE_Q_SUBKEYS_LEN: usize = 512;
const MAX_INSPECT_VALUE_A_SEQS_LEN: usize = MAX_INSPECT_VALUE_Q_SUBKEYS_LEN;
const MAX_INSPECT_VALUE_A_PEERS_LEN: usize = 20;
#[derive(Clone)]
pub(in crate::rpc_processor) struct ValidateInspectValueContext {
pub last_descriptor: Option<SignedValueDescriptor>,
pub subkeys: ValueSubkeyRangeSet,
pub vcrypto: CryptoSystemVersion,
}
impl fmt::Debug for ValidateInspectValueContext {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ValidateInspectValueContext")
.field("last_descriptor", &self.last_descriptor)
.field("vcrypto", &self.vcrypto.kind().to_string())
.finish()
}
}
#[derive(Debug, Clone)]
pub(in crate::rpc_processor) struct RPCOperationInspectValueQ {
key: TypedKey,
subkeys: ValueSubkeyRangeSet,
want_descriptor: bool,
}
impl RPCOperationInspectValueQ {
pub fn new(
key: TypedKey,
subkeys: ValueSubkeyRangeSet,
want_descriptor: bool,
) -> Result<Self, RPCError> {
// Needed because RangeSetBlaze uses different types here all the time
#[allow(clippy::unnecessary_cast)]
let subkeys_len = subkeys.len() as usize;
if subkeys_len > MAX_INSPECT_VALUE_Q_SUBKEYS_LEN {
return Err(RPCError::protocol("InspectValue subkeys length too long"));
}
Ok(Self {
key,
subkeys,
want_descriptor,
})
}
pub fn validate(&mut self, _validate_context: &RPCValidateContext) -> Result<(), RPCError> {
Ok(())
}
// pub fn key(&self) -> &TypedKey {
// &self.key
// }
// pub fn subkeys(&self) -> &ValueSubkeyRangeSet {
// &self.subkeys
// }
// pub fn want_descriptor(&self) -> bool {
// self.want_descriptor
// }
pub fn destructure(self) -> (TypedKey, ValueSubkeyRangeSet, bool) {
(self.key, self.subkeys, self.want_descriptor)
}
pub fn decode(
reader: &veilid_capnp::operation_inspect_value_q::Reader,
) -> Result<Self, RPCError> {
let k_reader = reader.reborrow().get_key().map_err(RPCError::protocol)?;
let key = decode_typed_key(&k_reader)?;
let sk_reader = reader.get_subkeys().map_err(RPCError::protocol)?;
// Maximum number of ranges that can hold the maximum number of subkeys is one subkey per range
if sk_reader.len() as usize > MAX_INSPECT_VALUE_Q_SUBKEYS_LEN {
return Err(RPCError::protocol("InspectValueQ too many subkey ranges"));
}
let mut subkeys = ValueSubkeyRangeSet::new();
for skr in sk_reader.iter() {
let vskr = (skr.get_start(), skr.get_end());
if vskr.0 > vskr.1 {
return Err(RPCError::protocol("invalid subkey range"));
}
if let Some(lvskr) = subkeys.last() {
if lvskr >= vskr.0 {
return Err(RPCError::protocol(
"subkey range out of order or not merged",
));
}
}
subkeys.ranges_insert(vskr.0..=vskr.1);
}
// Needed because RangeSetBlaze uses different types here all the time
#[allow(clippy::unnecessary_cast)]
if subkeys.len() as usize > MAX_INSPECT_VALUE_Q_SUBKEYS_LEN {
return Err(RPCError::protocol("InspectValueQ too many subkey ranges"));
}
let want_descriptor = reader.reborrow().get_want_descriptor();
Ok(Self {
key,
subkeys,
want_descriptor,
})
}
pub fn encode(
&self,
builder: &mut veilid_capnp::operation_inspect_value_q::Builder,
) -> Result<(), RPCError> {
let mut k_builder = builder.reborrow().init_key();
encode_typed_key(&self.key, &mut k_builder);
let mut sk_builder = builder.reborrow().init_subkeys(
self.subkeys
.ranges_len()
.try_into()
.map_err(RPCError::map_internal("invalid subkey range list length"))?,
);
for (i, skr) in self.subkeys.ranges().enumerate() {
let mut skr_builder = sk_builder.reborrow().get(i as u32);
skr_builder.set_start(*skr.start());
skr_builder.set_end(*skr.end());
}
builder.set_want_descriptor(self.want_descriptor);
Ok(())
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
#[derive(Debug, Clone)]
pub(in crate::rpc_processor) struct RPCOperationInspectValueA {
seqs: Vec<ValueSeqNum>,
peers: Vec<PeerInfo>,
descriptor: Option<SignedValueDescriptor>,
}
impl RPCOperationInspectValueA {
pub fn new(
seqs: Vec<ValueSeqNum>,
peers: Vec<PeerInfo>,
descriptor: Option<SignedValueDescriptor>,
) -> Result<Self, RPCError> {
if seqs.len() > MAX_INSPECT_VALUE_A_SEQS_LEN {
return Err(RPCError::protocol(
"encoded InspectValueA seqs length too long",
));
}
if peers.len() > MAX_INSPECT_VALUE_A_PEERS_LEN {
return Err(RPCError::protocol(
"encoded InspectValueA peers length too long",
));
}
Ok(Self {
seqs,
peers,
descriptor,
})
}
pub fn validate(&mut self, validate_context: &RPCValidateContext) -> Result<(), RPCError> {
let question_context = validate_context
.question_context
.as_ref()
.expect("InspectValueA requires question context");
let QuestionContext::InspectValue(inspect_value_context) = question_context else {
panic!("Wrong context type for InspectValueA");
};
// Ensure seqs returned does not exceeed subkeys requested
#[allow(clippy::unnecessary_cast)]
if self.seqs.len() > inspect_value_context.subkeys.len() as usize {
return Err(RPCError::protocol(
"InspectValue seqs length is greater than subkeys requested",
));
}
// Validate descriptor
if let Some(descriptor) = &self.descriptor {
// Ensure descriptor matches last one
if let Some(last_descriptor) = &inspect_value_context.last_descriptor {
if descriptor.cmp_no_sig(last_descriptor) != cmp::Ordering::Equal {
return Err(RPCError::protocol(
"InspectValue descriptor does not match last descriptor",
));
}
}
// Ensure the descriptor itself validates
descriptor
.validate(inspect_value_context.vcrypto.clone())
.map_err(RPCError::protocol)?;
}
PeerInfo::validate_vec(&mut self.peers, validate_context.crypto.clone());
Ok(())
}
// pub fn seqs(&self) -> &[ValueSeqNum] {
// &self.seqs
// }
// pub fn peers(&self) -> &[PeerInfo] {
// &self.peers
// }
// pub fn descriptor(&self) -> Option<&SignedValueDescriptor> {
// self.descriptor.as_ref()
// }
pub fn destructure(
self,
) -> (
Vec<ValueSeqNum>,
Vec<PeerInfo>,
Option<SignedValueDescriptor>,
) {
(self.seqs, self.peers, self.descriptor)
}
pub fn decode(
reader: &veilid_capnp::operation_inspect_value_a::Reader,
) -> Result<Self, RPCError> {
let seqs = if reader.has_seqs() {
let seqs_reader = reader.get_seqs().map_err(RPCError::protocol)?;
let Some(seqs) = seqs_reader.as_slice().map(|s| s.to_vec()) else {
return Err(RPCError::protocol("invalid decoded InspectValueA seqs"));
};
seqs
} else {
return Err(RPCError::protocol("missing decoded InspectValueA seqs"));
};
let peers_reader = reader.get_peers().map_err(RPCError::protocol)?;
if peers_reader.len() as usize > MAX_INSPECT_VALUE_A_PEERS_LEN {
return Err(RPCError::protocol(
"decoded InspectValueA peers length too long",
));
}
let mut peers = Vec::<PeerInfo>::with_capacity(
peers_reader
.len()
.try_into()
.map_err(RPCError::map_internal("too many peers"))?,
);
for p in peers_reader.iter() {
let peer_info = decode_peer_info(&p)?;
peers.push(peer_info);
}
let descriptor = if reader.has_descriptor() {
let d_reader = reader.get_descriptor().map_err(RPCError::protocol)?;
let descriptor = decode_signed_value_descriptor(&d_reader)?;
Some(descriptor)
} else {
None
};
Ok(Self {
seqs,
peers,
descriptor,
})
}
pub fn encode(
&self,
builder: &mut veilid_capnp::operation_inspect_value_a::Builder,
) -> Result<(), RPCError> {
let mut seqs_builder = builder.reborrow().init_seqs(
self.seqs
.len()
.try_into()
.map_err(RPCError::map_internal("invalid seqs list length"))?,
);
for (i, seq) in self.seqs.iter().enumerate() {
seqs_builder.set(i as u32, *seq);
}
let mut peers_builder = builder.reborrow().init_peers(
self.peers
.len()
.try_into()
.map_err(RPCError::map_internal("invalid peers list length"))?,
);
for (i, peer) in self.peers.iter().enumerate() {
let mut pi_builder = peers_builder.reborrow().get(i as u32);
encode_peer_info(peer, &mut pi_builder)?;
}
if let Some(descriptor) = &self.descriptor {
let mut d_builder = builder.reborrow().init_descriptor();
encode_signed_value_descriptor(descriptor, &mut d_builder)?;
}
Ok(())
}
}

View File

@ -1,7 +1,7 @@
use super::*;
use crate::storage_manager::SignedValueData;
const MAX_VALUE_CHANGED_SUBKEYS_LEN: usize = 512;
const MAX_VALUE_CHANGED_SUBKEY_RANGES_LEN: usize = 512;
#[derive(Debug, Clone)]
pub(in crate::rpc_processor) struct RPCOperationValueChanged {
@ -21,12 +21,12 @@ impl RPCOperationValueChanged {
watch_id: u64,
value: SignedValueData,
) -> Result<Self, RPCError> {
// Needed because RangeSetBlaze uses different types here all the time
#[allow(clippy::unnecessary_cast)]
let subkeys_len = subkeys.ranges_len() as usize;
if subkeys_len > MAX_VALUE_CHANGED_SUBKEYS_LEN {
return Err(RPCError::protocol("ValueChanged subkeys length too long"));
if subkeys_len > MAX_VALUE_CHANGED_SUBKEY_RANGES_LEN {
return Err(RPCError::protocol(
"ValueChanged subkey ranges length too long",
));
}
if watch_id == 0 {
@ -93,8 +93,10 @@ impl RPCOperationValueChanged {
let key = decode_typed_key(&k_reader)?;
let sk_reader = reader.get_subkeys().map_err(RPCError::protocol)?;
if sk_reader.len() as usize > MAX_VALUE_CHANGED_SUBKEYS_LEN {
return Err(RPCError::protocol("ValueChanged subkeys length too long"));
if sk_reader.len() as usize > MAX_VALUE_CHANGED_SUBKEY_RANGES_LEN {
return Err(RPCError::protocol(
"ValueChanged subkey ranges length too long",
));
}
let mut subkeys = ValueSubkeyRangeSet::new();

View File

@ -1,6 +1,6 @@
use super::*;
const MAX_WATCH_VALUE_Q_SUBKEYS_LEN: usize = 512;
const MAX_WATCH_VALUE_Q_SUBKEY_RANGES_LEN: usize = 512;
const MAX_WATCH_VALUE_A_PEERS_LEN: usize = 20;
#[derive(Debug, Clone)]
@ -25,11 +25,7 @@ impl RPCOperationWatchValueQ {
watcher: KeyPair,
vcrypto: CryptoSystemVersion,
) -> Result<Self, RPCError> {
// Needed because RangeSetBlaze uses different types here all the time
#[allow(clippy::unnecessary_cast)]
let subkeys_len = subkeys.ranges_len() as usize;
if subkeys_len > MAX_WATCH_VALUE_Q_SUBKEYS_LEN {
if subkeys.ranges_len() > MAX_WATCH_VALUE_Q_SUBKEY_RANGES_LEN {
return Err(RPCError::protocol("WatchValueQ subkeys length too long"));
}
@ -62,9 +58,7 @@ impl RPCOperationWatchValueQ {
count: u32,
watch_id: Option<u64>,
) -> Vec<u8> {
// Needed because RangeSetBlaze uses different types here all the time
#[allow(clippy::unnecessary_cast)]
let subkeys_len = subkeys.ranges_len() as usize;
let subkeys_len = subkeys.ranges_len();
let mut sig_data = Vec::with_capacity(PUBLIC_KEY_LENGTH + 4 + (subkeys_len * 8) + 8 + 8);
sig_data.extend_from_slice(&key.kind.0);
@ -168,8 +162,8 @@ impl RPCOperationWatchValueQ {
let key = decode_typed_key(&k_reader)?;
let sk_reader = reader.get_subkeys().map_err(RPCError::protocol)?;
if sk_reader.len() as usize > MAX_WATCH_VALUE_Q_SUBKEYS_LEN {
return Err(RPCError::protocol("WatchValueQ subkeys length too long"));
if sk_reader.len() as usize > MAX_WATCH_VALUE_Q_SUBKEY_RANGES_LEN {
return Err(RPCError::protocol("WatchValueQ too many subkey ranges"));
}
let mut subkeys = ValueSubkeyRangeSet::new();
for skr in sk_reader.iter() {

View File

@ -50,6 +50,7 @@ pub(in crate::rpc_processor) enum RPCQuestionDetail {
GetValueQ(Box<RPCOperationGetValueQ>),
SetValueQ(Box<RPCOperationSetValueQ>),
WatchValueQ(Box<RPCOperationWatchValueQ>),
InspectValueQ(Box<RPCOperationInspectValueQ>),
#[cfg(feature = "unstable-blockstore")]
SupplyBlockQ(Box<RPCOperationSupplyBlockQ>),
#[cfg(feature = "unstable-blockstore")]
@ -72,6 +73,7 @@ impl RPCQuestionDetail {
RPCQuestionDetail::GetValueQ(_) => "GetValueQ",
RPCQuestionDetail::SetValueQ(_) => "SetValueQ",
RPCQuestionDetail::WatchValueQ(_) => "WatchValueQ",
RPCQuestionDetail::InspectValueQ(_) => "InspectValueQ",
#[cfg(feature = "unstable-blockstore")]
RPCQuestionDetail::SupplyBlockQ(_) => "SupplyBlockQ",
#[cfg(feature = "unstable-blockstore")]
@ -92,6 +94,7 @@ impl RPCQuestionDetail {
RPCQuestionDetail::GetValueQ(r) => r.validate(validate_context),
RPCQuestionDetail::SetValueQ(r) => r.validate(validate_context),
RPCQuestionDetail::WatchValueQ(r) => r.validate(validate_context),
RPCQuestionDetail::InspectValueQ(r) => r.validate(validate_context),
#[cfg(feature = "unstable-blockstore")]
RPCQuestionDetail::SupplyBlockQ(r) => r.validate(validate_context),
#[cfg(feature = "unstable-blockstore")]
@ -140,6 +143,11 @@ impl RPCQuestionDetail {
let out = RPCOperationWatchValueQ::decode(&op_reader)?;
RPCQuestionDetail::WatchValueQ(Box::new(out))
}
veilid_capnp::question::detail::InspectValueQ(r) => {
let op_reader = r.map_err(RPCError::protocol)?;
let out = RPCOperationInspectValueQ::decode(&op_reader)?;
RPCQuestionDetail::InspectValueQ(Box::new(out))
}
#[cfg(feature = "unstable-blockstore")]
veilid_capnp::question::detail::SupplyBlockQ(r) => {
let op_reader = r.map_err(RPCError::protocol)?;
@ -186,6 +194,9 @@ impl RPCQuestionDetail {
RPCQuestionDetail::WatchValueQ(d) => {
d.encode(&mut builder.reborrow().init_watch_value_q())
}
RPCQuestionDetail::InspectValueQ(d) => {
d.encode(&mut builder.reborrow().init_inspect_value_q())
}
#[cfg(feature = "unstable-blockstore")]
RPCQuestionDetail::SupplyBlockQ(d) => {
d.encode(&mut builder.reborrow().init_supply_block_q())

View File

@ -8,6 +8,7 @@ mod rpc_app_message;
mod rpc_error;
mod rpc_find_node;
mod rpc_get_value;
mod rpc_inspect_value;
mod rpc_return_receipt;
mod rpc_route;
mod rpc_set_value;
@ -1621,6 +1622,7 @@ impl RPCProcessor {
RPCQuestionDetail::GetValueQ(_) => self.process_get_value_q(msg).await,
RPCQuestionDetail::SetValueQ(_) => self.process_set_value_q(msg).await,
RPCQuestionDetail::WatchValueQ(_) => self.process_watch_value_q(msg).await,
RPCQuestionDetail::InspectValueQ(_) => self.process_inspect_value_q(msg).await,
#[cfg(feature = "unstable-blockstore")]
RPCQuestionDetail::SupplyBlockQ(_) => self.process_supply_block_q(msg).await,
#[cfg(feature = "unstable-blockstore")]

View File

@ -0,0 +1,266 @@
use super::*;
use crate::storage_manager::SignedValueDescriptor;
#[derive(Clone, Debug)]
pub struct InspectValueAnswer {
pub seqs: Vec<ValueSeqNum>,
pub peers: Vec<PeerInfo>,
pub descriptor: Option<SignedValueDescriptor>,
}
impl RPCProcessor {
/// Sends an inspect value request and wait for response
/// Can be sent via all methods including relays
/// Safety routes may be used, but never private routes.
/// 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.
#[cfg_attr(
feature = "verbose-tracing",
instrument(level = "trace", skip(self, last_descriptor),
fields(ret.value.data.len,
ret.seqs,
ret.peers.len,
ret.latency
),err)
)]
pub async fn rpc_call_inspect_value(
self,
dest: Destination,
key: TypedKey,
subkeys: ValueSubkeyRangeSet,
last_descriptor: Option<SignedValueDescriptor>,
) ->RPCNetworkResult<Answer<InspectValueAnswer>> {
// Ensure destination never has a private route
// and get the target noderef so we can validate the response
let Some(target) = dest.node() else {
return Err(RPCError::internal(
"Never send get 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"));
};
let debug_string = format!(
"OUT ==> InspectValueQ({} #{}{}) => {}",
key,
&subkeys,
if last_descriptor.is_some() {
" +lastdesc"
} else {
""
},
dest
);
// Send the inspectvalue question
let inspect_value_q = RPCOperationInspectValueQ::new(key, subkeys.clone(), last_descriptor.is_none())?;
let question = RPCQuestion::new(
network_result_try!(self.get_destination_respond_to(&dest)?),
RPCQuestionDetail::InspectValueQ(Box::new(inspect_value_q)),
);
let question_context = QuestionContext::InspectValue(ValidateInspectValueContext {
last_descriptor,
subkeys,
vcrypto: vcrypto.clone(),
});
log_dht!(debug "{}", debug_string);
let waitable_reply = network_result_try!(
self.question(dest.clone(), question, Some(question_context))
.await?
);
// Keep the reply private route that was used to return with the answer
let reply_private_route = waitable_reply.reply_private_route;
// Wait for reply
let (msg, latency) = match self.wait_for_reply(waitable_reply, debug_string).await? {
TimeoutOr::Timeout => return Ok(NetworkResult::Timeout),
TimeoutOr::Value(v) => v,
};
// Get the right answer type
let (_, _, _, kind) = msg.operation.destructure();
let inspect_value_a = match kind {
RPCOperationKind::Answer(a) => match a.destructure() {
RPCAnswerDetail::InspectValueA(a) => a,
_ => return Ok(NetworkResult::invalid_message("not an inspectvalue answer")),
},
_ => return Ok(NetworkResult::invalid_message("not an answer")),
};
let (seqs, peers, descriptor) = inspect_value_a.destructure();
if debug_target_enabled!("dht") {
let debug_string_answer = format!(
"OUT <== InspectValueA({} {:?}{} peers={}) <= {}",
key,
seqs,
if descriptor.is_some() {
" +desc"
} else {
""
},
peers.len(),
dest
);
log_dht!(debug "{}", debug_string_answer);
let peer_ids:Vec<String> = peers.iter().filter_map(|p| p.node_ids().get(key.kind).map(|k| k.to_string())).collect();
log_dht!(debug "Peers: {:#?}", peer_ids);
}
// Validate peers returned are, in fact, closer to the key than the node we sent this to
let valid = match RoutingTable::verify_peers_closer(vcrypto, target_node_id, key, &peers) {
Ok(v) => v,
Err(e) => {
return Ok(NetworkResult::invalid_message(format!(
"missing cryptosystem in peers node ids: {}",
e
)));
}
};
if !valid {
return Ok(NetworkResult::invalid_message("non-closer peers returned"));
}
#[cfg(feature = "verbose-tracing")]
tracing::Span::current().record("ret.latency", latency.as_u64());
#[cfg(feature = "verbose-tracing")]
tracing::Span::current().record("ret.seqs", seqs);
#[cfg(feature = "verbose-tracing")]
tracing::Span::current().record("ret.peers.len", peers.len());
Ok(NetworkResult::value(Answer::new(
latency,
reply_private_route,
InspectValueAnswer {
seqs,
peers,
descriptor,
},
)))
}
////////////////////////////////////////////////////////////////////////////////////////////////
#[cfg_attr(feature="verbose-tracing", instrument(level = "trace", skip(self, msg), fields(msg.operation.op_id), ret, err))]
pub(crate) async fn process_inspect_value_q(
&self,
msg: RPCMessage,
) -> RPCNetworkResult<()> {
// Ensure this never came over a private route, safety route is okay though
match &msg.header.detail {
RPCMessageHeaderDetail::Direct(_) | RPCMessageHeaderDetail::SafetyRouted(_) => {}
RPCMessageHeaderDetail::PrivateRouted(_) => {
return Ok(NetworkResult::invalid_message(
"not processing inspect value request over private route",
))
}
}
// Ignore if disabled
let routing_table = self.routing_table();
let opi = routing_table.get_own_peer_info(msg.header.routing_domain());
if !opi
.signed_node_info()
.node_info()
.has_capability(CAP_DHT)
{
return Ok(NetworkResult::service_unavailable(
"dht is not available",
));
}
// Get the question
let kind = msg.operation.kind().clone();
let inspect_value_q = match kind {
RPCOperationKind::Question(q) => match q.destructure() {
(_, RPCQuestionDetail::InspectValueQ(q)) => q,
_ => panic!("not a inspectvalue question"),
},
_ => panic!("not a question"),
};
// Destructure
let (key, subkeys, want_descriptor) = inspect_value_q.destructure();
// Get the nodes that we know about that are closer to the the key than our own node
let routing_table = self.routing_table();
let closer_to_key_peers = network_result_try!(routing_table.find_preferred_peers_closer_to_key(key, vec![CAP_DHT, CAP_DHT_WATCH]));
if debug_target_enabled!("dht") {
let debug_string = format!(
"IN <=== InspectValueQ({} {}{}) <== {}",
key,
subkeys,
if want_descriptor {
" +wantdesc"
} else {
""
},
msg.header.direct_sender_node_id()
);
log_dht!(debug "{}", debug_string);
}
// See if we would have accepted this as a set
let set_value_count = {
let c = self.config.get();
c.network.dht.set_value_count as usize
};
let (inspect_result_seqs, inspect_result_descriptor) = if closer_to_key_peers.len() >= set_value_count {
// Not close enough
(Vec::new(), None)
} else {
// Close enough, lets get it
// See if we have this record ourselves
let storage_manager = self.storage_manager();
let inspect_result = network_result_try!(storage_manager
.inbound_inspect_value(key, subkeys, want_descriptor)
.await
.map_err(RPCError::internal)?);
(inspect_result.seqs, inspect_result.descriptor)
};
if debug_target_enabled!("dht") {
let debug_string_answer = format!(
"IN ===> InspectValueA({} {:?}{} peers={}) ==> {}",
key,
inspect_result_seqs,
if inspect_result_descriptor.is_some() {
" +desc"
} else {
""
},
closer_to_key_peers.len(),
msg.header.direct_sender_node_id()
);
log_dht!(debug "{}", debug_string_answer);
}
// Make GetValue answer
let inspect_value_a = RPCOperationInspectValueA::new(
inspect_result_seqs,
closer_to_key_peers,
inspect_result_descriptor.map(|x| (*x).clone()),
)?;
// Send GetValue answer
self.answer(msg, RPCAnswer::new(RPCAnswerDetail::InspectValueA(Box::new(inspect_value_a))))
.await
}
}

View File

@ -0,0 +1,267 @@
use super::*;
/// The context of the outbound_get_value operation
struct OutboundGxxx continue here etValueContext {
/// The latest value of the subkey, may be the value passed in
pub value: Option<Arc<SignedValueData>>,
/// The nodes that have returned the value so far (up to the consensus count)
pub value_nodes: Vec<NodeRef>,
/// The descriptor if we got a fresh one or empty if no descriptor was needed
pub descriptor: Option<Arc<SignedValueDescriptor>>,
/// The parsed schema from the descriptor if we have one
pub schema: Option<DHTSchema>,
}
/// The result of the outbound_get_value operation
pub(super) struct OutboundGetValueResult {
/// The subkey that was retrieved
pub subkey_result: SubkeyResult,
/// And where it was retrieved from
pub value_nodes: Vec<NodeRef>,
}
impl StorageManager {
/// Perform a 'inspect value' query on the network
pub(super) async fn outbound_get_value(
&self,
rpc_processor: RPCProcessor,
key: TypedKey,
subkey: ValueSubkey,
safety_selection: SafetySelection,
last_subkey_result: SubkeyResult,
) -> VeilidAPIResult<OutboundGetValueResult> {
let routing_table = rpc_processor.routing_table();
// Get the DHT parameters for 'GetValue'
let (key_count, consensus_count, fanout, timeout_us) = {
let c = self.unlocked_inner.config.get();
(
c.network.dht.max_find_node_count as usize,
c.network.dht.get_value_count as usize,
c.network.dht.get_value_fanout as usize,
TimestampDuration::from(ms_to_us(c.network.dht.get_value_timeout_ms)),
)
};
// Make do-get-value answer context
let schema = if let Some(d) = &last_subkey_result.descriptor {
Some(d.schema()?)
} else {
None
};
let context = Arc::new(Mutex::new(OutboundGetValueContext {
value: last_subkey_result.value,
value_nodes: vec![],
descriptor: last_subkey_result.descriptor.clone(),
schema,
}));
// Routine to call to generate fanout
let call_routine = |next_node: NodeRef| {
let rpc_processor = rpc_processor.clone();
let context = context.clone();
let last_descriptor = last_subkey_result.descriptor.clone();
async move {
let gva = network_result_try!(
rpc_processor
.clone()
.rpc_call_get_value(
Destination::direct(next_node.clone()).with_safety(safety_selection),
key,
subkey,
last_descriptor.map(|x| (*x).clone()),
)
.await?
);
// Keep the descriptor if we got one. If we had a last_descriptor it will
// already be validated by rpc_call_get_value
if let Some(descriptor) = gva.answer.descriptor {
let mut ctx = context.lock();
if ctx.descriptor.is_none() && ctx.schema.is_none() {
ctx.schema = Some(descriptor.schema().map_err(RPCError::invalid_format)?);
ctx.descriptor = Some(Arc::new(descriptor));
}
}
// Keep the value if we got one and it is newer and it passes schema validation
if let Some(value) = gva.answer.value {
log_stor!(debug "Got value back: len={} seq={}", value.value_data().data().len(), value.value_data().seq());
let mut ctx = context.lock();
// Ensure we have a schema and descriptor
let (Some(descriptor), Some(schema)) = (&ctx.descriptor, &ctx.schema) else {
// Got a value but no descriptor for it
// Move to the next node
return Ok(NetworkResult::invalid_message(
"Got value with no descriptor",
));
};
// Validate with schema
if !schema.check_subkey_value_data(
descriptor.owner(),
subkey,
value.value_data(),
) {
// Validation failed, ignore this value
// Move to the next node
return Ok(NetworkResult::invalid_message(format!(
"Schema validation failed on subkey {}",
subkey
)));
}
// If we have a prior value, see if this is a newer sequence number
if let Some(prior_value) = &ctx.value {
let prior_seq = prior_value.value_data().seq();
let new_seq = value.value_data().seq();
if new_seq == prior_seq {
// If sequence number is the same, the data should be the same
if prior_value.value_data() != value.value_data() {
// Move to the next node
return Ok(NetworkResult::invalid_message("value data mismatch"));
}
// Increase the consensus count for the existing value
ctx.value_nodes.push(next_node);
} else if new_seq > prior_seq {
// If the sequence number is greater, start over with the new value
ctx.value = Some(Arc::new(value));
// One node has shown us this value so far
ctx.value_nodes = vec![next_node];
} else {
// If the sequence number is older, ignore it
}
} else {
// If we have no prior value, keep it
ctx.value = Some(Arc::new(value));
// One node has shown us this value so far
ctx.value_nodes = vec![next_node];
}
}
// Return peers if we have some
log_network_result!(debug "GetValue fanout call returned peers {}", gva.answer.peers.len());
Ok(NetworkResult::value(gva.answer.peers))
}
};
// Routine to call to check if we're done at each step
let check_done = |_closest_nodes: &[NodeRef]| {
// If we have reached sufficient consensus, return done
let ctx = context.lock();
if ctx.value.is_some()
&& ctx.descriptor.is_some()
&& ctx.value_nodes.len() >= consensus_count
{
return Some(());
}
None
};
// Call the fanout
let fanout_call = FanoutCall::new(
routing_table.clone(),
key,
key_count,
fanout,
timeout_us,
capability_fanout_node_info_filter(vec![CAP_DHT, CAP_DHT_WATCH]),
call_routine,
check_done,
);
match fanout_call.run(vec![]).await {
// If we don't finish in the timeout (too much time passed checking for consensus)
TimeoutOr::Timeout => {
// Return the best answer we've got
let ctx = context.lock();
if ctx.value_nodes.len() >= consensus_count {
log_stor!(debug "GetValue Fanout Timeout Consensus");
} else {
log_stor!(debug "GetValue Fanout Timeout Non-Consensus: {}", ctx.value_nodes.len());
}
Ok(OutboundGetValueResult {
subkey_result: SubkeyResult {
value: ctx.value.clone(),
descriptor: ctx.descriptor.clone(),
},
value_nodes: ctx.value_nodes.clone(),
})
}
// If we finished with consensus (enough nodes returning the same value)
TimeoutOr::Value(Ok(Some(()))) => {
// Return the best answer we've got
let ctx = context.lock();
if ctx.value_nodes.len() >= consensus_count {
log_stor!(debug "GetValue Fanout Consensus");
} else {
log_stor!(debug "GetValue Fanout Non-Consensus: {}", ctx.value_nodes.len());
}
Ok(OutboundGetValueResult {
subkey_result: SubkeyResult {
value: ctx.value.clone(),
descriptor: ctx.descriptor.clone(),
},
value_nodes: ctx.value_nodes.clone(),
})
}
// If we finished without consensus (ran out of nodes before getting consensus)
TimeoutOr::Value(Ok(None)) => {
// Return the best answer we've got
let ctx = context.lock();
if ctx.value_nodes.len() >= consensus_count {
log_stor!(debug "GetValue Fanout Exhausted Consensus");
} else {
log_stor!(debug "GetValue Fanout Exhausted Non-Consensus: {}", ctx.value_nodes.len());
}
Ok(OutboundGetValueResult {
subkey_result: SubkeyResult {
value: ctx.value.clone(),
descriptor: ctx.descriptor.clone(),
},
value_nodes: ctx.value_nodes.clone(),
})
}
// Failed
TimeoutOr::Value(Err(e)) => {
// If we finished with an error, return that
log_stor!(debug "GetValue Fanout Error: {}", e);
Err(e.into())
}
}
}
/// Handle a received 'Get Value' query
pub async fn inbound_get_value(
&self,
key: TypedKey,
subkey: ValueSubkey,
want_descriptor: bool,
) -> VeilidAPIResult<NetworkResult<SubkeyResult>> {
let mut inner = self.lock().await?;
// See if this is a remote or local value
let (_is_local, last_subkey_result) = {
// See if the subkey we are getting has a last known local value
let mut last_subkey_result = inner.handle_get_local_value(key, subkey, true).await?;
// If this is local, it must have a descriptor already
if last_subkey_result.descriptor.is_some() {
if !want_descriptor {
last_subkey_result.descriptor = None;
}
(true, last_subkey_result)
} else {
// See if the subkey we are getting has a last known remote value
let last_subkey_result = inner
.handle_get_remote_value(key, subkey, want_descriptor)
.await?;
(false, last_subkey_result)
}
};
Ok(NetworkResult::value(last_subkey_result))
}
}