WIP spending ecash

This commit is contained in:
Simon Wicky
2023-10-23 11:27:06 +02:00
committed by durch
parent 5a831b6482
commit e41796b157
10 changed files with 92 additions and 46 deletions
Generated
+1
View File
@@ -7658,6 +7658,7 @@ dependencies = [
"nym-network-defaults",
"nym-service-provider-directory-common",
"nym-vesting-contract-common",
"nym_compact_ecash",
"openssl",
"prost 0.12.1",
"reqwest",
+4
View File
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
use nym_coconut_interface::CoconutError;
use nym_compact_ecash::error::CompactEcashError;
use nym_credential_storage::error::StorageError;
use nym_credentials::error::Error as CredentialsError;
use nym_crypto::asymmetric::encryption::KeyRecoveryError;
@@ -28,6 +29,9 @@ pub enum BandwidthControllerError {
#[error("Coconut error - {0}")]
CoconutError(#[from] CoconutError),
#[error("Ecash error - {0}")]
EcashError(#[from] CompactEcashError),
#[error("Validator client error - {0}")]
ValidatorError(#[from] ValidatorClientError),
+37 -33
View File
@@ -2,17 +2,15 @@
// SPDX-License-Identifier: Apache-2.0
use crate::error::BandwidthControllerError;
use nym_compact_ecash::scheme::{Payment, Wallet};
use nym_compact_ecash::setup::{setup, GroupParameters};
use nym_compact_ecash::{generate_keypair_user, Base58, PayInfo};
use nym_credential_storage::error::StorageError;
use nym_credential_storage::storage::Storage;
use nym_credentials::obtain_aggregate_verification_key;
use nym_validator_client::coconut::all_coconut_api_clients;
use nym_validator_client::nyxd::contract_traits::DkgQueryClient;
use std::str::FromStr;
use {
nym_coconut_interface::Base58,
nym_credentials::coconut::{
bandwidth::prepare_for_spending, utils::obtain_aggregate_verification_key,
},
};
pub mod acquire;
pub mod error;
@@ -31,57 +29,63 @@ impl<C, St: Storage> BandwidthController<C, St> {
&self.storage
}
pub async fn prepare_coconut_credential(
pub async fn prepare_ecash_credential(
&self,
) -> Result<(nym_coconut_interface::Credential, i64), BandwidthControllerError>
) -> Result<(Payment, String, i64), BandwidthControllerError>
where
C: DkgQueryClient + Sync + Send,
<St as Storage>::StorageError: Send + Sync + 'static,
{
let bandwidth_credential = self
let ecash_credential = self
.storage
.get_next_coconut_credential()
.get_next_ecash_credential()
.await
.map_err(|err| BandwidthControllerError::CredentialStorageError(Box::new(err)))?;
let voucher_value = u64::from_str(&bandwidth_credential.voucher_value)
let voucher_value = u64::from_str(&ecash_credential.voucher_value)
.map_err(|_| StorageError::InconsistentData)?;
let voucher_info = bandwidth_credential.voucher_info.clone();
let serial_number =
nym_coconut_interface::Attribute::try_from_bs58(bandwidth_credential.serial_number)?;
let binding_number =
nym_coconut_interface::Attribute::try_from_bs58(bandwidth_credential.binding_number)?;
let signature =
nym_coconut_interface::Signature::try_from_bs58(bandwidth_credential.signature)?;
let epoch_id = u64::from_str(&bandwidth_credential.epoch_id)
let voucher_info = ecash_credential.voucher_info.clone();
let wallet = Wallet::try_from_bs58(ecash_credential.wallet)?;
let epoch_id = u64::from_str(&ecash_credential.epoch_id)
.map_err(|_| StorageError::InconsistentData)?;
let coconut_api_clients = all_coconut_api_clients(&self.client, epoch_id).await?;
let verification_key = obtain_aggregate_verification_key(&coconut_api_clients).await?;
let some_L_I_guess = 100; //SW: TEMPORARY VALUE
let params = setup(some_L_I_guess);
let sk_user = generate_keypair_user(&GroupParameters::new()?).secret_key(); //SW : TODO Retreive key fro mcredential storage
let pay_info = PayInfo { info: [0u8; 32] }; //SW: TEMPORARY VALUE. Waiting for actual computation
let nb_tickets = 1u64; //SW: TEMPORARY VALUE, what should we put there?
// the below would only be executed once we know where we want to spend it (i.e. which gateway and stuff)
Ok((
prepare_for_spending(
voucher_value,
voucher_info,
serial_number,
binding_number,
epoch_id,
&signature,
&verification_key,
)?,
bandwidth_credential.id,
))
let (payment, _) = wallet.spend(
&params,
&verification_key,
&sk_user,
&pay_info,
false,
nb_tickets,
)?;
//SW : TODO Store new wallet
Ok((payment, wallet.to_bs58(), ecash_credential.id))
}
pub async fn consume_credential(&self, id: i64) -> Result<(), BandwidthControllerError>
pub async fn update_ecash_credential(
&self,
wallet: String,
id: i64,
) -> Result<(), BandwidthControllerError>
where
<St as Storage>::StorageError: Send + Sync + 'static,
{
// JS: shouldn't we send some contract/validator/gateway message here to actually, you know,
// consume it?
self.storage
.consume_coconut_credential(id)
.update_ecash_credential(wallet, id)
.await
.map_err(|err| BandwidthControllerError::CredentialStorageError(Box::new(err)))
}
@@ -567,18 +567,18 @@ impl<C, St> GatewayClient<C, St> {
return self.try_claim_testnet_bandwidth().await;
}
let (credential, credential_id) = self
let (payment, new_wallet, new_wallet_id) = self
.bandwidth_controller
.as_ref()
.unwrap()
.prepare_coconut_credential()
.prepare_ecash_credential()
.await?;
self.claim_coconut_bandwidth(credential).await?;
//self.claim_ecash_bandwidth(payment).await?;
self.bandwidth_controller
.as_ref()
.unwrap()
.consume_credential(credential_id)
.update_ecash_credential(new_wallet, new_wallet_id)
.await?;
Ok(())
@@ -91,4 +91,12 @@ impl Storage for EphemeralStorage {
Ok(())
}
async fn update_ecash_credential(&self, wallet: String, id: i64) -> Result<(), StorageError> {
// self.coconut_credential_manager
// .update_ecash_credential(wallet, id)
// .await;
//S W: TBD
Ok(())
}
}
@@ -122,4 +122,11 @@ impl Storage for PersistentStorage {
Ok(())
}
async fn update_ecash_credential(&self, release: String, id: i64) -> Result<(), StorageError> {
// self.coconut_credential_manager
//// .await?;
/// SW: TBD
Ok(())
}
}
+13
View File
@@ -57,4 +57,17 @@ pub trait Storage: Send + Sync {
///
/// * `id`: Id of the credential to be consumed.
async fn consume_coconut_credential(&self, id: i64) -> Result<(), Self::StorageError>;
/// Update in the database the specified credential.
///
/// # Arguments
///
/// * `wallet` : New Ecash wallet credential
/// * `id`: Id of the credential to be consumed.
///
async fn update_ecash_credential(
&self,
wallet: String,
id: i64,
) -> Result<(), Self::StorageError>;
}
@@ -250,7 +250,13 @@ where
let aggregated_verification_key =
nym_credentials::obtain_aggregate_verification_key(&credential_api_clients).await?;
if !credential.verify(&aggregated_verification_key) {
let aggregated_verification_key_converted =
nym_coconut_interface::VerificationKey::try_from(
aggregated_verification_key.to_bytes().as_slice(),
)
.expect("converstion should not fail"); //SW : TEMPORARY workaround for type conversion
if !credential.verify(&aggregated_verification_key_converted) {
return Err(RequestHandlingError::InvalidBandwidthCredential(
String::from("credential failed to verify on gateway"),
));
+3 -3
View File
@@ -4,14 +4,14 @@
use crate::coconut::error::Result;
use crate::nyxd;
use nym_coconut_dkg_common::types::EpochId;
use nym_coconut_interface::VerificationKey;
use nym_compact_ecash::VerificationKeyAuth;
use nym_credentials::coconut::utils::obtain_aggregate_verification_key;
use nym_validator_client::coconut::all_coconut_api_clients;
use std::ops::Deref;
#[async_trait]
pub trait APICommunicationChannel {
async fn aggregated_verification_key(&self, epoch_id: EpochId) -> Result<VerificationKey>;
async fn aggregated_verification_key(&self, epoch_id: EpochId) -> Result<VerificationKeyAuth>;
}
pub(crate) struct QueryCommunicationChannel {
@@ -26,7 +26,7 @@ impl QueryCommunicationChannel {
#[async_trait]
impl APICommunicationChannel for QueryCommunicationChannel {
async fn aggregated_verification_key(&self, epoch_id: EpochId) -> Result<VerificationKey> {
async fn aggregated_verification_key(&self, epoch_id: EpochId) -> Result<VerificationKeyAuth> {
let client = self.nyxd_client.0.read().await;
let coconut_api_clients = all_coconut_api_clients(client.deref(), epoch_id).await?;
let vk = obtain_aggregate_verification_key(&coconut_api_clients).await?;
+8 -5
View File
@@ -12,6 +12,7 @@ use keypair::KeyPair;
use nym_api_requests::coconut::{
BlindSignRequestBody, BlindedSignatureResponse, VerifyCredentialBody, VerifyCredentialResponse,
};
use nym_coconut::VerificationKey;
use nym_coconut_bandwidth_contract_common::spend_credential::{
funds_from_cosmos_msgs, SpendCredentialStatus,
};
@@ -137,10 +138,7 @@ impl State {
}
}
pub async fn verification_key(
&self,
epoch_id: EpochId,
) -> Result<nym_coconut_interface::VerificationKey> {
pub async fn verification_key(&self, epoch_id: EpochId) -> Result<VerificationKeyAuth> {
self.comm_channel
.aggregated_verification_key(epoch_id)
.await
@@ -281,9 +279,14 @@ pub async fn verify_bandwidth_credential(
let verification_key = state
.verification_key(*verify_credential_body.credential().epoch_id())
.await?;
let verification_key_converted =
VerificationKey::try_from(verification_key.to_bytes().as_slice())
.expect("converstion should not fail"); //SW : TEMPORARY workaround for type conversion
let mut vote_yes = verify_credential_body
.credential()
.verify(&verification_key);
.verify(&verification_key_converted);
vote_yes &= Coin::from(proposed_release_funds)
== Coin::new(