Up the max level to 4 and add the ZKP for the max number of blockages allowed in the level up protocol
This commit is contained in:
parent
088071571a
commit
654208769f
|
@ -57,20 +57,26 @@ use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
|
|||
/// upgrade protocol when they're already at the max level; they will
|
||||
/// get a fresh invites_remaining batch, and reset their level_since
|
||||
/// field to today's date, but will remain in the max level.
|
||||
pub const MAX_LEVEL: usize = 3;
|
||||
pub const MAX_LEVEL: usize = 4;
|
||||
|
||||
/// LEVEL_INTERVAL\[i\] for i >= 1 is the minimum number of days a user
|
||||
/// must be at trust level i before advancing to level i+1 (or as above,
|
||||
/// remain at level i if i == MAX_LEVEL). Note that the
|
||||
/// LEVEL_INTERVAL\[0\] entry is a dummy; the trust_promotion protocol
|
||||
/// is used instead of this one to move from level 0 to level 1.
|
||||
pub const LEVEL_INTERVAL: [u32; MAX_LEVEL + 1] = [0, 14, 28, 56];
|
||||
pub const LEVEL_INTERVAL: [u32; MAX_LEVEL + 1] = [0, 14, 28, 56, 84];
|
||||
|
||||
/// LEVEL_INVITATIONS\[i\] for i >= 1 is the number of invitations a
|
||||
/// user will be eligible to issue upon advancing from level i to level
|
||||
/// i+1. Again the LEVEL_INVITATIONS\[0\] entry is a dummy, as for
|
||||
/// LEVEL_INTERVAL.
|
||||
pub const LEVEL_INVITATIONS: [u32; MAX_LEVEL + 1] = [0, 2, 4, 6];
|
||||
pub const LEVEL_INVITATIONS: [u32; MAX_LEVEL + 1] = [0, 2, 4, 6, 8];
|
||||
|
||||
/// MAX_BLOCKAGES\[i\] for i >= 1 is the maximum number of bucket
|
||||
/// blockages this credential is allowed to have recorded in order to
|
||||
/// advance from level i to level i+1. Again the LEVEL_INVITATIONS\[0\]
|
||||
/// entry is a dummy, as for LEVEL_INTERVAL.
|
||||
pub const MAX_BLOCKAGES: [u32; MAX_LEVEL + 1] = [0, 4, 3, 2, 2];
|
||||
|
||||
pub struct Request {
|
||||
// Fields for blind showing the Lox credential
|
||||
|
@ -88,8 +94,8 @@ pub struct Request {
|
|||
CBucket_reach: RistrettoPoint,
|
||||
CQ_reach: RistrettoPoint,
|
||||
|
||||
// Fields for the inequality proof (level_since +
|
||||
// LEVEL_INTERVAL[level] <= today)
|
||||
// Fields for the inequality proof
|
||||
// level_since + LEVEL_INTERVAL[level] <= today
|
||||
CG1: RistrettoPoint,
|
||||
CG2: RistrettoPoint,
|
||||
CG3: RistrettoPoint,
|
||||
|
@ -108,6 +114,14 @@ pub struct Request {
|
|||
CG7sq: RistrettoPoint,
|
||||
CG8sq: RistrettoPoint,
|
||||
|
||||
// Fields for the inequality proof
|
||||
// blockages <= MAX_BLOCKAGES[level]
|
||||
CH1: RistrettoPoint,
|
||||
CH2: RistrettoPoint,
|
||||
CH0sq: RistrettoPoint,
|
||||
CH1sq: RistrettoPoint,
|
||||
CH2sq: RistrettoPoint,
|
||||
|
||||
// Fields for user blinding of the Lox credential to be issued
|
||||
D: RistrettoPoint,
|
||||
EncIdClient: (RistrettoPoint, RistrettoPoint),
|
||||
|
@ -158,14 +172,20 @@ define_proof! {
|
|||
g0, g1, g2, g3, g4, g5, g6, g7, g8,
|
||||
zg0, zg1, zg2, zg3, zg4, zg5, zg6, zg7, zg8,
|
||||
wg0, wg1, wg2, wg3, wg4, wg5, wg6, wg7, wg8,
|
||||
yg0, yg1, yg2, yg3, yg4, yg5, yg6, yg7, yg8),
|
||||
yg0, yg1, yg2, yg3, yg4, yg5, yg6, yg7, yg8,
|
||||
h0, h1, h2,
|
||||
zh0, zh1, zh2,
|
||||
wh0, wh1, wh2,
|
||||
yh0, yh1, yh2),
|
||||
(P, CBucket, CSince, CInvRemain, CBlockages, V, Xbucket, Xsince,
|
||||
Xinvremain, Xblockages,
|
||||
P_reach, CBucket_reach, V_reach, Xbucket_reach,
|
||||
D, EncIdClient0, EncIdClient1, EncBucket0, EncBucket1,
|
||||
EncBlockages0, EncBlockages1,
|
||||
CG0, CG1, CG2, CG3, CG4, CG5, CG6, CG7, CG8,
|
||||
CG0sq, CG1sq, CG2sq, CG3sq, CG4sq, CG5sq, CG6sq, CG7sq, CG8sq),
|
||||
CG0sq, CG1sq, CG2sq, CG3sq, CG4sq, CG5sq, CG6sq, CG7sq, CG8sq,
|
||||
CH0, CH1, CH2,
|
||||
CH0sq, CH1sq, CH2sq),
|
||||
(A, B) :
|
||||
// Blind showing of the Lox credential
|
||||
CBucket = (bucket*P + zbucket*A),
|
||||
|
@ -184,7 +204,7 @@ define_proof! {
|
|||
EncBlockages0 = (eblockages*B),
|
||||
EncBlockages1 = (blockages*B + eblockages*D),
|
||||
// Prove CSince encodes a value at least LEVEL_INTERVAL
|
||||
// days ago (at technically at most LEVEL_INTERVAL+511 days
|
||||
// days ago (and technically at most LEVEL_INTERVAL+511 days
|
||||
// ago): first prove each of g0, ..., g8 is a bit by proving that
|
||||
// gi = gi^2
|
||||
CG0 = (g0*P + zg0*A), CG0sq = (g0*CG0 + wg0*A), CG0sq = (g0*P + yg0*A),
|
||||
|
@ -195,11 +215,20 @@ define_proof! {
|
|||
CG5 = (g5*P + zg5*A), CG5sq = (g5*CG5 + wg5*A), CG5sq = (g5*P + yg5*A),
|
||||
CG6 = (g6*P + zg6*A), CG6sq = (g6*CG6 + wg6*A), CG6sq = (g6*P + yg6*A),
|
||||
CG7 = (g7*P + zg7*A), CG7sq = (g7*CG7 + wg7*A), CG7sq = (g7*P + yg7*A),
|
||||
CG8 = (g8*P + zg8*A), CG8sq = (g8*CG8 + wg8*A), CG8sq = (g8*P + yg8*A)
|
||||
CG8 = (g8*P + zg8*A), CG8sq = (g8*CG8 + wg8*A), CG8sq = (g8*P + yg8*A),
|
||||
// Then we'll check that CSince + LEVEL_INTERVAL*P + CG0 + 2*CG1
|
||||
// + 4*CG2 + 8*CG3 + ... + 256*CG8 = today*P by having the verifier
|
||||
// plug in today*P - (CSince + LEVEL_INTERVAL*P + 2*CG1 + 4*CG2
|
||||
// + ... + 256*CG8) as its value of CG0.
|
||||
|
||||
// Prove CBlockage encodes a value at most MAX_BLOCKAGES (and at least
|
||||
// MAX_BLOCKAGES-7)
|
||||
CH0 = (h0*P + zh0*A), CH0sq = (h0*CH0 + wh0*A), CH0sq = (h0*P + yh0*A),
|
||||
CH1 = (h1*P + zh1*A), CH1sq = (h1*CH1 + wh1*A), CH1sq = (h1*P + yh1*A),
|
||||
CH2 = (h2*P + zh2*A), CH2sq = (h2*CH2 + wh2*A), CH2sq = (h2*P + yh2*A)
|
||||
// Then we'll check that CBlockage + CH0 + 2*CH1 + 4*CH2 =
|
||||
// MAX_BLOCKAGES*P by having the verifier plug in MAX_BLOCKAGES*P -
|
||||
// (CBlockage - 2*CH1 - 4*CH2) as its value of CH0.
|
||||
}
|
||||
|
||||
define_proof! {
|
||||
|
@ -271,6 +300,15 @@ pub fn request(
|
|||
if diffdays > 511 {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
}
|
||||
// The current number of blockages
|
||||
let blockages: u32 = match scalar_u32(&lox_cred.blockages) {
|
||||
Some(v) => v,
|
||||
None => return Err(ProofError::VerificationFailure),
|
||||
};
|
||||
if blockages > MAX_BLOCKAGES[trust_level as usize] {
|
||||
return Err(ProofError::VerificationFailure);
|
||||
}
|
||||
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 {
|
||||
|
@ -445,6 +483,37 @@ pub fn request(
|
|||
let CG7sq = g7 * P + &yg7 * Atable;
|
||||
let CG8sq = g8 * P + &yg8 * Atable;
|
||||
|
||||
// The range proof that 0 <= blockage_diff <= 7
|
||||
|
||||
// Extract the 3 bits from blockage_diff
|
||||
let h0: Scalar = (blockage_diff & 1).into();
|
||||
let h1: Scalar = ((blockage_diff >> 1) & 1).into();
|
||||
let h2: Scalar = ((blockage_diff >> 2) & 1).into();
|
||||
|
||||
// Pick random factors for the Pedersen commitments
|
||||
let wh0 = Scalar::random(&mut rng);
|
||||
let zh1 = Scalar::random(&mut rng);
|
||||
let wh1 = Scalar::random(&mut rng);
|
||||
let zh2 = Scalar::random(&mut rng);
|
||||
let wh2 = Scalar::random(&mut rng);
|
||||
|
||||
// Compute zh0 to cancel things out as
|
||||
// zh0 = -(zblockages + 2*zh1 + 4*zh2)
|
||||
// but use Horner's method
|
||||
let zh0 = -(scalar_dbl(&(scalar_dbl(&zh2) + zh1)) + zblockages);
|
||||
|
||||
let yh0 = wh0 + h0 * zh0;
|
||||
let yh1 = wh1 + h1 * zh1;
|
||||
let yh2 = wh2 + h2 * zh2;
|
||||
|
||||
let CH0 = h0 * P + &zh0 * Atable;
|
||||
let CH1 = h1 * P + &zh1 * Atable;
|
||||
let CH2 = h2 * P + &zh2 * Atable;
|
||||
|
||||
let CH0sq = h0 * P + &yh0 * Atable;
|
||||
let CH1sq = h1 * P + &yh1 * Atable;
|
||||
let CH2sq = h2 * P + &yh2 * Atable;
|
||||
|
||||
// Construct the proof
|
||||
let mut transcript = Transcript::new(b"level upgrade request");
|
||||
let piUser = requestproof::prove_compact(
|
||||
|
@ -491,6 +560,12 @@ pub fn request(
|
|||
CG6sq: &CG6sq,
|
||||
CG7sq: &CG7sq,
|
||||
CG8sq: &CG8sq,
|
||||
CH0: &CH0,
|
||||
CH1: &CH1,
|
||||
CH2: &CH2,
|
||||
CH0sq: &CH0sq,
|
||||
CH1sq: &CH1sq,
|
||||
CH2sq: &CH2sq,
|
||||
bucket: &lox_cred.bucket,
|
||||
since: &lox_cred.level_since,
|
||||
invremain: &lox_cred.invites_remaining,
|
||||
|
@ -543,6 +618,18 @@ pub fn request(
|
|||
yg6: &yg6,
|
||||
yg7: &yg7,
|
||||
yg8: &yg8,
|
||||
h0: &h0,
|
||||
h1: &h1,
|
||||
h2: &h2,
|
||||
zh0: &zh0,
|
||||
zh1: &zh1,
|
||||
zh2: &zh2,
|
||||
wh0: &wh0,
|
||||
wh1: &wh1,
|
||||
wh2: &wh2,
|
||||
yh0: &yh0,
|
||||
yh1: &yh1,
|
||||
yh2: &yh2,
|
||||
},
|
||||
)
|
||||
.0;
|
||||
|
@ -581,6 +668,11 @@ pub fn request(
|
|||
CG6sq,
|
||||
CG7sq,
|
||||
CG8sq,
|
||||
CH1,
|
||||
CH2,
|
||||
CH0sq,
|
||||
CH1sq,
|
||||
CH2sq,
|
||||
piUser,
|
||||
},
|
||||
State {
|
||||
|
@ -652,6 +744,10 @@ impl BridgeAuth {
|
|||
) + req.CG1),
|
||||
);
|
||||
|
||||
// Recompute CH0 using Horner's method
|
||||
let mblk: Scalar = MAX_BLOCKAGES[level].into();
|
||||
let CH0prime = mblk * req.P - req.CBlockages - pt_dbl(&(pt_dbl(&req.CH2) + req.CH1));
|
||||
|
||||
// Verify the ZKP
|
||||
let mut transcript = Transcript::new(b"level upgrade request");
|
||||
requestproof::verify_compact(
|
||||
|
@ -699,6 +795,12 @@ impl BridgeAuth {
|
|||
CG6sq: &req.CG6sq.compress(),
|
||||
CG7sq: &req.CG7sq.compress(),
|
||||
CG8sq: &req.CG8sq.compress(),
|
||||
CH0: &CH0prime.compress(),
|
||||
CH1: &req.CH1.compress(),
|
||||
CH2: &req.CH2.compress(),
|
||||
CH0sq: &req.CH0sq.compress(),
|
||||
CH1sq: &req.CH1sq.compress(),
|
||||
CH2sq: &req.CH2sq.compress(),
|
||||
},
|
||||
)?;
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ define_proof! {
|
|||
EncBucket1 = (bucket*B + ebucket*D),
|
||||
D = (d*B),
|
||||
// Prove CSince encodes a value at least UNTRUSTED_INTERVAL
|
||||
// days ago (at technically at most UNTRUSTED_INTERVAL+511 days
|
||||
// days ago (and technically at most UNTRUSTED_INTERVAL+511 days
|
||||
// ago): first prove each of g0, ..., g8 is a bit by proving that
|
||||
// gi = gi^2
|
||||
CG0 = (g0*P + zg0*A), CG0sq = (g0*CG0 + wg0*A), CG0sq = (g0*P + yg0*A),
|
||||
|
|
Loading…
Reference in New Issue