Browse Source

Up the max level to 4 and add the ZKP for the max number of blockages allowed in the level up protocol

Ian Goldberg 3 years ago
parent
commit
c530d4a081
2 changed files with 112 additions and 10 deletions
  1. 111 9
      src/proto/level_up.rs
  2. 1 1
      src/proto/trust_promotion.rs

+ 111 - 9
src/proto/level_up.rs

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

+ 1 - 1
src/proto/trust_promotion.rs

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