Logo
    🎪

    Circuit Design - SnapDeals (Lightweight CC Sector Updates)

    • Design goals
    • Challenge Generation
    • Randomness Generation
    • Outcome
    • The Circuit
    • Parameters
    • Public inputs
    • Private inputs
    • Circuit

    Design goals

    There are two major pathways we use when designing the circuit

    • challenge generation and hash computation inside
    • or outside.

    We investigate feasibility of doing both challenge generation as well as computing hashes used as randomness during LSU, inside the circuit.

    Challenge Generation

    Challenge generation is a process in which we are aiming to generate a number of challenges C=2200C = 2200C=2200.

    [_,c8j+7,c8j+6,⋯ ,c8j+1,c8j]=Split-31bit(Poseidon–128(CommR,j))ci=ci mod N[\_, c_{8j+7}, c_{8j+6}, \cdots, c_{8j+1}, c_{8j}] = \text{Split-31bit}(\text{Poseidon–128}(CommR, j)) \\ c_i = c_i \bmod N[_,c8j+7​,c8j+6​,⋯,c8j+1​,c8j​]=Split-31bit(Poseidon–128(CommR,j))ci​=ci​modN

    The j∈[0,C/8)j \in [0,C/8)j∈[0,C/8) and NNN is sector size nodes. The Result of Poseidon-128 is split into 31 bit chunks (discarding 7 high bits) forming eight challenges, which then are taken  mod N\bmod NmodN.

    Based on input from ZCash team, Poseidon can be used as PRG for challenge generation. Using it in this manner would mean using Poseidon-128 in 2-ary variant, costing ~311 constraints, plus additional 256 constrains for binary decomposition (binary decomposition constraints may already be included in the cost of inclusion proofs).

    This results in 0.85M additional constraints.

    One Poseidon, Multiple challenges

    The Poseidon-128 outputs Fr field element which after decomposition results in 254.x bits of randomness. Our biggest NNN requires 31 bits of randomness. This means that we could use one Poseidon-128 evaluation to generate 8 challenges. It would reduce cost of challenge generation by factor of 8 as the binary decomposition can be shared as well.

    Randomness Generation

    We are settling on number of ρ\rhoρ per sector H=29=512H = 2^9 = 512H=29=512 (but want to keep some flexibility in final circuit), this gives us two options, we can either compute all H ρ values and use lookup to access ρ from these computed values; or we can compute ρ for each challenge and not use the fact that only H ρ computations need to be done.

    The latter option is promising as 512-ary lookup of dynamic values will cost at least 512 constraints. (please verify)

    ϕ=Posedion-128(CommD,OldCommR)ρci=Poseidon–128(ϕ,⌊ciHN⌋)\phi = \text{Posedion-128}(CommD, OldCommR) \\ \rho_{c_i} = \text{Poseidon–128}(\phi, \lfloor \frac{c_iH}{N} \rfloor)ϕ=Posedion-128(CommD,OldCommR)ρci​​=Poseidon–128(ϕ,⌊Nci​H​⌋)

    As both HHH and NNN are powers of two the ⌊ciHN⌋\lfloor \frac{c_iH}{N} \rfloor⌊Nci​H​⌋ computation can be easily performed using bit shift by selecting bits from decomposed cic_ici​.

    ⌊ciHN⌋=ci≫(log⁡2N−log⁡2H)\lfloor \frac{c_iH}{N} \rfloor = c_i \gg (\log_2N - \log_2H)⌊Nci​H​⌋=ci​≫(log2​N−log2​H)

    This results in ~312 constraints for ρi\rho_iρi​ generation (no decomposition, it is used as Fr).

    This results in additional 0.6M constraints when compared with accepting ρci\rho_{c_i}ρci​​as public input.

    Outcome

    Overall in circuit challenge and randomness generation increases circuit size by ~1.4M constraints which is 14% of estimated size of the circuit. Given that it decreases the number of public inputs by 4400, or 99.9%, the 14% increased proving cost will be well worth the reduction of verification cost.

    Poseidon-128

    The ~311 constraints for Poseidon is taken from here.

    Domain separation to be applied for both uses of Poseidon by means of Poseidon DST in Capacity field.

    The Circuit

    Single sector per circuit.

    Circuit needs to fulfill following roles:

    • Challenge Generation
    • Verifying Inclusion Proofs:
      • NewCommR
      • OldCommR
      • Data Commitment
    • Verifying Encoding
      • Generating ρi\rho_iρi​
      • Ri∗=Ri+Di∗ρiR^{*}_i = R_i + D_i*\rho_iRi∗​=Ri​+Di​∗ρi​

    Parameters

    N∈{25,218,224,230,231}N \in \{2^{5}, 2^{18}, 2^{24}, 2^{30}, 2^{31}\}N∈{25,218,224,230,231} - sector size in nodes

    Hs(N)={{2,2,2,2,2,2}if N=25{27,28,29,210,211,212}otherwiseHs(N) = \begin{cases}\{2, 2, 2,2,2,2\} & \text{if } N=2^5 \\ \{2^7, 2^8, 2^9, 2^{10}, 2^{11}, 2^{12}\} & \text{otherwise} \end{cases}Hs(N)={{2,2,2,2,2,2}{27,28,29,210,211,212}​if N=25otherwise​ - number of encoding hashes

    C(N)={2200for N∈{224,230,231}10otherwiseC(N) = \begin{cases}2200 & \text{for } N \in \{2^{24}, 2^{30}, 2^{31}\}\\ 10 & \text{otherwise} \end{cases}C(N)={220010​for N∈{224,230,231}otherwise​ - number of challenges

    Public inputs

    • OldCommR - CommR of existing CC sector
    • NewCommR - CommR of the sector after being updated with deals
    • CommD - Data commitment for data which is being updated into the sector
    • SectorID - not sure it needs to be a public input, on the actors side we have clear mapping of SectorID to OldCommR.
    • hSelect - one-hot encoding (bit-vector of 6 values, with only one bit set) of hSelecthSelecthSelect

    Private inputs

    • CommC
    • CommRLast
    • SectorID
    • for each cic_ici​
      • vanilla proofs
      • RciR_{c_i}Rci​​, DciD_{c_i}Dci​​, Rci∗R^{*}_{c_i}Rci​∗​ - old replica at ci{c_i}ci​, data at ci{c_i}ci​, new replica at ci{c_i}ci​

    Circuit

    The circuit consists of 2200 independent challenges to be verified.

    One part of circuit that may be shared is proving the openings of NewCommR and OldCommR to arrive at NewCommRLast and OldCommRLast.

    For j∈[0,C/8)j \in [0, C/8)j∈[0,C/8):

    • Challenge Generation: [c8∗j+7,⋯ ,c8∗j]=Poseidon–128(NewCommR,ParitionID∗86+j) mod N[c_{8*j+7},\cdots ,c_{8*j}] = \text{Poseidon–128}(\text{NewCommR}, ParitionID*86+j) \bmod N[c8∗j+7​,⋯,c8∗j​]=Poseidon–128(NewCommR,ParitionID∗86+j)modN
    • digest_index=ParitionID∗86+jc8∗j+7,⋯ ,c8∗j=Poseidon–128(NewCommR,digest_index) mod N\text{digest\_index} = ParitionID*86+j \\ c_{8*j+7},\cdots ,c_{8*j} = \text{Poseidon–128}(\text{NewCommR}, \text{digest\_index}) \bmod Ndigest_index=ParitionID∗86+jc8∗j+7​,⋯,c8∗j​=Poseidon–128(NewCommR,digest_index)modN

      Consists of one 2-ary Poseidon Hash and binary decomposition, binary decomposition allows to take the mod N\text{mod}\ Nmod N .

    For each i∈[0,C)i \in [0, C)i∈[0,C) following sub-circuit is created:

    • ρ\rhoρ Generation: ρci=Poseidon–128(ϕ,⌊ci∗HN⌋)\rho_{c_i} = \text{Poseidon–128}(\phi, \lfloor \frac{c_i*H}{N} \rfloor)ρci​​=Poseidon–128(ϕ,⌊Nci​∗H​⌋)
    • The ⌊ciHN⌋\lfloor \frac{c_iH}{N} \rfloor⌊Nci​H​⌋ can be constructed from binary decomposition of cic_ici​.

      To increase flexibility of the circuit at minimal cost we are suggesting ability to adjust HHH value based on public input.

      This can be easily done in circuit by having 5 computations of ⌊ci∗Hs[i]N⌋\lfloor \frac{c_i*Hs[i]}{N} \rfloor⌊Nci​∗Hs[i]​⌋ (one for each hSelecthSelecthSelect value), which are just linear combinations of decomposed cic_ici​ bits, and then selecting them based on the one-hot encoding of hSelect public input.

      ⌊ciHN⌋=∑k=05hSelect[k]⋅⌊ci⋅Hs[k]N⌋=∑k=05hSelect[k]⋅(ci≫(log⁡2N−log⁡2Hs[k]))\lfloor \frac{c_iH}{N} \rfloor = \sum_{k=0}^{5}hSelect[k] \cdot \lfloor \frac{c_i \cdot Hs[k]}{N} \rfloor = \\ \sum_{k=0}^{5}hSelect[k]\cdot \big( c_i \gg (\log_2N - \log_2{Hs[k]}) \big)⌊Nci​H​⌋=k=0∑5​hSelect[k]⋅⌊Nci​⋅Hs[k]​⌋=k=0∑5​hSelect[k]⋅(ci​≫(log2​N−log2​Hs[k]))

      If we do shared circuit for 32GB and 64GB, the condition or flag will need to feed into this circuit.

    • Inclusion proofs:
      • RciR_{c_i}Rci​​ is opening of OldCommR at position cic_ici​
      • Rci∗R^{*}_{c_i}Rci​∗​ is opening of NewCommR at position cic_ici​
      • DciD_{c_i}Dci​​is opening of CommD at position cic_ici​
    • Encoding Check: Rci∗=Rci+Dci∗ρciR^{*}_{c_i} = R_{c_i} + D_{c_i} * \rho_{c_i}Rci​∗​=Rci​​+Dci​​∗ρci​​ computed in Fr\text{F}rFr.
    image

    CryptoNet is a Protocol Labs initiative.