WIP spending ecash
This commit is contained in:
Generated
+1
@@ -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",
|
||||
|
||||
@@ -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),
|
||||
|
||||
|
||||
@@ -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(
|
||||
¶ms,
|
||||
&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(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"),
|
||||
));
|
||||
|
||||
@@ -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?;
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user