impl payment flow

This commit is contained in:
Simon Wicky
2023-10-24 10:34:51 +02:00
committed by durch
parent c1c58a7476
commit 74536467b6
10 changed files with 129 additions and 39 deletions
Generated
+9
View File
@@ -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",
+9 -3
View File
@@ -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 })
}
}
+1
View File
@@ -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" }
+1
View File
@@ -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]
+29
View File
@@ -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(&params, &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(),