validating request attributes
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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,
|
||||
|
||||
|
||||
@@ -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?)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user