credentials storage on gateway and api
This commit is contained in:
@@ -34,6 +34,9 @@ pub enum CompactEcashError {
|
||||
#[error("Could not decode base 58 string - {0}")]
|
||||
MalformedString(#[from] bs58::decode::Error),
|
||||
|
||||
#[error("Payment did not verify")]
|
||||
PaymentVerification,
|
||||
|
||||
#[error(
|
||||
"Deserailization error, expected at least {} bytes, got {}",
|
||||
min,
|
||||
|
||||
@@ -22,4 +22,10 @@ CREATE TABLE available_bandwidth
|
||||
available INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX `message_store_index` ON `message_store` (`client_address_bs58`, `content`);
|
||||
CREATE INDEX `message_store_index` ON `message_store` (`client_address_bs58`, `content`);
|
||||
|
||||
CREATE TABLE credentials
|
||||
(
|
||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
credentials TEXT NOT NULL
|
||||
);
|
||||
@@ -266,11 +266,14 @@ where
|
||||
))
|
||||
})?;
|
||||
|
||||
//SW PUT that in a new threads, ensuring it eventually gets sent
|
||||
self.inner
|
||||
.ecash_verifier
|
||||
.post_and_store_credential(current_api_clients, credential)
|
||||
.post_credential(current_api_clients, credential.clone())
|
||||
.await?;
|
||||
|
||||
self.inner.storage.insert_credential(credential).await?;
|
||||
|
||||
let bandwidth_value = 500000;
|
||||
|
||||
self.increase_bandwidth(bandwidth_value as i64).await?;
|
||||
|
||||
@@ -24,17 +24,11 @@ const MAX_FEEGRANT_UNYM: u128 = 10000;
|
||||
|
||||
pub(crate) struct EcashVerifier {
|
||||
nyxd_client: DirectSigningHttpRpcNyxdClient,
|
||||
mix_denom_base: String,
|
||||
}
|
||||
|
||||
impl EcashVerifier {
|
||||
pub fn new(nyxd_client: DirectSigningHttpRpcNyxdClient) -> Self {
|
||||
let mix_denom_base = nyxd_client.current_chain_details().mix_denom.base.clone();
|
||||
|
||||
EcashVerifier {
|
||||
nyxd_client,
|
||||
mix_denom_base,
|
||||
}
|
||||
EcashVerifier { nyxd_client }
|
||||
}
|
||||
|
||||
pub async fn all_current_ecash_api_clients(
|
||||
@@ -60,7 +54,7 @@ impl EcashVerifier {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn post_and_store_credential(
|
||||
pub async fn post_credential(
|
||||
&self,
|
||||
api_clients: Vec<CoconutApiClient>,
|
||||
credential: EcashCredential,
|
||||
@@ -72,28 +66,22 @@ impl EcashVerifier {
|
||||
);
|
||||
|
||||
for client in api_clients {
|
||||
let ret = client.api_client.verify_bandwidth_credential(&req).await; //SW PUT that in a new threads, ensuring it eventually gets sent
|
||||
warn!(
|
||||
"Return from {} : {:?}",
|
||||
client.api_client.nym_api.current_url(),
|
||||
ret
|
||||
);
|
||||
// match ret {
|
||||
// Ok(res) => {
|
||||
// if !res.verification_result {
|
||||
// debug!(
|
||||
// "Validator {} didn't accept the credential.",
|
||||
// client.api_client.nym_api.current_url()
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// Err(e) => {
|
||||
// warn!("Validator {} could not be reached. There might be a problem with the coconut endpoint - {:?}", client.api_client.nym_api.current_url(), e);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
let ret = client.api_client.verify_bandwidth_credential(&req).await;
|
||||
|
||||
//store credential
|
||||
match ret {
|
||||
Ok(res) => {
|
||||
if !res.verification_result {
|
||||
debug!(
|
||||
"Validator {} didn't accept the credential.",
|
||||
client.api_client.nym_api.current_url()
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Validator {} could not be reached. There might be a problem with the coconut endpoint - {:?}", client.api_client.nym_api.current_url(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct CredentialManager {
|
||||
connection_pool: sqlx::SqlitePool,
|
||||
}
|
||||
|
||||
impl CredentialManager {
|
||||
/// Creates new instance of the `CredentialManager` with the provided sqlite connection pool.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `connection_pool`: database connection pool to use.
|
||||
pub(crate) fn new(connection_pool: sqlx::SqlitePool) -> Self {
|
||||
CredentialManager { connection_pool }
|
||||
}
|
||||
|
||||
/// Inserts provided credential into the database.
|
||||
/// If the credential previously existed for the provided client, they are overwritten with the new data.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `credential`: base58 representation of an ecash credential
|
||||
pub(crate) async fn insert_credential(&self, credential: String) -> Result<(), sqlx::Error> {
|
||||
sqlx::query!(
|
||||
"INSERT OR REPLACE INTO credentials(credentials) VALUES (?)",
|
||||
credential
|
||||
)
|
||||
.execute(&self.connection_pool)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -2,18 +2,22 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::node::storage::bandwidth::BandwidthManager;
|
||||
use crate::node::storage::credential::CredentialManager;
|
||||
use crate::node::storage::error::StorageError;
|
||||
use crate::node::storage::inboxes::InboxManager;
|
||||
use crate::node::storage::models::{PersistedSharedKeys, StoredMessage};
|
||||
use crate::node::storage::shared_keys::SharedKeysManager;
|
||||
use async_trait::async_trait;
|
||||
use log::{debug, error};
|
||||
use nym_compact_ecash::scheme::EcashCredential;
|
||||
use nym_compact_ecash::Base58;
|
||||
use nym_gateway_requests::registration::handshake::SharedKeys;
|
||||
use nym_sphinx::DestinationAddressBytes;
|
||||
use sqlx::ConnectOptions;
|
||||
use std::path::Path;
|
||||
|
||||
mod bandwidth;
|
||||
mod credential;
|
||||
pub(crate) mod error;
|
||||
mod inboxes;
|
||||
mod models;
|
||||
@@ -134,6 +138,13 @@ pub(crate) trait Storage: Send + Sync {
|
||||
client_address: DestinationAddressBytes,
|
||||
amount: i64,
|
||||
) -> Result<(), StorageError>;
|
||||
|
||||
/// Stored the accepted credential
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `credential`: credential to store
|
||||
async fn insert_credential(&self, credential: EcashCredential) -> Result<(), StorageError>;
|
||||
}
|
||||
|
||||
// note that clone here is fine as upon cloning the same underlying pool will be used
|
||||
@@ -142,6 +153,7 @@ pub(crate) struct PersistentStorage {
|
||||
shared_key_manager: SharedKeysManager,
|
||||
inbox_manager: InboxManager,
|
||||
bandwidth_manager: BandwidthManager,
|
||||
credential_manager: CredentialManager,
|
||||
}
|
||||
|
||||
impl PersistentStorage {
|
||||
@@ -187,7 +199,8 @@ impl PersistentStorage {
|
||||
Ok(PersistentStorage {
|
||||
shared_key_manager: SharedKeysManager::new(connection_pool.clone()),
|
||||
inbox_manager: InboxManager::new(connection_pool.clone(), message_retrieval_limit),
|
||||
bandwidth_manager: BandwidthManager::new(connection_pool),
|
||||
bandwidth_manager: BandwidthManager::new(connection_pool.clone()),
|
||||
credential_manager: CredentialManager::new(connection_pool),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -304,6 +317,13 @@ impl Storage for PersistentStorage {
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn insert_credential(&self, credential: EcashCredential) -> Result<(), StorageError> {
|
||||
self.credential_manager
|
||||
.insert_credential(credential.to_bs58())
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// In-memory implementation of `Storage`. The intention is primarily in testing environments.
|
||||
|
||||
@@ -18,3 +18,7 @@ pub(crate) struct PersistedBandwidth {
|
||||
pub(crate) client_address_bs58: String,
|
||||
pub(crate) available: i64,
|
||||
}
|
||||
|
||||
pub(crate) struct Credentials {
|
||||
pub(crate) credential: String,
|
||||
}
|
||||
|
||||
@@ -76,6 +76,14 @@ create table gateway_ipv6_status
|
||||
FOREIGN KEY (gateway_details_id) REFERENCES gateway_details (id)
|
||||
);
|
||||
|
||||
create table credentials
|
||||
(
|
||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
credential TEXT NOT NULL,
|
||||
gateway_address TEXT NOT NULL
|
||||
|
||||
);
|
||||
|
||||
-- indices for faster lookups
|
||||
CREATE
|
||||
INDEX `mixnode_ipv4_status_index` ON `mixnode_ipv4_status` (`mixnode_details_id`, `timestamp` desc);
|
||||
|
||||
@@ -18,8 +18,10 @@ use nym_coconut_bandwidth_contract_common::spend_credential::{
|
||||
};
|
||||
use nym_coconut_dkg_common::types::EpochId;
|
||||
|
||||
use nym_compact_ecash::error::CompactEcashError;
|
||||
use nym_compact_ecash::scheme::keygen::{KeyPairAuth, SecretKeyAuth};
|
||||
use nym_compact_ecash::scheme::withdrawal::WithdrawalRequest;
|
||||
use nym_compact_ecash::scheme::EcashCredential;
|
||||
use nym_compact_ecash::setup::GroupParameters;
|
||||
use nym_compact_ecash::utils::BlindedSignature;
|
||||
use nym_compact_ecash::{PublicKeyUser, VerificationKeyAuth};
|
||||
@@ -31,7 +33,7 @@ use nym_crypto::asymmetric::encryption;
|
||||
use nym_crypto::shared_key::new_ephemeral_shared_key;
|
||||
use nym_crypto::symmetric::stream_cipher;
|
||||
use nym_validator_client::nym_api::routes::{BANDWIDTH, COCONUT_ROUTES};
|
||||
use nym_validator_client::nyxd::{Coin, Fee};
|
||||
use nym_validator_client::nyxd::{AccountId, Coin, Fee};
|
||||
use rand_07::rngs::OsRng;
|
||||
use rocket::fairing::AdHoc;
|
||||
use rocket::serde::json::Json;
|
||||
@@ -143,6 +145,17 @@ impl State {
|
||||
.aggregated_verification_key(epoch_id)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn store_credential(
|
||||
&self,
|
||||
credential: &EcashCredential,
|
||||
gateway_addr: &AccountId,
|
||||
) -> Result<()> {
|
||||
self.storage
|
||||
.insert_credential(credential, gateway_addr)
|
||||
.await
|
||||
.map_err(|err| err.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Getters, CopyGetters, Debug)]
|
||||
@@ -250,15 +263,23 @@ pub async fn verify_bandwidth_credential(
|
||||
.verification_key(*verify_credential_body.credential().epoch_id())
|
||||
.await?;
|
||||
|
||||
if let Err(err) = verify_credential_body.credential().payment().spend_verify(
|
||||
if let Err(_) = verify_credential_body.credential().payment().spend_verify(
|
||||
verify_credential_body.credential().params(),
|
||||
&verification_key,
|
||||
verify_credential_body.credential().pay_info(),
|
||||
) {
|
||||
return Err(CoconutError::CompactEcashInternalError(err));
|
||||
return Err(CoconutError::CompactEcashInternalError(
|
||||
CompactEcashError::PaymentVerification,
|
||||
));
|
||||
}
|
||||
|
||||
//store credential
|
||||
state
|
||||
.store_credential(
|
||||
verify_credential_body.credential(),
|
||||
verify_credential_body.gateway_cosmos_addr(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(Json(VerifyCredentialResponse::new(true)))
|
||||
}
|
||||
|
||||
@@ -1013,4 +1013,25 @@ impl StorageManager {
|
||||
|
||||
Ok(blinded_signature_response)
|
||||
}
|
||||
|
||||
/// Creates new credential entry for a given gateway addr.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `credential`: base58 repr of a credential.
|
||||
/// * `gateway_addr`: cosmos address of the gateway
|
||||
pub(crate) async fn insert_credential(
|
||||
&self,
|
||||
credential: String,
|
||||
gateway_addr: String,
|
||||
) -> Result<(), sqlx::Error> {
|
||||
sqlx::query!(
|
||||
"INSERT INTO credentials(credential, gateway_address) VALUES (?, ?)",
|
||||
credential,
|
||||
gateway_addr
|
||||
)
|
||||
.execute(&self.connection_pool)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,10 @@ use crate::node_status_api::models::{
|
||||
use crate::node_status_api::{ONE_DAY, ONE_HOUR};
|
||||
use crate::storage::manager::StorageManager;
|
||||
use crate::storage::models::{NodeStatus, TestingRoute};
|
||||
use nym_compact_ecash::scheme::EcashCredential;
|
||||
use nym_compact_ecash::Base58;
|
||||
use nym_mixnet_contract_common::MixId;
|
||||
use nym_validator_client::nyxd::AccountId;
|
||||
use rocket::fairing::AdHoc;
|
||||
use sqlx::ConnectOptions;
|
||||
use std::path::Path;
|
||||
@@ -737,4 +740,15 @@ impl NymApiStorage {
|
||||
.await
|
||||
.map_err(|err| err.into())
|
||||
}
|
||||
|
||||
pub(crate) async fn insert_credential(
|
||||
&self,
|
||||
credential: &EcashCredential,
|
||||
gateway_addr: &AccountId,
|
||||
) -> Result<(), NymApiStorageError> {
|
||||
self.manager
|
||||
.insert_credential(credential.to_bs58(), gateway_addr.to_string())
|
||||
.await
|
||||
.map_err(|err| err.into())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user