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
|
/// upgrade protocol when they're already at the max level; they will
|
||||||
/// get a fresh invites_remaining batch, and reset their level_since
|
/// get a fresh invites_remaining batch, and reset their level_since
|
||||||
/// field to today's date, but will remain in the max level.
|
/// 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
|
/// 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,
|
/// 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
|
/// remain at level i if i == MAX_LEVEL). Note that the
|
||||||
/// LEVEL_INTERVAL\[0\] entry is a dummy; the trust_promotion protocol
|
/// 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.
|
/// 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
|
/// 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
|
/// 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
|
/// i+1. Again the LEVEL_INVITATIONS\[0\] entry is a dummy, as for
|
||||||
/// LEVEL_INTERVAL.
|
/// 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 {
|
pub struct Request {
|
||||||
// Fields for blind showing the Lox credential
|
// Fields for blind showing the Lox credential
|
||||||
|
@ -88,8 +94,8 @@ pub struct Request {
|
||||||
CBucket_reach: RistrettoPoint,
|
CBucket_reach: RistrettoPoint,
|
||||||
CQ_reach: RistrettoPoint,
|
CQ_reach: RistrettoPoint,
|
||||||
|
|
||||||
// Fields for the inequality proof (level_since +
|
// Fields for the inequality proof
|
||||||
// LEVEL_INTERVAL[level] <= today)
|
// level_since + LEVEL_INTERVAL[level] <= today
|
||||||
CG1: RistrettoPoint,
|
CG1: RistrettoPoint,
|
||||||
CG2: RistrettoPoint,
|
CG2: RistrettoPoint,
|
||||||
CG3: RistrettoPoint,
|
CG3: RistrettoPoint,
|
||||||
|
@ -108,6 +114,14 @@ pub struct Request {
|
||||||
CG7sq: RistrettoPoint,
|
CG7sq: RistrettoPoint,
|
||||||
CG8sq: 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
|
// Fields for user blinding of the Lox credential to be issued
|
||||||
D: RistrettoPoint,
|
D: RistrettoPoint,
|
||||||
EncIdClient: (RistrettoPoint, RistrettoPoint),
|
EncIdClient: (RistrettoPoint, RistrettoPoint),
|
||||||
|
@ -158,14 +172,20 @@ define_proof! {
|
||||||
g0, g1, g2, g3, g4, g5, g6, g7, g8,
|
g0, g1, g2, g3, g4, g5, g6, g7, g8,
|
||||||
zg0, zg1, zg2, zg3, zg4, zg5, zg6, zg7, zg8,
|
zg0, zg1, zg2, zg3, zg4, zg5, zg6, zg7, zg8,
|
||||||
wg0, wg1, wg2, wg3, wg4, wg5, wg6, wg7, wg8,
|
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,
|
(P, CBucket, CSince, CInvRemain, CBlockages, V, Xbucket, Xsince,
|
||||||
Xinvremain, Xblockages,
|
Xinvremain, Xblockages,
|
||||||
P_reach, CBucket_reach, V_reach, Xbucket_reach,
|
P_reach, CBucket_reach, V_reach, Xbucket_reach,
|
||||||
D, EncIdClient0, EncIdClient1, EncBucket0, EncBucket1,
|
D, EncIdClient0, EncIdClient1, EncBucket0, EncBucket1,
|
||||||
EncBlockages0, EncBlockages1,
|
EncBlockages0, EncBlockages1,
|
||||||
CG0, CG1, CG2, CG3, CG4, CG5, CG6, CG7, CG8,
|
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) :
|
(A, B) :
|
||||||
// Blind showing of the Lox credential
|
// Blind showing of the Lox credential
|
||||||
CBucket = (bucket*P + zbucket*A),
|
CBucket = (bucket*P + zbucket*A),
|
||||||
|
@ -184,7 +204,7 @@ define_proof! {
|
||||||
EncBlockages0 = (eblockages*B),
|
EncBlockages0 = (eblockages*B),
|
||||||
EncBlockages1 = (blockages*B + eblockages*D),
|
EncBlockages1 = (blockages*B + eblockages*D),
|
||||||
// Prove CSince encodes a value at least LEVEL_INTERVAL
|
// 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
|
// ago): first prove each of g0, ..., g8 is a bit by proving that
|
||||||
// gi = gi^2
|
// gi = gi^2
|
||||||
CG0 = (g0*P + zg0*A), CG0sq = (g0*CG0 + wg0*A), CG0sq = (g0*P + yg0*A),
|
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),
|
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),
|
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),
|
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
|
// Then we'll check that CSince + LEVEL_INTERVAL*P + CG0 + 2*CG1
|
||||||
// + 4*CG2 + 8*CG3 + ... + 256*CG8 = today*P by having the verifier
|
// + 4*CG2 + 8*CG3 + ... + 256*CG8 = today*P by having the verifier
|
||||||
// plug in today*P - (CSince + LEVEL_INTERVAL*P + 2*CG1 + 4*CG2
|
// plug in today*P - (CSince + LEVEL_INTERVAL*P + 2*CG1 + 4*CG2
|
||||||
// + ... + 256*CG8) as its value of CG0.
|
// + ... + 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! {
|
define_proof! {
|
||||||
|
@ -271,6 +300,15 @@ pub fn request(
|
||||||
if diffdays > 511 {
|
if diffdays > 511 {
|
||||||
return Err(ProofError::VerificationFailure);
|
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
|
// The buckets in the Lox and Bucket Reachability credentials have
|
||||||
// to match
|
// to match
|
||||||
if lox_cred.bucket != reach_cred.bucket {
|
if lox_cred.bucket != reach_cred.bucket {
|
||||||
|
@ -445,6 +483,37 @@ pub fn request(
|
||||||
let CG7sq = g7 * P + &yg7 * Atable;
|
let CG7sq = g7 * P + &yg7 * Atable;
|
||||||
let CG8sq = g8 * P + &yg8 * 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
|
// Construct the proof
|
||||||
let mut transcript = Transcript::new(b"level upgrade request");
|
let mut transcript = Transcript::new(b"level upgrade request");
|
||||||
let piUser = requestproof::prove_compact(
|
let piUser = requestproof::prove_compact(
|
||||||
|
@ -491,6 +560,12 @@ pub fn request(
|
||||||
CG6sq: &CG6sq,
|
CG6sq: &CG6sq,
|
||||||
CG7sq: &CG7sq,
|
CG7sq: &CG7sq,
|
||||||
CG8sq: &CG8sq,
|
CG8sq: &CG8sq,
|
||||||
|
CH0: &CH0,
|
||||||
|
CH1: &CH1,
|
||||||
|
CH2: &CH2,
|
||||||
|
CH0sq: &CH0sq,
|
||||||
|
CH1sq: &CH1sq,
|
||||||
|
CH2sq: &CH2sq,
|
||||||
bucket: &lox_cred.bucket,
|
bucket: &lox_cred.bucket,
|
||||||
since: &lox_cred.level_since,
|
since: &lox_cred.level_since,
|
||||||
invremain: &lox_cred.invites_remaining,
|
invremain: &lox_cred.invites_remaining,
|
||||||
|
@ -543,6 +618,18 @@ pub fn request(
|
||||||
yg6: &yg6,
|
yg6: &yg6,
|
||||||
yg7: &yg7,
|
yg7: &yg7,
|
||||||
yg8: &yg8,
|
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;
|
.0;
|
||||||
|
@ -581,6 +668,11 @@ pub fn request(
|
||||||
CG6sq,
|
CG6sq,
|
||||||
CG7sq,
|
CG7sq,
|
||||||
CG8sq,
|
CG8sq,
|
||||||
|
CH1,
|
||||||
|
CH2,
|
||||||
|
CH0sq,
|
||||||
|
CH1sq,
|
||||||
|
CH2sq,
|
||||||
piUser,
|
piUser,
|
||||||
},
|
},
|
||||||
State {
|
State {
|
||||||
|
@ -652,6 +744,10 @@ impl BridgeAuth {
|
||||||
) + req.CG1),
|
) + 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
|
// Verify the ZKP
|
||||||
let mut transcript = Transcript::new(b"level upgrade request");
|
let mut transcript = Transcript::new(b"level upgrade request");
|
||||||
requestproof::verify_compact(
|
requestproof::verify_compact(
|
||||||
|
@ -699,6 +795,12 @@ impl BridgeAuth {
|
||||||
CG6sq: &req.CG6sq.compress(),
|
CG6sq: &req.CG6sq.compress(),
|
||||||
CG7sq: &req.CG7sq.compress(),
|
CG7sq: &req.CG7sq.compress(),
|
||||||
CG8sq: &req.CG8sq.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),
|
EncBucket1 = (bucket*B + ebucket*D),
|
||||||
D = (d*B),
|
D = (d*B),
|
||||||
// Prove CSince encodes a value at least UNTRUSTED_INTERVAL
|
// 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
|
// ago): first prove each of g0, ..., g8 is a bit by proving that
|
||||||
// gi = gi^2
|
// gi = gi^2
|
||||||
CG0 = (g0*P + zg0*A), CG0sq = (g0*CG0 + wg0*A), CG0sq = (g0*P + yg0*A),
|
CG0 = (g0*P + zg0*A), CG0sq = (g0*CG0 + wg0*A), CG0sq = (g0*P + yg0*A),
|
||||||
|
|
Loading…
Reference in New Issue