Compare commits

..

1 Commits

Author SHA1 Message Date
benedettadavico 2f98912778 fix nym-connect version 2023-06-20 13:56:38 +02:00
45 changed files with 102 additions and 753 deletions
+1 -2
View File
@@ -68,10 +68,8 @@ jobs:
working-directory: nym-connect/native/android
env:
ANDROID_SDK_ROOT: ${{ env.ANDROID_HOME }}
SENTRY_AUTH_TOKEN: ${{ secrets.NYMS5_ANDROID_SENTRY_AUTH_TOKEN }}
# build for arm64 and x86_64
run: |
echo "auth.token=$SENTRY_AUTH_TOKEN" | tee -a sentry.properties
./gradlew :app:assembleArch64Debug
./gradlew :app:assembleArch64Release
@@ -109,3 +107,4 @@ jobs:
files: |
apk/nyms5-arch64-debug.apk
apk/nyms5-arch64-release.apk
+12 -17
View File
@@ -27,22 +27,17 @@ jobs:
run: sudo apt-get update && sudo apt-get -y install build-essential curl wget libssl-dev libgtk-3-dev libudev-dev squashfs-tools git
continue-on-error: true
# - name: Update env variables to include go
# run: |
# sudo rm -rf /usr/local/go
# curl https://dl.google.com/go/go1.20.4.linux-amd64.tar.gz | sudo tar -C/usr/local -zxvf -
# cat <<'EOF' >>$HOME/.profile
# export GOROOT=/usr/local/go
# export GOPATH=$HOME/go
# export GO111MODULE=on
# export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin
# EOF
# source $HOME/.profile
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: "1.20.4"
- name: Update env variables to include go
run: |
sudo rm -rf /usr/local/go
curl https://dl.google.com/go/go1.19.2.linux-amd64.tar.gz | sudo tar -C/usr/local -zxvf -
cat <<'EOF' >>$HOME/.profile
export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export GO111MODULE=on
export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin
EOF
source $HOME/.profile
- name: Verify Go is installed
run: go version
@@ -51,7 +46,7 @@ jobs:
run: |
git clone https://github.com/tommyv1987/nyxd
cd nyxd
git checkout release/v0.31.1
git checkout release/v0.30.2
- name: Run nyxd
run: |
Generated
-5
View File
@@ -3507,10 +3507,8 @@ dependencies = [
"nym-multisig-contract-common",
"nym-name-service-common",
"nym-network-defaults",
"nym-pemstore",
"nym-service-provider-directory-common",
"nym-sphinx",
"nym-types",
"nym-validator-client",
"nym-vesting-contract-common",
"rand 0.6.5",
@@ -4404,7 +4402,6 @@ dependencies = [
"nym-pemstore",
"nym-sphinx-addressing",
"nym-sphinx-params",
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.7.3",
@@ -4432,7 +4429,6 @@ dependencies = [
"nym-crypto",
"nym-sphinx-addressing",
"nym-sphinx-params",
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.7.3",
@@ -4464,7 +4460,6 @@ dependencies = [
"nym-sphinx-chunking",
"nym-sphinx-forwarding",
"nym-sphinx-params",
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.7.3",
+3 -17
View File
@@ -2240,7 +2240,7 @@ dependencies = [
[[package]]
name = "nym-bin-common"
version = "0.6.0"
version = "0.5.0"
dependencies = [
"atty",
"clap",
@@ -2255,7 +2255,7 @@ dependencies = [
[[package]]
name = "nym-client-core"
version = "1.1.15"
version = "1.1.14"
dependencies = [
"async-trait",
"base64 0.21.2",
@@ -2300,7 +2300,7 @@ dependencies = [
[[package]]
name = "nym-client-wasm"
version = "1.1.1"
version = "1.1.0"
dependencies = [
"anyhow",
"async-trait",
@@ -2697,7 +2697,6 @@ dependencies = [
"nym-pemstore",
"nym-sphinx-addressing",
"nym-sphinx-params",
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.7.3",
@@ -2724,7 +2723,6 @@ dependencies = [
"nym-crypto",
"nym-sphinx-addressing",
"nym-sphinx-params",
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.7.3",
@@ -2755,7 +2753,6 @@ dependencies = [
"nym-sphinx-chunking",
"nym-sphinx-forwarding",
"nym-sphinx-params",
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.7.3",
@@ -2887,7 +2884,6 @@ dependencies = [
"nym-service-provider-directory-common",
"nym-vesting-contract",
"nym-vesting-contract-common",
"openssl",
"prost",
"reqwest",
"serde",
@@ -2978,15 +2974,6 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-src"
version = "111.26.0+1.1.1u"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efc62c9f12b22b8f5208c23a7200a442b2e5999f8bdf80233852122b5a4f6f37"
dependencies = [
"cc",
]
[[package]]
name = "openssl-sys"
version = "0.9.87"
@@ -2995,7 +2982,6 @@ checksum = "8e17f59264b2809d77ae94f0e1ebabc434773f370d6ca667bd223ea10e06cc7e"
dependencies = [
"cc",
"libc",
"openssl-src",
"pkg-config",
"vcpkg",
]
+4 -41
View File
@@ -116,11 +116,11 @@ async function testWithTester() {
// B) first get topology directly from nym-api
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
// const topology = await current_network_topology(validator)
// const nodeTester = await new NymNodeTester(topology, undefined, preferredGateway);
// const nodeTester = await new NymNodeTester(topology, preferredGateway);
//
// C) use nym-api in the constructor (note: it does no filtering for 'good' nodes on other layers)
// const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
// const nodeTester = await NymNodeTester.new_with_api(validator, undefined, preferredGateway)
// const nodeTester = await NymNodeTester.new_with_api(validator, preferredGateway)
// D, E, F) you also don't have to specify the gateway. if you don't, a random one (from your topology) will be used
// const topology = dummyTopology()
@@ -139,40 +139,6 @@ async function testWithTester() {
}
}
};
}
async function testerReconnection() {
const validator = 'https://qwerty-validator-api.qa.nymte.ch/api';
const nodeTester = await NymNodeTester.new_with_api(validator);
self.onmessage = async event => {
if (event.data && event.data.kind) {
switch (event.data.kind) {
case 'TestPacket': {
const {mixnodeIdentity} = event.data.args;
console.log("starting node test...");
let result1 = await nodeTester.test_node(mixnodeIdentity);
console.log("sleeping for 5s");
await new Promise(r => setTimeout(r, 5000));
await nodeTester.disconnect_from_gateway();
console.log("sleeping for 5s");
await new Promise(r => setTimeout(r, 5000));
await nodeTester.reconnect_to_gateway();
let result2 = await nodeTester.test_node(mixnodeIdentity);
printAndDisplayTestResult(result1)
printAndDisplayTestResult(result2)
}
}
}
};
}
async function testWithNymClient() {
@@ -364,17 +330,14 @@ async function main() {
// sets up better stack traces in case of in-rust panics
set_panic_hook();
// show reconnection capabilities
// await testerReconnection()
// run test on simplified and dedicated tester:
await testWithTester()
// await testWithTester()
// hook-up the whole client for testing
// await testWithNymClient()
// 'Normal' client setup (to send 'normal' messages)
// await normalNymClientUsage()
await normalNymClientUsage()
}
// Let's get started!
-38
View File
@@ -4,9 +4,6 @@
// due to expansion of #[wasm_bindgen] macro on NodeTestResult
#![allow(clippy::drop_non_drop)]
use crate::error::WasmClientError;
use crate::tester::LockedGatewayClient;
use js_sys::Promise;
use nym_node_tester_utils::processor::Received;
use nym_node_tester_utils::receiver::ReceivedReceiver;
use serde::{Deserialize, Serialize};
@@ -15,7 +12,6 @@ use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use tokio::sync::{Mutex as AsyncMutex, MutexGuard as AsyncMutexGuard};
use wasm_bindgen::prelude::*;
use wasm_bindgen_futures::future_to_promise;
use wasm_utils::{console_log, console_warn};
#[derive(Clone)]
@@ -111,37 +107,3 @@ impl Drop for TestMarker {
self.value.store(false, Ordering::SeqCst)
}
}
pub(crate) trait GatewayReconnection {
fn disconnect_from_gateway(&self) -> Promise;
fn reconnect_to_gateway(&self) -> Promise;
}
impl GatewayReconnection for LockedGatewayClient {
fn disconnect_from_gateway(&self) -> Promise {
let this = self.clone();
future_to_promise(async move {
let mut guard = this.lock().await;
guard
.disconnect()
.await
.map_err(|err| JsValue::from(WasmClientError::from(err)))?;
Ok(JsValue::undefined())
})
}
fn reconnect_to_gateway(&self) -> Promise {
let this = self.clone();
future_to_promise(async move {
let mut guard = this.lock().await;
guard
.try_reconnect()
.await
.map_err(|err| JsValue::from(WasmClientError::from(err)))?;
Ok(JsValue::undefined())
})
}
}
+10 -41
View File
@@ -7,7 +7,7 @@ use crate::helpers::{current_network_topology_async, setup_from_topology};
use crate::storage::ClientStorage;
use crate::tester::ephemeral_receiver::EphemeralTestReceiver;
use crate::tester::helpers::{
GatewayReconnection, NodeTestResult, ReceivedReceiverWrapper, TestMarker, WasmTestMessageExt,
NodeTestResult, ReceivedReceiverWrapper, TestMarker, WasmTestMessageExt,
};
use crate::topology::WasmNymTopology;
use futures::channel::mpsc;
@@ -73,7 +73,6 @@ pub struct NymNodeTester {
#[wasm_bindgen]
pub struct NymNodeTesterBuilder {
gateway: Option<IdentityKey>,
id: Option<String>,
base_topology: NymTopology,
@@ -95,11 +94,9 @@ impl NymNodeTesterBuilder {
#[wasm_bindgen(constructor)]
pub fn new(
base_topology: WasmNymTopology,
id: Option<String>,
gateway: Option<IdentityKey>,
) -> NymNodeTesterBuilder {
NymNodeTesterBuilder {
id,
gateway,
base_topology: base_topology.into(),
bandwidth_controller: None,
@@ -108,20 +105,15 @@ impl NymNodeTesterBuilder {
async fn _new_with_api(
api_url: String,
id: Option<String>,
gateway: Option<IdentityKey>,
) -> Result<Self, WasmClientError> {
let topology = current_network_topology_async(api_url).await?;
Ok(NymNodeTesterBuilder::new(topology, id, gateway))
Ok(NymNodeTesterBuilder::new(topology, gateway))
}
pub fn new_with_api(
api_url: String,
id: Option<String>,
gateway: Option<IdentityKey>,
) -> Promise {
pub fn new_with_api(gateway: Option<IdentityKey>, api_url: String) -> Promise {
future_to_promise(async move {
Self::_new_with_api(api_url, id, gateway)
Self::_new_with_api(api_url, gateway)
.await
.into_promise_result()
})
@@ -141,13 +133,7 @@ impl NymNodeTesterBuilder {
async fn _setup_client(mut self) -> Result<NymNodeTester, WasmClientError> {
let task_manager = TaskManager::default();
let storage_id = if let Some(client_id) = &self.id {
format!("{NODE_TESTER_ID}-{client_id}")
} else {
NODE_TESTER_ID.to_owned()
};
let client_store = ClientStorage::new_async(&storage_id, None).await?;
let client_store = ClientStorage::new_async(NODE_TESTER_ID, None).await?;
let init_details = self.gateway_info(&client_store).await?;
let gateway_endpoint = init_details.gateway_details;
@@ -248,46 +234,29 @@ async fn test_mixnode(
impl NymNodeTester {
#[wasm_bindgen(constructor)]
#[allow(clippy::new_ret_no_self)]
pub fn new(
topology: WasmNymTopology,
id: Option<String>,
gateway: Option<IdentityKey>,
) -> Promise {
pub fn new(topology: WasmNymTopology, gateway: Option<IdentityKey>) -> Promise {
console_log!("constructing node tester!");
NymNodeTesterBuilder::new(topology, id, gateway).setup_client()
NymNodeTesterBuilder::new(topology, gateway).setup_client()
}
async fn _new_with_api(
api_url: String,
id: Option<String>,
gateway: Option<IdentityKey>,
) -> Result<Self, WasmClientError> {
NymNodeTesterBuilder::_new_with_api(api_url, id, gateway)
NymNodeTesterBuilder::_new_with_api(api_url, gateway)
.await?
._setup_client()
.await
}
pub fn new_with_api(
api_url: String,
id: Option<String>,
gateway: Option<IdentityKey>,
) -> Promise {
pub fn new_with_api(api_url: String, gateway: Option<IdentityKey>) -> Promise {
future_to_promise(async move {
Self::_new_with_api(api_url, id, gateway)
Self::_new_with_api(api_url, gateway)
.await
.into_promise_result()
})
}
pub fn disconnect_from_gateway(&self) -> Promise {
self.gateway_client.disconnect_from_gateway()
}
pub fn reconnect_to_gateway(&self) -> Promise {
self.gateway_client.reconnect_to_gateway()
}
fn prepare_test_packets(
&self,
mixnode_identity: String,
@@ -10,7 +10,7 @@ use log::*;
use nym_sphinx::acknowledgements::AckKey;
use nym_sphinx::addressing::clients::Recipient;
use nym_sphinx::cover::generate_loop_cover_packet;
use nym_sphinx::params::{PacketSize, PacketType};
use nym_sphinx::params::PacketSize;
use nym_sphinx::utils::sample_poisson_duration;
use rand::{rngs::OsRng, CryptoRng, Rng};
use std::pin::Pin;
@@ -63,8 +63,6 @@ where
/// Optional secondary predefined packet size used for the loop cover messages.
secondary_packet_size: Option<PacketSize>,
packet_type: PacketType,
}
impl<R> Stream for LoopCoverTrafficStream<R>
@@ -137,7 +135,6 @@ impl LoopCoverTrafficStream<OsRng> {
topology_access,
primary_packet_size: traffic_config.primary_packet_size,
secondary_packet_size: traffic_config.secondary_packet_size,
packet_type: traffic_config.packet_type,
}
}
@@ -197,7 +194,7 @@ impl LoopCoverTrafficStream<OsRng> {
self.average_ack_delay,
self.cover_traffic.loop_cover_traffic_average_delay,
cover_traffic_packet_size,
self.packet_type,
nym_sphinx::params::PacketType::Mix,
)
.expect("Somehow failed to generate a loop cover message with a valid topology");
@@ -724,7 +724,7 @@ impl<C, St> GatewayClient<C, St> {
Ok(())
}
pub async fn try_reconnect(&mut self) -> Result<(), GatewayClientError> {
async fn try_reconnect(&mut self) -> Result<(), GatewayClientError> {
if !self.connection.is_established() {
self.establish_connection().await?;
}
@@ -738,12 +738,6 @@ impl<C, St> GatewayClient<C, St> {
Ok(())
}
pub async fn disconnect(&mut self) -> Result<(), GatewayClientError> {
self.recover_socket_connection().await?;
self.connection = SocketState::NotConnected;
Ok(())
}
pub async fn authenticate_and_start(&mut self) -> Result<Arc<SharedKeys>, GatewayClientError>
where
C: DkgQueryClient + Send + Sync,
@@ -48,21 +48,17 @@ impl PacketRouter {
// 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 outfox_ack_overhead =
PacketSize::OutfoxAckPacket.size() + MAX_NODE_ADDRESS_UNPADDED_LEN;
for received_packet in unwrapped_packets {
if received_packet.len() == PacketSize::AckPacket.plaintext_size()
// we don't know the real size of the payload, it could be anything <= 48 bytes
|| received_packet.len() <= PacketSize::OutfoxAckPacket.plaintext_size()
|| received_packet.len() == PacketSize::OutfoxAckPacket.plaintext_size()
{
received_acks.push(received_packet);
} else if received_packet.len()
== PacketSize::RegularPacket.plaintext_size() - ack_overhead
|| received_packet.len()
== PacketSize::OutfoxRegularPacket.plaintext_size() - outfox_ack_overhead
|| received_packet.len()
== PacketSize::OutfoxRegularPacket.size() - outfox_ack_overhead
== PacketSize::OutfoxRegularPacket.plaintext_size() - ack_overhead
|| received_packet.len() == PacketSize::OutfoxRegularPacket.size() - 6
{
trace!("routing regular packet");
received_messages.push(received_packet);
-3
View File
@@ -41,6 +41,3 @@ nym-multisig-contract-common = { path = "../cosmwasm-smart-contracts/multisig-co
nym-service-provider-directory-common = { path = "../cosmwasm-smart-contracts/service-provider-directory" }
nym-name-service-common = { path = "../cosmwasm-smart-contracts/name-service" }
nym-sphinx = { path = "../../common/nymsphinx" }
nym-pemstore = { path = "../../common/pemstore", version = "0.3.0" }
nym-types = { path = "../../common/types" }
@@ -1,68 +0,0 @@
use clap::{Args, Parser, Subcommand};
use nym_bin_common::output_format::OutputFormat;
use nym_crypto::asymmetric::identity;
use nym_types::helpers::ConsoleSigningOutput;
use nym_validator_client::nyxd::error::NyxdError;
use std::path::PathBuf;
#[derive(Debug, Args)]
#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)]
pub struct MixnetOperatorsIdentityKey {
#[clap(subcommand)]
pub command: MixnetOperatorsIdentityKeyCommands,
}
#[derive(Debug, Subcommand)]
pub enum MixnetOperatorsIdentityKeyCommands {
/// Register a name alias for a nym address
Sign(SignArgs),
}
#[derive(Debug, Parser)]
pub struct SignArgs {
/// Path to private identity key (example: private_identity_key.pem)
#[clap(long)]
private_key: PathBuf,
/// Base58 encoded message to sign
#[clap(long)]
base58_msg: String,
#[clap(short, long, default_value_t = OutputFormat::default())]
output: OutputFormat,
}
pub async fn sign(args: SignArgs) -> Result<(), NyxdError> {
eprintln!(">>> loading: {}", args.private_key.display());
let private_identity_key: identity::PrivateKey =
nym_pemstore::load_key(args.private_key).expect("failed to load key");
print_signed_msg(&private_identity_key, &args.base58_msg, args.output);
Ok(())
}
fn print_signed_msg(private_key: &identity::PrivateKey, raw_msg: &str, output: OutputFormat) {
let trimmed = raw_msg.trim();
eprintln!(">>> attempting to sign: {trimmed}");
let Ok(decoded) = bs58::decode(trimmed).into_vec() else {
println!("failed to base58 decode the message, did you copy it correctly?");
return;
};
eprintln!(">>> decoding the message...");
// we don't really care about what particular information is embedded inside of it,
// we just want to know if user correctly copied the string, i.e. whether it's a valid bs58 encoded json
if serde_json::from_slice::<serde_json::Value>(&decoded).is_err() {
println!("failed to parse the message after decoding, did you copy it correctly?");
return;
};
// if this is a valid json, it MUST be a valid string
let decoded_string = String::from_utf8(decoded.clone()).unwrap();
let signature = private_key.sign(&decoded).to_base58_string();
let sign_output = ConsoleSigningOutput::new(decoded_string, signature);
println!("{}", output.format(&sign_output));
}
@@ -4,7 +4,6 @@
use clap::{Args, Subcommand};
pub mod gateway;
pub mod identity_key;
pub mod mixnode;
pub mod name;
pub mod service;
@@ -27,6 +26,4 @@ pub enum MixnetOperatorsCommands {
ServiceProvider(service::MixnetOperatorsService),
/// Manage your registered name
Name(name::MixnetOperatorsName),
/// Sign messages using your private identity key
IdentityKey(identity_key::MixnetOperatorsIdentityKey),
}
@@ -3,7 +3,7 @@
use nym_sphinx_acknowledgements::surb_ack::SurbAckRecoveryError;
use nym_sphinx_addressing::nodes::NymNodeRoutingAddressError;
use nym_sphinx_types::{NymPacketError, OutfoxError, SphinxError};
use nym_sphinx_types::{NymPacketError, SphinxError};
use thiserror::Error;
#[derive(Error, Debug)]
@@ -25,7 +25,4 @@ pub enum MixProcessingError {
#[error("the received packet was set to use the very old and very much deprecated 'VPN' mode")]
ReceivedOldTypeVpnPacket,
#[error("failed to process received outfox packet: {0}")]
OutfoxProcessingError(#[from] OutfoxError),
}
@@ -20,14 +20,12 @@ use tracing::instrument;
type ForwardAck = MixPacket;
#[derive(Debug)]
pub struct ProcessedFinalHop {
pub destination: DestinationAddressBytes,
pub forward_ack: Option<ForwardAck>,
pub message: Vec<u8>,
}
#[derive(Debug)]
pub enum MixProcessingResult {
/// Contains unwrapped data that should first get delayed before being sent to next hop.
ForwardHop(MixPacket, Option<SphinxDelay>),
@@ -143,7 +141,7 @@ impl SphinxPacketProcessor {
match SurbAck::try_recover_first_hop_packet(&ack_data, packet_type) {
Ok((first_hop, packet)) => (first_hop, packet),
Err(err) => {
info!("Failed to recover first hop from ack data: {err}");
debug!("Failed to recover first hop from ack data: {err}");
return Err(err.into());
}
};
@@ -207,7 +205,7 @@ impl SphinxPacketProcessor {
if packet.is_final_hop() {
self.process_final_hop(
DestinationAddressBytes::from_bytes(next_address),
packet.recover_plaintext()?.to_vec(),
packet.recover_plaintext().to_vec(),
packet_size,
packet_type,
)
@@ -241,14 +239,7 @@ impl SphinxPacketProcessor {
// for forward packets, extract next hop and set delay (but do NOT delay here)
// for final packets, extract SURBAck
let final_processing_result =
self.perform_final_processing(processed_packet, packet_size, packet_type);
if final_processing_result.is_err() {
error!("{:?}", final_processing_result)
}
final_processing_result
self.perform_final_processing(processed_packet, packet_size, packet_type)
})
}
}
+2 -3
View File
@@ -15,12 +15,11 @@ thiserror = { workspace = true }
zeroize = { workspace = true }
nym-crypto = { path = "../../crypto", features = ["symmetric", "rand"] }
nym-pemstore = { path = "../../pemstore" }
nym-sphinx-addressing = { path = "../addressing" }
nym-sphinx-params = { path = "../params" }
nym-sphinx-routing = { path = "../routing" }
nym-sphinx-types = { path = "../types" }
nym-pemstore = { path = "../../pemstore" }
nym-topology = { path = "../../topology" }
[features]
serde = ["serde_crate", "generic-array"]
serde = ["serde_crate", "generic-array"]
@@ -9,7 +9,7 @@ use nym_sphinx_addressing::nodes::{
};
use nym_sphinx_params::packet_sizes::PacketSize;
use nym_sphinx_params::{PacketType, DEFAULT_NUM_MIX_HOPS};
use nym_sphinx_types::delays::Delay;
use nym_sphinx_types::delays::{self, Delay};
use nym_sphinx_types::{NymPacket, NymPacketError, MIN_PACKET_SIZE};
use nym_topology::{NymTopology, NymTopologyError};
use rand::{CryptoRng, RngCore};
@@ -51,7 +51,7 @@ impl SurbAck {
{
let route =
topology.random_route_to_gateway(rng, DEFAULT_NUM_MIX_HOPS, recipient.gateway())?;
let delays = nym_sphinx_routing::generate_hop_delays(average_delay, route.len());
let delays = delays::generate_from_average_duration(route.len(), average_delay);
let destination = recipient.as_sphinx_destination();
let surb_ack_payload = prepare_identifier(rng, ack_key, marshaled_fragment_id);
@@ -16,7 +16,6 @@ thiserror = "1"
nym-crypto = { path = "../../crypto", features = ["symmetric", "rand"] }
nym-sphinx-addressing = { path = "../addressing" }
nym-sphinx-params = { path = "../params" }
nym-sphinx-routing = { path = "../routing" }
nym-sphinx-types = { path = "../types" }
nym-topology = { path = "../../topology" }
@@ -7,7 +7,7 @@ use nym_sphinx_addressing::clients::Recipient;
use nym_sphinx_addressing::nodes::{NymNodeRoutingAddress, MAX_NODE_ADDRESS_UNPADDED_LEN};
use nym_sphinx_params::packet_sizes::PacketSize;
use nym_sphinx_params::{PacketType, ReplySurbKeyDigestAlgorithm, DEFAULT_NUM_MIX_HOPS};
use nym_sphinx_types::{NymPacket, SURBMaterial, SphinxError, SURB};
use nym_sphinx_types::{delays, NymPacket, SURBMaterial, SphinxError, SURB};
use nym_topology::{NymTopology, NymTopologyError};
use rand::{CryptoRng, RngCore};
use serde::de::{Error as SerdeError, Visitor};
@@ -96,7 +96,7 @@ impl ReplySurb {
{
let route =
topology.random_route_to_gateway(rng, DEFAULT_NUM_MIX_HOPS, recipient.gateway())?;
let delays = nym_sphinx_routing::generate_hop_delays(average_delay, route.len());
let delays = delays::generate_from_average_duration(route.len(), average_delay);
let destination = recipient.as_sphinx_destination();
let surb_material = SURBMaterial::new(route, delays, destination);
+1 -2
View File
@@ -15,8 +15,7 @@ nym-crypto = { path = "../../crypto" }
nym-sphinx-acknowledgements = { path = "../acknowledgements" }
nym-sphinx-addressing = { path = "../addressing" }
nym-sphinx-chunking = { path = "../chunking" }
nym-sphinx-forwarding = { path = "../forwarding" }
nym-sphinx-params = { path = "../params" }
nym-sphinx-routing = { path = "../routing" }
nym-sphinx-forwarding = { path = "../forwarding" }
nym-sphinx-types = { path = "../types" }
nym-topology = { path = "../../topology" }
+12 -29
View File
@@ -13,7 +13,7 @@ use nym_sphinx_params::packet_sizes::PacketSize;
use nym_sphinx_params::{
PacketEncryptionAlgorithm, PacketHkdfAlgorithm, PacketType, DEFAULT_NUM_MIX_HOPS,
};
use nym_sphinx_types::NymPacket;
use nym_sphinx_types::{delays, NymPacket};
use nym_topology::{NymTopology, NymTopologyError};
use rand::{CryptoRng, RngCore};
use std::convert::TryFrom;
@@ -91,7 +91,6 @@ where
>(rng, full_address.encryption_key());
let public_key_bytes = ephemeral_keypair.public_key().to_bytes();
let cover_size = packet_size.plaintext_size() - public_key_bytes.len() - ack_bytes.len();
let mut cover_content: Vec<_> = LOOP_COVER_MESSAGE_PAYLOAD
@@ -120,38 +119,22 @@ where
let route =
topology.random_route_to_gateway(rng, DEFAULT_NUM_MIX_HOPS, full_address.gateway())?;
let delays = nym_sphinx_routing::generate_hop_delays(average_packet_delay, route.len());
let delays = delays::generate_from_average_duration(route.len(), average_packet_delay);
let destination = full_address.as_sphinx_destination();
// once merged, that's an easy rng injection point for sphinx packets : )
let packet = NymPacket::sphinx_build(
packet_size.payload_size(),
packet_payload,
&route,
&destination,
&delays,
)?;
let first_hop_address =
NymNodeRoutingAddress::try_from(route.first().unwrap().address).unwrap();
// once merged, that's an easy rng injection point for sphinx packets : )
let packet = match packet_type {
PacketType::Mix => NymPacket::sphinx_build(
packet_size.payload_size(),
packet_payload,
&route,
&destination,
&delays,
)?,
#[allow(deprecated)]
PacketType::Vpn => NymPacket::sphinx_build(
packet_size.payload_size(),
packet_payload,
&route,
&destination,
&delays,
)?,
PacketType::Outfox => NymPacket::outfox_build(
packet_payload,
&route,
&destination,
Some(packet_size.plaintext_size()),
)?,
};
Ok(MixPacket::new(first_hop_address, packet, packet_type))
Ok(MixPacket::new(first_hop_address, packet, PacketType::Mix))
}
/// Helper function used to determine if given message represents a loop cover message.
+1 -11
View File
@@ -1,10 +1,8 @@
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use std::time::Duration;
use nym_sphinx_addressing::clients::Recipient;
use nym_sphinx_types::{delays, Delay, Node};
use nym_sphinx_types::Node;
use thiserror::Error;
pub trait SphinxRouteMaker {
@@ -43,11 +41,3 @@ impl SphinxRouteMaker for Vec<Node> {
}
}
}
pub fn generate_hop_delays(average_packet_delay: Duration, num_hops: usize) -> Vec<Delay> {
if average_packet_delay.is_zero() {
vec![nym_sphinx_types::Delay::new_from_millis(0); num_hops]
} else {
delays::generate_from_average_duration(num_hops, average_packet_delay)
}
}
+2 -2
View File
@@ -14,7 +14,7 @@ use nym_sphinx_chunking::fragment::{Fragment, FragmentIdentifier};
use nym_sphinx_forwarding::packet::MixPacket;
use nym_sphinx_params::packet_sizes::PacketSize;
use nym_sphinx_params::{PacketType, ReplySurbKeyDigestAlgorithm, DEFAULT_NUM_MIX_HOPS};
use nym_sphinx_types::{Delay, NymPacket};
use nym_sphinx_types::{delays, Delay, NymPacket};
use nym_topology::{NymTopology, NymTopologyError};
use rand::{CryptoRng, Rng};
use std::convert::TryFrom;
@@ -233,7 +233,7 @@ pub trait FragmentPreparer {
// including set of delays
let delays =
nym_sphinx_routing::generate_hop_delays(self.average_packet_delay(), route.len());
delays::generate_from_average_duration(route.len(), self.average_packet_delay());
// create the actual sphinx packet here. With valid route and correct payload size,
// there's absolutely no reason for this call to fail.
+4 -13
View File
@@ -177,29 +177,20 @@ impl TaskManager {
drop(notify_rx);
}
#[cfg(not(target_arch = "wasm32"))]
let interrupt_future = tokio::signal::ctrl_c();
// in wasm we'll never get our shutdown anyway...
#[cfg(target_arch = "wasm32")]
let interrupt_future = futures::future::pending::<()>();
futures::future::pending::<()>().await;
#[cfg(not(target_arch = "wasm32"))]
let wait_future = tokio::time::sleep(Duration::from_secs(self.shutdown_timer_secs));
// TODO: we should be using a `Delay` here for wasm
#[cfg(target_arch = "wasm32")]
let wait_future = futures::future::pending::<()>();
tokio::select! {
_ = self.notify_tx.closed() => {
log::info!("All registered tasks succesfully shutdown");
},
_ = interrupt_future => {
_ = tokio::signal::ctrl_c() => {
log::info!("Forcing shutdown");
}
_ = wait_future => {
log::info!("Timeout reached, forcing shutdown");
_ = tokio::time::sleep(Duration::from_secs(self.shutdown_timer_secs)) => {
log::info!("Timout reached, forcing shutdown");
},
}
}
+2 -17
View File
@@ -3220,7 +3220,7 @@ dependencies = [
[[package]]
name = "nym-bin-common"
version = "0.6.0"
version = "0.5.0"
dependencies = [
"atty",
"clap",
@@ -3235,7 +3235,7 @@ dependencies = [
[[package]]
name = "nym-client-core"
version = "1.1.15"
version = "1.1.14"
dependencies = [
"async-trait",
"base64 0.21.2",
@@ -3365,7 +3365,6 @@ dependencies = [
"nym-credential-storage",
"nym-crypto",
"nym-socks5-client-core",
"nym-sphinx",
"nym-task",
"pretty_env_logger",
"rand 0.8.5",
@@ -3736,7 +3735,6 @@ dependencies = [
"nym-pemstore",
"nym-sphinx-addressing",
"nym-sphinx-params",
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.7.3",
@@ -3762,7 +3760,6 @@ dependencies = [
"nym-crypto",
"nym-sphinx-addressing",
"nym-sphinx-params",
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.7.3",
@@ -3793,7 +3790,6 @@ dependencies = [
"nym-sphinx-chunking",
"nym-sphinx-forwarding",
"nym-sphinx-params",
"nym-sphinx-routing",
"nym-sphinx-types",
"nym-topology",
"rand 0.7.3",
@@ -3910,7 +3906,6 @@ dependencies = [
"nym-service-provider-directory-common",
"nym-vesting-contract",
"nym-vesting-contract-common",
"openssl",
"prost",
"reqwest",
"serde",
@@ -4050,15 +4045,6 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-src"
version = "111.26.0+1.1.1u"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efc62c9f12b22b8f5208c23a7200a442b2e5999f8bdf80233852122b5a4f6f37"
dependencies = [
"cc",
]
[[package]]
name = "openssl-sys"
version = "0.9.82"
@@ -4068,7 +4054,6 @@ dependencies = [
"autocfg",
"cc",
"libc",
"openssl-src",
"pkg-config",
"vcpkg",
]
-1
View File
@@ -53,7 +53,6 @@ nym-crypto = { path = "../../../common/crypto" }
nym-credential-storage = { path = "../../../common/credential-storage" }
nym-bin-common = { path = "../../../common/bin-common"}
nym-socks5-client-core = { path = "../../../common/socks5-client-core" }
nym-sphinx = { path = "../../../common/nymsphinx" }
nym-task = { path = "../../../common/task" }
[dev-dependencies]
@@ -160,11 +160,7 @@ pub async fn init_socks5_config(provider_address: String, chosen_gateway_id: Str
config.core.base.client.nym_api_urls = nym_config_common::parse_urls(&raw_validators);
}
let gateway_setup = if register_gateway {
GatewaySetup::new_fresh(Some(chosen_gateway_id), None)
} else {
GatewaySetup::MustLoad
};
let gateway_setup = GatewaySetup::new_fresh(Some(chosen_gateway_id), None);
// Setup gateway by either registering a new one, or reusing exiting keys
let key_store = OnDiskKeys::new(config.storage_paths.common_paths.keys.clone());
@@ -25,11 +25,6 @@ mod tasks;
mod window;
fn main() {
if std::env::var("NYM_CONNECT_ENABLE_MEDIUM").is_ok() {
std::env::set_var("NYM_CONNECT_DISABLE_COVER", "1");
std::env::set_var("NYM_CONNECT_ENABLE_MIXED_SIZE_PACKETS", "1");
std::env::set_var("NYM_CONNECT_DISABLE_PER_HOP_DELAYS", "1");
}
setup_env(None);
println!("Starting up...");
+1 -18
View File
@@ -4,10 +4,8 @@ use nym_client_core::client::base_client::storage::{MixnetClientStorage, OnDiskP
use nym_client_core::{config::GatewayEndpointConfig, error::ClientCoreStatusMessage};
use nym_socks5_client_core::NymClient as Socks5NymClient;
use nym_socks5_client_core::Socks5ControlMessageSender;
use nym_sphinx::params::PacketSize;
use nym_task::manager::TaskStatus;
use std::sync::Arc;
use std::time::Duration;
use tap::TapFallible;
use tokio::sync::RwLock;
@@ -41,7 +39,7 @@ pub async fn start_nym_socks5_client(
GatewayEndpointConfig,
)> {
log::info!("Loading config from file: {id}");
let mut config = Config::read_from_default_path(id)
let config = Config::read_from_default_path(id)
.tap_err(|_| log::warn!("Failed to load configuration file"))?;
let storage =
@@ -55,21 +53,6 @@ pub async fn start_nym_socks5_client(
.expect("failed to load gateway details")
.into();
// Disable both the loop cover traffic that runs in the background as well as the Poisson
// process that injects cover traffic into the traffic stream.
if std::env::var("NYM_CONNECT_DISABLE_COVER").is_ok() {
config.core.base.set_no_cover_traffic();
}
if std::env::var("NYM_CONNECT_ENABLE_MIXED_SIZE_PACKETS").is_ok() {
config.core.base.debug.traffic.secondary_packet_size = Some(PacketSize::ExtendedPacket16);
}
if std::env::var("NYM_CONNECT_DISABLE_PER_HOP_DELAY").is_ok() {
config.core.base.debug.traffic.average_packet_delay = Duration::ZERO;
config.core.base.debug.acknowledgements.average_ack_delay = Duration::ZERO;
}
log::info!("Starting socks5 client");
// Channel to send control messages to the socks5 client
+1 -4
View File
@@ -2,7 +2,6 @@ plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'org.jetbrains.kotlin.plugin.serialization' version '1.8.21'
id "io.sentry.android.gradle" version "3.11.0"
}
android {
@@ -102,20 +101,18 @@ dependencies {
implementation 'androidx.core:core-ktx:1.10.1'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.1'
implementation 'androidx.activity:activity-compose:1.7.2'
implementation 'androidx.activity:activity-compose:1.5.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0'
implementation platform('androidx.compose:compose-bom:2022.10.00')
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1'
implementation 'androidx.navigation:navigation-compose:2.6.0'
implementation 'androidx.compose.runtime:runtime-livedata'
implementation 'androidx.compose.ui:ui'
implementation 'androidx.compose.ui:ui-graphics'
implementation 'androidx.compose.ui:ui-tooling-preview'
implementation 'androidx.compose.material3:material3'
implementation 'androidx.work:work-runtime-ktx:2.8.1'
implementation 'androidx.datastore:datastore-preferences:1.0.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
@@ -17,7 +17,6 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Nyms5"
android:enableOnBackInvokedCallback="true"
tools:targetApi="31">
<activity
android:name=".MainActivity"
@@ -35,20 +34,6 @@
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
tools:node="remove" />
<!-- Sentry -->
<meta-data
android:name="io.sentry.auto-init"
android:value="false" />
<!-- enable screenshot for crashes -->
<meta-data
android:name="io.sentry.attach-screenshot"
android:value="true" />
<!-- enable view hierarchy for crashes -->
<meta-data
android:name="io.sentry.attach-view-hierarchy"
android:value="true" />
</application>
</manifest>
@@ -1,21 +1,9 @@
package net.nymtech.nyms5
import android.app.Application
import android.content.Context
import android.util.Log
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import androidx.work.Configuration
import androidx.work.DelegatingWorkerFactory
import io.sentry.android.core.SentryAndroid
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.runBlocking
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
val monitoringKey = booleanPreferencesKey("monitoring")
class App : Application(), Configuration.Provider {
companion object {
@@ -25,30 +13,6 @@ class App : Application(), Configuration.Provider {
private val tag = "App"
override fun onCreate() {
super.onCreate()
val app = this
runBlocking {
val monitoring = applicationContext.dataStore.data.map { preferences ->
preferences[monitoringKey] ?: false
}.first()
if (monitoring) {
Log.i(tag, "Performance monitoring and error reporting enabled")
SentryAndroid.init(app) { options ->
options.dsn =
"https://6872f5818bc147ef9c0fce114fcaac8a@o967446.ingest.sentry.io/4505306218102784"
options.enableAllAutoBreadcrumbs(true)
// TODO should be adjusted in production env
options.tracesSampleRate = 1.0
options.profilesSampleRate = 1.0
}
}
}
}
override fun getWorkManagerConfiguration(): Configuration {
val workerFactory = DelegatingWorkerFactory()
// pass in the NymProxy class instance
@@ -14,21 +14,11 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
@@ -44,8 +34,6 @@ import androidx.lifecycle.repeatOnLifecycle
import kotlinx.coroutines.launch
import net.nymtech.nyms5.ui.theme.NymTheme
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.graphics.Color
@@ -54,17 +42,8 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.font.FontStyle
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.work.WorkInfo
import androidx.work.WorkManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.map
class MainActivity : ComponentActivity() {
private val tag = "MainActivity"
@@ -102,16 +81,18 @@ class MainActivity : ComponentActivity() {
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
Log.d(tag, "____UI recompose")
applicationContext.dataStore.data.map { preferences ->
preferences[monitoringKey] ?: false
}.collect { monitoring ->
viewModel.uiState.collect {
setContent {
NymTheme {
Log.d(tag, "____uiState collect")
viewModel.uiState.collect {
setContent {
NymTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
val loading = it.loading
HomeScreen(it, monitoring, applicationContext.dataStore) {
S5ClientSwitch(it.connected, loading, {
if (!loading) {
when {
it -> {
@@ -125,7 +106,7 @@ class MainActivity : ComponentActivity() {
}
}
}
}
})
}
}
}
@@ -133,90 +114,6 @@ class MainActivity : ComponentActivity() {
}
}
}
override fun onStart() {
super.onStart()
viewModel.checkStateSync()
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun HomeScreen(
proxyState: MainViewModel.ProxyState,
monitoring: Boolean,
dataStore: DataStore<Preferences>,
onSwitch: (value: Boolean) -> Unit,
) {
val navController = rememberNavController()
var expanded by remember { mutableStateOf(false) }
val scope = rememberCoroutineScope()
Scaffold(topBar = {
CenterAlignedTopAppBar(
title = {
Text(stringResource(R.string.app_name))
},
navigationIcon = {
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route
if (currentRoute === "proxy") {
IconButton(onClick = { expanded = true }) {
Icon(
imageVector = Icons.Filled.Menu,
contentDescription = "Main menu"
)
}
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
DropdownMenuItem(onClick = {
navController.navigate("monitoring") {
popUpTo("proxy")
}
expanded = false
}, text = {
Text("Error reporting")
})
}
} else {
IconButton(onClick = {
navController.navigate("proxy") {
popUpTo("proxy")
}
}) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = "Back home"
)
}
}
},
)
}) { contentPadding ->
NavHost(
navController = navController,
startDestination = "proxy",
modifier = Modifier.padding(contentPadding)
) {
composable("proxy") {
S5ClientSwitch(
connected = proxyState.connected,
loading = proxyState.loading,
onSwitch = onSwitch
)
}
composable("monitoring") {
Monitoring(initialValue = monitoring) {
scope.launch(Dispatchers.IO) {
dataStore.edit { settings -> settings[monitoringKey] = it }
}
}
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@@ -301,46 +198,6 @@ fun S5ClientSwitch(
}
}
@Composable
fun Monitoring(
modifier: Modifier = Modifier,
initialValue: Boolean,
onSwitch: (value: Boolean) -> Unit,
) {
var monitoring by remember { mutableStateOf(initialValue) }
Column(
modifier = modifier
.padding(16.dp)
.verticalScroll(rememberScrollState())
) {
Row(
verticalAlignment = Alignment.CenterVertically
) {
Text("Enable error reporting")
Spacer(modifier = modifier.width(16.dp))
Switch(checked = monitoring, onCheckedChange = {
monitoring = it
onSwitch(it)
})
}
Spacer(modifier = modifier.height(18.dp))
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(
painter = painterResource(R.drawable.warning_24),
contentDescription = "copy to clipboard",
tint = Color.Yellow
)
Spacer(modifier = modifier.width(16.dp))
Text(stringResource(R.string.monitoring_desc_3), color = Color.Yellow)
}
Spacer(modifier = modifier.height(18.dp))
Text(stringResource(R.string.monitoring_desc_1))
Spacer(modifier = modifier.height(18.dp))
Text(stringResource(R.string.monitoring_desc_2))
}
}
@Preview
@Composable
fun PreviewSocks5Client() {
@@ -363,18 +220,3 @@ fun PreviewSocks5Client() {
}
}
}
@Preview
@Composable
fun PreviewMonitoring() {
NymTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Monitoring(initialValue = false) {
Log.d("Monitoring", "switch $it")
}
}
}
}
@@ -27,7 +27,7 @@ class MainViewModel(
private val workManager: WorkManager,
private val nymProxy: NymProxy
) : ViewModel() {
private val tag = "MainViewModel"
private val tag = "viewModel"
private val workRequest: OneTimeWorkRequest =
OneTimeWorkRequestBuilder<ProxyWorker>()
@@ -56,7 +56,8 @@ class MainViewModel(
// this viewModel instance is cleared
// use GlobalScope instead
GlobalScope.launch(Dispatchers.IO) {
// if the proxy process is still running ie. connected kill it
// if the proxy process is still running ie. connected
// kill it
if (nymProxy.getState() == NymProxy.Companion.State.CONNECTED) {
Log.d(tag, "stopping proxy")
nymProxy.stop()
@@ -130,29 +131,6 @@ class MainViewModel(
setDisconnected()
}
}
fun checkStateSync() {
Log.d(tag, "check state sync")
viewModelScope.launch(Dispatchers.IO) {
val proxyState = nymProxy.getState()
val workInfo = workManager.getWorkInfoById(ProxyWorker.workId).get()
Log.d(tag, "proxy state $proxyState, work state ${workInfo?.state}")
if (proxyState == NymProxy.Companion.State.CONNECTED &&
workInfo?.state != WorkInfo.State.RUNNING
) {
Log.w(tag, "⚠ state desync")
Log.i(tag, "stopping proxy")
cancelProxyWork()
}
if (proxyState == NymProxy.Companion.State.DISCONNECTED &&
workInfo?.state == WorkInfo.State.RUNNING
) {
Log.w(tag, "⚠ state desync")
Log.i(tag, "stopping worker")
workManager.cancelAllWorkByTag(ProxyWorker.workTag)
}
}
}
}
class MainViewModelFactory(
@@ -1,5 +0,0 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M1,21h22L12,2 1,21zM13,18h-2v-2h2v2zM13,14h-2v-4h2v4z"/>
</vector>
@@ -11,8 +11,4 @@
<string name="sp_url">https://harbourmaster.nymtech.net/v1/services?size=100</string>
<string name="default_sp">DpB3cHAchJiNBQi5FrZx2csXb1mrHkpYh9Wzf8Rjsuko.ANNWrvHqMYuertHGHUrZdBntQhpzfbWekB39qez9U2Vx@2BuMSfMW3zpeAjKXyKLhmY4QW1DXurrtSPEJ6CjX3SEh</string>
<string name="connected_text">Connected to the mixnet</string>
<string name="monitoring_desc_1">Help Nym developers to fix errors, crashes and improve the application by enabling this option. If errors occur or if the app crashes, it will automatically send a report. Also it tracks various performance metrics. We use sentry.io service to handle this.</string>
<string name="monitoring_desc_2">Note: A report can include your external IP, this can be useful to catch issues related to IP location.
All recorded data is used by Nym developers and for app development purposes only.</string>
<string name="monitoring_desc_3">You must restart the application for the change to take effect.</string>
</resources>
@@ -1,3 +0,0 @@
defaults.project=nym-connect-android
defaults.org=nymtech
# auth.token=xxx
+1 -3
View File
@@ -9,11 +9,9 @@ pub const DEFAULT_HOPS: usize = 4;
pub const ROUTING_INFORMATION_LENGTH_BY_STAGE: [u8; DEFAULT_HOPS] =
[DEFAULT_ROUTING_INFO_SIZE; DEFAULT_HOPS];
pub const MIN_PACKET_SIZE: usize = 48;
pub const MAGIC_SLICE: &[u8] = &[111, 102, 120];
pub const OUTFOX_PACKET_OVERHEAD: usize = MIX_PARAMS_LEN
+ (groupelementbytes() + tagbytes() + DEFAULT_ROUTING_INFO_SIZE as usize) * DEFAULT_HOPS
+ MAGIC_SLICE.len();
+ (groupelementbytes() + tagbytes() + DEFAULT_ROUTING_INFO_SIZE as usize) * DEFAULT_HOPS;
pub const fn groupelementbytes() -> usize {
GROUPELEMENTBYTES as usize
-3
View File
@@ -1,4 +1,3 @@
use crate::constants::MAGIC_SLICE;
use crate::constants::MIN_MESSAGE_LEN;
use crate::constants::MIX_PARAMS_LEN;
use chacha20::cipher::InvalidLength;
@@ -26,6 +25,4 @@ pub enum OutfoxError {
},
#[error("Header length must be {MIX_PARAMS_LEN}, got {0}")]
InvalidHeaderLength(usize),
#[error("Invalid magic bytes, expected: {:?}, got: {:?}", MAGIC_SLICE, 0)]
InvalidMagicBytes(Vec<u8>),
}
+11 -15
View File
@@ -7,7 +7,7 @@ use std::{
};
use crate::{
constants::{DEFAULT_HOPS, MAGIC_SLICE, MIN_PACKET_SIZE, MIX_PARAMS_LEN},
constants::{DEFAULT_HOPS, MIN_PACKET_SIZE, MIX_PARAMS_LEN},
error::OutfoxError,
format::{MixCreationParameters, MixStageParameters},
};
@@ -60,19 +60,16 @@ impl TryFrom<&[u8]> for OutfoxPacket {
}
impl OutfoxPacket {
pub fn recover_plaintext(&self) -> Result<Vec<u8>, OutfoxError> {
pub fn recover_plaintext(&self) -> Vec<u8> {
let plaintext = self.payload()[self.payload_range()].to_vec();
let mut plaintext = VecDeque::from_iter(plaintext);
while let Some(0) = plaintext.front() {
plaintext.pop_front();
}
let mut plaintext = plaintext.make_contiguous().to_vec();
let payload = plaintext.split_off(MAGIC_SLICE.len());
if plaintext != MAGIC_SLICE {
Err(OutfoxError::InvalidMagicBytes(plaintext))
} else {
Ok(payload)
if plaintext.starts_with(&[0]) {
let mut plaintext = VecDeque::from_iter(plaintext);
while let Some(0) = plaintext.front() {
plaintext.pop_front();
}
return plaintext.make_contiguous().to_vec();
}
plaintext
}
pub fn len(&self) -> usize {
@@ -103,12 +100,11 @@ impl OutfoxPacket {
MIN_PACKET_SIZE
} else {
packet_size
} + MAGIC_SLICE.len();
};
let mix_params = MixCreationParameters::new(packet_size as u16);
let padding = mix_params.total_packet_length() - payload.as_ref().len() - MAGIC_SLICE.len();
let padding = mix_params.total_packet_length() - payload.as_ref().len();
let mut buffer = vec![0; padding];
buffer.extend_from_slice(MAGIC_SLICE);
buffer.extend_from_slice(payload.as_ref());
// Last node in the route is a gateway, it will decrypt last, and get the final destination address
+3 -59
View File
@@ -88,7 +88,7 @@ mod tests {
}
#[test]
fn test_packet_params_short() {
fn test_packet_params() {
let (node1_pk, node1_pub) = sphinx_packet::crypto::keygen();
let node1 = Node::new(
NodeAddressBytes::from_bytes([0u8; NODE_ADDRESS_LENGTH]),
@@ -118,7 +118,7 @@ mod tests {
let route = [node1, node2.clone(), node3.clone(), gateway.clone()];
let payload = vec![0, 0, 1, 1, 1, 0, 0];
let payload = randombytes(21);
let packet =
OutfoxPacket::build(&payload, &route, &destination, Some(payload.len())).unwrap();
@@ -140,62 +140,6 @@ mod tests {
let destination_address = packet.decode_next_layer(&gateway_pk).unwrap();
assert_eq!(destination_address, destination.address.as_bytes());
assert_eq!(payload, packet.recover_plaintext().unwrap());
}
#[test]
fn test_packet_params_long() {
let (node1_pk, node1_pub) = sphinx_packet::crypto::keygen();
let node1 = Node::new(
NodeAddressBytes::from_bytes([0u8; NODE_ADDRESS_LENGTH]),
node1_pub,
);
let (node2_pk, node2_pub) = sphinx_packet::crypto::keygen();
let node2 = Node::new(
NodeAddressBytes::from_bytes([1u8; NODE_ADDRESS_LENGTH]),
node2_pub,
);
let (node3_pk, node3_pub) = sphinx_packet::crypto::keygen();
let node3 = Node::new(
NodeAddressBytes::from_bytes([2u8; NODE_ADDRESS_LENGTH]),
node3_pub,
);
let (gateway_pk, gateway_pub) = sphinx_packet::crypto::keygen();
let gateway = Node::new(
NodeAddressBytes::from_bytes([3u8; NODE_ADDRESS_LENGTH]),
gateway_pub,
);
let destination = Destination::new(
DestinationAddressBytes::from_bytes([9u8; NODE_ADDRESS_LENGTH]),
[0u8; 16],
);
let route = [node1, node2.clone(), node3.clone(), gateway.clone()];
let payload = randombytes(2048);
let packet =
OutfoxPacket::build(&payload, &route, &destination, Some(payload.len())).unwrap();
let packet_bytes = packet.to_bytes().unwrap();
println!(
"packet bytes length, {}, declared {}",
packet_bytes.len(),
packet.len()
);
let mut packet = OutfoxPacket::try_from(packet_bytes.as_slice()).unwrap();
let next_address = packet.decode_next_layer(&node1_pk).unwrap();
assert_eq!(next_address, node2.address.as_bytes());
let next_address = packet.decode_next_layer(&node2_pk).unwrap();
assert_eq!(next_address, node3.address.as_bytes());
let next_address = packet.decode_next_layer(&node3_pk).unwrap();
assert_eq!(next_address, gateway.address.as_bytes());
let destination_address = packet.decode_next_layer(&gateway_pk).unwrap();
assert_eq!(destination_address, destination.address.as_bytes());
assert_eq!(payload, packet.recover_plaintext().unwrap());
assert_eq!(payload, packet.recover_plaintext());
}
}
+2 -13
View File
@@ -2915,7 +2915,7 @@ dependencies = [
[[package]]
name = "nym-bin-common"
version = "0.6.0"
version = "0.5.0"
dependencies = [
"atty",
"clap",
@@ -3220,7 +3220,6 @@ dependencies = [
"nym-service-provider-directory-common",
"nym-vesting-contract",
"nym-vesting-contract-common",
"openssl",
"prost",
"reqwest",
"serde",
@@ -3298,7 +3297,7 @@ dependencies = [
[[package]]
name = "nym_wallet"
version = "1.2.5"
version = "1.2.4"
dependencies = [
"async-trait",
"base64 0.13.1",
@@ -3448,15 +3447,6 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-src"
version = "111.26.0+1.1.1u"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efc62c9f12b22b8f5208c23a7200a442b2e5999f8bdf80233852122b5a4f6f37"
dependencies = [
"cc",
]
[[package]]
name = "openssl-sys"
version = "0.9.80"
@@ -3466,7 +3456,6 @@ dependencies = [
"autocfg",
"cc",
"libc",
"openssl-src",
"pkg-config",
"vcpkg",
]
-1
View File
@@ -24,7 +24,6 @@
"prebuild": "yarn build:dependencies",
"build": "yarn build:only-this",
"build:only-this": "scripts/build-prod.sh",
"prebuild:dev": "yarn build:dependencies",
"build:dev": "yarn build:dev:only-this",
"build:dev:only-this": "scripts/build.sh"
},
@@ -1,15 +0,0 @@
use nym_cli_commands::context::ClientArgs;
use nym_network_defaults::NymNetworkDetails;
pub(crate) async fn execute(
_global_args: ClientArgs,
identity_key: nym_cli_commands::validator::mixnet::operators::identity_key::MixnetOperatorsIdentityKey,
_network_details: &NymNetworkDetails,
) -> anyhow::Result<()> {
let res = match identity_key.command {
nym_cli_commands::validator::mixnet::operators::identity_key::MixnetOperatorsIdentityKeyCommands::Sign(sign_args) => {
nym_cli_commands::validator::mixnet::operators::identity_key::sign(sign_args).await
}
};
Ok(res?)
}
@@ -5,7 +5,6 @@ use nym_cli_commands::context::ClientArgs;
use nym_network_defaults::NymNetworkDetails;
pub(crate) mod gateways;
pub(crate) mod identity_key;
pub(crate) mod mixnodes;
pub(crate) mod name;
pub(crate) mod services;
@@ -24,6 +23,5 @@ pub(crate) async fn execute(
) => mixnodes::execute(global_args, mixnode, network_details).await,
nym_cli_commands::validator::mixnet::operators::MixnetOperatorsCommands::ServiceProvider(service) => services::execute(global_args, service, network_details).await,
nym_cli_commands::validator::mixnet::operators::MixnetOperatorsCommands::Name(name) => name::execute(global_args, name, network_details).await,
nym_cli_commands::validator::mixnet::operators::MixnetOperatorsCommands::IdentityKey(identity_key) => identity_key::execute(global_args, identity_key, network_details).await,
}
}