Compare commits

..

11 Commits

Author SHA1 Message Date
Lawrence Stalder 887ae8c789 Added naming and tags 2024-10-18 14:43:46 +02:00
dynco-nym 12759a8460 Remove config in favor of clap args 2024-10-18 14:43:04 +02:00
Fran Arbanas 00b737d362 fix: docker build workflow 2024-10-18 14:14:10 +02:00
Fran Arbanas bd7b5db68f Merge branch 'feat/node-status-api-dockerfile' of github.com:nymtech/nym into feat/node-status-api-dockerfile 2024-10-18 14:08:36 +02:00
Fran Arbanas 80184c3a51 fix: change the way we read env vars for nyxd, nym api and explorer 2024-10-18 14:08:29 +02:00
Lawrence Stalder a13e9d8cc3 Misc changes to pathing and using yq instead of jq 2024-10-18 13:51:02 +02:00
Lawrence Stalder 003a835ee6 Added workflow for pushing node status api on harbor 2024-10-18 13:34:24 +02:00
Fran Arbanas a60f37ae88 feat: add dockerfile and env variables 2024-10-18 12:23:25 +02:00
dynco-nym 8d400ed4e0 Work with directory pre-v2.1
Rebase + point to earlier network client code

Adjust to new Nym API types

Refer to earlier client code

Revert "Rebase + point to earlier network client code"

This reverts commit dd75e7dc0695c25b0883e2f5dd15b7d70165e9e8.

Point to earlier commit
2024-10-16 14:33:23 +02:00
Dinko Zdravac e4ba6c815e Working HTTP server (#4941)
* Server file structure

* Create HTTP server
- graceful shutdown
- routes
- logging, CORS

* gateways WIP

* gateways API + swagger docs complete

* Mixnodes API + swagger docs complete

* Services API + swagger docs complete

* Commit summary insert

* Make troubleshooting DB easier

* Summary API + swagger docs

* Client log changes

* QOL improvements

- remove implicit panics via `as`
- safer DTO conversions
- add logging
- new config
2024-10-14 16:33:21 +02:00
Dinko Zdravac 1ee18d9efe Node Status API background task (#4854)
* Setup new package

* Setup DB

* Fetch & store mixnodes/GWs
- refactor db package structure
- finally solve DATABASE_URL: absolute path works best

* Additional query functionality
- missing only daily summary, which requires type refactoring

* Replace type alias tuples with structs

* Insert summary

* Add github job to build package

* Build script for sqlx

* Remove data dir
- useless now that sqlx DB sits in OUT_DIR

* PR feedback
2024-10-14 16:33:21 +02:00
468 changed files with 9152 additions and 10711 deletions
+2 -2
View File
@@ -4,7 +4,7 @@ on:
pull_request:
paths:
- 'common/**'
- 'nym-credential-proxy/**'
- 'nym-vpn-api/**'
- '.github/workflows/ci-build-vpn-api-wasm.yml'
jobs:
@@ -38,4 +38,4 @@ jobs:
- name: "Build"
run: make
working-directory: nym-credential-proxy/vpn-api-lib-wasm
working-directory: nym-vpn-api/vpn-api-lib-wasm
@@ -1,11 +1,11 @@
name: ci-nym-credential-proxy
name: ci-build-vpn-api
on:
pull_request:
paths:
- 'common/**'
- 'nym-credential-proxy/**'
- '.github/workspace/ci-nym-credential-proxy.yml'
- 'nym-vpn-api/**'
- '.github/workspace/ci-build-vpn-api.yml'
workflow_dispatch:
jobs:
@@ -13,7 +13,7 @@ jobs:
runs-on: arc-ubuntu-22.04
env:
CARGO_TERM_COLOR: always
MANIFEST_PATH: "--manifest-path nym-credential-proxy/Cargo.toml"
MANIFEST_PATH: "--manifest-path nym-vpn-api/Cargo.toml"
steps:
- name: Check out repository code
uses: actions/checkout@v4
@@ -16,7 +16,7 @@ jobs:
strategy:
fail-fast: false
matrix:
platform: [ arc-ubuntu-20.04 ]
platform: arc-ubuntu-20.04
runs-on: ${{ matrix.platform }}
env:
-11
View File
@@ -1,11 +0,0 @@
name: Hello world
on:
workflow_dispatch:
jobs:
my-job:
runs-on: arc-ubuntu-22.04
steps:
- name: my-step
run: echo "Hello World!"
@@ -1,50 +0,0 @@
name: Build and upload Credential Proxy container to harbor.nymte.ch
on:
workflow_dispatch:
env:
WORKING_DIRECTORY: "nym-credential-proxy"
CONTAINER_NAME: "credential-proxy"
jobs:
build-container:
runs-on: arc-ubuntu-22.04-dind
steps:
- name: Login to Harbor
uses: docker/login-action@v3
with:
registry: harbor.nymte.ch
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
password: ${{ secrets.HARBOR_ROBOT_SECRET }}
- name: Checkout repo
uses: actions/checkout@v4
- name: Configure git identity
run: |
git config --global user.email "lawrence@nymtech.net"
git config --global user.name "Lawrence Stalder"
- name: Get version from cargo.toml
uses: mikefarah/yq@v4.44.3
id: get_version
with:
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
- name: Remove existing tag if exists
run: |
if git rev-parse ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} >/dev/null 2>&1; then
echo "Tag ${{ steps.get_version.outputs.result }} already exists, deleting"
git push --delete origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
git tag -d ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
fi
- name: Create tag
run: |
git tag -a ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} -m "Version ${{ steps.get_version.outputs.result }}"
git push origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
- name: BuildAndPushImageOnHarbor
run: |
docker build -f ${{ env.WORKING_DIRECTORY }}/Dockerfile . -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.result }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
+49 -5
View File
@@ -1,11 +1,55 @@
name: Build and upload Node Status API container to harbor.nymte.ch
on:
workflow_dispatch:
env:
WORKING_DIRECTORY: "nym-node-status-api"
CONTAINER_NAME: "node-status-api"
jobs:
my-job:
runs-on: arc-ubuntu-22.04
build-container:
runs-on: arc-ubuntu-22.04-dind
steps:
- name: my-step
run: echo "Hello World!"
- name: Login to Harbor
uses: docker/login-action@v3
with:
registry: harbor.nymte.ch
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
password: ${{ secrets.HARBOR_ROBOT_SECRET }}
- name: Checkout repo
uses: actions/checkout@v4
- name: Configure git identity
run: |
git config --global user.email "lawrence@nymtech.net"
git config --global user.name "Lawrence Stalder"
- name: Get version from cargo.toml
uses: mikefarah/yq@v4.44.3
id: get_version
with:
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml
- name: Check if tag exists
run: |
if git rev-parse ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.value }} >/dev/null 2>&1; then
echo "Tag ${{ steps.get_version.outputs.value }} already exists"
fi
- name: Remove existing tag if exists
run: |
if git rev-parse ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.value }} >/dev/null 2>&1; then
git push --delete origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.value }}
git tag -d ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.value }}
fi
- name: Create tag
run: |
git tag -a ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.value }} -m "Version ${{ steps.get_version.outputs.value }}"
git push origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.value }}
- name: BuildAndPushImageOnHarbor
run: |
docker build -f ${{ env.WORKING_DIRECTORY }}/Dockerfile . -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.value }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
Generated
+1087 -616
View File
File diff suppressed because it is too large Load Diff
+8 -9
View File
@@ -85,7 +85,6 @@ members = [
"common/socks5-client-core",
"common/socks5/proxy-helpers",
"common/socks5/requests",
"common/statistics",
"common/store-cipher",
"common/task",
"common/topology",
@@ -119,6 +118,7 @@ members = [
"nym-node",
"nym-node/nym-node-http-api",
"nym-node/nym-node-requests",
"nym-node-status-api",
"nym-outfox",
"nym-validator-rewarder",
"tools/echo-server",
@@ -153,6 +153,7 @@ default-members = [
"nym-data-observatory",
"nym-node",
"nym-validator-rewarder",
"nym-node-status-api",
"service-providers/authenticator",
"service-providers/ip-packet-router",
"service-providers/network-requester",
@@ -233,10 +234,12 @@ dotenvy = "0.15.6"
ecdsa = "0.16"
ed25519-dalek = "2.1"
etherparse = "0.13.0"
envy = "0.4"
eyre = "0.6.9"
fastrand = "2.1.1"
flate2 = "1.0.34"
futures = "0.3.28"
futures-util = "0.3"
generic-array = "0.14.7"
getrandom = "0.2.10"
getset = "0.1.3"
@@ -266,6 +269,7 @@ ledger-transport-hid = "0.10.0"
log = "0.4"
maxminddb = "0.23.0"
mime = "0.3.17"
moka = { version = "0.12", features = ["future"] }
nix = "0.27.1"
notify = "5.1.0"
okapi = "0.7.0"
@@ -299,13 +303,14 @@ serde = "1.0.210"
serde_bytes = "0.11.15"
serde_derive = "1.0"
serde_json = "1.0.128"
serde_json_path = "0.6.7"
serde_repr = "0.1"
serde_with = "3.9.0"
serde_yaml = "0.9.25"
sha2 = "0.10.8"
si-scale = "0.2.3"
sphinx-packet = "0.1.1"
sqlx = "0.7.4"
sqlx = "0.6.3"
strum = "0.26"
subtle-encoding = "0.5"
syn = "1"
@@ -328,6 +333,7 @@ tracing = "0.1.37"
tracing-opentelemetry = "0.19.0"
tracing-subscriber = "0.3.16"
tracing-tree = "0.2.2"
tracing-log = "0.2"
ts-rs = "10.0.0"
tungstenite = { version = "0.20.1", default-features = false }
url = "2.5"
@@ -350,7 +356,6 @@ prometheus = { version = "0.13.0" }
bls12_381 = { git = "https://github.com/jstuczyn/bls12_381", default-features = false, branch = "temp/experimental-serdect" }
group = { version = "0.13.0", default-features = false }
ff = { version = "0.13.0", default-features = false }
subtle = "2.5.0"
# cosmwasm-related
cosmwasm-schema = "=1.4.3"
@@ -397,12 +402,6 @@ web-sys = "0.3.70"
# Profile settings for individual crates
# Compile-time verified queries do quite a bit of work at compile time. Incremental
# actions like cargo check and cargo build can be significantly faster when
# using an optimized build
[profile.dev.package.sqlx-macros]
opt-level = 3
[profile.release.package.nym-socks5-listener]
strip = true
codegen-units = 1
@@ -19,7 +19,4 @@ pub enum Error {
#[source]
source: hmac::digest::MacError,
},
#[error("conversion: {0}")]
Conversion(String),
}
+2 -3
View File
@@ -3,14 +3,13 @@
pub mod v1;
pub mod v2;
pub mod v3;
mod error;
pub use error::Error;
pub use v3 as latest;
pub use v2 as latest;
pub const CURRENT_VERSION: u8 = 3;
pub const CURRENT_VERSION: u8 = 2;
fn make_bincode_serializer() -> impl bincode::Options {
use bincode::Options;
@@ -1,188 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
use crate::{v2, v3};
impl From<v2::request::AuthenticatorRequest> for v3::request::AuthenticatorRequest {
fn from(authenticator_request: v2::request::AuthenticatorRequest) -> Self {
Self {
protocol: Protocol {
version: 2,
service_provider_type: ServiceProviderType::Authenticator,
},
data: authenticator_request.data.into(),
reply_to: authenticator_request.reply_to,
request_id: authenticator_request.request_id,
}
}
}
impl From<v2::request::AuthenticatorRequestData> for v3::request::AuthenticatorRequestData {
fn from(authenticator_request_data: v2::request::AuthenticatorRequestData) -> Self {
match authenticator_request_data {
v2::request::AuthenticatorRequestData::Initial(init_msg) => {
v3::request::AuthenticatorRequestData::Initial(init_msg.into())
}
v2::request::AuthenticatorRequestData::Final(gw_client) => {
v3::request::AuthenticatorRequestData::Final(gw_client.into())
}
v2::request::AuthenticatorRequestData::QueryBandwidth(pub_key) => {
v3::request::AuthenticatorRequestData::QueryBandwidth(pub_key)
}
}
}
}
impl From<v2::registration::InitMessage> for v3::registration::InitMessage {
fn from(init_msg: v2::registration::InitMessage) -> Self {
Self {
pub_key: init_msg.pub_key,
}
}
}
impl From<Box<v2::registration::FinalMessage>> for Box<v3::registration::FinalMessage> {
fn from(gw_client: Box<v2::registration::FinalMessage>) -> Self {
Box::new(v3::registration::FinalMessage {
gateway_client: gw_client.gateway_client.into(),
credential: gw_client.credential,
})
}
}
impl From<v2::registration::GatewayClient> for v3::registration::GatewayClient {
fn from(gw_client: v2::registration::GatewayClient) -> Self {
Self {
pub_key: gw_client.pub_key,
private_ip: gw_client.private_ip,
mac: gw_client.mac.into(),
}
}
}
impl From<v3::registration::GatewayClient> for v2::registration::GatewayClient {
fn from(gw_client: v3::registration::GatewayClient) -> Self {
Self {
pub_key: gw_client.pub_key,
private_ip: gw_client.private_ip,
mac: gw_client.mac.into(),
}
}
}
impl From<v2::registration::ClientMac> for v3::registration::ClientMac {
fn from(mac: v2::registration::ClientMac) -> Self {
Self::new(mac.to_vec())
}
}
impl From<v3::registration::ClientMac> for v2::registration::ClientMac {
fn from(mac: v3::registration::ClientMac) -> Self {
Self::new(mac.to_vec())
}
}
impl TryFrom<v3::response::AuthenticatorResponse> for v2::response::AuthenticatorResponse {
type Error = crate::Error;
fn try_from(
authenticator_response: v3::response::AuthenticatorResponse,
) -> Result<Self, Self::Error> {
Ok(Self {
data: authenticator_response.data.try_into()?,
reply_to: authenticator_response.reply_to,
protocol: authenticator_response.protocol,
})
}
}
impl TryFrom<v3::response::AuthenticatorResponseData> for v2::response::AuthenticatorResponseData {
type Error = crate::Error;
fn try_from(
authenticator_response_data: v3::response::AuthenticatorResponseData,
) -> Result<Self, Self::Error> {
match authenticator_response_data {
v3::response::AuthenticatorResponseData::PendingRegistration(
pending_registration_response,
) => Ok(
v2::response::AuthenticatorResponseData::PendingRegistration(
pending_registration_response.into(),
),
),
v3::response::AuthenticatorResponseData::Registered(registered_response) => Ok(
v2::response::AuthenticatorResponseData::Registered(registered_response.into()),
),
v3::response::AuthenticatorResponseData::RemainingBandwidth(
remaining_bandwidth_response,
) => Ok(v2::response::AuthenticatorResponseData::RemainingBandwidth(
remaining_bandwidth_response.into(),
)),
v3::response::AuthenticatorResponseData::TopUpBandwidth(_) => {
Err(Self::Error::Conversion(
"a v2 request couldn't produce a v3 only type of response".to_string(),
))
}
}
}
}
impl From<v3::response::PendingRegistrationResponse> for v2::response::PendingRegistrationResponse {
fn from(value: v3::response::PendingRegistrationResponse) -> Self {
Self {
request_id: value.request_id,
reply_to: value.reply_to,
reply: value.reply.into(),
}
}
}
impl From<v3::response::RegisteredResponse> for v2::response::RegisteredResponse {
fn from(value: v3::response::RegisteredResponse) -> Self {
Self {
request_id: value.request_id,
reply_to: value.reply_to,
reply: value.reply.into(),
}
}
}
impl From<v3::response::RemainingBandwidthResponse> for v2::response::RemainingBandwidthResponse {
fn from(value: v3::response::RemainingBandwidthResponse) -> Self {
Self {
request_id: value.request_id,
reply_to: value.reply_to,
reply: value.reply.map(Into::into),
}
}
}
impl From<v3::registration::RegistrationData> for v2::registration::RegistrationData {
fn from(value: v3::registration::RegistrationData) -> Self {
Self {
nonce: value.nonce,
gateway_data: value.gateway_data.into(),
wg_port: value.wg_port,
}
}
}
impl From<v3::registration::RegistredData> for v2::registration::RegistredData {
fn from(value: v3::registration::RegistredData) -> Self {
Self {
pub_key: value.pub_key,
private_ip: value.private_ip,
wg_port: value.wg_port,
}
}
}
impl From<v3::registration::RemainingBandwidthData> for v2::registration::RemainingBandwidthData {
fn from(value: v3::registration::RemainingBandwidthData) -> Self {
Self {
available_bandwidth: value.available_bandwidth,
}
}
}
@@ -1,10 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
pub mod conversion;
pub mod registration;
pub mod request;
pub mod response;
pub mod topup;
pub const VERSION: u8 = 3;
@@ -1,227 +0,0 @@
// -2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::error::Error;
use base64::{engine::general_purpose, Engine};
use nym_credentials_interface::CredentialSpendingData;
use nym_wireguard_types::PeerPublicKey;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::net::IpAddr;
use std::time::SystemTime;
use std::{fmt, ops::Deref, str::FromStr};
#[cfg(feature = "verify")]
use hmac::{Hmac, Mac};
#[cfg(feature = "verify")]
use nym_crypto::asymmetric::encryption::PrivateKey;
#[cfg(feature = "verify")]
use sha2::Sha256;
pub type PendingRegistrations = HashMap<PeerPublicKey, RegistrationData>;
pub type PrivateIPs = HashMap<IpAddr, Taken>;
#[cfg(feature = "verify")]
pub type HmacSha256 = Hmac<Sha256>;
pub type Nonce = u64;
pub type Taken = Option<SystemTime>;
pub const BANDWIDTH_CAP_PER_DAY: u64 = 1024 * 1024 * 1024; // 1 GB
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct InitMessage {
/// Base64 encoded x25519 public key
pub pub_key: PeerPublicKey,
}
impl InitMessage {
pub fn new(pub_key: PeerPublicKey) -> Self {
InitMessage { pub_key }
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct FinalMessage {
/// Gateway client data
pub gateway_client: GatewayClient,
/// Ecash credential
pub credential: Option<CredentialSpendingData>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RegistrationData {
pub nonce: u64,
pub gateway_data: GatewayClient,
pub wg_port: u16,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RegistredData {
pub pub_key: PeerPublicKey,
pub private_ip: IpAddr,
pub wg_port: u16,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RemainingBandwidthData {
pub available_bandwidth: i64,
}
/// Client that wants to register sends its PublicKey bytes mac digest encrypted with a DH shared secret.
/// Gateway/Nym node can then verify pub_key payload using the same process
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct GatewayClient {
/// Base64 encoded x25519 public key
pub pub_key: PeerPublicKey,
/// Assigned private IP
pub private_ip: IpAddr,
/// Sha256 hmac on the data (alongside the prior nonce)
pub mac: ClientMac,
}
impl GatewayClient {
#[cfg(feature = "verify")]
pub fn new(
local_secret: &PrivateKey,
remote_public: x25519_dalek::PublicKey,
private_ip: IpAddr,
nonce: u64,
) -> Self {
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
#[allow(clippy::expect_used)]
let static_secret = x25519_dalek::StaticSecret::from(local_secret.to_bytes());
let local_public: x25519_dalek::PublicKey = (&static_secret).into();
let dh = static_secret.diffie_hellman(&remote_public);
// TODO: change that to use our nym_crypto::hmac module instead
#[allow(clippy::expect_used)]
let mut mac = HmacSha256::new_from_slice(dh.as_bytes())
.expect("x25519 shared secret is always 32 bytes long");
mac.update(local_public.as_bytes());
mac.update(private_ip.to_string().as_bytes());
mac.update(&nonce.to_le_bytes());
GatewayClient {
pub_key: PeerPublicKey::new(local_public),
private_ip,
mac: ClientMac(mac.finalize().into_bytes().to_vec()),
}
}
// Reusable secret should be gateways Wireguard PK
// Client should perform this step when generating its payload, using its own WG PK
#[cfg(feature = "verify")]
pub fn verify(&self, gateway_key: &PrivateKey, nonce: u64) -> Result<(), Error> {
// convert from 1.0 x25519-dalek private key into 2.0 x25519-dalek
#[allow(clippy::expect_used)]
let static_secret = x25519_dalek::StaticSecret::from(gateway_key.to_bytes());
let dh = static_secret.diffie_hellman(&self.pub_key);
// TODO: change that to use our nym_crypto::hmac module instead
#[allow(clippy::expect_used)]
let mut mac = HmacSha256::new_from_slice(dh.as_bytes())
.expect("x25519 shared secret is always 32 bytes long");
mac.update(self.pub_key.as_bytes());
mac.update(self.private_ip.to_string().as_bytes());
mac.update(&nonce.to_le_bytes());
mac.verify_slice(&self.mac)
.map_err(|source| Error::FailedClientMacVerification {
client: self.pub_key.to_string(),
source,
})
}
pub fn pub_key(&self) -> PeerPublicKey {
self.pub_key
}
}
// TODO: change the inner type into generic array of size HmacSha256::OutputSize
// TODO2: rely on our internal crypto/hmac
#[derive(Debug, Clone)]
pub struct ClientMac(Vec<u8>);
impl fmt::Display for ClientMac {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", general_purpose::STANDARD.encode(&self.0))
}
}
impl ClientMac {
#[allow(dead_code)]
pub fn new(mac: Vec<u8>) -> Self {
ClientMac(mac)
}
}
impl Deref for ClientMac {
type Target = Vec<u8>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl FromStr for ClientMac {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mac_bytes: Vec<u8> =
general_purpose::STANDARD
.decode(s)
.map_err(|source| Error::MalformedClientMac {
mac: s.to_string(),
source,
})?;
Ok(ClientMac(mac_bytes))
}
}
impl Serialize for ClientMac {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let encoded_key = general_purpose::STANDARD.encode(self.0.clone());
serializer.serialize_str(&encoded_key)
}
}
impl<'de> Deserialize<'de> for ClientMac {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let encoded_key = String::deserialize(deserializer)?;
ClientMac::from_str(&encoded_key).map_err(serde::de::Error::custom)
}
}
#[cfg(test)]
mod tests {
use super::*;
use nym_crypto::asymmetric::encryption;
#[test]
#[cfg(feature = "verify")]
fn client_request_roundtrip() {
let mut rng = rand::thread_rng();
let gateway_key_pair = encryption::KeyPair::new(&mut rng);
let client_key_pair = encryption::KeyPair::new(&mut rng);
let nonce = 1234567890;
let client = GatewayClient::new(
client_key_pair.private_key(),
x25519_dalek::PublicKey::from(gateway_key_pair.public_key().to_bytes()),
"10.0.0.42".parse().unwrap(),
nonce,
);
assert!(client.verify(gateway_key_pair.private_key(), nonce).is_ok())
}
}
@@ -1,136 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::{
registration::{FinalMessage, InitMessage},
topup::TopUpMessage,
};
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
use nym_sphinx::addressing::Recipient;
use nym_wireguard_types::PeerPublicKey;
use serde::{Deserialize, Serialize};
use crate::make_bincode_serializer;
use super::VERSION;
fn generate_random() -> u64 {
use rand::RngCore;
let mut rng = rand::rngs::OsRng;
rng.next_u64()
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AuthenticatorRequest {
pub protocol: Protocol,
pub data: AuthenticatorRequestData,
pub reply_to: Recipient,
pub request_id: u64,
}
impl AuthenticatorRequest {
pub fn from_reconstructed_message(
message: &nym_sphinx::receiver::ReconstructedMessage,
) -> Result<Self, bincode::Error> {
use bincode::Options;
make_bincode_serializer().deserialize(&message.message)
}
pub fn new_initial_request(init_message: InitMessage, reply_to: Recipient) -> (Self, u64) {
let request_id = generate_random();
(
Self {
protocol: Protocol {
service_provider_type: ServiceProviderType::Authenticator,
version: VERSION,
},
data: AuthenticatorRequestData::Initial(init_message),
reply_to,
request_id,
},
request_id,
)
}
pub fn new_final_request(final_message: FinalMessage, reply_to: Recipient) -> (Self, u64) {
let request_id = generate_random();
(
Self {
protocol: Protocol {
service_provider_type: ServiceProviderType::Authenticator,
version: VERSION,
},
data: AuthenticatorRequestData::Final(Box::new(final_message)),
reply_to,
request_id,
},
request_id,
)
}
pub fn new_query_request(peer_public_key: PeerPublicKey, reply_to: Recipient) -> (Self, u64) {
let request_id = generate_random();
(
Self {
protocol: Protocol {
service_provider_type: ServiceProviderType::Authenticator,
version: VERSION,
},
data: AuthenticatorRequestData::QueryBandwidth(peer_public_key),
reply_to,
request_id,
},
request_id,
)
}
pub fn new_topup_request(top_up_message: TopUpMessage, reply_to: Recipient) -> (Self, u64) {
let request_id = generate_random();
(
Self {
protocol: Protocol {
service_provider_type: ServiceProviderType::Authenticator,
version: VERSION,
},
data: AuthenticatorRequestData::TopUpBandwidth(Box::new(top_up_message)),
reply_to,
request_id,
},
request_id,
)
}
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
use bincode::Options;
make_bincode_serializer().serialize(self)
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AuthenticatorRequestData {
Initial(InitMessage),
Final(Box<FinalMessage>),
QueryBandwidth(PeerPublicKey),
TopUpBandwidth(Box<TopUpMessage>),
}
#[cfg(test)]
mod tests {
use super::*;
use std::str::FromStr;
#[test]
fn check_first_bytes_protocol() {
let version = 2;
let data = AuthenticatorRequest {
protocol: Protocol { version, service_provider_type: ServiceProviderType::Authenticator },
data: AuthenticatorRequestData::Initial(InitMessage::new(
PeerPublicKey::from_str("yvNUDpT5l7W/xDhiu6HkqTHDQwbs/B3J5UrLmORl1EQ=").unwrap(),
)),
reply_to: Recipient::try_from_base58_string("D1rrpsysCGCYXy9saP8y3kmNpGtJZUXN9SvFoUcqAsM9.9Ssso1ea5NfkbMASdiseDSjTN1fSWda5SgEVjdSN4CvV@GJqd3ZxpXWSNxTfx7B1pPtswpetH4LnJdFeLeuY5KUuN").unwrap(),
request_id: 1,
};
let bytes = *data.to_bytes().unwrap().first_chunk::<2>().unwrap();
assert_eq!(bytes, [version, ServiceProviderType::Authenticator as u8]);
}
}
@@ -1,157 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use super::registration::{RegistrationData, RegistredData, RemainingBandwidthData};
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
use nym_sphinx::addressing::Recipient;
use serde::{Deserialize, Serialize};
use crate::make_bincode_serializer;
use super::VERSION;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AuthenticatorResponse {
pub protocol: Protocol,
pub data: AuthenticatorResponseData,
pub reply_to: Recipient,
}
impl AuthenticatorResponse {
pub fn new_pending_registration_success(
registration_data: RegistrationData,
request_id: u64,
reply_to: Recipient,
) -> Self {
Self {
protocol: Protocol {
service_provider_type: ServiceProviderType::Authenticator,
version: VERSION,
},
data: AuthenticatorResponseData::PendingRegistration(PendingRegistrationResponse {
reply: registration_data,
reply_to,
request_id,
}),
reply_to,
}
}
pub fn new_registered(
registred_data: RegistredData,
reply_to: Recipient,
request_id: u64,
) -> Self {
Self {
protocol: Protocol {
service_provider_type: ServiceProviderType::Authenticator,
version: VERSION,
},
data: AuthenticatorResponseData::Registered(RegisteredResponse {
reply: registred_data,
reply_to,
request_id,
}),
reply_to,
}
}
pub fn new_remaining_bandwidth(
remaining_bandwidth_data: Option<RemainingBandwidthData>,
reply_to: Recipient,
request_id: u64,
) -> Self {
Self {
protocol: Protocol {
service_provider_type: ServiceProviderType::Authenticator,
version: VERSION,
},
data: AuthenticatorResponseData::RemainingBandwidth(RemainingBandwidthResponse {
reply: remaining_bandwidth_data,
reply_to,
request_id,
}),
reply_to,
}
}
pub fn new_topup_bandwidth(
remaining_bandwidth_data: RemainingBandwidthData,
reply_to: Recipient,
request_id: u64,
) -> Self {
Self {
protocol: Protocol {
service_provider_type: ServiceProviderType::Authenticator,
version: VERSION,
},
data: AuthenticatorResponseData::TopUpBandwidth(TopUpBandwidthResponse {
reply: remaining_bandwidth_data,
reply_to,
request_id,
}),
reply_to,
}
}
pub fn recipient(&self) -> Recipient {
self.reply_to
}
pub fn to_bytes(&self) -> Result<Vec<u8>, bincode::Error> {
use bincode::Options;
make_bincode_serializer().serialize(self)
}
pub fn from_reconstructed_message(
message: &nym_sphinx::receiver::ReconstructedMessage,
) -> Result<Self, bincode::Error> {
use bincode::Options;
make_bincode_serializer().deserialize(&message.message)
}
pub fn id(&self) -> Option<u64> {
match &self.data {
AuthenticatorResponseData::PendingRegistration(response) => Some(response.request_id),
AuthenticatorResponseData::Registered(response) => Some(response.request_id),
AuthenticatorResponseData::RemainingBandwidth(response) => Some(response.request_id),
AuthenticatorResponseData::TopUpBandwidth(response) => Some(response.request_id),
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AuthenticatorResponseData {
PendingRegistration(PendingRegistrationResponse),
Registered(RegisteredResponse),
RemainingBandwidth(RemainingBandwidthResponse),
TopUpBandwidth(TopUpBandwidthResponse),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PendingRegistrationResponse {
pub request_id: u64,
pub reply_to: Recipient,
pub reply: RegistrationData,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RegisteredResponse {
pub request_id: u64,
pub reply_to: Recipient,
pub reply: RegistredData,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RemainingBandwidthResponse {
pub request_id: u64,
pub reply_to: Recipient,
pub reply: Option<RemainingBandwidthData>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TopUpBandwidthResponse {
pub request_id: u64,
pub reply_to: Recipient,
pub reply: RemainingBandwidthData,
}
@@ -1,15 +0,0 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use nym_credentials_interface::CredentialSpendingData;
use nym_wireguard_types::PeerPublicKey;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct TopUpMessage {
/// Base64 encoded x25519 public key
pub pub_key: PeerPublicKey,
/// Ecash credential
pub credential: CredentialSpendingData,
}
@@ -1,20 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT EXISTS (SELECT 1 FROM registered_gateway WHERE gateway_id_bs58 = ?) AS 'exists'",
"describe": {
"columns": [
{
"name": "exists",
"ordinal": 0,
"type_info": "Int"
}
],
"parameters": {
"Right": 1
},
"nullable": [
null
]
},
"hash": "06e743d143fcc4be20ca2af5e99b19f15d22fff72490473587a14cdc046fda32"
}
@@ -1,44 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT * FROM remote_gateway_details WHERE gateway_id_bs58 = ?",
"describe": {
"columns": [
{
"name": "gateway_id_bs58",
"ordinal": 0,
"type_info": "Text"
},
{
"name": "gateway_owner_address",
"ordinal": 1,
"type_info": "Text"
},
{
"name": "gateway_listener",
"ordinal": 2,
"type_info": "Text"
},
{
"name": "derived_aes128_ctr_blake3_hmac_keys_bs58",
"ordinal": 3,
"type_info": "Text"
},
{
"name": "derived_aes256_gcm_siv_key",
"ordinal": 4,
"type_info": "Blob"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
true,
false,
true,
true
]
},
"hash": "0e85ec18da67cf4e3df04ad80136571f6e920eb2290f20b1b8c5b0ab4b489985"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n UPDATE remote_gateway_details\n SET\n derived_aes128_ctr_blake3_hmac_keys_bs58 = ?,\n derived_aes256_gcm_siv_key = ?\n WHERE gateway_id_bs58 = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 3
},
"nullable": []
},
"hash": "0f1dfb89f1eb39f4a58787af0f53a7a93afb7e4d2e54e2d38fd79d31c8575a54"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "DELETE FROM remote_gateway_details WHERE gateway_id_bs58 = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "1da6904e72b5abb9abf75affb13af7974d7795b4cbdba234273345fe161df233"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "DELETE FROM custom_gateway_details WHERE gateway_id_bs58 = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "4f78619aca933484cd67cb89a376b2a5bec1c191993ff58f0c71c03e3ef6d92d"
}
@@ -1,26 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT * FROM custom_gateway_details WHERE gateway_id_bs58 = ?",
"describe": {
"columns": [
{
"name": "gateway_id_bs58",
"ordinal": 0,
"type_info": "Text"
},
{
"name": "data",
"ordinal": 1,
"type_info": "Blob"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
true
]
},
"hash": "54f552a9dbe95236f946ac2b6615e03504afa58e345ae16a128629d8e76f0a11"
}
@@ -1,20 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT gateway_id_bs58 FROM registered_gateway",
"describe": {
"columns": [
{
"name": "gateway_id_bs58",
"ordinal": 0,
"type_info": "Text"
}
],
"parameters": {
"Right": 0
},
"nullable": [
false
]
},
"hash": "5661cf1ad8bd5ca062e855e1971a8787133ee41814bd3efdd501f9ee0c050f2b"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "UPDATE active_gateway SET active_gateway_id_bs58 = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "80476cf2906eb0ecf7f66c16bc5682169b87f488b6927fa67fade6bf5abf7582"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n INSERT INTO registered_gateway(gateway_id_bs58, registration_timestamp, gateway_type) \n VALUES (?, ?, ?)\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 3
},
"nullable": []
},
"hash": "8909fd329e7e5fb16c4989b15b3d3a12bba1569520e01f6f074178e23d6ee89e"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n INSERT INTO remote_gateway_details(gateway_id_bs58, derived_aes128_ctr_blake3_hmac_keys_bs58, derived_aes256_gcm_siv_key, gateway_owner_address, gateway_listener)\n VALUES (?, ?, ?, ?, ?)\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 5
},
"nullable": []
},
"hash": "a6939bea03b10cde810a9a099bd597b4f51092e30a41c4085a8f8668f039f7c0"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n INSERT INTO custom_gateway_details(gateway_id_bs58, data) \n VALUES (?, ?)\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "b059bc3688b6b7f83f47048db9897720fd4e6f3211bf74030a9638f7bf6738e4"
}
@@ -1,20 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT active_gateway_id_bs58 FROM active_gateway",
"describe": {
"columns": [
{
"name": "active_gateway_id_bs58",
"ordinal": 0,
"type_info": "Text"
}
],
"parameters": {
"Right": 0
},
"nullable": [
true
]
},
"hash": "bf249752f08c283bf5942b6ff48125c24750b523cfcad1e5e9069dbf7050e2a1"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "DELETE FROM registered_gateway WHERE gateway_id_bs58 = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "f3ebe259e26c05ecdd33bd9085dbb91cd5046a8c9d4434cf085a4fa2ebf03e93"
}
@@ -29,10 +29,11 @@ impl StorageManager {
})?;
}
let opts = sqlx::sqlite::SqliteConnectOptions::new()
let mut opts = sqlx::sqlite::SqliteConnectOptions::new()
.filename(database_path)
.create_if_missing(true)
.disable_statement_logging();
.create_if_missing(true);
opts.disable_statement_logging();
let connection_pool = sqlx::SqlitePool::connect_with(opts)
.await
@@ -81,7 +82,7 @@ impl StorageManager {
sqlx::query!("SELECT EXISTS (SELECT 1 FROM registered_gateway WHERE gateway_id_bs58 = ?) AS 'exists'", gateway_id)
.fetch_one(&self.connection_pool)
.await
.map(|result| result.exists == Some(1))
.map(|result| result.exists == 1)
}
pub(crate) async fn maybe_get_registered_gateway(
@@ -110,11 +110,7 @@ impl GeoAwareTopologyProvider {
}
async fn get_topology(&self) -> Option<NymTopology> {
let mixnodes = match self
.validator_client
.get_basic_active_mixing_assigned_nodes(Some(self.client_version.clone()))
.await
{
let mixnodes = match self.validator_client.get_basic_mixnodes(None).await {
Err(err) => {
error!("failed to get network mixnodes - {err}");
return None;
@@ -122,11 +118,7 @@ impl GeoAwareTopologyProvider {
Ok(mixes) => mixes,
};
let gateways = match self
.validator_client
.get_all_basic_entry_assigned_nodes(Some(self.client_version.clone()))
.await
{
let gateways = match self.validator_client.get_basic_gateways(None).await {
Err(err) => {
error!("failed to get network gateways - {err}");
return None;
@@ -193,7 +185,8 @@ impl GeoAwareTopologyProvider {
.filter(|m| filtered_mixnode_ids.contains(&m.node_id))
.collect::<Vec<_>>();
let topology = nym_topology_from_basic_info(&mixnodes, &gateways);
let topology = nym_topology_from_basic_info(&mixnodes, &gateways)
.filter_system_version(&self.client_version);
// TODO: return real error type
check_layer_integrity(topology.clone()).ok()?;
@@ -98,7 +98,7 @@ impl NymApiTopologyProvider {
async fn get_current_compatible_topology(&mut self) -> Option<NymTopology> {
let mixnodes = match self
.validator_client
.get_basic_active_mixing_assigned_nodes(Some(self.client_version.clone()))
.get_basic_mixnodes(Some(self.client_version.clone()))
.await
{
Err(err) => {
@@ -110,7 +110,7 @@ impl NymApiTopologyProvider {
let gateways = match self
.validator_client
.get_all_basic_entry_assigned_nodes(Some(self.client_version.clone()))
.get_basic_gateways(Some(self.client_version.clone()))
.await
{
Err(err) => {
@@ -134,6 +134,7 @@ impl NymApiTopologyProvider {
g.performance.round_to_integer() >= self.config.min_gateway_performance
}),
);
if let Err(err) = self.check_layer_distribution(&topology) {
warn!("The current filtered active topology has extremely skewed layer distribution. It cannot be used: {err}");
self.use_next_nym_api();
+14 -7
View File
@@ -7,7 +7,7 @@ use futures::{SinkExt, StreamExt};
use log::{debug, info, trace, warn};
use nym_crypto::asymmetric::identity;
use nym_gateway_client::GatewayClient;
use nym_topology::{gateway, mix};
use nym_topology::{filter::VersionFilterable, gateway, mix};
use nym_validator_client::client::IdentityKeyRef;
use nym_validator_client::UserAgent;
use rand::{seq::SliceRandom, Rng};
@@ -94,7 +94,7 @@ pub async fn current_gateways<R: Rng>(
log::debug!("Fetching list of gateways from: {nym_api}");
let gateways = client.get_all_basic_entry_assigned_nodes(None).await?;
let gateways = client.get_basic_gateways(None).await?;
log::debug!("Found {} gateways", gateways.len());
log::trace!("Gateways: {:#?}", gateways);
@@ -102,12 +102,17 @@ pub async fn current_gateways<R: Rng>(
.iter()
.filter_map(|gateway| gateway.try_into().ok())
.collect::<Vec<gateway::LegacyNode>>();
log::debug!("After checking validity: {}", valid_gateways.len());
log::debug!("Ater checking validity: {}", valid_gateways.len());
log::trace!("Valid gateways: {:#?}", valid_gateways);
log::info!("nym-api reports {} valid gateways", valid_gateways.len());
// we were always filtering by version so I'm not removing that 'feature'
let filtered_gateways = valid_gateways.filter_by_version(env!("CARGO_PKG_VERSION"));
log::debug!("After filtering for version: {}", filtered_gateways.len());
log::trace!("Filtered gateways: {:#?}", filtered_gateways);
Ok(valid_gateways)
log::info!("nym-api reports {} valid gateways", filtered_gateways.len());
Ok(filtered_gateways)
}
pub async fn current_mixnodes<R: Rng>(
@@ -121,13 +126,15 @@ pub async fn current_mixnodes<R: Rng>(
log::trace!("Fetching list of mixnodes from: {nym_api}");
let mixnodes = client.get_basic_active_mixing_assigned_nodes(None).await?;
let mixnodes = client.get_basic_mixnodes(None).await?;
let valid_mixnodes = mixnodes
.iter()
.filter_map(|mixnode| mixnode.try_into().ok())
.collect::<Vec<mix::LegacyNode>>();
Ok(valid_mixnodes)
// we were always filtering by version so I'm not removing that 'feature'
let filtered_mixnodes = valid_mixnodes.filter_by_version(env!("CARGO_PKG_VERSION"));
Ok(filtered_mixnodes)
}
#[cfg(not(target_arch = "wasm32"))]
@@ -1,12 +1,9 @@
// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::backend::fs_backend::{
error::StorageError,
models::{
ReplySurbStorageMetadata, StoredReplyKey, StoredReplySurb, StoredSenderTag,
StoredSurbSender,
},
use crate::backend::fs_backend::error::StorageError;
use crate::backend::fs_backend::models::{
ReplySurbStorageMetadata, StoredReplyKey, StoredReplySurb, StoredSenderTag, StoredSurbSender,
};
use log::{error, info};
use sqlx::ConnectOptions;
@@ -30,10 +27,11 @@ impl StorageManager {
})?;
}
let opts = sqlx::sqlite::SqliteConnectOptions::new()
let mut opts = sqlx::sqlite::SqliteConnectOptions::new()
.filename(database_path)
.create_if_missing(fresh)
.disable_statement_logging();
.create_if_missing(fresh);
opts.disable_statement_logging();
let connection_pool = match sqlx::SqlitePool::connect_with(opts).await {
Ok(pool) => pool,
@@ -25,7 +25,7 @@ serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
nym-http-api-client = { path = "../../../common/http-api-client" }
thiserror = { workspace = true }
log = { workspace = true }
tracing = { workspace = true }
url = { workspace = true, features = ["serde"] }
tokio = { workspace = true, features = ["sync", "time"] }
time = { workspace = true, features = ["formatting"] }
@@ -265,6 +265,13 @@ impl NymApiClient {
NymApiClient { nym_api }
}
#[cfg(not(target_arch = "wasm32"))]
pub fn new_with_timeout(api_url: Url, timeout: std::time::Duration) -> Self {
let nym_api = nym_api::Client::new(api_url, Some(timeout));
NymApiClient { nym_api }
}
pub fn new_with_user_agent(api_url: Url, user_agent: UserAgent) -> Self {
let nym_api = nym_api::Client::builder::<_, ValidatorClientError>(api_url)
.expect("invalid api url")
@@ -283,7 +290,6 @@ impl NymApiClient {
self.nym_api.change_base_url(new_endpoint);
}
#[deprecated(note = "use get_basic_active_mixing_assigned_nodes instead")]
pub async fn get_basic_mixnodes(
&self,
semver_compatibility: Option<String>,
@@ -295,7 +301,6 @@ impl NymApiClient {
.nodes)
}
#[deprecated(note = "use get_all_basic_entry_assigned_nodes instead")]
pub async fn get_basic_gateways(
&self,
semver_compatibility: Option<String>,
@@ -307,70 +312,6 @@ impl NymApiClient {
.nodes)
}
/// retrieve basic information for nodes are capable of operating as an entry gateway
/// this includes legacy gateways and nym-nodes
pub async fn get_all_basic_entry_assigned_nodes(
&self,
semver_compatibility: Option<String>,
) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
// TODO: deal with paging in macro or some helper function or something, because it's the same pattern everywhere
let mut page = 0;
let mut nodes = Vec::new();
loop {
let mut res = self
.nym_api
.get_all_basic_entry_assigned_nodes(
semver_compatibility.clone(),
false,
Some(page),
None,
)
.await?;
nodes.append(&mut res.nodes.data);
if nodes.len() < res.nodes.pagination.total {
page += 1
} else {
break;
}
}
Ok(nodes)
}
/// retrieve basic information for nodes that got assigned 'mixing' node in this epoch
/// this includes legacy mixnodes and nym-nodes
pub async fn get_basic_active_mixing_assigned_nodes(
&self,
semver_compatibility: Option<String>,
) -> Result<Vec<SkimmedNode>, ValidatorClientError> {
// TODO: deal with paging in macro or some helper function or something, because it's the same pattern everywhere
let mut page = 0;
let mut nodes = Vec::new();
loop {
let mut res = self
.nym_api
.get_basic_active_mixing_assigned_nodes(
semver_compatibility.clone(),
false,
Some(page),
None,
)
.await?;
nodes.append(&mut res.nodes.data);
if nodes.len() < res.nodes.pagination.total {
page += 1
} else {
break;
}
}
Ok(nodes)
}
pub async fn get_cached_active_mixnodes(
&self,
) -> Result<Vec<MixNodeDetails>, ValidatorClientError> {
@@ -121,36 +121,36 @@ async fn test_nyxd_connection(
{
Ok(Err(NyxdError::TendermintErrorRpc(e))) => {
// If we get a tendermint-rpc error, we classify the node as not contactable
log::warn!("Checking: nyxd url: {url}: {}: {}", "failed".red(), e);
tracing::warn!("Checking: nyxd url: {url}: {}: {}", "failed".red(), e);
false
}
Ok(Err(NyxdError::AbciError { code, log, .. })) => {
// We accept the mixnet contract not found as ok from a connection standpoint. This happens
// for example on a pre-launch network.
log::debug!(
tracing::debug!(
"Checking: nyxd url: {url}: {}, but with abci error: {code}: {log}",
"success".green()
);
code == 18
}
Ok(Err(error @ NyxdError::NoContractAddressAvailable(_))) => {
log::warn!("Checking: nyxd url: {url}: {}: {error}", "failed".red());
tracing::warn!("Checking: nyxd url: {url}: {}: {error}", "failed".red());
false
}
Ok(Err(e)) => {
// For any other error, we're optimistic and just try anyway.
log::warn!(
tracing::warn!(
"Checking: nyxd_url: {url}: {}, but with error: {e}",
"success".green()
);
true
}
Ok(Ok(_)) => {
log::debug!("Checking: nyxd_url: {url}: {}", "success".green());
tracing::debug!("Checking: nyxd_url: {url}: {}", "success".green());
true
}
Err(e) => {
log::warn!("Checking: nyxd_url: {url}: {}: {e}", "failed".red());
tracing::warn!("Checking: nyxd_url: {url}: {}: {e}", "failed".red());
false
}
};
@@ -169,15 +169,15 @@ async fn test_nym_api_connection(
.await
{
Ok(Ok(_)) => {
log::debug!("Checking: api_url: {url}: {}", "success".green());
tracing::debug!("Checking: api_url: {url}: {}", "success".green());
true
}
Ok(Err(e)) => {
log::debug!("Checking: api_url: {url}: {}: {e}", "failed".red());
tracing::debug!("Checking: api_url: {url}: {}: {e}", "failed".red());
false
}
Err(e) => {
log::debug!("Checking: api_url: {url}: {}: {e}", "failed".red());
tracing::debug!("Checking: api_url: {url}: {}: {e}", "failed".red());
false
}
};
@@ -13,7 +13,6 @@ use nym_api_requests::ecash::VerificationKeyResponse;
use nym_api_requests::models::{
AnnotationResponse, LegacyDescribedMixNode, NodePerformanceResponse,
};
use nym_api_requests::nym_nodes::PaginatedCachedNodesResponse;
pub use nym_api_requests::{
ecash::{
models::{
@@ -41,6 +40,7 @@ use nym_mixnet_contract_common::mixnode::MixNodeDetails;
use nym_mixnet_contract_common::{GatewayBond, IdentityKeyRef, NodeId};
use time::format_description::BorrowedFormatItem;
use time::Date;
use tracing::instrument;
pub mod error;
pub mod routes;
@@ -52,11 +52,13 @@ pub fn rfc_3339_date() -> Vec<BorrowedFormatItem<'static>> {
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait NymApiClientExt: ApiClient {
#[instrument(level = "debug", skip(self))]
async fn get_mixnodes(&self) -> Result<Vec<MixNodeDetails>, NymAPIError> {
self.get_json(&[routes::API_VERSION, routes::MIXNODES], NO_PARAMS)
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_mixnodes_detailed(&self) -> Result<Vec<MixNodeBondAnnotated>, NymAPIError> {
self.get_json(
&[
@@ -70,6 +72,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_gateways_detailed(&self) -> Result<Vec<GatewayBondAnnotated>, NymAPIError> {
self.get_json(
&[
@@ -83,6 +86,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_mixnodes_detailed_unfiltered(
&self,
) -> Result<Vec<MixNodeBondAnnotated>, NymAPIError> {
@@ -98,11 +102,13 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_gateways(&self) -> Result<Vec<GatewayBond>, NymAPIError> {
self.get_json(&[routes::API_VERSION, routes::GATEWAYS], NO_PARAMS)
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_gateways_described(&self) -> Result<Vec<LegacyDescribedGateway>, NymAPIError> {
self.get_json(
&[routes::API_VERSION, routes::GATEWAYS, routes::DESCRIBED],
@@ -111,6 +117,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_mixnodes_described(&self) -> Result<Vec<LegacyDescribedMixNode>, NymAPIError> {
self.get_json(
&[routes::API_VERSION, routes::MIXNODES, routes::DESCRIBED],
@@ -119,6 +126,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[tracing::instrument(level = "debug", skip_all)]
async fn get_basic_mixnodes(
&self,
semver_compatibility: Option<String>,
@@ -142,6 +150,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_basic_gateways(
&self,
semver_compatibility: Option<String>,
@@ -165,88 +174,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
/// retrieve basic information for nodes are capable of operating as an entry gateway
/// this includes legacy gateways and nym-nodes
async fn get_all_basic_entry_assigned_nodes(
&self,
semver_compatibility: Option<String>,
no_legacy: bool,
page: Option<u32>,
per_page: Option<u32>,
) -> Result<PaginatedCachedNodesResponse<SkimmedNode>, NymAPIError> {
let mut params = Vec::new();
if let Some(arg) = &semver_compatibility {
params.push(("semver_compatibility", arg.clone()))
}
if no_legacy {
params.push(("no_legacy", "true".to_string()))
}
if let Some(page) = page {
params.push(("page", page.to_string()))
}
if let Some(per_page) = per_page {
params.push(("per_page", per_page.to_string()))
}
self.get_json(
&[
routes::API_VERSION,
"unstable",
"nym-nodes",
"skimmed",
"entry-gateways",
"all",
],
&params,
)
.await
}
/// retrieve basic information for nodes that got assigned 'mixing' node in this epoch
/// this includes legacy mixnodes and nym-nodes
async fn get_basic_active_mixing_assigned_nodes(
&self,
semver_compatibility: Option<String>,
no_legacy: bool,
page: Option<u32>,
per_page: Option<u32>,
) -> Result<PaginatedCachedNodesResponse<SkimmedNode>, NymAPIError> {
let mut params = Vec::new();
if let Some(arg) = &semver_compatibility {
params.push(("semver_compatibility", arg.clone()))
}
if no_legacy {
params.push(("no_legacy", "true".to_string()))
}
if let Some(page) = page {
params.push(("page", page.to_string()))
}
if let Some(per_page) = per_page {
params.push(("per_page", per_page.to_string()))
}
self.get_json(
&[
routes::API_VERSION,
"unstable",
"nym-nodes",
"skimmed",
"mixnodes",
"active",
],
&params,
)
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_active_mixnodes(&self) -> Result<Vec<MixNodeDetails>, NymAPIError> {
self.get_json(
&[routes::API_VERSION, routes::MIXNODES, routes::ACTIVE],
@@ -255,6 +183,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_active_mixnodes_detailed(&self) -> Result<Vec<MixNodeBondAnnotated>, NymAPIError> {
self.get_json(
&[
@@ -269,6 +198,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_rewarded_mixnodes(&self) -> Result<Vec<MixNodeDetails>, NymAPIError> {
self.get_json(
&[routes::API_VERSION, routes::MIXNODES, routes::REWARDED],
@@ -277,6 +207,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_mixnode_report(
&self,
mix_id: NodeId,
@@ -294,6 +225,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_gateway_report(
&self,
identity: IdentityKeyRef<'_>,
@@ -311,6 +243,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_mixnode_history(
&self,
mix_id: NodeId,
@@ -328,6 +261,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_gateway_history(
&self,
identity: IdentityKeyRef<'_>,
@@ -345,6 +279,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_rewarded_mixnodes_detailed(
&self,
) -> Result<Vec<MixNodeBondAnnotated>, NymAPIError> {
@@ -361,6 +296,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_gateway_core_status_count(
&self,
identity: IdentityKeyRef<'_>,
@@ -392,6 +328,7 @@ pub trait NymApiClientExt: ApiClient {
}
}
#[instrument(level = "debug", skip(self))]
async fn get_mixnode_core_status_count(
&self,
mix_id: NodeId,
@@ -424,6 +361,7 @@ pub trait NymApiClientExt: ApiClient {
}
}
#[instrument(level = "debug", skip(self))]
async fn get_mixnode_status(
&self,
mix_id: NodeId,
@@ -441,6 +379,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_mixnode_reward_estimation(
&self,
mix_id: NodeId,
@@ -458,6 +397,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn compute_mixnode_reward_estimation(
&self,
mix_id: NodeId,
@@ -477,6 +417,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_mixnode_stake_saturation(
&self,
mix_id: NodeId,
@@ -494,6 +435,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_mixnode_inclusion_probability(
&self,
mix_id: NodeId,
@@ -511,6 +453,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_current_node_performance(
&self,
node_id: NodeId,
@@ -541,6 +484,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_mixnodes_blacklisted(&self) -> Result<Vec<NodeId>, NymAPIError> {
self.get_json(
&[routes::API_VERSION, routes::MIXNODES, routes::BLACKLISTED],
@@ -549,6 +493,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn get_gateways_blacklisted(&self) -> Result<Vec<IdentityKey>, NymAPIError> {
self.get_json(
&[routes::API_VERSION, routes::GATEWAYS, routes::BLACKLISTED],
@@ -557,6 +502,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self, request_body))]
async fn blind_sign(
&self,
request_body: &BlindSignRequestBody,
@@ -573,6 +519,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self, request_body))]
async fn verify_ecash_ticket(
&self,
request_body: &VerifyEcashTicketBody,
@@ -589,6 +536,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self, request_body))]
async fn batch_redeem_ecash_tickets(
&self,
request_body: &BatchRedeemTicketsBody,
@@ -605,6 +553,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn double_spending_filter_v1(&self) -> Result<SpentCredentialsResponse, NymAPIError> {
self.get_json(
&[
@@ -617,6 +566,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn partial_expiration_date_signatures(
&self,
expiration_date: Option<Date>,
@@ -640,6 +590,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn partial_coin_indices_signatures(
&self,
epoch_id: Option<EpochId>,
@@ -660,6 +611,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn global_expiration_date_signatures(
&self,
expiration_date: Option<Date>,
@@ -683,6 +635,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn global_coin_indices_signatures(
&self,
epoch_id: Option<EpochId>,
@@ -703,6 +656,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn master_verification_key(
&self,
epoch_id: Option<EpochId>,
@@ -722,6 +676,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn epoch_credentials(
&self,
dkg_epoch: EpochId,
@@ -738,6 +693,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn issued_credential(
&self,
credential_id: i64,
@@ -754,6 +710,7 @@ pub trait NymApiClientExt: ApiClient {
.await
}
#[instrument(level = "debug", skip(self))]
async fn issued_credentials(
&self,
credential_ids: Vec<i64>,
@@ -8,9 +8,9 @@ use crate::nyxd::CosmWasmClient;
use async_trait::async_trait;
use cosmrs::AccountId;
use cosmwasm_std::Addr;
use log::trace;
use nym_coconut_dkg_common::types::{ChunkIndex, NodeIndex, StateAdvanceResponse};
use serde::Deserialize;
use tracing::trace;
use nym_coconut_dkg_common::dealer::RegisteredDealerDetails;
pub use nym_coconut_dkg_common::{
@@ -29,7 +29,6 @@ use cosmrs::proto::cosmwasm::wasm::v1::{
};
use cosmrs::tendermint::{block, chain, Hash};
use cosmrs::{AccountId, Coin as CosmosCoin, Tx};
use log::trace;
use prost::Message;
use serde::{Deserialize, Serialize};
@@ -68,7 +67,7 @@ pub trait CosmWasmClient: TendermintRpcClient {
Res: Message + Default,
{
if let Some(ref abci_path) = path {
trace!("performing query on abci path {abci_path}")
tracing::trace!("performing query on abci path {abci_path}")
}
let mut buf = Vec::with_capacity(req.encoded_len());
req.encode(&mut buf)?;
@@ -297,7 +296,7 @@ pub trait CosmWasmClient: TendermintRpcClient {
let start = Instant::now();
loop {
log::debug!(
tracing::debug!(
"Polling for result of including {} in a block...",
broadcasted.hash
);
@@ -522,7 +521,7 @@ pub trait CosmWasmClient: TendermintRpcClient {
.make_abci_query::<_, QuerySmartContractStateResponse>(path, req)
.await?;
trace!("raw query response: {}", String::from_utf8_lossy(&res.data));
tracing::trace!("raw query response: {}", String::from_utf8_lossy(&res.data));
Ok(serde_json::from_slice(&res.data)?)
}
@@ -25,12 +25,12 @@ use cosmrs::proto::cosmos::tx::signing::v1beta1::SignMode;
use cosmrs::staking::{MsgDelegate, MsgUndelegate};
use cosmrs::tx::{self, Msg};
use cosmrs::{cosmwasm, AccountId, Any, Tx};
use log::debug;
use serde::Serialize;
use sha2::Digest;
use sha2::Sha256;
use std::time::SystemTime;
use tendermint_rpc::endpoint::broadcast;
use tracing::debug;
fn empty_fee() -> tx::Fee {
tx::Fee {
@@ -7,9 +7,9 @@ use base64::Engine;
use cosmrs::abci::TxMsgData;
use cosmrs::cosmwasm::MsgExecuteContractResponse;
use cosmrs::proto::cosmos::base::query::v1beta1::{PageRequest, PageResponse};
use log::error;
use prost::bytes::Bytes;
use tendermint_rpc::endpoint::broadcast;
use tracing::error;
pub use cosmrs::abci::MsgResponse;
@@ -1,6 +1,8 @@
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::utils::CommonConfigsWrapper;
use anyhow::bail;
use clap::ArgGroup;
use clap::Parser;
use nym_credential_storage::initialise_persistent_storage;
@@ -29,7 +31,7 @@ impl FromStr for CredentialDataWrapper {
pub struct Args {
/// Config file of the client that is supposed to use the credential.
#[clap(long)]
pub(crate) credentials_store: PathBuf,
pub(crate) client_config: PathBuf,
/// Explicitly provide the encoded credential data (as base58)
#[clap(long, group = "cred_data")]
@@ -68,7 +70,21 @@ impl Args {
}
pub async fn execute(args: Args) -> anyhow::Result<()> {
let credentials_store = initialise_persistent_storage(args.credentials_store.clone()).await;
let loaded = CommonConfigsWrapper::try_load(&args.client_config)?;
if let Ok(id) = loaded.try_get_id() {
println!("loaded config file for client '{id}'");
}
let Ok(credentials_store) = loaded.try_get_credentials_store() else {
bail!("the loaded config does not have a credentials store information")
};
println!(
"using credentials store at '{}'",
credentials_store.display()
);
let credentials_store = initialise_persistent_storage(credentials_store).await;
let version = args.version;
let standalone = args.standalone;
@@ -10,13 +10,12 @@ use crate::{
use contracts_common::IdentityKeyRef;
use cosmwasm_std::{Coin, Decimal, StdError, StdResult, Uint128};
#[track_caller]
pub fn compare_decimals(a: Decimal, b: Decimal, epsilon: Option<Decimal>) {
let epsilon = epsilon.unwrap_or_else(|| Decimal::from_ratio(1u128, 100_000_000u128));
if a > b {
assert!(a - b < epsilon, "{a} != {b}, delta: {}", a - b)
assert!(a - b < epsilon, "{a} != {b}")
} else {
assert!(b - a < epsilon, "{a} != {b}, delta: {}", b - a)
assert!(b - a < epsilon, "{a} != {b}")
}
}
@@ -830,5 +830,4 @@ pub enum QueryMsg {
#[cw_serde]
pub struct MigrateMsg {
pub vesting_contract_address: Option<String>,
pub unsafe_skip_state_updates: Option<bool>,
}
@@ -1,32 +0,0 @@
{
"db_name": "SQLite",
"query": "\n SELECT epoch_id as \"epoch_id: u32\", serialised_signatures, serialization_revision as \"serialization_revision: u8\"\n FROM expiration_date_signatures\n WHERE expiration_date = ?\n ",
"describe": {
"columns": [
{
"name": "epoch_id: u32",
"ordinal": 0,
"type_info": "Int64"
},
{
"name": "serialised_signatures",
"ordinal": 1,
"type_info": "Blob"
},
{
"name": "serialization_revision: u8",
"ordinal": 2,
"type_info": "Int64"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false
]
},
"hash": "00d857b624e7edab1198114b17cbad1e16988a3f9989d135840500e1143ce5e5"
}
@@ -1,32 +0,0 @@
{
"db_name": "SQLite",
"query": "\n SELECT epoch_id as \"epoch_id: u32\", serialised_key, serialization_revision as \"serialization_revision: u8\"\n FROM master_verification_key WHERE epoch_id = ?\n ",
"describe": {
"columns": [
{
"name": "epoch_id: u32",
"ordinal": 0,
"type_info": "Int64"
},
{
"name": "serialised_key",
"ordinal": 1,
"type_info": "Blob"
},
{
"name": "serialization_revision: u8",
"ordinal": 2,
"type_info": "Int64"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false
]
},
"hash": "0112296b190328a3856d1adf51aafa2525da6c0b871633aad80ad555db9cf47c"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n INSERT OR IGNORE INTO expiration_date_signatures(expiration_date, epoch_id, serialised_signatures, serialization_revision)\n VALUES (?, ?, ?, ?);\n UPDATE expiration_date_signatures\n SET\n serialised_signatures = ?,\n serialization_revision = ?\n WHERE expiration_date = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 7
},
"nullable": []
},
"hash": "16d10f0ac0ed9ce4239937f46df3797a6a9ee7db2aab9f1b5e55f7c13c53bcc1"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n INSERT INTO ecash_ticketbook\n (serialization_revision, ticketbook_data, expiration_date, ticketbook_type, epoch_id, total_tickets, used_tickets)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 7
},
"nullable": []
},
"hash": "284b3ceae42f9320c30323dde47765854899103fd3c0fa670eb6809492270e02"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "DELETE FROM ecash_ticketbook WHERE expiration_date <= ?",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "37f82c9ec26b53d01601a2d6df82038a77ec37cca9f9aef18008dcd03030c2c4"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "DELETE FROM pending_issuance WHERE deposit_id = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "5c5d4bfabf18bc6fa56e76a9b98e38b7f6ceb8e9191a7b9201922efcf6b07966"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n INSERT INTO pending_issuance\n (deposit_id, serialization_revision, pending_ticketbook_data, expiration_date)\n VALUES (?, ?, ?, ?)\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 4
},
"nullable": []
},
"hash": "81a12a8a419c88b1c28a5533fde4d63462e9ea0049e2edafea1dc3f8476b33e4"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "UPDATE ecash_ticketbook SET used_tickets = used_tickets + ? WHERE id = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "84cad8b1078a4000830835e6349de3eb76fed954b7336530401db72cd008aff3"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n INSERT OR IGNORE INTO master_verification_key(epoch_id, serialised_key, serialization_revision) VALUES (?, ?, ?);\n UPDATE master_verification_key\n SET\n serialised_key = ?,\n serialization_revision = ?\n WHERE epoch_id = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 6
},
"nullable": []
},
"hash": "a5b18e66d77ff802e274623605e15dcfcffb502ba8398caefd56c481f44eb84e"
}
@@ -1,32 +0,0 @@
{
"db_name": "SQLite",
"query": "\n SELECT epoch_id as \"epoch_id: u32\", serialised_signatures, serialization_revision as \"serialization_revision: u8\"\n FROM coin_indices_signatures WHERE epoch_id = ?\n ",
"describe": {
"columns": [
{
"name": "epoch_id: u32",
"ordinal": 0,
"type_info": "Int64"
},
{
"name": "serialised_signatures",
"ordinal": 1,
"type_info": "Blob"
},
{
"name": "serialization_revision: u8",
"ordinal": 2,
"type_info": "Int64"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false
]
},
"hash": "ba96344db31b0f2155e2af53eaaeafc9b5f64061b6c9a829e2912945b6cffc82"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n UPDATE ecash_ticketbook\n SET used_tickets = used_tickets - ?\n WHERE id = ?\n AND used_tickets = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 3
},
"nullable": []
},
"hash": "bc823c54143e2dc590b91347cd089dde284b38a3a4960afed758206d03ca1cf4"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n INSERT OR IGNORE INTO coin_indices_signatures(epoch_id, serialised_signatures, serialization_revision) VALUES (?, ?, ?);\n UPDATE coin_indices_signatures\n SET\n serialised_signatures = ?,\n serialization_revision = ?\n WHERE epoch_id = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 6
},
"nullable": []
},
"hash": "bd1973696121b6128bd75ae80fab253c071e04eb853d4b0f3b21782ea57c2f68"
}
@@ -3,35 +3,27 @@
mod legacy_helpers;
use crate::{
backends::sqlite::{
get_next_unspent_ticketbook, increase_used_ticketbook_tickets, SqliteEcashTicketbookManager,
},
error::StorageError,
models::{BasicTicketbookInformation, RetrievedPendingTicketbook, RetrievedTicketbook},
persistent_storage::legacy_helpers::{
deserialise_v1_coin_index_signatures, deserialise_v1_expiration_date_signatures,
deserialise_v1_master_verification_key,
},
storage::Storage,
use crate::backends::sqlite::{
get_next_unspent_ticketbook, increase_used_ticketbook_tickets, SqliteEcashTicketbookManager,
};
use crate::error::StorageError;
use crate::models::{BasicTicketbookInformation, RetrievedPendingTicketbook, RetrievedTicketbook};
use crate::persistent_storage::legacy_helpers::{
deserialise_v1_coin_index_signatures, deserialise_v1_expiration_date_signatures,
deserialise_v1_master_verification_key,
};
use crate::storage::Storage;
use async_trait::async_trait;
use log::{debug, error};
use nym_compact_ecash::{
scheme::{
coin_indices_signatures::AnnotatedCoinIndexSignature,
expiration_date_signatures::AnnotatedExpirationDateSignature,
},
VerificationKeyAuth,
};
use nym_credentials::{
ecash::bandwidth::serialiser::{
keys::EpochVerificationKey,
signatures::{AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures},
VersionedSerialise,
},
IssuanceTicketBook, IssuedTicketBook,
use nym_compact_ecash::scheme::coin_indices_signatures::AnnotatedCoinIndexSignature;
use nym_compact_ecash::scheme::expiration_date_signatures::AnnotatedExpirationDateSignature;
use nym_compact_ecash::VerificationKeyAuth;
use nym_credentials::ecash::bandwidth::serialiser::keys::EpochVerificationKey;
use nym_credentials::ecash::bandwidth::serialiser::signatures::{
AggregatedCoinIndicesSignatures, AggregatedExpirationDateSignatures,
};
use nym_credentials::ecash::bandwidth::serialiser::VersionedSerialise;
use nym_credentials::{IssuanceTicketBook, IssuedTicketBook};
use nym_ecash_time::{ecash_today, Date, EcashTime};
use sqlx::ConnectOptions;
use std::path::Path;
@@ -55,10 +47,11 @@ impl PersistentStorage {
database_path.as_ref().as_os_str()
);
let opts = sqlx::sqlite::SqliteConnectOptions::new()
let mut opts = sqlx::sqlite::SqliteConnectOptions::new()
.filename(database_path)
.create_if_missing(true)
.disable_statement_logging();
.create_if_missing(true);
opts.disable_statement_logging();
let connection_pool = match sqlx::SqlitePool::connect_with(opts).await {
Ok(db) => db,
@@ -186,7 +179,7 @@ impl Storage for PersistentStorage {
// we don't want ticketbooks with expiration in the past
let Some(raw) =
get_next_unspent_ticketbook(&mut *tx, ticketbook_type, deadline, tickets).await?
get_next_unspent_ticketbook(&mut tx, ticketbook_type, deadline, tickets).await?
else {
// make sure to finish our tx
tx.commit().await?;
@@ -201,7 +194,7 @@ impl Storage for PersistentStorage {
))
})?;
increase_used_ticketbook_tickets(&mut *tx, raw.id, tickets).await?;
increase_used_ticketbook_tickets(&mut tx, raw.id, tickets).await?;
tx.commit().await?;
// set the number of spent tickets on the crypto object
@@ -1,32 +0,0 @@
{
"db_name": "SQLite",
"query": "\n SELECT \n id as \"id!\",\n client_address_bs58 as \"client_address_bs58!\",\n content as \"content!\" \n FROM message_store \n WHERE client_address_bs58 = ? AND id > ?\n ORDER BY id ASC\n LIMIT ?;\n ",
"describe": {
"columns": [
{
"name": "id!",
"ordinal": 0,
"type_info": "Int64"
},
{
"name": "client_address_bs58!",
"ordinal": 1,
"type_info": "Text"
},
{
"name": "content!",
"ordinal": 2,
"type_info": "Blob"
}
],
"parameters": {
"Right": 3
},
"nullable": [
false,
false,
false
]
},
"hash": "03fe56298a6d60cdd5304a2953811a533d59b4f1f0e4efecd32c09256b657e24"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "DELETE FROM ticket_verification WHERE ticket_id = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "0aaf87e0bec011910fa23aefa9a487247eb416d4203ab22b787fdcf15e47e586"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "DELETE FROM message_store WHERE id = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "10af1fe50f990be860548c7cc7ff051ab7d5cd812627a17758c0c8922593b9fd"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n DELETE FROM ticket_data\n WHERE ticket_id IN (\n SELECT ticket_id\n FROM verified_tickets\n WHERE proposal_id = ?\n )\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "23775a52dcfb001d53ae045898522a8c19a121f11bae07b80bc88e557eb2275e"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n INSERT OR IGNORE INTO wireguard_peer(public_key, preshared_key, protocol_version, endpoint, last_handshake, tx_bytes, rx_bytes, persistent_keepalive_interval, allowed_ips, client_id)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);\n\n UPDATE wireguard_peer \n SET preshared_key = ?, protocol_version = ?, endpoint = ?, last_handshake = ?, tx_bytes = ?, rx_bytes = ?, persistent_keepalive_interval = ?, allowed_ips = ?, client_id = ?\n WHERE public_key = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 20
},
"nullable": []
},
"hash": "24ce2c053db635df05d98529023a84bf91a622d4b75ad173976e0234c6380a7d"
}
@@ -1,74 +0,0 @@
{
"db_name": "SQLite",
"query": "\n SELECT *\n FROM wireguard_peer;\n ",
"describe": {
"columns": [
{
"name": "public_key",
"ordinal": 0,
"type_info": "Text"
},
{
"name": "preshared_key",
"ordinal": 1,
"type_info": "Text"
},
{
"name": "protocol_version",
"ordinal": 2,
"type_info": "Int64"
},
{
"name": "endpoint",
"ordinal": 3,
"type_info": "Text"
},
{
"name": "last_handshake",
"ordinal": 4,
"type_info": "Datetime"
},
{
"name": "tx_bytes",
"ordinal": 5,
"type_info": "Int64"
},
{
"name": "rx_bytes",
"ordinal": 6,
"type_info": "Int64"
},
{
"name": "persistent_keepalive_interval",
"ordinal": 7,
"type_info": "Int64"
},
{
"name": "allowed_ips",
"ordinal": 8,
"type_info": "Blob"
},
{
"name": "client_id",
"ordinal": 9,
"type_info": "Int64"
}
],
"parameters": {
"Right": 0
},
"nullable": [
false,
true,
true,
true,
true,
false,
false,
true,
false,
true
]
},
"hash": "2a55441d4e6134975b2c75f0b43491e9cf7bb52f41644d45c92e4b83f60b65cc"
}
@@ -1,20 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT signer_id FROM ecash_signer WHERE epoch_id = ?",
"describe": {
"columns": [
{
"name": "signer_id",
"ordinal": 0,
"type_info": "Int64"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "36b5b40e6466b67f6027257068438e4e45dd6506d806a25ce3a4c69723216fd3"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n UPDATE available_bandwidth\n SET available = available - ?\n WHERE client_id = (SELECT client_id FROM received_ticket WHERE id = ?)\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "3fa406efeffd9952af3cb044b028eb6d1770c694cf84097222c2bcf299fec680"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "DELETE FROM shared_keys WHERE client_address_bs58 = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "4642e5d93b4bb38b980d02c4cec2569ee16c78e2a71d9bab04b64314aedf4ac0"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "DELETE FROM verified_tickets WHERE proposal_id = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "4a142e21e2646dfcda32ed5dcd3f0b915bda6266a55b83c8c667fdbcfc90745b"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "UPDATE redemption_proposals SET resolved_at = ?, rejected = ? WHERE proposal_id = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 3
},
"nullable": []
},
"hash": "52406dc7b69af59d206542105d3b87114e3b9eda6dfaad180f2d154bc258d6bf"
}
@@ -1,38 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT * FROM shared_keys WHERE client_address_bs58 = ?",
"describe": {
"columns": [
{
"name": "client_id",
"ordinal": 0,
"type_info": "Int64"
},
{
"name": "client_address_bs58",
"ordinal": 1,
"type_info": "Text"
},
{
"name": "derived_aes128_ctr_blake3_hmac_keys_bs58",
"ordinal": 2,
"type_info": "Text"
},
{
"name": "derived_aes256_gcm_siv_key",
"ordinal": 3,
"type_info": "Blob"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
true,
true
]
},
"hash": "564c7da81081fab34754b76eeeedd48f3bc18842c03ef5a5c331bbee4c41c71c"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "INSERT INTO message_store(client_address_bs58, content) VALUES (?, ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "58ba6fb669847d7b82440178bc3ffd8de03c0308d0fc9cb8615a5d151e785864"
}
@@ -1,20 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT client_id FROM shared_keys WHERE client_address_bs58 = ?",
"describe": {
"columns": [
{
"name": "client_id",
"ordinal": 0,
"type_info": "Int64"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "5ee58c3050595614d550558879f54696dfcbddfb1b8575f5cc9690c4c2bffe25"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n UPDATE available_bandwidth\n SET expiration = ?\n WHERE client_id = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "61c0a61db0eed4ccbe3c623de183a0df5fbe61dff0048b3ab4b6823a7b248239"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "INSERT INTO verified_tickets (ticket_id) VALUES (?)",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "6c4a1c08a08714be34fe9bda2d2c9c7fb6a4e25272c1addfad87e26e7b16dfdc"
}
@@ -1,26 +0,0 @@
{
"db_name": "SQLite",
"query": "\n SELECT id, client_type as \"client_type: ClientType\"\n FROM clients\n WHERE id = ?\n ",
"describe": {
"columns": [
{
"name": "id",
"ordinal": 0,
"type_info": "Int64"
},
{
"name": "client_type: ClientType",
"ordinal": 1,
"type_info": "Text"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false
]
},
"hash": "72b268030ca7409c86806d6b5b253272629a3ebda7b89feacf8ed07ecf2e2c13"
}
@@ -1,26 +0,0 @@
{
"db_name": "SQLite",
"query": "\n SELECT t1.ticket_id, t1.data as \"data!\"\n FROM ticket_data as t1\n LEFT JOIN verified_tickets as t2\n ON t1.ticket_id = t2.ticket_id\n WHERE\n t2.ticket_id IS NULL\n AND\n t1.data IS NOT NULL\n ",
"describe": {
"columns": [
{
"name": "ticket_id",
"ordinal": 0,
"type_info": "Int64"
},
{
"name": "data!",
"ordinal": 1,
"type_info": "Blob"
}
],
"parameters": {
"Right": 0
},
"nullable": [
false,
true
]
},
"hash": "73e111225be2ce63d05f1a439a1fc9cc0359a960fe17a135a1d7f8975ebe38ef"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n UPDATE available_bandwidth\n SET available = available + ?\n WHERE client_id = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "76b91895b5cd8b4815f4e5b183117c16b6a36c180d9081ab2cce9992792e5a6a"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "INSERT INTO ticket_data(ticket_id, serial_number, data) VALUES (?, ?, ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 3
},
"nullable": []
},
"hash": "7cd38d342eddd578f35116cf024901f94bbf5575595e36345e1d25085a79b039"
}
@@ -1,20 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT EXISTS (SELECT 1 FROM ticket_data WHERE serial_number = ?) AS 'exists'",
"describe": {
"columns": [
{
"name": "exists",
"ordinal": 0,
"type_info": "Int"
}
],
"parameters": {
"Right": 1
},
"nullable": [
null
]
},
"hash": "7f8af0799d7ae5f751b9964e9566589bf768e7079079f584beb0c1ba16d43a5c"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "UPDATE received_ticket SET rejected = true WHERE id = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "8412b95638509f59d2daa30399ba864263e24b2ab75e0d8a2afbde75da8b6d5a"
}
@@ -1,20 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT signer_id FROM ticket_verification WHERE ticket_id = ?",
"describe": {
"columns": [
{
"name": "signer_id",
"ordinal": 0,
"type_info": "Int64"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "870e426955cf3d0e297522552a87af82979545975f9df3ac3584fd1bf56a46cd"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "UPDATE ticket_data SET data = NULL WHERE ticket_id = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "93fc72c1ee7cf5bbd1b69500ebb36928263d839ee515786cc9354cd8eac6f288"
}
@@ -1,20 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT available FROM available_bandwidth WHERE client_id = ?",
"describe": {
"columns": [
{
"name": "available",
"ordinal": 0,
"type_info": "Int64"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "9450b5f34620ec901e555f418eec6e0f489ed72d6b4f2b70ae1d905b4c46f0df"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "INSERT INTO available_bandwidth(client_id, available, expiration) VALUES (?, 0, ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "a2fef59c5d6176170920b940be39f7c98de25d36b7f6516fcc78037862aa7795"
}
@@ -1,26 +0,0 @@
{
"db_name": "SQLite",
"query": "\n SELECT t1.ticket_id, t2.serial_number\n FROM verified_tickets as t1\n JOIN ticket_data as t2\n ON t1.ticket_id = t2.ticket_id\n JOIN received_ticket as t3\n ON t1.ticket_id = t3.id\n\n ORDER BY t3.received_at ASC\n LIMIT 65535\n ",
"describe": {
"columns": [
{
"name": "ticket_id",
"ordinal": 0,
"type_info": "Int64"
},
{
"name": "serial_number",
"ordinal": 1,
"type_info": "Blob"
}
],
"parameters": {
"Right": 0
},
"nullable": [
false,
false
]
},
"hash": "af2a80cb05c0bff096e6eb830598fbb8ba0a69e0d7079e4600ff47db786e6642"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "DELETE FROM ticket_data WHERE ticket_id = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "b478ea151f9f82bb437fbaf697505c343f5eeedf602f21db6a292b174d3efe3e"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "INSERT INTO redemption_proposals (proposal_id, created_at) VALUES (?, ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "b83c2d75d90284c0f73e4ee1d46aa87273c8eb2e8e631020ed56969fbf5fa457"
}
@@ -1,26 +0,0 @@
{
"db_name": "SQLite",
"query": "\n SELECT t1.ticket_id, t2.serial_number\n FROM verified_tickets as t1\n JOIN ticket_data as t2\n ON t1.ticket_id = t2.ticket_id\n WHERE t1.proposal_id = ?\n ",
"describe": {
"columns": [
{
"name": "ticket_id",
"ordinal": 0,
"type_info": "Int64"
},
{
"name": "serial_number",
"ordinal": 1,
"type_info": "Blob"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false
]
},
"hash": "be36bdf12b8f2145cefca3111f146c71205167f1edcaef624b2f80d30bf269cc"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "INSERT INTO clients(client_type) VALUES (?)",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "c2c7ca734c87d151f7f260fe7aa1bf6c4db4fd7ee5a90fc15a94099d9b8ebb56"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n UPDATE available_bandwidth\n SET available = 0, expiration = ?\n WHERE client_id = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "cbf1d857ffc607cbaef81faac1c35f75549c0f959d9ce944d68abc524523daad"
}
@@ -1,74 +0,0 @@
{
"db_name": "SQLite",
"query": "\n SELECT * FROM wireguard_peer\n WHERE public_key = ?\n LIMIT 1\n ",
"describe": {
"columns": [
{
"name": "public_key",
"ordinal": 0,
"type_info": "Text"
},
{
"name": "preshared_key",
"ordinal": 1,
"type_info": "Text"
},
{
"name": "protocol_version",
"ordinal": 2,
"type_info": "Int64"
},
{
"name": "endpoint",
"ordinal": 3,
"type_info": "Text"
},
{
"name": "last_handshake",
"ordinal": 4,
"type_info": "Datetime"
},
{
"name": "tx_bytes",
"ordinal": 5,
"type_info": "Int64"
},
{
"name": "rx_bytes",
"ordinal": 6,
"type_info": "Int64"
},
{
"name": "persistent_keepalive_interval",
"ordinal": 7,
"type_info": "Int64"
},
{
"name": "allowed_ips",
"ordinal": 8,
"type_info": "Blob"
},
{
"name": "client_id",
"ordinal": 9,
"type_info": "Int64"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
true,
true,
true,
true,
false,
false,
true,
false,
true
]
},
"hash": "d968d8662a2327918b311d4017bf4c73f9e6f3b1be8ff81c1aebdf3791d59d4d"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n INSERT INTO ticket_verification (ticket_id, signer_id, verified_at, accepted)\n VALUES (?, ?, ?, ?)\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 4
},
"nullable": []
},
"hash": "da51030965d8f9ff0e2511ba6d6b9feecd619c043f9d70752521143de4c14959"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n INSERT OR IGNORE INTO shared_keys(client_id, client_address_bs58, derived_aes128_ctr_blake3_hmac_keys_bs58, derived_aes256_gcm_siv_key) VALUES (?, ?, ?, ?);\n\n UPDATE shared_keys\n SET\n derived_aes128_ctr_blake3_hmac_keys_bs58 = ?,\n derived_aes256_gcm_siv_key = ?\n WHERE client_address_bs58 = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 7
},
"nullable": []
},
"hash": "dd757b04743ab7e80948a60b6ee5ec36e716324498ec2178283a062d5b360464"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n DELETE FROM wireguard_peer\n WHERE public_key = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "e23f7137e1d2c38deba4653b54269b7f58d6fe9c71a7f9ee2b64f8237b7004fb"
}
@@ -1,32 +0,0 @@
{
"db_name": "SQLite",
"query": "\n SELECT \n id as \"id!\",\n client_address_bs58 as \"client_address_bs58!\",\n content as \"content!\"\n FROM message_store\n WHERE client_address_bs58 = ?\n ORDER BY id ASC\n LIMIT ?;\n ",
"describe": {
"columns": [
{
"name": "id!",
"ordinal": 0,
"type_info": "Int64"
},
{
"name": "client_address_bs58!",
"ordinal": 1,
"type_info": "Text"
},
{
"name": "content!",
"ordinal": 2,
"type_info": "Blob"
}
],
"parameters": {
"Right": 2
},
"nullable": [
false,
false,
false
]
},
"hash": "e3860c0c31ca03cc0b22ca34cef5f535a94c78d3491d44d7c8bf1b34a840839d"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n UPDATE available_bandwidth\n SET available = available - ?\n WHERE client_id = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "f02272f4f0e5a9f806532fa6e2f3323ef3edeeffdc30ce7f07608ba138d4bb02"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "INSERT INTO received_ticket (client_id, received_at) VALUES (?, ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "f2b630b29a9e85003c0457dc8a07d24996c50a306b81ad2ae0b30af6683cda0d"
}
@@ -1,20 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT proposal_id FROM redemption_proposals WHERE resolved_at IS NULL",
"describe": {
"columns": [
{
"name": "proposal_id",
"ordinal": 0,
"type_info": "Int64"
}
],
"parameters": {
"Right": 0
},
"nullable": [
false
]
},
"hash": "ff485c6b7e02423511b1fa55d5dd81d6c2f7228daf031c4621937e47804ce5b3"
}
+4 -4
View File
@@ -111,14 +111,14 @@ impl BandwidthManager {
amount,
client_id
)
.execute(&mut *tx)
.execute(&mut tx)
.await?;
let remaining = sqlx::query!(
"SELECT available FROM available_bandwidth WHERE client_id = ?",
client_id
)
.fetch_one(&mut *tx)
.fetch_one(&mut tx)
.await?
.available;
@@ -160,14 +160,14 @@ impl BandwidthManager {
amount,
client_id
)
.execute(&mut *tx)
.execute(&mut tx)
.await?;
let remaining = sqlx::query!(
"SELECT available FROM available_bandwidth WHERE client_id = ?",
client_id
)
.fetch_one(&mut *tx)
.fetch_one(&mut tx)
.await?
.available;
+4 -3
View File
@@ -286,13 +286,14 @@ impl PersistentStorage {
// TODO: we can inject here more stuff based on our gateway global config
// struct. Maybe different pool size or timeout intervals?
let opts = sqlx::sqlite::SqliteConnectOptions::new()
let mut opts = sqlx::sqlite::SqliteConnectOptions::new()
.filename(database_path)
.create_if_missing(true)
.disable_statement_logging();
.create_if_missing(true);
// TODO: do we want auto_vacuum ?
opts.disable_statement_logging();
let connection_pool = match sqlx::SqlitePool::connect_with(opts).await {
Ok(db) => db,
Err(err) => {

Some files were not shown because too many files have changed in this diff Show More