Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion common/credentials/src/ecash/bandwidth/issuance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ impl IssuanceTicketBook {
signing_request.withdrawal_request.clone(),
self.deposit_id,
request_signature,
signing_request.ecash_pub_key.clone(),
signing_request.ecash_pub_key,
signing_request.expiration_date,
signing_request.ticketbook_type,
)
Expand Down
41 changes: 37 additions & 4 deletions common/ecash-signer-check/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ use nym_validator_client::ecash::models::EcashSignerStatusResponse;
use nym_validator_client::models::{
ChainBlocksStatusResponse, ChainStatusResponse, SignerInformationResponse,
};
use nym_validator_client::nyxd::contract_traits::dkg_query_client::{
ContractVKShare, DealerDetails, Epoch,
};

mod client_check;
pub mod error;
Expand Down Expand Up @@ -48,7 +51,22 @@ pub async fn check_signers(
check_signers_with_client(&client).await
}

pub struct DkgDetails {
pub dkg_epoch: Epoch,
pub threshold: Option<u64>,
pub network_dealers: Vec<DealerDetails>,
pub submitted_shared: HashMap<u64, ContractVKShare>,
}

pub async fn check_signers_with_client<C>(client: &C) -> Result<SignersTestResult, SignerCheckError>
where
C: DkgQueryClient + Sync,
{
let dkg_details = dkg_details_with_client(client).await?;
check_known_dealers(dkg_details).await
}

pub async fn dkg_details_with_client<C>(client: &C) -> Result<DkgDetails, SignerCheckError>
where
C: DkgQueryClient + Sync,
{
Expand Down Expand Up @@ -79,16 +97,31 @@ where
.map(|share| (share.node_index, share))
.collect();

Ok(DkgDetails {
dkg_epoch,
threshold,
network_dealers: dealers,
submitted_shared: shares,
})
}

pub async fn check_known_dealers(
dkg_details: DkgDetails,
) -> Result<SignersTestResult, SignerCheckError> {
// 6. for each dealer attempt to perform the checks
let results = dealers
let results = dkg_details
.network_dealers
.into_iter()
.map(|d| {
let share = shares.get(&d.assigned_index);
check_client(d, dkg_epoch.epoch_id, share)
let share = dkg_details.submitted_shared.get(&d.assigned_index);
check_client(d, dkg_details.dkg_epoch.epoch_id, share)
})
.collect::<FuturesUnordered<_>>()
.collect::<Vec<_>>()
.await;

Ok(SignersTestResult { threshold, results })
Ok(SignersTestResult {
threshold: dkg_details.threshold,
results,
})
}
2 changes: 1 addition & 1 deletion common/gateway-requests/src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ mod tests {
.unwrap();
let blind_sig = issue(
keypair.secret_key(),
sig_req.ecash_pub_key.clone(),
sig_req.ecash_pub_key,
&sig_req.withdrawal_request,
expiration_date.ecash_unix_timestamp(),
issuance.ticketbook_type().encode(),
Expand Down
8 changes: 4 additions & 4 deletions common/nym_offline_compact_ecash/src/scheme/identify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,9 +319,9 @@ mod tests {
let sk = grp.random_scalar();
let sk_user = SecretKeyUser { sk };
let pk_user = sk_user.public_key();
public_keys.push(pk_user.clone());
public_keys.push(pk_user);
}
public_keys.push(user_keypair.public_key().clone());
public_keys.push(user_keypair.public_key());

let (req, req_info) =
withdrawal_request(user_keypair.secret_key(), expiration_date, t_type).unwrap();
Expand Down Expand Up @@ -462,9 +462,9 @@ mod tests {
let sk = grp.random_scalar();
let sk_user = SecretKeyUser { sk };
let pk_user = sk_user.public_key();
public_keys.push(pk_user.clone());
public_keys.push(pk_user);
}
public_keys.push(user_keypair.public_key().clone());
public_keys.push(user_keypair.public_key());

let (req, req_info) =
withdrawal_request(user_keypair.secret_key(), expiration_date, t_type).unwrap();
Expand Down
4 changes: 2 additions & 2 deletions common/nym_offline_compact_ecash/src/scheme/keygen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ impl Bytable for SecretKeyUser {

impl Base58 for SecretKeyUser {}

#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
#[derive(Debug, Eq, PartialEq, Clone, Copy, Serialize, Deserialize)]
pub struct PublicKeyUser {
pub(crate) pk: G1Projective,
}
Expand Down Expand Up @@ -554,7 +554,7 @@ impl KeyPairUser {
}

pub fn public_key(&self) -> PublicKeyUser {
self.public_key.clone()
self.public_key
}

pub fn to_bytes(&self) -> Vec<u8> {
Expand Down
4 changes: 2 additions & 2 deletions nym-api/src/ecash/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ impl CredentialRequest for BlindSignRequestBody {
}

fn ecash_pubkey(&self) -> PublicKeyUser {
self.ecash_pubkey.clone()
self.ecash_pubkey
}
}

Expand All @@ -60,7 +60,7 @@ pub(crate) fn blind_sign<C: CredentialRequest>(
) -> Result<BlindedSignature, EcashError> {
Ok(nym_compact_ecash::scheme::withdrawal::issue(
signing_key,
request.ecash_pubkey().clone(),
request.ecash_pubkey(),
request.withdrawal_request(),
request.expiration_date_timestamp(),
request.ticketbook_type(),
Expand Down
7 changes: 6 additions & 1 deletion nym-credential-proxy/nym-credential-proxy/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "nym-credential-proxy"
version = "0.1.7"
version = "0.1.8"
authors.workspace = true
repository.workspace = true
homepage.workspace = true
Expand Down Expand Up @@ -50,14 +50,19 @@ nym-validator-client = { path = "../../common/client-libs/validator-client" }
nym-network-defaults = { path = "../../common/network-defaults" }

nym-credential-proxy-requests = { path = "../nym-credential-proxy-requests", features = ["openapi"] }
nym-ecash-signer-check = { path = "../../common/ecash-signer-check" }

[dev-dependencies]
tempfile = { workspace = true }

[build-dependencies]
anyhow = { workspace = true }
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }

[features]
default = ["cors"]
cors = ["tower-http"]

[lints]
workspace = true
11 changes: 7 additions & 4 deletions nym-credential-proxy/nym-credential-proxy/build.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
// Copyright 2024 - Nym Technologies SA <[email protected]>
// SPDX-License-Identifier: GPL-3.0-only

use anyhow::Context;

#[tokio::main]
async fn main() {
async fn main() -> anyhow::Result<()> {
use sqlx::{Connection, SqliteConnection};
use std::env;

let out_dir = env::var("OUT_DIR").unwrap();
let out_dir = env::var("OUT_DIR")?;
let database_path = format!("{out_dir}/nym-credential-proxy-example.sqlite");

let mut conn = SqliteConnection::connect(&format!("sqlite://{database_path}?mode=rwc"))
.await
.expect("Failed to create SQLx database connection");
.context("Failed to create SQLx database connection")?;

sqlx::migrate!("./migrations")
.run(&mut conn)
.await
.expect("Failed to perform SQLx migrations");
.context("Failed to perform SQLx migrations")?;

println!("cargo:rustc-env=DATABASE_URL=sqlite://{}", &database_path);
Ok(())
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright 2025 - Nym Technologies SA <[email protected]>
* SPDX-License-Identifier: GPL-3.0-only
*/

CREATE TABLE ecash_deposit
(
-- id assigned [by the contract] to the deposit
deposit_id INTEGER PRIMARY KEY NOT NULL,

-- associated tx hash
deposit_tx_hash TEXT NOT NULL,

-- indication of when the deposit request has been created
-- (so that based on block timestamp we could potentially determine latency)
requested_on TIMESTAMP WITHOUT TIME ZONE NOT NULL,

-- the amount put in the deposit (informative, as we expect this to change in the future)
deposit_amount TEXT NOT NULL,

-- the private key generated for the purposes of the deposit (the public component has been put in the transaction)
ed25519_deposit_private_key BLOB NOT NULL
);


INSERT INTO ecash_deposit(deposit_id, deposit_tx_hash, requested_on, deposit_amount, ed25519_deposit_private_key)
SELECT deposit_id, deposit_tx_hash, requested_on, deposit_amount, ed25519_deposit_private_key
FROM ticketbook_deposit;


CREATE TABLE ecash_deposit_usage
(
deposit_id INTEGER PRIMARY KEY REFERENCES ecash_deposit (deposit_id),
ticketbooks_requested_on TIMESTAMP WITHOUT TIME ZONE NOT NULL,
client_pubkey BLOB NOT NULL,
request_uuid TEXT UNIQUE NOT NULL,

-- this has to be improved later on to resume issuance or something, but for now it's fine
ticketbook_request_error TEXT
);

INSERT INTO ecash_deposit_usage(deposit_id, ticketbooks_requested_on, client_pubkey, request_uuid)
SELECT deposit_id, 0, client_pubkey, request_uuid
FROM ticketbook_deposit;


CREATE TABLE partial_blinded_wallet_new
(
corresponding_deposit INTEGER NOT NULL REFERENCES ecash_deposit_usage (deposit_id),
epoch_id INTEGER NOT NULL,
expiration_date DATE NOT NULL,
node_id INTEGER NOT NULL,
created TIMESTAMP WITHOUT TIME ZONE NOT NULL,
blinded_signature BLOB NOT NULL
);

CREATE TABLE partial_blinded_wallet_failure_new
(
corresponding_deposit INTEGER NOT NULL REFERENCES ecash_deposit_usage (deposit_id),
epoch_id INTEGER NOT NULL,
expiration_date DATE NOT NULL,
node_id INTEGER NOT NULL,
created TIMESTAMP WITHOUT TIME ZONE NOT NULL,
failure_message TEXT NOT NULL
);

INSERT INTO partial_blinded_wallet_new
SELECT *
FROM partial_blinded_wallet;
INSERT INTO partial_blinded_wallet_failure_new
SELECT *
FROM partial_blinded_wallet_failure;

DROP TABLE partial_blinded_wallet;
DROP TABLE partial_blinded_wallet_failure;
DROP TABLE ticketbook_deposit;

ALTER TABLE partial_blinded_wallet_new
RENAME TO partial_blinded_wallet;
ALTER TABLE partial_blinded_wallet_failure_new
RENAME TO partial_blinded_wallet_failure;
23 changes: 19 additions & 4 deletions nym-credential-proxy/nym-credential-proxy/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use std::fs::create_dir_all;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::path::PathBuf;
use std::sync::OnceLock;
use std::time::Duration;
use tracing::info;

fn pretty_build_info_static() -> &'static str {
Expand Down Expand Up @@ -64,6 +65,23 @@ pub struct Cli {
)]
pub(crate) max_concurrent_deposits: usize,

/// Specify the size of the deposits buffer the credential proxy should have available at any time
/// (default: 256)
#[clap(
long,
env = "NYM_CREDENTIAL_PROXY_DEPOSITS_BUFFER",
default_value_t = 256
)]
pub(crate) deposits_buffer_size: usize,

#[clap(
long,
env = "NYM_CREDENTIAL_PROXY_QUORUM_CHECK_INTERVAL",
default_value = "5m",
value_parser = humantime::parse_duration
)]
pub(crate) quorum_check_interval: Duration,

#[clap(long, env = "NYM_CREDENTIAL_PROXY_PERSISTENT_STORAGE_STORAGE")]
pub(crate) persistent_storage_path: Option<PathBuf>,
}
Expand All @@ -90,10 +108,7 @@ impl Cli {
create_dir_all(parent).unwrap();
}

info!(
"setting the storage path path to {}",
default_path.display()
);
info!("setting the storage path to {}", default_path.display());

default_path
})
Expand Down
Loading
Loading