Use more descriptive error for lox proto functions
Request functions for protocols in the Lox library previously returned a ProofError error type, which is not verbose enough to allow for accurate debugging. This commit introduces a new error enum, CredentialError, with several types that allow for descriptive error messages.
This commit is contained in:
parent
bd58409762
commit
c92a14d612
|
@ -980,6 +980,7 @@ pub fn pt_dbl(P: &RistrettoPoint) -> RistrettoPoint {
|
|||
pub mod proto {
|
||||
pub mod blockage_migration;
|
||||
pub mod check_blockage;
|
||||
pub mod errors;
|
||||
pub mod issue_invite;
|
||||
pub mod level_up;
|
||||
pub mod migration;
|
||||
|
|
|
@ -52,6 +52,8 @@ use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
|
|||
use super::check_blockage::MIN_TRUST_LEVEL;
|
||||
use super::level_up::LEVEL_INVITATIONS;
|
||||
|
||||
use super::errors::CredentialError;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Request {
|
||||
// Fields for blind showing the Lox credential
|
||||
|
@ -182,7 +184,7 @@ pub fn request(
|
|||
migration_cred: &cred::Migration,
|
||||
lox_pub: &IssuerPubKey,
|
||||
migration_pub: &IssuerPubKey,
|
||||
) -> Result<(Request, State), ProofError> {
|
||||
) -> Result<(Request, State), CredentialError> {
|
||||
let A: &RistrettoPoint = &CMZ_A;
|
||||
let B: &RistrettoPoint = &CMZ_B;
|
||||
let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;
|
||||
|
@ -192,16 +194,24 @@ pub fn request(
|
|||
// ids match and the Lox credential bucket matches the Migration
|
||||
// credential from_bucket
|
||||
if lox_cred.id != migration_cred.lox_id || lox_cred.bucket != migration_cred.from_bucket {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::CredentialMismatch);
|
||||
}
|
||||
|
||||
// The trust level must be at least MIN_TRUST_LEVEL
|
||||
let level: u32 = match scalar_u32(&lox_cred.trust_level) {
|
||||
Some(v) => v,
|
||||
None => return Err(ProofError::VerificationFailure),
|
||||
None => {
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("trust_level"),
|
||||
String::from("could not be converted to u32"),
|
||||
))
|
||||
}
|
||||
};
|
||||
if level < MIN_TRUST_LEVEL {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("trust_level"),
|
||||
format!("level {:?} not in range", level),
|
||||
));
|
||||
}
|
||||
|
||||
// Blind showing the Lox credential
|
||||
|
|
|
@ -49,6 +49,8 @@ use super::super::scalar_u32;
|
|||
use super::super::{BridgeAuth, IssuerPubKey};
|
||||
use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
|
||||
|
||||
use super::errors::CredentialError;
|
||||
|
||||
/// The minimum trust level a Lox credential must have to be allowed to
|
||||
/// perform this protocol.
|
||||
pub const MIN_TRUST_LEVEL: u32 = 3;
|
||||
|
@ -122,7 +124,7 @@ define_proof! {
|
|||
pub fn request(
|
||||
lox_cred: &cred::Lox,
|
||||
lox_pub: &IssuerPubKey,
|
||||
) -> Result<(Request, State), ProofError> {
|
||||
) -> Result<(Request, State), CredentialError> {
|
||||
let A: &RistrettoPoint = &CMZ_A;
|
||||
let B: &RistrettoPoint = &CMZ_B;
|
||||
let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;
|
||||
|
@ -132,10 +134,18 @@ pub fn request(
|
|||
// that trust_level >= MIN_TRUST_LEVEL
|
||||
let level: u32 = match scalar_u32(&lox_cred.trust_level) {
|
||||
Some(v) => v,
|
||||
None => return Err(ProofError::VerificationFailure),
|
||||
None => {
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("trust_level"),
|
||||
String::from("could not be converted to u32"),
|
||||
))
|
||||
}
|
||||
};
|
||||
if level < MIN_TRUST_LEVEL {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("trust_level"),
|
||||
format!("level {:?} not in range", level),
|
||||
));
|
||||
}
|
||||
|
||||
// Blind showing the Lox credential
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
use thiserror::Error;
|
||||
|
||||
/// This error is thrown if the number of buckets/keys in the bridge table
|
||||
/// exceeds u32 MAX.It is unlikely this error will ever occur.
|
||||
#[derive(Error, Debug)]
|
||||
pub enum CredentialError {
|
||||
#[error("time threshold for operation will not be met for {0} more days")]
|
||||
TimeThresholdNotMet(u32),
|
||||
#[error("credential has expired")]
|
||||
CredentialExpired,
|
||||
#[error("invalid field {0}: {1}")]
|
||||
InvalidField(String, String),
|
||||
#[error("exceeded blockages threshold")]
|
||||
ExceededBlockagesThreshold,
|
||||
#[error("credential has no available invitations")]
|
||||
NoInvitationsRemaining,
|
||||
#[error("supplied credentials do not match")]
|
||||
CredentialMismatch,
|
||||
}
|
|
@ -62,6 +62,8 @@ use super::super::scalar_u32;
|
|||
use super::super::{BridgeAuth, IssuerPubKey};
|
||||
use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
|
||||
|
||||
use super::errors::CredentialError;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Request {
|
||||
// Fields for blind showing the Lox credential
|
||||
|
@ -261,7 +263,7 @@ pub fn request(
|
|||
lox_pub: &IssuerPubKey,
|
||||
reach_pub: &IssuerPubKey,
|
||||
today: u32,
|
||||
) -> Result<(Request, State), ProofError> {
|
||||
) -> Result<(Request, State), CredentialError> {
|
||||
let A: &RistrettoPoint = &CMZ_A;
|
||||
let B: &RistrettoPoint = &CMZ_B;
|
||||
let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;
|
||||
|
@ -270,20 +272,28 @@ pub fn request(
|
|||
// Ensure the credential can be correctly shown: it must be the case
|
||||
// that invites_remaining not be 0
|
||||
if lox_cred.invites_remaining == Scalar::ZERO {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::NoInvitationsRemaining);
|
||||
}
|
||||
// The buckets in the Lox and Bucket Reachability credentials have
|
||||
// to match
|
||||
if lox_cred.bucket != reach_cred.bucket {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::CredentialMismatch);
|
||||
}
|
||||
// The Bucket Reachability credential has to be dated today
|
||||
let reach_date: u32 = match scalar_u32(&reach_cred.date) {
|
||||
Some(v) => v,
|
||||
None => return Err(ProofError::VerificationFailure),
|
||||
None => {
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("date"),
|
||||
String::from("could not be converted to u32"),
|
||||
))
|
||||
}
|
||||
};
|
||||
if reach_date != today {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("date"),
|
||||
String::from("reachability credential must be generated today"),
|
||||
));
|
||||
}
|
||||
// The new invites_remaining
|
||||
let new_invites_remaining = lox_cred.invites_remaining - Scalar::ONE;
|
||||
|
|
|
@ -55,6 +55,8 @@ use super::super::{pt_dbl, scalar_dbl, scalar_u32};
|
|||
use super::super::{BridgeAuth, IssuerPubKey};
|
||||
use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
|
||||
|
||||
use super::errors::CredentialError;
|
||||
|
||||
/// The maximum trust level in the system. A user can run this level
|
||||
/// upgrade protocol when they're already at the max level; they will
|
||||
/// get a fresh invites_remaining batch, and reset their level_since
|
||||
|
@ -272,7 +274,7 @@ pub fn request(
|
|||
lox_pub: &IssuerPubKey,
|
||||
reach_pub: &IssuerPubKey,
|
||||
today: u32,
|
||||
) -> Result<(Request, State), ProofError> {
|
||||
) -> Result<(Request, State), CredentialError> {
|
||||
let A: &RistrettoPoint = &CMZ_A;
|
||||
let B: &RistrettoPoint = &CMZ_B;
|
||||
let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;
|
||||
|
@ -282,50 +284,83 @@ pub fn request(
|
|||
// that level_since + LEVEL_INTERVAL[level] <= today.
|
||||
let level_since: u32 = match scalar_u32(&lox_cred.level_since) {
|
||||
Some(v) => v,
|
||||
None => return Err(ProofError::VerificationFailure),
|
||||
None => {
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("level_since"),
|
||||
String::from("could not be converted to u32"),
|
||||
))
|
||||
}
|
||||
};
|
||||
// The trust level has to be at least 1
|
||||
let trust_level: u32 = match scalar_u32(&lox_cred.trust_level) {
|
||||
Some(v) => v,
|
||||
None => return Err(ProofError::VerificationFailure),
|
||||
None => {
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("trust_level"),
|
||||
String::from("could not be converted to u32"),
|
||||
))
|
||||
}
|
||||
};
|
||||
if trust_level < 1 || (trust_level as usize) > MAX_LEVEL {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("trust_level"),
|
||||
format!("level {:?} not in range", trust_level),
|
||||
));
|
||||
}
|
||||
// The trust level has to be no higher than the highest level
|
||||
let level_interval: u32 = match LEVEL_INTERVAL.get(trust_level as usize) {
|
||||
Some(&v) => v,
|
||||
None => return Err(ProofError::VerificationFailure),
|
||||
None => {
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("trust_level"),
|
||||
format!("level {:?} not in range", trust_level),
|
||||
))
|
||||
}
|
||||
};
|
||||
if level_since + level_interval > today {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::TimeThresholdNotMet(
|
||||
level_since + level_interval - today,
|
||||
));
|
||||
}
|
||||
// The credential can't be _too_ old
|
||||
let diffdays = today - (level_since + level_interval);
|
||||
if diffdays > 511 {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::CredentialExpired);
|
||||
}
|
||||
// The current number of blockages
|
||||
let blockages: u32 = match scalar_u32(&lox_cred.blockages) {
|
||||
Some(v) => v,
|
||||
None => return Err(ProofError::VerificationFailure),
|
||||
None => {
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("blockages"),
|
||||
String::from("could not be converted to u32"),
|
||||
))
|
||||
}
|
||||
};
|
||||
if blockages > MAX_BLOCKAGES[trust_level as usize] {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::ExceededBlockagesThreshold);
|
||||
}
|
||||
let blockage_diff = MAX_BLOCKAGES[trust_level as usize] - blockages;
|
||||
// The buckets in the Lox and Bucket Reachability credentials have
|
||||
// to match
|
||||
if lox_cred.bucket != reach_cred.bucket {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::CredentialMismatch);
|
||||
}
|
||||
// The Bucket Reachability credential has to be dated today
|
||||
let reach_date: u32 = match scalar_u32(&reach_cred.date) {
|
||||
Some(v) => v,
|
||||
None => return Err(ProofError::VerificationFailure),
|
||||
None => {
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("date"),
|
||||
String::from("could not be converted to u32"),
|
||||
))
|
||||
}
|
||||
};
|
||||
if reach_date != today {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("date"),
|
||||
String::from("reachability credential must be generated today"),
|
||||
));
|
||||
}
|
||||
// The new trust level
|
||||
let new_level = if (trust_level as usize) < MAX_LEVEL {
|
||||
|
|
|
@ -46,6 +46,8 @@ use super::super::dup_filter::SeenType;
|
|||
use super::super::{BridgeAuth, IssuerPubKey};
|
||||
use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
|
||||
|
||||
use super::errors::CredentialError;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Request {
|
||||
// Fields for blind showing the Lox credential
|
||||
|
@ -153,7 +155,7 @@ pub fn request(
|
|||
migration_cred: &cred::Migration,
|
||||
lox_pub: &IssuerPubKey,
|
||||
migration_pub: &IssuerPubKey,
|
||||
) -> Result<(Request, State), ProofError> {
|
||||
) -> Result<(Request, State), CredentialError> {
|
||||
let A: &RistrettoPoint = &CMZ_A;
|
||||
let B: &RistrettoPoint = &CMZ_B;
|
||||
let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;
|
||||
|
@ -163,13 +165,16 @@ pub fn request(
|
|||
// ids match and the Lox credential bucket matches the Migration
|
||||
// credential from_bucket
|
||||
if lox_cred.id != migration_cred.lox_id || lox_cred.bucket != migration_cred.from_bucket {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::CredentialMismatch);
|
||||
}
|
||||
|
||||
// This protocol only allows migrating from trust level 0 to trust
|
||||
// level 1
|
||||
if lox_cred.trust_level != Scalar::ZERO {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("trust_level"),
|
||||
String::from("must be zero"),
|
||||
));
|
||||
}
|
||||
|
||||
// Blind showing the Lox credential
|
||||
|
|
|
@ -38,6 +38,8 @@ use super::super::{pt_dbl, scalar_dbl, scalar_u32};
|
|||
use super::super::{BridgeAuth, IssuerPubKey};
|
||||
use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
|
||||
|
||||
use super::errors::CredentialError;
|
||||
|
||||
/// Invitations must be used within this many days of being issued.
|
||||
/// Note that if you change this number to be larger than 15, you must
|
||||
/// also add bits to the zero knowledge proof.
|
||||
|
@ -174,7 +176,7 @@ pub fn request(
|
|||
inv_cred: &cred::Invitation,
|
||||
invitation_pub: &IssuerPubKey,
|
||||
today: u32,
|
||||
) -> Result<(Request, State), ProofError> {
|
||||
) -> Result<(Request, State), CredentialError> {
|
||||
let A: &RistrettoPoint = &CMZ_A;
|
||||
let B: &RistrettoPoint = &CMZ_B;
|
||||
let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;
|
||||
|
@ -184,16 +186,24 @@ pub fn request(
|
|||
// that date + INVITATION_EXPIRY >= today.
|
||||
let date: u32 = match scalar_u32(&inv_cred.date) {
|
||||
Some(v) => v,
|
||||
None => return Err(ProofError::VerificationFailure),
|
||||
None => {
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("date"),
|
||||
String::from("could not be converted to u32"),
|
||||
))
|
||||
}
|
||||
};
|
||||
if date + INVITATION_EXPIRY < today {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::CredentialExpired);
|
||||
}
|
||||
let diffdays = date + INVITATION_EXPIRY - today;
|
||||
// If diffdays > 15, then since INVITATION_EXPIRY <= 15, then date
|
||||
// must be in the future. Reject.
|
||||
if diffdays > 15 {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("date"),
|
||||
String::from("credential was created in the future"),
|
||||
));
|
||||
}
|
||||
|
||||
// Blind showing the Invitation credential
|
||||
|
|
|
@ -48,6 +48,8 @@ use super::super::{pt_dbl, scalar_dbl, scalar_u32};
|
|||
use super::super::{BridgeAuth, IssuerPubKey};
|
||||
use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
|
||||
|
||||
use super::errors::CredentialError;
|
||||
|
||||
/// The minimum number of days a user has to be at trust level 0
|
||||
/// (untrusted) with their (single) bridge unblocked before they can
|
||||
/// move to level 1.
|
||||
|
@ -164,7 +166,7 @@ pub fn request(
|
|||
lox_cred: &cred::Lox,
|
||||
lox_pub: &IssuerPubKey,
|
||||
today: u32,
|
||||
) -> Result<(Request, State), ProofError> {
|
||||
) -> Result<(Request, State), CredentialError> {
|
||||
let A: &RistrettoPoint = &CMZ_A;
|
||||
let B: &RistrettoPoint = &CMZ_B;
|
||||
let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;
|
||||
|
@ -174,14 +176,21 @@ pub fn request(
|
|||
// that level_since + UNTRUSTED_INTERVAL <= today.
|
||||
let level_since: u32 = match scalar_u32(&lox_cred.level_since) {
|
||||
Some(v) => v,
|
||||
None => return Err(ProofError::VerificationFailure),
|
||||
None => {
|
||||
return Err(CredentialError::InvalidField(
|
||||
String::from("level_since"),
|
||||
String::from("could not be converted to u32"),
|
||||
))
|
||||
}
|
||||
};
|
||||
if level_since + UNTRUSTED_INTERVAL > today {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::TimeThresholdNotMet(
|
||||
level_since + UNTRUSTED_INTERVAL - today,
|
||||
));
|
||||
}
|
||||
let diffdays = today - (level_since + UNTRUSTED_INTERVAL);
|
||||
if diffdays > 511 {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
return Err(CredentialError::CredentialExpired);
|
||||
}
|
||||
|
||||
// Blind showing the Lox credential
|
||||
|
|
Loading…
Reference in New Issue