online mode on gateway

This commit is contained in:
Simon Wicky
2023-11-23 09:25:17 +01:00
committed by durch
parent e0f36537db
commit 8093932c7b
7 changed files with 144 additions and 12 deletions
@@ -671,6 +671,18 @@ impl EcashCredential {
bytes
}
pub fn value(&self) -> u64 {
todo!() //SW todo
}
pub fn blinded_serial_number(&self) -> String {
todo!() //SW todo
}
pub fn has_blinded_serial_number(&self, _blinded_serial_number_bs58: &str) -> Result<bool> {
todo!() //SW todo
}
}
impl TryFrom<&[u8]> for EcashCredential {
@@ -66,6 +66,12 @@ pub(crate) enum RequestHandlingError {
#[error("Not enough nym API endpoints provided. Needed {needed}, received {received}")]
NotEnoughNymAPIs { received: usize, needed: usize },
#[error("There was a problem with the proposal id: {reason}")]
ProposalIdError { reason: String },
#[error("Compact ecash error - {0}")]
CompactEcashError(#[from] nym_compact_ecash::error::CompactEcashError),
#[error("Coconut interface error - {0}")]
CoconutInterfaceError(#[from] nym_coconut_interface::error::CoconutInterfaceError),
@@ -251,11 +257,18 @@ where
.check_payment(&credential, &aggregated_verification_key)
.await?;
self.inner
.ecash_verifier
.post_credential(current_api_clients, credential.clone())?;
if self.inner.offline_credential_verification {
self.inner
.ecash_verifier
.post_credential(current_api_clients, credential.clone())?;
self.inner.storage.insert_credential(credential).await?;
self.inner.storage.insert_credential(credential).await?;
} else {
self.inner
.ecash_verifier
.release_funds(current_api_clients, &credential)
.await?;
}
let bandwidth_value = 100000000; //SW MAKE A GLOBAL PARAMETER
@@ -7,25 +7,36 @@ use super::authenticated::RequestHandlingError;
use chrono::Utc;
use futures::channel::mpsc::{self, UnboundedReceiver, UnboundedSender};
use futures::StreamExt;
use nym_api_requests::coconut::VerifyCredentialBody;
use log::*;
use nym_api_requests::coconut::OfflineVerifyCredentialBody;
use nym_compact_ecash::scheme::EcashCredential;
use nym_compact_ecash::setup::Parameters;
use nym_compact_ecash::{PayInfo, VerificationKeyAuth};
use nym_validator_client::coconut::all_ecash_api_clients;
use nym_validator_client::nyxd::AccountId;
use nym_validator_client::nyxd::{AccountId, Coin, Fee};
use nym_validator_client::{
nyxd::contract_traits::DkgQueryClient, CoconutApiClient, DirectSigningHttpRpcNyxdClient,
NymApiClient,
nyxd::{
contract_traits::{
CoconutBandwidthSigningClient, DkgQueryClient, MultisigQueryClient,
MultisigSigningClient,
},
cosmwasm_client::logs::{find_attribute, BANDWIDTH_PROPOSAL_ID},
},
CoconutApiClient, DirectSigningHttpRpcNyxdClient, NymApiClient,
};
use std::sync::Arc;
use std::sync::Mutex;
use std::time::SystemTime;
use tokio::time::{interval, Duration};
const TIME_RANGE_SEC: i64 = 30;
const CRED_SENDING_INTERVAL: u64 = 300;
const ONE_HOUR_SEC: u64 = 3600;
const MAX_FEEGRANT_UNYM: u128 = 10000;
pub(crate) struct EcashVerifier {
nyxd_client: DirectSigningHttpRpcNyxdClient,
mix_denom_base: String,
ecash_parameters: Parameters,
pk_bytes: [u8; 32], //bytes represenation of a pub key representing the verifier
pay_infos: Arc<Mutex<Vec<PayInfo>>>,
@@ -39,13 +50,19 @@ impl EcashVerifier {
pk_bytes: [u8; 32],
shutdown: nym_task::TaskClient,
storage: St,
offline_verification: bool,
) -> Self {
let mix_denom_base = nyxd_client.current_chain_details().mix_denom.base.clone();
let (cred_sender, cred_receiver) = mpsc::unbounded();
let cs = CredentialSender::new(cred_receiver, storage);
cs.start(shutdown);
//SW do not initialize unused elements
if offline_verification {
let cs = CredentialSender::new(cred_receiver, storage);
cs.start(shutdown);
}
EcashVerifier {
nyxd_client,
mix_denom_base,
ecash_parameters,
pk_bytes,
pay_infos: Arc::new(Mutex::new(Vec::new())),
@@ -199,6 +216,87 @@ impl EcashVerifier {
}
Ok(())
}
pub async fn release_funds(
&self,
api_clients: Vec<CoconutApiClient>,
credential: &EcashCredential,
) -> Result<(), RequestHandlingError> {
// Use a custom multiplier for revoke, as the default one (1.3)
// isn't enough
let revoke_fee = Some(Fee::Auto(Some(1.5)));
let res = self
.nyxd_client
.spend_credential(
Coin::new(
credential.value().into(), //SW THIS WILL BE A FIXED VALUE?
self.mix_denom_base.clone(),
),
credential.blinded_serial_number(), //SW what will this be?
self.nyxd_client.address().to_string(),
None,
)
.await?;
let proposal_id = find_attribute(&res.logs, "wasm", BANDWIDTH_PROPOSAL_ID)
.ok_or(RequestHandlingError::ProposalIdError {
reason: String::from("proposal id not found"),
})?
.value
.parse::<u64>()
.map_err(|_| RequestHandlingError::ProposalIdError {
reason: String::from("proposal id could not be parsed to u64"),
})?;
let proposal = self.nyxd_client.query_proposal(proposal_id).await?;
if !credential.has_blinded_serial_number(&proposal.description)? {
//SW serial number issue
return Err(RequestHandlingError::ProposalIdError {
reason: String::from("proposal has different serial number"),
});
}
let req = nym_api_requests::coconut::OnlineVerifyCredentialBody::new(
credential.clone(),
proposal_id,
self.nyxd_client.address(),
);
for client in api_clients {
self.nyxd_client
.grant_allowance(
&client.cosmos_address,
vec![Coin::new(MAX_FEEGRANT_UNYM, self.mix_denom_base.clone())],
SystemTime::now().checked_add(Duration::from_secs(ONE_HOUR_SEC)),
// It would be nice to be able to filter deeper, but for now only the msg type filter is avaialable
vec![String::from("/cosmwasm.wasm.v1.MsgExecuteContract")],
"Create allowance to vote the release of funds".to_string(),
None,
)
.await?;
let ret = client.api_client.verify_online_credential(&req).await;
self.nyxd_client
.revoke_allowance(
&client.cosmos_address,
"Cleanup the previous allowance for releasing funds".to_string(),
revoke_fee.clone(),
)
.await?;
match ret {
Ok(res) => {
if !res.verification_result {
debug!("Validator {} didn't accept the credential. It will probably vote No on the spending proposal", 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);
}
}
}
self.nyxd_client.execute_proposal(proposal_id, None).await?;
Ok(())
}
}
#[derive(Clone)]
@@ -226,7 +324,7 @@ where
async fn send_credential(pending: &PendingCredential) -> bool {
let request =
VerifyCredentialBody::new(pending.credential.clone(), pending.address.clone());
OfflineVerifyCredentialBody::new(pending.credential.clone(), pending.address.clone());
match pending.client.verify_offline_credential(&request).await {
Ok(res) => {
if !res.verification_result {
@@ -90,6 +90,7 @@ pub(crate) struct FreshHandler<R, S, St> {
rng: R,
local_identity: Arc<identity::KeyPair>,
pub(crate) only_coconut_credentials: bool,
pub(crate) offline_credential_verification: bool,
pub(crate) active_clients_store: ActiveClientsStore,
pub(crate) outbound_mix_sender: MixForwardingSender,
pub(crate) socket_connection: SocketStream<S>,
@@ -111,6 +112,7 @@ where
rng: R,
conn: S,
only_coconut_credentials: bool,
offline_credential_verification: bool,
outbound_mix_sender: MixForwardingSender,
local_identity: Arc<identity::KeyPair>,
storage: St,
@@ -121,6 +123,7 @@ where
rng,
active_clients_store,
only_coconut_credentials,
offline_credential_verification,
outbound_mix_sender,
socket_connection: SocketStream::RawTcp(conn),
local_identity,
@@ -18,6 +18,7 @@ pub(crate) struct Listener {
address: SocketAddr,
local_identity: Arc<identity::KeyPair>,
only_coconut_credentials: bool,
offline_credential_verification: bool,
pub(crate) ecash_verifier: Arc<EcashVerifier>,
}
@@ -26,12 +27,14 @@ impl Listener {
address: SocketAddr,
local_identity: Arc<identity::KeyPair>,
only_coconut_credentials: bool,
offline_credential_verification: bool,
ecash_verifier: Arc<EcashVerifier>,
) -> Self {
Listener {
address,
local_identity,
only_coconut_credentials,
offline_credential_verification,
ecash_verifier,
}
}
@@ -72,6 +75,7 @@ impl Listener {
OsRng,
socket,
self.only_coconut_credentials,
self.offline_credential_verification,
outbound_mix_sender.clone(),
Arc::clone(&self.local_identity),
storage.clone(),
+2
View File
@@ -231,6 +231,7 @@ impl<St> Gateway<St> {
listening_address,
Arc::clone(&self.identity_keypair),
self.config.gateway.only_coconut_credentials,
self.config.gateway.offline_credential_verification,
ecash_verifier,
)
.start(
@@ -472,6 +473,7 @@ impl<St> Gateway<St> {
self.identity_keypair.public_key().to_bytes(),
shutdown.subscribe().named("EcashVerifier"),
self.storage.clone(),
self.config.gateway.offline_credential_verification,
)
};
+1 -1
View File
@@ -347,7 +347,7 @@ pub async fn verify_online_credential(
//SW THIS WILL HAVE TO CHANGE AS WELL
vote_yes &= Coin::from(proposed_release_funds)
== Coin::new(
verify_credential_body.credential().voucher_value() as u128,
verify_credential_body.credential().value() as u128,
state.mix_denom.clone(),
);