impl payment flow
This commit is contained in:
Generated
+9
@@ -6665,6 +6665,7 @@ dependencies = [
|
||||
"nym-types",
|
||||
"nym-validator-client",
|
||||
"nym-wireguard",
|
||||
"nym_compact_ecash",
|
||||
"once_cell",
|
||||
"pretty_env_logger",
|
||||
"rand 0.7.3",
|
||||
@@ -6701,6 +6702,7 @@ dependencies = [
|
||||
"nym-sphinx",
|
||||
"nym-task",
|
||||
"nym-validator-client",
|
||||
"nym_compact_ecash",
|
||||
"rand 0.7.3",
|
||||
"serde",
|
||||
"thiserror",
|
||||
@@ -6728,6 +6730,7 @@ dependencies = [
|
||||
"nym-crypto",
|
||||
"nym-pemstore",
|
||||
"nym-sphinx",
|
||||
"nym_compact_ecash",
|
||||
"rand 0.7.3",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -7761,9 +7764,15 @@ dependencies = [
|
||||
"criterion",
|
||||
>>>>>>> b6a43787b (Add bilinear equations into the zk proof; the last eq passes the tests)
|
||||
"digest 0.9.0",
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
"ff 0.10.1",
|
||||
"group 0.10.0",
|
||||
=======
|
||||
"ff 0.11.1",
|
||||
"getset",
|
||||
"group 0.11.0",
|
||||
>>>>>>> be4119370 (impl payment flow)
|
||||
"itertools 0.10.5",
|
||||
=======
|
||||
"ff 0.11.0",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::BandwidthControllerError;
|
||||
use nym_compact_ecash::scheme::{Payment, Wallet};
|
||||
use nym_compact_ecash::scheme::{EcashCredential, Wallet};
|
||||
use nym_compact_ecash::setup::setup;
|
||||
use nym_compact_ecash::{Base58, PayInfo, SecretKeyUser};
|
||||
use nym_credential_storage::error::StorageError;
|
||||
@@ -31,7 +31,7 @@ impl<C, St: Storage> BandwidthController<C, St> {
|
||||
|
||||
pub async fn prepare_ecash_credential(
|
||||
&self,
|
||||
) -> Result<(Payment, String, i64), BandwidthControllerError>
|
||||
) -> Result<(EcashCredential, String, i64), BandwidthControllerError>
|
||||
where
|
||||
C: DkgQueryClient + Sync + Send,
|
||||
<St as Storage>::StorageError: Send + Sync + 'static,
|
||||
@@ -67,7 +67,13 @@ impl<C, St: Storage> BandwidthController<C, St> {
|
||||
nb_tickets,
|
||||
)?;
|
||||
|
||||
Ok((payment, wallet.to_bs58(), ecash_credential.id))
|
||||
let credential = EcashCredential::new(
|
||||
payment, //pay_info,
|
||||
//some_l_i_guess,
|
||||
epoch_id,
|
||||
);
|
||||
|
||||
Ok((credential, wallet.to_bs58(), ecash_credential.id))
|
||||
}
|
||||
|
||||
pub async fn update_ecash_credential(
|
||||
|
||||
@@ -19,6 +19,7 @@ tokio = { version = "1.24.1", features = ["macros"] }
|
||||
# internal
|
||||
nym-bandwidth-controller = { path = "../../bandwidth-controller" }
|
||||
nym-coconut-interface = { path = "../../coconut-interface" }
|
||||
nym_compact_ecash = { path = "../../nym_offline_compact_ecash" }
|
||||
nym-credential-storage = { path = "../../credential-storage" }
|
||||
nym-crypto = { path = "../../crypto" }
|
||||
nym-gateway-requests = { path = "../../../gateway/gateway-requests" }
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::{cleanup_socket_message, try_decrypt_binary_message};
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use log::*;
|
||||
use nym_bandwidth_controller::BandwidthController;
|
||||
use nym_coconut_interface::Credential;
|
||||
use nym_compact_ecash::scheme::EcashCredential;
|
||||
use nym_credential_storage::ephemeral_storage::EphemeralStorage as EphemeralCredentialStorage;
|
||||
use nym_credential_storage::storage::Storage as CredentialStorage;
|
||||
use nym_crypto::asymmetric::identity;
|
||||
@@ -513,14 +513,14 @@ impl<C, St> GatewayClient<C, St> {
|
||||
}
|
||||
}
|
||||
|
||||
async fn claim_coconut_bandwidth(
|
||||
async fn claim_ecash_bandwidth(
|
||||
&mut self,
|
||||
credential: Credential,
|
||||
credential: EcashCredential,
|
||||
) -> Result<(), GatewayClientError> {
|
||||
let mut rng = OsRng;
|
||||
let iv = IV::new_random(&mut rng);
|
||||
|
||||
let msg = ClientControlRequest::new_enc_coconut_bandwidth_credential(
|
||||
let msg = ClientControlRequest::new_enc_ecash_credential(
|
||||
&credential,
|
||||
self.shared_key.as_ref().unwrap(),
|
||||
iv,
|
||||
@@ -567,18 +567,18 @@ impl<C, St> GatewayClient<C, St> {
|
||||
return self.try_claim_testnet_bandwidth().await;
|
||||
}
|
||||
|
||||
let (_payment, new_wallet, new_wallet_id) = self
|
||||
let (credential, new_wallet, wallet_id) = self
|
||||
.bandwidth_controller
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.prepare_ecash_credential()
|
||||
.await?;
|
||||
|
||||
//self.claim_ecash_bandwidth(payment).await?;
|
||||
self.claim_ecash_bandwidth(credential).await?;
|
||||
self.bandwidth_controller
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.update_ecash_credential(new_wallet, new_wallet_id)
|
||||
.update_ecash_credential(new_wallet, wallet_id)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -16,6 +16,7 @@ thiserror = "1.0"
|
||||
sha2 = "0.9"
|
||||
bs58 = "0.4.0"
|
||||
serde = "1.0.189"
|
||||
getset = "0.1.1"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = { version = "0.3", features = ["html_reports"] }
|
||||
|
||||
@@ -3,6 +3,8 @@ use std::cell::Cell;
|
||||
use bls12_381::{G1Projective, G2Prepared, G2Projective, Scalar};
|
||||
use group::Curve;
|
||||
|
||||
use getset::{CopyGetters, Getters};
|
||||
|
||||
use crate::error::{CompactEcashError, Result};
|
||||
use crate::proofs::proof_spend::{SpendInstance, SpendProof, SpendWitness};
|
||||
use crate::scheme::keygen::{SecretKeyUser, VerificationKeyAuth};
|
||||
@@ -608,3 +610,41 @@ impl TryFrom<&[u8]> for Payment {
|
||||
Ok(payment)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Getters, CopyGetters, Clone, PartialEq)]
|
||||
pub struct EcashCredential {
|
||||
#[getset(get = "pub")]
|
||||
payment: Payment,
|
||||
//pub pay_info : PayInfo, ?
|
||||
//pub L : u64, ?
|
||||
#[getset(get = "pub")]
|
||||
epoch_id: u64,
|
||||
}
|
||||
|
||||
impl EcashCredential {
|
||||
pub fn new(payment: Payment, epoch_id: u64) -> Self {
|
||||
EcashCredential { payment, epoch_id }
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
let mut ecash_bytes = self.payment.to_bytes();
|
||||
ecash_bytes.extend_from_slice(&self.epoch_id.to_be_bytes());
|
||||
|
||||
ecash_bytes
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8]> for EcashCredential {
|
||||
type Error = CompactEcashError;
|
||||
fn try_from(bytes: &[u8]) -> Result<Self> {
|
||||
if bytes.len() < 8 {
|
||||
return Err(CompactEcashError::Deserialization(
|
||||
"Invalid byte array for EcashCredential deserialization".to_string(),
|
||||
));
|
||||
}
|
||||
let payment_bytes = &bytes[..bytes.len() - 8];
|
||||
let payment = Payment::try_from(payment_bytes)?;
|
||||
let epoch_id = u64::from_be_bytes(bytes[bytes.len() - 8..].try_into().unwrap());
|
||||
Ok(EcashCredential { payment, epoch_id })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ nym-node = { path = "../nym-node" }
|
||||
nym-api-requests = { path = "../nym-api/nym-api-requests" }
|
||||
nym-bin-common = { path = "../common/bin-common", features = ["output_format"] }
|
||||
nym-coconut-interface = { path = "../common/coconut-interface" }
|
||||
nym_compact_ecash = { path = "../common/nym_offline_compact_ecash" }
|
||||
nym-config = { path = "../common/config" }
|
||||
nym-credentials = { path = "../common/credentials" }
|
||||
nym-crypto = { path = "../common/crypto" }
|
||||
|
||||
@@ -25,6 +25,7 @@ nym-pemstore = { path = "../../common/pemstore" }
|
||||
nym-sphinx = { path = "../../common/nymsphinx" }
|
||||
|
||||
nym-coconut-interface = { path = "../../common/coconut-interface" }
|
||||
nym_compact_ecash = {path = "../../common/nym_offline_compact_ecash" }
|
||||
nym-credentials = { path = "../../common/credentials" }
|
||||
|
||||
[dependencies.tungstenite]
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::registration::handshake::SharedKeys;
|
||||
use crate::{GatewayMacSize, PROTOCOL_VERSION};
|
||||
use log::error;
|
||||
use nym_coconut_interface::Credential;
|
||||
use nym_compact_ecash::scheme::EcashCredential;
|
||||
use nym_crypto::generic_array::typenum::Unsigned;
|
||||
use nym_crypto::hmac::recompute_keyed_hmac_and_verify_tag;
|
||||
use nym_crypto::symmetric::stream_cipher;
|
||||
@@ -137,6 +138,10 @@ pub enum ClientControlRequest {
|
||||
enc_credential: Vec<u8>,
|
||||
iv: Vec<u8>,
|
||||
},
|
||||
EcashCredential {
|
||||
enc_credential: Vec<u8>,
|
||||
iv: Vec<u8>,
|
||||
},
|
||||
ClaimFreeTestnetBandwidth,
|
||||
}
|
||||
|
||||
@@ -177,6 +182,30 @@ impl ClientControlRequest {
|
||||
Credential::from_bytes(&credential_bytes)
|
||||
.map_err(|_| GatewayRequestsError::MalformedEncryption)
|
||||
}
|
||||
|
||||
pub fn new_enc_ecash_credential(
|
||||
credential: &EcashCredential,
|
||||
shared_key: &SharedKeys,
|
||||
iv: IV,
|
||||
) -> Self {
|
||||
let serialized_credential = credential.to_bytes();
|
||||
let enc_credential = shared_key.encrypt_and_tag(&serialized_credential, Some(iv.inner()));
|
||||
|
||||
ClientControlRequest::EcashCredential {
|
||||
enc_credential,
|
||||
iv: iv.to_bytes(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_from_enc_ecash_credential(
|
||||
enc_credential: Vec<u8>,
|
||||
shared_key: &SharedKeys,
|
||||
iv: IV,
|
||||
) -> Result<EcashCredential, GatewayRequestsError> {
|
||||
let credential_bytes = shared_key.decrypt_tagged(&enc_credential, Some(iv.inner()))?;
|
||||
EcashCredential::try_from(credential_bytes.as_slice())
|
||||
.map_err(|_| GatewayRequestsError::MalformedEncryption)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ClientControlRequest> for Message {
|
||||
|
||||
@@ -6,6 +6,7 @@ use futures::{
|
||||
FutureExt, StreamExt,
|
||||
};
|
||||
use log::*;
|
||||
use nym_compact_ecash::{setup::setup, PayInfo};
|
||||
use nym_gateway_requests::{
|
||||
iv::{IVConversionError, IV},
|
||||
types::{BinaryRequest, ServerResponse},
|
||||
@@ -23,7 +24,6 @@ use std::{convert::TryFrom, process, time::Duration};
|
||||
|
||||
use crate::node::{
|
||||
client_handling::{
|
||||
bandwidth::Bandwidth,
|
||||
websocket::{
|
||||
connection_handler::{ClientDetails, FreshHandler},
|
||||
message_receiver::{
|
||||
@@ -215,7 +215,7 @@ where
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `enc_credential`: raw encrypted bandwidth credential to verify.
|
||||
/// * `enc_credential`: raw encrypted credential to verify.
|
||||
/// * `iv`: fresh iv used for the credential.
|
||||
async fn handle_bandwidth(
|
||||
&mut self,
|
||||
@@ -223,7 +223,7 @@ where
|
||||
iv: Vec<u8>,
|
||||
) -> Result<ServerResponse, RequestHandlingError> {
|
||||
let iv = IV::try_from_bytes(&iv)?;
|
||||
let credential = ClientControlRequest::try_from_enc_coconut_bandwidth_credential(
|
||||
let credential = ClientControlRequest::try_from_enc_ecash_credential(
|
||||
enc_credential,
|
||||
&self.client.shared_keys,
|
||||
iv,
|
||||
@@ -250,35 +250,37 @@ where
|
||||
let aggregated_verification_key =
|
||||
nym_credentials::obtain_aggregate_verification_key(&credential_api_clients).await?;
|
||||
|
||||
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
|
||||
let params = setup(100); //SW: TEMPORARY VALUE, Take from credential?
|
||||
let pay_info = PayInfo { info: [0u8; 32] }; //SW: TEMPORARY VALUE, Take from credential?
|
||||
|
||||
if !credential.verify(&aggregated_verification_key_converted) {
|
||||
return Err(RequestHandlingError::InvalidBandwidthCredential(
|
||||
String::from("credential failed to verify on gateway"),
|
||||
));
|
||||
}
|
||||
credential
|
||||
.payment()
|
||||
.spend_verify(¶ms, &aggregated_verification_key, &pay_info)
|
||||
.map_err(|_| {
|
||||
RequestHandlingError::InvalidBandwidthCredential(String::from(
|
||||
"credential failed to verify on gateway",
|
||||
))
|
||||
})?;
|
||||
|
||||
self.inner
|
||||
.coconut_verifier
|
||||
.release_funds(current_api_clients, &credential)
|
||||
.await?;
|
||||
// self.inner
|
||||
// .coconut_verifier
|
||||
// .release_funds(current_api_clients, &credential)
|
||||
// .await?;
|
||||
|
||||
let bandwidth = Bandwidth::from(credential);
|
||||
let bandwidth_value = bandwidth.value();
|
||||
// let bandwidth = Bandwidth::from(credential);
|
||||
// let bandwidth_value = bandwidth.value();
|
||||
|
||||
if bandwidth_value > i64::MAX as u64 {
|
||||
// note that this would have represented more than 1 exabyte,
|
||||
// which is like 125,000 worth of hard drives so I don't think we have
|
||||
// to worry about it for now...
|
||||
warn!("Somehow we received bandwidth value higher than 9223372036854775807. We don't really want to deal with this now");
|
||||
return Err(RequestHandlingError::UnsupportedBandwidthValue(
|
||||
bandwidth_value,
|
||||
));
|
||||
}
|
||||
// if bandwidth_value > i64::MAX as u64 {
|
||||
// // note that this would have represented more than 1 exabyte,
|
||||
// // which is like 125,000 worth of hard drives so I don't think we have
|
||||
// // to worry about it for now...
|
||||
// warn!("Somehow we received bandwidth value higher than 9223372036854775807. We don't really want to deal with this now");
|
||||
// return Err(RequestHandlingError::UnsupportedBandwidthValue(
|
||||
// bandwidth_value,
|
||||
// ));
|
||||
// }
|
||||
|
||||
let bandwidth_value = 500000;
|
||||
|
||||
self.increase_bandwidth(bandwidth_value as i64).await?;
|
||||
let available_total = self.get_available_bandwidth().await?;
|
||||
@@ -363,7 +365,7 @@ where
|
||||
match ClientControlRequest::try_from(raw_request) {
|
||||
Err(e) => RequestHandlingError::InvalidTextRequest(e).into_error_message(),
|
||||
Ok(request) => match request {
|
||||
ClientControlRequest::BandwidthCredential { enc_credential, iv } => self
|
||||
ClientControlRequest::EcashCredential { enc_credential, iv } => self
|
||||
.handle_bandwidth(enc_credential, iv)
|
||||
.await
|
||||
.into_ws_message(),
|
||||
|
||||
Reference in New Issue
Block a user