Running CI also on windows and macOS (#512)
* Running CI also on windows and macOS * Rust 2021 formatting * clippy::upper_case_acronyms where appropriate * Allowing unknown clippy lints * Further clippy updates * Building wasm client during CI * wasm actions update * added working directory to cargo jobs * Temporarily disabled wasm test and clippy
This commit is contained in:
committed by
GitHub
parent
6f8ae53f0c
commit
83753af944
@@ -4,14 +4,12 @@ on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
ci:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ${{ matrix.os }}
|
||||
continue-on-error: ${{ matrix.rust == 'nightly' }}
|
||||
strategy:
|
||||
matrix:
|
||||
rust:
|
||||
- stable
|
||||
- beta
|
||||
- nightly
|
||||
rust: [stable, beta, nightly]
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
name: Wasm Client
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
ci:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
target: wasm32-unknown-unknown
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: build
|
||||
args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown
|
||||
|
||||
# for some reason this does not seem to work correctly, leave it for later, building is good enough for now
|
||||
# - uses: actions-rs/cargo@v1
|
||||
# with:
|
||||
# command: test
|
||||
# args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown
|
||||
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fmt
|
||||
args: --manifest-path clients/webassembly/Cargo.toml -- --check
|
||||
|
||||
# for some reason this does not seem to work correctly, leave it for later, building is good enough for now
|
||||
# - uses: actions-rs/cargo@v1
|
||||
# with:
|
||||
# command: clippy
|
||||
# args: --manifest-path clients/webassembly/Cargo.toml --target wasm32-unknown-unknown -- -D warnings
|
||||
@@ -1,6 +1,6 @@
|
||||
use futures::channel::mpsc;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use nymsphinx::anonymous_replies::ReplySURB;
|
||||
use nymsphinx::anonymous_replies::ReplySurb;
|
||||
|
||||
pub type InputMessageSender = mpsc::UnboundedSender<InputMessage>;
|
||||
pub type InputMessageReceiver = mpsc::UnboundedReceiver<InputMessage>;
|
||||
@@ -13,7 +13,7 @@ pub enum InputMessage {
|
||||
with_reply_surb: bool,
|
||||
},
|
||||
Reply {
|
||||
reply_surb: ReplySURB,
|
||||
reply_surb: ReplySurb,
|
||||
data: Vec<u8>,
|
||||
},
|
||||
}
|
||||
@@ -27,7 +27,7 @@ impl InputMessage {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_reply(reply_surb: ReplySURB, data: Vec<u8>) -> Self {
|
||||
pub fn new_reply(reply_surb: ReplySurb, data: Vec<u8>) -> Self {
|
||||
InputMessage::Reply { reply_surb, data }
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -22,7 +22,7 @@ use crate::client::{
|
||||
};
|
||||
use futures::StreamExt;
|
||||
use log::*;
|
||||
use nymsphinx::anonymous_replies::ReplySURB;
|
||||
use nymsphinx::anonymous_replies::ReplySurb;
|
||||
use nymsphinx::preparer::MessagePreparer;
|
||||
use nymsphinx::{acknowledgements::AckKey, addressing::clients::Recipient};
|
||||
use rand::{CryptoRng, Rng};
|
||||
@@ -75,7 +75,7 @@ where
|
||||
}
|
||||
|
||||
// we require topology for replies to generate surb_acks
|
||||
async fn handle_reply(&mut self, reply_surb: ReplySURB, data: Vec<u8>) -> Option<RealMessage> {
|
||||
async fn handle_reply(&mut self, reply_surb: ReplySurb, data: Vec<u8>) -> Option<RealMessage> {
|
||||
let topology_permit = self.topology_access.get_read_permit().await;
|
||||
let topology = match topology_permit.try_get_valid_topology_ref(&self.ack_recipient, None) {
|
||||
Some(topology_ref) => topology_ref,
|
||||
|
||||
@@ -21,8 +21,8 @@ use futures::lock::Mutex;
|
||||
use futures::StreamExt;
|
||||
use gateway_client::MixnetMessageReceiver;
|
||||
use log::*;
|
||||
use nymsphinx::anonymous_replies::{encryption_key::EncryptionKeyDigest, SURBEncryptionKey};
|
||||
use nymsphinx::params::{ReplySURBEncryptionAlgorithm, ReplySURBKeyDigestAlgorithm};
|
||||
use nymsphinx::anonymous_replies::{encryption_key::EncryptionKeyDigest, SurbEncryptionKey};
|
||||
use nymsphinx::params::{ReplySurbEncryptionAlgorithm, ReplySurbKeyDigestAlgorithm};
|
||||
use nymsphinx::receiver::{MessageReceiver, MessageRecoveryError, ReconstructedMessage};
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
@@ -191,11 +191,11 @@ impl ReceivedMessagesBuffer {
|
||||
|
||||
fn process_received_reply(
|
||||
reply_ciphertext: &[u8],
|
||||
reply_key: SURBEncryptionKey,
|
||||
reply_key: SurbEncryptionKey,
|
||||
) -> Option<ReconstructedMessage> {
|
||||
let zero_iv = stream_cipher::zero_iv::<ReplySURBEncryptionAlgorithm>();
|
||||
let zero_iv = stream_cipher::zero_iv::<ReplySurbEncryptionAlgorithm>();
|
||||
|
||||
let mut reply_msg = stream_cipher::decrypt::<ReplySURBEncryptionAlgorithm>(
|
||||
let mut reply_msg = stream_cipher::decrypt::<ReplySurbEncryptionAlgorithm>(
|
||||
&reply_key.inner(),
|
||||
&zero_iv,
|
||||
reply_ciphertext,
|
||||
@@ -221,7 +221,7 @@ impl ReceivedMessagesBuffer {
|
||||
let mut completed_messages = Vec::new();
|
||||
let mut inner_guard = self.inner.lock().await;
|
||||
|
||||
let reply_surb_digest_size = ReplySURBKeyDigestAlgorithm::output_size();
|
||||
let reply_surb_digest_size = ReplySurbKeyDigestAlgorithm::output_size();
|
||||
|
||||
// first check if this is a reply or a chunked message
|
||||
// TODO: verify with @AP if this way of doing it is safe or whether it could
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
use log::*;
|
||||
use nymsphinx::anonymous_replies::{
|
||||
encryption_key::EncryptionKeyDigest, encryption_key::Unsigned, SURBEncryptionKey,
|
||||
SURBEncryptionKeySize,
|
||||
encryption_key::EncryptionKeyDigest, encryption_key::Unsigned, SurbEncryptionKey,
|
||||
SurbEncryptionKeySize,
|
||||
};
|
||||
use std::path::Path;
|
||||
|
||||
@@ -49,24 +49,24 @@ impl ReplyKeyStorage {
|
||||
Ok(ReplyKeyStorage { db })
|
||||
}
|
||||
|
||||
fn read_encryption_key(&self, raw_key: sled::IVec) -> SURBEncryptionKey {
|
||||
fn read_encryption_key(&self, raw_key: sled::IVec) -> SurbEncryptionKey {
|
||||
let key_bytes_ref = raw_key.as_ref();
|
||||
// if this fails it means we have some database corruption and we
|
||||
// absolutely can't continue
|
||||
|
||||
if key_bytes_ref.len() != SURBEncryptionKeySize::to_usize() {
|
||||
if key_bytes_ref.len() != SurbEncryptionKeySize::to_usize() {
|
||||
error!("REPLY KEY STORAGE DATA CORRUPTION - ENCRYPTION KEY HAS INVALID LENGTH");
|
||||
panic!("REPLY KEY STORAGE DATA CORRUPTION - ENCRYPTION KEY HAS INVALID LENGTH");
|
||||
}
|
||||
|
||||
// this can only fail if the bytes have invalid length but we already asserted it
|
||||
SURBEncryptionKey::try_from_bytes(key_bytes_ref).unwrap()
|
||||
SurbEncryptionKey::try_from_bytes(key_bytes_ref).unwrap()
|
||||
}
|
||||
|
||||
// TOOD: perhaps we could also store some part of original message here too?
|
||||
pub fn insert_encryption_key(
|
||||
&mut self,
|
||||
encryption_key: SURBEncryptionKey,
|
||||
encryption_key: SurbEncryptionKey,
|
||||
) -> Result<(), ReplyKeyStorageError> {
|
||||
let digest = encryption_key.compute_digest();
|
||||
|
||||
@@ -89,7 +89,7 @@ impl ReplyKeyStorage {
|
||||
pub fn get_and_remove_encryption_key(
|
||||
&self,
|
||||
key_digest: EncryptionKeyDigest,
|
||||
) -> Result<Option<SURBEncryptionKey>, ReplyKeyStorageError> {
|
||||
) -> Result<Option<SurbEncryptionKey>, ReplyKeyStorageError> {
|
||||
let removal_result = match self.db.remove(&key_digest.to_vec()) {
|
||||
Err(e) => Err(ReplyKeyStorageError::DbReadError(e)),
|
||||
Ok(existing_key) => {
|
||||
|
||||
@@ -42,7 +42,7 @@ use gateway_client::{
|
||||
use log::*;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use nymsphinx::addressing::nodes::NodeIdentity;
|
||||
use nymsphinx::anonymous_replies::ReplySURB;
|
||||
use nymsphinx::anonymous_replies::ReplySurb;
|
||||
use nymsphinx::params::PacketMode;
|
||||
use nymsphinx::receiver::ReconstructedMessage;
|
||||
use tokio::runtime::Runtime;
|
||||
@@ -132,7 +132,7 @@ impl NymClient {
|
||||
mix_sender: BatchMixMessageSender,
|
||||
) {
|
||||
let packet_mode = if self.config.get_base().get_vpn_mode() {
|
||||
PacketMode::VPN
|
||||
PacketMode::Vpn
|
||||
} else {
|
||||
PacketMode::Mix
|
||||
};
|
||||
@@ -297,7 +297,7 @@ impl NymClient {
|
||||
/// EXPERIMENTAL DIRECT RUST API
|
||||
/// It's untested and there are absolutely no guarantees about it (but seems to have worked
|
||||
/// well enough in local tests)
|
||||
pub fn send_reply(&mut self, reply_surb: ReplySURB, message: Vec<u8>) {
|
||||
pub fn send_reply(&mut self, reply_surb: ReplySurb, message: Vec<u8>) {
|
||||
let input_msg = InputMessage::new_reply(reply_surb, message);
|
||||
|
||||
self.input_tx
|
||||
|
||||
@@ -22,7 +22,7 @@ use futures::channel::mpsc;
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use log::*;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use nymsphinx::anonymous_replies::ReplySURB;
|
||||
use nymsphinx::anonymous_replies::ReplySurb;
|
||||
use nymsphinx::receiver::ReconstructedMessage;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio_tungstenite::{
|
||||
@@ -100,9 +100,9 @@ impl Handler {
|
||||
None
|
||||
}
|
||||
|
||||
fn handle_reply(&mut self, reply_surb: ReplySURB, message: Vec<u8>) -> Option<ServerResponse> {
|
||||
if message.len() > ReplySURB::max_msg_len(Default::default()) {
|
||||
return Some(ServerResponse::new_error(format!("too long message to put inside a reply SURB. Received: {} bytes and maximum is {} bytes", message.len(), ReplySURB::max_msg_len(Default::default()))));
|
||||
fn handle_reply(&mut self, reply_surb: ReplySurb, message: Vec<u8>) -> Option<ServerResponse> {
|
||||
if message.len() > ReplySurb::max_msg_len(Default::default()) {
|
||||
return Some(ServerResponse::new_error(format!("too long message to put inside a reply SURB. Received: {} bytes and maximum is {} bytes", message.len(), ReplySurb::max_msg_len(Default::default()))));
|
||||
}
|
||||
|
||||
let input_msg = InputMessage::new_reply(reply_surb, message);
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
use crate::error::{self, ErrorKind};
|
||||
use crate::text::ClientRequestText;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use nymsphinx::anonymous_replies::ReplySURB;
|
||||
use nymsphinx::anonymous_replies::ReplySurb;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::mem::size_of;
|
||||
|
||||
@@ -42,7 +42,7 @@ pub enum ClientRequest {
|
||||
},
|
||||
Reply {
|
||||
message: Vec<u8>,
|
||||
reply_surb: ReplySURB,
|
||||
reply_surb: ReplySurb,
|
||||
},
|
||||
SelfAddress,
|
||||
}
|
||||
@@ -119,7 +119,7 @@ impl ClientRequest {
|
||||
}
|
||||
|
||||
// REPLY_REQUEST_TAG || surb_len || surb || message_len || message
|
||||
fn serialize_reply(message: Vec<u8>, reply_surb: ReplySURB) -> Vec<u8> {
|
||||
fn serialize_reply(message: Vec<u8>, reply_surb: ReplySurb) -> Vec<u8> {
|
||||
let reply_surb_bytes = reply_surb.to_bytes();
|
||||
let surb_len_bytes = (reply_surb_bytes.len() as u64).to_be_bytes();
|
||||
let message_len_bytes = (message.len() as u64).to_be_bytes();
|
||||
@@ -164,7 +164,7 @@ impl ClientRequest {
|
||||
let surb_bound = 1 + size_of::<u64>() + reply_surb_len as usize;
|
||||
|
||||
let reply_surb_bytes = &b[1 + size_of::<u64>()..surb_bound];
|
||||
let reply_surb = match ReplySURB::from_bytes(reply_surb_bytes) {
|
||||
let reply_surb = match ReplySurb::from_bytes(reply_surb_bytes) {
|
||||
Ok(reply_surb) => reply_surb,
|
||||
Err(err) => {
|
||||
return Err(error::Error::new(
|
||||
@@ -333,7 +333,7 @@ mod tests {
|
||||
#[test]
|
||||
fn reply_request_serialization_works() {
|
||||
let reply_surb_string = "CjfVbHbfAjbC3W1BvNHGXmM8KNAnDNYGaHMLqVDxRYeo352csAihstup9bvqXam4dTWgfHak6KYwL9STaxWJ47E8XFZbSEvs7hEsfCkxr6K9WJuSBPK84GDDEvad8ZAuMCoaXsAd5S2Lj9a5eYyzG4SL1jHzhSMni55LyJwumxo1ZTGZNXggxw1RREosvyzNrW9Rsi3owyPqLCwXpiei2tHZty8w8midVvg8vDa7ZEJD842CLv8D4ohynSG7gDpqTrhkRaqYAuz7dzqNbMXLJRM7v823Jn16fA1L7YQxmcaUdUigyRSgTdb4i9ebiLGSyJ1iDe6Acz613PQZh6Ua3bZ2zVKq3dSycpDm9ngarRK4zJrAaUxRkdih8YzW3BY4nL9eqkfKA4N1TWCLaRU7zpSaf8yMEwrAZReU3d5zLV8c5KBfa2w8R5anhQeBojduZEGEad8kkHuKU52Zg93FeWHvH1qgZaEJMHH4nN7gKXz9mvWDhYwyF4vt3Uy2NhCHC3N5pL1gMme27YcoPcTEia1fxKZtnt6rtEozzTrAgCJGswigkFbkafiV5QaJwLKTUxtzhkZ57eEuLPte9UvJHzhhXUQ2CV7R2BUkJjYZy3Zsx6YYvdYWiAFFkWUwNEGA4QpShUHciBfsQVHQ7pN41YcyYUhbywQDFnTVgEmdUZ1XCBi3gyK5U3tDQmFzP1u9m3mWrUA8qB9mRDE7ptNDm5c3c1458L6uXLUth7sdMaa1Was5LCmCdmNDtvNpCDAEt1in6q6mrZFR85aCSU9b1baNGwZoCqPpPvydkVe63gXWoi8ebvdyxARrqACFrSB3ZdY3uJBw8CTMNkKK6MvcefMkSVVsbLd36TQAtYSCqrpiMc5dQuKcEu5QfciwvWYXYx8WFNAgKwP2mv49KCTvfozNDUCbjzDwSx92Zv5zjG8HbFpB13bY9UZGeyTPvv7gGxCzjGjJGbW6FRAheRQaaje5fUgCNM95Tv7wBmAMRHHFgWafeK1sdFH7dtCX9u898HucGTaboSKLsVh8J78gbbkHErwjMh7y9YRkceq5TTYS5da4kHnyNKYWSbxgZrmFg44XGKoeYcqoHB3XTZrdsf7F5fFeNwnihkmADvhAcaxXUmVqq4rQFZH84a1iC3WBWXYcqiZH2L7ujGWV7mMDT4HBEerDYjc8rNY4xGTPfivCrBCJW1i14aqW8xRdsdgTM88eTksvC3WPJLJ7iMzfKXeL7fMW1Ek6QGyQtLBW98vEESpdcDg6DeZ5rMz6VqjTGGqcCaFGfHoqtfxMDaBAEsyQ8h7XDX6dg1wq9wH6j4Tw7Tj1MEv1b8uj5NJkozZdzVdYA2QyE2Dp8vuurQG6uVdTDNww2d88RBQ8sVgjxN8gR45y4woJLhFAaNTAtrY6wDTxyXST13ni6oyqdYxjFVk9Am4v3DzH7Y2K8iRVSHfTk4FRbPULyaeK6wt2anvMJH1XdvVRgc14h67MnBxMgMD1UFk8AErN7CDj26fppe3c5G6KozJe4cSqQUGbBjVzBnrHCruqrfZBn5hNZHTV37bQiomqhRQXohxhuKEnNrGbAe1xNvJr9X";
|
||||
let reply_surb = ReplySURB::from_base58_string(reply_surb_string).unwrap();
|
||||
let reply_surb = ReplySurb::from_base58_string(reply_surb_string).unwrap();
|
||||
let reply_request = ClientRequest::Reply {
|
||||
message: b"foomp".to_vec(),
|
||||
reply_surb,
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
use crate::error::{self, ErrorKind};
|
||||
use crate::text::ServerResponseText;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use nymsphinx::anonymous_replies::ReplySURB;
|
||||
use nymsphinx::anonymous_replies::ReplySurb;
|
||||
use nymsphinx::receiver::ReconstructedMessage;
|
||||
use std::convert::TryInto;
|
||||
use std::mem::size_of;
|
||||
@@ -111,7 +111,7 @@ impl ServerResponse {
|
||||
let surb_bound = 2 + size_of::<u64>() + reply_surb_len as usize;
|
||||
|
||||
let reply_surb_bytes = &b[2 + size_of::<u64>()..surb_bound];
|
||||
let reply_surb = match ReplySURB::from_bytes(reply_surb_bytes) {
|
||||
let reply_surb = match ReplySurb::from_bytes(reply_surb_bytes) {
|
||||
Ok(reply_surb) => reply_surb,
|
||||
Err(err) => {
|
||||
return Err(error::Error::new(
|
||||
@@ -339,7 +339,7 @@ mod tests {
|
||||
|
||||
let received_with_surb = ServerResponse::Received(ReconstructedMessage {
|
||||
message: b"foomp".to_vec(),
|
||||
reply_surb: Some(ReplySURB::from_base58_string(reply_surb_string).unwrap()),
|
||||
reply_surb: Some(ReplySurb::from_base58_string(reply_surb_string).unwrap()),
|
||||
});
|
||||
let bytes = received_with_surb.serialize();
|
||||
let recovered = ServerResponse::deserialize(&bytes).unwrap();
|
||||
|
||||
@@ -16,7 +16,7 @@ use crate::error::ErrorKind;
|
||||
use crate::requests::ClientRequest;
|
||||
use crate::responses::ServerResponse;
|
||||
use nymsphinx::addressing::clients::Recipient;
|
||||
use nymsphinx::anonymous_replies::ReplySURB;
|
||||
use nymsphinx::anonymous_replies::ReplySurb;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
|
||||
@@ -75,7 +75,7 @@ impl TryInto<ClientRequest> for ClientRequestText {
|
||||
reply_surb,
|
||||
} => {
|
||||
let message_bytes = message.into_bytes();
|
||||
let reply_surb = ReplySURB::from_base58_string(reply_surb).map_err(|err| {
|
||||
let reply_surb = ReplySurb::from_base58_string(reply_surb).map_err(|err| {
|
||||
Self::Error::new(ErrorKind::MalformedRequest, err.to_string())
|
||||
})?;
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ impl NymClient {
|
||||
mix_sender: BatchMixMessageSender,
|
||||
) {
|
||||
let packet_mode = if self.config.get_base().get_vpn_mode() {
|
||||
PacketMode::VPN
|
||||
PacketMode::Vpn
|
||||
} else {
|
||||
PacketMode::Mix
|
||||
};
|
||||
|
||||
@@ -34,7 +34,7 @@ pub(crate) mod received_processor;
|
||||
const DEFAULT_AVERAGE_PACKET_DELAY: Duration = Duration::from_millis(200);
|
||||
const DEFAULT_AVERAGE_ACK_DELAY: Duration = Duration::from_millis(200);
|
||||
const DEFAULT_GATEWAY_RESPONSE_TIMEOUT: Duration = Duration::from_millis(1_500);
|
||||
const DEFAULT_PACKET_MODE: PacketMode = PacketMode::VPN;
|
||||
const DEFAULT_PACKET_MODE: PacketMode = PacketMode::Vpn;
|
||||
const DEFAULT_VPN_KEY_REUSE_LIMIT: usize = 1000;
|
||||
|
||||
#[wasm_bindgen]
|
||||
|
||||
@@ -50,10 +50,10 @@ impl PacketRouter {
|
||||
// remember: gateway removes final layer of sphinx encryption and from the unwrapped
|
||||
// data he takes the SURB-ACK and first hop address.
|
||||
// currently SURB-ACKs are attached in EVERY packet, even cover, so this is always true
|
||||
let ack_overhead = PacketSize::ACKPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN;
|
||||
let ack_overhead = PacketSize::AckPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN;
|
||||
|
||||
for received_packet in unwrapped_packets {
|
||||
if received_packet.len() == PacketSize::ACKPacket.plaintext_size() {
|
||||
if received_packet.len() == PacketSize::AckPacket.plaintext_size() {
|
||||
received_acks.push(received_packet);
|
||||
} else if received_packet.len()
|
||||
== PacketSize::RegularPacket.plaintext_size() - ack_overhead
|
||||
|
||||
@@ -18,8 +18,8 @@ use crate::models::mixnode::MixRegistrationInfo;
|
||||
use crate::models::topology::Topology;
|
||||
use crate::rest_requests::{
|
||||
ActiveTopologyGet, ActiveTopologyGetResponse, BatchMixStatusPost, GatewayRegisterPost,
|
||||
MixRegisterPost, MixStatusPost, NodeUnregisterDelete, RESTRequest, RESTRequestError,
|
||||
ReputationPatch, TopologyGet, TopologyGetResponse,
|
||||
MixRegisterPost, MixStatusPost, NodeUnregisterDelete, ReputationPatch, RestRequest,
|
||||
RestRequestError, TopologyGet, TopologyGetResponse,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
@@ -66,22 +66,22 @@ struct OkResponse {
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase", untagged)]
|
||||
pub(crate) enum DefaultRESTResponse {
|
||||
pub(crate) enum DefaultRestResponse {
|
||||
Ok(OkResponse),
|
||||
Error(ErrorResponses),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ValidatorClientError {
|
||||
RESTRequestError(RESTRequestError),
|
||||
RestRequestError(RestRequestError),
|
||||
ReqwestClientError(reqwest::Error),
|
||||
ValidatorError(String),
|
||||
UnexpectedResponse(String),
|
||||
}
|
||||
|
||||
impl From<RESTRequestError> for ValidatorClientError {
|
||||
fn from(err: RESTRequestError) -> Self {
|
||||
ValidatorClientError::RESTRequestError(err)
|
||||
impl From<RestRequestError> for ValidatorClientError {
|
||||
fn from(err: RestRequestError) -> Self {
|
||||
ValidatorClientError::RestRequestError(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ impl From<reqwest::Error> for ValidatorClientError {
|
||||
impl Display for ValidatorClientError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
ValidatorClientError::RESTRequestError(err) => {
|
||||
ValidatorClientError::RestRequestError(err) => {
|
||||
write!(f, "could not prepare the REST request - {}", err)
|
||||
}
|
||||
ValidatorClientError::ReqwestClientError(err) => {
|
||||
@@ -151,7 +151,7 @@ impl Client {
|
||||
}
|
||||
}
|
||||
|
||||
async fn make_rest_request<R: RESTRequest>(
|
||||
async fn make_rest_request<R: RestRequest>(
|
||||
&self,
|
||||
request: R,
|
||||
) -> Result<R::ExpectedJsonResponse> {
|
||||
@@ -174,8 +174,8 @@ impl Client {
|
||||
Some(mix_registration_info),
|
||||
)?;
|
||||
match self.make_rest_request(req).await? {
|
||||
DefaultRESTResponse::Ok(_) => Ok(()),
|
||||
DefaultRESTResponse::Error(err) => Err(err.into()),
|
||||
DefaultRestResponse::Ok(_) => Ok(()),
|
||||
DefaultRestResponse::Error(err) => Err(err.into()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ impl Client {
|
||||
Some(gateway_registration_info),
|
||||
)?;
|
||||
match self.make_rest_request(req).await? {
|
||||
DefaultRESTResponse::Ok(ok_res) => {
|
||||
DefaultRestResponse::Ok(ok_res) => {
|
||||
if ok_res.ok {
|
||||
Ok(())
|
||||
} else {
|
||||
@@ -199,7 +199,7 @@ impl Client {
|
||||
))
|
||||
}
|
||||
}
|
||||
DefaultRESTResponse::Error(err) => Err(err.into()),
|
||||
DefaultRestResponse::Error(err) => Err(err.into()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ impl Client {
|
||||
NodeUnregisterDelete::new(&self.config.base_url, Some(vec![node_id]), None, None)?;
|
||||
|
||||
match self.make_rest_request(req).await? {
|
||||
DefaultRESTResponse::Ok(ok_res) => {
|
||||
DefaultRestResponse::Ok(ok_res) => {
|
||||
if ok_res.ok {
|
||||
Ok(())
|
||||
} else {
|
||||
@@ -217,7 +217,7 @@ impl Client {
|
||||
))
|
||||
}
|
||||
}
|
||||
DefaultRESTResponse::Error(err) => Err(err.into()),
|
||||
DefaultRestResponse::Error(err) => Err(err.into()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,7 +238,7 @@ impl Client {
|
||||
None,
|
||||
)?;
|
||||
match self.make_rest_request(req).await? {
|
||||
DefaultRESTResponse::Ok(ok_res) => {
|
||||
DefaultRestResponse::Ok(ok_res) => {
|
||||
if ok_res.ok {
|
||||
Ok(())
|
||||
} else {
|
||||
@@ -247,7 +247,7 @@ impl Client {
|
||||
))
|
||||
}
|
||||
}
|
||||
DefaultRESTResponse::Error(err) => Err(err.into()),
|
||||
DefaultRestResponse::Error(err) => Err(err.into()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,7 +270,7 @@ impl Client {
|
||||
pub async fn post_mixmining_status(&self, status: MixStatus) -> Result<()> {
|
||||
let req = MixStatusPost::new(&self.config.base_url, None, None, Some(status))?;
|
||||
match self.make_rest_request(req).await? {
|
||||
DefaultRESTResponse::Ok(ok_res) => {
|
||||
DefaultRestResponse::Ok(ok_res) => {
|
||||
if ok_res.ok {
|
||||
Ok(())
|
||||
} else {
|
||||
@@ -279,14 +279,14 @@ impl Client {
|
||||
))
|
||||
}
|
||||
}
|
||||
DefaultRESTResponse::Error(err) => Err(err.into()),
|
||||
DefaultRestResponse::Error(err) => Err(err.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn post_batch_mixmining_status(&self, batch_status: BatchMixStatus) -> Result<()> {
|
||||
let req = BatchMixStatusPost::new(&self.config.base_url, None, None, Some(batch_status))?;
|
||||
match self.make_rest_request(req).await? {
|
||||
DefaultRESTResponse::Ok(ok_res) => {
|
||||
DefaultRestResponse::Ok(ok_res) => {
|
||||
if ok_res.ok {
|
||||
Ok(())
|
||||
} else {
|
||||
@@ -295,7 +295,7 @@ impl Client {
|
||||
))
|
||||
}
|
||||
}
|
||||
DefaultRESTResponse::Error(err) => Err(err.into()),
|
||||
DefaultRestResponse::Error(err) => Err(err.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
use crate::models::topology::Topology;
|
||||
use crate::rest_requests::{PathParam, QueryParam, RESTRequest, RESTRequestError};
|
||||
use crate::rest_requests::{PathParam, QueryParam, RestRequest, RestRequestError};
|
||||
use crate::ErrorResponses;
|
||||
use reqwest::{Method, Url};
|
||||
use serde::Deserialize;
|
||||
@@ -29,7 +29,7 @@ pub(crate) enum Response {
|
||||
Error(ErrorResponses),
|
||||
}
|
||||
|
||||
impl RESTRequest for Request {
|
||||
impl RestRequest for Request {
|
||||
const METHOD: Method = Method::GET;
|
||||
const RELATIVE_PATH: &'static str = "/api/mixmining/topology/active";
|
||||
|
||||
@@ -41,9 +41,9 @@ impl RESTRequest for Request {
|
||||
_: Option<Vec<PathParam>>,
|
||||
_: Option<Vec<QueryParam>>,
|
||||
_: Option<Self::JsonPayload>,
|
||||
) -> Result<Self, RESTRequestError> {
|
||||
) -> Result<Self, RestRequestError> {
|
||||
let url = Url::parse(&format!("{}{}", base_url, Self::RELATIVE_PATH))
|
||||
.map_err(|err| RESTRequestError::MalformedUrl(err.to_string()))?;
|
||||
.map_err(|err| RestRequestError::MalformedUrl(err.to_string()))?;
|
||||
|
||||
Ok(Request { url })
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
// limitations under the License.
|
||||
|
||||
use crate::models::gateway::GatewayRegistrationInfo;
|
||||
use crate::rest_requests::{PathParam, QueryParam, RESTRequest, RESTRequestError};
|
||||
use crate::DefaultRESTResponse;
|
||||
use crate::rest_requests::{PathParam, QueryParam, RestRequest, RestRequestError};
|
||||
use crate::DefaultRestResponse;
|
||||
use reqwest::{Method, Url};
|
||||
|
||||
pub struct Request {
|
||||
@@ -22,22 +22,22 @@ pub struct Request {
|
||||
payload: GatewayRegistrationInfo,
|
||||
}
|
||||
|
||||
impl RESTRequest for Request {
|
||||
impl RestRequest for Request {
|
||||
const METHOD: Method = Method::POST;
|
||||
const RELATIVE_PATH: &'static str = "/api/mixmining/register/gateway";
|
||||
|
||||
type JsonPayload = GatewayRegistrationInfo;
|
||||
type ExpectedJsonResponse = DefaultRESTResponse;
|
||||
type ExpectedJsonResponse = DefaultRestResponse;
|
||||
|
||||
fn new(
|
||||
base_url: &str,
|
||||
_: Option<Vec<PathParam>>,
|
||||
_: Option<Vec<QueryParam>>,
|
||||
body_payload: Option<Self::JsonPayload>,
|
||||
) -> Result<Self, RESTRequestError> {
|
||||
let payload = body_payload.ok_or(RESTRequestError::NoPayloadProvided)?;
|
||||
) -> Result<Self, RestRequestError> {
|
||||
let payload = body_payload.ok_or(RestRequestError::NoPayloadProvided)?;
|
||||
let url = Url::parse(&format!("{}{}", base_url, Self::RELATIVE_PATH))
|
||||
.map_err(|err| RESTRequestError::MalformedUrl(err.to_string()))?;
|
||||
.map_err(|err| RestRequestError::MalformedUrl(err.to_string()))?;
|
||||
|
||||
Ok(Request { url, payload })
|
||||
}
|
||||
|
||||
+7
-7
@@ -1,6 +1,6 @@
|
||||
use crate::models::mixmining::BatchMixStatus;
|
||||
use crate::rest_requests::{PathParam, QueryParam, RESTRequest, RESTRequestError};
|
||||
use crate::DefaultRESTResponse;
|
||||
use crate::rest_requests::{PathParam, QueryParam, RestRequest, RestRequestError};
|
||||
use crate::DefaultRestResponse;
|
||||
use reqwest::{Method, Url};
|
||||
|
||||
pub struct Request {
|
||||
@@ -8,21 +8,21 @@ pub struct Request {
|
||||
payload: BatchMixStatus,
|
||||
}
|
||||
|
||||
impl RESTRequest for Request {
|
||||
impl RestRequest for Request {
|
||||
const METHOD: Method = Method::POST;
|
||||
const RELATIVE_PATH: &'static str = "/api/mixmining/batch";
|
||||
type JsonPayload = BatchMixStatus;
|
||||
type ExpectedJsonResponse = DefaultRESTResponse;
|
||||
type ExpectedJsonResponse = DefaultRestResponse;
|
||||
|
||||
fn new(
|
||||
base_url: &str,
|
||||
_: Option<Vec<PathParam>>,
|
||||
_: Option<Vec<QueryParam>>,
|
||||
body_payload: Option<Self::JsonPayload>,
|
||||
) -> Result<Self, RESTRequestError> {
|
||||
let payload = body_payload.ok_or(RESTRequestError::NoPayloadProvided)?;
|
||||
) -> Result<Self, RestRequestError> {
|
||||
let payload = body_payload.ok_or(RestRequestError::NoPayloadProvided)?;
|
||||
let url = Url::parse(&format!("{}{}", base_url, Self::RELATIVE_PATH))
|
||||
.map_err(|err| RESTRequestError::MalformedUrl(err.to_string()))?;
|
||||
.map_err(|err| RestRequestError::MalformedUrl(err.to_string()))?;
|
||||
Ok(Request { url, payload })
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::models::mixmining::MixStatus;
|
||||
use crate::rest_requests::{PathParam, QueryParam, RESTRequest, RESTRequestError};
|
||||
use crate::DefaultRESTResponse;
|
||||
use crate::rest_requests::{PathParam, QueryParam, RestRequest, RestRequestError};
|
||||
use crate::DefaultRestResponse;
|
||||
use reqwest::{Method, Url};
|
||||
|
||||
pub struct Request {
|
||||
@@ -8,21 +8,21 @@ pub struct Request {
|
||||
payload: MixStatus,
|
||||
}
|
||||
|
||||
impl RESTRequest for Request {
|
||||
impl RestRequest for Request {
|
||||
const METHOD: Method = Method::POST;
|
||||
const RELATIVE_PATH: &'static str = "/api/mixmining";
|
||||
type JsonPayload = MixStatus;
|
||||
type ExpectedJsonResponse = DefaultRESTResponse;
|
||||
type ExpectedJsonResponse = DefaultRestResponse;
|
||||
|
||||
fn new(
|
||||
base_url: &str,
|
||||
_: Option<Vec<PathParam>>,
|
||||
_: Option<Vec<QueryParam>>,
|
||||
body_payload: Option<Self::JsonPayload>,
|
||||
) -> Result<Self, RESTRequestError> {
|
||||
let payload = body_payload.ok_or(RESTRequestError::NoPayloadProvided)?;
|
||||
) -> Result<Self, RestRequestError> {
|
||||
let payload = body_payload.ok_or(RestRequestError::NoPayloadProvided)?;
|
||||
let url = Url::parse(&format!("{}{}", base_url, Self::RELATIVE_PATH))
|
||||
.map_err(|err| RESTRequestError::MalformedUrl(err.to_string()))?;
|
||||
.map_err(|err| RestRequestError::MalformedUrl(err.to_string()))?;
|
||||
Ok(Request { url, payload })
|
||||
}
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
// limitations under the License.
|
||||
|
||||
use crate::models::mixnode::MixRegistrationInfo;
|
||||
use crate::rest_requests::{PathParam, QueryParam, RESTRequest, RESTRequestError};
|
||||
use crate::DefaultRESTResponse;
|
||||
use crate::rest_requests::{PathParam, QueryParam, RestRequest, RestRequestError};
|
||||
use crate::DefaultRestResponse;
|
||||
use reqwest::{Method, Url};
|
||||
|
||||
pub struct Request {
|
||||
@@ -22,22 +22,22 @@ pub struct Request {
|
||||
payload: MixRegistrationInfo,
|
||||
}
|
||||
|
||||
impl RESTRequest for Request {
|
||||
impl RestRequest for Request {
|
||||
const METHOD: Method = Method::POST;
|
||||
const RELATIVE_PATH: &'static str = "/api/mixmining/register/mix";
|
||||
|
||||
type JsonPayload = MixRegistrationInfo;
|
||||
type ExpectedJsonResponse = DefaultRESTResponse;
|
||||
type ExpectedJsonResponse = DefaultRestResponse;
|
||||
|
||||
fn new(
|
||||
base_url: &str,
|
||||
_: Option<Vec<PathParam>>,
|
||||
_: Option<Vec<QueryParam>>,
|
||||
body_payload: Option<Self::JsonPayload>,
|
||||
) -> Result<Self, RESTRequestError> {
|
||||
let payload = body_payload.ok_or(RESTRequestError::NoPayloadProvided)?;
|
||||
) -> Result<Self, RestRequestError> {
|
||||
let payload = body_payload.ok_or(RestRequestError::NoPayloadProvided)?;
|
||||
let url = Url::parse(&format!("{}{}", base_url, Self::RELATIVE_PATH))
|
||||
.map_err(|err| RESTRequestError::MalformedUrl(err.to_string()))?;
|
||||
.map_err(|err| RestRequestError::MalformedUrl(err.to_string()))?;
|
||||
|
||||
Ok(Request { url, payload })
|
||||
}
|
||||
|
||||
@@ -40,35 +40,35 @@ type PathParam<'a> = &'a str;
|
||||
type QueryParam<'a> = (&'a str, &'a str);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum RESTRequestError {
|
||||
pub enum RestRequestError {
|
||||
InvalidPathParams,
|
||||
InvalidQueryParams,
|
||||
NoPayloadProvided,
|
||||
MalformedUrl(String),
|
||||
}
|
||||
|
||||
impl Display for RESTRequestError {
|
||||
impl Display for RestRequestError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
RESTRequestError::InvalidPathParams => write!(
|
||||
RestRequestError::InvalidPathParams => write!(
|
||||
f,
|
||||
"invalid number of path parameters was provided or they were malformed"
|
||||
),
|
||||
RESTRequestError::InvalidQueryParams => write!(
|
||||
RestRequestError::InvalidQueryParams => write!(
|
||||
f,
|
||||
"invalid number of query parameters was provided or they were malformed"
|
||||
),
|
||||
RESTRequestError::NoPayloadProvided => {
|
||||
RestRequestError::NoPayloadProvided => {
|
||||
write!(f, "no request payload was provided while it was expected")
|
||||
}
|
||||
RESTRequestError::MalformedUrl(url) => {
|
||||
RestRequestError::MalformedUrl(url) => {
|
||||
write!(f, "tried to make request to malformed url ({})", url)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait RESTRequest {
|
||||
pub(crate) trait RestRequest {
|
||||
// 'GET', 'POST', 'DELETE', etc.
|
||||
const METHOD: Method;
|
||||
const RELATIVE_PATH: &'static str;
|
||||
@@ -81,7 +81,7 @@ pub(crate) trait RESTRequest {
|
||||
path_params: Option<Vec<PathParam>>,
|
||||
query_params: Option<Vec<QueryParam>>,
|
||||
body_payload: Option<Self::JsonPayload>,
|
||||
) -> Result<Self, RESTRequestError>
|
||||
) -> Result<Self, RestRequestError>
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
|
||||
@@ -12,36 +12,36 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::rest_requests::{PathParam, QueryParam, RESTRequest, RESTRequestError};
|
||||
use crate::DefaultRESTResponse;
|
||||
use crate::rest_requests::{PathParam, QueryParam, RestRequest, RestRequestError};
|
||||
use crate::DefaultRestResponse;
|
||||
use reqwest::{Method, Url};
|
||||
|
||||
pub struct Request {
|
||||
url: Url,
|
||||
}
|
||||
|
||||
impl RESTRequest for Request {
|
||||
impl RestRequest for Request {
|
||||
const METHOD: Method = Method::DELETE;
|
||||
const RELATIVE_PATH: &'static str = "/api/mixmining/register";
|
||||
type JsonPayload = ();
|
||||
type ExpectedJsonResponse = DefaultRESTResponse;
|
||||
type ExpectedJsonResponse = DefaultRestResponse;
|
||||
|
||||
fn new(
|
||||
base_url: &str,
|
||||
path_params: Option<Vec<PathParam>>,
|
||||
_: Option<Vec<QueryParam>>,
|
||||
_: Option<Self::JsonPayload>,
|
||||
) -> Result<Self, RESTRequestError> {
|
||||
) -> Result<Self, RestRequestError> {
|
||||
// node unregister requires single path param - the node id
|
||||
let path_params = path_params.ok_or(RESTRequestError::InvalidPathParams)?;
|
||||
let path_params = path_params.ok_or(RestRequestError::InvalidPathParams)?;
|
||||
if path_params.len() != 1 {
|
||||
return Err(RESTRequestError::InvalidPathParams);
|
||||
return Err(RestRequestError::InvalidPathParams);
|
||||
}
|
||||
// <base_url>/api/mixmining/register/{id}
|
||||
let base = format!("{}{}/{}", base_url, Self::RELATIVE_PATH, path_params[0]);
|
||||
|
||||
let url =
|
||||
Url::parse(&base).map_err(|err| RESTRequestError::MalformedUrl(err.to_string()))?;
|
||||
Url::parse(&base).map_err(|err| RestRequestError::MalformedUrl(err.to_string()))?;
|
||||
|
||||
Ok(Request { url })
|
||||
}
|
||||
|
||||
@@ -12,43 +12,43 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::rest_requests::{PathParam, QueryParam, RESTRequest, RESTRequestError};
|
||||
use crate::DefaultRESTResponse;
|
||||
use crate::rest_requests::{PathParam, QueryParam, RestRequest, RestRequestError};
|
||||
use crate::DefaultRestResponse;
|
||||
use reqwest::{Method, Url};
|
||||
|
||||
pub struct Request {
|
||||
url: Url,
|
||||
}
|
||||
|
||||
impl RESTRequest for Request {
|
||||
impl RestRequest for Request {
|
||||
const METHOD: Method = Method::PATCH;
|
||||
const RELATIVE_PATH: &'static str = "/api/mixmining/reputation";
|
||||
type JsonPayload = ();
|
||||
type ExpectedJsonResponse = DefaultRESTResponse;
|
||||
type ExpectedJsonResponse = DefaultRestResponse;
|
||||
|
||||
fn new(
|
||||
base_url: &str,
|
||||
path_params: Option<Vec<PathParam>>,
|
||||
query_params: Option<Vec<QueryParam>>,
|
||||
_: Option<Self::JsonPayload>,
|
||||
) -> Result<Self, RESTRequestError> {
|
||||
) -> Result<Self, RestRequestError> {
|
||||
// set reputation requires single path param - the node id
|
||||
// and single query param - what reputation should it be set to
|
||||
let path_params = path_params.ok_or(RESTRequestError::InvalidPathParams)?;
|
||||
let path_params = path_params.ok_or(RestRequestError::InvalidPathParams)?;
|
||||
if path_params.len() != 1 {
|
||||
return Err(RESTRequestError::InvalidPathParams);
|
||||
return Err(RestRequestError::InvalidPathParams);
|
||||
}
|
||||
|
||||
let query_params = query_params.ok_or(RESTRequestError::InvalidQueryParams)?;
|
||||
let query_params = query_params.ok_or(RestRequestError::InvalidQueryParams)?;
|
||||
if query_params.len() != 1 {
|
||||
return Err(RESTRequestError::InvalidQueryParams);
|
||||
return Err(RestRequestError::InvalidQueryParams);
|
||||
}
|
||||
|
||||
// <base_url>/api/mixmining/reputation/{id}
|
||||
let base = format!("{}{}/{}", base_url, Self::RELATIVE_PATH, path_params[0]);
|
||||
|
||||
let url = Url::parse_with_params(&base, query_params)
|
||||
.map_err(|err| RESTRequestError::MalformedUrl(err.to_string()))?;
|
||||
.map_err(|err| RestRequestError::MalformedUrl(err.to_string()))?;
|
||||
|
||||
Ok(Request { url })
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
use crate::models::topology::Topology;
|
||||
use crate::rest_requests::{PathParam, QueryParam, RESTRequest, RESTRequestError};
|
||||
use crate::rest_requests::{PathParam, QueryParam, RestRequest, RestRequestError};
|
||||
use crate::ErrorResponses;
|
||||
use reqwest::{Method, Url};
|
||||
use serde::Deserialize;
|
||||
@@ -29,7 +29,7 @@ pub(crate) enum Response {
|
||||
Error(ErrorResponses),
|
||||
}
|
||||
|
||||
impl RESTRequest for Request {
|
||||
impl RestRequest for Request {
|
||||
const METHOD: Method = Method::GET;
|
||||
const RELATIVE_PATH: &'static str = "/api/mixmining/topology";
|
||||
|
||||
@@ -41,9 +41,9 @@ impl RESTRequest for Request {
|
||||
_: Option<Vec<PathParam>>,
|
||||
_: Option<Vec<QueryParam>>,
|
||||
_: Option<Self::JsonPayload>,
|
||||
) -> Result<Self, RESTRequestError> {
|
||||
) -> Result<Self, RestRequestError> {
|
||||
let url = Url::parse(&format!("{}{}", base_url, Self::RELATIVE_PATH))
|
||||
.map_err(|err| RESTRequestError::MalformedUrl(err.to_string()))?;
|
||||
.map_err(|err| RestRequestError::MalformedUrl(err.to_string()))?;
|
||||
|
||||
Ok(Request { url })
|
||||
}
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#![allow(renamed_and_removed_lints)]
|
||||
#![allow(unknown_lints)] // beta-nightly
|
||||
#![allow(clippy::unknown_clippy_lints)] // `clippy::upper_case_acronyms` does not exist on stable just yet
|
||||
use generic_array::{typenum::Unsigned, GenericArray};
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use stream_cipher::{Nonce, StreamCipher, SyncStreamCipher};
|
||||
@@ -12,6 +18,9 @@ pub use stream_cipher::{Key, NewStreamCipher};
|
||||
// means that for, for example, 128-bit security, after generating 2^64 IVs
|
||||
// we are going to have 50% chance of collision. But perhaps that's fine?
|
||||
// TODO2: ask @AP if what I wrote here even makes sense in the context of what we're doing.
|
||||
|
||||
// I think 'IV' looks better than 'Iv', feel free to change that.
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
pub type IV<C> = Nonce<C>;
|
||||
|
||||
pub fn generate_key<C, R>(rng: &mut R) -> Key<C>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use nymsphinx_acknowledgements::surb_ack::SURBAckRecoveryError;
|
||||
use nymsphinx_acknowledgements::surb_ack::SurbAckRecoveryError;
|
||||
use nymsphinx_addressing::nodes::NymNodeRoutingAddressError;
|
||||
use nymsphinx_types::Error as SphinxError;
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
@@ -21,8 +21,8 @@ use std::fmt::{self, Display, Formatter};
|
||||
pub enum MixProcessingError {
|
||||
SphinxProcessingError(SphinxError),
|
||||
InvalidHopAddress(NymNodeRoutingAddressError),
|
||||
NoSURBAckInFinalHop,
|
||||
MalformedSURBAck(SURBAckRecoveryError),
|
||||
NoSurbAckInFinalHop,
|
||||
MalformedSurbAck(SurbAckRecoveryError),
|
||||
}
|
||||
|
||||
impl From<SphinxError> for MixProcessingError {
|
||||
@@ -42,11 +42,11 @@ impl From<NymNodeRoutingAddressError> for MixProcessingError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SURBAckRecoveryError> for MixProcessingError {
|
||||
fn from(err: SURBAckRecoveryError) -> Self {
|
||||
impl From<SurbAckRecoveryError> for MixProcessingError {
|
||||
fn from(err: SurbAckRecoveryError) -> Self {
|
||||
use MixProcessingError::*;
|
||||
|
||||
MalformedSURBAck(err)
|
||||
MalformedSurbAck(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,10 +59,10 @@ impl Display for MixProcessingError {
|
||||
MixProcessingError::InvalidHopAddress(address_err) => {
|
||||
write!(f, "Invalid Hop Address - {:?}", address_err)
|
||||
}
|
||||
MixProcessingError::NoSURBAckInFinalHop => {
|
||||
MixProcessingError::NoSurbAckInFinalHop => {
|
||||
write!(f, "No SURBAck present in the final hop data")
|
||||
}
|
||||
MixProcessingError::MalformedSURBAck(surb_ack_err) => {
|
||||
MixProcessingError::MalformedSurbAck(surb_ack_err) => {
|
||||
write!(f, "Malformed SURBAck - {:?}", surb_ack_err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
use crate::cached_packet_processor::cache::KeyCache;
|
||||
use crate::cached_packet_processor::error::MixProcessingError;
|
||||
use log::*;
|
||||
use nymsphinx_acknowledgements::surb_ack::SURBAck;
|
||||
use nymsphinx_acknowledgements::surb_ack::SurbAck;
|
||||
use nymsphinx_addressing::nodes::NymNodeRoutingAddress;
|
||||
use nymsphinx_forwarding::packet::MixPacket;
|
||||
use nymsphinx_framing::packet::FramedSphinxPacket;
|
||||
@@ -181,11 +181,11 @@ impl CachedPacketProcessor {
|
||||
) -> Result<(Vec<u8>, Vec<u8>), MixProcessingError> {
|
||||
// in theory it's impossible for this to fail since it managed to go into correct `match`
|
||||
// branch at the caller
|
||||
if extracted_data.len() < SURBAck::len() {
|
||||
return Err(MixProcessingError::NoSURBAckInFinalHop);
|
||||
if extracted_data.len() < SurbAck::len() {
|
||||
return Err(MixProcessingError::NoSurbAckInFinalHop);
|
||||
}
|
||||
|
||||
let message = extracted_data.split_off(SURBAck::len());
|
||||
let message = extracted_data.split_off(SurbAck::len());
|
||||
let ack_data = extracted_data;
|
||||
Ok((ack_data, message))
|
||||
}
|
||||
@@ -199,14 +199,14 @@ impl CachedPacketProcessor {
|
||||
packet_mode: PacketMode,
|
||||
) -> Result<(Option<MixPacket>, Vec<u8>), MixProcessingError> {
|
||||
match packet_size {
|
||||
PacketSize::ACKPacket => {
|
||||
PacketSize::AckPacket => {
|
||||
trace!("received an ack packet!");
|
||||
Ok((None, data))
|
||||
}
|
||||
PacketSize::RegularPacket | PacketSize::ExtendedPacket => {
|
||||
trace!("received a normal packet!");
|
||||
let (ack_data, message) = self.split_hop_data_into_ack_and_message(data)?;
|
||||
let (ack_first_hop, ack_packet) = SURBAck::try_recover_first_hop_packet(&ack_data)?;
|
||||
let (ack_first_hop, ack_packet) = SurbAck::try_recover_first_hop_packet(&ack_data)?;
|
||||
let forward_ack = MixPacket::new(ack_first_hop, ack_packet, packet_mode);
|
||||
Ok((Some(forward_ack), message))
|
||||
}
|
||||
@@ -403,7 +403,7 @@ mod tests {
|
||||
assert!(processor.vpn_key_cache.is_empty());
|
||||
|
||||
let final_hop = make_valid_final_sphinx_packet(Default::default(), local_keys.1);
|
||||
let framed = FramedSphinxPacket::new(final_hop, PacketMode::VPN);
|
||||
let framed = FramedSphinxPacket::new(final_hop, PacketMode::Vpn);
|
||||
|
||||
processor.perform_initial_unwrapping(framed).unwrap();
|
||||
assert_eq!(processor.vpn_key_cache.len(), 1);
|
||||
@@ -416,7 +416,7 @@ mod tests {
|
||||
assert!(processor.vpn_key_cache.is_empty());
|
||||
|
||||
let forward_hop = make_valid_forward_sphinx_packet(Default::default(), local_keys.1);
|
||||
let framed = FramedSphinxPacket::new(forward_hop, PacketMode::VPN);
|
||||
let framed = FramedSphinxPacket::new(forward_hop, PacketMode::Vpn);
|
||||
|
||||
processor.perform_initial_unwrapping(framed).unwrap();
|
||||
assert_eq!(processor.vpn_key_cache.len(), 1);
|
||||
@@ -457,28 +457,28 @@ mod tests {
|
||||
.split_hop_data_into_ack_and_message(short_data)
|
||||
.is_err());
|
||||
|
||||
let sufficient_data = vec![42u8; SURBAck::len()];
|
||||
let sufficient_data = vec![42u8; SurbAck::len()];
|
||||
let (ack, data) = processor
|
||||
.split_hop_data_into_ack_and_message(sufficient_data.clone())
|
||||
.unwrap();
|
||||
assert_eq!(sufficient_data, ack);
|
||||
assert!(data.is_empty());
|
||||
|
||||
let long_data = vec![42u8; SURBAck::len() * 5];
|
||||
let long_data = vec![42u8; SurbAck::len() * 5];
|
||||
let (ack, data) = processor
|
||||
.split_hop_data_into_ack_and_message(long_data)
|
||||
.unwrap();
|
||||
assert_eq!(ack.len(), SURBAck::len());
|
||||
assert_eq!(data.len(), SURBAck::len() * 4)
|
||||
assert_eq!(ack.len(), SurbAck::len());
|
||||
assert_eq!(data.len(), SurbAck::len() * 4)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn splitting_into_ack_and_message_returns_whole_data_for_ack() {
|
||||
let processor = fixture();
|
||||
|
||||
let data = vec![42u8; SURBAck::len() + 10];
|
||||
let data = vec![42u8; SurbAck::len() + 10];
|
||||
let (ack, message) = processor
|
||||
.split_into_ack_and_message(data.clone(), PacketSize::ACKPacket, Default::default())
|
||||
.split_into_ack_and_message(data.clone(), PacketSize::AckPacket, Default::default())
|
||||
.unwrap();
|
||||
assert!(ack.is_none());
|
||||
assert_eq!(data, message)
|
||||
|
||||
@@ -41,7 +41,7 @@ pub fn recover_identifier(
|
||||
) -> Option<SerializedFragmentIdentifier> {
|
||||
// The content of an 'ACK' packet consists of AckEncryptionAlgorithm::IV followed by
|
||||
// serialized FragmentIdentifier
|
||||
if iv_id_ciphertext.len() != PacketSize::ACKPacket.plaintext_size() {
|
||||
if iv_id_ciphertext.len() != PacketSize::AckPacket.plaintext_size() {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,21 +28,20 @@ use std::convert::TryFrom;
|
||||
use std::time;
|
||||
use topology::{NymTopology, NymTopologyError};
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub struct SURBAck {
|
||||
pub struct SurbAck {
|
||||
surb_ack_packet: SphinxPacket,
|
||||
first_hop_address: NymNodeRoutingAddress,
|
||||
expected_total_delay: Delay,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SURBAckRecoveryError {
|
||||
pub enum SurbAckRecoveryError {
|
||||
InvalidPacketSize,
|
||||
InvalidAddress,
|
||||
InvalidSphinxPacket,
|
||||
}
|
||||
|
||||
impl SURBAck {
|
||||
impl SurbAck {
|
||||
pub fn construct<R>(
|
||||
rng: &mut R,
|
||||
recipient: &Recipient,
|
||||
@@ -63,7 +62,7 @@ impl SURBAck {
|
||||
let surb_ack_payload = prepare_identifier(rng, ack_key, marshaled_fragment_id);
|
||||
|
||||
let mut surb_builder =
|
||||
SphinxPacketBuilder::new().with_payload_size(PacketSize::ACKPacket.payload_size());
|
||||
SphinxPacketBuilder::new().with_payload_size(PacketSize::AckPacket.payload_size());
|
||||
if let Some(initial_secret) = initial_sphinx_secret {
|
||||
surb_builder = surb_builder.with_initial_secret(initial_secret);
|
||||
}
|
||||
@@ -77,7 +76,7 @@ impl SURBAck {
|
||||
let first_hop_address =
|
||||
NymNodeRoutingAddress::try_from(route.first().unwrap().address).unwrap();
|
||||
|
||||
Ok(SURBAck {
|
||||
Ok(SurbAck {
|
||||
surb_ack_packet,
|
||||
first_hop_address,
|
||||
expected_total_delay,
|
||||
@@ -87,7 +86,7 @@ impl SURBAck {
|
||||
pub fn len() -> usize {
|
||||
// TODO: this will be variable once/if we decide to introduce optimization described
|
||||
// in common/nymsphinx/chunking/src/lib.rs:available_plaintext_size()
|
||||
PacketSize::ACKPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN
|
||||
PacketSize::AckPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN
|
||||
}
|
||||
|
||||
pub fn prepare_for_sending(self) -> (Delay, Vec<u8>) {
|
||||
@@ -104,13 +103,13 @@ impl SURBAck {
|
||||
// partial reciprocal of `prepare_for_sending` performed by the gateway
|
||||
pub fn try_recover_first_hop_packet(
|
||||
b: &[u8],
|
||||
) -> Result<(NymNodeRoutingAddress, SphinxPacket), SURBAckRecoveryError> {
|
||||
) -> Result<(NymNodeRoutingAddress, SphinxPacket), SurbAckRecoveryError> {
|
||||
if b.len() != Self::len() {
|
||||
Err(SURBAckRecoveryError::InvalidPacketSize)
|
||||
Err(SurbAckRecoveryError::InvalidPacketSize)
|
||||
} else {
|
||||
let address = match NymNodeRoutingAddress::try_from_bytes(&b) {
|
||||
Ok(address) => address,
|
||||
Err(_) => return Err(SURBAckRecoveryError::InvalidAddress),
|
||||
Err(_) => return Err(SurbAckRecoveryError::InvalidAddress),
|
||||
};
|
||||
|
||||
// TODO: this will be variable once/if we decide to introduce optimization described
|
||||
@@ -118,7 +117,7 @@ impl SURBAck {
|
||||
let address_offset = MAX_NODE_ADDRESS_UNPADDED_LEN;
|
||||
let packet = match SphinxPacket::from_bytes(&b[address_offset..]) {
|
||||
Ok(packet) => packet,
|
||||
Err(_) => return Err(SURBAckRecoveryError::InvalidSphinxPacket),
|
||||
Err(_) => return Err(SurbAckRecoveryError::InvalidSphinxPacket),
|
||||
};
|
||||
|
||||
Ok((address, packet))
|
||||
|
||||
@@ -34,7 +34,7 @@ pub const MAX_NODE_ADDRESS_UNPADDED_LEN: usize = 19;
|
||||
#[derive(Debug)]
|
||||
pub enum NymNodeRoutingAddressError {
|
||||
InsufficientNumberOfBytesAvailableError,
|
||||
InvalidIPVersion,
|
||||
InvalidIpVersion,
|
||||
}
|
||||
|
||||
/// Current representation of Node routing information used in Nym system.
|
||||
@@ -114,7 +114,7 @@ impl NymNodeRoutingAddress {
|
||||
address_octets.copy_from_slice(&b[3..19]);
|
||||
IpAddr::V6(Ipv6Addr::from(address_octets))
|
||||
}
|
||||
_ => return Err(NymNodeRoutingAddressError::InvalidIPVersion),
|
||||
_ => return Err(NymNodeRoutingAddressError::InvalidIpVersion),
|
||||
};
|
||||
|
||||
Ok(Self(SocketAddr::new(ip, port)))
|
||||
|
||||
@@ -19,52 +19,52 @@ use crypto::{
|
||||
symmetric::stream_cipher::{generate_key, Key, NewStreamCipher},
|
||||
Digest,
|
||||
};
|
||||
use nymsphinx_params::{ReplySURBEncryptionAlgorithm, ReplySURBKeyDigestAlgorithm};
|
||||
use nymsphinx_params::{ReplySurbEncryptionAlgorithm, ReplySurbKeyDigestAlgorithm};
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
|
||||
pub type EncryptionKeyDigest =
|
||||
GenericArray<u8, <ReplySURBKeyDigestAlgorithm as Digest>::OutputSize>;
|
||||
GenericArray<u8, <ReplySurbKeyDigestAlgorithm as Digest>::OutputSize>;
|
||||
|
||||
pub type SURBEncryptionKeySize = <ReplySURBEncryptionAlgorithm as NewStreamCipher>::KeySize;
|
||||
pub type SurbEncryptionKeySize = <ReplySurbEncryptionAlgorithm as NewStreamCipher>::KeySize;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SURBEncryptionKey(Key<ReplySURBEncryptionAlgorithm>);
|
||||
pub struct SurbEncryptionKey(Key<ReplySurbEncryptionAlgorithm>);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SURBEncryptionKeyError {
|
||||
pub enum SurbEncryptionKeyError {
|
||||
BytesOfInvalidLengthError,
|
||||
}
|
||||
|
||||
impl Display for SURBEncryptionKeyError {
|
||||
impl Display for SurbEncryptionKeyError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
SURBEncryptionKeyError::BytesOfInvalidLengthError => {
|
||||
SurbEncryptionKeyError::BytesOfInvalidLengthError => {
|
||||
write!(f, "provided bytes have invalid length")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for SURBEncryptionKeyError {}
|
||||
impl std::error::Error for SurbEncryptionKeyError {}
|
||||
|
||||
impl SURBEncryptionKey {
|
||||
impl SurbEncryptionKey {
|
||||
/// Generates fresh pseudorandom key that is going to be used by the recipient of the message
|
||||
/// to encrypt payload of the reply. It is only generated when reply-SURB is attached.
|
||||
pub fn new<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
|
||||
SURBEncryptionKey(generate_key::<ReplySURBEncryptionAlgorithm, _>(rng))
|
||||
SurbEncryptionKey(generate_key::<ReplySurbEncryptionAlgorithm, _>(rng))
|
||||
}
|
||||
|
||||
pub fn try_from_bytes(bytes: &[u8]) -> Result<Self, SURBEncryptionKeyError> {
|
||||
if bytes.len() != SURBEncryptionKeySize::to_usize() {
|
||||
return Err(SURBEncryptionKeyError::BytesOfInvalidLengthError);
|
||||
pub fn try_from_bytes(bytes: &[u8]) -> Result<Self, SurbEncryptionKeyError> {
|
||||
if bytes.len() != SurbEncryptionKeySize::to_usize() {
|
||||
return Err(SurbEncryptionKeyError::BytesOfInvalidLengthError);
|
||||
}
|
||||
|
||||
Ok(SURBEncryptionKey(GenericArray::clone_from_slice(bytes)))
|
||||
Ok(SurbEncryptionKey(GenericArray::clone_from_slice(bytes)))
|
||||
}
|
||||
|
||||
pub fn compute_digest(&self) -> EncryptionKeyDigest {
|
||||
crypto_hash::compute_digest::<ReplySURBKeyDigestAlgorithm>(&self.0)
|
||||
crypto_hash::compute_digest::<ReplySurbKeyDigestAlgorithm>(&self.0)
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
@@ -75,7 +75,7 @@ impl SURBEncryptionKey {
|
||||
self.0.as_ref()
|
||||
}
|
||||
|
||||
pub fn inner(&self) -> &Key<ReplySURBEncryptionAlgorithm> {
|
||||
pub fn inner(&self) -> &Key<ReplySurbEncryptionAlgorithm> {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,5 +15,5 @@
|
||||
pub mod encryption_key;
|
||||
pub mod reply_surb;
|
||||
|
||||
pub use encryption_key::{SURBEncryptionKey, SURBEncryptionKeySize};
|
||||
pub use reply_surb::{ReplySURB, ReplySURBError};
|
||||
pub use encryption_key::{SurbEncryptionKey, SurbEncryptionKeySize};
|
||||
pub use reply_surb::{ReplySurb, ReplySurbError};
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
// limitations under the License.
|
||||
|
||||
use crate::encryption_key::{
|
||||
SURBEncryptionKey, SURBEncryptionKeyError, SURBEncryptionKeySize, Unsigned,
|
||||
SurbEncryptionKey, SurbEncryptionKeyError, SurbEncryptionKeySize, Unsigned,
|
||||
};
|
||||
use crypto::Digest;
|
||||
use nymsphinx_addressing::clients::Recipient;
|
||||
use nymsphinx_addressing::nodes::{NymNodeRoutingAddress, MAX_NODE_ADDRESS_UNPADDED_LEN};
|
||||
use nymsphinx_params::packet_sizes::PacketSize;
|
||||
use nymsphinx_params::{ReplySURBKeyDigestAlgorithm, DEFAULT_NUM_MIX_HOPS};
|
||||
use nymsphinx_params::{ReplySurbKeyDigestAlgorithm, DEFAULT_NUM_MIX_HOPS};
|
||||
use nymsphinx_types::{delays, Error as SphinxError, SURBMaterial, SphinxPacket, SURB};
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use serde::de::{Error as SerdeError, Visitor};
|
||||
@@ -30,26 +30,26 @@ use std::time;
|
||||
use topology::{NymTopology, NymTopologyError};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ReplySURBError {
|
||||
pub enum ReplySurbError {
|
||||
UnpaddedMessageError,
|
||||
MalformedStringError(bs58::decode::Error),
|
||||
RecoveryError(SphinxError),
|
||||
InvalidEncryptionKeyData(SURBEncryptionKeyError),
|
||||
InvalidEncryptionKeyData(SurbEncryptionKeyError),
|
||||
}
|
||||
|
||||
impl fmt::Display for ReplySURBError {
|
||||
impl fmt::Display for ReplySurbError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
ReplySURBError::UnpaddedMessageError => {
|
||||
ReplySurbError::UnpaddedMessageError => {
|
||||
write!(f, "tried to use reply SURB with an unpadded message")
|
||||
}
|
||||
ReplySURBError::MalformedStringError(decode_err) => {
|
||||
ReplySurbError::MalformedStringError(decode_err) => {
|
||||
write!(f, "reply SURB is incorrectly formatted: {}", decode_err)
|
||||
}
|
||||
ReplySURBError::RecoveryError(sphinx_err) => {
|
||||
ReplySurbError::RecoveryError(sphinx_err) => {
|
||||
write!(f, "failed to recover reply SURB from bytes: {}", sphinx_err)
|
||||
}
|
||||
ReplySURBError::InvalidEncryptionKeyData(surb_key_err) => write!(
|
||||
ReplySurbError::InvalidEncryptionKeyData(surb_key_err) => write!(
|
||||
f,
|
||||
"failed to recover reply SURB encryption key from bytes: {}",
|
||||
surb_key_err
|
||||
@@ -59,23 +59,23 @@ impl fmt::Display for ReplySURBError {
|
||||
}
|
||||
|
||||
// since we have Debug and Display might as well slap Error on top of it too
|
||||
impl std::error::Error for ReplySURBError {}
|
||||
impl std::error::Error for ReplySurbError {}
|
||||
|
||||
impl From<SURBEncryptionKeyError> for ReplySURBError {
|
||||
fn from(err: SURBEncryptionKeyError) -> Self {
|
||||
ReplySURBError::InvalidEncryptionKeyData(err)
|
||||
impl From<SurbEncryptionKeyError> for ReplySurbError {
|
||||
fn from(err: SurbEncryptionKeyError) -> Self {
|
||||
ReplySurbError::InvalidEncryptionKeyData(err)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ReplySURB {
|
||||
pub struct ReplySurb {
|
||||
surb: SURB,
|
||||
encryption_key: SURBEncryptionKey,
|
||||
encryption_key: SurbEncryptionKey,
|
||||
}
|
||||
|
||||
// Serialize + Deserialize is not really used anymore (it was for a CBOR experiment)
|
||||
// however, if we decided we needed it again, it's already here
|
||||
impl Serialize for ReplySURB {
|
||||
impl Serialize for ReplySurb {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -84,15 +84,15 @@ impl Serialize for ReplySURB {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for ReplySURB {
|
||||
impl<'de> Deserialize<'de> for ReplySurb {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'de>>::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct ReplySURBVisitor;
|
||||
struct ReplySurbVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for ReplySURBVisitor {
|
||||
type Value = ReplySURB;
|
||||
impl<'de> Visitor<'de> for ReplySurbVisitor {
|
||||
type Value = ReplySurb;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(formatter, "A replySURB must contain a valid symmetric encryption key and a correctly formed sphinx header")
|
||||
@@ -102,20 +102,20 @@ impl<'de> Deserialize<'de> for ReplySURB {
|
||||
where
|
||||
E: SerdeError,
|
||||
{
|
||||
ReplySURB::from_bytes(bytes)
|
||||
ReplySurb::from_bytes(bytes)
|
||||
.map_err(|_| SerdeError::invalid_length(bytes.len(), &self))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_bytes(ReplySURBVisitor)
|
||||
deserializer.deserialize_bytes(ReplySurbVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl ReplySURB {
|
||||
impl ReplySurb {
|
||||
pub fn max_msg_len(packet_size: PacketSize) -> usize {
|
||||
// For detailed explanation (of ack overhead) refer to common\nymsphinx\src\preparer.rs::available_plaintext_per_packet()
|
||||
let ack_overhead = MAX_NODE_ADDRESS_UNPADDED_LEN + PacketSize::ACKPacket.size();
|
||||
packet_size.plaintext_size() - ack_overhead - ReplySURBKeyDigestAlgorithm::output_size() - 1
|
||||
let ack_overhead = MAX_NODE_ADDRESS_UNPADDED_LEN + PacketSize::AckPacket.size();
|
||||
packet_size.plaintext_size() - ack_overhead - ReplySurbKeyDigestAlgorithm::output_size() - 1
|
||||
}
|
||||
|
||||
// TODO: should this return `ReplySURBError` for consistency sake
|
||||
@@ -137,9 +137,9 @@ impl ReplySURB {
|
||||
let surb_material = SURBMaterial::new(route, delays, destination);
|
||||
|
||||
// this can't fail as we know we have a valid route to gateway and have correct number of delays
|
||||
Ok(ReplySURB {
|
||||
Ok(ReplySurb {
|
||||
surb: surb_material.construct_SURB().unwrap(),
|
||||
encryption_key: SURBEncryptionKey::new(rng),
|
||||
encryption_key: SurbEncryptionKey::new(rng),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -150,13 +150,13 @@ impl ReplySURB {
|
||||
|
||||
// the SURB itself consists of SURB_header, first hop address and set of payload keys
|
||||
// (note extra 1 for the gateway)
|
||||
SURBEncryptionKeySize::to_usize()
|
||||
SurbEncryptionKeySize::to_usize()
|
||||
+ HEADER_SIZE
|
||||
+ NODE_ADDRESS_LENGTH
|
||||
+ (1 + mix_hops as usize) * PAYLOAD_KEY_SIZE
|
||||
}
|
||||
|
||||
pub fn encryption_key(&self) -> &SURBEncryptionKey {
|
||||
pub fn encryption_key(&self) -> &SurbEncryptionKey {
|
||||
&self.encryption_key
|
||||
}
|
||||
|
||||
@@ -169,16 +169,16 @@ impl ReplySURB {
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, ReplySURBError> {
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, ReplySurbError> {
|
||||
let encryption_key =
|
||||
SURBEncryptionKey::try_from_bytes(&bytes[..SURBEncryptionKeySize::to_usize()])?;
|
||||
SurbEncryptionKey::try_from_bytes(&bytes[..SurbEncryptionKeySize::to_usize()])?;
|
||||
|
||||
let surb = match SURB::from_bytes(&bytes[SURBEncryptionKeySize::to_usize()..]) {
|
||||
Err(err) => return Err(ReplySURBError::RecoveryError(err)),
|
||||
let surb = match SURB::from_bytes(&bytes[SurbEncryptionKeySize::to_usize()..]) {
|
||||
Err(err) => return Err(ReplySurbError::RecoveryError(err)),
|
||||
Ok(surb) => surb,
|
||||
};
|
||||
|
||||
Ok(ReplySURB {
|
||||
Ok(ReplySurb {
|
||||
surb,
|
||||
encryption_key,
|
||||
})
|
||||
@@ -188,10 +188,10 @@ impl ReplySURB {
|
||||
bs58::encode(&self.to_bytes()).into_string()
|
||||
}
|
||||
|
||||
pub fn from_base58_string<S: Into<String>>(val: S) -> Result<Self, ReplySURBError> {
|
||||
pub fn from_base58_string<S: Into<String>>(val: S) -> Result<Self, ReplySurbError> {
|
||||
let bytes = match bs58::decode(val.into()).into_vec() {
|
||||
Ok(decoded) => decoded,
|
||||
Err(err) => return Err(ReplySURBError::MalformedStringError(err)),
|
||||
Err(err) => return Err(ReplySurbError::MalformedStringError(err)),
|
||||
};
|
||||
Self::from_bytes(&bytes)
|
||||
}
|
||||
@@ -206,11 +206,11 @@ impl ReplySURB {
|
||||
self,
|
||||
message: &[u8],
|
||||
packet_size: Option<PacketSize>,
|
||||
) -> Result<(SphinxPacket, NymNodeRoutingAddress), ReplySURBError> {
|
||||
) -> Result<(SphinxPacket, NymNodeRoutingAddress), ReplySurbError> {
|
||||
let packet_size = packet_size.unwrap_or_else(Default::default);
|
||||
|
||||
if message.len() != packet_size.plaintext_size() {
|
||||
return Err(ReplySURBError::UnpaddedMessageError);
|
||||
return Err(ReplySurbError::UnpaddedMessageError);
|
||||
}
|
||||
|
||||
// this can realistically only fail on too long messages and we just checked for that
|
||||
|
||||
@@ -453,7 +453,7 @@ mod fragment_tests {
|
||||
use rand::{thread_rng, RngCore};
|
||||
|
||||
fn max_plaintext_size() -> usize {
|
||||
PacketSize::default().plaintext_size() - PacketSize::ACKPacket.size()
|
||||
PacketSize::default().plaintext_size() - PacketSize::AckPacket.size()
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -147,7 +147,7 @@ mod tests {
|
||||
// plaintext len should not affect this at all, but let's test it with something tiny
|
||||
// and reasonable
|
||||
let used_plaintext_len = PacketSize::default().plaintext_size()
|
||||
- PacketSize::ACKPacket.size()
|
||||
- PacketSize::AckPacket.size()
|
||||
- MAX_NODE_ADDRESS_UNPADDED_LEN;
|
||||
|
||||
let plaintext_lens = vec![17, used_plaintext_len, 20, 42, 10000];
|
||||
|
||||
@@ -311,7 +311,7 @@ mod tests {
|
||||
use nymsphinx_params::packet_sizes::PacketSize;
|
||||
|
||||
fn max_plaintext_size() -> usize {
|
||||
PacketSize::default().plaintext_size() - PacketSize::ACKPacket.size()
|
||||
PacketSize::default().plaintext_size() - PacketSize::AckPacket.size()
|
||||
}
|
||||
|
||||
fn verify_unlinked_set_payload(mut set: FragmentSet, payload: &[u8]) {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
use crypto::shared_key::new_ephemeral_shared_key;
|
||||
use crypto::symmetric::stream_cipher;
|
||||
use nymsphinx_acknowledgements::surb_ack::SURBAck;
|
||||
use nymsphinx_acknowledgements::surb_ack::SurbAck;
|
||||
use nymsphinx_acknowledgements::AckKey;
|
||||
use nymsphinx_addressing::clients::Recipient;
|
||||
use nymsphinx_addressing::nodes::{NymNodeRoutingAddress, NymNodeRoutingAddressError};
|
||||
@@ -66,11 +66,11 @@ pub fn generate_loop_cover_surb_ack<R>(
|
||||
ack_key: &AckKey,
|
||||
full_address: &Recipient,
|
||||
average_ack_delay: time::Duration,
|
||||
) -> Result<SURBAck, CoverMessageError>
|
||||
) -> Result<SurbAck, CoverMessageError>
|
||||
where
|
||||
R: RngCore + CryptoRng,
|
||||
{
|
||||
Ok(SURBAck::construct(
|
||||
Ok(SurbAck::construct(
|
||||
rng,
|
||||
full_address,
|
||||
ack_key,
|
||||
|
||||
@@ -37,7 +37,7 @@ impl Display for MixPacketFormattingError {
|
||||
write!(
|
||||
f,
|
||||
"received request had invalid size. (actual: {}, but expected one of: {} (ACK), {} (REGULAR), {} (EXTENDED))",
|
||||
actual, PacketSize::ACKPacket.size(), PacketSize::RegularPacket.size(), PacketSize::ExtendedPacket.size()
|
||||
actual, PacketSize::AckPacket.size(), PacketSize::RegularPacket.size(), PacketSize::ExtendedPacket.size()
|
||||
),
|
||||
MalformedSphinxPacket => write!(f, "received sphinx packet was malformed"),
|
||||
InvalidPacketMode => write!(f, "provided packet mode is invalid")
|
||||
|
||||
@@ -86,7 +86,7 @@ impl Decoder for SphinxCodec {
|
||||
if src.is_empty() {
|
||||
// can't do anything if we have no bytes, but let's reserve enough for the most
|
||||
// conservative case, i.e. receiving an ack packet
|
||||
src.reserve(Header::SIZE + PacketSize::ACKPacket.size());
|
||||
src.reserve(Header::SIZE + PacketSize::AckPacket.size());
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ impl Decoder for SphinxCodec {
|
||||
let next_frame_len = next_packet_len.size() + Header::SIZE;
|
||||
src.reserve(next_frame_len - 1);
|
||||
} else {
|
||||
src.reserve(Header::SIZE + PacketSize::ACKPacket.size());
|
||||
src.reserve(Header::SIZE + PacketSize::AckPacket.size());
|
||||
}
|
||||
|
||||
Ok(Some(nymsphinx_packet))
|
||||
@@ -218,7 +218,7 @@ mod packet_encoding {
|
||||
assert!(SphinxCodec.decode(&mut empty_bytes).unwrap().is_none());
|
||||
assert_eq!(
|
||||
empty_bytes.capacity(),
|
||||
Header::SIZE + PacketSize::ACKPacket.size()
|
||||
Header::SIZE + PacketSize::AckPacket.size()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ mod packet_encoding {
|
||||
fn for_bytes_with_header() {
|
||||
// if header gets decoded there should be enough bytes for the entire frame
|
||||
let packet_sizes = vec![
|
||||
PacketSize::ACKPacket,
|
||||
PacketSize::AckPacket,
|
||||
PacketSize::RegularPacket,
|
||||
PacketSize::ExtendedPacket,
|
||||
];
|
||||
@@ -256,7 +256,7 @@ mod packet_encoding {
|
||||
assert!(SphinxCodec.decode(&mut bytes).unwrap().is_some());
|
||||
assert_eq!(
|
||||
bytes.capacity(),
|
||||
Header::SIZE + PacketSize::ACKPacket.size()
|
||||
Header::SIZE + PacketSize::AckPacket.size()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -264,7 +264,7 @@ mod packet_encoding {
|
||||
fn for_full_frame_with_extra_byte() {
|
||||
// if there was at least 1 byte left, there should be enough space for entire next frame
|
||||
let packet_sizes = vec![
|
||||
PacketSize::ACKPacket,
|
||||
PacketSize::AckPacket,
|
||||
PacketSize::RegularPacket,
|
||||
PacketSize::ExtendedPacket,
|
||||
];
|
||||
|
||||
@@ -147,7 +147,7 @@ mod header_encoding {
|
||||
#[test]
|
||||
fn header_encoding_reserves_enough_bytes_for_full_sphinx_packet() {
|
||||
let packet_sizes = vec![
|
||||
PacketSize::ACKPacket,
|
||||
PacketSize::AckPacket,
|
||||
PacketSize::RegularPacket,
|
||||
PacketSize::ExtendedPacket,
|
||||
];
|
||||
|
||||
@@ -40,7 +40,7 @@ pub type PacketHkdfAlgorithm = blake3::Hasher;
|
||||
pub type GatewaySharedKeyHkdfAlgorithm = blake3::Hasher;
|
||||
|
||||
/// Hashing algorithm used when computing digest of a reply SURB encryption key.
|
||||
pub type ReplySURBKeyDigestAlgorithm = blake3::Hasher;
|
||||
pub type ReplySurbKeyDigestAlgorithm = blake3::Hasher;
|
||||
|
||||
/// Hashing algorithm used when computing integrity (H)Mac for message exchanged between client and gateway.
|
||||
// TODO: if updated, the pem type defined in gateway\gateway-requests\src\registration\handshake\shared_key
|
||||
@@ -67,4 +67,4 @@ pub type PacketEncryptionAlgorithm = Aes128Ctr;
|
||||
/// Encryption algorithm used for end-to-end encryption of reply messages constructed using ReplySURBs.
|
||||
// TODO: I don't see any reason for it to be different than what is used for regular packets. Perhaps
|
||||
// it could be potentially insecure to use anything else?
|
||||
pub type ReplySURBEncryptionAlgorithm = PacketEncryptionAlgorithm;
|
||||
pub type ReplySurbEncryptionAlgorithm = PacketEncryptionAlgorithm;
|
||||
|
||||
@@ -26,7 +26,7 @@ pub enum PacketMode {
|
||||
|
||||
/// Represents a VPN packet that should not be delayed and ideally cached pre-computed keys
|
||||
/// should be used for unwrapping data. Note that it does not offer the same level of anonymity.
|
||||
VPN = 1,
|
||||
Vpn = 1,
|
||||
}
|
||||
|
||||
impl PacketMode {
|
||||
@@ -35,7 +35,7 @@ impl PacketMode {
|
||||
}
|
||||
|
||||
pub fn is_vpn(self) -> bool {
|
||||
self == PacketMode::VPN
|
||||
self == PacketMode::Vpn
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ impl TryFrom<u8> for PacketMode {
|
||||
fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
|
||||
match value {
|
||||
_ if value == (PacketMode::Mix as u8) => Ok(Self::Mix),
|
||||
_ if value == (PacketMode::VPN as u8) => Ok(Self::VPN),
|
||||
_ if value == (PacketMode::Vpn as u8) => Ok(Self::Vpn),
|
||||
_ => Err(InvalidPacketMode),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ pub enum PacketSize {
|
||||
RegularPacket = 1,
|
||||
|
||||
// for sending SURB-ACKs
|
||||
ACKPacket = 2,
|
||||
AckPacket = 2,
|
||||
|
||||
// for example for streaming fast and furious in uncompressed 10bit 4K HDR quality
|
||||
ExtendedPacket = 3,
|
||||
@@ -50,7 +50,7 @@ impl TryFrom<u8> for PacketSize {
|
||||
fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
|
||||
match value {
|
||||
_ if value == (PacketSize::RegularPacket as u8) => Ok(Self::RegularPacket),
|
||||
_ if value == (PacketSize::ACKPacket as u8) => Ok(Self::ACKPacket),
|
||||
_ if value == (PacketSize::AckPacket as u8) => Ok(Self::AckPacket),
|
||||
_ if value == (PacketSize::ExtendedPacket as u8) => Ok(Self::ExtendedPacket),
|
||||
_ => Err(InvalidPacketSize),
|
||||
}
|
||||
@@ -61,7 +61,7 @@ impl PacketSize {
|
||||
pub fn size(self) -> usize {
|
||||
match self {
|
||||
PacketSize::RegularPacket => REGULAR_PACKET_SIZE,
|
||||
PacketSize::ACKPacket => ACK_PACKET_SIZE,
|
||||
PacketSize::AckPacket => ACK_PACKET_SIZE,
|
||||
PacketSize::ExtendedPacket => EXTENDED_PACKET_SIZE,
|
||||
}
|
||||
}
|
||||
@@ -77,8 +77,8 @@ impl PacketSize {
|
||||
pub fn get_type(size: usize) -> std::result::Result<Self, InvalidPacketSize> {
|
||||
if PacketSize::RegularPacket.size() == size {
|
||||
Ok(PacketSize::RegularPacket)
|
||||
} else if PacketSize::ACKPacket.size() == size {
|
||||
Ok(PacketSize::ACKPacket)
|
||||
} else if PacketSize::AckPacket.size() == size {
|
||||
Ok(PacketSize::AckPacket)
|
||||
} else if PacketSize::ExtendedPacket.size() == size {
|
||||
Ok(PacketSize::ExtendedPacket)
|
||||
} else {
|
||||
|
||||
@@ -12,24 +12,24 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use self::vpn_manager::VPNManager;
|
||||
use self::vpn_manager::VpnManager;
|
||||
use crate::chunking;
|
||||
use crypto::asymmetric::encryption;
|
||||
use crypto::shared_key::new_ephemeral_shared_key;
|
||||
use crypto::symmetric::stream_cipher;
|
||||
use crypto::Digest;
|
||||
use nymsphinx_acknowledgements::surb_ack::SURBAck;
|
||||
use nymsphinx_acknowledgements::surb_ack::SurbAck;
|
||||
use nymsphinx_acknowledgements::AckKey;
|
||||
use nymsphinx_addressing::clients::Recipient;
|
||||
use nymsphinx_addressing::nodes::{NymNodeRoutingAddress, MAX_NODE_ADDRESS_UNPADDED_LEN};
|
||||
use nymsphinx_anonymous_replies::encryption_key::SURBEncryptionKey;
|
||||
use nymsphinx_anonymous_replies::reply_surb::ReplySURB;
|
||||
use nymsphinx_anonymous_replies::encryption_key::SurbEncryptionKey;
|
||||
use nymsphinx_anonymous_replies::reply_surb::ReplySurb;
|
||||
use nymsphinx_chunking::fragment::{Fragment, FragmentIdentifier};
|
||||
use nymsphinx_forwarding::packet::MixPacket;
|
||||
use nymsphinx_params::packet_sizes::PacketSize;
|
||||
use nymsphinx_params::{
|
||||
PacketEncryptionAlgorithm, PacketHkdfAlgorithm, PacketMode, ReplySURBEncryptionAlgorithm,
|
||||
ReplySURBKeyDigestAlgorithm, DEFAULT_NUM_MIX_HOPS,
|
||||
PacketEncryptionAlgorithm, PacketHkdfAlgorithm, PacketMode, ReplySurbEncryptionAlgorithm,
|
||||
ReplySurbKeyDigestAlgorithm, DEFAULT_NUM_MIX_HOPS,
|
||||
};
|
||||
use nymsphinx_types::builder::SphinxPacketBuilder;
|
||||
use nymsphinx_types::{delays, Delay};
|
||||
@@ -95,7 +95,7 @@ pub struct MessagePreparer<R: CryptoRng + Rng> {
|
||||
|
||||
/// If the VPN mode is activated, this underlying secret will be used for multiple sphinx
|
||||
/// packets created.
|
||||
vpn_manager: Option<VPNManager>,
|
||||
vpn_manager: Option<VpnManager>,
|
||||
}
|
||||
|
||||
impl<R> MessagePreparer<R>
|
||||
@@ -111,7 +111,7 @@ where
|
||||
vpn_key_reuse_limit: Option<usize>,
|
||||
) -> Self {
|
||||
let vpn_manager = if mode.is_vpn() {
|
||||
Some(VPNManager::new(
|
||||
Some(VpnManager::new(
|
||||
&mut rng,
|
||||
vpn_key_reuse_limit.expect("No key reuse limit provided in vpn mode!"),
|
||||
))
|
||||
@@ -159,7 +159,7 @@ where
|
||||
// and only then perform the chunking with `available_plaintext_size` being called per chunk.
|
||||
// However this will probably introduce bunch of complexity
|
||||
// for relatively not a lot of gain, so it shouldn't be done just yet.
|
||||
let ack_overhead = MAX_NODE_ADDRESS_UNPADDED_LEN + PacketSize::ACKPacket.size();
|
||||
let ack_overhead = MAX_NODE_ADDRESS_UNPADDED_LEN + PacketSize::AckPacket.size();
|
||||
let ephemeral_public_key_overhead = encryption::PUBLIC_KEY_SIZE;
|
||||
|
||||
self.packet_size.plaintext_size() - ack_overhead - ephemeral_public_key_overhead
|
||||
@@ -192,9 +192,9 @@ where
|
||||
message: Vec<u8>,
|
||||
should_attach: bool,
|
||||
topology: &NymTopology,
|
||||
) -> Result<(Vec<u8>, Option<SURBEncryptionKey>), PreparationError> {
|
||||
) -> Result<(Vec<u8>, Option<SurbEncryptionKey>), PreparationError> {
|
||||
if should_attach {
|
||||
let reply_surb = ReplySURB::construct(
|
||||
let reply_surb = ReplySurb::construct(
|
||||
&mut self.rng,
|
||||
&self.sender_address,
|
||||
self.average_packet_delay,
|
||||
@@ -343,10 +343,10 @@ where
|
||||
fragment_id: FragmentIdentifier,
|
||||
topology: &NymTopology,
|
||||
ack_key: &AckKey,
|
||||
) -> Result<SURBAck, NymTopologyError> {
|
||||
) -> Result<SurbAck, NymTopologyError> {
|
||||
if let Some(vpn_manager) = self.vpn_manager.as_mut() {
|
||||
let initial_secret = vpn_manager.use_secret(&mut self.rng).await;
|
||||
SURBAck::construct(
|
||||
SurbAck::construct(
|
||||
&mut self.rng,
|
||||
&self.sender_address,
|
||||
ack_key,
|
||||
@@ -356,7 +356,7 @@ where
|
||||
Some(&initial_secret),
|
||||
)
|
||||
} else {
|
||||
SURBAck::construct(
|
||||
SurbAck::construct(
|
||||
&mut self.rng,
|
||||
&self.sender_address,
|
||||
ack_key,
|
||||
@@ -376,7 +376,7 @@ where
|
||||
message: Vec<u8>,
|
||||
with_reply_surb: bool,
|
||||
topology: &NymTopology,
|
||||
) -> Result<(Vec<Fragment>, Option<SURBEncryptionKey>), PreparationError> {
|
||||
) -> Result<(Vec<Fragment>, Option<SurbEncryptionKey>), PreparationError> {
|
||||
let (message, reply_key) =
|
||||
self.optionally_attach_reply_surb(message, with_reply_surb, topology)?;
|
||||
|
||||
@@ -389,7 +389,7 @@ where
|
||||
pub async fn prepare_reply_for_use(
|
||||
&mut self,
|
||||
message: Vec<u8>,
|
||||
reply_surb: ReplySURB,
|
||||
reply_surb: ReplySurb,
|
||||
topology: &NymTopology,
|
||||
ack_key: &AckKey,
|
||||
) -> Result<(MixPacket, FragmentIdentifier), PreparationError> {
|
||||
@@ -398,11 +398,11 @@ where
|
||||
// and need 1 byte to indicate padding length (this is not the case for 'normal' messages
|
||||
// as there the padding is added for the whole message)
|
||||
// so before doing any processing, let's see if we have enough space for it all
|
||||
let ack_overhead = MAX_NODE_ADDRESS_UNPADDED_LEN + PacketSize::ACKPacket.size();
|
||||
let ack_overhead = MAX_NODE_ADDRESS_UNPADDED_LEN + PacketSize::AckPacket.size();
|
||||
if message.len()
|
||||
> self.packet_size.plaintext_size()
|
||||
- ack_overhead
|
||||
- ReplySURBKeyDigestAlgorithm::output_size()
|
||||
- ReplySurbKeyDigestAlgorithm::output_size()
|
||||
- 1
|
||||
{
|
||||
return Err(PreparationError::TooLongReplyMessageError);
|
||||
@@ -422,7 +422,7 @@ where
|
||||
let zero_pad_len = self.packet_size.plaintext_size()
|
||||
- message.len()
|
||||
- ack_overhead
|
||||
- ReplySURBKeyDigestAlgorithm::output_size()
|
||||
- ReplySurbKeyDigestAlgorithm::output_size()
|
||||
- 1;
|
||||
|
||||
// create reply message that will reach the recipient:
|
||||
@@ -433,8 +433,8 @@ where
|
||||
.collect();
|
||||
|
||||
// encrypt the reply message
|
||||
let zero_iv = stream_cipher::zero_iv::<ReplySURBEncryptionAlgorithm>();
|
||||
stream_cipher::encrypt_in_place::<ReplySURBEncryptionAlgorithm>(
|
||||
let zero_iv = stream_cipher::zero_iv::<ReplySurbEncryptionAlgorithm>();
|
||||
stream_cipher::encrypt_in_place::<ReplySurbEncryptionAlgorithm>(
|
||||
reply_surb.encryption_key().inner(),
|
||||
&zero_iv,
|
||||
&mut reply_content,
|
||||
|
||||
@@ -27,7 +27,7 @@ pub(super) type SpinhxKeyRef<'a> = RwLockReadGuard<'a, EphemeralSecret>;
|
||||
pub(super) type SpinhxKeyRef<'a> = &'a EphemeralSecret;
|
||||
|
||||
#[cfg_attr(not(target_arch = "wasm32"), derive(Clone))]
|
||||
pub(super) struct VPNManager {
|
||||
pub(super) struct VpnManager {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
inner: Arc<Inner>,
|
||||
|
||||
@@ -55,14 +55,14 @@ struct Inner {
|
||||
packets_with_current_secret: AtomicUsize,
|
||||
}
|
||||
|
||||
impl VPNManager {
|
||||
impl VpnManager {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub(super) fn new<R>(mut rng: R, secret_reuse_limit: usize) -> Self
|
||||
where
|
||||
R: CryptoRng + Rng,
|
||||
{
|
||||
let initial_secret = EphemeralSecret::new_with_rng(&mut rng);
|
||||
VPNManager {
|
||||
VpnManager {
|
||||
inner: Arc::new(Inner {
|
||||
secret_reuse_limit,
|
||||
current_initial_secret: RwLock::new(initial_secret),
|
||||
@@ -77,7 +77,7 @@ impl VPNManager {
|
||||
R: CryptoRng + Rng,
|
||||
{
|
||||
let initial_secret = EphemeralSecret::new_with_rng(&mut rng);
|
||||
VPNManager {
|
||||
VpnManager {
|
||||
inner: Inner {
|
||||
secret_reuse_limit,
|
||||
current_initial_secret: initial_secret,
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
use crypto::asymmetric::encryption;
|
||||
use crypto::shared_key::recompute_shared_key;
|
||||
use crypto::symmetric::stream_cipher;
|
||||
use nymsphinx_anonymous_replies::reply_surb::{ReplySURB, ReplySURBError};
|
||||
use nymsphinx_anonymous_replies::reply_surb::{ReplySurb, ReplySurbError};
|
||||
use nymsphinx_chunking::fragment::Fragment;
|
||||
use nymsphinx_chunking::reconstruction::MessageReconstructor;
|
||||
use nymsphinx_params::{PacketEncryptionAlgorithm, PacketHkdfAlgorithm, DEFAULT_NUM_MIX_HOPS};
|
||||
@@ -27,13 +27,13 @@ pub struct ReconstructedMessage {
|
||||
pub message: Vec<u8>,
|
||||
|
||||
/// Optional ReplySURB to allow for an anonymous reply to the sender.
|
||||
pub reply_surb: Option<ReplySURB>,
|
||||
pub reply_surb: Option<ReplySurb>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MessageRecoveryError {
|
||||
InvalidSurbPrefixError,
|
||||
MalformedSURBError(ReplySURBError),
|
||||
MalformedSurbError(ReplySurbError),
|
||||
InvalidRemoteEphemeralKey(encryption::KeyRecoveryError),
|
||||
MalformedFragmentError,
|
||||
InvalidMessagePaddingError,
|
||||
@@ -41,9 +41,9 @@ pub enum MessageRecoveryError {
|
||||
TooShortMessageError,
|
||||
}
|
||||
|
||||
impl From<ReplySURBError> for MessageRecoveryError {
|
||||
fn from(err: ReplySURBError) -> Self {
|
||||
MessageRecoveryError::MalformedSURBError(err)
|
||||
impl From<ReplySurbError> for MessageRecoveryError {
|
||||
fn from(err: ReplySurbError) -> Self {
|
||||
MessageRecoveryError::MalformedSurbError(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,17 +78,17 @@ impl MessageReceiver {
|
||||
fn recover_reply_surb_from_message(
|
||||
&self,
|
||||
message: &mut Vec<u8>,
|
||||
) -> Result<Option<ReplySURB>, MessageRecoveryError> {
|
||||
) -> Result<Option<ReplySurb>, MessageRecoveryError> {
|
||||
match message[0] {
|
||||
n if n == false as u8 => {
|
||||
message.remove(0);
|
||||
Ok(None)
|
||||
}
|
||||
n if n == true as u8 => {
|
||||
let surb_len: usize = ReplySURB::serialized_len(self.num_mix_hops);
|
||||
let surb_len: usize = ReplySurb::serialized_len(self.num_mix_hops);
|
||||
// note the extra +1 (due to 0/1 message prefix)
|
||||
let surb_bytes = &message[1..1 + surb_len];
|
||||
let reply_surb = ReplySURB::from_bytes(surb_bytes)?;
|
||||
let reply_surb = ReplySurb::from_bytes(surb_bytes)?;
|
||||
|
||||
*message = message.drain(1 + surb_len..).collect();
|
||||
Ok(Some(reply_surb))
|
||||
@@ -304,7 +304,7 @@ mod message_receiver {
|
||||
let topology = topology_fixture();
|
||||
|
||||
let reply_surb =
|
||||
ReplySURB::construct(&mut OsRng, &dummy_recipient, average_delay, &topology).unwrap();
|
||||
ReplySurb::construct(&mut OsRng, &dummy_recipient, average_delay, &topology).unwrap();
|
||||
|
||||
let reply_surb_bytes = reply_surb.to_bytes();
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#![allow(renamed_and_removed_lints)]
|
||||
#![allow(unknown_lints)] // beta-nightly
|
||||
#![allow(clippy::unknown_clippy_lints)] // `clippy::upper_case_acronyms` does not exist on stable just yet
|
||||
use crypto::generic_array::{typenum::Unsigned, GenericArray};
|
||||
use crypto::symmetric::stream_cipher::{random_iv, NewStreamCipher, IV};
|
||||
use nymsphinx::params::GatewayEncryptionAlgorithm;
|
||||
@@ -8,9 +11,13 @@ use rand::{CryptoRng, RngCore};
|
||||
|
||||
type NonceSize = <GatewayEncryptionAlgorithm as NewStreamCipher>::NonceSize;
|
||||
|
||||
// I think 'IV' looks better than 'Iv', feel free to change that.
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
pub struct AuthenticationIV(IV<GatewayEncryptionAlgorithm>);
|
||||
|
||||
#[derive(Debug)]
|
||||
// I think 'IV' looks better than 'Iv', feel free to change that.
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
pub enum IVConversionError {
|
||||
DecodeError(bs58::decode::Error),
|
||||
BytesOfInvalidLengthError,
|
||||
|
||||
@@ -58,7 +58,7 @@ impl TryInto<String> for RegistrationHandshake {
|
||||
#[derive(Debug)]
|
||||
pub enum GatewayRequestsError {
|
||||
TooShortRequest,
|
||||
InvalidMAC,
|
||||
InvalidMac,
|
||||
IncorrectlyEncodedAddress,
|
||||
RequestOfInvalidSize(usize),
|
||||
MalformedSphinxPacket,
|
||||
@@ -72,13 +72,13 @@ impl fmt::Display for GatewayRequestsError {
|
||||
use GatewayRequestsError::*;
|
||||
match self {
|
||||
TooShortRequest => write!(f, "the request is too short"),
|
||||
InvalidMAC => write!(f, "provided MAC is invalid"),
|
||||
InvalidMac => write!(f, "provided MAC is invalid"),
|
||||
IncorrectlyEncodedAddress => write!(f, "address field was incorrectly encoded"),
|
||||
RequestOfInvalidSize(actual) =>
|
||||
write!(
|
||||
f,
|
||||
"received request had invalid size. (actual: {}, but expected one of: {} (ACK), {} (REGULAR), {} (EXTENDED))",
|
||||
actual, PacketSize::ACKPacket.size(), PacketSize::RegularPacket.size(), PacketSize::ExtendedPacket.size()
|
||||
actual, PacketSize::AckPacket.size(), PacketSize::RegularPacket.size(), PacketSize::ExtendedPacket.size()
|
||||
),
|
||||
MalformedSphinxPacket => write!(f, "received sphinx packet was malformed"),
|
||||
MalformedEncryption => write!(f, "the received encrypted data was malformed"),
|
||||
@@ -226,7 +226,7 @@ impl BinaryRequest {
|
||||
message_bytes,
|
||||
mac_tag,
|
||||
) {
|
||||
return Err(GatewayRequestsError::InvalidMAC);
|
||||
return Err(GatewayRequestsError::InvalidMac);
|
||||
}
|
||||
|
||||
// couldn't have made the first borrow mutable as you can't have an immutable borrow
|
||||
@@ -291,7 +291,7 @@ impl BinaryResponse {
|
||||
message_bytes,
|
||||
mac_tag,
|
||||
) {
|
||||
return Err(GatewayRequestsError::InvalidMAC);
|
||||
return Err(GatewayRequestsError::InvalidMac);
|
||||
}
|
||||
|
||||
let zero_iv = stream_cipher::zero_iv::<GatewayEncryptionAlgorithm>();
|
||||
|
||||
@@ -37,7 +37,7 @@ use tokio_tungstenite::{
|
||||
//// but as byproduct this might (or might not) break the clean "SocketStream" enum here
|
||||
|
||||
enum SocketStream<S> {
|
||||
RawTCP(S),
|
||||
RawTcp(S),
|
||||
UpgradedWebSocket(WebSocketStream<S>),
|
||||
Invalid,
|
||||
}
|
||||
@@ -78,7 +78,7 @@ where
|
||||
shared_key: None,
|
||||
clients_handler_sender,
|
||||
outbound_mix_sender,
|
||||
socket_connection: SocketStream::RawTCP(conn),
|
||||
socket_connection: SocketStream::RawTcp(conn),
|
||||
local_identity,
|
||||
}
|
||||
}
|
||||
@@ -89,7 +89,7 @@ where
|
||||
{
|
||||
self.socket_connection =
|
||||
match std::mem::replace(&mut self.socket_connection, SocketStream::Invalid) {
|
||||
SocketStream::RawTCP(conn) => {
|
||||
SocketStream::RawTcp(conn) => {
|
||||
// TODO: perhaps in the future, rather than panic here (and uncleanly shut tcp stream)
|
||||
// return a result with an error?
|
||||
let ws_stream = match tokio_tungstenite::accept_async(conn).await {
|
||||
|
||||
@@ -35,7 +35,7 @@ impl Gateway {
|
||||
identity: identity::KeyPair,
|
||||
) -> Self {
|
||||
let registered_clients_ledger = match ClientLedger::load(config.get_clients_ledger_path()) {
|
||||
Err(e) => panic!(format!("Failed to load the ledger - {:?}", e)),
|
||||
Err(e) => panic!("Failed to load the ledger - {:?}", e),
|
||||
Ok(ledger) => ledger,
|
||||
};
|
||||
let client_inbox_storage = inboxes::ClientStorage::new(
|
||||
|
||||
Reference in New Issue
Block a user