level_up.rs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  1. /*! A module for the protocol for the user to increase their trust level
  2. (from a level at least 1; use the trust promotion protocol to go from
  3. untrusted (level 0) to minimally trusted (level 1).
  4. They are allowed to do this as long as some amount of time (depending on
  5. their current level) has elapsed since their last level change, and they
  6. have a Bucket Reachability credential for their current bucket and
  7. today's date. (Such credentials are placed daily in the encrypted
  8. bridge table.)
  9. The user presents their current Lox credential:
  10. - id: revealed
  11. - bucket: blinded
  12. - trust_level: revealed, and must be at least 1
  13. - level_since: blinded, but proved in ZK that it's at least the
  14. appropriate number of days ago
  15. - invites_remaining: blinded
  16. - invites_issued: blinded
  17. and a Bucket Reachability credential:
  18. - date: revealed to be today
  19. - bucket: blinded, but proved in ZK that it's the same as in the Lox
  20. credential above
  21. and a new Lox credential to be issued:
  22. - id: jointly chosen by the user and BA
  23. - bucket: blinded, but proved in ZK that it's the same as in the Lox
  24. credential above
  25. - trust_level: revealed to be one more than the trust level above
  26. - level_since: today
  27. - invites_remaining: blinded, but proved in ZK that it's the same as in
  28. the Lox credential above, _plus_ a per-level constant
  29. - invites_issued: blinded, but proved in ZK that it's the same as in the
  30. Lox credential above
  31. */
  32. use curve25519_dalek::ristretto::RistrettoBasepointTable;
  33. use curve25519_dalek::ristretto::RistrettoPoint;
  34. use curve25519_dalek::scalar::Scalar;
  35. use curve25519_dalek::traits::IsIdentity;
  36. use zkp::CompactProof;
  37. use zkp::ProofError;
  38. use zkp::Transcript;
  39. use super::super::cred;
  40. use super::super::dup_filter::SeenType;
  41. use super::super::{pt_dbl, scalar_dbl, scalar_u32};
  42. use super::super::{BridgeAuth, IssuerPubKey};
  43. use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
  44. /// LEVEL_INTERVAL\[i\] for i >= 1 is the minimum number of days a user
  45. /// must be at trust level i before advancing to level i+1. The large
  46. /// last entry makes it impossible to advance past the top level. Note
  47. /// that the LEVEL_INTERVAL\[0\] entry is a dummy; the trust_promotion
  48. /// protocol is used instead of this one to move from level 0 to level
  49. /// 1.
  50. pub const LEVEL_INTERVAL: [u32; 5] = [0, 14, 28, 56, u32::MAX];
  51. /// LEVEL_INVITATIONS\[i\] for i >= 1 is the number of additional
  52. /// invitations a user will be eligible to issue upon advancing from
  53. /// level i to level i+1. Again the LEVEL_INVITATIONS\[0\] entry is a
  54. /// dummy, as for LEVEL_INTERVAL. Also the last entry is 0 because
  55. /// users cannot advance above the highest level.
  56. pub const LEVEL_INVITATIONS: [u32; 5] = [0, 2, 4, 6, 0];
  57. pub struct Request {
  58. // Fields for blind showing the Lox credential
  59. P: RistrettoPoint,
  60. id: Scalar,
  61. CBucket: RistrettoPoint,
  62. level: Scalar,
  63. CSince: RistrettoPoint,
  64. CInvRemain: RistrettoPoint,
  65. CInvIssued: RistrettoPoint,
  66. CQ: RistrettoPoint,
  67. // Fields for blind showing the Bucket Reachability credential
  68. P_reach: RistrettoPoint,
  69. CBucket_reach: RistrettoPoint,
  70. CQ_reach: RistrettoPoint,
  71. // Fields for the inequality proof (level_since +
  72. // LEVEL_INTERVAL[level] <= today)
  73. CG1: RistrettoPoint,
  74. CG2: RistrettoPoint,
  75. CG3: RistrettoPoint,
  76. CG4: RistrettoPoint,
  77. CG5: RistrettoPoint,
  78. CG6: RistrettoPoint,
  79. CG7: RistrettoPoint,
  80. CG8: RistrettoPoint,
  81. CG0sq: RistrettoPoint,
  82. CG1sq: RistrettoPoint,
  83. CG2sq: RistrettoPoint,
  84. CG3sq: RistrettoPoint,
  85. CG4sq: RistrettoPoint,
  86. CG5sq: RistrettoPoint,
  87. CG6sq: RistrettoPoint,
  88. CG7sq: RistrettoPoint,
  89. CG8sq: RistrettoPoint,
  90. // Fields for user blinding of the Lox credential to be issued
  91. D: RistrettoPoint,
  92. EncIdClient: (RistrettoPoint, RistrettoPoint),
  93. EncBucket: (RistrettoPoint, RistrettoPoint),
  94. EncInvRemain: (RistrettoPoint, RistrettoPoint),
  95. EncInvIssued: (RistrettoPoint, RistrettoPoint),
  96. // The combined ZKP
  97. piUser: CompactProof,
  98. }
  99. #[derive(Debug)]
  100. pub struct State {
  101. d: Scalar,
  102. D: RistrettoPoint,
  103. EncIdClient: (RistrettoPoint, RistrettoPoint),
  104. EncBucket: (RistrettoPoint, RistrettoPoint),
  105. EncInvRemain: (RistrettoPoint, RistrettoPoint),
  106. EncInvIssued: (RistrettoPoint, RistrettoPoint),
  107. id_client: Scalar,
  108. bucket: Scalar,
  109. level: Scalar,
  110. invremain: Scalar,
  111. invissued: Scalar,
  112. }
  113. pub struct Response {
  114. // The fields for the new Lox credential; the new trust level is one
  115. // more than the old trust level, so we don't have to include it
  116. // here explicitly
  117. P: RistrettoPoint,
  118. EncQ: (RistrettoPoint, RistrettoPoint),
  119. id_server: Scalar,
  120. level_since: Scalar,
  121. TId: RistrettoPoint,
  122. TBucket: RistrettoPoint,
  123. TInvRemain: RistrettoPoint,
  124. TInvIssued: RistrettoPoint,
  125. // The fields for the implicit noop migration ("nm") credential
  126. P_nm: RistrettoPoint,
  127. EncQ_nm: (RistrettoPoint, RistrettoPoint),
  128. TId_nm: RistrettoPoint,
  129. TBucket_nm: RistrettoPoint,
  130. // The ZKP
  131. piBlindIssue: CompactProof,
  132. }
  133. define_proof! {
  134. requestproof,
  135. "Level Upgrade Request",
  136. (bucket, since, invremain, invissued, zbucket, zsince, zinvremain,
  137. zinvissued, negzQ,
  138. zbucket_reach, negzQ_reach,
  139. d, eid_client, ebucket, einvremain, einvissued, id_client,
  140. g0, g1, g2, g3, g4, g5, g6, g7, g8,
  141. zg0, zg1, zg2, zg3, zg4, zg5, zg6, zg7, zg8,
  142. wg0, wg1, wg2, wg3, wg4, wg5, wg6, wg7, wg8,
  143. yg0, yg1, yg2, yg3, yg4, yg5, yg6, yg7, yg8),
  144. (P, CBucket, CSince, CInvRemain, CInvIssued, V, Xbucket, Xsince,
  145. Xinvremain, Xinvissued,
  146. P_reach, CBucket_reach, V_reach, Xbucket_reach,
  147. D, EncIdClient0, EncIdClient1, EncBucket0, EncBucket1,
  148. EncInvRemain0, EncInvRemain1_minus_LEVELINV_B,
  149. EncInvIssued0, EncInvIssued1,
  150. CG0, CG1, CG2, CG3, CG4, CG5, CG6, CG7, CG8,
  151. CG0sq, CG1sq, CG2sq, CG3sq, CG4sq, CG5sq, CG6sq, CG7sq, CG8sq),
  152. (A, B) :
  153. // Blind showing of the Lox credential
  154. CBucket = (bucket*P + zbucket*A),
  155. CSince = (since*P + zsince*A),
  156. CInvRemain = (invremain*P + zinvremain*A),
  157. CInvIssued = (invissued*P + zinvissued*A),
  158. // Blind showing of the Bucket Reachability credential; note the
  159. // same bucket is used in the proof
  160. CBucket_reach = (bucket*P_reach + zbucket_reach*A),
  161. // User blinding of the Lox credential to be issued
  162. D = (d*B),
  163. EncIdClient0 = (eid_client*B),
  164. EncIdClient1 = (id_client*B + eid_client*D),
  165. EncBucket0 = (ebucket*B),
  166. EncBucket1 = (bucket*B + ebucket*D),
  167. EncInvRemain0 = (einvremain*B),
  168. EncInvRemain1_minus_LEVELINV_B = (invremain*B + einvremain*D),
  169. EncInvIssued0 = (einvissued*B),
  170. EncInvIssued1 = (invissued*B + einvissued*D),
  171. // Prove CSince encodes a value at least LEVEL_INTERVAL
  172. // days ago (at technically at most LEVEL_INTERVAL+511 days
  173. // ago): first prove each of g0, ..., g8 is a bit by proving that
  174. // gi = gi^2
  175. CG0 = (g0*P + zg0*A), CG0sq = (g0*CG0 + wg0*A), CG0sq = (g0*P + yg0*A),
  176. CG1 = (g1*P + zg1*A), CG1sq = (g1*CG1 + wg1*A), CG1sq = (g1*P + yg1*A),
  177. CG2 = (g2*P + zg2*A), CG2sq = (g2*CG2 + wg2*A), CG2sq = (g2*P + yg2*A),
  178. CG3 = (g3*P + zg3*A), CG3sq = (g3*CG3 + wg3*A), CG3sq = (g3*P + yg3*A),
  179. CG4 = (g4*P + zg4*A), CG4sq = (g4*CG4 + wg4*A), CG4sq = (g4*P + yg4*A),
  180. CG5 = (g5*P + zg5*A), CG5sq = (g5*CG5 + wg5*A), CG5sq = (g5*P + yg5*A),
  181. CG6 = (g6*P + zg6*A), CG6sq = (g6*CG6 + wg6*A), CG6sq = (g6*P + yg6*A),
  182. CG7 = (g7*P + zg7*A), CG7sq = (g7*CG7 + wg7*A), CG7sq = (g7*P + yg7*A),
  183. CG8 = (g8*P + zg8*A), CG8sq = (g8*CG8 + wg8*A), CG8sq = (g8*P + yg8*A)
  184. // Then we'll check that CSince + LEVEL_INTERVAL*P + CG0 + 2*CG1
  185. // + 4*CG2 + 8*CG3 + ... + 256*CG8 = today*P by having the verifier
  186. // plug in today*P - (CSince + LEVEL_INTERVAL*P + 2*CG1 + 4*CG2
  187. // + ... + 256*CG8) as its value of CG0.
  188. }
  189. pub fn request(
  190. lox_cred: &cred::Lox,
  191. reach_cred: &cred::BucketReachability,
  192. lox_pub: &IssuerPubKey,
  193. reach_pub: &IssuerPubKey,
  194. today: u32,
  195. ) -> Result<(Request, State), ProofError> {
  196. let A: &RistrettoPoint = &CMZ_A;
  197. let B: &RistrettoPoint = &CMZ_B;
  198. let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;
  199. let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE;
  200. // Ensure the credential can be correctly shown: it must be the case
  201. // that level_since + LEVEL_INTERVAL[level] <= today.
  202. let level_since: u32 = match scalar_u32(&lox_cred.level_since) {
  203. Some(v) => v,
  204. None => return Err(ProofError::VerificationFailure),
  205. };
  206. // The trust level has to be at least 1
  207. let trust_level: u32 = match scalar_u32(&lox_cred.trust_level) {
  208. Some(v) => v,
  209. None => return Err(ProofError::VerificationFailure),
  210. };
  211. if trust_level < 1 {
  212. return Err(ProofError::VerificationFailure);
  213. }
  214. // The trust level has to be no higher than the highest level
  215. let level_interval: u32 = match LEVEL_INTERVAL.get(trust_level as usize) {
  216. Some(&v) => v,
  217. None => return Err(ProofError::VerificationFailure),
  218. };
  219. if level_since + level_interval > today {
  220. return Err(ProofError::VerificationFailure);
  221. }
  222. // The credential can't be _too_ old
  223. let diffdays = today - (level_since + level_interval);
  224. if diffdays > 511 {
  225. return Err(ProofError::VerificationFailure);
  226. }
  227. // The buckets in the Lox and Bucket Reachability credentials have
  228. // to match
  229. if lox_cred.bucket != reach_cred.bucket {
  230. return Err(ProofError::VerificationFailure);
  231. }
  232. // The Bucket Reachability credential has to be dated today
  233. let reach_date: u32 = match scalar_u32(&reach_cred.date) {
  234. Some(v) => v,
  235. None => return Err(ProofError::VerificationFailure),
  236. };
  237. if reach_date != today {
  238. return Err(ProofError::VerificationFailure);
  239. }
  240. // Blind showing the Lox credential
  241. // Reblind P and Q
  242. let mut rng = rand::thread_rng();
  243. let t = Scalar::random(&mut rng);
  244. let P = t * lox_cred.P;
  245. let Q = t * lox_cred.Q;
  246. // Form Pedersen commitments to the blinded attributes
  247. let zbucket = Scalar::random(&mut rng);
  248. let zsince = Scalar::random(&mut rng);
  249. let zinvremain = Scalar::random(&mut rng);
  250. let zinvissued = Scalar::random(&mut rng);
  251. let CBucket = lox_cred.bucket * P + &zbucket * Atable;
  252. let CSince = lox_cred.level_since * P + &zsince * Atable;
  253. let CInvRemain = lox_cred.invites_remaining * P + &zinvremain * Atable;
  254. let CInvIssued = lox_cred.invites_issued * P + &zinvissued * Atable;
  255. // Form a Pedersen commitment to the MAC Q
  256. // We flip the sign of zQ from that of the Hyphae paper so that
  257. // the ZKP has a "+" instead of a "-", as that's what the zkp
  258. // macro supports.
  259. let negzQ = Scalar::random(&mut rng);
  260. let CQ = Q - &negzQ * Atable;
  261. // Compute the "error factor"
  262. let V = zbucket * lox_pub.X[2]
  263. + zsince * lox_pub.X[4]
  264. + zinvremain * lox_pub.X[5]
  265. + zinvissued * lox_pub.X[6]
  266. + &negzQ * Atable;
  267. // Blind showing the Bucket Reachability credential
  268. // Reblind P and Q
  269. let t_reach = Scalar::random(&mut rng);
  270. let P_reach = t_reach * reach_cred.P;
  271. let Q_reach = t_reach * reach_cred.Q;
  272. // Form Pedersen commitments to the blinded attributes
  273. let zbucket_reach = Scalar::random(&mut rng);
  274. let CBucket_reach = reach_cred.bucket * P_reach + &zbucket_reach * Atable;
  275. // Form a Pedersen commitment to the MAC Q
  276. // We flip the sign of zQ from that of the Hyphae paper so that
  277. // the ZKP has a "+" instead of a "-", as that's what the zkp
  278. // macro supports.
  279. let negzQ_reach = Scalar::random(&mut rng);
  280. let CQ_reach = Q_reach - &negzQ_reach * Atable;
  281. // Compute the "error factor"
  282. let V_reach = zbucket_reach * reach_pub.X[2] + &negzQ_reach * Atable;
  283. // User blinding for the Lox certificate to be issued
  284. // Pick an ElGamal keypair
  285. let d = Scalar::random(&mut rng);
  286. let D = &d * Btable;
  287. // Pick a random client component of the id
  288. let id_client = Scalar::random(&mut rng);
  289. // Encrypt it (times the basepoint B) to the ElGamal public key D we
  290. // just created
  291. let eid_client = Scalar::random(&mut rng);
  292. let EncIdClient = (&eid_client * Btable, &id_client * Btable + eid_client * D);
  293. // Encrypt the other blinded fields (times B) to D as well
  294. let ebucket = Scalar::random(&mut rng);
  295. let EncBucket = (&ebucket * Btable, &lox_cred.bucket * Btable + ebucket * D);
  296. let newinvites: Scalar = LEVEL_INVITATIONS[trust_level as usize].into();
  297. let einvremain = Scalar::random(&mut rng);
  298. let EncInvRemain = (
  299. &einvremain * Btable,
  300. &(lox_cred.invites_remaining + newinvites) * Btable + einvremain * D,
  301. );
  302. let einvissued = Scalar::random(&mut rng);
  303. let EncInvIssued = (
  304. &einvissued * Btable,
  305. &lox_cred.invites_issued * Btable + einvissued * D,
  306. );
  307. // The range proof that 0 <= diffdays <= 511
  308. // Extract the 9 bits from diffdays
  309. let g0: Scalar = (diffdays & 1).into();
  310. let g1: Scalar = ((diffdays >> 1) & 1).into();
  311. let g2: Scalar = ((diffdays >> 2) & 1).into();
  312. let g3: Scalar = ((diffdays >> 3) & 1).into();
  313. let g4: Scalar = ((diffdays >> 4) & 1).into();
  314. let g5: Scalar = ((diffdays >> 5) & 1).into();
  315. let g6: Scalar = ((diffdays >> 6) & 1).into();
  316. let g7: Scalar = ((diffdays >> 7) & 1).into();
  317. let g8: Scalar = ((diffdays >> 8) & 1).into();
  318. // Pick random factors for the Pedersen commitments
  319. let wg0 = Scalar::random(&mut rng);
  320. let zg1 = Scalar::random(&mut rng);
  321. let wg1 = Scalar::random(&mut rng);
  322. let zg2 = Scalar::random(&mut rng);
  323. let wg2 = Scalar::random(&mut rng);
  324. let zg3 = Scalar::random(&mut rng);
  325. let wg3 = Scalar::random(&mut rng);
  326. let zg4 = Scalar::random(&mut rng);
  327. let wg4 = Scalar::random(&mut rng);
  328. let zg5 = Scalar::random(&mut rng);
  329. let wg5 = Scalar::random(&mut rng);
  330. let zg6 = Scalar::random(&mut rng);
  331. let wg6 = Scalar::random(&mut rng);
  332. let zg7 = Scalar::random(&mut rng);
  333. let wg7 = Scalar::random(&mut rng);
  334. let zg8 = Scalar::random(&mut rng);
  335. let wg8 = Scalar::random(&mut rng);
  336. // Compute zg0 to cancel things out as
  337. // zg0 = -(zsince + 2*zg1 + 4*zg2 + 8*zg3 + 16*zg4 + 32*zg5 + 64*zg6 + 128*zg7 + 256*zg8)
  338. // but use Horner's method
  339. let zg0 = -(scalar_dbl(
  340. &(scalar_dbl(
  341. &(scalar_dbl(
  342. &(scalar_dbl(
  343. &(scalar_dbl(
  344. &(scalar_dbl(&(scalar_dbl(&(scalar_dbl(&zg8) + zg7)) + zg6)) + zg5),
  345. ) + zg4),
  346. ) + zg3),
  347. ) + zg2),
  348. ) + zg1),
  349. ) + zsince);
  350. let yg0 = wg0 + g0 * zg0;
  351. let yg1 = wg1 + g1 * zg1;
  352. let yg2 = wg2 + g2 * zg2;
  353. let yg3 = wg3 + g3 * zg3;
  354. let yg4 = wg4 + g4 * zg4;
  355. let yg5 = wg5 + g5 * zg5;
  356. let yg6 = wg6 + g6 * zg6;
  357. let yg7 = wg7 + g7 * zg7;
  358. let yg8 = wg8 + g8 * zg8;
  359. let CG0 = g0 * P + &zg0 * Atable;
  360. let CG1 = g1 * P + &zg1 * Atable;
  361. let CG2 = g2 * P + &zg2 * Atable;
  362. let CG3 = g3 * P + &zg3 * Atable;
  363. let CG4 = g4 * P + &zg4 * Atable;
  364. let CG5 = g5 * P + &zg5 * Atable;
  365. let CG6 = g6 * P + &zg6 * Atable;
  366. let CG7 = g7 * P + &zg7 * Atable;
  367. let CG8 = g8 * P + &zg8 * Atable;
  368. let CG0sq = g0 * P + &yg0 * Atable;
  369. let CG1sq = g1 * P + &yg1 * Atable;
  370. let CG2sq = g2 * P + &yg2 * Atable;
  371. let CG3sq = g3 * P + &yg3 * Atable;
  372. let CG4sq = g4 * P + &yg4 * Atable;
  373. let CG5sq = g5 * P + &yg5 * Atable;
  374. let CG6sq = g6 * P + &yg6 * Atable;
  375. let CG7sq = g7 * P + &yg7 * Atable;
  376. let CG8sq = g8 * P + &yg8 * Atable;
  377. // Construct the proof
  378. let mut transcript = Transcript::new(b"level upgrade request");
  379. let piUser = requestproof::prove_compact(
  380. &mut transcript,
  381. requestproof::ProveAssignments {
  382. A: &A,
  383. B: &B,
  384. P: &P,
  385. CBucket: &CBucket,
  386. CSince: &CSince,
  387. CInvRemain: &CInvRemain,
  388. CInvIssued: &CInvIssued,
  389. V: &V,
  390. Xbucket: &lox_pub.X[2],
  391. Xsince: &lox_pub.X[4],
  392. Xinvremain: &lox_pub.X[5],
  393. Xinvissued: &lox_pub.X[6],
  394. P_reach: &P_reach,
  395. CBucket_reach: &CBucket_reach,
  396. V_reach: &V_reach,
  397. Xbucket_reach: &reach_pub.X[2],
  398. D: &D,
  399. EncIdClient0: &EncIdClient.0,
  400. EncIdClient1: &EncIdClient.1,
  401. EncBucket0: &EncBucket.0,
  402. EncBucket1: &EncBucket.1,
  403. EncInvRemain0: &EncInvRemain.0,
  404. EncInvRemain1_minus_LEVELINV_B: &(EncInvRemain.1 - &newinvites * Btable),
  405. EncInvIssued0: &EncInvIssued.0,
  406. EncInvIssued1: &EncInvIssued.1,
  407. CG0: &CG0,
  408. CG1: &CG1,
  409. CG2: &CG2,
  410. CG3: &CG3,
  411. CG4: &CG4,
  412. CG5: &CG5,
  413. CG6: &CG6,
  414. CG7: &CG7,
  415. CG8: &CG8,
  416. CG0sq: &CG0sq,
  417. CG1sq: &CG1sq,
  418. CG2sq: &CG2sq,
  419. CG3sq: &CG3sq,
  420. CG4sq: &CG4sq,
  421. CG5sq: &CG5sq,
  422. CG6sq: &CG6sq,
  423. CG7sq: &CG7sq,
  424. CG8sq: &CG8sq,
  425. bucket: &lox_cred.bucket,
  426. since: &lox_cred.level_since,
  427. invremain: &lox_cred.invites_remaining,
  428. invissued: &lox_cred.invites_issued,
  429. zbucket: &zbucket,
  430. zsince: &zsince,
  431. zinvremain: &zinvremain,
  432. zinvissued: &zinvissued,
  433. negzQ: &negzQ,
  434. zbucket_reach: &zbucket_reach,
  435. negzQ_reach: &negzQ_reach,
  436. d: &d,
  437. eid_client: &eid_client,
  438. ebucket: &ebucket,
  439. einvremain: &einvremain,
  440. einvissued: &einvissued,
  441. id_client: &id_client,
  442. g0: &g0,
  443. g1: &g1,
  444. g2: &g2,
  445. g3: &g3,
  446. g4: &g4,
  447. g5: &g5,
  448. g6: &g6,
  449. g7: &g7,
  450. g8: &g8,
  451. zg0: &zg0,
  452. zg1: &zg1,
  453. zg2: &zg2,
  454. zg3: &zg3,
  455. zg4: &zg4,
  456. zg5: &zg5,
  457. zg6: &zg6,
  458. zg7: &zg7,
  459. zg8: &zg8,
  460. wg0: &wg0,
  461. wg1: &wg1,
  462. wg2: &wg2,
  463. wg3: &wg3,
  464. wg4: &wg4,
  465. wg5: &wg5,
  466. wg6: &wg6,
  467. wg7: &wg7,
  468. wg8: &wg8,
  469. yg0: &yg0,
  470. yg1: &yg1,
  471. yg2: &yg2,
  472. yg3: &yg3,
  473. yg4: &yg4,
  474. yg5: &yg5,
  475. yg6: &yg6,
  476. yg7: &yg7,
  477. yg8: &yg8,
  478. },
  479. )
  480. .0;
  481. Ok((
  482. Request {
  483. P,
  484. id: lox_cred.id,
  485. CBucket,
  486. level: lox_cred.trust_level,
  487. CSince,
  488. CInvRemain,
  489. CInvIssued,
  490. CQ,
  491. P_reach,
  492. CBucket_reach,
  493. CQ_reach,
  494. D,
  495. EncIdClient,
  496. EncBucket,
  497. EncInvRemain,
  498. EncInvIssued,
  499. CG1,
  500. CG2,
  501. CG3,
  502. CG4,
  503. CG5,
  504. CG6,
  505. CG7,
  506. CG8,
  507. CG0sq,
  508. CG1sq,
  509. CG2sq,
  510. CG3sq,
  511. CG4sq,
  512. CG5sq,
  513. CG6sq,
  514. CG7sq,
  515. CG8sq,
  516. piUser,
  517. },
  518. State {
  519. d,
  520. D,
  521. EncIdClient,
  522. EncBucket,
  523. EncInvRemain,
  524. EncInvIssued,
  525. id_client,
  526. bucket: lox_cred.bucket,
  527. level: lox_cred.trust_level + Scalar::one(),
  528. invremain: lox_cred.invites_remaining + newinvites,
  529. invissued: lox_cred.invites_issued,
  530. },
  531. ))
  532. }