validating request attributes

This commit is contained in:
Jędrzej Stuczyński
2024-02-09 17:35:07 +00:00
parent b4880db840
commit f0666b33d2
4 changed files with 76 additions and 5 deletions
@@ -6,7 +6,7 @@ use std::sync::OnceLock;
pub use issuance::IssuanceBandwidthCredential;
pub use issued::IssuedBandwidthCredential;
pub use nym_credentials_interface::{
CredentialSigningData, CredentialSpendingData, CredentialType, Parameters,
CredentialSigningData, CredentialSpendingData, CredentialType, Parameters, UnknownCredentialType
};
pub mod freepass;
+43 -1
View File
@@ -18,16 +18,56 @@ use nym_coconut_bandwidth_contract_common::spend_credential::{
funds_from_cosmos_msgs, SpendCredentialStatus,
};
use nym_coconut_dkg_common::types::EpochId;
use nym_credentials::coconut::bandwidth::freepass::MAX_FREE_PASS_VALIDITY;
use nym_credentials::coconut::bandwidth::{
bandwidth_credential_params, IssuanceBandwidthCredential,
bandwidth_credential_params, CredentialType, IssuanceBandwidthCredential,
};
use nym_validator_client::nyxd::Coin;
use rocket::serde::json::Json;
use rocket::State as RocketState;
use std::ops::Deref;
use time::OffsetDateTime;
mod helpers;
fn validate_freepass_public_attributes(res: &FreePassRequest) -> Result<()> {
let public_attributes = &res.public_attributes_plain;
if public_attributes.len() != IssuanceBandwidthCredential::PUBLIC_ATTRIBUTES as usize {
return Err(CoconutError::InvalidFreePassAttributes {
got: public_attributes.len(),
expected: IssuanceBandwidthCredential::PUBLIC_ATTRIBUTES as usize,
});
}
// SAFETY: we just ensured correct number of attributes
let expiry_raw = public_attributes.first().unwrap();
let type_raw = public_attributes.get(1).unwrap();
let parsed_type = type_raw.parse::<CredentialType>()?;
if parsed_type != CredentialType::FreePass {
return Err(CoconutError::InvalidFreePassTypeAttribute { got: parsed_type });
}
let expiry_timestamp: i64 = expiry_raw
.parse()
.map_err(|source| CoconutError::ExpiryDateParsingFailure { source })?;
let expiry_date = OffsetDateTime::from_unix_timestamp(expiry_timestamp).map_err(|source| {
CoconutError::InvalidExpiryDate {
unix_timestamp: expiry_timestamp,
source,
}
})?;
let now = OffsetDateTime::now_utc();
if expiry_date > now + MAX_FREE_PASS_VALIDITY {
return Err(CoconutError::TooLongFreePass { expiry_date });
}
Ok(())
}
#[post("/free-pass", data = "<freepass_request_body>")]
pub async fn post_free_pass(
freepass_request_body: Json<FreePassRequest>,
@@ -36,6 +76,8 @@ pub async fn post_free_pass(
debug!("Received free pass sign request");
trace!("body: {:?}", freepass_request_body);
validate_freepass_public_attributes(&freepass_request_body)?;
// grab the admin of the bandwidth contract
let Some(authorised_admin) = state.get_bandwidth_contract_admin().await? else {
error!("our bandwidth contract does not have an admin set! We won't be able to migrate the contract! We should redeploy it ASAP");
+30 -1
View File
@@ -3,7 +3,7 @@
use crate::node_status_api::models::NymApiStorageError;
use nym_coconut_dkg_common::types::{ChunkIndex, DealingIndex, EpochId};
use nym_credentials::coconut::bandwidth::CredentialType;
use nym_credentials::coconut::bandwidth::{CredentialType, UnknownCredentialType};
use nym_crypto::asymmetric::{
encryption::KeyRecoveryError,
identity::{Ed25519RecoveryError, SignatureError},
@@ -18,6 +18,8 @@ use rocket::{response, Request, Response};
use std::io::Cursor;
use std::num::ParseIntError;
use thiserror::Error;
use time::error::ComponentRange;
use time::OffsetDateTime;
pub type Result<T> = std::result::Result<T, CoconutError>;
@@ -50,6 +52,33 @@ pub enum CoconutError {
#[error("only secp256k1 keys are supported for free pass issuance")]
UnsupportedNonSecp256k1Key,
#[error("received credential request for an unknown type: {0}")]
UnknownCredentialType(#[from] UnknownCredentialType),
#[error("the provided free pass request had an unexpected number of public attributes. got {got} but expected {expected}")]
InvalidFreePassAttributes { got: usize, expected: usize },
#[error("the provided free pass request had an invalid type attribute (got: '{got}')")]
InvalidFreePassTypeAttribute { got: CredentialType },
#[error("failed to parse the free pass expiry date: {source}")]
ExpiryDateParsingFailure {
#[source]
source: ParseIntError,
},
#[error("failed to parse expiry timestamp into proper datetime: {source}")]
InvalidExpiryDate {
unix_timestamp: i64,
#[source]
source: ComponentRange,
},
#[error(
"the provided free pass request has too long expiry (expiry is set to on {expiry_date})"
)]
TooLongFreePass { expiry_date: OffsetDateTime },
#[error("the received bandwidth voucher did not contain deposit value")]
MissingBandwidthValue,
+2 -2
View File
@@ -169,10 +169,10 @@ impl CoconutStorageExt for NymApiStorage {
}
async fn get_current_freepass_nonce(&self) -> Result<u32, NymApiStorageError> {
todo!()
Ok(self.manager.get_current_freepass_nonce().await?)
}
async fn update_and_validate_freepass_nonce(&self, new: u32) -> Result<(), NymApiStorageError> {
todo!()
Ok(self.manager.update_and_validate_freepass_nonce(new).await?)
}
}