From 67be63c91c54e3730f89887a7548670b7dda1ca4 Mon Sep 17 00:00:00 2001 From: Christien Rioux Date: Sun, 6 Jul 2025 18:55:17 -0400 Subject: [PATCH] Variable Length Keys --- Cargo.lock | 33 +- veilid-core/Cargo.toml | 23 +- .../examples/private_route/src/main.rs | 2 +- veilid-core/proto/veilid.capnp | 156 +- veilid-core/proto/veilid_capnp.rs | 3411 ++++---- veilid-core/src/crypto/crypto_system.rs | 86 +- veilid-core/src/crypto/dh_cache.rs | 6 +- veilid-core/src/crypto/envelope.rs | 100 +- veilid-core/src/crypto/guard.rs | 70 +- veilid-core/src/crypto/mod.rs | 41 +- veilid-core/src/crypto/none/mod.rs | 181 +- veilid-core/src/crypto/none/sizes.rs | 12 + veilid-core/src/crypto/receipt.rs | 24 +- veilid-core/src/crypto/tests/test_crypto.rs | 42 +- veilid-core/src/crypto/tests/test_types.rs | 79 +- .../src/crypto/types/byte_array_types.rs | 392 +- veilid-core/src/crypto/types/crypto_typed.rs | 80 +- .../src/crypto/types/crypto_typed_group.rs | 31 +- veilid-core/src/crypto/types/keypair.rs | 39 +- veilid-core/src/crypto/types/mod.rs | 24 +- veilid-core/src/crypto/vld0/mod.rs | 192 +- veilid-core/src/crypto/vld0/sizes.rs | 12 + .../src/network_manager/address_filter.rs | 4 +- .../bootstrap/bootstrap_record.rs | 10 +- veilid-core/src/network_manager/mod.rs | 33 +- .../src/network_manager/receipt_manager.rs | 2 +- veilid-core/src/network_manager/send_data.rs | 26 +- veilid-core/src/network_manager/stats.rs | 2 +- .../network_manager/tests/test_bootstrap.rs | 8 +- .../tests/test_signed_node_info.rs | 16 +- veilid-core/src/routing_table/bucket.rs | 14 +- veilid-core/src/routing_table/bucket_entry.rs | 6 +- veilid-core/src/routing_table/debug.rs | 2 +- veilid-core/src/routing_table/find_peers.rs | 57 +- veilid-core/src/routing_table/mod.rs | 84 +- veilid-core/src/routing_table/privacy.rs | 49 +- .../src/routing_table/route_spec_store/mod.rs | 227 +- .../remote_private_route_info.rs | 2 +- .../route_spec_store/route_set_spec_detail.rs | 30 +- .../route_spec_store_cache.rs | 76 +- .../route_spec_store_content.rs | 31 +- .../routing_table/routing_table_inner/mod.rs | 84 +- .../src/routing_table/tasks/bootstrap.rs | 4 +- .../src/routing_table/tasks/kick_buckets.rs | 6 +- .../tasks/private_route_management.rs | 28 +- .../tests/test_serialize_routing_table.rs | 2 +- .../types/signed_direct_node_info.rs | 2 +- .../types/signed_relayed_node_info.rs | 6 +- .../rpc_processor/coders/byte_array_types.rs | 72 + .../src/rpc_processor/coders/key256.rs | 40 - veilid-core/src/rpc_processor/coders/mod.rs | 12 +- veilid-core/src/rpc_processor/coders/nonce.rs | 31 - .../coders/operations/operation_find_node.rs | 4 +- .../coders/operations/operation_get_value.rs | 6 +- .../operations/operation_inspect_value.rs | 4 +- .../coders/operations/operation_route.rs | 17 +- .../coders/operations/operation_set_value.rs | 6 +- .../operations/operation_value_changed.rs | 4 +- .../operations/operation_watch_value.rs | 55 +- .../src/rpc_processor/coders/peer_info.rs | 4 +- .../coders/private_safety_route.rs | 32 +- .../src/rpc_processor/coders/signature512.rs | 52 - .../coders/signed_direct_node_info.rs | 4 +- .../coders/signed_relayed_node_info.rs | 8 +- .../rpc_processor/coders/signed_value_data.rs | 8 +- .../coders/signed_value_descriptor.rs | 8 +- .../src/rpc_processor/coders/typed_key.rs | 62 - .../rpc_processor/coders/typed_signature.rs | 23 - veilid-core/src/rpc_processor/destination.rs | 42 +- .../src/rpc_processor/fanout/fanout_call.rs | 14 +- .../src/rpc_processor/fanout/fanout_queue.rs | 2 +- .../src/rpc_processor/message_header.rs | 6 +- veilid-core/src/rpc_processor/mod.rs | 97 +- .../src/rpc_processor/rendered_operation.rs | 3 - veilid-core/src/rpc_processor/rpc_app_call.rs | 4 +- .../src/rpc_processor/rpc_app_message.rs | 2 +- .../src/rpc_processor/rpc_find_node.rs | 6 +- .../src/rpc_processor/rpc_get_value.rs | 38 +- .../src/rpc_processor/rpc_inspect_value.rs | 42 +- veilid-core/src/rpc_processor/rpc_route.rs | 116 +- .../src/rpc_processor/rpc_set_value.rs | 37 +- veilid-core/src/rpc_processor/rpc_status.rs | 2 +- .../rpc_processor/rpc_validate_dial_info.rs | 2 +- .../src/rpc_processor/rpc_value_changed.rs | 4 +- .../src/rpc_processor/rpc_watch_value.rs | 49 +- .../storage_manager/active_subkey_writes.rs | 5 +- veilid-core/src/storage_manager/debug.rs | 4 +- veilid-core/src/storage_manager/get_value.rs | 25 +- .../src/storage_manager/inspect_value.rs | 15 +- veilid-core/src/storage_manager/mod.rs | 289 +- .../storage_manager/offline_subkey_writes.rs | 8 +- .../outbound_watch_manager/mod.rs | 18 +- .../outbound_watch_parameters.rs | 2 +- .../outbound_watch_state.rs | 8 +- .../outbound_watch_manager/per_node_state.rs | 4 +- .../record_store/inbound_watch.rs | 2 +- .../src/storage_manager/record_store/keys.rs | 49 +- .../src/storage_manager/record_store/mod.rs | 256 +- .../record_store/opened_record.rs | 10 +- .../storage_manager/record_store/record.rs | 2 +- veilid-core/src/storage_manager/rehydrate.rs | 34 +- veilid-core/src/storage_manager/schema.rs | 160 + veilid-core/src/storage_manager/set_value.rs | 52 +- .../tasks/check_outbound_watches.rs | 3 +- .../tasks/offline_subkey_writes.rs | 31 +- .../tasks/rehydrate_records.rs | 2 +- .../types/signed_value_data.rs | 52 +- .../types/signed_value_descriptor.rs | 54 +- .../src/storage_manager/watch_value.rs | 131 +- veilid-core/src/table_store/mod.rs | 82 +- veilid-core/src/table_store/table_db.rs | 53 +- .../src/table_store/tests/test_table_store.rs | 12 +- veilid-core/src/tests/common/test_dht.rs | 152 +- veilid-core/src/veilid_api/api.rs | 54 +- veilid-core/src/veilid_api/debug.rs | 130 +- veilid-core/src/veilid_api/routing_context.rs | 95 +- .../src/veilid_api/serialize_helpers/mod.rs | 7 +- .../serialize_untyped_vld0.rs | 30 + veilid-core/src/veilid_api/tests/fixtures.rs | 65 +- veilid-core/src/veilid_api/tests/mod.rs | 2 +- .../src/veilid_api/tests/test_types.rs | 14 +- .../src/veilid_api/tests/test_types_dht.rs | 4 +- .../veilid_api/tests/test_types_dht_schema.rs | 10 +- .../src/veilid_api/types/app_message_call.rs | 12 +- .../types/dht/dht_record_descriptor.rs | 22 +- .../src/veilid_api/types/dht/schema/dflt.rs | 46 +- .../src/veilid_api/types/dht/schema/mod.rs | 21 +- .../src/veilid_api/types/dht/schema/smpl.rs | 111 +- .../types/dht/set_dht_value_options.rs | 4 +- .../src/veilid_api/types/dht/value_data.rs | 47 +- veilid-core/src/veilid_api/types/safety.rs | 6 +- .../src/veilid_api/types/veilid_state.rs | 4 +- .../example/integration_test/app_test.dart | 2 + .../example/integration_test/test_crypto.dart | 2 +- .../example/integration_test/test_dht.dart | 44 +- .../test_routing_context.dart | 10 +- veilid-flutter/example/pubspec.lock | 24 +- veilid-flutter/lib/routing_context.dart | 104 +- .../lib/routing_context.freezed.dart | 96 +- veilid-flutter/lib/routing_context.g.dart | 23 +- veilid-flutter/lib/veilid.dart | 7 +- veilid-flutter/lib/veilid_config.g.dart | 6 +- veilid-flutter/lib/veilid_crypto.dart | 137 +- veilid-flutter/lib/veilid_encoding.dart | 268 +- veilid-flutter/lib/veilid_ffi.dart | 413 +- veilid-flutter/lib/veilid_js.dart | 130 +- veilid-flutter/lib/veilid_state.g.dart | 8 +- .../packages/veilid_test/pubspec.yaml | 2 +- veilid-flutter/pubspec.yaml | 1 + veilid-flutter/rust/src/dart_ffi.rs | 407 +- veilid-python/tests/test_dht.py | 182 +- veilid-python/tests/test_routing_context.py | 10 +- veilid-python/veilid/api.py | 95 +- veilid-python/veilid/json_api.py | 247 +- veilid-python/veilid/operations.py | 16 +- veilid-python/veilid/schema/RecvMessage.json | 7378 +++++++++-------- veilid-python/veilid/schema/Request.json | 3164 +++---- veilid-python/veilid/types.py | 197 +- veilid-remote-api/Cargo.toml | 2 +- veilid-remote-api/src/crypto_system.rs | 86 +- veilid-remote-api/src/lib.rs | 15 +- veilid-remote-api/src/process.rs | 90 +- veilid-remote-api/src/routing_context.rs | 18 +- veilid-server/src/main.rs | 9 +- veilid-server/src/server.rs | 11 +- veilid-wasm/src/lib.rs | 340 +- veilid-wasm/src/veilid_client_js.rs | 83 + veilid-wasm/src/veilid_crypto_js.rs | 342 +- veilid-wasm/src/veilid_routing_context_js.rs | 117 +- .../tests/src/VeilidRoutingContext.test.ts | 4 +- veilid-wasm/tests/src/veilidCrypto.test.ts | 54 +- 171 files changed, 12847 insertions(+), 10261 deletions(-) create mode 100644 veilid-core/src/crypto/none/sizes.rs create mode 100644 veilid-core/src/crypto/vld0/sizes.rs create mode 100644 veilid-core/src/rpc_processor/coders/byte_array_types.rs delete mode 100644 veilid-core/src/rpc_processor/coders/key256.rs delete mode 100644 veilid-core/src/rpc_processor/coders/nonce.rs delete mode 100644 veilid-core/src/rpc_processor/coders/signature512.rs delete mode 100644 veilid-core/src/rpc_processor/coders/typed_key.rs delete mode 100644 veilid-core/src/rpc_processor/coders/typed_signature.rs create mode 100644 veilid-core/src/storage_manager/schema.rs create mode 100644 veilid-core/src/veilid_api/serialize_helpers/serialize_untyped_vld0.rs diff --git a/Cargo.lock b/Cargo.lock index e99e9846..9e66dd95 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -870,6 +870,9 @@ name = "bytes" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +dependencies = [ + "serde", +] [[package]] name = "capnp" @@ -4574,6 +4577,26 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "ref-cast" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "regex" version = "1.11.1" @@ -4890,11 +4913,12 @@ dependencies = [ [[package]] name = "schemars" -version = "0.8.22" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" +checksum = "1375ba8ef45a6f15d83fa8748f1079428295d403d6ea991d09ab100155fbc06d" dependencies = [ "dyn-clone", + "ref-cast", "schemars_derive", "serde", "serde_json", @@ -4902,9 +4926,9 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.22" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" +checksum = "2b13ed22d6d49fe23712e068770b5c4df4a693a2b02eeff8e7ca3135627a24f6" dependencies = [ "proc-macro2", "quote", @@ -6412,6 +6436,7 @@ dependencies = [ "backtrace", "blake3", "bosion", + "bytes 1.10.1", "capnp", "capnpc", "cfg-if 1.0.0", diff --git a/veilid-core/Cargo.toml b/veilid-core/Cargo.toml index a2a4ebce..1a6fa3ba 100644 --- a/veilid-core/Cargo.toml +++ b/veilid-core/Cargo.toml @@ -45,8 +45,22 @@ rt-tokio = [ ] # Crypto support features -enable-crypto-vld0 = [ "ed25519-dalek", "x25519-dalek", "curve25519-dalek", "blake3", "chacha20poly1305", "chacha20", "argon2" ] -enable-crypto-none = [ "ed25519-dalek", "curve25519-dalek", "blake3", "argon2", "digest" ] +enable-crypto-vld0 = [ + "ed25519-dalek", + "x25519-dalek", + "curve25519-dalek", + "blake3", + "chacha20poly1305", + "chacha20", + "argon2", +] +enable-crypto-none = [ + "ed25519-dalek", + "curve25519-dalek", + "blake3", + "argon2", + "digest", +] # Debugging and testing features verbose-tracing = [] @@ -134,7 +148,7 @@ blake3 = { version = "1.8.2", optional = true } chacha20poly1305 = { version = "0.10.1", optional = true } chacha20 = { version = "0.9.1", optional = true } argon2 = { version = "0.5.3", optional = true } -digest = { version = "0.10.7", optional = true, features = [ "rand_core" ]} +digest = { version = "0.10.7", optional = true, features = ["rand_core"] } # Network async-std-resolver = { version = "0.24.4", optional = true } @@ -147,7 +161,7 @@ serde_json = { version = "1.0.140" } serde-big-array = "0.5.1" json = "0.12.4" data-encoding = { version = "2.8.0" } -schemars = "0.8.22" +schemars = "1.0.3" lz4_flex = { version = "0.11.3", default-features = false, features = [ "safe-encode", "safe-decode", @@ -155,6 +169,7 @@ lz4_flex = { version = "0.11.3", default-features = false, features = [ indent = "0.1.1" sanitize-filename = "0.5.0" serde_with = "3.12.0" +bytes = { version = "1.10.1", features = ["serde"] } # Dependencies for native builds only # Linux, Windows, Mac, iOS, Android diff --git a/veilid-core/examples/private_route/src/main.rs b/veilid-core/examples/private_route/src/main.rs index 6c6cafb2..52bf8565 100644 --- a/veilid-core/examples/private_route/src/main.rs +++ b/veilid-core/examples/private_route/src/main.rs @@ -233,7 +233,7 @@ async fn open_route( if val.is_empty() { break; } - try_again_loop(|| async { rc.app_message(Target::PrivateRoute(route_id), val.as_bytes().to_vec()).await }) + try_again_loop(|| async { rc.app_message(Target::RouteId(route_id.clone()), val.as_bytes().to_vec()).await }) .await?; } else { break; diff --git a/veilid-core/proto/veilid.capnp b/veilid-core/proto/veilid.capnp index 170e5365..8725bd05 100644 --- a/veilid-core/proto/veilid.capnp +++ b/veilid-core/proto/veilid.capnp @@ -1,50 +1,59 @@ @0x8ffce8033734ab02; -# IDs And Hashes +# Typed IDs and Hashes ############################## -struct Key256 @0xdde44e3286f6a90d { - u0 @0 :UInt64; - u1 @1 :UInt64; - u2 @2 :UInt64; - u3 @3 :UInt64; +# DHT Record Key +struct RecordKey @0xcd55475a98deb0c1 { + kind @0 :CryptoKind; + value @1 :Data; } -struct Signature512 @0x806749043a129c12 { - u0 @0 :UInt64; - u1 @1 :UInt64; - u2 @2 :UInt64; - u3 @3 :UInt64; - u4 @4 :UInt64; - u5 @5 :UInt64; - u6 @6 :UInt64; - u7 @7 :UInt64; +# Blockstore Block Id +struct BlockId @0xed3678a9e4771a22 { + kind @0 :CryptoKind; + value @1 :Data; } -struct Nonce24 @0xb6260db25d8d7dfc { - u0 @0 :UInt64; - u1 @1 :UInt64; - u2 @2 :UInt64; +# Node Id (hash of node public key) +struct NodeId @0xce9822f1cebca1bb { + kind @0 :CryptoKind; + value @1 :Data; } -using PublicKey = Key256; # Node id / Hash / DHT key / Route id, etc -using Nonce = Nonce24; # One-time encryption nonce -using Signature = Signature512; # Signature block -using TunnelID = UInt64; # Id for tunnels +# Public Key +struct PublicKey @0xfc522f2dbdf30cee { + kind @0 :CryptoKind; + value @1 :Data; +} + +# DHT Route Id +struct RouteId @0xc8ae026d91da0ae6 { + kind @0 :CryptoKind; + value @1 :Data; +} + +# Signature +struct Signature @0xf06fa6e2ac8726a2 { + kind @0 :CryptoKind; + value @1 :Data; +} + +# Untyped generic one-time encryption nonce +struct Nonce @0x9b00866db77b59f6 { + value @0 :Data; +} + + +# Convenience Typedefs +################################################################ + +using TunnelId = UInt64; # Id for tunnels using CryptoKind = UInt32; # FOURCC code for cryptography type using ValueSeqNum = UInt32; # sequence numbers for values using Subkey = UInt32; # subkey index for dht using Capability = UInt32; # FOURCC code for capability -struct TypedKey @0xe2d567a9f1e61b29 { - kind @0 :CryptoKind; - key @1 :PublicKey; -} - -struct TypedSignature @0x963170c7298e3884 { - kind @0 :CryptoKind; - signature @1 :Signature; -} # Node Dial Info ################################################################ @@ -122,7 +131,7 @@ struct SignalInfoReverseConnect @0xd9ebd3bd0d46e013 { # Private Routes ############################## -struct RouteHopData @0x8ce231f9d1b7adf2 { +struct RouteHopData @0x9d45cb1880e79fdb { nonce @0 :Nonce; # nonce for encrypted blob blob @1 :Data; # encrypted blob with ENC(nonce,DH(PK,SK)) # if this is a safety route RouteHopData, there is a single byte tag appended to the end of the encrypted blob @@ -134,7 +143,7 @@ struct RouteHopData @0x8ce231f9d1b7adf2 { struct RouteHop @0xf8f672d75cce0c3b { node :union { - nodeId @0 :PublicKey; # node id key only for established routes (kind is the same as the pr or sr it is part of) + nodeId @0 :NodeId; # node id key only for established routes (kind is the same as the pr or sr it is part of) peerInfo @1 :PeerInfo; # full peer info for this hop to establish the route } nextHop @2 :RouteHopData; # optional: If this the end of a private route, this field will not exist @@ -142,21 +151,19 @@ struct RouteHop @0xf8f672d75cce0c3b { } struct PrivateRoute @0x8a83fccb0851e776 { - publicKey @0 :TypedKey; # private route public key (unique per private route) - hopCount @1 :UInt8; # Count of hops left in the private route (for timeout calculation purposes only) + publicKey @0 :PublicKey; # private route public key (unique per private route) hops :union { - firstHop @2 :RouteHop; # first hop of a private route is unencrypted (hopcount > 0) - data @3 :RouteHopData; # private route has more hops (hopcount > 0 && hopcount < total_hopcount) - empty @4 :Void; # private route has ended (hopcount = 0) + firstHop @1 :RouteHop; # first hop of a private route is unencrypted (hopcount > 0) + data @2 :RouteHopData; # private route has more hops (hopcount > 0 && hopcount < total_hopcount) + empty @3 :Void; # private route has ended (hopcount = 0) } } struct SafetyRoute @0xf554734d07cb5d59 { - publicKey @0 :TypedKey; # safety route public key (unique per safety route) - hopCount @1 :UInt8; # Count of hops left in the safety route (for timeout calculation purposes only) + publicKey @0 :PublicKey; # safety route public key (unique per safety route) hops :union { - data @2 :RouteHopData; # safety route has more hops - private @3 :PrivateRoute; # safety route has ended and private route follows + data @1 :RouteHopData; # safety route has more hops + private @2 :PrivateRoute; # safety route has ended and private route follows } } @@ -220,18 +227,18 @@ struct NodeInfo @0xe125d847e3f9f419 { dialInfoDetailList @6 :List(DialInfoDetail); # inbound dial info details for this node } -struct SignedDirectNodeInfo @0xe0e7ea3e893a3dd7 { +struct SignedDirectNodeInfo @0xa70f85e77dafc0cd { nodeInfo @0 :NodeInfo; # node info timestamp @1 :UInt64; # when signed node info was generated - signatures @2 :List(TypedSignature); # signatures + signatures @2 :List(Signature); # signatures } -struct SignedRelayedNodeInfo @0xb39e8428ccd87cbb { +struct SignedRelayedNodeInfo @0x8b193d500b11573f { nodeInfo @0 :NodeInfo; # node info - relayIds @1 :List(TypedKey); # node ids for relay + relayIds @1 :List(NodeId); # node ids for relay relayInfo @2 :SignedDirectNodeInfo; # signed node info for relay timestamp @3 :UInt64; # when signed node info was generated - signatures @4 :List(TypedSignature); # signatures + signatures @4 :List(Signature); # signatures } struct SignedNodeInfo @0xd2478ce5f593406a { @@ -241,12 +248,12 @@ struct SignedNodeInfo @0xd2478ce5f593406a { } } -struct PeerInfo @0xfe2d722d5d3c4bcb { - nodeIds @0 :List(TypedKey); # node ids for 'closer peer' +struct PeerInfo @0xb33ceb3dd583dbf7 { + nodeIds @0 :List(NodeId); # node ids for 'closer peer' signedNodeInfo @1 :SignedNodeInfo; # signed node info for 'closer peer' } -struct RoutedOperation @0xcbcb8535b839e9dd { +struct RoutedOperation @0xa074e6662fe5aa92 { sequencing @0 :Sequencing; # sequencing preference to use to pass the message along signatures @1 :List(Signature); # signatures from nodes that have handled the private route nonce @2 :Nonce; # nonce Xmsg @@ -272,8 +279,8 @@ struct OperationReturnReceipt @0xeb0fb5b5a9160eeb { receipt @0 :Data; # receipt being returned to its origin } -struct OperationFindNodeQ @0xfdef788fe9623bcd { - nodeId @0 :TypedKey; # node id to locate +struct OperationFindNodeQ @0xca524d602e9d86ca { + nodeId @0 :NodeId; # node id to locate capabilities @1 :List(Capability); # required capabilities returned peers must have } @@ -303,13 +310,13 @@ struct SubkeyRange @0xf592dac0a4d0171c { end @1 :Subkey; # the end of a subkey range } -struct SignedValueData @0xb4b7416f169f2a3d { +struct SignedValueData @0xff3944efaaf7fc18 { seq @0 :ValueSeqNum; # sequence number of value data @1 :Data; # value or subvalue contents writer @2 :PublicKey; # the public key of the writer signature @3 :Signature; # signature of data at this subkey, using the writer key (which may be the same as the owner key) # signature covers: - # * ownerKey + # * owner public key # * subkey # * sequence number # * data @@ -325,8 +332,8 @@ struct SignedValueDescriptor @0xe7911cd3f9e1b0e7 { } -struct OperationGetValueQ @0xf88a5b6da5eda5d0 { - key @0 :TypedKey; # DHT Key = Hash(ownerKeyKind) of: [ ownerKeyValue, schema ] +struct OperationGetValueQ @0x8c176d26517ea24d { + key @0 :RecordKey; # DHT Key = Hash(ownerKeyKind) of: [ ownerKeyValue, schema ] subkey @1 :Subkey; # the index of the subkey wantDescriptor @2 :Bool; # whether or not to include the descriptor for the key } @@ -339,7 +346,7 @@ struct OperationGetValueA @0xd896bb46f2e0249f { } struct OperationSetValueQ @0xbac06191ff8bdbc5 { - key @0 :TypedKey; # DHT Key = Hash(ownerKeyKind) of: [ ownerKeyValue, schema ] + key @0 :RecordKey; # DHT Key = Hash(ownerKeyKind) of: [ ownerKeyValue, schema ] subkey @1 :Subkey; # the index of the subkey value @2 :SignedValueData; # value or subvalue contents (older or equal seq number gets dropped) descriptor @3 :SignedValueDescriptor; # optional: the descriptor if needed @@ -352,7 +359,7 @@ struct OperationSetValueA @0x9378d0732dc95be2 { } struct OperationWatchValueQ @0xf9a5a6c547b9b228 { - key @0 :TypedKey; # key for value to watch + key @0 :RecordKey; # key for value to watch subkeys @1 :List(SubkeyRange); # subkey range to watch (up to 512 subranges). An empty range here should not be specified unless cancelling a watch (count=0). expiration @2 :UInt64; # requested timestamp when this watch will expire in usec since epoch (watch can return less, 0 for max) count @3 :UInt32; # requested number of changes to watch for (0 = cancel, 1 = single shot, 2+ = counter, UINT32_MAX = continuous) @@ -369,7 +376,7 @@ struct OperationWatchValueA @0xa726cab7064ba893 { } struct OperationInspectValueQ @0xdef712d2fd16f55a { - key @0 :TypedKey; # DHT Key = Hash(ownerKeyKind) of: [ ownerKeyValue, schema ] + key @0 :RecordKey; # 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 } @@ -381,7 +388,7 @@ struct OperationInspectValueA @0xb8b57faf960ee102 { } struct OperationValueChanged @0xd1c59ebdd8cc1bf6 { - key @0 :TypedKey; # key for value that changed + key @0 :RecordKey; # 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) count @2 :UInt32; # remaining changes left (0 means watch has expired) watchId @3 :UInt64; # watch id this value change came from @@ -389,7 +396,8 @@ struct OperationValueChanged @0xd1c59ebdd8cc1bf6 { } struct OperationSupplyBlockQ @0xadbf4c542d749971 { - blockId @0 :TypedKey; # hash of the block we can supply + blockId @0 :BlockId; # hash of the block we can supply + routeId @1 :RouteId; # the private route endpoint for this block supplier } struct OperationSupplyBlockA @0xf003822e83b5c0d7 { @@ -398,13 +406,13 @@ struct OperationSupplyBlockA @0xf003822e83b5c0d7 { } struct OperationFindBlockQ @0xaf4353ff004c7156 { - blockId @0 :TypedKey; # hash of the block to locate + blockId @0 :BlockId; # hash of the block to locate } struct OperationFindBlockA @0xc51455bc4915465d { data @0 :Data; # Optional: the actual block data if we have that block ourselves # null if we don't have a block to return - suppliers @1 :List(PeerInfo); # returned list of suppliers if we have them + suppliers @1 :List(RouteId); # returned list of supplier private route ids if we have them peers @2 :List(PeerInfo); # returned 'closer peer' information } @@ -429,24 +437,24 @@ enum TunnelError @0xb82c6bfb1ec38c7c { struct TunnelEndpoint @0xc2602aa983cc337d { mode @0 :TunnelEndpointMode; # what kind of endpoint this is - description @1 :Text; # endpoint description (TODO) + description @1 :Data; # endpoint description (TODO) } struct FullTunnel @0x9821c3dc75373f63 { - id @0 :TunnelID; # tunnel id to use everywhere + id @0 :TunnelId; # tunnel id to use everywhere timeout @1 :UInt64; # duration from last data when this expires if no data is sent or received local @2 :TunnelEndpoint; # local endpoint remote @3 :TunnelEndpoint; # remote endpoint } struct PartialTunnel @0x827a7ebc02be2fc8 { - id @0 :TunnelID; # tunnel id to use everywhere + id @0 :TunnelId; # tunnel id to use everywhere timeout @1 :UInt64; # timestamp when this expires if not completed local @2 :TunnelEndpoint; # local endpoint } struct OperationStartTunnelQ @0xa9c49afce44187af { - id @0 :TunnelID; # tunnel id to use everywhere + id @0 :TunnelId; # tunnel id to use everywhere localMode @1 :TunnelEndpointMode; # what kind of local endpoint mode is being requested depth @2 :UInt8; # the number of nodes in the tunnel } @@ -459,7 +467,7 @@ struct OperationStartTunnelA @0x818162e4cc61bf1e { } struct OperationCompleteTunnelQ @0xe978594588eb950b { - id @0 :TunnelID; # tunnel id to use everywhere + id @0 :TunnelId; # tunnel id to use everywhere localMode @1 :TunnelEndpointMode; # what kind of local endpoint mode is being requested depth @2 :UInt8; # the number of nodes in the tunnel endpoint @3 :TunnelEndpoint; # the remote endpoint to complete @@ -473,12 +481,12 @@ struct OperationCompleteTunnelA @0x84090791bb765f2a { } struct OperationCancelTunnelQ @0xae2811ae0a003738 { - id @0 :TunnelID; # the tunnel id to cancel + id @0 :TunnelId; # the tunnel id to cancel } struct OperationCancelTunnelA @0xbba23c992eff97bc { union { - tunnel @0 :TunnelID; # the tunnel id that was cancelled + tunnel @0 :TunnelId; # the tunnel id that was cancelled error @1 :TunnelError; # if we couldn't cancel, why not } } @@ -501,6 +509,7 @@ struct Question @0xd8510bc33492ef70 { watchValueQ @7 :OperationWatchValueQ; inspectValueQ @8 :OperationInspectValueQ; + # Blockstore operations # #[cfg(feature="unstable-blockstore")] # supplyBlockQ @9 :OperationSupplyBlockQ; # findBlockQ @10 :OperationFindBlockQ; @@ -542,9 +551,10 @@ struct Answer @0xacacb8b6988c1058 { watchValueA @5 :OperationWatchValueA; inspectValueA @6 :OperationInspectValueA; + # Blockstore operations # #[cfg(feature="unstable-blockstore")] - #supplyBlockA @7 :OperationSupplyBlockA; - #findBlockA @8 :OperationFindBlockA; + # supplyBlockA @7 :OperationSupplyBlockA; + # findBlockA @8 :OperationFindBlockA; # Tunnel operations # #[cfg(feature="unstable-tunnels")] diff --git a/veilid-core/proto/veilid_capnp.rs b/veilid-core/proto/veilid_capnp.rs index 103ffe5f..e55399b0 100644 --- a/veilid-core/proto/veilid_capnp.rs +++ b/veilid-core/proto/veilid_capnp.rs @@ -3,931 +3,7 @@ // source: proto/veilid.capnp -pub mod key256 { - #[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 <> ::core::marker::Copy for Reader<'_,> {} - impl <> ::core::clone::Clone for Reader<'_,> { - fn clone(&self) -> Self { *self } - } - - impl <> ::capnp::traits::HasTypeId for Reader<'_,> { - 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> 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 <> ::core::fmt::Debug for Reader<'_,> { - 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 { - ::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 <> Reader<'_,> { - pub fn reborrow(&self) -> Reader<'_,> { - Self { .. *self } - } - - pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { - self.reader.total_size() - } - #[inline] - pub fn get_u0(self) -> u64 { - self.reader.get_data_field::(0) - } - #[inline] - pub fn get_u1(self) -> u64 { - self.reader.get_data_field::(1) - } - #[inline] - pub fn get_u2(self) -> u64 { - self.reader.get_data_field::(2) - } - #[inline] - pub fn get_u3(self) -> u64 { - self.reader.get_data_field::(3) - } - } - - pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } - impl <> ::capnp::traits::HasStructSize for Builder<'_,> { - const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 4, pointers: 0 }; - } - impl <> ::capnp::traits::HasTypeId for Builder<'_,> { - 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> 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(::STRUCT_SIZE).into() - } - fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { - ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) - } - } - - impl <> ::capnp::traits::SetterInput> for Reader<'_,> { - 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_u0(self) -> u64 { - self.builder.get_data_field::(0) - } - #[inline] - pub fn set_u0(&mut self, value: u64) { - self.builder.set_data_field::(0, value); - } - #[inline] - pub fn get_u1(self) -> u64 { - self.builder.get_data_field::(1) - } - #[inline] - pub fn set_u1(&mut self, value: u64) { - self.builder.set_data_field::(1, value); - } - #[inline] - pub fn get_u2(self) -> u64 { - self.builder.get_data_field::(2) - } - #[inline] - pub fn set_u2(&mut self, value: u64) { - self.builder.set_data_field::(2, value); - } - #[inline] - pub fn get_u3(self) -> u64 { - self.builder.get_data_field::(3) - } - #[inline] - pub fn set_u3(&mut self, value: u64) { - self.builder.set_data_field::(3, 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 { - } - mod _private { - pub static ENCODED_NODE: [::capnp::Word; 79] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), - ::capnp::word(13, 169, 246, 134, 50, 78, 228, 221), - ::capnp::word(19, 0, 0, 0, 1, 0, 4, 0), - ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), - ::capnp::word(0, 0, 7, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(71, 0, 0, 0, 16, 1, 0, 0), - ::capnp::word(21, 0, 0, 0, 210, 0, 0, 0), - ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(29, 0, 0, 0, 231, 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, 75, 101, 121, 50, 53), - ::capnp::word(54, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), - ::capnp::word(16, 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(97, 0, 0, 0, 26, 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(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(101, 0, 0, 0, 26, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(96, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(108, 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(105, 0, 0, 0, 26, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(100, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(112, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(3, 0, 0, 0, 3, 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(109, 0, 0, 0, 26, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(104, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(116, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(117, 48, 0, 0, 0, 0, 0, 0), - ::capnp::word(9, 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(9, 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(117, 49, 0, 0, 0, 0, 0, 0), - ::capnp::word(9, 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(9, 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(117, 50, 0, 0, 0, 0, 0, 0), - ::capnp::word(9, 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(9, 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(117, 51, 0, 0, 0, 0, 0, 0), - ::capnp::word(9, 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(9, 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 => ::introspect(), - 1 => ::introspect(), - 2 => ::introspect(), - 3 => ::introspect(), - _ => panic!("invalid field index {}", index), - } - } - pub fn get_annotation_types(child_index: Option, 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, - members_by_name: MEMBERS_BY_NAME, - }; - pub static NONUNION_MEMBERS : &[u16] = &[0,1,2,3]; - pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; - pub static MEMBERS_BY_NAME : &[u16] = &[0,1,2,3]; - pub const TYPE_ID: u64 = 0xdde4_4e32_86f6_a90d; - } -} - -pub mod signature512 { - #[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 <> ::core::marker::Copy for Reader<'_,> {} - impl <> ::core::clone::Clone for Reader<'_,> { - fn clone(&self) -> Self { *self } - } - - impl <> ::capnp::traits::HasTypeId for Reader<'_,> { - 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> 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 <> ::core::fmt::Debug for Reader<'_,> { - 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 { - ::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 <> Reader<'_,> { - pub fn reborrow(&self) -> Reader<'_,> { - Self { .. *self } - } - - pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { - self.reader.total_size() - } - #[inline] - pub fn get_u0(self) -> u64 { - self.reader.get_data_field::(0) - } - #[inline] - pub fn get_u1(self) -> u64 { - self.reader.get_data_field::(1) - } - #[inline] - pub fn get_u2(self) -> u64 { - self.reader.get_data_field::(2) - } - #[inline] - pub fn get_u3(self) -> u64 { - self.reader.get_data_field::(3) - } - #[inline] - pub fn get_u4(self) -> u64 { - self.reader.get_data_field::(4) - } - #[inline] - pub fn get_u5(self) -> u64 { - self.reader.get_data_field::(5) - } - #[inline] - pub fn get_u6(self) -> u64 { - self.reader.get_data_field::(6) - } - #[inline] - pub fn get_u7(self) -> u64 { - self.reader.get_data_field::(7) - } - } - - pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } - impl <> ::capnp::traits::HasStructSize for Builder<'_,> { - const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 8, pointers: 0 }; - } - impl <> ::capnp::traits::HasTypeId for Builder<'_,> { - 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> 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(::STRUCT_SIZE).into() - } - fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { - ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) - } - } - - impl <> ::capnp::traits::SetterInput> for Reader<'_,> { - 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_u0(self) -> u64 { - self.builder.get_data_field::(0) - } - #[inline] - pub fn set_u0(&mut self, value: u64) { - self.builder.set_data_field::(0, value); - } - #[inline] - pub fn get_u1(self) -> u64 { - self.builder.get_data_field::(1) - } - #[inline] - pub fn set_u1(&mut self, value: u64) { - self.builder.set_data_field::(1, value); - } - #[inline] - pub fn get_u2(self) -> u64 { - self.builder.get_data_field::(2) - } - #[inline] - pub fn set_u2(&mut self, value: u64) { - self.builder.set_data_field::(2, value); - } - #[inline] - pub fn get_u3(self) -> u64 { - self.builder.get_data_field::(3) - } - #[inline] - pub fn set_u3(&mut self, value: u64) { - self.builder.set_data_field::(3, value); - } - #[inline] - pub fn get_u4(self) -> u64 { - self.builder.get_data_field::(4) - } - #[inline] - pub fn set_u4(&mut self, value: u64) { - self.builder.set_data_field::(4, value); - } - #[inline] - pub fn get_u5(self) -> u64 { - self.builder.get_data_field::(5) - } - #[inline] - pub fn set_u5(&mut self, value: u64) { - self.builder.set_data_field::(5, value); - } - #[inline] - pub fn get_u6(self) -> u64 { - self.builder.get_data_field::(6) - } - #[inline] - pub fn set_u6(&mut self, value: u64) { - self.builder.set_data_field::(6, value); - } - #[inline] - pub fn get_u7(self) -> u64 { - self.builder.get_data_field::(7) - } - #[inline] - pub fn set_u7(&mut self, value: u64) { - self.builder.set_data_field::(7, 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 { - } - mod _private { - pub static ENCODED_NODE: [::capnp::Word; 139] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), - ::capnp::word(18, 156, 18, 58, 4, 73, 103, 128), - ::capnp::word(19, 0, 0, 0, 1, 0, 8, 0), - ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), - ::capnp::word(0, 0, 7, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(18, 1, 0, 0, 133, 2, 0, 0), - ::capnp::word(21, 0, 0, 0, 2, 1, 0, 0), - ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(29, 0, 0, 0, 199, 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), - ::capnp::word(105, 108, 105, 100, 46, 99, 97, 112), - ::capnp::word(110, 112, 58, 83, 105, 103, 110, 97), - ::capnp::word(116, 117, 114, 101, 53, 49, 50, 0), - ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), - ::capnp::word(32, 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(209, 0, 0, 0, 26, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(204, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(216, 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(213, 0, 0, 0, 26, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(208, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(220, 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(217, 0, 0, 0, 26, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(212, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(224, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(3, 0, 0, 0, 3, 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(221, 0, 0, 0, 26, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(216, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(228, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(4, 0, 0, 0, 4, 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(225, 0, 0, 0, 26, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(220, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(232, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(5, 0, 0, 0, 5, 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(229, 0, 0, 0, 26, 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(6, 0, 0, 0, 6, 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(233, 0, 0, 0, 26, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(228, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(240, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(7, 0, 0, 0, 7, 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(237, 0, 0, 0, 26, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(232, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(244, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(117, 48, 0, 0, 0, 0, 0, 0), - ::capnp::word(9, 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(9, 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(117, 49, 0, 0, 0, 0, 0, 0), - ::capnp::word(9, 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(9, 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(117, 50, 0, 0, 0, 0, 0, 0), - ::capnp::word(9, 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(9, 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(117, 51, 0, 0, 0, 0, 0, 0), - ::capnp::word(9, 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(9, 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(117, 52, 0, 0, 0, 0, 0, 0), - ::capnp::word(9, 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(9, 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(117, 53, 0, 0, 0, 0, 0, 0), - ::capnp::word(9, 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(9, 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(117, 54, 0, 0, 0, 0, 0, 0), - ::capnp::word(9, 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(9, 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(117, 55, 0, 0, 0, 0, 0, 0), - ::capnp::word(9, 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(9, 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 => ::introspect(), - 1 => ::introspect(), - 2 => ::introspect(), - 3 => ::introspect(), - 4 => ::introspect(), - 5 => ::introspect(), - 6 => ::introspect(), - 7 => ::introspect(), - _ => panic!("invalid field index {}", index), - } - } - pub fn get_annotation_types(child_index: Option, 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, - members_by_name: MEMBERS_BY_NAME, - }; - pub static NONUNION_MEMBERS : &[u16] = &[0,1,2,3,4,5,6,7]; - pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; - pub static MEMBERS_BY_NAME : &[u16] = &[0,1,2,3,4,5,6,7]; - pub const TYPE_ID: u64 = 0x8067_4904_3a12_9c12; - } -} - -pub mod nonce24 { - #[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 <> ::core::marker::Copy for Reader<'_,> {} - impl <> ::core::clone::Clone for Reader<'_,> { - fn clone(&self) -> Self { *self } - } - - impl <> ::capnp::traits::HasTypeId for Reader<'_,> { - 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> 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 <> ::core::fmt::Debug for Reader<'_,> { - 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 { - ::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 <> Reader<'_,> { - pub fn reborrow(&self) -> Reader<'_,> { - Self { .. *self } - } - - pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { - self.reader.total_size() - } - #[inline] - pub fn get_u0(self) -> u64 { - self.reader.get_data_field::(0) - } - #[inline] - pub fn get_u1(self) -> u64 { - self.reader.get_data_field::(1) - } - #[inline] - pub fn get_u2(self) -> u64 { - self.reader.get_data_field::(2) - } - } - - pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } - impl <> ::capnp::traits::HasStructSize for Builder<'_,> { - const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 3, pointers: 0 }; - } - impl <> ::capnp::traits::HasTypeId for Builder<'_,> { - 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> 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(::STRUCT_SIZE).into() - } - fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { - ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) - } - } - - impl <> ::capnp::traits::SetterInput> for Reader<'_,> { - 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_u0(self) -> u64 { - self.builder.get_data_field::(0) - } - #[inline] - pub fn set_u0(&mut self, value: u64) { - self.builder.set_data_field::(0, value); - } - #[inline] - pub fn get_u1(self) -> u64 { - self.builder.get_data_field::(1) - } - #[inline] - pub fn set_u1(&mut self, value: u64) { - self.builder.set_data_field::(1, value); - } - #[inline] - pub fn get_u2(self) -> u64 { - self.builder.get_data_field::(2) - } - #[inline] - pub fn set_u2(&mut self, value: u64) { - self.builder.set_data_field::(2, 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 { - } - mod _private { - pub static ENCODED_NODE: [::capnp::Word; 64] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), - ::capnp::word(252, 125, 141, 93, 178, 13, 38, 182), - ::capnp::word(19, 0, 0, 0, 1, 0, 3, 0), - ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), - ::capnp::word(0, 0, 7, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(135, 2, 0, 0, 40, 3, 0, 0), - ::capnp::word(21, 0, 0, 0, 218, 0, 0, 0), - ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(29, 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, 78, 111, 110, 99, 101), - ::capnp::word(50, 52, 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, 26, 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, 26, 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(80, 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(77, 0, 0, 0, 26, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(72, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(84, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(117, 48, 0, 0, 0, 0, 0, 0), - ::capnp::word(9, 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(9, 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(117, 49, 0, 0, 0, 0, 0, 0), - ::capnp::word(9, 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(9, 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(117, 50, 0, 0, 0, 0, 0, 0), - ::capnp::word(9, 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(9, 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 => ::introspect(), - 1 => ::introspect(), - 2 => ::introspect(), - _ => panic!("invalid field index {}", index), - } - } - pub fn get_annotation_types(child_index: Option, 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, - members_by_name: MEMBERS_BY_NAME, - }; - pub static NONUNION_MEMBERS : &[u16] = &[0,1,2]; - pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; - pub static MEMBERS_BY_NAME : &[u16] = &[0,1,2]; - pub const TYPE_ID: u64 = 0xb626_0db2_5d8d_7dfc; - } -} - -pub mod typed_key { +pub mod record_key { #[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() } } @@ -993,11 +69,11 @@ pub mod typed_key { self.reader.get_data_field::(0) } #[inline] - pub fn get_key(self) -> ::capnp::Result> { + pub fn get_value(self) -> ::capnp::Result<::capnp::data::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 { + pub fn has_value(&self) -> bool { !self.reader.get_pointer_field(0).is_null() } } @@ -1063,19 +139,19 @@ pub mod typed_key { self.builder.set_data_field::(0, value); } #[inline] - pub fn get_key(self) -> ::capnp::Result> { + pub fn get_value(self) -> ::capnp::Result<::capnp::data::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::key256::Reader<'_>) -> ::capnp::Result<()> { - ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) + pub fn set_value(&mut self, value: ::capnp::data::Reader<'_>) { + self.builder.reborrow().get_pointer_field(0).set_data(value); } #[inline] - pub fn init_key(self, ) -> crate::veilid_capnp::key256::Builder<'a> { - ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) + pub fn init_value(self, size: u32) -> ::capnp::data::Builder<'a> { + self.builder.get_pointer_field(0).init_data(size) } #[inline] - pub fn has_key(&self) -> bool { + pub fn has_value(&self) -> bool { !self.builder.is_pointer_field_null(0) } } @@ -1087,20 +163,17 @@ pub mod typed_key { } } impl Pipeline { - pub fn get_key(&self) -> crate::veilid_capnp::key256::Pipeline { - ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) - } } mod _private { pub static ENCODED_NODE: [::capnp::Word; 49] = [ ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), - ::capnp::word(41, 27, 230, 241, 169, 103, 213, 226), + ::capnp::word(193, 176, 222, 152, 90, 71, 85, 205), ::capnp::word(19, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(203, 5, 0, 0, 75, 6, 0, 0), - ::capnp::word(21, 0, 0, 0, 226, 0, 0, 0), + ::capnp::word(94, 0, 0, 0, 218, 0, 0, 0), + ::capnp::word(21, 0, 0, 0, 234, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(29, 0, 0, 0, 119, 0, 0, 0), @@ -1108,8 +181,8 @@ pub mod typed_key { ::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, 84, 121, 112, 101, 100), - ::capnp::word(75, 101, 121, 0, 0, 0, 0, 0), + ::capnp::word(110, 112, 58, 82, 101, 99, 111, 114), + ::capnp::word(100, 75, 101, 121, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(8, 0, 0, 0, 3, 0, 4, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -1122,7 +195,7 @@ pub mod typed_key { ::capnp::word(1, 0, 0, 0, 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(45, 0, 0, 0, 34, 0, 0, 0), + ::capnp::word(45, 0, 0, 0, 50, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), @@ -1134,260 +207,19 @@ pub mod typed_key { ::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(107, 101, 121, 0, 0, 0, 0, 0), - ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(13, 169, 246, 134, 50, 78, 228, 221), + ::capnp::word(118, 97, 108, 117, 101, 0, 0, 0), + ::capnp::word(13, 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(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(13, 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 => ::introspect(), - 1 => ::introspect(), - _ => panic!("invalid field index {}", index), - } - } - pub fn get_annotation_types(child_index: Option, 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, - members_by_name: MEMBERS_BY_NAME, - }; - pub static NONUNION_MEMBERS : &[u16] = &[0,1]; - pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; - pub static MEMBERS_BY_NAME : &[u16] = &[1,0]; - pub const TYPE_ID: u64 = 0xe2d5_67a9_f1e6_1b29; - } -} - -pub mod typed_signature { - #[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 <> ::core::marker::Copy for Reader<'_,> {} - impl <> ::core::clone::Clone for Reader<'_,> { - fn clone(&self) -> Self { *self } - } - - impl <> ::capnp::traits::HasTypeId for Reader<'_,> { - 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> 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 <> ::core::fmt::Debug for Reader<'_,> { - 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 { - ::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_kind(self) -> u32 { - self.reader.get_data_field::(0) - } - #[inline] - pub fn get_signature(self) -> ::capnp::Result> { - ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) - } - #[inline] - pub fn has_signature(&self) -> bool { - !self.reader.get_pointer_field(0).is_null() - } - } - - pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } - impl <> ::capnp::traits::HasStructSize for Builder<'_,> { - const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 1, pointers: 1 }; - } - impl <> ::capnp::traits::HasTypeId for Builder<'_,> { - 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> 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(::STRUCT_SIZE).into() - } - fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { - ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) - } - } - - impl <> ::capnp::traits::SetterInput> for Reader<'_,> { - 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_kind(self) -> u32 { - self.builder.get_data_field::(0) - } - #[inline] - pub fn set_kind(&mut self, value: u32) { - self.builder.set_data_field::(0, value); - } - #[inline] - pub fn get_signature(self) -> ::capnp::Result> { - ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) - } - #[inline] - pub fn set_signature(&mut self, value: crate::veilid_capnp::signature512::Reader<'_>) -> ::capnp::Result<()> { - ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) - } - #[inline] - pub fn init_signature(self, ) -> crate::veilid_capnp::signature512::Builder<'a> { - ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) - } - #[inline] - pub fn has_signature(&self) -> bool { - !self.builder.is_pointer_field_null(0) - } - } - - 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_signature(&self) -> crate::veilid_capnp::signature512::Pipeline { - ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) - } - } - mod _private { - pub static ENCODED_NODE: [::capnp::Word; 51] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), - ::capnp::word(132, 56, 142, 41, 199, 112, 49, 150), - ::capnp::word(19, 0, 0, 0, 1, 0, 1, 0), - ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), - ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(77, 6, 0, 0, 211, 6, 0, 0), - ::capnp::word(21, 0, 0, 0, 18, 1, 0, 0), - ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(33, 0, 0, 0, 119, 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, 84, 121, 112, 101, 100), - ::capnp::word(83, 105, 103, 110, 97, 116, 117, 114), - ::capnp::word(101, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), - ::capnp::word(8, 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(41, 0, 0, 0, 42, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(36, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(48, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(1, 0, 0, 0, 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(45, 0, 0, 0, 82, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(44, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(56, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(107, 105, 110, 100, 0, 0, 0, 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(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(115, 105, 103, 110, 97, 116, 117, 114), - ::capnp::word(101, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(18, 156, 18, 58, 4, 73, 103, 128), - ::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 => ::introspect(), - 1 => ::introspect(), + 1 => <::capnp::data::Owned as ::capnp::introspect::Introspect>::introspect(), _ => panic!("invalid field index {}", index), } } @@ -1403,7 +235,1395 @@ pub mod typed_signature { pub static NONUNION_MEMBERS : &[u16] = &[0,1]; pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; pub static MEMBERS_BY_NAME : &[u16] = &[0,1]; - pub const TYPE_ID: u64 = 0x9631_70c7_298e_3884; + pub const TYPE_ID: u64 = 0xcd55_475a_98de_b0c1; + } +} + +pub mod block_id { + #[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 <> ::core::marker::Copy for Reader<'_,> {} + impl <> ::core::clone::Clone for Reader<'_,> { + fn clone(&self) -> Self { *self } + } + + impl <> ::capnp::traits::HasTypeId for Reader<'_,> { + 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> 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 <> ::core::fmt::Debug for Reader<'_,> { + 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 { + ::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_kind(self) -> u32 { + self.reader.get_data_field::(0) + } + #[inline] + pub fn get_value(self) -> ::capnp::Result<::capnp::data::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn has_value(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + } + + pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } + impl <> ::capnp::traits::HasStructSize for Builder<'_,> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 1, pointers: 1 }; + } + impl <> ::capnp::traits::HasTypeId for Builder<'_,> { + 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> 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(::STRUCT_SIZE).into() + } + fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { + ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) + } + } + + impl <> ::capnp::traits::SetterInput> for Reader<'_,> { + 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_kind(self) -> u32 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_kind(&mut self, value: u32) { + self.builder.set_data_field::(0, value); + } + #[inline] + pub fn get_value(self) -> ::capnp::Result<::capnp::data::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn set_value(&mut self, value: ::capnp::data::Reader<'_>) { + self.builder.reborrow().get_pointer_field(0).set_data(value); + } + #[inline] + pub fn init_value(self, size: u32) -> ::capnp::data::Builder<'a> { + self.builder.get_pointer_field(0).init_data(size) + } + #[inline] + pub fn has_value(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + } + + 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 { + } + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 49] = [ + ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + ::capnp::word(34, 26, 119, 228, 169, 120, 54, 237), + ::capnp::word(19, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), + ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(242, 0, 0, 0, 108, 1, 0, 0), + ::capnp::word(21, 0, 0, 0, 218, 0, 0, 0), + ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 119, 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, 66, 108, 111, 99, 107), + ::capnp::word(73, 100, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(8, 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(41, 0, 0, 0, 42, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(36, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(48, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 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(45, 0, 0, 0, 50, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(107, 105, 110, 100, 0, 0, 0, 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(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(118, 97, 108, 117, 101, 0, 0, 0), + ::capnp::word(13, 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(13, 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 => ::introspect(), + 1 => <::capnp::data::Owned as ::capnp::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types(child_index: Option, 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, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS : &[u16] = &[0,1]; + pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; + pub static MEMBERS_BY_NAME : &[u16] = &[0,1]; + pub const TYPE_ID: u64 = 0xed36_78a9_e477_1a22; + } +} + +pub mod node_id { + #[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 <> ::core::marker::Copy for Reader<'_,> {} + impl <> ::core::clone::Clone for Reader<'_,> { + fn clone(&self) -> Self { *self } + } + + impl <> ::capnp::traits::HasTypeId for Reader<'_,> { + 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> 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 <> ::core::fmt::Debug for Reader<'_,> { + 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 { + ::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_kind(self) -> u32 { + self.reader.get_data_field::(0) + } + #[inline] + pub fn get_value(self) -> ::capnp::Result<::capnp::data::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn has_value(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + } + + pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } + impl <> ::capnp::traits::HasStructSize for Builder<'_,> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 1, pointers: 1 }; + } + impl <> ::capnp::traits::HasTypeId for Builder<'_,> { + 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> 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(::STRUCT_SIZE).into() + } + fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { + ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) + } + } + + impl <> ::capnp::traits::SetterInput> for Reader<'_,> { + 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_kind(self) -> u32 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_kind(&mut self, value: u32) { + self.builder.set_data_field::(0, value); + } + #[inline] + pub fn get_value(self) -> ::capnp::Result<::capnp::data::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn set_value(&mut self, value: ::capnp::data::Reader<'_>) { + self.builder.reborrow().get_pointer_field(0).set_data(value); + } + #[inline] + pub fn init_value(self, size: u32) -> ::capnp::data::Builder<'a> { + self.builder.get_pointer_field(0).init_data(size) + } + #[inline] + pub fn has_value(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + } + + 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 { + } + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 49] = [ + ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + ::capnp::word(187, 161, 188, 206, 241, 34, 152, 206), + ::capnp::word(19, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), + ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(146, 1, 0, 0, 11, 2, 0, 0), + ::capnp::word(21, 0, 0, 0, 210, 0, 0, 0), + ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 119, 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, 78, 111, 100, 101, 73), + ::capnp::word(100, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(8, 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(41, 0, 0, 0, 42, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(36, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(48, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 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(45, 0, 0, 0, 50, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(107, 105, 110, 100, 0, 0, 0, 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(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(118, 97, 108, 117, 101, 0, 0, 0), + ::capnp::word(13, 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(13, 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 => ::introspect(), + 1 => <::capnp::data::Owned as ::capnp::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types(child_index: Option, 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, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS : &[u16] = &[0,1]; + pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; + pub static MEMBERS_BY_NAME : &[u16] = &[0,1]; + pub const TYPE_ID: u64 = 0xce98_22f1_cebc_a1bb; + } +} + +pub mod public_key { + #[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 <> ::core::marker::Copy for Reader<'_,> {} + impl <> ::core::clone::Clone for Reader<'_,> { + fn clone(&self) -> Self { *self } + } + + impl <> ::capnp::traits::HasTypeId for Reader<'_,> { + 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> 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 <> ::core::fmt::Debug for Reader<'_,> { + 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 { + ::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_kind(self) -> u32 { + self.reader.get_data_field::(0) + } + #[inline] + pub fn get_value(self) -> ::capnp::Result<::capnp::data::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn has_value(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + } + + pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } + impl <> ::capnp::traits::HasStructSize for Builder<'_,> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 1, pointers: 1 }; + } + impl <> ::capnp::traits::HasTypeId for Builder<'_,> { + 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> 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(::STRUCT_SIZE).into() + } + fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { + ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) + } + } + + impl <> ::capnp::traits::SetterInput> for Reader<'_,> { + 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_kind(self) -> u32 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_kind(&mut self, value: u32) { + self.builder.set_data_field::(0, value); + } + #[inline] + pub fn get_value(self) -> ::capnp::Result<::capnp::data::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn set_value(&mut self, value: ::capnp::data::Reader<'_>) { + self.builder.reborrow().get_pointer_field(0).set_data(value); + } + #[inline] + pub fn init_value(self, size: u32) -> ::capnp::data::Builder<'a> { + self.builder.get_pointer_field(0).init_data(size) + } + #[inline] + pub fn has_value(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + } + + 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 { + } + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 49] = [ + ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + ::capnp::word(238, 12, 243, 189, 45, 47, 82, 252), + ::capnp::word(19, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), + ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(26, 2, 0, 0, 150, 2, 0, 0), + ::capnp::word(21, 0, 0, 0, 234, 0, 0, 0), + ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 119, 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, 80, 117, 98, 108, 105), + ::capnp::word(99, 75, 101, 121, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(8, 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(41, 0, 0, 0, 42, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(36, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(48, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 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(45, 0, 0, 0, 50, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(107, 105, 110, 100, 0, 0, 0, 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(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(118, 97, 108, 117, 101, 0, 0, 0), + ::capnp::word(13, 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(13, 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 => ::introspect(), + 1 => <::capnp::data::Owned as ::capnp::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types(child_index: Option, 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, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS : &[u16] = &[0,1]; + pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; + pub static MEMBERS_BY_NAME : &[u16] = &[0,1]; + pub const TYPE_ID: u64 = 0xfc52_2f2d_bdf3_0cee; + } +} + +pub mod route_id { + #[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 <> ::core::marker::Copy for Reader<'_,> {} + impl <> ::core::clone::Clone for Reader<'_,> { + fn clone(&self) -> Self { *self } + } + + impl <> ::capnp::traits::HasTypeId for Reader<'_,> { + 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> 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 <> ::core::fmt::Debug for Reader<'_,> { + 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 { + ::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_kind(self) -> u32 { + self.reader.get_data_field::(0) + } + #[inline] + pub fn get_value(self) -> ::capnp::Result<::capnp::data::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn has_value(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + } + + pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } + impl <> ::capnp::traits::HasStructSize for Builder<'_,> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 1, pointers: 1 }; + } + impl <> ::capnp::traits::HasTypeId for Builder<'_,> { + 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> 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(::STRUCT_SIZE).into() + } + fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { + ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) + } + } + + impl <> ::capnp::traits::SetterInput> for Reader<'_,> { + 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_kind(self) -> u32 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_kind(&mut self, value: u32) { + self.builder.set_data_field::(0, value); + } + #[inline] + pub fn get_value(self) -> ::capnp::Result<::capnp::data::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn set_value(&mut self, value: ::capnp::data::Reader<'_>) { + self.builder.reborrow().get_pointer_field(0).set_data(value); + } + #[inline] + pub fn init_value(self, size: u32) -> ::capnp::data::Builder<'a> { + self.builder.get_pointer_field(0).init_data(size) + } + #[inline] + pub fn has_value(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + } + + 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 { + } + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 49] = [ + ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + ::capnp::word(230, 10, 218, 145, 109, 2, 174, 200), + ::capnp::word(19, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), + ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(167, 2, 0, 0, 33, 3, 0, 0), + ::capnp::word(21, 0, 0, 0, 218, 0, 0, 0), + ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 119, 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, 82, 111, 117, 116, 101), + ::capnp::word(73, 100, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(8, 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(41, 0, 0, 0, 42, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(36, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(48, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 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(45, 0, 0, 0, 50, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(107, 105, 110, 100, 0, 0, 0, 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(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(118, 97, 108, 117, 101, 0, 0, 0), + ::capnp::word(13, 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(13, 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 => ::introspect(), + 1 => <::capnp::data::Owned as ::capnp::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types(child_index: Option, 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, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS : &[u16] = &[0,1]; + pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; + pub static MEMBERS_BY_NAME : &[u16] = &[0,1]; + pub const TYPE_ID: u64 = 0xc8ae_026d_91da_0ae6; + } +} + +pub mod signature { + #[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 <> ::core::marker::Copy for Reader<'_,> {} + impl <> ::core::clone::Clone for Reader<'_,> { + fn clone(&self) -> Self { *self } + } + + impl <> ::capnp::traits::HasTypeId for Reader<'_,> { + 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> 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 <> ::core::fmt::Debug for Reader<'_,> { + 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 { + ::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_kind(self) -> u32 { + self.reader.get_data_field::(0) + } + #[inline] + pub fn get_value(self) -> ::capnp::Result<::capnp::data::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn has_value(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + } + + pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } + impl <> ::capnp::traits::HasStructSize for Builder<'_,> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 1, pointers: 1 }; + } + impl <> ::capnp::traits::HasTypeId for Builder<'_,> { + 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> 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(::STRUCT_SIZE).into() + } + fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { + ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) + } + } + + impl <> ::capnp::traits::SetterInput> for Reader<'_,> { + 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_kind(self) -> u32 { + self.builder.get_data_field::(0) + } + #[inline] + pub fn set_kind(&mut self, value: u32) { + self.builder.set_data_field::(0, value); + } + #[inline] + pub fn get_value(self) -> ::capnp::Result<::capnp::data::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn set_value(&mut self, value: ::capnp::data::Reader<'_>) { + self.builder.reborrow().get_pointer_field(0).set_data(value); + } + #[inline] + pub fn init_value(self, size: u32) -> ::capnp::data::Builder<'a> { + self.builder.get_pointer_field(0).init_data(size) + } + #[inline] + pub fn has_value(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + } + + 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 { + } + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 49] = [ + ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + ::capnp::word(162, 38, 135, 172, 226, 166, 111, 240), + ::capnp::word(19, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), + ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(47, 3, 0, 0, 171, 3, 0, 0), + ::capnp::word(21, 0, 0, 0, 234, 0, 0, 0), + ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 119, 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, 83, 105, 103, 110, 97), + ::capnp::word(116, 117, 114, 101, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(8, 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(41, 0, 0, 0, 42, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(36, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(48, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 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(45, 0, 0, 0, 50, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(107, 105, 110, 100, 0, 0, 0, 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(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(118, 97, 108, 117, 101, 0, 0, 0), + ::capnp::word(13, 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(13, 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 => ::introspect(), + 1 => <::capnp::data::Owned as ::capnp::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types(child_index: Option, 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, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS : &[u16] = &[0,1]; + pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; + pub static MEMBERS_BY_NAME : &[u16] = &[0,1]; + pub const TYPE_ID: u64 = 0xf06f_a6e2_ac87_26a2; + } +} + +pub mod nonce { + #[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 <> ::core::marker::Copy for Reader<'_,> {} + impl <> ::core::clone::Clone for Reader<'_,> { + fn clone(&self) -> Self { *self } + } + + impl <> ::capnp::traits::HasTypeId for Reader<'_,> { + 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> 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 <> ::core::fmt::Debug for Reader<'_,> { + 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 { + ::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_value(self) -> ::capnp::Result<::capnp::data::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn has_value(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + } + + pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } + impl <> ::capnp::traits::HasStructSize for Builder<'_,> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 0, pointers: 1 }; + } + impl <> ::capnp::traits::HasTypeId for Builder<'_,> { + 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> 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(::STRUCT_SIZE).into() + } + fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { + ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) + } + } + + impl <> ::capnp::traits::SetterInput> for Reader<'_,> { + 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_value(self) -> ::capnp::Result<::capnp::data::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn set_value(&mut self, value: ::capnp::data::Reader<'_>) { + self.builder.reborrow().get_pointer_field(0).set_data(value); + } + #[inline] + pub fn init_value(self, size: u32) -> ::capnp::data::Builder<'a> { + self.builder.get_pointer_field(0).init_data(size) + } + #[inline] + pub fn has_value(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + } + + 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 { + } + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 34] = [ + ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + ::capnp::word(246, 89, 123, 183, 109, 134, 0, 155), + ::capnp::word(19, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), + ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(217, 3, 0, 0, 36, 4, 0, 0), + ::capnp::word(21, 0, 0, 0, 202, 0, 0, 0), + ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 63, 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, 78, 111, 110, 99, 101), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(4, 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(13, 0, 0, 0, 50, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(8, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(20, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(118, 97, 108, 117, 101, 0, 0, 0), + ::capnp::word(13, 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(13, 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::data::Owned as ::capnp::introspect::Introspect>::introspect(), + _ => panic!("invalid field index {}", index), + } + } + pub fn get_annotation_types(child_index: Option, 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, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS : &[u16] = &[0]; + pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; + pub static MEMBERS_BY_NAME : &[u16] = &[0]; + pub const TYPE_ID: u64 = 0x9b00_866d_b77b_59f6; } } @@ -1552,7 +1772,7 @@ pub mod address_i_p_v4 { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(0, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(40, 7, 0, 0, 169, 7, 0, 0), + ::capnp::word(116, 6, 0, 0, 245, 6, 0, 0), ::capnp::word(21, 0, 0, 0, 250, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -1784,7 +2004,7 @@ pub mod address_i_p_v6 { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(0, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(171, 7, 0, 0, 231, 8, 0, 0), + ::capnp::word(247, 6, 0, 0, 51, 8, 0, 0), ::capnp::word(21, 0, 0, 0, 250, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -2090,7 +2310,7 @@ pub mod address { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 2, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(233, 8, 0, 0, 125, 9, 0, 0), + ::capnp::word(53, 8, 0, 0, 201, 8, 0, 0), ::capnp::word(21, 0, 0, 0, 218, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -2335,7 +2555,7 @@ pub mod socket_address { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(127, 9, 0, 0, 254, 9, 0, 0), + ::capnp::word(203, 8, 0, 0, 74, 9, 0, 0), ::capnp::word(21, 0, 0, 0, 10, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -2445,7 +2665,7 @@ pub static ENCODED_NODE: [::capnp::Word; 35] = [ ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 10, 0, 0, 169, 10, 0, 0), + ::capnp::word(76, 9, 0, 0, 245, 9, 0, 0), ::capnp::word(21, 0, 0, 0, 2, 1, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -2640,7 +2860,7 @@ pub mod dial_info_u_d_p { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(171, 10, 0, 0, 5, 11, 0, 0), + ::capnp::word(247, 9, 0, 0, 81, 10, 0, 0), ::capnp::word(21, 0, 0, 0, 250, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -2852,7 +3072,7 @@ pub mod dial_info_t_c_p { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(7, 11, 0, 0, 97, 11, 0, 0), + ::capnp::word(83, 10, 0, 0, 173, 10, 0, 0), ::capnp::word(21, 0, 0, 0, 250, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -3088,7 +3308,7 @@ pub mod dial_info_w_s { ::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(99, 11, 0, 0, 227, 11, 0, 0), + ::capnp::word(175, 10, 0, 0, 47, 11, 0, 0), ::capnp::word(21, 0, 0, 0, 242, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -3340,7 +3560,7 @@ pub mod dial_info_w_s_s { ::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(229, 11, 0, 0, 102, 12, 0, 0), + ::capnp::word(49, 11, 0, 0, 178, 11, 0, 0), ::capnp::word(21, 0, 0, 0, 250, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -3675,7 +3895,7 @@ pub mod dial_info { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 4, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(104, 12, 0, 0, 88, 13, 0, 0), + ::capnp::word(180, 11, 0, 0, 164, 12, 0, 0), ::capnp::word(21, 0, 0, 0, 226, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -3966,7 +4186,7 @@ pub mod signal_info_hole_punch { ::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(132, 13, 0, 0, 130, 14, 0, 0), + ::capnp::word(208, 12, 0, 0, 206, 13, 0, 0), ::capnp::word(21, 0, 0, 0, 58, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -4005,7 +4225,7 @@ pub mod signal_info_hole_punch { ::capnp::word(112, 101, 101, 114, 73, 110, 102, 111), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(203, 75, 60, 93, 45, 114, 45, 254), + ::capnp::word(247, 219, 131, 213, 61, 235, 60, 179), ::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), @@ -4219,7 +4439,7 @@ pub mod signal_info_reverse_connect { ::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(132, 14, 0, 0, 145, 15, 0, 0), + ::capnp::word(208, 13, 0, 0, 221, 14, 0, 0), ::capnp::word(21, 0, 0, 0, 98, 1, 0, 0), ::capnp::word(41, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -4259,7 +4479,7 @@ pub mod signal_info_reverse_connect { ::capnp::word(112, 101, 101, 114, 73, 110, 102, 111), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(203, 75, 60, 93, 45, 114, 45, 254), + ::capnp::word(247, 219, 131, 213, 61, 235, 60, 179), ::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), @@ -4351,7 +4571,7 @@ pub mod route_hop_data { self.reader.total_size() } #[inline] - pub fn get_nonce(self) -> ::capnp::Result> { + pub fn get_nonce(self) -> ::capnp::Result> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) } #[inline] @@ -4421,15 +4641,15 @@ pub mod route_hop_data { self.builder.as_reader().total_size() } #[inline] - pub fn get_nonce(self) -> ::capnp::Result> { + pub fn get_nonce(self) -> ::capnp::Result> { ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) } #[inline] - pub fn set_nonce(&mut self, value: crate::veilid_capnp::nonce24::Reader<'_>) -> ::capnp::Result<()> { + pub fn set_nonce(&mut self, value: crate::veilid_capnp::nonce::Reader<'_>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) } #[inline] - pub fn init_nonce(self, ) -> crate::veilid_capnp::nonce24::Builder<'a> { + pub fn init_nonce(self, ) -> crate::veilid_capnp::nonce::Builder<'a> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) } #[inline] @@ -4461,19 +4681,19 @@ pub mod route_hop_data { } } impl Pipeline { - pub fn get_nonce(&self) -> crate::veilid_capnp::nonce24::Pipeline { + pub fn get_nonce(&self) -> crate::veilid_capnp::nonce::Pipeline { ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) } } mod _private { pub static ENCODED_NODE: [::capnp::Word; 49] = [ ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), - ::capnp::word(242, 173, 183, 209, 249, 49, 226, 140), + ::capnp::word(219, 159, 231, 128, 24, 203, 69, 157), ::capnp::word(19, 0, 0, 0, 1, 0, 0, 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(196, 15, 0, 0, 79, 19, 0, 0), + ::capnp::word(16, 15, 0, 0, 146, 18, 0, 0), ::capnp::word(21, 0, 0, 0, 2, 1, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -4502,7 +4722,7 @@ pub mod route_hop_data { ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), ::capnp::word(110, 111, 110, 99, 101, 0, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(252, 125, 141, 93, 178, 13, 38, 182), + ::capnp::word(246, 89, 123, 183, 109, 134, 0, 155), ::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), @@ -4519,7 +4739,7 @@ pub mod route_hop_data { ]; pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { match index { - 0 => ::introspect(), + 0 => ::introspect(), 1 => <::capnp::data::Owned as ::capnp::introspect::Introspect>::introspect(), _ => panic!("invalid field index {}", index), } @@ -4536,7 +4756,7 @@ pub mod route_hop_data { pub static NONUNION_MEMBERS : &[u16] = &[0,1]; pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; pub static MEMBERS_BY_NAME : &[u16] = &[1,0]; - pub const TYPE_ID: u64 = 0x8ce2_31f9_d1b7_adf2; + pub const TYPE_ID: u64 = 0x9d45_cb18_80e7_9fdb; } } @@ -4717,7 +4937,7 @@ pub mod route_hop { ::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(81, 19, 0, 0, 193, 21, 0, 0), + ::capnp::word(148, 18, 0, 0, 4, 21, 0, 0), ::capnp::word(21, 0, 0, 0, 226, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -4747,7 +4967,7 @@ pub mod route_hop { ::capnp::word(110, 111, 100, 101, 0, 0, 0, 0), ::capnp::word(110, 101, 120, 116, 72, 111, 112, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(242, 173, 183, 209, 249, 49, 226, 140), + ::capnp::word(219, 159, 231, 128, 24, 203, 69, 157), ::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), @@ -4920,12 +5140,12 @@ pub mod route_hop { self.builder.as_reader().total_size() } #[inline] - pub fn set_node_id(&mut self, value: crate::veilid_capnp::key256::Reader<'_>) -> ::capnp::Result<()> { + pub fn set_node_id(&mut self, value: crate::veilid_capnp::node_id::Reader<'_>) -> ::capnp::Result<()> { self.builder.set_data_field::(0, 0); ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) } #[inline] - pub fn init_node_id(self, ) -> crate::veilid_capnp::key256::Builder<'a> { + pub fn init_node_id(self, ) -> crate::veilid_capnp::node_id::Builder<'a> { self.builder.set_data_field::(0, 0); ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) } @@ -5012,7 +5232,7 @@ pub mod route_hop { ::capnp::word(56, 0, 0, 0, 2, 0, 1, 0), ::capnp::word(110, 111, 100, 101, 73, 100, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(13, 169, 246, 134, 50, 78, 228, 221), + ::capnp::word(187, 161, 188, 206, 241, 34, 152, 206), ::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), @@ -5021,7 +5241,7 @@ pub mod route_hop { ::capnp::word(112, 101, 101, 114, 73, 110, 102, 111), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(203, 75, 60, 93, 45, 114, 45, 254), + ::capnp::word(247, 219, 131, 213, 61, 235, 60, 179), ::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), @@ -5030,7 +5250,7 @@ pub mod route_hop { ]; pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { match index { - 0 => ::introspect(), + 0 => ::introspect(), 1 => ::introspect(), _ => panic!("invalid field index {}", index), } @@ -5053,8 +5273,8 @@ pub mod route_hop { NodeId(A0), PeerInfo(A1), } - pub type WhichReader<'a,> = Which<::capnp::Result>,::capnp::Result>>; - pub type WhichBuilder<'a,> = Which<::capnp::Result>,::capnp::Result>>; + pub type WhichReader<'a,> = Which<::capnp::Result>,::capnp::Result>>; + pub type WhichBuilder<'a,> = Which<::capnp::Result>,::capnp::Result>>; } } @@ -5120,7 +5340,7 @@ pub mod private_route { self.reader.total_size() } #[inline] - pub fn get_public_key(self) -> ::capnp::Result> { + pub fn get_public_key(self) -> ::capnp::Result> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) } #[inline] @@ -5128,10 +5348,6 @@ pub mod private_route { !self.reader.get_pointer_field(0).is_null() } #[inline] - pub fn get_hop_count(self) -> u8 { - self.reader.get_data_field::(0) - } - #[inline] pub fn get_hops(self) -> crate::veilid_capnp::private_route::hops::Reader<'a> { self.reader.into() } @@ -5190,15 +5406,15 @@ pub mod private_route { self.builder.as_reader().total_size() } #[inline] - pub fn get_public_key(self) -> ::capnp::Result> { + pub fn get_public_key(self) -> ::capnp::Result> { ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) } #[inline] - pub fn set_public_key(&mut self, value: crate::veilid_capnp::typed_key::Reader<'_>) -> ::capnp::Result<()> { + pub fn set_public_key(&mut self, value: crate::veilid_capnp::public_key::Reader<'_>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) } #[inline] - pub fn init_public_key(self, ) -> crate::veilid_capnp::typed_key::Builder<'a> { + pub fn init_public_key(self, ) -> crate::veilid_capnp::public_key::Builder<'a> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) } #[inline] @@ -5206,20 +5422,12 @@ pub mod private_route { !self.builder.is_pointer_field_null(0) } #[inline] - pub fn get_hop_count(self) -> u8 { - self.builder.get_data_field::(0) - } - #[inline] - pub fn set_hop_count(&mut self, value: u8) { - self.builder.set_data_field::(0, value); - } - #[inline] pub fn get_hops(self) -> crate::veilid_capnp::private_route::hops::Builder<'a> { self.builder.into() } #[inline] pub fn init_hops(mut self, ) -> crate::veilid_capnp::private_route::hops::Builder<'a> { - self.builder.set_data_field::(1, 0); + self.builder.set_data_field::(0, 0); self.builder.reborrow().get_pointer_field(1).clear(); self.builder.into() } @@ -5232,7 +5440,7 @@ pub mod private_route { } } impl Pipeline { - pub fn get_public_key(&self) -> crate::veilid_capnp::typed_key::Pipeline { + pub fn get_public_key(&self) -> crate::veilid_capnp::public_key::Pipeline { ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) } pub fn get_hops(&self) -> crate::veilid_capnp::private_route::hops::Pipeline { @@ -5240,18 +5448,18 @@ pub mod private_route { } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 59] = [ + pub static ENCODED_NODE: [::capnp::Word; 43] = [ ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), ::capnp::word(118, 231, 81, 8, 203, 252, 131, 138), ::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(195, 21, 0, 0, 89, 24, 0, 0), + ::capnp::word(6, 21, 0, 0, 18, 23, 0, 0), ::capnp::word(21, 0, 0, 0, 2, 1, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(29, 0, 0, 0, 175, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 119, 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), @@ -5259,53 +5467,36 @@ pub mod private_route { ::capnp::word(110, 112, 58, 80, 114, 105, 118, 97), ::capnp::word(116, 101, 82, 111, 117, 116, 101, 0), ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), - ::capnp::word(12, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(8, 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, 82, 0, 0, 0), + ::capnp::word(41, 0, 0, 0, 82, 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(80, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), ::capnp::word(1, 0, 0, 0, 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(77, 0, 0, 0, 74, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(76, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(88, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(2, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(56, 83, 93, 93, 37, 237, 192, 139), - ::capnp::word(85, 0, 0, 0, 42, 0, 0, 0), + ::capnp::word(156, 151, 18, 47, 236, 23, 165, 251), + ::capnp::word(49, 0, 0, 0, 42, 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(112, 117, 98, 108, 105, 99, 75, 101), ::capnp::word(121, 0, 0, 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(238, 12, 243, 189, 45, 47, 82, 252), ::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(104, 111, 112, 67, 111, 117, 110, 116), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(6, 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(6, 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(104, 111, 112, 115, 0, 0, 0, 0), ]; pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { match index { - 0 => ::introspect(), - 1 => ::introspect(), - 2 => ::introspect(), + 0 => ::introspect(), + 1 => ::introspect(), _ => panic!("invalid field index {}", index), } } @@ -5318,9 +5509,9 @@ pub mod private_route { members_by_discriminant: MEMBERS_BY_DISCRIMINANT, members_by_name: MEMBERS_BY_NAME, }; - pub static NONUNION_MEMBERS : &[u16] = &[0,1,2]; + pub static NONUNION_MEMBERS : &[u16] = &[0,1]; pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; - pub static MEMBERS_BY_NAME : &[u16] = &[1,2,0]; + pub static MEMBERS_BY_NAME : &[u16] = &[1,0]; pub const TYPE_ID: u64 = 0x8a83_fccb_0851_e776; } @@ -5389,17 +5580,17 @@ pub mod private_route { } #[inline] pub fn has_first_hop(&self) -> bool { - if self.reader.get_data_field::(1) != 0 { return false; } + if self.reader.get_data_field::(0) != 0 { return false; } !self.reader.get_pointer_field(1).is_null() } #[inline] pub fn has_data(&self) -> bool { - if self.reader.get_data_field::(1) != 1 { return false; } + if self.reader.get_data_field::(0) != 1 { return false; } !self.reader.get_pointer_field(1).is_null() } #[inline] pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { - match self.reader.get_data_field::(1) { + match self.reader.get_data_field::(0) { 0 => { ::core::result::Result::Ok(FirstHop( ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None) @@ -5474,41 +5665,41 @@ pub mod private_route { } #[inline] pub fn set_first_hop(&mut self, value: crate::veilid_capnp::route_hop::Reader<'_>) -> ::capnp::Result<()> { - self.builder.set_data_field::(1, 0); + self.builder.set_data_field::(0, 0); ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false) } #[inline] pub fn init_first_hop(self, ) -> crate::veilid_capnp::route_hop::Builder<'a> { - self.builder.set_data_field::(1, 0); + self.builder.set_data_field::(0, 0); ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), 0) } #[inline] pub fn has_first_hop(&self) -> bool { - if self.builder.get_data_field::(1) != 0 { return false; } + if self.builder.get_data_field::(0) != 0 { return false; } !self.builder.is_pointer_field_null(1) } #[inline] pub fn set_data(&mut self, value: crate::veilid_capnp::route_hop_data::Reader<'_>) -> ::capnp::Result<()> { - self.builder.set_data_field::(1, 1); + self.builder.set_data_field::(0, 1); ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false) } #[inline] pub fn init_data(self, ) -> crate::veilid_capnp::route_hop_data::Builder<'a> { - self.builder.set_data_field::(1, 1); + self.builder.set_data_field::(0, 1); ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), 0) } #[inline] pub fn has_data(&self) -> bool { - if self.builder.get_data_field::(1) != 1 { return false; } + if self.builder.get_data_field::(0) != 1 { return false; } !self.builder.is_pointer_field_null(1) } #[inline] pub fn set_empty(&mut self, _value: ()) { - self.builder.set_data_field::(1, 2); + self.builder.set_data_field::(0, 2); } #[inline] pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { - match self.builder.get_data_field::(1) { + match self.builder.get_data_field::(0) { 0 => { ::core::result::Result::Ok(FirstHop( ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None) @@ -5540,11 +5731,11 @@ pub mod private_route { mod _private { pub static ENCODED_NODE: [::capnp::Word; 65] = [ ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), - ::capnp::word(56, 83, 93, 93, 37, 237, 192, 139), + ::capnp::word(156, 151, 18, 47, 236, 23, 165, 251), ::capnp::word(32, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(118, 231, 81, 8, 203, 252, 131, 138), ::capnp::word(2, 0, 7, 0, 1, 0, 3, 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(21, 0, 0, 0, 42, 1, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -5559,21 +5750,21 @@ pub mod private_route { ::capnp::word(104, 111, 112, 115, 0, 0, 0, 0), ::capnp::word(12, 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, 1, 0, 1, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(69, 0, 0, 0, 74, 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(80, 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, 1, 0, 2, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(77, 0, 0, 0, 42, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(72, 0, 0, 0, 3, 0, 1, 0), ::capnp::word(84, 0, 0, 0, 2, 0, 1, 0), ::capnp::word(2, 0, 253, 255, 0, 0, 0, 0), - ::capnp::word(0, 0, 1, 0, 4, 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(81, 0, 0, 0, 50, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -5590,7 +5781,7 @@ pub mod private_route { ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(100, 97, 116, 97, 0, 0, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(242, 173, 183, 209, 249, 49, 226, 140), + ::capnp::word(219, 159, 231, 128, 24, 203, 69, 157), ::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), @@ -5625,7 +5816,7 @@ pub mod private_route { pub static NONUNION_MEMBERS : &[u16] = &[]; pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[0,1,2]; pub static MEMBERS_BY_NAME : &[u16] = &[1,2,0]; - pub const TYPE_ID: u64 = 0x8bc0_ed25_5d5d_5338; + pub const TYPE_ID: u64 = 0xfba5_17ec_2f12_979c; } pub enum Which { FirstHop(A0), @@ -5699,7 +5890,7 @@ pub mod safety_route { self.reader.total_size() } #[inline] - pub fn get_public_key(self) -> ::capnp::Result> { + pub fn get_public_key(self) -> ::capnp::Result> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) } #[inline] @@ -5707,10 +5898,6 @@ pub mod safety_route { !self.reader.get_pointer_field(0).is_null() } #[inline] - pub fn get_hop_count(self) -> u8 { - self.reader.get_data_field::(0) - } - #[inline] pub fn get_hops(self) -> crate::veilid_capnp::safety_route::hops::Reader<'a> { self.reader.into() } @@ -5769,15 +5956,15 @@ pub mod safety_route { self.builder.as_reader().total_size() } #[inline] - pub fn get_public_key(self) -> ::capnp::Result> { + pub fn get_public_key(self) -> ::capnp::Result> { ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) } #[inline] - pub fn set_public_key(&mut self, value: crate::veilid_capnp::typed_key::Reader<'_>) -> ::capnp::Result<()> { + pub fn set_public_key(&mut self, value: crate::veilid_capnp::public_key::Reader<'_>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) } #[inline] - pub fn init_public_key(self, ) -> crate::veilid_capnp::typed_key::Builder<'a> { + pub fn init_public_key(self, ) -> crate::veilid_capnp::public_key::Builder<'a> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) } #[inline] @@ -5785,20 +5972,12 @@ pub mod safety_route { !self.builder.is_pointer_field_null(0) } #[inline] - pub fn get_hop_count(self) -> u8 { - self.builder.get_data_field::(0) - } - #[inline] - pub fn set_hop_count(&mut self, value: u8) { - self.builder.set_data_field::(0, value); - } - #[inline] pub fn get_hops(self) -> crate::veilid_capnp::safety_route::hops::Builder<'a> { self.builder.into() } #[inline] pub fn init_hops(mut self, ) -> crate::veilid_capnp::safety_route::hops::Builder<'a> { - self.builder.set_data_field::(1, 0); + self.builder.set_data_field::(0, 0); self.builder.reborrow().get_pointer_field(1).clear(); self.builder.into() } @@ -5811,7 +5990,7 @@ pub mod safety_route { } } impl Pipeline { - pub fn get_public_key(&self) -> crate::veilid_capnp::typed_key::Pipeline { + pub fn get_public_key(&self) -> crate::veilid_capnp::public_key::Pipeline { ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) } pub fn get_hops(&self) -> crate::veilid_capnp::safety_route::hops::Pipeline { @@ -5819,18 +5998,18 @@ pub mod safety_route { } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 59] = [ + pub static ENCODED_NODE: [::capnp::Word; 43] = [ ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), ::capnp::word(89, 93, 203, 7, 77, 115, 84, 245), ::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(92, 24, 0, 0, 83, 26, 0, 0), + ::capnp::word(21, 23, 0, 0, 131, 24, 0, 0), ::capnp::word(21, 0, 0, 0, 250, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(29, 0, 0, 0, 175, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 119, 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), @@ -5838,53 +6017,36 @@ pub mod safety_route { ::capnp::word(110, 112, 58, 83, 97, 102, 101, 116), ::capnp::word(121, 82, 111, 117, 116, 101, 0, 0), ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), - ::capnp::word(12, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(8, 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, 82, 0, 0, 0), + ::capnp::word(41, 0, 0, 0, 82, 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(80, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), ::capnp::word(1, 0, 0, 0, 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(77, 0, 0, 0, 74, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(76, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(88, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(2, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(26, 107, 173, 97, 187, 247, 201, 172), - ::capnp::word(85, 0, 0, 0, 42, 0, 0, 0), + ::capnp::word(231, 64, 119, 140, 243, 87, 65, 214), + ::capnp::word(49, 0, 0, 0, 42, 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(112, 117, 98, 108, 105, 99, 75, 101), ::capnp::word(121, 0, 0, 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(238, 12, 243, 189, 45, 47, 82, 252), ::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(104, 111, 112, 67, 111, 117, 110, 116), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(6, 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(6, 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(104, 111, 112, 115, 0, 0, 0, 0), ]; pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { match index { - 0 => ::introspect(), - 1 => ::introspect(), - 2 => ::introspect(), + 0 => ::introspect(), + 1 => ::introspect(), _ => panic!("invalid field index {}", index), } } @@ -5897,9 +6059,9 @@ pub mod safety_route { members_by_discriminant: MEMBERS_BY_DISCRIMINANT, members_by_name: MEMBERS_BY_NAME, }; - pub static NONUNION_MEMBERS : &[u16] = &[0,1,2]; + pub static NONUNION_MEMBERS : &[u16] = &[0,1]; pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; - pub static MEMBERS_BY_NAME : &[u16] = &[1,2,0]; + pub static MEMBERS_BY_NAME : &[u16] = &[1,0]; pub const TYPE_ID: u64 = 0xf554_734d_07cb_5d59; } @@ -5968,17 +6130,17 @@ pub mod safety_route { } #[inline] pub fn has_data(&self) -> bool { - if self.reader.get_data_field::(1) != 0 { return false; } + if self.reader.get_data_field::(0) != 0 { return false; } !self.reader.get_pointer_field(1).is_null() } #[inline] pub fn has_private(&self) -> bool { - if self.reader.get_data_field::(1) != 1 { return false; } + if self.reader.get_data_field::(0) != 1 { return false; } !self.reader.get_pointer_field(1).is_null() } #[inline] pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { - match self.reader.get_data_field::(1) { + match self.reader.get_data_field::(0) { 0 => { ::core::result::Result::Ok(Data( ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None) @@ -6048,37 +6210,37 @@ pub mod safety_route { } #[inline] pub fn set_data(&mut self, value: crate::veilid_capnp::route_hop_data::Reader<'_>) -> ::capnp::Result<()> { - self.builder.set_data_field::(1, 0); + self.builder.set_data_field::(0, 0); ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false) } #[inline] pub fn init_data(self, ) -> crate::veilid_capnp::route_hop_data::Builder<'a> { - self.builder.set_data_field::(1, 0); + self.builder.set_data_field::(0, 0); ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), 0) } #[inline] pub fn has_data(&self) -> bool { - if self.builder.get_data_field::(1) != 0 { return false; } + if self.builder.get_data_field::(0) != 0 { return false; } !self.builder.is_pointer_field_null(1) } #[inline] pub fn set_private(&mut self, value: crate::veilid_capnp::private_route::Reader<'_>) -> ::capnp::Result<()> { - self.builder.set_data_field::(1, 1); + self.builder.set_data_field::(0, 1); ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false) } #[inline] pub fn init_private(self, ) -> crate::veilid_capnp::private_route::Builder<'a> { - self.builder.set_data_field::(1, 1); + self.builder.set_data_field::(0, 1); ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), 0) } #[inline] pub fn has_private(&self) -> bool { - if self.builder.get_data_field::(1) != 1 { return false; } + if self.builder.get_data_field::(0) != 1 { return false; } !self.builder.is_pointer_field_null(1) } #[inline] pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { - match self.builder.get_data_field::(1) { + match self.builder.get_data_field::(0) { 0 => { ::core::result::Result::Ok(Data( ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None) @@ -6105,11 +6267,11 @@ pub mod safety_route { mod _private { pub static ENCODED_NODE: [::capnp::Word; 49] = [ ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), - ::capnp::word(26, 107, 173, 97, 187, 247, 201, 172), + ::capnp::word(231, 64, 119, 140, 243, 87, 65, 214), ::capnp::word(31, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(89, 93, 203, 7, 77, 115, 84, 245), ::capnp::word(2, 0, 7, 0, 1, 0, 2, 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(21, 0, 0, 0, 34, 1, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -6124,14 +6286,14 @@ pub mod safety_route { ::capnp::word(111, 112, 115, 0, 0, 0, 0, 0), ::capnp::word(8, 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, 1, 0, 1, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(41, 0, 0, 0, 42, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(36, 0, 0, 0, 3, 0, 1, 0), ::capnp::word(48, 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, 1, 0, 2, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(45, 0, 0, 0, 66, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -6139,7 +6301,7 @@ pub mod safety_route { ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), ::capnp::word(100, 97, 116, 97, 0, 0, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(242, 173, 183, 209, 249, 49, 226, 140), + ::capnp::word(219, 159, 231, 128, 24, 203, 69, 157), ::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), @@ -6173,7 +6335,7 @@ pub mod safety_route { pub static NONUNION_MEMBERS : &[u16] = &[]; pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[0,1]; pub static MEMBERS_BY_NAME : &[u16] = &[0,1]; - pub const TYPE_ID: u64 = 0xacc9_f7bb_61ad_6b1a; + pub const TYPE_ID: u64 = 0xd641_57f3_8c77_40e7; } pub enum Which { Data(A0), @@ -6226,7 +6388,7 @@ pub static ENCODED_NODE: [::capnp::Word; 37] = [ ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(130, 26, 0, 0, 125, 28, 0, 0), + ::capnp::word(178, 24, 0, 0, 173, 26, 0, 0), ::capnp::word(21, 0, 0, 0, 2, 1, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -6309,7 +6471,7 @@ pub static ENCODED_NODE: [::capnp::Word; 49] = [ ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(127, 28, 0, 0, 204, 31, 0, 0), + ::capnp::word(175, 26, 0, 0, 252, 29, 0, 0), ::capnp::word(21, 0, 0, 0, 10, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -6398,7 +6560,7 @@ pub static ENCODED_NODE: [::capnp::Word; 34] = [ ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(206, 31, 0, 0, 85, 32, 0, 0), + ::capnp::word(254, 29, 0, 0, 133, 30, 0, 0), ::capnp::word(21, 0, 0, 0, 242, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -6604,7 +6766,7 @@ pub mod dial_info_detail { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(87, 32, 0, 0, 223, 32, 0, 0), + ::capnp::word(135, 30, 0, 0, 15, 31, 0, 0), ::capnp::word(21, 0, 0, 0, 18, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -6806,7 +6968,7 @@ pub mod node_status { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(0, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(225, 32, 0, 0, 49, 33, 0, 0), + ::capnp::word(17, 31, 0, 0, 97, 31, 0, 0), ::capnp::word(21, 0, 0, 0, 242, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -7019,7 +7181,7 @@ pub mod protocol_type_set { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(0, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(51, 33, 0, 0, 253, 33, 0, 0), + ::capnp::word(99, 31, 0, 0, 45, 32, 0, 0), ::capnp::word(21, 0, 0, 0, 26, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -7276,7 +7438,7 @@ pub mod address_type_set { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(0, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(255, 33, 0, 0, 122, 34, 0, 0), + ::capnp::word(47, 32, 0, 0, 170, 32, 0, 0), ::capnp::word(21, 0, 0, 0, 18, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -7504,7 +7666,7 @@ pub mod sender_info { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(124, 34, 0, 0, 8, 35, 0, 0), + ::capnp::word(172, 32, 0, 0, 56, 33, 0, 0), ::capnp::word(21, 0, 0, 0, 242, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -7851,7 +8013,7 @@ pub mod node_info { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(6, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(10, 35, 0, 0, 171, 37, 0, 0), + ::capnp::word(58, 33, 0, 0, 219, 35, 0, 0), ::capnp::word(21, 0, 0, 0, 226, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -8097,7 +8259,7 @@ pub mod signed_direct_node_info { self.reader.get_data_field::(0) } #[inline] - pub fn get_signatures(self) -> ::capnp::Result<::capnp::struct_list::Reader<'a,crate::veilid_capnp::typed_signature::Owned>> { + pub fn get_signatures(self) -> ::capnp::Result<::capnp::struct_list::Reader<'a,crate::veilid_capnp::signature::Owned>> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None) } #[inline] @@ -8183,15 +8345,15 @@ pub mod signed_direct_node_info { self.builder.set_data_field::(0, value); } #[inline] - pub fn get_signatures(self) -> ::capnp::Result<::capnp::struct_list::Builder<'a,crate::veilid_capnp::typed_signature::Owned>> { + pub fn get_signatures(self) -> ::capnp::Result<::capnp::struct_list::Builder<'a,crate::veilid_capnp::signature::Owned>> { ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None) } #[inline] - pub fn set_signatures(&mut self, value: ::capnp::struct_list::Reader<'_,crate::veilid_capnp::typed_signature::Owned>) -> ::capnp::Result<()> { + pub fn set_signatures(&mut self, value: ::capnp::struct_list::Reader<'_,crate::veilid_capnp::signature::Owned>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false) } #[inline] - pub fn init_signatures(self, size: u32) -> ::capnp::struct_list::Builder<'a,crate::veilid_capnp::typed_signature::Owned> { + pub fn init_signatures(self, size: u32) -> ::capnp::struct_list::Builder<'a,crate::veilid_capnp::signature::Owned> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), size) } #[inline] @@ -8214,12 +8376,12 @@ pub mod signed_direct_node_info { mod _private { pub static ENCODED_NODE: [::capnp::Word; 72] = [ ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), - ::capnp::word(215, 61, 58, 137, 62, 234, 231, 224), + ::capnp::word(205, 192, 175, 125, 231, 133, 15, 167), ::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(173, 37, 0, 0, 199, 38, 0, 0), + ::capnp::word(221, 35, 0, 0, 247, 36, 0, 0), ::capnp::word(21, 0, 0, 0, 66, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -8279,7 +8441,7 @@ pub mod signed_direct_node_info { ::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(132, 56, 142, 41, 199, 112, 49, 150), + ::capnp::word(162, 38, 135, 172, 226, 166, 111, 240), ::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), @@ -8290,7 +8452,7 @@ pub mod signed_direct_node_info { match index { 0 => ::introspect(), 1 => ::introspect(), - 2 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), + 2 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), _ => panic!("invalid field index {}", index), } } @@ -8306,7 +8468,7 @@ pub mod signed_direct_node_info { pub static NONUNION_MEMBERS : &[u16] = &[0,1,2]; pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; pub static MEMBERS_BY_NAME : &[u16] = &[0,2,1]; - pub const TYPE_ID: u64 = 0xe0e7_ea3e_893a_3dd7; + pub const TYPE_ID: u64 = 0xa70f_85e7_7daf_c0cd; } } @@ -8380,7 +8542,7 @@ pub mod signed_relayed_node_info { !self.reader.get_pointer_field(0).is_null() } #[inline] - pub fn get_relay_ids(self) -> ::capnp::Result<::capnp::struct_list::Reader<'a,crate::veilid_capnp::typed_key::Owned>> { + pub fn get_relay_ids(self) -> ::capnp::Result<::capnp::struct_list::Reader<'a,crate::veilid_capnp::node_id::Owned>> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None) } #[inline] @@ -8400,7 +8562,7 @@ pub mod signed_relayed_node_info { self.reader.get_data_field::(0) } #[inline] - pub fn get_signatures(self) -> ::capnp::Result<::capnp::struct_list::Reader<'a,crate::veilid_capnp::typed_signature::Owned>> { + pub fn get_signatures(self) -> ::capnp::Result<::capnp::struct_list::Reader<'a,crate::veilid_capnp::signature::Owned>> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(3), ::core::option::Option::None) } #[inline] @@ -8478,15 +8640,15 @@ pub mod signed_relayed_node_info { !self.builder.is_pointer_field_null(0) } #[inline] - pub fn get_relay_ids(self) -> ::capnp::Result<::capnp::struct_list::Builder<'a,crate::veilid_capnp::typed_key::Owned>> { + pub fn get_relay_ids(self) -> ::capnp::Result<::capnp::struct_list::Builder<'a,crate::veilid_capnp::node_id::Owned>> { ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None) } #[inline] - pub fn set_relay_ids(&mut self, value: ::capnp::struct_list::Reader<'_,crate::veilid_capnp::typed_key::Owned>) -> ::capnp::Result<()> { + pub fn set_relay_ids(&mut self, value: ::capnp::struct_list::Reader<'_,crate::veilid_capnp::node_id::Owned>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false) } #[inline] - pub fn init_relay_ids(self, size: u32) -> ::capnp::struct_list::Builder<'a,crate::veilid_capnp::typed_key::Owned> { + pub fn init_relay_ids(self, size: u32) -> ::capnp::struct_list::Builder<'a,crate::veilid_capnp::node_id::Owned> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), size) } #[inline] @@ -8518,15 +8680,15 @@ pub mod signed_relayed_node_info { self.builder.set_data_field::(0, value); } #[inline] - pub fn get_signatures(self) -> ::capnp::Result<::capnp::struct_list::Builder<'a,crate::veilid_capnp::typed_signature::Owned>> { + pub fn get_signatures(self) -> ::capnp::Result<::capnp::struct_list::Builder<'a,crate::veilid_capnp::signature::Owned>> { ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(3), ::core::option::Option::None) } #[inline] - pub fn set_signatures(&mut self, value: ::capnp::struct_list::Reader<'_,crate::veilid_capnp::typed_signature::Owned>) -> ::capnp::Result<()> { + pub fn set_signatures(&mut self, value: ::capnp::struct_list::Reader<'_,crate::veilid_capnp::signature::Owned>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(3), value, false) } #[inline] - pub fn init_signatures(self, size: u32) -> ::capnp::struct_list::Builder<'a,crate::veilid_capnp::typed_signature::Owned> { + pub fn init_signatures(self, size: u32) -> ::capnp::struct_list::Builder<'a,crate::veilid_capnp::signature::Owned> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(3), size) } #[inline] @@ -8552,12 +8714,12 @@ pub mod signed_relayed_node_info { mod _private { pub static ENCODED_NODE: [::capnp::Word; 109] = [ ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), - ::capnp::word(187, 124, 216, 204, 40, 132, 158, 179), + ::capnp::word(63, 87, 17, 11, 80, 61, 25, 139), ::capnp::word(19, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(4, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(201, 38, 0, 0, 134, 40, 0, 0), + ::capnp::word(249, 36, 0, 0, 182, 38, 0, 0), ::capnp::word(21, 0, 0, 0, 74, 1, 0, 0), ::capnp::word(41, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -8623,7 +8785,7 @@ pub mod signed_relayed_node_info { ::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(41, 27, 230, 241, 169, 103, 213, 226), + ::capnp::word(187, 161, 188, 206, 241, 34, 152, 206), ::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), @@ -8632,7 +8794,7 @@ pub mod signed_relayed_node_info { ::capnp::word(114, 101, 108, 97, 121, 73, 110, 102), ::capnp::word(111, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(215, 61, 58, 137, 62, 234, 231, 224), + ::capnp::word(205, 192, 175, 125, 231, 133, 15, 167), ::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), @@ -8654,7 +8816,7 @@ pub mod signed_relayed_node_info { ::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(132, 56, 142, 41, 199, 112, 49, 150), + ::capnp::word(162, 38, 135, 172, 226, 166, 111, 240), ::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), @@ -8664,10 +8826,10 @@ pub mod signed_relayed_node_info { pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { match index { 0 => ::introspect(), - 1 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), + 1 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), 2 => ::introspect(), 3 => ::introspect(), - 4 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), + 4 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), _ => panic!("invalid field index {}", index), } } @@ -8683,7 +8845,7 @@ pub mod signed_relayed_node_info { pub static NONUNION_MEMBERS : &[u16] = &[0,1,2,3,4]; pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; pub static MEMBERS_BY_NAME : &[u16] = &[0,1,2,4,3]; - pub const TYPE_ID: u64 = 0xb39e_8428_ccd8_7cbb; + pub const TYPE_ID: u64 = 0x8b19_3d50_0b11_573f; } } @@ -8894,7 +9056,7 @@ pub mod signed_node_info { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 2, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(136, 40, 0, 0, 143, 41, 0, 0), + ::capnp::word(184, 38, 0, 0, 191, 39, 0, 0), ::capnp::word(21, 0, 0, 0, 18, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -8924,7 +9086,7 @@ pub mod signed_node_info { ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), ::capnp::word(100, 105, 114, 101, 99, 116, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(215, 61, 58, 137, 62, 234, 231, 224), + ::capnp::word(205, 192, 175, 125, 231, 133, 15, 167), ::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), @@ -8932,7 +9094,7 @@ pub mod signed_node_info { ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(114, 101, 108, 97, 121, 101, 100, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(187, 124, 216, 204, 40, 132, 158, 179), + ::capnp::word(63, 87, 17, 11, 80, 61, 25, 139), ::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), @@ -9030,7 +9192,7 @@ pub mod peer_info { self.reader.total_size() } #[inline] - pub fn get_node_ids(self) -> ::capnp::Result<::capnp::struct_list::Reader<'a,crate::veilid_capnp::typed_key::Owned>> { + pub fn get_node_ids(self) -> ::capnp::Result<::capnp::struct_list::Reader<'a,crate::veilid_capnp::node_id::Owned>> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) } #[inline] @@ -9100,15 +9262,15 @@ pub mod peer_info { self.builder.as_reader().total_size() } #[inline] - pub fn get_node_ids(self) -> ::capnp::Result<::capnp::struct_list::Builder<'a,crate::veilid_capnp::typed_key::Owned>> { + pub fn get_node_ids(self) -> ::capnp::Result<::capnp::struct_list::Builder<'a,crate::veilid_capnp::node_id::Owned>> { ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) } #[inline] - pub fn set_node_ids(&mut self, value: ::capnp::struct_list::Reader<'_,crate::veilid_capnp::typed_key::Owned>) -> ::capnp::Result<()> { + pub fn set_node_ids(&mut self, value: ::capnp::struct_list::Reader<'_,crate::veilid_capnp::node_id::Owned>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) } #[inline] - pub fn init_node_ids(self, size: u32) -> ::capnp::struct_list::Builder<'a,crate::veilid_capnp::typed_key::Owned> { + pub fn init_node_ids(self, size: u32) -> ::capnp::struct_list::Builder<'a,crate::veilid_capnp::node_id::Owned> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), size) } #[inline] @@ -9147,12 +9309,12 @@ pub mod peer_info { mod _private { pub static ENCODED_NODE: [::capnp::Word; 54] = [ ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), - ::capnp::word(203, 75, 60, 93, 45, 114, 45, 254), + ::capnp::word(247, 219, 131, 213, 61, 235, 60, 179), ::capnp::word(19, 0, 0, 0, 1, 0, 0, 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(145, 41, 0, 0, 106, 42, 0, 0), + ::capnp::word(193, 39, 0, 0, 154, 40, 0, 0), ::capnp::word(21, 0, 0, 0, 226, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -9185,7 +9347,7 @@ pub mod peer_info { ::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(41, 27, 230, 241, 169, 103, 213, 226), + ::capnp::word(187, 161, 188, 206, 241, 34, 152, 206), ::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), @@ -9203,7 +9365,7 @@ pub mod peer_info { ]; pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { match index { - 0 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), + 0 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), 1 => ::introspect(), _ => panic!("invalid field index {}", index), } @@ -9220,7 +9382,7 @@ pub mod peer_info { pub static NONUNION_MEMBERS : &[u16] = &[0,1]; pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; pub static MEMBERS_BY_NAME : &[u16] = &[0,1]; - pub const TYPE_ID: u64 = 0xfe2d_722d_5d3c_4bcb; + pub const TYPE_ID: u64 = 0xb33c_eb3d_d583_dbf7; } } @@ -9290,7 +9452,7 @@ pub mod routed_operation { ::core::convert::TryInto::try_into(self.reader.get_data_field::(0)) } #[inline] - pub fn get_signatures(self) -> ::capnp::Result<::capnp::struct_list::Reader<'a,crate::veilid_capnp::signature512::Owned>> { + pub fn get_signatures(self) -> ::capnp::Result<::capnp::struct_list::Reader<'a,crate::veilid_capnp::signature::Owned>> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) } #[inline] @@ -9298,7 +9460,7 @@ pub mod routed_operation { !self.reader.get_pointer_field(0).is_null() } #[inline] - pub fn get_nonce(self) -> ::capnp::Result> { + pub fn get_nonce(self) -> ::capnp::Result> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None) } #[inline] @@ -9376,15 +9538,15 @@ pub mod routed_operation { self.builder.set_data_field::(0, value as u16); } #[inline] - pub fn get_signatures(self) -> ::capnp::Result<::capnp::struct_list::Builder<'a,crate::veilid_capnp::signature512::Owned>> { + pub fn get_signatures(self) -> ::capnp::Result<::capnp::struct_list::Builder<'a,crate::veilid_capnp::signature::Owned>> { ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) } #[inline] - pub fn set_signatures(&mut self, value: ::capnp::struct_list::Reader<'_,crate::veilid_capnp::signature512::Owned>) -> ::capnp::Result<()> { + pub fn set_signatures(&mut self, value: ::capnp::struct_list::Reader<'_,crate::veilid_capnp::signature::Owned>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) } #[inline] - pub fn init_signatures(self, size: u32) -> ::capnp::struct_list::Builder<'a,crate::veilid_capnp::signature512::Owned> { + pub fn init_signatures(self, size: u32) -> ::capnp::struct_list::Builder<'a,crate::veilid_capnp::signature::Owned> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), size) } #[inline] @@ -9392,15 +9554,15 @@ pub mod routed_operation { !self.builder.is_pointer_field_null(0) } #[inline] - pub fn get_nonce(self) -> ::capnp::Result> { + pub fn get_nonce(self) -> ::capnp::Result> { ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None) } #[inline] - pub fn set_nonce(&mut self, value: crate::veilid_capnp::nonce24::Reader<'_>) -> ::capnp::Result<()> { + pub fn set_nonce(&mut self, value: crate::veilid_capnp::nonce::Reader<'_>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false) } #[inline] - pub fn init_nonce(self, ) -> crate::veilid_capnp::nonce24::Builder<'a> { + pub fn init_nonce(self, ) -> crate::veilid_capnp::nonce::Builder<'a> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), 0) } #[inline] @@ -9432,19 +9594,19 @@ pub mod routed_operation { } } impl Pipeline { - pub fn get_nonce(&self) -> crate::veilid_capnp::nonce24::Pipeline { + pub fn get_nonce(&self) -> crate::veilid_capnp::nonce::Pipeline { ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(1)) } } mod _private { pub static ENCODED_NODE: [::capnp::Word; 86] = [ ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), - ::capnp::word(221, 233, 57, 184, 53, 133, 203, 203), + ::capnp::word(146, 170, 229, 47, 102, 230, 116, 160), ::capnp::word(19, 0, 0, 0, 1, 0, 1, 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(108, 42, 0, 0, 49, 44, 0, 0), + ::capnp::word(156, 40, 0, 0, 97, 42, 0, 0), ::capnp::word(21, 0, 0, 0, 26, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -9502,7 +9664,7 @@ pub mod routed_operation { ::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(18, 156, 18, 58, 4, 73, 103, 128), + ::capnp::word(162, 38, 135, 172, 226, 166, 111, 240), ::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), @@ -9510,7 +9672,7 @@ pub mod routed_operation { ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(110, 111, 110, 99, 101, 0, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(252, 125, 141, 93, 178, 13, 38, 182), + ::capnp::word(246, 89, 123, 183, 109, 134, 0, 155), ::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), @@ -9528,8 +9690,8 @@ pub mod routed_operation { pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { match index { 0 => ::introspect(), - 1 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), - 2 => ::introspect(), + 1 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), + 2 => ::introspect(), 3 => <::capnp::data::Owned as ::capnp::introspect::Introspect>::introspect(), _ => panic!("invalid field index {}", index), } @@ -9546,7 +9708,7 @@ pub mod routed_operation { pub static NONUNION_MEMBERS : &[u16] = &[0,1,2,3]; pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; pub static MEMBERS_BY_NAME : &[u16] = &[3,2,0,1]; - pub const TYPE_ID: u64 = 0xcbcb_8535_b839_e9dd; + pub const TYPE_ID: u64 = 0xa074_e666_2fe5_aa92; } } @@ -9710,7 +9872,7 @@ pub mod operation_status_q { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(51, 44, 0, 0, 210, 44, 0, 0), + ::capnp::word(99, 42, 0, 0, 2, 43, 0, 0), ::capnp::word(21, 0, 0, 0, 34, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -9950,7 +10112,7 @@ pub mod operation_status_a { ::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(212, 44, 0, 0, 222, 45, 0, 0), + ::capnp::word(4, 43, 0, 0, 14, 44, 0, 0), ::capnp::word(21, 0, 0, 0, 34, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -10216,7 +10378,7 @@ pub mod operation_validate_dial_info { ::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(224, 45, 0, 0, 72, 47, 0, 0), + ::capnp::word(16, 44, 0, 0, 120, 45, 0, 0), ::capnp::word(21, 0, 0, 0, 106, 1, 0, 0), ::capnp::word(41, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -10460,7 +10622,7 @@ pub mod operation_return_receipt { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(74, 47, 0, 0, 222, 47, 0, 0), + ::capnp::word(122, 45, 0, 0, 14, 46, 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), @@ -10575,7 +10737,7 @@ pub mod operation_find_node_q { self.reader.total_size() } #[inline] - pub fn get_node_id(self) -> ::capnp::Result> { + pub fn get_node_id(self) -> ::capnp::Result> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) } #[inline] @@ -10645,15 +10807,15 @@ pub mod operation_find_node_q { self.builder.as_reader().total_size() } #[inline] - pub fn get_node_id(self) -> ::capnp::Result> { + pub fn get_node_id(self) -> ::capnp::Result> { ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) } #[inline] - pub fn set_node_id(&mut self, value: crate::veilid_capnp::typed_key::Reader<'_>) -> ::capnp::Result<()> { + pub fn set_node_id(&mut self, value: crate::veilid_capnp::node_id::Reader<'_>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) } #[inline] - pub fn init_node_id(self, ) -> crate::veilid_capnp::typed_key::Builder<'a> { + pub fn init_node_id(self, ) -> crate::veilid_capnp::node_id::Builder<'a> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) } #[inline] @@ -10685,19 +10847,19 @@ pub mod operation_find_node_q { } } impl Pipeline { - pub fn get_node_id(&self) -> crate::veilid_capnp::typed_key::Pipeline { + pub fn get_node_id(&self) -> crate::veilid_capnp::node_id::Pipeline { ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) } } mod _private { pub static ENCODED_NODE: [::capnp::Word; 55] = [ ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), - ::capnp::word(205, 59, 98, 233, 143, 120, 239, 253), + ::capnp::word(202, 134, 157, 46, 96, 77, 82, 202), ::capnp::word(19, 0, 0, 0, 1, 0, 0, 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(224, 47, 0, 0, 202, 48, 0, 0), + ::capnp::word(16, 46, 0, 0, 246, 46, 0, 0), ::capnp::word(21, 0, 0, 0, 50, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -10727,7 +10889,7 @@ pub mod operation_find_node_q { ::capnp::word(72, 0, 0, 0, 2, 0, 1, 0), ::capnp::word(110, 111, 100, 101, 73, 100, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(41, 27, 230, 241, 169, 103, 213, 226), + ::capnp::word(187, 161, 188, 206, 241, 34, 152, 206), ::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), @@ -10749,7 +10911,7 @@ pub mod operation_find_node_q { ]; pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { match index { - 0 => ::introspect(), + 0 => ::introspect(), 1 => <::capnp::primitive_list::Owned as ::capnp::introspect::Introspect>::introspect(), _ => panic!("invalid field index {}", index), } @@ -10766,7 +10928,7 @@ pub mod operation_find_node_q { pub static NONUNION_MEMBERS : &[u16] = &[0,1]; pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; pub static MEMBERS_BY_NAME : &[u16] = &[1,0]; - pub const TYPE_ID: u64 = 0xfdef_788f_e962_3bcd; + pub const TYPE_ID: u64 = 0xca52_4d60_2e9d_86ca; } } @@ -10927,7 +11089,7 @@ pub mod operation_find_node_a { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(204, 48, 0, 0, 90, 49, 0, 0), + ::capnp::word(248, 46, 0, 0, 134, 47, 0, 0), ::capnp::word(21, 0, 0, 0, 50, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -10954,7 +11116,7 @@ pub mod operation_find_node_a { ::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(247, 219, 131, 213, 61, 235, 60, 179), ::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), @@ -11170,7 +11332,7 @@ pub mod operation_route { ::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(92, 49, 0, 0, 45, 50, 0, 0), + ::capnp::word(136, 47, 0, 0, 89, 48, 0, 0), ::capnp::word(21, 0, 0, 0, 18, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -11210,7 +11372,7 @@ pub mod operation_route { ::capnp::word(111, 112, 101, 114, 97, 116, 105, 111), ::capnp::word(110, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(221, 233, 57, 184, 53, 133, 203, 203), + ::capnp::word(146, 170, 229, 47, 102, 230, 116, 160), ::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), @@ -11397,7 +11559,7 @@ pub mod operation_app_call_q { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(47, 50, 0, 0, 183, 50, 0, 0), + ::capnp::word(91, 48, 0, 0, 227, 48, 0, 0), ::capnp::word(21, 0, 0, 0, 42, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -11606,7 +11768,7 @@ pub mod operation_app_call_a { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(185, 50, 0, 0, 68, 51, 0, 0), + ::capnp::word(229, 48, 0, 0, 112, 49, 0, 0), ::capnp::word(21, 0, 0, 0, 42, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -11815,7 +11977,7 @@ pub mod operation_app_message { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(70, 51, 0, 0, 208, 51, 0, 0), + ::capnp::word(114, 49, 0, 0, 252, 49, 0, 0), ::capnp::word(21, 0, 0, 0, 58, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -12024,7 +12186,7 @@ pub mod subkey_range { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(0, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(210, 51, 0, 0, 166, 52, 0, 0), + ::capnp::word(254, 49, 0, 0, 210, 50, 0, 0), ::capnp::word(21, 0, 0, 0, 250, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -12165,7 +12327,7 @@ pub mod signed_value_data { !self.reader.get_pointer_field(0).is_null() } #[inline] - pub fn get_writer(self) -> ::capnp::Result> { + pub fn get_writer(self) -> ::capnp::Result> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None) } #[inline] @@ -12173,7 +12335,7 @@ pub mod signed_value_data { !self.reader.get_pointer_field(1).is_null() } #[inline] - pub fn get_signature(self) -> ::capnp::Result> { + pub fn get_signature(self) -> ::capnp::Result> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(2), ::core::option::Option::None) } #[inline] @@ -12259,15 +12421,15 @@ pub mod signed_value_data { !self.builder.is_pointer_field_null(0) } #[inline] - pub fn get_writer(self) -> ::capnp::Result> { + pub fn get_writer(self) -> ::capnp::Result> { ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None) } #[inline] - pub fn set_writer(&mut self, value: crate::veilid_capnp::key256::Reader<'_>) -> ::capnp::Result<()> { + pub fn set_writer(&mut self, value: crate::veilid_capnp::public_key::Reader<'_>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false) } #[inline] - pub fn init_writer(self, ) -> crate::veilid_capnp::key256::Builder<'a> { + pub fn init_writer(self, ) -> crate::veilid_capnp::public_key::Builder<'a> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), 0) } #[inline] @@ -12275,15 +12437,15 @@ pub mod signed_value_data { !self.builder.is_pointer_field_null(1) } #[inline] - pub fn get_signature(self) -> ::capnp::Result> { + pub fn get_signature(self) -> ::capnp::Result> { ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(2), ::core::option::Option::None) } #[inline] - pub fn set_signature(&mut self, value: crate::veilid_capnp::signature512::Reader<'_>) -> ::capnp::Result<()> { + pub fn set_signature(&mut self, value: crate::veilid_capnp::signature::Reader<'_>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(2), value, false) } #[inline] - pub fn init_signature(self, ) -> crate::veilid_capnp::signature512::Builder<'a> { + pub fn init_signature(self, ) -> crate::veilid_capnp::signature::Builder<'a> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(2), 0) } #[inline] @@ -12299,22 +12461,22 @@ pub mod signed_value_data { } } impl Pipeline { - pub fn get_writer(&self) -> crate::veilid_capnp::key256::Pipeline { + pub fn get_writer(&self) -> crate::veilid_capnp::public_key::Pipeline { ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(1)) } - pub fn get_signature(&self) -> crate::veilid_capnp::signature512::Pipeline { + pub fn get_signature(&self) -> crate::veilid_capnp::signature::Pipeline { ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(2)) } } mod _private { pub static ENCODED_NODE: [::capnp::Word; 81] = [ ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), - ::capnp::word(61, 42, 159, 22, 111, 65, 183, 180), + ::capnp::word(24, 252, 247, 170, 239, 68, 57, 255), ::capnp::word(19, 0, 0, 0, 1, 0, 1, 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(172, 52, 0, 0, 199, 56, 0, 0), + ::capnp::word(216, 50, 0, 0, 251, 54, 0, 0), ::capnp::word(21, 0, 0, 0, 26, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -12374,7 +12536,7 @@ pub mod signed_value_data { ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(119, 114, 105, 116, 101, 114, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(13, 169, 246, 134, 50, 78, 228, 221), + ::capnp::word(238, 12, 243, 189, 45, 47, 82, 252), ::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), @@ -12383,7 +12545,7 @@ pub mod signed_value_data { ::capnp::word(115, 105, 103, 110, 97, 116, 117, 114), ::capnp::word(101, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(18, 156, 18, 58, 4, 73, 103, 128), + ::capnp::word(162, 38, 135, 172, 226, 166, 111, 240), ::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), @@ -12394,8 +12556,8 @@ pub mod signed_value_data { match index { 0 => ::introspect(), 1 => <::capnp::data::Owned as ::capnp::introspect::Introspect>::introspect(), - 2 => ::introspect(), - 3 => ::introspect(), + 2 => ::introspect(), + 3 => ::introspect(), _ => panic!("invalid field index {}", index), } } @@ -12411,7 +12573,7 @@ pub mod signed_value_data { pub static NONUNION_MEMBERS : &[u16] = &[0,1,2,3]; pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; pub static MEMBERS_BY_NAME : &[u16] = &[1,0,3,2]; - pub const TYPE_ID: u64 = 0xb4b7_416f_169f_2a3d; + pub const TYPE_ID: u64 = 0xff39_44ef_aaf7_fc18; } } @@ -12477,7 +12639,7 @@ pub mod signed_value_descriptor { self.reader.total_size() } #[inline] - pub fn get_owner(self) -> ::capnp::Result> { + pub fn get_owner(self) -> ::capnp::Result> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) } #[inline] @@ -12493,7 +12655,7 @@ pub mod signed_value_descriptor { !self.reader.get_pointer_field(1).is_null() } #[inline] - pub fn get_signature(self) -> ::capnp::Result> { + pub fn get_signature(self) -> ::capnp::Result> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(2), ::core::option::Option::None) } #[inline] @@ -12555,15 +12717,15 @@ pub mod signed_value_descriptor { self.builder.as_reader().total_size() } #[inline] - pub fn get_owner(self) -> ::capnp::Result> { + pub fn get_owner(self) -> ::capnp::Result> { ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) } #[inline] - pub fn set_owner(&mut self, value: crate::veilid_capnp::key256::Reader<'_>) -> ::capnp::Result<()> { + pub fn set_owner(&mut self, value: crate::veilid_capnp::public_key::Reader<'_>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) } #[inline] - pub fn init_owner(self, ) -> crate::veilid_capnp::key256::Builder<'a> { + pub fn init_owner(self, ) -> crate::veilid_capnp::public_key::Builder<'a> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) } #[inline] @@ -12587,15 +12749,15 @@ pub mod signed_value_descriptor { !self.builder.is_pointer_field_null(1) } #[inline] - pub fn get_signature(self) -> ::capnp::Result> { + pub fn get_signature(self) -> ::capnp::Result> { ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(2), ::core::option::Option::None) } #[inline] - pub fn set_signature(&mut self, value: crate::veilid_capnp::signature512::Reader<'_>) -> ::capnp::Result<()> { + pub fn set_signature(&mut self, value: crate::veilid_capnp::signature::Reader<'_>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(2), value, false) } #[inline] - pub fn init_signature(self, ) -> crate::veilid_capnp::signature512::Builder<'a> { + pub fn init_signature(self, ) -> crate::veilid_capnp::signature::Builder<'a> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(2), 0) } #[inline] @@ -12611,10 +12773,10 @@ pub mod signed_value_descriptor { } } impl Pipeline { - pub fn get_owner(&self) -> crate::veilid_capnp::key256::Pipeline { + pub fn get_owner(&self) -> crate::veilid_capnp::public_key::Pipeline { ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) } - pub fn get_signature(&self) -> crate::veilid_capnp::signature512::Pipeline { + pub fn get_signature(&self) -> crate::veilid_capnp::signature::Pipeline { ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(2)) } } @@ -12626,7 +12788,7 @@ pub mod signed_value_descriptor { ::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(201, 56, 0, 0, 179, 58, 0, 0), + ::capnp::word(253, 54, 0, 0, 231, 56, 0, 0), ::capnp::word(21, 0, 0, 0, 74, 1, 0, 0), ::capnp::word(41, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -12664,7 +12826,7 @@ pub mod signed_value_descriptor { ::capnp::word(92, 0, 0, 0, 2, 0, 1, 0), ::capnp::word(111, 119, 110, 101, 114, 0, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(13, 169, 246, 134, 50, 78, 228, 221), + ::capnp::word(238, 12, 243, 189, 45, 47, 82, 252), ::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), @@ -12682,7 +12844,7 @@ pub mod signed_value_descriptor { ::capnp::word(115, 105, 103, 110, 97, 116, 117, 114), ::capnp::word(101, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(18, 156, 18, 58, 4, 73, 103, 128), + ::capnp::word(162, 38, 135, 172, 226, 166, 111, 240), ::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), @@ -12691,9 +12853,9 @@ pub mod signed_value_descriptor { ]; pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { match index { - 0 => ::introspect(), + 0 => ::introspect(), 1 => <::capnp::data::Owned as ::capnp::introspect::Introspect>::introspect(), - 2 => ::introspect(), + 2 => ::introspect(), _ => panic!("invalid field index {}", index), } } @@ -12775,7 +12937,7 @@ pub mod operation_get_value_q { self.reader.total_size() } #[inline] - pub fn get_key(self) -> ::capnp::Result> { + pub fn get_key(self) -> ::capnp::Result> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) } #[inline] @@ -12845,15 +13007,15 @@ pub mod operation_get_value_q { self.builder.as_reader().total_size() } #[inline] - pub fn get_key(self) -> ::capnp::Result> { + pub fn get_key(self) -> ::capnp::Result> { ::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<()> { + pub fn set_key(&mut self, value: crate::veilid_capnp::record_key::Reader<'_>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::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> { + pub fn init_key(self, ) -> crate::veilid_capnp::record_key::Builder<'a> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) } #[inline] @@ -12885,19 +13047,19 @@ pub mod operation_get_value_q { } } impl Pipeline { - pub fn get_key(&self) -> crate::veilid_capnp::typed_key::Pipeline { + pub fn get_key(&self) -> crate::veilid_capnp::record_key::Pipeline { ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) } } mod _private { pub static ENCODED_NODE: [::capnp::Word; 66] = [ ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), - ::capnp::word(208, 165, 237, 165, 109, 91, 138, 248), + ::capnp::word(77, 162, 126, 81, 38, 109, 23, 140), ::capnp::word(19, 0, 0, 0, 1, 0, 1, 0), ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(182, 58, 0, 0, 29, 60, 0, 0), + ::capnp::word(234, 56, 0, 0, 81, 58, 0, 0), ::capnp::word(21, 0, 0, 0, 50, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -12934,7 +13096,7 @@ pub mod operation_get_value_q { ::capnp::word(88, 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(193, 176, 222, 152, 90, 71, 85, 205), ::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), @@ -12960,7 +13122,7 @@ pub mod operation_get_value_q { ]; pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { match index { - 0 => ::introspect(), + 0 => ::introspect(), 1 => ::introspect(), 2 => ::introspect(), _ => panic!("invalid field index {}", index), @@ -12978,7 +13140,7 @@ pub mod operation_get_value_q { pub static NONUNION_MEMBERS : &[u16] = &[0,1,2]; pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; pub static MEMBERS_BY_NAME : &[u16] = &[0,1,2]; - pub const TYPE_ID: u64 = 0xf88a_5b6d_a5ed_a5d0; + pub const TYPE_ID: u64 = 0x8c17_6d26_517e_a24d; } } @@ -13193,7 +13355,7 @@ pub mod operation_get_value_a { ::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(32, 60, 0, 0, 197, 61, 0, 0), + ::capnp::word(84, 58, 0, 0, 249, 59, 0, 0), ::capnp::word(21, 0, 0, 0, 50, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -13230,7 +13392,7 @@ pub mod operation_get_value_a { ::capnp::word(104, 0, 0, 0, 2, 0, 1, 0), ::capnp::word(118, 97, 108, 117, 101, 0, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(61, 42, 159, 22, 111, 65, 183, 180), + ::capnp::word(24, 252, 247, 170, 239, 68, 57, 255), ::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), @@ -13242,7 +13404,7 @@ pub mod operation_get_value_a { ::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(247, 219, 131, 213, 61, 235, 60, 179), ::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), @@ -13344,7 +13506,7 @@ pub mod operation_set_value_q { self.reader.total_size() } #[inline] - pub fn get_key(self) -> ::capnp::Result> { + pub fn get_key(self) -> ::capnp::Result> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) } #[inline] @@ -13426,15 +13588,15 @@ pub mod operation_set_value_q { self.builder.as_reader().total_size() } #[inline] - pub fn get_key(self) -> ::capnp::Result> { + pub fn get_key(self) -> ::capnp::Result> { ::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<()> { + pub fn set_key(&mut self, value: crate::veilid_capnp::record_key::Reader<'_>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::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> { + pub fn init_key(self, ) -> crate::veilid_capnp::record_key::Builder<'a> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) } #[inline] @@ -13490,7 +13652,7 @@ pub mod operation_set_value_q { } } impl Pipeline { - pub fn get_key(&self) -> crate::veilid_capnp::typed_key::Pipeline { + pub fn get_key(&self) -> crate::veilid_capnp::record_key::Pipeline { ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) } pub fn get_value(&self) -> crate::veilid_capnp::signed_value_data::Pipeline { @@ -13508,7 +13670,7 @@ pub mod operation_set_value_q { ::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(199, 61, 0, 0, 163, 63, 0, 0), + ::capnp::word(251, 59, 0, 0, 215, 61, 0, 0), ::capnp::word(21, 0, 0, 0, 50, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -13552,7 +13714,7 @@ pub mod operation_set_value_q { ::capnp::word(120, 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(193, 176, 222, 152, 90, 71, 85, 205), ::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), @@ -13568,7 +13730,7 @@ pub mod operation_set_value_q { ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(118, 97, 108, 117, 101, 0, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(61, 42, 159, 22, 111, 65, 183, 180), + ::capnp::word(24, 252, 247, 170, 239, 68, 57, 255), ::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), @@ -13586,7 +13748,7 @@ pub mod operation_set_value_q { ]; pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { match index { - 0 => ::introspect(), + 0 => ::introspect(), 1 => ::introspect(), 2 => ::introspect(), 3 => ::introspect(), @@ -13805,7 +13967,7 @@ pub mod operation_set_value_a { ::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(165, 63, 0, 0, 74, 65, 0, 0), + ::capnp::word(217, 61, 0, 0, 126, 63, 0, 0), ::capnp::word(21, 0, 0, 0, 50, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -13850,7 +14012,7 @@ pub mod operation_set_value_a { ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(118, 97, 108, 117, 101, 0, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(61, 42, 159, 22, 111, 65, 183, 180), + ::capnp::word(24, 252, 247, 170, 239, 68, 57, 255), ::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), @@ -13862,7 +14024,7 @@ pub mod operation_set_value_a { ::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(247, 219, 131, 213, 61, 235, 60, 179), ::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), @@ -13955,7 +14117,7 @@ pub mod operation_watch_value_q { self.reader.total_size() } #[inline] - pub fn get_key(self) -> ::capnp::Result> { + pub fn get_key(self) -> ::capnp::Result> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) } #[inline] @@ -13983,7 +14145,7 @@ pub mod operation_watch_value_q { self.reader.get_data_field::(2) } #[inline] - pub fn get_watcher(self) -> ::capnp::Result> { + pub fn get_watcher(self) -> ::capnp::Result> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(2), ::core::option::Option::None) } #[inline] @@ -13991,7 +14153,7 @@ pub mod operation_watch_value_q { !self.reader.get_pointer_field(2).is_null() } #[inline] - pub fn get_signature(self) -> ::capnp::Result> { + pub fn get_signature(self) -> ::capnp::Result> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(3), ::core::option::Option::None) } #[inline] @@ -14053,15 +14215,15 @@ pub mod operation_watch_value_q { self.builder.as_reader().total_size() } #[inline] - pub fn get_key(self) -> ::capnp::Result> { + pub fn get_key(self) -> ::capnp::Result> { ::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<()> { + pub fn set_key(&mut self, value: crate::veilid_capnp::record_key::Reader<'_>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::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> { + pub fn init_key(self, ) -> crate::veilid_capnp::record_key::Builder<'a> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) } #[inline] @@ -14109,15 +14271,15 @@ pub mod operation_watch_value_q { self.builder.set_data_field::(2, value); } #[inline] - pub fn get_watcher(self) -> ::capnp::Result> { + pub fn get_watcher(self) -> ::capnp::Result> { ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(2), ::core::option::Option::None) } #[inline] - pub fn set_watcher(&mut self, value: crate::veilid_capnp::key256::Reader<'_>) -> ::capnp::Result<()> { + pub fn set_watcher(&mut self, value: crate::veilid_capnp::public_key::Reader<'_>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(2), value, false) } #[inline] - pub fn init_watcher(self, ) -> crate::veilid_capnp::key256::Builder<'a> { + pub fn init_watcher(self, ) -> crate::veilid_capnp::public_key::Builder<'a> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(2), 0) } #[inline] @@ -14125,15 +14287,15 @@ pub mod operation_watch_value_q { !self.builder.is_pointer_field_null(2) } #[inline] - pub fn get_signature(self) -> ::capnp::Result> { + pub fn get_signature(self) -> ::capnp::Result> { ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(3), ::core::option::Option::None) } #[inline] - pub fn set_signature(&mut self, value: crate::veilid_capnp::signature512::Reader<'_>) -> ::capnp::Result<()> { + pub fn set_signature(&mut self, value: crate::veilid_capnp::signature::Reader<'_>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(3), value, false) } #[inline] - pub fn init_signature(self, ) -> crate::veilid_capnp::signature512::Builder<'a> { + pub fn init_signature(self, ) -> crate::veilid_capnp::signature::Builder<'a> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(3), 0) } #[inline] @@ -14149,13 +14311,13 @@ pub mod operation_watch_value_q { } } impl Pipeline { - pub fn get_key(&self) -> crate::veilid_capnp::typed_key::Pipeline { + pub fn get_key(&self) -> crate::veilid_capnp::record_key::Pipeline { ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) } - pub fn get_watcher(&self) -> crate::veilid_capnp::key256::Pipeline { + pub fn get_watcher(&self) -> crate::veilid_capnp::public_key::Pipeline { ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(2)) } - pub fn get_signature(&self) -> crate::veilid_capnp::signature512::Pipeline { + pub fn get_signature(&self) -> crate::veilid_capnp::signature::Pipeline { ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(3)) } } @@ -14167,7 +14329,7 @@ pub mod operation_watch_value_q { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(4, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(76, 65, 0, 0, 119, 69, 0, 0), + ::capnp::word(128, 63, 0, 0, 171, 67, 0, 0), ::capnp::word(21, 0, 0, 0, 66, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -14232,7 +14394,7 @@ pub mod operation_watch_value_q { ::capnp::word(236, 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(193, 176, 222, 152, 90, 71, 85, 205), ::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), @@ -14277,7 +14439,7 @@ pub mod operation_watch_value_q { ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(119, 97, 116, 99, 104, 101, 114, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(13, 169, 246, 134, 50, 78, 228, 221), + ::capnp::word(238, 12, 243, 189, 45, 47, 82, 252), ::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), @@ -14286,7 +14448,7 @@ pub mod operation_watch_value_q { ::capnp::word(115, 105, 103, 110, 97, 116, 117, 114), ::capnp::word(101, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(18, 156, 18, 58, 4, 73, 103, 128), + ::capnp::word(162, 38, 135, 172, 226, 166, 111, 240), ::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), @@ -14295,13 +14457,13 @@ pub mod operation_watch_value_q { ]; pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { match index { - 0 => ::introspect(), + 0 => ::introspect(), 1 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), 2 => ::introspect(), 3 => ::introspect(), 4 => ::introspect(), - 5 => ::introspect(), - 6 => ::introspect(), + 5 => ::introspect(), + 6 => ::introspect(), _ => panic!("invalid field index {}", index), } } @@ -14514,7 +14676,7 @@ pub mod operation_watch_value_a { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(121, 69, 0, 0, 188, 71, 0, 0), + ::capnp::word(173, 67, 0, 0, 240, 69, 0, 0), ::capnp::word(21, 0, 0, 0, 66, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -14580,7 +14742,7 @@ pub mod operation_watch_value_a { ::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(247, 219, 131, 213, 61, 235, 60, 179), ::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), @@ -14682,7 +14844,7 @@ pub mod operation_inspect_value_q { self.reader.total_size() } #[inline] - pub fn get_key(self) -> ::capnp::Result> { + pub fn get_key(self) -> ::capnp::Result> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) } #[inline] @@ -14756,15 +14918,15 @@ pub mod operation_inspect_value_q { self.builder.as_reader().total_size() } #[inline] - pub fn get_key(self) -> ::capnp::Result> { + pub fn get_key(self) -> ::capnp::Result> { ::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<()> { + pub fn set_key(&mut self, value: crate::veilid_capnp::record_key::Reader<'_>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::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> { + pub fn init_key(self, ) -> crate::veilid_capnp::record_key::Builder<'a> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) } #[inline] @@ -14804,7 +14966,7 @@ pub mod operation_inspect_value_q { } } impl Pipeline { - pub fn get_key(&self) -> crate::veilid_capnp::typed_key::Pipeline { + pub fn get_key(&self) -> crate::veilid_capnp::record_key::Pipeline { ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) } } @@ -14816,7 +14978,7 @@ pub mod operation_inspect_value_q { ::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(190, 71, 0, 0, 98, 73, 0, 0), + ::capnp::word(242, 69, 0, 0, 150, 71, 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), @@ -14854,7 +15016,7 @@ pub mod operation_inspect_value_q { ::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(193, 176, 222, 152, 90, 71, 85, 205), ::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), @@ -14884,7 +15046,7 @@ pub mod operation_inspect_value_q { ]; pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { match index { - 0 => ::introspect(), + 0 => ::introspect(), 1 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), 2 => ::introspect(), _ => panic!("invalid field index {}", index), @@ -15114,7 +15276,7 @@ pub mod operation_inspect_value_a { ::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(100, 73, 0, 0, 223, 75, 0, 0), + ::capnp::word(152, 71, 0, 0, 19, 74, 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), @@ -15168,7 +15330,7 @@ pub mod operation_inspect_value_a { ::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(247, 219, 131, 213, 61, 235, 60, 179), ::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), @@ -15270,7 +15432,7 @@ pub mod operation_value_changed { self.reader.total_size() } #[inline] - pub fn get_key(self) -> ::capnp::Result> { + pub fn get_key(self) -> ::capnp::Result> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) } #[inline] @@ -15356,15 +15518,15 @@ pub mod operation_value_changed { self.builder.as_reader().total_size() } #[inline] - pub fn get_key(self) -> ::capnp::Result> { + pub fn get_key(self) -> ::capnp::Result> { ::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<()> { + pub fn set_key(&mut self, value: crate::veilid_capnp::record_key::Reader<'_>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::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> { + pub fn init_key(self, ) -> crate::veilid_capnp::record_key::Builder<'a> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) } #[inline] @@ -15428,7 +15590,7 @@ pub mod operation_value_changed { } } impl Pipeline { - pub fn get_key(&self) -> crate::veilid_capnp::typed_key::Pipeline { + pub fn get_key(&self) -> crate::veilid_capnp::record_key::Pipeline { ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) } pub fn get_value(&self) -> crate::veilid_capnp::signed_value_data::Pipeline { @@ -15443,7 +15605,7 @@ pub mod operation_value_changed { ::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(225, 75, 0, 0, 87, 78, 0, 0), + ::capnp::word(21, 74, 0, 0, 139, 76, 0, 0), ::capnp::word(21, 0, 0, 0, 74, 1, 0, 0), ::capnp::word(41, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -15495,7 +15657,7 @@ pub mod operation_value_changed { ::capnp::word(164, 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(193, 176, 222, 152, 90, 71, 85, 205), ::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), @@ -15531,7 +15693,7 @@ pub mod operation_value_changed { ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(118, 97, 108, 117, 101, 0, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(61, 42, 159, 22, 111, 65, 183, 180), + ::capnp::word(24, 252, 247, 170, 239, 68, 57, 255), ::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), @@ -15540,7 +15702,7 @@ pub mod operation_value_changed { ]; pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { match index { - 0 => ::introspect(), + 0 => ::introspect(), 1 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), 2 => ::introspect(), 3 => ::introspect(), @@ -15626,18 +15788,26 @@ pub mod operation_supply_block_q { self.reader.total_size() } #[inline] - pub fn get_block_id(self) -> ::capnp::Result> { + pub fn get_block_id(self) -> ::capnp::Result> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) } #[inline] pub fn has_block_id(&self) -> bool { !self.reader.get_pointer_field(0).is_null() } + #[inline] + pub fn get_route_id(self) -> ::capnp::Result> { + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None) + } + #[inline] + pub fn has_route_id(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } } pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } impl <> ::capnp::traits::HasStructSize for Builder<'_,> { - const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 0, pointers: 1 }; + const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 0, pointers: 2 }; } impl <> ::capnp::traits::HasTypeId for Builder<'_,> { const TYPE_ID: u64 = _private::TYPE_ID; @@ -15688,21 +15858,37 @@ pub mod operation_supply_block_q { self.builder.as_reader().total_size() } #[inline] - pub fn get_block_id(self) -> ::capnp::Result> { + pub fn get_block_id(self) -> ::capnp::Result> { ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) } #[inline] - pub fn set_block_id(&mut self, value: crate::veilid_capnp::typed_key::Reader<'_>) -> ::capnp::Result<()> { + pub fn set_block_id(&mut self, value: crate::veilid_capnp::block_id::Reader<'_>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) } #[inline] - pub fn init_block_id(self, ) -> crate::veilid_capnp::typed_key::Builder<'a> { + pub fn init_block_id(self, ) -> crate::veilid_capnp::block_id::Builder<'a> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) } #[inline] pub fn has_block_id(&self) -> bool { !self.builder.is_pointer_field_null(0) } + #[inline] + pub fn get_route_id(self) -> ::capnp::Result> { + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None) + } + #[inline] + pub fn set_route_id(&mut self, value: crate::veilid_capnp::route_id::Reader<'_>) -> ::capnp::Result<()> { + ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false) + } + #[inline] + pub fn init_route_id(self, ) -> crate::veilid_capnp::route_id::Builder<'a> { + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), 0) + } + #[inline] + pub fn has_route_id(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } } pub struct Pipeline { _typeless: ::capnp::any_pointer::Pipeline } @@ -15712,23 +15898,26 @@ pub mod operation_supply_block_q { } } impl Pipeline { - pub fn get_block_id(&self) -> crate::veilid_capnp::typed_key::Pipeline { + pub fn get_block_id(&self) -> crate::veilid_capnp::block_id::Pipeline { ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) } + pub fn get_route_id(&self) -> crate::veilid_capnp::route_id::Pipeline { + ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(1)) + } } mod _private { - pub static ENCODED_NODE: [::capnp::Word; 36] = [ + pub static ENCODED_NODE: [::capnp::Word; 51] = [ ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), ::capnp::word(113, 153, 116, 45, 84, 76, 191, 173), ::capnp::word(19, 0, 0, 0, 1, 0, 0, 0), ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), - ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(2, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(89, 78, 0, 0, 231, 78, 0, 0), + ::capnp::word(141, 76, 0, 0, 136, 77, 0, 0), ::capnp::word(21, 0, 0, 0, 74, 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, 63, 0, 0, 0), + ::capnp::word(37, 0, 0, 0, 119, 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), @@ -15738,17 +15927,32 @@ pub mod operation_supply_block_q { ::capnp::word(108, 121, 66, 108, 111, 99, 107, 81), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), - ::capnp::word(4, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(8, 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(13, 0, 0, 0, 66, 0, 0, 0), + ::capnp::word(41, 0, 0, 0, 66, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(8, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(20, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(36, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(48, 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(45, 0, 0, 0, 66, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), ::capnp::word(98, 108, 111, 99, 107, 73, 100, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(41, 27, 230, 241, 169, 103, 213, 226), + ::capnp::word(34, 26, 119, 228, 169, 120, 54, 237), + ::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(114, 111, 117, 116, 101, 73, 100, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(230, 10, 218, 145, 109, 2, 174, 200), ::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), @@ -15757,7 +15961,8 @@ pub mod operation_supply_block_q { ]; pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { match index { - 0 => ::introspect(), + 0 => ::introspect(), + 1 => ::introspect(), _ => panic!("invalid field index {}", index), } } @@ -15770,9 +15975,9 @@ pub mod operation_supply_block_q { members_by_discriminant: MEMBERS_BY_DISCRIMINANT, members_by_name: MEMBERS_BY_NAME, }; - pub static NONUNION_MEMBERS : &[u16] = &[0]; + pub static NONUNION_MEMBERS : &[u16] = &[0,1]; pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; - pub static MEMBERS_BY_NAME : &[u16] = &[0]; + pub static MEMBERS_BY_NAME : &[u16] = &[0,1]; pub const TYPE_ID: u64 = 0xadbf_4c54_2d74_9971; } } @@ -15946,7 +16151,7 @@ pub mod operation_supply_block_a { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(233, 78, 0, 0, 29, 80, 0, 0), + ::capnp::word(138, 77, 0, 0, 190, 78, 0, 0), ::capnp::word(21, 0, 0, 0, 74, 1, 0, 0), ::capnp::word(41, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -15990,7 +16195,7 @@ pub mod operation_supply_block_a { ::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(247, 219, 131, 213, 61, 235, 60, 179), ::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), @@ -16082,7 +16287,7 @@ pub mod operation_find_block_q { self.reader.total_size() } #[inline] - pub fn get_block_id(self) -> ::capnp::Result> { + pub fn get_block_id(self) -> ::capnp::Result> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) } #[inline] @@ -16144,15 +16349,15 @@ pub mod operation_find_block_q { self.builder.as_reader().total_size() } #[inline] - pub fn get_block_id(self) -> ::capnp::Result> { + pub fn get_block_id(self) -> ::capnp::Result> { ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) } #[inline] - pub fn set_block_id(&mut self, value: crate::veilid_capnp::typed_key::Reader<'_>) -> ::capnp::Result<()> { + pub fn set_block_id(&mut self, value: crate::veilid_capnp::block_id::Reader<'_>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) } #[inline] - pub fn init_block_id(self, ) -> crate::veilid_capnp::typed_key::Builder<'a> { + pub fn init_block_id(self, ) -> crate::veilid_capnp::block_id::Builder<'a> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) } #[inline] @@ -16168,7 +16373,7 @@ pub mod operation_find_block_q { } } impl Pipeline { - pub fn get_block_id(&self) -> crate::veilid_capnp::typed_key::Pipeline { + pub fn get_block_id(&self) -> crate::veilid_capnp::block_id::Pipeline { ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(0)) } } @@ -16180,7 +16385,7 @@ pub mod operation_find_block_q { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(31, 80, 0, 0, 167, 80, 0, 0), + ::capnp::word(192, 78, 0, 0, 72, 79, 0, 0), ::capnp::word(21, 0, 0, 0, 58, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -16203,7 +16408,7 @@ pub mod operation_find_block_q { ::capnp::word(20, 0, 0, 0, 2, 0, 1, 0), ::capnp::word(98, 108, 111, 99, 107, 73, 100, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(41, 27, 230, 241, 169, 103, 213, 226), + ::capnp::word(34, 26, 119, 228, 169, 120, 54, 237), ::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), @@ -16212,7 +16417,7 @@ pub mod operation_find_block_q { ]; pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { match index { - 0 => ::introspect(), + 0 => ::introspect(), _ => panic!("invalid field index {}", index), } } @@ -16302,7 +16507,7 @@ pub mod operation_find_block_a { !self.reader.get_pointer_field(0).is_null() } #[inline] - pub fn get_suppliers(self) -> ::capnp::Result<::capnp::struct_list::Reader<'a,crate::veilid_capnp::peer_info::Owned>> { + pub fn get_suppliers(self) -> ::capnp::Result<::capnp::struct_list::Reader<'a,crate::veilid_capnp::route_id::Owned>> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None) } #[inline] @@ -16388,15 +16593,15 @@ pub mod operation_find_block_a { !self.builder.is_pointer_field_null(0) } #[inline] - pub fn get_suppliers(self) -> ::capnp::Result<::capnp::struct_list::Builder<'a,crate::veilid_capnp::peer_info::Owned>> { + pub fn get_suppliers(self) -> ::capnp::Result<::capnp::struct_list::Builder<'a,crate::veilid_capnp::route_id::Owned>> { ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None) } #[inline] - pub fn set_suppliers(&mut self, value: ::capnp::struct_list::Reader<'_,crate::veilid_capnp::peer_info::Owned>) -> ::capnp::Result<()> { + pub fn set_suppliers(&mut self, value: ::capnp::struct_list::Reader<'_,crate::veilid_capnp::route_id::Owned>) -> ::capnp::Result<()> { ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false) } #[inline] - pub fn init_suppliers(self, size: u32) -> ::capnp::struct_list::Builder<'a,crate::veilid_capnp::peer_info::Owned> { + pub fn init_suppliers(self, size: u32) -> ::capnp::struct_list::Builder<'a,crate::veilid_capnp::route_id::Owned> { ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), size) } #[inline] @@ -16437,7 +16642,7 @@ pub mod operation_find_block_a { ::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(169, 80, 0, 0, 122, 82, 0, 0), + ::capnp::word(74, 79, 0, 0, 44, 81, 0, 0), ::capnp::word(21, 0, 0, 0, 58, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -16487,7 +16692,7 @@ pub mod operation_find_block_a { ::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(230, 10, 218, 145, 109, 2, 174, 200), ::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), @@ -16499,7 +16704,7 @@ pub mod operation_find_block_a { ::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(247, 219, 131, 213, 61, 235, 60, 179), ::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), @@ -16509,7 +16714,7 @@ pub mod operation_find_block_a { pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { match index { 0 => <::capnp::data::Owned as ::capnp::introspect::Introspect>::introspect(), - 1 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), + 1 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), 2 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), _ => panic!("invalid field index {}", index), } @@ -16737,7 +16942,7 @@ pub mod operation_signal { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 2, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(124, 82, 0, 0, 45, 83, 0, 0), + ::capnp::word(46, 81, 0, 0, 223, 81, 0, 0), ::capnp::word(21, 0, 0, 0, 26, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -16851,7 +17056,7 @@ pub static ENCODED_NODE: [::capnp::Word; 28] = [ ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(47, 83, 0, 0, 233, 83, 0, 0), + ::capnp::word(225, 81, 0, 0, 155, 82, 0, 0), ::capnp::word(21, 0, 0, 0, 50, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -16921,7 +17126,7 @@ pub static ENCODED_NODE: [::capnp::Word; 38] = [ ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(235, 83, 0, 0, 91, 85, 0, 0), + ::capnp::word(157, 82, 0, 0, 13, 84, 0, 0), ::capnp::word(21, 0, 0, 0, 250, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -17025,7 +17230,7 @@ pub mod tunnel_endpoint { ::core::convert::TryInto::try_into(self.reader.get_data_field::(0)) } #[inline] - pub fn get_description(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { + pub fn get_description(self) -> ::capnp::Result<::capnp::data::Reader<'a>> { ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) } #[inline] @@ -17095,16 +17300,16 @@ pub mod tunnel_endpoint { self.builder.set_data_field::(0, value as u16); } #[inline] - pub fn get_description(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { + pub fn get_description(self) -> ::capnp::Result<::capnp::data::Builder<'a>> { ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) } #[inline] - pub fn set_description(&mut self, value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>) { - ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() + pub fn set_description(&mut self, value: ::capnp::data::Reader<'_>) { + self.builder.reborrow().get_pointer_field(0).set_data(value); } #[inline] - pub fn init_description(self, size: u32) -> ::capnp::text::Builder<'a> { - self.builder.get_pointer_field(0).init_text(size) + pub fn init_description(self, size: u32) -> ::capnp::data::Builder<'a> { + self.builder.get_pointer_field(0).init_data(size) } #[inline] pub fn has_description(&self) -> bool { @@ -17128,7 +17333,7 @@ pub mod tunnel_endpoint { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(93, 85, 0, 0, 56, 86, 0, 0), + ::capnp::word(15, 84, 0, 0, 234, 84, 0, 0), ::capnp::word(21, 0, 0, 0, 18, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -17166,18 +17371,18 @@ pub mod tunnel_endpoint { ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(100, 101, 115, 99, 114, 105, 112, 116), ::capnp::word(105, 111, 110, 0, 0, 0, 0, 0), - ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(13, 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(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(13, 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 => ::introspect(), - 1 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), + 1 => <::capnp::data::Owned as ::capnp::introspect::Introspect>::introspect(), _ => panic!("invalid field index {}", index), } } @@ -17408,7 +17613,7 @@ pub mod full_tunnel { ::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(58, 86, 0, 0, 207, 87, 0, 0), + ::capnp::word(236, 84, 0, 0, 129, 86, 0, 0), ::capnp::word(21, 0, 0, 0, 242, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -17691,7 +17896,7 @@ pub mod partial_tunnel { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(209, 87, 0, 0, 3, 89, 0, 0), + ::capnp::word(131, 86, 0, 0, 181, 87, 0, 0), ::capnp::word(21, 0, 0, 0, 10, 1, 0, 0), ::capnp::word(37, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -17944,7 +18149,7 @@ pub mod operation_start_tunnel_q { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(0, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(5, 89, 0, 0, 89, 90, 0, 0), + ::capnp::word(183, 87, 0, 0, 11, 89, 0, 0), ::capnp::word(21, 0, 0, 0, 74, 1, 0, 0), ::capnp::word(41, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -18222,7 +18427,7 @@ pub mod operation_start_tunnel_a { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 2, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(91, 90, 0, 0, 89, 91, 0, 0), + ::capnp::word(13, 89, 0, 0, 11, 90, 0, 0), ::capnp::word(21, 0, 0, 0, 74, 1, 0, 0), ::capnp::word(41, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -18493,7 +18698,7 @@ pub mod operation_complete_tunnel_q { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(91, 91, 0, 0, 12, 93, 0, 0), + ::capnp::word(13, 90, 0, 0, 190, 91, 0, 0), ::capnp::word(21, 0, 0, 0, 98, 1, 0, 0), ::capnp::word(41, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -18788,7 +18993,7 @@ pub mod operation_complete_tunnel_a { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 2, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(14, 93, 0, 0, 12, 94, 0, 0), + ::capnp::word(192, 91, 0, 0, 190, 92, 0, 0), ::capnp::word(21, 0, 0, 0, 98, 1, 0, 0), ::capnp::word(41, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -19008,7 +19213,7 @@ pub mod operation_cancel_tunnel_q { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(0, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(14, 94, 0, 0, 149, 94, 0, 0), + ::capnp::word(192, 92, 0, 0, 71, 93, 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), @@ -19238,7 +19443,7 @@ pub mod operation_cancel_tunnel_a { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(0, 0, 7, 0, 0, 0, 2, 0), ::capnp::word(4, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(151, 94, 0, 0, 146, 95, 0, 0), + ::capnp::word(73, 93, 0, 0, 68, 94, 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), @@ -19480,7 +19685,7 @@ pub mod question { ::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(177, 95, 0, 0, 24, 100, 0, 0), + ::capnp::word(99, 94, 0, 0, 234, 98, 0, 0), ::capnp::word(21, 0, 0, 0, 226, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -20228,7 +20433,7 @@ pub mod question { ::capnp::word(102, 105, 110, 100, 78, 111, 100, 101), ::capnp::word(81, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(205, 59, 98, 233, 143, 120, 239, 253), + ::capnp::word(202, 134, 157, 46, 96, 77, 82, 202), ::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), @@ -20246,7 +20451,7 @@ pub mod question { ::capnp::word(103, 101, 116, 86, 97, 108, 117, 101), ::capnp::word(81, 0, 0, 0, 0, 0, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(208, 165, 237, 165, 109, 91, 138, 248), + ::capnp::word(77, 162, 126, 81, 38, 109, 23, 140), ::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), @@ -20470,7 +20675,7 @@ pub mod statement { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(61, 100, 0, 0, 8, 102, 0, 0), + ::capnp::word(15, 99, 0, 0, 218, 100, 0, 0), ::capnp::word(21, 0, 0, 0, 234, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -21137,7 +21342,7 @@ pub mod answer { ::capnp::word(2, 171, 52, 55, 3, 232, 252, 143), ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(36, 102, 0, 0, 192, 105, 0, 0), + ::capnp::word(246, 100, 0, 0, 179, 104, 0, 0), ::capnp::word(21, 0, 0, 0, 210, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -21903,7 +22108,7 @@ pub mod operation { ::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(194, 105, 0, 0, 1, 108, 0, 0), + ::capnp::word(181, 104, 0, 0, 244, 106, 0, 0), ::capnp::word(21, 0, 0, 0, 234, 0, 0, 0), ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), @@ -21955,7 +22160,7 @@ pub mod operation { ::capnp::word(115, 101, 110, 100, 101, 114, 80, 101), ::capnp::word(101, 114, 73, 110, 102, 111, 0, 0), ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(203, 75, 60, 93, 45, 114, 45, 254), + ::capnp::word(247, 219, 131, 213, 61, 235, 60, 179), ::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), @@ -22327,6 +22532,6 @@ pub mod operation { } } -//BUILDHASH:d299ae03245f6c89b9bc93626cd5df415ad3ddf5fb23f9b4395809c1bba656e5 +//BUILDHASH:f35acc286a6f1b7d777c29c2ce83273d40dc6c01e5206a27834d99dc88988a2c //CAPNPDESIREDVERSIONHASH:7fbd210ebec11f65a97190ef900795c4b8da3805af3f5a1b8d1d272556b292ca diff --git a/veilid-core/src/crypto/crypto_system.rs b/veilid-core/src/crypto/crypto_system.rs index 3a29a3d3..07b945cc 100644 --- a/veilid-core/src/crypto/crypto_system.rs +++ b/veilid-core/src/crypto/crypto_system.rs @@ -16,7 +16,6 @@ pub trait CryptoSystem { // Generation fn random_bytes(&self, len: u32) -> Vec; - fn default_salt_length(&self) -> u32; fn hash_password(&self, password: &[u8], salt: &[u8]) -> VeilidAPIResult; fn verify_password(&self, password: &[u8], password_hash: &str) -> VeilidAPIResult; fn derive_shared_secret( @@ -38,9 +37,9 @@ pub trait CryptoSystem { domain: &[u8], ) -> VeilidAPIResult { let dh = self.compute_dh(key, secret)?; - Ok(BareSharedSecret::from(self.generate_hash( - &[&dh.bytes, domain, VEILID_DOMAIN_API].concat(), - ))) + Ok(BareSharedSecret::from( + self.generate_hash(&[&dh, domain, VEILID_DOMAIN_API].concat()), + )) } fn generate_keypair(&self) -> BareKeyPair; fn generate_hash(&self, data: &[u8]) -> BareHashDigest; @@ -50,6 +49,76 @@ pub trait CryptoSystem { ) -> VeilidAPIResult; // Validation + fn shared_secret_length(&self) -> usize; + fn nonce_length(&self) -> usize; + fn hash_digest_length(&self) -> usize; + fn public_key_length(&self) -> usize; + fn secret_key_length(&self) -> usize; + fn signature_length(&self) -> usize; + fn default_salt_length(&self) -> usize; + fn aead_overhead(&self) -> usize; + + fn check_shared_secret(&self, secret: &BareSharedSecret) -> VeilidAPIResult<()> { + if secret.len() != self.shared_secret_length() { + apibail_generic!(format!( + "invalid shared secret length: {} != {}", + secret.len(), + self.shared_secret_length() + )); + } + Ok(()) + } + fn check_nonce(&self, nonce: &BareNonce) -> VeilidAPIResult<()> { + if nonce.len() != self.nonce_length() { + apibail_generic!(format!( + "invalid nonce length: {} != {}", + nonce.len(), + self.nonce_length() + )); + } + Ok(()) + } + fn check_hash_digest(&self, hash: &BareHashDigest) -> VeilidAPIResult<()> { + if hash.len() != self.hash_digest_length() { + apibail_generic!(format!( + "invalid hash digest length: {} != {}", + hash.len(), + self.hash_digest_length() + )); + } + Ok(()) + } + fn check_public_key(&self, key: &BarePublicKey) -> VeilidAPIResult<()> { + if key.len() != self.public_key_length() { + apibail_generic!(format!( + "invalid public key length: {} != {}", + key.len(), + self.public_key_length() + )); + } + Ok(()) + } + fn check_secret_key(&self, key: &BareSecretKey) -> VeilidAPIResult<()> { + if key.len() != self.secret_key_length() { + apibail_generic!(format!( + "invalid secret key length: {} != {}", + key.len(), + self.secret_key_length() + )); + } + Ok(()) + } + fn check_signature(&self, signature: &BareSignature) -> VeilidAPIResult<()> { + if signature.len() != self.signature_length() { + apibail_generic!(format!( + "invalid signature length: {} != {}", + signature.len(), + self.signature_length() + )); + } + Ok(()) + } + fn validate_keypair(&self, key: &BarePublicKey, secret: &BareSecretKey) -> bool; fn validate_hash(&self, data: &[u8], hash: &BareHashDigest) -> bool; fn validate_hash_reader( @@ -76,7 +145,6 @@ pub trait CryptoSystem { ) -> VeilidAPIResult; // AEAD Encrypt/Decrypt - fn aead_overhead(&self) -> usize; fn decrypt_in_place_aead( &self, body: &mut Vec, @@ -112,24 +180,24 @@ pub trait CryptoSystem { body: &mut [u8], nonce: &BareNonce, shared_secret: &BareSharedSecret, - ); + ) -> VeilidAPIResult<()>; fn crypt_b2b_no_auth( &self, in_buf: &[u8], out_buf: &mut [u8], nonce: &BareNonce, shared_secret: &BareSharedSecret, - ); + ) -> VeilidAPIResult<()>; fn crypt_no_auth_aligned_8( &self, body: &[u8], nonce: &BareNonce, shared_secret: &BareSharedSecret, - ) -> Vec; + ) -> VeilidAPIResult>; fn crypt_no_auth_unaligned( &self, body: &[u8], nonce: &BareNonce, shared_secret: &BareSharedSecret, - ) -> Vec; + ) -> VeilidAPIResult>; } diff --git a/veilid-core/src/crypto/dh_cache.rs b/veilid-core/src/crypto/dh_cache.rs index d4274725..86b64c08 100644 --- a/veilid-core/src/crypto/dh_cache.rs +++ b/veilid-core/src/crypto/dh_cache.rs @@ -20,9 +20,9 @@ pub fn cache_to_bytes(cache: &DHCache) -> Vec { let cnt: usize = cache.len(); let mut out: Vec = Vec::with_capacity(cnt * (32 + 32 + 32)); for e in cache.iter() { - out.extend(&e.0.key.bytes); - out.extend(&e.0.secret.bytes); - out.extend(&e.1.shared_secret.bytes); + out.extend_from_slice(&e.0.key); + out.extend_from_slice(&e.0.secret); + out.extend_from_slice(&e.1.shared_secret); } let mut rev: Vec = Vec::with_capacity(out.len()); for d in out.chunks(32 + 32 + 32).rev() { diff --git a/veilid-core/src/crypto/envelope.rs b/veilid-core/src/crypto/envelope.rs index e49e8769..6e988253 100644 --- a/veilid-core/src/crypto/envelope.rs +++ b/veilid-core/src/crypto/envelope.rs @@ -130,32 +130,33 @@ impl Envelope { .into(); // Get nonce and sender node id - let nonce_slice: [u8; NONCE_LENGTH] = data[0x12..0x2A] + let mut nonce_slice: [u8; VLD0_NONCE_LENGTH] = data[0x12..0x2A] .try_into() .map_err(VeilidAPIError::internal)?; - let sender_id_slice: [u8; PUBLIC_KEY_LENGTH] = data[0x2A..0x4A] + let mut sender_id_slice: [u8; VLD0_HASH_DIGEST_LENGTH] = data[0x2A..0x4A] .try_into() .map_err(VeilidAPIError::internal)?; - let recipient_id_slice: [u8; PUBLIC_KEY_LENGTH] = data[0x4A..0x6A] + let mut recipient_id_slice: [u8; VLD0_HASH_DIGEST_LENGTH] = data[0x4A..0x6A] .try_into() .map_err(VeilidAPIError::internal)?; - let mut nonce: BareNonce = BareNonce::new(nonce_slice); - let mut sender_id = BareNodeId::new(sender_id_slice); - let mut recipient_id = BareNodeId::new(recipient_id_slice); // Apply network key (not the best, but it will keep networks from colliding without much overhead) if let Some(nk) = network_key.as_ref() { - for n in 0..NONCE_LENGTH { - nonce.bytes[n] ^= nk.bytes[n]; + for n in 0..VLD0_NONCE_LENGTH { + nonce_slice[n] ^= nk[n]; } - for n in 0..CRYPTO_KEY_LENGTH { - sender_id.bytes[n] ^= nk.bytes[n]; + for n in 0..VLD0_HASH_DIGEST_LENGTH { + sender_id_slice[n] ^= nk[n]; } - for n in 0..CRYPTO_KEY_LENGTH { - recipient_id.bytes[n] ^= nk.bytes[n]; + for n in 0..VLD0_HASH_DIGEST_LENGTH { + recipient_id_slice[n] ^= nk[n]; } } + let nonce: BareNonce = BareNonce::new(&nonce_slice); + let sender_id = BareNodeId::new(&sender_id_slice); + let recipient_id = BareNodeId::new(&recipient_id_slice); + // Ensure sender_id and recipient_id are not the same if sender_id == recipient_id { apibail_parse_error!( @@ -173,7 +174,11 @@ impl Envelope { // Validate signature if !vcrypto - .verify(&sender_id.into(), &data[0..(data.len() - 64)], &signature) + .verify( + &sender_id.clone().into(), + &data[0..(data.len() - 64)], + &signature, + ) .map_err(VeilidAPIError::internal)? { apibail_parse_error!("signature verification of envelope failed", signature); @@ -202,17 +207,24 @@ impl Envelope { let vcrypto = crypto .get(self.crypto_kind) .expect("need to ensure only valid crypto kinds here"); - let mut dh_secret = vcrypto.cached_dh(&self.sender_id.into(), node_id_secret)?; + let mut dh_secret = vcrypto.cached_dh(&self.sender_id.clone().into(), node_id_secret)?; // Apply network key if let Some(nk) = network_key.as_ref() { - for n in 0..CRYPTO_KEY_LENGTH { - dh_secret.bytes[n] ^= nk.bytes[n]; + let mut dh_secret_bytes = dh_secret.to_vec(); + + for n in 0..VLD0_SHARED_SECRET_LENGTH { + dh_secret_bytes[n] ^= nk[n]; } + + dh_secret = BareSharedSecret::new(&dh_secret_bytes); } // Decrypt message without authentication - let body = - vcrypto.crypt_no_auth_aligned_8(&data[0x6A..data.len() - 64], &self.nonce, &dh_secret); + let body = vcrypto.crypt_no_auth_aligned_8( + &data[0x6A..data.len() - 64], + &self.nonce, + &dh_secret, + )?; // Decompress body let body = decompress_size_prepended(&body, Some(MAX_ENVELOPE_SIZE))?; @@ -252,7 +264,7 @@ impl Envelope { let vcrypto = crypto .get(self.crypto_kind) .expect("need to ensure only valid crypto kinds here"); - let mut dh_secret = vcrypto.cached_dh(&self.recipient_id.into(), node_id_secret)?; + let mut dh_secret = vcrypto.cached_dh(&self.recipient_id.clone().into(), node_id_secret)?; // Write envelope body let mut data = vec![0u8; envelope_size]; @@ -268,30 +280,34 @@ impl Envelope { // Write timestamp data[0x0A..0x12].copy_from_slice(&self.timestamp.as_u64().to_le_bytes()); // Write nonce - data[0x12..0x2A].copy_from_slice(&self.nonce.bytes); + data[0x12..0x2A].copy_from_slice(&self.nonce); // Write sender node id - data[0x2A..0x4A].copy_from_slice(&self.sender_id.bytes); + data[0x2A..0x4A].copy_from_slice(&self.sender_id); // Write recipient node id - data[0x4A..0x6A].copy_from_slice(&self.recipient_id.bytes); + data[0x4A..0x6A].copy_from_slice(&self.recipient_id); // Apply network key (not the best, but it will keep networks from colliding without much overhead) if let Some(nk) = network_key.as_ref() { - for n in 0..SECRET_KEY_LENGTH { - dh_secret.bytes[n] ^= nk.bytes[n]; + let mut dh_secret_bytes = dh_secret.to_vec(); + + for n in 0..VLD0_SHARED_SECRET_LENGTH { + dh_secret_bytes[n] ^= nk[n]; } - for n in 0..NONCE_LENGTH { - data[0x12 + n] ^= nk.bytes[n]; + for n in 0..VLD0_NONCE_LENGTH { + data[0x12 + n] ^= nk[n]; } - for n in 0..CRYPTO_KEY_LENGTH { - data[0x2A + n] ^= nk.bytes[n]; + for n in 0..VLD0_HASH_DIGEST_LENGTH { + data[0x2A + n] ^= nk[n]; } - for n in 0..CRYPTO_KEY_LENGTH { - data[0x4A + n] ^= nk.bytes[n]; + for n in 0..VLD0_HASH_DIGEST_LENGTH { + data[0x4A + n] ^= nk[n]; } + + dh_secret = BareSharedSecret::new(&dh_secret_bytes); } // Encrypt message - let encrypted_body = vcrypto.crypt_no_auth_unaligned(&body, &self.nonce, &dh_secret); + let encrypted_body = vcrypto.crypt_no_auth_unaligned(&body, &self.nonce, &dh_secret)?; // Write body if !encrypted_body.is_empty() { @@ -300,13 +316,13 @@ impl Envelope { // Sign the envelope let signature = vcrypto.sign( - &self.sender_id.into(), + &self.sender_id.clone().into(), node_id_secret, &data[0..(envelope_size - 64)], )?; // Append the signature - data[(envelope_size - 64)..].copy_from_slice(&signature.bytes); + data[(envelope_size - 64)..].copy_from_slice(&signature); Ok(data) } @@ -326,24 +342,24 @@ impl Envelope { #[expect(dead_code)] pub fn get_nonce(&self) -> BareNonce { - self.nonce + self.nonce.clone() } #[expect(dead_code)] - pub fn get_sender_id(&self) -> BareNodeId { - self.sender_id + pub fn get_bare_sender_id(&self) -> BareNodeId { + self.sender_id.clone() } - pub fn get_sender_typed_id(&self) -> NodeId { - NodeId::new(self.crypto_kind, self.sender_id) + pub fn get_sender_id(&self) -> NodeId { + NodeId::new(self.crypto_kind, self.sender_id.clone()) } #[expect(dead_code)] - pub fn get_recipient_id(&self) -> BareNodeId { - self.recipient_id + pub fn get_bare_recipient_id(&self) -> BareNodeId { + self.recipient_id.clone() } - pub fn get_recipient_typed_id(&self) -> NodeId { - NodeId::new(self.crypto_kind, self.recipient_id) + pub fn get_recipient_id(&self) -> NodeId { + NodeId::new(self.crypto_kind, self.recipient_id.clone()) } } diff --git a/veilid-core/src/crypto/guard.rs b/veilid-core/src/crypto/guard.rs index 7c067dd1..2aecfa8a 100644 --- a/veilid-core/src/crypto/guard.rs +++ b/veilid-core/src/crypto/guard.rs @@ -62,10 +62,7 @@ impl AsyncCryptoSystemGuard<'_> { pub async fn random_bytes(&self, len: u32) -> Vec { yielding(|| self.guard.random_bytes(len)).await } - #[must_use] - pub fn default_salt_length(&self) -> u32 { - self.guard.default_salt_length() - } + pub async fn hash_password(&self, password: &[u8], salt: &[u8]) -> VeilidAPIResult { yielding(|| self.guard.hash_password(password, salt)).await } @@ -104,7 +101,7 @@ impl AsyncCryptoSystemGuard<'_> { ) -> VeilidAPIResult { let dh = self.compute_dh(key, secret).await?; Ok(BareSharedSecret::from( - self.generate_hash(&[&dh.bytes, domain, VEILID_DOMAIN_API].concat()) + self.generate_hash(&[&dh, domain, VEILID_DOMAIN_API].concat()) .await, )) } @@ -125,6 +122,56 @@ impl AsyncCryptoSystemGuard<'_> { } // Validation + #[must_use] + pub fn shared_secret_length(&self) -> usize { + self.guard.shared_secret_length() + } + #[must_use] + pub fn nonce_length(&self) -> usize { + self.guard.nonce_length() + } + #[must_use] + pub fn hash_digest_length(&self) -> usize { + self.guard.hash_digest_length() + } + #[must_use] + pub fn public_key_length(&self) -> usize { + self.guard.public_key_length() + } + #[must_use] + pub fn secret_key_length(&self) -> usize { + self.guard.secret_key_length() + } + #[must_use] + pub fn signature_length(&self) -> usize { + self.guard.signature_length() + } + #[must_use] + pub fn aead_overhead(&self) -> usize { + self.guard.aead_overhead() + } + #[must_use] + pub fn default_salt_length(&self) -> usize { + self.guard.default_salt_length() + } + pub fn check_shared_secret(&self, secret: &BareSharedSecret) -> VeilidAPIResult<()> { + self.guard.check_shared_secret(secret) + } + pub fn check_nonce(&self, nonce: &BareNonce) -> VeilidAPIResult<()> { + self.guard.check_nonce(nonce) + } + pub fn check_hash_digest(&self, hash: &BareHashDigest) -> VeilidAPIResult<()> { + self.guard.check_hash_digest(hash) + } + pub fn check_public_key(&self, key: &BarePublicKey) -> VeilidAPIResult<()> { + self.guard.check_public_key(key) + } + pub fn check_secret_key(&self, key: &BareSecretKey) -> VeilidAPIResult<()> { + self.guard.check_secret_key(key) + } + pub fn check_signature(&self, signature: &BareSignature) -> VeilidAPIResult<()> { + self.guard.check_signature(signature) + } pub async fn validate_keypair(&self, key: &BarePublicKey, secret: &BareSecretKey) -> bool { yielding(|| self.guard.validate_keypair(key, secret)).await } @@ -165,11 +212,6 @@ impl AsyncCryptoSystemGuard<'_> { } // AEAD Encrypt/Decrypt - #[must_use] - pub fn aead_overhead(&self) -> usize { - self.guard.aead_overhead() - } - pub async fn decrypt_in_place_aead( &self, body: &mut Vec, @@ -232,7 +274,7 @@ impl AsyncCryptoSystemGuard<'_> { body: &mut [u8], nonce: &BareNonce, shared_secret: &BareSharedSecret, - ) { + ) -> VeilidAPIResult<()> { yielding(|| { self.guard .crypt_in_place_no_auth(body, nonce, shared_secret) @@ -246,7 +288,7 @@ impl AsyncCryptoSystemGuard<'_> { out_buf: &mut [u8], nonce: &BareNonce, shared_secret: &BareSharedSecret, - ) { + ) -> VeilidAPIResult<()> { yielding(|| { self.guard .crypt_b2b_no_auth(in_buf, out_buf, nonce, shared_secret) @@ -259,7 +301,7 @@ impl AsyncCryptoSystemGuard<'_> { body: &[u8], nonce: &BareNonce, shared_secret: &BareSharedSecret, - ) -> Vec { + ) -> VeilidAPIResult> { yielding(|| { self.guard .crypt_no_auth_aligned_8(body, nonce, shared_secret) @@ -272,7 +314,7 @@ impl AsyncCryptoSystemGuard<'_> { body: &[u8], nonce: &BareNonce, shared_secret: &BareSharedSecret, - ) -> Vec { + ) -> VeilidAPIResult> { yielding(|| { self.guard .crypt_no_auth_unaligned(body, nonce, shared_secret) diff --git a/veilid-core/src/crypto/mod.rs b/veilid-core/src/crypto/mod.rs index 51939015..91d12372 100644 --- a/veilid-core/src/crypto/mod.rs +++ b/veilid-core/src/crypto/mod.rs @@ -8,6 +8,7 @@ mod types; pub mod crypto_system; #[cfg(feature = "enable-crypto-none")] pub(crate) mod none; + #[doc(hidden)] pub mod tests; #[cfg(feature = "enable-crypto-vld0")] @@ -22,11 +23,11 @@ pub(crate) use receipt::*; pub use types::*; #[cfg(feature = "enable-crypto-none")] -pub use none::CRYPTO_KIND_NONE; +pub use none::sizes::*; #[cfg(feature = "enable-crypto-none")] pub(crate) use none::*; #[cfg(feature = "enable-crypto-vld0")] -pub use vld0::CRYPTO_KIND_VLD0; +pub use vld0::sizes::*; #[cfg(feature = "enable-crypto-vld0")] pub(crate) use vld0::*; @@ -70,6 +71,7 @@ pub type EnvelopeVersion = u8; pub const VALID_ENVELOPE_VERSIONS: [EnvelopeVersion; 1] = [0u8]; /// Number of envelope versions to keep on structures if many are present beyond the ones we consider valid pub const MAX_ENVELOPE_VERSIONS: usize = 3; + /// Return the best envelope version we support #[must_use] pub fn best_envelope_version() -> EnvelopeVersion { @@ -154,7 +156,7 @@ impl Crypto { self.config().with(|c| { for ck in VALID_CRYPTO_KINDS { if let Some(nid) = c.network.routing_table.node_id.get(ck) { - cache_validity_key.append(&mut nid.value.bytes.to_vec()); + cache_validity_key.extend_from_slice(nid.ref_value()); } } }); @@ -270,12 +272,12 @@ impl Crypto { let mut out = PublicKeyGroup::with_capacity(public_keys.len()); for sig in typed_signatures { for nid in public_keys { - if nid.kind == sig.kind { - if let Some(vcrypto) = self.get(sig.kind) { - if !vcrypto.verify(&nid.value, data, &sig.value)? { + if nid.kind() == sig.kind() { + if let Some(vcrypto) = self.get(sig.kind()) { + if !vcrypto.verify(nid.ref_value(), data, sig.ref_value())? { return Ok(None); } - out.add(*nid); + out.add(nid.clone()); } } } @@ -297,8 +299,9 @@ impl Crypto { { let mut out = Vec::::with_capacity(typed_key_pairs.len()); for kp in typed_key_pairs { - if let Some(vcrypto) = self.get(kp.kind) { - let sig = vcrypto.sign(&kp.value.key, &kp.value.secret, data)?; + if let Some(vcrypto) = self.get(kp.kind()) { + let sig = + vcrypto.sign(kp.ref_value().ref_key(), kp.ref_value().ref_secret(), data)?; out.push(transform(kp, sig)) } } @@ -331,13 +334,15 @@ impl Crypto { ) -> VeilidAPIResult { Ok( match self.inner.lock().dh_cache.entry(DHCacheKey { - key: *key, - secret: *secret, + key: key.clone(), + secret: secret.clone(), }) { - Entry::Occupied(e) => e.get().shared_secret, + Entry::Occupied(e) => e.get().shared_secret.clone(), Entry::Vacant(e) => { let shared_secret = vcrypto.compute_dh(key, secret)?; - e.insert(DHCacheValue { shared_secret }); + e.insert(DHCacheValue { + shared_secret: shared_secret.clone(), + }); shared_secret } }, @@ -404,7 +409,7 @@ impl Crypto { if let (Some(node_id), Some(node_id_secret)) = (node_id, node_id_secret) { // Validate node id if !vcrypto - .validate_keypair(&node_id.value.into(), &node_id_secret.value) + .validate_keypair(&node_id.value().into(), &node_id_secret.value()) .await { apibail_generic!(format!( @@ -418,8 +423,8 @@ impl Crypto { veilid_log!(self debug "generating new node_id_{}", ck); let kp = vcrypto.generate_keypair().await; ( - NodeId::new(ck, kp.key.into()), - SecretKey::new(ck, kp.secret), + NodeId::new(ck, kp.key().into()), + SecretKey::new(ck, kp.secret()), ) }; veilid_log!(self info "Node Id: {}", node_id); @@ -451,8 +456,8 @@ impl Crypto { let (node_id, node_id_secret) = { let kp = vcrypto.generate_keypair().await; ( - NodeId::new(ck, kp.key.into()), - SecretKey::new(ck, kp.secret), + NodeId::new(ck, kp.key().into()), + SecretKey::new(ck, kp.secret()), ) }; #[cfg(not(test))] diff --git a/veilid-core/src/crypto/none/mod.rs b/veilid-core/src/crypto/none/mod.rs index a67d8c68..ce223e9a 100644 --- a/veilid-core/src/crypto/none/mod.rs +++ b/veilid-core/src/crypto/none/mod.rs @@ -1,51 +1,72 @@ +pub mod sizes; + use super::*; use argon2::password_hash::Salt; use data_encoding::BASE64URL_NOPAD; use digest::rand_core::RngCore; use digest::Digest; -const AEAD_OVERHEAD: usize = PUBLIC_KEY_LENGTH; +const NONE_AEAD_OVERHEAD: usize = NONE_PUBLIC_KEY_LENGTH; pub const CRYPTO_KIND_NONE: CryptoKind = CryptoKind(*b"NONE"); +pub use sizes::*; pub fn none_generate_keypair() -> BareKeyPair { let mut csprng = VeilidRng {}; - let mut pub_bytes = [0u8; PUBLIC_KEY_LENGTH]; - let mut sec_bytes = [0u8; SECRET_KEY_LENGTH]; + let mut pub_bytes = [0u8; NONE_PUBLIC_KEY_LENGTH]; + let mut sec_bytes = [0u8; NONE_SECRET_KEY_LENGTH]; csprng.fill_bytes(&mut pub_bytes); - for n in 0..PUBLIC_KEY_LENGTH { + for n in 0..NONE_PUBLIC_KEY_LENGTH { sec_bytes[n] = !pub_bytes[n]; } - let dht_key = BarePublicKey::new(pub_bytes); - let dht_key_secret = BareSecretKey::new(sec_bytes); + let dht_key = BarePublicKey::new(&pub_bytes); + let dht_key_secret = BareSecretKey::new(&sec_bytes); BareKeyPair::new(dht_key, dht_key_secret) } -fn do_xor_32(a: &[u8], b: &[u8]) -> [u8; 32] { +fn do_xor_32(a: &[u8], b: &[u8]) -> VeilidAPIResult<[u8; 32]> { + if a.len() != 32 || b.len() != 32 { + apibail_generic!("wrong key length"); + } let mut out = [0u8; 32]; for n in 0..32 { out[n] = a[n] ^ b[n]; } - out + Ok(out) } -fn do_xor_inplace(a: &mut [u8], key: &[u8]) { +fn do_xor_inplace(a: &mut [u8], key: &[u8]) -> VeilidAPIResult<()> { + if a.len() != 32 || key.is_empty() { + apibail_generic!("wrong key length"); + } for n in 0..a.len() { a[n] ^= key[n % key.len()]; } + + Ok(()) } -fn do_xor_b2b(a: &[u8], b: &mut [u8], key: &[u8]) { +fn do_xor_b2b(a: &[u8], b: &mut [u8], key: &[u8]) -> VeilidAPIResult<()> { + if a.len() != 32 || b.len() != 32 || key.is_empty() { + apibail_generic!("wrong key length"); + } + for n in 0..a.len() { b[n] = a[n] ^ key[n % key.len()]; } + + Ok(()) } -fn is_bytes_eq_32(a: &[u8], v: u8) -> bool { +fn is_bytes_eq_32(a: &[u8], v: u8) -> VeilidAPIResult { + if a.len() != 32 { + apibail_generic!("wrong key length"); + } + for n in 0..32 { if a[n] != v { - return false; + return Ok(false); } } - true + Ok(true) } /// None CryptoSystem @@ -86,9 +107,6 @@ impl CryptoSystem for CryptoSystemNONE { random_bytes(bytes.as_mut()); bytes } - fn default_salt_length(&self) -> u32 { - 4 - } fn hash_password(&self, password: &[u8], salt: &[u8]) -> VeilidAPIResult { if salt.len() < Salt::MIN_LENGTH || salt.len() > Salt::MAX_LENGTH { apibail_generic!("invalid salt length"); @@ -106,7 +124,7 @@ impl CryptoSystem for CryptoSystemNONE { let Ok(salt) = BASE64URL_NOPAD.decode(salt.as_bytes()) else { apibail_generic!("invalid salt"); }; - return Ok(&self.hash_password(password, &salt)? == password_hash); + Ok(self.hash_password(password, &salt)? == password_hash) } fn derive_shared_secret( @@ -118,33 +136,33 @@ impl CryptoSystem for CryptoSystemNONE { apibail_generic!("invalid salt length"); } Ok(BareSharedSecret::new( - *blake3::hash(self.hash_password(password, salt)?.as_bytes()).as_bytes(), + blake3::hash(self.hash_password(password, salt)?.as_bytes()).as_bytes(), )) } fn random_nonce(&self) -> BareNonce { - let mut nonce = [0u8; NONCE_LENGTH]; + let mut nonce = [0u8; NONE_NONCE_LENGTH]; random_bytes(&mut nonce); - BareNonce::new(nonce) + BareNonce::new(&nonce) } fn random_shared_secret(&self) -> BareSharedSecret { - let mut s = [0u8; SHARED_SECRET_LENGTH]; + let mut s = [0u8; NONE_SHARED_SECRET_LENGTH]; random_bytes(&mut s); - BareSharedSecret::new(s) + BareSharedSecret::new(&s) } fn compute_dh( &self, key: &BarePublicKey, secret: &BareSecretKey, ) -> VeilidAPIResult { - let s = do_xor_32(&key.bytes, &secret.bytes); - Ok(BareSharedSecret::new(s)) + let s = do_xor_32(key, secret)?; + Ok(BareSharedSecret::new(&s)) } fn generate_keypair(&self) -> BareKeyPair { none_generate_keypair() } fn generate_hash(&self, data: &[u8]) -> BareHashDigest { - BareHashDigest::new(*blake3::hash(data).as_bytes()) + BareHashDigest::new(blake3::hash(data).as_bytes()) } fn generate_hash_reader( &self, @@ -152,10 +170,35 @@ impl CryptoSystem for CryptoSystemNONE { ) -> VeilidAPIResult { let mut hasher = blake3::Hasher::new(); std::io::copy(reader, &mut hasher).map_err(VeilidAPIError::generic)?; - Ok(BarePublicKey::new(*hasher.finalize().as_bytes())) + Ok(BarePublicKey::new(hasher.finalize().as_bytes())) } // Validation + fn default_salt_length(&self) -> usize { + 4 + } + fn shared_secret_length(&self) -> usize { + NONE_SHARED_SECRET_LENGTH + } + fn nonce_length(&self) -> usize { + NONE_NONCE_LENGTH + } + fn hash_digest_length(&self) -> usize { + NONE_HASH_DIGEST_LENGTH + } + fn aead_overhead(&self) -> usize { + NONE_AEAD_OVERHEAD + } + fn public_key_length(&self) -> usize { + NONE_PUBLIC_KEY_LENGTH + } + fn secret_key_length(&self) -> usize { + NONE_SECRET_KEY_LENGTH + } + fn signature_length(&self) -> usize { + NONE_SIGNATURE_LENGTH + } + fn validate_keypair(&self, dht_key: &BarePublicKey, dht_key_secret: &BareSecretKey) -> bool { let data = vec![0u8; 512]; let Ok(sig) = self.sign(dht_key, dht_key_secret, &data) else { @@ -168,7 +211,7 @@ impl CryptoSystem for CryptoSystemNONE { } fn validate_hash(&self, data: &[u8], dht_key: &BareHashDigest) -> bool { let bytes = *blake3::hash(data).as_bytes(); - bytes == dht_key.bytes + bytes == dht_key.bytes() } fn validate_hash_reader( &self, @@ -178,17 +221,17 @@ impl CryptoSystem for CryptoSystemNONE { let mut hasher = blake3::Hasher::new(); std::io::copy(reader, &mut hasher).map_err(VeilidAPIError::generic)?; let bytes = *hasher.finalize().as_bytes(); - Ok(bytes == dht_key.bytes) + Ok(bytes == dht_key.bytes()) } // Distance Metric fn distance(&self, key1: &BareHashDigest, key2: &BareHashDigest) -> BareHashDistance { - let mut bytes = [0u8; HASH_DIGEST_LENGTH]; + let mut bytes = [0u8; NONE_HASH_DIGEST_LENGTH]; for (n, byte) in bytes.iter_mut().enumerate() { - *byte = key1.bytes[n] ^ key2.bytes[n]; + *byte = key1[n] ^ key2[n]; } - BareHashDistance::new(bytes) + BareHashDistance::new(&bytes) } // Authentication @@ -198,7 +241,7 @@ impl CryptoSystem for CryptoSystemNONE { dht_key_secret: &BareSecretKey, data: &[u8], ) -> VeilidAPIResult { - if !is_bytes_eq_32(&do_xor_32(&dht_key.bytes, &dht_key_secret.bytes), 0xFFu8) { + if !is_bytes_eq_32(&do_xor_32(dht_key, dht_key_secret)?, 0xFFu8)? { return Err(VeilidAPIError::parse_error( "Keypair is invalid", "invalid keys", @@ -208,14 +251,15 @@ impl CryptoSystem for CryptoSystemNONE { let mut dig = Blake3Digest512::new(); dig.update(data); let sig = dig.finalize(); - let in_sig_bytes: [u8; SIGNATURE_LENGTH] = sig.into(); - let mut sig_bytes = [0u8; SIGNATURE_LENGTH]; + let in_sig_bytes: [u8; NONE_SIGNATURE_LENGTH] = sig.into(); + let mut sig_bytes = [0u8; NONE_SIGNATURE_LENGTH]; sig_bytes[0..32].copy_from_slice(&in_sig_bytes[0..32]); - sig_bytes[32..64].copy_from_slice(&do_xor_32(&in_sig_bytes[32..64], &dht_key_secret.bytes)); - let dht_sig = BareSignature::new(sig_bytes.into()); + sig_bytes[32..64].copy_from_slice(&do_xor_32(&in_sig_bytes[32..64], dht_key_secret)?); + let dht_sig = BareSignature::new(&sig_bytes); println!("DEBUG dht_sig: {:?}", dht_sig); Ok(dht_sig) } + fn verify( &self, dht_key: &BarePublicKey, @@ -225,27 +269,23 @@ impl CryptoSystem for CryptoSystemNONE { let mut dig = Blake3Digest512::new(); dig.update(data); let sig = dig.finalize(); - let in_sig_bytes: [u8; SIGNATURE_LENGTH] = sig.into(); - let mut verify_bytes = [0u8; SIGNATURE_LENGTH]; - verify_bytes[0..32] - .copy_from_slice(&do_xor_32(&in_sig_bytes[0..32], &signature.bytes[0..32])); + let in_sig_bytes: [u8; NONE_SIGNATURE_LENGTH] = sig.into(); + let mut verify_bytes = [0u8; NONE_SIGNATURE_LENGTH]; + verify_bytes[0..32].copy_from_slice(&do_xor_32(&in_sig_bytes[0..32], &signature[0..32])?); verify_bytes[32..64] - .copy_from_slice(&do_xor_32(&in_sig_bytes[32..64], &signature.bytes[32..64])); + .copy_from_slice(&do_xor_32(&in_sig_bytes[32..64], &signature[32..64])?); - if !is_bytes_eq_32(&verify_bytes[0..32], 0u8) { + if !is_bytes_eq_32(&verify_bytes[0..32], 0u8)? { return Ok(false); } - if !is_bytes_eq_32(&do_xor_32(&verify_bytes[32..64], &dht_key.bytes), 0xFFu8) { + if !is_bytes_eq_32(&do_xor_32(&verify_bytes[32..64], dht_key)?, 0xFFu8)? { return Ok(false); } - return Ok(true); + Ok(true) } // AEAD Encrypt/Decrypt - fn aead_overhead(&self) -> usize { - AEAD_OVERHEAD - } fn decrypt_in_place_aead( &self, body: &mut Vec, @@ -253,19 +293,18 @@ impl CryptoSystem for CryptoSystemNONE { shared_secret: &BareSharedSecret, _associated_data: Option<&[u8]>, ) -> VeilidAPIResult<()> { - let mut blob = nonce.bytes.to_vec(); + let mut blob = nonce.to_vec(); blob.extend_from_slice(&[0u8; 8]); - let blob = do_xor_32(&blob, &shared_secret.bytes); + let blob = do_xor_32(&blob, shared_secret)?; - if body.len() < AEAD_OVERHEAD { + if body.len() < NONE_AEAD_OVERHEAD { return Err(VeilidAPIError::generic("invalid length")); } - if &body[body.len() - AEAD_OVERHEAD..] != &blob { + if body[body.len() - NONE_AEAD_OVERHEAD..] != blob { return Err(VeilidAPIError::generic("invalid keyblob")); } - body.truncate(body.len() - AEAD_OVERHEAD); - do_xor_inplace(body, &blob); - Ok(()) + body.truncate(body.len() - NONE_AEAD_OVERHEAD); + do_xor_inplace(body, &blob) } fn decrypt_aead( @@ -289,10 +328,10 @@ impl CryptoSystem for CryptoSystemNONE { shared_secret: &BareSharedSecret, _associated_data: Option<&[u8]>, ) -> VeilidAPIResult<()> { - let mut blob = nonce.bytes.to_vec(); + let mut blob = nonce.to_vec(); blob.extend_from_slice(&[0u8; 8]); - let blob = do_xor_32(&blob, &shared_secret.bytes); - do_xor_inplace(body, &blob); + let blob = do_xor_32(&blob, shared_secret)?; + do_xor_inplace(body, &blob)?; body.append(&mut blob.to_vec()); Ok(()) } @@ -317,11 +356,11 @@ impl CryptoSystem for CryptoSystemNONE { body: &mut [u8], nonce: &BareNonce, shared_secret: &BareSharedSecret, - ) { - let mut blob = nonce.bytes.to_vec(); + ) -> VeilidAPIResult<()> { + let mut blob = nonce.to_vec(); blob.extend_from_slice(&[0u8; 8]); - let blob = do_xor_32(&blob, &shared_secret.bytes); - do_xor_inplace(body, &blob); + let blob = do_xor_32(&blob, shared_secret)?; + do_xor_inplace(body, &blob) } fn crypt_b2b_no_auth( @@ -330,11 +369,11 @@ impl CryptoSystem for CryptoSystemNONE { out_buf: &mut [u8], nonce: &BareNonce, shared_secret: &BareSharedSecret, - ) { - let mut blob = nonce.bytes.to_vec(); + ) -> VeilidAPIResult<()> { + let mut blob = nonce.to_vec(); blob.extend_from_slice(&[0u8; 8]); - let blob = do_xor_32(&blob, &shared_secret.bytes); - do_xor_b2b(in_buf, out_buf, &blob); + let blob = do_xor_32(&blob, shared_secret)?; + do_xor_b2b(in_buf, out_buf, &blob) } fn crypt_no_auth_aligned_8( @@ -342,10 +381,10 @@ impl CryptoSystem for CryptoSystemNONE { in_buf: &[u8], nonce: &BareNonce, shared_secret: &BareSharedSecret, - ) -> Vec { + ) -> VeilidAPIResult> { let mut out_buf = unsafe { aligned_8_u8_vec_uninit(in_buf.len()) }; - self.crypt_b2b_no_auth(in_buf, &mut out_buf, nonce, shared_secret); - out_buf + self.crypt_b2b_no_auth(in_buf, &mut out_buf, nonce, shared_secret)?; + Ok(out_buf) } fn crypt_no_auth_unaligned( @@ -353,9 +392,9 @@ impl CryptoSystem for CryptoSystemNONE { in_buf: &[u8], nonce: &BareNonce, shared_secret: &BareSharedSecret, - ) -> Vec { + ) -> VeilidAPIResult> { let mut out_buf = unsafe { unaligned_u8_vec_uninit(in_buf.len()) }; - self.crypt_b2b_no_auth(in_buf, &mut out_buf, nonce, shared_secret); - out_buf + self.crypt_b2b_no_auth(in_buf, &mut out_buf, nonce, shared_secret)?; + Ok(out_buf) } } diff --git a/veilid-core/src/crypto/none/sizes.rs b/veilid-core/src/crypto/none/sizes.rs new file mode 100644 index 00000000..b744e5f4 --- /dev/null +++ b/veilid-core/src/crypto/none/sizes.rs @@ -0,0 +1,12 @@ +/// Length of a crypto key in bytes +pub const NONE_PUBLIC_KEY_LENGTH: usize = 32; +/// Length of a secret key in bytes +pub const NONE_SECRET_KEY_LENGTH: usize = 32; +/// Length of a signature in bytes +pub const NONE_SIGNATURE_LENGTH: usize = 64; +/// Length of a nonce in bytes +pub const NONE_NONCE_LENGTH: usize = 24; +/// Length of a hash digest in bytes +pub const NONE_HASH_DIGEST_LENGTH: usize = 32; +/// Length of a shared secret in bytes +pub const NONE_SHARED_SECRET_LENGTH: usize = 32; diff --git a/veilid-core/src/crypto/receipt.rs b/veilid-core/src/crypto/receipt.rs index dd2c4441..8f6d0716 100644 --- a/veilid-core/src/crypto/receipt.rs +++ b/veilid-core/src/crypto/receipt.rs @@ -125,7 +125,11 @@ impl Receipt { // Validate signature if !vcrypto - .verify(&sender_id.into(), &data[0..(data.len() - 64)], &signature) + .verify( + &sender_id.clone().into(), + &data[0..(data.len() - 64)], + &signature, + ) .map_err(VeilidAPIError::generic)? { apibail_parse_error!("signature failure in receipt", signature); @@ -178,9 +182,9 @@ impl Receipt { // Write size data[0x08..0x0A].copy_from_slice(&(receipt_size as u16).to_le_bytes()); // Write nonce - data[0x0A..0x22].copy_from_slice(&self.nonce.bytes); + data[0x0A..0x22].copy_from_slice(&self.nonce); // Write sender node id - data[0x22..0x42].copy_from_slice(&self.sender_id.bytes); + data[0x22..0x42].copy_from_slice(&self.sender_id); // Write extra data if !self.extra_data.is_empty() { data[0x42..(receipt_size - 64)].copy_from_slice(self.extra_data.as_slice()); @@ -188,13 +192,13 @@ impl Receipt { // Sign the receipt let signature = vcrypto .sign( - &self.sender_id.into(), + &self.sender_id.clone().into(), secret, &data[0..(receipt_size - 64)], ) .map_err(VeilidAPIError::generic)?; // Append the signature - data[(receipt_size - 64)..].copy_from_slice(&signature.bytes); + data[(receipt_size - 64)..].copy_from_slice(&signature); Ok(data) } @@ -210,17 +214,17 @@ impl Receipt { } pub fn get_nonce(&self) -> BareNonce { - self.nonce + self.nonce.clone() } #[expect(dead_code)] - pub fn get_sender_id(&self) -> BareNodeId { - self.sender_id + pub fn get_bare_sender_id(&self) -> BareNodeId { + self.sender_id.clone() } #[expect(dead_code)] - pub fn get_sender_typed_id(&self) -> NodeId { - NodeId::new(self.crypto_kind, self.sender_id) + pub fn get_sender_id(&self) -> NodeId { + NodeId::new(self.crypto_kind, self.sender_id.clone()) } #[must_use] diff --git a/veilid-core/src/crypto/tests/test_crypto.rs b/veilid-core/src/crypto/tests/test_crypto.rs index a356c9e8..7bee9484 100644 --- a/veilid-core/src/crypto/tests/test_crypto.rs +++ b/veilid-core/src/crypto/tests/test_crypto.rs @@ -118,7 +118,10 @@ pub async fn test_no_auth(vcrypto: &AsyncCryptoSystemGuard<'_>) { let mut body = LOREM_IPSUM.to_vec(); let body2 = body.clone(); let size_before_encrypt = body.len(); - vcrypto.crypt_in_place_no_auth(&mut body, &n1, &ss1).await; + vcrypto + .crypt_in_place_no_auth(&mut body, &n1, &ss1) + .await + .expect("should succeed"); let size_after_encrypt = body.len(); assert_eq!( @@ -128,32 +131,51 @@ pub async fn test_no_auth(vcrypto: &AsyncCryptoSystemGuard<'_>) { let mut body3 = body.clone(); let mut body4 = body.clone(); - vcrypto.crypt_in_place_no_auth(&mut body, &n1, &ss1).await; + vcrypto + .crypt_in_place_no_auth(&mut body, &n1, &ss1) + .await + .expect("should succeed"); assert_eq!(body, body2, "result after decrypt should be the same"); - vcrypto.crypt_in_place_no_auth(&mut body3, &n2, &ss1).await; + vcrypto + .crypt_in_place_no_auth(&mut body3, &n2, &ss1) + .await + .expect("should succeed"); assert_ne!(body3, body, "decrypt should not be equal with wrong nonce"); - vcrypto.crypt_in_place_no_auth(&mut body4, &n1, &ss2).await; + vcrypto + .crypt_in_place_no_auth(&mut body4, &n1, &ss2) + .await + .expect("should succeed"); assert_ne!(body4, body, "decrypt should not be equal with wrong secret"); let body5 = vcrypto .crypt_no_auth_unaligned(LOREM_IPSUM, &n1, &ss1) - .await; - let body6 = vcrypto.crypt_no_auth_unaligned(&body5, &n1, &ss1).await; + .await + .unwrap(); + let body6 = vcrypto + .crypt_no_auth_unaligned(&body5, &n1, &ss1) + .await + .unwrap(); let body7 = vcrypto .crypt_no_auth_unaligned(LOREM_IPSUM, &n1, &ss1) - .await; + .await + .unwrap(); assert_eq!(body6, LOREM_IPSUM); assert_eq!(body5, body7); let body5 = vcrypto .crypt_no_auth_aligned_8(LOREM_IPSUM, &n1, &ss1) - .await; - let body6 = vcrypto.crypt_no_auth_aligned_8(&body5, &n1, &ss1).await; + .await + .unwrap(); + let body6 = vcrypto + .crypt_no_auth_aligned_8(&body5, &n1, &ss1) + .await + .unwrap(); let body7 = vcrypto .crypt_no_auth_aligned_8(LOREM_IPSUM, &n1, &ss1) - .await; + .await + .unwrap(); assert_eq!(body6, LOREM_IPSUM); assert_eq!(body5, body7); } diff --git a/veilid-core/src/crypto/tests/test_types.rs b/veilid-core/src/crypto/tests/test_types.rs index ac1e2f9d..2a836177 100644 --- a/veilid-core/src/crypto/tests/test_types.rs +++ b/veilid-core/src/crypto/tests/test_types.rs @@ -3,8 +3,8 @@ use core::convert::TryFrom; static LOREM_IPSUM:&str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "; static CHEEZBURGER: &str = "I can has cheezburger"; -static EMPTY_KEY: [u8; PUBLIC_KEY_LENGTH] = [0u8; PUBLIC_KEY_LENGTH]; -static EMPTY_KEY_SECRET: [u8; SECRET_KEY_LENGTH] = [0u8; SECRET_KEY_LENGTH]; +static EMPTY_KEY: [u8; VLD0_PUBLIC_KEY_LENGTH] = [0u8; VLD0_PUBLIC_KEY_LENGTH]; +static EMPTY_KEY_SECRET: [u8; VLD0_SECRET_KEY_LENGTH] = [0u8; VLD0_SECRET_KEY_LENGTH]; pub async fn test_generate_secret(vcrypto: &AsyncCryptoSystemGuard<'_>) { // Verify keys generate @@ -12,8 +12,8 @@ pub async fn test_generate_secret(vcrypto: &AsyncCryptoSystemGuard<'_>) { let (dht_key2, dht_key_secret2) = vcrypto.generate_keypair().await.into_split(); // Verify byte patterns are different between public and secret - assert_ne!(dht_key.bytes, dht_key_secret.bytes); - assert_ne!(dht_key2.bytes, dht_key_secret2.bytes); + assert_ne!(dht_key.bytes(), dht_key_secret.bytes()); + assert_ne!(dht_key2.bytes(), dht_key_secret2.bytes()); // Verify the keys and secrets are different across keypairs assert_ne!(dht_key, dht_key2); @@ -142,8 +142,8 @@ pub async fn test_sign_and_verify(vcrypto: &AsyncCryptoSystemGuard<'_>) { pub async fn test_key_conversions(vcrypto: &AsyncCryptoSystemGuard<'_>) { // Test default key let (dht_key, dht_key_secret) = (BarePublicKey::default(), BareSecretKey::default()); - assert_eq!(dht_key.bytes, EMPTY_KEY); - assert_eq!(dht_key_secret.bytes, EMPTY_KEY_SECRET); + assert!(dht_key.bytes().is_empty()); + assert!(dht_key_secret.bytes().is_empty()); let dht_key_string = String::from(&dht_key); trace!("dht_key_string: {:?}", dht_key_string); let dht_key_string2 = String::from(&dht_key); @@ -193,28 +193,18 @@ pub async fn test_key_conversions(vcrypto: &AsyncCryptoSystemGuard<'_>) { // Assert string roundtrip assert_eq!(String::from(&dht_key2_back), dht_key2_string); // These conversions should fail - assert!(BarePublicKey::try_from("whatever").is_err()); - assert!(BareSecretKey::try_from("whatever").is_err()); - assert!(BarePublicKey::try_from("").is_err()); - assert!(BareSecretKey::try_from("").is_err()); + assert!(BarePublicKey::try_from("whatever!").is_err()); + assert!(BareSecretKey::try_from("whatever!").is_err()); assert!(BarePublicKey::try_from(" ").is_err()); assert!(BareSecretKey::try_from(" ").is_err()); - assert!(BarePublicKey::try_from( - "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq" - ) - .is_err()); - assert!(BareSecretKey::try_from( - "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq" - ) - .is_err()); } pub async fn test_encode_decode(vcrypto: &AsyncCryptoSystemGuard<'_>) { let dht_key = BarePublicKey::try_decode("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA").unwrap(); let dht_key_secret = BareSecretKey::try_decode("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA").unwrap(); - let dht_key_b = BarePublicKey::new(EMPTY_KEY); - let dht_key_secret_b = BareSecretKey::new(EMPTY_KEY_SECRET); + let dht_key_b = BarePublicKey::new(&EMPTY_KEY); + let dht_key_secret_b = BareSecretKey::new(&EMPTY_KEY_SECRET); assert_eq!(dht_key, dht_key_b); assert_eq!(dht_key_secret, dht_key_secret_b); @@ -247,7 +237,7 @@ pub async fn test_encode_decode(vcrypto: &AsyncCryptoSystemGuard<'_>) { assert_eq!(dht_key_secret2, d2s); // Failures - let f1 = BareSecretKey::try_decode("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); + let f1 = BareSecretKey::try_decode("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!"); assert!(f1.is_err()); let f2 = BareSecretKey::try_decode("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&"); assert!(f2.is_err()); @@ -259,6 +249,7 @@ pub fn test_typed_convert(vcrypto: &AsyncCryptoSystemGuard<'_>) { vcrypto.kind() ); let tk1 = PublicKey::from_str(&tks1).expect("failed"); + assert!(vcrypto.check_public_key(tk1.ref_value()).is_ok()); let tks1x = tk1.to_string(); assert_eq!(tks1, tks1x); @@ -266,29 +257,35 @@ pub fn test_typed_convert(vcrypto: &AsyncCryptoSystemGuard<'_>) { "{}:7lxDEabK_qgjbe38RtBa3IZLrud84P6NhGP-pRTZzd", vcrypto.kind() ); - let _tk2 = PublicKey::from_str(&tks2).expect_err("succeeded when it shouldnt have"); + let _tk2 = PublicKey::from_str(&tks2).expect_err("should fail"); - let tks3 = "XXXX:7lxDEabK_qgjbe38RtBa3IZLrud84P6NhGP-pRTZzdQ".to_string(); + let tks3 = format!( + "{}:7lxDEabK_qgjbe38RtBa3IZLrud84P6NhGP-pRTZ", + vcrypto.kind() + ); let tk3 = PublicKey::from_str(&tks3).expect("failed"); - let tks3x = tk3.to_string(); - assert_eq!(tks3, tks3x); + assert!(vcrypto.check_public_key(tk3.ref_value()).is_err()); - let tks4 = "XXXX:7lxDEabK_qgjbe38RtBa3IZLrud84P6NhGP-pRTZzd".to_string(); - let _tk4 = PublicKey::from_str(&tks4).expect_err("succeeded when it shouldnt have"); + let tks4 = "XXXX:7lxDEabK_qgjbe38RtBa3IZLrud84P6NhGP-pRTZzdQ".to_string(); + let tk4 = PublicKey::from_str(&tks4).expect("failed"); + let tks4x = tk4.to_string(); + assert_eq!(tks4, tks4x); + // Enable this when we switch crypto to using typed keys too + //assert!(vcrypto.check_public_key(&tk4).is_err()); let tks5 = "XXX:7lxDEabK_qgjbe38RtBa3IZLrud84P6NhGP-pRTZzdQ".to_string(); - let _tk5 = PublicKey::from_str(&tks5).expect_err("succeeded when it shouldnt have"); + let _tk5 = PublicKey::from_str(&tks5).expect_err("should fail"); let tks6 = "7lxDEabK_qgjbe38RtBa3IZLrud84P6NhGP-pRTZzdQ".to_string(); let tk6 = PublicKey::from_str(&tks6).expect("failed"); let tks6x = tk6.to_string(); assert!(tks6x.ends_with(&tks6)); - let b = Vec::from(tk6); + let b = Vec::from(tk6.clone()); let tk7 = PublicKey::try_from(b).expect("should succeed"); assert_eq!(tk7, tk6); - let b = Vec::from(tk6); + let b = Vec::from(tk6.clone()); let tk8 = PublicKey::try_from(b.as_slice()).expect("should succeed"); assert_eq!(tk8, tk6); } @@ -303,12 +300,12 @@ async fn test_hash(vcrypto: &AsyncCryptoSystemGuard<'_>) { let k5 = vcrypto.generate_hash(LOREM_IPSUM.as_bytes()).await; let k6 = vcrypto.generate_hash(CHEEZBURGER.as_bytes()).await; - s.insert(k1); - s.insert(k2); - s.insert(k3); - s.insert(k4); - s.insert(k5); - s.insert(k6); + s.insert(k1.clone()); + s.insert(k2.clone()); + s.insert(k3.clone()); + s.insert(k4.clone()); + s.insert(k5.clone()); + s.insert(k6.clone()); assert_eq!(s.len(), 6); let v1 = vcrypto.generate_hash("abc".as_bytes()).await; @@ -390,23 +387,23 @@ async fn test_operations(vcrypto: &AsyncCryptoSystemGuard<'_>) { } pub fn test_public_key_ordering() { - let k1 = BarePublicKey::new([ + let k1 = BarePublicKey::new(&[ 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]); - let k2 = BarePublicKey::new([ + let k2 = BarePublicKey::new(&[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]); - let k3 = BarePublicKey::new([ + let k3 = BarePublicKey::new(&[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, ]); - let k4 = BarePublicKey::new([ + let k4 = BarePublicKey::new(&[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ]); - let k5 = BarePublicKey::new([ + let k5 = BarePublicKey::new(&[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]); diff --git a/veilid-core/src/crypto/types/byte_array_types.rs b/veilid-core/src/crypto/types/byte_array_types.rs index c71e174c..aa00ed10 100644 --- a/veilid-core/src/crypto/types/byte_array_types.rs +++ b/veilid-core/src/crypto/types/byte_array_types.rs @@ -1,71 +1,21 @@ use super::*; use core::cmp::{Eq, Ord, PartialEq, PartialOrd}; -use core::convert::{TryFrom, TryInto}; +use core::convert::TryFrom; use core::fmt; use core::hash::Hash; +use bytes::{Bytes, BytesMut}; use data_encoding::BASE64URL_NOPAD; ////////////////////////////////////////////////////////////////////// -/// Length of a crypto key in bytes -#[allow(dead_code)] -pub const CRYPTO_KEY_LENGTH: usize = 32; -/// Length of a crypto key in bytes after encoding to base64url -#[allow(dead_code)] -pub const CRYPTO_KEY_LENGTH_ENCODED: usize = 43; -/// Length of a crypto key in bytes -#[allow(dead_code)] -pub const PUBLIC_KEY_LENGTH: usize = CRYPTO_KEY_LENGTH; -/// Length of a crypto key in bytes after encoding to base64url -#[allow(dead_code)] -pub const PUBLIC_KEY_LENGTH_ENCODED: usize = CRYPTO_KEY_LENGTH_ENCODED; -/// Length of a secret key in bytes -#[allow(dead_code)] -pub const SECRET_KEY_LENGTH: usize = CRYPTO_KEY_LENGTH; -/// Length of a secret key in bytes after encoding to base64url -#[allow(dead_code)] -pub const SECRET_KEY_LENGTH_ENCODED: usize = CRYPTO_KEY_LENGTH_ENCODED; -/// Length of a signature in bytes -#[allow(dead_code)] -pub const SIGNATURE_LENGTH: usize = 64; -/// Length of a signature in bytes after encoding to base64url -#[allow(dead_code)] -pub const SIGNATURE_LENGTH_ENCODED: usize = 86; -/// Length of a nonce in bytes -#[allow(dead_code)] -pub const NONCE_LENGTH: usize = 24; -/// Length of a nonce in bytes after encoding to base64url -#[allow(dead_code)] -pub const NONCE_LENGTH_ENCODED: usize = 32; -/// Length of a hash digest in bytes -#[allow(dead_code)] -pub const HASH_DIGEST_LENGTH: usize = CRYPTO_KEY_LENGTH; -/// Length of a hash digest in bytes after encoding to base64url -#[allow(dead_code)] -pub const HASH_DIGEST_LENGTH_ENCODED: usize = CRYPTO_KEY_LENGTH_ENCODED; -/// Length of a shared secret in bytes -#[allow(dead_code)] -pub const SHARED_SECRET_LENGTH: usize = HASH_DIGEST_LENGTH; -/// Length of a shared secret in bytes after encoding to base64url -#[allow(dead_code)] -pub const SHARED_SECRET_LENGTH_ENCODED: usize = HASH_DIGEST_LENGTH_ENCODED; -/// Length of a route id in bytes -#[allow(dead_code)] -pub const ROUTE_ID_LENGTH: usize = HASH_DIGEST_LENGTH; -/// Length of a route id in bytes after encoding to base64url -#[allow(dead_code)] -pub const ROUTE_ID_LENGTH_ENCODED: usize = HASH_DIGEST_LENGTH_ENCODED; - -////////////////////////////////////////////////////////////////////// - pub trait Encodable where Self: Sized, { fn encode(&self) -> String; - fn encoded_len() -> usize; + fn encoded_len(&self) -> usize; fn try_decode>(input: S) -> VeilidAPIResult { let b = input.as_ref().as_bytes(); Self::try_decode_bytes(b) @@ -73,11 +23,25 @@ where fn try_decode_bytes(b: &[u8]) -> VeilidAPIResult; } +////////////////////////////////////////////////////////////////////// +pub trait ByteArrayType +where + Self: Sized, +{ + fn len(&self) -> usize; + fn is_empty(&self) -> bool; + fn bytes(&self) -> &[u8]; + fn bit(&self, index: usize) -> bool; + fn first_nonzero_bit(&self) -> Option; + fn nibble(&self, index: usize) -> u8; + fn first_nonzero_nibble(&self) -> Option<(usize, u8)>; +} + ////////////////////////////////////////////////////////////////////// macro_rules! byte_array_type { - ($name:ident, $size:expr, $encoded_size:expr) => { - #[derive(Clone, Copy, Hash, PartialOrd, Ord, PartialEq, Eq)] + ($name:ident) => { + #[derive(Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))] #[cfg_attr( all(target_arch = "wasm32", target_os = "unknown"), @@ -90,7 +54,110 @@ macro_rules! byte_array_type { all(target_arch = "wasm32", target_os = "unknown"), tsify(type = "string") )] - pub bytes: [u8; $size], + bytes: Bytes, + } + impl $name { + pub fn new(data: &[u8]) -> Self { + Self { + bytes: Bytes::copy_from_slice(data), + } + } + fn new_from_bytes(bytes: Bytes) -> Self { + Self { bytes } + } + } + impl Default for $name { + fn default() -> Self { + Self { + bytes: Bytes::new(), + } + } + } + impl ByteArrayType for $name { + fn len(&self) -> usize { + self.bytes.len() + } + fn is_empty(&self) -> bool { + self.bytes.is_empty() + } + fn bytes(&self) -> &[u8] { + &self.bytes + } + // Big endian bit ordering + #[must_use] + fn bit(&self, index: usize) -> bool { + let bi = index / 8; + let ti = 7 - (index % 8); + ((self.bytes[bi] >> ti) & 1) != 0 + } + + #[must_use] + fn first_nonzero_bit(&self) -> Option { + for i in 0..self.bytes.len() { + let b = self.bytes[i]; + if b != 0 { + for n in 0..8 { + if ((b >> (7 - n)) & 1u8) != 0u8 { + return Some((i * 8) + n); + } + } + unreachable!("nonzero byte must have nonzero bit"); + } + } + None + } + + // Big endian nibble ordering + #[must_use] + fn nibble(&self, index: usize) -> u8 { + let bi = index / 2; + if index & 1 == 0 { + (self.bytes[bi] >> 4) & 0xFu8 + } else { + self.bytes[bi] & 0xFu8 + } + } + + #[must_use] + fn first_nonzero_nibble(&self) -> Option<(usize, u8)> { + for i in 0..(self.bytes.len() * 2) { + let n = self.nibble(i); + if n != 0 { + return Some((i, n)); + } + } + None + } + } + impl Encodable for $name { + fn encode(&self) -> String { + BASE64URL_NOPAD.encode(&self.bytes) + } + fn encoded_len(&self) -> usize { + BASE64URL_NOPAD.encode_len(self.bytes.len()) + } + fn try_decode_bytes(b: &[u8]) -> VeilidAPIResult { + if b.len() == 0 { + return Ok(Self::default()); + } + let decode_len = BASE64URL_NOPAD + .decode_len(b.len()) + .map_err(|_| VeilidAPIError::generic("failed to get decode length"))?; + let mut bytes = BytesMut::zeroed(decode_len); + let bytes_len = BASE64URL_NOPAD + .decode_mut(b, &mut bytes) + .map_err(|_| VeilidAPIError::generic("failed to decode"))?; + bytes.truncate(bytes_len); + Ok(Self::new_from_bytes(bytes.freeze())) + } + } + + impl core::ops::Deref for $name { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + &self.bytes + } } impl serde::Serialize for $name { @@ -109,103 +176,10 @@ macro_rules! byte_array_type { D: serde::Deserializer<'de>, { let s = ::deserialize(deserializer)?; - if s == "" { - return Ok($name::default()); - } - $name::try_decode(s.as_str()).map_err(serde::de::Error::custom) + Self::try_decode(s.as_str()).map_err(serde::de::Error::custom) } } - impl Default for $name { - fn default() -> Self { - Self { - bytes: [0u8; $size], - } - } - } - - impl $name { - pub fn new(bytes: [u8; $size]) -> Self { - Self { bytes } - } - - // Big endian bit ordering - #[must_use] - pub fn bit(&self, index: usize) -> bool { - assert!(index < ($size * 8)); - let bi = index / 8; - let ti = 7 - (index % 8); - ((self.bytes[bi] >> ti) & 1) != 0 - } - - #[must_use] - pub fn first_nonzero_bit(&self) -> Option { - for i in 0..$size { - let b = self.bytes[i]; - if b != 0 { - for n in 0..8 { - if ((b >> (7 - n)) & 1u8) != 0u8 { - return Some((i * 8) + n); - } - } - panic!("wtf") - } - } - None - } - - // Big endian nibble ordering - #[must_use] - pub fn nibble(&self, index: usize) -> u8 { - assert!(index < ($size * 2)); - let bi = index / 2; - if index & 1 == 0 { - (self.bytes[bi] >> 4) & 0xFu8 - } else { - self.bytes[bi] & 0xFu8 - } - } - - #[must_use] - pub fn first_nonzero_nibble(&self) -> Option<(usize, u8)> { - for i in 0..($size * 2) { - let n = self.nibble(i); - if n != 0 { - return Some((i, n)); - } - } - None - } - } - - impl Encodable for $name { - fn encode(&self) -> String { - BASE64URL_NOPAD.encode(&self.bytes) - } - fn encoded_len() -> usize { - $encoded_size - } - fn try_decode_bytes(b: &[u8]) -> VeilidAPIResult { - let mut bytes = [0u8; $size]; - let res = BASE64URL_NOPAD.decode_len(b.len()); - match res { - Ok(v) => { - if v != $size { - apibail_generic!("Incorrect length in decode"); - } - } - Err(_) => { - apibail_generic!("Failed to decode"); - } - } - - let res = BASE64URL_NOPAD.decode_mut(b, &mut bytes); - match res { - Ok(_) => Ok(Self::new(bytes)), - Err(_) => apibail_generic!("Failed to decode"), - } - } - } impl fmt::Display for $name { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.encode()) @@ -237,7 +211,7 @@ macro_rules! byte_array_type { impl TryFrom for $name { type Error = VeilidAPIError; fn try_from(value: String) -> Result { - $name::try_from(value.as_str()) + Self::try_from(value.as_str()) } } @@ -247,43 +221,30 @@ macro_rules! byte_array_type { Self::try_decode(value) } } - impl TryFrom<&[u8]> for $name { - type Error = VeilidAPIError; - fn try_from(v: &[u8]) -> Result { - let vl = v.len(); - Ok(Self { - bytes: v.try_into().map_err(|_| { - VeilidAPIError::generic(format!( - "Expected a slice of length {} but it was {}", - $size, vl - )) - })?, - }) - } - } - impl TryFrom> for $name { - type Error = VeilidAPIError; - fn try_from(v: Vec) -> Result { - let vl = v.len(); - Ok(Self { - bytes: v.try_into().map_err(|_| { - VeilidAPIError::generic(format!( - "Expected a vec of length {} but it was {}", - $size, vl - )) - })?, - }) - } - } impl From<$name> for Vec { fn from(value: $name) -> Self { - value.bytes.to_vec() + value.bytes().to_vec() } } + impl AsRef<[u8]> for $name { fn as_ref(&self) -> &[u8] { - &self.bytes + self.bytes() + } + } + impl From<&[u8]> for $name { + fn from(v: &[u8]) -> Self { + Self { + bytes: Bytes::copy_from_slice(v), + } + } + } + impl From> for $name { + fn from(v: Vec) -> Self { + Self { + bytes: Bytes::from(v), + } } } }; @@ -291,80 +252,53 @@ macro_rules! byte_array_type { ///////////////////////////////////////// -byte_array_type!(BarePublicKey, PUBLIC_KEY_LENGTH, PUBLIC_KEY_LENGTH_ENCODED); -byte_array_type!(BareSecretKey, SECRET_KEY_LENGTH, SECRET_KEY_LENGTH_ENCODED); -byte_array_type!(BareSignature, SIGNATURE_LENGTH, SIGNATURE_LENGTH_ENCODED); -byte_array_type!(BareNonce, NONCE_LENGTH, NONCE_LENGTH_ENCODED); +byte_array_type!(BarePublicKey); +byte_array_type!(BareSecretKey); +byte_array_type!(BareSignature); +byte_array_type!(BareNonce); /* Notes: - These are actually BareHashDigest types, but not interchangable: - - BareRouteId (eventually will be a BareRecordKey type with DHT Routes) - - BareRecordKey - BareSharedSecret + - BareRecordKey + - BareRouteId (eventually will be a BareRecordKey type with DHT Routes) + - BareNodeId (constructible from BarePublicKey) + - BareMemberId (constructible from BarePublicKey) */ // BareHashDigest sub-types -byte_array_type!( - BareHashDigest, - HASH_DIGEST_LENGTH, - HASH_DIGEST_LENGTH_ENCODED -); -byte_array_type!( - BareSharedSecret, - SHARED_SECRET_LENGTH, - SHARED_SECRET_LENGTH_ENCODED -); -byte_array_type!(BareRouteId, ROUTE_ID_LENGTH, ROUTE_ID_LENGTH_ENCODED); -byte_array_type!( - BareRecordKey, - HASH_DIGEST_LENGTH, - HASH_DIGEST_LENGTH_ENCODED -); -byte_array_type!( - BareHashDistance, - HASH_DIGEST_LENGTH, - HASH_DIGEST_LENGTH_ENCODED -); - -// BareNodeId is currently the same as BarePublicKey, but will eventually be a sub-type of BareHashDigest. -byte_array_type!(BareNodeId, PUBLIC_KEY_LENGTH, PUBLIC_KEY_LENGTH_ENCODED); - -#[expect(dead_code)] -trait HashCoordinate { - fn from_hash_coordinate(hash_digest: BareHashDigest) -> Self; - fn to_hash_coordinate(&self) -> BareHashDigest; -} +byte_array_type!(BareHashDigest); +byte_array_type!(BareSharedSecret); +byte_array_type!(BareRecordKey); +byte_array_type!(BareHashDistance); +byte_array_type!(BareRouteId); +byte_array_type!(BareNodeId); +byte_array_type!(BareMemberId); // Temporary adapters for converting to/from BareHashDigest types // Removing these will show where there's still issues. impl From for BareSharedSecret { fn from(value: BareHashDigest) -> Self { - Self::new(value.bytes) + Self::new(value.bytes()) } } impl From for BareRecordKey { fn from(value: BareHashDigest) -> Self { - Self::new(value.bytes) + Self::new(value.bytes()) } } impl From for BareHashDigest { fn from(value: BareRecordKey) -> Self { - Self::new(value.bytes) + Self::new(value.bytes()) } } impl From for BareHashDigest { fn from(value: BareNodeId) -> Self { - Self::new(value.bytes) - } -} - -impl From for BarePublicKey { - fn from(value: BareHashDigest) -> Self { - Self::new(value.bytes) + Self::new(value.bytes()) } } @@ -374,12 +308,12 @@ impl From for BarePublicKey { */ impl From for BareNodeId { fn from(value: BarePublicKey) -> Self { - Self::new(value.bytes) + Self::new(value.bytes()) } } impl From for BarePublicKey { fn from(value: BareNodeId) -> Self { - Self::new(value.bytes) + Self::new(value.bytes()) } } diff --git a/veilid-core/src/crypto/types/crypto_typed.rs b/veilid-core/src/crypto/types/crypto_typed.rs index 56d6eca8..a87b204c 100644 --- a/veilid-core/src/crypto/types/crypto_typed.rs +++ b/veilid-core/src/crypto/types/crypto_typed.rs @@ -1,13 +1,13 @@ use super::*; -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[must_use] pub struct CryptoTyped where - K: Clone + Copy + fmt::Debug + PartialEq + Eq + Hash, + K: Clone + fmt::Debug + PartialEq + Eq + Hash, { - pub kind: CryptoKind, - pub value: K, + kind: CryptoKind, + value: K, } cfg_if::cfg_if! { @@ -21,15 +21,29 @@ export type CryptoTyped = `${CryptoKind}:${TCryptoKey impl CryptoTyped where - K: Clone + Copy + fmt::Debug + PartialEq + Eq + Hash, + K: Clone + fmt::Debug + PartialEq + Eq + Hash, { pub fn new(kind: CryptoKind, value: K) -> Self { Self { kind, value } } + + pub fn kind(&self) -> CryptoKind { + self.kind + } + pub fn value(&self) -> K { + self.value.clone() + } + pub fn ref_value(&self) -> &K { + &self.value + } + pub fn into_value(self) -> K { + self.value + } } + impl PartialOrd for CryptoTyped where - K: Clone + Copy + fmt::Debug + PartialEq + Eq + Hash, + K: Clone + fmt::Debug + PartialEq + Eq + Hash, K: Ord + PartialOrd, { fn partial_cmp(&self, other: &Self) -> Option { @@ -39,7 +53,7 @@ where impl Ord for CryptoTyped where - K: Clone + Copy + fmt::Debug + PartialEq + Eq + Hash, + K: Clone + fmt::Debug + PartialEq + Eq + Hash, K: Ord + PartialOrd, { fn cmp(&self, other: &Self) -> cmp::Ordering { @@ -53,7 +67,7 @@ where impl fmt::Display for CryptoTyped where - K: Clone + Copy + fmt::Debug + PartialEq + Eq + Hash, + K: Clone + fmt::Debug + PartialEq + Eq + Hash, K: fmt::Display, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { @@ -63,29 +77,27 @@ where impl FromStr for CryptoTyped where - K: Clone + Copy + fmt::Debug + PartialEq + Eq + Hash, + K: Clone + fmt::Debug + PartialEq + Eq + Hash, K: Encodable, { type Err = VeilidAPIError; fn from_str(s: &str) -> Result { let b = s.as_bytes(); - if b.len() == (5 + K::encoded_len()) && b[4..5] == b":"[..] { + if b.len() > 5 && b[4..5] == b":"[..] { let kind: CryptoKind = b[0..4].try_into().expect("should not fail to convert"); let value = K::try_decode_bytes(&b[5..])?; Ok(Self { kind, value }) - } else if b.len() == K::encoded_len() { + } else { let kind = best_crypto_kind(); let value = K::try_decode_bytes(b)?; Ok(Self { kind, value }) - } else { - apibail_generic!("invalid cryptotyped format"); } } } impl TryFrom for CryptoTyped where - K: Clone + Copy + fmt::Debug + PartialEq + Eq + Hash, + K: Clone + fmt::Debug + PartialEq + Eq + Hash, K: Encodable, { type Error = VeilidAPIError; @@ -97,7 +109,7 @@ where impl TryFrom<&str> for CryptoTyped where - K: Clone + Copy + fmt::Debug + PartialEq + Eq + Hash, + K: Clone + fmt::Debug + PartialEq + Eq + Hash, K: Encodable, { type Error = VeilidAPIError; @@ -109,8 +121,8 @@ where impl<'a, K> TryFrom<&'a [u8]> for CryptoTyped where - K: Clone + Copy + fmt::Debug + PartialEq + Eq + Hash, - K: TryFrom<&'a [u8], Error = VeilidAPIError>, + K: Clone + fmt::Debug + PartialEq + Eq + Hash, + K: From<&'a [u8]>, { type Error = VeilidAPIError; @@ -119,15 +131,15 @@ where apibail_generic!("invalid cryptotyped format"); } let kind: CryptoKind = b[0..4].try_into()?; - let value: K = b[4..].try_into()?; + let value: K = b[4..].into(); Ok(Self { kind, value }) } } impl TryFrom> for CryptoTyped where - K: Clone + Copy + fmt::Debug + PartialEq + Eq + Hash, - K: for<'a> TryFrom<&'a [u8], Error = VeilidAPIError>, + K: Clone + fmt::Debug + PartialEq + Eq + Hash, + K: for<'a> From<&'a [u8]>, { type Error = VeilidAPIError; @@ -138,7 +150,7 @@ where impl From> for Vec where - K: Clone + Copy + fmt::Debug + PartialEq + Eq + Hash, + K: Clone + fmt::Debug + PartialEq + Eq + Hash, K: AsRef<[u8]>, { fn from(v: CryptoTyped) -> Self { @@ -150,7 +162,7 @@ where impl<'de, K> Deserialize<'de> for CryptoTyped where - K: Clone + Copy + fmt::Debug + PartialEq + Eq + Hash, + K: Clone + fmt::Debug + PartialEq + Eq + Hash, K: Encodable, { fn deserialize(deserializer: D) -> Result @@ -163,7 +175,7 @@ where } impl Serialize for CryptoTyped where - K: Clone + Copy + fmt::Debug + PartialEq + Eq + Hash, + K: Clone + fmt::Debug + PartialEq + Eq + Hash, K: fmt::Display, { fn serialize(&self, serializer: S) -> Result @@ -173,3 +185,25 @@ where serializer.collect_str(self) } } + +impl CryptoTyped { + pub fn new_from_parts(key: PublicKey, bare_secret: BareSecretKey) -> Self { + Self { + kind: key.kind(), + value: BareKeyPair::new(key.value(), bare_secret), + } + } + + pub fn key(&self) -> PublicKey { + PublicKey::new(self.kind, self.ref_value().key()) + } + pub fn secret(&self) -> SecretKey { + SecretKey::new(self.kind, self.ref_value().secret()) + } + pub fn bare_secret(&self) -> BareSecretKey { + self.ref_value().secret() + } + pub fn ref_bare_secret(&self) -> &BareSecretKey { + self.ref_value().ref_secret() + } +} diff --git a/veilid-core/src/crypto/types/crypto_typed_group.rs b/veilid-core/src/crypto/types/crypto_typed_group.rs index 0db8cc98..6e06f6dd 100644 --- a/veilid-core/src/crypto/types/crypto_typed_group.rs +++ b/veilid-core/src/crypto/types/crypto_typed_group.rs @@ -5,7 +5,6 @@ use super::*; pub struct CryptoTypedGroup where K: Clone - + Copy + fmt::Debug + fmt::Display + FromStr @@ -31,7 +30,6 @@ export type CryptoTypedGroup = Array CryptoTypedGroup where K: Clone - + Copy + fmt::Debug + fmt::Display + FromStr @@ -55,7 +53,7 @@ where pub fn kinds(&self) -> Vec { let mut out = Vec::new(); for tk in &self.items { - out.push(tk.kind); + out.push(tk.kind()); } out.sort_by(compare_crypto_kind); out @@ -64,17 +62,17 @@ where pub fn keys(&self) -> Vec { let mut out = Vec::new(); for tk in &self.items { - out.push(tk.value); + out.push(tk.value()); } out } #[must_use] pub fn get(&self, kind: CryptoKind) -> Option> { - self.items.iter().find(|x| x.kind == kind).copied() + self.items.iter().find(|x| x.kind() == kind).cloned() } pub fn add(&mut self, typed_key: CryptoTyped) { for x in &mut self.items { - if x.kind == typed_key.kind { + if x.kind() == typed_key.kind() { *x = typed_key; return; } @@ -85,17 +83,17 @@ where pub fn add_all(&mut self, typed_keys: &[CryptoTyped]) { 'outer: for typed_key in typed_keys { for x in &mut self.items { - if x.kind == typed_key.kind { - *x = *typed_key; + if x.kind() == typed_key.kind() { + *x = typed_key.clone(); continue 'outer; } } - self.items.push(*typed_key); + self.items.push(typed_key.clone()); } self.items.sort() } pub fn remove(&mut self, kind: CryptoKind) -> Option> { - if let Some(idx) = self.items.iter().position(|x| x.kind == kind) { + if let Some(idx) = self.items.iter().position(|x| x.kind() == kind) { return Some(self.items.remove(idx)); } None @@ -110,8 +108,8 @@ where pub fn best(&self) -> Option> { self.items .iter() - .find(|k| VALID_CRYPTO_KINDS.contains(&k.kind)) - .copied() + .find(|k| VALID_CRYPTO_KINDS.contains(&k.kind())) + .cloned() } #[must_use] pub fn is_empty(&self) -> bool { @@ -137,7 +135,7 @@ where } pub fn contains_value(&self, value: &K) -> bool { for tk in &self.items { - if tk.value == *value { + if tk.ref_value() == value { return true; } } @@ -148,7 +146,6 @@ where impl core::ops::Deref for CryptoTypedGroup where K: Clone - + Copy + fmt::Debug + fmt::Display + FromStr @@ -170,7 +167,6 @@ where impl fmt::Display for CryptoTypedGroup where K: Clone - + Copy + fmt::Debug + fmt::Display + FromStr @@ -198,7 +194,6 @@ where impl FromStr for CryptoTypedGroup where K: Clone - + Copy + fmt::Debug + fmt::Display + FromStr @@ -229,7 +224,6 @@ where impl From> for CryptoTypedGroup where K: Clone - + Copy + fmt::Debug + fmt::Display + FromStr @@ -249,7 +243,6 @@ where impl From>> for CryptoTypedGroup where K: Clone - + Copy + fmt::Debug + fmt::Display + FromStr @@ -269,7 +262,6 @@ where impl From<&[CryptoTyped]> for CryptoTypedGroup where K: Clone - + Copy + fmt::Debug + fmt::Display + FromStr @@ -289,7 +281,6 @@ where impl From> for Vec> where K: Clone - + Copy + fmt::Debug + fmt::Display + FromStr diff --git a/veilid-core/src/crypto/types/keypair.rs b/veilid-core/src/crypto/types/keypair.rs index a77d0915..bff071e9 100644 --- a/veilid-core/src/crypto/types/keypair.rs +++ b/veilid-core/src/crypto/types/keypair.rs @@ -1,10 +1,10 @@ use super::*; -#[derive(Clone, Copy, Default, PartialOrd, Ord, PartialEq, Eq, Hash)] +#[derive(Clone, Default, PartialOrd, Ord, PartialEq, Eq, Hash)] #[must_use] pub struct BareKeyPair { - pub key: BarePublicKey, - pub secret: BareSecretKey, + key: BarePublicKey, + secret: BareSecretKey, } cfg_if::cfg_if! { @@ -20,8 +20,23 @@ impl BareKeyPair { pub fn new(key: BarePublicKey, secret: BareSecretKey) -> Self { Self { key, secret } } + pub fn key(&self) -> BarePublicKey { + self.key.clone() + } + pub fn secret(&self) -> BareSecretKey { + self.secret.clone() + } + pub fn ref_key(&self) -> &BarePublicKey { + &self.key + } + pub fn ref_secret(&self) -> &BareSecretKey { + &self.secret + } pub fn split(&self) -> (BarePublicKey, BareSecretKey) { - (self.key, self.secret) + (self.key.clone(), self.secret.clone()) + } + pub fn ref_split(&self) -> (&BarePublicKey, &BareSecretKey) { + (&self.key, &self.secret) } pub fn into_split(self) -> (BarePublicKey, BareSecretKey) { (self.key, self.secret) @@ -32,15 +47,19 @@ impl Encodable for BareKeyPair { fn encode(&self) -> String { format!("{}:{}", self.key.encode(), self.secret.encode()) } - fn encoded_len() -> usize { - BarePublicKey::encoded_len() + 1 + BareSecretKey::encoded_len() + fn encoded_len(&self) -> usize { + self.key.encoded_len() + 1 + self.secret.encoded_len() } fn try_decode_bytes(b: &[u8]) -> VeilidAPIResult { - if b.len() != Self::encoded_len() { - apibail_parse_error!("input has wrong encoded length", format!("len={}", b.len())); + let parts: Vec<_> = b.split(|x| *x == b':').collect(); + if parts.len() != 2 { + apibail_parse_error!( + "input has incorrect parts", + format!("parts={}", parts.len()) + ); } - let key = BarePublicKey::try_decode_bytes(&b[0..BarePublicKey::encoded_len()])?; - let secret = BareSecretKey::try_decode_bytes(&b[(BarePublicKey::encoded_len() + 1)..])?; + let key = BarePublicKey::try_decode_bytes(parts[0])?; + let secret = BareSecretKey::try_decode_bytes(parts[1])?; Ok(BareKeyPair { key, secret }) } } diff --git a/veilid-core/src/crypto/types/mod.rs b/veilid-core/src/crypto/types/mod.rs index 0e5c961e..36bd29ab 100644 --- a/veilid-core/src/crypto/types/mod.rs +++ b/veilid-core/src/crypto/types/mod.rs @@ -63,13 +63,15 @@ pub type Signature = CryptoTyped; #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), declare)] pub type SharedSecret = CryptoTyped; #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), declare)] -pub type RouteId = CryptoTyped; +pub type HashDigest = CryptoTyped; #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), declare)] pub type RecordKey = CryptoTyped; #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), declare)] pub type NodeId = CryptoTyped; #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), declare)] -pub type HashDigest = CryptoTyped; +pub type RouteId = CryptoTyped; +#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), declare)] +pub type MemberId = CryptoTyped; #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), declare)] pub type PublicKeyGroup = CryptoTypedGroup; @@ -82,48 +84,50 @@ pub type SignatureGroup = CryptoTypedGroup; #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), declare)] pub type SharedSecretGroup = CryptoTypedGroup; #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), declare)] -pub type RouteIdGroup = CryptoTypedGroup; +pub type HashDigestGroup = CryptoTypedGroup; #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), declare)] pub type RecordKeyGroup = CryptoTypedGroup; #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), declare)] pub type NodeIdGroup = CryptoTypedGroup; #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), declare)] -pub type HashDigestGroup = CryptoTypedGroup; +pub type RouteIdGroup = CryptoTypedGroup; +#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), declare)] +pub type MemberIdGroup = CryptoTypedGroup; impl From for HashDigest { fn from(value: NodeId) -> Self { - HashDigest::new(value.kind, value.value.into()) + HashDigest::new(value.kind(), value.into_value().into()) } } impl From for HashDigest { fn from(value: RecordKey) -> Self { - HashDigest::new(value.kind, value.value.into()) + HashDigest::new(value.kind(), value.into_value().into()) } } impl From for PublicKey { fn from(value: NodeId) -> Self { - PublicKey::new(value.kind, value.value.into()) + PublicKey::new(value.kind(), value.into_value().into()) } } impl From for NodeId { fn from(value: PublicKey) -> Self { - NodeId::new(value.kind, value.value.into()) + NodeId::new(value.kind(), value.into_value().into()) } } impl From for PublicKeyGroup { fn from(value: NodeIdGroup) -> Self { - let items: Vec = value.iter().map(|node_id| (*node_id).into()).collect(); + let items: Vec = value.iter().map(|node_id| node_id.clone().into()).collect(); PublicKeyGroup::from(items) } } impl From for NodeIdGroup { fn from(value: PublicKeyGroup) -> Self { - let items: Vec = value.iter().map(|node_id| (*node_id).into()).collect(); + let items: Vec = value.iter().map(|node_id| node_id.clone().into()).collect(); NodeIdGroup::from(items) } } diff --git a/veilid-core/src/crypto/vld0/mod.rs b/veilid-core/src/crypto/vld0/mod.rs index 62be39f9..968a2352 100644 --- a/veilid-core/src/crypto/vld0/mod.rs +++ b/veilid-core/src/crypto/vld0/mod.rs @@ -1,3 +1,5 @@ +pub mod sizes; + use super::*; use argon2::{ @@ -13,25 +15,32 @@ use curve25519_dalek::digest::Digest; use ed25519_dalek as ed; use x25519_dalek as xd; -const VEILID_DOMAIN_SIGN: &[u8] = b"VLD0_SIGN"; -const VEILID_DOMAIN_CRYPT: &[u8] = b"VLD0_CRYPT"; +const VLD0_DOMAIN_SIGN: &[u8] = b"VLD0_SIGN"; +const VLD0_DOMAIN_CRYPT: &[u8] = b"VLD0_CRYPT"; -const AEAD_OVERHEAD: usize = 16; +const VLD0_AEAD_OVERHEAD: usize = 16; pub const CRYPTO_KIND_VLD0: CryptoKind = CryptoKind(*b"VLD0"); +pub use sizes::*; fn public_to_x25519_pk(public: &BarePublicKey) -> VeilidAPIResult { - let pk_ed = ed::VerifyingKey::from_bytes(&public.bytes).map_err(VeilidAPIError::internal)?; + let pk_ed = ed::VerifyingKey::from_bytes( + public + .bytes() + .try_into() + .map_err(VeilidAPIError::internal)?, + ) + .map_err(VeilidAPIError::internal)?; Ok(xd::PublicKey::from(*pk_ed.to_montgomery().as_bytes())) } fn secret_to_x25519_sk(secret: &BareSecretKey) -> VeilidAPIResult { // NOTE: ed::SigningKey.to_scalar() does not produce an unreduced scalar, we want the raw bytes here // See https://github.com/dalek-cryptography/curve25519-dalek/issues/565 - let hash: [u8; SIGNATURE_LENGTH] = ed::Sha512::default() - .chain_update(secret.bytes) + let hash: [u8; VLD0_SIGNATURE_LENGTH] = ed::Sha512::default() + .chain_update(secret.bytes()) .finalize() .into(); - let mut output = [0u8; SECRET_KEY_LENGTH]; - output.copy_from_slice(&hash[..SECRET_KEY_LENGTH]); + let mut output = [0u8; VLD0_SECRET_KEY_LENGTH]; + output.copy_from_slice(&hash[..VLD0_SECRET_KEY_LENGTH]); Ok(xd::StaticSecret::from(output)) } @@ -40,8 +49,8 @@ pub(crate) fn vld0_generate_keypair() -> BareKeyPair { let mut csprng = VeilidRng {}; let signing_key = ed::SigningKey::generate(&mut csprng); let verifying_key = signing_key.verifying_key(); - let public_key = BarePublicKey::new(verifying_key.to_bytes()); - let secret_key = BareSecretKey::new(signing_key.to_bytes()); + let public_key = BarePublicKey::new(&verifying_key.to_bytes()); + let secret_key = BareSecretKey::new(&signing_key.to_bytes()); BareKeyPair::new(public_key, secret_key) } @@ -86,9 +95,7 @@ impl CryptoSystem for CryptoSystemVLD0 { random_bytes(bytes.as_mut()); bytes } - fn default_salt_length(&self) -> u32 { - 16 - } + #[instrument(level = "trace", target = "crypto", skip_all)] fn hash_password(&self, password: &[u8], salt: &[u8]) -> VeilidAPIResult { if salt.len() < Salt::MIN_LENGTH || salt.len() > Salt::MAX_LENGTH { @@ -129,25 +136,25 @@ impl CryptoSystem for CryptoSystemVLD0 { // Argon2 with default params (Argon2id v19) let argon2 = Argon2::default(); - let mut output_key_material = [0u8; SHARED_SECRET_LENGTH]; + let mut output_key_material = [0u8; VLD0_SHARED_SECRET_LENGTH]; argon2 .hash_password_into(password, salt, &mut output_key_material) .map_err(VeilidAPIError::generic)?; - Ok(BareSharedSecret::new(output_key_material)) + Ok(BareSharedSecret::new(&output_key_material)) } #[instrument(level = "trace", target = "crypto", skip_all)] fn random_nonce(&self) -> BareNonce { - let mut nonce = [0u8; NONCE_LENGTH]; + let mut nonce = [0u8; VLD0_NONCE_LENGTH]; random_bytes(&mut nonce); - BareNonce::new(nonce) + BareNonce::new(&nonce) } #[instrument(level = "trace", target = "crypto", skip_all)] fn random_shared_secret(&self) -> BareSharedSecret { - let mut s = [0u8; SHARED_SECRET_LENGTH]; + let mut s = [0u8; VLD0_SHARED_SECRET_LENGTH]; random_bytes(&mut s); - BareSharedSecret::new(s) + BareSharedSecret::new(&s) } #[instrument(level = "trace", target = "crypto", skip_all)] @@ -162,11 +169,11 @@ impl CryptoSystem for CryptoSystemVLD0 { let dh_bytes = sk_xd.diffie_hellman(&pk_xd).to_bytes(); let mut hasher = blake3::Hasher::new(); - hasher.update(VEILID_DOMAIN_CRYPT); + hasher.update(VLD0_DOMAIN_CRYPT); hasher.update(&dh_bytes); let output = hasher.finalize(); - Ok(BareSharedSecret::new(*output.as_bytes())) + Ok(BareSharedSecret::new(output.as_bytes())) } #[instrument(level = "trace", target = "crypto", skip_all)] @@ -176,7 +183,7 @@ impl CryptoSystem for CryptoSystemVLD0 { #[instrument(level = "trace", target = "crypto", skip_all)] fn generate_hash(&self, data: &[u8]) -> BareHashDigest { - BareHashDigest::new(*blake3::hash(data).as_bytes()) + BareHashDigest::new(blake3::hash(data).as_bytes()) } #[instrument(level = "trace", target = "crypto", skip_all)] @@ -186,10 +193,35 @@ impl CryptoSystem for CryptoSystemVLD0 { ) -> VeilidAPIResult { let mut hasher = blake3::Hasher::new(); std::io::copy(reader, &mut hasher).map_err(VeilidAPIError::generic)?; - Ok(BarePublicKey::new(*hasher.finalize().as_bytes())) + Ok(BarePublicKey::new(hasher.finalize().as_bytes())) } // Validation + fn shared_secret_length(&self) -> usize { + VLD0_SHARED_SECRET_LENGTH + } + fn nonce_length(&self) -> usize { + VLD0_NONCE_LENGTH + } + fn hash_digest_length(&self) -> usize { + VLD0_HASH_DIGEST_LENGTH + } + fn public_key_length(&self) -> usize { + VLD0_PUBLIC_KEY_LENGTH + } + fn secret_key_length(&self) -> usize { + VLD0_SECRET_KEY_LENGTH + } + fn signature_length(&self) -> usize { + VLD0_SIGNATURE_LENGTH + } + fn default_salt_length(&self) -> usize { + 16 + } + fn aead_overhead(&self) -> usize { + VLD0_AEAD_OVERHEAD + } + #[instrument(level = "trace", target = "crypto", skip_all)] fn validate_keypair(&self, public_key: &BarePublicKey, secret_key: &BareSecretKey) -> bool { let data = vec![0u8; 512]; @@ -206,7 +238,7 @@ impl CryptoSystem for CryptoSystemVLD0 { fn validate_hash(&self, data: &[u8], hash_digest: &BareHashDigest) -> bool { let bytes = *blake3::hash(data).as_bytes(); - bytes == hash_digest.bytes + bytes == hash_digest.bytes() } #[instrument(level = "trace", target = "crypto", skip_all)] @@ -218,19 +250,19 @@ impl CryptoSystem for CryptoSystemVLD0 { let mut hasher = blake3::Hasher::new(); std::io::copy(reader, &mut hasher).map_err(VeilidAPIError::generic)?; let bytes = *hasher.finalize().as_bytes(); - Ok(bytes == hash_digest.bytes) + Ok(bytes == hash_digest.bytes()) } // Distance Metric #[instrument(level = "trace", target = "crypto", skip_all)] fn distance(&self, hash1: &BareHashDigest, hash2: &BareHashDigest) -> BareHashDistance { - let mut bytes = [0u8; CRYPTO_KEY_LENGTH]; + let mut bytes = [0u8; VLD0_HASH_DIGEST_LENGTH]; - (0..CRYPTO_KEY_LENGTH).for_each(|n| { - bytes[n] = hash1.bytes[n] ^ hash2.bytes[n]; + (0..VLD0_HASH_DIGEST_LENGTH).for_each(|n| { + bytes[n] = hash1[n] ^ hash2[n]; }); - BareHashDistance::new(bytes) + BareHashDistance::new(&bytes) } // Authentication @@ -241,11 +273,11 @@ impl CryptoSystem for CryptoSystemVLD0 { secret_key: &BareSecretKey, data: &[u8], ) -> VeilidAPIResult { - let mut kpb: [u8; SECRET_KEY_LENGTH + PUBLIC_KEY_LENGTH] = - [0u8; SECRET_KEY_LENGTH + PUBLIC_KEY_LENGTH]; + let mut kpb: [u8; VLD0_SECRET_KEY_LENGTH + VLD0_PUBLIC_KEY_LENGTH] = + [0u8; VLD0_SECRET_KEY_LENGTH + VLD0_PUBLIC_KEY_LENGTH]; - kpb[..SECRET_KEY_LENGTH].copy_from_slice(&secret_key.bytes); - kpb[SECRET_KEY_LENGTH..].copy_from_slice(&public_key.bytes); + kpb[..VLD0_SECRET_KEY_LENGTH].copy_from_slice(secret_key); + kpb[VLD0_SECRET_KEY_LENGTH..].copy_from_slice(public_key); let keypair = ed::SigningKey::from_keypair_bytes(&kpb) .map_err(|e| VeilidAPIError::parse_error("Keypair is invalid", e))?; @@ -253,10 +285,10 @@ impl CryptoSystem for CryptoSystemVLD0 { dig.update(data); let sig_bytes = keypair - .sign_prehashed(dig, Some(VEILID_DOMAIN_SIGN)) + .sign_prehashed(dig, Some(VLD0_DOMAIN_SIGN)) .map_err(VeilidAPIError::internal)?; - let sig = BareSignature::new(sig_bytes.to_bytes()); + let sig = BareSignature::new(&sig_bytes.to_bytes()); if !self.verify(public_key, data, &sig)? { apibail_internal!("newly created signature does not verify"); @@ -271,15 +303,25 @@ impl CryptoSystem for CryptoSystemVLD0 { data: &[u8], signature: &BareSignature, ) -> VeilidAPIResult { - let pk = ed::VerifyingKey::from_bytes(&public_key.bytes) - .map_err(|e| VeilidAPIError::parse_error("Public key is invalid", e))?; - let sig = ed::Signature::from_bytes(&signature.bytes); + let pk = ed::VerifyingKey::from_bytes( + public_key + .bytes() + .try_into() + .map_err(VeilidAPIError::internal)?, + ) + .map_err(|e| VeilidAPIError::parse_error("Public key is invalid", e))?; + let sig = ed::Signature::from_bytes( + signature + .bytes() + .try_into() + .map_err(VeilidAPIError::internal)?, + ); let mut dig: ed::Sha512 = ed::Sha512::default(); dig.update(data); if pk - .verify_prehashed_strict(dig, Some(VEILID_DOMAIN_SIGN), &sig) + .verify_prehashed_strict(dig, Some(VLD0_DOMAIN_SIGN), &sig) .is_err() { return Ok(false); @@ -288,10 +330,6 @@ impl CryptoSystem for CryptoSystemVLD0 { } // AEAD Encrypt/Decrypt - fn aead_overhead(&self) -> usize { - AEAD_OVERHEAD - } - #[instrument(level = "trace", target = "crypto", skip_all)] fn decrypt_in_place_aead( &self, @@ -300,8 +338,15 @@ impl CryptoSystem for CryptoSystemVLD0 { shared_secret: &BareSharedSecret, associated_data: Option<&[u8]>, ) -> VeilidAPIResult<()> { - let key = ch::Key::from(shared_secret.bytes); - let xnonce = ch::XNonce::from(nonce.bytes); + let shared_secret_bytes: [u8; VLD0_SHARED_SECRET_LENGTH] = shared_secret + .bytes() + .try_into() + .map_err(VeilidAPIError::internal)?; + let nonce_bytes: [u8; VLD0_NONCE_LENGTH] = + nonce.bytes().try_into().map_err(VeilidAPIError::internal)?; + + let key = ch::Key::from(shared_secret_bytes); + let xnonce = ch::XNonce::from(nonce_bytes); let aead = ch::XChaCha20Poly1305::new(&key); aead.decrypt_in_place(&xnonce, associated_data.unwrap_or(b""), body) .map_err(map_to_string) @@ -331,8 +376,15 @@ impl CryptoSystem for CryptoSystemVLD0 { shared_secret: &BareSharedSecret, associated_data: Option<&[u8]>, ) -> VeilidAPIResult<()> { - let key = ch::Key::from(shared_secret.bytes); - let xnonce = ch::XNonce::from(nonce.bytes); + let shared_secret_bytes: [u8; VLD0_SHARED_SECRET_LENGTH] = shared_secret + .bytes() + .try_into() + .map_err(VeilidAPIError::internal)?; + let nonce_bytes: [u8; VLD0_NONCE_LENGTH] = + nonce.bytes().try_into().map_err(VeilidAPIError::internal)?; + + let key = ch::Key::from(shared_secret_bytes); + let xnonce = ch::XNonce::from(nonce_bytes); let aead = ch::XChaCha20Poly1305::new(&key); aead.encrypt_in_place(&xnonce, associated_data.unwrap_or(b""), body) @@ -362,10 +414,19 @@ impl CryptoSystem for CryptoSystemVLD0 { body: &mut [u8], nonce: &BareNonce, shared_secret: &BareSharedSecret, - ) { - let mut cipher = - ::new(&shared_secret.bytes.into(), &nonce.bytes.into()); + ) -> VeilidAPIResult<()> { + let shared_secret_bytes: [u8; VLD0_SHARED_SECRET_LENGTH] = shared_secret + .bytes() + .try_into() + .map_err(VeilidAPIError::internal)?; + let nonce_bytes: [u8; VLD0_NONCE_LENGTH] = + nonce.bytes().try_into().map_err(VeilidAPIError::internal)?; + let key = ch::Key::from(shared_secret_bytes); + let xnonce = ch::XNonce::from(nonce_bytes); + + let mut cipher = ::new(&key, &xnonce); cipher.apply_keystream(body); + Ok(()) } #[instrument(level = "trace", target = "crypto", skip_all)] @@ -375,10 +436,21 @@ impl CryptoSystem for CryptoSystemVLD0 { out_buf: &mut [u8], nonce: &BareNonce, shared_secret: &BareSharedSecret, - ) { - let mut cipher = - ::new(&shared_secret.bytes.into(), &nonce.bytes.into()); - cipher.apply_keystream_b2b(in_buf, out_buf).unwrap(); + ) -> VeilidAPIResult<()> { + let shared_secret_bytes: [u8; VLD0_SHARED_SECRET_LENGTH] = shared_secret + .bytes() + .try_into() + .map_err(VeilidAPIError::internal)?; + let nonce_bytes: [u8; VLD0_NONCE_LENGTH] = + nonce.bytes().try_into().map_err(VeilidAPIError::internal)?; + let key = ch::Key::from(shared_secret_bytes); + let xnonce = ch::XNonce::from(nonce_bytes); + + let mut cipher = ::new(&key, &xnonce); + cipher + .apply_keystream_b2b(in_buf, out_buf) + .map_err(VeilidAPIError::generic)?; + Ok(()) } #[instrument(level = "trace", target = "crypto", skip_all)] @@ -387,10 +459,10 @@ impl CryptoSystem for CryptoSystemVLD0 { in_buf: &[u8], nonce: &BareNonce, shared_secret: &BareSharedSecret, - ) -> Vec { + ) -> VeilidAPIResult> { let mut out_buf = unsafe { aligned_8_u8_vec_uninit(in_buf.len()) }; - self.crypt_b2b_no_auth(in_buf, &mut out_buf, nonce, shared_secret); - out_buf + self.crypt_b2b_no_auth(in_buf, &mut out_buf, nonce, shared_secret)?; + Ok(out_buf) } #[instrument(level = "trace", target = "crypto", skip_all)] @@ -399,9 +471,9 @@ impl CryptoSystem for CryptoSystemVLD0 { in_buf: &[u8], nonce: &BareNonce, shared_secret: &BareSharedSecret, - ) -> Vec { + ) -> VeilidAPIResult> { let mut out_buf = unsafe { unaligned_u8_vec_uninit(in_buf.len()) }; - self.crypt_b2b_no_auth(in_buf, &mut out_buf, nonce, shared_secret); - out_buf + self.crypt_b2b_no_auth(in_buf, &mut out_buf, nonce, shared_secret)?; + Ok(out_buf) } } diff --git a/veilid-core/src/crypto/vld0/sizes.rs b/veilid-core/src/crypto/vld0/sizes.rs new file mode 100644 index 00000000..59cb38f9 --- /dev/null +++ b/veilid-core/src/crypto/vld0/sizes.rs @@ -0,0 +1,12 @@ +/// Length of a crypto key in bytes +pub const VLD0_PUBLIC_KEY_LENGTH: usize = 32; +/// Length of a secret key in bytes +pub const VLD0_SECRET_KEY_LENGTH: usize = 32; +/// Length of a signature in bytes +pub const VLD0_SIGNATURE_LENGTH: usize = 64; +/// Length of a nonce in bytes +pub const VLD0_NONCE_LENGTH: usize = 24; +/// Length of a hash digest in bytes +pub const VLD0_HASH_DIGEST_LENGTH: usize = 32; +/// Length of a shared secret in bytes +pub const VLD0_SHARED_SECRET_LENGTH: usize = 32; diff --git a/veilid-core/src/network_manager/address_filter.rs b/veilid-core/src/network_manager/address_filter.rs index 873c559a..fb83f03a 100644 --- a/veilid-core/src/network_manager/address_filter.rs +++ b/veilid-core/src/network_manager/address_filter.rs @@ -184,7 +184,7 @@ impl AddressFilter { if cur_ts.as_u64().saturating_sub(value.timestamp.as_u64()) > self.punishment_duration_min as u64 * 60_000_000u64 { - dead_keys.push(*key); + dead_keys.push(key.clone()); } } for key in dead_keys { @@ -310,7 +310,7 @@ impl AddressFilter { } pub fn punish_node_id(&self, node_id: NodeId, reason: PunishmentReason) { - if let Ok(Some(nr)) = self.routing_table().lookup_node_ref(node_id) { + if let Ok(Some(nr)) = self.routing_table().lookup_node_ref(node_id.clone()) { // make the entry dead if it's punished nr.operate_mut(|_rti, e| e.set_punished(Some(reason))); } diff --git a/veilid-core/src/network_manager/bootstrap/bootstrap_record.rs b/veilid-core/src/network_manager/bootstrap/bootstrap_record.rs index 554ec830..e3eace61 100644 --- a/veilid-core/src/network_manager/bootstrap/bootstrap_record.rs +++ b/veilid-core/src/network_manager/bootstrap/bootstrap_record.rs @@ -156,7 +156,7 @@ impl BootstrapRecord { let crypto = network_manager.crypto(); let sig = match crypto.generate_signatures(v1.as_bytes(), &[signing_key_pair], |kp, sig| { - Signature::new(kp.kind, sig).to_string() + Signature::new(kp.kind(), sig).to_string() }) { Ok(v) => { let Some(sig) = v.first().cloned() else { @@ -393,13 +393,13 @@ impl BootstrapRecord { // Validate signature against any signing keys if we have them if !signing_keys.is_empty() { let mut validated = false; - for key in signing_keys.iter().copied() { + for key in signing_keys { if let Some(valid_keys) = network_manager.crypto().verify_signatures( - &[key], + &[key.clone()], signed_str.as_bytes(), - &[sig], + &[sig.clone()], )? { - if valid_keys.contains(&key) { + if valid_keys.contains(key) { validated = true; break; } diff --git a/veilid-core/src/network_manager/mod.rs b/veilid-core/src/network_manager/mod.rs index 016eddef..8ff80625 100644 --- a/veilid-core/src/network_manager/mod.rs +++ b/veilid-core/src/network_manager/mod.rs @@ -286,7 +286,7 @@ impl NetworkManager { Some( bcs.derive_shared_secret( network_key_password.as_bytes(), - &bcs.generate_hash(network_key_password.as_bytes()).bytes, + &bcs.generate_hash(network_key_password.as_bytes()), ) .expect("failed to derive network key"), ) @@ -616,9 +616,9 @@ impl NetworkManager { let receipt = Receipt::try_new( best_envelope_version(), - node_id.kind, + node_id.kind(), nonce, - node_id.value, + node_id.value(), extra_data, )?; let out = receipt @@ -656,9 +656,9 @@ impl NetworkManager { let receipt = Receipt::try_new( best_envelope_version(), - node_id.kind, + node_id.kind(), nonce, - node_id.value, + node_id.value(), extra_data, )?; let out = receipt @@ -881,7 +881,7 @@ impl NetworkManager { // DH to get encryption key let routing_table = self.routing_table(); let crypto = self.crypto(); - let Some(vcrypto) = crypto.get(dest_node_id.kind) else { + let Some(vcrypto) = crypto.get(dest_node_id.kind()) else { bail!("should not have a destination with incompatible crypto here"); }; @@ -895,11 +895,11 @@ impl NetworkManager { // Encode envelope let envelope = Envelope::new( version, - node_id.kind, + node_id.kind(), ts, nonce, - node_id.value, - dest_node_id.value, + node_id.value(), + dest_node_id.value(), ); envelope .to_encrypted_data(&crypto, body.as_ref(), &node_id_secret, &self.network_key) @@ -1101,15 +1101,15 @@ impl NetworkManager { let rpc = self.rpc_processor(); // See if this sender is punished, if so, ignore the packet - let sender_id = envelope.get_sender_typed_id(); - if self.address_filter().is_node_id_punished(sender_id) { + let sender_id = envelope.get_sender_id(); + if self.address_filter().is_node_id_punished(sender_id.clone()) { return Ok(false); } // Peek at header and see if we need to relay this // If the recipient id is not our node id, then it needs relaying - let recipient_id = envelope.get_recipient_typed_id(); - if !routing_table.matches_own_node_id(&[recipient_id]) { + let recipient_id = envelope.get_recipient_id(); + if !routing_table.matches_own_node_id(&[recipient_id.clone()]) { // See if the source node is allowed to resolve nodes // This is a costly operation, so only outbound-relay permitted // nodes are allowed to do this, for example PWA users @@ -1119,10 +1119,13 @@ impl NetworkManager { // xxx: that 'localnetwork' routing domain nodes could be allowed to // xxx: full relay as well as client_allowlist nodes... - let some_relay_nr = if self.check_client_allowlist(sender_id) { + let some_relay_nr = if self.check_client_allowlist(sender_id.clone()) { // Full relay allowed, do a full resolve_node match rpc - .resolve_node(recipient_id, SafetySelection::Unsafe(Sequencing::default())) + .resolve_node( + recipient_id.clone(), + SafetySelection::Unsafe(Sequencing::default()), + ) .await { Ok(v) => v.map(|nr| nr.default_filtered()), diff --git a/veilid-core/src/network_manager/receipt_manager.rs b/veilid-core/src/network_manager/receipt_manager.rs index dfc636c8..3b30ff8f 100644 --- a/veilid-core/src/network_manager/receipt_manager.rs +++ b/veilid-core/src/network_manager/receipt_manager.rs @@ -231,7 +231,7 @@ impl ReceiptManager { let receipt_inner = v.lock(); if receipt_inner.expiration_ts <= now { // Expire this receipt - expired_nonces.push(*k); + expired_nonces.push(k.clone()); } else if new_next_oldest_ts.is_none() || receipt_inner.expiration_ts < new_next_oldest_ts.unwrap() { diff --git a/veilid-core/src/network_manager/send_data.rs b/veilid-core/src/network_manager/send_data.rs index 0d8d1697..725a77ba 100644 --- a/veilid-core/src/network_manager/send_data.rs +++ b/veilid-core/src/network_manager/send_data.rs @@ -503,7 +503,7 @@ impl NetworkManager { if target_node_ref .node_ids() .iter() - .any(|nid| self.address_filter().is_node_id_punished(*nid)) + .any(|nid| self.address_filter().is_node_id_punished(nid.clone())) { return Ok(None); } @@ -647,7 +647,11 @@ impl NetworkManager { ContactMethod::Direct(di) => Some(NodeContactMethodKind::Direct(di)), ContactMethod::SignalReverse(relay_key, target_key) => { let mut relay_nr = routing_table - .lookup_and_filter_noderef(relay_key, routing_domain.into(), dial_info_filter)? + .lookup_and_filter_noderef( + relay_key.clone(), + routing_domain.into(), + dial_info_filter, + )? .ok_or_else(|| { eyre!( "couldn't look up relay for signal reverse: {} with filter {:?}", @@ -702,7 +706,11 @@ impl NetworkManager { } ContactMethod::SignalHolePunch(relay_key, target_key) => { let mut relay_nr = routing_table - .lookup_and_filter_noderef(relay_key, routing_domain.into(), dial_info_filter)? + .lookup_and_filter_noderef( + relay_key.clone(), + routing_domain.into(), + dial_info_filter, + )? .ok_or_else(|| { eyre!( "couldn't look up relay for hole punch: {} with filter {:?}", @@ -732,7 +740,11 @@ impl NetworkManager { } ContactMethod::InboundRelay(relay_key) => { let mut relay_nr = routing_table - .lookup_and_filter_noderef(relay_key, routing_domain.into(), dial_info_filter)? + .lookup_and_filter_noderef( + relay_key.clone(), + routing_domain.into(), + dial_info_filter, + )? .ok_or_else(|| { eyre!( "couldn't look up relay for inbound relay: {} with filter {:?}", @@ -745,7 +757,11 @@ impl NetworkManager { } ContactMethod::OutboundRelay(relay_key) => { let mut relay_nr = routing_table - .lookup_and_filter_noderef(relay_key, routing_domain.into(), dial_info_filter)? + .lookup_and_filter_noderef( + relay_key.clone(), + routing_domain.into(), + dial_info_filter, + )? .ok_or_else(|| { eyre!( "couldn't look up relay for outbound relay: {} with filter {:?}", diff --git a/veilid-core/src/network_manager/stats.rs b/veilid-core/src/network_manager/stats.rs index 4cdca5ad..4a36c5f3 100644 --- a/veilid-core/src/network_manager/stats.rs +++ b/veilid-core/src/network_manager/stats.rs @@ -127,7 +127,7 @@ impl NetworkManager { if let Ok(Some(nr)) = routing_table.lookup_node_ref(k) { let peer_stats = nr.peer_stats(); let peer = PeerTableData { - node_ids: nr.node_ids().iter().copied().collect(), + node_ids: nr.node_ids().iter().cloned().collect(), peer_address: v.last_connection.remote().to_string(), peer_stats, }; diff --git a/veilid-core/src/network_manager/tests/test_bootstrap.rs b/veilid-core/src/network_manager/tests/test_bootstrap.rs index fd902241..82b859e4 100644 --- a/veilid-core/src/network_manager/tests/test_bootstrap.rs +++ b/veilid-core/src/network_manager/tests/test_bootstrap.rs @@ -77,10 +77,14 @@ pub async fn test_bootstrap_v1() { println!("signing_key_pairs: {:?}", signing_key_pairs); let signing_keys = signing_key_pairs .iter() - .map(|skp| PublicKey::new(skp.kind, skp.value.key)) + .map(|skp| PublicKey::new(skp.kind(), skp.ref_value().key())) .collect::>(); let v1str = bsrec - .to_v1_string(&network_manager, &dial_info_converter, signing_key_pairs[0]) + .to_v1_string( + &network_manager, + &dial_info_converter, + signing_key_pairs[0].clone(), + ) .await .expect("should make string"); let bsrec2 = BootstrapRecord::new_from_v1_str( diff --git a/veilid-core/src/network_manager/tests/test_signed_node_info.rs b/veilid-core/src/network_manager/tests/test_signed_node_info.rs index e06b12c3..eb55a92c 100644 --- a/veilid-core/src/network_manager/tests/test_signed_node_info.rs +++ b/veilid-core/src/network_manager/tests/test_signed_node_info.rs @@ -31,11 +31,11 @@ pub async fn test_signed_node_info() { let keypair = vcrypto.generate_keypair(); let sni = SignedDirectNodeInfo::make_signatures( &crypto, - vec![KeyPair::new(ck, keypair)], + vec![KeyPair::new(ck, keypair.clone())], node_info.clone(), ) .unwrap(); - let tks: PublicKeyGroup = PublicKey::new(ck, keypair.key).into(); + let tks: PublicKeyGroup = PublicKey::new(ck, keypair.key()).into(); let tks_node_ids = NodeIdGroup::from(tks.clone()); let oldtkslen = tks.len(); let sdni = SignedDirectNodeInfo::new( @@ -49,7 +49,7 @@ pub async fn test_signed_node_info() { // Test incorrect validation let keypair1 = vcrypto.generate_keypair(); - let tks1: PublicKeyGroup = PublicKey::new(ck, keypair1.key).into(); + let tks1: PublicKeyGroup = PublicKey::new(ck, keypair1.key()).into(); let sdni = SignedDirectNodeInfo::new( node_info.clone(), sni.timestamp(), @@ -63,7 +63,7 @@ pub async fn test_signed_node_info() { PublicKey::new(fake_crypto_kind, BarePublicKey::default()).into(); let mut sigsfake = sni.signatures().to_vec(); sigsfake.push(Signature::new(fake_crypto_kind, BareSignature::default())); - tksfake.add(PublicKey::new(ck, keypair.key)); + tksfake.add(PublicKey::new(ck, keypair.key())); let sdnifake = SignedDirectNodeInfo::new(node_info.clone(), sni.timestamp(), sigsfake.clone()); let tksfake_validated = sdnifake.validate(&tksfake.into(), &crypto).unwrap(); @@ -86,12 +86,12 @@ pub async fn test_signed_node_info() { // Test correct validation let keypair2 = vcrypto.generate_keypair(); - let tks2: PublicKeyGroup = PublicKey::new(ck, keypair2.key).into(); + let tks2: PublicKeyGroup = PublicKey::new(ck, keypair2.key()).into(); let oldtks2len = tks2.len(); let sni2 = SignedRelayedNodeInfo::make_signatures( &crypto, - vec![KeyPair::new(ck, keypair2)], + vec![KeyPair::new(ck, keypair2.clone())], node_info2.clone(), tks_node_ids.clone(), sni.clone(), @@ -111,7 +111,7 @@ pub async fn test_signed_node_info() { // Test incorrect validation let keypair3 = vcrypto.generate_keypair(); - let tks3: PublicKeyGroup = PublicKey::new(ck, keypair3.key).into(); + let tks3: PublicKeyGroup = PublicKey::new(ck, keypair3.key()).into(); let srni = SignedRelayedNodeInfo::new( node_info2.clone(), @@ -128,7 +128,7 @@ pub async fn test_signed_node_info() { PublicKey::new(fake_crypto_kind, BarePublicKey::default()).into(); let mut sigsfake3 = sni2.signatures().to_vec(); sigsfake3.push(Signature::new(fake_crypto_kind, BareSignature::default())); - tksfake3.add(PublicKey::new(ck, keypair2.key)); + tksfake3.add(PublicKey::new(ck, keypair2.key())); let srnifake = SignedRelayedNodeInfo::new( node_info2.clone(), tks.clone().into(), diff --git a/veilid-core/src/routing_table/bucket.rs b/veilid-core/src/routing_table/bucket.rs index a722c2fe..a3bafcaf 100644 --- a/veilid-core/src/routing_table/bucket.rs +++ b/veilid-core/src/routing_table/bucket.rs @@ -69,7 +69,7 @@ impl Bucket { entry_index as u32 }); entries.push(SerializedBucketEntryData { - key: *k, + key: k.clone(), value: *entry_index, }); } @@ -83,7 +83,10 @@ impl Bucket { veilid_log!(self trace "Node added: {}:{}", self.kind, node_id_key); // Add new entry - let entry = Arc::new(BucketEntry::new(NodeId::new(self.kind, node_id_key))); + let entry = Arc::new(BucketEntry::new(NodeId::new( + self.kind, + node_id_key.clone(), + ))); self.entries.insert(node_id_key, entry.clone()); // Return the new entry @@ -132,8 +135,11 @@ impl Bucket { let mut extra_entries = bucket_len - bucket_depth; // Get the sorted list of entries by their kick order - let mut sorted_entries: Vec<(BareNodeId, Arc)> = - self.entries.iter().map(|(k, v)| (*k, v.clone())).collect(); + let mut sorted_entries: Vec<(BareNodeId, Arc)> = self + .entries + .iter() + .map(|(k, v)| (k.clone(), v.clone())) + .collect(); let cur_ts = Timestamp::now(); sorted_entries.sort_by(|a, b| -> core::cmp::Ordering { if a.0 == b.0 { diff --git a/veilid-core/src/routing_table/bucket_entry.rs b/veilid-core/src/routing_table/bucket_entry.rs index 52da5072..1c0520cd 100644 --- a/veilid-core/src/routing_table/bucket_entry.rs +++ b/veilid-core/src/routing_table/bucket_entry.rs @@ -295,13 +295,13 @@ impl BucketEntryInner { /// Results Err() if this operation would add more crypto kinds than we support pub fn add_node_id(&mut self, node_id: NodeId) -> EyreResult> { let total_node_id_count = self.validated_node_ids.len() + self.unsupported_node_ids.len(); - let node_ids = if VALID_CRYPTO_KINDS.contains(&node_id.kind) { + let node_ids = if VALID_CRYPTO_KINDS.contains(&node_id.kind()) { &mut self.validated_node_ids } else { &mut self.unsupported_node_ids }; - if let Some(old_node_id) = node_ids.get(node_id.kind) { + if let Some(old_node_id) = node_ids.get(node_id.kind()) { // If this was already there we do nothing if old_node_id == node_id { return Ok(None); @@ -1223,7 +1223,7 @@ pub(crate) struct BucketEntry { impl BucketEntry { pub(super) fn new(first_node_id: NodeId) -> Self { // First node id should always be one we support since TypedKeySets are sorted and we must have at least one supported key - assert!(VALID_CRYPTO_KINDS.contains(&first_node_id.kind)); + assert!(VALID_CRYPTO_KINDS.contains(&first_node_id.kind())); let now = Timestamp::now(); let inner = BucketEntryInner { diff --git a/veilid-core/src/routing_table/debug.rs b/veilid-core/src/routing_table/debug.rs index ae24eea2..dde7cd34 100644 --- a/veilid-core/src/routing_table/debug.rs +++ b/veilid-core/src/routing_table/debug.rs @@ -217,7 +217,7 @@ impl RoutingTable { if !filtered_entries.is_empty() { out += &format!("{} Bucket #{}:\n", ck, b); for e in filtered_entries { - let node = *e.0; + let node = e.0.clone(); let can_be_relay = e.1.with(inner, |_rti, e| relay_node_filter(e)); let is_relay = inner diff --git a/veilid-core/src/routing_table/find_peers.rs b/veilid-core/src/routing_table/find_peers.rs index 09952a52..0e7ada7c 100644 --- a/veilid-core/src/routing_table/find_peers.rs +++ b/veilid-core/src/routing_table/find_peers.rs @@ -1,17 +1,17 @@ use super::*; impl RoutingTable { - /// Utility to find the closest nodes to a particular key, preferring reliable nodes first, + /// Utility to find the closest nodes to a particular hash coordinate, preferring reliable nodes first, /// including possibly our own node and nodes further away from the key than our own, /// returning their peer info #[instrument(level = "trace", target = "rtab", skip_all)] pub fn find_preferred_closest_peers( &self, routing_domain: RoutingDomain, - key: NodeId, + hash_coordinate: &HashDigest, capabilities: &[VeilidCapability], ) -> NetworkResult>> { - if Crypto::validate_crypto_kind(key.kind).is_err() { + if Crypto::validate_crypto_kind(hash_coordinate.kind()).is_err() { return NetworkResult::invalid_message("invalid crypto kind"); } @@ -48,7 +48,7 @@ impl RoutingTable { let closest_nodes = match self.find_preferred_closest_nodes( node_count, - key.into(), + hash_coordinate.clone(), filters, // transform |rti, entry| { @@ -57,7 +57,10 @@ impl RoutingTable { ) { Ok(v) => v, Err(e) => { - error!("failed to find closest nodes for key {}: {}", key, e); + error!( + "failed to find closest nodes for key {}: {}", + hash_coordinate, e + ); return NetworkResult::invalid_message("failed to find closest nodes for key"); } }; @@ -72,11 +75,11 @@ impl RoutingTable { pub fn find_preferred_peers_closer_to_key( &self, routing_domain: RoutingDomain, - key: RecordKey, + hash_coordinate: &HashDigest, required_capabilities: Vec, ) -> NetworkResult>> { // add node information for the requesting node to our routing table - let crypto_kind = key.kind; + let crypto_kind = hash_coordinate.kind(); let own_node_id = self.node_id(crypto_kind); // find N nodes closest to the target node in our routing table @@ -88,10 +91,11 @@ impl RoutingTable { let vcrypto = &vcrypto; let own_distance = vcrypto.distance( - &BareHashDigest::from(own_node_id.value), - &BareHashDigest::from(key.value), + &BareHashDigest::from(own_node_id.value()), + &hash_coordinate.value(), ); + let value = hash_coordinate.value(); let filter = Box::new( move |rti: &RoutingTableInner, opt_entry: Option>| { // Exclude our own node @@ -115,10 +119,8 @@ impl RoutingTable { let Some(entry_node_id) = e.node_ids().get(crypto_kind) else { return false; }; - let entry_distance = vcrypto.distance( - &BareHashDigest::from(entry_node_id.value), - &BareHashDigest::from(key.value), - ); + let entry_distance = vcrypto + .distance(&BareHashDigest::from(entry_node_id.value()), &value.clone()); if entry_distance >= own_distance { return false; } @@ -135,7 +137,7 @@ impl RoutingTable { // let closest_nodes = match self.find_preferred_closest_nodes( node_count, - key.into(), + hash_coordinate.clone(), filters, // transform |rti, entry| { @@ -146,7 +148,10 @@ impl RoutingTable { ) { Ok(v) => v, Err(e) => { - error!("failed to find closest nodes for key {}: {}", key, e); + error!( + "failed to find closest nodes for key {}: {}", + hash_coordinate, e + ); return NetworkResult::invalid_message("failed to find closest nodes for key"); } }; @@ -155,8 +160,8 @@ impl RoutingTable { // This same test is used on the other side so we vet things here let valid = match Self::verify_peers_closer( vcrypto, - own_node_id.into(), - key.into(), + &own_node_id.clone().into(), + &hash_coordinate.clone(), &closest_nodes, ) { Ok(v) => v, @@ -167,7 +172,7 @@ impl RoutingTable { if !valid { error!( "non-closer peers returned: own_node_id={:#?} key={:#?} closest_nodes={:#?}", - own_node_id, key, closest_nodes + own_node_id, hash_coordinate, closest_nodes ); } @@ -178,23 +183,23 @@ impl RoutingTable { #[instrument(level = "trace", target = "rtab", skip_all, err)] pub fn verify_peers_closer( vcrypto: &crypto::CryptoSystemGuard<'_>, - key_far: HashDigest, - key_near: HashDigest, + key_far: &HashDigest, + key_near: &HashDigest, peers: &[Arc], ) -> EyreResult { let kind = vcrypto.kind(); - if key_far.kind != kind || key_near.kind != kind { + if key_far.kind() != kind || key_near.kind() != kind { bail!("keys all need the same cryptosystem"); } let mut closer = true; - let d_far = vcrypto.distance(&key_far.value, &key_near.value); + let d_far = vcrypto.distance(key_far.ref_value(), key_near.ref_value()); for peer in peers { let Some(key_peer) = peer.node_ids().get(kind) else { bail!("peers need to have a key with the same cryptosystem"); }; - let d_near = vcrypto.distance(&key_near.value, &key_peer.value.into()); + let d_near = vcrypto.distance(key_near.ref_value(), &key_peer.value().into()); if d_far < d_near { let warning = format!( r#"peer: {} @@ -203,9 +208,9 @@ far (self): {} d_near: {} d_far: {} cmp: {:?}"#, - key_peer.value, - key_near.value, - key_far.value, + key_peer, + key_near, + key_far, d_near, d_far, d_near.cmp(&d_far) diff --git a/veilid-core/src/routing_table/mod.rs b/veilid-core/src/routing_table/mod.rs index 5f9483a4..9b5bd523 100644 --- a/veilid-core/src/routing_table/mod.rs +++ b/veilid-core/src/routing_table/mod.rs @@ -35,6 +35,12 @@ impl_veilid_log_facility!("rtab"); ////////////////////////////////////////////////////////////////////////// +/// Routing table bucket count (one per bit per 32 byte node id) +pub const BUCKET_COUNT: usize = 256; +/// Fixed length for NodeId in bytes +#[expect(dead_code)] +pub const NODE_ID_LENGTH: usize = 32; + /// Minimum number of nodes we need, per crypto kind, per routing domain, or we trigger a bootstrap pub const MIN_BOOTSTRAP_CONNECTIVITY_PEERS: usize = 4; /// Set of routing domains that use the bootstrap mechanism @@ -312,7 +318,7 @@ impl RoutingTable { pub fn node_id_secret_key(&self, kind: CryptoKind) -> BareSecretKey { self.config() .with(|c| c.network.routing_table.node_id_secret.get(kind).unwrap()) - .value + .value() } pub fn node_ids(&self) -> NodeIdGroup { @@ -325,7 +331,7 @@ impl RoutingTable { for ck in VALID_CRYPTO_KINDS { tkps.push(KeyPair::new( ck, - BareKeyPair::new(self.node_id(ck).value.into(), self.node_id_secret_key(ck)), + BareKeyPair::new(self.node_id(ck).value().into(), self.node_id_secret_key(ck)), )); } tkps @@ -333,8 +339,8 @@ impl RoutingTable { pub fn matches_own_node_id(&self, node_ids: &[NodeId]) -> bool { for ni in node_ids { - if let Some(v) = self.node_ids().get(ni.kind) { - if v.value == ni.value { + if let Some(v) = self.node_ids().get(ni.kind()) { + if v.ref_value() == ni.ref_value() { return true; } } @@ -344,22 +350,52 @@ impl RoutingTable { pub fn matches_own_node_id_key(&self, node_id_key: &BareNodeId) -> bool { for tk in self.node_ids().iter() { - if tk.value == *node_id_key { + if tk.ref_value() == node_id_key { return true; } } false } - pub fn calculate_bucket_index(&self, node_id: &NodeId) -> BucketIndex { + /// Produce node id from public key + pub fn generate_node_id(&self, public_key: &PublicKey) -> VeilidAPIResult { + if public_key.ref_value().len() == NODE_ID_LENGTH { + return Ok(NodeId::new( + public_key.kind(), + BareNodeId::new(public_key.ref_value()), + )); + } let crypto = self.crypto(); - let self_node_id_key = self.node_id(node_id.kind).value; - let vcrypto = crypto.get(node_id.kind).unwrap(); + let Some(vcrypto) = crypto.get(public_key.kind()) else { + apibail_generic!("unsupported cryptosystem"); + }; + + let idhash = vcrypto.generate_hash(public_key.ref_value()); + assert!( + idhash.len() >= NODE_ID_LENGTH, + "generate_hash needs to produce at least {} bytes", + NODE_ID_LENGTH + ); + Ok(NodeId::new( + public_key.kind(), + BareNodeId::new(&idhash[0..NODE_ID_LENGTH]), + )) + } + + pub fn calculate_bucket_index(&self, node_id: &NodeId) -> BucketIndex { + assert_eq!( + node_id.ref_value().len() * 8, + BUCKET_COUNT, + "NodeId should be hashed down to BUCKET_COUNT bits" + ); + let crypto = self.crypto(); + let self_node_id_key = self.node_id(node_id.kind()).value(); + let vcrypto = crypto.get(node_id.kind()).unwrap(); ( - node_id.kind, + node_id.kind(), vcrypto .distance( - &BareHashDigest::from(node_id.value), + &BareHashDigest::from(node_id.value()), &BareHashDigest::from(self_node_id_key), ) .first_nonzero_bit() @@ -427,20 +463,18 @@ impl RoutingTable { let c = config.get(); for ck in VALID_CRYPTO_KINDS { if let Some(nid) = c.network.routing_table.node_id.get(ck) { - cache_validity_key.append(&mut nid.value.bytes.to_vec()); + cache_validity_key.extend_from_slice(nid.ref_value()); } } for b in &c.network.routing_table.bootstrap { - cache_validity_key.append(&mut b.as_bytes().to_vec()); + cache_validity_key.extend_from_slice(b.as_bytes()); } - cache_validity_key.append( - &mut c - .network + cache_validity_key.extend_from_slice( + c.network .network_key_password .clone() .unwrap_or_default() - .as_bytes() - .to_vec(), + .as_bytes(), ); }; @@ -515,7 +549,7 @@ impl RoutingTable { veilid_log!(inner warn "crypto kind is not valid, not loading routing table"); return Ok(()); } - if v.len() != PUBLIC_KEY_LENGTH * 8 { + if v.len() != BUCKET_COUNT { veilid_log!(inner warn "bucket count is different, not loading routing table"); return Ok(()); } @@ -665,7 +699,7 @@ impl RoutingTable { fn queue_bucket_kicks(&self, node_ids: NodeIdGroup) { for node_id in node_ids.iter() { // Skip node ids we didn't add to buckets - if !VALID_CRYPTO_KINDS.contains(&node_id.kind) { + if !VALID_CRYPTO_KINDS.contains(&node_id.kind()) { continue; } @@ -677,7 +711,7 @@ impl RoutingTable { /// Resolve an existing routing table entry using any crypto kind and return a reference to it pub fn lookup_any_node_ref(&self, node_id_key: BareNodeId) -> EyreResult> { - self.inner.read().lookup_any_node_ref(node_id_key) + self.inner.read().lookup_bare_node_ref(node_id_key) } /// Resolve an existing routing table entry and return a reference to it @@ -748,22 +782,22 @@ impl RoutingTable { { let inner = self.inner.read(); for (k, _v) in &inner.recent_peers { - recent_peers.push(*k); + recent_peers.push(k.clone()); } } // look up each node and make sure the connection is still live // (uses same logic as send_data, ensuring last_connection works for UDP) - for e in &recent_peers { + for node_id in &recent_peers { let mut dead = true; - if let Ok(Some(nr)) = self.lookup_node_ref(*e) { + if let Ok(Some(nr)) = self.lookup_node_ref(node_id.clone()) { if let Some(last_connection) = nr.last_flow() { - out.push((*e, RecentPeersEntry { last_connection })); + out.push((node_id.clone(), RecentPeersEntry { last_connection })); dead = false; } } if dead { - dead_peers.push(e); + dead_peers.push(node_id); } } diff --git a/veilid-core/src/routing_table/privacy.rs b/veilid-core/src/routing_table/privacy.rs index a0db14b7..f776c5ac 100644 --- a/veilid-core/src/routing_table/privacy.rs +++ b/veilid-core/src/routing_table/privacy.rs @@ -26,7 +26,7 @@ impl fmt::Debug for RouteHopData { #[derive(Clone, Debug)] pub(crate) enum RouteNode { /// Route node is optimized, no contact method information as this node id has been seen before - BareNodeId(BareNodeId), + NodeId(NodeId), /// Route node with full contact method information to ensure the peer is reachable PeerInfo(Arc), } @@ -34,20 +34,16 @@ pub(crate) enum RouteNode { impl RouteNode { pub fn validate(&self, crypto: &Crypto) -> VeilidAPIResult<()> { match self { - RouteNode::BareNodeId(_) => Ok(()), + RouteNode::NodeId(_) => Ok(()), RouteNode::PeerInfo(pi) => pi.validate(crypto), } } - pub fn node_ref( - &self, - routing_table: &RoutingTable, - crypto_kind: CryptoKind, - ) -> Option { + pub fn node_ref(&self, routing_table: &RoutingTable) -> Option { match self { - RouteNode::BareNodeId(id) => { + RouteNode::NodeId(id) => { // - match routing_table.lookup_node_ref(NodeId::new(crypto_kind, *id)) { + match routing_table.lookup_node_ref(id.clone()) { Ok(nr) => nr, Err(e) => { veilid_log!(routing_table debug "failed to look up route node: {}", e); @@ -68,15 +64,15 @@ impl RouteNode { } } - pub fn describe(&self, crypto_kind: CryptoKind) -> String { + pub fn describe(&self) -> String { match self { - RouteNode::BareNodeId(id) => { - format!("{}", NodeId::new(crypto_kind, *id)) + RouteNode::NodeId(id) => { + format!("{}", id) } - RouteNode::PeerInfo(pi) => match pi.node_ids().get(crypto_kind) { + RouteNode::PeerInfo(pi) => match pi.node_ids().best() { Some(id) => format!("{}", id), None => { - format!("({})?{}", crypto_kind, pi.node_ids()) + format!("?({})", pi.node_ids()) } }, } @@ -122,7 +118,6 @@ impl PrivateRouteHops { pub(crate) struct PrivateRoute { /// The public key used for the entire route pub public_key: PublicKey, - pub hop_count: u8, pub hops: PrivateRouteHops, } @@ -131,7 +126,6 @@ impl PrivateRoute { pub fn new_stub(public_key: PublicKey, node: RouteNode) -> Self { Self { public_key, - hop_count: 1, hops: PrivateRouteHops::FirstHop(Box::new(RouteHop { node, next_hop: None, @@ -153,7 +147,7 @@ impl PrivateRoute { /// Get the crypto kind in use for this route pub fn crypto_kind(&self) -> CryptoKind { - self.public_key.kind + self.public_key.kind() } /// Remove the first unencrypted hop if possible @@ -162,13 +156,6 @@ impl PrivateRoute { PrivateRouteHops::FirstHop(first_hop) => { let first_hop_node = first_hop.node.clone(); - // Reduce hop count - if self.hop_count > 0 { - self.hop_count -= 1; - } else { - error!("hop count should not be 0 for first hop"); - } - // Go to next hop self.hops = match first_hop.next_hop.take() { Some(rhd) => PrivateRouteHops::Data(rhd), @@ -189,8 +176,8 @@ impl PrivateRoute { // Get the safety route to use from the spec Some(match &pr_first_hop.node { - RouteNode::BareNodeId(n) => NodeId::new(self.public_key.kind, *n), - RouteNode::PeerInfo(p) => p.node_ids().get(self.public_key.kind).unwrap(), + RouteNode::NodeId(n) => n.clone(), + RouteNode::PeerInfo(p) => p.node_ids().get(self.public_key.kind()).unwrap(), }) } } @@ -199,9 +186,8 @@ impl fmt::Display for PrivateRoute { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, - "PR({:?}+{}{})", + "PR({:?}+{})", self.public_key, - self.hop_count, match &self.hops { PrivateRouteHops::FirstHop(_) => { format!( @@ -233,7 +219,6 @@ pub(crate) enum SafetyRouteHops { #[derive(Clone, Debug)] pub(crate) struct SafetyRoute { pub public_key: PublicKey, - pub hop_count: u8, pub hops: SafetyRouteHops, } @@ -245,7 +230,6 @@ impl SafetyRoute { assert!(matches!(private_route.hops, PrivateRouteHops::Data(_))); Self { public_key, - hop_count: 0, hops: SafetyRouteHops::Private(private_route), } } @@ -257,7 +241,7 @@ impl SafetyRoute { /// Get the crypto kind in use for this route pub fn crypto_kind(&self) -> CryptoKind { - self.public_key.kind + self.public_key.kind() } } @@ -265,9 +249,8 @@ impl fmt::Display for SafetyRoute { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, - "SR({:?}+{}{})", + "SR({:?}+{})", self.public_key, - self.hop_count, match &self.hops { SafetyRouteHops::Data(_) => "".to_owned(), SafetyRouteHops::Private(p) => format!("->{}", p), diff --git a/veilid-core/src/routing_table/route_spec_store/mod.rs b/veilid-core/src/routing_table/route_spec_store/mod.rs index e4790040..4cc2489c 100644 --- a/veilid-core/src/routing_table/route_spec_store/mod.rs +++ b/veilid-core/src/routing_table/route_spec_store/mod.rs @@ -168,7 +168,7 @@ impl RouteSpecStore { directions: DirectionSet, avoid_nodes: &[NodeId], automatic: bool, - ) -> VeilidAPIResult { + ) -> VeilidAPIResult { let inner = &mut *self.inner.lock(); let routing_table = self.routing_table(); let rti = &mut *routing_table.inner.write(); @@ -195,7 +195,7 @@ impl RouteSpecStore { directions: DirectionSet, avoid_nodes: &[NodeId], automatic: bool, - ) -> VeilidAPIResult { + ) -> VeilidAPIResult { use core::cmp::Ordering; if safety_spec.preferred_route.is_some() { @@ -488,20 +488,21 @@ impl RouteSpecStore { // Get the hop cache key for a particular route permutation // uses the same algorithm as RouteSetSpecDetail::make_cache_key let route_permutation_to_hop_cache = - |_rti: &RoutingTableInner, nodes: &[NodeRef], perm: &[usize]| -> Vec { - let mut cache: Vec = Vec::with_capacity(perm.len() * PUBLIC_KEY_LENGTH); + |_rti: &RoutingTableInner, nodes: &[NodeRef], perm: &[usize]| -> Option> { + let mut cachelen = 0usize; + let mut nodebytes = Vec::::with_capacity(perm.len()); for n in perm { - cache.extend_from_slice( - &nodes[*n] - .locked(rti) - .best_node_id() - .map(|bni| bni.value.bytes) - .unwrap_or_default(), - ); + let b = nodes[*n].locked(rti).best_node_id()?.value(); + cachelen += b.len(); + nodebytes.push(b); } - cache + let mut cache: Vec = Vec::with_capacity(cachelen); + for b in nodebytes { + cache.extend_from_slice(&b); + } + Some(cache) }; - let cache_key = route_permutation_to_hop_cache(rti, &nodes, permutation); + let cache_key = route_permutation_to_hop_cache(rti, &nodes, permutation)?; // Skip routes we have already seen if inner.cache.contains_route(&cache_key) { @@ -641,23 +642,16 @@ impl RouteSpecStore { for crypto_kind in crypto_kinds.iter().copied() { let vcrypto = crypto.get(crypto_kind).unwrap(); let keypair = vcrypto.generate_keypair(); - let hops: Vec = route_nodes + let hops: Vec = route_nodes .iter() - .map(|v| { - nodes[*v] - .locked(rti) - .node_ids() - .get(crypto_kind) - .unwrap() - .value - }) + .map(|v| nodes[*v].locked(rti).node_ids().get(crypto_kind).unwrap()) .collect(); route_set.insert( - keypair.key, + keypair.key(), RouteSpecDetail { crypto_kind, - secret_key: keypair.secret, + secret_key: keypair.secret(), hops, }, ); @@ -680,7 +674,7 @@ impl RouteSpecStore { inner.cache.add_to_cache(rti, &rssd); // Keep route in spec store - inner.content.add_detail(id, rssd); + inner.content.add_detail(id.clone(), rssd); Ok(id) } @@ -690,9 +684,9 @@ impl RouteSpecStore { pub fn with_signature_validated_route( &self, public_key: &PublicKey, - signatures: &[BareSignature], + signatures: &[Signature], data: &[u8], - last_hop_id: BareNodeId, + last_hop_id: &NodeId, callback: F, ) -> Option where @@ -701,21 +695,21 @@ impl RouteSpecStore { { let inner = &*self.inner.lock(); let crypto = self.crypto(); - let Some(vcrypto) = crypto.get(public_key.kind) else { + let Some(vcrypto) = crypto.get(public_key.kind()) else { veilid_log!(self debug "can't handle route with public key: {:?}", public_key); return None; }; - let Some(rsid) = inner.content.get_id_by_key(&public_key.value) else { - veilid_log!(self debug target: "network_result", "route id does not exist: {:?}", public_key.value); + let Some(rsid) = inner.content.get_id_by_key(public_key.ref_value()) else { + veilid_log!(self debug target: "network_result", "route id does not exist: {:?}", public_key.ref_value()); return None; }; let Some(rssd) = inner.content.get_detail(&rsid) else { veilid_log!(self debug "route detail does not exist: {:?}", rsid); return None; }; - let Some(rsd) = rssd.get_route_by_key(&public_key.value) else { - veilid_log!(self debug "route set {:?} does not have key: {:?}", rsid, public_key.value); + let Some(rsd) = rssd.get_route_by_key(public_key.ref_value()) else { + veilid_log!(self debug "route set {:?} does not have key: {:?}", rsid, public_key.ref_value()); return None; }; @@ -727,24 +721,28 @@ impl RouteSpecStore { } // Validate signatures to ensure the route was handled by the nodes and not messed with // This is in private route (reverse) order as we are receiving over the route - for (hop_n, hop_public_key) in rsd.hops.iter().rev().enumerate() { + for (hop_n, hop_node_id) in rsd.hops.iter().rev().enumerate() { // The last hop is not signed, as the whole packet is signed if hop_n == signatures.len() { // Verify the node we received the routed operation from is the last hop in our route - if *hop_public_key != last_hop_id { - veilid_log!(self debug "received routed operation from the wrong hop ({} should be {}) on private route {}", hop_public_key.encode(), last_hop_id.encode(), public_key); + if hop_node_id != last_hop_id { + veilid_log!(self debug "received routed operation from the wrong hop ({} should be {}) on private route {}", hop_node_id, last_hop_id, public_key); return None; } } else { // Verify a signature for a hop node along the route - match vcrypto.verify(&(*hop_public_key).into(), data, &signatures[hop_n]) { + match vcrypto.verify( + &hop_node_id.ref_value().clone().into(), + data, + signatures[hop_n].ref_value(), + ) { Ok(true) => {} Ok(false) => { - veilid_log!(self debug "invalid signature for hop {} at {} on private route {}", hop_n, hop_public_key, public_key); + veilid_log!(self debug "invalid signature for hop {} at {} on private route {}", hop_n, hop_node_id, public_key); return None; } Err(e) => { - veilid_log!(self debug "error verifying signature for hop {} at {} on private route {}: {}", hop_n, hop_public_key, public_key, e); + veilid_log!(self debug "error verifying signature for hop {} at {} on private route {}: {}", hop_n, hop_node_id, public_key, e); return None; } } @@ -757,7 +755,7 @@ impl RouteSpecStore { #[instrument(level = "trace", target = "route", skip(self), ret, err)] async fn test_allocated_route( &self, - private_route_id: BareRouteId, + private_route_id: RouteId, ) -> VeilidAPIResult> { // Make loopback route to test with let (dest, hops) = { @@ -836,10 +834,7 @@ impl RouteSpecStore { } #[instrument(level = "trace", target = "route", skip(self), ret, err)] - async fn test_remote_route( - &self, - private_route_id: BareRouteId, - ) -> VeilidAPIResult> { + async fn test_remote_route(&self, private_route_id: RouteId) -> VeilidAPIResult> { // Make private route test let dest = { // Get the route to test @@ -882,7 +877,7 @@ impl RouteSpecStore { /// Release an allocated route that is no longer in use #[instrument(level = "trace", target = "route", skip(self), ret)] - fn release_allocated_route(&self, id: BareRouteId) -> bool { + fn release_allocated_route(&self, id: RouteId) -> bool { let mut inner = self.inner.lock(); let Some(rssd) = inner.content.remove_detail(&id) else { return false; @@ -899,7 +894,7 @@ impl RouteSpecStore { } /// Check if a route id is remote or not - pub fn is_route_id_remote(&self, id: &BareRouteId) -> bool { + pub fn is_route_id_remote(&self, id: &RouteId) -> bool { let inner = &mut *self.inner.lock(); let cur_ts = Timestamp::now(); inner @@ -910,7 +905,7 @@ impl RouteSpecStore { /// Test an allocated route for continuity #[instrument(level = "trace", target = "route", skip(self), ret, err)] - pub async fn test_route(&self, id: BareRouteId) -> VeilidAPIResult> { + pub async fn test_route(&self, id: RouteId) -> VeilidAPIResult> { let is_remote = self.is_route_id_remote(&id); if is_remote { self.test_remote_route(id).await @@ -921,7 +916,7 @@ impl RouteSpecStore { /// Release an allocated or remote route that is no longer in use #[instrument(level = "trace", target = "route", skip(self), ret)] - pub fn release_route(&self, id: BareRouteId) -> bool { + pub fn release_route(&self, id: RouteId) -> bool { let is_remote = self.is_route_id_remote(&id); if is_remote { self.release_remote_private_route(id) @@ -943,7 +938,7 @@ impl RouteSpecStore { sequencing: Sequencing, directions: DirectionSet, avoid_nodes: &[NodeId], - ) -> Option { + ) -> Option { let cur_ts = Timestamp::now(); let mut routes = Vec::new(); @@ -993,13 +988,13 @@ impl RouteSpecStore { }); // Return the best one if we got one - routes.first().map(|r| *r.0) + routes.first().map(|r| r.0.clone()) } /// List all allocated routes pub fn list_allocated_routes(&self, mut filter: F) -> Vec where - F: FnMut(&BareRouteId, &RouteSetSpecDetail) -> Option, + F: FnMut(&RouteId, &RouteSetSpecDetail) -> Option, { let inner = self.inner.lock(); let mut out = Vec::with_capacity(inner.content.get_detail_count()); @@ -1014,7 +1009,7 @@ impl RouteSpecStore { /// List all allocated routes pub fn list_remote_routes(&self, mut filter: F) -> Vec where - F: FnMut(&BareRouteId, &RemotePrivateRouteInfo) -> Option, + F: FnMut(&RouteId, &RemotePrivateRouteInfo) -> Option, { let inner = self.inner.lock(); let cur_ts = Timestamp::now(); @@ -1031,7 +1026,7 @@ impl RouteSpecStore { } /// Get the debug description of a route - pub fn debug_route(&self, id: &BareRouteId) -> Option { + pub fn debug_route(&self, id: &RouteId) -> Option { let inner = &mut *self.inner.lock(); let cur_ts = Timestamp::now(); if let Some(rpri) = inner.cache.peek_remote_private_route(cur_ts, id) { @@ -1046,7 +1041,7 @@ impl RouteSpecStore { ////////////////////////////////////////////////////////////////////// /// Choose the best private route from a private route set to communicate with - pub fn best_remote_private_route(&self, id: &BareRouteId) -> Option { + pub fn best_remote_private_route(&self, id: &RouteId) -> Option { let inner = &mut *self.inner.lock(); let cur_ts = Timestamp::now(); let rpri = inner.cache.get_remote_private_route(cur_ts, id)?; @@ -1075,18 +1070,8 @@ impl RouteSpecStore { let Some(vcrypto) = crypto.get(crypto_kind) else { apibail_generic!("crypto not supported for route"); }; - let pr_pubkey = private_route.public_key.value; - let pr_hopcount = private_route.hop_count as usize; - let max_route_hop_count = self.max_route_hop_count; + let pr_pubkey = private_route.public_key.value(); - // Check private route hop count isn't larger than the max route hop count plus one for the 'first hop' header - if pr_hopcount > (max_route_hop_count + 1) { - apibail_invalid_argument!( - "private route hop count too long", - "private_route.hop_count", - pr_hopcount - ); - } // See if we are using a safety route, if not, short circuit this operation let safety_spec = match safety_selection { // Safety route spec to use @@ -1098,9 +1083,9 @@ impl RouteSpecStore { }; let opt_first_hop = match pr_first_hop_node { - RouteNode::BareNodeId(id) => rti - .lookup_node_ref(NodeId::new(crypto_kind, id)) - .map_err(VeilidAPIError::internal)?, + RouteNode::NodeId(id) => { + rti.lookup_node_ref(id).map_err(VeilidAPIError::internal)? + } RouteNode::PeerInfo(pi) => Some( rti.register_node_with_peer_info(pi, false) .map_err(VeilidAPIError::internal)? @@ -1139,7 +1124,7 @@ impl RouteSpecStore { && safety_spec.preferred_route == opt_private_route_id { // Private route is also safety route during loopback test - pr_pubkey + pr_pubkey.clone() } else { let Some(avoid_node_id) = private_route.first_hop_node_id() else { apibail_generic!("compiled private route should have first hop"); @@ -1181,13 +1166,13 @@ impl RouteSpecStore { .merge_filter(NodeRefFilter::new().with_routing_domain(RoutingDomain::PublicInternet)); // Get the safety route secret key - let secret = safety_rsd.secret_key; + let secret = safety_rsd.secret_key.clone(); // See if we have a cached route we can use if optimize { if let Some(safety_route) = inner .cache - .lookup_compiled_route_cache(sr_pubkey, pr_pubkey) + .lookup_compiled_route_cache(sr_pubkey.clone(), pr_pubkey.clone()) { // Build compiled route let compiled_route = CompiledRoute { @@ -1227,7 +1212,7 @@ impl RouteSpecStore { blob_data = { // Encrypt the previous blob ENC(nonce, DH(PKhop,SKsr)) let dh_secret = vcrypto - .cached_dh(&safety_rsd.hops[h].into(), &safety_rsd.secret_key) + .cached_dh(&safety_rsd.hops[h].value().into(), &safety_rsd.secret_key) .map_err(VeilidAPIError::internal)?; let enc_msg_data = vcrypto .encrypt_aead(blob_data.as_slice(), &nonce, &dh_secret, None) @@ -1243,10 +1228,10 @@ impl RouteSpecStore { let route_hop = RouteHop { node: if optimize { // Optimized, no peer info, just the dht key - RouteNode::BareNodeId(safety_rsd.hops[h]) + RouteNode::NodeId(safety_rsd.hops[h].clone()) } else { // Full peer info, required until we are sure the route has been fully established - let node_id = NodeId::new(safety_rsd.crypto_kind, safety_rsd.hops[h]); + let node_id = safety_rsd.hops[h].clone(); let pi = rti .with_node_entry(node_id, |entry| { entry.with(rti, |_rti, e| { @@ -1279,7 +1264,7 @@ impl RouteSpecStore { // Encode first RouteHopData let dh_secret = vcrypto - .cached_dh(&safety_rsd.hops[0].into(), &safety_rsd.secret_key) + .cached_dh(&safety_rsd.hops[0].value().into(), &safety_rsd.secret_key) .map_err(VeilidAPIError::internal)?; let enc_msg_data = vcrypto .encrypt_aead(blob_data.as_slice(), &nonce, &dh_secret, None) @@ -1295,8 +1280,7 @@ impl RouteSpecStore { // Build safety route let safety_route = SafetyRoute { - public_key: PublicKey::new(crypto_kind, sr_pubkey), - hop_count: safety_spec.hop_count as u8, + public_key: PublicKey::new(crypto_kind, sr_pubkey.clone()), hops, }; @@ -1304,7 +1288,7 @@ impl RouteSpecStore { if optimize { inner .cache - .add_to_compiled_route_cache(pr_pubkey, safety_route.clone()); + .add_to_compiled_route_cache(pr_pubkey.clone(), safety_route.clone()); } // Build compiled route @@ -1348,13 +1332,13 @@ impl RouteSpecStore { } // See if the preferred route is here - if let Some(preferred_route) = safety_spec.preferred_route { - if let Some(preferred_rssd) = inner.content.get_detail(&preferred_route) { + if let Some(preferred_route) = &safety_spec.preferred_route { + if let Some(preferred_rssd) = inner.content.get_detail(preferred_route) { // Only use the preferred route if it has the desired crypto kind if let Some(preferred_key) = preferred_rssd.get_route_set_keys().get(crypto_kind) { // Only use the preferred route if it doesn't contain the avoid nodes if !preferred_rssd.contains_nodes(avoid_nodes) { - return Ok(preferred_key.value); + return Ok(preferred_key.value()); } } } @@ -1393,7 +1377,7 @@ impl RouteSpecStore { .get_route_set_keys() .get(crypto_kind) .unwrap() - .value; + .value(); Ok(sr_pubkey) } @@ -1455,7 +1439,7 @@ impl RouteSpecStore { rsd.crypto_kind ); }; - RouteNode::BareNodeId(node_id.value) + RouteNode::NodeId(node_id) } else { RouteNode::PeerInfo(published_peer_info) }, @@ -1476,7 +1460,7 @@ impl RouteSpecStore { }; // Encrypt the previous blob ENC(nonce, DH(PKhop,SKpr)) - let dh_secret = vcrypto.cached_dh(&rsd.hops[h].into(), &rsd.secret_key)?; + let dh_secret = vcrypto.cached_dh(&rsd.hops[h].value().into(), &rsd.secret_key)?; let enc_msg_data = vcrypto.encrypt_aead(blob_data.as_slice(), &nonce, &dh_secret, None)?; let route_hop_data = RouteHopData { @@ -1487,10 +1471,10 @@ impl RouteSpecStore { route_hop = RouteHop { node: if optimized { // Optimized, no peer info, just the dht key - RouteNode::BareNodeId(rsd.hops[h]) + RouteNode::NodeId(rsd.hops[h].clone()) } else { // Full peer info, required until we are sure the route has been fully established - let node_id = NodeId::new(rsd.crypto_kind, rsd.hops[h]); + let node_id = rsd.hops[h].clone(); let pi = rti .with_node_entry(node_id, |entry| { entry.with(rti, |_rti, e| { @@ -1508,9 +1492,7 @@ impl RouteSpecStore { } let private_route = PrivateRoute { - public_key: PublicKey::new(rsd.crypto_kind, *key), - // add hop for 'FirstHop' - hop_count: (hop_count + 1).try_into().unwrap(), + public_key: PublicKey::new(rsd.crypto_kind, key.clone()), hops: PrivateRouteHops::FirstHop(Box::new(route_hop)), }; Ok(private_route) @@ -1549,7 +1531,7 @@ impl RouteSpecStore { #[instrument(level = "trace", target = "route", skip_all)] pub fn assemble_private_routes( &self, - id: &BareRouteId, + id: &RouteId, optimized: Option, ) -> VeilidAPIResult> { let inner = &*self.inner.lock(); @@ -1572,7 +1554,7 @@ impl RouteSpecStore { /// It is safe to import the same route more than once and it will return the same route id /// Returns a route set id #[instrument(level = "trace", target = "route", skip_all)] - pub fn import_remote_private_route_blob(&self, blob: Vec) -> VeilidAPIResult { + pub fn import_remote_private_route_blob(&self, blob: Vec) -> VeilidAPIResult { let cur_ts = Timestamp::now(); // decode the pr blob @@ -1597,7 +1579,7 @@ impl RouteSpecStore { inner .cache - .cache_remote_private_route(cur_ts, id, private_routes); + .cache_remote_private_route(cur_ts, id.clone(), private_routes); Ok(id) } @@ -1609,7 +1591,7 @@ impl RouteSpecStore { pub fn add_remote_private_route( &self, private_route: PrivateRoute, - ) -> VeilidAPIResult { + ) -> VeilidAPIResult { let cur_ts = Timestamp::now(); // Make a single route set @@ -1634,20 +1616,20 @@ impl RouteSpecStore { inner .cache - .cache_remote_private_route(cur_ts, id, private_routes); + .cache_remote_private_route(cur_ts, id.clone(), private_routes); Ok(id) } /// Release a remote private route that is no longer in use #[instrument(level = "trace", target = "route", skip_all)] - pub fn release_remote_private_route(&self, id: BareRouteId) -> bool { + pub fn release_remote_private_route(&self, id: RouteId) -> bool { let inner = &mut *self.inner.lock(); inner.cache.remove_remote_private_route(id) } /// Get a route id for a route's public key - pub fn get_route_id_for_key(&self, key: &BarePublicKey) -> Option { + pub fn get_route_id_for_key(&self, key: &BarePublicKey) -> Option { let inner = &mut *self.inner.lock(); // Check for local route if let Some(id) = inner.content.get_id_by_key(key) { @@ -1740,7 +1722,10 @@ impl RouteSpecStore { let inner = &mut *self.inner.lock(); // Check for stub route - if self.routing_table().matches_own_node_id_key(&(*key).into()) { + if self + .routing_table() + .matches_own_node_id_key(&key.clone().into()) + { return None; } @@ -1778,7 +1763,7 @@ impl RouteSpecStore { /// Mark route as published /// When first deserialized, routes must be re-published in order to ensure they remain /// in the RouteSpecStore. - pub fn mark_route_published(&self, id: &BareRouteId, published: bool) -> VeilidAPIResult<()> { + pub fn mark_route_published(&self, id: &RouteId, published: bool) -> VeilidAPIResult<()> { let inner = &mut *self.inner.lock(); let Some(rssd) = inner.content.get_detail_mut(id) else { apibail_invalid_target!("route does not exist"); @@ -1886,55 +1871,67 @@ impl RouteSpecStore { Ok(out) } - /// Generate BareRouteId from typed key set of route public keys - fn generate_allocated_route_id( - &self, - rssd: &RouteSetSpecDetail, - ) -> VeilidAPIResult { + /// Generate RouteId from typed key set of route public keys + fn generate_allocated_route_id(&self, rssd: &RouteSetSpecDetail) -> VeilidAPIResult { let route_set_keys = rssd.get_route_set_keys(); let crypto = self.crypto(); - let mut idbytes = Vec::with_capacity(PUBLIC_KEY_LENGTH * route_set_keys.len()); + let pkbyteslen = route_set_keys + .iter() + .fold(0, |acc, x| acc + x.ref_value().len()); + let mut pkbytes = Vec::with_capacity(pkbyteslen); let mut best_kind: Option = None; for tk in route_set_keys.iter() { if best_kind.is_none() - || compare_crypto_kind(&tk.kind, best_kind.as_ref().unwrap()) == cmp::Ordering::Less + || compare_crypto_kind(&tk.kind(), best_kind.as_ref().unwrap()) + == cmp::Ordering::Less { - best_kind = Some(tk.kind); + best_kind = Some(tk.kind()); } - idbytes.extend_from_slice(&tk.value.bytes); + pkbytes.extend_from_slice(tk.ref_value()); } let Some(best_kind) = best_kind else { apibail_internal!("no compatible crypto kinds in route"); }; let vcrypto = crypto.get(best_kind).unwrap(); - Ok(BareRouteId::new(vcrypto.generate_hash(&idbytes).bytes)) + Ok(RouteId::new( + vcrypto.kind(), + BareRouteId::new(vcrypto.generate_hash(&pkbytes).bytes()), + )) } - /// Generate BareRouteId from set of private routes + /// Generate RouteId from set of private routes fn generate_remote_route_id( &self, private_routes: &[PrivateRoute], - ) -> VeilidAPIResult { + ) -> VeilidAPIResult { let crypto = self.crypto(); - let mut idbytes = Vec::with_capacity(PUBLIC_KEY_LENGTH * private_routes.len()); + let pkbyteslen = private_routes + .iter() + .fold(0, |acc, x| acc + x.public_key.ref_value().len()); + let mut pkbytes = Vec::with_capacity(pkbyteslen); let mut best_kind: Option = None; for private_route in private_routes { if best_kind.is_none() - || compare_crypto_kind(&private_route.public_key.kind, best_kind.as_ref().unwrap()) - == cmp::Ordering::Less + || compare_crypto_kind( + &private_route.public_key.kind(), + best_kind.as_ref().unwrap(), + ) == cmp::Ordering::Less { - best_kind = Some(private_route.public_key.kind); + best_kind = Some(private_route.public_key.kind()); } - idbytes.extend_from_slice(&private_route.public_key.value.bytes); + pkbytes.extend_from_slice(private_route.public_key.ref_value()); } let Some(best_kind) = best_kind else { apibail_internal!("no compatible crypto kinds in route"); }; let vcrypto = crypto.get(best_kind).unwrap(); - Ok(BareRouteId::new(vcrypto.generate_hash(&idbytes).bytes)) + Ok(RouteId::new( + vcrypto.kind(), + BareRouteId::new(vcrypto.generate_hash(&pkbytes).bytes()), + )) } } diff --git a/veilid-core/src/routing_table/route_spec_store/remote_private_route_info.rs b/veilid-core/src/routing_table/route_spec_store/remote_private_route_info.rs index 5ce72a66..2f5c0f4e 100644 --- a/veilid-core/src/routing_table/route_spec_store/remote_private_route_info.rs +++ b/veilid-core/src/routing_table/route_spec_store/remote_private_route_info.rs @@ -35,7 +35,7 @@ impl RemotePrivateRouteInfo { acc } }) - .filter(|x| VALID_CRYPTO_KINDS.contains(&x.public_key.kind)) + .filter(|x| VALID_CRYPTO_KINDS.contains(&x.public_key.kind())) .cloned() } pub fn get_stats(&self) -> &RouteStats { diff --git a/veilid-core/src/routing_table/route_spec_store/route_set_spec_detail.rs b/veilid-core/src/routing_table/route_spec_store/route_set_spec_detail.rs index 51df8499..2a505b49 100644 --- a/veilid-core/src/routing_table/route_spec_store/route_set_spec_detail.rs +++ b/veilid-core/src/routing_table/route_spec_store/route_set_spec_detail.rs @@ -7,7 +7,7 @@ pub struct RouteSpecDetail { /// Secret key pub secret_key: BareSecretKey, /// Route hops (node id keys) - pub hops: Vec, + pub hops: Vec, } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -60,12 +60,12 @@ impl RouteSetSpecDetail { pub fn get_route_set_keys(&self) -> PublicKeyGroup { let mut tks = PublicKeyGroup::new(); for (k, v) in &self.route_set { - tks.add(PublicKey::new(v.crypto_kind, *k)); + tks.add(PublicKey::new(v.crypto_kind, k.clone())); } tks } pub fn get_best_route_set_key(&self) -> Option { - self.get_route_set_keys().best().map(|k| k.value) + self.get_route_set_keys().best().map(|k| k.value()) } pub fn set_hop_node_refs(&mut self, node_refs: Vec) { self.hop_node_refs = node_refs; @@ -112,7 +112,7 @@ impl RouteSetSpecDetail { pub fn contains_nodes(&self, nodes: &[NodeId]) -> bool { for tk in nodes { for rsd in self.route_set.values() { - if rsd.crypto_kind == tk.kind && rsd.hops.contains(&tk.value) { + if rsd.crypto_kind == tk.kind() && rsd.hops.contains(tk) { return true; } } @@ -124,17 +124,21 @@ impl RouteSetSpecDetail { } /// Generate a key for the cache that can be used to uniquely identify this route's contents - pub fn make_cache_key(&self, rti: &RoutingTableInner) -> Vec { + pub fn make_cache_key(&self, rti: &RoutingTableInner) -> Option> { let hops = &self.hop_node_refs; - let mut cache: Vec = Vec::with_capacity(hops.len() * PUBLIC_KEY_LENGTH); + + let mut cachelen = 0usize; + let mut nodebytes = Vec::::with_capacity(hops.len()); for hop in hops { - cache.extend_from_slice( - &hop.locked(rti) - .best_node_id() - .map(|bni| bni.value.bytes) - .unwrap_or_default(), - ); + let b = hop.locked(rti).best_node_id()?.value(); + cachelen += b.len(); + nodebytes.push(b); } - cache + let mut cache: Vec = Vec::with_capacity(cachelen); + for b in nodebytes { + cache.extend_from_slice(&b); + } + + Some(cache) } } diff --git a/veilid-core/src/routing_table/route_spec_store/route_spec_store_cache.rs b/veilid-core/src/routing_table/route_spec_store/route_spec_store_cache.rs index dc6b6887..98c46b40 100644 --- a/veilid-core/src/routing_table/route_spec_store/route_spec_store_cache.rs +++ b/veilid-core/src/routing_table/route_spec_store/route_spec_store_cache.rs @@ -26,21 +26,21 @@ pub struct RouteSpecStoreCache { /// Registry accessor registry: VeilidComponentRegistry, /// How many times nodes have been used - used_nodes: HashMap, + used_nodes: HashMap, /// How many times nodes have been used at the terminal point of a route - used_end_nodes: HashMap, + used_end_nodes: HashMap, /// Route spec hop cache, used to quickly disqualify routes hop_cache: HashSet>, /// Remote private routes we've imported and statistics - remote_private_route_set_cache: LruCache, + remote_private_route_set_cache: LruCache, /// Remote private route ids indexed by route's public key - remote_private_routes_by_key: HashMap, + remote_private_routes_by_key: HashMap, /// Compiled route cache compiled_route_cache: LruCache, /// List of dead allocated routes - dead_routes: Vec, + dead_routes: Vec, /// List of dead remote routes - dead_remote_routes: Vec, + dead_remote_routes: Vec, } impl_veilid_component_registry_accessor!(RouteSpecStoreCache); @@ -62,19 +62,21 @@ impl RouteSpecStoreCache { /// add an allocated route set to our cache via its cache key pub fn add_to_cache(&mut self, rti: &RoutingTableInner, rssd: &RouteSetSpecDetail) { - let cache_key = rssd.make_cache_key(rti); + let Some(cache_key) = rssd.make_cache_key(rti) else { + panic!("all routes should have a cache key"); + }; if !self.hop_cache.insert(cache_key) { panic!("route should never be inserted twice"); } for (_pk, rsd) in rssd.iter_route_set() { for h in &rsd.hops { self.used_nodes - .entry(*h) + .entry(h.clone()) .and_modify(|e| *e += 1) .or_insert(1); } self.used_end_nodes - .entry(*rsd.hops.last().unwrap()) + .entry(rsd.hops.last().unwrap().clone()) .and_modify(|e| *e += 1) .or_insert(1); } @@ -89,10 +91,12 @@ impl RouteSpecStoreCache { pub fn remove_from_cache( &mut self, rti: &RoutingTableInner, - id: BareRouteId, + id: RouteId, rssd: &RouteSetSpecDetail, ) -> bool { - let cache_key = rssd.make_cache_key(rti); + let Some(cache_key) = rssd.make_cache_key(rti) else { + panic!("all routes should have a cache key"); + }; // Remove from hop cache if !self.hop_cache.remove(&cache_key) { @@ -101,7 +105,7 @@ impl RouteSpecStoreCache { for (pk, rsd) in rssd.iter_route_set() { for h in &rsd.hops { // Remove from used nodes cache - match self.used_nodes.entry(*h) { + match self.used_nodes.entry(h.clone()) { std::collections::hash_map::Entry::Occupied(mut o) => { *o.get_mut() -= 1; if *o.get() == 0 { @@ -114,7 +118,7 @@ impl RouteSpecStoreCache { } } // Remove from end nodes cache - match self.used_end_nodes.entry(*rsd.hops.last().unwrap()) { + match self.used_end_nodes.entry(rsd.hops.last().cloned().unwrap()) { std::collections::hash_map::Entry::Occupied(mut o) => { *o.get_mut() -= 1; if *o.get() == 0 { @@ -141,27 +145,23 @@ impl RouteSpecStoreCache { /// calculate how many times a node with a particular node id set has been used anywhere in the path of our allocated routes pub fn get_used_node_count(&self, node_ids: &NodeIdGroup) -> usize { node_ids.iter().fold(0usize, |acc, k| { - acc + self.used_nodes.get(&k.value).cloned().unwrap_or_default() + acc + self.used_nodes.get(k).cloned().unwrap_or_default() }) } /// calculate how many times a node with a particular node id set has been used at the end of the path of our allocated routes pub fn get_used_end_node_count(&self, node_ids: &NodeIdGroup) -> usize { node_ids.iter().fold(0usize, |acc, k| { - acc + self - .used_end_nodes - .get(&k.value) - .cloned() - .unwrap_or_default() + acc + self.used_end_nodes.get(k).cloned().unwrap_or_default() }) } /// add remote private route to caches - fn add_remote_private_route(&mut self, id: BareRouteId, rprinfo: RemotePrivateRouteInfo) { + fn add_remote_private_route(&mut self, id: RouteId, rprinfo: RemotePrivateRouteInfo) { // also store in id by key table for private_route in rprinfo.get_private_routes() { self.remote_private_routes_by_key - .insert(private_route.public_key.value, id); + .insert(private_route.public_key.value(), id.clone()); } let mut dead = None; @@ -179,21 +179,21 @@ impl RouteSpecStoreCache { for dead_private_route in dead_rpri.get_private_routes() { let _ = self .remote_private_routes_by_key - .remove(&dead_private_route.public_key.value) + .remove(dead_private_route.public_key.ref_value()) .unwrap(); - self.invalidate_compiled_route_cache(&dead_private_route.public_key.value); + self.invalidate_compiled_route_cache(dead_private_route.public_key.ref_value()); } self.dead_remote_routes.push(dead_id); } } /// iterate all of the remote private routes we have in the cache - pub fn get_remote_private_route_ids(&self, cur_ts: Timestamp) -> Vec { + pub fn get_remote_private_route_ids(&self, cur_ts: Timestamp) -> Vec { self.remote_private_route_set_cache .iter() .filter_map(|(id, rpri)| { if !rpri.did_expire(cur_ts) { - Some(*id) + Some(id.clone()) } else { None } @@ -206,7 +206,7 @@ impl RouteSpecStoreCache { pub fn get_remote_private_route( &mut self, cur_ts: Timestamp, - id: &BareRouteId, + id: &RouteId, ) -> Option<&RemotePrivateRouteInfo> { if let Some(rpri) = self.remote_private_route_set_cache.get_mut(id) { if !rpri.did_expire(cur_ts) { @@ -222,7 +222,7 @@ impl RouteSpecStoreCache { pub fn get_remote_private_route_mut( &mut self, cur_ts: Timestamp, - id: &BareRouteId, + id: &RouteId, ) -> Option<&mut RemotePrivateRouteInfo> { if let Some(rpri) = self.remote_private_route_set_cache.get_mut(id) { if !rpri.did_expire(cur_ts) { @@ -238,7 +238,7 @@ impl RouteSpecStoreCache { pub fn peek_remote_private_route( &self, cur_ts: Timestamp, - id: &BareRouteId, + id: &RouteId, ) -> Option<&RemotePrivateRouteInfo> { if let Some(rpri) = self.remote_private_route_set_cache.peek(id) { if !rpri.did_expire(cur_ts) { @@ -253,7 +253,7 @@ impl RouteSpecStoreCache { pub fn peek_remote_private_route_mut( &mut self, cur_ts: Timestamp, - id: &BareRouteId, + id: &RouteId, ) -> Option<&mut RemotePrivateRouteInfo> { if let Some(rpri) = self.remote_private_route_set_cache.peek_mut(id) { if !rpri.did_expire(cur_ts) { @@ -265,7 +265,7 @@ impl RouteSpecStoreCache { } /// look up a remote private route id by one of the route public keys - pub fn get_remote_private_route_id_by_key(&self, key: &BarePublicKey) -> Option { + pub fn get_remote_private_route_id_by_key(&self, key: &BarePublicKey) -> Option { self.remote_private_routes_by_key.get(key).cloned() } @@ -276,7 +276,7 @@ impl RouteSpecStoreCache { pub fn cache_remote_private_route( &mut self, cur_ts: Timestamp, - id: BareRouteId, + id: RouteId, private_routes: Vec, ) { // get id for this route set @@ -292,7 +292,7 @@ impl RouteSpecStoreCache { // New remote private route cache entry let rpri = RemotePrivateRouteInfo::new(private_routes, cur_ts); - self.add_remote_private_route(id, rpri); + self.add_remote_private_route(id.clone(), rpri); if self.peek_remote_private_route_mut(cur_ts, &id).is_none() { panic!("remote private route should exist"); }; @@ -300,16 +300,16 @@ impl RouteSpecStoreCache { } /// remove a remote private route from the cache - pub fn remove_remote_private_route(&mut self, id: BareRouteId) -> bool { + pub fn remove_remote_private_route(&mut self, id: RouteId) -> bool { let Some(rprinfo) = self.remote_private_route_set_cache.remove(&id) else { return false; }; for private_route in rprinfo.get_private_routes() { let _ = self .remote_private_routes_by_key - .remove(&private_route.public_key.value) + .remove(private_route.public_key.ref_value()) .unwrap(); - self.invalidate_compiled_route_cache(&private_route.public_key.value); + self.invalidate_compiled_route_cache(private_route.public_key.ref_value()); } self.dead_remote_routes.push(id); true @@ -322,8 +322,8 @@ impl RouteSpecStoreCache { safety_route: SafetyRoute, ) { let key = CompiledRouteCacheKey { - sr_pubkey: safety_route.public_key.value, - pr_pubkey, + sr_pubkey: safety_route.public_key.value(), + pr_pubkey: pr_pubkey.clone(), }; if let Some(v) = self.compiled_route_cache.insert(key, safety_route) { @@ -358,7 +358,7 @@ impl RouteSpecStoreCache { } /// Take the dead local and remote routes so we can update clients - pub fn take_dead_routes(&mut self) -> Option<(Vec, Vec)> { + pub fn take_dead_routes(&mut self) -> Option<(Vec, Vec)> { if self.dead_routes.is_empty() && self.dead_remote_routes.is_empty() { // Nothing to do return None; diff --git a/veilid-core/src/routing_table/route_spec_store/route_spec_store_content.rs b/veilid-core/src/routing_table/route_spec_store/route_spec_store_content.rs index f57791de..04976298 100644 --- a/veilid-core/src/routing_table/route_spec_store/route_spec_store_content.rs +++ b/veilid-core/src/routing_table/route_spec_store/route_spec_store_content.rs @@ -4,9 +4,9 @@ use super::*; #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub(super) struct RouteSpecStoreContent { /// All of the route sets we have allocated so far indexed by key (many to one) - id_by_key: HashMap, + id_by_key: HashMap, /// All of the route sets we have allocated so far - details: HashMap, + details: HashMap, } impl RouteSpecStoreContent { @@ -24,19 +24,18 @@ impl RouteSpecStoreContent { for (rsid, rssd) in content.details.iter_mut() { // Get best route since they all should resolve let Some(pk) = rssd.get_best_route_set_key() else { - dead_ids.push(*rsid); + dead_ids.push(rsid.clone()); continue; }; let Some(rsd) = rssd.get_route_by_key(&pk) else { - dead_ids.push(*rsid); + dead_ids.push(rsid.clone()); continue; }; // Go through best route and resolve noderefs let mut hop_node_refs = Vec::with_capacity(rsd.hops.len()); for h in &rsd.hops { - let Ok(Some(nr)) = routing_table.lookup_node_ref(NodeId::new(rsd.crypto_kind, *h)) - else { - dead_ids.push(*rsid); + let Ok(Some(nr)) = routing_table.lookup_node_ref(h.clone()) else { + dead_ids.push(rsid.clone()); break; }; hop_node_refs.push(nr); @@ -62,16 +61,16 @@ impl RouteSpecStoreContent { Ok(()) } - pub fn add_detail(&mut self, id: BareRouteId, detail: RouteSetSpecDetail) { + pub fn add_detail(&mut self, id: RouteId, detail: RouteSetSpecDetail) { assert!(!self.details.contains_key(&id)); // also store in id by key table for (pk, _) in detail.iter_route_set() { - self.id_by_key.insert(*pk, id); + self.id_by_key.insert(pk.clone(), id.clone()); } self.details.insert(id, detail); } - pub fn remove_detail(&mut self, id: &BareRouteId) -> Option { + pub fn remove_detail(&mut self, id: &RouteId) -> Option { let detail = self.details.remove(id)?; for (pk, _) in detail.iter_route_set() { let _ = self.id_by_key.remove(pk).unwrap(); @@ -81,21 +80,19 @@ impl RouteSpecStoreContent { pub fn get_detail_count(&self) -> usize { self.details.len() } - pub fn get_detail(&self, id: &BareRouteId) -> Option<&RouteSetSpecDetail> { + pub fn get_detail(&self, id: &RouteId) -> Option<&RouteSetSpecDetail> { self.details.get(id) } - pub fn get_detail_mut(&mut self, id: &BareRouteId) -> Option<&mut RouteSetSpecDetail> { + pub fn get_detail_mut(&mut self, id: &RouteId) -> Option<&mut RouteSetSpecDetail> { self.details.get_mut(id) } - pub fn get_id_by_key(&self, key: &BarePublicKey) -> Option { + pub fn get_id_by_key(&self, key: &BarePublicKey) -> Option { self.id_by_key.get(key).cloned() } - // pub fn iter_ids(&self) -> std::collections::hash_map::Keys { + // pub fn iter_ids(&self) -> std::collections::hash_map::Keys { // self.details.keys() // } - pub fn iter_details( - &self, - ) -> std::collections::hash_map::Iter { + pub fn iter_details(&self) -> std::collections::hash_map::Iter { self.details.iter() } diff --git a/veilid-core/src/routing_table/routing_table_inner/mod.rs b/veilid-core/src/routing_table/routing_table_inner/mod.rs index 6176ab44..b80fc974 100644 --- a/veilid-core/src/routing_table/routing_table_inner/mod.rs +++ b/veilid-core/src/routing_table/routing_table_inner/mod.rs @@ -342,8 +342,8 @@ impl RoutingTableInner { // Size the buckets (one per bit), one bucket set per crypto kind self.buckets.clear(); for ck in VALID_CRYPTO_KINDS { - let mut ckbuckets = Vec::with_capacity(PUBLIC_KEY_LENGTH * 8); - for _ in 0..PUBLIC_KEY_LENGTH * 8 { + let mut ckbuckets = Vec::with_capacity(BUCKET_COUNT); + for _ in 0..BUCKET_COUNT { let bucket = Bucket::new(self.registry(), ck); ckbuckets.push(bucket); } @@ -666,7 +666,7 @@ impl RoutingTableInner { let mut old_peer_infos = vec![]; for node_id in node_ids { - let ck = node_id.kind; + let ck = node_id.kind(); let is_existing_node_id = existing_node_ids.contains(node_id); existing_node_ids.remove(ck); @@ -686,12 +686,12 @@ impl RoutingTableInner { } // Add new node id to entry - if let Some(old_node_id) = e.add_node_id(*node_id)? { + if let Some(old_node_id) = e.add_node_id(node_id.clone())? { // Remove any old node id for this crypto kind if VALID_CRYPTO_KINDS.contains(&ck) { let bucket_index = routing_table.calculate_bucket_index(&old_node_id); let bucket = self.get_bucket_mut(bucket_index); - bucket.remove_entry(&old_node_id.value); + bucket.remove_entry(old_node_id.ref_value()); routing_table.kick_queue.lock().insert(bucket_index); } } @@ -700,7 +700,7 @@ impl RoutingTableInner { if VALID_CRYPTO_KINDS.contains(&ck) { let bucket_index = routing_table.calculate_bucket_index(node_id); let bucket = self.get_bucket_mut(bucket_index); - bucket.add_existing_entry(node_id.value, entry.clone()); + bucket.add_existing_entry(node_id.value(), entry.clone()); // Kick bucket routing_table.kick_queue.lock().insert(bucket_index); @@ -709,11 +709,11 @@ impl RoutingTableInner { // Remove from buckets if node id wasn't seen in new peer info list for node_id in existing_node_ids.iter() { - let ck = node_id.kind; + let ck = node_id.kind(); if VALID_CRYPTO_KINDS.contains(&ck) { let bucket_index = routing_table.calculate_bucket_index(node_id); let bucket = self.get_bucket_mut(bucket_index); - bucket.remove_entry(&node_id.value); + bucket.remove_entry(node_id.ref_value()); entry.with_mut_inner(|e| e.remove_node_id(ck)); } } @@ -763,15 +763,15 @@ impl RoutingTableInner { let mut supported_node_ids = NodeIdGroup::new(); for node_id in node_ids.iter() { // Ignore node ids we don't support - if !VALID_CRYPTO_KINDS.contains(&node_id.kind) { + if !VALID_CRYPTO_KINDS.contains(&node_id.kind()) { continue; } - supported_node_ids.add(*node_id); + supported_node_ids.add(node_id.clone()); // Find the first in crypto sort order let bucket_index = routing_table.calculate_bucket_index(node_id); let bucket = self.get_bucket(bucket_index); - if let Some(entry) = bucket.entry(&node_id.value) { + if let Some(entry) = bucket.entry(node_id.ref_value()) { // Best entry is the first one in sorted order that exists from the node id list // Everything else that matches will be overwritten in the bucket and the // existing noderefs will eventually unref and drop the old unindexed bucketentry @@ -806,10 +806,10 @@ impl RoutingTableInner { } // If no entry exists yet, add the first entry to a bucket, possibly evicting a bucket member - let first_node_id = supported_node_ids[0]; + let first_node_id = supported_node_ids[0].clone(); let bucket_entry = routing_table.calculate_bucket_index(&first_node_id); let bucket = self.get_bucket_mut(bucket_entry); - let new_entry = bucket.add_new_entry(first_node_id.value); + let new_entry = bucket.add_new_entry(first_node_id.value()); self.all_entries.insert(new_entry.clone()); routing_table.kick_queue.lock().insert(bucket_entry); @@ -832,9 +832,9 @@ impl RoutingTableInner { /// Resolve an existing routing table entry using any crypto kind and return a reference to it #[instrument(level = "trace", skip_all, err)] - pub fn lookup_any_node_ref(&self, node_id_key: BareNodeId) -> EyreResult> { + pub fn lookup_bare_node_ref(&self, node_id_key: BareNodeId) -> EyreResult> { for ck in VALID_CRYPTO_KINDS { - if let Some(nr) = self.lookup_node_ref(NodeId::new(ck, node_id_key))? { + if let Some(nr) = self.lookup_node_ref(NodeId::new(ck, node_id_key.clone()))? { return Ok(Some(nr)); } } @@ -844,17 +844,17 @@ impl RoutingTableInner { /// Resolve an existing routing table entry and return a reference to it #[instrument(level = "trace", skip_all, err)] pub fn lookup_node_ref(&self, node_id: NodeId) -> EyreResult> { - if self.routing_table().matches_own_node_id(&[node_id]) { + if self.routing_table().matches_own_node_id(&[node_id.clone()]) { bail!("can't look up own node id in routing table"); } - if !VALID_CRYPTO_KINDS.contains(&node_id.kind) { + if !VALID_CRYPTO_KINDS.contains(&node_id.kind()) { bail!("can't look up node id with invalid crypto kind"); } let bucket_index = self.routing_table().calculate_bucket_index(&node_id); let bucket = self.get_bucket(bucket_index); Ok(bucket - .entry(&node_id.value) + .entry(node_id.ref_value()) .map(|e| NodeRef::new(self.registry(), e))) } @@ -881,17 +881,17 @@ impl RoutingTableInner { where F: FnOnce(Arc) -> R, { - if self.routing_table().matches_own_node_id(&[node_id]) { + if self.routing_table().matches_own_node_id(&[node_id.clone()]) { veilid_log!(self error "can't look up own node id in routing table"); return None; } - if !VALID_CRYPTO_KINDS.contains(&node_id.kind) { + if !VALID_CRYPTO_KINDS.contains(&node_id.kind()) { veilid_log!(self error "can't look up node id with invalid crypto kind"); return None; } let bucket_entry = self.routing_table().calculate_bucket_index(&node_id); let bucket = self.get_bucket(bucket_entry); - bucket.entry(&node_id.value).map(f) + bucket.entry(node_id.ref_value()).map(f) } /// Shortcut function to add a node to our routing table if it doesn't exist @@ -1326,7 +1326,7 @@ impl RoutingTableInner { pub fn find_preferred_closest_nodes( &self, node_count: usize, - node_id: HashDigest, + hash_coordinate: HashDigest, mut filters: VecDeque, transform: T, ) -> VeilidAPIResult> @@ -1337,7 +1337,7 @@ impl RoutingTableInner { let routing_table = self.routing_table(); // Get the crypto kind - let crypto_kind = node_id.kind; + let crypto_kind = hash_coordinate.kind(); let crypto = self.crypto(); let Some(vcrypto) = crypto.get(crypto_kind) else { apibail_generic!("invalid crypto kind"); @@ -1400,8 +1400,14 @@ impl RoutingTableInner { }; // distance is the next metric, closer nodes first - let da = vcrypto.distance(&BareHashDigest::from(a_key.value), &node_id.value); - let db = vcrypto.distance(&BareHashDigest::from(b_key.value), &node_id.value); + let da = vcrypto.distance( + &BareHashDigest::from(a_key.value()), + hash_coordinate.ref_value(), + ); + let db = vcrypto.distance( + &BareHashDigest::from(b_key.value()), + hash_coordinate.ref_value(), + ); da.cmp(&db) }; @@ -1418,7 +1424,7 @@ impl RoutingTableInner { closest_nodes: &[NodeRef], ) -> Vec { // Lock all noderefs - let kind = node_id.kind; + let kind = node_id.kind(); let mut closest_nodes_locked: Vec = closest_nodes .iter() .filter_map(|nr| { @@ -1593,9 +1599,9 @@ impl RoutingTableInner { #[instrument(level = "trace", skip_all)] pub fn make_closest_noderef_sort<'a>( crypto: &'a Crypto, - node_id: HashDigest, + hash_coordinate: HashDigest, ) -> impl Fn(&LockedNodeRef, &LockedNodeRef) -> core::cmp::Ordering + 'a { - let kind = node_id.kind; + let kind = hash_coordinate.kind(); // Get cryptoversion to check distance with let vcrypto = crypto.get(kind).unwrap(); @@ -1612,8 +1618,14 @@ pub fn make_closest_noderef_sort<'a>( let b_key = b_entry.node_ids().get(kind).unwrap(); // distance is the next metric, closer nodes first - let da = vcrypto.distance(&BareHashDigest::from(a_key.value), &node_id.value); - let db = vcrypto.distance(&BareHashDigest::from(b_key.value), &node_id.value); + let da = vcrypto.distance( + &BareHashDigest::from(a_key.value()), + hash_coordinate.ref_value(), + ); + let db = vcrypto.distance( + &BareHashDigest::from(b_key.value()), + hash_coordinate.ref_value(), + ); da.cmp(&db) }) }) @@ -1622,21 +1634,21 @@ pub fn make_closest_noderef_sort<'a>( pub fn make_closest_node_id_sort( crypto: &Crypto, - node_id: NodeId, + hash_coordinate: HashDigest, ) -> impl Fn(&BareNodeId, &BareNodeId) -> core::cmp::Ordering + '_ { - let kind = node_id.kind; + let kind = hash_coordinate.kind(); // Get cryptoversion to check distance with let vcrypto = crypto.get(kind).unwrap(); move |a: &BareNodeId, b: &BareNodeId| -> core::cmp::Ordering { // distance is the next metric, closer nodes first let da = vcrypto.distance( - &BareHashDigest::from(*a), - &BareHashDigest::from(node_id.value), + &BareHashDigest::from(a.bytes()), + hash_coordinate.ref_value(), ); let db = vcrypto.distance( - &BareHashDigest::from(*b), - &BareHashDigest::from(node_id.value), + &BareHashDigest::from(b.bytes()), + hash_coordinate.ref_value(), ); da.cmp(&db) } diff --git a/veilid-core/src/routing_table/tasks/bootstrap.rs b/veilid-core/src/routing_table/tasks/bootstrap.rs index a71b91e8..6ad33f2f 100644 --- a/veilid-core/src/routing_table/tasks/bootstrap.rs +++ b/veilid-core/src/routing_table/tasks/bootstrap.rs @@ -77,7 +77,7 @@ impl RoutingTable { if self.matches_own_node_id(peer_node_ids) { veilid_log!(self debug "Ignoring own node in bootstrap response"); } else { - for nid in peer.node_ids().iter().copied() { + for nid in peer.node_ids().iter().cloned() { bootstrapped_peer_id_set.insert(nid); } bootstrapped_peers.push(peer); @@ -134,7 +134,7 @@ impl RoutingTable { let mut rd_peer_ids = BTreeSet::new(); for peer in bootstrapped_peers.iter() { if peer.routing_domain() == rd { - for nid in peer.node_ids().iter().copied() { + for nid in peer.node_ids().iter().cloned() { rd_peer_ids.insert(nid); } } diff --git a/veilid-core/src/routing_table/tasks/kick_buckets.rs b/veilid-core/src/routing_table/tasks/kick_buckets.rs index ddc16e32..e8aef13b 100644 --- a/veilid-core/src/routing_table/tasks/kick_buckets.rs +++ b/veilid-core/src/routing_table/tasks/kick_buckets.rs @@ -30,7 +30,7 @@ impl RoutingTable { let Some(buckets) = inner.buckets.get(&kind) else { continue; }; - let sort = make_closest_node_id_sort(&crypto, our_node_id); + let sort = make_closest_node_id_sort(&crypto, our_node_id.into()); let mut closest_peers = BTreeSet::::new(); let mut closest_unreliable_count = 0usize; @@ -60,14 +60,14 @@ impl RoutingTable { BucketEntryState::Unreliable => { // Add to closest unreliable nodes list if closest_unreliable_count < KEEP_N_CLOSEST_UNRELIABLE_PEERS_COUNT { - closest_peers.insert(*key); + closest_peers.insert(key.clone()); closest_unreliable_count += 1; } } BucketEntryState::Reliable => { // Add to closest reliable nodes list if closest_reliable_count < KEEP_N_CLOSEST_RELIABLE_PEERS_COUNT { - closest_peers.insert(*key); + closest_peers.insert(key.clone()); closest_reliable_count += 1; } } diff --git a/veilid-core/src/routing_table/tasks/private_route_management.rs b/veilid-core/src/routing_table/tasks/private_route_management.rs index a8bf0bbb..056bf2a8 100644 --- a/veilid-core/src/routing_table/tasks/private_route_management.rs +++ b/veilid-core/src/routing_table/tasks/private_route_management.rs @@ -19,7 +19,7 @@ impl RoutingTable { }) } /// Fastest routes sort - fn route_sort_latency_fn(a: &(BareRouteId, u64), b: &(BareRouteId, u64)) -> cmp::Ordering { + fn route_sort_latency_fn(a: &(RouteId, u64), b: &(RouteId, u64)) -> cmp::Ordering { let mut al = a.1; let mut bl = b.1; // Treat zero latency as uncalculated @@ -46,14 +46,14 @@ impl RoutingTable { /// /// If a route doesn't 'need_testing', then we neither test nor drop it #[instrument(level = "trace", skip(self))] - fn get_allocated_routes_to_test(&self, cur_ts: Timestamp) -> Vec { + fn get_allocated_routes_to_test(&self, cur_ts: Timestamp) -> Vec { let default_route_hop_count = self .config() .with(|c| c.network.rpc.default_route_hop_count as usize); - let mut must_test_routes = Vec::::new(); - let mut unpublished_routes = Vec::<(BareRouteId, u64)>::new(); - let mut expired_routes = Vec::::new(); + let mut must_test_routes = Vec::::new(); + let mut unpublished_routes = Vec::<(RouteId, u64)>::new(); + let mut expired_routes = Vec::::new(); self.route_spec_store().list_allocated_routes(|k, v| { let stats = v.get_stats(); // Ignore nodes that don't need testing @@ -63,15 +63,15 @@ impl RoutingTable { // If this has been published, always test if we need it // Also if the route has never been tested, test it at least once if v.is_published() || stats.last_known_valid_ts.is_none() { - must_test_routes.push(*k); + must_test_routes.push(k.clone()); } // If this is a default route hop length, include it in routes to keep alive else if v.hop_count() == default_route_hop_count { - unpublished_routes.push((*k, stats.latency.average.as_u64())); + unpublished_routes.push((k.clone(), stats.latency.average.as_u64())); } // Else this is a route that hasnt been used recently enough and we can tear it down else { - expired_routes.push(*k); + expired_routes.push(k.clone()); } Option::<()>::None }); @@ -85,13 +85,13 @@ impl RoutingTable { background_safety_route_count, unpublished_routes.len(), )) { - must_test_routes.push(unpublished_route.0); + must_test_routes.push(unpublished_route.0.clone()); } // Kill off all but N unpublished routes rather than testing them if unpublished_routes.len() > background_safety_route_count { for x in &unpublished_routes[background_safety_route_count..] { - expired_routes.push(x.0); + expired_routes.push(x.0.clone()); } } @@ -110,7 +110,7 @@ impl RoutingTable { async fn test_route_set( &self, stop_token: StopToken, - routes_needing_testing: Vec, + routes_needing_testing: Vec, ) -> EyreResult<()> { if routes_needing_testing.is_empty() { return Ok(()); @@ -119,7 +119,7 @@ impl RoutingTable { #[derive(Default, Debug)] struct TestRouteContext { - dead_routes: Vec, + dead_routes: Vec, } let ctx = Arc::new(Mutex::new(TestRouteContext::default())); @@ -129,7 +129,7 @@ impl RoutingTable { let ctx = ctx.clone(); unord.push( async move { - let success = match self.route_spec_store().test_route(r).await { + let success = match self.route_spec_store().test_route(r.clone()).await { // Test had result Ok(Some(v)) => v, // Test could not be performed at this time @@ -242,7 +242,7 @@ impl RoutingTable { let remote_routes_needing_testing = self.route_spec_store().list_remote_routes(|k, v| { let stats = v.get_stats(); if stats.needs_testing(cur_ts) { - Some(*k) + Some(k.clone()) } else { None } diff --git a/veilid-core/src/routing_table/tests/test_serialize_routing_table.rs b/veilid-core/src/routing_table/tests/test_serialize_routing_table.rs index 005e95a6..ae687fad 100644 --- a/veilid-core/src/routing_table/tests/test_serialize_routing_table.rs +++ b/veilid-core/src/routing_table/tests/test_serialize_routing_table.rs @@ -4,7 +4,7 @@ use crate::{routing_table::*, RegisteredComponents, VALID_CRYPTO_KINDS}; fn make_mock_typed_node_id(kind: CryptoKind, idx: u8) -> NodeId { NodeId::new( kind, - BareNodeId::new([ + BareNodeId::new(&[ idx, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]), diff --git a/veilid-core/src/routing_table/types/signed_direct_node_info.rs b/veilid-core/src/routing_table/types/signed_direct_node_info.rs index 0035f1cb..0ff990b6 100644 --- a/veilid-core/src/routing_table/types/signed_direct_node_info.rs +++ b/veilid-core/src/routing_table/types/signed_direct_node_info.rs @@ -63,7 +63,7 @@ impl SignedDirectNodeInfo { let node_info_bytes = Self::make_signature_bytes(&node_info, timestamp)?; let typed_signatures = crypto.generate_signatures(&node_info_bytes, &typed_key_pairs, |kp, s| { - Signature::new(kp.kind, s) + Signature::new(kp.kind(), s) })?; Ok(Self { node_info, diff --git a/veilid-core/src/routing_table/types/signed_relayed_node_info.rs b/veilid-core/src/routing_table/types/signed_relayed_node_info.rs index 7d789eaa..3e1d829d 100644 --- a/veilid-core/src/routing_table/types/signed_relayed_node_info.rs +++ b/veilid-core/src/routing_table/types/signed_relayed_node_info.rs @@ -93,7 +93,7 @@ impl SignedRelayedNodeInfo { Self::make_signature_bytes(&node_info, &relay_ids, &relay_info, timestamp)?; let typed_signatures = crypto.generate_signatures(&node_info_bytes, &typed_key_pairs, |kp, s| { - Signature::new(kp.kind, s) + Signature::new(kp.kind(), s) })?; Ok(Self { node_info, @@ -121,8 +121,8 @@ impl SignedRelayedNodeInfo { // Add relay ids to signature for relay_id in relay_ids { let mut rid_msg = ::capnp::message::Builder::new_default(); - let mut rid_builder = rid_msg.init_root::(); - encode_typed_node_id(relay_id, &mut rid_builder); + let mut rid_builder = rid_msg.init_root::(); + encode_node_id(relay_id, &mut rid_builder); sig_bytes.append(&mut builder_to_vec(rid_msg).map_err(VeilidAPIError::internal)?); } diff --git a/veilid-core/src/rpc_processor/coders/byte_array_types.rs b/veilid-core/src/rpc_processor/coders/byte_array_types.rs new file mode 100644 index 00000000..bccd7025 --- /dev/null +++ b/veilid-core/src/rpc_processor/coders/byte_array_types.rs @@ -0,0 +1,72 @@ +use super::*; +use paste::paste; + +// Utility Macros +macro_rules! define_typed_byte_data_coder { + ($capnp_name: ident, $rust_name: ident) => { + paste! { + pub fn [< decode_ $capnp_name >]( + reader: &veilid_capnp::$capnp_name::Reader, + ) -> Result<$rust_name, RPCError> { + rpc_ignore_missing_property!(reader, value); + let value = reader.get_value()?; + let kind = reader.get_kind(); + + Ok($rust_name::new( + CryptoKind::from(kind.to_be_bytes()), + [< Bare $rust_name >]::new(value), + )) + } + + pub fn [< encode_ $capnp_name >]( + $capnp_name: &$rust_name, + builder: &mut veilid_capnp::$capnp_name::Builder, + ) { + builder.set_kind(u32::from_be_bytes($capnp_name.kind().0)); + builder.set_value($capnp_name.ref_value()); + } + } + }; +} + +macro_rules! define_untyped_byte_data_coder { + ($capnp_name: ident, $rust_name: ident) => { + paste! { + pub fn [< decode_ $capnp_name >]( + reader: &veilid_capnp::$capnp_name::Reader, + ) -> Result<$rust_name, RPCError> { + rpc_ignore_missing_property!(reader, value); + let value = reader.get_value()?; + + Ok( + [< $rust_name >]::new(value), + ) + } + + pub fn [< encode_ $capnp_name >]( + $capnp_name: &$rust_name, + builder: &mut veilid_capnp::$capnp_name::Builder, + ) { + builder.set_value($capnp_name); + } + } + }; +} + +// RecordKey +define_typed_byte_data_coder!(record_key, RecordKey); +// BlockId +#[cfg(feature = "unstable-blockstore")] +define_typed_byte_data_coder!(block_id, BlockId); +// NodeId +define_typed_byte_data_coder!(node_id, NodeId); +// PublicKey +define_typed_byte_data_coder!(public_key, PublicKey); +// RouteId +#[cfg(feature = "unstable-blockstore")] +define_typed_byte_data_coder!(route_id, RouteId); +// Signature +define_typed_byte_data_coder!(signature, Signature); + +// Nonce +define_untyped_byte_data_coder!(nonce, BareNonce); diff --git a/veilid-core/src/rpc_processor/coders/key256.rs b/veilid-core/src/rpc_processor/coders/key256.rs deleted file mode 100644 index 3ff27ed0..00000000 --- a/veilid-core/src/rpc_processor/coders/key256.rs +++ /dev/null @@ -1,40 +0,0 @@ -use super::*; -use core::convert::TryInto; - -pub fn decode_key256(public_key: &veilid_capnp::key256::Reader) -> BarePublicKey { - let u0 = public_key.get_u0().to_be_bytes(); - let u1 = public_key.get_u1().to_be_bytes(); - let u2 = public_key.get_u2().to_be_bytes(); - let u3 = public_key.get_u3().to_be_bytes(); - - let mut x: [u8; 32] = Default::default(); - x[0..8].copy_from_slice(&u0); - x[8..16].copy_from_slice(&u1); - x[16..24].copy_from_slice(&u2); - x[24..32].copy_from_slice(&u3); - - BarePublicKey::new(x) -} - -pub fn encode_key256(key: &BarePublicKey, builder: &mut veilid_capnp::key256::Builder) { - builder.set_u0(u64::from_be_bytes( - key.bytes[0..8] - .try_into() - .expect("slice with incorrect length"), - )); - builder.set_u1(u64::from_be_bytes( - key.bytes[8..16] - .try_into() - .expect("slice with incorrect length"), - )); - builder.set_u2(u64::from_be_bytes( - key.bytes[16..24] - .try_into() - .expect("slice with incorrect length"), - )); - builder.set_u3(u64::from_be_bytes( - key.bytes[24..32] - .try_into() - .expect("slice with incorrect length"), - )); -} diff --git a/veilid-core/src/rpc_processor/coders/mod.rs b/veilid-core/src/rpc_processor/coders/mod.rs index c49daab0..c6b59651 100644 --- a/veilid-core/src/rpc_processor/coders/mod.rs +++ b/veilid-core/src/rpc_processor/coders/mod.rs @@ -1,13 +1,12 @@ mod address; mod address_type_set; +mod byte_array_types; mod dial_info; mod dial_info_class; mod dial_info_detail; -mod key256; mod network_class; mod node_info; mod node_status; -mod nonce; mod operations; mod peer_info; mod private_safety_route; @@ -15,7 +14,6 @@ mod protocol_type_set; mod sender_info; mod sequencing; mod signal_info; -mod signature512; mod signed_direct_node_info; mod signed_node_info; mod signed_relayed_node_info; @@ -24,19 +22,16 @@ mod signed_value_descriptor; mod socket_address; #[cfg(feature = "unstable-tunnels")] mod tunnel; -mod typed_key; -mod typed_signature; pub use address::*; pub use address_type_set::*; +pub use byte_array_types::*; pub use dial_info::*; pub use dial_info_class::*; pub use dial_info_detail::*; -pub use key256::*; pub use network_class::*; pub use node_info::*; pub use node_status::*; -pub use nonce::*; pub use operations::*; pub use peer_info::*; pub use private_safety_route::*; @@ -44,7 +39,6 @@ pub use protocol_type_set::*; pub use sender_info::*; pub use sequencing::*; pub use signal_info::*; -pub use signature512::*; pub use signed_direct_node_info::*; pub use signed_node_info::*; pub use signed_relayed_node_info::*; @@ -53,8 +47,6 @@ pub use signed_value_descriptor::*; pub use socket_address::*; #[cfg(feature = "unstable-tunnels")] pub use tunnel::*; -pub use typed_key::*; -pub use typed_signature::*; use super::*; diff --git a/veilid-core/src/rpc_processor/coders/nonce.rs b/veilid-core/src/rpc_processor/coders/nonce.rs deleted file mode 100644 index c3d28574..00000000 --- a/veilid-core/src/rpc_processor/coders/nonce.rs +++ /dev/null @@ -1,31 +0,0 @@ -use super::*; - -pub fn encode_nonce(nonce: &BareNonce, builder: &mut veilid_capnp::nonce24::Builder) { - builder.set_u0(u64::from_be_bytes( - nonce.bytes[0..8] - .try_into() - .expect("slice with incorrect length"), - )); - builder.set_u1(u64::from_be_bytes( - nonce.bytes[8..16] - .try_into() - .expect("slice with incorrect length"), - )); - builder.set_u2(u64::from_be_bytes( - nonce.bytes[16..24] - .try_into() - .expect("slice with incorrect length"), - )); -} - -pub fn decode_nonce(reader: &veilid_capnp::nonce24::Reader) -> BareNonce { - let u0 = reader.get_u0().to_be_bytes(); - let u1 = reader.get_u1().to_be_bytes(); - let u2 = reader.get_u2().to_be_bytes(); - - BareNonce::new([ - u0[0], u0[1], u0[2], u0[3], u0[4], u0[5], u0[6], u0[7], // u0 - u1[0], u1[1], u1[2], u1[3], u1[4], u1[5], u1[6], u1[7], // u1 - u2[0], u2[1], u2[2], u2[3], u2[4], u2[5], u2[6], u2[7], // u2 - ]) -} diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_find_node.rs b/veilid-core/src/rpc_processor/coders/operations/operation_find_node.rs index 5a7bc4b7..6b307f65 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_find_node.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_find_node.rs @@ -36,7 +36,7 @@ impl RPCOperationFindNodeQ { ) -> Result { rpc_ignore_missing_property!(reader, node_id); let ni_reader = reader.get_node_id()?; - let node_id = decode_typed_node_id(&ni_reader)?; + let node_id = decode_node_id(&ni_reader)?; rpc_ignore_missing_property!(reader, capabilities); let cap_reader = reader.get_capabilities()?; @@ -60,7 +60,7 @@ impl RPCOperationFindNodeQ { builder: &mut veilid_capnp::operation_find_node_q::Builder, ) -> Result<(), RPCError> { let mut ni_builder = builder.reborrow().init_node_id(); - encode_typed_node_id(&self.node_id, &mut ni_builder); + encode_node_id(&self.node_id, &mut ni_builder); let mut cap_builder = builder .reborrow() diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_get_value.rs b/veilid-core/src/rpc_processor/coders/operations/operation_get_value.rs index d8ef152d..61e21d13 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_get_value.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_get_value.rs @@ -58,7 +58,7 @@ impl RPCOperationGetValueQ { ) -> Result { rpc_ignore_missing_property!(reader, key); let k_reader = reader.get_key()?; - let key = decode_typed_record_key(&k_reader)?; + let key = decode_record_key(&k_reader)?; let subkey = reader.get_subkey(); let want_descriptor = reader.get_want_descriptor(); Ok(Self { @@ -72,7 +72,7 @@ impl RPCOperationGetValueQ { builder: &mut veilid_capnp::operation_get_value_q::Builder, ) -> Result<(), RPCError> { let mut k_builder = builder.reborrow().init_key(); - encode_typed_record_key(&self.key, &mut k_builder); + encode_record_key(&self.key, &mut k_builder); builder.set_subkey(self.subkey); builder.set_want_descriptor(self.want_descriptor); Ok(()) @@ -150,7 +150,7 @@ impl RPCOperationGetValueA { // And the signed value data if !value - .validate(descriptor.owner(), get_value_context.subkey, &vcrypto) + .validate(descriptor.ref_owner(), get_value_context.subkey, &vcrypto) .map_err(RPCError::protocol)? { return Err(RPCError::protocol("signed value data did not validate")); diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_inspect_value.rs b/veilid-core/src/rpc_processor/coders/operations/operation_inspect_value.rs index baf801ce..a264a7a3 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_inspect_value.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_inspect_value.rs @@ -54,7 +54,7 @@ impl RPCOperationInspectValueQ { ) -> Result { rpc_ignore_missing_property!(reader, key); let k_reader = reader.get_key()?; - let key = decode_typed_record_key(&k_reader)?; + let key = decode_record_key(&k_reader)?; rpc_ignore_missing_property!(reader, subkeys); let sk_reader = reader.get_subkeys()?; @@ -89,7 +89,7 @@ impl RPCOperationInspectValueQ { builder: &mut veilid_capnp::operation_inspect_value_q::Builder, ) -> Result<(), RPCError> { let mut k_builder = builder.reborrow().init_key(); - encode_typed_record_key(&self.key, &mut k_builder); + encode_record_key(&self.key, &mut k_builder); let mut sk_builder = builder.reborrow().init_subkeys( self.subkeys diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_route.rs b/veilid-core/src/rpc_processor/coders/operations/operation_route.rs index 9b462d9c..0d2f3a4d 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_route.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_route.rs @@ -4,7 +4,7 @@ use super::*; pub(in crate::rpc_processor) struct RoutedOperation { routing_domain: RoutingDomain, sequencing: Sequencing, - signatures: Vec, + signatures: Vec, nonce: BareNonce, data: Vec, } @@ -46,11 +46,11 @@ impl RoutedOperation { pub fn sequencing(&self) -> Sequencing { self.sequencing } - pub fn signatures(&self) -> &[BareSignature] { + pub fn signatures(&self) -> &[Signature] { &self.signatures } - pub fn add_signature(&mut self, signature: BareSignature) { + pub fn add_signature(&mut self, signature: Signature) { self.signatures.push(signature); } @@ -71,22 +71,23 @@ impl RoutedOperation { ) -> Result { rpc_ignore_missing_property!(reader, signatures); let sigs_reader = reader.get_signatures()?; - let mut signatures = Vec::::with_capacity( + let mut signatures = Vec::::with_capacity( sigs_reader .len() .try_into() .map_err(RPCError::map_internal("too many signatures"))?, ); for s in sigs_reader.iter() { - // TODO: wants .ignore_ok() eventually - let sig = decode_signature512(&s); + let Some(sig) = decode_signature(&s).ignore_ok()? else { + continue; + }; signatures.push(sig); } let sequencing = decode_sequencing(reader.get_sequencing()?); rpc_ignore_missing_property!(reader, nonce); let n_reader = reader.get_nonce()?; - let nonce = decode_nonce(&n_reader); + let nonce = decode_nonce(&n_reader)?; rpc_ignore_missing_property!(reader, data); let data = reader.get_data()?; @@ -114,7 +115,7 @@ impl RoutedOperation { ); for (i, sig) in self.signatures.iter().enumerate() { let mut sig_builder = sigs_builder.reborrow().get(i as u32); - encode_signature512(sig, &mut sig_builder); + encode_signature(sig, &mut sig_builder); } let mut n_builder = builder.reborrow().init_nonce(); encode_nonce(&self.nonce, &mut n_builder); diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_set_value.rs b/veilid-core/src/rpc_processor/coders/operations/operation_set_value.rs index 758a4d5f..0acf9f1b 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_set_value.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_set_value.rs @@ -78,7 +78,7 @@ impl RPCOperationSetValueQ { ) -> Result { rpc_ignore_missing_property!(reader, key); let k_reader = reader.get_key()?; - let key = decode_typed_record_key(&k_reader)?; + let key = decode_record_key(&k_reader)?; let subkey = reader.get_subkey(); @@ -105,7 +105,7 @@ impl RPCOperationSetValueQ { builder: &mut veilid_capnp::operation_set_value_q::Builder, ) -> Result<(), RPCError> { let mut k_builder = builder.reborrow().init_key(); - encode_typed_record_key(&self.key, &mut k_builder); + encode_record_key(&self.key, &mut k_builder); builder.set_subkey(self.subkey); let mut v_builder = builder.reborrow().init_value(); encode_signed_value_data(&self.value, &mut v_builder)?; @@ -164,7 +164,7 @@ impl RPCOperationSetValueA { // And the signed value data if !value .validate( - set_value_context.descriptor.owner(), + set_value_context.descriptor.ref_owner(), set_value_context.subkey, &vcrypto, ) diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_value_changed.rs b/veilid-core/src/rpc_processor/coders/operations/operation_value_changed.rs index c4388887..f7987e85 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_value_changed.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_value_changed.rs @@ -106,7 +106,7 @@ impl RPCOperationValueChanged { ) -> Result { rpc_ignore_missing_property!(reader, key); let k_reader = reader.get_key()?; - let key = decode_typed_record_key(&k_reader)?; + let key = decode_record_key(&k_reader)?; rpc_ignore_missing_property!(reader, subkeys); let sk_reader = reader.get_subkeys()?; @@ -149,7 +149,7 @@ impl RPCOperationValueChanged { builder: &mut veilid_capnp::operation_value_changed::Builder, ) -> Result<(), RPCError> { let mut k_builder = builder.reborrow().init_key(); - encode_typed_record_key(&self.key, &mut k_builder); + encode_record_key(&self.key, &mut k_builder); let mut sk_builder = builder.reborrow().init_subkeys( self.subkeys diff --git a/veilid-core/src/rpc_processor/coders/operations/operation_watch_value.rs b/veilid-core/src/rpc_processor/coders/operations/operation_watch_value.rs index d01f5344..1670b440 100644 --- a/veilid-core/src/rpc_processor/coders/operations/operation_watch_value.rs +++ b/veilid-core/src/rpc_processor/coders/operations/operation_watch_value.rs @@ -10,8 +10,8 @@ pub(in crate::rpc_processor) struct RPCOperationWatchValueQ { expiration: u64, count: u32, watch_id: Option, - watcher: BarePublicKey, - signature: BareSignature, + watcher: PublicKey, + signature: Signature, } impl RPCOperationWatchValueQ { @@ -21,7 +21,7 @@ impl RPCOperationWatchValueQ { expiration: u64, count: u32, watch_id: Option, - watcher: BareKeyPair, + watcher: KeyPair, vcrypto: &CryptoSystemGuard<'_>, ) -> Result { if subkeys.ranges_len() > MAX_WATCH_VALUE_Q_SUBKEY_RANGES_LEN { @@ -34,9 +34,16 @@ impl RPCOperationWatchValueQ { } let signature_data = Self::make_signature_data(&key, &subkeys, expiration, count, watch_id); - let signature = vcrypto - .sign(&watcher.key, &watcher.secret, &signature_data) - .map_err(RPCError::protocol)?; + let signature = Signature::new( + vcrypto.kind(), + vcrypto + .sign( + watcher.ref_value().ref_key(), + watcher.ref_value().ref_secret(), + &signature_data, + ) + .map_err(RPCError::protocol)?, + ); Ok(Self { key, @@ -44,7 +51,7 @@ impl RPCOperationWatchValueQ { expiration, count, watch_id, - watcher: watcher.key, + watcher: PublicKey::new(watcher.kind(), watcher.ref_value().key()), signature, }) } @@ -60,9 +67,9 @@ impl RPCOperationWatchValueQ { let subkeys_ranges_len = subkeys.ranges_len(); let mut sig_data = - Vec::with_capacity(PUBLIC_KEY_LENGTH + 4 + (subkeys_ranges_len * 8) + 8 + 8); - sig_data.extend_from_slice(&key.kind.0); - sig_data.extend_from_slice(&key.value.bytes); + Vec::with_capacity(key.ref_value().len() + 4 + (subkeys_ranges_len * 8) + 8 + 8); + sig_data.extend_from_slice(&key.kind().0); + sig_data.extend_from_slice(key.ref_value()); for sk in subkeys.ranges() { sig_data.extend_from_slice(&sk.start().to_le_bytes()); sig_data.extend_from_slice(&sk.end().to_le_bytes()); @@ -77,7 +84,7 @@ impl RPCOperationWatchValueQ { pub fn validate(&mut self, validate_context: &RPCValidateContext) -> Result<(), RPCError> { let crypto = validate_context.crypto(); - let Some(vcrypto) = crypto.get(self.key.kind) else { + let Some(vcrypto) = crypto.get(self.watcher.kind()) else { return Err(RPCError::protocol("unsupported cryptosystem")); }; @@ -89,7 +96,11 @@ impl RPCOperationWatchValueQ { self.watch_id, ); if !vcrypto - .verify(&self.watcher, &sig_data, &self.signature) + .verify( + self.watcher.ref_value(), + &sig_data, + self.signature.ref_value(), + ) .map_err(RPCError::protocol)? { return Err(RPCError::protocol("failed to validate watcher signature")); @@ -129,11 +140,11 @@ impl RPCOperationWatchValueQ { } #[expect(dead_code)] - pub fn watcher(&self) -> &BarePublicKey { + pub fn watcher(&self) -> &PublicKey { &self.watcher } #[expect(dead_code)] - pub fn signature(&self) -> &BareSignature { + pub fn signature(&self) -> &Signature { &self.signature } pub fn destructure( @@ -144,8 +155,8 @@ impl RPCOperationWatchValueQ { u64, u32, Option, - BarePublicKey, - BareSignature, + PublicKey, + Signature, ) { ( self.key, @@ -164,7 +175,7 @@ impl RPCOperationWatchValueQ { ) -> Result { rpc_ignore_missing_property!(reader, key); let k_reader = reader.get_key()?; - let key = decode_typed_record_key(&k_reader)?; + let key = decode_record_key(&k_reader)?; rpc_ignore_missing_property!(reader, subkeys); let sk_reader = reader.get_subkeys()?; @@ -195,11 +206,11 @@ impl RPCOperationWatchValueQ { rpc_ignore_missing_property!(reader, watcher); let w_reader = reader.get_watcher()?; - let watcher = decode_key256(&w_reader); + let watcher = decode_public_key(&w_reader)?; rpc_ignore_missing_property!(reader, signature); let s_reader = reader.get_signature()?; - let signature = decode_signature512(&s_reader); + let signature = decode_signature(&s_reader)?; Ok(Self { key, @@ -217,7 +228,7 @@ impl RPCOperationWatchValueQ { builder: &mut veilid_capnp::operation_watch_value_q::Builder, ) -> Result<(), RPCError> { let mut k_builder = builder.reborrow().init_key(); - encode_typed_record_key(&self.key, &mut k_builder); + encode_record_key(&self.key, &mut k_builder); let mut sk_builder = builder.reborrow().init_subkeys( self.subkeys @@ -235,10 +246,10 @@ impl RPCOperationWatchValueQ { builder.set_watch_id(self.watch_id.unwrap_or(0u64)); let mut w_builder = builder.reborrow().init_watcher(); - encode_key256(&self.watcher, &mut w_builder); + encode_public_key(&self.watcher, &mut w_builder); let mut s_builder = builder.reborrow().init_signature(); - encode_signature512(&self.signature, &mut s_builder); + encode_signature(&self.signature, &mut s_builder); Ok(()) } diff --git a/veilid-core/src/rpc_processor/coders/peer_info.rs b/veilid-core/src/rpc_processor/coders/peer_info.rs index 8408047d..1773e09c 100644 --- a/veilid-core/src/rpc_processor/coders/peer_info.rs +++ b/veilid-core/src/rpc_processor/coders/peer_info.rs @@ -12,7 +12,7 @@ pub fn decode_peer_info( let mut node_ids = NodeIdGroup::with_capacity(nids_reader.len() as usize); for nid_reader in nids_reader.iter() { - let Some(nid) = decode_typed_node_id(&nid_reader).ignore_ok()? else { + let Some(nid) = decode_node_id(&nid_reader).ignore_ok()? else { continue; }; node_ids.add(nid); @@ -38,7 +38,7 @@ pub fn encode_peer_info( .map_err(RPCError::map_invalid_format("out of bound error"))?, ); for (i, nid) in peer_info.node_ids().iter().enumerate() { - encode_typed_node_id( + encode_node_id( nid, &mut nids_builder.reborrow().get( i.try_into() diff --git a/veilid-core/src/rpc_processor/coders/private_safety_route.rs b/veilid-core/src/rpc_processor/coders/private_safety_route.rs index 72e21a12..7e692cfc 100644 --- a/veilid-core/src/rpc_processor/coders/private_safety_route.rs +++ b/veilid-core/src/rpc_processor/coders/private_safety_route.rs @@ -6,7 +6,7 @@ pub fn decode_route_hop_data( reader: &veilid_capnp::route_hop_data::Reader, ) -> Result { rpc_ignore_missing_property!(reader, nonce); - let nonce = decode_nonce(&reader.get_nonce()?); + let nonce = decode_nonce(&reader.get_nonce()?)?; rpc_ignore_missing_property!(reader, blob); let blob = reader.get_blob()?.to_vec(); @@ -45,7 +45,7 @@ pub fn decode_route_hop( let node = match reader.get_node().which()? { veilid_capnp::route_hop::node::Which::NodeId(ni) => { let ni_reader = ni?; - RouteNode::BareNodeId(decode_key256(&ni_reader).into()) + RouteNode::NodeId(decode_node_id(&ni_reader)?) } veilid_capnp::route_hop::node::Which::PeerInfo(pi) => { let pi_reader = pi?; @@ -71,9 +71,9 @@ pub fn encode_route_hop( ) -> Result<(), RPCError> { let node_builder = builder.reborrow().init_node(); match &route_hop.node { - RouteNode::BareNodeId(ni) => { + RouteNode::NodeId(ni) => { let mut ni_builder = node_builder.init_node_id(); - encode_key256(&(*ni).into(), &mut ni_builder); + encode_node_id(ni, &mut ni_builder); } RouteNode::PeerInfo(pi) => { let mut pi_builder = node_builder.init_peer_info(); @@ -94,8 +94,7 @@ pub fn decode_private_route( reader: &veilid_capnp::private_route::Reader, ) -> Result { rpc_ignore_missing_property!(reader, public_key); - let public_key = decode_typed_public_key(&reader.get_public_key()?)?; - let hop_count = reader.get_hop_count(); + let public_key = decode_public_key(&reader.get_public_key()?)?; let hops = match reader.get_hops().which()? { veilid_capnp::private_route::hops::Which::FirstHop(rh_reader) => { @@ -109,22 +108,17 @@ pub fn decode_private_route( veilid_capnp::private_route::hops::Which::Empty(_) => PrivateRouteHops::Empty, }; - Ok(PrivateRoute { - public_key, - hop_count, - hops, - }) + Ok(PrivateRoute { public_key, hops }) } pub fn encode_private_route( private_route: &PrivateRoute, builder: &mut veilid_capnp::private_route::Builder, ) -> Result<(), RPCError> { - encode_typed_public_key( + encode_public_key( &private_route.public_key, &mut builder.reborrow().init_public_key(), ); - builder.set_hop_count(private_route.hop_count); let mut h_builder = builder.reborrow().init_hops(); match &private_route.hops { PrivateRouteHops::FirstHop(first_hop) => { @@ -149,8 +143,7 @@ pub fn decode_safety_route( reader: &veilid_capnp::safety_route::Reader, ) -> Result { rpc_ignore_missing_property!(reader, public_key); - let public_key = decode_typed_public_key(&reader.get_public_key()?)?; - let hop_count = reader.get_hop_count(); + let public_key = decode_public_key(&reader.get_public_key()?)?; let hops = match reader.get_hops().which()? { veilid_capnp::safety_route::hops::Which::Data(rhd_reader) => { let rhd_reader = rhd_reader?; @@ -162,22 +155,17 @@ pub fn decode_safety_route( } }; - Ok(SafetyRoute { - public_key, - hop_count, - hops, - }) + Ok(SafetyRoute { public_key, hops }) } pub fn encode_safety_route( safety_route: &SafetyRoute, builder: &mut veilid_capnp::safety_route::Builder, ) -> Result<(), RPCError> { - encode_typed_public_key( + encode_public_key( &safety_route.public_key, &mut builder.reborrow().init_public_key(), ); - builder.set_hop_count(safety_route.hop_count); let h_builder = builder.reborrow().init_hops(); match &safety_route.hops { SafetyRouteHops::Data(rhd) => { diff --git a/veilid-core/src/rpc_processor/coders/signature512.rs b/veilid-core/src/rpc_processor/coders/signature512.rs deleted file mode 100644 index ede4dc20..00000000 --- a/veilid-core/src/rpc_processor/coders/signature512.rs +++ /dev/null @@ -1,52 +0,0 @@ -use super::*; - -pub fn encode_signature512(sig: &BareSignature, builder: &mut veilid_capnp::signature512::Builder) { - let sig = &sig.bytes; - - builder.set_u0(u64::from_be_bytes( - sig[0..8].try_into().expect("slice with incorrect length"), - )); - builder.set_u1(u64::from_be_bytes( - sig[8..16].try_into().expect("slice with incorrect length"), - )); - builder.set_u2(u64::from_be_bytes( - sig[16..24].try_into().expect("slice with incorrect length"), - )); - builder.set_u3(u64::from_be_bytes( - sig[24..32].try_into().expect("slice with incorrect length"), - )); - builder.set_u4(u64::from_be_bytes( - sig[32..40].try_into().expect("slice with incorrect length"), - )); - builder.set_u5(u64::from_be_bytes( - sig[40..48].try_into().expect("slice with incorrect length"), - )); - builder.set_u6(u64::from_be_bytes( - sig[48..56].try_into().expect("slice with incorrect length"), - )); - builder.set_u7(u64::from_be_bytes( - sig[56..64].try_into().expect("slice with incorrect length"), - )); -} - -pub fn decode_signature512(reader: &veilid_capnp::signature512::Reader) -> BareSignature { - let u0 = reader.get_u0().to_be_bytes(); - let u1 = reader.get_u1().to_be_bytes(); - let u2 = reader.get_u2().to_be_bytes(); - let u3 = reader.get_u3().to_be_bytes(); - let u4 = reader.get_u4().to_be_bytes(); - let u5 = reader.get_u5().to_be_bytes(); - let u6 = reader.get_u6().to_be_bytes(); - let u7 = reader.get_u7().to_be_bytes(); - - BareSignature::new([ - u0[0], u0[1], u0[2], u0[3], u0[4], u0[5], u0[6], u0[7], // u0 - u1[0], u1[1], u1[2], u1[3], u1[4], u1[5], u1[6], u1[7], // u1 - u2[0], u2[1], u2[2], u2[3], u2[4], u2[5], u2[6], u2[7], // u2 - u3[0], u3[1], u3[2], u3[3], u3[4], u3[5], u3[6], u3[7], // u3 - u4[0], u4[1], u4[2], u4[3], u4[4], u4[5], u4[6], u4[7], // u4 - u5[0], u5[1], u5[2], u5[3], u5[4], u5[5], u5[6], u5[7], // u5 - u6[0], u6[1], u6[2], u6[3], u6[4], u6[5], u6[6], u6[7], // u6 - u7[0], u7[1], u7[2], u7[3], u7[4], u7[5], u7[6], u7[7], // u7 - ]) -} diff --git a/veilid-core/src/rpc_processor/coders/signed_direct_node_info.rs b/veilid-core/src/rpc_processor/coders/signed_direct_node_info.rs index 2a0d817e..09edf452 100644 --- a/veilid-core/src/rpc_processor/coders/signed_direct_node_info.rs +++ b/veilid-core/src/rpc_processor/coders/signed_direct_node_info.rs @@ -14,7 +14,7 @@ pub fn decode_signed_direct_node_info( let sigs_len = rpc_ignore_max_len!(sigs_reader, MAX_CRYPTO_KINDS); let mut typed_signatures = Vec::with_capacity(sigs_len); for sig_reader in sigs_reader { - let Some(typed_signature) = decode_typed_signature(&sig_reader).ignore_ok()? else { + let Some(typed_signature) = decode_signature(&sig_reader).ignore_ok()? else { continue; }; typed_signatures.push(typed_signature); @@ -47,7 +47,7 @@ pub fn encode_signed_direct_node_info( .map_err(RPCError::map_invalid_format("out of bound error"))?, ); for (i, typed_signature) in signed_direct_node_info.signatures().iter().enumerate() { - encode_typed_signature( + encode_signature( typed_signature, &mut sigs_builder.reborrow().get( i.try_into() diff --git a/veilid-core/src/rpc_processor/coders/signed_relayed_node_info.rs b/veilid-core/src/rpc_processor/coders/signed_relayed_node_info.rs index 8aae1e93..ff801662 100644 --- a/veilid-core/src/rpc_processor/coders/signed_relayed_node_info.rs +++ b/veilid-core/src/rpc_processor/coders/signed_relayed_node_info.rs @@ -12,7 +12,7 @@ pub fn decode_signed_relayed_node_info( let rid_count = rpc_ignore_max_len!(rids_reader, MAX_CRYPTO_KINDS); let mut relay_ids = NodeIdGroup::with_capacity(rid_count); for rid_reader in rids_reader { - let Some(relay_id) = decode_typed_node_id(&rid_reader).ignore_ok()? else { + let Some(relay_id) = decode_node_id(&rid_reader).ignore_ok()? else { continue; }; relay_ids.add(relay_id); @@ -31,7 +31,7 @@ pub fn decode_signed_relayed_node_info( let sig_count = rpc_ignore_max_len!(sigs_reader, MAX_CRYPTO_KINDS); let mut typed_signatures = Vec::with_capacity(sig_count); for sig_reader in sigs_reader { - let Some(typed_signature) = decode_typed_signature(&sig_reader).ignore_ok()? else { + let Some(typed_signature) = decode_signature(&sig_reader).ignore_ok()? else { continue; }; typed_signatures.push(typed_signature); @@ -61,7 +61,7 @@ pub fn encode_signed_relayed_node_info( .map_err(RPCError::map_invalid_format("out of bound error"))?, ); for (i, typed_key) in signed_relayed_node_info.relay_ids().iter().enumerate() { - encode_typed_node_id( + encode_node_id( typed_key, &mut rids_builder.reborrow().get( i.try_into() @@ -85,7 +85,7 @@ pub fn encode_signed_relayed_node_info( .map_err(RPCError::map_invalid_format("out of bound error"))?, ); for (i, typed_signature) in signed_relayed_node_info.signatures().iter().enumerate() { - encode_typed_signature( + encode_signature( typed_signature, &mut sigs_builder.reborrow().get( i.try_into() diff --git a/veilid-core/src/rpc_processor/coders/signed_value_data.rs b/veilid-core/src/rpc_processor/coders/signed_value_data.rs index fa1675e2..7fcd1488 100644 --- a/veilid-core/src/rpc_processor/coders/signed_value_data.rs +++ b/veilid-core/src/rpc_processor/coders/signed_value_data.rs @@ -9,10 +9,10 @@ pub fn decode_signed_value_data( let data = reader.get_data()?.to_vec(); rpc_ignore_missing_property!(reader, writer); let wr = reader.get_writer()?; - let writer = decode_key256(&wr); + let writer = decode_public_key(&wr)?; rpc_ignore_missing_property!(reader, signature); let sr = reader.get_signature()?; - let signature = decode_signature512(&sr); + let signature = decode_signature(&sr)?; Ok(SignedValueData::new( ValueData::new_with_seq(seq, data, writer).map_err(RPCError::protocol)?, @@ -27,8 +27,8 @@ pub fn encode_signed_value_data( builder.set_seq(signed_value_data.value_data().seq()); builder.set_data(signed_value_data.value_data().data()); let mut wb = builder.reborrow().init_writer(); - encode_key256(signed_value_data.value_data().writer(), &mut wb); + encode_public_key(signed_value_data.value_data().ref_writer(), &mut wb); let mut sb = builder.reborrow().init_signature(); - encode_signature512(signed_value_data.signature(), &mut sb); + encode_signature(signed_value_data.signature(), &mut sb); Ok(()) } diff --git a/veilid-core/src/rpc_processor/coders/signed_value_descriptor.rs b/veilid-core/src/rpc_processor/coders/signed_value_descriptor.rs index d62b257b..3f530384 100644 --- a/veilid-core/src/rpc_processor/coders/signed_value_descriptor.rs +++ b/veilid-core/src/rpc_processor/coders/signed_value_descriptor.rs @@ -6,12 +6,12 @@ pub fn decode_signed_value_descriptor( ) -> Result { rpc_ignore_missing_property!(reader, owner); let or = reader.get_owner()?; - let owner = decode_key256(&or); + let owner = decode_public_key(&or)?; rpc_ignore_missing_property!(reader, schema_data); let schema_data = reader.get_schema_data()?.to_vec(); rpc_ignore_missing_property!(reader, signature); let sr = reader.get_signature()?; - let signature = decode_signature512(&sr); + let signature = decode_signature(&sr)?; Ok(SignedValueDescriptor::new(owner, schema_data, signature)) } @@ -20,9 +20,9 @@ pub fn encode_signed_value_descriptor( builder: &mut veilid_capnp::signed_value_descriptor::Builder, ) -> Result<(), RPCError> { let mut ob = builder.reborrow().init_owner(); - encode_key256(signed_value_descriptor.owner(), &mut ob); + encode_public_key(signed_value_descriptor.ref_owner(), &mut ob); builder.set_schema_data(signed_value_descriptor.schema_data()); let mut sb = builder.reborrow().init_signature(); - encode_signature512(signed_value_descriptor.signature(), &mut sb); + encode_signature(signed_value_descriptor.ref_signature(), &mut sb); Ok(()) } diff --git a/veilid-core/src/rpc_processor/coders/typed_key.rs b/veilid-core/src/rpc_processor/coders/typed_key.rs deleted file mode 100644 index 8b9c0578..00000000 --- a/veilid-core/src/rpc_processor/coders/typed_key.rs +++ /dev/null @@ -1,62 +0,0 @@ -use super::*; - -pub fn decode_typed_public_key( - reader: &veilid_capnp::typed_key::Reader, -) -> Result { - rpc_ignore_missing_property!(reader, key); - let key_reader = reader.get_key()?; - let kind = reader.get_kind(); - - Ok(PublicKey::new( - CryptoKind::from(kind.to_be_bytes()), - decode_key256(&key_reader), - )) -} - -pub fn encode_typed_public_key( - typed_key: &PublicKey, - builder: &mut veilid_capnp::typed_key::Builder, -) { - builder.set_kind(u32::from_be_bytes(typed_key.kind.0)); - let mut key_builder = builder.reborrow().init_key(); - encode_key256(&typed_key.value, &mut key_builder); -} - -pub fn decode_typed_node_id(reader: &veilid_capnp::typed_key::Reader) -> Result { - rpc_ignore_missing_property!(reader, key); - let key_reader = reader.get_key()?; - let kind = reader.get_kind(); - - Ok(NodeId::new( - CryptoKind::from(kind.to_be_bytes()), - BareNodeId::new(decode_key256(&key_reader).bytes), - )) -} - -pub fn encode_typed_node_id(typed_key: &NodeId, builder: &mut veilid_capnp::typed_key::Builder) { - builder.set_kind(u32::from_be_bytes(typed_key.kind.0)); - let mut key_builder = builder.reborrow().init_key(); - encode_key256(&BarePublicKey::new(typed_key.value.bytes), &mut key_builder); -} - -pub fn decode_typed_record_key( - reader: &veilid_capnp::typed_key::Reader, -) -> Result { - rpc_ignore_missing_property!(reader, key); - let key_reader = reader.get_key()?; - let kind = reader.get_kind(); - - Ok(RecordKey::new( - CryptoKind::from(kind.to_be_bytes()), - BareRecordKey::new(decode_key256(&key_reader).bytes), - )) -} - -pub fn encode_typed_record_key( - typed_key: &RecordKey, - builder: &mut veilid_capnp::typed_key::Builder, -) { - builder.set_kind(u32::from_be_bytes(typed_key.kind.0)); - let mut key_builder = builder.reborrow().init_key(); - encode_key256(&BarePublicKey::new(typed_key.value.bytes), &mut key_builder); -} diff --git a/veilid-core/src/rpc_processor/coders/typed_signature.rs b/veilid-core/src/rpc_processor/coders/typed_signature.rs deleted file mode 100644 index 0a8acb16..00000000 --- a/veilid-core/src/rpc_processor/coders/typed_signature.rs +++ /dev/null @@ -1,23 +0,0 @@ -use super::*; - -pub fn decode_typed_signature( - reader: &veilid_capnp::typed_signature::Reader, -) -> Result { - rpc_ignore_missing_property!(reader, signature); - let sig_reader = reader.get_signature()?; - let kind = reader.get_kind(); - - Ok(Signature::new( - CryptoKind::from(kind.to_be_bytes()), - decode_signature512(&sig_reader), - )) -} - -pub fn encode_typed_signature( - typed_signature: &Signature, - builder: &mut veilid_capnp::typed_signature::Builder, -) { - builder.set_kind(u32::from_be_bytes(typed_signature.kind.0)); - let mut sig_builder = builder.reborrow().init_signature(); - encode_signature512(&typed_signature.value, &mut sig_builder); -} diff --git a/veilid-core/src/rpc_processor/destination.rs b/veilid-core/src/rpc_processor/destination.rs index b7b00a3e..6db7093e 100644 --- a/veilid-core/src/rpc_processor/destination.rs +++ b/veilid-core/src/rpc_processor/destination.rs @@ -130,18 +130,20 @@ impl Destination { Destination::Direct { node, safety_selection: _, - } => Ok(Target::BareNodeId( - node.best_node_id() - .ok_or_else(|| RPCError::protocol("no supported node id"))?, - )), + } => { + Ok(Target::NodeId(node.best_node_id().ok_or_else(|| { + RPCError::protocol("no supported node id") + })?)) + } Destination::Relay { relay: _, node, safety_selection: _, - } => Ok(Target::BareNodeId( - node.best_node_id() - .ok_or_else(|| RPCError::protocol("no supported node id"))?, - )), + } => { + Ok(Target::NodeId(node.best_node_id().ok_or_else(|| { + RPCError::protocol("no supported node id") + })?)) + } Destination::PrivateRoute { private_route, safety_selection: _, @@ -152,7 +154,7 @@ impl Destination { .add_remote_private_route(private_route.clone()) .map_err(RPCError::protocol)?; - Ok(Target::PrivateRoute(route_id)) + Ok(Target::RouteId(route_id)) } } } @@ -289,9 +291,9 @@ impl RPCProcessor { safety_selection: SafetySelection, ) -> Result { match target { - Target::BareNodeId(node_id) => { + Target::NodeId(node_id) => { // Resolve node - let nr = match self.resolve_node(node_id, safety_selection).await? { + let nr = match self.resolve_node(node_id, safety_selection.clone()).await? { Some(nr) => nr, None => { return Err(RPCError::network("could not resolve node id")); @@ -305,7 +307,7 @@ impl RPCProcessor { safety_selection, }) } - Target::PrivateRoute(rsid) => { + Target::RouteId(rsid) => { // Get remote private route let Some(private_route) = self .routing_table() @@ -345,7 +347,7 @@ impl RPCProcessor { let crypto_kind = target .best_node_id() .ok_or_else(|| RPCError::protocol("no supported node id"))? - .kind; + .kind(); let pr_key = network_result_try!(rss .get_private_route_for_safety_spec( crypto_kind, @@ -376,7 +378,7 @@ impl RPCProcessor { let crypto_kind = target .best_node_id() .ok_or_else(|| RPCError::protocol("no supported node id"))? - .kind; + .kind(); let mut avoid_nodes = relay.node_ids(); avoid_nodes.add_all(&target.node_ids()); @@ -402,7 +404,7 @@ impl RPCProcessor { )); }; - let crypto_kind = private_route.public_key.kind; + let crypto_kind = private_route.public_key.kind(); match safety_selection { SafetySelection::Unsafe(_) => { @@ -418,10 +420,10 @@ impl RPCProcessor { // Determine if we can use optimized nodeinfo let route_node = if rss.has_remote_private_route_seen_our_node_info( - &private_route.public_key.value, + private_route.public_key.ref_value(), &published_peer_info, ) { - RouteNode::BareNodeId(routing_table.node_id(crypto_kind).value) + RouteNode::NodeId(routing_table.node_id(crypto_kind)) } else { RouteNode::PeerInfo(published_peer_info) }; @@ -438,12 +440,12 @@ impl RPCProcessor { // Check for loopback test let opt_private_route_id = - rss.get_route_id_for_key(&private_route.public_key.value); + rss.get_route_id_for_key(private_route.public_key.ref_value()); let pr_key = if opt_private_route_id.is_some() && safety_spec.preferred_route == opt_private_route_id { // Private route is also safety route during loopback test - private_route.public_key.value + private_route.public_key.value() } else { // Get the private route to respond to that matches the safety route spec we sent the request with network_result_try!(rss @@ -519,7 +521,7 @@ impl RPCProcessor { // If this was received over our private route, it's okay to respond to a private route via our safety route NetworkResult::value(Destination::private_route( pr.clone(), - SafetySelection::Safe(detail.safety_spec), + SafetySelection::Safe(detail.safety_spec.clone()), )) } } diff --git a/veilid-core/src/rpc_processor/fanout/fanout_call.rs b/veilid-core/src/rpc_processor/fanout/fanout_call.rs index af872eef..4ae018aa 100644 --- a/veilid-core/src/rpc_processor/fanout/fanout_call.rs +++ b/veilid-core/src/rpc_processor/fanout/fanout_call.rs @@ -400,7 +400,7 @@ impl<'a> FanoutCall<'a> { self.routing_table .find_preferred_closest_nodes( self.node_count, - self.hash_coordinate, + self.hash_coordinate.clone(), filters, transform, ) @@ -415,7 +415,7 @@ impl<'a> FanoutCall<'a> { pub async fn run(&self, init_fanout_queue: Vec) -> Result { // Create context for this run let crypto = self.routing_table.crypto(); - let Some(vcrypto) = crypto.get(self.hash_coordinate.kind) else { + let Some(vcrypto) = crypto.get(self.hash_coordinate.kind()) else { return Err(RPCError::internal( "should not try this on crypto we don't support", )); @@ -425,12 +425,12 @@ impl<'a> FanoutCall<'a> { b_key: &CryptoTyped| -> core::cmp::Ordering { let da = vcrypto.distance( - &BareHashDigest::from(a_key.value), - &self.hash_coordinate.value, + &BareHashDigest::from(a_key.value()), + self.hash_coordinate.ref_value(), ); let db = vcrypto.distance( - &BareHashDigest::from(b_key.value), - &self.hash_coordinate.value, + &BareHashDigest::from(b_key.value()), + self.hash_coordinate.ref_value(), ); da.cmp(&db) }, @@ -438,7 +438,7 @@ impl<'a> FanoutCall<'a> { let context = Arc::new(Mutex::new(FanoutContext { fanout_queue: FanoutQueue::new( self.routing_table.registry(), - self.hash_coordinate.kind, + self.hash_coordinate.kind(), node_sort, self.consensus_count, ), diff --git a/veilid-core/src/rpc_processor/fanout/fanout_queue.rs b/veilid-core/src/rpc_processor/fanout/fanout_queue.rs index 47c66915..6b5e88d7 100644 --- a/veilid-core/src/rpc_processor/fanout/fanout_queue.rs +++ b/veilid-core/src/rpc_processor/fanout/fanout_queue.rs @@ -123,7 +123,7 @@ impl<'a> FanoutQueue<'a> { } // Add the new node self.nodes.insert( - key, + key.clone(), FanoutNode { node_ref: node_ref.clone(), status: FanoutNodeStatus::Queued, diff --git a/veilid-core/src/rpc_processor/message_header.rs b/veilid-core/src/rpc_processor/message_header.rs index f7457aaf..99006a91 100644 --- a/veilid-core/src/rpc_processor/message_header.rs +++ b/veilid-core/src/rpc_processor/message_header.rs @@ -74,9 +74,9 @@ impl MessageHeader { } pub fn direct_sender_node_id(&self) -> NodeId { match &self.detail { - RPCMessageHeaderDetail::Direct(d) => d.envelope.get_sender_typed_id(), - RPCMessageHeaderDetail::SafetyRouted(s) => s.direct.envelope.get_sender_typed_id(), - RPCMessageHeaderDetail::PrivateRouted(p) => p.direct.envelope.get_sender_typed_id(), + RPCMessageHeaderDetail::Direct(d) => d.envelope.get_sender_id(), + RPCMessageHeaderDetail::SafetyRouted(s) => s.direct.envelope.get_sender_id(), + RPCMessageHeaderDetail::PrivateRouted(p) => p.direct.envelope.get_sender_id(), } } } diff --git a/veilid-core/src/rpc_processor/mod.rs b/veilid-core/src/rpc_processor/mod.rs index 70bff655..471f4cb6 100644 --- a/veilid-core/src/rpc_processor/mod.rs +++ b/veilid-core/src/rpc_processor/mod.rs @@ -41,8 +41,8 @@ mod rpc_start_tunnel; pub(crate) use answer::*; pub(crate) use coders::{ - builder_to_vec, decode_private_route, encode_node_info, encode_private_route, encode_route_hop, - encode_signed_direct_node_info, encode_typed_node_id, RPCDecodeContext, + builder_to_vec, decode_private_route, encode_node_id, encode_node_info, encode_private_route, + encode_route_hop, encode_signed_direct_node_info, RPCDecodeContext, MAX_INSPECT_VALUE_A_SEQS_LEN, }; pub(crate) use destination::*; @@ -146,7 +146,6 @@ pub(crate) struct RPCProcessor { timeout_us: TimestampDuration, queue_size: u32, concurrency: u32, - max_route_hop_count: usize, waiting_rpc_table: OperationWaiter>, waiting_app_call_table: OperationWaiter, ()>, startup_context: RPCProcessorStartupContext, @@ -172,7 +171,7 @@ impl RPCProcessor { startup_context: RPCProcessorStartupContext, ) -> Self { // make local copy of node id for easy access - let (concurrency, queue_size, max_route_hop_count, timeout_us) = { + let (concurrency, queue_size, timeout_us) = { let config = registry.config(); let c = config.get(); @@ -180,7 +179,6 @@ impl RPCProcessor { let mut concurrency = c.network.rpc.concurrency; let queue_size = c.network.rpc.queue_size; let timeout_us = TimestampDuration::new(ms_to_us(c.network.rpc.timeout_ms)); - let max_route_hop_count = c.network.rpc.max_route_hop_count as usize; if concurrency == 0 { concurrency = get_concurrency(); if concurrency == 0 { @@ -190,7 +188,7 @@ impl RPCProcessor { // Default RPC concurrency is the number of CPUs * 16 rpc workers per core, as a single worker takes about 1% CPU when relaying and 16% is reasonable for baseline plus relay concurrency *= RPC_WORKERS_PER_CORE; } - (concurrency, queue_size, max_route_hop_count, timeout_us) + (concurrency, queue_size, timeout_us) }; Self { @@ -199,7 +197,6 @@ impl RPCProcessor { timeout_us, queue_size, concurrency, - max_route_hop_count, waiting_rpc_table: OperationWaiter::new(), waiting_app_call_table: OperationWaiter::new(), startup_context, @@ -374,7 +371,7 @@ impl RPCProcessor { let routing_domain = RoutingDomain::PublicInternet; // Ignore own node - if routing_table.matches_own_node_id(&[node_id]) { + if routing_table.matches_own_node_id(&[node_id.clone()]) { return TimeoutOr::Value(Err(RPCError::network("can't search for own node id"))); } @@ -382,14 +379,17 @@ impl RPCProcessor { let result = Arc::new(Mutex::new(Option::::None)); let registry = self.registry(); + let node_id2 = node_id.clone(); let call_routine = Arc::new(move |next_node: NodeRef| { let registry = registry.clone(); + let node_id = node_id2.clone(); + let safety_selection = safety_selection.clone(); Box::pin(async move { let this = registry.rpc_processor(); match this .rpc_call_find_node( Destination::direct(next_node.routing_domain_filtered(routing_domain)) - .with_safety(safety_selection), + .with_safety(safety_selection.clone()), node_id, vec![], ) @@ -416,8 +416,9 @@ impl RPCProcessor { // Routine to call to check if we're done at each step let result2 = result.clone(); + let node_id2 = node_id.clone(); let check_done = Arc::new(move |_: &FanoutResult| -> bool { - let Ok(Some(nr)) = routing_table.lookup_node_ref(node_id) else { + let Ok(Some(nr)) = routing_table.lookup_node_ref(node_id2.clone()) else { return false; }; @@ -483,7 +484,7 @@ impl RPCProcessor { // First see if we have the node in our routing table already let mut existing_nr = None; if let Some(nr) = routing_table - .lookup_node_ref(node_id) + .lookup_node_ref(node_id.clone()) .map_err(RPCError::internal)? { existing_nr = Some(nr.clone()); @@ -575,7 +576,7 @@ impl RPCProcessor { let node_id = self .routing_table() .node_id(sr.direct.envelope.get_crypto_kind()); - if node_id.value != reply_private_route.into() { + if node_id.value() != reply_private_route.into() { return Err(RPCError::protocol( "should have received reply from safety route to a stub", )); @@ -611,8 +612,7 @@ impl RPCProcessor { // Get useful private route properties let pr_is_stub = remote_private_route.is_stub(); - let pr_hop_count = remote_private_route.hop_count; - let pr_pubkey = remote_private_route.public_key.value; + let pr_pubkey = remote_private_route.public_key.value(); let crypto_kind = remote_private_route.crypto_kind(); let Some(vcrypto) = crypto.get(crypto_kind) else { return Err(RPCError::internal( @@ -621,11 +621,12 @@ impl RPCProcessor { }; // Compile the safety route with the private route + let sequencing = safety_selection.get_sequencing(); let compiled_route: CompiledRoute = network_result_try!(rss .compile_safety_route(safety_selection, remote_private_route) .to_rpc_network_result()?); let sr_is_stub = compiled_route.safety_route.is_stub(); - let sr_pubkey = compiled_route.safety_route.public_key.value; + let sr_pubkey = compiled_route.safety_route.public_key.value(); // Encrypt routed operation // Xmsg + ENC(Xmsg, DH(PKapr, SKbsr)) @@ -638,15 +639,9 @@ impl RPCProcessor { .map_err(RPCError::map_internal("encryption failed"))?; // Make the routed operation - let operation = RoutedOperation::new( - routing_domain, - safety_selection.get_sequencing(), - nonce, - enc_msg_data, - ); + let operation = RoutedOperation::new(routing_domain, sequencing, nonce, enc_msg_data); // Prepare route operation - let sr_hop_count = compiled_route.safety_route.hop_count; let route_operation = RPCOperationRoute::new(compiled_route.safety_route, operation); let ssni_route = self.get_sender_peer_info(&Destination::direct(compiled_route.first_hop.clone())); @@ -661,14 +656,10 @@ impl RPCProcessor { operation.encode(&mut route_operation)?; let out_message = builder_to_vec(route_msg)?; - // Get the first hop this is going to - let out_hop_count = (1 + sr_hop_count + pr_hop_count) as usize; - let out = RenderedOperation { message: out_message, destination_node_ref: compiled_route.first_hop.unfiltered(), node_ref: compiled_route.first_hop, - hop_count: out_hop_count, safety_route: if sr_is_stub { None } else { Some(sr_pubkey) }, remote_private_route: if pr_is_stub { None } else { Some(pr_pubkey) }, reply_private_route, @@ -701,7 +692,7 @@ impl RPCProcessor { let reply_private_route = match operation.kind() { RPCOperationKind::Question(q) => match q.respond_to() { RespondTo::Sender => None, - RespondTo::PrivateRoute(pr) => Some(pr.public_key.value), + RespondTo::PrivateRoute(pr) => Some(pr.public_key.value()), }, RPCOperationKind::Statement(_) | RPCOperationKind::Answer(_) => None, }; @@ -710,12 +701,12 @@ impl RPCProcessor { match dest { Destination::Direct { node: ref node_ref, - safety_selection, + ref safety_selection, } | Destination::Relay { relay: ref node_ref, node: _, - safety_selection, + ref safety_selection, } => { // Send to a node without a private route // -------------------------------------- @@ -737,8 +728,8 @@ impl RPCProcessor { SafetySelection::Unsafe(sequencing) => { // Apply safety selection sequencing requirement if it is more strict than the node_ref's sequencing requirement let mut node_ref = node_ref.clone(); - if sequencing > node_ref.sequencing() { - node_ref.set_sequencing(sequencing) + if *sequencing > node_ref.sequencing() { + node_ref.set_sequencing(*sequencing) } // Reply private route should be None here, even for questions @@ -750,7 +741,6 @@ impl RPCProcessor { message, destination_node_ref, node_ref, - hop_count: 1, safety_route: None, remote_private_route: None, reply_private_route: None, @@ -786,7 +776,7 @@ impl RPCProcessor { // Wrap with safety route out = self.wrap_with_route( routing_domain, - safety_selection, + safety_selection.clone(), private_route, reply_private_route, message, @@ -1142,15 +1132,24 @@ impl RPCProcessor { message, destination_node_ref, node_ref, - hop_count, safety_route, remote_private_route, reply_private_route, } = network_result_try!(self.render_operation(dest.clone(), &operation)?); // Calculate answer timeout - // Timeout is number of hops times the timeout per hop - let timeout_us = self.timeout_us * (hop_count as u64); + // + // Maximum timeout is number of hops times the timeout per hop, but the hop + // count is not known for routes. + // + // Practical timeout for routed operations is twice the node-to-node maximum timeout + // or performance suffers. If there are too many timeouts on a route, the route + // should fail to test, and a newer and hopefully faster route will be allocated. + let timeout_us = if safety_route.is_some() || remote_private_route.is_some() { + self.timeout_us * 2u64 + } else { + self.timeout_us + }; // Set up op id eventual let handle = self.waiting_rpc_table.add_op_waiter(op_id, context); @@ -1174,8 +1173,8 @@ impl RPCProcessor { RPCKind::Question, send_ts, node_ref.unfiltered(), - safety_route, - remote_private_route, + safety_route.clone(), + remote_private_route.clone(), ); RPCError::network(e) })?; @@ -1195,8 +1194,8 @@ impl RPCProcessor { send_ts, bytes, node_ref.unfiltered(), - safety_route, - remote_private_route, + safety_route.clone(), + remote_private_route.clone(), send_data_result.is_ordered(), ); @@ -1241,7 +1240,6 @@ impl RPCProcessor { message, destination_node_ref, node_ref, - hop_count: _, safety_route, remote_private_route, reply_private_route: _, @@ -1266,8 +1264,8 @@ impl RPCProcessor { RPCKind::Statement, send_ts, node_ref.unfiltered(), - safety_route, - remote_private_route, + safety_route.clone(), + remote_private_route.clone(), ); RPCError::network(e) })?; @@ -1276,7 +1274,7 @@ impl RPCProcessor { let send_ts = Timestamp::now(); let send_data_result = network_result_value_or_log!(self res => [ format!(": node_ref={}, destination_node_ref={}, message.len={}", node_ref, destination_node_ref, message_len) ] { // If we couldn't send we're still cleaning up - self.record_send_failure(RPCKind::Statement, send_ts, node_ref.unfiltered(), safety_route, remote_private_route); + self.record_send_failure(RPCKind::Statement, send_ts, node_ref.unfiltered(), safety_route.clone(), remote_private_route.clone()); network_result_raise!(res); } ); @@ -1315,7 +1313,6 @@ impl RPCProcessor { message, destination_node_ref, node_ref, - hop_count: _, safety_route, remote_private_route, reply_private_route: _, @@ -1340,8 +1337,8 @@ impl RPCProcessor { RPCKind::Answer, send_ts, node_ref.unfiltered(), - safety_route, - remote_private_route, + safety_route.clone(), + remote_private_route.clone(), ); RPCError::network(e) })?; @@ -1350,7 +1347,7 @@ impl RPCProcessor { let send_ts = Timestamp::now(); let send_data_result = network_result_value_or_log!(self res => [ format!(": node_ref={}, destination_node_ref={}, message.len={}", node_ref, destination_node_ref, message_len) ] { // If we couldn't send we're still cleaning up - self.record_send_failure(RPCKind::Answer, send_ts, node_ref.unfiltered(), safety_route, remote_private_route); + self.record_send_failure(RPCKind::Answer, send_ts, node_ref.unfiltered(), safety_route.clone(), remote_private_route.clone()); network_result_raise!(res); } ); @@ -1427,7 +1424,7 @@ impl RPCProcessor { let msg = match &encoded_msg.header.detail { RPCMessageHeaderDetail::Direct(detail) => { // Get sender node id - let sender_node_id = detail.envelope.get_sender_typed_id(); + let sender_node_id = detail.envelope.get_sender_id(); // Decode and validate the RPC operation let decode_res = self.decode_rpc_operation(&encoded_msg); @@ -1464,7 +1461,7 @@ impl RPCProcessor { // Get the sender noderef, incorporating sender's peer info let sender_peer_info = operation.sender_peer_info(); let mut opt_sender_nr: Option = network_result_try!(self - .process_sender_peer_info(routing_domain, sender_node_id, &sender_peer_info)? => { + .process_sender_peer_info(routing_domain, sender_node_id.clone(), &sender_peer_info)? => { veilid_log!(self debug target:"network_result", "Sender PeerInfo: {:?}", sender_peer_info); veilid_log!(self debug target:"network_result", "From Operation: {:?}", operation.kind()); veilid_log!(self debug target:"network_result", "With Detail: {:?}", detail); diff --git a/veilid-core/src/rpc_processor/rendered_operation.rs b/veilid-core/src/rpc_processor/rendered_operation.rs index 090454dc..f217aec0 100644 --- a/veilid-core/src/rpc_processor/rendered_operation.rs +++ b/veilid-core/src/rpc_processor/rendered_operation.rs @@ -8,8 +8,6 @@ pub struct RenderedOperation { pub destination_node_ref: NodeRef, /// Node to send envelope to (may not be destination node in case of relay) pub node_ref: FilteredNodeRef, - /// Total safety + private route hop count + 1 hop for the initial send - pub hop_count: usize, /// The safety route used to send the message pub safety_route: Option, /// The private route used to send the message @@ -24,7 +22,6 @@ impl fmt::Debug for RenderedOperation { .field("message(len)", &self.message.len()) .field("destination_node_ref", &self.destination_node_ref) .field("node_ref", &self.node_ref) - .field("hop_count", &self.hop_count) .field("safety_route", &self.safety_route) .field("remote_private_route", &self.remote_private_route) .field("reply_private_route", &self.reply_private_route) diff --git a/veilid-core/src/rpc_processor/rpc_app_call.rs b/veilid-core/src/rpc_processor/rpc_app_call.rs index 7f0403a8..d880749f 100644 --- a/veilid-core/src/rpc_processor/rpc_app_call.rs +++ b/veilid-core/src/rpc_processor/rpc_app_call.rs @@ -29,7 +29,7 @@ impl RPCProcessor { let waitable_reply = network_result_try!(self.question(dest, question, None).await?); // Keep the reply private route that was used to return with the answer - let reply_private_route = waitable_reply.context.reply_private_route; + let reply_private_route = waitable_reply.context.reply_private_route.clone(); // Wait for reply let (msg, latency) = match self.wait_for_reply(waitable_reply, debug_string).await? { @@ -84,7 +84,7 @@ impl RPCProcessor { // Get the private route this came over let opt_pr_pubkey = match &msg.header.detail { RPCMessageHeaderDetail::Direct(_) | RPCMessageHeaderDetail::SafetyRouted(_) => None, - RPCMessageHeaderDetail::PrivateRouted(pr) => Some(pr.private_route), + RPCMessageHeaderDetail::PrivateRouted(pr) => Some(pr.private_route.clone()), }; let route_id = if let Some(pr_pubkey) = opt_pr_pubkey { let rss = routing_table.route_spec_store(); diff --git a/veilid-core/src/rpc_processor/rpc_app_message.rs b/veilid-core/src/rpc_processor/rpc_app_message.rs index 69abc6e9..7b19d810 100644 --- a/veilid-core/src/rpc_processor/rpc_app_message.rs +++ b/veilid-core/src/rpc_processor/rpc_app_message.rs @@ -47,7 +47,7 @@ impl RPCProcessor { // Get the private route this came over let opt_pr_pubkey = match &msg.header.detail { RPCMessageHeaderDetail::Direct(_) | RPCMessageHeaderDetail::SafetyRouted(_) => None, - RPCMessageHeaderDetail::PrivateRouted(pr) => Some(pr.private_route), + RPCMessageHeaderDetail::PrivateRouted(pr) => Some(pr.private_route.clone()), }; let route_id = if let Some(pr_pubkey) = opt_pr_pubkey { let rss = routing_table.route_spec_store(); diff --git a/veilid-core/src/rpc_processor/rpc_find_node.rs b/veilid-core/src/rpc_processor/rpc_find_node.rs index 3e5287cd..5989897d 100644 --- a/veilid-core/src/rpc_processor/rpc_find_node.rs +++ b/veilid-core/src/rpc_processor/rpc_find_node.rs @@ -36,7 +36,7 @@ impl RPCProcessor { } let find_node_q_detail = RPCQuestionDetail::FindNodeQ(Box::new( - RPCOperationFindNodeQ::new(node_id, capabilities.clone()), + RPCOperationFindNodeQ::new(node_id.clone(), capabilities.clone()), )); let find_node_q = RPCQuestion::new( network_result_try!(self.get_destination_respond_to(&dest)?), @@ -49,7 +49,7 @@ impl RPCProcessor { let waitable_reply = network_result_try!(self.question(dest, find_node_q, None).await?); // Keep the reply private route that was used to return with the answer - let reply_private_route = waitable_reply.context.reply_private_route; + let reply_private_route = waitable_reply.context.reply_private_route.clone(); // Wait for reply let (msg, latency) = match self.wait_for_reply(waitable_reply, debug_string).await? { @@ -120,7 +120,7 @@ impl RPCProcessor { let closest_nodes = network_result_try!(routing_table.find_preferred_closest_peers( routing_domain, - node_id, + &node_id.clone().into(), &capabilities )); diff --git a/veilid-core/src/rpc_processor/rpc_get_value.rs b/veilid-core/src/rpc_processor/rpc_get_value.rs index f5f90a58..9a59c076 100644 --- a/veilid-core/src/rpc_processor/rpc_get_value.rs +++ b/veilid-core/src/rpc_processor/rpc_get_value.rs @@ -28,7 +28,7 @@ impl RPCProcessor { pub async fn rpc_call_get_value( &self, dest: Destination, - key: RecordKey, + record_key: RecordKey, subkey: ValueSubkey, last_descriptor: Option, ) -> RPCNetworkResult> { @@ -48,16 +48,16 @@ impl RPCProcessor { // Get the target node id let crypto = self.crypto(); - let Some(vcrypto) = crypto.get(key.kind) else { + let Some(vcrypto) = crypto.get(record_key.kind()) else { return Err(RPCError::internal("unsupported cryptosystem")); }; - let Some(target_node_id) = target_node_ids.get(key.kind) else { + let Some(target_node_id) = target_node_ids.get(record_key.kind()) else { return Err(RPCError::internal("No node id for crypto kind")); }; let debug_string = format!( "OUT ==> GetValueQ({} #{}{}) => {}", - key, + record_key, subkey, if last_descriptor.is_some() { " +lastdesc" @@ -68,7 +68,8 @@ impl RPCProcessor { ); // Send the getvalue question - let get_value_q = RPCOperationGetValueQ::new(key, subkey, last_descriptor.is_none()); + let get_value_q = + RPCOperationGetValueQ::new(record_key.clone(), subkey, last_descriptor.is_none()); let question = RPCQuestion::new( network_result_try!(self.get_destination_respond_to(&dest)?), RPCQuestionDetail::GetValueQ(Box::new(get_value_q)), @@ -88,7 +89,7 @@ impl RPCProcessor { ); // Keep the reply private route that was used to return with the answer - let reply_private_route = waitable_reply.context.reply_private_route; + let reply_private_route = waitable_reply.context.reply_private_route.clone(); // Wait for reply let (msg, latency) = match self.wait_for_reply(waitable_reply, debug_string).await? { @@ -122,7 +123,7 @@ impl RPCProcessor { let debug_string_answer = format!( "OUT <== GetValueA({} #{}{}{} peers={}) <= {}", - key, + record_key, subkey, debug_string_value, if descriptor.is_some() { " +desc" } else { "" }, @@ -134,7 +135,7 @@ impl RPCProcessor { let peer_ids: Vec = peers .iter() - .filter_map(|p| p.node_ids().get(key.kind).map(|k| k.to_string())) + .filter_map(|p| p.node_ids().get(record_key.kind()).map(|k| k.to_string())) .collect(); veilid_log!(self debug target: "dht", "Peers: {:#?}", peer_ids); } @@ -142,8 +143,8 @@ impl RPCProcessor { // 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.into(), - key.into(), + &target_node_id.clone().into(), + &record_key.clone().into(), &peers, ) { Ok(v) => v, @@ -219,17 +220,20 @@ impl RPCProcessor { }; // Destructure - let (key, subkey, want_descriptor) = get_value_q.destructure(); + let (record_key, subkey, want_descriptor) = get_value_q.destructure(); // Get the nodes that we know about that are closer to the the key than our own node - let closer_to_key_peers = network_result_try!( - routing_table.find_preferred_peers_closer_to_key(routing_domain, key, vec![CAP_DHT]) - ); + let closer_to_key_peers = network_result_try!(routing_table + .find_preferred_peers_closer_to_key( + routing_domain, + &record_key.clone().into(), + vec![CAP_DHT] + )); if debug_target_enabled!("dht") { let debug_string = format!( "IN <=== GetValueQ({} #{}{}) <== {}", - key, + record_key, subkey, if want_descriptor { " +wantdesc" } else { "" }, msg.header.direct_sender_node_id() @@ -252,7 +256,7 @@ impl RPCProcessor { // See if we have this record ourselves let storage_manager = self.storage_manager(); let get_result = network_result_try!(storage_manager - .inbound_get_value(key, subkey, want_descriptor) + .inbound_get_value(record_key.clone(), subkey, want_descriptor) .await .map_err(RPCError::internal)?); (get_result.opt_value, get_result.opt_descriptor) @@ -273,7 +277,7 @@ impl RPCProcessor { let debug_string_answer = format!( "IN ===> GetValueA({} #{}{}{} peers={}) ==> {}", - key, + record_key, subkey, debug_string_value, if get_result_descriptor.is_some() { diff --git a/veilid-core/src/rpc_processor/rpc_inspect_value.rs b/veilid-core/src/rpc_processor/rpc_inspect_value.rs index ae6d7fbd..408f1926 100644 --- a/veilid-core/src/rpc_processor/rpc_inspect_value.rs +++ b/veilid-core/src/rpc_processor/rpc_inspect_value.rs @@ -30,7 +30,7 @@ impl RPCProcessor { pub async fn rpc_call_inspect_value( &self, dest: Destination, - key: RecordKey, + record_key: RecordKey, subkeys: ValueSubkeyRangeSet, last_descriptor: Option, ) -> RPCNetworkResult> { @@ -50,16 +50,16 @@ impl RPCProcessor { // Get the target node id let crypto = self.crypto(); - let Some(vcrypto) = crypto.get(key.kind) else { + let Some(vcrypto) = crypto.get(record_key.kind()) else { return Err(RPCError::internal("unsupported cryptosystem")); }; - let Some(target_node_id) = target_node_ids.get(key.kind) else { + let Some(target_node_id) = target_node_ids.get(record_key.kind()) else { return Err(RPCError::internal("No node id for crypto kind")); }; let debug_string = format!( "OUT ==> InspectValueQ({} #{}{}) => {}", - key, + record_key, &subkeys, if last_descriptor.is_some() { " +lastdesc" @@ -70,8 +70,11 @@ impl RPCProcessor { ); // Send the inspectvalue question - let inspect_value_q = - RPCOperationInspectValueQ::new(key, subkeys.clone(), last_descriptor.is_none())?; + let inspect_value_q = RPCOperationInspectValueQ::new( + record_key.clone(), + 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)), @@ -91,7 +94,7 @@ impl RPCProcessor { ); // Keep the reply private route that was used to return with the answer - let reply_private_route = waitable_reply.context.reply_private_route; + let reply_private_route = waitable_reply.context.reply_private_route.clone(); // Wait for reply let (msg, latency) = match self.wait_for_reply(waitable_reply, debug_string).await? { @@ -118,7 +121,7 @@ impl RPCProcessor { if debug_target_enabled!("dht") { let debug_string_answer = format!( "OUT <== InspectValueA({} {} peers={}) <= {} seqs:\n{}", - key, + record_key, if descriptor.is_some() { " +desc" } else { "" }, peers.len(), dest, @@ -129,7 +132,7 @@ impl RPCProcessor { let peer_ids: Vec = peers .iter() - .filter_map(|p| p.node_ids().get(key.kind).map(|k| k.to_string())) + .filter_map(|p| p.node_ids().get(record_key.kind()).map(|k| k.to_string())) .collect(); veilid_log!(self debug target: "dht", "Peers: {:#?}", peer_ids); } @@ -137,8 +140,8 @@ impl RPCProcessor { // 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.into(), - key.into(), + &target_node_id.clone().into(), + &record_key.clone().into(), &peers, ) { Ok(v) => v, @@ -205,17 +208,20 @@ impl RPCProcessor { }; // Destructure - let (key, subkeys, want_descriptor) = inspect_value_q.destructure(); + let (record_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 closer_to_key_peers = network_result_try!( - routing_table.find_preferred_peers_closer_to_key(routing_domain, key, vec![CAP_DHT]) - ); + let closer_to_key_peers = network_result_try!(routing_table + .find_preferred_peers_closer_to_key( + routing_domain, + &record_key.clone().into(), + vec![CAP_DHT] + )); if debug_target_enabled!("dht") { let debug_string = format!( "IN <=== InspectValueQ({} {}{}) <== {}", - key, + record_key, subkeys, if want_descriptor { " +wantdesc" } else { "" }, msg.header.direct_sender_node_id() @@ -239,7 +245,7 @@ impl RPCProcessor { // 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) + .inbound_inspect_value(record_key.clone(), subkeys, want_descriptor) .await .map_err(RPCError::internal)?); ( @@ -255,7 +261,7 @@ impl RPCProcessor { if debug_target_enabled!("dht") { let debug_string_answer = format!( "IN ===> InspectValueA({} {:?}{} peers={}) ==> {}", - key, + record_key, inspect_result_seqs, if inspect_result_descriptor.is_some() { " +desc" diff --git a/veilid-core/src/rpc_processor/rpc_route.rs b/veilid-core/src/rpc_processor/rpc_route.rs index 47f9e9c6..52ef485c 100644 --- a/veilid-core/src/rpc_processor/rpc_route.rs +++ b/veilid-core/src/rpc_processor/rpc_route.rs @@ -10,32 +10,12 @@ impl RPCProcessor { route_hop: RouteHop, safety_route: SafetyRoute, ) -> RPCNetworkResult<()> { - // Make sure hop count makes sense - if safety_route.hop_count as usize > self.max_route_hop_count { - return Ok(NetworkResult::invalid_message( - "Safety route hop count too high to process", - )); - } - if safety_route.hop_count == 0 { - return Ok(NetworkResult::invalid_message( - "Safety route hop count should not be zero if there are more hops", - )); - } - if route_hop.next_hop.is_none() { - return Ok(NetworkResult::invalid_message( - "Safety route hop must have next hop", - )); - } - // Get next hop node ref let routing_table = self.routing_table(); - let Some(next_hop_nr) = route_hop - .node - .node_ref(&routing_table, safety_route.public_key.kind) - else { + let Some(next_hop_nr) = route_hop.node.node_ref(&routing_table) else { return Ok(NetworkResult::invalid_message(format!( "could not get route node hop ref: {}", - route_hop.node.describe(safety_route.public_key.kind) + route_hop.node.describe() ))); }; @@ -46,7 +26,6 @@ impl RPCProcessor { let next_hop_route = RPCOperationRoute::new( SafetyRoute { public_key: safety_route.public_key, - hop_count: safety_route.hop_count - 1, hops: SafetyRouteHops::Data(route_hop.next_hop.unwrap()), }, routed_operation, @@ -67,21 +46,12 @@ impl RPCProcessor { safety_route_public_key: PublicKey, next_private_route: PrivateRoute, ) -> RPCNetworkResult<()> { - // Make sure hop count makes sense - if next_private_route.hop_count as usize > self.max_route_hop_count { - return Ok(NetworkResult::invalid_message( - "Private route hop count too high to process", - )); - } - // Get next hop node ref let routing_table = self.routing_table(); - let Some(next_hop_nr) = - next_route_node.node_ref(&routing_table, safety_route_public_key.kind) - else { + let Some(next_hop_nr) = next_route_node.node_ref(&routing_table) else { return Ok(NetworkResult::invalid_message(format!( "could not get route node hop ref: {}", - next_route_node.describe(safety_route_public_key.kind) + next_route_node.describe() ))); }; @@ -92,7 +62,6 @@ impl RPCProcessor { let next_hop_route = RPCOperationRoute::new( SafetyRoute { public_key: safety_route_public_key, - hop_count: 0, hops: SafetyRouteHops::Private(next_private_route), }, routed_operation, @@ -122,8 +91,8 @@ impl RPCProcessor { // 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 Ok(dh_secret) = vcrypto.cached_dh(&remote_sr_pubkey.value, &node_id_secret) else { + .node_id_secret_key(remote_sr_pubkey.kind()); + let Ok(dh_secret) = vcrypto.cached_dh(remote_sr_pubkey.ref_value(), &node_id_secret) else { return Ok(NetworkResult::invalid_message( "dh failed for remote safety route for safety routed operation", )); @@ -146,7 +115,7 @@ impl RPCProcessor { // Pass message to RPC system self.enqueue_safety_routed_message( detail, - remote_sr_pubkey.value, + remote_sr_pubkey.value(), routed_operation.sequencing(), body, ) @@ -166,7 +135,7 @@ impl RPCProcessor { pr_pubkey: PublicKey, ) -> RPCNetworkResult<()> { // Get sender id of the peer with the crypto kind of the route - let Some(sender_id) = detail.sender_noderef.node_ids().get(pr_pubkey.kind) else { + let Some(sender_id) = detail.sender_noderef.node_ids().get(pr_pubkey.kind()) else { return Ok(NetworkResult::invalid_message( "route node doesnt have a required crypto kind for routed operation", )); @@ -176,16 +145,16 @@ impl RPCProcessor { // Ensure the route is validated, and construct a return safetyspec that matches the inbound preferences let routing_table = self.routing_table(); let rss = routing_table.route_spec_store(); - let preferred_route = rss.get_route_id_for_key(&pr_pubkey.value); + let preferred_route = rss.get_route_id_for_key(pr_pubkey.ref_value()); let Some((secret_key, safety_spec)) = rss.with_signature_validated_route( &pr_pubkey, routed_operation.signatures(), routed_operation.data(), - sender_id.value, + &sender_id, |rssd, rsd| { ( - rsd.secret_key, + rsd.secret_key.clone(), SafetySpec { preferred_route, hop_count: rssd.hop_count(), @@ -202,7 +171,7 @@ 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 Ok(dh_secret) = vcrypto.cached_dh(&remote_sr_pubkey.value, &secret_key) else { + let Ok(dh_secret) = vcrypto.cached_dh(remote_sr_pubkey.ref_value(), &secret_key) else { return Ok(NetworkResult::invalid_message( "dh failed for remote safety route for private routed operation", )); @@ -221,8 +190,8 @@ impl RPCProcessor { // Pass message to RPC system self.enqueue_private_routed_message( detail, - remote_sr_pubkey.value, - pr_pubkey.value, + remote_sr_pubkey.value(), + pr_pubkey.value(), safety_spec, body, ) @@ -242,7 +211,11 @@ impl RPCProcessor { ) -> RPCNetworkResult<()> { // If the private route public key is our node id, then this was sent via safety route to our node directly // so there will be no signatures to validate - if self.routing_table().node_ids().contains(&pr_pubkey.into()) { + if self + .routing_table() + .node_ids() + .contains(&pr_pubkey.clone().into()) + { // The private route was a stub self.process_safety_routed_operation( detail, @@ -291,13 +264,6 @@ impl RPCProcessor { &mut routed_operation )?); - // Ensure hop count > 0 - if private_route.hop_count == 0 { - return Ok(NetworkResult::invalid_message( - "route should not be at the end", - )); - } - // Make next PrivateRoute and pass it on return self .process_route_private_route_hop( @@ -306,7 +272,6 @@ impl RPCProcessor { sr_pubkey, PrivateRoute { public_key: private_route.public_key, - hop_count: private_route.hop_count - 1, hops: route_hop .next_hop .map(PrivateRouteHops::Data) @@ -336,7 +301,7 @@ impl RPCProcessor { ) -> RPCNetworkResult { // Get crypto kind let crypto = self.crypto(); - let crypto_kind = pr_pubkey.kind; + let crypto_kind = pr_pubkey.kind(); let Some(vcrypto) = crypto.get(crypto_kind) else { return Ok(NetworkResult::invalid_message( "private route hop data crypto is not supported", @@ -346,7 +311,7 @@ impl RPCProcessor { // Decrypt the blob with DEC(nonce, DH(the PR'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(&pr_pubkey.value, &node_id_secret) + .cached_dh(pr_pubkey.ref_value(), &node_id_secret) .map_err(RPCError::protocol)?; let dec_blob_data = match vcrypto.decrypt_aead( &route_hop_data.blob, @@ -381,13 +346,16 @@ impl RPCProcessor { if route_hop.next_hop.is_some() { let node_id = self.routing_table().node_id(crypto_kind); let node_id_secret = self.routing_table().node_id_secret_key(crypto_kind); - let sig = vcrypto - .sign( - &node_id.value.into(), - &node_id_secret, - routed_operation.data(), - ) - .map_err(RPCError::internal)?; + let sig = Signature::new( + vcrypto.kind(), + vcrypto + .sign( + &node_id.value().into(), + &node_id_secret, + routed_operation.data(), + ) + .map_err(RPCError::internal)?, + ); routed_operation.add_signature(sig); } @@ -452,7 +420,7 @@ impl RPCProcessor { // 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 Ok(dh_secret) = - vcrypto.cached_dh(&safety_route.public_key.value, &node_id_secret) + vcrypto.cached_dh(safety_route.public_key.ref_value(), &node_id_secret) else { return Ok(NetworkResult::invalid_message( "dh failed for safety route hop", @@ -583,13 +551,6 @@ impl RPCProcessor { &mut routed_operation )?); - // Ensure hop count > 0 - if private_route.hop_count == 0 { - return Ok(NetworkResult::invalid_message( - "route should not be at the end", - )); - } - // Make next PrivateRoute and pass it on network_result_try!( self.process_route_private_route_hop( @@ -598,7 +559,6 @@ impl RPCProcessor { safety_route.public_key, PrivateRoute { public_key: private_route.public_key, - hop_count: private_route.hop_count - 1, hops: route_hop .next_hop .map(PrivateRouteHops::Data) @@ -609,18 +569,6 @@ impl RPCProcessor { ); } PrivateRouteHops::Empty => { - // Ensure hop count == 0 - if private_route.hop_count != 0 { - return Ok(NetworkResult::invalid_message( - "route should be at the end", - )); - } - if safety_route.hop_count != 0 { - return Ok(NetworkResult::invalid_message( - "Safety hop count should be zero if switched to private route", - )); - } - // No hops left, time to process the routed operation network_result_try!(self.process_routed_operation( detail, diff --git a/veilid-core/src/rpc_processor/rpc_set_value.rs b/veilid-core/src/rpc_processor/rpc_set_value.rs index 0c64294c..74fe336b 100644 --- a/veilid-core/src/rpc_processor/rpc_set_value.rs +++ b/veilid-core/src/rpc_processor/rpc_set_value.rs @@ -30,7 +30,7 @@ impl RPCProcessor { pub async fn rpc_call_set_value( &self, dest: Destination, - key: RecordKey, + record_key: RecordKey, subkey: ValueSubkey, value: SignedValueData, descriptor: SignedValueDescriptor, @@ -52,16 +52,16 @@ impl RPCProcessor { // Get the target node id let crypto = self.crypto(); - let Some(vcrypto) = crypto.get(key.kind) else { + let Some(vcrypto) = crypto.get(record_key.kind()) else { return Err(RPCError::internal("unsupported cryptosystem")); }; - let Some(target_node_id) = target_node_ids.get(key.kind) else { + let Some(target_node_id) = target_node_ids.get(record_key.kind()) else { return Err(RPCError::internal("No node id for crypto kind")); }; let debug_string = format!( "OUT ==> SetValueQ({} #{} len={} seq={} writer={}{}) => {}", - key, + record_key, subkey, value.value_data().data().len(), value.value_data().seq(), @@ -72,7 +72,7 @@ impl RPCProcessor { // Send the setvalue question let set_value_q = RPCOperationSetValueQ::new( - key, + record_key.clone(), subkey, value, if send_descriptor { @@ -101,7 +101,7 @@ impl RPCProcessor { ); // Keep the reply private route that was used to return with the answer - let reply_private_route = waitable_reply.context.reply_private_route; + let reply_private_route = waitable_reply.context.reply_private_route.clone(); // Wait for reply let (msg, latency) = match self.wait_for_reply(waitable_reply, debug_string).await? { @@ -136,7 +136,7 @@ impl RPCProcessor { let debug_string_answer = format!( "OUT <== SetValueA({} #{}{}{} peers={}) <= {}", - key, + record_key, subkey, if set { " +set" } else { "" }, debug_string_value, @@ -148,7 +148,7 @@ impl RPCProcessor { let peer_ids: Vec = peers .iter() - .filter_map(|p| p.node_ids().get(key.kind).map(|k| k.to_string())) + .filter_map(|p| p.node_ids().get(record_key.kind()).map(|k| k.to_string())) .collect(); veilid_log!(self debug target: "dht", "Peers: {:#?}", peer_ids); } @@ -156,8 +156,8 @@ impl RPCProcessor { // 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.into(), - key.into(), + &target_node_id.clone().into(), + &record_key.clone().into(), &peers, ) { Ok(v) => v, @@ -231,20 +231,23 @@ impl RPCProcessor { }; // Destructure - let (key, subkey, value, descriptor) = set_value_q.destructure(); + let (record_key, subkey, value, descriptor) = set_value_q.destructure(); // Get target for ValueChanged notifications let dest = network_result_try!(self.get_respond_to_destination(&msg)); let target = dest.get_target(&routing_table)?; // Get the nodes that we know about that are closer to the the key than our own node - let closer_to_key_peers = network_result_try!( - routing_table.find_preferred_peers_closer_to_key(routing_domain, key, vec![CAP_DHT]) - ); + let closer_to_key_peers = network_result_try!(routing_table + .find_preferred_peers_closer_to_key( + routing_domain, + &record_key.clone().into(), + vec![CAP_DHT] + )); let debug_string = format!( "IN <=== SetValueQ({} #{} len={} seq={} writer={}{}) <== {}", - key, + record_key, subkey, value.value_data().data().len(), value.value_data().seq(), @@ -270,7 +273,7 @@ impl RPCProcessor { let storage_manager = self.storage_manager(); let new_value = network_result_try!(storage_manager .inbound_set_value( - key, + record_key.clone(), subkey, Arc::new(value), descriptor.map(Arc::new), @@ -297,7 +300,7 @@ impl RPCProcessor { let debug_string_answer = format!( "IN ===> SetValueA({} #{}{}{} peers={}) ==> {}", - key, + record_key, subkey, if set { " +set" } else { "" }, debug_string_value, diff --git a/veilid-core/src/rpc_processor/rpc_status.rs b/veilid-core/src/rpc_processor/rpc_status.rs index d52e2ecc..5a30a4d2 100644 --- a/veilid-core/src/rpc_processor/rpc_status.rs +++ b/veilid-core/src/rpc_processor/rpc_status.rs @@ -78,7 +78,7 @@ impl RPCProcessor { let send_data_method = waitable_reply.context.send_data_result.clone(); // Keep the reply private route that was used to return with the answer - let reply_private_route = waitable_reply.context.reply_private_route; + let reply_private_route = waitable_reply.context.reply_private_route.clone(); // Wait for reply let (msg, latency) = match self.wait_for_reply(waitable_reply, debug_string).await? { diff --git a/veilid-core/src/rpc_processor/rpc_validate_dial_info.rs b/veilid-core/src/rpc_processor/rpc_validate_dial_info.rs index dfee59aa..83d41c81 100644 --- a/veilid-core/src/rpc_processor/rpc_validate_dial_info.rs +++ b/veilid-core/src/rpc_processor/rpc_validate_dial_info.rs @@ -131,7 +131,7 @@ impl RPCProcessor { // We filter on the -outgoing- protocol capability status not the node's dial info // Use the address type though, to ensure we reach an ipv6 capable node if this is // an ipv6 address - let sender_node_id = detail.envelope.get_sender_typed_id(); + let sender_node_id = detail.envelope.get_sender_id(); let routing_domain = detail.routing_domain; let node_count = self .config() diff --git a/veilid-core/src/rpc_processor/rpc_value_changed.rs b/veilid-core/src/rpc_processor/rpc_value_changed.rs index 63d8909a..fe4a450e 100644 --- a/veilid-core/src/rpc_processor/rpc_value_changed.rs +++ b/veilid-core/src/rpc_processor/rpc_value_changed.rs @@ -56,7 +56,7 @@ impl RPCProcessor { // Try it as the node if, and the storage manager will reject the // value change if it doesn't match the active watch's node id let inbound_node_id = match &msg.header.detail { - RPCMessageHeaderDetail::Direct(d) => d.envelope.get_sender_typed_id(), + RPCMessageHeaderDetail::Direct(d) => d.envelope.get_sender_id(), RPCMessageHeaderDetail::SafetyRouted(_) => { return Ok(NetworkResult::invalid_message( "not processing value change over safety route", @@ -64,7 +64,7 @@ impl RPCProcessor { } RPCMessageHeaderDetail::PrivateRouted(p) => NodeId::new( p.direct.envelope.get_crypto_kind(), - p.remote_safety_route.into(), + p.remote_safety_route.clone().into(), ), }; diff --git a/veilid-core/src/rpc_processor/rpc_watch_value.rs b/veilid-core/src/rpc_processor/rpc_watch_value.rs index 06bd7cb9..dee68d7d 100644 --- a/veilid-core/src/rpc_processor/rpc_watch_value.rs +++ b/veilid-core/src/rpc_processor/rpc_watch_value.rs @@ -27,11 +27,11 @@ impl RPCProcessor { pub async fn rpc_call_watch_value( &self, dest: Destination, - key: RecordKey, + record_key: RecordKey, subkeys: ValueSubkeyRangeSet, expiration: Timestamp, count: u32, - watcher: BareKeyPair, + watcher: KeyPair, watch_id: Option, ) -> RPCNetworkResult> { let _guard = self @@ -50,10 +50,10 @@ impl RPCProcessor { // Get the target node id let crypto = self.crypto(); - let Some(vcrypto) = crypto.get(key.kind) else { + let Some(vcrypto) = crypto.get(record_key.kind()) else { return Err(RPCError::internal("unsupported cryptosystem")); }; - let Some(target_node_id) = target_node_ids.get(key.kind) else { + let Some(target_node_id) = target_node_ids.get(record_key.kind()) else { return Err(RPCError::internal("No node id for crypto kind")); }; @@ -64,17 +64,17 @@ impl RPCProcessor { } else { "".to_owned() }, - key, + record_key, subkeys, expiration, count, dest, - watcher.key + watcher ); // Send the watchvalue question let watch_value_q = RPCOperationWatchValueQ::new( - key, + record_key.clone(), subkeys.clone(), expiration.as_u64(), count, @@ -93,7 +93,7 @@ impl RPCProcessor { network_result_try!(self.question(dest.clone(), question, None).await?); // Keep the reply private route that was used to return with the answer - let reply_private_route = waitable_reply.context.reply_private_route; + let reply_private_route = waitable_reply.context.reply_private_route.clone(); // Wait for reply let (msg, latency) = match self.wait_for_reply(waitable_reply, debug_string).await? { @@ -117,7 +117,7 @@ impl RPCProcessor { "OUT <== WatchValueA({}id={} {} #{:?}@{} peers={}) <= {}", if accepted { "+accept " } else { "" }, watch_id, - key, + record_key, subkeys, expiration, peers.len(), @@ -128,7 +128,7 @@ impl RPCProcessor { let peer_ids: Vec = peers .iter() - .filter_map(|p| p.node_ids().get(key.kind).map(|k| k.to_string())) + .filter_map(|p| p.node_ids().get(record_key.kind()).map(|k| k.to_string())) .collect(); veilid_log!(self debug target: "dht", "Peers: {:#?}", peer_ids); } @@ -155,8 +155,8 @@ impl RPCProcessor { // 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.into(), - key.into(), + &target_node_id.clone().into(), + &record_key.clone().into(), &peers, ) { Ok(v) => v, @@ -233,9 +233,16 @@ impl RPCProcessor { }; // Destructure - let (key, subkeys, expiration, count, watch_id, watcher, _signature) = + let (record_key, subkeys, expiration, count, watch_id, watcher, _signature) = watch_value_q.destructure(); + // Extract member id for watcher + let Ok(watcher_member_id) = self.storage_manager().generate_member_id(&watcher) else { + return Ok(NetworkResult::invalid_message( + "could not generate member id for watcher public key", + )); + }; + // Get target for ValueChanged notifications let dest = network_result_try!(self.get_respond_to_destination(&msg)); let target = dest.get_target(&routing_table)?; @@ -248,12 +255,12 @@ impl RPCProcessor { } else { "".to_owned() }, - key, + record_key, subkeys, expiration, count, msg.header.direct_sender_node_id(), - watcher + watcher_member_id ); veilid_log!(self debug target: "dht", "{}", debug_string); @@ -261,7 +268,11 @@ impl RPCProcessor { // Get the nodes that we know about that are closer to the the key than our own node let closer_to_key_peers = network_result_try!(routing_table - .find_preferred_peers_closer_to_key(routing_domain, key, vec![CAP_DHT, CAP_DHT_WATCH])); + .find_preferred_peers_closer_to_key( + routing_domain, + &record_key.clone().into(), + vec![CAP_DHT, CAP_DHT_WATCH] + )); // See if we would have accepted this as a set, same set_value_count for watches let set_value_count = self @@ -279,14 +290,14 @@ impl RPCProcessor { subkeys: subkeys.clone(), expiration: Timestamp::new(expiration), count, - watcher, + watcher_member_id, target, }; // See if we have this record ourselves, if so, accept the watch let storage_manager = self.storage_manager(); let watch_result = network_result_try!(storage_manager - .inbound_watch_value(key, params, watch_id) + .inbound_watch_value(record_key.clone(), params, watch_id) .await .map_err(RPCError::internal)?); @@ -308,7 +319,7 @@ impl RPCProcessor { "IN ===> WatchValueA({}id={} {} #{} expiration={} peers={}) ==> {}", if ret_accepted { "+accept " } else { "" }, ret_watch_id, - key, + record_key, subkeys, ret_expiration, closer_to_key_peers.len(), diff --git a/veilid-core/src/storage_manager/active_subkey_writes.rs b/veilid-core/src/storage_manager/active_subkey_writes.rs index d94161de..6180ad44 100644 --- a/veilid-core/src/storage_manager/active_subkey_writes.rs +++ b/veilid-core/src/storage_manager/active_subkey_writes.rs @@ -34,7 +34,10 @@ impl StorageManager { record_key: RecordKey, subkey: ValueSubkey, ) -> Option { - let asw = inner.active_subkey_writes.entry(record_key).or_default(); + let asw = inner + .active_subkey_writes + .entry(record_key.clone()) + .or_default(); if asw.contains(subkey) { veilid_log!(self debug "already writing to this subkey: {}:{}", record_key, subkey); None diff --git a/veilid-core/src/storage_manager/debug.rs b/veilid-core/src/storage_manager/debug.rs index f467a52a..e7fa96e4 100644 --- a/veilid-core/src/storage_manager/debug.rs +++ b/veilid-core/src/storage_manager/debug.rs @@ -41,7 +41,7 @@ impl StorageManager { let mut out = "[\n".to_owned(); for (k, v) in &inner.offline_subkey_writes { let record_info = local_record_store - .peek_record(*k, |r| format!("{} nodes", r.detail().nodes.len())) + .peek_record(k, |r| format!("{} nodes", r.detail().nodes.len())) .unwrap_or("Not found".to_owned()); out += &format!(" {}:{:?}, {}\n", k, v, record_info); @@ -108,7 +108,7 @@ impl StorageManager { let Some(local_record_store) = &inner.local_record_store else { return "not initialized".to_owned(); }; - let local_debug = local_record_store.debug_record_info(record_key); + let local_debug = local_record_store.debug_record_info(record_key.clone()); let opened_debug = if let Some(o) = inner.opened_records.get(&record_key) { format!("Opened Record: {:#?}\n", o) diff --git a/veilid-core/src/storage_manager/get_value.rs b/veilid-core/src/storage_manager/get_value.rs index b585fdb3..27c4e823 100644 --- a/veilid-core/src/storage_manager/get_value.rs +++ b/veilid-core/src/storage_manager/get_value.rs @@ -47,7 +47,7 @@ impl StorageManager { // Get the nodes we know are caching this value to seed the fanout let init_fanout_queue = { - self.get_value_nodes(record_key) + self.get_value_nodes(record_key.clone()) .await? .unwrap_or_default() .into_iter() @@ -81,11 +81,15 @@ impl StorageManager { let call_routine = { let context = context.clone(); let registry = self.registry(); + let record_key = record_key.clone(); + let safety_selection = safety_selection.clone(); Arc::new( move |next_node: NodeRef| -> PinBoxFutureStatic { let context = context.clone(); let registry = registry.clone(); + let record_key = record_key.clone(); let last_descriptor = last_get_result.opt_descriptor.clone(); + let safety_selection = safety_selection.clone(); Box::pin(async move { let rpc_processor = registry.rpc_processor(); let gva = match @@ -93,7 +97,7 @@ impl StorageManager { .rpc_call_get_value( Destination::direct(next_node.routing_domain_filtered(routing_domain)) .with_safety(safety_selection), - record_key, + record_key.clone(), subkey, last_descriptor.map(|x| (*x).clone()), ) @@ -145,8 +149,8 @@ impl StorageManager { }; // Validate with schema - if schema.check_subkey_value_data( - descriptor.owner(), + if registry.storage_manager().check_subkey_value_data(schema, + descriptor.ref_owner(), subkey, value.value_data(), ).is_err() { @@ -255,7 +259,7 @@ impl StorageManager { let routing_table = registry.routing_table(); let fanout_call = FanoutCall::new( &routing_table, - record_key.into(), + record_key.clone().into(), key_count, fanout, consensus_count, @@ -316,6 +320,7 @@ impl StorageManager { Box::new( move |result: VeilidAPIResult| -> PinBoxFutureStatic { let registry=registry.clone(); + let key = key.clone(); Box::pin(async move { let this = registry.storage_manager(); let result = match result { @@ -326,7 +331,7 @@ impl StorageManager { } }; let is_incomplete = result.fanout_result.kind.is_incomplete(); - let value_data = match this.process_outbound_get_value_result(key, subkey, Some(last_seq), result).await { + let value_data = match this.process_outbound_get_value_result(key.clone(), subkey, Some(last_seq), result).await { Ok(Some(v)) => v, Ok(None) => { return is_incomplete; @@ -344,7 +349,7 @@ impl StorageManager { // if the sequence number changed since our first partial update // Send with a max count as this is not attached to any watch if last_seq != value_data.seq() { - this.update_callback_value_change(key,ValueSubkeyRangeSet::single(subkey), u32::MAX, Some(value_data)); + this.update_callback_value_change(key.clone(),ValueSubkeyRangeSet::single(subkey), u32::MAX, Some(value_data)); } // Return done @@ -371,7 +376,7 @@ impl StorageManager { // Get cryptosystem let crypto = self.crypto(); - let Some(vcrypto) = crypto.get(record_key.kind) else { + let Some(vcrypto) = crypto.get(record_key.kind()) else { apibail_generic!("unsupported cryptosystem"); }; @@ -381,7 +386,7 @@ impl StorageManager { Self::process_fanout_results_inner( &mut inner, &vcrypto, - record_key, + record_key.clone(), core::iter::once((ValueSubkeyRangeSet::single(subkey), result.fanout_result)), false, self.config() @@ -416,7 +421,7 @@ impl StorageManager { let (_is_local, last_get_result) = { // See if the subkey we are getting has a last known local value let mut last_get_result = self - .handle_get_local_value_inner(&mut inner, key, subkey, true) + .handle_get_local_value_inner(&mut inner, key.clone(), subkey, true) .await?; // If this is local, it must have a descriptor already if last_get_result.opt_descriptor.is_some() { diff --git a/veilid-core/src/storage_manager/inspect_value.rs b/veilid-core/src/storage_manager/inspect_value.rs index 3d8135b1..aa0e87bf 100644 --- a/veilid-core/src/storage_manager/inspect_value.rs +++ b/veilid-core/src/storage_manager/inspect_value.rs @@ -88,7 +88,7 @@ impl StorageManager { // Get the nodes we know are caching this value to seed the fanout let init_fanout_queue = { - self.get_value_nodes(record_key) + self.get_value_nodes(record_key.clone()) .await? .unwrap_or_default() .into_iter() @@ -125,12 +125,16 @@ impl StorageManager { let call_routine = { let context = context.clone(); let registry = self.registry(); + let record_key = record_key.clone(); + let safety_selection = safety_selection.clone(); Arc::new( move |next_node: NodeRef| -> PinBoxFutureStatic { let context = context.clone(); let registry = registry.clone(); let opt_descriptor = local_inspect_result.opt_descriptor(); let subkeys = subkeys.clone(); + let record_key = record_key.clone(); + let safety_selection = safety_selection.clone(); Box::pin(async move { let rpc_processor = registry.rpc_processor(); @@ -138,7 +142,7 @@ impl StorageManager { rpc_processor .rpc_call_inspect_value( Destination::direct(next_node.routing_domain_filtered(routing_domain)).with_safety(safety_selection), - record_key, + record_key.clone(), subkeys.clone(), opt_descriptor.map(|x| (*x).clone()), ) @@ -368,7 +372,12 @@ impl StorageManager { let (_is_local, inspect_result) = { // See if the subkey we are getting has a last known local value let mut local_inspect_result = self - .handle_inspect_local_value_inner(&mut inner, record_key, subkeys.clone(), true) + .handle_inspect_local_value_inner( + &mut inner, + record_key.clone(), + subkeys.clone(), + true, + ) .await?; // If this is local, it must have a descriptor already if local_inspect_result.opt_descriptor().is_some() { diff --git a/veilid-core/src/storage_manager/mod.rs b/veilid-core/src/storage_manager/mod.rs index 90bb7e09..609de05f 100644 --- a/veilid-core/src/storage_manager/mod.rs +++ b/veilid-core/src/storage_manager/mod.rs @@ -6,6 +6,7 @@ mod offline_subkey_writes; mod outbound_watch_manager; mod record_store; mod rehydrate; +mod schema; mod set_value; mod tasks; mod types; @@ -28,6 +29,8 @@ pub use types::*; impl_veilid_log_facility!("stor"); +/// Fixed length of MemberId (DHT Schema member id) in bytes +pub const MEMBER_ID_LENGTH: usize = 32; /// The maximum size of a single subkey pub(crate) const MAX_SUBKEY_SIZE: usize = ValueData::MAX_LEN; /// The maximum total size of all subkeys of a record @@ -488,7 +491,7 @@ impl StorageManager { Destination::direct( node_ref.routing_domain_filtered(RoutingDomain::PublicInternet), ) - .with_safety(current.params().safety_selection), + .with_safety(current.params().safety_selection.clone()), ) } } @@ -501,13 +504,12 @@ impl StorageManager { #[instrument(level = "trace", target = "stor", skip_all)] pub fn get_record_key( &self, - kind: CryptoKind, schema: DHTSchema, - owner_key: &BarePublicKey, + owner_key: &PublicKey, ) -> VeilidAPIResult { // Get cryptosystem let crypto = self.crypto(); - let Some(vcrypto) = crypto.get(kind) else { + let Some(vcrypto) = crypto.get(owner_key.kind()) else { apibail_generic!("unsupported cryptosystem"); }; @@ -515,7 +517,24 @@ impl StorageManager { schema.validate()?; let schema_data = schema.compile(); - Ok(Self::get_key(&vcrypto, owner_key, &schema_data)) + Ok(Self::make_record_key( + &vcrypto, + owner_key.ref_value(), + &schema_data, + )) + } + + fn make_record_key( + vcrypto: &CryptoSystemGuard<'_>, + owner_key: &BarePublicKey, + schema_data: &[u8], + ) -> RecordKey { + let mut hash_data = Vec::::with_capacity(owner_key.len() + 4 + schema_data.len()); + hash_data.extend_from_slice(&vcrypto.kind().0); + hash_data.extend_from_slice(owner_key); + hash_data.extend_from_slice(schema_data); + let hash = vcrypto.generate_hash(&hash_data); + RecordKey::new(vcrypto.kind(), BareRecordKey::from(hash)) } /// Create a local record from scratch with a new owner key, open it, and return the opened descriptor @@ -523,7 +542,7 @@ impl StorageManager { &self, kind: CryptoKind, schema: DHTSchema, - owner: Option, + owner: Option, safety_selection: SafetySelection, ) -> VeilidAPIResult { let Ok(_guard) = self.startup_lock.enter() else { @@ -538,7 +557,13 @@ impl StorageManager { // Create a new owned local record from scratch let (key, owner) = self - .create_new_owned_local_record_inner(&mut inner, kind, schema, owner, safety_selection) + .create_new_owned_local_record_inner( + &mut inner, + kind, + schema, + owner, + safety_selection.clone(), + ) .await?; // Now that the record is made we should always succeed to open the existing record @@ -553,7 +578,7 @@ impl StorageManager { pub async fn open_record( &self, record_key: RecordKey, - writer: Option, + writer: Option, safety_selection: SafetySelection, ) -> VeilidAPIResult { let Ok(_guard) = self.startup_lock.enter() else { @@ -564,7 +589,12 @@ impl StorageManager { // See if we have a local record already or not if let Some(res) = self - .open_existing_record_inner(&mut inner, record_key, writer, safety_selection) + .open_existing_record_inner( + &mut inner, + record_key.clone(), + writer.clone(), + safety_selection.clone(), + ) .await? { drop(inner); @@ -593,9 +623,9 @@ impl StorageManager { // Use the safety selection we opened the record with let result = self .outbound_inspect_value( - record_key, + record_key.clone(), ValueSubkeyRangeSet::single(0), - safety_selection, + safety_selection.clone(), InspectResult::default(), false, ) @@ -613,7 +643,12 @@ impl StorageManager { let mut inner = self.inner.lock().await; if let Some(res) = self - .open_existing_record_inner(&mut inner, record_key, writer, safety_selection) + .open_existing_record_inner( + &mut inner, + record_key.clone(), + writer.clone(), + safety_selection.clone(), + ) .await? { // Don't bother to rehydrate in this edge case @@ -655,7 +690,7 @@ impl StorageManager { // Attempt to close the record, returning the opened record if it wasn't already closed let mut inner = self.inner.lock().await; - let keys = inner.opened_records.keys().copied().collect::>(); + let keys = inner.opened_records.keys().cloned().collect::>(); for key in keys { Self::close_record_inner(&mut inner, key)?; } @@ -672,7 +707,7 @@ impl StorageManager { // Ensure the record is closed let mut inner = self.inner.lock().await; - Self::close_record_inner(&mut inner, record_key)?; + Self::close_record_inner(&mut inner, record_key.clone())?; // Get record from the local store let Some(local_record_store) = inner.local_record_store.as_mut() else { @@ -705,7 +740,7 @@ impl StorageManager { // See if the requested subkey is our local record store let last_get_result = self - .handle_get_local_value_inner(&mut inner, record_key, subkey, true) + .handle_get_local_value_inner(&mut inner, record_key.clone(), subkey, true) .await?; // Return the existing value if we have one unless we are forcing a refresh @@ -734,7 +769,12 @@ impl StorageManager { .as_ref() .map(|v| v.value_data().seq()); let res_rx = self - .outbound_get_value(record_key, subkey, safety_selection, last_get_result) + .outbound_get_value( + record_key.clone(), + subkey, + safety_selection, + last_get_result, + ) .await?; // Wait for the first result @@ -746,7 +786,7 @@ impl StorageManager { // Process the returned result let out = self - .process_outbound_get_value_result(record_key, subkey, opt_last_seq, result) + .process_outbound_get_value_result(record_key.clone(), subkey, opt_last_seq, result) .await?; if let Some(out) = &out { @@ -754,7 +794,7 @@ impl StorageManager { if partial { self.process_deferred_outbound_get_value_result( res_rx, - record_key, + record_key.clone(), subkey, out.seq(), ); @@ -781,7 +821,7 @@ impl StorageManager { // Get cryptosystem let crypto = self.crypto(); - let Some(vcrypto) = crypto.get(record_key.kind) else { + let Some(vcrypto) = crypto.get(record_key.kind()) else { apibail_generic!("unsupported cryptosystem"); }; @@ -796,7 +836,10 @@ impl StorageManager { }; // Use the specified writer, or if not specified, the default writer when the record was opened - let opt_writer = options.as_ref().and_then(|o| o.writer).or(opt_writer); + let opt_writer = options + .as_ref() + .and_then(|o| o.writer.clone()) + .or(opt_writer); let allow_offline = options .unwrap_or_default() .allow_offline @@ -809,7 +852,7 @@ impl StorageManager { // See if the subkey we are modifying has a last known local value let last_get_result = self - .handle_get_local_value_inner(&mut inner, record_key, subkey, true) + .handle_get_local_value_inner(&mut inner, record_key.clone(), subkey, true) .await?; // Get the descriptor and schema for the key @@ -821,20 +864,22 @@ impl StorageManager { // Make new subkey data let value_data = if let Some(last_signed_value_data) = last_get_result.opt_value { if last_signed_value_data.value_data().data() == data - && last_signed_value_data.value_data().writer() == &writer.key + && last_signed_value_data.value_data().ref_writer() == &writer.key() { // Data and writer is the same, nothing is changing, // just return that we set it, but no network activity needs to happen return Ok(None); } let seq = last_signed_value_data.value_data().seq(); - ValueData::new_with_seq(seq + 1, data, writer.key)? + ValueData::new_with_seq(seq + 1, data, writer.key())? } else { - ValueData::new(data, writer.key)? + ValueData::new(data, writer.key())? }; // Validate with schema - if let Err(e) = schema.check_subkey_value_data(descriptor.owner(), subkey, &value_data) { + if let Err(e) = + self.check_subkey_value_data(&schema, descriptor.ref_owner(), subkey, &value_data) + { veilid_log!(self debug "schema validation error: {}", e); // Validation failed, ignore this value apibail_generic!(format!( @@ -846,10 +891,10 @@ impl StorageManager { // Sign the new value data with the writer let signed_value_data = Arc::new(SignedValueData::make_signature( value_data, - descriptor.owner(), + &descriptor.owner(), subkey, &vcrypto, - writer.secret, + &writer.bare_secret(), )?); // Check if we are offline @@ -872,7 +917,7 @@ impl StorageManager { // Note that we are writing this subkey in the foreground // If it appears we are already doing this, then put it to the background/offline queue - let opt_guard = self.mark_active_subkey_write_inner(&mut inner, record_key, subkey); + let opt_guard = self.mark_active_subkey_write_inner(&mut inner, record_key.clone(), subkey); if opt_guard.is_none() { if allow_offline == AllowOffline(false) { apibail_try_again!("offline, try again later"); @@ -898,9 +943,9 @@ impl StorageManager { // Use the safety selection we opened the record with let res_rx = match self .outbound_set_value( - record_key, + record_key.clone(), subkey, - safety_selection, + safety_selection.clone(), signed_value_data.clone(), descriptor, ) @@ -917,7 +962,7 @@ impl StorageManager { if allow_offline == AllowOffline(true) { self.add_offline_subkey_write_inner( &mut inner, - record_key, + record_key.clone(), subkey, safety_selection, signed_value_data.clone(), @@ -990,10 +1035,10 @@ impl StorageManager { // Process the returned result let out = self .process_outbound_set_value_result( - record_key, + record_key.clone(), subkey, signed_value_data.value_data().clone(), - safety_selection, + safety_selection.clone(), result, ) .await?; @@ -1038,10 +1083,10 @@ impl StorageManager { let opt_value_data = self .process_outbound_set_value_result( - record_key, + record_key.clone(), subkey, signed_value_data.value_data().clone(), - safety_selection, + safety_selection.clone(), result, ) .await?; @@ -1080,14 +1125,14 @@ impl StorageManager { expiration: Timestamp, count: u32, ) -> VeilidAPIResult { - let key = watch_lock.tag(); + let record_key = watch_lock.tag(); // Obtain the inner state lock let mut inner = self.inner.lock().await; // Get the safety selection and the writer we opened this record let (safety_selection, opt_watcher) = { - let Some(opened_record) = inner.opened_records.get(&key) else { + let Some(opened_record) = inner.opened_records.get(&record_key) else { // Record must be opened already to change watch apibail_generic!("record not open"); }; @@ -1106,7 +1151,7 @@ impl StorageManager { // Get the schema so we can truncate the watch to the number of subkeys let schema = if let Some(lrs) = inner.local_record_store.as_ref() { - let Some(schema) = lrs.peek_record(key, |r| r.schema()) else { + let Some(schema) = lrs.peek_record(&record_key, |r| r.schema()) else { apibail_generic!("no local record found"); }; schema @@ -1148,7 +1193,7 @@ impl StorageManager { let active = desired_params.is_some(); inner .outbound_watch_manager - .set_desired_watch(key, desired_params); + .set_desired_watch(record_key, desired_params); // Drop the lock for network access drop(inner); @@ -1168,7 +1213,10 @@ impl StorageManager { // Obtain the watch change lock // (may need to wait for background operations to complete on the watch) - let watch_lock = self.outbound_watch_lock_table.lock_tag(record_key).await; + let watch_lock = self + .outbound_watch_lock_table + .lock_tag(record_key.clone()) + .await; // Calculate change to existing watch let (subkeys, count, expiration_ts) = { @@ -1247,7 +1295,7 @@ impl StorageManager { // Get cryptosystem let crypto = self.crypto(); - let Some(vcrypto) = crypto.get(record_key.kind) else { + let Some(vcrypto) = crypto.get(record_key.kind()) else { apibail_generic!("unsupported cryptosystem"); }; @@ -1261,7 +1309,7 @@ impl StorageManager { // See if the requested record is our local record store let mut local_inspect_result = self - .handle_inspect_local_value_inner(&mut inner, record_key, subkeys.clone(), true) + .handle_inspect_local_value_inner(&mut inner, record_key.clone(), subkeys.clone(), true) .await?; // Get the offline subkeys for this record still only returning the ones we're inspecting @@ -1319,7 +1367,7 @@ impl StorageManager { // Get the inspect record report from the network let result = self .outbound_inspect_value( - record_key, + record_key.clone(), subkeys, safety_selection, if matches!(scope, DHTReportScope::SyncGet | DHTReportScope::SyncSet) { @@ -1343,7 +1391,7 @@ impl StorageManager { Self::process_fanout_results_inner( &mut inner, &vcrypto, - record_key, + record_key.clone(), results_iter, false, self.config() @@ -1378,14 +1426,14 @@ impl StorageManager { let dest = rpc_processor .resolve_target_to_destination( - vc.target, + vc.target.clone(), SafetySelection::Unsafe(Sequencing::PreferOrdered), ) .await .map_err(VeilidAPIError::from)?; network_result_value_or_log!(self rpc_processor - .rpc_call_value_changed(dest, vc.record_key, vc.subkeys.clone(), vc.count, vc.watch_id, vc.value.map(|v| (*v).clone()) ) + .rpc_call_value_changed(dest, vc.record_key.clone(), vc.subkeys.clone(), vc.count, vc.watch_id, vc.value.map(|v| (*v).clone()) ) .await .map_err(VeilidAPIError::from)? => [format!(": dest={:?} vc={:?}", dest, vc)] {}); @@ -1464,9 +1512,9 @@ impl StorageManager { inner: &mut StorageManagerInner, kind: CryptoKind, schema: DHTSchema, - owner: Option, + owner: Option, safety_selection: SafetySelection, - ) -> VeilidAPIResult<(RecordKey, BareKeyPair)> { + ) -> VeilidAPIResult<(RecordKey, KeyPair)> { // Get cryptosystem let crypto = self.crypto(); let Some(vcrypto) = crypto.get(kind) else { @@ -1483,11 +1531,12 @@ impl StorageManager { let config = self.config(); let cfg = config.get(); if let Some(node_id) = cfg.network.routing_table.node_id.get(kind) { - if schema.is_member(&node_id.value.into()) { + let node_member_id = BareMemberId::new(node_id.ref_value()); + if schema.is_member(&node_member_id) { apibail_invalid_argument!( "node id can not be schema member", "schema", - node_id.value + node_id.value() ); } } @@ -1497,17 +1546,24 @@ impl StorageManager { let schema_data = schema.compile(); // New values require a new owner key if not given - let owner = owner.unwrap_or_else(|| vcrypto.generate_keypair()); + let owner = if let Some(owner) = owner { + if owner.kind() != vcrypto.kind() { + apibail_invalid_argument!("owner is wrong crypto kind", "owner", owner); + } + owner + } else { + KeyPair::new(vcrypto.kind(), vcrypto.generate_keypair()) + }; // Calculate dht key - let dht_key = Self::get_key(&vcrypto, &owner.key, &schema_data); + let record_key = Self::make_record_key(&vcrypto, owner.ref_value().ref_key(), &schema_data); // Make a signed value descriptor for this dht value let signed_value_descriptor = Arc::new(SignedValueDescriptor::make_signature( - owner.key, + owner.key(), schema_data, &vcrypto, - owner.secret, + owner.bare_secret(), )?); // Add new local value record @@ -1516,9 +1572,11 @@ impl StorageManager { let record = Record::::new(cur_ts, signed_value_descriptor, local_record_detail)?; - local_record_store.new_record(dht_key, record).await?; + local_record_store + .new_record(record_key.clone(), record) + .await?; - Ok((dht_key, owner)) + Ok((record_key, owner)) } #[instrument(level = "trace", target = "stor", skip_all, err)] @@ -1527,7 +1585,7 @@ impl StorageManager { inner: &mut StorageManagerInner, record_key: RecordKey, safety_selection: SafetySelection, - ) -> VeilidAPIResult> { + ) -> VeilidAPIResult> { // Get local record store let Some(local_record_store) = inner.local_record_store.as_mut() else { apibail_not_initialized!(); @@ -1542,7 +1600,7 @@ impl StorageManager { // Return record details r.clone() }; - let Some(remote_record) = remote_record_store.with_record(record_key, rcb) else { + let Some(remote_record) = remote_record_store.with_record(&record_key, rcb) else { // No local or remote record found, return None return Ok(None); }; @@ -1555,13 +1613,13 @@ impl StorageManager { LocalRecordDetail::new(safety_selection), )?; local_record_store - .new_record(record_key, local_record) + .new_record(record_key.clone(), local_record) .await?; // Move copy subkey data from remote to local store for subkey in remote_record.stored_subkeys().iter() { let Some(get_result) = remote_record_store - .get_subkey(record_key, subkey, false) + .get_subkey(record_key.clone(), subkey, false) .await? else { // Subkey was missing @@ -1575,7 +1633,7 @@ impl StorageManager { }; local_record_store .set_subkey( - record_key, + record_key.clone(), subkey, subkey_data, InboundWatchUpdateMode::NoUpdate, @@ -1585,15 +1643,17 @@ impl StorageManager { // Move watches local_record_store.move_watches( - record_key, - remote_record_store.move_watches(record_key, None), + record_key.clone(), + remote_record_store.move_watches(record_key.clone(), None), ); // Delete remote record from store - remote_record_store.delete_record(record_key).await?; + remote_record_store + .delete_record(record_key.clone()) + .await?; // Return record information as transferred to local record - Ok(Some((*remote_record.owner(), remote_record.schema()))) + Ok(Some((remote_record.owner(), remote_record.schema()))) } #[instrument(level = "trace", target = "stor", skip_all, err)] @@ -1601,7 +1661,7 @@ impl StorageManager { &self, inner: &mut StorageManagerInner, record_key: RecordKey, - writer: Option, + writer: Option, safety_selection: SafetySelection, ) -> VeilidAPIResult> { // Get local record store @@ -1614,18 +1674,22 @@ impl StorageManager { // Process local record // Keep the safety selection we opened the record with - r.detail_mut().safety_selection = safety_selection; + r.detail_mut().safety_selection = safety_selection.clone(); // Return record details - (*r.owner(), r.schema()) + (r.owner(), r.schema()) }; - let (owner, schema) = match local_record_store.with_record_mut(record_key, cb) { + let (owner, schema) = match local_record_store.with_record_mut(&record_key, cb) { Some(v) => v, None => { // If we don't have a local record yet, check to see if we have a remote record // if so, migrate it to a local record let Some(v) = self - .move_remote_record_to_local_inner(&mut *inner, record_key, safety_selection) + .move_remote_record_to_local_inner( + &mut *inner, + record_key.clone(), + safety_selection.clone(), + ) .await? else { // No remote record either @@ -1638,9 +1702,9 @@ impl StorageManager { // If the writer we chose is also the owner, we have the owner secret // Otherwise this is just another subkey writer - let owner_secret = if let Some(writer) = writer { - if writer.key == owner { - Some(writer.secret) + let owner_secret = if let Some(writer) = writer.clone() { + if writer.key() == owner { + Some(writer.bare_secret()) } else { None } @@ -1651,12 +1715,12 @@ impl StorageManager { // Write open record inner .opened_records - .entry(record_key) + .entry(record_key.clone()) .and_modify(|e| { - e.set_writer(writer); - e.set_safety_selection(safety_selection); + e.set_writer(writer.clone()); + e.set_safety_selection(safety_selection.clone()); }) - .or_insert_with(|| OpenedRecord::new(writer, safety_selection)); + .or_insert_with(|| OpenedRecord::new(writer.clone(), safety_selection.clone())); // Make DHT Record Descriptor to return let descriptor = DHTRecordDescriptor::new(record_key, owner, owner_secret, schema); @@ -1668,7 +1732,7 @@ impl StorageManager { &self, inner: &mut StorageManagerInner, record_key: RecordKey, - writer: Option, + writer: Option, inspect_result: InspectResult, safety_selection: SafetySelection, ) -> VeilidAPIResult { @@ -1683,13 +1747,13 @@ impl StorageManager { apibail_generic!("no descriptor"); }; // Get owner - let owner = *signed_value_descriptor.owner(); + let owner = signed_value_descriptor.owner(); // If the writer we chose is also the owner, we have the owner secret // Otherwise this is just another subkey writer - let owner_secret = if let Some(writer) = writer { - if writer.key == owner { - Some(writer.secret) + let owner_secret = if let Some(writer) = &writer { + if writer.key() == owner { + Some(writer.bare_secret()) } else { None } @@ -1707,14 +1771,17 @@ impl StorageManager { let record = Record::::new( Timestamp::now(), signed_value_descriptor, - LocalRecordDetail::new(safety_selection), + LocalRecordDetail::new(safety_selection.clone()), )?; - local_record_store.new_record(record_key, record).await?; + local_record_store + .new_record(record_key.clone(), record) + .await?; // Write open record - inner - .opened_records - .insert(record_key, OpenedRecord::new(writer, safety_selection)); + inner.opened_records.insert( + record_key.clone(), + OpenedRecord::new(writer, safety_selection), + ); // Make DHT Record Descriptor to return let descriptor = DHTRecordDescriptor::new(record_key, owner, owner_secret, schema); @@ -1735,14 +1802,14 @@ impl StorageManager { // Get routing table to see if we still know about these nodes let routing_table = self.routing_table(); - let opt_value_nodes = local_record_store.peek_record(record_key, |r| { + let opt_value_nodes = local_record_store.peek_record(&record_key, |r| { let d = r.detail(); d.nodes .keys() - .copied() + .cloned() .filter_map(|x| { routing_table - .lookup_node_ref(NodeId::new(record_key.kind, x)) + .lookup_node_ref(NodeId::new(record_key.kind(), x)) .ok() .flatten() }) @@ -1765,14 +1832,14 @@ impl StorageManager { let local_record_store = inner.local_record_store.as_mut().unwrap(); let cur_ts = Timestamp::now(); - local_record_store.with_record_mut(record_key, |r| { + local_record_store.with_record_mut(&record_key, |r| { let d = r.detail_mut(); for (subkeys, fanout_result) in subkey_results_iter { for node_id in fanout_result .value_nodes .iter() - .filter_map(|x| x.node_ids().get(record_key.kind).map(|k| k.value)) + .filter_map(|x| x.node_ids().get(record_key.kind()).map(|k| k.value())) { let pnd = d.nodes.entry(node_id).or_default(); if is_set || pnd.last_set == Timestamp::default() { @@ -1787,7 +1854,7 @@ impl StorageManager { let mut nodes_ts = d .nodes .iter() - .map(|kv| (*kv.0, kv.1.last_seen)) + .map(|kv| (kv.0.clone(), kv.1.last_seen)) .collect::>(); nodes_ts.sort_by(|a, b| { // Timestamp is first metric @@ -1797,12 +1864,12 @@ impl StorageManager { } // Distance is the next metric, closer nodes first let da = vcrypto.distance( - &BareHashDigest::from(a.0), - &BareHashDigest::from(record_key.value), + &BareHashDigest::from(a.0.clone()), + &BareHashDigest::from(record_key.value()), ); let db = vcrypto.distance( - &BareHashDigest::from(b.0), - &BareHashDigest::from(record_key.value), + &BareHashDigest::from(b.0.clone()), + &BareHashDigest::from(record_key.value()), ); da.cmp(&db) }); @@ -1820,7 +1887,10 @@ impl StorageManager { let Some(local_record_store) = inner.local_record_store.as_mut() else { apibail_not_initialized!(); }; - if local_record_store.peek_record(record_key, |_| {}).is_none() { + if local_record_store + .peek_record(&record_key, |_| {}) + .is_none() + { apibail_key_not_found!(record_key); } @@ -1846,7 +1916,7 @@ impl StorageManager { // See if the value is in the offline subkey writes first, // since it may not have been committed yet to the local record store if let Some(get_result) = - self.get_offline_subkey_writes_subkey(inner, record_key, subkey, want_descriptor)? + self.get_offline_subkey_writes_subkey(inner, &record_key, subkey, want_descriptor)? { return Ok(get_result); } @@ -1880,7 +1950,7 @@ impl StorageManager { // See if this new data supercedes any offline subkey writes self.remove_old_offline_subkey_writes_inner( inner, - record_key, + record_key.clone(), subkey, signed_value_data.clone(), ); @@ -1967,7 +2037,7 @@ impl StorageManager { // See if we have a remote record already or not if remote_record_store - .with_record(record_key, |_| {}) + .with_record(&record_key, |_| {}) .is_none() { // record didn't exist, make it @@ -1978,7 +2048,9 @@ impl StorageManager { signed_value_descriptor, remote_record_detail, )?; - remote_record_store.new_record(record_key, record).await? + remote_record_store + .new_record(record_key.clone(), record) + .await? }; // Write subkey to remote store @@ -2018,19 +2090,6 @@ impl StorageManager { ) } - fn get_key( - vcrypto: &CryptoSystemGuard<'_>, - owner_key: &BarePublicKey, - schema_data: &[u8], - ) -> RecordKey { - let mut hash_data = Vec::::with_capacity(PUBLIC_KEY_LENGTH + 4 + schema_data.len()); - hash_data.extend_from_slice(&vcrypto.kind().0); - hash_data.extend_from_slice(&owner_key.bytes); - hash_data.extend_from_slice(schema_data); - let hash = vcrypto.generate_hash(&hash_data); - RecordKey::new(vcrypto.kind(), BareRecordKey::from(hash)) - } - #[instrument(level = "trace", target = "stor", skip_all)] fn process_deferred_results( &self, diff --git a/veilid-core/src/storage_manager/offline_subkey_writes.rs b/veilid-core/src/storage_manager/offline_subkey_writes.rs index 38b65cf9..d06d7a73 100644 --- a/veilid-core/src/storage_manager/offline_subkey_writes.rs +++ b/veilid-core/src/storage_manager/offline_subkey_writes.rs @@ -49,14 +49,14 @@ impl StorageManager { pub(super) fn get_offline_subkey_writes_subkey( &self, inner: &mut StorageManagerInner, - record_key: RecordKey, + record_key: &RecordKey, subkey: ValueSubkey, want_descriptor: bool, ) -> VeilidAPIResult> { let Some(local_record_store) = inner.local_record_store.as_mut() else { apibail_not_initialized!(); }; - let Some(osw) = inner.offline_subkey_writes.get(&record_key) else { + let Some(osw) = inner.offline_subkey_writes.get(record_key) else { return Ok(None); }; let Some(signed_value_data) = osw.subkey_value_data.get(&subkey).cloned() else { @@ -93,7 +93,7 @@ impl StorageManager { signed_value_data: Arc, ) { // Get the offline subkey write record - match inner.offline_subkey_writes.entry(record_key) { + match inner.offline_subkey_writes.entry(record_key.clone()) { hashlink::linked_hash_map::Entry::Occupied(mut o) => { let finished = { let osw = o.get_mut(); @@ -154,7 +154,7 @@ impl StorageManager { ); // Get the offline subkey write record - match inner.offline_subkey_writes.entry(record_key) { + match inner.offline_subkey_writes.entry(record_key.clone()) { hashlink::linked_hash_map::Entry::Occupied(mut o) => { let finished = { let osw = o.get_mut(); diff --git a/veilid-core/src/storage_manager/outbound_watch_manager/mod.rs b/veilid-core/src/storage_manager/outbound_watch_manager/mod.rs index 44878f4d..9eaf1eb0 100644 --- a/veilid-core/src/storage_manager/outbound_watch_manager/mod.rs +++ b/veilid-core/src/storage_manager/outbound_watch_manager/mod.rs @@ -32,7 +32,7 @@ impl fmt::Display for OutboundWatchManager { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut out = format!("outbound_watches({}): [\n", self.outbound_watches.len()); { - let mut keys = self.outbound_watches.keys().copied().collect::>(); + let mut keys = self.outbound_watches.keys().cloned().collect::>(); keys.sort(); for k in keys { @@ -43,7 +43,7 @@ impl fmt::Display for OutboundWatchManager { out += "]\n"; out += &format!("per_node_states({}): [\n", self.per_node_states.len()); { - let mut keys = self.per_node_states.keys().copied().collect::>(); + let mut keys = self.per_node_states.keys().cloned().collect::>(); keys.sort(); for k in keys { @@ -60,7 +60,7 @@ impl fmt::Display for OutboundWatchManager { let mut keys = self .needs_change_inspection .keys() - .copied() + .cloned() .collect::>(); keys.sort(); @@ -92,7 +92,7 @@ impl OutboundWatchManager { pub fn prepare(&mut self, routing_table: VeilidComponentGuard<'_, RoutingTable>) { for (pnk, pns) in &mut self.per_node_states { - pns.watch_node_ref = match routing_table.lookup_node_ref(pnk.node_id) { + pns.watch_node_ref = match routing_table.lookup_node_ref(pnk.node_id.clone()) { Ok(v) => v, Err(e) => { veilid_log!(routing_table debug "Error looking up outbound watch node ref: {}", e); @@ -103,7 +103,7 @@ impl OutboundWatchManager { self.per_node_states .retain(|_, v| v.watch_node_ref.is_some()); - let keys = self.per_node_states.keys().copied().collect::>(); + let keys = self.per_node_states.keys().cloned().collect::>(); for v in self.outbound_watches.values_mut() { if let Some(state) = v.state_mut() { @@ -133,7 +133,7 @@ impl OutboundWatchManager { // Watch does not exist, add one if that's what is desired if let Some(desired) = desired_watch { self.outbound_watches - .insert(record_key, OutboundWatch::new(record_key, desired)); + .insert(record_key.clone(), OutboundWatch::new(record_key, desired)); } } } @@ -163,7 +163,7 @@ impl OutboundWatchManager { for (pnk, pns) in &self.per_node_states { if pns.count == 0 { // If per-node watch is done, add to finished list - finished_pnks.insert(*pnk); + finished_pnks.insert(pnk.clone()); } else if !pns .watch_node_ref .as_ref() @@ -172,10 +172,10 @@ impl OutboundWatchManager { .is_alive() { // If node is unreachable add to dead list - dead_pnks.insert(*pnk); + dead_pnks.insert(pnk.clone()); } else if cur_ts >= pns.expiration_ts { // If per-node watch has expired add to expired list - expired_pnks.insert(*pnk); + expired_pnks.insert(pnk.clone()); } } diff --git a/veilid-core/src/storage_manager/outbound_watch_manager/outbound_watch_parameters.rs b/veilid-core/src/storage_manager/outbound_watch_manager/outbound_watch_parameters.rs index cd402e0b..637feab4 100644 --- a/veilid-core/src/storage_manager/outbound_watch_manager/outbound_watch_parameters.rs +++ b/veilid-core/src/storage_manager/outbound_watch_manager/outbound_watch_parameters.rs @@ -13,7 +13,7 @@ pub struct OutboundWatchParameters { /// Subkeys requested for this watch pub subkeys: ValueSubkeyRangeSet, /// What key to use to perform the watch - pub opt_watcher: Option, + pub opt_watcher: Option, /// What safety selection to use on the network pub safety_selection: SafetySelection, } diff --git a/veilid-core/src/storage_manager/outbound_watch_manager/outbound_watch_state.rs b/veilid-core/src/storage_manager/outbound_watch_manager/outbound_watch_state.rs index 3c981272..c12bab04 100644 --- a/veilid-core/src/storage_manager/outbound_watch_manager/outbound_watch_state.rs +++ b/veilid-core/src/storage_manager/outbound_watch_manager/outbound_watch_state.rs @@ -163,7 +163,13 @@ impl OutboundWatchState { self.value_changed_routes = self .nodes .iter() - .filter_map(|x| per_node_state.get(x).unwrap().opt_value_changed_route) + .filter_map(|x| { + per_node_state + .get(x) + .cloned() + .unwrap() + .opt_value_changed_route + }) .collect(); res diff --git a/veilid-core/src/storage_manager/outbound_watch_manager/per_node_state.rs b/veilid-core/src/storage_manager/outbound_watch_manager/per_node_state.rs index 43d467fa..a3de08ba 100644 --- a/veilid-core/src/storage_manager/outbound_watch_manager/per_node_state.rs +++ b/veilid-core/src/storage_manager/outbound_watch_manager/per_node_state.rs @@ -2,7 +2,7 @@ use super::*; impl_veilid_log_facility!("stor"); -#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)] +#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)] pub(in crate::storage_manager) struct PerNodeKey { /// Watched record key pub record_key: RecordKey, @@ -36,7 +36,7 @@ pub(in crate::storage_manager) struct PerNodeState { /// SafetySelection used to contact the node pub safety_selection: SafetySelection, /// What key was used to perform the watch - pub opt_watcher: Option, + pub opt_watcher: Option, /// The expiration of a successful watch pub expiration_ts: Timestamp, /// How many value change notifications are left diff --git a/veilid-core/src/storage_manager/record_store/inbound_watch.rs b/veilid-core/src/storage_manager/record_store/inbound_watch.rs index b9655be0..2f058d1d 100644 --- a/veilid-core/src/storage_manager/record_store/inbound_watch.rs +++ b/veilid-core/src/storage_manager/record_store/inbound_watch.rs @@ -10,7 +10,7 @@ pub struct InboundWatchParameters { /// How many updates are left before forced expiration pub count: u32, /// The watching schema member key, or an anonymous key - pub watcher: BarePublicKey, + pub watcher_member_id: MemberId, /// The place where updates are sent pub target: Target, } diff --git a/veilid-core/src/storage_manager/record_store/keys.rs b/veilid-core/src/storage_manager/record_store/keys.rs index fb3da3e4..59a76e5f 100644 --- a/veilid-core/src/storage_manager/record_store/keys.rs +++ b/veilid-core/src/storage_manager/record_store/keys.rs @@ -1,63 +1,48 @@ use super::*; -#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct RecordTableKey { - pub key: RecordKey, + pub record_key: RecordKey, } impl RecordTableKey { - pub fn bytes(&self) -> [u8; HASH_DIGEST_LENGTH + 4] { - let mut bytes = [0u8; HASH_DIGEST_LENGTH + 4]; - bytes[0..4].copy_from_slice(&self.key.kind.0); - bytes[4..HASH_DIGEST_LENGTH + 4].copy_from_slice(&self.key.value.bytes); - bytes + pub fn bytes(&self) -> Vec { + Vec::from(self.record_key.clone()) } } impl TryFrom<&[u8]> for RecordTableKey { type Error = EyreReport; fn try_from(bytes: &[u8]) -> Result { - if bytes.len() != HASH_DIGEST_LENGTH + 4 { - bail!("invalid bytes length"); - } - let kind = CryptoKind::try_from(&bytes[0..4]).wrap_err("invalid kind")?; - let value = - BareRecordKey::try_from(&bytes[4..HASH_DIGEST_LENGTH + 4]).wrap_err("invalid value")?; - let key = RecordKey::new(kind, value); - Ok(RecordTableKey { key }) + let key = RecordKey::try_from(bytes)?; + Ok(RecordTableKey { record_key: key }) } } -#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct SubkeyTableKey { - pub key: RecordKey, + pub record_key: RecordKey, pub subkey: ValueSubkey, } impl SubkeyTableKey { - pub fn bytes(&self) -> [u8; HASH_DIGEST_LENGTH + 4 + 4] { - let mut bytes = [0u8; HASH_DIGEST_LENGTH + 4 + 4]; - bytes[0..4].copy_from_slice(&self.key.kind.0); - bytes[4..HASH_DIGEST_LENGTH + 4].copy_from_slice(&self.key.value.bytes); - bytes[HASH_DIGEST_LENGTH + 4..HASH_DIGEST_LENGTH + 4 + 4] - .copy_from_slice(&self.subkey.to_le_bytes()); + pub fn bytes(&self) -> Vec { + let mut bytes = Vec::<_>::from(self.record_key.clone()); + bytes.extend_from_slice(&self.subkey.to_le_bytes()); bytes } } impl TryFrom<&[u8]> for SubkeyTableKey { type Error = EyreReport; fn try_from(bytes: &[u8]) -> Result { - if bytes.len() != HASH_DIGEST_LENGTH + 4 { - bail!("invalid bytes length"); - } - let kind = CryptoKind::try_from(&bytes[0..4]).wrap_err("invalid kind")?; - let value = - BareRecordKey::try_from(&bytes[4..HASH_DIGEST_LENGTH + 4]).wrap_err("invalid value")?; + let key = RecordKey::try_from(&bytes[0..bytes.len() - 4])?; let subkey = ValueSubkey::from_le_bytes( - bytes[HASH_DIGEST_LENGTH + 4..HASH_DIGEST_LENGTH + 4 + 4] + bytes[(bytes.len() - 4)..] .try_into() .wrap_err("invalid subkey")?, ); - let key = RecordKey::new(kind, value); - Ok(SubkeyTableKey { key, subkey }) + Ok(SubkeyTableKey { + record_key: key, + subkey, + }) } } diff --git a/veilid-core/src/storage_manager/record_store/mod.rs b/veilid-core/src/storage_manager/record_store/mod.rs index ef179f58..3f242d4d 100644 --- a/veilid-core/src/storage_manager/record_store/mod.rs +++ b/veilid-core/src/storage_manager/record_store/mod.rs @@ -284,14 +284,17 @@ where } // add to index and ensure we deduplicate in the case of an error - if let Some(v) = self.record_index.insert_with_callback(ri.0, ri.1, |k, v| { - // If the configuration change, we only want to keep the 'limits.max_records' records - dead_records.push(DeadRecord { - key: k, - record: v, - in_total_storage: true, - }); - }) { + if let Some(v) = self + .record_index + .insert_with_callback(ri.0.clone(), ri.1, |k, v| { + // If the configuration change, we only want to keep the 'limits.max_records' records + dead_records.push(DeadRecord { + key: k, + record: v, + in_total_storage: true, + }); + }) + { // This shouldn't happen, but deduplicate anyway veilid_log!(self warn "duplicate record in table: {:?}", ri.0); dead_records.push(DeadRecord { @@ -412,7 +415,7 @@ where for sk in stored_subkeys.iter() { // From table let stk = SubkeyTableKey { - key: dr.key.key, + record_key: dr.key.record_key.clone(), subkey: sk, }; let stkb = stk.bytes(); @@ -469,8 +472,12 @@ where } #[instrument(level = "trace", target = "stor", skip_all, err)] - pub async fn new_record(&mut self, key: RecordKey, record: Record) -> VeilidAPIResult<()> { - let rtk = RecordTableKey { key }; + pub async fn new_record( + &mut self, + record_key: RecordKey, + record: Record, + ) -> VeilidAPIResult<()> { + let rtk = RecordTableKey { record_key }; if self.record_index.contains_key(&rtk) { apibail_internal!("record already exists"); } @@ -495,9 +502,12 @@ where // Save to record index let mut dead_records = Vec::new(); - if let Some(v) = self.record_index.insert_with_callback(rtk, record, |k, v| { - dead_records.push((k, v)); - }) { + if let Some(v) = self + .record_index + .insert_with_callback(rtk.clone(), record, |k, v| { + dead_records.push((k, v)); + }) + { // Shouldn't happen but log it veilid_log!(self warn "new duplicate record in table: {:?}", rtk); self.add_dead_record(rtk, v); @@ -510,13 +520,13 @@ where } #[instrument(level = "trace", target = "stor", skip_all, err)] - pub async fn delete_record(&mut self, key: RecordKey) -> VeilidAPIResult<()> { + pub async fn delete_record(&mut self, record_key: RecordKey) -> VeilidAPIResult<()> { // Get the record table key - let rtk = RecordTableKey { key }; + let rtk = RecordTableKey { record_key }; // Remove record from the index let Some(record) = self.record_index.remove(&rtk) else { - apibail_key_not_found!(key); + apibail_key_not_found!(rtk.record_key.clone()); }; // Remove watches @@ -526,7 +536,7 @@ where self.changed_watched_values.remove(&rtk); // Invalidate inspect cache for this key - self.inspect_cache.invalidate(&rtk.key); + self.inspect_cache.invalidate(&rtk.record_key); // Remove from table store immediately self.add_dead_record(rtk, record); @@ -536,19 +546,23 @@ where } #[instrument(level = "trace", target = "stor", skip_all)] - pub(super) fn contains_record(&mut self, key: RecordKey) -> bool { - let rtk = RecordTableKey { key }; + pub(super) fn contains_record(&mut self, record_key: &RecordKey) -> bool { + let rtk = RecordTableKey { + record_key: record_key.clone(), + }; self.record_index.contains_key(&rtk) } #[instrument(level = "trace", target = "stor", skip_all)] - pub(super) fn with_record(&mut self, key: RecordKey, f: F) -> Option + pub(super) fn with_record(&mut self, record_key: &RecordKey, f: F) -> Option where F: FnOnce(&Record) -> R, { // Get record from index let mut out = None; - let rtk = RecordTableKey { key }; + let rtk = RecordTableKey { + record_key: record_key.clone(), + }; if let Some(record) = self.record_index.get_mut(&rtk) { // Callback out = Some(f(record)); @@ -566,13 +580,15 @@ where } #[instrument(level = "trace", target = "stor", skip_all)] - pub(super) fn peek_record(&self, key: RecordKey, f: F) -> Option + pub(super) fn peek_record(&self, record_key: &RecordKey, f: F) -> Option where F: FnOnce(&Record) -> R, { // Get record from index let mut out = None; - let rtk = RecordTableKey { key }; + let rtk = RecordTableKey { + record_key: record_key.clone(), + }; if let Some(record) = self.record_index.peek(&rtk) { // Callback out = Some(f(record)); @@ -581,13 +597,15 @@ where } #[instrument(level = "trace", target = "stor", skip_all)] - pub(super) fn with_record_mut(&mut self, key: RecordKey, f: F) -> Option + pub(super) fn with_record_mut(&mut self, record_key: &RecordKey, f: F) -> Option where F: FnOnce(&mut Record) -> R, { // Get record from index let mut out = None; - let rtk = RecordTableKey { key }; + let rtk = RecordTableKey { + record_key: record_key.clone(), + }; if let Some(record) = self.record_index.get_mut(&rtk) { // Callback out = Some(f(record)); @@ -607,22 +625,24 @@ where #[instrument(level = "trace", target = "stor", skip_all, err)] pub async fn get_subkey( &mut self, - key: RecordKey, + record_key: RecordKey, subkey: ValueSubkey, want_descriptor: bool, ) -> VeilidAPIResult> { // Get record from index - let Some((subkey_count, has_subkey, opt_descriptor)) = self.with_record(key, |record| { - ( - record.subkey_count(), - record.stored_subkeys().contains(subkey), - if want_descriptor { - Some(record.descriptor().clone()) - } else { - None - }, - ) - }) else { + let Some((subkey_count, has_subkey, opt_descriptor)) = + self.with_record(&record_key, |record| { + ( + record.subkey_count(), + record.stored_subkeys().contains(subkey), + if want_descriptor { + Some(record.descriptor().clone()) + } else { + None + }, + ) + }) + else { // Record not available return Ok(None); }; @@ -642,7 +662,7 @@ where } // If subkey exists in subkey cache, use that - let stk = SubkeyTableKey { key, subkey }; + let stk = SubkeyTableKey { record_key, subkey }; if let Some(record_data) = self.subkey_cache.get(&stk) { let out = record_data.signed_value_data().clone(); @@ -675,22 +695,24 @@ where #[instrument(level = "trace", target = "stor", skip_all, err)] pub async fn peek_subkey( &self, - key: RecordKey, + record_key: RecordKey, subkey: ValueSubkey, want_descriptor: bool, ) -> VeilidAPIResult> { // record from index - let Some((subkey_count, has_subkey, opt_descriptor)) = self.peek_record(key, |record| { - ( - record.subkey_count(), - record.stored_subkeys().contains(subkey), - if want_descriptor { - Some(record.descriptor().clone()) - } else { - None - }, - ) - }) else { + let Some((subkey_count, has_subkey, opt_descriptor)) = + self.peek_record(&record_key, |record| { + ( + record.subkey_count(), + record.stored_subkeys().contains(subkey), + if want_descriptor { + Some(record.descriptor().clone()) + } else { + None + }, + ) + }) + else { // Record not available return Ok(None); }; @@ -710,7 +732,7 @@ where } // If subkey exists in subkey cache, use that - let stk = SubkeyTableKey { key, subkey }; + let stk = SubkeyTableKey { record_key, subkey }; if let Some(record_data) = self.subkey_cache.peek(&stk) { let out = record_data.signed_value_data().clone(); @@ -740,7 +762,7 @@ where #[instrument(level = "trace", target = "stor", skip_all)] async fn update_watched_value( &mut self, - key: RecordKey, + record_key: RecordKey, subkey: ValueSubkey, watch_update_mode: InboundWatchUpdateMode, ) { @@ -753,7 +775,7 @@ where return; } - let rtk = RecordTableKey { key }; + let rtk = RecordTableKey { record_key }; let Some(wr) = self.watched_records.get_mut(&rtk) else { return; }; @@ -779,7 +801,7 @@ where #[instrument(level = "trace", target = "stor", skip_all, err)] pub async fn set_subkey( &mut self, - key: RecordKey, + record_key: RecordKey, subkey: ValueSubkey, signed_value_data: Arc, watch_update_mode: InboundWatchUpdateMode, @@ -794,10 +816,12 @@ where } // Get record subkey count and total size of all record subkey data exclusive of structures - let Some((subkey_count, prior_record_data_size)) = self.with_record(key, |record| { - (record.subkey_count(), record.record_data_size()) - }) else { - apibail_invalid_argument!("no record at this key", "key", key); + let Some((subkey_count, prior_record_data_size)) = self + .with_record(&record_key, |record| { + (record.subkey_count(), record.record_data_size()) + }) + else { + apibail_invalid_argument!("no record at this key", "key", record_key); }; // Check if the subkey is in range @@ -809,7 +833,10 @@ where let mut prior_subkey_size = 0usize; // If subkey exists in subkey cache, use that - let stk = SubkeyTableKey { key, subkey }; + let stk = SubkeyTableKey { + record_key: record_key.clone(), + subkey, + }; let stk_bytes = stk.bytes(); if let Some(record_data) = self.subkey_cache.peek(&stk) { @@ -855,7 +882,7 @@ where // Write to inspect cache self.inspect_cache.replace_subkey_seq( - &stk.key, + &stk.record_key, subkey, subkey_record_data.signed_value_data().value_data().seq(), ); @@ -864,7 +891,7 @@ where self.add_to_subkey_cache(stk, subkey_record_data); // Update record - self.with_record_mut(key, |record| { + self.with_record_mut(&record_key, |record| { record.store_subkey(subkey); record.set_record_data_size(new_record_data_size); }) @@ -874,7 +901,7 @@ where self.total_storage_space.commit().unwrap(); // Send updates to - self.update_watched_value(key, subkey, watch_update_mode) + self.update_watched_value(record_key, subkey, watch_update_mode) .await; Ok(()) @@ -883,12 +910,12 @@ where #[instrument(level = "trace", target = "stor", skip_all, err)] pub async fn inspect_record( &mut self, - key: RecordKey, + record_key: RecordKey, subkeys: &ValueSubkeyRangeSet, want_descriptor: bool, ) -> VeilidAPIResult> { // Get record from index - let Some((schema_subkeys, opt_descriptor)) = self.with_record(key, |record| { + let Some((schema_subkeys, opt_descriptor)) = self.with_record(&record_key, |record| { // Get number of subkeys from schema and ensure we are getting the // right number of sequence numbers betwen that and what we asked for let schema_subkeys = record @@ -917,7 +944,7 @@ where } // See if we have this inspection cached - if let Some(icv) = self.inspect_cache.get(&key, &schema_subkeys) { + if let Some(icv) = self.inspect_cache.get(&record_key, &schema_subkeys) { return Ok(Some(InspectResult::new( self, subkeys.clone(), @@ -932,7 +959,10 @@ where #[allow(clippy::unnecessary_cast)] let mut seqs = Vec::with_capacity(schema_subkeys.len() as usize); for subkey in schema_subkeys.iter() { - let stk = SubkeyTableKey { key, subkey }; + let stk = SubkeyTableKey { + record_key: record_key.clone(), + subkey, + }; let opt_seq = if let Some(record_data) = self.subkey_cache.peek(&stk) { Some(record_data.signed_value_data().value_data().seq()) } else { @@ -949,7 +979,7 @@ where // Save seqs cache self.inspect_cache.put( - key, + record_key, schema_subkeys.clone(), InspectCacheL2Value { seqs: seqs.clone() }, ); @@ -967,7 +997,7 @@ where #[instrument(level = "trace", target = "stor", skip_all, err)] pub async fn _change_existing_watch( &mut self, - key: RecordKey, + record_key: RecordKey, params: InboundWatchParameters, watch_id: u64, ) -> VeilidAPIResult { @@ -978,7 +1008,7 @@ where apibail_internal!("zero expiration should have been resolved to max by now"); } // Get the watch list for this record - let rtk = RecordTableKey { key }; + let rtk = RecordTableKey { record_key }; let Some(watch_list) = self.watched_records.get_mut(&rtk) else { // No watches, nothing to change return Ok(InboundWatchResult::Rejected); @@ -988,7 +1018,7 @@ where for w in &mut watch_list.watches { // If the watch id doesn't match, then we're not updating // Also do not allow the watcher key to change - if w.id == watch_id && w.params.watcher == params.watcher { + if w.id == watch_id && w.params.watcher_member_id == params.watcher_member_id { // Updating an existing watch w.params = params; return Ok(InboundWatchResult::Changed { @@ -1004,12 +1034,14 @@ where #[instrument(level = "trace", target = "stor", skip_all, err)] pub async fn _create_new_watch( &mut self, - key: RecordKey, + record_key: RecordKey, params: InboundWatchParameters, - member_check: Box bool + Send>, + member_check: Box bool + Send>, ) -> VeilidAPIResult { // Generate a record-unique watch id > 0 - let rtk = RecordTableKey { key }; + let rtk = RecordTableKey { + record_key: record_key.clone(), + }; let mut id = 0; while id == 0 { id = get_random_u64(); @@ -1036,19 +1068,18 @@ where let mut watch_count = 0; let mut target_watch_count = 0; - let is_member = member_check(params.watcher); + let is_member = member_check(¶ms.watcher_member_id); - let rtk = RecordTableKey { key }; if let Some(watched_record) = self.watched_records.get_mut(&rtk) { // Total up the number of watches for this key for w in &mut watched_record.watches { // See if this watch should be counted toward any limits let count_watch = if is_member { // If the watcher is a member of the schema, then consider the total per-watcher key - w.params.watcher == params.watcher + w.params.watcher_member_id == params.watcher_member_id } else { // If the watcher is not a member of the schema, the check if this watch is an anonymous watch and contributes to per-record key total - !member_check(w.params.watcher) + !member_check(&w.params.watcher_member_id) }; // For any watch, if the target matches our also tally that separately @@ -1095,14 +1126,16 @@ where #[instrument(level = "trace", target = "stor", skip_all, err)] pub async fn watch_record( &mut self, - key: RecordKey, + record_key: RecordKey, mut params: InboundWatchParameters, opt_watch_id: Option, ) -> VeilidAPIResult { // If count is zero then we're cancelling a watch completely if params.count == 0 { if let Some(watch_id) = opt_watch_id { - let cancelled = self.cancel_watch(key, watch_id, params.watcher).await?; + let cancelled = self + .cancel_watch(record_key.clone(), watch_id, params.watcher_member_id) + .await?; if cancelled { return Ok(InboundWatchResult::Cancelled); } @@ -1122,7 +1155,9 @@ where } else if params.expiration.as_u64() < min_ts { // Don't add watches with too low of an expiration time if let Some(watch_id) = opt_watch_id { - let cancelled = self.cancel_watch(key, watch_id, params.watcher).await?; + let cancelled = self + .cancel_watch(record_key, watch_id, params.watcher_member_id) + .await?; if cancelled { return Ok(InboundWatchResult::Cancelled); } @@ -1131,20 +1166,26 @@ where } // Make a closure to check for member vs anonymous - let Some(member_check) = self.with_record(key, |record| { + let Some((schema, owner)) = self.with_record(&record_key, |record| { let schema = record.schema(); - let owner = *record.owner(); - Box::new(move |watcher| owner == watcher || schema.is_member(&watcher)) + let owner = record.owner(); + (schema, owner) }) else { // Record not found return Ok(InboundWatchResult::Rejected); }; + let owner_member_id = self.storage_manager().generate_member_id(&owner)?; + let member_check = Box::new(move |watcher: &MemberId| { + owner_member_id == *watcher || schema.is_member(watcher.ref_value()) + }); // Create or update depending on if a watch id is specified or not if let Some(watch_id) = opt_watch_id { - self._change_existing_watch(key, params, watch_id).await + self._change_existing_watch(record_key, params, watch_id) + .await } else { - self._create_new_watch(key, params, member_check).await + self._create_new_watch(record_key, params, member_check) + .await } } @@ -1153,22 +1194,22 @@ where #[instrument(level = "trace", target = "stor", skip_all, err)] async fn cancel_watch( &mut self, - key: RecordKey, + record_key: RecordKey, watch_id: u64, - watcher: BarePublicKey, + watcher_member_id: MemberId, ) -> VeilidAPIResult { if watch_id == 0 { apibail_internal!("should not have let a zero watch id get here"); } // See if we are cancelling an existing watch - let rtk = RecordTableKey { key }; + let rtk = RecordTableKey { record_key }; let mut is_empty = false; let mut ret = false; if let Some(watch_list) = self.watched_records.get_mut(&rtk) { let mut dead_watcher = None; for (wn, w) in watch_list.watches.iter_mut().enumerate() { // Must match the watch id and the watcher key to cancel - if w.id == watch_id && w.params.watcher == watcher { + if w.id == watch_id && w.params.watcher_member_id == watcher_member_id { // Canceling an existing watch dead_watcher = Some(wn); ret = true; @@ -1193,15 +1234,15 @@ where #[instrument(level = "trace", target = "stor", skip_all)] pub fn move_watches( &mut self, - key: RecordKey, + record_key: RecordKey, in_watch: Option<(InboundWatchList, bool)>, ) -> Option<(InboundWatchList, bool)> { - let rtk = RecordTableKey { key }; + let rtk = RecordTableKey { record_key }; let out = self.watched_records.remove(&rtk); if let Some(in_watch) = in_watch { - self.watched_records.insert(rtk, in_watch.0); + self.watched_records.insert(rtk.clone(), in_watch.0); if in_watch.1 { - self.changed_watched_values.insert(rtk); + self.changed_watched_values.insert(rtk.clone()); } } let is_watched = self.changed_watched_values.remove(&rtk); @@ -1263,8 +1304,8 @@ where } evcis.push(EarlyValueChangedInfo { - target: w.params.target, - key: rtk.key, + target: w.params.target.clone(), + key: rtk.record_key.clone(), subkeys, count, watch_id: w.id, @@ -1276,6 +1317,7 @@ where watch.watches.remove(dw); if watch.watches.is_empty() { empty_watched_records.push(rtk); + break; } } } @@ -1290,7 +1332,7 @@ where veilid_log!(self error "first subkey should exist for value change notification"); continue; }; - let get_result = match self.get_subkey(evci.key, first_subkey, false).await { + let get_result = match self.get_subkey(evci.key.clone(), first_subkey, false).await { Ok(Some(skr)) => skr, Ok(None) => { veilid_log!(self error "subkey should have data for value change notification"); @@ -1345,7 +1387,7 @@ where for (rik, rec) in &self.record_index { out += &format!( " {} age={} len={} subkeys={}\n", - rik.key, + rik.record_key, display_duration(get_timestamp() - rec.last_touched().as_u64()), rec.record_data_size(), rec.stored_subkeys(), @@ -1359,21 +1401,21 @@ where out += &format!("Total Storage Space: {}\n", self.total_storage_space.get()); out += &format!("Dead Records: {}\n", self.dead_records.len()); for dr in &self.dead_records { - out += &format!(" {}\n", dr.key.key); + out += &format!(" {}\n", dr.key.record_key); } out += &format!("Changed Records: {}\n", self.changed_records.len()); for cr in &self.changed_records { - out += &format!(" {}\n", cr.key); + out += &format!(" {}\n", cr.record_key); } out } - pub fn debug_record_info(&self, key: RecordKey) -> String { + pub fn debug_record_info(&self, record_key: RecordKey) -> String { let record_info = self - .peek_record(key, |r| format!("{:#?}", r)) + .peek_record(&record_key, |r| format!("{:#?}", r)) .unwrap_or("Not found".to_owned()); - let watched_record = match self.watched_records.get(&RecordTableKey { key }) { + let watched_record = match self.watched_records.get(&RecordTableKey { record_key }) { Some(w) => { format!("Remote Watches: {:#?}", w) } @@ -1382,8 +1424,12 @@ where format!("{}\n{}\n", record_info, watched_record) } - pub async fn debug_record_subkey_info(&self, key: RecordKey, subkey: ValueSubkey) -> String { - match self.peek_subkey(key, subkey, true).await { + pub async fn debug_record_subkey_info( + &self, + record_key: RecordKey, + subkey: ValueSubkey, + ) -> String { + match self.peek_subkey(record_key, subkey, true).await { Ok(Some(v)) => { format!("{:#?}", v) } diff --git a/veilid-core/src/storage_manager/record_store/opened_record.rs b/veilid-core/src/storage_manager/record_store/opened_record.rs index de382089..afc210de 100644 --- a/veilid-core/src/storage_manager/record_store/opened_record.rs +++ b/veilid-core/src/storage_manager/record_store/opened_record.rs @@ -7,29 +7,29 @@ pub(in crate::storage_manager) struct OpenedRecord { /// The key pair used to perform writes to subkey on this opened record /// Without this, set_value() will fail regardless of which key or subkey is being written to /// as all writes are signed - writer: Option, + writer: Option, /// The safety selection in current use safety_selection: SafetySelection, } impl OpenedRecord { - pub fn new(writer: Option, safety_selection: SafetySelection) -> Self { + pub fn new(writer: Option, safety_selection: SafetySelection) -> Self { Self { writer, safety_selection, } } - pub fn writer(&self) -> Option<&BareKeyPair> { + pub fn writer(&self) -> Option<&KeyPair> { self.writer.as_ref() } - pub fn set_writer(&mut self, writer: Option) { + pub fn set_writer(&mut self, writer: Option) { self.writer = writer; } pub fn safety_selection(&self) -> SafetySelection { - self.safety_selection + self.safety_selection.clone() } pub fn set_safety_selection(&mut self, safety_selection: SafetySelection) { self.safety_selection = safety_selection; diff --git a/veilid-core/src/storage_manager/record_store/record.rs b/veilid-core/src/storage_manager/record_store/record.rs index 4d1bac76..b7695310 100644 --- a/veilid-core/src/storage_manager/record_store/record.rs +++ b/veilid-core/src/storage_manager/record_store/record.rs @@ -37,7 +37,7 @@ where pub fn descriptor(&self) -> Arc { self.descriptor.clone() } - pub fn owner(&self) -> &BarePublicKey { + pub fn owner(&self) -> PublicKey { self.descriptor.owner() } diff --git a/veilid-core/src/storage_manager/rehydrate.rs b/veilid-core/src/storage_manager/rehydrate.rs index 22435990..99eec59a 100644 --- a/veilid-core/src/storage_manager/rehydrate.rs +++ b/veilid-core/src/storage_manager/rehydrate.rs @@ -77,8 +77,8 @@ impl StorageManager { let Some(local_record_store) = inner.local_record_store.as_mut() else { apibail_not_initialized!(); }; - let Some(safety_selection) = - local_record_store.with_record(record_key, |rec| rec.detail().safety_selection) + let Some(safety_selection) = local_record_store + .with_record(&record_key, |rec| rec.detail().safety_selection.clone()) else { apibail_key_not_found!(record_key); }; @@ -88,7 +88,7 @@ impl StorageManager { // See if the requested record is our local record store let local_inspect_result = self - .handle_inspect_local_value_inner(&mut inner, record_key, subkeys.clone(), true) + .handle_inspect_local_value_inner(&mut inner, record_key.clone(), subkeys.clone(), true) .await?; // Get rpc processor and drop mutex so we don't block while getting the value from the network @@ -105,9 +105,9 @@ impl StorageManager { // Get the inspect record report from the network let result = self .outbound_inspect_value( - record_key, + record_key.clone(), local_inspect_result.subkeys().clone(), - safety_selection, + safety_selection.clone(), InspectResult::default(), true, ) @@ -119,7 +119,7 @@ impl StorageManager { { return self .rehydrate_all_subkeys( - record_key, + record_key.clone(), subkeys, consensus_count, safety_selection, @@ -130,7 +130,7 @@ impl StorageManager { return self .rehydrate_required_subkeys( - record_key, + record_key.clone(), subkeys, consensus_count, safety_selection, @@ -149,7 +149,7 @@ impl StorageManager { ) -> bool { // Get value to rehydrate with let get_result = match self - .handle_get_local_value_inner(inner, record_key, subkey, false) + .handle_get_local_value_inner(inner, record_key.clone(), subkey, false) .await { Ok(v) => v, @@ -192,7 +192,12 @@ impl StorageManager { if local_inspect_result.seqs()[n].is_some() { // Rehydrate subkey if self - .rehydrate_single_subkey_inner(&mut inner, record_key, subkey, safety_selection) + .rehydrate_single_subkey_inner( + &mut inner, + record_key.clone(), + subkey, + safety_selection.clone(), + ) .await { rehydrated.insert(subkey); @@ -228,7 +233,7 @@ impl StorageManager { // Get cryptosystem let crypto = self.crypto(); - let Some(vcrypto) = crypto.get(record_key.kind) else { + let Some(vcrypto) = crypto.get(record_key.kind()) else { apibail_generic!("unsupported cryptosystem"); }; @@ -248,7 +253,12 @@ impl StorageManager { if sfr.consensus_nodes.len() < consensus_count { // Rehydrate subkey if self - .rehydrate_single_subkey_inner(&mut inner, record_key, subkey, safety_selection) + .rehydrate_single_subkey_inner( + &mut inner, + record_key.clone(), + subkey, + safety_selection.clone(), + ) .await { rehydrated.insert(subkey); @@ -273,7 +283,7 @@ impl StorageManager { Self::process_fanout_results_inner( &mut inner, &vcrypto, - record_key, + record_key.clone(), results_iter, false, self.config() diff --git a/veilid-core/src/storage_manager/schema.rs b/veilid-core/src/storage_manager/schema.rs new file mode 100644 index 00000000..39a5e4ae --- /dev/null +++ b/veilid-core/src/storage_manager/schema.rs @@ -0,0 +1,160 @@ +use super::*; + +impl StorageManager { + /// Produce member id from writer public key + pub fn generate_member_id(&self, writer_key: &PublicKey) -> VeilidAPIResult { + if writer_key.ref_value().len() == MEMBER_ID_LENGTH { + return Ok(MemberId::new( + writer_key.kind(), + BareMemberId::new(writer_key.ref_value()), + )); + } + let crypto = self.crypto(); + let Some(vcrypto) = crypto.get(writer_key.kind()) else { + apibail_generic!("unsupported cryptosystem"); + }; + + let idhash = vcrypto.generate_hash(writer_key.ref_value()); + assert!( + idhash.len() >= MEMBER_ID_LENGTH, + "generate_hash needs to produce at least {} bytes", + MEMBER_ID_LENGTH + ); + Ok(MemberId::new( + writer_key.kind(), + BareMemberId::new(&idhash[0..MEMBER_ID_LENGTH]), + )) + } + + /// Check a subkey value data against the schema + pub fn check_subkey_value_data( + &self, + schema: &DHTSchema, + owner: &PublicKey, + subkey: ValueSubkey, + value_data: &ValueData, + ) -> VeilidAPIResult<()> { + match schema { + DHTSchema::DFLT(d) => self.check_subkey_value_data_dflt(d, owner, subkey, value_data), + DHTSchema::SMPL(s) => self.check_subkey_value_data_smpl(s, owner, subkey, value_data), + } + } + + /// Check a subkey value data against the DFLT schema + pub fn check_subkey_value_data_dflt( + &self, + schema_dflt: &DHTSchemaDFLT, + owner: &PublicKey, + subkey: ValueSubkey, + value_data: &ValueData, + ) -> VeilidAPIResult<()> { + let subkey = subkey as usize; + + // Check if subkey is in owner range + if subkey < (schema_dflt.o_cnt() as usize) { + // Check value data has valid writer + if value_data.ref_writer() == owner { + let max_value_len = usize::min( + MAX_SUBKEY_SIZE, + MAX_RECORD_DATA_SIZE / schema_dflt.o_cnt() as usize, + ); + + // Ensure value size is within additional limit + if value_data.data_size() <= max_value_len { + return Ok(()); + } + + // Value too big + apibail_invalid_argument!( + "value too big", + "data", + format!("{:?}", value_data.data()) + ); + } + + // Wrong writer + apibail_invalid_argument!( + "wrong writer", + "writer", + format!("{:?} != {:?}", value_data.writer(), owner) + ); + } + + // Subkey out of range + apibail_invalid_argument!("subkey out of range", "subkey", subkey); + } + + /// Check a subkey value data against the SMPL schema + pub(crate) fn check_subkey_value_data_smpl( + &self, + schema_smpl: &DHTSchemaSMPL, + owner: &PublicKey, + subkey: ValueSubkey, + value_data: &ValueData, + ) -> VeilidAPIResult<()> { + let mut cur_subkey = subkey as usize; + + let max_value_len = usize::min( + MAX_SUBKEY_SIZE, + MAX_RECORD_DATA_SIZE / (schema_smpl.max_subkey() + 1) as usize, + ); + + // Check if subkey is in owner range + if cur_subkey < (schema_smpl.o_cnt() as usize) { + // Check value data has valid writer + if value_data.ref_writer() == owner { + // Ensure value size is within additional limit + if value_data.data_size() <= max_value_len { + return Ok(()); + } + + // Value too big + apibail_invalid_argument!( + "value too big", + "data", + format!("{:?}", value_data.data()) + ); + } + // Wrong writer + apibail_invalid_argument!( + "wrong writer", + "writer", + format!("{:?}", value_data.writer()) + ); + } + cur_subkey -= schema_smpl.o_cnt() as usize; + + let writer_hash = self.generate_member_id(value_data.ref_writer())?; + + // Check all member ranges + for m in schema_smpl.members() { + // Check if subkey is in member range + if cur_subkey < (m.m_cnt as usize) { + // Check value data has valid writer + if writer_hash.ref_value() == &m.m_key { + // Ensure value size is in allowed range + if value_data.data_size() <= max_value_len { + return Ok(()); + } + + // Value too big + apibail_invalid_argument!( + "value too big", + "data", + format!("{:?}", value_data.data()) + ); + } + // Wrong writer + apibail_invalid_argument!( + "wrong writer", + "writer", + format!("{:?}", value_data.writer()) + ); + } + cur_subkey -= m.m_cnt as usize; + } + + // Subkey out of range + apibail_invalid_argument!("subkey out of range", "subkey", subkey); + } +} diff --git a/veilid-core/src/storage_manager/set_value.rs b/veilid-core/src/storage_manager/set_value.rs index c701e6ec..0f88199a 100644 --- a/veilid-core/src/storage_manager/set_value.rs +++ b/veilid-core/src/storage_manager/set_value.rs @@ -48,7 +48,7 @@ impl StorageManager { // Get the nodes we know are caching this value to seed the fanout let init_fanout_queue = { - self.get_value_nodes(record_key) + self.get_value_nodes(record_key.clone()) .await? .unwrap_or_default() .into_iter() @@ -76,12 +76,16 @@ impl StorageManager { let call_routine = { let context = context.clone(); let registry = self.registry(); + let record_key = record_key.clone(); + let safety_selection = safety_selection.clone(); Arc::new( move |next_node: NodeRef| -> PinBoxFutureStatic { let registry = registry.clone(); let context = context.clone(); let descriptor = descriptor.clone(); + let record_key = record_key.clone(); + let safety_selection = safety_selection.clone(); Box::pin(async move { let rpc_processor = registry.rpc_processor(); @@ -99,7 +103,7 @@ impl StorageManager { .rpc_call_set_value( Destination::direct(next_node.routing_domain_filtered(routing_domain)) .with_safety(safety_selection), - record_key, + record_key.clone(), subkey, (*value).clone(), (*descriptor).clone(), @@ -142,8 +146,8 @@ impl StorageManager { veilid_log!(registry debug "SetValue got value back: len={} seq={}", value.value_data().data().len(), value.value_data().seq()); // Validate with schema - if ctx.schema.check_subkey_value_data( - descriptor.owner(), + if registry.storage_manager().check_subkey_value_data(&ctx.schema, + descriptor.ref_owner(), subkey, value.value_data(), ).is_err() { @@ -284,12 +288,15 @@ impl StorageManager { ) { let registry = self.registry(); let last_requested_value_data = Arc::new(Mutex::new(requested_value_data)); + self.process_deferred_results( res_rx, Box::new( move |result: VeilidAPIResult| -> PinBoxFutureStatic { let registry = registry.clone(); let last_requested_value_data = last_requested_value_data.clone(); + let safety_selection = safety_selection.clone(); + let record_key = record_key.clone(); Box::pin(async move { let this = registry.storage_manager(); @@ -302,7 +309,7 @@ impl StorageManager { }; let is_incomplete = result.fanout_result.kind.is_incomplete(); let requested_value_data = last_requested_value_data.lock().clone(); - let value_data = match this.process_outbound_set_value_result(record_key, subkey, requested_value_data, safety_selection, result).await { + let value_data = match this.process_outbound_set_value_result(record_key.clone(), subkey, requested_value_data, safety_selection, result).await { Ok(Some(v)) => v, Ok(None) => { return is_incomplete; @@ -351,7 +358,7 @@ impl StorageManager { ) -> Result, VeilidAPIError> { // Get cryptosystem let crypto = self.crypto(); - let Some(vcrypto) = crypto.get(record_key.kind) else { + let Some(vcrypto) = crypto.get(record_key.kind()) else { apibail_generic!("unsupported cryptosystem"); }; @@ -359,12 +366,13 @@ impl StorageManager { let mut inner = self.inner.lock().await; // Report on fanout result offline - let was_offline = self.check_fanout_set_offline(record_key, subkey, &result.fanout_result); + let was_offline = + self.check_fanout_set_offline(record_key.clone(), subkey, &result.fanout_result); if was_offline { // Failed to write, try again later self.add_offline_subkey_write_inner( &mut inner, - record_key, + record_key.clone(), subkey, safety_selection, result.signed_value_data.clone(), @@ -375,7 +383,7 @@ impl StorageManager { Self::process_fanout_results_inner( &mut inner, &vcrypto, - record_key, + record_key.clone(), core::iter::once((ValueSubkeyRangeSet::single(subkey), result.fanout_result)), true, self.config() @@ -407,7 +415,7 @@ impl StorageManager { #[instrument(level = "trace", target = "dht", skip_all)] pub async fn inbound_set_value( &self, - key: RecordKey, + record_key: RecordKey, subkey: ValueSubkey, value: Arc, descriptor: Option>, @@ -419,15 +427,20 @@ impl StorageManager { let (is_local, last_get_result) = { // See if the subkey we are modifying has a last known local value let last_get_result = self - .handle_get_local_value_inner(&mut inner, key, subkey, true) + .handle_get_local_value_inner(&mut inner, record_key.clone(), subkey, true) .await?; // If this is local, it must have a descriptor already if last_get_result.opt_descriptor.is_some() { (true, last_get_result) } else { // See if the subkey we are modifying has a last known remote value - let last_get_result = - Self::handle_get_remote_value_inner(&mut inner, key, subkey, true).await?; + let last_get_result = Self::handle_get_remote_value_inner( + &mut inner, + record_key.clone(), + subkey, + true, + ) + .await?; (false, last_get_result) } }; @@ -480,8 +493,13 @@ impl StorageManager { }; // Validate new value with schema - if schema - .check_subkey_value_data(actual_descriptor.owner(), subkey, value.value_data()) + if self + .check_subkey_value_data( + &schema, + actual_descriptor.ref_owner(), + subkey, + value.value_data(), + ) .is_err() { // Validation failed, ignore this value @@ -492,7 +510,7 @@ impl StorageManager { let res = if is_local { self.handle_set_local_value_inner( &mut inner, - key, + record_key.clone(), subkey, value, InboundWatchUpdateMode::ExcludeTarget(target), @@ -501,7 +519,7 @@ impl StorageManager { } else { Self::handle_set_remote_value_inner( &mut inner, - key, + record_key.clone(), subkey, value, actual_descriptor, diff --git a/veilid-core/src/storage_manager/tasks/check_outbound_watches.rs b/veilid-core/src/storage_manager/tasks/check_outbound_watches.rs index 96028920..2724c6ec 100644 --- a/veilid-core/src/storage_manager/tasks/check_outbound_watches.rs +++ b/veilid-core/src/storage_manager/tasks/check_outbound_watches.rs @@ -20,7 +20,8 @@ impl StorageManager { // Iterate all outbound watches and determine what work needs doing if any for (k, v) in &mut inner.outbound_watch_manager.outbound_watches { // Get next work on watch and queue it if we have something to do - if let Some(op_fut) = self.get_next_outbound_watch_operation(*k, None, cur_ts, v) { + if let Some(op_fut) = self.get_next_outbound_watch_operation(k.clone(), None, cur_ts, v) + { self.background_operation_processor.add_future(op_fut); }; } diff --git a/veilid-core/src/storage_manager/tasks/offline_subkey_writes.rs b/veilid-core/src/storage_manager/tasks/offline_subkey_writes.rs index 0592e74a..b7d224c2 100644 --- a/veilid-core/src/storage_manager/tasks/offline_subkey_writes.rs +++ b/veilid-core/src/storage_manager/tasks/offline_subkey_writes.rs @@ -41,7 +41,7 @@ impl StorageManager { }; let get_result = { let mut inner = self.inner.lock().await; - self.handle_get_local_value_inner(&mut inner, key, subkey, true) + self.handle_get_local_value_inner(&mut inner, key.clone(), subkey, true) .await }; let Ok(get_result) = get_result else { @@ -60,7 +60,13 @@ impl StorageManager { }; veilid_log!(self debug "Offline subkey write: {}:{} len={}", key, subkey, value.value_data().data().len()); let osvres = self - .outbound_set_value(key, subkey, safety_selection, value.clone(), descriptor) + .outbound_set_value( + key.clone(), + subkey, + safety_selection, + value.clone(), + descriptor, + ) .await; match osvres { Ok(res_rx) => { @@ -80,7 +86,7 @@ impl StorageManager { self.handle_set_local_value_inner( &mut inner, - key, + key.clone(), subkey, result.signed_value_data.clone(), InboundWatchUpdateMode::UpdateAll, @@ -124,9 +130,9 @@ impl StorageManager { let result = match self .write_single_offline_subkey( stop_token.clone(), - work_item.record_key, + work_item.record_key.clone(), subkey, - work_item.safety_selection, + work_item.safety_selection.clone(), ) .await? { @@ -143,8 +149,11 @@ impl StorageManager { }; // Process non-partial setvalue result - let was_offline = - self.check_fanout_set_offline(work_item.record_key, subkey, &result.fanout_result); + let was_offline = self.check_fanout_set_offline( + work_item.record_key.clone(), + subkey, + &result.fanout_result, + ); if !was_offline { written_subkeys.insert(subkey); } @@ -174,14 +183,14 @@ impl StorageManager { let subkeys_still_offline = result.work_item.subkeys.difference(&result.written_subkeys); self.finish_offline_subkey_writes_inner( &mut inner, - result.work_item.record_key, + result.work_item.record_key.clone(), result.written_subkeys, subkeys_still_offline, ); // Keep the list of nodes that returned a value for later reference let crypto = self.crypto(); - let vcrypto = crypto.get(result.work_item.record_key.kind).unwrap(); + let vcrypto = crypto.get(result.work_item.record_key.kind()).unwrap(); Self::process_fanout_results_inner( &mut inner, @@ -210,8 +219,8 @@ impl StorageManager { osw.subkeys_in_flight.insert(sk); // And return a work item for it return Some(WorkItem { - record_key: *record_key, - safety_selection: osw.safety_selection, + record_key: record_key.clone(), + safety_selection: osw.safety_selection.clone(), subkeys: ValueSubkeyRangeSet::single(sk), }); } diff --git a/veilid-core/src/storage_manager/tasks/rehydrate_records.rs b/veilid-core/src/storage_manager/tasks/rehydrate_records.rs index 67431abc..a1fe9059 100644 --- a/veilid-core/src/storage_manager/tasks/rehydrate_records.rs +++ b/veilid-core/src/storage_manager/tasks/rehydrate_records.rs @@ -20,7 +20,7 @@ impl StorageManager { for req in reqs { futs.push(async move { let res = self - .rehydrate_record(req.0, req.1.subkeys.clone(), req.1.consensus_count) + .rehydrate_record(req.0.clone(), req.1.subkeys.clone(), req.1.consensus_count) .await; let _report = match res { diff --git a/veilid-core/src/storage_manager/types/signed_value_data.rs b/veilid-core/src/storage_manager/types/signed_value_data.rs index c0970fbe..8c03d7b6 100644 --- a/veilid-core/src/storage_manager/types/signed_value_data.rs +++ b/veilid-core/src/storage_manager/types/signed_value_data.rs @@ -5,10 +5,10 @@ use super::*; #[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize)] pub struct SignedValueData { value_data: ValueData, - signature: BareSignature, + signature: Signature, } impl SignedValueData { - pub fn new(value_data: ValueData, signature: BareSignature) -> Self { + pub fn new(value_data: ValueData, signature: Signature) -> Self { Self { value_data, signature, @@ -17,26 +17,43 @@ impl SignedValueData { pub fn validate( &self, - owner: &BarePublicKey, + owner: &PublicKey, subkey: ValueSubkey, vcrypto: &CryptoSystemGuard<'_>, ) -> VeilidAPIResult { let node_info_bytes = Self::make_signature_bytes(&self.value_data, owner, subkey)?; + if vcrypto.kind() != self.value_data.ref_writer().kind() { + return Ok(false); + } + if vcrypto.kind() != self.signature.kind() { + return Ok(false); + } // validate signature - vcrypto.verify(self.value_data.writer(), &node_info_bytes, &self.signature) + vcrypto.verify( + self.value_data.ref_writer().ref_value(), + &node_info_bytes, + self.signature.ref_value(), + ) } pub fn make_signature( value_data: ValueData, - owner: &BarePublicKey, + owner: &PublicKey, subkey: ValueSubkey, vcrypto: &CryptoSystemGuard<'_>, - writer_secret: BareSecretKey, + writer_secret: &BareSecretKey, ) -> VeilidAPIResult { let node_info_bytes = Self::make_signature_bytes(&value_data, owner, subkey)?; // create signature - let signature = vcrypto.sign(value_data.writer(), &writer_secret, &node_info_bytes)?; + let signature = Signature::new( + vcrypto.kind(), + vcrypto.sign( + value_data.ref_writer().ref_value(), + writer_secret, + &node_info_bytes, + )?, + ); Ok(Self { value_data, signature, @@ -47,7 +64,7 @@ impl SignedValueData { &self.value_data } - pub fn signature(&self) -> &BareSignature { + pub fn signature(&self) -> &Signature { &self.signature } @@ -61,14 +78,25 @@ impl SignedValueData { fn make_signature_bytes( value_data: &ValueData, - owner: &BarePublicKey, + owner: &PublicKey, subkey: ValueSubkey, ) -> VeilidAPIResult> { - let mut node_info_bytes = - Vec::with_capacity(PUBLIC_KEY_LENGTH + 4 + 4 + value_data.data().len()); + let owner_len; + let is_vld0 = if owner.kind() == CRYPTO_KIND_VLD0 { + owner_len = owner.ref_value().len(); + true + } else { + owner_len = owner.ref_value().len() + 4; + false + }; + + let mut node_info_bytes = Vec::with_capacity(owner_len + 4 + 4 + value_data.data().len()); // Add owner to signature - node_info_bytes.extend_from_slice(&owner.bytes); + if !is_vld0 { + node_info_bytes.extend_from_slice(&owner.kind().0); + } + node_info_bytes.extend_from_slice(owner.ref_value()); // Add subkey to signature node_info_bytes.extend_from_slice(&subkey.to_le_bytes()); // Add sequence number to signature diff --git a/veilid-core/src/storage_manager/types/signed_value_descriptor.rs b/veilid-core/src/storage_manager/types/signed_value_descriptor.rs index 4da6c276..3fc927f1 100644 --- a/veilid-core/src/storage_manager/types/signed_value_descriptor.rs +++ b/veilid-core/src/storage_manager/types/signed_value_descriptor.rs @@ -4,12 +4,14 @@ use super::*; #[derive(Clone, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize)] pub struct SignedValueDescriptor { - owner: BarePublicKey, + #[serde(with = "public_key_try_untyped_vld0")] + owner: PublicKey, schema_data: Vec, - signature: BareSignature, + #[serde(with = "signature_try_untyped_vld0")] + signature: Signature, } impl SignedValueDescriptor { - pub fn new(owner: BarePublicKey, schema_data: Vec, signature: BareSignature) -> Self { + pub fn new(owner: PublicKey, schema_data: Vec, signature: Signature) -> Self { Self { owner, schema_data, @@ -18,11 +20,27 @@ impl SignedValueDescriptor { } pub fn validate(&self, vcrypto: &CryptoSystemGuard<'_>) -> VeilidAPIResult<()> { + if self.owner.kind() != vcrypto.kind() { + apibail_parse_error!( + "wrong kind of owner for signed value descriptor", + &self.owner + ); + } + if self.signature.kind() != vcrypto.kind() { + apibail_parse_error!( + "wrong kind of signature for signed value descriptor", + &self.signature + ); + } // validate signature - if !vcrypto.verify(&self.owner, &self.schema_data, &self.signature)? { + if !vcrypto.verify( + self.owner.ref_value(), + &self.schema_data, + self.signature.ref_value(), + )? { apibail_parse_error!( "failed to validate signature of signed value descriptor", - self.signature + &self.signature ); } // validate schema @@ -30,7 +48,11 @@ impl SignedValueDescriptor { Ok(()) } - pub fn owner(&self) -> &BarePublicKey { + pub fn owner(&self) -> PublicKey { + self.owner.clone() + } + + pub fn ref_owner(&self) -> &PublicKey { &self.owner } @@ -42,18 +64,32 @@ impl SignedValueDescriptor { DHTSchema::try_from(self.schema_data.as_slice()) } - pub fn signature(&self) -> &BareSignature { + #[expect(dead_code)] + pub fn signature(&self) -> Signature { + self.signature.clone() + } + + pub fn ref_signature(&self) -> &Signature { &self.signature } pub fn make_signature( - owner: BarePublicKey, + owner: PublicKey, schema_data: Vec, vcrypto: &CryptoSystemGuard<'_>, owner_secret: BareSecretKey, ) -> VeilidAPIResult { + if owner.kind() != vcrypto.kind() { + apibail_parse_error!( + "wrong kind of owner for signed value descriptor signature", + &owner + ); + } // create signature - let signature = vcrypto.sign(&owner, &owner_secret, &schema_data)?; + let signature = Signature::new( + vcrypto.kind(), + vcrypto.sign(owner.ref_value(), &owner_secret, &schema_data)?, + ); Ok(Self { owner, schema_data, diff --git a/veilid-core/src/storage_manager/watch_value.rs b/veilid-core/src/storage_manager/watch_value.rs index 256f599d..4d6c7e81 100644 --- a/veilid-core/src/storage_manager/watch_value.rs +++ b/veilid-core/src/storage_manager/watch_value.rs @@ -48,7 +48,7 @@ impl StorageManager { pub(super) async fn outbound_watch_value_cancel( &self, watch_lock: AsyncTagLockGuard, - opt_watcher: Option, + opt_watcher: Option, safety_selection: SafetySelection, watch_node: NodeRef, watch_id: u64, @@ -59,12 +59,8 @@ impl StorageManager { // Get the appropriate watcher key, if anonymous use a static anonymous watch key // which lives for the duration of the app's runtime - let watcher = opt_watcher.unwrap_or_else(|| { - self.anonymous_watch_keys - .get(record_key.kind) - .unwrap() - .value - }); + let watcher = opt_watcher + .unwrap_or_else(|| self.anonymous_watch_keys.get(record_key.kind()).unwrap()); let wva = VeilidAPIError::from_network_result( self.rpc_processor() @@ -109,12 +105,9 @@ impl StorageManager { // Get the appropriate watcher key, if anonymous use a static anonymous watch key // which lives for the duration of the app's runtime - let watcher = params.opt_watcher.unwrap_or_else(|| { - self.anonymous_watch_keys - .get(record_key.kind) - .unwrap() - .value - }); + let watcher = params + .opt_watcher + .unwrap_or_else(|| self.anonymous_watch_keys.get(record_key.kind()).unwrap()); let wva = VeilidAPIError::from_network_result( pin_future!(self.rpc_processor().rpc_call_watch_value( @@ -184,16 +177,14 @@ impl StorageManager { // Get the appropriate watcher key, if anonymous use a static anonymous watch key // which lives for the duration of the app's runtime - let watcher = params.opt_watcher.unwrap_or_else(|| { - self.anonymous_watch_keys - .get(record_key.kind) - .unwrap() - .value - }); + let watcher = params + .opt_watcher + .clone() + .unwrap_or_else(|| self.anonymous_watch_keys.get(record_key.kind()).unwrap()); // Get the nodes we know are caching this value to seed the fanout let init_fanout_queue = { - self.get_value_nodes(record_key) + self.get_value_nodes(record_key.clone()) .await? .unwrap_or_default() .into_iter() @@ -213,16 +204,20 @@ impl StorageManager { let context = context.clone(); let registry = self.registry(); let params = params.clone(); + let record_key = record_key.clone(); + let watcher = watcher.clone(); Arc::new( move |next_node: NodeRef| -> PinBoxFutureStatic { let context = context.clone(); let registry = registry.clone(); + let record_key = record_key.clone(); + let watcher = watcher.clone(); let params = params.clone(); // See if we have an existing watch id for this node - let node_id = next_node.node_ids().get(record_key.kind).unwrap(); + let node_id = next_node.node_ids().get(record_key.kind()).unwrap(); let pnk = PerNodeKey { - record_key, + record_key: record_key.clone(), node_id, }; let watch_id = per_node_state.get(&pnk).map(|pns| pns.watch_id); @@ -234,7 +229,7 @@ impl StorageManager { rpc_processor .rpc_call_watch_value( Destination::direct(next_node.routing_domain_filtered(routing_domain)).with_safety(params.safety_selection), - record_key, + record_key.clone(), params.subkeys, params.expiration_ts, params.count, @@ -332,7 +327,7 @@ impl StorageManager { let routing_table = self.routing_table(); let fanout_call = FanoutCall::new( &routing_table, - record_key.into(), + record_key.clone().into(), key_count, fanout, consensus_count, @@ -351,7 +346,7 @@ impl StorageManager { // Get cryptosystem let crypto = self.crypto(); - let Some(vcrypto) = crypto.get(record_key.kind) else { + let Some(vcrypto) = crypto.get(record_key.kind()) else { apibail_generic!("unsupported cryptosystem"); }; @@ -437,10 +432,10 @@ impl StorageManager { .cloned() else { veilid_log!(self warn "missing per-node state for watch"); - missing_pnks.insert(*pnk); + missing_pnks.insert(pnk.clone()); continue; }; - per_node_states.push((*pnk, per_node_state)); + per_node_states.push((pnk.clone(), per_node_state)); } state.edit(&inner.outbound_watch_manager.per_node_states, |editor| { @@ -560,10 +555,10 @@ impl StorageManager { .cloned() else { veilid_log!(self warn "missing per-node state for watch"); - missing_pnks.insert(*pnk); + missing_pnks.insert(pnk.clone()); continue; }; - per_node_states.push((*pnk, per_node_state)); + per_node_states.push((pnk.clone(), per_node_state)); } state.edit(&inner.outbound_watch_manager.per_node_states, |editor| { editor.retain_nodes(|x| !missing_pnks.contains(x)); @@ -655,7 +650,7 @@ impl StorageManager { .iter() .map(|pnk| { ( - *pnk, + pnk.clone(), inner .outbound_watch_manager .per_node_states @@ -680,7 +675,7 @@ impl StorageManager { } // Add inactive per node state if the record key matches if pnk.record_key == record_key { - per_node_state.insert(*pnk, pns.clone()); + per_node_state.insert(pnk.clone(), pns.clone()); } } @@ -698,7 +693,11 @@ impl StorageManager { match res { Ok(owvresult) => { // Update state - self.process_outbound_watch_value_result_inner(inner, record_key, owvresult); + self.process_outbound_watch_value_result_inner( + inner, + record_key.clone(), + owvresult, + ); // If we succeeded update the last consensus node count let Some(outbound_watch) = inner @@ -737,6 +736,8 @@ impl StorageManager { record_key: RecordKey, owvresult: OutboundWatchValueResult, ) { + let kind = record_key.kind(); + let Some(outbound_watch) = inner .outbound_watch_manager .outbound_watches @@ -760,13 +761,9 @@ impl StorageManager { // Handle accepted for accepted_watch in owvresult.accepted { - let node_id = accepted_watch - .node_ref - .node_ids() - .get(record_key.kind) - .unwrap(); + let node_id = accepted_watch.node_ref.node_ids().get(kind).unwrap(); let pnk = PerNodeKey { - record_key, + record_key: record_key.clone(), node_id, }; @@ -778,13 +775,13 @@ impl StorageManager { if expiration_ts.as_u64() != 0 && count > 0 { // Insert state, possibly overwriting an existing one let watch_id = accepted_watch.watch_id; - let opt_watcher = desired.opt_watcher; - let safety_selection = desired.safety_selection; + let opt_watcher = desired.opt_watcher.clone(); + let safety_selection = desired.safety_selection.clone(); let watch_node_ref = Some(accepted_watch.node_ref); let opt_value_changed_route = accepted_watch.opt_value_changed_route; inner.outbound_watch_manager.per_node_states.insert( - pnk, + pnk.clone(), PerNodeState { watch_id, safety_selection, @@ -804,9 +801,9 @@ impl StorageManager { } // Eliminate rejected for rejected_node_ref in owvresult.rejected { - let node_id = rejected_node_ref.node_ids().get(record_key.kind).unwrap(); + let node_id = rejected_node_ref.node_ids().get(kind).unwrap(); let pnk = PerNodeKey { - record_key, + record_key: record_key.clone(), node_id, }; inner.outbound_watch_manager.per_node_states.remove(&pnk); @@ -814,9 +811,9 @@ impl StorageManager { } // Drop unanswered but leave in per node state for ignored_node_ref in owvresult.ignored { - let node_id = ignored_node_ref.node_ids().get(record_key.kind).unwrap(); + let node_id = ignored_node_ref.node_ids().get(kind).unwrap(); let pnk = PerNodeKey { - record_key, + record_key: record_key.clone(), node_id, }; remove_nodes.insert(pnk); @@ -927,7 +924,7 @@ impl StorageManager { let this = registry.storage_manager(); let report = match this - .inspect_record(record_key, subkeys.clone(), DHTReportScope::SyncGet) + .inspect_record(record_key.clone(), subkeys.clone(), DHTReportScope::SyncGet) .await { Ok(v) => v, @@ -943,7 +940,10 @@ impl StorageManager { while !newer_online_subkeys.is_empty() { let first_changed_subkey = newer_online_subkeys.first().unwrap(); - let value = match this.get_value(record_key, first_changed_subkey, true).await { + let value = match this + .get_value(record_key.clone(), first_changed_subkey, true) + .await + { Ok(v) => v, Err(e) => { veilid_log!(this debug "Failed to get changed record: {}", e); @@ -956,8 +956,10 @@ impl StorageManager { if opt_local_seq.is_none() || value.seq() > opt_local_seq.unwrap() { // Calculate the update let (changed_subkeys, remaining_count, value) = { - let _watch_lock = - this.outbound_watch_lock_table.lock_tag(record_key).await; + let _watch_lock = this + .outbound_watch_lock_table + .lock_tag(record_key.clone()) + .await; let inner = &mut *this.inner.lock().await; // Get the outbound watch @@ -1032,7 +1034,7 @@ impl StorageManager { let Some(local_record_store) = inner.local_record_store.as_mut() else { apibail_not_initialized!(); }; - if local_record_store.contains_record(key) { + if local_record_store.contains_record(&key) { return local_record_store .watch_record(key, params, watch_id) .await @@ -1041,7 +1043,7 @@ impl StorageManager { let Some(remote_record_store) = inner.remote_record_store.as_mut() else { apibail_not_initialized!(); }; - if remote_record_store.contains_record(key) { + if remote_record_store.contains_record(&key) { return remote_record_store .watch_record(key, params, watch_id) .await @@ -1063,7 +1065,10 @@ impl StorageManager { watch_id: u64, ) -> VeilidAPIResult> { // Operate on the watch for this record - let watch_lock = self.outbound_watch_lock_table.lock_tag(record_key).await; + let watch_lock = self + .outbound_watch_lock_table + .lock_tag(record_key.clone()) + .await; // Update local record store with new value let (report_value_change, value, remaining_count, reportable_subkeys) = { @@ -1092,8 +1097,8 @@ impl StorageManager { // If the reporting node is not part of our current watch, don't process the value change let pnk = PerNodeKey { - record_key, - node_id: inbound_node_id, + record_key: record_key.clone(), + node_id: inbound_node_id.clone(), }; if !state.nodes().contains(&pnk) { return Ok(NetworkResult::value(())); @@ -1165,22 +1170,24 @@ impl StorageManager { return Ok(NetworkResult::value(())); }; - // Null out default value - let value = value.filter(|value| *value.value_data() != ValueData::default()); - // Set the local value let mut report_value_change = false; if let Some(value) = &value { let last_get_result = self - .handle_get_local_value_inner(inner, record_key, first_subkey, true) + .handle_get_local_value_inner(inner, record_key.clone(), first_subkey, true) .await?; let descriptor = last_get_result.opt_descriptor.unwrap(); let schema = descriptor.schema()?; // Validate with schema - if schema - .check_subkey_value_data(descriptor.owner(), first_subkey, value.value_data()) + if self + .check_subkey_value_data( + &schema, + descriptor.ref_owner(), + first_subkey, + value.value_data(), + ) .is_err() { // Validation failed, ignore this value @@ -1213,7 +1220,7 @@ impl StorageManager { if report_value_change { self.handle_set_local_value_inner( inner, - record_key, + record_key.clone(), first_subkey, value.clone(), InboundWatchUpdateMode::NoUpdate, @@ -1303,7 +1310,7 @@ impl StorageManager { for (record_key, outbound_watch) in &inner.outbound_watch_manager.outbound_watches { if let Some(state) = outbound_watch.state() { let reportable_subkeys = state.params().subkeys.clone(); - change_inspects.push((*record_key, reportable_subkeys)); + change_inspects.push((record_key.clone(), reportable_subkeys)); } } diff --git a/veilid-core/src/table_store/mod.rs b/veilid-core/src/table_store/mod.rs index a34b4cb0..02268495 100644 --- a/veilid-core/src/table_store/mod.rs +++ b/veilid-core/src/table_store/mod.rs @@ -268,8 +268,9 @@ impl TableStore { dek_bytes: &[u8], device_encryption_key_password: &str, ) -> EyreResult { - // Ensure the key is at least as long as necessary if unencrypted - if dek_bytes.len() < (4 + SHARED_SECRET_LENGTH) { + // Ensure the key is at least as long as necessary + // to check for crypto kind + if dek_bytes.len() < 4 { bail!("device encryption key is not valid"); } @@ -282,18 +283,20 @@ impl TableStore { if !device_encryption_key_password.is_empty() { if dek_bytes.len() - != (4 + SHARED_SECRET_LENGTH + vcrypto.aead_overhead() + NONCE_LENGTH) + != (4 + + vcrypto.shared_secret_length() + + vcrypto.aead_overhead() + + vcrypto.nonce_length()) { bail!("password protected device encryption key is not valid"); } - let protected_key = &dek_bytes[4..(4 + SHARED_SECRET_LENGTH + vcrypto.aead_overhead())]; - let nonce = BareNonce::try_from( - &dek_bytes[(4 + SHARED_SECRET_LENGTH + vcrypto.aead_overhead())..], - ) - .wrap_err("invalid nonce")?; - + let protected_key = + &dek_bytes[4..(4 + vcrypto.shared_secret_length() + vcrypto.aead_overhead())]; + let nonce = BareNonce::new( + &dek_bytes[(4 + vcrypto.shared_secret_length() + vcrypto.aead_overhead())..], + ); let shared_secret = vcrypto - .derive_shared_secret(device_encryption_key_password.as_bytes(), &nonce.bytes) + .derive_shared_secret(device_encryption_key_password.as_bytes(), &nonce) .await .wrap_err("failed to derive shared secret")?; @@ -304,18 +307,17 @@ impl TableStore { return Ok(SharedSecret::new( kind, - BareSharedSecret::try_from(unprotected_key.as_slice()) - .wrap_err("invalid shared secret")?, + BareSharedSecret::new(unprotected_key.as_slice()), )); } - if dek_bytes.len() != (4 + SHARED_SECRET_LENGTH) { - bail!("password protected device encryption key is not valid"); + if dek_bytes.len() != (4 + vcrypto.shared_secret_length()) { + bail!("unprotected device encryption key is not valid"); } Ok(SharedSecret::new( kind, - BareSharedSecret::try_from(&dek_bytes[4..])?, + BareSharedSecret::new(&dek_bytes[4..]), )) } @@ -329,33 +331,34 @@ impl TableStore { if device_encryption_key_password.is_empty() { veilid_log!(self debug "no dek password"); // Return the unprotected key bytes - let mut out = Vec::with_capacity(4 + SHARED_SECRET_LENGTH); - out.extend_from_slice(&dek.kind.0); - out.extend_from_slice(&dek.value.bytes); - return Ok(out); + return Ok(Vec::from(dek)); } // Get cryptosystem let crypto = self.crypto(); - let Some(vcrypto) = crypto.get_async(dek.kind) else { - bail!("unsupported cryptosystem '{}'", dek.kind); + let Some(vcrypto) = crypto.get_async(dek.kind()) else { + bail!("unsupported cryptosystem '{}'", dek.kind()); }; let nonce = vcrypto.random_nonce().await; let shared_secret = vcrypto - .derive_shared_secret(device_encryption_key_password.as_bytes(), &nonce.bytes) + .derive_shared_secret(device_encryption_key_password.as_bytes(), &nonce) .await .wrap_err("failed to derive shared secret")?; - let mut protected_key = vcrypto - .encrypt_aead(&dek.value.bytes, &nonce, &shared_secret, None) + let protected_key = vcrypto + .encrypt_aead(dek.ref_value(), &nonce, &shared_secret, None) .await .wrap_err("failed to decrypt device encryption key")?; - let mut out = - Vec::with_capacity(4 + SHARED_SECRET_LENGTH + vcrypto.aead_overhead() + NONCE_LENGTH); - out.extend_from_slice(&dek.kind.0); - out.append(&mut protected_key); - out.extend_from_slice(&nonce.bytes); - assert!(out.len() == 4 + SHARED_SECRET_LENGTH + vcrypto.aead_overhead() + NONCE_LENGTH); + let mut out = Vec::with_capacity( + 4 + vcrypto.shared_secret_length() + vcrypto.aead_overhead() + vcrypto.nonce_length(), + ); + out.extend_from_slice(&dek.kind().0); + out.extend_from_slice(&protected_key); + out.extend_from_slice(&nonce); + assert_eq!( + out.len(), + 4 + vcrypto.shared_secret_length() + vcrypto.aead_overhead() + vcrypto.nonce_length() + ); Ok(out) } @@ -441,19 +444,20 @@ impl TableStore { // Get device encryption key from protected store let mut device_encryption_key = self.load_device_encryption_key().await?; let mut device_encryption_key_changed = false; - if let Some(device_encryption_key) = device_encryption_key { + if let Some(device_encryption_key) = &device_encryption_key { // If encryption in current use is not the best encryption, then run table migration let best_kind = best_crypto_kind(); - if device_encryption_key.kind != best_kind { + if device_encryption_key.kind() != best_kind { // XXX: Run migration. See issue #209 + veilid_log!(self error "Need to write migration support"); } } else { // If we don't have an encryption key yet, then make one with the best cryptography and save it - let best_kind = best_crypto_kind(); - let mut shared_secret = BareSharedSecret::default(); - random_bytes(&mut shared_secret.bytes); + let crypto = self.crypto(); + let vcrypto = crypto.best_async(); + let shared_secret = vcrypto.random_shared_secret().await; - device_encryption_key = Some(SharedSecret::new(best_kind, shared_secret)); + device_encryption_key = Some(SharedSecret::new(vcrypto.kind(), shared_secret)); device_encryption_key_changed = true; } @@ -466,7 +470,7 @@ impl TableStore { // Save encryption key if it has changed or if the protecting password wants to change if device_encryption_key_changed || changing_password { - self.save_device_encryption_key(device_encryption_key) + self.save_device_encryption_key(device_encryption_key.clone()) .await?; } @@ -619,8 +623,8 @@ impl TableStore { table_name.clone(), self.registry(), db, - inner.encryption_key, - inner.encryption_key, + inner.encryption_key.clone(), + inner.encryption_key.clone(), column_count, ); diff --git a/veilid-core/src/table_store/table_db.rs b/veilid-core/src/table_store/table_db.rs index 49e892a8..14e30e57 100644 --- a/veilid-core/src/table_store/table_db.rs +++ b/veilid-core/src/table_store/table_db.rs @@ -14,11 +14,11 @@ impl_veilid_log_facility!("tstore"); #[must_use] struct CryptInfo { - typed_key: SharedSecret, + secret: SharedSecret, } impl CryptInfo { - pub fn new(typed_key: SharedSecret) -> Self { - Self { typed_key } + pub fn new(secret: SharedSecret) -> Self { + Self { secret } } } @@ -131,28 +131,27 @@ impl TableDB { let data = compress_prepend_size(data); if let Some(ei) = &self.unlocked_inner.encrypt_info { let crypto = self.crypto(); - let vcrypto = crypto.get(ei.typed_key.kind).unwrap(); - let mut out = unsafe { unaligned_u8_vec_uninit(NONCE_LENGTH + data.len()) }; + let vcrypto = crypto.get(ei.secret.kind()).unwrap(); + let mut out = unsafe { unaligned_u8_vec_uninit(vcrypto.nonce_length() + data.len()) }; if keyed_nonce { // Key content nonce - let mut noncedata = Vec::with_capacity(data.len() + PUBLIC_KEY_LENGTH); + let mut noncedata = Vec::with_capacity(data.len() + ei.secret.ref_value().len()); noncedata.extend_from_slice(&data); - noncedata.extend_from_slice(&ei.typed_key.value.bytes); + noncedata.extend_from_slice(ei.secret.ref_value()); let noncehash = vcrypto.generate_hash(&noncedata); - out[0..NONCE_LENGTH].copy_from_slice(&noncehash.bytes[0..NONCE_LENGTH]) + // Key content nonce is first 'nonce_length' bytes of generated hash + out[0..vcrypto.nonce_length()] + .copy_from_slice(&noncehash[0..vcrypto.nonce_length()]); } else { // Random nonce - random_bytes(&mut out[0..NONCE_LENGTH]); + random_bytes(&mut out[0..vcrypto.nonce_length()]); } - let (nonce, encout) = out.split_at_mut(NONCE_LENGTH); - vcrypto.crypt_b2b_no_auth( - &data, - encout, - &BareNonce::try_from(&nonce[0..NONCE_LENGTH]).unwrap(), - &ei.typed_key.value, - ); + let (nonce, encout) = out.split_at_mut(vcrypto.nonce_length()); + vcrypto + .crypt_b2b_no_auth(&data, encout, &BareNonce::new(nonce), ei.secret.ref_value()) + .unwrap(); out } else { data @@ -164,20 +163,22 @@ impl TableDB { fn maybe_decrypt(&self, data: &[u8]) -> std::io::Result> { if let Some(di) = &self.unlocked_inner.decrypt_info { let crypto = self.crypto(); - let vcrypto = crypto.get(di.typed_key.kind).unwrap(); - assert!(data.len() >= NONCE_LENGTH); - if data.len() == NONCE_LENGTH { + let vcrypto = crypto.get(di.secret.kind()).unwrap(); + assert!(data.len() >= vcrypto.nonce_length()); + if data.len() == vcrypto.nonce_length() { return Ok(Vec::new()); } - let mut out = unsafe { unaligned_u8_vec_uninit(data.len() - NONCE_LENGTH) }; + let mut out = unsafe { unaligned_u8_vec_uninit(data.len() - vcrypto.nonce_length()) }; - vcrypto.crypt_b2b_no_auth( - &data[NONCE_LENGTH..], - &mut out, - &BareNonce::try_from(&data[0..NONCE_LENGTH]).unwrap(), - &di.typed_key.value, - ); + vcrypto + .crypt_b2b_no_auth( + &data[vcrypto.nonce_length()..], + &mut out, + &BareNonce::new(&data[0..vcrypto.nonce_length()]), + di.secret.ref_value(), + ) + .unwrap(); decompress_size_prepended(&out, None).map_err(|e| std::io::Error::other(e.to_string())) } else { decompress_size_prepended(data, None).map_err(|e| std::io::Error::other(e.to_string())) diff --git a/veilid-core/src/table_store/tests/test_table_store.rs b/veilid-core/src/table_store/tests/test_table_store.rs index bdacdaea..63858e00 100644 --- a/veilid-core/src/table_store/tests/test_table_store.rs +++ b/veilid-core/src/table_store/tests/test_table_store.rs @@ -180,7 +180,7 @@ pub async fn test_json(vcrypto: &AsyncCryptoSystemGuard<'_>, ts: &TableStore) { panic!("couldn't decode: {}", e); } }; - assert_eq!(d, Some(keypair), "keys should be equal"); + assert_eq!(d, Some(keypair.clone()), "keys should be equal"); let d = match db.delete_json::(0, b"asdf").await { Ok(x) => x, @@ -188,7 +188,7 @@ pub async fn test_json(vcrypto: &AsyncCryptoSystemGuard<'_>, ts: &TableStore) { panic!("couldn't decode: {}", e); } }; - assert_eq!(d, Some(keypair), "keys should be equal"); + assert_eq!(d, Some(keypair.clone()), "keys should be equal"); assert!( db.store(1, b"foo", b"1234567890").await.is_ok(), @@ -206,7 +206,7 @@ pub async fn test_protect_unprotect(vcrypto: &AsyncCryptoSystemGuard<'_>, ts: &T let dek1 = SharedSecret::new( vcrypto.kind(), - BareSharedSecret::new([ + BareSharedSecret::new(&[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]), @@ -214,7 +214,7 @@ pub async fn test_protect_unprotect(vcrypto: &AsyncCryptoSystemGuard<'_>, ts: &T let dek2 = SharedSecret::new( vcrypto.kind(), - BareSharedSecret::new([ + BareSharedSecret::new(&[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, ]), @@ -222,7 +222,7 @@ pub async fn test_protect_unprotect(vcrypto: &AsyncCryptoSystemGuard<'_>, ts: &T let dek3 = SharedSecret::new( vcrypto.kind(), - BareSharedSecret::new([0x80u8; SHARED_SECRET_LENGTH]), + BareSharedSecret::new(&[0x80u8; VLD0_SHARED_SECRET_LENGTH]), ); let deks = [dek1, dek2, dek3]; @@ -240,7 +240,7 @@ pub async fn test_protect_unprotect(vcrypto: &AsyncCryptoSystemGuard<'_>, ts: &T for password in passwords { trace!("testing dek {} with password {}", dek, password); let dek_bytes = ts - .maybe_protect_device_encryption_key(dek, password) + .maybe_protect_device_encryption_key(dek.clone(), password) .await .unwrap_or_else(|_| panic!("protect: dek: '{}' pw: '{}'", dek, password)); diff --git a/veilid-core/src/tests/common/test_dht.rs b/veilid-core/src/tests/common/test_dht.rs index e88c1885..d729edc9 100644 --- a/veilid-core/src/tests/common/test_dht.rs +++ b/veilid-core/src/tests/common/test_dht.rs @@ -8,35 +8,35 @@ use lazy_static::*; lazy_static! { static ref BOGUS_KEY: RecordKey = RecordKey::from(CryptoTyped::new( TEST_CRYPTO_KIND, - BareRecordKey::new([0u8; 32]) + BareRecordKey::new(&[0u8; 32]) )); } pub async fn test_get_dht_value_unopened(api: VeilidAPI) { let rc = api.routing_context().unwrap(); - let result = rc.get_dht_value(*BOGUS_KEY, 0, false).await; + let result = rc.get_dht_value(BOGUS_KEY.clone(), 0, false).await; assert_err!(result); } pub async fn test_open_dht_record_nonexistent_no_writer(api: VeilidAPI) { let rc = api.routing_context().unwrap(); - let result = rc.get_dht_value(*BOGUS_KEY, 0, false).await; + let result = rc.get_dht_value(BOGUS_KEY.clone(), 0, false).await; assert_err!(result); } pub async fn test_close_dht_record_nonexistent(api: VeilidAPI) { let rc = api.routing_context().unwrap(); - let result = rc.close_dht_record(*BOGUS_KEY).await; + let result = rc.close_dht_record(BOGUS_KEY.clone()).await; assert_err!(result); } pub async fn test_delete_dht_record_nonexistent(api: VeilidAPI) { let rc = api.routing_context().unwrap(); - let result = rc.delete_dht_record(*BOGUS_KEY).await; + let result = rc.delete_dht_record(BOGUS_KEY.clone()).await; assert_err!(result); } @@ -48,8 +48,8 @@ pub async fn test_create_delete_dht_record_simple(api: VeilidAPI) { .await .unwrap(); - let dht_key = *rec.key(); - rc.close_dht_record(dht_key).await.unwrap(); + let dht_key = rec.key(); + rc.close_dht_record(dht_key.clone()).await.unwrap(); rc.delete_dht_record(dht_key).await.unwrap(); } @@ -58,22 +58,22 @@ pub async fn test_create_dht_record_with_owner(api: VeilidAPI) { let crypto = api.crypto().unwrap(); let cs = crypto.get(TEST_CRYPTO_KIND).unwrap(); - let owner_keypair = cs.generate_keypair(); + let owner_keypair = KeyPair::new(cs.kind(), cs.generate_keypair()); let rec = rc .create_dht_record( DHTSchema::dflt(1).unwrap(), - Some(owner_keypair), + Some(owner_keypair.clone()), Some(TEST_CRYPTO_KIND), ) .await .unwrap(); - assert_eq!(rec.owner(), &owner_keypair.key); + assert_eq!(rec.ref_owner(), &owner_keypair.key()); - let dht_key = *rec.key(); - rc.close_dht_record(dht_key).await.unwrap(); - rc.delete_dht_record(dht_key).await.unwrap(); + let dht_key = rec.key(); + rc.close_dht_record(dht_key.clone()).await.unwrap(); + rc.delete_dht_record(dht_key.clone()).await.unwrap(); } pub async fn test_get_dht_record_key(api: VeilidAPI) { @@ -81,25 +81,29 @@ pub async fn test_get_dht_record_key(api: VeilidAPI) { let crypto = api.crypto().unwrap(); let cs = crypto.get(TEST_CRYPTO_KIND).unwrap(); - let owner_keypair = cs.generate_keypair(); + let owner_keypair = KeyPair::new(cs.kind(), cs.generate_keypair()); let schema = DHTSchema::dflt(1).unwrap(); // create the record normally let rec = rc - .create_dht_record(schema.clone(), Some(owner_keypair), Some(TEST_CRYPTO_KIND)) + .create_dht_record( + schema.clone(), + Some(owner_keypair.clone()), + Some(TEST_CRYPTO_KIND), + ) .await .unwrap(); // recreate the record key from the metadata alone let key = rc - .get_dht_record_key(schema.clone(), &owner_keypair.key, Some(TEST_CRYPTO_KIND)) + .get_dht_record_key(schema.clone(), &owner_keypair.key()) .unwrap(); // keys should be the same - assert_eq!(key, *rec.key()); + assert_eq!(key, rec.key()); - let dht_key = *rec.key(); - rc.close_dht_record(dht_key).await.unwrap(); + let dht_key = rec.key(); + rc.close_dht_record(dht_key.clone()).await.unwrap(); rc.delete_dht_record(dht_key).await.unwrap(); } @@ -110,11 +114,11 @@ pub async fn test_get_dht_value_nonexistent(api: VeilidAPI) { .create_dht_record(DHTSchema::dflt(1).unwrap(), None, Some(TEST_CRYPTO_KIND)) .await .unwrap(); - let dht_key = *rec.key(); - let result = rc.get_dht_value(dht_key, 0, false).await; + let dht_key = rec.key(); + let result = rc.get_dht_value(dht_key.clone(), 0, false).await; assert_eq!(result.expect("should not be error"), None); - rc.close_dht_record(dht_key).await.unwrap(); + rc.close_dht_record(dht_key.clone()).await.unwrap(); rc.delete_dht_record(dht_key).await.unwrap(); } @@ -125,14 +129,16 @@ pub async fn test_set_get_dht_value(api: VeilidAPI) { .create_dht_record(DHTSchema::dflt(2).unwrap(), None, Some(TEST_CRYPTO_KIND)) .await .unwrap(); - let dht_key = *rec.key(); + let dht_key = rec.key(); let test_value = String::from("BLAH BLAH BLAH").as_bytes().to_vec(); // convert string to byte array - let set_dht_value_result = rc.set_dht_value(dht_key, 0, test_value.clone(), None).await; + let set_dht_value_result = rc + .set_dht_value(dht_key.clone(), 0, test_value.clone(), None) + .await; assert_eq!(set_dht_value_result.expect("should be Ok(None)"), None); - let get_dht_value_result_0_non_force = rc.get_dht_value(dht_key, 0, false).await; + let get_dht_value_result_0_non_force = rc.get_dht_value(dht_key.clone(), 0, false).await; assert_eq!( get_dht_value_result_0_non_force .expect("should not be error") @@ -142,7 +148,7 @@ pub async fn test_set_get_dht_value(api: VeilidAPI) { ); // works in python, fails in rust - let get_dht_value_result_0_force = rc.get_dht_value(dht_key, 0, true).await; + let get_dht_value_result_0_force = rc.get_dht_value(dht_key.clone(), 0, true).await; assert_eq!( get_dht_value_result_0_force .expect("should not be error") @@ -151,7 +157,7 @@ pub async fn test_set_get_dht_value(api: VeilidAPI) { test_value.clone() ); - let get_dht_value_result_1_non_force = rc.get_dht_value(dht_key, 1, false).await; + let get_dht_value_result_1_non_force = rc.get_dht_value(dht_key.clone(), 1, false).await; assert_eq!( get_dht_value_result_1_non_force.expect("should not be error"), None @@ -162,7 +168,7 @@ pub async fn test_set_get_dht_value(api: VeilidAPI) { // get_dht_value_result_1_non_force.expect("should hold value") // ); - rc.close_dht_record(dht_key).await.unwrap(); + rc.close_dht_record(dht_key.clone()).await.unwrap(); rc.delete_dht_record(dht_key).await.unwrap(); } @@ -173,10 +179,10 @@ pub async fn test_open_writer_dht_value(api: VeilidAPI) { .create_dht_record(DHTSchema::dflt(2).unwrap(), None, Some(TEST_CRYPTO_KIND)) .await .unwrap(); - let key = *rec.key(); + let key = rec.key(); let owner = rec.owner(); let secret = rec.owner_secret().unwrap(); - let keypair = BareKeyPair::new(*owner, *secret); + let keypair = KeyPair::new_from_parts(owner.clone(), secret.clone()); let test_value_1 = String::from("Qwertyuiop Asdfghjkl Zxcvbnm") .as_bytes() @@ -192,10 +198,12 @@ pub async fn test_open_writer_dht_value(api: VeilidAPI) { // 5. Read data from subkey 0 with force_refresh, check data // 6. Read data from subkey 1 with force_refresh, check data // 7. Overwrite value 1 twice, check that there's no errors - let set_dht_test_value_1_result = rc.set_dht_value(key, 1, test_value_1.clone(), None).await; + let set_dht_test_value_1_result = rc + .set_dht_value(key.clone(), 1, test_value_1.clone(), None) + .await; assert!(set_dht_test_value_1_result.is_ok()); - let get_dht_value_result_1_non_force = rc.get_dht_value(key, 1, false).await; + let get_dht_value_result_1_non_force = rc.get_dht_value(key.clone(), 1, false).await; assert!(get_dht_value_result_1_non_force.is_ok()); let get_dht_value_result_1_non_force = get_dht_value_result_1_non_force .unwrap() @@ -204,16 +212,18 @@ pub async fn test_open_writer_dht_value(api: VeilidAPI) { assert_eq!(get_dht_value_result_1_non_force.seq(), 0); assert_eq!(get_dht_value_result_1_non_force.writer(), owner); - let get_dht_value_result_0_non_force = rc.get_dht_value(key, 0, false).await; + let get_dht_value_result_0_non_force = rc.get_dht_value(key.clone(), 0, false).await; assert_eq!( get_dht_value_result_0_non_force.expect("should not be error"), None ); - let set_dht_test_value_0_result = rc.set_dht_value(key, 0, test_data_2.clone(), None).await; + let set_dht_test_value_0_result = rc + .set_dht_value(key.clone(), 0, test_data_2.clone(), None) + .await; assert!(set_dht_test_value_0_result.is_ok()); - let get_dht_value_result_0_force = rc.get_dht_value(key, 0, true).await; + let get_dht_value_result_0_force = rc.get_dht_value(key.clone(), 0, true).await; assert_eq!( get_dht_value_result_0_force .expect("should be OK(result)") @@ -222,7 +232,7 @@ pub async fn test_open_writer_dht_value(api: VeilidAPI) { test_data_2 ); - let get_dht_value_result_1_force = rc.get_dht_value(key, 1, true).await; + let get_dht_value_result_1_force = rc.get_dht_value(key.clone(), 1, true).await; assert_eq!( get_dht_value_result_1_force .expect("should be OK(result)") @@ -231,10 +241,14 @@ pub async fn test_open_writer_dht_value(api: VeilidAPI) { test_value_1 ); - let overwrite_value_1_result_1 = rc.set_dht_value(key, 1, test_value_1.clone(), None).await; + let overwrite_value_1_result_1 = rc + .set_dht_value(key.clone(), 1, test_value_1.clone(), None) + .await; assert!(overwrite_value_1_result_1.is_ok()); - let overwrite_value_1_result_2 = rc.set_dht_value(key, 1, test_data_2.clone(), None).await; + let overwrite_value_1_result_2 = rc + .set_dht_value(key.clone(), 1, test_data_2.clone(), None) + .await; assert!(overwrite_value_1_result_2.is_ok()); // Now that we initialized some subkeys @@ -242,8 +256,8 @@ pub async fn test_open_writer_dht_value(api: VeilidAPI) { // Delete things locally and reopen and see if we can write // with the same writer key - rc.close_dht_record(key).await.unwrap(); - rc.delete_dht_record(key).await.unwrap(); + rc.close_dht_record(key.clone()).await.unwrap(); + rc.delete_dht_record(key.clone()).await.unwrap(); // Scenario 2 // 1. Open DHT record with existing keys @@ -253,17 +267,19 @@ pub async fn test_open_writer_dht_value(api: VeilidAPI) { // 4. Check that subkey 1 can be overwritten // 5. Read data from subkey 1 with force_refresh, check data - let rec = rc.open_dht_record(key, Some(keypair)).await; + let rec = rc.open_dht_record(key.clone(), Some(keypair.clone())).await; assert!(rec.is_ok()); let rec = rec.unwrap(); - assert_eq!(rec.key().value, key.value); - assert_eq!(rec.key().kind, key.kind); + assert_eq!(rec.ref_key().value(), key.value()); + assert_eq!(rec.ref_key().kind(), key.kind()); assert_eq!(rec.owner(), owner); assert_eq!(rec.owner_secret().unwrap(), secret); assert_eq!(rec.schema(), &DHTSchema::dflt(2).unwrap()); //Verify subkey 1 can be set before it is get but newer is available online - let set_dht_test_value_1_result = rc.set_dht_value(key, 1, test_data_3.clone(), None).await; + let set_dht_test_value_1_result = rc + .set_dht_value(key.clone(), 1, test_data_3.clone(), None) + .await; assert!(set_dht_test_value_1_result.is_ok()); let vdtemp = set_dht_test_value_1_result.unwrap().unwrap(); assert_eq!(vdtemp.data(), test_data_2); @@ -271,11 +287,13 @@ pub async fn test_open_writer_dht_value(api: VeilidAPI) { assert_eq!(vdtemp.writer(), owner); // Verify subkey 1 can be set a second time and it updates because seq is newer - let set_dht_test_value_1_result = rc.set_dht_value(key, 1, test_data_3.clone(), None).await; + let set_dht_test_value_1_result = rc + .set_dht_value(key.clone(), 1, test_data_3.clone(), None) + .await; assert!(set_dht_test_value_1_result.is_ok()); // Verify the network got the subkey update with a refresh check - let get_dht_value_result_1_force = rc.get_dht_value(key, 1, true).await; + let get_dht_value_result_1_force = rc.get_dht_value(key.clone(), 1, true).await; assert!(get_dht_value_result_1_force.is_ok()); let get_dht_value_result_1_force = get_dht_value_result_1_force .expect("should be OK(result)") @@ -286,8 +304,8 @@ pub async fn test_open_writer_dht_value(api: VeilidAPI) { // Delete things locally and reopen and see if we can write // with a different writer key (should fail) - rc.close_dht_record(key).await.unwrap(); - rc.delete_dht_record(key).await.unwrap(); + rc.close_dht_record(key.clone()).await.unwrap(); + rc.delete_dht_record(key.clone()).await.unwrap(); // Scenario 3 // 1. Open DHT record with new keypair @@ -296,31 +314,35 @@ pub async fn test_open_writer_dht_value(api: VeilidAPI) { // 4. Try writing to subkey 0, expect error let crypto = api.crypto().unwrap(); - let cs = crypto.get(key.kind).unwrap(); - assert!(cs.validate_keypair(owner, secret)); - let other_keypair = cs.generate_keypair(); + let cs = crypto.get(key.kind()).unwrap(); + assert!(cs.validate_keypair(owner.ref_value(), &secret)); + let other_keypair = KeyPair::new(cs.kind(), cs.generate_keypair()); - let rec = rc.open_dht_record(key, Some(other_keypair)).await; + let rec = rc.open_dht_record(key.clone(), Some(other_keypair)).await; assert!(rec.is_ok()); let rec = rec.unwrap(); - assert_eq!(rec.key().value, key.value); - assert_eq!(rec.key().kind, key.kind); + assert_eq!(rec.ref_key().value(), key.value()); + assert_eq!(rec.ref_key().kind(), key.kind()); assert_eq!(rec.owner(), owner); assert_eq!(rec.owner_secret(), None); assert_eq!(rec.schema(), &DHTSchema::dflt(2).unwrap()); // Verify subkey 1 can NOT be set because we have the wrong writer - let set_dht_test_value_0_result = rc.set_dht_value(key, 1, test_value_1.clone(), None).await; + let set_dht_test_value_0_result = rc + .set_dht_value(key.clone(), 1, test_value_1.clone(), None) + .await; assert_err!(set_dht_test_value_0_result); // Verify subkey 0 can NOT be set because we have the wrong writer - let set_dht_test_value_0_result = rc.set_dht_value(key, 0, test_value_1.clone(), None).await; + let set_dht_test_value_0_result = rc + .set_dht_value(key.clone(), 0, test_value_1.clone(), None) + .await; assert_err!(set_dht_test_value_0_result); // Verify subkey 0 can be set because we have overridden with the correct writer let set_dht_test_value_0_result = rc .set_dht_value( - key, + key.clone(), 0, test_value_1.clone(), Some(SetDHTValueOptions { @@ -331,7 +353,7 @@ pub async fn test_open_writer_dht_value(api: VeilidAPI) { .await; assert!(set_dht_test_value_0_result.is_ok()); - rc.close_dht_record(key).await.unwrap(); + rc.close_dht_record(key.clone()).await.unwrap(); rc.delete_dht_record(key).await.unwrap(); } @@ -343,18 +365,20 @@ pub async fn test_set_dht_value_allow_offline(api: VeilidAPI) { .create_dht_record(DHTSchema::dflt(1).unwrap(), None, Some(CRYPTO_KIND_VLD0)) .await .unwrap(); - let dht_key = *rec.key(); + let dht_key = rec.key(); let test_value = String::from("Test offline value").as_bytes().to_vec(); // Test 1: Default behavior (options = None) should allow offline writes - let set_result = rc.set_dht_value(dht_key, 0, test_value.clone(), None).await; + let set_result = rc + .set_dht_value(dht_key.clone(), 0, test_value.clone(), None) + .await; assert!(set_result.is_ok()); // Test 2: Default behavior (allow_offline = None) should allow offline writes let set_result = rc .set_dht_value( - dht_key, + dht_key.clone(), 0, test_value.clone(), Some(SetDHTValueOptions { @@ -368,7 +392,7 @@ pub async fn test_set_dht_value_allow_offline(api: VeilidAPI) { // Test 3: Explicitly allow offline writes let set_result = rc .set_dht_value( - dht_key, + dht_key.clone(), 1, test_value.clone(), Some(SetDHTValueOptions { @@ -382,7 +406,7 @@ pub async fn test_set_dht_value_allow_offline(api: VeilidAPI) { // Test 4: Disallow offline writes let set_result = rc .set_dht_value( - dht_key, + dht_key.clone(), 2, test_value.clone(), Some(SetDHTValueOptions { @@ -394,7 +418,7 @@ pub async fn test_set_dht_value_allow_offline(api: VeilidAPI) { assert!(set_result.is_err()); assert!(set_result.unwrap_err().to_string().contains("offline")); - rc.close_dht_record(dht_key).await.unwrap(); + rc.close_dht_record(dht_key.clone()).await.unwrap(); rc.delete_dht_record(dht_key).await.unwrap(); } diff --git a/veilid-core/src/veilid_api/api.rs b/veilid-core/src/veilid_api/api.rs index 1ee15eb8..81b15bb3 100644 --- a/veilid-core/src/veilid_api/api.rs +++ b/veilid-core/src/veilid_api/api.rs @@ -220,37 +220,15 @@ impl VeilidAPI { RoutingContext::try_new(self.clone()) } - /// Parse a string into a target object that can be used in a [RoutingContext]. - /// - /// Strings are in base64url format and can either be a remote route id or a node id. - /// Strings may have a [CryptoKind] prefix separated by a colon, such as: - /// `VLD0:XmnGyJrjMJBRC5ayJZRPXWTBspdX36-pbLb98H3UMeE` but if the prefix is left off - /// `XmnGyJrjMJBRC5ayJZRPXWTBspdX36-pbLb98H3UMeE` will be parsed with the 'best' cryptosystem - /// available (at the time of this writing this is `VLD0`). - #[instrument(target = "veilid_api", level = "debug", skip(self), fields(__VEILID_LOG_KEY = self.log_key(), s=s.to_string()), ret, err)] - pub fn parse_as_target(&self, s: S) -> VeilidAPIResult { - let s = s.to_string(); + //////////////////////////////////////////////////////////////// + // DHT Schema Creation - veilid_log!(self debug - "VeilidAPI::parse_as_target(s: {:?})", s); - - // Is this a route id? - if let Ok(rrid) = BareRouteId::from_str(&s) { - let routing_table = self.core_context()?.routing_table(); - let rss = routing_table.route_spec_store(); - - // Is this a valid remote route id? (can't target allocated routes) - if rss.is_route_id_remote(&rrid) { - return Ok(Target::PrivateRoute(rrid)); - } - } - - // Is this a node id? - if let Ok(nid) = NodeId::from_str(&s) { - return Ok(Target::BareNodeId(nid)); - } - - Err(VeilidAPIError::parse_error("Unable to parse as target", s)) + /// Create a new MemberId for use with in creating `DHTSchema`s. + #[instrument(target = "veilid_api", level = "debug", skip(self), fields(__VEILID_LOG_KEY = self.log_key()), ret, err)] + pub fn generate_member_id(&self, writer_key: &PublicKey) -> VeilidAPIResult { + veilid_log!(self debug "VeilidAPI::generate_member_id(writer_key: {:?}", writer_key); + let storage_manager = self.core_context()?.storage_manager(); + storage_manager.generate_member_id(writer_key) } //////////////////////////////////////////////////////////////// @@ -264,7 +242,7 @@ impl VeilidAPI { /// Returns a route id and 'blob' that can be published over some means (DHT or otherwise) to be /// imported by another Veilid node. //#[instrument(target = "veilid_api", level = "debug", skip(self), ret, err)] - pub async fn new_private_route(&self) -> VeilidAPIResult<(BareRouteId, Vec)> { + pub async fn new_private_route(&self) -> VeilidAPIResult<(RouteId, Vec)> { Box::pin(self.new_custom_private_route( &VALID_CRYPTO_KINDS, Stability::Reliable, @@ -287,7 +265,7 @@ impl VeilidAPI { crypto_kinds: &[CryptoKind], stability: Stability, sequencing: Sequencing, - ) -> VeilidAPIResult<(BareRouteId, Vec)> { + ) -> VeilidAPIResult<(RouteId, Vec)> { veilid_log!(self debug "VeilidAPI::new_custom_private_route(crypto_kinds: {:?}, stability: {:?}, sequencing: {:?})", crypto_kinds, @@ -315,16 +293,16 @@ impl VeilidAPI { let rss = routing_table.route_spec_store(); let route_id = rss.allocate_route(crypto_kinds, &safety_spec, DirectionSet::all(), &[], false)?; - match Box::pin(rss.test_route(route_id)).await? { + match Box::pin(rss.test_route(route_id.clone())).await? { Some(true) => { // route tested okay } Some(false) => { - rss.release_route(route_id); + rss.release_route(route_id.clone()); apibail_generic!("allocated route failed to test"); } None => { - rss.release_route(route_id); + rss.release_route(route_id.clone()); apibail_generic!("allocated route could not be tested"); } } @@ -346,7 +324,7 @@ impl VeilidAPI { /// /// Returns a route id that can be used to send private messages to the node creating this route. #[instrument(target = "veilid_api", level = "debug", fields(__VEILID_LOG_KEY = self.log_key()), skip(self), ret, err)] - pub fn import_remote_private_route(&self, blob: Vec) -> VeilidAPIResult { + pub fn import_remote_private_route(&self, blob: Vec) -> VeilidAPIResult { veilid_log!(self debug "VeilidAPI::import_remote_private_route(blob: {:?})", blob); let routing_table = self.core_context()?.routing_table(); @@ -359,12 +337,12 @@ impl VeilidAPI { /// This will deactivate the route and free its resources and it can no longer be sent to /// or received from. #[instrument(target = "veilid_api", level = "debug", fields(__VEILID_LOG_KEY = self.log_key()), skip(self), ret, err)] - pub fn release_private_route(&self, route_id: BareRouteId) -> VeilidAPIResult<()> { + pub fn release_private_route(&self, route_id: RouteId) -> VeilidAPIResult<()> { veilid_log!(self debug "VeilidAPI::release_private_route(route_id: {:?})", route_id); let routing_table = self.core_context()?.routing_table(); let rss = routing_table.route_spec_store(); - if !rss.release_route(route_id) { + if !rss.release_route(route_id.clone()) { apibail_invalid_argument!("release_private_route", "key", route_id); } Ok(()) diff --git a/veilid-core/src/veilid_api/debug.rs b/veilid-core/src/veilid_api/debug.rs index 5916365a..6775dd40 100644 --- a/veilid-core/src/veilid_api/debug.rs +++ b/veilid-core/src/veilid_api/debug.rs @@ -13,7 +13,7 @@ impl_veilid_log_facility!("veilid_debug"); #[derive(Default)] pub(crate) struct DebugCache { - pub imported_routes: Vec, + pub imported_routes: Vec, pub opened_record_contexts: Lazy>, } @@ -102,7 +102,7 @@ fn get_route_id( registry: VeilidComponentRegistry, allow_allocated: bool, allow_remote: bool, -) -> impl Fn(&str) -> Option { +) -> impl Fn(&str) -> Option { move |text: &str| { if text.is_empty() { return None; @@ -110,16 +110,16 @@ fn get_route_id( let routing_table = registry.routing_table(); let rss = routing_table.route_spec_store(); - match BareRouteId::from_str(text).ok() { + match RouteId::from_str(text).ok() { Some(key) => { if allow_allocated { - let routes = rss.list_allocated_routes(|k, _| Some(*k)); + let routes = rss.list_allocated_routes(|k, _| Some(k.clone())); if routes.contains(&key) { return Some(key); } } if allow_remote { - let rroutes = rss.list_remote_routes(|k, _| Some(*k)); + let rroutes = rss.list_remote_routes(|k, _| Some(k.clone())); if rroutes.contains(&key) { return Some(key); } @@ -127,19 +127,29 @@ fn get_route_id( } None => { if allow_allocated { - let routes = rss.list_allocated_routes(|k, _| Some(*k)); + let routes = rss.list_allocated_routes(|k, _| Some(k.clone())); for r in routes { - let rkey = r.encode(); - if rkey.starts_with(text) { + let rkey = r.to_string(); + if rkey.starts_with(text) + || rkey + .split_once(':') + .map(|(_, b)| b.starts_with(text)) + .unwrap_or(false) + { return Some(r); } } } if allow_remote { - let routes = rss.list_remote_routes(|k, _| Some(*k)); + let routes = rss.list_remote_routes(|k, _| Some(k.clone())); for r in routes { - let rkey = r.encode(); - if rkey.starts_with(text) { + let rkey = r.to_string(); + if rkey.starts_with(text) + || rkey + .split_once(':') + .map(|(_, b)| b.starts_with(text)) + .unwrap_or(false) + { return Some(r); } } @@ -237,12 +247,6 @@ fn get_node_id(text: &str) -> Option { fn get_typed_node_id(text: &str) -> Option { NodeId::from_str(text).ok() } -fn get_record_key(text: &str) -> Option { - BareRecordKey::from_str(text).ok() -} -fn get_keypair(text: &str) -> Option { - BareKeyPair::from_str(text).ok() -} fn get_typedkeypair(text: &str) -> Option { KeyPair::from_str(text).ok() } @@ -258,13 +262,7 @@ fn get_crypto_system_version<'a>( } fn get_dht_key_no_safety(text: &str) -> Option { - let key = if let Some(key) = get_record_key(text) { - RecordKey::new(best_crypto_kind(), key) - } else if let Some(key) = get_typed_record_key(text) { - key - } else { - return None; - }; + let key = get_typed_record_key(text)?; Some(key) } @@ -284,13 +282,7 @@ fn get_dht_key( return None; } - let key = if let Some(key) = get_record_key(text) { - RecordKey::new(best_crypto_kind(), key) - } else if let Some(key) = get_typed_record_key(text) { - key - } else { - return None; - }; + let key = get_typed_record_key(text)?; Some((key, ss)) } @@ -303,15 +295,7 @@ fn resolve_node_ref( move |text| { let text = text.to_owned(); Box::pin(async move { - let nr = if let Some(key) = get_node_id(&text) { - let node_id = NodeId::new(best_crypto_kind(), key); - registry - .rpc_processor() - .resolve_node(node_id, safety_selection) - .await - .ok() - .flatten()? - } else if let Some(node_id) = get_typed_node_id(&text) { + let nr = if let Some(node_id) = get_typed_node_id(&text) { registry .rpc_processor() .resolve_node(node_id, safety_selection) @@ -338,15 +322,7 @@ fn resolve_filtered_node_ref( .map(|x| (x.0, Some(x.1))) .unwrap_or((&text, None)); - let nr = if let Some(key) = get_node_id(text) { - let node_id = NodeId::new(best_crypto_kind(), key); - registry - .rpc_processor() - .resolve_node(node_id, safety_selection) - .await - .ok() - .flatten()? - } else if let Some(node_id) = get_typed_node_id(text) { + let nr = if let Some(node_id) = get_typed_node_id(text) { registry .rpc_processor() .resolve_node(node_id, safety_selection) @@ -1258,7 +1234,7 @@ impl VeilidAPI { )?; // Release route - let out = match rss.release_route(route_id) { + let out = match rss.release_route(route_id.clone()) { true => { // release imported self.with_debug_cache(|dc| { @@ -1315,11 +1291,11 @@ impl VeilidAPI { let out = BASE64URL_NOPAD.encode(&blob_data); veilid_log!(registry info "Published route {} as {} bytes:\n{}", - route_id.encode(), + route_id, blob_data.len(), out ); - format!("Published route {}", route_id.encode()) + format!("Published route {}", route_id) } Err(e) => { format!("Couldn't assemble private route: {}", e) @@ -1375,19 +1351,19 @@ impl VeilidAPI { let routing_table = registry.routing_table(); let rss = routing_table.route_spec_store(); - let routes = rss.list_allocated_routes(|k, _| Some(*k)); + let routes = rss.list_allocated_routes(|k, _| Some(k.clone())); let mut out = format!("Allocated Routes: (count = {}):\n", routes.len()); for r in routes { - out.push_str(&format!("{}\n", r.encode())); + out.push_str(&format!("{}\n", r)); } - let remote_routes = rss.list_remote_routes(|k, _| Some(*k)); + let remote_routes = rss.list_remote_routes(|k, _| Some(k.clone())); out.push_str(&format!( "Remote Routes: (count = {}):\n", remote_routes.len() )); for r in remote_routes { - out.push_str(&format!("{}\n", r.encode())); + out.push_str(&format!("{}\n", r)); } Ok(out) @@ -1577,7 +1553,7 @@ impl VeilidAPI { // Save routing context for record self.with_debug_cache(|dc| { - dc.opened_record_contexts.insert(*record.key(), rc); + dc.opened_record_contexts.insert(record.key(), rc); }); Ok(format!( @@ -1600,7 +1576,7 @@ impl VeilidAPI { get_dht_key(registry.clone()), )?; let writer = - get_debug_argument_at(&args, 2, "debug_record_open", "writer", get_keypair).ok(); + get_debug_argument_at(&args, 2, "debug_record_open", "writer", get_typedkeypair).ok(); // Get routing context with optional safety let rc = self.routing_context()?; @@ -1614,14 +1590,14 @@ impl VeilidAPI { }; // Do a record open - let record = match rc.open_dht_record(key, writer).await { + let record = match rc.open_dht_record(key.clone(), writer).await { Err(e) => return Ok(format!("Can't open DHT record: {}", e)), Ok(v) => v, }; // Save routing context for record self.with_debug_cache(|dc| { - dc.opened_record_contexts.insert(*record.key(), rc); + dc.opened_record_contexts.insert(record.key(), rc); }); Ok(format!("Opened: {} : {:?}", key, record)) @@ -1633,7 +1609,7 @@ impl VeilidAPI { .get_opened_dht_record_context(&args, "debug_record_close", "key", 1)?; // Do a record close - if let Err(e) = rc.close_dht_record(key).await { + if let Err(e) = rc.close_dht_record(key.clone()).await { return Ok(format!("Can't close DHT record: {}", e)); }; @@ -1663,7 +1639,7 @@ impl VeilidAPI { 3 + opt_arg_add, "debug_record_set", "writer", - get_keypair, + get_typedkeypair, ) { Ok(v) => { opt_arg_add += 1; @@ -1815,18 +1791,18 @@ impl VeilidAPI { let out = if let Some(subkey) = subkey { let li = storage_manager - .debug_local_record_subkey_info(key, subkey) + .debug_local_record_subkey_info(key.clone(), subkey) .await; let ri = storage_manager - .debug_remote_record_subkey_info(key, subkey) + .debug_remote_record_subkey_info(key.clone(), subkey) .await; format!( "Local Subkey Info:\n{}\n\nRemote Subkey Info:\n{}\n", li, ri ) } else { - let li = storage_manager.debug_local_record_info(key).await; - let ri = storage_manager.debug_remote_record_info(key).await; + let li = storage_manager.debug_local_record_info(key.clone()).await; + let ri = storage_manager.debug_remote_record_info(key.clone()).await; format!("Local Info:\n{}\n\nRemote Info:\n{}\n", li, ri) }; Ok(out) @@ -2425,8 +2401,8 @@ TableDB Operations: let n = get_number(text)?; self.with_debug_cache(|dc| { - let prid = *dc.imported_routes.get(n)?; - let Some(private_route) = rss.best_remote_private_route(&prid) else { + let prid = dc.imported_routes.get(n)?; + let Some(private_route) = rss.best_remote_private_route(prid) else { // Remove imported route let _ = dc.imported_routes.remove(n); veilid_log!(registry info "removed dead imported route {}", n); @@ -2442,9 +2418,11 @@ TableDB Operations: )) } else if let Some((first, second)) = text.split_once('@') { // Relay - let relay_nr = - resolve_filtered_node_ref(registry.clone(), ss.unwrap_or_default())(second) - .await?; + let relay_nr = resolve_filtered_node_ref( + registry.clone(), + ss.clone().unwrap_or_default(), + )(second) + .await?; let target_nr = get_node_ref(registry.clone())(first)?; let mut d = Destination::relay(relay_nr, target_nr); @@ -2455,9 +2433,11 @@ TableDB Operations: Some(d) } else { // Direct - let target_nr = - resolve_filtered_node_ref(registry.clone(), ss.unwrap_or_default())(text) - .await?; + let target_nr = resolve_filtered_node_ref( + registry.clone(), + ss.clone().unwrap_or_default(), + )(text) + .await?; let mut d = Destination::direct(target_nr); if let Some(ss) = ss { @@ -2481,7 +2461,7 @@ TableDB Operations: .ok() .or_else(|| { // If unspecified, use the most recent key opened or created - self.with_debug_cache(|dc| dc.opened_record_contexts.back().map(|kv| kv.0).copied()) + self.with_debug_cache(|dc| dc.opened_record_contexts.back().map(|kv| kv.0).cloned()) }) { Some(k) => k, None => { diff --git a/veilid-core/src/veilid_api/routing_context.rs b/veilid-core/src/veilid_api/routing_context.rs index ede0b87c..beaee676 100644 --- a/veilid-core/src/veilid_api/routing_context.rs +++ b/veilid-core/src/veilid_api/routing_context.rs @@ -5,13 +5,22 @@ impl_veilid_log_facility!("veilid_api"); /////////////////////////////////////////////////////////////////////////////////////// /// Valid destinations for a message sent over a routing context. -#[derive(Clone, Debug, Eq, PartialEq, Hash, Copy, PartialOrd, Ord)] +#[derive( + Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord, Serialize, Deserialize, JsonSchema, +)] +#[cfg_attr( + all(target_arch = "wasm32", target_os = "unknown"), + derive(Tsify), + tsify(from_wasm_abi, into_wasm_abi, namespace) +)] #[must_use] pub enum Target { - /// Node by its public key. - BareNodeId(NodeId), + /// Node by its node id + #[schemars(with = "String")] + NodeId(NodeId), /// Remote private route by its id. - PrivateRoute(BareRouteId), + #[schemars(with = "String")] + RouteId(RouteId), } pub(crate) struct RoutingContextUnlockedInner { @@ -23,7 +32,7 @@ pub(crate) struct RoutingContextUnlockedInner { /// /// By default routing contexts have 'safety routing' enabled which offers sender privacy. /// privacy. To disable this and send RPC operations straight from the node use [RoutingContext::with_safety()] with a [SafetySelection::Unsafe] parameter. -/// To enable receiver privacy, you should send to a private route BareRouteId that you have imported, rather than directly to a BareNodeId. +/// To enable receiver privacy, you should send to a private route RouteId that you have imported, rather than directly to a NodeId. /// #[derive(Clone)] #[must_use] @@ -123,10 +132,10 @@ impl RoutingContext { Self { api: self.api.clone(), unlocked_inner: Arc::new(RoutingContextUnlockedInner { - safety_selection: match self.unlocked_inner.safety_selection { + safety_selection: match &self.unlocked_inner.safety_selection { SafetySelection::Unsafe(_) => SafetySelection::Unsafe(sequencing), SafetySelection::Safe(safety_spec) => SafetySelection::Safe(SafetySpec { - preferred_route: safety_spec.preferred_route, + preferred_route: safety_spec.preferred_route.clone(), hop_count: safety_spec.hop_count, stability: safety_spec.stability, sequencing, @@ -138,13 +147,13 @@ impl RoutingContext { /// Get the safety selection in use on this routing context. pub fn safety(&self) -> SafetySelection { - self.unlocked_inner.safety_selection + self.unlocked_inner.safety_selection.clone() } /// Get the sequencing used by this routing context pub fn sequencing(&self) -> Sequencing { - match self.unlocked_inner.safety_selection { - SafetySelection::Unsafe(sequencing) => sequencing, + match &self.unlocked_inner.safety_selection { + SafetySelection::Unsafe(sequencing) => *sequencing, SafetySelection::Safe(safety_spec) => safety_spec.sequencing, } } @@ -161,8 +170,10 @@ impl RoutingContext { let rpc_processor = self.api.core_context()?.rpc_processor(); Box::pin( - rpc_processor - .resolve_target_to_destination(target, self.unlocked_inner.safety_selection), + rpc_processor.resolve_target_to_destination( + target, + self.unlocked_inner.safety_selection.clone(), + ), ) .await .map_err(VeilidAPIError::invalid_target) @@ -221,15 +232,15 @@ impl RoutingContext { /// /// Veilid apps may use this for arbitrary message passing. /// - /// * `target` - a private route. + /// * `target` - a private route id /// * `message` - an arbitrary message blob of up to 32768 bytes. /// /// Returns an answer blob of up to 32768 bytes. pub async fn app_call(&self, target: Target, message: Vec) -> VeilidAPIResult> { match target { - Target::PrivateRoute(_) => self.internal_app_call(target, message).await, - Target::BareNodeId(_) => Err(VeilidAPIError::invalid_target( - "Only PrivateRoute targets are allowed without the footgun feature", + Target::RouteId(_) => self.internal_app_call(target, message).await, + Target::NodeId(_) => Err(VeilidAPIError::invalid_target( + "Only RouteId targets are allowed without the footgun feature", )), } } @@ -281,8 +292,8 @@ impl RoutingContext { /// * `message` - an arbitrary message blob of up to 32768 bytes. pub async fn app_message(&self, target: Target, message: Vec) -> VeilidAPIResult<()> { match target { - Target::PrivateRoute(_) => self.internal_app_message(target, message).await, - Target::BareNodeId(_) => Err(VeilidAPIError::invalid_target( + Target::RouteId(_) => self.internal_app_message(target, message).await, + Target::NodeId(_) => Err(VeilidAPIError::invalid_target( "Only PrivateRoute targets are allowed without the footgun feature", )), } @@ -291,38 +302,36 @@ impl RoutingContext { /////////////////////////////////// // DHT Records - /// Deterministicly builds the record key for a given schema and owner public key + /// Deterministicly builds the record key for a given schema and owner public key. + /// The crypto kind of the record key will be that of the `owner` public key #[instrument(target = "veilid_api", level = "debug", fields(__VEILID_LOG_KEY = self.log_key()), ret, err)] pub fn get_dht_record_key( &self, schema: DHTSchema, - owner_key: &BarePublicKey, - kind: Option, + owner_key: &PublicKey, ) -> VeilidAPIResult { veilid_log!(self debug - "RoutingContext::get_dht_record_key(self: {:?}, schema: {:?}, owner_key: {:?}, kind: {:?})", self, schema, owner_key, kind); + "RoutingContext::get_dht_record_key(self: {:?}, schema: {:?}, owner_key: {:?}", self, schema, owner_key); schema.validate()?; - let kind = kind.unwrap_or(best_crypto_kind()); - Crypto::validate_crypto_kind(kind)?; let storage_manager = self.api.core_context()?.storage_manager(); - storage_manager.get_record_key(kind, schema, owner_key) + storage_manager.get_record_key(schema, owner_key) } /// Creates a new DHT record /// /// The record is considered 'open' after the create operation succeeds. /// * 'schema' - the schema to use when creating the DHT record - /// * 'owner' - optionally specify an owner keypair to use. If you leave this as None then a random one will be generated + /// * 'owner' - optionally specify an owner keypair to use. If you leave this as None then a random one will be generated. If specified, the crypto kind of the owner must match that of the `kind` parameter /// * 'kind' - specify a cryptosystem kind to use. Normally you will leave this as None to choose the 'best' cryptosystem available. - /// Returns the newly allocated DHT record's key if successful. + /// Returns the newly allocated DHT record's key if successful. /// /// Note: if you pass in an owner keypair this call is a deterministic! This means that if you try to create a new record for a given owner and schema that already exists it *will* fail. #[instrument(target = "veilid_api", level = "debug", fields(__VEILID_LOG_KEY = self.log_key()), ret, err)] pub async fn create_dht_record( &self, schema: DHTSchema, - owner: Option, + owner: Option, kind: Option, ) -> VeilidAPIResult { veilid_log!(self debug @@ -337,7 +346,7 @@ impl RoutingContext { kind, schema, owner, - self.unlocked_inner.safety_selection, + self.unlocked_inner.safety_selection.clone(), )) .await } @@ -357,16 +366,20 @@ impl RoutingContext { pub async fn open_dht_record( &self, key: RecordKey, - default_writer: Option, + default_writer: Option, ) -> VeilidAPIResult { veilid_log!(self debug "RoutingContext::open_dht_record(self: {:?}, key: {:?}, default_writer: {:?})", self, key, default_writer); - Crypto::validate_crypto_kind(key.kind)?; + Crypto::validate_crypto_kind(key.kind())?; let storage_manager = self.api.core_context()?.storage_manager(); storage_manager - .open_record(key, default_writer, self.unlocked_inner.safety_selection) + .open_record( + key, + default_writer, + self.unlocked_inner.safety_selection.clone(), + ) .await } @@ -378,7 +391,7 @@ impl RoutingContext { veilid_log!(self debug "RoutingContext::close_dht_record(self: {:?}, key: {:?})", self, key); - Crypto::validate_crypto_kind(key.kind)?; + Crypto::validate_crypto_kind(key.kind())?; let storage_manager = self.api.core_context()?.storage_manager(); Box::pin(storage_manager.close_record(key)).await @@ -394,7 +407,7 @@ impl RoutingContext { veilid_log!(self debug "RoutingContext::delete_dht_record(self: {:?}, key: {:?})", self, key); - Crypto::validate_crypto_kind(key.kind)?; + Crypto::validate_crypto_kind(key.kind())?; let storage_manager = self.api.core_context()?.storage_manager(); Box::pin(storage_manager.delete_record(key)).await @@ -416,7 +429,7 @@ impl RoutingContext { veilid_log!(self debug "RoutingContext::get_dht_value(self: {:?}, key: {:?}, subkey: {:?}, force_refresh: {:?})", self, key, subkey, force_refresh); - Crypto::validate_crypto_kind(key.kind)?; + Crypto::validate_crypto_kind(key.kind())?; let storage_manager = self.api.core_context()?.storage_manager(); Box::pin(storage_manager.get_value(key, subkey, force_refresh)).await @@ -440,7 +453,7 @@ impl RoutingContext { veilid_log!(self debug "RoutingContext::set_dht_value(self: {:?}, key: {:?}, subkey: {:?}, data: len={}, options: {:?})", self, key, subkey, data.len(), options); - Crypto::validate_crypto_kind(key.kind)?; + Crypto::validate_crypto_kind(key.kind())?; let storage_manager = self.api.core_context()?.storage_manager(); Box::pin(storage_manager.set_value(key, subkey, data, options)).await @@ -485,7 +498,7 @@ impl RoutingContext { let expiration = expiration.unwrap_or_default(); let count = count.unwrap_or(u32::MAX); - Crypto::validate_crypto_kind(key.kind)?; + Crypto::validate_crypto_kind(key.kind())?; let storage_manager = self.api.core_context()?.storage_manager(); Box::pin(storage_manager.watch_values(key, subkeys, expiration, count)).await @@ -513,7 +526,7 @@ impl RoutingContext { "RoutingContext::cancel_dht_watch(self: {:?}, key: {:?}, subkeys: {:?}", self, key, subkeys); let subkeys = subkeys.unwrap_or_default(); - Crypto::validate_crypto_kind(key.kind)?; + Crypto::validate_crypto_kind(key.kind())?; let storage_manager = self.api.core_context()?.storage_manager(); Box::pin(storage_manager.cancel_watch_values(key, subkeys)).await @@ -570,7 +583,7 @@ impl RoutingContext { "RoutingContext::inspect_dht_record(self: {:?}, key: {:?}, subkeys: {:?}, scope: {:?})", self, key, subkeys, scope); let subkeys = subkeys.unwrap_or_default(); - Crypto::validate_crypto_kind(key.kind)?; + Crypto::validate_crypto_kind(key.kind())?; let storage_manager = self.api.core_context()?.storage_manager(); Box::pin(storage_manager.inspect_record(key, subkeys, scope)).await @@ -581,13 +594,13 @@ impl RoutingContext { #[cfg(feature = "unstable-blockstore")] #[instrument(target = "veilid_api", level = "debug", fields(__VEILID_LOG_KEY = self.log_key()), ret, err)] - pub async fn find_block(&self, _block_id: BarePublicKey) -> VeilidAPIResult> { + pub async fn find_block(&self, _block_id: BlockId) -> VeilidAPIResult> { panic!("unimplemented"); } #[cfg(feature = "unstable-blockstore")] #[instrument(target = "veilid_api", level = "debug", fields(__VEILID_LOG_KEY = self.log_key()), ret, err)] - pub async fn supply_block(&self, _block_id: BarePublicKey) -> VeilidAPIResult { + pub async fn supply_block(&self, _block_id: BlockId) -> VeilidAPIResult { panic!("unimplemented"); } } diff --git a/veilid-core/src/veilid_api/serialize_helpers/mod.rs b/veilid-core/src/veilid_api/serialize_helpers/mod.rs index 5a22cdfe..b864bc89 100644 --- a/veilid-core/src/veilid_api/serialize_helpers/mod.rs +++ b/veilid-core/src/veilid_api/serialize_helpers/mod.rs @@ -1,9 +1,12 @@ use super::*; use core::fmt::Debug; +mod compression; pub mod serialize_arc; mod serialize_json; pub mod serialize_range_set_blaze; -pub use serialize_json::*; -mod compression; +mod serialize_untyped_vld0; + pub use compression::*; +pub use serialize_json::*; +pub use serialize_untyped_vld0::*; diff --git a/veilid-core/src/veilid_api/serialize_helpers/serialize_untyped_vld0.rs b/veilid-core/src/veilid_api/serialize_helpers/serialize_untyped_vld0.rs new file mode 100644 index 00000000..fb507e2f --- /dev/null +++ b/veilid-core/src/veilid_api/serialize_helpers/serialize_untyped_vld0.rs @@ -0,0 +1,30 @@ +macro_rules! untyped_vld0_serializers { + ($rust_name:ident, $typed:ty, $bare:ty) => { + paste::paste! { + pub mod [< $rust_name _try_untyped_vld0 >] { + use crate::{Encodable, CRYPTO_KIND_VLD0}; + use core::str::FromStr; + use serde::{Deserialize, Deserializer, Serialize, Serializer}; + + pub fn serialize(v: &$typed, s: S) -> Result { + v.serialize(s) + } + pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<$typed, D::Error> { + let s = ::deserialize(d)?; + match $typed::from_str(&s) { + Ok(v) => Ok(v), + Err(e) => match $bare::try_decode(&s) { + Ok(v) => Ok($typed::new(CRYPTO_KIND_VLD0, v)), + Err(_) => Err(serde::de::Error::custom(e)), + }, + } + } + } + } + }; +} + +// public_key_try_untyped_vld0 +untyped_vld0_serializers!(public_key, crate::PublicKey, crate::BarePublicKey); +// signature_try_untyped_vld0 +untyped_vld0_serializers!(signature, crate::Signature, crate::BareSignature); diff --git a/veilid-core/src/veilid_api/tests/fixtures.rs b/veilid-core/src/veilid_api/tests/fixtures.rs index 24bcd6c1..45c272a6 100644 --- a/veilid-core/src/veilid_api/tests/fixtures.rs +++ b/veilid-core/src/veilid_api/tests/fixtures.rs @@ -2,6 +2,7 @@ use crate::*; // Fixtures used by various tests +#[must_use] pub fn fix_latencystats() -> LatencyStats { LatencyStats { fastest: TimestampDuration::from(1234), @@ -14,6 +15,7 @@ pub fn fix_latencystats() -> LatencyStats { } } +#[must_use] pub fn fix_transferstats() -> TransferStats { TransferStats { total: ByteCount::from(1_000_000), @@ -23,6 +25,7 @@ pub fn fix_transferstats() -> TransferStats { } } +#[must_use] pub fn fix_transferstatsdownup() -> TransferStatsDownUp { TransferStatsDownUp { down: fix_transferstats(), @@ -30,6 +33,7 @@ pub fn fix_transferstatsdownup() -> TransferStatsDownUp { } } +#[must_use] pub fn fix_answerstats() -> AnswerStats { AnswerStats { span: TimestampDuration::new_secs(10), @@ -45,6 +49,7 @@ pub fn fix_answerstats() -> AnswerStats { } } +#[must_use] pub fn fix_rpcstats() -> RPCStats { RPCStats { messages_sent: 1_000_000, @@ -61,6 +66,7 @@ pub fn fix_rpcstats() -> RPCStats { } } +#[must_use] pub fn fix_statestats() -> StateStats { StateStats { span: TimestampDuration::new_secs(10), @@ -80,6 +86,7 @@ pub fn fix_statestats() -> StateStats { } } +#[must_use] pub fn fix_peerstats() -> PeerStats { PeerStats { time_added: Timestamp::from(1685569176894), @@ -91,51 +98,61 @@ pub fn fix_peerstats() -> PeerStats { } pub fn fix_publickey() -> BarePublicKey { - let mut fake_key = [0u8; CRYPTO_KEY_LENGTH]; + let mut fake_key = [0u8; VLD0_PUBLIC_KEY_LENGTH]; random_bytes(&mut fake_key); - BarePublicKey::new(fake_key) + BarePublicKey::new(&fake_key) } pub fn fix_recordkey() -> BareRecordKey { - let mut fake_key = [0u8; CRYPTO_KEY_LENGTH]; + let mut fake_key = [0u8; VLD0_HASH_DIGEST_LENGTH]; random_bytes(&mut fake_key); - BareRecordKey::new(fake_key) + BareRecordKey::new(&fake_key) } pub fn fix_routeid() -> BareRouteId { - let mut fake_key = [0u8; CRYPTO_KEY_LENGTH]; + let mut fake_key = [0u8; VLD0_HASH_DIGEST_LENGTH]; random_bytes(&mut fake_key); - BareRouteId::new(fake_key) + BareRouteId::new(&fake_key) } pub fn fix_nodeid() -> BareNodeId { - let mut fake_key = [0u8; CRYPTO_KEY_LENGTH]; + let mut fake_key = [0u8; VLD0_HASH_DIGEST_LENGTH]; random_bytes(&mut fake_key); - BareNodeId::new(fake_key) + BareNodeId::new(&fake_key) +} + +pub fn fix_memberid() -> BareMemberId { + let mut fake_key = [0u8; VLD0_HASH_DIGEST_LENGTH]; + random_bytes(&mut fake_key); + BareMemberId::new(&fake_key) +} + +pub fn fix_hashdigest() -> BareHashDigest { + let mut fake_key = [0u8; VLD0_HASH_DIGEST_LENGTH]; + random_bytes(&mut fake_key); + BareHashDigest::new(&fake_key) } pub fn fix_typednodeid() -> NodeId { - let mut fake_key = [0u8; CRYPTO_KEY_LENGTH]; - random_bytes(&mut fake_key); - NodeId { - kind: CryptoKind::from_str("FAKE").unwrap(), - value: fix_nodeid(), - } + NodeId::new(CryptoKind::from_str("FAKE").unwrap(), fix_nodeid()) +} + +pub fn fix_typedrouteid() -> RouteId { + RouteId::new(CryptoKind::from_str("FAKE").unwrap(), fix_routeid()) } pub fn fix_typedrecordkey() -> RecordKey { - let mut fake_key = [0u8; CRYPTO_KEY_LENGTH]; - random_bytes(&mut fake_key); - RecordKey { - kind: CryptoKind::from_str("FAKE").unwrap(), - value: fix_recordkey(), - } + RecordKey::new(CryptoKind::from_str("FAKE").unwrap(), fix_recordkey()) +} + +pub fn fix_typedpublickey() -> PublicKey { + PublicKey::new(CryptoKind::from_str("FAKE").unwrap(), fix_publickey()) } pub fn fix_secretkey() -> BareSecretKey { - let mut fake_key = [0u8; CRYPTO_KEY_LENGTH]; + let mut fake_key = [0u8; VLD0_SECRET_KEY_LENGTH]; random_bytes(&mut fake_key); - BareSecretKey::new(fake_key) + BareSecretKey::new(&fake_key) } pub fn fix_peertabledata() -> PeerTableData { @@ -299,6 +316,8 @@ pub fn fix_veilidvaluechange() -> VeilidValueChange { key: fix_typedrecordkey(), subkeys: ValueSubkeyRangeSet::new(), count: 5, - value: Some(ValueData::new_with_seq(23, b"ValueData".to_vec(), fix_publickey()).unwrap()), + value: Some( + ValueData::new_with_seq(23, b"ValueData".to_vec(), fix_typedpublickey()).unwrap(), + ), } } diff --git a/veilid-core/src/veilid_api/tests/mod.rs b/veilid-core/src/veilid_api/tests/mod.rs index 1d0d9680..cd2c13a0 100644 --- a/veilid-core/src/veilid_api/tests/mod.rs +++ b/veilid-core/src/veilid_api/tests/mod.rs @@ -1,4 +1,4 @@ -mod fixtures; +pub mod fixtures; #[doc(hidden)] pub mod test_serialize_json; mod test_types; diff --git a/veilid-core/src/veilid_api/tests/test_types.rs b/veilid-core/src/veilid_api/tests/test_types.rs index bb39e7af..89f6277d 100644 --- a/veilid-core/src/veilid_api/tests/test_types.rs +++ b/veilid-core/src/veilid_api/tests/test_types.rs @@ -15,7 +15,7 @@ pub fn test_alignedu64() { pub fn test_veilidappmessage() { let orig = VeilidAppMessage::new( Some(fix_typednodeid()), - Some(fix_routeid()), + Some(fix_typedrouteid()), b"Hi there!".to_vec(), ); let copy = deserialize_json(&serialize_json(&orig)).unwrap(); @@ -26,7 +26,7 @@ pub fn test_veilidappmessage() { pub fn test_veilidappcall() { let orig = VeilidAppCall::new( Some(fix_typednodeid()), - Some(fix_routeid()), + Some(fix_typedrouteid()), b"Well, hello!".to_vec(), OperationId::from(123), ); @@ -62,19 +62,19 @@ pub fn test_stability() { pub fn test_safetyselection() { let orig = SafetySelection::Unsafe(Sequencing::EnsureOrdered); - let copy = deserialize_json(&serialize_json(orig)).unwrap(); + let copy = deserialize_json(&serialize_json(orig.clone())).unwrap(); assert_eq!(orig, copy); } pub fn test_safetyspec() { let orig = SafetySpec { - preferred_route: Some(fix_routeid()), + preferred_route: Some(fix_typedrouteid()), hop_count: 23, stability: Stability::default(), sequencing: Sequencing::default(), }; - let copy = deserialize_json(&serialize_json(orig)).unwrap(); + let copy = deserialize_json(&serialize_json(orig.clone())).unwrap(); assert_eq!(orig, copy); } @@ -242,8 +242,8 @@ pub fn test_veilidstatenetwork() { pub fn test_veilidroutechange() { let orig = VeilidRouteChange { - dead_routes: vec![fix_routeid()], - dead_remote_routes: vec![fix_routeid()], + dead_routes: vec![fix_typedrouteid()], + dead_remote_routes: vec![fix_typedrouteid()], }; let copy = deserialize_json(&serialize_json(&orig)).unwrap(); diff --git a/veilid-core/src/veilid_api/tests/test_types_dht.rs b/veilid-core/src/veilid_api/tests/test_types_dht.rs index 3d4e2c7a..b0d0cf41 100644 --- a/veilid-core/src/veilid_api/tests/test_types_dht.rs +++ b/veilid-core/src/veilid_api/tests/test_types_dht.rs @@ -7,7 +7,7 @@ use range_set_blaze::*; pub fn test_dhtrecorddescriptor() { let orig = DHTRecordDescriptor::new( fix_typedrecordkey(), - fix_publickey(), + fix_typedpublickey(), Some(fix_secretkey()), DHTSchema::dflt(4321).unwrap(), ); @@ -19,7 +19,7 @@ pub fn test_dhtrecorddescriptor() { // value_data pub fn test_valuedata() { - let orig = ValueData::new_with_seq(42, b"Brent Spiner".to_vec(), fix_publickey()); + let orig = ValueData::new_with_seq(42, b"Brent Spiner".to_vec(), fix_typedpublickey()); let copy = deserialize_json(&serialize_json(&orig)).unwrap(); assert_eq!(orig, copy); diff --git a/veilid-core/src/veilid_api/tests/test_types_dht_schema.rs b/veilid-core/src/veilid_api/tests/test_types_dht_schema.rs index aa7f7845..620c2ab0 100644 --- a/veilid-core/src/veilid_api/tests/test_types_dht_schema.rs +++ b/veilid-core/src/veilid_api/tests/test_types_dht_schema.rs @@ -18,11 +18,11 @@ pub fn test_dhtschema() { 91, vec![ DHTSchemaSMPLMember { - m_key: fix_publickey(), + m_key: fix_memberid(), m_cnt: 5, }, DHTSchemaSMPLMember { - m_key: fix_publickey(), + m_key: fix_memberid(), m_cnt: 6, }, ], @@ -38,7 +38,7 @@ pub fn test_dhtschema() { pub fn test_dhtschemasmplmember() { let orig = DHTSchemaSMPLMember { - m_key: fix_publickey(), + m_key: fix_memberid(), m_cnt: 7, }; let copy = deserialize_json(&serialize_json(&orig)).unwrap(); @@ -51,11 +51,11 @@ pub fn test_dhtschemasmpl() { 91, vec![ DHTSchemaSMPLMember { - m_key: fix_publickey(), + m_key: fix_memberid(), m_cnt: 8, }, DHTSchemaSMPLMember { - m_key: fix_publickey(), + m_key: fix_memberid(), m_cnt: 9, }, ], diff --git a/veilid-core/src/veilid_api/types/app_message_call.rs b/veilid-core/src/veilid_api/types/app_message_call.rs index c9656c9b..658399b7 100644 --- a/veilid-core/src/veilid_api/types/app_message_call.rs +++ b/veilid-core/src/veilid_api/types/app_message_call.rs @@ -19,7 +19,7 @@ pub struct VeilidAppMessage { all(target_arch = "wasm32", target_os = "unknown"), tsify(optional, type = "string") )] - route_id: Option, + route_id: Option, #[cfg_attr( not(all(target_arch = "wasm32", target_os = "unknown")), @@ -35,7 +35,7 @@ pub struct VeilidAppMessage { } impl VeilidAppMessage { - pub fn new(sender: Option, route_id: Option, message: Vec) -> Self { + pub fn new(sender: Option, route_id: Option, message: Vec) -> Self { Self { sender, route_id, @@ -51,7 +51,7 @@ impl VeilidAppMessage { /// Some(route_id) if the message was received over a private route, None if received only a safety route or directly. #[must_use] - pub fn route_id(&self) -> Option<&BareRouteId> { + pub fn route_id(&self) -> Option<&RouteId> { self.route_id.as_ref() } @@ -78,7 +78,7 @@ pub struct VeilidAppCall { all(target_arch = "wasm32", target_os = "unknown"), tsify(optional, type = "string") )] - route_id: Option, + route_id: Option, #[cfg_attr( not(all(target_arch = "wasm32", target_os = "unknown")), @@ -100,7 +100,7 @@ pub struct VeilidAppCall { impl VeilidAppCall { pub fn new( sender: Option, - route_id: Option, + route_id: Option, message: Vec, call_id: OperationId, ) -> Self { @@ -120,7 +120,7 @@ impl VeilidAppCall { /// Some(route_id) if the request was received over a private route, None if received only a safety route or directly. #[must_use] - pub fn route_id(&self) -> Option<&BareRouteId> { + pub fn route_id(&self) -> Option<&RouteId> { self.route_id.as_ref() } diff --git a/veilid-core/src/veilid_api/types/dht/dht_record_descriptor.rs b/veilid-core/src/veilid_api/types/dht/dht_record_descriptor.rs index 76582b27..1c39d7a8 100644 --- a/veilid-core/src/veilid_api/types/dht/dht_record_descriptor.rs +++ b/veilid-core/src/veilid_api/types/dht/dht_record_descriptor.rs @@ -14,7 +14,8 @@ pub struct DHTRecordDescriptor { key: RecordKey, /// The public key of the owner #[schemars(with = "String")] - owner: BarePublicKey, + #[serde(with = "public_key_try_untyped_vld0")] + owner: PublicKey, /// If this key is being created: Some(the secret key of the owner) /// If this key is just being opened: None #[schemars(with = "Option")] @@ -27,7 +28,7 @@ pub struct DHTRecordDescriptor { impl DHTRecordDescriptor { pub(crate) fn new( key: RecordKey, - owner: BarePublicKey, + owner: PublicKey, owner_secret: Option, schema: DHTSchema, ) -> Self { @@ -39,15 +40,24 @@ impl DHTRecordDescriptor { } } - pub fn key(&self) -> &RecordKey { + pub fn key(&self) -> RecordKey { + self.key.clone() + } + pub fn ref_key(&self) -> &RecordKey { &self.key } - pub fn owner(&self) -> &BarePublicKey { + pub fn owner(&self) -> PublicKey { + self.owner.clone() + } + pub fn ref_owner(&self) -> &PublicKey { &self.owner } - #[must_use] - pub fn owner_secret(&self) -> Option<&BareSecretKey> { + pub fn owner_secret(&self) -> Option { + self.owner_secret.clone() + } + #[must_use] + pub fn ref_owner_secret(&self) -> Option<&BareSecretKey> { self.owner_secret.as_ref() } diff --git a/veilid-core/src/veilid_api/types/dht/schema/dflt.rs b/veilid-core/src/veilid_api/types/dht/schema/dflt.rs index d008a47b..cc8c3673 100644 --- a/veilid-core/src/veilid_api/types/dht/schema/dflt.rs +++ b/veilid-core/src/veilid_api/types/dht/schema/dflt.rs @@ -1,5 +1,4 @@ use super::*; -use crate::storage_manager::{MAX_RECORD_DATA_SIZE, MAX_SUBKEY_SIZE}; /// Default DHT Schema (DFLT) #[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, JsonSchema)] @@ -61,50 +60,9 @@ impl DHTSchemaDFLT { 0 } - /// Check a subkey value data against the schema - pub fn check_subkey_value_data( - &self, - owner: &BarePublicKey, - subkey: ValueSubkey, - value_data: &ValueData, - ) -> VeilidAPIResult<()> { - let subkey = subkey as usize; - - // Check if subkey is in owner range - if subkey < (self.o_cnt as usize) { - // Check value data has valid writer - if value_data.writer() == owner { - let max_value_len = - usize::min(MAX_SUBKEY_SIZE, MAX_RECORD_DATA_SIZE / self.o_cnt as usize); - - // Ensure value size is within additional limit - if value_data.data_size() <= max_value_len { - return Ok(()); - } - - // Value too big - apibail_invalid_argument!( - "value too big", - "data", - format!("{:?}", value_data.data()) - ); - } - - // Wrong writer - apibail_invalid_argument!( - "wrong writer", - "writer", - format!("{:?}", value_data.writer()) - ); - } - - // Subkey out of range - apibail_invalid_argument!("subkey out of range", "subkey", subkey); - } - - /// Check if a key is a schema member + /// Check if a hash is a schema member #[must_use] - pub fn is_member(&self, _key: &BarePublicKey) -> bool { + pub fn is_member(&self, _member_id: &BareMemberId) -> bool { false } } diff --git a/veilid-core/src/veilid_api/types/dht/schema/mod.rs b/veilid-core/src/veilid_api/types/dht/schema/mod.rs index dd37dcb1..4d251f7e 100644 --- a/veilid-core/src/veilid_api/types/dht/schema/mod.rs +++ b/veilid-core/src/veilid_api/types/dht/schema/mod.rs @@ -63,25 +63,12 @@ impl DHTSchema { } } - /// Check a subkey value data against the schema - pub fn check_subkey_value_data( - &self, - owner: &BarePublicKey, - subkey: ValueSubkey, - value_data: &ValueData, - ) -> VeilidAPIResult<()> { - match self { - DHTSchema::DFLT(d) => d.check_subkey_value_data(owner, subkey, value_data), - DHTSchema::SMPL(s) => s.check_subkey_value_data(owner, subkey, value_data), - } - } - - /// Check if a key is a schema member + /// Check if a hash is a schema member #[must_use] - pub fn is_member(&self, key: &BarePublicKey) -> bool { + pub fn is_member(&self, member_id: &BareMemberId) -> bool { match self { - DHTSchema::DFLT(d) => d.is_member(key), - DHTSchema::SMPL(s) => s.is_member(key), + DHTSchema::DFLT(d) => d.is_member(member_id), + DHTSchema::SMPL(s) => s.is_member(member_id), } } diff --git a/veilid-core/src/veilid_api/types/dht/schema/smpl.rs b/veilid-core/src/veilid_api/types/dht/schema/smpl.rs index 427d39ce..3cac3bdd 100644 --- a/veilid-core/src/veilid_api/types/dht/schema/smpl.rs +++ b/veilid-core/src/veilid_api/types/dht/schema/smpl.rs @@ -1,5 +1,5 @@ use super::*; -use crate::storage_manager::{MAX_RECORD_DATA_SIZE, MAX_SUBKEY_SIZE}; +use crate::storage_manager::MEMBER_ID_LENGTH; /// Simple DHT Schema (SMPL) Member #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema)] @@ -12,7 +12,7 @@ use crate::storage_manager::{MAX_RECORD_DATA_SIZE, MAX_SUBKEY_SIZE}; pub struct DHTSchemaSMPLMember { /// Member key #[schemars(with = "String")] - pub m_key: BarePublicKey, + pub m_key: BareMemberId, /// Member subkey count pub m_cnt: u16, } @@ -45,10 +45,17 @@ impl DHTSchemaSMPL { /// Validate the data representation pub fn validate(&self) -> VeilidAPIResult<()> { - let keycount = self - .members - .iter() - .fold(self.o_cnt as usize, |acc, x| acc + (x.m_cnt as usize)); + let mut keycount = self.o_cnt as usize; + for m in &self.members { + if m.m_key.len() != MEMBER_ID_LENGTH { + apibail_invalid_argument!( + "member hash digest is wrong size", + "m_key.len()", + m.m_key.len() + ); + } + keycount += m.m_cnt as usize; + } if keycount == 0 { apibail_invalid_argument!("must have at least one subkey", "keycount", keycount); @@ -74,7 +81,7 @@ impl DHTSchemaSMPL { #[must_use] pub fn compile(&self) -> Vec { let mut out = Vec::::with_capacity( - Self::FIXED_SIZE + (self.members.len() * (PUBLIC_KEY_LENGTH + 2)), + Self::FIXED_SIZE + (self.members.len() * (MEMBER_ID_LENGTH + 2)), ); // kind out.extend_from_slice(&Self::FCC); @@ -83,7 +90,7 @@ impl DHTSchemaSMPL { // members for m in &self.members { // m_key - out.extend_from_slice(&m.m_key.bytes); + out.extend_from_slice(&m.m_key); // m_cnt out.extend_from_slice(&m.m_cnt.to_le_bytes()); } @@ -106,82 +113,11 @@ impl DHTSchemaSMPL { self.members.len() * mem::size_of::() } - /// Check a subkey value data against the schema - pub fn check_subkey_value_data( - &self, - owner: &BarePublicKey, - subkey: ValueSubkey, - value_data: &ValueData, - ) -> VeilidAPIResult<()> { - let mut cur_subkey = subkey as usize; - - let max_value_len = usize::min( - MAX_SUBKEY_SIZE, - MAX_RECORD_DATA_SIZE / (self.max_subkey() + 1) as usize, - ); - - // Check if subkey is in owner range - if cur_subkey < (self.o_cnt as usize) { - // Check value data has valid writer - if value_data.writer() == owner { - // Ensure value size is within additional limit - if value_data.data_size() <= max_value_len { - return Ok(()); - } - - // Value too big - apibail_invalid_argument!( - "value too big", - "data", - format!("{:?}", value_data.data()) - ); - } - // Wrong writer - apibail_invalid_argument!( - "wrong writer", - "writer", - format!("{:?}", value_data.writer()) - ); - } - cur_subkey -= self.o_cnt as usize; - - // Check all member ranges - for m in &self.members { - // Check if subkey is in member range - if cur_subkey < (m.m_cnt as usize) { - // Check value data has valid writer - if value_data.writer() == &m.m_key { - // Ensure value size is in allowed range - if value_data.data_size() <= max_value_len { - return Ok(()); - } - - // Value too big - apibail_invalid_argument!( - "value too big", - "data", - format!("{:?}", value_data.data()) - ); - } - // Wrong writer - apibail_invalid_argument!( - "wrong writer", - "writer", - format!("{:?}", value_data.writer()) - ); - } - cur_subkey -= m.m_cnt as usize; - } - - // Subkey out of range - apibail_invalid_argument!("subkey out of range", "subkey", subkey); - } - - /// Check if a key is a schema member + /// Check if a hash is a schema member #[must_use] - pub fn is_member(&self, key: &BarePublicKey) -> bool { + pub fn is_member(&self, member_id: &BareMemberId) -> bool { for m in &self.members { - if m.m_key == *key { + if &m.m_key == member_id { return true; } } @@ -198,20 +134,19 @@ impl TryFrom<&[u8]> for DHTSchemaSMPL { if b[0..4] != Self::FCC { apibail_generic!("wrong fourcc"); } - if (b.len() - Self::FIXED_SIZE) % (PUBLIC_KEY_LENGTH + 2) != 0 { + if (b.len() - Self::FIXED_SIZE) % (MEMBER_ID_LENGTH + 2) != 0 { apibail_generic!("invalid member length"); } let o_cnt = u16::from_le_bytes(b[4..6].try_into().map_err(VeilidAPIError::internal)?); - let members_len = (b.len() - Self::FIXED_SIZE) / (PUBLIC_KEY_LENGTH + 2); + let members_len = (b.len() - Self::FIXED_SIZE) / (MEMBER_ID_LENGTH + 2); let mut members: Vec = Vec::with_capacity(members_len); for n in 0..members_len { - let mstart = Self::FIXED_SIZE + n * (PUBLIC_KEY_LENGTH + 2); - let m_key = BarePublicKey::try_from(&b[mstart..mstart + PUBLIC_KEY_LENGTH]) - .map_err(VeilidAPIError::internal)?; + let mstart = Self::FIXED_SIZE + n * (MEMBER_ID_LENGTH + 2); + let m_key = BareMemberId::new(&b[mstart..mstart + MEMBER_ID_LENGTH]); let m_cnt = u16::from_le_bytes( - b[mstart + PUBLIC_KEY_LENGTH..mstart + PUBLIC_KEY_LENGTH + 2] + b[mstart + MEMBER_ID_LENGTH..mstart + MEMBER_ID_LENGTH + 2] .try_into() .map_err(VeilidAPIError::internal)?, ); diff --git a/veilid-core/src/veilid_api/types/dht/set_dht_value_options.rs b/veilid-core/src/veilid_api/types/dht/set_dht_value_options.rs index 090320ce..35794d53 100644 --- a/veilid-core/src/veilid_api/types/dht/set_dht_value_options.rs +++ b/veilid-core/src/veilid_api/types/dht/set_dht_value_options.rs @@ -1,4 +1,4 @@ -use crate::{BareKeyPair, Deserialize, JsonSchema, Serialize}; +use crate::{Deserialize, JsonSchema, KeyPair, Serialize}; #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] use crate::Tsify; @@ -24,7 +24,7 @@ impl Default for AllowOffline { )] pub struct SetDHTValueOptions { #[schemars(with = "Option")] - pub writer: Option, + pub writer: Option, /// Defaults to true. If false, the value will not be written if the node is offline, /// and a TryAgain error will be returned. pub allow_offline: Option, diff --git a/veilid-core/src/veilid_api/types/dht/value_data.rs b/veilid-core/src/veilid_api/types/dht/value_data.rs index ee0d0c26..70201aef 100644 --- a/veilid-core/src/veilid_api/types/dht/value_data.rs +++ b/veilid-core/src/veilid_api/types/dht/value_data.rs @@ -1,7 +1,7 @@ use super::*; use veilid_api::VeilidAPIResult; -#[derive(Clone, Default, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize, JsonSchema)] #[cfg_attr( all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify), @@ -27,13 +27,14 @@ pub struct ValueData { /// The public identity key of the writer of the data #[schemars(with = "String")] - writer: BarePublicKey, + #[serde(with = "public_key_try_untyped_vld0")] + writer: PublicKey, } impl ValueData { pub const MAX_LEN: usize = 32768; - pub fn new(data: Vec, writer: BarePublicKey) -> VeilidAPIResult { + pub fn new(data: Vec, writer: PublicKey) -> VeilidAPIResult { if data.len() > Self::MAX_LEN { apibail_generic!("invalid size"); } @@ -46,7 +47,7 @@ impl ValueData { pub fn new_with_seq( seq: ValueSeqNum, data: Vec, - writer: BarePublicKey, + writer: PublicKey, ) -> VeilidAPIResult { if data.len() > Self::MAX_LEN { apibail_generic!("invalid size"); @@ -59,7 +60,11 @@ impl ValueData { self.seq } - pub fn writer(&self) -> &BarePublicKey { + pub fn writer(&self) -> PublicKey { + self.writer.clone() + } + + pub fn ref_writer(&self) -> &PublicKey { &self.writer } @@ -92,34 +97,22 @@ impl fmt::Debug for ValueData { #[cfg(test)] mod tests { use super::*; + use crate::tests::fixtures::*; #[test] fn value_data_ok() { - assert!(ValueData::new( - vec![0; ValueData::MAX_LEN], - BarePublicKey { bytes: [0; 32] } - ) - .is_ok()); - assert!(ValueData::new_with_seq( - 0, - vec![0; ValueData::MAX_LEN], - BarePublicKey { bytes: [0; 32] } - ) - .is_ok()); + assert!(ValueData::new(vec![0; ValueData::MAX_LEN], fix_typedpublickey()).is_ok()); + assert!( + ValueData::new_with_seq(0, vec![0; ValueData::MAX_LEN], fix_typedpublickey()).is_ok() + ); } #[test] fn value_data_too_long() { - assert!(ValueData::new( - vec![0; ValueData::MAX_LEN + 1], - BarePublicKey { bytes: [0; 32] } - ) - .is_err()); - assert!(ValueData::new_with_seq( - 0, - vec![0; ValueData::MAX_LEN + 1], - BarePublicKey { bytes: [0; 32] } - ) - .is_err()); + assert!(ValueData::new(vec![0; ValueData::MAX_LEN + 1], fix_typedpublickey()).is_err()); + assert!( + ValueData::new_with_seq(0, vec![0; ValueData::MAX_LEN + 1], fix_typedpublickey()) + .is_err() + ); } } diff --git a/veilid-core/src/veilid_api/types/safety.rs b/veilid-core/src/veilid_api/types/safety.rs index 57661a1f..55d6939d 100644 --- a/veilid-core/src/veilid_api/types/safety.rs +++ b/veilid-core/src/veilid_api/types/safety.rs @@ -47,7 +47,7 @@ impl Default for Stability { /// The choice of safety route to include in compiled routes. #[derive( - Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, JsonSchema, + Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, JsonSchema, )] #[cfg_attr( all(target_arch = "wasm32", target_os = "unknown"), @@ -79,7 +79,7 @@ impl Default for SafetySelection { /// Options for safety routes (sender privacy). #[derive( - Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, JsonSchema, + Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, JsonSchema, )] #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))] #[must_use] @@ -90,7 +90,7 @@ pub struct SafetySpec { all(target_arch = "wasm32", target_os = "unknown"), tsify(optional, type = "string") )] - pub preferred_route: Option, + pub preferred_route: Option, /// Must be greater than 0. pub hop_count: usize, /// Prefer reliability over speed. diff --git a/veilid-core/src/veilid_api/types/veilid_state.rs b/veilid-core/src/veilid_api/types/veilid_state.rs index b8ea2167..ae2cb890 100644 --- a/veilid-core/src/veilid_api/types/veilid_state.rs +++ b/veilid-core/src/veilid_api/types/veilid_state.rs @@ -137,10 +137,10 @@ pub struct VeilidStateNetwork { pub struct VeilidRouteChange { /// If a private route that was allocated has died, it is listed here. #[schemars(with = "Vec")] - pub dead_routes: Vec, + pub dead_routes: Vec, /// If a private route that was imported has died, it is listed here. #[schemars(with = "Vec")] - pub dead_remote_routes: Vec, + pub dead_remote_routes: Vec, } /// Describe changes to the Veilid node configuration diff --git a/veilid-flutter/example/integration_test/app_test.dart b/veilid-flutter/example/integration_test/app_test.dart index 03bdbe7c..cfd04a43 100644 --- a/veilid-flutter/example/integration_test/app_test.dart +++ b/veilid-flutter/example/integration_test/app_test.dart @@ -71,6 +71,8 @@ void main() { 'create delete dht record simple', testCreateDeleteDHTRecordSimple); test('create delete dht record no close', testCreateDeleteDHTRecordNoClose); + test('create delete dht record with deterministic key', + testCreateDHTRecordWithDeterministicKey); test('get dht value nonexistent', testGetDHTValueNonexistent); test('set get dht value', testSetGetDHTValue); test('set get dht value with owner', testSetGetDHTValueWithOwner); diff --git a/veilid-flutter/example/integration_test/test_crypto.dart b/veilid-flutter/example/integration_test/test_crypto.dart index 4a72209c..9a285eef 100644 --- a/veilid-flutter/example/integration_test/test_crypto.dart +++ b/veilid-flutter/example/integration_test/test_crypto.dart @@ -55,7 +55,7 @@ Future testSignAndVerifySignatures() async { // BareSignature match final sigs = await Veilid.instance.generateSignatures( - utf8.encode('abc123'), [KeyPair.fromKeyPair(kind, kp1)]); + utf8.encode('abc123'), [KeyPair.fromBareKeyPair(kind, kp1)]); expect( await Veilid.instance.verifySignatures( [PublicKey(kind: kind, value: kp1.key)], utf8.encode('abc123'), sigs), diff --git a/veilid-flutter/example/integration_test/test_dht.dart b/veilid-flutter/example/integration_test/test_dht.dart index eb2ce7a8..839661a8 100644 --- a/veilid-flutter/example/integration_test/test_dht.dart +++ b/veilid-flutter/example/integration_test/test_dht.dart @@ -5,7 +5,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:veilid/veilid.dart'; final bogusKey = - PublicKey.fromString('VLD0:qD10lHHPD1_Qr23_Qy-1JnxTht12eaWwENVG_m2v7II'); + RecordKey.fromString('VLD0:qD10lHHPD1_Qr23_Qy-1JnxTht12eaWwENVG_m2v7II'); Future testGetDHTValueUnopened() async { final rc = await Veilid.instance.routingContext(); @@ -106,7 +106,8 @@ Future testSetGetDHTValueWithOwner() async { final rc = await Veilid.instance.routingContext(); try { final cs = await Veilid.instance.bestCryptoSystem(); - final ownerKeyPair = await cs.generateKeyPair(); + final ownerKeyPair = + KeyPair.fromBareKeyPair(cs.kind(), await cs.generateKeyPair()); final rec = await rc.createDHTRecord(const DHTSchema.dflt(oCnt: 2), owner: ownerKeyPair); @@ -129,6 +130,32 @@ Future testSetGetDHTValueWithOwner() async { } } +Future testCreateDHTRecordWithDeterministicKey() async { + final rc = await Veilid.instance.routingContext(); + try { + final bestCryptoSystem = await Veilid.instance.bestCryptoSystem(); + final bestCryptoKind = bestCryptoSystem.kind(); + final ownerKeyPair = await bestCryptoSystem.generateKeyPair(); + final owner = ownerKeyPair.key; + final secret = ownerKeyPair.secret; + const schema = DHTSchema.dflt(oCnt: 1); + final dhtRecordKey = await rc.getDHTRecordKey( + schema, PublicKey(kind: bestCryptoKind, value: owner)); + final dhtRecord = await rc.createDHTRecord(const DHTSchema.dflt(oCnt: 1), + owner: KeyPair.fromBareKeyPair(bestCryptoKind, ownerKeyPair), + kind: bestCryptoKind); + expect(dhtRecord.key, equals(dhtRecordKey)); + expect( + dhtRecord.owner, equals(PublicKey(kind: bestCryptoKind, value: owner))); + expect(dhtRecord.ownerSecret, equals(secret)); + expect(dhtRecord.schema, equals(schema)); + await rc.closeDHTRecord(dhtRecord.key); + await rc.deleteDHTRecord(dhtRecord.key); + } finally { + rc.close(); + } +} + Future testOpenWriterDHTValue() async { final rc = await Veilid.instance.routingContext(); try { @@ -138,8 +165,9 @@ Future testOpenWriterDHTValue() async { final secret = rec.ownerSecret!; final cs = await Veilid.instance.getCryptoSystem(rec.key.kind); - expect(await cs.validateKeyPair(owner, secret), isTrue); - final otherKeyPair = await cs.generateKeyPair(); + expect(await cs.validateKeyPair(owner.value, secret), isTrue); + final otherKeyPair = + KeyPair.fromBareKeyPair(cs.kind(), await cs.generateKeyPair()); final va = utf8.encode('Qwertyuiop Asdfghjkl Zxcvbnm'); final vb = utf8.encode('1234567890'); @@ -193,7 +221,7 @@ Future testOpenWriterDHTValue() async { await rc.deleteDHTRecord(key); rec = await rc.openDHTRecord(key, - writer: BareKeyPair(key: owner, secret: secret)); + writer: KeyPair.fromPublicAndBareSecret(owner, secret)); expect(rec, isNotNull); expect(rec.key, equals(key)); expect(rec.owner, equals(owner)); @@ -245,7 +273,7 @@ Future testOpenWriterDHTValue() async { // exists online at seq 0 vdtemp = await rc.setDHTValue(key, 0, va, options: SetDHTValueOptions( - writer: BareKeyPair(key: owner, secret: secret))); + writer: KeyPair.fromPublicAndBareSecret(owner, secret))); expect(vdtemp, isNotNull); expect(vdtemp!.data, equals(vb)); expect(vdtemp.seq, equals(0)); @@ -254,7 +282,7 @@ Future testOpenWriterDHTValue() async { // Should update the second time to seq 1 vdtemp = await rc.setDHTValue(key, 0, va, options: SetDHTValueOptions( - writer: BareKeyPair(key: owner, secret: secret))); + writer: KeyPair.fromPublicAndBareSecret(owner, secret))); expect(vdtemp, isNull); // Clean up @@ -265,7 +293,7 @@ Future testOpenWriterDHTValue() async { } } -Future settle(VeilidRoutingContext rc, PublicKey key, int subkey) async { +Future settle(VeilidRoutingContext rc, RecordKey key, int subkey) async { // Wait for set to settle do { await Future.delayed(const Duration(milliseconds: 100)); diff --git a/veilid-flutter/example/integration_test/test_routing_context.dart b/veilid-flutter/example/integration_test/test_routing_context.dart index 3ce19f15..82bf4b85 100644 --- a/veilid-flutter/example/integration_test/test_routing_context.dart +++ b/veilid-flutter/example/integration_test/test_routing_context.dart @@ -73,7 +73,7 @@ Future testAppMessageLoopback(Stream updateStream) async { try { // send an app message to our own private route final message = utf8.encode('abcd1234'); - await rc.appMessage(prr, message); + await rc.appMessage(TargetRouteId(routeId: prr), message); // we should get the same message back final update = await appMessageQueue.stream.first; @@ -115,7 +115,8 @@ Future testAppCallLoopback(Stream updateStream) async { try { // send an app call to our own private route final message = utf8.encode('abcd1234'); - final appCallFuture = rc.appCall(prr, message); + final appCallFuture = + rc.appCall(TargetRouteId(routeId: prr), message); // we should get the same call back final update = await appCallQueue.stream.first; @@ -176,7 +177,7 @@ Future testAppMessageLoopbackBigPackets( for (var i = 0; i < 5; i++) { // send an app message to our own private route final message = await cs.randomBytes(random.nextInt(32768)); - await rc.appMessage(prr, message); + await rc.appMessage(TargetRouteId(routeId: prr), message); sentMessages.add(base64Url.encode(message)); } @@ -241,7 +242,8 @@ Future testAppCallLoopbackBigPackets( for (var i = 0; i < 5; i++) { // send an app message to our own private route final message = await cs.randomBytes(random.nextInt(32768)); - final outmessage = await rc.appCall(prr, message); + final outmessage = + await rc.appCall(TargetRouteId(routeId: prr), message); expect(message, equals(outmessage)); } diff --git a/veilid-flutter/example/pubspec.lock b/veilid-flutter/example/pubspec.lock index 621ca6d0..efa4392a 100644 --- a/veilid-flutter/example/pubspec.lock +++ b/veilid-flutter/example/pubspec.lock @@ -13,18 +13,18 @@ packages: dependency: transitive description: name: async - sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" + sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 url: "https://pub.dev" source: hosted - version: "2.13.0" + version: "2.12.0" async_tools: dependency: transitive description: name: async_tools - sha256: afd5426e76631172f8ce6a6359b264b092fa9d2a52cd2528100115be9525e067 + sha256: "9611c1efeae7e6d342721d0c2caf2e4783d91fba6a9637d7badfa2dccf8de2a2" url: "https://pub.dev" source: hosted - version: "0.1.9" + version: "0.1.10" boolean_selector: dependency: transitive description: @@ -101,10 +101,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" + sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" url: "https://pub.dev" source: hosted - version: "1.3.3" + version: "1.3.2" ffi: dependency: transitive description: @@ -195,10 +195,10 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" + sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec url: "https://pub.dev" source: hosted - version: "10.0.9" + version: "10.0.8" leak_tracker_flutter_testing: dependency: transitive description: @@ -462,18 +462,18 @@ packages: dependency: transitive description: name: vm_service - sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 + sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" url: "https://pub.dev" source: hosted - version: "15.0.0" + version: "14.3.1" webdriver: dependency: transitive description: name: webdriver - sha256: "2f3a14ca026957870cfd9c635b83507e0e51d8091568e90129fbf805aba7cade" + sha256: "3d773670966f02a646319410766d3b5e1037efb7f07cc68f844d5e06cd4d61c8" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.0.4" xdg_directories: dependency: transitive description: diff --git a/veilid-flutter/lib/routing_context.dart b/veilid-flutter/lib/routing_context.dart index bb360a22..b07df726 100644 --- a/veilid-flutter/lib/routing_context.dart +++ b/veilid-flutter/lib/routing_context.dart @@ -78,13 +78,13 @@ sealed class DHTSchema with _$DHTSchema { _$DHTSchemaFromJson(json as Map); } -const DHTSchema defaultDHTSchema = DHTSchema.dflt(oCnt: 1); +const defaultDHTSchema = DHTSchema.dflt(oCnt: 1); @freezed sealed class DHTSchemaMember with _$DHTSchemaMember { @Assert('mCnt > 0 && mCnt <= 65535', 'value out of range') const factory DHTSchemaMember({ - required PublicKey mKey, + required MemberId mKey, required int mCnt, }) = _DHTSchemaMember; @@ -98,35 +98,35 @@ sealed class DHTSchemaMember with _$DHTSchemaMember { @freezed sealed class DHTRecordDescriptor with _$DHTRecordDescriptor { const factory DHTRecordDescriptor({ - required PublicKey key, - required BarePublicKey owner, + required RecordKey key, + required PublicKey owner, required DHTSchema schema, - BarePublicKey? ownerSecret, + BareSecretKey? ownerSecret, }) = _DHTRecordDescriptor; factory DHTRecordDescriptor.fromJson(dynamic json) => _$DHTRecordDescriptorFromJson(json as Map); } extension DHTRecordDescriptorExt on DHTRecordDescriptor { - BareKeyPair? ownerKeyPair() { + BareKeyPair? ownerBareKeyPair() { if (ownerSecret == null) { return null; } - return BareKeyPair(key: owner, secret: ownerSecret!); + return BareKeyPair(key: owner.value, secret: ownerSecret!); } - PublicKey? ownerTypedSecret() { + SecretKey? ownerSecretKey() { if (ownerSecret == null) { return null; } - return PublicKey(kind: key.kind, value: ownerSecret!); + return SecretKey(kind: owner.kind, value: ownerSecret!); } - KeyPair? ownerTypedKeyPair() { + KeyPair? ownerKeyPair() { if (ownerSecret == null) { return null; } - return KeyPair(kind: key.kind, key: owner, secret: ownerSecret!); + return KeyPair(kind: owner.kind, key: owner.value, secret: ownerSecret!); } } @@ -139,7 +139,7 @@ sealed class ValueData with _$ValueData { const factory ValueData({ required int seq, @Uint8ListJsonConverter.jsIsArray() required Uint8List data, - required BarePublicKey writer, + required PublicKey writer, }) = _ValueData; factory ValueData.fromJson(dynamic json) => @@ -229,19 +229,69 @@ sealed class SafetySpec with _$SafetySpec { required int hopCount, required Stability stability, required Sequencing sequencing, - String? preferredRoute, + RouteId? preferredRoute, }) = _SafetySpec; factory SafetySpec.fromJson(dynamic json) => _$SafetySpecFromJson(json as Map); } +////////////////////////////////////// +/// Target + +@immutable +abstract class Target { + factory Target.fromJson(dynamic jsond) { + final json = jsond as Map; + if (json.containsKey('NodeId')) { + return TargetNodeId(nodeId: NodeId.fromJson(json['NodeId'])); + } else if (json.containsKey('RouteId')) { + return TargetRouteId(routeId: RouteId.fromJson(json['RouteId'])); + } else { + throw const VeilidAPIExceptionInternal('Invalid Target'); + } + } + Map toJson(); +} + +@immutable +class TargetNodeId extends Equatable implements Target { + // + const TargetNodeId({ + required this.nodeId, + }); + final NodeId nodeId; + @override + List get props => [nodeId]; + @override + bool? get stringify => null; + + @override + Map toJson() => {'NodeId': nodeId.toJson()}; +} + +@immutable +class TargetRouteId extends Equatable implements Target { + // + const TargetRouteId({ + required this.routeId, + }); + final RouteId routeId; + @override + List get props => [routeId]; + @override + bool? get stringify => null; + + @override + Map toJson() => {'RouteId': routeId.toJson()}; +} + ////////////////////////////////////// /// RouteBlob @freezed sealed class RouteBlob with _$RouteBlob { const factory RouteBlob( - {required String routeId, + {required RouteId routeId, @Uint8ListJsonConverter() required Uint8List blob}) = _RouteBlob; factory RouteBlob.fromJson(dynamic json) => _$RouteBlobFromJson(json as Map); @@ -278,7 +328,7 @@ enum DHTReportScope { @freezed sealed class SetDHTValueOptions with _$SetDHTValueOptions { const factory SetDHTValueOptions({ - BareKeyPair? writer, + KeyPair? writer, bool? allowOffline, }) = _SetDHTValueOptions; @@ -307,24 +357,24 @@ abstract class VeilidRoutingContext { Future safety(); // App call/message - Future appCall(String target, Uint8List request); - Future appMessage(String target, Uint8List message); + Future appCall(Target target, Uint8List request); + Future appMessage(Target target, Uint8List message); // DHT Operations Future createDHTRecord(DHTSchema schema, - {BareKeyPair? owner, CryptoKind kind = 0}); - Future openDHTRecord(PublicKey key, - {BareKeyPair? writer}); - Future closeDHTRecord(PublicKey key); - Future deleteDHTRecord(PublicKey key); - Future getDHTValue(PublicKey key, int subkey, + {KeyPair? owner, CryptoKind kind = 0}); + Future openDHTRecord(RecordKey key, {KeyPair? writer}); + Future closeDHTRecord(RecordKey key); + Future deleteDHTRecord(RecordKey key); + Future getDHTRecordKey(DHTSchema schema, PublicKey owner); + Future getDHTValue(RecordKey key, int subkey, {bool forceRefresh = false}); - Future setDHTValue(PublicKey key, int subkey, Uint8List data, + Future setDHTValue(RecordKey key, int subkey, Uint8List data, {SetDHTValueOptions? options}); - Future watchDHTValues(PublicKey key, + Future watchDHTValues(RecordKey key, {List? subkeys, Timestamp? expiration, int? count}); - Future cancelDHTWatch(PublicKey key, {List? subkeys}); - Future inspectDHTRecord(PublicKey key, + Future cancelDHTWatch(RecordKey key, {List? subkeys}); + Future inspectDHTRecord(RecordKey key, {List? subkeys, DHTReportScope scope = DHTReportScope.local}); } diff --git a/veilid-flutter/lib/routing_context.freezed.dart b/veilid-flutter/lib/routing_context.freezed.dart index c02fe079..40bf1bf8 100644 --- a/veilid-flutter/lib/routing_context.freezed.dart +++ b/veilid-flutter/lib/routing_context.freezed.dart @@ -271,7 +271,7 @@ class _$DHTSchemaSMPLCopyWithImpl<$Res> /// @nodoc mixin _$DHTSchemaMember { - PublicKey get mKey; + MemberId get mKey; int get mCnt; /// Create a copy of DHTSchemaMember @@ -310,7 +310,7 @@ abstract mixin class $DHTSchemaMemberCopyWith<$Res> { DHTSchemaMember value, $Res Function(DHTSchemaMember) _then) = _$DHTSchemaMemberCopyWithImpl; @useResult - $Res call({PublicKey mKey, int mCnt}); + $Res call({MemberId mKey, int mCnt}); } /// @nodoc @@ -333,7 +333,7 @@ class _$DHTSchemaMemberCopyWithImpl<$Res> mKey: null == mKey ? _self.mKey : mKey // ignore: cast_nullable_to_non_nullable - as PublicKey, + as MemberId, mCnt: null == mCnt ? _self.mCnt : mCnt // ignore: cast_nullable_to_non_nullable @@ -351,7 +351,7 @@ class _DHTSchemaMember implements DHTSchemaMember { _$DHTSchemaMemberFromJson(json); @override - final PublicKey mKey; + final MemberId mKey; @override final int mCnt; @@ -397,7 +397,7 @@ abstract mixin class _$DHTSchemaMemberCopyWith<$Res> __$DHTSchemaMemberCopyWithImpl; @override @useResult - $Res call({PublicKey mKey, int mCnt}); + $Res call({MemberId mKey, int mCnt}); } /// @nodoc @@ -420,7 +420,7 @@ class __$DHTSchemaMemberCopyWithImpl<$Res> mKey: null == mKey ? _self.mKey : mKey // ignore: cast_nullable_to_non_nullable - as PublicKey, + as MemberId, mCnt: null == mCnt ? _self.mCnt : mCnt // ignore: cast_nullable_to_non_nullable @@ -431,10 +431,10 @@ class __$DHTSchemaMemberCopyWithImpl<$Res> /// @nodoc mixin _$DHTRecordDescriptor { - PublicKey get key; - BarePublicKey get owner; + RecordKey get key; + PublicKey get owner; DHTSchema get schema; - BarePublicKey? get ownerSecret; + BareSecretKey? get ownerSecret; /// Create a copy of DHTRecordDescriptor /// with the given fields replaced by the non-null parameter values. @@ -476,10 +476,10 @@ abstract mixin class $DHTRecordDescriptorCopyWith<$Res> { _$DHTRecordDescriptorCopyWithImpl; @useResult $Res call( - {PublicKey key, - BarePublicKey owner, + {RecordKey key, + PublicKey owner, DHTSchema schema, - BarePublicKey? ownerSecret}); + BareSecretKey? ownerSecret}); $DHTSchemaCopyWith<$Res> get schema; } @@ -506,11 +506,11 @@ class _$DHTRecordDescriptorCopyWithImpl<$Res> key: null == key ? _self.key : key // ignore: cast_nullable_to_non_nullable - as PublicKey, + as RecordKey, owner: null == owner ? _self.owner : owner // ignore: cast_nullable_to_non_nullable - as BarePublicKey, + as PublicKey, schema: null == schema ? _self.schema : schema // ignore: cast_nullable_to_non_nullable @@ -518,7 +518,7 @@ class _$DHTRecordDescriptorCopyWithImpl<$Res> ownerSecret: freezed == ownerSecret ? _self.ownerSecret : ownerSecret // ignore: cast_nullable_to_non_nullable - as BarePublicKey?, + as BareSecretKey?, )); } @@ -545,13 +545,13 @@ class _DHTRecordDescriptor implements DHTRecordDescriptor { _$DHTRecordDescriptorFromJson(json); @override - final PublicKey key; + final RecordKey key; @override - final BarePublicKey owner; + final PublicKey owner; @override final DHTSchema schema; @override - final BarePublicKey? ownerSecret; + final BareSecretKey? ownerSecret; /// Create a copy of DHTRecordDescriptor /// with the given fields replaced by the non-null parameter values. @@ -600,10 +600,10 @@ abstract mixin class _$DHTRecordDescriptorCopyWith<$Res> @override @useResult $Res call( - {PublicKey key, - BarePublicKey owner, + {RecordKey key, + PublicKey owner, DHTSchema schema, - BarePublicKey? ownerSecret}); + BareSecretKey? ownerSecret}); @override $DHTSchemaCopyWith<$Res> get schema; @@ -631,11 +631,11 @@ class __$DHTRecordDescriptorCopyWithImpl<$Res> key: null == key ? _self.key : key // ignore: cast_nullable_to_non_nullable - as PublicKey, + as RecordKey, owner: null == owner ? _self.owner : owner // ignore: cast_nullable_to_non_nullable - as BarePublicKey, + as PublicKey, schema: null == schema ? _self.schema : schema // ignore: cast_nullable_to_non_nullable @@ -643,7 +643,7 @@ class __$DHTRecordDescriptorCopyWithImpl<$Res> ownerSecret: freezed == ownerSecret ? _self.ownerSecret : ownerSecret // ignore: cast_nullable_to_non_nullable - as BarePublicKey?, + as BareSecretKey?, )); } @@ -663,7 +663,7 @@ mixin _$ValueData { int get seq; @Uint8ListJsonConverter.jsIsArray() Uint8List get data; - BarePublicKey get writer; + PublicKey get writer; /// Create a copy of ValueData /// with the given fields replaced by the non-null parameter values. @@ -704,7 +704,7 @@ abstract mixin class $ValueDataCopyWith<$Res> { $Res call( {int seq, @Uint8ListJsonConverter.jsIsArray() Uint8List data, - BarePublicKey writer}); + PublicKey writer}); } /// @nodoc @@ -735,7 +735,7 @@ class _$ValueDataCopyWithImpl<$Res> implements $ValueDataCopyWith<$Res> { writer: null == writer ? _self.writer : writer // ignore: cast_nullable_to_non_nullable - as BarePublicKey, + as PublicKey, )); } } @@ -757,7 +757,7 @@ class _ValueData implements ValueData { @Uint8ListJsonConverter.jsIsArray() final Uint8List data; @override - final BarePublicKey writer; + final PublicKey writer; /// Create a copy of ValueData /// with the given fields replaced by the non-null parameter values. @@ -806,7 +806,7 @@ abstract mixin class _$ValueDataCopyWith<$Res> $Res call( {int seq, @Uint8ListJsonConverter.jsIsArray() Uint8List data, - BarePublicKey writer}); + PublicKey writer}); } /// @nodoc @@ -837,7 +837,7 @@ class __$ValueDataCopyWithImpl<$Res> implements _$ValueDataCopyWith<$Res> { writer: null == writer ? _self.writer : writer // ignore: cast_nullable_to_non_nullable - as BarePublicKey, + as PublicKey, )); } } @@ -847,7 +847,7 @@ mixin _$SafetySpec { int get hopCount; Stability get stability; Sequencing get sequencing; - String? get preferredRoute; + RouteId? get preferredRoute; /// Create a copy of SafetySpec /// with the given fields replaced by the non-null parameter values. @@ -895,7 +895,7 @@ abstract mixin class $SafetySpecCopyWith<$Res> { {int hopCount, Stability stability, Sequencing sequencing, - String? preferredRoute}); + RouteId? preferredRoute}); } /// @nodoc @@ -931,7 +931,7 @@ class _$SafetySpecCopyWithImpl<$Res> implements $SafetySpecCopyWith<$Res> { preferredRoute: freezed == preferredRoute ? _self.preferredRoute : preferredRoute // ignore: cast_nullable_to_non_nullable - as String?, + as RouteId?, )); } } @@ -954,7 +954,7 @@ class _SafetySpec implements SafetySpec { @override final Sequencing sequencing; @override - final String? preferredRoute; + final RouteId? preferredRoute; /// Create a copy of SafetySpec /// with the given fields replaced by the non-null parameter values. @@ -1009,7 +1009,7 @@ abstract mixin class _$SafetySpecCopyWith<$Res> {int hopCount, Stability stability, Sequencing sequencing, - String? preferredRoute}); + RouteId? preferredRoute}); } /// @nodoc @@ -1045,14 +1045,14 @@ class __$SafetySpecCopyWithImpl<$Res> implements _$SafetySpecCopyWith<$Res> { preferredRoute: freezed == preferredRoute ? _self.preferredRoute : preferredRoute // ignore: cast_nullable_to_non_nullable - as String?, + as RouteId?, )); } } /// @nodoc mixin _$RouteBlob { - String get routeId; + RouteId get routeId; @Uint8ListJsonConverter() Uint8List get blob; @@ -1091,7 +1091,7 @@ abstract mixin class $RouteBlobCopyWith<$Res> { factory $RouteBlobCopyWith(RouteBlob value, $Res Function(RouteBlob) _then) = _$RouteBlobCopyWithImpl; @useResult - $Res call({String routeId, @Uint8ListJsonConverter() Uint8List blob}); + $Res call({RouteId routeId, @Uint8ListJsonConverter() Uint8List blob}); } /// @nodoc @@ -1113,7 +1113,7 @@ class _$RouteBlobCopyWithImpl<$Res> implements $RouteBlobCopyWith<$Res> { routeId: null == routeId ? _self.routeId : routeId // ignore: cast_nullable_to_non_nullable - as String, + as RouteId, blob: null == blob ? _self.blob : blob // ignore: cast_nullable_to_non_nullable @@ -1131,7 +1131,7 @@ class _RouteBlob implements RouteBlob { _$RouteBlobFromJson(json); @override - final String routeId; + final RouteId routeId; @override @Uint8ListJsonConverter() final Uint8List blob; @@ -1179,7 +1179,7 @@ abstract mixin class _$RouteBlobCopyWith<$Res> __$RouteBlobCopyWithImpl; @override @useResult - $Res call({String routeId, @Uint8ListJsonConverter() Uint8List blob}); + $Res call({RouteId routeId, @Uint8ListJsonConverter() Uint8List blob}); } /// @nodoc @@ -1201,7 +1201,7 @@ class __$RouteBlobCopyWithImpl<$Res> implements _$RouteBlobCopyWith<$Res> { routeId: null == routeId ? _self.routeId : routeId // ignore: cast_nullable_to_non_nullable - as String, + as RouteId, blob: null == blob ? _self.blob : blob // ignore: cast_nullable_to_non_nullable @@ -1455,7 +1455,7 @@ class __$DHTRecordReportCopyWithImpl<$Res> /// @nodoc mixin _$SetDHTValueOptions { - BareKeyPair? get writer; + KeyPair? get writer; bool? get allowOffline; /// Create a copy of SetDHTValueOptions @@ -1495,7 +1495,7 @@ abstract mixin class $SetDHTValueOptionsCopyWith<$Res> { SetDHTValueOptions value, $Res Function(SetDHTValueOptions) _then) = _$SetDHTValueOptionsCopyWithImpl; @useResult - $Res call({BareKeyPair? writer, bool? allowOffline}); + $Res call({KeyPair? writer, bool? allowOffline}); } /// @nodoc @@ -1518,7 +1518,7 @@ class _$SetDHTValueOptionsCopyWithImpl<$Res> writer: freezed == writer ? _self.writer : writer // ignore: cast_nullable_to_non_nullable - as BareKeyPair?, + as KeyPair?, allowOffline: freezed == allowOffline ? _self.allowOffline : allowOffline // ignore: cast_nullable_to_non_nullable @@ -1535,7 +1535,7 @@ class _SetDHTValueOptions implements SetDHTValueOptions { _$SetDHTValueOptionsFromJson(json); @override - final BareKeyPair? writer; + final KeyPair? writer; @override final bool? allowOffline; @@ -1582,7 +1582,7 @@ abstract mixin class _$SetDHTValueOptionsCopyWith<$Res> __$SetDHTValueOptionsCopyWithImpl; @override @useResult - $Res call({BareKeyPair? writer, bool? allowOffline}); + $Res call({KeyPair? writer, bool? allowOffline}); } /// @nodoc @@ -1605,7 +1605,7 @@ class __$SetDHTValueOptionsCopyWithImpl<$Res> writer: freezed == writer ? _self.writer : writer // ignore: cast_nullable_to_non_nullable - as BareKeyPair?, + as KeyPair?, allowOffline: freezed == allowOffline ? _self.allowOffline : allowOffline // ignore: cast_nullable_to_non_nullable diff --git a/veilid-flutter/lib/routing_context.g.dart b/veilid-flutter/lib/routing_context.g.dart index ee410298..d6196750 100644 --- a/veilid-flutter/lib/routing_context.g.dart +++ b/veilid-flutter/lib/routing_context.g.dart @@ -36,7 +36,7 @@ Map _$DHTSchemaSMPLToJson(DHTSchemaSMPL instance) => _DHTSchemaMember _$DHTSchemaMemberFromJson(Map json) => _DHTSchemaMember( - mKey: Typed.fromJson(json['m_key']), + mKey: Typed.fromJson(json['m_key']), mCnt: (json['m_cnt'] as num).toInt(), ); @@ -48,12 +48,12 @@ Map _$DHTSchemaMemberToJson(_DHTSchemaMember instance) => _DHTRecordDescriptor _$DHTRecordDescriptorFromJson(Map json) => _DHTRecordDescriptor( - key: Typed.fromJson(json['key']), - owner: FixedEncodedString43.fromJson(json['owner']), + key: Typed.fromJson(json['key']), + owner: Typed.fromJson(json['owner']), schema: DHTSchema.fromJson(json['schema']), ownerSecret: json['owner_secret'] == null ? null - : FixedEncodedString43.fromJson(json['owner_secret']), + : BareSecretKey.fromJson(json['owner_secret']), ); Map _$DHTRecordDescriptorToJson( @@ -68,7 +68,7 @@ Map _$DHTRecordDescriptorToJson( _ValueData _$ValueDataFromJson(Map json) => _ValueData( seq: (json['seq'] as num).toInt(), data: const Uint8ListJsonConverter.jsIsArray().fromJson(json['data']), - writer: FixedEncodedString43.fromJson(json['writer']), + writer: Typed.fromJson(json['writer']), ); Map _$ValueDataToJson(_ValueData instance) => @@ -82,7 +82,9 @@ _SafetySpec _$SafetySpecFromJson(Map json) => _SafetySpec( hopCount: (json['hop_count'] as num).toInt(), stability: Stability.fromJson(json['stability']), sequencing: Sequencing.fromJson(json['sequencing']), - preferredRoute: json['preferred_route'] as String?, + preferredRoute: json['preferred_route'] == null + ? null + : Typed.fromJson(json['preferred_route']), ); Map _$SafetySpecToJson(_SafetySpec instance) => @@ -90,17 +92,17 @@ Map _$SafetySpecToJson(_SafetySpec instance) => 'hop_count': instance.hopCount, 'stability': instance.stability.toJson(), 'sequencing': instance.sequencing.toJson(), - 'preferred_route': instance.preferredRoute, + 'preferred_route': instance.preferredRoute?.toJson(), }; _RouteBlob _$RouteBlobFromJson(Map json) => _RouteBlob( - routeId: json['route_id'] as String, + routeId: Typed.fromJson(json['route_id']), blob: const Uint8ListJsonConverter().fromJson(json['blob']), ); Map _$RouteBlobToJson(_RouteBlob instance) => { - 'route_id': instance.routeId, + 'route_id': instance.routeId.toJson(), 'blob': const Uint8ListJsonConverter().toJson(instance.blob), }; @@ -131,8 +133,7 @@ Map _$DHTRecordReportToJson(_DHTRecordReport instance) => _SetDHTValueOptions _$SetDHTValueOptionsFromJson(Map json) => _SetDHTValueOptions( - writer: - json['writer'] == null ? null : BareKeyPair.fromJson(json['writer']), + writer: json['writer'] == null ? null : KeyPair.fromJson(json['writer']), allowOffline: json['allow_offline'] as bool?, ); diff --git a/veilid-flutter/lib/veilid.dart b/veilid-flutter/lib/veilid.dart index 60ac26c6..c16a3c25 100644 --- a/veilid-flutter/lib/veilid.dart +++ b/veilid-flutter/lib/veilid.dart @@ -205,12 +205,15 @@ abstract class Veilid { (await routingContext()) .withSafety(SafetySelectionUnsafe(sequencing: sequencing)); + // Id generation + Future generateMemberId(PublicKey writerKey); + // Private route allocation Future newPrivateRoute(); Future newCustomPrivateRoute( Stability stability, Sequencing sequencing); - Future importRemotePrivateRoute(Uint8List blob); - Future releasePrivateRoute(String routeId); + Future importRemotePrivateRoute(Uint8List blob); + Future releasePrivateRoute(RouteId routeId); // App calls Future appCallReply(String callId, Uint8List message); diff --git a/veilid-flutter/lib/veilid_config.g.dart b/veilid-flutter/lib/veilid_config.g.dart index 74094a83..1e6b8e62 100644 --- a/veilid-flutter/lib/veilid_config.g.dart +++ b/veilid-flutter/lib/veilid_config.g.dart @@ -424,15 +424,15 @@ _VeilidConfigRoutingTable _$VeilidConfigRoutingTableFromJson( Map json) => _VeilidConfigRoutingTable( nodeId: (json['node_id'] as List) - .map(Typed.fromJson) + .map(Typed.fromJson) .toList(), nodeIdSecret: (json['node_id_secret'] as List) - .map(Typed.fromJson) + .map(Typed.fromJson) .toList(), bootstrap: (json['bootstrap'] as List).map((e) => e as String).toList(), bootstrapKeys: (json['bootstrap_keys'] as List) - .map(Typed.fromJson) + .map(Typed.fromJson) .toList(), limitOverAttached: (json['limit_over_attached'] as num).toInt(), limitFullyAttached: (json['limit_fully_attached'] as num).toInt(), diff --git a/veilid-flutter/lib/veilid_crypto.dart b/veilid-flutter/lib/veilid_crypto.dart index 61a4d475..6eb08c7c 100644 --- a/veilid-flutter/lib/veilid_crypto.dart +++ b/veilid-flutter/lib/veilid_crypto.dart @@ -77,32 +77,6 @@ class Typed extends Equatable { return b.toBytes(); } - static int encodedLength() { - switch (X) { - case const (Typed): - return FixedEncodedString32.encodedLength() + 5; - case const (Typed): - return FixedEncodedString43.encodedLength() + 5; - case const (Typed): - return FixedEncodedString86.encodedLength() + 5; - default: - throw UnimplementedError(); - } - } - - static int decodedLength() { - switch (X) { - case const (Typed): - return FixedEncodedString32.decodedLength() + 4; - case const (Typed): - return FixedEncodedString43.decodedLength() + 4; - case const (Typed): - return FixedEncodedString86.decodedLength() + 4; - default: - throw UnimplementedError(); - } - } - String toJson() => toString(); } @@ -118,13 +92,13 @@ class BareKeyPair extends Equatable { throw const FormatException('malformed string'); } final key = BarePublicKey.fromString(parts[0]); - final secret = BarePublicKey.fromString(parts[1]); + final secret = BareSecretKey.fromString(parts[1]); return BareKeyPair(key: key, secret: secret); } factory BareKeyPair.fromJson(dynamic json) => BareKeyPair.fromString(json as String); final BarePublicKey key; - final BarePublicKey secret; + final BareSecretKey secret; @override List get props => [key, secret]; @@ -148,15 +122,18 @@ class KeyPair extends Equatable { } final kind = cryptoKindFromString(parts[0]); final key = BarePublicKey.fromString(parts[1]); - final secret = BarePublicKey.fromString(parts[2]); + final secret = BareSecretKey.fromString(parts[2]); return KeyPair(kind: kind, key: key, secret: secret); } factory KeyPair.fromJson(dynamic json) => KeyPair.fromString(json as String); - factory KeyPair.fromKeyPair(CryptoKind kind, BareKeyPair keyPair) => + factory KeyPair.fromBareKeyPair(CryptoKind kind, BareKeyPair keyPair) => KeyPair(kind: kind, key: keyPair.key, secret: keyPair.secret); + factory KeyPair.fromPublicAndBareSecret( + PublicKey key, BareSecretKey secret) => + KeyPair(kind: key.kind, key: key.value, secret: secret); final CryptoKind kind; final BarePublicKey key; - final BarePublicKey secret; + final BareSecretKey secret; @override List get props => [kind, key, secret]; @@ -167,49 +144,75 @@ class KeyPair extends Equatable { BareKeyPair toKeyPair() => BareKeyPair(key: key, secret: secret); } -typedef CryptoKey = FixedEncodedString43; -typedef BareSignature = FixedEncodedString86; -typedef BareNonce = FixedEncodedString32; - -typedef BarePublicKey = CryptoKey; -typedef BareSecretKey = CryptoKey; -typedef BareHashDigest = CryptoKey; -typedef BareSharedSecret = CryptoKey; -typedef BareHashDistance = CryptoKey; - typedef PublicKey = Typed; +typedef Signature = Typed; +typedef Nonce = Typed; typedef SecretKey = Typed; typedef HashDigest = Typed; - -typedef Signature = Typed; +typedef SharedSecret = Typed; +typedef HashDistance = Typed; +typedef RecordKey = Typed; +typedef RouteId = Typed; +typedef NodeId = Typed; +typedef MemberId = Typed; ////////////////////////////////////// /// VeilidCryptoSystem abstract class VeilidCryptoSystem { CryptoKind kind(); + + // Cached Operations + Future cachedDH(BarePublicKey key, BareSecretKey secret); - Future computeDH(BarePublicKey key, BareSecretKey secret); - Future generateSharedSecret( - BarePublicKey key, BareSecretKey secret, Uint8List domain); + + // Generation + Future randomBytes(int len); - Future defaultSaltLength(); Future hashPassword(Uint8List password, Uint8List salt); Future verifyPassword(Uint8List password, String passwordHash); Future deriveSharedSecret( Uint8List password, Uint8List salt); Future randomNonce(); Future randomSharedSecret(); + Future computeDH(BarePublicKey key, BareSecretKey secret); + Future generateSharedSecret( + BarePublicKey key, BareSecretKey secret, Uint8List domain); Future generateKeyPair(); Future generateHash(Uint8List data); //Future generateHashReader(Stream> reader); + + // Validation + + Future sharedSecretLength(); + Future nonceLength(); + Future hashDigestLength(); + Future publicKeyLength(); + Future secretKeyLength(); + Future signatureLength(); + Future aeadOverhead(); + Future defaultSaltLength(); + + Future checkSharedSecret(BareSharedSecret secret); + Future checkNonce(BareNonce nonce); + Future checkHashDigest(BareHashDigest digest); + Future checkPublicKey(BarePublicKey key); + Future checkSecretKey(BareSecretKey key); + Future checkSignature(BareSignature signature); + Future validateKeyPair(BarePublicKey key, BareSecretKey secret); Future validateKeyPairWithKeyPair(BareKeyPair keyPair) => validateKeyPair(keyPair.key, keyPair.secret); Future validateHash(Uint8List data, BareHashDigest hash); //Future validateHashReader(Stream> reader, HashDigest hash); - Future distance(CryptoKey key1, CryptoKey key2); + + // Distance Metric + + Future distance(BareHashDigest key1, BareHashDigest key2); + + // Authentication + Future sign( BarePublicKey key, BareSecretKey secret, Uint8List data); Future signWithKeyPair(BareKeyPair keyPair, Uint8List data) => @@ -217,7 +220,9 @@ abstract class VeilidCryptoSystem { Future verify( BarePublicKey key, Uint8List data, BareSignature signature); - Future aeadOverhead(); + + // AEAD Encrypt/Decrypt + Future decryptAead(Uint8List body, BareNonce nonce, BareSharedSecret sharedSecret, Uint8List? associatedData); Future encryptAead(Uint8List body, BareNonce nonce, @@ -238,13 +243,12 @@ abstract class VeilidCryptoSystem { Future decryptAeadWithNonce( Uint8List body, BareSharedSecret secret) async { - if (body.length < BareNonce.decodedLength()) { + final nlen = await nonceLength(); + if (body.length < nlen) { throw const FormatException('not enough data to decrypt'); } - final nonce = BareNonce.fromBytes( - body.sublist(body.length - BareNonce.decodedLength())); - final encryptedData = - body.sublist(0, body.length - BareNonce.decodedLength()); + final nonce = BareNonce.fromBytes(body.sublist(body.length - nlen)); + final encryptedData = body.sublist(0, body.length - nlen); // decrypt return decryptAead(encryptedData, nonce, secret, null); } @@ -261,17 +265,20 @@ abstract class VeilidCryptoSystem { Future decryptAeadWithPassword( Uint8List body, String password) async { - if (body.length < BareNonce.decodedLength()) { + final nlen = await nonceLength(); + if (body.length < nlen) { throw const FormatException('not enough data to decrypt'); } final ekbytes = Uint8List.fromList(utf8.encode(password)); - final bodyBytes = body.sublist(0, body.length - BareNonce.decodedLength()); - final saltBytes = body.sublist(body.length - BareNonce.decodedLength()); + final bodyBytes = body.sublist(0, body.length - nlen); + final saltBytes = body.sublist(body.length - nlen); final nonce = BareNonce.fromBytes(saltBytes); final sharedSecret = await deriveSharedSecret(ekbytes, saltBytes); return decryptAead(bodyBytes, nonce, sharedSecret, null); } + // NoAuth Encrypt/Decrypt + Future encryptNoAuthWithNonce( Uint8List body, BareSharedSecret secret) async { // generate nonce @@ -285,13 +292,12 @@ abstract class VeilidCryptoSystem { Future decryptNoAuthWithNonce( Uint8List body, BareSharedSecret secret) async { - if (body.length < BareNonce.decodedLength()) { + final nlen = await nonceLength(); + if (body.length < nlen) { throw const FormatException('not enough data to decrypt'); } - final nonce = BareNonce.fromBytes( - body.sublist(body.length - BareNonce.decodedLength())); - final encryptedData = - body.sublist(0, body.length - BareNonce.decodedLength()); + final nonce = BareNonce.fromBytes(body.sublist(body.length - nlen)); + final encryptedData = body.sublist(0, body.length - nlen); // decrypt return cryptNoAuth(encryptedData, nonce, secret); } @@ -308,12 +314,13 @@ abstract class VeilidCryptoSystem { Future decryptNoAuthWithPassword( Uint8List body, String password) async { - if (body.length < BareNonce.decodedLength()) { + final nlen = await nonceLength(); + if (body.length < nlen) { throw const FormatException('not enough data to decrypt'); } final ekbytes = Uint8List.fromList(utf8.encode(password)); - final bodyBytes = body.sublist(0, body.length - BareNonce.decodedLength()); - final saltBytes = body.sublist(body.length - BareNonce.decodedLength()); + final bodyBytes = body.sublist(0, body.length - nlen); + final saltBytes = body.sublist(body.length - nlen); final nonce = BareNonce.fromBytes(saltBytes); final sharedSecret = await deriveSharedSecret(ekbytes, saltBytes); return cryptNoAuth(bodyBytes, nonce, sharedSecret); diff --git a/veilid-flutter/lib/veilid_encoding.dart b/veilid-flutter/lib/veilid_encoding.dart index 4cde365a..198a36e8 100644 --- a/veilid-flutter/lib/veilid_encoding.dart +++ b/veilid-flutter/lib/veilid_encoding.dart @@ -41,51 +41,51 @@ class Uint8ListJsonConverter implements JsonConverter { } @immutable -abstract class EncodedString extends Equatable { - const EncodedString(String s) : contents = s; - final String contents; - @override - List get props => [contents]; +sealed class EncodedString extends Equatable { + EncodedString._fromBytes(Uint8List bytes) + : contents = base64UrlNoPadEncode(bytes); + EncodedString._fromString(String s) : contents = s { + // Ensure things can be decoded, will throw an exception if it fails + base64UrlNoPadDecode(contents); + } + EncodedString._fromJson(dynamic json) : contents = json as String { + // Ensure things can be decoded, will throw an exception if it fails + base64UrlNoPadDecode(contents); + } + + String toJson() => toString(); Uint8List decode() => base64UrlNoPadDecode(contents); @override String toString() => contents; - static int encodedLength() { - switch (T) { - case FixedEncodedString32: - return FixedEncodedString32.encodedLength(); - case FixedEncodedString43: - return FixedEncodedString43.encodedLength(); - case FixedEncodedString86: - return FixedEncodedString86.encodedLength(); - default: - throw UnimplementedError(); - } - } - - static int decodedLength() { - switch (T) { - case FixedEncodedString32: - return FixedEncodedString32.decodedLength(); - case FixedEncodedString43: - return FixedEncodedString43.decodedLength(); - case FixedEncodedString86: - return FixedEncodedString86.decodedLength(); - default: - throw UnimplementedError(); - } - } + //////////////////////////////////////////////////////////////////////////// static T fromBytes(Uint8List bytes) { switch (T) { - case FixedEncodedString32: - return FixedEncodedString32.fromBytes(bytes) as T; - case FixedEncodedString43: - return FixedEncodedString43.fromBytes(bytes) as T; - case FixedEncodedString86: - return FixedEncodedString86.fromBytes(bytes) as T; + case const (BarePublicKey): + return BarePublicKey.fromBytes(bytes) as T; + case const (BareSignature): + return BareSignature.fromBytes(bytes) as T; + case const (BareNonce): + return BareNonce.fromBytes(bytes) as T; + case const (BareSecretKey): + return BareSecretKey.fromBytes(bytes) as T; + case const (BareHashDigest): + return BareHashDigest.fromBytes(bytes) as T; + case const (BareSharedSecret): + return BareSharedSecret.fromBytes(bytes) as T; + case const (BareHashDistance): + return BareHashDistance.fromBytes(bytes) as T; + case const (BareRecordKey): + return BareRecordKey.fromBytes(bytes) as T; + case const (BareRouteId): + return BareRouteId.fromBytes(bytes) as T; + case const (BareNodeId): + return BareNodeId.fromBytes(bytes) as T; + case const (BareMemberId): + return BareMemberId.fromBytes(bytes) as T; default: throw UnimplementedError(); } @@ -93,93 +93,131 @@ abstract class EncodedString extends Equatable { static T fromString(String s) { switch (T) { - case FixedEncodedString32: - return FixedEncodedString32.fromString(s) as T; - case FixedEncodedString43: - return FixedEncodedString43.fromString(s) as T; - case FixedEncodedString86: - return FixedEncodedString86.fromString(s) as T; + case const (BarePublicKey): + return BarePublicKey.fromString(s) as T; + case const (BareSignature): + return BareSignature.fromString(s) as T; + case const (BareNonce): + return BareNonce.fromString(s) as T; + case const (BareSecretKey): + return BareSecretKey.fromString(s) as T; + case const (BareHashDigest): + return BareHashDigest.fromString(s) as T; + case const (BareSharedSecret): + return BareSharedSecret.fromString(s) as T; + case const (BareHashDistance): + return BareHashDistance.fromString(s) as T; + case const (BareRecordKey): + return BareRecordKey.fromString(s) as T; + case const (BareRouteId): + return BareRouteId.fromString(s) as T; + case const (BareNodeId): + return BareNodeId.fromString(s) as T; + case const (BareMemberId): + return BareMemberId.fromString(s) as T; default: throw UnimplementedError(); } } + + static T fromJson(dynamic json) { + switch (T) { + case const (BarePublicKey): + return BarePublicKey.fromJson(json) as T; + case const (BareSignature): + return BareSignature.fromJson(json) as T; + case const (BareNonce): + return BareNonce.fromJson(json) as T; + case const (BareSecretKey): + return BareSecretKey.fromJson(json) as T; + case const (BareHashDigest): + return BareHashDigest.fromJson(json) as T; + case const (BareSharedSecret): + return BareSharedSecret.fromJson(json) as T; + case const (BareHashDistance): + return BareHashDistance.fromJson(json) as T; + case const (BareRecordKey): + return BareRecordKey.fromJson(json) as T; + case const (BareRouteId): + return BareRouteId.fromJson(json) as T; + case const (BareNodeId): + return BareNodeId.fromJson(json) as T; + case const (BareMemberId): + return BareMemberId.fromJson(json) as T; + default: + throw UnimplementedError(); + } + } + + //////////////////////////////////////////////////////////////////////////// + + final String contents; + @override + List get props => [contents]; } -@immutable -class FixedEncodedString32 extends EncodedString { - factory FixedEncodedString32.fromBytes(Uint8List bytes) { - if (bytes.length != decodedLength()) { - throw Exception('length ${bytes.length} should be ${decodedLength()}'); - } - return FixedEncodedString32._(base64UrlNoPadEncode(bytes)); - } - - factory FixedEncodedString32.fromString(String s) { - final d = base64UrlNoPadDecode(s); - if (d.length != decodedLength()) { - throw Exception('length ${s.length} should be ${encodedLength()}'); - } - return FixedEncodedString32._(s); - } - factory FixedEncodedString32.fromJson(dynamic json) => - FixedEncodedString32.fromString(json as String); - const FixedEncodedString32._(super.s); - static int encodedLength() => 32; - - static int decodedLength() => 24; - - String toJson() => toString(); +class BarePublicKey extends EncodedString { + BarePublicKey.fromBytes(super.bytes) : super._fromBytes(); + BarePublicKey.fromString(super.s) : super._fromString(); + BarePublicKey.fromJson(super.json) : super._fromJson(); } -@immutable -class FixedEncodedString43 extends EncodedString { - factory FixedEncodedString43.fromBytes(Uint8List bytes) { - if (bytes.length != decodedLength()) { - throw Exception('length ${bytes.length} should be ${decodedLength()}'); - } - return FixedEncodedString43._(base64UrlNoPadEncode(bytes)); - } - - factory FixedEncodedString43.fromString(String s) { - final d = base64UrlNoPadDecode(s); - if (d.length != decodedLength()) { - throw Exception('length ${s.length} should be ${encodedLength()}'); - } - return FixedEncodedString43._(s); - } - factory FixedEncodedString43.fromJson(dynamic json) => - FixedEncodedString43.fromString(json as String); - const FixedEncodedString43._(super.s); - static int encodedLength() => 43; - - static int decodedLength() => 32; - - String toJson() => toString(); +class BareSignature extends EncodedString { + BareSignature.fromBytes(super.bytes) : super._fromBytes(); + BareSignature.fromString(super.s) : super._fromString(); + BareSignature.fromJson(super.json) : super._fromJson(); } -@immutable -class FixedEncodedString86 extends EncodedString { - factory FixedEncodedString86.fromBytes(Uint8List bytes) { - if (bytes.length != decodedLength()) { - throw Exception('length ${bytes.length} should be ${decodedLength()}'); - } - return FixedEncodedString86._(base64UrlNoPadEncode(bytes)); - } - - factory FixedEncodedString86.fromString(String s) { - final d = base64UrlNoPadDecode(s); - if (d.length != decodedLength()) { - throw Exception('length ${s.length} should be ${encodedLength()}'); - } - return FixedEncodedString86._(s); - } - - factory FixedEncodedString86.fromJson(dynamic json) => - FixedEncodedString86.fromString(json as String); - const FixedEncodedString86._(super.s); - static int encodedLength() => 86; - - static int decodedLength() => 64; - - String toJson() => toString(); +class BareNonce extends EncodedString { + BareNonce.fromBytes(super.bytes) : super._fromBytes(); + BareNonce.fromString(super.s) : super._fromString(); + BareNonce.fromJson(super.json) : super._fromJson(); +} + +class BareSecretKey extends EncodedString { + BareSecretKey.fromBytes(super.bytes) : super._fromBytes(); + BareSecretKey.fromString(super.s) : super._fromString(); + BareSecretKey.fromJson(super.json) : super._fromJson(); +} + +class BareHashDigest extends EncodedString { + BareHashDigest.fromBytes(super.bytes) : super._fromBytes(); + BareHashDigest.fromString(super.s) : super._fromString(); + BareHashDigest.fromJson(super.json) : super._fromJson(); +} + +class BareSharedSecret extends EncodedString { + BareSharedSecret.fromBytes(super.bytes) : super._fromBytes(); + BareSharedSecret.fromString(super.s) : super._fromString(); + BareSharedSecret.fromJson(super.json) : super._fromJson(); +} + +class BareHashDistance extends EncodedString { + BareHashDistance.fromBytes(super.bytes) : super._fromBytes(); + BareHashDistance.fromString(super.s) : super._fromString(); + BareHashDistance.fromJson(super.json) : super._fromJson(); +} + +class BareRecordKey extends EncodedString { + BareRecordKey.fromBytes(super.bytes) : super._fromBytes(); + BareRecordKey.fromString(super.s) : super._fromString(); + BareRecordKey.fromJson(super.json) : super._fromJson(); +} + +class BareRouteId extends EncodedString { + BareRouteId.fromBytes(super.bytes) : super._fromBytes(); + BareRouteId.fromString(super.s) : super._fromString(); + BareRouteId.fromJson(super.json) : super._fromJson(); +} + +class BareNodeId extends EncodedString { + BareNodeId.fromBytes(super.bytes) : super._fromBytes(); + BareNodeId.fromString(super.s) : super._fromString(); + BareNodeId.fromJson(super.json) : super._fromJson(); +} + +class BareMemberId extends EncodedString { + BareMemberId.fromBytes(super.bytes) : super._fromBytes(); + BareMemberId.fromString(super.s) : super._fromString(); + BareMemberId.fromJson(super.json) : super._fromJson(); } diff --git a/veilid-flutter/lib/veilid_ffi.dart b/veilid-flutter/lib/veilid_ffi.dart index cdc49532..77a87ac4 100644 --- a/veilid-flutter/lib/veilid_ffi.dart +++ b/veilid-flutter/lib/veilid_ffi.dart @@ -66,6 +66,10 @@ typedef _RoutingContextAppCallDart = void Function( // id: u32, target: FfiStr, request: FfiStr) typedef _RoutingContextAppMessageDart = void Function( int, int, Pointer, Pointer); +// fn routing_context_get_dht_record_key(port: i64, +// id: u32, schema: FfiStr, owner: FfiStr) +typedef _RoutingContextGetDHTRecordKeyDart = void Function( + int, int, Pointer, Pointer); // fn routing_context_create_dht_record(port: i64, // id: u32, schema: FfiStr, owner: FfiStr, kind: u32) typedef _RoutingContextCreateDHTRecordDart = void Function( @@ -101,6 +105,9 @@ typedef _RoutingContextCancelDHTWatchDart = void Function( typedef _RoutingContextInspectDHTRecordDart = void Function( int, int, Pointer, Pointer, Pointer); +// fn generate_member_id(port: i64, writer_key: FfiStr) +typedef _GenerateMemberIdDart = void Function(int, Pointer); + // fn new_private_route(port: i64) typedef _NewPrivateRouteDart = void Function(int); // fn new_custom_private_route(port: i64, stability: FfiStr, sequencing: FfiStr) @@ -171,8 +178,36 @@ typedef _CryptoGenerateSharedSecretDart = void Function( int, int, Pointer, Pointer, Pointer); // fn crypto_random_bytes(port: i64, kind: u32, len: u32) typedef _CryptoRandomBytesDart = void Function(int, int, int); +// fn crypto_shared_secret_length(port: i64, kind: u32) +typedef _CryptoSharedSecretLengthDart = void Function(int, int); +// fn crypto_nonce_length(port: i64, kind: u32) +typedef _CryptoNonceLengthDart = void Function(int, int); +// fn crypto_hash_digest_length(port: i64, kind: u32) +typedef _CryptoHashDigestLengthDart = void Function(int, int); +// fn crypto_public_key_length(port: i64, kind: u32) +typedef _CryptoPublicKeyLengthDart = void Function(int, int); +// fn crypto_secret_key_length(port: i64, kind: u32) +typedef _CryptoSecretKeyLengthDart = void Function(int, int); +// fn crypto_signature_length(port: i64, kind: u32) +typedef _CryptoSignatureLengthDart = void Function(int, int); // fn crypto_default_salt_length(port: i64, kind: u32) typedef _CryptoDefaultSaltLengthDart = void Function(int, int); +// fn crypto_aead_overhead(port: i64, kind: u32) +typedef _CryptoAeadOverheadDart = void Function(int, int); + +// fn crypto_check_shared_secret(port: i64, kind: u32, secret: FfiStr) +typedef _CryptoCheckSharedSecretDart = void Function(int, int, Pointer); +// fn crypto_check_nonce(port: i64, kind: u32, nonce: FfiStr) +typedef _CryptoCheckNonceDart = void Function(int, int, Pointer); +// fn crypto_check_hash_digest(port: i64, kind: u32, digest: FfiStr) +typedef _CryptoCheckHashDigestDart = void Function(int, int, Pointer); +// fn crypto_check_public_key(port: i64, kind: u32, key: FfiStr) +typedef _CryptoCheckPublicKeyDart = void Function(int, int, Pointer); +// fn crypto_check_secret_key(port: i64, kind: u32, key: FfiStr) +typedef _CryptoCheckSecretKeyDart = void Function(int, int, Pointer); +// fn crypto_check_signature(port: i64, kind: u32, signature: FfiStr) +typedef _CryptoCheckSignatureDart = void Function(int, int, Pointer); + // fn crypto_hash_password(port: i64, kind: u32, password: FfiStr, salt: FfiStr) typedef _CryptoHashPasswordDart = void Function( int, int, Pointer, Pointer); @@ -182,7 +217,8 @@ typedef _CryptoVerifyPasswordDart = void Function( int, int, Pointer, Pointer); // fn crypto_derive_shared_secret(port: i64, // kind: u32, password: FfiStr, salt: FfiStr ) - +typedef _CryptoDeriveSharedSecretDart = void Function( + int, int, Pointer, Pointer); // fn crypto_random_nonce(port: i64, kind: u32) typedef _CryptoRandomNonceDart = void Function(int, int); // fn crypto_random_shared_secret(port: i64, kind: u32) @@ -209,8 +245,6 @@ typedef _CryptoSignDart = void Function( // kind: u32, key: FfiStr, data: FfiStr, signature: FfiStr) typedef _CryptoVerifyDart = void Function( int, int, Pointer, Pointer, Pointer); -// fn crypto_aead_overhead(port: i64, kind: u32) -typedef _CryptoAeadOverheadDart = void Function(int, int); // fn crypto_decrypt_aead(port: i64, // kind: u32, body: FfiStr, nonce: FfiStr, // shared_secret: FfiStr, associated_data: FfiStr) @@ -254,15 +288,15 @@ typedef _DefaultVeilidConfigDart = Pointer Function(); typedef _VeilidFeaturesDart = Pointer Function(); // Async message types -const int messageOk = 0; -const int messageErr = 1; -const int messageOkJson = 2; -const int messageErrJson = 3; -const int messageStreamItem = 4; -const int messageStreamItemJson = 5; -const int messageStreamAbort = 6; -const int messageStreamAbortJson = 7; -const int messageStreamClose = 8; +const messageOk = 0; +const messageErr = 1; +const messageOkJson = 2; +const messageErrJson = 3; +const messageStreamItem = 4; +const messageStreamItemJson = 5; +const messageStreamAbort = 6; +const messageStreamAbortJson = 7; +const messageStreamClose = 8; // Interface factory for high level Veilid API Veilid getVeilid() => VeilidFFI(_dylib); @@ -273,8 +307,7 @@ Uint8List convertUint8ListFromJson(dynamic json) => dynamic convertUint8ListToJson(Uint8List data) => base64UrlNoPadEncode(data); // Parse handle async returns -Future processFuturePlain(Future future) async => - future.then((value) { +Future processFuturePlain(Future future) => future.then((value) { final list = value as List; switch (list[0] as int) { case messageOk: @@ -307,7 +340,7 @@ Future processFuturePlain(Future future) async => }, test: (e) => e is! VeilidAPIException); Future processFutureJson( - T Function(dynamic) jsonConstructor, Future future) async => + T Function(dynamic) jsonConstructor, Future future) => future.then((value) { final list = value as List; switch (list[0] as int) { @@ -346,7 +379,7 @@ Future processFutureJson( }, test: (e) => e is! VeilidAPIException); Future processFutureOptJson( - T Function(dynamic) jsonConstructor, Future future) async => + T Function(dynamic) jsonConstructor, Future future) => future.then((value) { final list = value as List; switch (list[0] as int) { @@ -386,8 +419,7 @@ Future processFutureOptJson( throw VeilidAPIExceptionInternal('$e\nStack Trace:\n$s'); }, test: (e) => e is! VeilidAPIException); -Future processFutureVoid(Future future) async => - future.then((value) { +Future processFutureVoid(Future future) => future.then((value) { final list = value as List; switch (list[0] as int) { case messageOk: @@ -430,7 +462,7 @@ Future processFutureVoid(Future future) async => }, test: (e) => e is! VeilidAPIException); Future> processFutureStream( - Stream returnStream, Future future) async => + Stream returnStream, Future future) => future.then((value) { final list = value as List; switch (list[0] as int) { @@ -600,35 +632,49 @@ class VeilidRoutingContextFFI extends VeilidRoutingContext { } @override - Future appCall(String target, Uint8List request) async { + Future appCall(Target target, Uint8List request) async { _ctx.ensureValid(); - final nativeEncodedTarget = target.toNativeUtf8(); + final nativeTarget = jsonEncode(target).toNativeUtf8(); final nativeEncodedRequest = base64UrlNoPadEncode(request).toNativeUtf8(); final recvPort = ReceivePort('routing_context_app_call'); final sendPort = recvPort.sendPort; - _ctx.ffi._routingContextAppCall(sendPort.nativePort, _ctx.id!, - nativeEncodedTarget, nativeEncodedRequest); + _ctx.ffi._routingContextAppCall( + sendPort.nativePort, _ctx.id!, nativeTarget, nativeEncodedRequest); final out = await processFuturePlain(recvPort.first); return base64UrlNoPadDecode(out); } @override - Future appMessage(String target, Uint8List message) async { + Future appMessage(Target target, Uint8List message) { _ctx.ensureValid(); - final nativeEncodedTarget = target.toNativeUtf8(); + final nativeTarget = jsonEncode(target).toNativeUtf8(); final nativeEncodedMessage = base64UrlNoPadEncode(message).toNativeUtf8(); final recvPort = ReceivePort('routing_context_app_message'); final sendPort = recvPort.sendPort; - _ctx.ffi._routingContextAppMessage(sendPort.nativePort, _ctx.id!, - nativeEncodedTarget, nativeEncodedMessage); + _ctx.ffi._routingContextAppMessage( + sendPort.nativePort, _ctx.id!, nativeTarget, nativeEncodedMessage); return processFutureVoid(recvPort.first); } + @override + Future getDHTRecordKey(DHTSchema schema, PublicKey owner) async { + _ctx.ensureValid(); + final nativeSchema = jsonEncode(schema).toNativeUtf8(); + final nativeOwner = jsonEncode(owner).toNativeUtf8(); + final recvPort = ReceivePort('routing_context_get_dht_record_key'); + final sendPort = recvPort.sendPort; + _ctx.ffi._routingContextGetDHTRecordKey( + sendPort.nativePort, _ctx.id!, nativeSchema, nativeOwner); + final recordKey = + await processFutureJson(RecordKey.fromJson, recvPort.first); + return recordKey; + } + @override Future createDHTRecord(DHTSchema schema, - {BareKeyPair? owner, CryptoKind kind = 0}) async { + {KeyPair? owner, CryptoKind kind = 0}) async { _ctx.ensureValid(); final nativeSchema = jsonEncode(schema).toNativeUtf8(); final nativeOwner = @@ -643,8 +689,8 @@ class VeilidRoutingContextFFI extends VeilidRoutingContext { } @override - Future openDHTRecord(PublicKey key, - {BareKeyPair? writer}) async { + Future openDHTRecord(RecordKey key, + {KeyPair? writer}) async { _ctx.ensureValid(); final nativeKey = jsonEncode(key).toNativeUtf8(); final nativeWriter = @@ -659,7 +705,7 @@ class VeilidRoutingContextFFI extends VeilidRoutingContext { } @override - Future closeDHTRecord(PublicKey key) async { + Future closeDHTRecord(RecordKey key) { _ctx.ensureValid(); final nativeKey = jsonEncode(key).toNativeUtf8(); final recvPort = ReceivePort('routing_context_close_dht_record'); @@ -670,7 +716,7 @@ class VeilidRoutingContextFFI extends VeilidRoutingContext { } @override - Future deleteDHTRecord(PublicKey key) async { + Future deleteDHTRecord(RecordKey key) { _ctx.ensureValid(); final nativeKey = jsonEncode(key).toNativeUtf8(); final recvPort = ReceivePort('routing_context_delete_dht_record'); @@ -681,7 +727,7 @@ class VeilidRoutingContextFFI extends VeilidRoutingContext { } @override - Future getDHTValue(PublicKey key, int subkey, + Future getDHTValue(RecordKey key, int subkey, {bool forceRefresh = false}) async { _ctx.ensureValid(); final nativeKey = jsonEncode(key).toNativeUtf8(); @@ -695,7 +741,7 @@ class VeilidRoutingContextFFI extends VeilidRoutingContext { } @override - Future setDHTValue(PublicKey key, int subkey, Uint8List data, + Future setDHTValue(RecordKey key, int subkey, Uint8List data, {SetDHTValueOptions? options}) async { _ctx.ensureValid(); final nativeKey = jsonEncode(key).toNativeUtf8(); @@ -713,7 +759,7 @@ class VeilidRoutingContextFFI extends VeilidRoutingContext { } @override - Future watchDHTValues(PublicKey key, + Future watchDHTValues(RecordKey key, {List? subkeys, Timestamp? expiration, int? count}) async { @@ -735,7 +781,7 @@ class VeilidRoutingContextFFI extends VeilidRoutingContext { } @override - Future cancelDHTWatch(PublicKey key, + Future cancelDHTWatch(RecordKey key, {List? subkeys}) async { subkeys ??= []; @@ -752,7 +798,7 @@ class VeilidRoutingContextFFI extends VeilidRoutingContext { } @override - Future inspectDHTRecord(PublicKey key, + Future inspectDHTRecord(RecordKey key, {List? subkeys, DHTReportScope scope = DHTReportScope.local}) async { subkeys ??= []; @@ -829,7 +875,7 @@ class VeilidTableDBTransactionFFI extends VeilidTableDBTransaction { } @override - Future store(int col, Uint8List key, Uint8List value) async { + Future store(int col, Uint8List key, Uint8List value) { _tdbt.ensureValid(); final nativeEncodedKey = base64UrlNoPadEncode(key).toNativeUtf8(); final nativeEncodedValue = base64UrlNoPadEncode(value).toNativeUtf8(); @@ -847,7 +893,7 @@ class VeilidTableDBTransactionFFI extends VeilidTableDBTransaction { } @override - Future delete(int col, Uint8List key) async { + Future delete(int col, Uint8List key) { _tdbt.ensureValid(); final nativeEncodedKey = base64UrlNoPadEncode(key).toNativeUtf8(); @@ -901,7 +947,7 @@ class VeilidTableDBFFI extends VeilidTableDB { } @override - Future> getKeys(int col) async { + Future> getKeys(int col) { _tdb.ensureValid(); final recvPort = ReceivePort('veilid_table_db_get_keys'); @@ -923,7 +969,7 @@ class VeilidTableDBFFI extends VeilidTableDB { } @override - Future store(int col, Uint8List key, Uint8List value) async { + Future store(int col, Uint8List key, Uint8List value) { _tdb.ensureValid(); final nativeEncodedKey = base64UrlNoPadEncode(key).toNativeUtf8(); @@ -992,8 +1038,7 @@ class VeilidCryptoSystemFFI extends VeilidCryptoSystem { CryptoKind kind() => _kind; @override - Future cachedDH( - BarePublicKey key, BareSecretKey secret) async { + Future cachedDH(BarePublicKey key, BareSecretKey secret) { final nativeKey = jsonEncode(key).toNativeUtf8(); final nativeSecret = jsonEncode(secret).toNativeUtf8(); @@ -1004,8 +1049,7 @@ class VeilidCryptoSystemFFI extends VeilidCryptoSystem { } @override - Future computeDH( - BarePublicKey key, BareSecretKey secret) async { + Future computeDH(BarePublicKey key, BareSecretKey secret) { final nativeKey = jsonEncode(key).toNativeUtf8(); final nativeSecret = jsonEncode(secret).toNativeUtf8(); @@ -1017,7 +1061,7 @@ class VeilidCryptoSystemFFI extends VeilidCryptoSystem { @override Future generateSharedSecret( - BarePublicKey key, BareSecretKey secret, Uint8List domain) async { + BarePublicKey key, BareSecretKey secret, Uint8List domain) { final nativeKey = jsonEncode(key).toNativeUtf8(); final nativeSecret = jsonEncode(secret).toNativeUtf8(); final nativeDomain = base64UrlNoPadEncode(domain).toNativeUtf8(); @@ -1039,7 +1083,55 @@ class VeilidCryptoSystemFFI extends VeilidCryptoSystem { } @override - Future defaultSaltLength() async { + Future sharedSecretLength() { + final recvPort = ReceivePort('crypto_shared_secret_length'); + final sendPort = recvPort.sendPort; + _ffi._cryptoSharedSecretLength(sendPort.nativePort, _kind); + return processFuturePlain(recvPort.first); + } + + @override + Future nonceLength() { + final recvPort = ReceivePort('crypto_nonce_length'); + final sendPort = recvPort.sendPort; + _ffi._cryptoNonceLength(sendPort.nativePort, _kind); + return processFuturePlain(recvPort.first); + } + + @override + Future hashDigestLength() { + final recvPort = ReceivePort('crypto_hash_digest_length'); + final sendPort = recvPort.sendPort; + _ffi._cryptoHashDigestLength(sendPort.nativePort, _kind); + return processFuturePlain(recvPort.first); + } + + @override + Future publicKeyLength() { + final recvPort = ReceivePort('crypto_public_key_length'); + final sendPort = recvPort.sendPort; + _ffi._cryptoPublicKeyLength(sendPort.nativePort, _kind); + return processFuturePlain(recvPort.first); + } + + @override + Future secretKeyLength() { + final recvPort = ReceivePort('crypto_secret_key_length'); + final sendPort = recvPort.sendPort; + _ffi._cryptoSecretKeyLength(sendPort.nativePort, _kind); + return processFuturePlain(recvPort.first); + } + + @override + Future signatureLength() { + final recvPort = ReceivePort('crypto_signature_length'); + final sendPort = recvPort.sendPort; + _ffi._cryptoSignatureLength(sendPort.nativePort, _kind); + return processFuturePlain(recvPort.first); + } + + @override + Future defaultSaltLength() { final recvPort = ReceivePort('crypto_default_salt_length'); final sendPort = recvPort.sendPort; _ffi._cryptoDefaultSaltLength(sendPort.nativePort, _kind); @@ -1047,7 +1139,72 @@ class VeilidCryptoSystemFFI extends VeilidCryptoSystem { } @override - Future hashPassword(Uint8List password, Uint8List salt) async { + Future aeadOverhead() { + final recvPort = ReceivePort('crypto_aead_overhead'); + final sendPort = recvPort.sendPort; + _ffi._cryptoAeadOverhead( + sendPort.nativePort, + _kind, + ); + return processFuturePlain(recvPort.first); + } + + @override + Future checkSharedSecret(BareSharedSecret secret) { + final nativeSecret = jsonEncode(secret).toNativeUtf8(); + final recvPort = ReceivePort('crypto_check_shared_secret'); + final sendPort = recvPort.sendPort; + _ffi._cryptoCheckSharedSecret(sendPort.nativePort, _kind, nativeSecret); + return processFutureVoid(recvPort.first); + } + + @override + Future checkNonce(BareNonce nonce) { + final nativeNonce = jsonEncode(nonce).toNativeUtf8(); + final recvPort = ReceivePort('crypto_check_nonce'); + final sendPort = recvPort.sendPort; + _ffi._cryptoCheckNonce(sendPort.nativePort, _kind, nativeNonce); + return processFutureVoid(recvPort.first); + } + + @override + Future checkHashDigest(BareHashDigest digest) { + final nativeDigest = jsonEncode(digest).toNativeUtf8(); + final recvPort = ReceivePort('crypto_check_hash_digest'); + final sendPort = recvPort.sendPort; + _ffi._cryptoCheckHashDigest(sendPort.nativePort, _kind, nativeDigest); + return processFutureVoid(recvPort.first); + } + + @override + Future checkPublicKey(BarePublicKey key) { + final nativeKey = jsonEncode(key).toNativeUtf8(); + final recvPort = ReceivePort('crypto_check_public_key'); + final sendPort = recvPort.sendPort; + _ffi._cryptoCheckPublicKey(sendPort.nativePort, _kind, nativeKey); + return processFutureVoid(recvPort.first); + } + + @override + Future checkSecretKey(BareSecretKey key) { + final nativeKey = jsonEncode(key).toNativeUtf8(); + final recvPort = ReceivePort('crypto_check_secret_key'); + final sendPort = recvPort.sendPort; + _ffi._cryptoCheckSecretKey(sendPort.nativePort, _kind, nativeKey); + return processFutureVoid(recvPort.first); + } + + @override + Future checkSignature(BareSignature signature) { + final nativeSignature = jsonEncode(signature).toNativeUtf8(); + final recvPort = ReceivePort('crypto_check_signature'); + final sendPort = recvPort.sendPort; + _ffi._cryptoCheckSignature(sendPort.nativePort, _kind, nativeSignature); + return processFutureVoid(recvPort.first); + } + + @override + Future hashPassword(Uint8List password, Uint8List salt) { final nativeEncodedPassword = base64UrlNoPadEncode(password).toNativeUtf8(); final nativeEncodedSalt = base64UrlNoPadEncode(salt).toNativeUtf8(); @@ -1059,7 +1216,7 @@ class VeilidCryptoSystemFFI extends VeilidCryptoSystem { } @override - Future verifyPassword(Uint8List password, String passwordHash) async { + Future verifyPassword(Uint8List password, String passwordHash) { final nativeEncodedPassword = base64UrlNoPadEncode(password).toNativeUtf8(); final nativeEncodedPasswordHash = passwordHash.toNativeUtf8(); @@ -1072,7 +1229,7 @@ class VeilidCryptoSystemFFI extends VeilidCryptoSystem { @override Future deriveSharedSecret( - Uint8List password, Uint8List salt) async { + Uint8List password, Uint8List salt) { final nativeEncodedPassword = base64UrlNoPadEncode(password).toNativeUtf8(); final nativeEncodedSalt = base64UrlNoPadEncode(salt).toNativeUtf8(); @@ -1084,7 +1241,7 @@ class VeilidCryptoSystemFFI extends VeilidCryptoSystem { } @override - Future randomNonce() async { + Future randomNonce() { final recvPort = ReceivePort('crypto_random_nonce'); final sendPort = recvPort.sendPort; _ffi._cryptoRandomNonce(sendPort.nativePort, _kind); @@ -1092,7 +1249,7 @@ class VeilidCryptoSystemFFI extends VeilidCryptoSystem { } @override - Future randomSharedSecret() async { + Future randomSharedSecret() { final recvPort = ReceivePort('crypto_random_shared_secret'); final sendPort = recvPort.sendPort; _ffi._cryptoRandomSharedSecret(sendPort.nativePort, _kind); @@ -1100,7 +1257,7 @@ class VeilidCryptoSystemFFI extends VeilidCryptoSystem { } @override - Future generateKeyPair() async { + Future generateKeyPair() { final recvPort = ReceivePort('crypto_generate_key_pair'); final sendPort = recvPort.sendPort; _ffi._cryptoGenerateKeyPair(sendPort.nativePort, _kind); @@ -1108,7 +1265,7 @@ class VeilidCryptoSystemFFI extends VeilidCryptoSystem { } @override - Future generateHash(Uint8List data) async { + Future generateHash(Uint8List data) { final nativeEncodedData = base64UrlNoPadEncode(data).toNativeUtf8(); final recvPort = ReceivePort('crypto_generate_hash'); @@ -1118,7 +1275,7 @@ class VeilidCryptoSystemFFI extends VeilidCryptoSystem { } @override - Future validateKeyPair(BarePublicKey key, BareSecretKey secret) async { + Future validateKeyPair(BarePublicKey key, BareSecretKey secret) { final nativeKey = jsonEncode(key).toNativeUtf8(); final nativeSecret = jsonEncode(secret).toNativeUtf8(); @@ -1130,7 +1287,7 @@ class VeilidCryptoSystemFFI extends VeilidCryptoSystem { } @override - Future validateHash(Uint8List data, BareHashDigest hash) async { + Future validateHash(Uint8List data, BareHashDigest hash) { final nativeEncodedData = base64UrlNoPadEncode(data).toNativeUtf8(); final nativeHash = jsonEncode(hash).toNativeUtf8(); @@ -1142,7 +1299,7 @@ class VeilidCryptoSystemFFI extends VeilidCryptoSystem { } @override - Future distance(CryptoKey key1, CryptoKey key2) async { + Future distance(BareHashDigest key1, BareHashDigest key2) { final nativeKey1 = jsonEncode(key1).toNativeUtf8(); final nativeKey2 = jsonEncode(key2).toNativeUtf8(); @@ -1154,7 +1311,7 @@ class VeilidCryptoSystemFFI extends VeilidCryptoSystem { @override Future sign( - BarePublicKey key, BareSecretKey secret, Uint8List data) async { + BarePublicKey key, BareSecretKey secret, Uint8List data) { final nativeKey = jsonEncode(key).toNativeUtf8(); final nativeSecret = jsonEncode(secret).toNativeUtf8(); final nativeEncodedData = base64UrlNoPadEncode(data).toNativeUtf8(); @@ -1168,7 +1325,7 @@ class VeilidCryptoSystemFFI extends VeilidCryptoSystem { @override Future verify( - BarePublicKey key, Uint8List data, BareSignature signature) async { + BarePublicKey key, Uint8List data, BareSignature signature) { final nativeKey = jsonEncode(key).toNativeUtf8(); final nativeEncodedData = base64UrlNoPadEncode(data).toNativeUtf8(); final nativeSignature = jsonEncode(signature).toNativeUtf8(); @@ -1180,17 +1337,6 @@ class VeilidCryptoSystemFFI extends VeilidCryptoSystem { return processFuturePlain(recvPort.first); } - @override - Future aeadOverhead() async { - final recvPort = ReceivePort('crypto_aead_overhead'); - final sendPort = recvPort.sendPort; - _ffi._cryptoAeadOverhead( - sendPort.nativePort, - _kind, - ); - return processFuturePlain(recvPort.first); - } - @override Future decryptAead(Uint8List body, BareNonce nonce, BareSharedSecret sharedSecret, Uint8List? associatedData) async { @@ -1299,6 +1445,10 @@ class VeilidFFI extends Veilid { _routingContextAppMessage = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer, Pointer), _RoutingContextAppMessageDart>('routing_context_app_message'), + _routingContextGetDHTRecordKey = dylib.lookupFunction< + Void Function(Int64, Uint32, Pointer, Pointer), + _RoutingContextGetDHTRecordKeyDart>( + 'routing_context_get_dht_record_key'), _routingContextCreateDHTRecord = dylib.lookupFunction< Void Function( @@ -1338,6 +1488,9 @@ class VeilidFFI extends Veilid { Int64, Uint32, Pointer, Pointer, Pointer), _RoutingContextInspectDHTRecordDart>( 'routing_context_inspect_dht_record'), + _generateMemberId = dylib.lookupFunction< + Void Function(Int64, Pointer), + _GenerateMemberIdDart>('generate_member_id'), _newPrivateRoute = dylib.lookupFunction( 'new_private_route'), @@ -1417,12 +1570,49 @@ class VeilidFFI extends Veilid { Void Function( Int64, Uint32, Pointer, Pointer, Pointer), _CryptoGenerateSharedSecretDart>('crypto_generate_shared_secret'), - _cryptoRandomBytes = dylib.lookupFunction< - Void Function(Int64, Uint32, Uint32), - _CryptoRandomBytesDart>('crypto_random_bytes'), + _cryptoSharedSecretLength = dylib.lookupFunction< + Void Function(Int64, Uint32), + _CryptoSharedSecretLengthDart>('crypto_shared_secret_length'), + _cryptoNonceLength = dylib.lookupFunction('crypto_nonce_length'), + _cryptoHashDigestLength = dylib.lookupFunction< + Void Function(Int64, Uint32), + _CryptoHashDigestLengthDart>('crypto_hash_digest_length'), + _cryptoPublicKeyLength = dylib.lookupFunction< + Void Function(Int64, Uint32), + _CryptoPublicKeyLengthDart>('crypto_public_key_length'), + _cryptoSecretKeyLength = dylib.lookupFunction< + Void Function(Int64, Uint32), + _CryptoSecretKeyLengthDart>('crypto_secret_key_length'), + _cryptoSignatureLength = dylib.lookupFunction< + Void Function(Int64, Uint32), + _CryptoSignatureLengthDart>('crypto_signature_length'), _cryptoDefaultSaltLength = dylib.lookupFunction< Void Function(Int64, Uint32), _CryptoDefaultSaltLengthDart>('crypto_default_salt_length'), + _cryptoAeadOverhead = dylib.lookupFunction('crypto_aead_overhead'), + _cryptoCheckSharedSecret = dylib.lookupFunction< + Void Function(Int64, Uint32, Pointer), + _CryptoCheckSharedSecretDart>('crypto_check_shared_secret'), + _cryptoCheckNonce = dylib.lookupFunction< + Void Function(Int64, Uint32, Pointer), + _CryptoCheckNonceDart>('crypto_check_nonce'), + _cryptoCheckHashDigest = dylib.lookupFunction< + Void Function(Int64, Uint32, Pointer), + _CryptoCheckHashDigestDart>('crypto_check_hash_digest'), + _cryptoCheckPublicKey = dylib.lookupFunction< + Void Function(Int64, Uint32, Pointer), + _CryptoCheckPublicKeyDart>('crypto_check_public_key'), + _cryptoCheckSecretKey = dylib.lookupFunction< + Void Function(Int64, Uint32, Pointer), + _CryptoCheckSecretKeyDart>('crypto_check_secret_key'), + _cryptoCheckSignature = dylib.lookupFunction< + Void Function(Int64, Uint32, Pointer), + _CryptoCheckSignatureDart>('crypto_check_signature'), + _cryptoRandomBytes = dylib.lookupFunction< + Void Function(Int64, Uint32, Uint32), + _CryptoRandomBytesDart>('crypto_random_bytes'), _cryptoHashPassword = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer, Pointer), _CryptoHashPasswordDart>('crypto_hash_password'), @@ -1431,7 +1621,7 @@ class VeilidFFI extends Veilid { _CryptoVerifyPasswordDart>('crypto_verify_password'), _cryptoDeriveSharedSecret = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer, Pointer), - _CryptoVerifyPasswordDart>('crypto_derive_shared_secret'), + _CryptoDeriveSharedSecretDart>('crypto_derive_shared_secret'), _cryptoRandomNonce = dylib.lookupFunction('crypto_random_nonce'), _cryptoRandomSharedSecret = dylib.lookupFunction< @@ -1460,8 +1650,6 @@ class VeilidFFI extends Veilid { Void Function( Int64, Uint32, Pointer, Pointer, Pointer), _CryptoVerifyDart>('crypto_verify'), - _cryptoAeadOverhead = dylib.lookupFunction('crypto_aead_overhead'), _cryptoDecryptAead = dylib.lookupFunction< Void Function(Int64, Uint32, Pointer, Pointer, Pointer, Pointer), @@ -1521,6 +1709,7 @@ class VeilidFFI extends Veilid { final _RoutingContextSafetyDart _routingContextSafety; final _RoutingContextAppCallDart _routingContextAppCall; final _RoutingContextAppMessageDart _routingContextAppMessage; + final _RoutingContextGetDHTRecordKeyDart _routingContextGetDHTRecordKey; final _RoutingContextCreateDHTRecordDart _routingContextCreateDHTRecord; final _RoutingContextOpenDHTRecordDart _routingContextOpenDHTRecord; final _RoutingContextCloseDHTRecordDart _routingContextCloseDHTRecord; @@ -1531,6 +1720,8 @@ class VeilidFFI extends Veilid { final _RoutingContextCancelDHTWatchDart _routingContextCancelDHTWatch; final _RoutingContextInspectDHTRecordDart _routingContextInspectDHTRecord; + final _GenerateMemberIdDart _generateMemberId; + final _NewPrivateRouteDart _newPrivateRoute; final _NewCustomPrivateRouteDart _newCustomPrivateRoute; final _ImportRemotePrivateRouteDart _importRemotePrivateRoute; @@ -1564,11 +1755,25 @@ class VeilidFFI extends Veilid { final _CryptoGenerateSharedSecretDart _cryptoGenerateSharedSecret; final _CryptoRandomBytesDart _cryptoRandomBytes; - final _CryptoDefaultSaltLengthDart _cryptoDefaultSaltLength; final _CryptoHashPasswordDart _cryptoHashPassword; final _CryptoVerifyPasswordDart _cryptoVerifyPassword; - final void Function(int, int, Pointer, Pointer) - _cryptoDeriveSharedSecret; + final _CryptoDeriveSharedSecretDart _cryptoDeriveSharedSecret; + + final _CryptoSharedSecretLengthDart _cryptoSharedSecretLength; + final _CryptoNonceLengthDart _cryptoNonceLength; + final _CryptoHashDigestLengthDart _cryptoHashDigestLength; + final _CryptoPublicKeyLengthDart _cryptoPublicKeyLength; + final _CryptoSecretKeyLengthDart _cryptoSecretKeyLength; + final _CryptoSignatureLengthDart _cryptoSignatureLength; + final _CryptoDefaultSaltLengthDart _cryptoDefaultSaltLength; + final _CryptoAeadOverheadDart _cryptoAeadOverhead; + + final _CryptoCheckSharedSecretDart _cryptoCheckSharedSecret; + final _CryptoCheckNonceDart _cryptoCheckNonce; + final _CryptoCheckHashDigestDart _cryptoCheckHashDigest; + final _CryptoCheckPublicKeyDart _cryptoCheckPublicKey; + final _CryptoCheckSecretKeyDart _cryptoCheckSecretKey; + final _CryptoCheckSignatureDart _cryptoCheckSignature; final _CryptoRandomNonceDart _cryptoRandomNonce; final _CryptoRandomSharedSecretDart _cryptoRandomSharedSecret; @@ -1579,7 +1784,6 @@ class VeilidFFI extends Veilid { final _CryptoDistanceDart _cryptoDistance; final _CryptoSignDart _cryptoSign; final _CryptoVerifyDart _cryptoVerify; - final _CryptoAeadOverheadDart _cryptoAeadOverhead; final _CryptoDecryptAeadDart _cryptoDecryptAead; final _CryptoEncryptAeadDart _cryptoEncryptAead; final _CryptoCryptNoAuthDart _cryptoCryptNoAuth; @@ -1621,7 +1825,7 @@ class VeilidFFI extends Veilid { } @override - Future> startupVeilidCore(VeilidConfig config) async { + Future> startupVeilidCore(VeilidConfig config) { final nativeConfig = jsonEncode(config).toNativeUtf8(); final recvStreamPort = ReceivePort('veilid_api_stream'); final sendStreamPort = recvStreamPort.sendPort; @@ -1636,7 +1840,7 @@ class VeilidFFI extends Veilid { } @override - Future getVeilidState() async { + Future getVeilidState() { final recvPort = ReceivePort('get_veilid_state'); final sendPort = recvPort.sendPort; _getVeilidState(sendPort.nativePort); @@ -1644,7 +1848,7 @@ class VeilidFFI extends Veilid { } @override - Future isShutdown() async { + Future isShutdown() { final recvPort = ReceivePort('is_shutdown'); final sendPort = recvPort.sendPort; _isShutdown(sendPort.nativePort); @@ -1652,7 +1856,7 @@ class VeilidFFI extends Veilid { } @override - Future attach() async { + Future attach() { final recvPort = ReceivePort('attach'); final sendPort = recvPort.sendPort; _attach(sendPort.nativePort); @@ -1660,7 +1864,7 @@ class VeilidFFI extends Veilid { } @override - Future detach() async { + Future detach() { final recvPort = ReceivePort('detach'); final sendPort = recvPort.sendPort; _detach(sendPort.nativePort); @@ -1668,7 +1872,7 @@ class VeilidFFI extends Veilid { } @override - Future shutdownVeilidCore() async { + Future shutdownVeilidCore() { final recvPort = ReceivePort('shutdown_veilid_core'); final sendPort = recvPort.sendPort; _shutdownVeilidCore(sendPort.nativePort); @@ -1686,7 +1890,16 @@ class VeilidFFI extends Veilid { } @override - Future newPrivateRoute() async { + Future generateMemberId(PublicKey writerKey) { + final recvPort = ReceivePort('generate_member_id'); + final sendPort = recvPort.sendPort; + _generateMemberId( + sendPort.nativePort, jsonEncode(writerKey).toNativeUtf8()); + return processFutureJson(MemberId.fromJson, recvPort.first); + } + + @override + Future newPrivateRoute() { final recvPort = ReceivePort('new_private_route'); final sendPort = recvPort.sendPort; _newPrivateRoute(sendPort.nativePort); @@ -1695,7 +1908,7 @@ class VeilidFFI extends Veilid { @override Future newCustomPrivateRoute( - Stability stability, Sequencing sequencing) async { + Stability stability, Sequencing sequencing) { final recvPort = ReceivePort('new_custom_private_route'); final sendPort = recvPort.sendPort; _newCustomPrivateRoute( @@ -1707,27 +1920,27 @@ class VeilidFFI extends Veilid { } @override - Future importRemotePrivateRoute(Uint8List blob) async { + Future importRemotePrivateRoute(Uint8List blob) { final nativeEncodedBlob = base64UrlNoPadEncode(blob).toNativeUtf8(); final recvPort = ReceivePort('import_remote_private_route'); final sendPort = recvPort.sendPort; _importRemotePrivateRoute(sendPort.nativePort, nativeEncodedBlob); - return processFuturePlain(recvPort.first); + return processFutureJson(RouteId.fromJson, recvPort.first); } @override - Future releasePrivateRoute(String routeId) async { - final nativeEncodedRouteId = routeId.toNativeUtf8(); + Future releasePrivateRoute(RouteId routeId) { + final nativeRouteId = jsonEncode(routeId).toNativeUtf8(); final recvPort = ReceivePort('release_private_route'); final sendPort = recvPort.sendPort; - _releasePrivateRoute(sendPort.nativePort, nativeEncodedRouteId); + _releasePrivateRoute(sendPort.nativePort, nativeRouteId); return processFutureVoid(recvPort.first); } @override - Future appCallReply(String callId, Uint8List message) async { + Future appCallReply(String callId, Uint8List message) { final nativeCallId = callId.toNativeUtf8(); final nativeEncodedMessage = base64UrlNoPadEncode(message).toNativeUtf8(); final recvPort = ReceivePort('app_call_reply'); @@ -1746,7 +1959,7 @@ class VeilidFFI extends Veilid { } @override - Future deleteTableDB(String name) async { + Future deleteTableDB(String name) { final recvPort = ReceivePort('delete_table_db'); final sendPort = recvPort.sendPort; _deleteTableDb(sendPort.nativePort, name.toNativeUtf8()); @@ -1774,8 +1987,8 @@ class VeilidFFI extends Veilid { VeilidCryptoSystemFFI._(this, _bestCryptoKind()); @override - Future?> verifySignatures(List nodeIds, - Uint8List data, List signatures) async { + Future?> verifySignatures( + List nodeIds, Uint8List data, List signatures) { final nativeNodeIds = jsonEncode(nodeIds).toNativeUtf8(); final nativeData = base64UrlNoPadEncode(data).toNativeUtf8(); final nativeSignatures = jsonEncode(signatures).toNativeUtf8(); @@ -1790,7 +2003,7 @@ class VeilidFFI extends Veilid { @override Future> generateSignatures( - Uint8List data, List keyPairs) async { + Uint8List data, List keyPairs) { final nativeData = base64UrlNoPadEncode(data).toNativeUtf8(); final nativeKeyPairs = jsonEncode(keyPairs).toNativeUtf8(); @@ -1808,7 +2021,7 @@ class VeilidFFI extends Veilid { } @override - Future generateKeyPair(CryptoKind kind) async { + Future generateKeyPair(CryptoKind kind) { final recvPort = ReceivePort('generate_key_pair'); final sendPort = recvPort.sendPort; _generateKeyPair(sendPort.nativePort, kind); @@ -1816,7 +2029,7 @@ class VeilidFFI extends Veilid { } @override - Future debug(String command) async { + Future debug(String command) { final nativeCommand = command.toNativeUtf8(); final recvPort = ReceivePort('debug'); final sendPort = recvPort.sendPort; diff --git a/veilid-flutter/lib/veilid_js.dart b/veilid-flutter/lib/veilid_js.dart index f46c6ca0..52191e8e 100644 --- a/veilid-flutter/lib/veilid_js.dart +++ b/veilid-flutter/lib/veilid_js.dart @@ -120,26 +120,39 @@ class VeilidRoutingContextJS extends VeilidRoutingContext { } @override - Future appCall(String target, Uint8List request) async { + Future appCall(Target target, Uint8List request) async { final id = _ctx.requireId(); final encodedRequest = base64UrlNoPadEncode(request); - return base64UrlNoPadDecode(await _wrapApiPromise(js_util.callMethod( - wasm, 'routing_context_app_call', [id, target, encodedRequest]))); + return base64UrlNoPadDecode(await _wrapApiPromise(js_util.callMethod(wasm, + 'routing_context_app_call', [id, jsonEncode(target), encodedRequest]))); } @override - Future appMessage(String target, Uint8List message) { + Future appMessage(Target target, Uint8List message) { final id = _ctx.requireId(); final encodedMessage = base64UrlNoPadEncode(message); return _wrapApiPromise(js_util.callMethod( - wasm, 'routing_context_app_message', [id, target, encodedMessage])); + wasm, + 'routing_context_app_message', + [id, jsonEncode(target), encodedMessage])); + } + + @override + Future getDHTRecordKey(DHTSchema schema, PublicKey owner) async { + final id = _ctx.requireId(); + return RecordKey.fromJson(jsonDecode(await _wrapApiPromise( + js_util.callMethod(wasm, 'routing_context_get_dht_record_key', [ + id, + jsonEncode(schema), + jsonEncode(owner), + ])))); } @override Future createDHTRecord(DHTSchema schema, - {BareKeyPair? owner, CryptoKind kind = 0}) async { + {KeyPair? owner, CryptoKind kind = 0}) async { final id = _ctx.requireId(); return DHTRecordDescriptor.fromJson(jsonDecode(await _wrapApiPromise(js_util .callMethod(wasm, 'routing_context_create_dht_record', [ @@ -151,8 +164,8 @@ class VeilidRoutingContextJS extends VeilidRoutingContext { } @override - Future openDHTRecord(PublicKey key, - {BareKeyPair? writer}) async { + Future openDHTRecord(RecordKey key, + {KeyPair? writer}) async { final id = _ctx.requireId(); return DHTRecordDescriptor.fromJson(jsonDecode(await _wrapApiPromise(js_util .callMethod(wasm, 'routing_context_open_dht_record', [ @@ -163,21 +176,21 @@ class VeilidRoutingContextJS extends VeilidRoutingContext { } @override - Future closeDHTRecord(PublicKey key) { + Future closeDHTRecord(RecordKey key) { final id = _ctx.requireId(); return _wrapApiPromise(js_util.callMethod( wasm, 'routing_context_close_dht_record', [id, jsonEncode(key)])); } @override - Future deleteDHTRecord(PublicKey key) { + Future deleteDHTRecord(RecordKey key) { final id = _ctx.requireId(); return _wrapApiPromise(js_util.callMethod( wasm, 'routing_context_delete_dht_record', [id, jsonEncode(key)])); } @override - Future getDHTValue(PublicKey key, int subkey, + Future getDHTValue(RecordKey key, int subkey, {bool forceRefresh = false}) async { final id = _ctx.requireId(); final opt = await _wrapApiPromise(js_util.callMethod( @@ -192,7 +205,7 @@ class VeilidRoutingContextJS extends VeilidRoutingContext { } @override - Future setDHTValue(PublicKey key, int subkey, Uint8List data, + Future setDHTValue(RecordKey key, int subkey, Uint8List data, {SetDHTValueOptions? options}) async { final id = _ctx.requireId(); final opt = await _wrapApiPromise( @@ -211,10 +224,8 @@ class VeilidRoutingContextJS extends VeilidRoutingContext { } @override - Future watchDHTValues(PublicKey key, - {List? subkeys, - Timestamp? expiration, - int? count}) async { + Future watchDHTValues(RecordKey key, + {List? subkeys, Timestamp? expiration, int? count}) { subkeys ??= []; expiration ??= Timestamp.zero(); count ??= 0xFFFFFFFF; @@ -231,7 +242,7 @@ class VeilidRoutingContextJS extends VeilidRoutingContext { } @override - Future cancelDHTWatch(PublicKey key, + Future cancelDHTWatch(RecordKey key, {List? subkeys}) { subkeys ??= []; @@ -243,7 +254,7 @@ class VeilidRoutingContextJS extends VeilidRoutingContext { } @override - Future inspectDHTRecord(PublicKey key, + Future inspectDHTRecord(RecordKey key, {List? subkeys, DHTReportScope scope = DHTReportScope.local}) async { subkeys ??= []; @@ -296,10 +307,65 @@ class VeilidCryptoSystemJS extends VeilidCryptoSystem { base64UrlNoPadDecode(await _wrapApiPromise( js_util.callMethod(wasm, 'crypto_random_bytes', [_kind, len]))); + @override + Future sharedSecretLength() => _wrapApiPromise( + js_util.callMethod(wasm, 'crypto_shared_secret_length', [_kind])); + + @override + Future nonceLength() => + _wrapApiPromise(js_util.callMethod(wasm, 'crypto_nonce_length', [_kind])); + + @override + Future hashDigestLength() => _wrapApiPromise( + js_util.callMethod(wasm, 'crypto_hash_digest_length', [_kind])); + + @override + Future publicKeyLength() => _wrapApiPromise( + js_util.callMethod(wasm, 'crypto_public_key_length', [_kind])); + + @override + Future secretKeyLength() => _wrapApiPromise( + js_util.callMethod(wasm, 'crypto_secret_key_length', [_kind])); + + @override + Future signatureLength() => _wrapApiPromise( + js_util.callMethod(wasm, 'crypto_signature_length', [_kind])); + @override Future defaultSaltLength() => _wrapApiPromise( js_util.callMethod(wasm, 'crypto_default_salt_length', [_kind])); + @override + Future aeadOverhead() => _wrapApiPromise( + js_util.callMethod(wasm, 'crypto_aead_overhead', [_kind])); + + @override + Future checkSharedSecret(BareSharedSecret secret) => + _wrapApiPromise(js_util.callMethod( + wasm, 'crypto_check_shared_secret', [_kind, jsonEncode(secret)])); + + @override + Future checkNonce(BareNonce nonce) => _wrapApiPromise(js_util + .callMethod(wasm, 'crypto_check_nonce', [_kind, jsonEncode(nonce)])); + + @override + Future checkHashDigest(BareHashDigest digest) => + _wrapApiPromise(js_util.callMethod( + wasm, 'crypto_check_hash_digest', [_kind, jsonEncode(digest)])); + + @override + Future checkPublicKey(BarePublicKey key) => _wrapApiPromise(js_util + .callMethod(wasm, 'crypto_check_public_key', [_kind, jsonEncode(key)])); + + @override + Future checkSecretKey(BareSecretKey key) => _wrapApiPromise(js_util + .callMethod(wasm, 'crypto_check_secret_key', [_kind, jsonEncode(key)])); + + @override + Future checkSignature(BareSignature signature) => + _wrapApiPromise(js_util.callMethod( + wasm, 'crypto_check_signature', [_kind, jsonEncode(signature)])); + @override Future hashPassword(Uint8List password, Uint8List salt) => _wrapApiPromise(js_util.callMethod(wasm, 'crypto_hash_password', @@ -352,7 +418,8 @@ class VeilidCryptoSystemJS extends VeilidCryptoSystem { [_kind, base64UrlNoPadEncode(data), jsonEncode(hash)])); @override - Future distance(CryptoKey key1, CryptoKey key2) async => + Future distance( + BareHashDigest key1, BareHashDigest key2) async => BareHashDistance.fromJson(jsonDecode(await _wrapApiPromise(js_util .callMethod(wasm, 'crypto_distance', [_kind, jsonEncode(key1), jsonEncode(key2)])))); @@ -378,10 +445,6 @@ class VeilidCryptoSystemJS extends VeilidCryptoSystem { jsonEncode(signature), ])); - @override - Future aeadOverhead() => _wrapApiPromise( - js_util.callMethod(wasm, 'crypto_aead_overhead', [_kind])); - @override Future decryptAead(Uint8List body, BareNonce nonce, BareSharedSecret sharedSecret, Uint8List? associatedData) async => @@ -635,8 +698,8 @@ class VeilidJS extends Veilid { js_util.callMethod(wasm, 'get_veilid_state', [])))); @override - Future isShutdown() async => - await _wrapApiPromise(js_util.callMethod(wasm, 'is_shutdown', [])); + Future isShutdown() => + _wrapApiPromise(js_util.callMethod(wasm, 'is_shutdown', [])); @override Future attach() => @@ -698,6 +761,11 @@ class VeilidJS extends Veilid { return VeilidRoutingContextJS._(_Ctx(rcid, this)); } + @override + Future generateMemberId(PublicKey writerKey) async => + MemberId.fromJson(jsonDecode(await _wrapApiPromise(js_util + .callMethod(wasm, 'generate_member_id', [jsonEncode(writerKey)])))); + @override Future newPrivateRoute() async => RouteBlob.fromJson(jsonDecode(await _wrapApiPromise( @@ -715,15 +783,15 @@ class VeilidJS extends Veilid { } @override - Future importRemotePrivateRoute(Uint8List blob) { + Future importRemotePrivateRoute(Uint8List blob) async { final encodedBlob = base64UrlNoPadEncode(blob); - return _wrapApiPromise( - js_util.callMethod(wasm, 'import_remote_private_route', [encodedBlob])); + return RouteId.fromJson(jsonDecode(await _wrapApiPromise(js_util + .callMethod(wasm, 'import_remote_private_route', [encodedBlob])))); } @override - Future releasePrivateRoute(String routeId) => _wrapApiPromise( - js_util.callMethod(wasm, 'release_private_route', [routeId])); + Future releasePrivateRoute(RouteId routeId) => _wrapApiPromise( + js_util.callMethod(wasm, 'release_private_route', [jsonEncode(routeId)])); @override Future appCallReply(String callId, Uint8List message) { @@ -747,7 +815,7 @@ class VeilidJS extends Veilid { Timestamp now() => Timestamp.fromString(js_util.callMethod(wasm, 'now', [])); @override - Future debug(String command) async => + Future debug(String command) => _wrapApiPromise(js_util.callMethod(wasm, 'debug', [command])); @override diff --git a/veilid-flutter/lib/veilid_state.g.dart b/veilid-flutter/lib/veilid_state.g.dart index 3de9ec69..af6a65f4 100644 --- a/veilid-flutter/lib/veilid_state.g.dart +++ b/veilid-flutter/lib/veilid_state.g.dart @@ -195,7 +195,7 @@ Map _$PeerStatsToJson(_PeerStats instance) => _PeerTableData _$PeerTableDataFromJson(Map json) => _PeerTableData( nodeIds: (json['node_ids'] as List) - .map(Typed.fromJson) + .map(Typed.fromJson) .toList(), peerAddress: json['peer_address'] as String, peerStats: PeerStats.fromJson(json['peer_stats']), @@ -228,7 +228,7 @@ VeilidAppMessage _$VeilidAppMessageFromJson(Map json) => const Uint8ListJsonConverter.jsIsArray().fromJson(json['message']), sender: json['sender'] == null ? null - : Typed.fromJson(json['sender']), + : Typed.fromJson(json['sender']), routeId: json['route_id'] as String?, $type: json['kind'] as String?, ); @@ -249,7 +249,7 @@ VeilidAppCall _$VeilidAppCallFromJson(Map json) => callId: json['call_id'] as String, sender: json['sender'] == null ? null - : Typed.fromJson(json['sender']), + : Typed.fromJson(json['sender']), routeId: json['route_id'] as String?, $type: json['kind'] as String?, ); @@ -343,7 +343,7 @@ Map _$VeilidUpdateRouteChangeToJson( VeilidUpdateValueChange _$VeilidUpdateValueChangeFromJson( Map json) => VeilidUpdateValueChange( - key: Typed.fromJson(json['key']), + key: Typed.fromJson(json['key']), subkeys: (json['subkeys'] as List) .map(ValueSubkeyRange.fromJson) .toList(), diff --git a/veilid-flutter/packages/veilid_test/pubspec.yaml b/veilid-flutter/packages/veilid_test/pubspec.yaml index 19d7e6ea..df56eaba 100644 --- a/veilid-flutter/packages/veilid_test/pubspec.yaml +++ b/veilid-flutter/packages/veilid_test/pubspec.yaml @@ -9,7 +9,7 @@ environment: # Add regular dependencies here. dependencies: - async_tools: ^0.1.9 + async_tools: ^0.1.10 veilid: path: ../.. diff --git a/veilid-flutter/pubspec.yaml b/veilid-flutter/pubspec.yaml index 55b742f9..422a56e6 100644 --- a/veilid-flutter/pubspec.yaml +++ b/veilid-flutter/pubspec.yaml @@ -34,6 +34,7 @@ dev_dependencies: freezed: ^3.0.4 json_serializable: ^6.8.0 lint_hard: ^6.0.0 + test: ^1.25.15 # The following section is specific to Flutter. flutter: diff --git a/veilid-flutter/rust/src/dart_ffi.rs b/veilid-flutter/rust/src/dart_ffi.rs index b0addfae..8ec19e17 100644 --- a/veilid-flutter/rust/src/dart_ffi.rs +++ b/veilid-flutter/rust/src/dart_ffi.rs @@ -15,7 +15,7 @@ use std::sync::Arc; use tracing::*; use tracing_flame::FlameLayer; use tracing_subscriber::prelude::*; -use veilid_core::{tools::*, Encodable}; +use veilid_core::tools::*; // Detect flutter load/unload cfg_if! { @@ -135,7 +135,7 @@ pub struct VeilidFFIConfig { #[derive(Debug, Deserialize, Serialize)] pub struct VeilidFFIRouteBlob { - pub route_id: veilid_core::BareRouteId, + pub route_id: veilid_core::RouteId, #[serde(with = "veilid_core::as_human_base64")] pub blob: Vec, } @@ -639,7 +639,8 @@ pub extern "C" fn routing_context_safety(port: i64, id: u32) { #[no_mangle] #[instrument(level = "trace", target = "ffi", skip_all)] pub extern "C" fn routing_context_app_call(port: i64, id: u32, target: FfiStr, request: FfiStr) { - let target_string: String = target.into_opt_string().unwrap(); + let target: veilid_core::Target = + veilid_core::deserialize_opt_json(target.into_opt_string()).unwrap(); let request: Vec = data_encoding::BASE64URL_NOPAD .decode(request.into_opt_string().unwrap().as_bytes()) .unwrap(); @@ -647,8 +648,6 @@ pub extern "C" fn routing_context_app_call(port: i64, id: u32, target: FfiStr, r async move { let routing_context = get_routing_context(id, "routing_context_app_call")?; - let veilid_api = get_veilid_api().await?; - let target = veilid_api.parse_as_target(target_string)?; let answer = routing_context.app_call(target, request).await?; let answer = data_encoding::BASE64URL_NOPAD.encode(&answer); APIResult::Ok(answer) @@ -660,7 +659,8 @@ pub extern "C" fn routing_context_app_call(port: i64, id: u32, target: FfiStr, r #[no_mangle] #[instrument(level = "trace", target = "ffi", skip_all)] pub extern "C" fn routing_context_app_message(port: i64, id: u32, target: FfiStr, message: FfiStr) { - let target_string: String = target.into_opt_string().unwrap(); + let target: veilid_core::Target = + veilid_core::deserialize_opt_json(target.into_opt_string()).unwrap(); let message: Vec = data_encoding::BASE64URL_NOPAD .decode(message.into_opt_string().unwrap().as_bytes()) .unwrap(); @@ -668,8 +668,6 @@ pub extern "C" fn routing_context_app_message(port: i64, id: u32, target: FfiStr async move { let routing_context = get_routing_context(id, "routing_context_app_message")?; - let veilid_api = get_veilid_api().await?; - let target = veilid_api.parse_as_target(target_string)?; routing_context.app_message(target, message).await?; APIRESULT_VOID } @@ -677,6 +675,30 @@ pub extern "C" fn routing_context_app_message(port: i64, id: u32, target: FfiStr ); } +#[no_mangle] +#[instrument(level = "trace", target = "ffi", skip_all)] +pub extern "C" fn routing_context_get_dht_record_key( + port: i64, + id: u32, + schema: FfiStr, + owner: FfiStr, +) { + let schema: veilid_core::DHTSchema = + veilid_core::deserialize_opt_json(schema.into_opt_string()).unwrap(); + let owner: veilid_core::PublicKey = + veilid_core::deserialize_opt_json(owner.into_opt_string()).unwrap(); + + DartIsolateWrapper::new(port).spawn_result_json( + async move { + let routing_context = get_routing_context(id, "routing_context_get_dht_record_key")?; + + let record_key = routing_context.get_dht_record_key(schema, &owner)?; + APIResult::Ok(record_key) + } + .in_current_span(), + ); +} + #[no_mangle] #[instrument(level = "trace", target = "ffi", skip_all)] pub extern "C" fn routing_context_create_dht_record( @@ -693,7 +715,7 @@ pub extern "C" fn routing_context_create_dht_record( }; let schema: veilid_core::DHTSchema = veilid_core::deserialize_opt_json(schema.into_opt_string()).unwrap(); - let owner: Option = owner + let owner: Option = owner .into_opt_string() .map(|s| veilid_core::deserialize_json(&s).unwrap()); @@ -715,7 +737,7 @@ pub extern "C" fn routing_context_create_dht_record( pub extern "C" fn routing_context_open_dht_record(port: i64, id: u32, key: FfiStr, writer: FfiStr) { let key: veilid_core::RecordKey = veilid_core::deserialize_opt_json(key.into_opt_string()).unwrap(); - let writer: Option = writer + let writer: Option = writer .into_opt_string() .map(|s| veilid_core::deserialize_json(&s).unwrap()); DartIsolateWrapper::new(port).spawn_result_json( @@ -899,6 +921,24 @@ pub extern "C" fn routing_context_inspect_dht_record( ); } +#[no_mangle] +#[instrument(level = "trace", target = "ffi", skip_all)] +pub extern "C" fn generate_member_id(port: i64, writer_key: FfiStr) { + let writer_key: veilid_core::PublicKey = + veilid_core::deserialize_opt_json(writer_key.into_opt_string()).unwrap(); + + DartIsolateWrapper::new(port).spawn_result_json( + async move { + let veilid_api = get_veilid_api().await?; + + let member_id = veilid_api.generate_member_id(&writer_key)?; + + APIResult::Ok(member_id) + } + .in_current_span(), + ); +} + #[no_mangle] #[instrument(level = "trace", target = "ffi", skip_all)] pub extern "C" fn new_private_route(port: i64) { @@ -946,12 +986,11 @@ pub extern "C" fn import_remote_private_route(port: i64, blob: FfiStr) { let blob: Vec = data_encoding::BASE64URL_NOPAD .decode(blob.into_opt_string().unwrap().as_bytes()) .unwrap(); - DartIsolateWrapper::new(port).spawn_result( + DartIsolateWrapper::new(port).spawn_result_json( async move { let veilid_api = get_veilid_api().await?; - let route_id = veilid_api.import_remote_private_route(blob)?.encode(); - + let route_id = veilid_api.import_remote_private_route(blob)?; APIResult::Ok(route_id) } .in_current_span(), @@ -961,7 +1000,9 @@ pub extern "C" fn import_remote_private_route(port: i64, blob: FfiStr) { #[no_mangle] #[instrument(level = "trace", target = "ffi", skip_all)] pub extern "C" fn release_private_route(port: i64, route_id: FfiStr) { - let route_id = veilid_core::BareRouteId::try_decode(route_id.into_string()).unwrap(); + let route_id: veilid_core::RouteId = + veilid_core::deserialize_opt_json(route_id.into_opt_string()).unwrap(); + DartIsolateWrapper::new(port).spawn_result( async move { let veilid_api = get_veilid_api().await?; @@ -1325,7 +1366,7 @@ pub extern "C" fn generate_signatures(port: i64, data: FfiStr, key_pairs: FfiStr let veilid_api = get_veilid_api().await?; let crypto = veilid_api.crypto()?; let out = crypto.generate_signatures(&data, &key_pairs, |k, s| { - veilid_core::Signature::new(k.kind, s) + veilid_core::Signature::new(k.kind(), s) })?; APIResult::Ok(out) } @@ -1463,6 +1504,144 @@ pub extern "C" fn crypto_random_bytes(port: i64, kind: u32, len: u32) { ); } +#[no_mangle] +#[instrument(level = "trace", target = "ffi", skip_all)] +pub extern "C" fn crypto_shared_secret_length(port: i64, kind: u32) { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + + DartIsolateWrapper::new(port).spawn_result( + async move { + let veilid_api = get_veilid_api().await?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_shared_secret_length", + "kind", + kind.to_string(), + ) + })?; + let out = csv.shared_secret_length(); + APIResult::Ok(out) + } + .in_current_span(), + ); +} + +#[no_mangle] +#[instrument(level = "trace", target = "ffi", skip_all)] +pub extern "C" fn crypto_nonce_length(port: i64, kind: u32) { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + + DartIsolateWrapper::new(port).spawn_result( + async move { + let veilid_api = get_veilid_api().await?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_nonce_length", + "kind", + kind.to_string(), + ) + })?; + let out = csv.nonce_length(); + APIResult::Ok(out) + } + .in_current_span(), + ); +} + +#[no_mangle] +#[instrument(level = "trace", target = "ffi", skip_all)] +pub extern "C" fn crypto_hash_digest_length(port: i64, kind: u32) { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + + DartIsolateWrapper::new(port).spawn_result( + async move { + let veilid_api = get_veilid_api().await?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_hash_digest_length", + "kind", + kind.to_string(), + ) + })?; + let out = csv.hash_digest_length(); + APIResult::Ok(out) + } + .in_current_span(), + ); +} + +#[no_mangle] +#[instrument(level = "trace", target = "ffi", skip_all)] +pub extern "C" fn crypto_public_key_length(port: i64, kind: u32) { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + + DartIsolateWrapper::new(port).spawn_result( + async move { + let veilid_api = get_veilid_api().await?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_public_key_length", + "kind", + kind.to_string(), + ) + })?; + let out = csv.public_key_length(); + APIResult::Ok(out) + } + .in_current_span(), + ); +} + +#[no_mangle] +#[instrument(level = "trace", target = "ffi", skip_all)] +pub extern "C" fn crypto_secret_key_length(port: i64, kind: u32) { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + + DartIsolateWrapper::new(port).spawn_result( + async move { + let veilid_api = get_veilid_api().await?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_secret_key_length", + "kind", + kind.to_string(), + ) + })?; + let out = csv.secret_key_length(); + APIResult::Ok(out) + } + .in_current_span(), + ); +} + +#[no_mangle] +#[instrument(level = "trace", target = "ffi", skip_all)] +pub extern "C" fn crypto_signature_length(port: i64, kind: u32) { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + + DartIsolateWrapper::new(port).spawn_result( + async move { + let veilid_api = get_veilid_api().await?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_signature_length", + "kind", + kind.to_string(), + ) + })?; + let out = csv.signature_length(); + APIResult::Ok(out) + } + .in_current_span(), + ); +} + #[no_mangle] #[instrument(level = "trace", target = "ffi", skip_all)] pub extern "C" fn crypto_default_salt_length(port: i64, kind: u32) { @@ -1486,6 +1665,179 @@ pub extern "C" fn crypto_default_salt_length(port: i64, kind: u32) { ); } +#[no_mangle] +#[instrument(level = "trace", target = "ffi", skip_all)] +pub extern "C" fn crypto_aead_overhead(port: i64, kind: u32) { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + + DartIsolateWrapper::new(port).spawn_result( + async move { + let veilid_api = get_veilid_api().await?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_aead_overhead", + "kind", + kind.to_string(), + ) + })?; + let out = csv.aead_overhead(); + APIResult::Ok(out) + } + .in_current_span(), + ); +} + +#[no_mangle] +#[instrument(level = "trace", target = "ffi", skip_all)] +pub extern "C" fn crypto_check_shared_secret(port: i64, kind: u32, secret: FfiStr) { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + let secret: veilid_core::BareSharedSecret = + veilid_core::deserialize_opt_json(secret.into_opt_string()).unwrap(); + + DartIsolateWrapper::new(port).spawn_result( + async move { + let veilid_api = get_veilid_api().await?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_check_shared_secret", + "kind", + kind.to_string(), + ) + })?; + csv.check_shared_secret(&secret)?; + APIRESULT_VOID + } + .in_current_span(), + ); +} + +#[no_mangle] +#[instrument(level = "trace", target = "ffi", skip_all)] +pub extern "C" fn crypto_check_nonce(port: i64, kind: u32, nonce: FfiStr) { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + let nonce: veilid_core::BareNonce = + veilid_core::deserialize_opt_json(nonce.into_opt_string()).unwrap(); + + DartIsolateWrapper::new(port).spawn_result( + async move { + let veilid_api = get_veilid_api().await?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_check_nonce", + "kind", + kind.to_string(), + ) + })?; + csv.check_nonce(&nonce)?; + APIRESULT_VOID + } + .in_current_span(), + ); +} + +#[no_mangle] +#[instrument(level = "trace", target = "ffi", skip_all)] +pub extern "C" fn crypto_check_hash_digest(port: i64, kind: u32, digest: FfiStr) { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + let digest: veilid_core::BareHashDigest = + veilid_core::deserialize_opt_json(digest.into_opt_string()).unwrap(); + + DartIsolateWrapper::new(port).spawn_result( + async move { + let veilid_api = get_veilid_api().await?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_check_hash_digest", + "kind", + kind.to_string(), + ) + })?; + csv.check_hash_digest(&digest)?; + APIRESULT_VOID + } + .in_current_span(), + ); +} + +#[no_mangle] +#[instrument(level = "trace", target = "ffi", skip_all)] +pub extern "C" fn crypto_check_public_key(port: i64, kind: u32, key: FfiStr) { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + let key: veilid_core::BarePublicKey = + veilid_core::deserialize_opt_json(key.into_opt_string()).unwrap(); + + DartIsolateWrapper::new(port).spawn_result( + async move { + let veilid_api = get_veilid_api().await?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_check_public_key", + "kind", + kind.to_string(), + ) + })?; + csv.check_public_key(&key)?; + APIRESULT_VOID + } + .in_current_span(), + ); +} + +#[no_mangle] +#[instrument(level = "trace", target = "ffi", skip_all)] +pub extern "C" fn crypto_check_secret_key(port: i64, kind: u32, key: FfiStr) { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + let key: veilid_core::BareSecretKey = + veilid_core::deserialize_opt_json(key.into_opt_string()).unwrap(); + + DartIsolateWrapper::new(port).spawn_result( + async move { + let veilid_api = get_veilid_api().await?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_check_secret_key", + "kind", + kind.to_string(), + ) + })?; + csv.check_secret_key(&key)?; + APIRESULT_VOID + } + .in_current_span(), + ); +} + +#[no_mangle] +#[instrument(level = "trace", target = "ffi", skip_all)] +pub extern "C" fn crypto_check_signature(port: i64, kind: u32, signature: FfiStr) { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + let signature: veilid_core::BareSignature = + veilid_core::deserialize_opt_json(signature.into_opt_string()).unwrap(); + + DartIsolateWrapper::new(port).spawn_result( + async move { + let veilid_api = get_veilid_api().await?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_check_signature", + "kind", + kind.to_string(), + ) + })?; + csv.check_signature(&signature)?; + APIRESULT_VOID + } + .in_current_span(), + ); +} + #[no_mangle] #[instrument(level = "trace", target = "ffi", skip_all)] pub extern "C" fn crypto_hash_password(port: i64, kind: u32, password: FfiStr, salt: FfiStr) { @@ -1831,29 +2183,6 @@ pub extern "C" fn crypto_verify( ); } -#[no_mangle] -#[instrument(level = "trace", target = "ffi", skip_all)] -pub extern "C" fn crypto_aead_overhead(port: i64, kind: u32) { - let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); - - DartIsolateWrapper::new(port).spawn_result( - async move { - let veilid_api = get_veilid_api().await?; - let crypto = veilid_api.crypto()?; - let csv = crypto.get(kind).ok_or_else(|| { - veilid_core::VeilidAPIError::invalid_argument( - "crypto_aead_overhead", - "kind", - kind.to_string(), - ) - })?; - let out = csv.aead_overhead(); - APIResult::Ok(out) - } - .in_current_span(), - ); -} - #[no_mangle] #[instrument(level = "trace", target = "ffi", skip_all)] pub extern "C" fn crypto_decrypt_aead( @@ -1992,7 +2321,7 @@ pub extern "C" fn crypto_crypt_no_auth( kind.to_string(), ) })?; - csv.crypt_in_place_no_auth(&mut body, &nonce, &shared_secret); + csv.crypt_in_place_no_auth(&mut body, &nonce, &shared_secret)?; let body = data_encoding::BASE64URL_NOPAD.encode(&body); APIResult::Ok(body) } diff --git a/veilid-python/tests/test_dht.py b/veilid-python/tests/test_dht.py index fe2f8b00..212f8a7b 100644 --- a/veilid-python/tests/test_dht.py +++ b/veilid-python/tests/test_dht.py @@ -10,14 +10,14 @@ from veilid import ValueSubkey, Timestamp, SafetySelection from veilid.types import ValueSeqNum, VeilidJSONEncoder ################################################################## -BOGUS_KEY = veilid.PublicKey.from_value( - veilid.CryptoKind.CRYPTO_KIND_VLD0, veilid.BarePublicKey.from_bytes(b' ')) +BOGUS_KEY = veilid.RecordKey.from_value( + veilid.CryptoKind.CRYPTO_KIND_VLD0, veilid.BareRecordKey.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): await rc.get_dht_value(BOGUS_KEY, ValueSubkey(0), False) @@ -102,10 +102,17 @@ async def test_set_get_dht_value_with_owner(api_connection: veilid.VeilidAPI): cs = await api_connection.best_crypto_system() async with cs: - owner = await cs.generate_key_pair() + owner = veilid.KeyPair.from_value(await cs.kind(), await cs.generate_key_pair()) + + record_key = await rc.get_dht_record_key(veilid.DHTSchema.dflt(2), owner = owner.key()) rec = await rc.create_dht_record(veilid.DHTSchema.dflt(2), owner=owner) + assert rec.key == record_key + assert rec.owner == owner.key() + assert rec.owner_secret is not None + assert rec.owner_secret == owner.secret().value() + vd = await rc.set_dht_value(rec.key, ValueSubkey(0), b"BLAH BLAH BLAH") assert vd is None @@ -132,54 +139,56 @@ async def test_open_writer_dht_value(api_connection: veilid.VeilidAPI): rc = await api_connection.new_routing_context() async with rc: rec = await rc.create_dht_record(veilid.DHTSchema.dflt(2)) - key = rec.key + record_key = rec.key owner = rec.owner secret = rec.owner_secret assert secret is not None + owner_keypair = rec.owner_key_pair() + assert owner_keypair != None + assert owner_keypair.key() == owner + assert owner_keypair.secret().value() == secret - #print(f"key:{key}") - - cs = await api_connection.get_crypto_system(rec.key.kind()) + cs = await api_connection.get_crypto_system(owner.kind()) async with cs: - assert await cs.validate_key_pair(owner, secret) - other_keypair = await cs.generate_key_pair() + assert await cs.validate_key_pair(owner.value(), secret) + other_keypair = veilid.KeyPair.from_value(await cs.kind(), await cs.generate_key_pair()) va = b"Qwertyuiop Asdfghjkl Zxcvbnm" vb = b"1234567890" vc = b"!@#$%^&*()" # Test subkey writes - vdtemp = await rc.set_dht_value(key, ValueSubkey(1), va) + vdtemp = await rc.set_dht_value(record_key, ValueSubkey(1), va) assert vdtemp is None - vdtemp = await rc.get_dht_value(key, ValueSubkey(1), False) + vdtemp = await rc.get_dht_value(record_key, ValueSubkey(1), False) assert vdtemp is not None assert vdtemp.data == va assert vdtemp.seq == 0 assert vdtemp.writer == owner - vdtemp = await rc.get_dht_value(key, ValueSubkey(0), False) + vdtemp = await rc.get_dht_value(record_key, ValueSubkey(0), False) assert vdtemp is None - vdtemp = await rc.set_dht_value(key, ValueSubkey(0), vb) + vdtemp = await rc.set_dht_value(record_key, ValueSubkey(0), vb) assert vdtemp is None await sync(rc, [rec]) - vdtemp = await rc.get_dht_value(key, ValueSubkey(0), True) + vdtemp = await rc.get_dht_value(record_key, ValueSubkey(0), True) assert vdtemp is not None assert vdtemp.data == vb - vdtemp = await rc.get_dht_value(key, ValueSubkey(1), True) + vdtemp = await rc.get_dht_value(record_key, ValueSubkey(1), True) assert vdtemp is not None assert vdtemp.data == va # Equal value should not trigger sequence number update - vdtemp = await rc.set_dht_value(key, ValueSubkey(1), va) + vdtemp = await rc.set_dht_value(record_key, ValueSubkey(1), va) assert vdtemp is None # Different value should trigger sequence number update - vdtemp = await rc.set_dht_value(key, ValueSubkey(1), vb) + vdtemp = await rc.set_dht_value(record_key, ValueSubkey(1), vb) assert vdtemp is None # Now that we initialized some subkeys @@ -188,32 +197,32 @@ async def test_open_writer_dht_value(api_connection: veilid.VeilidAPI): # with the same writer key await sync(rc, [rec]) - await rc.close_dht_record(key) - await rc.delete_dht_record(key) + await rc.close_dht_record(record_key) + await rc.delete_dht_record(record_key) - rec = await rc.open_dht_record(key, veilid.BareKeyPair.from_parts(owner, secret)) + rec = await rc.open_dht_record(record_key, rec.owner_key_pair()) assert rec is not None - assert rec.key == key + assert rec.key == record_key assert rec.owner == owner assert rec.owner_secret == secret assert isinstance(rec.schema, veilid.DHTSchemaDFLT) assert rec.schema.o_cnt == 2 # Verify subkey 1 can be set before it is get but newer is available online - vdtemp = await rc.set_dht_value(key, ValueSubkey(1), vc) + vdtemp = await rc.set_dht_value(record_key, ValueSubkey(1), vc) assert vdtemp is not None assert vdtemp.data == vb assert vdtemp.seq == 1 assert vdtemp.writer == owner # Verify subkey 1 can be set a second time and it updates because seq is newer - vdtemp = await rc.set_dht_value(key, ValueSubkey(1), vc) + vdtemp = await rc.set_dht_value(record_key, ValueSubkey(1), vc) assert vdtemp is None await sync(rc, [rec]) # Verify the network got the subkey update with a refresh check - vdtemp = await rc.get_dht_value(key, ValueSubkey(1), True) + vdtemp = await rc.get_dht_value(record_key, ValueSubkey(1), True) assert vdtemp is not None assert vdtemp.data == vc assert vdtemp.seq == 2 @@ -222,12 +231,12 @@ async def test_open_writer_dht_value(api_connection: veilid.VeilidAPI): # Delete things locally and reopen and see if we can write # with a different writer key (should fail) - await rc.close_dht_record(key) - await rc.delete_dht_record(key) + await rc.close_dht_record(record_key) + await rc.delete_dht_record(record_key) - rec = await rc.open_dht_record(key, other_keypair) + rec = await rc.open_dht_record(record_key, other_keypair) assert rec is not None - assert rec.key == key + assert rec.key == record_key assert rec.owner == owner assert rec.owner_secret is None assert isinstance(rec.schema, veilid.DHTSchemaDFLT) @@ -235,27 +244,27 @@ async def test_open_writer_dht_value(api_connection: veilid.VeilidAPI): # Verify subkey 1 can NOT be set because we have the wrong writer with pytest.raises(veilid.VeilidAPIError): - await rc.set_dht_value(key, ValueSubkey(1), va) + await rc.set_dht_value(record_key, ValueSubkey(1), va) # Verify subkey 0 can NOT be set because we have the wrong writer with pytest.raises(veilid.VeilidAPIError): - await rc.set_dht_value(key, ValueSubkey(0), va) + await rc.set_dht_value(record_key, ValueSubkey(0), va) # Verify subkey 0 can be set because override with the right writer # Should have prior sequence number as its returned value because it exists online at seq 0 - vdtemp = await rc.set_dht_value(key, ValueSubkey(0), va, veilid.SetDHTValueOptions(veilid.BareKeyPair.from_parts(owner, secret))) + vdtemp = await rc.set_dht_value(record_key, ValueSubkey(0), va, veilid.SetDHTValueOptions(writer=owner_keypair)) assert vdtemp is not None assert vdtemp.data == vb assert vdtemp.seq == 0 assert vdtemp.writer == owner # Should update the second time to seq 1 - vdtemp = await rc.set_dht_value(key, ValueSubkey(0), va, veilid.SetDHTValueOptions(veilid.BareKeyPair.from_parts(owner, secret))) + vdtemp = await rc.set_dht_value(record_key, ValueSubkey(0), va, veilid.SetDHTValueOptions(writer=owner_keypair)) assert vdtemp is None # Clean up - await rc.close_dht_record(key) - await rc.delete_dht_record(key) + await rc.close_dht_record(record_key) + await rc.delete_dht_record(record_key) @pytest.mark.asyncio @@ -263,51 +272,54 @@ async def test_open_writer_dht_value_no_offline(api_connection: veilid.VeilidAPI rc = await api_connection.new_routing_context() async with rc: rec = await rc.create_dht_record(veilid.DHTSchema.dflt(2)) - key = rec.key + record_key = rec.key owner = rec.owner secret = rec.owner_secret assert secret is not None - #print(f"key:{key}") + owner_keypair = rec.owner_key_pair() + assert owner_keypair != None + assert owner_keypair.key() == owner + assert owner_keypair.secret().value() == secret cs = await api_connection.get_crypto_system(rec.key.kind()) async with cs: - assert await cs.validate_key_pair(owner, secret) - other_keypair = await cs.generate_key_pair() + assert await cs.validate_key_pair(owner.value(), secret) + other_keypair = veilid.KeyPair.from_value(await cs.kind(), await cs.generate_key_pair()) va = b"Qwertyuiop Asdfghjkl Zxcvbnm" vb = b"1234567890" vc = b"!@#$%^&*()" # Test subkey writes - vdtemp = await rc.set_dht_value(key, ValueSubkey(1), va, veilid.SetDHTValueOptions(None, False)) + vdtemp = await rc.set_dht_value(record_key, ValueSubkey(1), va, veilid.SetDHTValueOptions(None, False)) assert vdtemp is None - vdtemp = await rc.get_dht_value(key, ValueSubkey(1), False) + vdtemp = await rc.get_dht_value(record_key, ValueSubkey(1), False) assert vdtemp is not None assert vdtemp.data == va assert vdtemp.seq == 0 assert vdtemp.writer == owner - vdtemp = await rc.get_dht_value(key, ValueSubkey(0), False) + vdtemp = await rc.get_dht_value(record_key, ValueSubkey(0), False) assert vdtemp is None - vdtemp = await rc.set_dht_value(key, ValueSubkey(0), vb, veilid.SetDHTValueOptions(None, False)) + vdtemp = await rc.set_dht_value(record_key, ValueSubkey(0), vb, veilid.SetDHTValueOptions(None, False)) assert vdtemp is None - vdtemp = await rc.get_dht_value(key, ValueSubkey(0), True) + vdtemp = await rc.get_dht_value(record_key, ValueSubkey(0), True) assert vdtemp is not None assert vdtemp.data == vb - vdtemp = await rc.get_dht_value(key, ValueSubkey(1), True) + vdtemp = await rc.get_dht_value(record_key, ValueSubkey(1), True) assert vdtemp is not None assert vdtemp.data == va # Equal value should not trigger sequence number update - vdtemp = await rc.set_dht_value(key, ValueSubkey(1), va, veilid.SetDHTValueOptions(None, False)) + vdtemp = await rc.set_dht_value(record_key, ValueSubkey(1), va, veilid.SetDHTValueOptions(None, False)) assert vdtemp is None # Different value should trigger sequence number update - vdtemp = await rc.set_dht_value(key, ValueSubkey(1), vb, veilid.SetDHTValueOptions(None, False)) + vdtemp = await rc.set_dht_value(record_key, ValueSubkey(1), vb, veilid.SetDHTValueOptions(None, False)) assert vdtemp is None # Now that we initialized some subkeys @@ -315,30 +327,30 @@ async def test_open_writer_dht_value_no_offline(api_connection: veilid.VeilidAPI # Delete things locally and reopen and see if we can write # with the same writer key - await rc.close_dht_record(key) - await rc.delete_dht_record(key) + await rc.close_dht_record(record_key) + await rc.delete_dht_record(record_key) - rec = await rc.open_dht_record(key, veilid.BareKeyPair.from_parts(owner, secret)) + rec = await rc.open_dht_record(record_key, rec.owner_key_pair()) assert rec is not None - assert rec.key == key + assert rec.key == record_key assert rec.owner == owner assert rec.owner_secret == secret assert isinstance(rec.schema, veilid.DHTSchemaDFLT) assert rec.schema.o_cnt == 2 # Verify subkey 1 can be set before it is get but newer is available online - vdtemp = await rc.set_dht_value(key, ValueSubkey(1), vc, veilid.SetDHTValueOptions(None, False)) + vdtemp = await rc.set_dht_value(record_key, ValueSubkey(1), vc, veilid.SetDHTValueOptions(None, False)) assert vdtemp is not None assert vdtemp.data == vb assert vdtemp.seq == 1 assert vdtemp.writer == owner # Verify subkey 1 can be set a second time and it updates because seq is newer - vdtemp = await rc.set_dht_value(key, ValueSubkey(1), vc, veilid.SetDHTValueOptions(None, False)) + vdtemp = await rc.set_dht_value(record_key, ValueSubkey(1), vc, veilid.SetDHTValueOptions(None, False)) assert vdtemp is None # Verify the network got the subkey update with a refresh check - vdtemp = await rc.get_dht_value(key, ValueSubkey(1), True) + vdtemp = await rc.get_dht_value(record_key, ValueSubkey(1), True) assert vdtemp is not None assert vdtemp.data == vc assert vdtemp.seq == 2 @@ -347,12 +359,12 @@ async def test_open_writer_dht_value_no_offline(api_connection: veilid.VeilidAPI # Delete things locally and reopen and see if we can write # with a different writer key (should fail) - await rc.close_dht_record(key) - await rc.delete_dht_record(key) + await rc.close_dht_record(record_key) + await rc.delete_dht_record(record_key) - rec = await rc.open_dht_record(key, other_keypair) + rec = await rc.open_dht_record(record_key, other_keypair) assert rec is not None - assert rec.key == key + assert rec.key == record_key assert rec.owner == owner assert rec.owner_secret is None assert isinstance(rec.schema, veilid.DHTSchemaDFLT) @@ -360,27 +372,27 @@ async def test_open_writer_dht_value_no_offline(api_connection: veilid.VeilidAPI # Verify subkey 1 can NOT be set because we have the wrong writer with pytest.raises(veilid.VeilidAPIError): - await rc.set_dht_value(key, ValueSubkey(1), va, veilid.SetDHTValueOptions(None, False)) + await rc.set_dht_value(record_key, ValueSubkey(1), va, veilid.SetDHTValueOptions(None, False)) # Verify subkey 0 can NOT be set because we have the wrong writer with pytest.raises(veilid.VeilidAPIError): - await rc.set_dht_value(key, ValueSubkey(0), va, veilid.SetDHTValueOptions(None, False)) + await rc.set_dht_value(record_key, ValueSubkey(0), va, veilid.SetDHTValueOptions(None, False)) # Verify subkey 0 can be set because override with the right writer # Should have prior sequence number as its returned value because it exists online at seq 0 - vdtemp = await rc.set_dht_value(key, ValueSubkey(0), va, veilid.SetDHTValueOptions(veilid.BareKeyPair.from_parts(owner, secret), False)) + vdtemp = await rc.set_dht_value(record_key, ValueSubkey(0), va, veilid.SetDHTValueOptions(writer=owner_keypair, allow_offline=False)) assert vdtemp is not None assert vdtemp.data == vb assert vdtemp.seq == 0 assert vdtemp.writer == owner # Should update the second time to seq 1 - vdtemp = await rc.set_dht_value(key, ValueSubkey(0), va, veilid.SetDHTValueOptions(veilid.BareKeyPair.from_parts(owner, secret), False)) + vdtemp = await rc.set_dht_value(record_key, ValueSubkey(0), va, veilid.SetDHTValueOptions(writer=owner_keypair, allow_offline=False)) assert vdtemp is None # Clean up - await rc.close_dht_record(key) - await rc.delete_dht_record(key) + await rc.close_dht_record(record_key) + await rc.delete_dht_record(record_key) @@ -682,7 +694,7 @@ async def test_inspect_dht_record(api_connection: veilid.VeilidAPI): -async def _run_test_schema_limit(api_connection: veilid.VeilidAPI, open_record: Callable[[veilid.RoutingContext, int], Awaitable[tuple[veilid.DHTRecordDescriptor, Optional[veilid.BareKeyPair]]]], count: int, test_data: bytes): +async def _run_test_schema_limit(api_connection: veilid.VeilidAPI, open_record: Callable[[veilid.RoutingContext, int], Awaitable[tuple[veilid.DHTRecordDescriptor, Optional[veilid.KeyPair]]]], count: int, test_data: bytes): rc = await api_connection.new_routing_context() async with rc: (desc, writer) = await open_record(rc, count) @@ -712,7 +724,7 @@ async def _run_test_schema_limit(api_connection: veilid.VeilidAPI, open_record: @pytest.mark.asyncio async def test_schema_limit_dflt(api_connection: veilid.VeilidAPI): - async def open_record(rc: veilid.RoutingContext, count: int) -> tuple[veilid.DHTRecordDescriptor, Optional[veilid.BareKeyPair]]: + async def open_record(rc: veilid.RoutingContext, count: int) -> tuple[veilid.DHTRecordDescriptor, Optional[veilid.KeyPair]]: schema = veilid.DHTSchema.dflt(count) desc = await rc.create_dht_record(schema) return (desc, desc.owner_key_pair()) @@ -744,12 +756,12 @@ async def test_schema_limit_dflt(api_connection: veilid.VeilidAPI): @pytest.mark.asyncio async def test_schema_limit_smpl(api_connection: veilid.VeilidAPI): - async def open_record(rc: veilid.RoutingContext, count: int) -> tuple[veilid.DHTRecordDescriptor, veilid.BareKeyPair]: + async def open_record(rc: veilid.RoutingContext, count: int) -> tuple[veilid.DHTRecordDescriptor, veilid.KeyPair]: cs = await api_connection.best_crypto_system() async with cs: - writer_keypair = await cs.generate_key_pair() - - schema = veilid.DHTSchema.smpl(0, [veilid.DHTSchemaSMPLMember(writer_keypair.key(), count)]) + writer_keypair = veilid.KeyPair.from_value(await cs.kind(), await cs.generate_key_pair()) + writer_id = await api_connection.generate_member_id(writer_keypair.key()) + schema = veilid.DHTSchema.smpl(0, [veilid.DHTSchemaSMPLMember(writer_id.value(), count)]) desc = await rc.create_dht_record(schema) await rc.open_dht_record(desc.key, writer_keypair) @@ -782,9 +794,9 @@ async def test_schema_limit_smpl(api_connection: veilid.VeilidAPI): @pytest.mark.skipif(os.getenv("INTEGRATION") != "1", reason="integration test requires two servers running") @pytest.mark.asyncio async def test_dht_integration_writer_reader(): - + async def null_update_callback(update: veilid.VeilidUpdate): - pass + pass try: api0 = await veilid.api_connector(null_update_callback, 0) @@ -818,7 +830,7 @@ async def test_dht_integration_writer_reader(): for n in range(COUNT): desc = await rc0.create_dht_record(schema) records.append(desc) - print(f' {n}: key={desc.key} owner={desc.owner_key_pair()}') + print(f' {n}: key={desc.key} owner={desc.owner_bare_key_pair()}') await rc0.set_dht_value(desc.key, ValueSubkey(0), TEST_DATA) @@ -836,13 +848,13 @@ async def test_dht_integration_writer_reader(): assert vd1 is not None assert vd1.data == TEST_DATA await rc1.close_dht_record(desc1.key) - + @pytest.mark.skipif(os.getenv("STRESS") != "1", reason="stress test takes a long time") @pytest.mark.asyncio async def test_dht_write_read_local(): - + async def null_update_callback(update: veilid.VeilidUpdate): pass @@ -855,7 +867,7 @@ async def test_dht_write_read_local(): # purge local and remote record stores to ensure we start fresh await api0.debug("record purge local") await api0.debug("record purge remote") - + # make routing contexts rc0 = await api0.new_routing_context() async with rc0: @@ -878,7 +890,7 @@ async def test_dht_write_read_local(): await rc0.set_dht_value(desc.key, ValueSubkey(1), TEST_DATA2) print(f' {n}: {desc.key} {desc.owner}:{desc.owner_secret}') - + await sync(rc0, records) for desc0 in records: @@ -892,16 +904,16 @@ async def test_dht_write_read_local(): n = 0 for desc0 in records: desc1 = await rc0.open_dht_record(desc0.key) - + vd0 = await rc0.get_dht_value(desc1.key, ValueSubkey(0), force_refresh=True) assert vd0 is not None assert vd0.data == TEST_DATA - + vd1 = await rc0.get_dht_value(desc1.key, ValueSubkey(1), force_refresh=True) assert vd1 is not None assert vd1.data == TEST_DATA2 await rc0.close_dht_record(desc1.key) - + print(f' {n}') n += 1 @@ -1048,13 +1060,13 @@ async def sync_win( # Record inspection and completion state # Records we are done inspecting and have finished sync - donerecords: set[veilid.PublicKey] = set() + donerecords: set[veilid.RecordKey] = set() # Records we are currently inspecting that are in the futures set - futurerecords: set[veilid.PublicKey] = set() + futurerecords: set[veilid.RecordKey] = set() # All the futures we are waiting for futures = set() # The record report state - recordreports: dict[veilid.PublicKey, veilid.DHTRecordReport] = dict() + recordreports: dict[veilid.RecordKey, veilid.DHTRecordReport] = dict() # Add initial futures with None key for fut in init_futures: @@ -1069,7 +1081,7 @@ async def sync_win( for n, desc in enumerate(records): if desc.key in donerecords or desc.key in futurerecords: continue - async def _do_inspect(key: veilid.PublicKey): + async def _do_inspect(key: veilid.RecordKey): return (key, await rc.inspect_dht_record(key, [])) futures.add(asyncio.create_task(_do_inspect(desc.key))) futurerecords.add(desc.key) @@ -1079,7 +1091,7 @@ async def sync_win( # Process finished futures into the state for rr_fut in done: - key: veilid.PublicKey + key: veilid.RecordKey rr: veilid.DHTRecordReport key, rr = await rr_fut if key is not None: diff --git a/veilid-python/tests/test_routing_context.py b/veilid-python/tests/test_routing_context.py index 9f3d6fac..4d141935 100644 --- a/veilid-python/tests/test_routing_context.py +++ b/veilid-python/tests/test_routing_context.py @@ -75,7 +75,7 @@ async def test_routing_context_app_message_loopback(): try: # send an app message to our own private route message = b"abcd1234" - await rc.app_message(prr, message) + await rc.app_message(veilid.TargetRouteId(prr), message) # we should get the same message back update: veilid.VeilidUpdate = await asyncio.wait_for( @@ -123,7 +123,7 @@ async def test_routing_context_app_call_loopback(): # send an app message to our own private route request = b"abcd1234" - app_call_task = asyncio.create_task(rc.app_call(prr, request), name="app call task") + app_call_task = asyncio.create_task(rc.app_call(veilid.TargetRouteId(prr), request), name="app call task") # we should get the same request back update: veilid.VeilidUpdate = await asyncio.wait_for(app_call_queue.get(), timeout=10) @@ -184,7 +184,7 @@ async def test_routing_context_app_message_loopback_big_packets(): for _ in range(5): # send a random sized random app message to our own private route message = random.randbytes(random.randint(0, 32768)) - await rc.app_message(prr, message) + await rc.app_message(veilid.TargetRouteId(prr), message) sent_messages.add(message) @@ -253,7 +253,7 @@ async def test_routing_context_app_call_loopback_big_packets(): for _ in range(5): # send a random sized random app message to our own private route message = random.randbytes(random.randint(0, 32768)) - out_message = await rc.app_call(prr, message) + out_message = await rc.app_call(veilid.TargetRouteId(prr), message) assert message == out_message finally: @@ -297,7 +297,7 @@ async def test_routing_context_app_message_loopback_bandwidth(): message = random.randbytes(16384) for _ in range(10000): # send a random sized random app message to our own private route - await rc.app_message(prr, message) + await rc.app_message(veilid.TargetRouteId(prr), message) # we should get the same number of messages back (not storing all that data) for _ in range(10000): diff --git a/veilid-python/veilid/api.py b/veilid-python/veilid/api.py index cfe3670c..6530e75e 100644 --- a/veilid-python/veilid/api.py +++ b/veilid-python/veilid/api.py @@ -49,49 +49,54 @@ class RoutingContext(ABC): pass @abstractmethod - async def app_call(self, target: types.PublicKey | types.BareRouteId, message: bytes) -> bytes: + async def app_call(self, target: types.Target, message: bytes) -> bytes: pass @abstractmethod - async def app_message(self, target: types.PublicKey | types.BareRouteId, message: bytes): + async def app_message(self, target: types.Target, message: bytes): + pass + + @abstractmethod + async def get_dht_record_key( + self, schema: types.DHTSchema, owner: types.PublicKey) -> types.RecordKey: pass @abstractmethod async def create_dht_record( - self, schema: types.DHTSchema, owner: Optional[types.BareKeyPair] = None, kind: Optional[types.CryptoKind] = None + self, schema: types.DHTSchema, owner: Optional[types.KeyPair] = None, kind: Optional[types.CryptoKind] = None ) -> types.DHTRecordDescriptor: pass @abstractmethod async def open_dht_record( - self, key: types.PublicKey, writer: Optional[types.BareKeyPair] = None + self, key: types.RecordKey, writer: Optional[types.KeyPair] = None ) -> types.DHTRecordDescriptor: pass @abstractmethod - async def close_dht_record(self, key: types.PublicKey): + async def close_dht_record(self, key: types.RecordKey): pass @abstractmethod - async def delete_dht_record(self, key: types.PublicKey): + async def delete_dht_record(self, key: types.RecordKey): pass @abstractmethod async def get_dht_value( - self, key: types.PublicKey, subkey: types.ValueSubkey, force_refresh: bool = False + self, key: types.RecordKey, subkey: types.ValueSubkey, force_refresh: bool = False ) -> Optional[types.ValueData]: pass @abstractmethod async def set_dht_value( - self, key: types.PublicKey, subkey: types.ValueSubkey, data: bytes, options: Optional[types.SetDHTValueOptions] = None + self, key: types.RecordKey, subkey: types.ValueSubkey, data: bytes, options: Optional[types.SetDHTValueOptions] = None ) -> Optional[types.ValueData]: pass @abstractmethod async def watch_dht_values( self, - key: types.PublicKey, + key: types.RecordKey, subkeys: list[tuple[types.ValueSubkey, types.ValueSubkey]] = [], expiration: types.Timestamp = types.Timestamp(0), count: int = 0xFFFFFFFF, @@ -101,7 +106,7 @@ class RoutingContext(ABC): @abstractmethod async def cancel_dht_watch( self, - key: types.PublicKey, + key: types.RecordKey, subkeys: list[tuple[types.ValueSubkey, types.ValueSubkey]] = [], ) -> bool: pass @@ -109,7 +114,7 @@ class RoutingContext(ABC): @abstractmethod async def inspect_dht_record( self, - key: types.PublicKey, + key: types.RecordKey, subkeys: list[tuple[types.ValueSubkey, types.ValueSubkey]], scope: types.DHTReportScope = types.DHTReportScope.LOCAL, ) -> types.DHTRecordReport: @@ -254,10 +259,62 @@ class CryptoSystem(ABC): async def random_bytes(self, len: int) -> bytes: pass + @abstractmethod + async def shared_secret_length(self) -> int: + pass + + @abstractmethod + async def nonce_length(self) -> int: + pass + + @abstractmethod + async def hash_digest_length(self) -> int: + pass + + @abstractmethod + async def public_key_length(self) -> int: + pass + + @abstractmethod + async def secret_key_length(self) -> int: + pass + + @abstractmethod + async def signature_length(self) -> int: + pass + @abstractmethod async def default_salt_length(self) -> int: pass + @abstractmethod + async def aead_overhead(self) -> int: + pass + + @abstractmethod + async def check_shared_secret(self, secret: types.BareSharedSecret): + pass + + @abstractmethod + async def check_nonce(self, nonce: types.BareNonce): + pass + + @abstractmethod + async def check_hash_digest(self, digest: types.BareHashDigest): + pass + + @abstractmethod + async def check_public_key(self, key: types.BarePublicKey): + pass + + @abstractmethod + async def check_secret_key(self, key: types.BareSecretKey): + pass + + @abstractmethod + async def check_signature(self, signature: types.BareSignature): + pass + @abstractmethod async def hash_password(self, password: bytes, salt: bytes) -> str: pass @@ -310,10 +367,6 @@ class CryptoSystem(ABC): async def verify(self, key: types.BarePublicKey, data: bytes, signature: types.BareSignature) -> bool: pass - @abstractmethod - async def aead_overhead(self) -> int: - pass - @abstractmethod async def decrypt_aead( self, @@ -387,7 +440,7 @@ class VeilidAPI(ABC): pass @abstractmethod - async def new_private_route(self) -> tuple[types.BareRouteId, bytes]: + async def new_private_route(self) -> tuple[types.RouteId, bytes]: pass @abstractmethod @@ -396,15 +449,15 @@ class VeilidAPI(ABC): kinds: list[types.CryptoKind], stability: types.Stability, sequencing: types.Sequencing, - ) -> tuple[types.BareRouteId, bytes]: + ) -> tuple[types.RouteId, bytes]: pass @abstractmethod - async def import_remote_private_route(self, blob: bytes) -> types.BareRouteId: + async def import_remote_private_route(self, blob: bytes) -> types.RouteId: pass @abstractmethod - async def release_private_route(self, route_id: types.BareRouteId): + async def release_private_route(self, route_id: types.RouteId): pass @abstractmethod @@ -450,6 +503,10 @@ class VeilidAPI(ABC): async def generate_key_pair(self, kind: types.CryptoKind) -> list[types.KeyPair]: pass + @abstractmethod + async def generate_member_id(self, writer_key: types.PublicKey) -> types.MemberId: + pass + @abstractmethod async def now(self) -> types.Timestamp: pass diff --git a/veilid-python/veilid/json_api.py b/veilid-python/veilid/json_api.py index c02275ac..c48ac40e 100644 --- a/veilid-python/veilid/json_api.py +++ b/veilid-python/veilid/json_api.py @@ -32,13 +32,14 @@ from .types import ( BareNonce, OperationId, BarePublicKey, - BareRouteId, + RouteId, SafetySelection, BareSecretKey, Sequencing, SetDHTValueOptions, BareSharedSecret, BareSignature, + MemberId, Stability, Timestamp, PublicKey, @@ -48,6 +49,8 @@ from .types import ( ValueSubkey, VeilidJSONEncoder, VeilidVersion, + Target, + RecordKey, urlsafe_b64decode_no_pad, ) @@ -333,14 +336,23 @@ class _JsonVeilidAPI(VeilidAPI): async def detach(self): raise_api_result(await self.send_ndjson_request(Operation.DETACH)) - async def new_private_route(self) -> tuple[BareRouteId, bytes]: + async def generate_member_id(self, writer_key: PublicKey) -> MemberId: + assert isinstance(writer_key, PublicKey) + + return MemberId( + raise_api_result( + await self.send_ndjson_request(Operation.GENERATE_MEMBER_ID, writer_key=writer_key) + ) + ) + + async def new_private_route(self) -> tuple[RouteId, bytes]: return NewPrivateRouteResult.from_json( raise_api_result(await self.send_ndjson_request(Operation.NEW_PRIVATE_ROUTE)) ).to_tuple() async def new_custom_private_route( self, kinds: list[CryptoKind], stability: Stability, sequencing: Sequencing - ) -> tuple[BareRouteId, bytes]: + ) -> tuple[RouteId, bytes]: assert isinstance(kinds, list) for k in kinds: assert isinstance(k, CryptoKind) @@ -358,17 +370,17 @@ class _JsonVeilidAPI(VeilidAPI): ) ).to_tuple() - async def import_remote_private_route(self, blob: bytes) -> BareRouteId: + async def import_remote_private_route(self, blob: bytes) -> RouteId: assert isinstance(blob, bytes) - return BareRouteId( + return RouteId( raise_api_result( await self.send_ndjson_request(Operation.IMPORT_REMOTE_PRIVATE_ROUTE, blob=blob) ) ) - async def release_private_route(self, route_id: BareRouteId): - assert isinstance(route_id, BareRouteId) + async def release_private_route(self, route_id: RouteId): + assert isinstance(route_id, RouteId) raise_api_result( await self.send_ndjson_request(Operation.RELEASE_PRIVATE_ROUTE, route_id=route_id) @@ -603,8 +615,8 @@ class _JsonRoutingContext(RoutingContext): ) ) ) - async def app_call(self, target: PublicKey | BareRouteId, message: bytes) -> bytes: - assert isinstance(target, PublicKey) or isinstance(target, BareRouteId) + async def app_call(self, target: Target, message: bytes) -> bytes: + assert isinstance(target, Target) assert isinstance(message, bytes) return urlsafe_b64decode_no_pad( @@ -620,8 +632,8 @@ class _JsonRoutingContext(RoutingContext): ) ) - async def app_message(self, target: PublicKey | BareRouteId, message: bytes): - assert isinstance(target, PublicKey) or isinstance(target, BareRouteId) + async def app_message(self, target: Target, message: bytes): + assert isinstance(target, Target) assert isinstance(message, bytes) raise_api_result( @@ -635,11 +647,28 @@ class _JsonRoutingContext(RoutingContext): ) ) + + async def get_dht_record_key( + self, schema: DHTSchema, owner: PublicKey) -> RecordKey: + assert isinstance(schema, DHTSchema) + assert isinstance(owner, PublicKey) + + return raise_api_result( + await self.api.send_ndjson_request( + Operation.ROUTING_CONTEXT, + validate=validate_rc_op, + rc_id=self.rc_id, + rc_op=RoutingContextOperation.GET_DHT_RECORD_KEY, + schema=schema, + owner=owner, + ) + ) + async def create_dht_record( - self, schema: DHTSchema, owner: Optional[BareKeyPair] = None, kind: Optional[CryptoKind] = None + self, schema: DHTSchema, owner: Optional[KeyPair] = None, kind: Optional[CryptoKind] = None ) -> DHTRecordDescriptor: assert isinstance(schema, DHTSchema) - assert owner is None or isinstance(owner, BareKeyPair) + assert owner is None or isinstance(owner, KeyPair) assert kind is None or isinstance(kind, CryptoKind) return DHTRecordDescriptor.from_json( @@ -657,10 +686,10 @@ class _JsonRoutingContext(RoutingContext): ) async def open_dht_record( - self, key: PublicKey, writer: Optional[BareKeyPair] = None + self, key: RecordKey, writer: Optional[KeyPair] = None ) -> DHTRecordDescriptor: - assert isinstance(key, PublicKey) - assert writer is None or isinstance(writer, BareKeyPair) + assert isinstance(key, RecordKey) + assert writer is None or isinstance(writer, KeyPair) return DHTRecordDescriptor.from_json( raise_api_result( @@ -675,8 +704,8 @@ class _JsonRoutingContext(RoutingContext): ) ) - async def close_dht_record(self, key: PublicKey): - assert isinstance(key, PublicKey) + async def close_dht_record(self, key: RecordKey): + assert isinstance(key, RecordKey) raise_api_result( await self.api.send_ndjson_request( @@ -688,8 +717,8 @@ class _JsonRoutingContext(RoutingContext): ) ) - async def delete_dht_record(self, key: PublicKey): - assert isinstance(key, PublicKey) + async def delete_dht_record(self, key: RecordKey): + assert isinstance(key, RecordKey) raise_api_result( await self.api.send_ndjson_request( @@ -702,9 +731,9 @@ class _JsonRoutingContext(RoutingContext): ) async def get_dht_value( - self, key: PublicKey, subkey: ValueSubkey, force_refresh: bool = False + self, key: RecordKey, subkey: ValueSubkey, force_refresh: bool = False ) -> Optional[ValueData]: - assert isinstance(key, PublicKey) + assert isinstance(key, RecordKey) assert isinstance(subkey, ValueSubkey) assert isinstance(force_refresh, bool) @@ -722,9 +751,9 @@ class _JsonRoutingContext(RoutingContext): return None if ret is None else ValueData.from_json(ret) async def set_dht_value( - self, key: PublicKey, subkey: ValueSubkey, data: bytes, options: Optional[SetDHTValueOptions] = None + self, key: RecordKey, subkey: ValueSubkey, data: bytes, options: Optional[SetDHTValueOptions] = None ) -> Optional[ValueData]: - assert isinstance(key, PublicKey) + assert isinstance(key, RecordKey) assert isinstance(subkey, ValueSubkey) assert isinstance(data, bytes) assert options is None or isinstance(options, SetDHTValueOptions) @@ -745,12 +774,12 @@ class _JsonRoutingContext(RoutingContext): async def watch_dht_values( self, - key: PublicKey, + key: RecordKey, subkeys: list[tuple[ValueSubkey, ValueSubkey]] = [], expiration: Timestamp = Timestamp(0), count: int = 0xFFFFFFFF, ) -> bool: - assert isinstance(key, PublicKey) + assert isinstance(key, RecordKey) assert isinstance(subkeys, list) for s in subkeys: assert isinstance(s, tuple) @@ -774,9 +803,9 @@ class _JsonRoutingContext(RoutingContext): async def cancel_dht_watch( - self, key: PublicKey, subkeys: list[tuple[ValueSubkey, ValueSubkey]] = [] + self, key: RecordKey, subkeys: list[tuple[ValueSubkey, ValueSubkey]] = [] ) -> bool: - assert isinstance(key, PublicKey) + assert isinstance(key, RecordKey) assert isinstance(subkeys, list) for s in subkeys: assert isinstance(s, tuple) @@ -796,11 +825,11 @@ class _JsonRoutingContext(RoutingContext): async def inspect_dht_record( self, - key: PublicKey, + key: RecordKey, subkeys: list[tuple[ValueSubkey, ValueSubkey]], scope: DHTReportScope = DHTReportScope.LOCAL, ) -> DHTRecordReport: - assert isinstance(key, PublicKey) + assert isinstance(key, RecordKey) assert isinstance(subkeys, list) for s in subkeys: assert isinstance(s, tuple) @@ -1173,6 +1202,66 @@ class _JsonCryptoSystem(CryptoSystem): ) ) + async def shared_secret_length(self) -> int: + return raise_api_result( + await self.api.send_ndjson_request( + Operation.CRYPTO_SYSTEM, + validate=validate_cs_op, + cs_id=self.cs_id, + cs_op=CryptoSystemOperation.SHARED_SECRET_LENGTH, + ) + ) + + async def nonce_length(self) -> int: + return raise_api_result( + await self.api.send_ndjson_request( + Operation.CRYPTO_SYSTEM, + validate=validate_cs_op, + cs_id=self.cs_id, + cs_op=CryptoSystemOperation.NONCE_LENGTH, + ) + ) + + async def hash_digest_length(self) -> int: + return raise_api_result( + await self.api.send_ndjson_request( + Operation.CRYPTO_SYSTEM, + validate=validate_cs_op, + cs_id=self.cs_id, + cs_op=CryptoSystemOperation.HASH_DIGEST_LENGTH, + ) + ) + + async def public_key_length(self) -> int: + return raise_api_result( + await self.api.send_ndjson_request( + Operation.CRYPTO_SYSTEM, + validate=validate_cs_op, + cs_id=self.cs_id, + cs_op=CryptoSystemOperation.PUBLIC_KEY_LENGTH, + ) + ) + + async def secret_key_length(self) -> int: + return raise_api_result( + await self.api.send_ndjson_request( + Operation.CRYPTO_SYSTEM, + validate=validate_cs_op, + cs_id=self.cs_id, + cs_op=CryptoSystemOperation.SECRET_KEY_LENGTH, + ) + ) + + async def signature_length(self) -> int: + return raise_api_result( + await self.api.send_ndjson_request( + Operation.CRYPTO_SYSTEM, + validate=validate_cs_op, + cs_id=self.cs_id, + cs_op=CryptoSystemOperation.SIGNATURE_LENGTH, + ) + ) + async def default_salt_length(self) -> int: return raise_api_result( await self.api.send_ndjson_request( @@ -1183,6 +1272,94 @@ class _JsonCryptoSystem(CryptoSystem): ) ) + async def aead_overhead(self) -> int: + return raise_api_result( + await self.api.send_ndjson_request( + Operation.CRYPTO_SYSTEM, + validate=validate_cs_op, + cs_id=self.cs_id, + cs_op=CryptoSystemOperation.AEAD_OVERHEAD, + ) + ) + + async def check_shared_secret(self, secret: BareSharedSecret): + assert isinstance(secret, BareSharedSecret) + + return raise_api_result( + await self.api.send_ndjson_request( + Operation.CRYPTO_SYSTEM, + validate=validate_cs_op, + cs_id=self.cs_id, + cs_op=CryptoSystemOperation.CHECK_SHARED_SECRET, + secret=secret, + ) + ) + + async def check_nonce(self, nonce: BareNonce): + assert isinstance(nonce, BareNonce) + + return raise_api_result( + await self.api.send_ndjson_request( + Operation.CRYPTO_SYSTEM, + validate=validate_cs_op, + cs_id=self.cs_id, + cs_op=CryptoSystemOperation.CHECK_NONCE, + nonce=nonce, + ) + ) + + async def check_hash_digest(self, digest: BareHashDigest): + assert isinstance(digest, BareHashDigest) + + return raise_api_result( + await self.api.send_ndjson_request( + Operation.CRYPTO_SYSTEM, + validate=validate_cs_op, + cs_id=self.cs_id, + cs_op=CryptoSystemOperation.CHECK_HASH_DIGEST, + digest=digest, + ) + ) + + async def check_public_key(self, key: BarePublicKey): + assert isinstance(key, BarePublicKey) + + return raise_api_result( + await self.api.send_ndjson_request( + Operation.CRYPTO_SYSTEM, + validate=validate_cs_op, + cs_id=self.cs_id, + cs_op=CryptoSystemOperation.CHECK_PUBLIC_KEY, + key=key, + ) + ) + + async def check_secret_key(self, key: BareSecretKey): + assert isinstance(key, BareSecretKey) + + return raise_api_result( + await self.api.send_ndjson_request( + Operation.CRYPTO_SYSTEM, + validate=validate_cs_op, + cs_id=self.cs_id, + cs_op=CryptoSystemOperation.CHECK_SECRET_KEY, + key=key, + ) + ) + + async def check_signature(self, signature: BareSignature): + assert isinstance(signature, BareSignature) + + return raise_api_result( + await self.api.send_ndjson_request( + Operation.CRYPTO_SYSTEM, + validate=validate_cs_op, + cs_id=self.cs_id, + cs_op=CryptoSystemOperation.CHECK_SIGNATURE, + signature=signature, + ) + ) + async def hash_password(self, password: bytes, salt: bytes) -> str: assert isinstance(password, bytes) assert isinstance(salt, bytes) @@ -1364,16 +1541,6 @@ class _JsonCryptoSystem(CryptoSystem): ) ) - async def aead_overhead(self) -> int: - return raise_api_result( - await self.api.send_ndjson_request( - Operation.CRYPTO_SYSTEM, - validate=validate_cs_op, - cs_id=self.cs_id, - cs_op=CryptoSystemOperation.AEAD_OVERHEAD, - ) - ) - async def decrypt_aead( self, body: bytes, diff --git a/veilid-python/veilid/operations.py b/veilid-python/veilid/operations.py index f6767201..4fa24a7e 100644 --- a/veilid-python/veilid/operations.py +++ b/veilid-python/veilid/operations.py @@ -8,6 +8,7 @@ class Operation(StrEnum): IS_SHUTDOWN = "IsShutdown" ATTACH = "Attach" DETACH = "Detach" + GENERATE_MEMBER_ID = "GenerateMemberId" NEW_PRIVATE_ROUTE = "NewPrivateRoute" NEW_CUSTOM_PRIVATE_ROUTE = "NewCustomPrivateRoute" IMPORT_REMOTE_PRIVATE_ROUTE = "ImportRemotePrivateRoute" @@ -42,6 +43,7 @@ class RoutingContextOperation(StrEnum): SAFETY = "Safety" APP_CALL = "AppCall" APP_MESSAGE = "AppMessage" + GET_DHT_RECORD_KEY = "GetDhtRecordKey" CREATE_DHT_RECORD = "CreateDhtRecord" OPEN_DHT_RECORD = "OpenDhtRecord" CLOSE_DHT_RECORD = "CloseDhtRecord" @@ -80,7 +82,20 @@ class CryptoSystemOperation(StrEnum): COMPUTE_DH = "ComputeDh" GENERATE_SHARED_SECRET = "GenerateSharedSecret" RANDOM_BYTES = "RandomBytes" + SHARED_SECRET_LENGTH = "SharedSecretLength" + NONCE_LENGTH = "NonceLength" + HASH_DIGEST_LENGTH = "HashDigestLength" + PUBLIC_KEY_LENGTH = "PublicKeyLength" + SECRET_KEY_LENGTH = "SecretKeyLength" + SIGNATURE_LENGTH = "SignatureLength" DEFAULT_SALT_LENGTH = "DefaultSaltLength" + AEAD_OVERHEAD = "AeadOverhead" + CHECK_SHARED_SECRET = "CheckSharedSecret" + CHECK_NONCE = "CheckNonce" + CHECK_HASH_DIGEST = "CheckHashDigest" + CHECK_PUBLIC_KEY = "CheckPublicKey" + CHECK_SECRET_KEY = "CheckSecretKey" + CHECK_SIGNATURE = "CheckSignature" HASH_PASSWORD = "HashPassword" VERIFY_PASSWORD = "VerifyPassword" DERIVE_SHARED_SECRET = "DeriveSharedSecret" @@ -93,7 +108,6 @@ class CryptoSystemOperation(StrEnum): DISTANCE = "Distance" SIGN = "Sign" VERIFY = "Verify" - AEAD_OVERHEAD = "AeadOverhead" DECRYPT_AEAD = "DecryptAead" ENCRYPT_AEAD = "EncryptAead" CRYPT_NO_AUTH = "CryptNoAuth" diff --git a/veilid-python/veilid/schema/RecvMessage.json b/veilid-python/veilid/schema/RecvMessage.json index 12ffb941..4c0b8dbc 100644 --- a/veilid-python/veilid/schema/RecvMessage.json +++ b/veilid-python/veilid/schema/RecvMessage.json @@ -1,2928 +1,110 @@ { - "$schema": "http://json-schema.org/draft-07/schema#", + "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "RecvMessage", "oneOf": [ { "type": "object", - "oneOf": [ - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "Control" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "$ref": "#/definitions/VeilidState" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "GetState" - ] - } - } - }, - { - "type": "object", - "required": [ - "op", - "value" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "IsShutdown" - ] - }, - "value": { - "type": "boolean" - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "null" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "Attach" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "null" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "Detach" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "$ref": "#/definitions/NewPrivateRouteResult" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "NewPrivateRoute" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "$ref": "#/definitions/NewPrivateRouteResult" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "NewCustomPrivateRoute" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "ImportRemotePrivateRoute" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "null" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "ReleasePrivateRoute" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "null" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "AppCallReply" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "NewRoutingContext" - ] - } - } - }, - { - "type": "object", - "oneOf": [ - { - "type": "object", - "required": [ - "rc_op" - ], - "properties": { - "rc_op": { - "type": "string", - "enum": [ - "InvalidId" - ] - } - } - }, - { - "type": "object", - "required": [ - "rc_op" - ], - "properties": { - "rc_op": { - "type": "string", - "enum": [ - "Release" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "rc_op" - ], - "properties": { - "rc_op": { - "type": "string", - "enum": [ - "WithDefaultSafety" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "rc_op" - ], - "properties": { - "rc_op": { - "type": "string", - "enum": [ - "WithSafety" - ] - } - } - }, - { - "type": "object", - "required": [ - "rc_op", - "value" - ], - "properties": { - "rc_op": { - "type": "string", - "enum": [ - "WithSequencing" - ] - }, - "value": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - } - }, - { - "type": "object", - "required": [ - "rc_op", - "value" - ], - "properties": { - "rc_op": { - "type": "string", - "enum": [ - "Safety" - ] - }, - "value": { - "$ref": "#/definitions/SafetySelection" - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "rc_op" - ], - "properties": { - "rc_op": { - "type": "string", - "enum": [ - "AppCall" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "null" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "rc_op" - ], - "properties": { - "rc_op": { - "type": "string", - "enum": [ - "AppMessage" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "$ref": "#/definitions/DHTRecordDescriptor" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "rc_op" - ], - "properties": { - "rc_op": { - "type": "string", - "enum": [ - "CreateDhtRecord" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "$ref": "#/definitions/DHTRecordDescriptor" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "rc_op" - ], - "properties": { - "rc_op": { - "type": "string", - "enum": [ - "OpenDhtRecord" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "null" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "rc_op" - ], - "properties": { - "rc_op": { - "type": "string", - "enum": [ - "CloseDhtRecord" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "null" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "rc_op" - ], - "properties": { - "rc_op": { - "type": "string", - "enum": [ - "DeleteDhtRecord" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "value": { - "anyOf": [ - { - "$ref": "#/definitions/ValueData" - }, - { - "type": "null" - } - ] - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "rc_op" - ], - "properties": { - "rc_op": { - "type": "string", - "enum": [ - "GetDhtValue" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "value": { - "anyOf": [ - { - "$ref": "#/definitions/ValueData" - }, - { - "type": "null" - } - ] - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "rc_op" - ], - "properties": { - "rc_op": { - "type": "string", - "enum": [ - "SetDhtValue" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "boolean" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "rc_op" - ], - "properties": { - "rc_op": { - "type": "string", - "enum": [ - "WatchDhtValues" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "boolean" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "rc_op" - ], - "properties": { - "rc_op": { - "type": "string", - "enum": [ - "CancelDhtWatch" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "$ref": "#/definitions/DHTRecordReport" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "rc_op" - ], - "properties": { - "rc_op": { - "type": "string", - "enum": [ - "InspectDhtRecord" - ] - } - } - } - ], - "required": [ - "op", - "rc_id" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "RoutingContext" - ] - }, - "rc_id": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "OpenTableDb" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "boolean" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "DeleteTableDb" - ] - } - } - }, - { - "type": "object", - "oneOf": [ - { - "type": "object", - "required": [ - "db_op" - ], - "properties": { - "db_op": { - "type": "string", - "enum": [ - "InvalidId" - ] - } - } - }, - { - "type": "object", - "required": [ - "db_op" - ], - "properties": { - "db_op": { - "type": "string", - "enum": [ - "Release" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "db_op" - ], - "properties": { - "db_op": { - "type": "string", - "enum": [ - "GetColumnCount" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "db_op" - ], - "properties": { - "db_op": { - "type": "string", - "enum": [ - "GetKeys" - ] - } - } - }, - { - "type": "object", - "required": [ - "db_op", - "value" - ], - "properties": { - "db_op": { - "type": "string", - "enum": [ - "Transact" - ] - }, - "value": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "null" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "db_op" - ], - "properties": { - "db_op": { - "type": "string", - "enum": [ - "Store" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "value": { - "type": [ - "string", - "null" - ] - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "db_op" - ], - "properties": { - "db_op": { - "type": "string", - "enum": [ - "Load" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "value": { - "type": [ - "string", - "null" - ] - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "db_op" - ], - "properties": { - "db_op": { - "type": "string", - "enum": [ - "Delete" - ] - } - } - } - ], - "required": [ - "db_id", - "op" - ], - "properties": { - "db_id": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "op": { - "type": "string", - "enum": [ - "TableDb" - ] - } - } - }, - { - "type": "object", - "oneOf": [ - { - "type": "object", - "required": [ - "tx_op" - ], - "properties": { - "tx_op": { - "type": "string", - "enum": [ - "InvalidId" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "null" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "tx_op" - ], - "properties": { - "tx_op": { - "type": "string", - "enum": [ - "Commit" - ] - } - } - }, - { - "type": "object", - "required": [ - "tx_op" - ], - "properties": { - "tx_op": { - "type": "string", - "enum": [ - "Rollback" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "null" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "tx_op" - ], - "properties": { - "tx_op": { - "type": "string", - "enum": [ - "Store" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "null" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "tx_op" - ], - "properties": { - "tx_op": { - "type": "string", - "enum": [ - "Delete" - ] - } - } - } - ], - "required": [ - "op", - "tx_id" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "TableDbTransaction" - ] - }, - "tx_id": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "GetCryptoSystem" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "BestCryptoSystem" - ] - } - } - }, - { - "type": "object", - "oneOf": [ - { - "type": "object", - "required": [ - "cs_op" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "InvalidId" - ] - } - } - }, - { - "type": "object", - "required": [ - "cs_op" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "Release" - ] - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "value" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "Kind" - ] - }, - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "cs_op" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "CachedDh" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "cs_op" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "ComputeDh" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "cs_op" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "GenerateSharedSecret" - ] - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "value" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "RandomBytes" - ] - }, - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "value" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "DefaultSaltLength" - ] - }, - "value": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "cs_op" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "HashPassword" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "boolean" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "cs_op" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "VerifyPassword" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "cs_op" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "DeriveSharedSecret" - ] - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "value" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "RandomNonce" - ] - }, - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "value" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "RandomSharedSecret" - ] - }, - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "value" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "GenerateKeyPair" - ] - }, - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "value" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "GenerateHash" - ] - }, - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "value" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "ValidateKeyPair" - ] - }, - "value": { - "type": "boolean" - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "value" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "ValidateHash" - ] - }, - "value": { - "type": "boolean" - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "value" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "Distance" - ] - }, - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "cs_op" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "Sign" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "boolean" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "cs_op" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "Verify" - ] - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "value" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "AeadOverhead" - ] - }, - "value": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "cs_op" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "DecryptAead" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "cs_op" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "EncryptAead" - ] - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "value" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "CryptNoAuth" - ] - }, - "value": { - "type": "string" - } - } - } - ], - "required": [ - "cs_id", - "op" - ], - "properties": { - "cs_id": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "op": { - "type": "string", - "enum": [ - "CryptoSystem" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "value": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "VerifySignatures" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "GenerateSignatures" - ] - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "GenerateKeyPair" - ] - } - } - }, - { - "type": "object", - "required": [ - "op", - "value" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "Now" - ] - }, - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/definitions/VeilidAPIError" - } - } - } - ], - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "Debug" - ] - } - } - }, - { - "type": "object", - "required": [ - "op", - "value" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "VeilidVersionString" - ] - }, - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "major", - "minor", - "op", - "patch" - ], - "properties": { - "major": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "minor": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "op": { - "type": "string", - "enum": [ - "VeilidVersion" - ] - }, - "patch": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - } - }, - { - "type": "object", - "required": [ - "op", - "value" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "DefaultVeilidConfig" - ] - }, - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "op", - "value" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "VeilidFeatures" - ] - }, - "value": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - ], - "required": [ - "type" - ], "properties": { - "id": { - "description": "Operation Id (pairs with Request, or empty if unidirectional).", - "default": 0, - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, "type": { "type": "string", - "enum": [ - "Response" - ] + "const": "Response" } - } + }, + "$ref": "#/$defs/Response", + "required": [ + "type" + ] }, { - "description": "An update from the veilid-core to the host application describing a change to the internal state of the Veilid node.", "type": "object", - "oneOf": [ - { - "description": "A VeilidCore log message with optional backtrace.", - "type": "object", - "required": [ - "kind", - "log_level", - "message" - ], - "properties": { - "backtrace": { - "type": [ - "string", - "null" - ] - }, - "kind": { - "type": "string", - "enum": [ - "Log" - ] - }, - "log_level": { - "$ref": "#/definitions/VeilidLogLevel" - }, - "message": { - "type": "string" - } - } - }, - { - "description": "Direct statement blob passed to hosting application for processing.", - "type": "object", - "required": [ - "kind", - "message" - ], - "properties": { - "kind": { - "type": "string", - "enum": [ - "AppMessage" - ] - }, - "message": { - "type": "string" - }, - "route_id": { - "type": [ - "string", - "null" - ] - }, - "sender": { - "type": [ - "string", - "null" - ] - } - } - }, - { - "description": "Direct question blob passed to hosting application for processing to send an eventual AppReply.", - "type": "object", - "required": [ - "call_id", - "kind", - "message" - ], - "properties": { - "call_id": { - "type": "string" - }, - "kind": { - "type": "string", - "enum": [ - "AppCall" - ] - }, - "message": { - "type": "string" - }, - "route_id": { - "type": [ - "string", - "null" - ] - }, - "sender": { - "type": [ - "string", - "null" - ] - } - } - }, - { - "description": "Describe the attachment state of the Veilid node", - "type": "object", - "required": [ - "kind", - "local_network_ready", - "public_internet_ready", - "state", - "uptime" - ], - "properties": { - "attached_uptime": { - "description": "Uptime since last attach, empty if the node is currently detached", - "type": [ - "string", - "null" - ] - }, - "kind": { - "type": "string", - "enum": [ - "Attachment" - ] - }, - "local_network_ready": { - "description": "If attached and there are enough reachable nodes in the routing table to perform all the actions of the LocalNetwork RoutingDomain.", - "type": "boolean" - }, - "public_internet_ready": { - "description": "If attached and there are enough reachable nodes in the routing table to perform all the actions of the PublicInternet RoutingDomain, including things like private/safety route allocation and DHT operations.", - "type": "boolean" - }, - "state": { - "description": "The overall quality of the routing table if attached, or the current state the attachment state machine.", - "allOf": [ - { - "$ref": "#/definitions/AttachmentState" - } - ] - }, - "uptime": { - "description": "Node uptime", - "type": "string" - } - } - }, - { - "description": "Describe the current network state of the Veilid node", - "type": "object", - "required": [ - "bps_down", - "bps_up", - "kind", - "peers", - "started" - ], - "properties": { - "bps_down": { - "description": "The total number of bytes per second used by Veilid currently in the download direction.", - "type": "string" - }, - "bps_up": { - "description": "The total number of bytes per second used by Veilid currently in the upload direction.", - "type": "string" - }, - "kind": { - "type": "string", - "enum": [ - "Network" - ] - }, - "peers": { - "description": "The list of most recently accessed peers. This is not an active connection table, nor is representative of the entire routing table.", - "type": "array", - "items": { - "$ref": "#/definitions/PeerTableData" - } - }, - "started": { - "description": "If the network has been started or not.", - "type": "boolean" - } - } - }, - { - "description": "Describe changes to the Veilid node configuration Currently this is only ever emitted once, however we reserve the right to add the ability to change the configuration or have it changed by the Veilid node itself during runtime.", - "type": "object", - "required": [ - "config", - "kind" - ], - "properties": { - "config": { - "description": "If the Veilid node configuration has changed the full new config will be here.", - "allOf": [ - { - "$ref": "#/definitions/VeilidConfig" - } - ] - }, - "kind": { - "type": "string", - "enum": [ - "Config" - ] - } - } - }, - { - "description": "Describe a private route change that has happened", - "type": "object", - "required": [ - "dead_remote_routes", - "dead_routes", - "kind" - ], - "properties": { - "dead_remote_routes": { - "description": "If a private route that was imported has died, it is listed here.", - "type": "array", - "items": { - "type": "string" - } - }, - "dead_routes": { - "description": "If a private route that was allocated has died, it is listed here.", - "type": "array", - "items": { - "type": "string" - } - }, - "kind": { - "type": "string", - "enum": [ - "RouteChange" - ] - } - } - }, - { - "description": "Describe when DHT records have subkey values changed", - "type": "object", - "required": [ - "count", - "key", - "kind", - "subkeys" - ], - "properties": { - "count": { - "description": "The count remaining on the watch that triggered this value change If there is no watch and this is received, it will be set to u32::MAX If this value is zero, any watch present on the value has died.", - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "key": { - "description": "The DHT Record key that changed", - "type": "string" - }, - "kind": { - "type": "string", - "enum": [ - "ValueChange" - ] - }, - "subkeys": { - "description": "The portion of the DHT Record's subkeys that have changed If the subkey range is empty, any watch present on the value has died.", - "type": "array", - "items": { - "type": "array", - "items": [ - { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - ], - "maxItems": 2, - "minItems": 2 - } - }, - "value": { - "description": "The (optional) value data for the first subkey in the subkeys range If 'subkeys' is not a single value, other values than the first value must be retrieved with RoutingContext::get_dht_value().", - "anyOf": [ - { - "$ref": "#/definitions/ValueData" - }, - { - "type": "null" - } - ] - } - } - }, - { - "type": "object", - "required": [ - "kind" - ], - "properties": { - "kind": { - "type": "string", - "enum": [ - "Shutdown" - ] - } - } - } - ], - "required": [ - "type" - ], "properties": { "type": { "type": "string", - "enum": [ - "Update" - ] + "const": "Update" } - } + }, + "$ref": "#/$defs/VeilidUpdate", + "required": [ + "type" + ] } ], - "definitions": { + "$defs": { "AnswerStats": { "description": "Measurement of round-trip RPC question/answer performance", "type": "object", - "required": [ - "answers", - "consecutive_answers_average", - "consecutive_answers_maximum", - "consecutive_answers_minimum", - "consecutive_lost_answers_average", - "consecutive_lost_answers_maximum", - "consecutive_lost_answers_minimum", - "lost_answers", - "questions", - "span" - ], "properties": { "answers": { "description": "number of answers received in this span", "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "consecutive_answers_average": { "description": "average number of received answers before a lost answer in this span", "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "consecutive_answers_maximum": { "description": "maximum number of received answers before a lost answer in this span", "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "consecutive_answers_minimum": { "description": "minimum number of received answers before a lost answer in this span", "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "consecutive_lost_answers_average": { "description": "average number of timeouts before a received answer in this span", "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "consecutive_lost_answers_maximum": { "description": "maximum number of timeouts before a received answer in this span", "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "consecutive_lost_answers_minimum": { "description": "minimum number of timeouts before a received answer in this span", "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "lost_answers": { "description": "number of lost answers in this span", "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "questions": { "description": "number of questions sent in this span", "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "span": { "description": "total amount of time measured", - "type": "string" + "$ref": "#/$defs/TimestampDuration" } - } + }, + "required": [ + "span", + "questions", + "answers", + "lost_answers", + "consecutive_answers_maximum", + "consecutive_answers_average", + "consecutive_answers_minimum", + "consecutive_lost_answers_maximum", + "consecutive_lost_answers_average", + "consecutive_lost_answers_minimum" + ] }, "AttachmentState": { "description": "Attachment abstraction for network 'signal strength'.", @@ -2938,14 +120,951 @@ "Detaching" ] }, + "ByteCount": { + "type": "string" + }, + "CryptoSystemResponse": { + "type": "object", + "properties": { + "cs_id": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "oneOf": [ + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "InvalidId" + } + }, + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "Release" + } + }, + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "Kind" + }, + "value": { + "type": "string" + } + }, + "required": [ + "cs_op", + "value" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "CachedDh" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "ComputeDh" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "GenerateSharedSecret" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "RandomBytes" + }, + "value": { + "type": "string" + } + }, + "required": [ + "cs_op", + "value" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "SharedSecretLength" + }, + "value": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "cs_op", + "value" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "NonceLength" + }, + "value": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "cs_op", + "value" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "HashDigestLength" + }, + "value": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "cs_op", + "value" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "PublicKeyLength" + }, + "value": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "cs_op", + "value" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "SecretKeyLength" + }, + "value": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "cs_op", + "value" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "SignatureLength" + }, + "value": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "cs_op", + "value" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "DefaultSaltLength" + }, + "value": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "cs_op", + "value" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "AeadOverhead" + }, + "value": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "cs_op", + "value" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "CheckSharedSecret" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "null" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "CheckNonce" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "null" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "CheckHashDigest" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "null" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "CheckPublicKey" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "null" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "CheckSecretKey" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "null" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "CheckSignature" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "null" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "HashPassword" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "VerifyPassword" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "boolean" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "DeriveSharedSecret" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "RandomNonce" + }, + "value": { + "type": "string" + } + }, + "required": [ + "cs_op", + "value" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "RandomSharedSecret" + }, + "value": { + "type": "string" + } + }, + "required": [ + "cs_op", + "value" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "GenerateKeyPair" + }, + "value": { + "type": "string" + } + }, + "required": [ + "cs_op", + "value" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "GenerateHash" + }, + "value": { + "type": "string" + } + }, + "required": [ + "cs_op", + "value" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "ValidateKeyPair" + }, + "value": { + "type": "boolean" + } + }, + "required": [ + "cs_op", + "value" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "ValidateHash" + }, + "value": { + "type": "boolean" + } + }, + "required": [ + "cs_op", + "value" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "Distance" + }, + "value": { + "type": "string" + } + }, + "required": [ + "cs_op", + "value" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "Sign" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "Verify" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "boolean" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "DecryptAead" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "EncryptAead" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "CryptNoAuth" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "cs_op" + ] + } + ], + "required": [ + "cs_id" + ] + }, "DHTRecordDescriptor": { "description": "DHT Record Descriptor", "type": "object", - "required": [ - "key", - "owner", - "schema" - ], "properties": { "key": { "description": "DHT Key = Hash(ownerKeyKind) of: [ ownerKeyValue, schema ]", @@ -2956,7 +1075,7 @@ "type": "string" }, "owner_secret": { - "description": "If this key is being created: Some(the secret key of the owner) If this key is just being opened: None", + "description": "If this key is being created: Some(the secret key of the owner)\nIf this key is just being opened: None", "type": [ "string", "null" @@ -2964,23 +1083,18 @@ }, "schema": { "description": "The schema in use associated with the key", - "allOf": [ - { - "$ref": "#/definitions/DHTSchema" - } - ] + "$ref": "#/$defs/DHTSchema" } - } + }, + "required": [ + "key", + "owner", + "schema" + ] }, "DHTRecordReport": { "description": "DHT Record Report", "type": "object", - "required": [ - "local_seqs", - "network_seqs", - "offline_subkeys", - "subkeys" - ], "properties": { "local_seqs": { "description": "The sequence numbers of each subkey requested from a locally stored DHT Record", @@ -2991,7 +1105,7 @@ "null" ], "format": "uint32", - "minimum": 0.0 + "minimum": 0 } }, "network_seqs": { @@ -3003,179 +1117,162 @@ "null" ], "format": "uint32", - "minimum": 0.0 + "minimum": 0 } }, "offline_subkeys": { "description": "The subkeys that have been writen offline that still need to be flushed", - "type": "array", - "items": { - "type": "array", - "items": [ - { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - ], - "maxItems": 2, - "minItems": 2 - } + "$ref": "#/$defs/ValueSubkeyRangeSet" }, "subkeys": { - "description": "The actual subkey range within the schema being reported on This may be a subset of the requested range if it exceeds the schema limits or has more than 512 subkeys", - "type": "array", - "items": { - "type": "array", - "items": [ - { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - ], - "maxItems": 2, - "minItems": 2 - } + "description": "The actual subkey range within the schema being reported on\nThis may be a subset of the requested range if it exceeds the schema limits\nor has more than 512 subkeys", + "$ref": "#/$defs/ValueSubkeyRangeSet" } - } + }, + "required": [ + "subkeys", + "offline_subkeys", + "local_seqs", + "network_seqs" + ] }, "DHTSchema": { "description": "Enum over all the supported DHT Schemas", "oneOf": [ { - "description": "Default DHT Schema (DFLT)", "type": "object", - "required": [ - "kind", - "o_cnt" - ], "properties": { "kind": { "type": "string", - "enum": [ - "DFLT" - ] - }, - "o_cnt": { - "description": "Owner subkey count", - "type": "integer", - "format": "uint16", - "minimum": 0.0 + "const": "DFLT" } - } + }, + "$ref": "#/$defs/DHTSchemaDFLT", + "required": [ + "kind" + ] }, { - "description": "Simple DHT Schema (SMPL)", "type": "object", - "required": [ - "kind", - "members", - "o_cnt" - ], "properties": { "kind": { "type": "string", - "enum": [ - "SMPL" - ] - }, - "members": { - "description": "Members", - "type": "array", - "items": { - "$ref": "#/definitions/DHTSchemaSMPLMember" - } - }, - "o_cnt": { - "description": "Owner subkey count", - "type": "integer", - "format": "uint16", - "minimum": 0.0 + "const": "SMPL" } - } + }, + "$ref": "#/$defs/DHTSchemaSMPL", + "required": [ + "kind" + ] } ] }, + "DHTSchemaDFLT": { + "description": "Default DHT Schema (DFLT)", + "type": "object", + "properties": { + "o_cnt": { + "description": "Owner subkey count", + "type": "integer", + "format": "uint16", + "maximum": 65535, + "minimum": 0 + } + }, + "required": [ + "o_cnt" + ] + }, + "DHTSchemaSMPL": { + "description": "Simple DHT Schema (SMPL)", + "type": "object", + "properties": { + "members": { + "description": "Members", + "type": "array", + "items": { + "$ref": "#/$defs/DHTSchemaSMPLMember" + } + }, + "o_cnt": { + "description": "Owner subkey count", + "type": "integer", + "format": "uint16", + "maximum": 65535, + "minimum": 0 + } + }, + "required": [ + "o_cnt", + "members" + ] + }, "DHTSchemaSMPLMember": { "description": "Simple DHT Schema (SMPL) Member", "type": "object", - "required": [ - "m_cnt", - "m_key" - ], "properties": { "m_cnt": { "description": "Member subkey count", "type": "integer", "format": "uint16", - "minimum": 0.0 + "maximum": 65535, + "minimum": 0 }, "m_key": { "description": "Member key", "type": "string" } - } + }, + "required": [ + "m_key", + "m_cnt" + ] }, "LatencyStats": { "description": "Measurement of communications latency to this node over all RPC questions", "type": "object", - "required": [ - "average", - "fastest", - "slowest" - ], "properties": { "average": { "description": "average latency over the ROLLING_LATENCIES_SIZE last latencies", - "type": "string" + "$ref": "#/$defs/TimestampDuration" }, "fastest": { "description": "fastest latency in the ROLLING_LATENCIES_SIZE last latencies", - "type": "string" + "$ref": "#/$defs/TimestampDuration" }, "p75": { "description": "p75 latency in the ROLLING_LATENCIES_SIZE", - "default": "0", - "type": "string" + "$ref": "#/$defs/TimestampDuration", + "default": "0" }, "p90": { "description": "p90 latency in the ROLLING_LATENCIES_SIZE", - "default": "0", - "type": "string" + "$ref": "#/$defs/TimestampDuration", + "default": "0" }, "slowest": { "description": "slowest latency in the ROLLING_LATENCIES_SIZE last latencies", - "type": "string" + "$ref": "#/$defs/TimestampDuration" }, "tm75": { "description": "trimmed mean with lowest 75% latency in the ROLLING_LATENCIES_SIZE", - "default": "0", - "type": "string" + "$ref": "#/$defs/TimestampDuration", + "default": "0" }, "tm90": { "description": "trimmed mean with lowest 90% latency in the ROLLING_LATENCIES_SIZE", - "default": "0", - "type": "string" + "$ref": "#/$defs/TimestampDuration", + "default": "0" } - } + }, + "required": [ + "fastest", + "average", + "slowest" + ] }, "NewPrivateRouteResult": { "type": "object", - "required": [ - "blob", - "route_id" - ], "properties": { "blob": { "type": "string" @@ -3183,29 +1280,31 @@ "route_id": { "type": "string" } - } + }, + "required": [ + "route_id", + "blob" + ] }, "PeerStats": { "description": "Statistics for a peer in the routing table", "type": "object", - "required": [ - "time_added" - ], "properties": { "latency": { "description": "latency stats for this peer", - "default": null, "anyOf": [ { - "$ref": "#/definitions/LatencyStats" + "$ref": "#/$defs/LatencyStats" }, { "type": "null" } - ] + ], + "default": null }, "rpc_stats": { "description": "information about RPCs", + "$ref": "#/$defs/RPCStats", "default": { "answer_ordered": { "answers": 0, @@ -3240,15 +1339,11 @@ "questions_in_flight": 0, "recent_lost_answers_ordered": 0, "recent_lost_answers_unordered": 0 - }, - "allOf": [ - { - "$ref": "#/definitions/RPCStats" - } - ] + } }, "state": { "description": "state stats for this peer", + "$ref": "#/$defs/StateStats", "default": { "dead": "0", "punished": "0", @@ -3264,19 +1359,15 @@ "reliable": "0", "span": "0", "unreliable": "0" - }, - "allOf": [ - { - "$ref": "#/definitions/StateStats" - } - ] + } }, "time_added": { "description": "when the peer was added to the routing table", - "type": "string" + "$ref": "#/$defs/Timestamp" }, "transfer": { "description": "transfer stats for this peer", + "$ref": "#/$defs/TransferStatsDownUp", "default": { "down": { "average": "0", @@ -3290,23 +1381,16 @@ "minimum": "0", "total": "0" } - }, - "allOf": [ - { - "$ref": "#/definitions/TransferStatsDownUp" - } - ] + } } - } + }, + "required": [ + "time_added" + ] }, "PeerTableData": { "description": "Describe a recently accessed peer", "type": "object", - "required": [ - "node_ids", - "peer_address", - "peer_stats" - ], "properties": { "node_ids": { "description": "The node ids used by this peer", @@ -3321,26 +1405,22 @@ }, "peer_stats": { "description": "Statistics we have collected on this peer.", - "allOf": [ - { - "$ref": "#/definitions/PeerStats" - } - ] + "$ref": "#/$defs/PeerStats" } - } + }, + "required": [ + "node_ids", + "peer_address", + "peer_stats" + ] }, "RPCStats": { "description": "Statistics for RPC operations performed on a node", "type": "object", - "required": [ - "failed_to_send", - "messages_rcvd", - "messages_sent", - "questions_in_flight" - ], "properties": { "answer_ordered": { "description": "ordered rpc answer stats for this peer", + "$ref": "#/$defs/AnswerStats", "default": { "answers": 0, "consecutive_answers_average": 0, @@ -3352,15 +1432,11 @@ "lost_answers": 0, "questions": 0, "span": "0" - }, - "allOf": [ - { - "$ref": "#/definitions/AnswerStats" - } - ] + } }, "answer_unordered": { "description": "unordered rpc answer stats for this peer", + "$ref": "#/$defs/AnswerStats", "default": { "answers": 0, "consecutive_answers_average": 0, @@ -3372,73 +1448,1552 @@ "lost_answers": 0, "questions": 0, "span": "0" - }, - "allOf": [ - { - "$ref": "#/definitions/AnswerStats" - } - ] + } }, "failed_to_send": { "description": "number of messages that have failed to send or connections dropped since we last successfully sent one", "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "first_consecutive_seen_ts": { "description": "the timestamp of the first consecutive proof-of-life for this node (an answer or received question)", - "type": [ - "string", - "null" + "anyOf": [ + { + "$ref": "#/$defs/Timestamp" + }, + { + "type": "null" + } ] }, "last_question_ts": { "description": "when the peer was last questioned (either successfully or not) and we wanted an answer", - "type": [ - "string", - "null" + "anyOf": [ + { + "$ref": "#/$defs/Timestamp" + }, + { + "type": "null" + } ] }, "last_seen_ts": { "description": "when the peer was last seen for any reason, including when we first attempted to reach out to it", - "type": [ - "string", - "null" + "anyOf": [ + { + "$ref": "#/$defs/Timestamp" + }, + { + "type": "null" + } ] }, "messages_rcvd": { "description": "number of rpcs that have been received in the total entry time range", "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "messages_sent": { "description": "number of rpcs that have been sent in the total entry time range", "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "questions_in_flight": { "description": "number of questions issued that have yet to be answered", "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "recent_lost_answers_ordered": { "description": "number of answers that have been lost consecutively over an ordered channel", - "default": 0, "type": "integer", "format": "uint32", - "minimum": 0.0 + "default": 0, + "minimum": 0 }, "recent_lost_answers_unordered": { "description": "number of answers that have been lost consecutively over an unordered channel", - "default": 0, "type": "integer", "format": "uint32", - "minimum": 0.0 + "default": 0, + "minimum": 0 } - } + }, + "required": [ + "messages_sent", + "messages_rcvd", + "questions_in_flight", + "failed_to_send" + ] + }, + "Response": { + "type": "object", + "properties": { + "id": { + "description": "Operation Id (pairs with Request, or empty if unidirectional).", + "type": "integer", + "format": "uint32", + "default": 0, + "minimum": 0 + } + }, + "oneOf": [ + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "Control" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "GetState" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "$ref": "#/$defs/VeilidState" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "IsShutdown" + }, + "value": { + "type": "boolean" + } + }, + "required": [ + "op", + "value" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "Attach" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "null" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "Detach" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "null" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "GenerateMemberId" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "NewPrivateRoute" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "$ref": "#/$defs/NewPrivateRouteResult" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "NewCustomPrivateRoute" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "$ref": "#/$defs/NewPrivateRouteResult" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "ImportRemotePrivateRoute" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "ReleasePrivateRoute" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "null" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "AppCallReply" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "null" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "NewRoutingContext" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "RoutingContext" + } + }, + "$ref": "#/$defs/RoutingContextResponse", + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "OpenTableDb" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "DeleteTableDb" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "boolean" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "TableDb" + } + }, + "$ref": "#/$defs/TableDbResponse", + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "TableDbTransaction" + } + }, + "$ref": "#/$defs/TableDbTransactionResponse", + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "GetCryptoSystem" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "BestCryptoSystem" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "CryptoSystem" + } + }, + "$ref": "#/$defs/CryptoSystemResponse", + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "VerifySignatures" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + } + } + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "GenerateSignatures" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "GenerateKeyPair" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "Now" + }, + "value": { + "type": "string" + } + }, + "required": [ + "op", + "value" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "Debug" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "VeilidVersionString" + }, + "value": { + "type": "string" + } + }, + "required": [ + "op", + "value" + ] + }, + { + "type": "object", + "properties": { + "major": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "minor": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "op": { + "type": "string", + "const": "VeilidVersion" + }, + "patch": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "op", + "major", + "minor", + "patch" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "DefaultVeilidConfig" + }, + "value": { + "type": "string" + } + }, + "required": [ + "op", + "value" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "VeilidFeatures" + }, + "value": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "op", + "value" + ] + } + ] + }, + "RoutingContextResponse": { + "type": "object", + "properties": { + "rc_id": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "oneOf": [ + { + "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "InvalidId" + } + }, + "required": [ + "rc_op" + ] + }, + { + "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "Release" + } + }, + "required": [ + "rc_op" + ] + }, + { + "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "WithDefaultSafety" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "rc_op" + ] + }, + { + "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "WithSafety" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "rc_op" + ] + }, + { + "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "WithSequencing" + }, + "value": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "rc_op", + "value" + ] + }, + { + "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "Safety" + }, + "value": { + "$ref": "#/$defs/SafetySelection" + } + }, + "required": [ + "rc_op", + "value" + ] + }, + { + "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "AppCall" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "rc_op" + ] + }, + { + "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "AppMessage" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "null" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "rc_op" + ] + }, + { + "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "GetDhtRecordKey" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "rc_op" + ] + }, + { + "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "CreateDhtRecord" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "$ref": "#/$defs/DHTRecordDescriptor" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "rc_op" + ] + }, + { + "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "OpenDhtRecord" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "$ref": "#/$defs/DHTRecordDescriptor" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "rc_op" + ] + }, + { + "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "CloseDhtRecord" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "null" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "rc_op" + ] + }, + { + "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "DeleteDhtRecord" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "null" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "rc_op" + ] + }, + { + "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "GetDhtValue" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "anyOf": [ + { + "$ref": "#/$defs/ValueData" + }, + { + "type": "null" + } + ] + } + } + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "rc_op" + ] + }, + { + "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "SetDhtValue" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "anyOf": [ + { + "$ref": "#/$defs/ValueData" + }, + { + "type": "null" + } + ] + } + } + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "rc_op" + ] + }, + { + "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "WatchDhtValues" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "boolean" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "rc_op" + ] + }, + { + "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "CancelDhtWatch" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "boolean" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "rc_op" + ] + }, + { + "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "InspectDhtRecord" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "$ref": "#/$defs/DHTRecordReport" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "rc_op" + ] + } + ], + "required": [ + "rc_id" + ] }, "SafetySelection": { "description": "The choice of safety route to include in compiled routes.", @@ -3446,45 +3001,40 @@ { "description": "Don't use a safety route, only specify the sequencing preference.", "type": "object", - "required": [ - "Unsafe" - ], "properties": { "Unsafe": { - "$ref": "#/definitions/Sequencing" + "$ref": "#/$defs/Sequencing" } }, - "additionalProperties": false + "additionalProperties": false, + "required": [ + "Unsafe" + ] }, { "description": "Use a safety route and parameters specified by a SafetySpec.", "type": "object", - "required": [ - "Safe" - ], "properties": { "Safe": { - "$ref": "#/definitions/SafetySpec" + "$ref": "#/$defs/SafetySpec" } }, - "additionalProperties": false + "additionalProperties": false, + "required": [ + "Safe" + ] } ] }, "SafetySpec": { "description": "Options for safety routes (sender privacy).", "type": "object", - "required": [ - "hop_count", - "sequencing", - "stability" - ], "properties": { "hop_count": { "description": "Must be greater than 0.", "type": "integer", "format": "uint", - "minimum": 0.0 + "minimum": 0 }, "preferred_route": { "description": "Preferred safety route set id if it still exists.", @@ -3495,21 +3045,18 @@ }, "sequencing": { "description": "Prefer connection-oriented sequenced protocols.", - "allOf": [ - { - "$ref": "#/definitions/Sequencing" - } - ] + "$ref": "#/$defs/Sequencing" }, "stability": { "description": "Prefer reliability over speed.", - "allOf": [ - { - "$ref": "#/definitions/Stability" - } - ] + "$ref": "#/$defs/Stability" } - } + }, + "required": [ + "hop_count", + "stability", + "sequencing" + ] }, "Sequencing": { "type": "string", @@ -3529,67 +3076,61 @@ "StateReasonStats": { "description": "Measurement of what state reasons the node has been in over a time span", "type": "object", - "required": [ - "can_not_send", - "failed_to_send", - "in_unreliable_ping_span", - "lost_answers", - "no_ping_response", - "not_seen_consecutively", - "too_many_lost_answers" - ], "properties": { "can_not_send": { "description": "time spent dead due to being unable to send", - "type": "string" + "$ref": "#/$defs/TimestampDuration" }, "failed_to_send": { "description": "time spent unreliable because of failures to send", - "type": "string" + "$ref": "#/$defs/TimestampDuration" }, "in_unreliable_ping_span": { "description": "time spent unreliable because we are in the unreliable ping span", - "type": "string" + "$ref": "#/$defs/TimestampDuration" }, "lost_answers": { "description": "time spent unreliable because of lost answers", - "type": "string" + "$ref": "#/$defs/TimestampDuration" }, "no_ping_response": { "description": "time spent dead because of no ping response", - "type": "string" + "$ref": "#/$defs/TimestampDuration" }, "not_seen_consecutively": { "description": "time spent unreliable because of not being seen consecutively", - "type": "string" + "$ref": "#/$defs/TimestampDuration" }, "too_many_lost_answers": { "description": "time spent dead because of too many lost answers", - "type": "string" + "$ref": "#/$defs/TimestampDuration" } - } + }, + "required": [ + "can_not_send", + "too_many_lost_answers", + "no_ping_response", + "failed_to_send", + "lost_answers", + "not_seen_consecutively", + "in_unreliable_ping_span" + ] }, "StateStats": { "description": "Measurement of what states the node has been in over a time span", "type": "object", - "required": [ - "dead", - "punished", - "reliable", - "span", - "unreliable" - ], "properties": { "dead": { "description": "amount of time spent in a dead state", - "type": "string" + "$ref": "#/$defs/TimestampDuration" }, "punished": { "description": "amount of time spent in a punished state", - "type": "string" + "$ref": "#/$defs/TimestampDuration" }, "reason": { "description": "state reason stats for this peer", + "$ref": "#/$defs/StateReasonStats", "default": { "can_not_send": "0", "failed_to_send": "0", @@ -3598,78 +3139,470 @@ "no_ping_response": "0", "not_seen_consecutively": "0", "too_many_lost_answers": "0" - }, - "allOf": [ - { - "$ref": "#/definitions/StateReasonStats" - } - ] + } }, "reliable": { "description": "amount of time spent in a reliable state", - "type": "string" + "$ref": "#/$defs/TimestampDuration" }, "span": { "description": "total amount of time measured", - "type": "string" + "$ref": "#/$defs/TimestampDuration" }, "unreliable": { "description": "amount of time spent in an unreliable state", - "type": "string" + "$ref": "#/$defs/TimestampDuration" } - } + }, + "required": [ + "span", + "reliable", + "unreliable", + "dead", + "punished" + ] + }, + "TableDbResponse": { + "type": "object", + "properties": { + "db_id": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "oneOf": [ + { + "type": "object", + "properties": { + "db_op": { + "type": "string", + "const": "InvalidId" + } + }, + "required": [ + "db_op" + ] + }, + { + "type": "object", + "properties": { + "db_op": { + "type": "string", + "const": "Release" + } + }, + "required": [ + "db_op" + ] + }, + { + "type": "object", + "properties": { + "db_op": { + "type": "string", + "const": "GetColumnCount" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "db_op" + ] + }, + { + "type": "object", + "properties": { + "db_op": { + "type": "string", + "const": "GetKeys" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "db_op" + ] + }, + { + "type": "object", + "properties": { + "db_op": { + "type": "string", + "const": "Transact" + }, + "value": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "db_op", + "value" + ] + }, + { + "type": "object", + "properties": { + "db_op": { + "type": "string", + "const": "Store" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "null" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "db_op" + ] + }, + { + "type": "object", + "properties": { + "db_op": { + "type": "string", + "const": "Load" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": [ + "string", + "null" + ] + } + } + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "db_op" + ] + }, + { + "type": "object", + "properties": { + "db_op": { + "type": "string", + "const": "Delete" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": [ + "string", + "null" + ] + } + } + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "db_op" + ] + } + ], + "required": [ + "db_id" + ] + }, + "TableDbTransactionResponse": { + "type": "object", + "properties": { + "tx_id": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "oneOf": [ + { + "type": "object", + "properties": { + "tx_op": { + "type": "string", + "const": "InvalidId" + } + }, + "required": [ + "tx_op" + ] + }, + { + "type": "object", + "properties": { + "tx_op": { + "type": "string", + "const": "Commit" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "null" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "tx_op" + ] + }, + { + "type": "object", + "properties": { + "tx_op": { + "type": "string", + "const": "Rollback" + } + }, + "required": [ + "tx_op" + ] + }, + { + "type": "object", + "properties": { + "tx_op": { + "type": "string", + "const": "Store" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "null" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "tx_op" + ] + }, + { + "type": "object", + "properties": { + "tx_op": { + "type": "string", + "const": "Delete" + } + }, + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "null" + } + }, + "required": [ + "value" + ] + }, + { + "type": "object", + "properties": { + "error": { + "$ref": "#/$defs/VeilidAPIError" + } + }, + "required": [ + "error" + ] + } + ], + "required": [ + "tx_op" + ] + } + ], + "required": [ + "tx_id" + ] + }, + "Timestamp": { + "type": "string" + }, + "TimestampDuration": { + "type": "string" }, "TransferStats": { "description": "Measurement of how much data has transferred to or from this node over a time span", "type": "object", - "required": [ - "average", - "maximum", - "minimum", - "total" - ], "properties": { "average": { "description": "average rate over the ROLLING_TRANSFERS_SIZE last amounts", - "type": "string" + "$ref": "#/$defs/ByteCount" }, "maximum": { "description": "maximum rate over the ROLLING_TRANSFERS_SIZE last amounts", - "type": "string" + "$ref": "#/$defs/ByteCount" }, "minimum": { "description": "minimum rate over the ROLLING_TRANSFERS_SIZE last amounts", - "type": "string" + "$ref": "#/$defs/ByteCount" }, "total": { "description": "total amount transferred ever", - "type": "string" + "$ref": "#/$defs/ByteCount" } - } + }, + "required": [ + "total", + "maximum", + "average", + "minimum" + ] }, "TransferStatsDownUp": { "description": "Transfer statistics from a node to our own (down) and", "type": "object", + "properties": { + "down": { + "$ref": "#/$defs/TransferStats" + }, + "up": { + "$ref": "#/$defs/TransferStats" + } + }, "required": [ "down", "up" - ], - "properties": { - "down": { - "$ref": "#/definitions/TransferStats" - }, - "up": { - "$ref": "#/definitions/TransferStats" - } - } + ] }, "ValueData": { "type": "object", - "required": [ - "data", - "seq", - "writer" - ], "properties": { "data": { "description": "The contents of a DHT Record", @@ -3679,366 +3612,384 @@ "description": "An increasing sequence number to time-order the DHT record changes", "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "writer": { "description": "The public identity key of the writer of the data", "type": "string" } + }, + "required": [ + "seq", + "data", + "writer" + ] + }, + "ValueSubkeyRangeSet": { + "type": "array", + "items": { + "type": "array", + "maxItems": 2, + "minItems": 2, + "prefixItems": [ + { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + ] } }, "VeilidAPIError": { "oneOf": [ { "type": "object", - "required": [ - "kind" - ], "properties": { "kind": { "type": "string", - "enum": [ - "NotInitialized" - ] + "const": "NotInitialized" } - } + }, + "required": [ + "kind" + ] }, { "type": "object", - "required": [ - "kind" - ], "properties": { "kind": { "type": "string", - "enum": [ - "AlreadyInitialized" - ] + "const": "AlreadyInitialized" } - } + }, + "required": [ + "kind" + ] }, { "type": "object", - "required": [ - "kind" - ], "properties": { "kind": { "type": "string", - "enum": [ - "Timeout" - ] + "const": "Timeout" } - } + }, + "required": [ + "kind" + ] }, { "type": "object", - "required": [ - "kind", - "message" - ], "properties": { "kind": { "type": "string", - "enum": [ - "TryAgain" - ] + "const": "TryAgain" }, "message": { "type": "string" } - } - }, - { - "type": "object", - "required": [ - "kind" - ], - "properties": { - "kind": { - "type": "string", - "enum": [ - "Shutdown" - ] - } - } - }, - { - "type": "object", + }, "required": [ "kind", "message" - ], + ] + }, + { + "type": "object", "properties": { "kind": { "type": "string", - "enum": [ - "InvalidTarget" - ] + "const": "Shutdown" + } + }, + "required": [ + "kind" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "InvalidTarget" }, "message": { "type": "string" } - } - }, - { - "type": "object", + }, "required": [ "kind", "message" - ], + ] + }, + { + "type": "object", "properties": { "kind": { "type": "string", - "enum": [ - "NoConnection" - ] + "const": "NoConnection" }, "message": { "type": "string" } - } + }, + "required": [ + "kind", + "message" + ] }, { "type": "object", - "required": [ - "key", - "kind" - ], "properties": { "key": { "type": "string" }, "kind": { "type": "string", - "enum": [ - "KeyNotFound" - ] + "const": "KeyNotFound" } - } + }, + "required": [ + "kind", + "key" + ] }, { "type": "object", - "required": [ - "kind", - "message" - ], "properties": { "kind": { "type": "string", - "enum": [ - "Internal" - ] + "const": "Internal" }, "message": { "type": "string" } - } - }, - { - "type": "object", + }, "required": [ "kind", "message" - ], + ] + }, + { + "type": "object", "properties": { "kind": { "type": "string", - "enum": [ - "Unimplemented" - ] + "const": "Unimplemented" }, "message": { "type": "string" } - } + }, + "required": [ + "kind", + "message" + ] }, { "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "ParseError" + }, + "message": { + "type": "string" + }, + "value": { + "type": "string" + } + }, "required": [ "kind", "message", "value" - ], + ] + }, + { + "type": "object", + "properties": { + "argument": { + "type": "string" + }, + "context": { + "type": "string" + }, + "kind": { + "type": "string", + "const": "InvalidArgument" + }, + "value": { + "type": "string" + } + }, + "required": [ + "kind", + "context", + "argument", + "value" + ] + }, + { + "type": "object", + "properties": { + "argument": { + "type": "string" + }, + "context": { + "type": "string" + }, + "kind": { + "type": "string", + "const": "MissingArgument" + } + }, + "required": [ + "kind", + "context", + "argument" + ] + }, + { + "type": "object", "properties": { "kind": { "type": "string", - "enum": [ - "ParseError" - ] + "const": "Generic" }, "message": { "type": "string" - }, - "value": { - "type": "string" } - } - }, - { - "type": "object", - "required": [ - "argument", - "context", - "kind", - "value" - ], - "properties": { - "argument": { - "type": "string" - }, - "context": { - "type": "string" - }, - "kind": { - "type": "string", - "enum": [ - "InvalidArgument" - ] - }, - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "argument", - "context", - "kind" - ], - "properties": { - "argument": { - "type": "string" - }, - "context": { - "type": "string" - }, - "kind": { - "type": "string", - "enum": [ - "MissingArgument" - ] - } - } - }, - { - "type": "object", + }, "required": [ "kind", "message" - ], - "properties": { - "kind": { - "type": "string", - "enum": [ - "Generic" - ] - }, - "message": { - "type": "string" - } - } + ] } ] }, + "VeilidAppCall": { + "description": "Direct question blob passed to hosting application for processing to send an eventual AppReply.", + "type": "object", + "properties": { + "call_id": { + "type": "string" + }, + "message": { + "type": "string" + }, + "route_id": { + "type": [ + "string", + "null" + ] + }, + "sender": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "message", + "call_id" + ] + }, + "VeilidAppMessage": { + "description": "Direct statement blob passed to hosting application for processing.", + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "route_id": { + "type": [ + "string", + "null" + ] + }, + "sender": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "message" + ] + }, "VeilidCapability": { "description": "A four-character code", - "type": "array", - "items": { - "type": "integer", - "format": "uint8", - "minimum": 0.0 - }, - "maxItems": 4, - "minItems": 4 + "type": "string" }, "VeilidConfig": { "description": "Top level of the Veilid configuration tree", "type": "object", - "required": [ - "block_store", - "capabilities", - "namespace", - "network", - "program_name", - "protected_store", - "table_store" - ], "properties": { "block_store": { "description": "Configuring the block store (storage of large content-addressable content)", - "allOf": [ - { - "$ref": "#/definitions/VeilidConfigBlockStore" - } - ] + "$ref": "#/$defs/VeilidConfigBlockStore" }, "capabilities": { "description": "Capabilities to enable for your application/node", - "allOf": [ - { - "$ref": "#/definitions/VeilidConfigCapabilities" - } - ] + "$ref": "#/$defs/VeilidConfigCapabilities" }, "namespace": { - "description": "To run multiple Veilid nodes within the same application, either through a single process running api_startup/api_startup_json multiple times, or your application running mulitple times side-by-side there needs to be a key used to partition the application's storage (in the TableStore, ProtectedStore, etc). An empty value here is the default, but if you run multiple veilid nodes concurrently, you should set this to a string that uniquely identifies this -instance- within the same 'program_name'. Must be a valid filename for all Veilid-capable systems, which means no backslashes or forward slashes in the name. Stick to a-z,0-9,_ and space and you should be fine.", + "description": "To run multiple Veilid nodes within the same application, either through a single process running\napi_startup/api_startup_json multiple times, or your application running mulitple times side-by-side\nthere needs to be a key used to partition the application's storage (in the TableStore, ProtectedStore, etc).\nAn empty value here is the default, but if you run multiple veilid nodes concurrently, you should set this\nto a string that uniquely identifies this -instance- within the same 'program_name'.\nMust be a valid filename for all Veilid-capable systems, which means no backslashes or forward slashes\nin the name. Stick to a-z,0-9,_ and space and you should be fine.", "type": "string" }, "network": { "description": "Configuring how Veilid interacts with the low level network", - "allOf": [ - { - "$ref": "#/definitions/VeilidConfigNetwork" - } - ] + "$ref": "#/$defs/VeilidConfigNetwork" }, "program_name": { - "description": "An identifier used to describe the program using veilid-core. Used to partition storage locations in places like the ProtectedStore. Must be non-empty and a valid filename for all Veilid-capable systems, which means no backslashes or forward slashes in the name. Stick to a-z,0-9,_ and space and you should be fine.\n\nCaution: If you change this string, there is no migration support. Your app's protected store and table store will very likely experience data loss. Pick a program name and stick with it. This is not a 'visible' identifier and it should uniquely identify your application.", + "description": "An identifier used to describe the program using veilid-core.\nUsed to partition storage locations in places like the ProtectedStore.\nMust be non-empty and a valid filename for all Veilid-capable systems, which means\nno backslashes or forward slashes in the name. Stick to a-z,0-9,_ and space and you should be fine.\n\nCaution: If you change this string, there is no migration support. Your app's protected store and\ntable store will very likely experience data loss. Pick a program name and stick with it. This is\nnot a 'visible' identifier and it should uniquely identify your application.", "type": "string" }, "protected_store": { "description": "Configuring the protected store (keychain/keyring/etc)", - "allOf": [ - { - "$ref": "#/definitions/VeilidConfigProtectedStore" - } - ] + "$ref": "#/$defs/VeilidConfigProtectedStore" }, "table_store": { "description": "Configuring the table store (persistent encrypted database)", - "allOf": [ - { - "$ref": "#/definitions/VeilidConfigTableStore" - } - ] + "$ref": "#/$defs/VeilidConfigTableStore" } - } + }, + "required": [ + "program_name", + "namespace", + "capabilities", + "protected_store", + "table_store", + "block_store", + "network" + ] }, "VeilidConfigApplication": { "description": "Application configuration.\n\nConfigure web access to the Progressive Web App (PWA).\n\nTo be implemented...", "type": "object", - "required": [ - "http", - "https" - ], "properties": { "http": { - "$ref": "#/definitions/VeilidConfigHTTP" + "$ref": "#/$defs/VeilidConfigHTTP" }, "https": { - "$ref": "#/definitions/VeilidConfigHTTPS" + "$ref": "#/$defs/VeilidConfigHTTPS" } - } + }, + "required": [ + "https", + "http" + ] }, "VeilidConfigBlockStore": { "type": "object", - "required": [ - "delete", - "directory" - ], "properties": { "delete": { "type": "boolean" @@ -4046,170 +3997,169 @@ "directory": { "type": "string" } - } + }, + "required": [ + "directory", + "delete" + ] }, "VeilidConfigCapabilities": { "type": "object", - "required": [ - "disable" - ], "properties": { "disable": { "type": "array", "items": { - "$ref": "#/definitions/VeilidCapability" + "$ref": "#/$defs/VeilidCapability" } } - } + }, + "required": [ + "disable" + ] }, "VeilidConfigDHT": { - "description": "Configure the Distributed Hash Table (DHT). Defaults should be used here unless you are absolutely sure you know what you're doing. If you change the count/fanout/timeout parameters, you may render your node inoperable for correct DHT operations.", + "description": "Configure the Distributed Hash Table (DHT).\nDefaults should be used here unless you are absolutely sure you know what you're doing.\nIf you change the count/fanout/timeout parameters, you may render your node inoperable\nfor correct DHT operations.", "type": "object", - "required": [ - "get_value_count", - "get_value_fanout", - "get_value_timeout_ms", - "local_max_subkey_cache_memory_mb", - "local_subkey_cache_size", - "max_find_node_count", - "max_watch_expiration_ms", - "member_watch_limit", - "min_peer_count", - "min_peer_refresh_time_ms", - "public_watch_limit", - "remote_max_records", - "remote_max_storage_space_mb", - "remote_max_subkey_cache_memory_mb", - "remote_subkey_cache_size", - "resolve_node_count", - "resolve_node_fanout", - "resolve_node_timeout_ms", - "set_value_count", - "set_value_fanout", - "set_value_timeout_ms", - "validate_dial_info_receipt_time_ms" - ], "properties": { "get_value_count": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "get_value_fanout": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "get_value_timeout_ms": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "local_max_subkey_cache_memory_mb": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "local_subkey_cache_size": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "max_find_node_count": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "max_watch_expiration_ms": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "member_watch_limit": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "min_peer_count": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "min_peer_refresh_time_ms": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "public_watch_limit": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "remote_max_records": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "remote_max_storage_space_mb": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "remote_max_subkey_cache_memory_mb": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "remote_subkey_cache_size": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "resolve_node_count": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "resolve_node_fanout": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "resolve_node_timeout_ms": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "set_value_count": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "set_value_fanout": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "set_value_timeout_ms": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "validate_dial_info_receipt_time_ms": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 } - } + }, + "required": [ + "max_find_node_count", + "resolve_node_timeout_ms", + "resolve_node_count", + "resolve_node_fanout", + "get_value_timeout_ms", + "get_value_count", + "get_value_fanout", + "set_value_timeout_ms", + "set_value_count", + "set_value_fanout", + "min_peer_count", + "min_peer_refresh_time_ms", + "validate_dial_info_receipt_time_ms", + "local_subkey_cache_size", + "local_max_subkey_cache_memory_mb", + "remote_subkey_cache_size", + "remote_max_records", + "remote_max_subkey_cache_memory_mb", + "remote_max_storage_space_mb", + "public_watch_limit", + "member_watch_limit", + "max_watch_expiration_ms" + ] }, "VeilidConfigHTTP": { - "description": "Enable and configure HTTP access to the Veilid node.\n\n```yaml http: enabled: false listen_address: ':5150' path: 'app\" url: 'https://localhost:5150' ```", + "description": "Enable and configure HTTP access to the Veilid node.\n\n```yaml\nhttp:\n enabled: false\n listen_address: ':5150'\n path: 'app\"\n url: 'https://localhost:5150'\n```", "type": "object", - "required": [ - "enabled", - "listen_address", - "path" - ], "properties": { "enabled": { "type": "boolean" @@ -4226,16 +4176,16 @@ "null" ] } - } + }, + "required": [ + "enabled", + "listen_address", + "path" + ] }, "VeilidConfigHTTPS": { - "description": "Enable and configure HTTPS access to the Veilid node.\n\n```yaml https: enabled: false listen_address: ':5150' path: 'app' url: 'https://localhost:5150' ```", + "description": "Enable and configure HTTPS access to the Veilid node.\n\n```yaml\nhttps:\n enabled: false\n listen_address: ':5150'\n path: 'app'\n url: 'https://localhost:5150'\n```", "type": "object", - "required": [ - "enabled", - "listen_address", - "path" - ], "properties": { "enabled": { "type": "boolean" @@ -4252,48 +4202,33 @@ "null" ] } - } + }, + "required": [ + "enabled", + "listen_address", + "path" + ] }, "VeilidConfigNetwork": { "type": "object", - "required": [ - "application", - "client_allowlist_timeout_ms", - "connection_inactivity_timeout_ms", - "connection_initial_timeout_ms", - "dht", - "hole_punch_receipt_time_ms", - "max_connection_frequency_per_min", - "max_connections_per_ip4", - "max_connections_per_ip6_prefix", - "max_connections_per_ip6_prefix_size", - "privacy", - "protocol", - "restricted_nat_retries", - "reverse_connection_receipt_time_ms", - "routing_table", - "rpc", - "tls", - "upnp" - ], "properties": { "application": { - "$ref": "#/definitions/VeilidConfigApplication" + "$ref": "#/$defs/VeilidConfigApplication" }, "client_allowlist_timeout_ms": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "connection_inactivity_timeout_ms": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "connection_initial_timeout_ms": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "detect_address_changes": { "type": [ @@ -4302,32 +4237,32 @@ ] }, "dht": { - "$ref": "#/definitions/VeilidConfigDHT" + "$ref": "#/$defs/VeilidConfigDHT" }, "hole_punch_receipt_time_ms": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "max_connection_frequency_per_min": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "max_connections_per_ip4": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "max_connections_per_ip6_prefix": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "max_connections_per_ip6_prefix_size": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "network_key_password": { "type": [ @@ -4336,56 +4271,69 @@ ] }, "privacy": { - "$ref": "#/definitions/VeilidConfigPrivacy" + "$ref": "#/$defs/VeilidConfigPrivacy" }, "protocol": { - "$ref": "#/definitions/VeilidConfigProtocol" + "$ref": "#/$defs/VeilidConfigProtocol" }, "restricted_nat_retries": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "reverse_connection_receipt_time_ms": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "routing_table": { - "$ref": "#/definitions/VeilidConfigRoutingTable" + "$ref": "#/$defs/VeilidConfigRoutingTable" }, "rpc": { - "$ref": "#/definitions/VeilidConfigRPC" + "$ref": "#/$defs/VeilidConfigRPC" }, "tls": { - "$ref": "#/definitions/VeilidConfigTLS" + "$ref": "#/$defs/VeilidConfigTLS" }, "upnp": { "type": "boolean" } - } + }, + "required": [ + "connection_initial_timeout_ms", + "connection_inactivity_timeout_ms", + "max_connections_per_ip4", + "max_connections_per_ip6_prefix", + "max_connections_per_ip6_prefix_size", + "max_connection_frequency_per_min", + "client_allowlist_timeout_ms", + "reverse_connection_receipt_time_ms", + "hole_punch_receipt_time_ms", + "routing_table", + "rpc", + "dht", + "upnp", + "restricted_nat_retries", + "tls", + "application", + "protocol", + "privacy" + ] }, "VeilidConfigPrivacy": { - "description": "Privacy preferences for routes.\n\n```yaml privacy: require_inbound_relay: false country_code_denylist: [] # only with `--features=geolocation` ```", + "description": "Privacy preferences for routes.\n\n```yaml\nprivacy:\n require_inbound_relay: false\n country_code_denylist: [] # only with `--features=geolocation`\n```", "type": "object", - "required": [ - "require_inbound_relay" - ], "properties": { "require_inbound_relay": { "type": "boolean" } - } + }, + "required": [ + "require_inbound_relay" + ] }, "VeilidConfigProtectedStore": { "type": "object", - "required": [ - "allow_insecure_fallback", - "always_use_insecure_storage", - "delete", - "device_encryption_key_password", - "directory" - ], "properties": { "allow_insecure_fallback": { "type": "boolean" @@ -4408,57 +4356,59 @@ "null" ] } - } + }, + "required": [ + "allow_insecure_fallback", + "always_use_insecure_storage", + "directory", + "delete", + "device_encryption_key_password" + ] }, "VeilidConfigProtocol": { - "description": "Configure Network Protocols.\n\nVeilid can communicate over UDP, TCP, and Web Sockets.\n\nAll protocols are available by default, and the Veilid node will sort out which protocol is used for each peer connection.", + "description": "Configure Network Protocols.\n\nVeilid can communicate over UDP, TCP, and Web Sockets.\n\nAll protocols are available by default, and the Veilid node will\nsort out which protocol is used for each peer connection.", "type": "object", - "required": [ - "tcp", - "udp", - "ws", - "wss" - ], "properties": { "tcp": { - "$ref": "#/definitions/VeilidConfigTCP" + "$ref": "#/$defs/VeilidConfigTCP" }, "udp": { - "$ref": "#/definitions/VeilidConfigUDP" + "$ref": "#/$defs/VeilidConfigUDP" }, "ws": { - "$ref": "#/definitions/VeilidConfigWS" + "$ref": "#/$defs/VeilidConfigWS" }, "wss": { - "$ref": "#/definitions/VeilidConfigWSS" + "$ref": "#/$defs/VeilidConfigWSS" } - } + }, + "required": [ + "udp", + "tcp", + "ws", + "wss" + ] }, "VeilidConfigRPC": { "description": "Configure RPC.", "type": "object", - "required": [ - "concurrency", - "default_route_hop_count", - "max_route_hop_count", - "queue_size", - "timeout_ms" - ], "properties": { "concurrency": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "default_route_hop_count": { "type": "integer", "format": "uint8", - "minimum": 0.0 + "maximum": 255, + "minimum": 0 }, "max_route_hop_count": { "type": "integer", "format": "uint8", - "minimum": 0.0 + "maximum": 255, + "minimum": 0 }, "max_timestamp_ahead_ms": { "type": [ @@ -4466,7 +4416,7 @@ "null" ], "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "max_timestamp_behind_ms": { "type": [ @@ -4474,34 +4424,30 @@ "null" ], "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "queue_size": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "timeout_ms": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 } - } + }, + "required": [ + "concurrency", + "queue_size", + "timeout_ms", + "max_route_hop_count", + "default_route_hop_count" + ] }, "VeilidConfigRoutingTable": { "description": "Configure the network routing table.", "type": "object", - "required": [ - "bootstrap", - "bootstrap_keys", - "limit_attached_good", - "limit_attached_strong", - "limit_attached_weak", - "limit_fully_attached", - "limit_over_attached", - "node_id", - "node_id_secret" - ], "properties": { "bootstrap": { "type": "array", @@ -4518,27 +4464,27 @@ "limit_attached_good": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "limit_attached_strong": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "limit_attached_weak": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "limit_fully_attached": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "limit_over_attached": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "node_id": { "type": "array", @@ -4552,17 +4498,22 @@ "type": "string" } } - } + }, + "required": [ + "node_id", + "node_id_secret", + "bootstrap", + "bootstrap_keys", + "limit_over_attached", + "limit_fully_attached", + "limit_attached_strong", + "limit_attached_good", + "limit_attached_weak" + ] }, "VeilidConfigTCP": { - "description": "Enable and configure TCP.\n\n```yaml tcp: connect: true listen: true max_connections: 32 listen_address: ':5150' public_address: ''", + "description": "Enable and configure TCP.\n\n```yaml\ntcp:\n connect: true\n listen: true\n max_connections: 32\n listen_address: ':5150'\n public_address: ''", "type": "object", - "required": [ - "connect", - "listen", - "listen_address", - "max_connections" - ], "properties": { "connect": { "type": "boolean" @@ -4576,7 +4527,7 @@ "max_connections": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "public_address": { "type": [ @@ -4584,16 +4535,17 @@ "null" ] } - } + }, + "required": [ + "connect", + "listen", + "max_connections", + "listen_address" + ] }, "VeilidConfigTLS": { - "description": "Configure TLS.\n\n```yaml tls: certificate_path: /path/to/cert private_key_path: /path/to/private/key connection_initial_timeout_ms: 2000", + "description": "Configure TLS.\n\n```yaml\ntls:\n certificate_path: /path/to/cert\n private_key_path: /path/to/private/key\n connection_initial_timeout_ms: 2000", "type": "object", - "required": [ - "certificate_path", - "connection_initial_timeout_ms", - "private_key_path" - ], "properties": { "certificate_path": { "type": "string" @@ -4601,19 +4553,20 @@ "connection_initial_timeout_ms": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "private_key_path": { "type": "string" } - } + }, + "required": [ + "certificate_path", + "private_key_path", + "connection_initial_timeout_ms" + ] }, "VeilidConfigTableStore": { "type": "object", - "required": [ - "delete", - "directory" - ], "properties": { "delete": { "type": "boolean" @@ -4621,16 +4574,15 @@ "directory": { "type": "string" } - } + }, + "required": [ + "directory", + "delete" + ] }, "VeilidConfigUDP": { - "description": "Enable and configure UDP.\n\n```yaml udp: enabled: true socket_pool_size: 0 listen_address: ':5150' public_address: '' ```", + "description": "Enable and configure UDP.\n\n```yaml\nudp:\n enabled: true\n socket_pool_size: 0\n listen_address: ':5150'\n public_address: ''\n```", "type": "object", - "required": [ - "enabled", - "listen_address", - "socket_pool_size" - ], "properties": { "enabled": { "type": "boolean" @@ -4647,20 +4599,18 @@ "socket_pool_size": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 } - } + }, + "required": [ + "enabled", + "socket_pool_size", + "listen_address" + ] }, "VeilidConfigWS": { - "description": "Enable and configure Web Sockets.\n\n```yaml ws: connect: true listen: true max_connections: 32 listen_address: ':5150' path: 'ws' url: 'ws://localhost:5150/ws'", + "description": "Enable and configure Web Sockets.\n\n```yaml\nws:\n connect: true\n listen: true\n max_connections: 32\n listen_address: ':5150'\n path: 'ws'\n url: 'ws://localhost:5150/ws'", "type": "object", - "required": [ - "connect", - "listen", - "listen_address", - "max_connections", - "path" - ], "properties": { "connect": { "type": "boolean" @@ -4674,7 +4624,7 @@ "max_connections": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "path": { "type": "string" @@ -4685,18 +4635,18 @@ "null" ] } - } + }, + "required": [ + "connect", + "listen", + "max_connections", + "listen_address", + "path" + ] }, "VeilidConfigWSS": { - "description": "Enable and configure Secure Web Sockets.\n\n```yaml wss: connect: true listen: false max_connections: 32 listen_address: ':5150' path: 'ws' url: ''", + "description": "Enable and configure Secure Web Sockets.\n\n```yaml\nwss:\n connect: true\n listen: false\n max_connections: 32\n listen_address: ':5150'\n path: 'ws'\n url: ''", "type": "object", - "required": [ - "connect", - "listen", - "listen_address", - "max_connections", - "path" - ], "properties": { "connect": { "type": "boolean" @@ -4710,7 +4660,7 @@ "max_connections": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "path": { "type": "string" @@ -4721,7 +4671,36 @@ "null" ] } - } + }, + "required": [ + "connect", + "listen", + "max_connections", + "listen_address", + "path" + ] + }, + "VeilidLog": { + "description": "A VeilidCore log message with optional backtrace.", + "type": "object", + "properties": { + "backtrace": { + "type": [ + "string", + "null" + ] + }, + "log_level": { + "$ref": "#/$defs/VeilidLogLevel" + }, + "message": { + "type": "string" + } + }, + "required": [ + "log_level", + "message" + ] }, "VeilidLogLevel": { "description": "Log level for VeilidCore.", @@ -4734,41 +4713,63 @@ "Trace" ] }, + "VeilidRouteChange": { + "description": "Describe a private route change that has happened", + "type": "object", + "properties": { + "dead_remote_routes": { + "description": "If a private route that was imported has died, it is listed here.", + "type": "array", + "items": { + "type": "string" + } + }, + "dead_routes": { + "description": "If a private route that was allocated has died, it is listed here.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "dead_routes", + "dead_remote_routes" + ] + }, "VeilidState": { "description": "A queriable state of the internals of veilid-core.", "type": "object", - "required": [ - "attachment", - "config", - "network" - ], "properties": { "attachment": { - "$ref": "#/definitions/VeilidStateAttachment" + "$ref": "#/$defs/VeilidStateAttachment" }, "config": { - "$ref": "#/definitions/VeilidStateConfig" + "$ref": "#/$defs/VeilidStateConfig" }, "network": { - "$ref": "#/definitions/VeilidStateNetwork" + "$ref": "#/$defs/VeilidStateNetwork" } - } + }, + "required": [ + "attachment", + "network", + "config" + ] }, "VeilidStateAttachment": { "description": "Describe the attachment state of the Veilid node", "type": "object", - "required": [ - "local_network_ready", - "public_internet_ready", - "state", - "uptime" - ], "properties": { "attached_uptime": { "description": "Uptime since last attach, empty if the node is currently detached", - "type": [ - "string", - "null" + "anyOf": [ + { + "$ref": "#/$defs/TimestampDuration" + }, + { + "type": "null" + } ] }, "local_network_ready": { @@ -4776,70 +4777,225 @@ "type": "boolean" }, "public_internet_ready": { - "description": "If attached and there are enough reachable nodes in the routing table to perform all the actions of the PublicInternet RoutingDomain, including things like private/safety route allocation and DHT operations.", + "description": "If attached and there are enough reachable nodes in the routing table to perform all the actions of the PublicInternet RoutingDomain,\nincluding things like private/safety route allocation and DHT operations.", "type": "boolean" }, "state": { "description": "The overall quality of the routing table if attached, or the current state the attachment state machine.", - "allOf": [ - { - "$ref": "#/definitions/AttachmentState" - } - ] + "$ref": "#/$defs/AttachmentState" }, "uptime": { "description": "Node uptime", - "type": "string" + "$ref": "#/$defs/TimestampDuration" } - } + }, + "required": [ + "state", + "public_internet_ready", + "local_network_ready", + "uptime" + ] }, "VeilidStateConfig": { - "description": "Describe changes to the Veilid node configuration Currently this is only ever emitted once, however we reserve the right to add the ability to change the configuration or have it changed by the Veilid node itself during runtime.", + "description": "Describe changes to the Veilid node configuration\nCurrently this is only ever emitted once, however we reserve the right to\nadd the ability to change the configuration or have it changed by the Veilid node\nitself during runtime.", "type": "object", - "required": [ - "config" - ], "properties": { "config": { "description": "If the Veilid node configuration has changed the full new config will be here.", - "allOf": [ - { - "$ref": "#/definitions/VeilidConfig" - } - ] + "$ref": "#/$defs/VeilidConfig" } - } + }, + "required": [ + "config" + ] }, "VeilidStateNetwork": { "description": "Describe the current network state of the Veilid node", "type": "object", - "required": [ - "bps_down", - "bps_up", - "peers", - "started" - ], "properties": { "bps_down": { "description": "The total number of bytes per second used by Veilid currently in the download direction.", - "type": "string" + "$ref": "#/$defs/ByteCount" }, "bps_up": { "description": "The total number of bytes per second used by Veilid currently in the upload direction.", - "type": "string" + "$ref": "#/$defs/ByteCount" }, "peers": { - "description": "The list of most recently accessed peers. This is not an active connection table, nor is representative of the entire routing table.", + "description": "The list of most recently accessed peers.\nThis is not an active connection table, nor is representative of the entire routing table.", "type": "array", "items": { - "$ref": "#/definitions/PeerTableData" + "$ref": "#/$defs/PeerTableData" } }, "started": { "description": "If the network has been started or not.", "type": "boolean" } - } + }, + "required": [ + "started", + "bps_down", + "bps_up", + "peers" + ] + }, + "VeilidUpdate": { + "description": "An update from the veilid-core to the host application describing a change\nto the internal state of the Veilid node.", + "oneOf": [ + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "Log" + } + }, + "$ref": "#/$defs/VeilidLog", + "required": [ + "kind" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "AppMessage" + } + }, + "$ref": "#/$defs/VeilidAppMessage", + "required": [ + "kind" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "AppCall" + } + }, + "$ref": "#/$defs/VeilidAppCall", + "required": [ + "kind" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "Attachment" + } + }, + "$ref": "#/$defs/VeilidStateAttachment", + "required": [ + "kind" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "Network" + } + }, + "$ref": "#/$defs/VeilidStateNetwork", + "required": [ + "kind" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "Config" + } + }, + "$ref": "#/$defs/VeilidStateConfig", + "required": [ + "kind" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "RouteChange" + } + }, + "$ref": "#/$defs/VeilidRouteChange", + "required": [ + "kind" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "ValueChange" + } + }, + "$ref": "#/$defs/VeilidValueChange", + "required": [ + "kind" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "Shutdown" + } + }, + "required": [ + "kind" + ] + } + ] + }, + "VeilidValueChange": { + "description": "Describe when DHT records have subkey values changed", + "type": "object", + "properties": { + "count": { + "description": "The count remaining on the watch that triggered this value change\nIf there is no watch and this is received, it will be set to u32::MAX\nIf this value is zero, any watch present on the value has died.", + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "key": { + "description": "The DHT Record key that changed", + "type": "string" + }, + "subkeys": { + "description": "The portion of the DHT Record's subkeys that have changed\nIf the subkey range is empty, any watch present on the value has died.", + "$ref": "#/$defs/ValueSubkeyRangeSet" + }, + "value": { + "description": "The (optional) value data for the first subkey in the subkeys range\nIf 'subkeys' is not a single value, other values than the first value\nmust be retrieved with RoutingContext::get_dht_value().", + "anyOf": [ + { + "$ref": "#/$defs/ValueData" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "key", + "subkeys", + "count" + ] } } } diff --git a/veilid-python/veilid/schema/Request.json b/veilid-python/veilid/schema/Request.json index a8308ffd..72504293 100644 --- a/veilid-python/veilid/schema/Request.json +++ b/veilid-python/veilid/schema/Request.json @@ -1,14 +1,19 @@ { - "$schema": "http://json-schema.org/draft-07/schema#", + "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "Request", "type": "object", + "properties": { + "id": { + "description": "Operation Id (pairs with Response, or empty if unidirectional).", + "type": "integer", + "format": "uint32", + "default": 0, + "minimum": 0 + } + }, "oneOf": [ { "type": "object", - "required": [ - "args", - "op" - ], "properties": { "args": { "type": "array", @@ -18,88 +23,92 @@ }, "op": { "type": "string", - "enum": [ - "Control" - ] + "const": "Control" } - } + }, + "required": [ + "op", + "args" + ] }, { "type": "object", - "required": [ - "op" - ], "properties": { "op": { "type": "string", - "enum": [ - "GetState" - ] + "const": "GetState" } - } + }, + "required": [ + "op" + ] }, { "type": "object", - "required": [ - "op" - ], "properties": { "op": { "type": "string", - "enum": [ - "IsShutdown" - ] + "const": "IsShutdown" } - } + }, + "required": [ + "op" + ] }, { "type": "object", - "required": [ - "op" - ], "properties": { "op": { "type": "string", - "enum": [ - "Attach" - ] + "const": "Attach" } - } + }, + "required": [ + "op" + ] }, { "type": "object", - "required": [ - "op" - ], "properties": { "op": { "type": "string", - "enum": [ - "Detach" - ] + "const": "Detach" } - } + }, + "required": [ + "op" + ] }, { "type": "object", - "required": [ - "op" - ], "properties": { "op": { "type": "string", - "enum": [ - "NewPrivateRoute" - ] + "const": "GenerateMemberId" + }, + "writer_key": { + "type": "string" } - } + }, + "required": [ + "op", + "writer_key" + ] }, { "type": "object", + "properties": { + "op": { + "type": "string", + "const": "NewPrivateRoute" + } + }, "required": [ - "kinds", "op" - ], + ] + }, + { + "type": "object", "properties": { "kinds": { "type": "array", @@ -109,71 +118,56 @@ }, "op": { "type": "string", - "enum": [ - "NewCustomPrivateRoute" - ] + "const": "NewCustomPrivateRoute" }, "sequencing": { - "default": "NoPreference", - "allOf": [ - { - "$ref": "#/definitions/Sequencing" - } - ] + "$ref": "#/$defs/Sequencing", + "default": "NoPreference" }, "stability": { - "default": "LowLatency", - "allOf": [ - { - "$ref": "#/definitions/Stability" - } - ] + "$ref": "#/$defs/Stability", + "default": "LowLatency" } - } + }, + "required": [ + "op", + "kinds" + ] }, { "type": "object", - "required": [ - "blob", - "op" - ], "properties": { "blob": { "type": "string" }, "op": { "type": "string", - "enum": [ - "ImportRemotePrivateRoute" - ] + "const": "ImportRemotePrivateRoute" } - } + }, + "required": [ + "op", + "blob" + ] }, { "type": "object", - "required": [ - "op", - "route_id" - ], "properties": { "op": { "type": "string", - "enum": [ - "ReleasePrivateRoute" - ] + "const": "ReleasePrivateRoute" }, "route_id": { "type": "string" } - } + }, + "required": [ + "op", + "route_id" + ] }, { "type": "object", - "required": [ - "call_id", - "message", - "op" - ], "properties": { "call_id": { "type": "string" @@ -183,157 +177,1174 @@ }, "op": { "type": "string", - "enum": [ - "AppCallReply" - ] + "const": "AppCallReply" } - } + }, + "required": [ + "op", + "call_id", + "message" + ] }, { "type": "object", - "required": [ - "op" - ], "properties": { "op": { "type": "string", - "enum": [ - "NewRoutingContext" - ] + "const": "NewRoutingContext" } - } + }, + "required": [ + "op" + ] }, { "type": "object", + "properties": { + "op": { + "type": "string", + "const": "RoutingContext" + } + }, + "$ref": "#/$defs/RoutingContextRequest", + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "column_count": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "name": { + "type": "string" + }, + "op": { + "type": "string", + "const": "OpenTableDb" + } + }, + "required": [ + "op", + "name", + "column_count" + ] + }, + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "op": { + "type": "string", + "const": "DeleteTableDb" + } + }, + "required": [ + "op", + "name" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "TableDb" + } + }, + "$ref": "#/$defs/TableDbRequest", + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "TableDbTransaction" + } + }, + "$ref": "#/$defs/TableDbTransactionRequest", + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string" + }, + "op": { + "type": "string", + "const": "GetCryptoSystem" + } + }, + "required": [ + "op", + "kind" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "BestCryptoSystem" + } + }, + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "CryptoSystem" + } + }, + "$ref": "#/$defs/CryptoSystemRequest", + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "data": { + "type": "string" + }, + "node_ids": { + "type": "array", + "items": { + "type": "string" + } + }, + "op": { + "type": "string", + "const": "VerifySignatures" + }, + "signatures": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "op", + "node_ids", + "data", + "signatures" + ] + }, + { + "type": "object", + "properties": { + "data": { + "type": "string" + }, + "key_pairs": { + "type": "array", + "items": { + "type": "string" + } + }, + "op": { + "type": "string", + "const": "GenerateSignatures" + } + }, + "required": [ + "op", + "data", + "key_pairs" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string" + }, + "op": { + "type": "string", + "const": "GenerateKeyPair" + } + }, + "required": [ + "op", + "kind" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "Now" + } + }, + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "command": { + "type": "string" + }, + "op": { + "type": "string", + "const": "Debug" + } + }, + "required": [ + "op", + "command" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "VeilidVersionString" + } + }, + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "VeilidVersion" + } + }, + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "VeilidFeatures" + } + }, + "required": [ + "op" + ] + }, + { + "type": "object", + "properties": { + "op": { + "type": "string", + "const": "DefaultVeilidConfig" + } + }, + "required": [ + "op" + ] + } + ], + "$defs": { + "AllowOffline": { + "type": "boolean" + }, + "CryptoSystemRequest": { + "type": "object", + "properties": { + "cs_id": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, "oneOf": [ { "type": "object", - "required": [ - "rc_op" - ], "properties": { - "rc_op": { + "cs_op": { "type": "string", - "enum": [ - "Release" - ] + "const": "Release" } - } + }, + "required": [ + "cs_op" + ] }, { "type": "object", - "required": [ - "rc_op" - ], "properties": { - "rc_op": { + "cs_op": { "type": "string", - "enum": [ - "WithDefaultSafety" - ] + "const": "Kind" } - } + }, + "required": [ + "cs_op" + ] }, { "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "CachedDh" + }, + "key": { + "type": "string" + }, + "secret": { + "type": "string" + } + }, + "required": [ + "cs_op", + "key", + "secret" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "ComputeDh" + }, + "key": { + "type": "string" + }, + "secret": { + "type": "string" + } + }, + "required": [ + "cs_op", + "key", + "secret" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "GenerateSharedSecret" + }, + "domain": { + "type": "string" + }, + "key": { + "type": "string" + }, + "secret": { + "type": "string" + } + }, + "required": [ + "cs_op", + "key", + "secret", + "domain" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "RandomBytes" + }, + "len": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "required": [ + "cs_op", + "len" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "SharedSecretLength" + } + }, + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "NonceLength" + } + }, + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "HashDigestLength" + } + }, + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "PublicKeyLength" + } + }, + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "SecretKeyLength" + } + }, + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "SignatureLength" + } + }, + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "DefaultSaltLength" + } + }, + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "AeadOverhead" + } + }, + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "CheckSharedSecret" + }, + "secret": { + "type": "string" + } + }, + "required": [ + "cs_op", + "secret" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "CheckNonce" + }, + "nonce": { + "type": "string" + } + }, + "required": [ + "cs_op", + "nonce" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "CheckHashDigest" + }, + "digest": { + "type": "string" + } + }, + "required": [ + "cs_op", + "digest" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "CheckPublicKey" + }, + "key": { + "type": "string" + } + }, + "required": [ + "cs_op", + "key" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "CheckSecretKey" + }, + "key": { + "type": "string" + } + }, + "required": [ + "cs_op", + "key" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "CheckSignature" + }, + "signature": { + "type": "string" + } + }, + "required": [ + "cs_op", + "signature" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "HashPassword" + }, + "password": { + "type": "string" + }, + "salt": { + "type": "string" + } + }, + "required": [ + "cs_op", + "password", + "salt" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "VerifyPassword" + }, + "password": { + "type": "string" + }, + "password_hash": { + "type": "string" + } + }, + "required": [ + "cs_op", + "password", + "password_hash" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "DeriveSharedSecret" + }, + "password": { + "type": "string" + }, + "salt": { + "type": "string" + } + }, + "required": [ + "cs_op", + "password", + "salt" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "RandomNonce" + } + }, + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "RandomSharedSecret" + } + }, + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "GenerateKeyPair" + } + }, + "required": [ + "cs_op" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "GenerateHash" + }, + "data": { + "type": "string" + } + }, + "required": [ + "cs_op", + "data" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "ValidateKeyPair" + }, + "key": { + "type": "string" + }, + "secret": { + "type": "string" + } + }, + "required": [ + "cs_op", + "key", + "secret" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "ValidateHash" + }, + "data": { + "type": "string" + }, + "hash_digest": { + "type": "string" + } + }, + "required": [ + "cs_op", + "data", + "hash_digest" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "Distance" + }, + "key1": { + "type": "string" + }, + "key2": { + "type": "string" + } + }, + "required": [ + "cs_op", + "key1", + "key2" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "Sign" + }, + "data": { + "type": "string" + }, + "key": { + "type": "string" + }, + "secret": { + "type": "string" + } + }, + "required": [ + "cs_op", + "key", + "secret", + "data" + ] + }, + { + "type": "object", + "properties": { + "cs_op": { + "type": "string", + "const": "Verify" + }, + "data": { + "type": "string" + }, + "key": { + "type": "string" + }, + "signature": { + "type": "string" + } + }, + "required": [ + "cs_op", + "key", + "data", + "signature" + ] + }, + { + "type": "object", + "properties": { + "associated_data": { + "type": [ + "string", + "null" + ] + }, + "body": { + "type": "string" + }, + "cs_op": { + "type": "string", + "const": "DecryptAead" + }, + "nonce": { + "type": "string" + }, + "shared_secret": { + "type": "string" + } + }, + "required": [ + "cs_op", + "body", + "nonce", + "shared_secret" + ] + }, + { + "type": "object", + "properties": { + "associated_data": { + "type": [ + "string", + "null" + ] + }, + "body": { + "type": "string" + }, + "cs_op": { + "type": "string", + "const": "EncryptAead" + }, + "nonce": { + "type": "string" + }, + "shared_secret": { + "type": "string" + } + }, + "required": [ + "cs_op", + "body", + "nonce", + "shared_secret" + ] + }, + { + "type": "object", + "properties": { + "body": { + "type": "string" + }, + "cs_op": { + "type": "string", + "const": "CryptNoAuth" + }, + "nonce": { + "type": "string" + }, + "shared_secret": { + "type": "string" + } + }, + "required": [ + "cs_op", + "body", + "nonce", + "shared_secret" + ] + } + ], + "required": [ + "cs_id" + ] + }, + "DHTReportScope": { + "description": "DHT Record Report Scope", + "oneOf": [ + { + "description": "Return only the local copy sequence numbers\nUseful for seeing what subkeys you have locally and which ones have not been retrieved", + "type": "string", + "const": "Local" + }, + { + "description": "Return the local sequence numbers and the network sequence numbers with GetValue fanout parameters\nProvides an independent view of both the local sequence numbers and the network sequence numbers for nodes that\nwould be reached as if the local copy did not exist locally.\nUseful for determining if the current local copy should be updated from the network.", + "type": "string", + "const": "SyncGet" + }, + { + "description": "Return the local sequence numbers and the network sequence numbers with SetValue fanout parameters\nProvides an independent view of both the local sequence numbers and the network sequence numbers for nodes that\nwould be reached as if the local copy did not exist locally.\nUseful for determining if the unchanged local copy should be pushed to the network.", + "type": "string", + "const": "SyncSet" + }, + { + "description": "Return the local sequence numbers and the network sequence numbers with GetValue fanout parameters\nProvides an view of both the local sequence numbers and the network sequence numbers for nodes that\nwould be reached as if a GetValue operation were being performed, including accepting newer values from the network.\nUseful for determining which subkeys would change with a GetValue operation", + "type": "string", + "const": "UpdateGet" + }, + { + "description": "Return the local sequence numbers and the network sequence numbers with SetValue fanout parameters\nProvides an view of both the local sequence numbers and the network sequence numbers for nodes that\nwould be reached as if a SetValue operation were being performed, including accepting newer values from the network.\nThis simulates a SetValue with the initial sequence number incremented by 1, like a real SetValue would when updating.\nUseful for determine which subkeys would change on an SetValue operation", + "type": "string", + "const": "UpdateSet" + } + ] + }, + "DHTSchema": { + "description": "Enum over all the supported DHT Schemas", + "oneOf": [ + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "DFLT" + } + }, + "$ref": "#/$defs/DHTSchemaDFLT", + "required": [ + "kind" + ] + }, + { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "SMPL" + } + }, + "$ref": "#/$defs/DHTSchemaSMPL", + "required": [ + "kind" + ] + } + ] + }, + "DHTSchemaDFLT": { + "description": "Default DHT Schema (DFLT)", + "type": "object", + "properties": { + "o_cnt": { + "description": "Owner subkey count", + "type": "integer", + "format": "uint16", + "maximum": 65535, + "minimum": 0 + } + }, + "required": [ + "o_cnt" + ] + }, + "DHTSchemaSMPL": { + "description": "Simple DHT Schema (SMPL)", + "type": "object", + "properties": { + "members": { + "description": "Members", + "type": "array", + "items": { + "$ref": "#/$defs/DHTSchemaSMPLMember" + } + }, + "o_cnt": { + "description": "Owner subkey count", + "type": "integer", + "format": "uint16", + "maximum": 65535, + "minimum": 0 + } + }, + "required": [ + "o_cnt", + "members" + ] + }, + "DHTSchemaSMPLMember": { + "description": "Simple DHT Schema (SMPL) Member", + "type": "object", + "properties": { + "m_cnt": { + "description": "Member subkey count", + "type": "integer", + "format": "uint16", + "maximum": 65535, + "minimum": 0 + }, + "m_key": { + "description": "Member key", + "type": "string" + } + }, + "required": [ + "m_key", + "m_cnt" + ] + }, + "RoutingContextRequest": { + "type": "object", + "properties": { + "rc_id": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "oneOf": [ + { + "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "Release" + } + }, + "required": [ + "rc_op" + ] + }, + { + "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "WithDefaultSafety" + } + }, + "required": [ + "rc_op" + ] + }, + { + "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "WithSafety" + }, + "safety_selection": { + "$ref": "#/$defs/SafetySelection" + } + }, "required": [ "rc_op", "safety_selection" - ], - "properties": { - "rc_op": { - "type": "string", - "enum": [ - "WithSafety" - ] - }, - "safety_selection": { - "$ref": "#/definitions/SafetySelection" - } - } + ] }, { "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "WithSequencing" + }, + "sequencing": { + "$ref": "#/$defs/Sequencing" + } + }, "required": [ "rc_op", "sequencing" - ], - "properties": { - "rc_op": { - "type": "string", - "enum": [ - "WithSequencing" - ] - }, - "sequencing": { - "$ref": "#/definitions/Sequencing" - } - } + ] }, { "type": "object", + "properties": { + "rc_op": { + "type": "string", + "const": "Safety" + } + }, "required": [ "rc_op" - ], - "properties": { - "rc_op": { - "type": "string", - "enum": [ - "Safety" - ] - } - } + ] }, { "type": "object", - "required": [ - "message", - "rc_op", - "target" - ], "properties": { "message": { "type": "string" }, "rc_op": { "type": "string", - "enum": [ - "AppCall" - ] + "const": "AppCall" }, "target": { - "type": "string" + "$ref": "#/$defs/Target" } - } + }, + "required": [ + "rc_op", + "target", + "message" + ] }, { "type": "object", - "required": [ - "message", - "rc_op", - "target" - ], "properties": { "message": { "type": "string" }, "rc_op": { "type": "string", - "enum": [ - "AppMessage" - ] + "const": "AppMessage" }, "target": { - "type": "string" + "$ref": "#/$defs/Target" } - } + }, + "required": [ + "rc_op", + "target", + "message" + ] }, { "type": "object", + "properties": { + "owner": { + "type": "string" + }, + "rc_op": { + "type": "string", + "const": "GetDhtRecordKey" + }, + "schema": { + "$ref": "#/$defs/DHTSchema" + } + }, "required": [ "rc_op", - "schema" - ], + "schema", + "owner" + ] + }, + { + "type": "object", "properties": { "kind": { "type": [ @@ -349,30 +1360,26 @@ }, "rc_op": { "type": "string", - "enum": [ - "CreateDhtRecord" - ] + "const": "CreateDhtRecord" }, "schema": { - "$ref": "#/definitions/DHTSchema" + "$ref": "#/$defs/DHTSchema" } - } + }, + "required": [ + "rc_op", + "schema" + ] }, { "type": "object", - "required": [ - "key", - "rc_op" - ], "properties": { "key": { "type": "string" }, "rc_op": { "type": "string", - "enum": [ - "OpenDhtRecord" - ] + "const": "OpenDhtRecord" }, "writer": { "type": [ @@ -380,52 +1387,46 @@ "null" ] } - } - }, - { - "type": "object", + }, "required": [ - "key", - "rc_op" - ], - "properties": { - "key": { - "type": "string" - }, - "rc_op": { - "type": "string", - "enum": [ - "CloseDhtRecord" - ] - } - } - }, - { - "type": "object", - "required": [ - "key", - "rc_op" - ], - "properties": { - "key": { - "type": "string" - }, - "rc_op": { - "type": "string", - "enum": [ - "DeleteDhtRecord" - ] - } - } - }, - { - "type": "object", - "required": [ - "force_refresh", - "key", "rc_op", - "subkey" - ], + "key" + ] + }, + { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "rc_op": { + "type": "string", + "const": "CloseDhtRecord" + } + }, + "required": [ + "rc_op", + "key" + ] + }, + { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "rc_op": { + "type": "string", + "const": "DeleteDhtRecord" + } + }, + "required": [ + "rc_op", + "key" + ] + }, + { + "type": "object", "properties": { "force_refresh": { "type": "boolean" @@ -435,25 +1436,23 @@ }, "rc_op": { "type": "string", - "enum": [ - "GetDhtValue" - ] + "const": "GetDhtValue" }, "subkey": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 } - } + }, + "required": [ + "rc_op", + "key", + "subkey", + "force_refresh" + ] }, { "type": "object", - "required": [ - "data", - "key", - "rc_op", - "subkey" - ], "properties": { "data": { "type": "string" @@ -464,7 +1463,7 @@ "options": { "anyOf": [ { - "$ref": "#/definitions/SetDHTValueOptions" + "$ref": "#/$defs/SetDHTValueOptions" }, { "type": "null" @@ -473,23 +1472,23 @@ }, "rc_op": { "type": "string", - "enum": [ - "SetDhtValue" - ] + "const": "SetDhtValue" }, "subkey": { "type": "integer", "format": "uint32", - "minimum": 0.0 + "minimum": 0 } - } + }, + "required": [ + "rc_op", + "key", + "subkey", + "data" + ] }, { "type": "object", - "required": [ - "key", - "rc_op" - ], "properties": { "count": { "type": [ @@ -497,1334 +1496,142 @@ "null" ], "format": "uint32", - "minimum": 0.0 + "minimum": 0 }, "expiration": { - "type": [ - "string", - "null" - ] - }, - "key": { - "type": "string" - }, - "rc_op": { - "type": "string", - "enum": [ - "WatchDhtValues" - ] - }, - "subkeys": { - "type": [ - "array", - "null" - ], - "items": { - "type": "array", - "items": [ - { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - ], - "maxItems": 2, - "minItems": 2 - } - } - } - }, - { - "type": "object", - "required": [ - "key", - "rc_op" - ], - "properties": { - "key": { - "type": "string" - }, - "rc_op": { - "type": "string", - "enum": [ - "CancelDhtWatch" - ] - }, - "subkeys": { - "type": [ - "array", - "null" - ], - "items": { - "type": "array", - "items": [ - { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - ], - "maxItems": 2, - "minItems": 2 - } - } - } - }, - { - "type": "object", - "required": [ - "key", - "rc_op" - ], - "properties": { - "key": { - "type": "string" - }, - "rc_op": { - "type": "string", - "enum": [ - "InspectDhtRecord" - ] - }, - "scope": { - "default": "Local", - "allOf": [ + "anyOf": [ { - "$ref": "#/definitions/DHTReportScope" + "$ref": "#/$defs/Timestamp" + }, + { + "type": "null" } ] }, + "key": { + "type": "string" + }, + "rc_op": { + "type": "string", + "const": "WatchDhtValues" + }, "subkeys": { - "type": [ - "array", - "null" - ], - "items": { - "type": "array", - "items": [ - { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - ], - "maxItems": 2, - "minItems": 2 - } + "anyOf": [ + { + "$ref": "#/$defs/ValueSubkeyRangeSet" + }, + { + "type": "null" + } + ] } - } + }, + "required": [ + "rc_op", + "key" + ] + }, + { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "rc_op": { + "type": "string", + "const": "CancelDhtWatch" + }, + "subkeys": { + "anyOf": [ + { + "$ref": "#/$defs/ValueSubkeyRangeSet" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "rc_op", + "key" + ] + }, + { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "rc_op": { + "type": "string", + "const": "InspectDhtRecord" + }, + "scope": { + "$ref": "#/$defs/DHTReportScope", + "default": "Local" + }, + "subkeys": { + "anyOf": [ + { + "$ref": "#/$defs/ValueSubkeyRangeSet" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "rc_op", + "key" + ] } ], "required": [ - "op", "rc_id" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "RoutingContext" - ] - }, - "rc_id": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - } - }, - { - "type": "object", - "required": [ - "column_count", - "name", - "op" - ], - "properties": { - "column_count": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "name": { - "type": "string" - }, - "op": { - "type": "string", - "enum": [ - "OpenTableDb" - ] - } - } - }, - { - "type": "object", - "required": [ - "name", - "op" - ], - "properties": { - "name": { - "type": "string" - }, - "op": { - "type": "string", - "enum": [ - "DeleteTableDb" - ] - } - } - }, - { - "type": "object", - "oneOf": [ - { - "type": "object", - "required": [ - "db_op" - ], - "properties": { - "db_op": { - "type": "string", - "enum": [ - "Release" - ] - } - } - }, - { - "type": "object", - "required": [ - "db_op" - ], - "properties": { - "db_op": { - "type": "string", - "enum": [ - "GetColumnCount" - ] - } - } - }, - { - "type": "object", - "required": [ - "col", - "db_op" - ], - "properties": { - "col": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "db_op": { - "type": "string", - "enum": [ - "GetKeys" - ] - } - } - }, - { - "type": "object", - "required": [ - "db_op" - ], - "properties": { - "db_op": { - "type": "string", - "enum": [ - "Transact" - ] - } - } - }, - { - "type": "object", - "required": [ - "col", - "db_op", - "key", - "value" - ], - "properties": { - "col": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "db_op": { - "type": "string", - "enum": [ - "Store" - ] - }, - "key": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "col", - "db_op", - "key" - ], - "properties": { - "col": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "db_op": { - "type": "string", - "enum": [ - "Load" - ] - }, - "key": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "col", - "db_op", - "key" - ], - "properties": { - "col": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "db_op": { - "type": "string", - "enum": [ - "Delete" - ] - }, - "key": { - "type": "string" - } - } - } - ], - "required": [ - "db_id", - "op" - ], - "properties": { - "db_id": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "op": { - "type": "string", - "enum": [ - "TableDb" - ] - } - } - }, - { - "type": "object", - "oneOf": [ - { - "type": "object", - "required": [ - "tx_op" - ], - "properties": { - "tx_op": { - "type": "string", - "enum": [ - "Commit" - ] - } - } - }, - { - "type": "object", - "required": [ - "tx_op" - ], - "properties": { - "tx_op": { - "type": "string", - "enum": [ - "Rollback" - ] - } - } - }, - { - "type": "object", - "required": [ - "col", - "key", - "tx_op", - "value" - ], - "properties": { - "col": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "key": { - "type": "string" - }, - "tx_op": { - "type": "string", - "enum": [ - "Store" - ] - }, - "value": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "col", - "key", - "tx_op" - ], - "properties": { - "col": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "key": { - "type": "string" - }, - "tx_op": { - "type": "string", - "enum": [ - "Delete" - ] - } - } - } - ], - "required": [ - "op", - "tx_id" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "TableDbTransaction" - ] - }, - "tx_id": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - } - }, - { - "type": "object", - "required": [ - "kind", - "op" - ], - "properties": { - "kind": { - "type": "string" - }, - "op": { - "type": "string", - "enum": [ - "GetCryptoSystem" - ] - } - } - }, - { - "type": "object", - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "BestCryptoSystem" - ] - } - } - }, - { - "type": "object", - "oneOf": [ - { - "type": "object", - "required": [ - "cs_op" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "Release" - ] - } - } - }, - { - "type": "object", - "required": [ - "cs_op" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "Kind" - ] - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "key", - "secret" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "CachedDh" - ] - }, - "key": { - "type": "string" - }, - "secret": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "key", - "secret" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "ComputeDh" - ] - }, - "key": { - "type": "string" - }, - "secret": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "domain", - "key", - "secret" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "GenerateSharedSecret" - ] - }, - "domain": { - "type": "string" - }, - "key": { - "type": "string" - }, - "secret": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "len" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "RandomBytes" - ] - }, - "len": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - } - }, - { - "type": "object", - "required": [ - "cs_op" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "DefaultSaltLength" - ] - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "password", - "salt" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "HashPassword" - ] - }, - "password": { - "type": "string" - }, - "salt": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "password", - "password_hash" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "VerifyPassword" - ] - }, - "password": { - "type": "string" - }, - "password_hash": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "password", - "salt" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "DeriveSharedSecret" - ] - }, - "password": { - "type": "string" - }, - "salt": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "cs_op" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "RandomNonce" - ] - } - } - }, - { - "type": "object", - "required": [ - "cs_op" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "RandomSharedSecret" - ] - } - } - }, - { - "type": "object", - "required": [ - "cs_op" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "GenerateKeyPair" - ] - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "data" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "GenerateHash" - ] - }, - "data": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "key", - "secret" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "ValidateKeyPair" - ] - }, - "key": { - "type": "string" - }, - "secret": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "data", - "hash_digest" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "ValidateHash" - ] - }, - "data": { - "type": "string" - }, - "hash_digest": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "key1", - "key2" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "Distance" - ] - }, - "key1": { - "type": "string" - }, - "key2": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "data", - "key", - "secret" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "Sign" - ] - }, - "data": { - "type": "string" - }, - "key": { - "type": "string" - }, - "secret": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "cs_op", - "data", - "key", - "signature" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "Verify" - ] - }, - "data": { - "type": "string" - }, - "key": { - "type": "string" - }, - "signature": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "cs_op" - ], - "properties": { - "cs_op": { - "type": "string", - "enum": [ - "AeadOverhead" - ] - } - } - }, - { - "type": "object", - "required": [ - "body", - "cs_op", - "nonce", - "shared_secret" - ], - "properties": { - "associated_data": { - "type": [ - "string", - "null" - ] - }, - "body": { - "type": "string" - }, - "cs_op": { - "type": "string", - "enum": [ - "DecryptAead" - ] - }, - "nonce": { - "type": "string" - }, - "shared_secret": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "body", - "cs_op", - "nonce", - "shared_secret" - ], - "properties": { - "associated_data": { - "type": [ - "string", - "null" - ] - }, - "body": { - "type": "string" - }, - "cs_op": { - "type": "string", - "enum": [ - "EncryptAead" - ] - }, - "nonce": { - "type": "string" - }, - "shared_secret": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "body", - "cs_op", - "nonce", - "shared_secret" - ], - "properties": { - "body": { - "type": "string" - }, - "cs_op": { - "type": "string", - "enum": [ - "CryptNoAuth" - ] - }, - "nonce": { - "type": "string" - }, - "shared_secret": { - "type": "string" - } - } - } - ], - "required": [ - "cs_id", - "op" - ], - "properties": { - "cs_id": { - "type": "integer", - "format": "uint32", - "minimum": 0.0 - }, - "op": { - "type": "string", - "enum": [ - "CryptoSystem" - ] - } - } - }, - { - "type": "object", - "required": [ - "data", - "node_ids", - "op", - "signatures" - ], - "properties": { - "data": { - "type": "string" - }, - "node_ids": { - "type": "array", - "items": { - "type": "string" - } - }, - "op": { - "type": "string", - "enum": [ - "VerifySignatures" - ] - }, - "signatures": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - { - "type": "object", - "required": [ - "data", - "key_pairs", - "op" - ], - "properties": { - "data": { - "type": "string" - }, - "key_pairs": { - "type": "array", - "items": { - "type": "string" - } - }, - "op": { - "type": "string", - "enum": [ - "GenerateSignatures" - ] - } - } - }, - { - "type": "object", - "required": [ - "kind", - "op" - ], - "properties": { - "kind": { - "type": "string" - }, - "op": { - "type": "string", - "enum": [ - "GenerateKeyPair" - ] - } - } - }, - { - "type": "object", - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "Now" - ] - } - } - }, - { - "type": "object", - "required": [ - "command", - "op" - ], - "properties": { - "command": { - "type": "string" - }, - "op": { - "type": "string", - "enum": [ - "Debug" - ] - } - } - }, - { - "type": "object", - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "VeilidVersionString" - ] - } - } - }, - { - "type": "object", - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "VeilidVersion" - ] - } - } - }, - { - "type": "object", - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "VeilidFeatures" - ] - } - } - }, - { - "type": "object", - "required": [ - "op" - ], - "properties": { - "op": { - "type": "string", - "enum": [ - "DefaultVeilidConfig" - ] - } - } - } - ], - "properties": { - "id": { - "description": "Operation Id (pairs with Response, or empty if unidirectional).", - "default": 0, - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - }, - "definitions": { - "AllowOffline": { - "type": "boolean" - }, - "DHTReportScope": { - "description": "DHT Record Report Scope", - "oneOf": [ - { - "description": "Return only the local copy sequence numbers Useful for seeing what subkeys you have locally and which ones have not been retrieved", - "type": "string", - "enum": [ - "Local" - ] - }, - { - "description": "Return the local sequence numbers and the network sequence numbers with GetValue fanout parameters Provides an independent view of both the local sequence numbers and the network sequence numbers for nodes that would be reached as if the local copy did not exist locally. Useful for determining if the current local copy should be updated from the network.", - "type": "string", - "enum": [ - "SyncGet" - ] - }, - { - "description": "Return the local sequence numbers and the network sequence numbers with SetValue fanout parameters Provides an independent view of both the local sequence numbers and the network sequence numbers for nodes that would be reached as if the local copy did not exist locally. Useful for determining if the unchanged local copy should be pushed to the network.", - "type": "string", - "enum": [ - "SyncSet" - ] - }, - { - "description": "Return the local sequence numbers and the network sequence numbers with GetValue fanout parameters Provides an view of both the local sequence numbers and the network sequence numbers for nodes that would be reached as if a GetValue operation were being performed, including accepting newer values from the network. Useful for determining which subkeys would change with a GetValue operation", - "type": "string", - "enum": [ - "UpdateGet" - ] - }, - { - "description": "Return the local sequence numbers and the network sequence numbers with SetValue fanout parameters Provides an view of both the local sequence numbers and the network sequence numbers for nodes that would be reached as if a SetValue operation were being performed, including accepting newer values from the network. This simulates a SetValue with the initial sequence number incremented by 1, like a real SetValue would when updating. Useful for determine which subkeys would change on an SetValue operation", - "type": "string", - "enum": [ - "UpdateSet" - ] - } ] }, - "DHTSchema": { - "description": "Enum over all the supported DHT Schemas", - "oneOf": [ - { - "description": "Default DHT Schema (DFLT)", - "type": "object", - "required": [ - "kind", - "o_cnt" - ], - "properties": { - "kind": { - "type": "string", - "enum": [ - "DFLT" - ] - }, - "o_cnt": { - "description": "Owner subkey count", - "type": "integer", - "format": "uint16", - "minimum": 0.0 - } - } - }, - { - "description": "Simple DHT Schema (SMPL)", - "type": "object", - "required": [ - "kind", - "members", - "o_cnt" - ], - "properties": { - "kind": { - "type": "string", - "enum": [ - "SMPL" - ] - }, - "members": { - "description": "Members", - "type": "array", - "items": { - "$ref": "#/definitions/DHTSchemaSMPLMember" - } - }, - "o_cnt": { - "description": "Owner subkey count", - "type": "integer", - "format": "uint16", - "minimum": 0.0 - } - } - } - ] - }, - "DHTSchemaSMPLMember": { - "description": "Simple DHT Schema (SMPL) Member", - "type": "object", - "required": [ - "m_cnt", - "m_key" - ], - "properties": { - "m_cnt": { - "description": "Member subkey count", - "type": "integer", - "format": "uint16", - "minimum": 0.0 - }, - "m_key": { - "description": "Member key", - "type": "string" - } - } - }, "SafetySelection": { "description": "The choice of safety route to include in compiled routes.", "oneOf": [ { "description": "Don't use a safety route, only specify the sequencing preference.", "type": "object", - "required": [ - "Unsafe" - ], "properties": { "Unsafe": { - "$ref": "#/definitions/Sequencing" + "$ref": "#/$defs/Sequencing" } }, - "additionalProperties": false + "additionalProperties": false, + "required": [ + "Unsafe" + ] }, { "description": "Use a safety route and parameters specified by a SafetySpec.", "type": "object", - "required": [ - "Safe" - ], "properties": { "Safe": { - "$ref": "#/definitions/SafetySpec" + "$ref": "#/$defs/SafetySpec" } }, - "additionalProperties": false + "additionalProperties": false, + "required": [ + "Safe" + ] } ] }, "SafetySpec": { "description": "Options for safety routes (sender privacy).", "type": "object", - "required": [ - "hop_count", - "sequencing", - "stability" - ], "properties": { "hop_count": { "description": "Must be greater than 0.", "type": "integer", "format": "uint", - "minimum": 0.0 + "minimum": 0 }, "preferred_route": { "description": "Preferred safety route set id if it still exists.", @@ -1835,21 +1642,18 @@ }, "sequencing": { "description": "Prefer connection-oriented sequenced protocols.", - "allOf": [ - { - "$ref": "#/definitions/Sequencing" - } - ] + "$ref": "#/$defs/Sequencing" }, "stability": { "description": "Prefer reliability over speed.", - "allOf": [ - { - "$ref": "#/definitions/Stability" - } - ] + "$ref": "#/$defs/Stability" } - } + }, + "required": [ + "hop_count", + "stability", + "sequencing" + ] }, "Sequencing": { "type": "string", @@ -1863,10 +1667,10 @@ "type": "object", "properties": { "allow_offline": { - "description": "Defaults to true. If false, the value will not be written if the node is offline, and a TryAgain error will be returned.", + "description": "Defaults to true. If false, the value will not be written if the node is offline,\nand a TryAgain error will be returned.", "anyOf": [ { - "$ref": "#/definitions/AllowOffline" + "$ref": "#/$defs/AllowOffline" }, { "type": "null" @@ -1887,6 +1691,286 @@ "LowLatency", "Reliable" ] + }, + "TableDbRequest": { + "type": "object", + "properties": { + "db_id": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "oneOf": [ + { + "type": "object", + "properties": { + "db_op": { + "type": "string", + "const": "Release" + } + }, + "required": [ + "db_op" + ] + }, + { + "type": "object", + "properties": { + "db_op": { + "type": "string", + "const": "GetColumnCount" + } + }, + "required": [ + "db_op" + ] + }, + { + "type": "object", + "properties": { + "col": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "db_op": { + "type": "string", + "const": "GetKeys" + } + }, + "required": [ + "db_op", + "col" + ] + }, + { + "type": "object", + "properties": { + "db_op": { + "type": "string", + "const": "Transact" + } + }, + "required": [ + "db_op" + ] + }, + { + "type": "object", + "properties": { + "col": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "db_op": { + "type": "string", + "const": "Store" + }, + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "db_op", + "col", + "key", + "value" + ] + }, + { + "type": "object", + "properties": { + "col": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "db_op": { + "type": "string", + "const": "Load" + }, + "key": { + "type": "string" + } + }, + "required": [ + "db_op", + "col", + "key" + ] + }, + { + "type": "object", + "properties": { + "col": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "db_op": { + "type": "string", + "const": "Delete" + }, + "key": { + "type": "string" + } + }, + "required": [ + "db_op", + "col", + "key" + ] + } + ], + "required": [ + "db_id" + ] + }, + "TableDbTransactionRequest": { + "type": "object", + "properties": { + "tx_id": { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + }, + "oneOf": [ + { + "type": "object", + "properties": { + "tx_op": { + "type": "string", + "const": "Commit" + } + }, + "required": [ + "tx_op" + ] + }, + { + "type": "object", + "properties": { + "tx_op": { + "type": "string", + "const": "Rollback" + } + }, + "required": [ + "tx_op" + ] + }, + { + "type": "object", + "properties": { + "col": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "key": { + "type": "string" + }, + "tx_op": { + "type": "string", + "const": "Store" + }, + "value": { + "type": "string" + } + }, + "required": [ + "tx_op", + "col", + "key", + "value" + ] + }, + { + "type": "object", + "properties": { + "col": { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + "key": { + "type": "string" + }, + "tx_op": { + "type": "string", + "const": "Delete" + } + }, + "required": [ + "tx_op", + "col", + "key" + ] + } + ], + "required": [ + "tx_id" + ] + }, + "Target": { + "description": "Valid destinations for a message sent over a routing context.", + "oneOf": [ + { + "description": "Node by its node id", + "type": "object", + "properties": { + "NodeId": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "NodeId" + ] + }, + { + "description": "Remote private route by its id.", + "type": "object", + "properties": { + "RouteId": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "RouteId" + ] + } + ] + }, + "Timestamp": { + "type": "string" + }, + "ValueSubkeyRangeSet": { + "type": "array", + "items": { + "type": "array", + "maxItems": 2, + "minItems": 2, + "prefixItems": [ + { + "type": "integer", + "format": "uint32", + "minimum": 0 + }, + { + "type": "integer", + "format": "uint32", + "minimum": 0 + } + ] + } } } } diff --git a/veilid-python/veilid/types.py b/veilid-python/veilid/types.py index 68ad4870..b0bcebda 100644 --- a/veilid-python/veilid/types.py +++ b/veilid-python/veilid/types.py @@ -85,6 +85,9 @@ class SafetySelectionKind(StrEnum): UNSAFE = "Unsafe" SAFE = "Safe" +class TargetKind(StrEnum): + ROUTE_ID= "RouteId" + NODE_ID = "NodeId" class DHTReportScope(StrEnum): LOCAL = "Local" @@ -112,11 +115,6 @@ class ByteCount(int): class OperationId(str): pass - -class BareRouteId(str): - pass - - class EncodedString(str): def to_bytes(self) -> bytes: return urlsafe_b64decode_no_pad(self) @@ -126,35 +124,41 @@ class EncodedString(str): assert isinstance(b, bytes) return cls(urlsafe_b64encode_no_pad(b)) - class BareHashDistance(EncodedString): pass +class BareRecordKey(EncodedString): + pass class BarePublicKey(EncodedString): pass - class BareSecretKey(EncodedString): pass - class BareSharedSecret(EncodedString): pass - class BareHashDigest(EncodedString): pass - class BareSignature(EncodedString): pass - class BareNonce(EncodedString): pass +class BareRouteId(EncodedString): + pass + +class BareNodeId(EncodedString): + pass + +class BareMemberId(EncodedString): + pass + + class BareKeyPair(str): @classmethod def from_parts(cls, key: BarePublicKey, secret: BareSecretKey) -> Self: @@ -168,11 +172,6 @@ class BareKeyPair(str): def secret(self) -> BareSecretKey: return BareSecretKey(self.split(":", 1)[1]) - def to_parts(self) -> tuple[BarePublicKey, BareSecretKey]: - public, secret = self.split(":", 1) - return (BarePublicKey(public), BareSecretKey(secret)) - - class CryptoTyped(str): def kind(self) -> CryptoKind: if self[4] != ":": @@ -185,6 +184,16 @@ class CryptoTyped(str): return self[5:] +class RecordKey(CryptoTyped): + @classmethod + def from_value(cls, kind: CryptoKind, value: BareRecordKey) -> Self: + assert isinstance(kind, CryptoKind) + assert isinstance(value, BareRecordKey) + return cls(f"{kind}:{value}") + + def value(self) -> BareRecordKey: + return BareRecordKey(self._value()) + class PublicKey(CryptoTyped): @classmethod def from_value(cls, kind: CryptoKind, value: BarePublicKey) -> Self: @@ -217,6 +226,11 @@ class KeyPair(CryptoTyped): def value(self) -> BareKeyPair: return BareKeyPair(self._value()) + def key(self) -> PublicKey: + return PublicKey.from_value(kind=self.kind(), value=self.value().key()) + + def secret(self) -> SecretKey: + return SecretKey.from_value(kind=self.kind(), value=self.value().secret()) class Signature(CryptoTyped): @classmethod @@ -228,6 +242,35 @@ class Signature(CryptoTyped): def value(self) -> BareSignature: return BareSignature(self._value()) +class RouteId(CryptoTyped): + @classmethod + def from_value(cls, kind: CryptoKind, value: BareRouteId) -> Self: + assert isinstance(kind, CryptoKind) + assert isinstance(value, BareRouteId) + return cls(f"{kind}:{value}") + + def value(self) -> BareRouteId: + return BareRouteId(self._value()) + +class NodeId(CryptoTyped): + @classmethod + def from_value(cls, kind: CryptoKind, value: BareNodeId) -> Self: + assert isinstance(kind, CryptoKind) + assert isinstance(value, BareNodeId) + return cls(f"{kind}:{value}") + + def value(self) -> BareNodeId: + return BareNodeId(self._value()) + +class MemberId(CryptoTyped): + @classmethod + def from_value(cls, kind: CryptoKind, value: BareMemberId) -> Self: + assert isinstance(kind, CryptoKind) + assert isinstance(value, BareMemberId) + return cls(f"{kind}:{value}") + + def value(self) -> BareMemberId: + return BareMemberId(self._value()) class ValueSubkey(int): pass @@ -287,30 +330,30 @@ class VeilidVersion: class NewPrivateRouteResult: - route_id: BareRouteId + route_id: RouteId blob: bytes - def __init__(self, route_id: BareRouteId, blob: bytes): - assert isinstance(route_id, BareRouteId) + def __init__(self, route_id: RouteId, blob: bytes): + assert isinstance(route_id, RouteId) assert isinstance(blob, bytes) self.route_id = route_id self.blob = blob - def to_tuple(self) -> tuple[BareRouteId, bytes]: + def to_tuple(self) -> tuple[RouteId, bytes]: return (self.route_id, self.blob) @classmethod def from_json(cls, j: dict) -> Self: - return cls(BareRouteId(j["route_id"]), urlsafe_b64decode_no_pad(j["blob"])) + return cls(RouteId(j["route_id"]), urlsafe_b64decode_no_pad(j["blob"])) class DHTSchemaSMPLMember: - m_key: BarePublicKey + m_key: BareMemberId m_cnt: int - def __init__(self, m_key: BarePublicKey, m_cnt: int): - assert isinstance(m_key, BarePublicKey) + def __init__(self, m_key: BareMemberId, m_cnt: int): + assert isinstance(m_key, BareMemberId) assert isinstance(m_cnt, int) self.m_key = m_key @@ -318,7 +361,7 @@ class DHTSchemaSMPLMember: @classmethod def from_json(cls, j: dict) -> Self: - return cls(BarePublicKey(j["m_key"]), j["m_cnt"]) + return cls(BareMemberId(j["m_key"]), j["m_cnt"]) def to_json(self) -> dict: return self.__dict__ @@ -401,15 +444,15 @@ class DHTSchemaSMPL(DHTSchema): raise Exception("Invalid DHTSchemaSMPL") class DHTRecordDescriptor: - key: PublicKey - owner: BarePublicKey + key: RecordKey + owner: PublicKey owner_secret: Optional[BareSecretKey] schema: DHTSchema def __init__( self, - key: PublicKey, - owner: BarePublicKey, + key: RecordKey, + owner: PublicKey, owner_secret: Optional[BareSecretKey], schema: DHTSchema, ): @@ -421,16 +464,21 @@ class DHTRecordDescriptor: def __repr__(self) -> str: return f"<{self.__class__.__name__}(key={self.key!r}, owner={self.owner!r}, owner_secret={self.owner_secret!r}, schema={self.schema!r})>" - def owner_key_pair(self) -> Optional[BareKeyPair]: + def owner_bare_key_pair(self) -> Optional[BareKeyPair]: if self.owner_secret is None: return None - return BareKeyPair.from_parts(self.owner, self.owner_secret) + return BareKeyPair.from_parts(self.owner.value(), self.owner_secret) + + def owner_key_pair(self) -> Optional[KeyPair]: + if self.owner_secret is None: + return None + return KeyPair.from_value(self.owner.kind(), BareKeyPair.from_parts(self.owner.value(), self.owner_secret)) @classmethod def from_json(cls, j: dict) -> Self: return cls( - PublicKey(j["key"]), - BarePublicKey(j["owner"]), + RecordKey(j["key"]), + PublicKey(j["owner"]), None if j["owner_secret"] is None else BareSecretKey(j["owner_secret"]), DHTSchema.from_json(j["schema"]), ) @@ -475,10 +523,10 @@ class DHTRecordReport: class SetDHTValueOptions: - writer: Optional[BareKeyPair] + writer: Optional[KeyPair] allow_offline: Optional[bool] - def __init__(self, writer: Optional[BareKeyPair] = None, allow_offline: Optional[bool] = None): + def __init__(self, writer: Optional[KeyPair] = None, allow_offline: Optional[bool] = None): self.writer = writer self.allow_offline = allow_offline @@ -488,7 +536,7 @@ class SetDHTValueOptions: @classmethod def from_json(cls, j: dict) -> Self: return cls( - BareKeyPair(j["writer"]) if "writer" in j else None, + KeyPair(j["writer"]) if "writer" in j else None, j["allow_offline"] if "allow_offline" in j else None, ) @@ -499,9 +547,9 @@ class SetDHTValueOptions: class ValueData: seq: ValueSeqNum data: bytes - writer: BarePublicKey + writer: PublicKey - def __init__(self, seq: ValueSeqNum, data: bytes, writer: BarePublicKey): + def __init__(self, seq: ValueSeqNum, data: bytes, writer: PublicKey): self.seq = seq self.data = data self.writer = writer @@ -537,7 +585,7 @@ class ValueData: return cls( ValueSeqNum(j["seq"]), urlsafe_b64decode_no_pad(j["data"]), - BarePublicKey(j["writer"]), + PublicKey(j["writer"]), ) def to_json(self) -> dict: @@ -645,3 +693,74 @@ class SafetySelectionSafe(SafetySelection): def to_json(self) -> dict: return {"Safe": self.safety_spec.to_json()} + + + +class Target(ABC): + + @property + @abstractmethod + def kind(self) -> TargetKind: + pass + + @classmethod + def node_id(cls, node_id: NodeId) -> Self: + return TargetNodeId(node_id=node_id) # type: ignore + + @classmethod + def route_id(cls, route_id: RouteId) -> Self: + return TargetRouteId(route_id=route_id) # type: ignore + + @classmethod + def from_json(cls, j: dict) -> Self: + if "NodeId" in j: + return cls.node_id(NodeId(j["NodeId"])) + elif "RouteId" in j: + return cls.route_id(RouteId(j["Unsafe"])) + raise Exception("Invalid Target") + + @abstractmethod + def to_json(self) -> dict: + pass + +@final +class TargetNodeId(Target): + id: NodeId + + def __init__(self, node_id: NodeId): + assert isinstance(node_id, NodeId) + self.id = node_id + + @property + def kind(self): + return TargetKind.NODE_ID + + @classmethod + def from_json(cls, j: dict) -> Self: + if "NodeId" in j: + return cls(NodeId(j["NodeId"])) + raise Exception("Invalid TargetNodeId") + + def to_json(self) -> dict: + return {"NodeId": self.id} + +@final +class TargetRouteId(Target): + id: RouteId + + def __init__(self, route_id: RouteId): + assert isinstance(route_id, RouteId) + self.id = route_id + + @property + def kind(self): + return TargetKind.ROUTE_ID + + @classmethod + def from_json(cls, j: dict) -> Self: + if "RouteId" in j: + return cls(RouteId(j["RouteId"])) + raise Exception("Invalid TargetRouteId") + + def to_json(self) -> dict: + return {"RouteId": self.id} diff --git a/veilid-remote-api/Cargo.toml b/veilid-remote-api/Cargo.toml index 21fa447c..ef69e68e 100644 --- a/veilid-remote-api/Cargo.toml +++ b/veilid-remote-api/Cargo.toml @@ -21,7 +21,7 @@ veilid-core = { version = "0.4.8", path = "../veilid-core" } tracing = { version = "^0", features = ["log", "attributes"] } serde = { version = "1.0.218", features = ["derive", "rc"] } serde_json = { version = "1.0.140" } -schemars = "0.8.22" +schemars = "1.0.3" parking_lot = "0.12.3" [lints] diff --git a/veilid-remote-api/src/crypto_system.rs b/veilid-remote-api/src/crypto_system.rs index 46c8fcd0..b2fd3b6a 100644 --- a/veilid-remote-api/src/crypto_system.rs +++ b/veilid-remote-api/src/crypto_system.rs @@ -43,7 +43,38 @@ pub enum CryptoSystemRequestOp { RandomBytes { len: u32, }, + SharedSecretLength, + NonceLength, + HashDigestLength, + PublicKeyLength, + SecretKeyLength, + SignatureLength, DefaultSaltLength, + AeadOverhead, + CheckSharedSecret { + #[schemars(with = "String")] + secret: BareSharedSecret, + }, + CheckNonce { + #[schemars(with = "String")] + nonce: BareNonce, + }, + CheckHashDigest { + #[schemars(with = "String")] + digest: BareHashDigest, + }, + CheckPublicKey { + #[schemars(with = "String")] + key: BarePublicKey, + }, + CheckSecretKey { + #[schemars(with = "String")] + key: BareSecretKey, + }, + CheckSignature { + #[schemars(with = "String")] + signature: BareSignature, + }, HashPassword { #[serde(with = "as_human_base64")] #[schemars(with = "String")] @@ -111,7 +142,6 @@ pub enum CryptoSystemRequestOp { #[schemars(with = "String")] signature: BareSignature, }, - AeadOverhead, DecryptAead { #[serde(with = "as_human_base64")] #[schemars(with = "String")] @@ -175,9 +205,54 @@ pub enum CryptoSystemResponseOp { #[schemars(with = "String")] value: Vec, }, + SharedSecretLength { + value: u32, + }, + NonceLength { + value: u32, + }, + HashDigestLength { + value: u32, + }, + PublicKeyLength { + value: u32, + }, + SecretKeyLength { + value: u32, + }, + SignatureLength { + value: u32, + }, DefaultSaltLength { value: u32, }, + AeadOverhead { + value: u32, + }, + CheckSharedSecret { + #[serde(flatten)] + result: ApiResult<()>, + }, + CheckNonce { + #[serde(flatten)] + result: ApiResult<()>, + }, + CheckHashDigest { + #[serde(flatten)] + result: ApiResult<()>, + }, + CheckPublicKey { + #[serde(flatten)] + result: ApiResult<()>, + }, + CheckSecretKey { + #[serde(flatten)] + result: ApiResult<()>, + }, + CheckSignature { + #[serde(flatten)] + result: ApiResult<()>, + }, HashPassword { #[serde(flatten)] result: ApiResult, @@ -226,9 +301,6 @@ pub enum CryptoSystemResponseOp { #[serde(flatten)] result: ApiResult, }, - AeadOverhead { - value: u32, - }, DecryptAead { #[serde(flatten)] #[schemars(with = "ApiResult")] @@ -240,8 +312,8 @@ pub enum CryptoSystemResponseOp { result: ApiResultWithVecU8, }, CryptNoAuth { - #[serde(with = "as_human_base64")] - #[schemars(with = "String")] - value: Vec, + #[serde(flatten)] + #[schemars(with = "ApiResult")] + result: ApiResultWithVecU8, }, } diff --git a/veilid-remote-api/src/lib.rs b/veilid-remote-api/src/lib.rs index 257f9907..c254e705 100644 --- a/veilid-remote-api/src/lib.rs +++ b/veilid-remote-api/src/lib.rs @@ -63,6 +63,10 @@ pub enum RequestOp { IsShutdown, Attach, Detach, + GenerateMemberId { + #[schemars(with = "String")] + writer_key: PublicKey, + }, NewPrivateRoute, NewCustomPrivateRoute { #[schemars(with = "Vec")] @@ -79,7 +83,7 @@ pub enum RequestOp { }, ReleasePrivateRoute { #[schemars(with = "String")] - route_id: BareRouteId, + route_id: RouteId, }, AppCallReply { #[schemars(with = "String")] @@ -142,7 +146,7 @@ pub enum RequestOp { #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] pub struct NewPrivateRouteResult { #[schemars(with = "String")] - route_id: BareRouteId, + route_id: RouteId, #[serde(with = "as_human_base64")] #[schemars(with = "String")] blob: Vec, @@ -170,6 +174,11 @@ pub enum ResponseOp { #[serde(flatten)] result: ApiResult<()>, }, + GenerateMemberId { + #[serde(flatten)] + #[schemars(with = "ApiResult")] + result: ApiResultWithString, + }, NewPrivateRoute { #[serde(flatten)] result: ApiResult, @@ -181,7 +190,7 @@ pub enum ResponseOp { ImportRemotePrivateRoute { #[serde(flatten)] #[schemars(with = "ApiResult")] - result: ApiResultWithString, + result: ApiResultWithString, }, ReleasePrivateRoute { #[serde(flatten)] diff --git a/veilid-remote-api/src/process.rs b/veilid-remote-api/src/process.rs index d5146063..6f14020c 100644 --- a/veilid-remote-api/src/process.rs +++ b/veilid-remote-api/src/process.rs @@ -256,24 +256,21 @@ impl JsonRequestProcessor { RoutingContextRequestOp::AppCall { target, message } => { RoutingContextResponseOp::AppCall { result: to_json_api_result_with_vec_u8( - async { - routing_context - .app_call(self.api.parse_as_target(target)?, message) - .await - } - .await, + async { routing_context.app_call(target, message).await }.await, ), } } RoutingContextRequestOp::AppMessage { target, message } => { RoutingContextResponseOp::AppMessage { result: to_json_api_result( - async { - routing_context - .app_message(self.api.parse_as_target(target)?, message) - .await - } - .await, + async { routing_context.app_message(target, message).await }.await, + ), + } + } + RoutingContextRequestOp::GetDhtRecordKey { schema, owner } => { + RoutingContextResponseOp::GetDhtRecordKey { + result: to_json_api_result_with_string( + routing_context.get_dht_record_key(schema, &owner), ), } } @@ -482,9 +479,60 @@ impl JsonRequestProcessor { CryptoSystemRequestOp::RandomBytes { len } => CryptoSystemResponseOp::RandomBytes { value: csv.random_bytes(len), }, - CryptoSystemRequestOp::DefaultSaltLength => CryptoSystemResponseOp::DefaultSaltLength { - value: csv.default_salt_length(), + CryptoSystemRequestOp::SharedSecretLength => { + CryptoSystemResponseOp::SharedSecretLength { + value: csv.shared_secret_length() as u32, + } + } + CryptoSystemRequestOp::NonceLength => CryptoSystemResponseOp::NonceLength { + value: csv.nonce_length() as u32, }, + CryptoSystemRequestOp::HashDigestLength => CryptoSystemResponseOp::HashDigestLength { + value: csv.hash_digest_length() as u32, + }, + CryptoSystemRequestOp::PublicKeyLength => CryptoSystemResponseOp::PublicKeyLength { + value: csv.public_key_length() as u32, + }, + CryptoSystemRequestOp::SecretKeyLength => CryptoSystemResponseOp::SecretKeyLength { + value: csv.secret_key_length() as u32, + }, + CryptoSystemRequestOp::SignatureLength => CryptoSystemResponseOp::SignatureLength { + value: csv.signature_length() as u32, + }, + CryptoSystemRequestOp::DefaultSaltLength => CryptoSystemResponseOp::DefaultSaltLength { + value: csv.default_salt_length() as u32, + }, + CryptoSystemRequestOp::AeadOverhead => CryptoSystemResponseOp::AeadOverhead { + value: csv.aead_overhead() as u32, + }, + CryptoSystemRequestOp::CheckSharedSecret { secret } => { + CryptoSystemResponseOp::CheckSharedSecret { + result: to_json_api_result(csv.check_shared_secret(&secret)), + } + } + CryptoSystemRequestOp::CheckNonce { nonce } => CryptoSystemResponseOp::CheckNonce { + result: to_json_api_result(csv.check_nonce(&nonce)), + }, + CryptoSystemRequestOp::CheckHashDigest { digest } => { + CryptoSystemResponseOp::CheckHashDigest { + result: to_json_api_result(csv.check_hash_digest(&digest)), + } + } + CryptoSystemRequestOp::CheckPublicKey { key } => { + CryptoSystemResponseOp::CheckPublicKey { + result: to_json_api_result(csv.check_public_key(&key)), + } + } + CryptoSystemRequestOp::CheckSecretKey { key } => { + CryptoSystemResponseOp::CheckSecretKey { + result: to_json_api_result(csv.check_secret_key(&key)), + } + } + CryptoSystemRequestOp::CheckSignature { signature } => { + CryptoSystemResponseOp::CheckSignature { + result: to_json_api_result(csv.check_signature(&signature)), + } + } CryptoSystemRequestOp::HashPassword { password, salt } => { CryptoSystemResponseOp::HashPassword { result: to_json_api_result(csv.hash_password(&password, &salt)), @@ -540,9 +588,6 @@ impl JsonRequestProcessor { } => CryptoSystemResponseOp::Verify { result: to_json_api_result(csv.verify(&key, &data, &signature)), }, - CryptoSystemRequestOp::AeadOverhead => CryptoSystemResponseOp::AeadOverhead { - value: csv.aead_overhead() as u32, - }, CryptoSystemRequestOp::DecryptAead { body, nonce, @@ -574,7 +619,11 @@ impl JsonRequestProcessor { nonce, shared_secret, } => CryptoSystemResponseOp::CryptNoAuth { - value: csv.crypt_no_auth_unaligned(&body, &nonce, &shared_secret), + result: to_json_api_result_with_vec_u8(csv.crypt_no_auth_unaligned( + &body, + &nonce, + &shared_secret, + )), }, }; CryptoSystemResponse { @@ -605,6 +654,9 @@ impl JsonRequestProcessor { RequestOp::Detach => ResponseOp::Detach { result: to_json_api_result(self.api.detach().await), }, + RequestOp::GenerateMemberId { writer_key } => ResponseOp::GenerateMemberId { + result: to_json_api_result_with_string(self.api.generate_member_id(&writer_key)), + }, RequestOp::NewPrivateRoute => ResponseOp::NewPrivateRoute { result: to_json_api_result(self.api.new_private_route().await.map(|r| { NewPrivateRouteResult { @@ -811,7 +863,7 @@ impl JsonRequestProcessor { result: to_json_api_result_with_vec_string(crypto.generate_signatures( &data, &key_pairs, - |k, s| Signature::new(k.kind, s), + |k, s| Signature::new(k.kind(), s), )), } } diff --git a/veilid-remote-api/src/routing_context.rs b/veilid-remote-api/src/routing_context.rs index 5358b365..dbca6d54 100644 --- a/veilid-remote-api/src/routing_context.rs +++ b/veilid-remote-api/src/routing_context.rs @@ -27,21 +27,26 @@ pub enum RoutingContextRequestOp { }, Safety, AppCall { - target: String, + target: Target, #[serde(with = "as_human_base64")] #[schemars(with = "String")] message: Vec, }, AppMessage { - target: String, + target: Target, #[serde(with = "as_human_base64")] #[schemars(with = "String")] message: Vec, }, + GetDhtRecordKey { + schema: DHTSchema, + #[schemars(with = "String")] + owner: PublicKey, + }, CreateDhtRecord { schema: DHTSchema, #[schemars(with = "Option")] - owner: Option, + owner: Option, #[schemars(with = "Option")] kind: Option, }, @@ -49,7 +54,7 @@ pub enum RoutingContextRequestOp { #[schemars(with = "String")] key: RecordKey, #[schemars(with = "Option")] - writer: Option, + writer: Option, }, CloseDhtRecord { #[schemars(with = "String")] @@ -123,6 +128,11 @@ pub enum RoutingContextResponseOp { #[serde(flatten)] result: ApiResult<()>, }, + GetDhtRecordKey { + #[serde(flatten)] + #[schemars(with = "ApiResult")] + result: ApiResultWithString, + }, CreateDhtRecord { #[serde(flatten)] result: ApiResult>, diff --git a/veilid-server/src/main.rs b/veilid-server/src/main.rs index 04f8df57..26e863fd 100644 --- a/veilid-server/src/main.rs +++ b/veilid-server/src/main.rs @@ -424,21 +424,18 @@ fn main() -> EyreResult<()> { // --- Generate DHT Key --- if let Some(ckstr) = args.generate_key_pair { + println!("Keys:\n"); if ckstr.is_empty() { - let mut tks = veilid_core::PublicKeyGroup::new(); - let mut tss = veilid_core::SecretKeyGroup::new(); for ck in veilid_core::VALID_CRYPTO_KINDS { let tkp = veilid_core::Crypto::generate_keypair(ck).wrap_err("invalid crypto kind")?; - tks.add(veilid_core::PublicKey::new(tkp.kind, tkp.value.key)); - tss.add(veilid_core::SecretKey::new(tkp.kind, tkp.value.secret)); + println!("{}\n", tkp); } - println!("Public Keys:\n{}\nSecret Keys:\n{}\n", tks, tss); } else { let ck: veilid_core::CryptoKind = veilid_core::CryptoKind::from_str(&ckstr).wrap_err("couldn't parse crypto kind")?; let tkp = veilid_core::Crypto::generate_keypair(ck).wrap_err("invalid crypto kind")?; - println!("{}", tkp); + println!("{}\n", tkp); } return Ok(()); } diff --git a/veilid-server/src/server.rs b/veilid-server/src/server.rs index 95903c57..764d30d2 100644 --- a/veilid-server/src/server.rs +++ b/veilid-server/src/server.rs @@ -12,7 +12,7 @@ use std::time::{Duration, Instant}; use tracing::*; use veilid_core::tools::*; -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum ServerMode { Normal, ShutdownImmediate, @@ -163,7 +163,7 @@ pub async fn run_veilid_server_subnode( } // Process dump-txt-record - if let ServerMode::DumpTXTRecord(keypair) = server_mode { + if let ServerMode::DumpTXTRecord(keypair) = &server_mode { let start_time = Instant::now(); while Instant::now().duration_since(start_time) < Duration::from_secs(10) { match veilid_api.get_state().await { @@ -246,7 +246,12 @@ pub async fn run_veilid_server( debug!("Spawning subnode {}", subnode); let jh = spawn( &format!("subnode{}", subnode), - run_veilid_server_subnode(subnode, settings.clone(), server_mode, veilid_logs.clone()), + run_veilid_server_subnode( + subnode, + settings.clone(), + server_mode.clone(), + veilid_logs.clone(), + ), ); all_subnodes_jh.push(jh); } diff --git a/veilid-wasm/src/lib.rs b/veilid-wasm/src/lib.rs index 4e3511ba..967ed059 100644 --- a/veilid-wasm/src/lib.rs +++ b/veilid-wasm/src/lib.rs @@ -175,7 +175,7 @@ pub struct VeilidWASMConfig { tsify(from_wasm_abi, into_wasm_abi) )] pub struct VeilidRouteBlob { - pub route_id: veilid_core::BareRouteId, + pub route_id: veilid_core::RouteId, #[serde(with = "veilid_core::as_human_base64")] #[cfg_attr( all(target_arch = "wasm32", target_os = "unknown"), @@ -464,16 +464,17 @@ pub fn routing_context_safety(id: u32) -> Promise { } #[wasm_bindgen()] -pub fn routing_context_app_call(id: u32, target_string: String, request: String) -> Promise { +pub fn routing_context_app_call(id: u32, target: String, request: String) -> Promise { wrap_api_future_plain(async move { + let target: veilid_core::Target = + veilid_core::deserialize_json(&target).map_err(VeilidAPIError::generic)?; + let request: Vec = data_encoding::BASE64URL_NOPAD .decode(request.as_bytes()) .map_err(VeilidAPIError::generic)?; let routing_context = get_routing_context(id, "routing_context_app_call")?; - let veilid_api = get_veilid_api()?; - let target = veilid_api.parse_as_target(target_string)?; let answer = routing_context.app_call(target, request).await?; let answer = data_encoding::BASE64URL_NOPAD.encode(&answer); APIResult::Ok(answer) @@ -481,20 +482,37 @@ pub fn routing_context_app_call(id: u32, target_string: String, request: String) } #[wasm_bindgen()] -pub fn routing_context_app_message(id: u32, target_string: String, message: String) -> Promise { +pub fn routing_context_app_message(id: u32, target: String, message: String) -> Promise { wrap_api_future_void(async move { + let target: veilid_core::Target = + veilid_core::deserialize_json(&target).map_err(VeilidAPIError::generic)?; + let message: Vec = data_encoding::BASE64URL_NOPAD .decode(message.as_bytes()) .map_err(VeilidAPIError::generic)?; let routing_context = get_routing_context(id, "routing_context_app_message")?; - let veilid_api = get_veilid_api()?; - let target = veilid_api.parse_as_target(target_string)?; routing_context.app_message(target, message).await?; APIRESULT_UNDEFINED }) } +#[wasm_bindgen()] +pub fn routing_context_get_dht_record_key(id: u32, schema: String, owner: String) -> Promise { + wrap_api_future_json(async move { + let schema: veilid_core::DHTSchema = + veilid_core::deserialize_json(&schema).map_err(VeilidAPIError::generic)?; + let owner: veilid_core::PublicKey = + veilid_core::deserialize_json(&owner).map_err(VeilidAPIError::generic)?; + + let routing_context = get_routing_context(id, "routing_context_get_dht_record_key")?; + + let key = routing_context.get_dht_record_key(schema, &owner)?; + + APIResult::Ok(key) + }) +} + #[wasm_bindgen()] pub fn routing_context_create_dht_record( id: u32, @@ -508,7 +526,7 @@ pub fn routing_context_create_dht_record( } else { Some(veilid_core::CryptoKind::from(kind)) }; - let owner: Option = match owner { + let owner: Option = match owner { Some(s) => Some(veilid_core::deserialize_json(&s).map_err(VeilidAPIError::generic)?), None => None, }; @@ -529,7 +547,7 @@ pub fn routing_context_open_dht_record(id: u32, key: String, writer: Option = match writer { + let writer: Option = match writer { Some(s) => Some(veilid_core::deserialize_json(&s).map_err(VeilidAPIError::generic)?), None => None, }; @@ -682,6 +700,20 @@ pub fn routing_context_inspect_dht_record( }) } +#[wasm_bindgen()] +pub fn generate_member_id(writer_key: String) -> Promise { + wrap_api_future_json(async move { + let writer_key: veilid_core::PublicKey = + veilid_core::deserialize_json(&writer_key).map_err(VeilidAPIError::generic)?; + + let veilid_api = get_veilid_api()?; + + let member_id = veilid_api.generate_member_id(&writer_key)?; + + APIResult::Ok(member_id) + }) +} + #[wasm_bindgen()] pub fn new_private_route() -> Promise { wrap_api_future_json(async move { @@ -717,7 +749,7 @@ pub fn new_custom_private_route(stability: String, sequencing: String) -> Promis #[wasm_bindgen()] pub fn import_remote_private_route(blob: String) -> Promise { - wrap_api_future_plain(async move { + wrap_api_future_json(async move { let blob: Vec = data_encoding::BASE64URL_NOPAD .decode(blob.as_bytes()) .map_err(VeilidAPIError::generic)?; @@ -725,15 +757,15 @@ pub fn import_remote_private_route(blob: String) -> Promise { let key = veilid_api.import_remote_private_route(blob)?; - APIResult::Ok(key.encode()) + APIResult::Ok(key) }) } #[wasm_bindgen()] pub fn release_private_route(route_id: String) -> Promise { wrap_api_future_void(async move { - let route_id: veilid_core::BareRouteId = - veilid_core::BareRouteId::try_decode(&route_id).map_err(VeilidAPIError::generic)?; + let route_id: veilid_core::RouteId = + veilid_core::deserialize_json(&route_id).map_err(VeilidAPIError::generic)?; let veilid_api = get_veilid_api()?; veilid_api.release_private_route(route_id)?; APIRESULT_UNDEFINED @@ -1031,7 +1063,7 @@ pub fn generate_signatures(data: String, key_pairs: String) -> Promise { let veilid_api = get_veilid_api()?; let crypto = veilid_api.crypto()?; let out = crypto.generate_signatures(&data, &key_pairs, |k, s| { - veilid_core::Signature::new(k.kind, s) + veilid_core::Signature::new(k.kind(), s) })?; APIResult::Ok(out) }) @@ -1147,6 +1179,120 @@ pub fn crypto_random_bytes(kind: u32, len: u32) -> Promise { }) } +#[wasm_bindgen()] +pub fn crypto_shared_secret_length(kind: u32) -> Promise { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + + wrap_api_future_plain(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_shared_secret_length", + "kind", + kind.to_string(), + ) + })?; + let out = csv.shared_secret_length(); + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn crypto_nonce_length(kind: u32) -> Promise { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + + wrap_api_future_plain(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_nonce_length", + "kind", + kind.to_string(), + ) + })?; + let out = csv.nonce_length(); + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn crypto_hash_digest_length(kind: u32) -> Promise { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + + wrap_api_future_plain(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_hash_digest_length", + "kind", + kind.to_string(), + ) + })?; + let out = csv.hash_digest_length(); + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn crypto_public_key_length(kind: u32) -> Promise { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + + wrap_api_future_plain(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_public_key_length", + "kind", + kind.to_string(), + ) + })?; + let out = csv.public_key_length(); + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn crypto_secret_key_length(kind: u32) -> Promise { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + + wrap_api_future_plain(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_secret_key_length", + "kind", + kind.to_string(), + ) + })?; + let out = csv.secret_key_length(); + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn crypto_signature_length(kind: u32) -> Promise { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + + wrap_api_future_plain(async move { + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_signature_length", + "kind", + kind.to_string(), + ) + })?; + let out = csv.signature_length(); + APIResult::Ok(out) + }) +} + #[wasm_bindgen()] pub fn crypto_default_salt_length(kind: u32) -> Promise { let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); @@ -1166,6 +1312,151 @@ pub fn crypto_default_salt_length(kind: u32) -> Promise { }) } +#[wasm_bindgen()] +pub fn crypto_aead_overhead(kind: u32) -> Promise { + wrap_api_future_plain(async move { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_aead_overhead", + "kind", + kind.to_string(), + ) + })?; + let out = csv.aead_overhead(); + APIResult::Ok(out) + }) +} + +#[wasm_bindgen()] +pub fn crypto_check_shared_secret(kind: u32, secret: String) -> Promise { + wrap_api_future_void(async move { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + let secret: veilid_core::BareSharedSecret = + veilid_core::deserialize_json(&secret).map_err(VeilidAPIError::generic)?; + + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_check_shared_secret", + "kind", + kind.to_string(), + ) + })?; + csv.check_shared_secret(&secret)?; + APIRESULT_UNDEFINED + }) +} + +#[wasm_bindgen()] +pub fn crypto_check_nonce(kind: u32, nonce: String) -> Promise { + wrap_api_future_void(async move { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + let nonce: veilid_core::BareNonce = + veilid_core::deserialize_json(&nonce).map_err(VeilidAPIError::generic)?; + + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_check_nonce", + "kind", + kind.to_string(), + ) + })?; + csv.check_nonce(&nonce)?; + APIRESULT_UNDEFINED + }) +} + +#[wasm_bindgen()] +pub fn crypto_check_hash_digest(kind: u32, digest: String) -> Promise { + wrap_api_future_void(async move { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + let digest: veilid_core::BareHashDigest = + veilid_core::deserialize_json(&digest).map_err(VeilidAPIError::generic)?; + + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_check_hash_digest", + "kind", + kind.to_string(), + ) + })?; + csv.check_hash_digest(&digest)?; + APIRESULT_UNDEFINED + }) +} + +#[wasm_bindgen()] +pub fn crypto_check_public_key(kind: u32, key: String) -> Promise { + wrap_api_future_void(async move { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + let key: veilid_core::BarePublicKey = + veilid_core::deserialize_json(&key).map_err(VeilidAPIError::generic)?; + + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_check_public_key", + "kind", + kind.to_string(), + ) + })?; + csv.check_public_key(&key)?; + APIRESULT_UNDEFINED + }) +} + +#[wasm_bindgen()] +pub fn crypto_check_secret_key(kind: u32, key: String) -> Promise { + wrap_api_future_void(async move { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + let key: veilid_core::BareSecretKey = + veilid_core::deserialize_json(&key).map_err(VeilidAPIError::generic)?; + + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_check_secret_key", + "kind", + kind.to_string(), + ) + })?; + csv.check_secret_key(&key)?; + APIRESULT_UNDEFINED + }) +} + +#[wasm_bindgen()] +pub fn crypto_check_signature(kind: u32, signature: String) -> Promise { + wrap_api_future_void(async move { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); + let signature: veilid_core::BareSignature = + veilid_core::deserialize_json(&signature).map_err(VeilidAPIError::generic)?; + + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let csv = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_check_signature", + "kind", + kind.to_string(), + ) + })?; + csv.check_signature(&signature)?; + APIRESULT_UNDEFINED + }) +} + #[wasm_bindgen()] pub fn crypto_hash_password(kind: u32, password: String, salt: String) -> Promise { wrap_api_future_plain(async move { @@ -1438,25 +1729,6 @@ pub fn crypto_verify(kind: u32, key: String, data: String, signature: String) -> }) } -#[wasm_bindgen()] -pub fn crypto_aead_overhead(kind: u32) -> Promise { - wrap_api_future_plain(async move { - let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from(kind); - - let veilid_api = get_veilid_api()?; - let crypto = veilid_api.crypto()?; - let csv = crypto.get(kind).ok_or_else(|| { - veilid_core::VeilidAPIError::invalid_argument( - "crypto_aead_overhead", - "kind", - kind.to_string(), - ) - })?; - let out = csv.aead_overhead(); - APIResult::Ok(out) - }) -} - #[wasm_bindgen()] pub fn crypto_decrypt_aead( kind: u32, @@ -1592,7 +1864,7 @@ pub fn crypto_crypt_no_auth( kind.to_string(), ) })?; - csv.crypt_in_place_no_auth(&mut body, &nonce, &shared_secret); + csv.crypt_in_place_no_auth(&mut body, &nonce, &shared_secret)?; let out = data_encoding::BASE64URL_NOPAD.encode(&body); APIResult::Ok(out) }) diff --git a/veilid-wasm/src/veilid_client_js.rs b/veilid-wasm/src/veilid_client_js.rs index ff3b9764..1da51cc7 100644 --- a/veilid-wasm/src/veilid_client_js.rs +++ b/veilid-wasm/src/veilid_client_js.rs @@ -183,6 +183,89 @@ impl VeilidClient { APIRESULT_UNDEFINED } + /// Create a new MemberId for use with in creating `DHTSchema`s. + pub fn generateMemberId(writer_key: String) -> APIResult { + let writer_key: veilid_core::PublicKey = PublicKey::from_str(&writer_key)?; + + let veilid_api = get_veilid_api()?; + + let member_id = veilid_api.generate_member_id(&writer_key)?; + + APIResult::Ok(member_id.to_string()) + } + + /// Allocate a new private route set with default cryptography and network options. + /// Returns a route id and a publishable 'blob' with the route encrypted with each crypto kind. + /// Those nodes importing the blob will have their choice of which crypto kind to use. + /// + /// Returns a route id and 'blob' that can be published over some means (DHT or otherwise) to be imported by another Veilid node. + pub async fn newPrivateRoute() -> APIResult { + let veilid_api = get_veilid_api()?; + + let (route_id, blob) = veilid_api.new_private_route().await?; + + let route_blob = VeilidRouteBlob { route_id, blob }; + APIResult::Ok(route_blob) + } + + /// Import a private route blob as a remote private route. + /// + /// Returns a route id that can be used to send private messages to the node creating this route. + pub fn importRemotePrivateRoute(&self, blob: String) -> APIResult { + let blob = unmarshall(blob)?; + let veilid_api = get_veilid_api()?; + let route_id = veilid_api.import_remote_private_route(blob)?; + APIResult::Ok(route_id.to_string()) + } + + /// Allocate a new private route and specify a specific cryptosystem, stability and sequencing preference. + /// Returns a route id and a publishable 'blob' with the route encrypted with each crypto kind. + /// Those nodes importing the blob will have their choice of which crypto kind to use. + /// + /// Returns a route id and 'blob' that can be published over some means (DHT or otherwise) to be imported by another Veilid node. + pub async fn newCustomPrivateRoute( + stability: Stability, + sequencing: Sequencing, + ) -> APIResult { + let veilid_api = get_veilid_api()?; + + let (route_id, blob) = veilid_api + .new_custom_private_route(&veilid_core::VALID_CRYPTO_KINDS, stability, sequencing) + .await?; + + let route_blob = VeilidRouteBlob { route_id, blob }; + APIResult::Ok(route_blob) + } + + /// Release either a locally allocated or remotely imported private route. + /// + /// This will deactivate the route and free its resources and it can no longer be sent to or received from. + pub fn releasePrivateRoute(route_id: String) -> APIResult<()> { + let route_id: veilid_core::RouteId = RouteId::from_str(&route_id)?; + let veilid_api = get_veilid_api()?; + veilid_api.release_private_route(route_id)?; + APIRESULT_UNDEFINED + } + + /// Respond to an AppCall received over a VeilidUpdate::AppCall. + /// + /// * `call_id` - specifies which call to reply to, and it comes from a VeilidUpdate::AppCall, specifically the VeilidAppCall::id() value. + /// * `message` - is an answer blob to be returned by the remote node's RoutingContext::app_call() function, and may be up to 32768 bytes + pub async fn appCallReply(call_id: String, message: Box<[u8]>) -> APIResult<()> { + let message = message.into_vec(); + let call_id = match call_id.parse() { + Ok(v) => v, + Err(e) => { + return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument( + e, "call_id", call_id, + )) + } + }; + let veilid_api = get_veilid_api()?; + veilid_api.app_call_reply(call_id, message).await?; + APIRESULT_UNDEFINED + } + /// Get the current timestamp, in string format #[must_use] pub fn now() -> String { diff --git a/veilid-wasm/src/veilid_crypto_js.rs b/veilid-wasm/src/veilid_crypto_js.rs index 01c21347..4dd13e66 100644 --- a/veilid-wasm/src/veilid_crypto_js.rs +++ b/veilid-wasm/src/veilid_crypto_js.rs @@ -101,7 +101,103 @@ impl VeilidCrypto { APIResult::Ok(out) } - pub fn defaultSaltLength(kind: String) -> APIResult { + pub fn sharedSecretLength(kind: String) -> APIResult { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from_str(&kind)?; + + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let crypto_system = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_shared_secret_length", + "kind", + kind.to_string(), + ) + })?; + let out = crypto_system.shared_secret_length(); + APIResult::Ok(out) + } + + pub fn nonceLength(kind: String) -> APIResult { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from_str(&kind)?; + + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let crypto_system = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_nonce_length", + "kind", + kind.to_string(), + ) + })?; + let out = crypto_system.nonce_length(); + APIResult::Ok(out) + } + + pub fn hashDigestLength(kind: String) -> APIResult { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from_str(&kind)?; + + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let crypto_system = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_hash_digest_length", + "kind", + kind.to_string(), + ) + })?; + let out = crypto_system.hash_digest_length(); + APIResult::Ok(out) + } + + pub fn publicKeyLength(kind: String) -> APIResult { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from_str(&kind)?; + + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let crypto_system = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_public_key_length", + "kind", + kind.to_string(), + ) + })?; + let out = crypto_system.public_key_length(); + APIResult::Ok(out) + } + + pub fn secretKeyLength(kind: String) -> APIResult { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from_str(&kind)?; + + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let crypto_system = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_secret_key_length", + "kind", + kind.to_string(), + ) + })?; + let out = crypto_system.secret_key_length(); + APIResult::Ok(out) + } + + pub fn signatureLength(kind: String) -> APIResult { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from_str(&kind)?; + + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let crypto_system = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_signature_length", + "kind", + kind.to_string(), + ) + })?; + let out = crypto_system.signature_length(); + APIResult::Ok(out) + } + + pub fn defaultSaltLength(kind: String) -> APIResult { let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from_str(&kind)?; let veilid_api = get_veilid_api()?; @@ -117,6 +213,124 @@ impl VeilidCrypto { APIResult::Ok(out) } + pub fn aeadOverhead(kind: String) -> APIResult { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from_str(&kind)?; + + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let crypto_system = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_aead_overhead", + "kind", + kind.to_string(), + ) + })?; + let out = crypto_system.aead_overhead(); + APIResult::Ok(out) + } + + pub fn checkSharedSecret(kind: String, secret: String) -> APIResult<()> { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from_str(&kind)?; + let secret = veilid_core::BareSharedSecret::from_str(&secret)?; + + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let crypto_system = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_check_shared_secret", + "kind", + kind.to_string(), + ) + })?; + crypto_system.check_shared_secret(&secret)?; + APIRESULT_UNDEFINED + } + + pub fn checkNonce(kind: String, nonce: String) -> APIResult<()> { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from_str(&kind)?; + let nonce = veilid_core::BareNonce::from_str(&nonce)?; + + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let crypto_system = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_check_nonce", + "kind", + kind.to_string(), + ) + })?; + crypto_system.check_nonce(&nonce)?; + APIRESULT_UNDEFINED + } + + pub fn checkHashDigest(kind: String, digest: String) -> APIResult<()> { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from_str(&kind)?; + let digest = veilid_core::BareHashDigest::from_str(&digest)?; + + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let crypto_system = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_check_hash_digest", + "kind", + kind.to_string(), + ) + })?; + crypto_system.check_hash_digest(&digest)?; + APIRESULT_UNDEFINED + } + + pub fn checkPublicKey(kind: String, key: String) -> APIResult<()> { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from_str(&kind)?; + let key = veilid_core::BarePublicKey::from_str(&key)?; + + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let crypto_system = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_check_public_key", + "kind", + kind.to_string(), + ) + })?; + crypto_system.check_public_key(&key)?; + APIRESULT_UNDEFINED + } + + pub fn checkSecretKey(kind: String, key: String) -> APIResult<()> { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from_str(&kind)?; + let key = veilid_core::BareSecretKey::from_str(&key)?; + + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let crypto_system = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_check_secret_key", + "kind", + kind.to_string(), + ) + })?; + crypto_system.check_secret_key(&key)?; + APIRESULT_UNDEFINED + } + + pub fn checkSignature(kind: String, signature: String) -> APIResult<()> { + let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from_str(&kind)?; + let signature = veilid_core::BareSignature::from_str(&signature)?; + + let veilid_api = get_veilid_api()?; + let crypto = veilid_api.crypto()?; + let crypto_system = crypto.get(kind).ok_or_else(|| { + veilid_core::VeilidAPIError::invalid_argument( + "crypto_check_signature", + "kind", + kind.to_string(), + ) + })?; + crypto_system.check_signature(&signature)?; + APIRESULT_UNDEFINED + } + pub fn hashPassword(kind: String, password: Box<[u8]>, salt: Box<[u8]>) -> APIResult { let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from_str(&kind)?; @@ -270,7 +484,7 @@ impl VeilidCrypto { let veilid_api = get_veilid_api()?; let crypto = veilid_api.crypto()?; let out = crypto.generate_signatures(&data, &key_pairs, |k, s| { - veilid_core::Signature::new(k.kind, s).to_string() + veilid_core::Signature::new(k.kind(), s).to_string() })?; let out = into_unchecked_string_array(out); APIResult::Ok(out) @@ -401,22 +615,6 @@ impl VeilidCrypto { APIResult::Ok(out) } - pub fn aeadOverhead(kind: String) -> APIResult { - let kind: veilid_core::CryptoKind = veilid_core::CryptoKind::from_str(&kind)?; - - let veilid_api = get_veilid_api()?; - let crypto = veilid_api.crypto()?; - let crypto_system = crypto.get(kind).ok_or_else(|| { - veilid_core::VeilidAPIError::invalid_argument( - "crypto_aead_overhead", - "kind", - kind.to_string(), - ) - })?; - let out = crypto_system.aead_overhead(); - APIResult::Ok(out) - } - pub fn decryptAead( kind: String, body: Box<[u8]>, @@ -495,7 +693,7 @@ impl VeilidCrypto { kind.to_string(), ) })?; - crypto_system.crypt_in_place_no_auth(&mut body, &nonce, &shared_secret); + crypto_system.crypt_in_place_no_auth(&mut body, &nonce, &shared_secret)?; APIResult::Ok(body) } @@ -504,115 +702,45 @@ impl VeilidCrypto { // (written as getters since wasm_bindgen doesn't support export of const) // -------------------------------- - /// Length of a crypto key in bytes + /// Length of a VLD0 hash digest in bytes #[wasm_bindgen(getter)] #[must_use] - pub fn CRYPTO_KEY_LENGTH() -> usize { - veilid_core::CRYPTO_KEY_LENGTH + pub fn VLD0_HASH_DIGEST_LENGTH() -> usize { + veilid_core::VLD0_HASH_DIGEST_LENGTH } - /// Length of a crypto key in bytes after encoding to base64url + /// Length of a VLD0 nonce in bytes #[wasm_bindgen(getter)] #[must_use] - pub fn CRYPTO_KEY_LENGTH_ENCODED() -> usize { - veilid_core::CRYPTO_KEY_LENGTH_ENCODED + pub fn VLD0_NONCE_LENGTH() -> usize { + veilid_core::VLD0_NONCE_LENGTH } - /// Length of a hash digest in bytes + /// Length of a VLD0 public key in bytes #[wasm_bindgen(getter)] #[must_use] - pub fn HASH_DIGEST_LENGTH() -> usize { - veilid_core::HASH_DIGEST_LENGTH + pub fn VLD0_PUBLIC_KEY_LENGTH() -> usize { + veilid_core::VLD0_PUBLIC_KEY_LENGTH } - /// Length of a hash digest in bytes after encoding to base64url + /// Length of a VLD0 secret key in bytes #[wasm_bindgen(getter)] #[must_use] - pub fn HASH_DIGEST_LENGTH_ENCODED() -> usize { - veilid_core::HASH_DIGEST_LENGTH_ENCODED + pub fn VLD0_SECRET_KEY_LENGTH() -> usize { + veilid_core::VLD0_SECRET_KEY_LENGTH } - /// Length of a nonce in bytes + /// Length of a VLD0 shared secret in bytes #[wasm_bindgen(getter)] #[must_use] - pub fn NONCE_LENGTH() -> usize { - veilid_core::NONCE_LENGTH + pub fn VLD0_SHARED_SECRET_LENGTH() -> usize { + veilid_core::VLD0_SHARED_SECRET_LENGTH } - /// Length of a nonce in bytes after encoding to base64url + /// Length of a VLD0 signature in bytes #[wasm_bindgen(getter)] #[must_use] - pub fn NONCE_LENGTH_ENCODED() -> usize { - veilid_core::NONCE_LENGTH_ENCODED - } - - /// Length of a crypto key in bytes - #[wasm_bindgen(getter)] - #[must_use] - pub fn PUBLIC_KEY_LENGTH() -> usize { - veilid_core::PUBLIC_KEY_LENGTH - } - - /// Length of a crypto key in bytes after encoding to base64url - #[wasm_bindgen(getter)] - #[must_use] - pub fn PUBLIC_KEY_LENGTH_ENCODED() -> usize { - veilid_core::PUBLIC_KEY_LENGTH_ENCODED - } - - /// Length of a route id in bytes - #[wasm_bindgen(getter)] - #[must_use] - pub fn ROUTE_ID_LENGTH() -> usize { - veilid_core::ROUTE_ID_LENGTH - } - - /// Length of a route id in bytes after encoding to base64url - #[wasm_bindgen(getter)] - #[must_use] - pub fn ROUTE_ID_LENGTH_ENCODED() -> usize { - veilid_core::ROUTE_ID_LENGTH_ENCODED - } - - /// Length of a secret key in bytes - #[wasm_bindgen(getter)] - #[must_use] - pub fn SECRET_KEY_LENGTH() -> usize { - veilid_core::SECRET_KEY_LENGTH - } - - /// Length of a secret key in bytes after encoding to base64url - #[wasm_bindgen(getter)] - #[must_use] - pub fn SECRET_KEY_LENGTH_ENCODED() -> usize { - veilid_core::SECRET_KEY_LENGTH_ENCODED - } - - /// Length of a shared secret in bytes - #[wasm_bindgen(getter)] - #[must_use] - pub fn SHARED_SECRET_LENGTH() -> usize { - veilid_core::SHARED_SECRET_LENGTH - } - - /// Length of a shared secret in bytes after encoding to base64url - #[wasm_bindgen(getter)] - #[must_use] - pub fn SHARED_SECRET_LENGTH_ENCODED() -> usize { - veilid_core::SHARED_SECRET_LENGTH_ENCODED - } - - /// Length of a signature in bytes - #[wasm_bindgen(getter)] - #[must_use] - pub fn SIGNATURE_LENGTH() -> usize { - veilid_core::SIGNATURE_LENGTH - } - - /// Length of a signature in bytes after encoding to base64url - #[wasm_bindgen(getter)] - #[must_use] - pub fn SIGNATURE_LENGTH_ENCODED() -> usize { - veilid_core::SIGNATURE_LENGTH_ENCODED + pub fn VLD0_SIGNATURE_LENGTH() -> usize { + veilid_core::VLD0_SIGNATURE_LENGTH } } diff --git a/veilid-wasm/src/veilid_routing_context_js.rs b/veilid-wasm/src/veilid_routing_context_js.rs index 159ecddd..e36b2f9f 100644 --- a/veilid-wasm/src/veilid_routing_context_js.rs +++ b/veilid-wasm/src/veilid_routing_context_js.rs @@ -23,83 +23,7 @@ impl VeilidRoutingContext { } // -------------------------------- - // Static methods - // -------------------------------- - - /// Allocate a new private route set with default cryptography and network options. - /// Returns a route id and a publishable 'blob' with the route encrypted with each crypto kind. - /// Those nodes importing the blob will have their choice of which crypto kind to use. - /// - /// Returns a route id and 'blob' that can be published over some means (DHT or otherwise) to be imported by another Veilid node. - pub async fn newPrivateRoute() -> APIResult { - let veilid_api = get_veilid_api()?; - - let (route_id, blob) = veilid_api.new_private_route().await?; - - let route_blob = VeilidRouteBlob { route_id, blob }; - APIResult::Ok(route_blob) - } - - /// Import a private route blob as a remote private route. - /// - /// Returns a route id that can be used to send private messages to the node creating this route. - pub fn importRemotePrivateRoute(&self, blob: String) -> APIResult { - let blob = unmarshall(blob)?; - let veilid_api = get_veilid_api()?; - let route_id = veilid_api.import_remote_private_route(blob)?; - APIResult::Ok(route_id) - } - - /// Allocate a new private route and specify a specific cryptosystem, stability and sequencing preference. - /// Returns a route id and a publishable 'blob' with the route encrypted with each crypto kind. - /// Those nodes importing the blob will have their choice of which crypto kind to use. - /// - /// Returns a route id and 'blob' that can be published over some means (DHT or otherwise) to be imported by another Veilid node. - pub async fn newCustomPrivateRoute( - stability: Stability, - sequencing: Sequencing, - ) -> APIResult { - let veilid_api = get_veilid_api()?; - - let (route_id, blob) = veilid_api - .new_custom_private_route(&veilid_core::VALID_CRYPTO_KINDS, stability, sequencing) - .await?; - - let route_blob = VeilidRouteBlob { route_id, blob }; - APIResult::Ok(route_blob) - } - - /// Release either a locally allocated or remotely imported private route. - /// - /// This will deactivate the route and free its resources and it can no longer be sent to or received from. - pub fn releasePrivateRoute(route_id: String) -> APIResult<()> { - let route_id: veilid_core::BareRouteId = BareRouteId::from_str(&route_id)?; - let veilid_api = get_veilid_api()?; - veilid_api.release_private_route(route_id)?; - APIRESULT_UNDEFINED - } - - /// Respond to an AppCall received over a VeilidUpdate::AppCall. - /// - /// * `call_id` - specifies which call to reply to, and it comes from a VeilidUpdate::AppCall, specifically the VeilidAppCall::id() value. - /// * `message` - is an answer blob to be returned by the remote node's RoutingContext::app_call() function, and may be up to 32768 bytes - pub async fn appCallReply(call_id: String, message: Box<[u8]>) -> APIResult<()> { - let message = message.into_vec(); - let call_id = match call_id.parse() { - Ok(v) => v, - Err(e) => { - return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument( - e, "call_id", call_id, - )) - } - }; - let veilid_api = get_veilid_api()?; - veilid_api.app_call_reply(call_id, message).await?; - APIRESULT_UNDEFINED - } - - // -------------------------------- - // Instance methods + // Methods // -------------------------------- fn getRoutingContext(&self) -> APIResult { @@ -154,14 +78,12 @@ impl VeilidRoutingContext { /// /// Veilid apps may use this for arbitrary message passing. /// - /// @param {string} target - can be either a direct node id or a private route. + /// @param {string} target - a private route id, or in 'footgun' mode, a direct node id /// @param {string} message - an arbitrary message blob of up to `32768` bytes. #[wasm_bindgen(skip_jsdoc)] - pub async fn appMessage(&self, target_string: String, message: Box<[u8]>) -> APIResult<()> { + pub async fn appMessage(&self, target: Target, message: Box<[u8]>) -> APIResult<()> { let routing_context = self.getRoutingContext()?; let message = message.into_vec(); - let veilid_api = get_veilid_api()?; - let target = veilid_api.parse_as_target(target_string)?; routing_context.app_message(target, message).await?; APIRESULT_UNDEFINED } @@ -170,20 +92,14 @@ impl VeilidRoutingContext { /// /// Veilid apps may use this for arbitrary message passing. /// - /// @param {string} target_string - can be either a direct node id or a private route. + /// @param {string} target - a private route id, or in 'footgun' mode, a direct node id /// @param {Uint8Array} message - an arbitrary message blob of up to `32768` bytes. /// @returns {Uint8Array} an answer blob of up to `32768` bytes. #[wasm_bindgen(skip_jsdoc)] - pub async fn appCall( - &self, - target_string: String, - request: Box<[u8]>, - ) -> APIResult { + pub async fn appCall(&self, target: Target, request: Box<[u8]>) -> APIResult { let request: Vec = request.into_vec(); let routing_context = self.getRoutingContext()?; - let veilid_api = get_veilid_api()?; - let target = veilid_api.parse_as_target(target_string)?; let answer = routing_context.app_call(target, request).await?; let answer = Uint8Array::from(answer.as_slice()); APIResult::Ok(answer) @@ -192,21 +108,14 @@ impl VeilidRoutingContext { /////////////////////////////////// // DHT Records - /// Deterministicly builds the record key for a given schema and owner public key + /// Deterministicly builds the record key for a given schema and owner public key. + /// The crypto kind of the record key will be that of the `owner` public key #[allow(clippy::unused_async)] - pub async fn getDhtRecordKey( - &self, - schema: DHTSchema, - owner: String, - kind: Option, - ) -> APIResult { - let owner = BarePublicKey::from_str(&owner)?; - let crypto_kind = kind - .map(|kind| veilid_core::CryptoKind::from_str(&kind)) - .map_or(APIResult::Ok(None), |r| r.map(Some))?; + pub async fn getDhtRecordKey(&self, schema: DHTSchema, owner: String) -> APIResult { + let owner = PublicKey::from_str(&owner)?; let routing_context = self.getRoutingContext()?; - let key = routing_context.get_dht_record_key(schema, &owner, crypto_kind)?; + let key = routing_context.get_dht_record_key(schema, &owner)?; APIResult::Ok(key.to_string()) } @@ -214,7 +123,7 @@ impl VeilidRoutingContext { /// /// The record is considered 'open' after the create operation succeeds. /// * 'schema' - the schema to use when creating the DHT record - /// * 'owner' - optionally specify an owner keypair to use. If you leave this as None then a random one will be generated + /// * 'owner' - optionally specify an owner keypair to use. If you leave this as None then a random one will be generated. If specified, the crypto kind of the owner must match that of the `kind` parameter /// * 'kind' - specify a cryptosystem kind to use. Normally you will leave this as None to choose the 'best' cryptosystem available. /// Returns the newly allocated DHT record's key if successful. /// @@ -229,7 +138,7 @@ impl VeilidRoutingContext { .map(|kind| veilid_core::CryptoKind::from_str(&kind)) .map_or(APIResult::Ok(None), |r| r.map(Some))?; let owner_keypair = owner - .map(|owner| BareKeyPair::from_str(&owner)) + .map(|owner| KeyPair::from_str(&owner)) .map_or(APIResult::Ok(None), |r| r.map(Some))?; let routing_context = self.getRoutingContext()?; @@ -260,7 +169,7 @@ impl VeilidRoutingContext { ) -> APIResult { let key = RecordKey::from_str(&key)?; let default_writer = default_writer - .map(|default_writer| BareKeyPair::from_str(&default_writer)) + .map(|default_writer| KeyPair::from_str(&default_writer)) .map_or(APIResult::Ok(None), |r| r.map(Some))?; let routing_context = self.getRoutingContext()?; diff --git a/veilid-wasm/tests/src/VeilidRoutingContext.test.ts b/veilid-wasm/tests/src/VeilidRoutingContext.test.ts index 40c7cc6c..94b6ee2d 100644 --- a/veilid-wasm/tests/src/VeilidRoutingContext.test.ts +++ b/veilid-wasm/tests/src/VeilidRoutingContext.test.ts @@ -103,12 +103,12 @@ describe('VeilidRoutingContext', () => { const bestCryptoKind = veilidCrypto.bestCryptoKind(); const ownerKeyPair = veilidCrypto.generateKeyPair(bestCryptoKind); const [owner, secret] = ownerKeyPair.split(':'); - const dhtRecordKey = await routingContext.getDhtRecordKey({ kind: 'DFLT', o_cnt: 1 }, owner, bestCryptoKind); + const dhtRecordKey = await routingContext.getDhtRecordKey({ kind: 'DFLT', o_cnt: 1 }, `${bestCryptoKind}:owner`); const dhtRecord = await routingContext.createDhtRecord({ kind: 'DFLT', o_cnt: 1 }, ownerKeyPair, bestCryptoKind); expect(dhtRecord.key).toBeDefined(); expect(dhtRecord.key).toEqual(dhtRecordKey); expect(dhtRecord.owner).toBeDefined(); - expect(dhtRecord.owner).toEqual(owner); + expect(dhtRecord.owner).toEqual(`${bestCryptoKind}:${owner}`); expect(dhtRecord.owner_secret).toBeDefined(); expect(dhtRecord.owner_secret).toEqual(secret); expect(dhtRecord.schema).toEqual({ kind: 'DFLT', o_cnt: 1 }); diff --git a/veilid-wasm/tests/src/veilidCrypto.test.ts b/veilid-wasm/tests/src/veilidCrypto.test.ts index 90a6fc9d..f24e0f51 100644 --- a/veilid-wasm/tests/src/veilidCrypto.test.ts +++ b/veilid-wasm/tests/src/veilidCrypto.test.ts @@ -143,53 +143,23 @@ describe('veilidCrypto', () => { }); describe('constants', () => { - it('CRYPTO_KEY_LENGTH', () => { - expect(typeof veilidCrypto.CRYPTO_KEY_LENGTH).toBe('number'); + it('VLD0_HASH_DIGEST_LENGTH', () => { + expect(typeof veilidCrypto.VLD0_HASH_DIGEST_LENGTH).toBe('number'); }); - it('CRYPTO_KEY_LENGTH_ENCODED', () => { - expect(typeof veilidCrypto.CRYPTO_KEY_LENGTH_ENCODED).toBe('number'); + it('VLD0_NONCE_LENGTH', () => { + expect(typeof veilidCrypto.VLD0_NONCE_LENGTH).toBe('number'); }); - it('HASH_DIGEST_LENGTH', () => { - expect(typeof veilidCrypto.HASH_DIGEST_LENGTH).toBe('number'); + it('VLD0_PUBLIC_KEY_LENGTH', () => { + expect(typeof veilidCrypto.VLD0_PUBLIC_KEY_LENGTH).toBe('number'); }); - it('HASH_DIGEST_LENGTH_ENCODED', () => { - expect(typeof veilidCrypto.HASH_DIGEST_LENGTH_ENCODED).toBe('number'); + it('VLD0_SECRET_KEY_LENGTH', () => { + expect(typeof veilidCrypto.VLD0_SECRET_KEY_LENGTH).toBe('number'); }); - it('NONCE_LENGTH', () => { - expect(typeof veilidCrypto.NONCE_LENGTH).toBe('number'); + it('VLD0_SHARED_SECRET_LENGTH', () => { + expect(typeof veilidCrypto.VLD0_SHARED_SECRET_LENGTH).toBe('number'); }); - it('NONCE_LENGTH_ENCODED', () => { - expect(typeof veilidCrypto.NONCE_LENGTH_ENCODED).toBe('number'); - }); - it('PUBLIC_KEY_LENGTH', () => { - expect(typeof veilidCrypto.PUBLIC_KEY_LENGTH).toBe('number'); - }); - it('PUBLIC_KEY_LENGTH_ENCODED', () => { - expect(typeof veilidCrypto.PUBLIC_KEY_LENGTH_ENCODED).toBe('number'); - }); - it('ROUTE_ID_LENGTH', () => { - expect(typeof veilidCrypto.ROUTE_ID_LENGTH).toBe('number'); - }); - it('ROUTE_ID_LENGTH_ENCODED', () => { - expect(typeof veilidCrypto.ROUTE_ID_LENGTH_ENCODED).toBe('number'); - }); - it('SECRET_KEY_LENGTH', () => { - expect(typeof veilidCrypto.SECRET_KEY_LENGTH).toBe('number'); - }); - it('SECRET_KEY_LENGTH_ENCODED', () => { - expect(typeof veilidCrypto.SECRET_KEY_LENGTH_ENCODED).toBe('number'); - }); - it('SHARED_SECRET_LENGTH', () => { - expect(typeof veilidCrypto.SHARED_SECRET_LENGTH).toBe('number'); - }); - it('SHARED_SECRET_LENGTH_ENCODED', () => { - expect(typeof veilidCrypto.SHARED_SECRET_LENGTH_ENCODED).toBe('number'); - }); - it('SIGNATURE_LENGTH', () => { - expect(typeof veilidCrypto.SIGNATURE_LENGTH).toBe('number'); - }); - it('SIGNATURE_LENGTH_ENCODED', () => { - expect(typeof veilidCrypto.SIGNATURE_LENGTH_ENCODED).toBe('number'); + it('VLD0_SIGNATURE_LENGTH', () => { + expect(typeof veilidCrypto.VLD0_SIGNATURE_LENGTH).toBe('number'); }); }); });