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:
Ian Goldberg 2021-05-03 14:59:55 -04:00
parent 088071571a
commit 654208769f
2 changed files with 112 additions and 10 deletions

View File

@ -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(),
},
)?;

View File

@ -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),