Skip to content

Commit

Permalink
feat: remove offset shifts in plonk compile
Browse files Browse the repository at this point in the history
  • Loading branch information
gbotrel committed Mar 9, 2022
1 parent 12f8a25 commit 121b111
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 84 deletions.
2 changes: 1 addition & 1 deletion frontend/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func parseCircuit(builder Builder, circuit Circuit) (err error) {
}
// recursively parse through reflection the circuits members to find all Constraints that need to be allocated
// (secret or public inputs)
s, err = schema.Parse(circuit, tVariable, handler)
_, err = schema.Parse(circuit, tVariable, handler)
if err != nil {
return err
}
Expand Down
100 changes: 17 additions & 83 deletions frontend/cs/scs/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func (system *scs) addPlonkConstraint(l, r, o compiled.Term, cidl, cidr, cidm1,
// newInternalVariable creates a new wire, appends it on the list of wires of the circuit, sets
// the wire's id to the number of wires, and returns it
func (system *scs) newInternalVariable() compiled.Term {
idx := system.NbInternalVariables
idx := system.NbInternalVariables + system.NbPublicVariables + system.NbSecretVariables
system.NbInternalVariables++
return compiled.Pack(idx, compiled.CoeffIdOne, schema.Internal)
}
Expand All @@ -119,7 +119,7 @@ func (system *scs) AddPublicVariable(name string) frontend.Variable {

// AddSecretVariable creates a new Secret Variable
func (system *scs) AddSecretVariable(name string) frontend.Variable {
idx := len(system.Secret)
idx := len(system.Secret) + system.NbPublicVariables
system.Secret = append(system.Secret, name)
return compiled.Pack(idx, compiled.CoeffIdOne, schema.Secret)
}
Expand Down Expand Up @@ -217,14 +217,19 @@ func (system *scs) checkVariables() error {
cptPublic--
}
case schema.Secret:
vID -= system.NbPublicVariables
if !secretConstrained[vID] {
secretConstrained[vID] = true
cptSecret--
}
case schema.Internal:
if _, ok := system.MHints[vID]; !mHintsConstrained[vID] && ok {
mHintsConstrained[vID] = true
cptHints--
if _, ok := system.MHints[vID]; ok {
vID -= (system.NbPublicVariables + system.NbSecretVariables)
if !mHintsConstrained[vID] {
mHintsConstrained[vID] = true
cptHints--
}

}
}
}
Expand Down Expand Up @@ -301,86 +306,13 @@ func (cs *scs) Compile() (frontend.CompiledConstraintSystem, error) {
ConstraintSystem: cs.ConstraintSystem,
Constraints: cs.Constraints,
}
res.NbPublicVariables = len(cs.Public)
res.NbSecretVariables = len(cs.Secret)

// Logs, DebugInfo and hints are copied, the only thing that will change
// is that ID of the wires will be offseted to take into account the final wire vector ordering
// that is: public wires | secret wires | internal wires

// shift variable ID
// we want publicWires | privateWires | internalWires
shiftVID := func(oldID int, visibility schema.Visibility) int {
switch visibility {
case schema.Internal:
return oldID + res.NbPublicVariables + res.NbSecretVariables
case schema.Public:
return oldID
case schema.Secret:
return oldID + res.NbPublicVariables
default:
return oldID
}
}

offsetTermID := func(t *compiled.Term) {
_, VID, visibility := t.Unpack()
t.SetWireID(shiftVID(VID, visibility))
}

// offset the IDs of all constraints so that the variables are
// numbered like this: [publicVariables | secretVariables | internalVariables ]
for i := 0; i < len(res.Constraints); i++ {
r1c := &res.Constraints[i]
offsetTermID(&r1c.L)
offsetTermID(&r1c.R)
offsetTermID(&r1c.O)
offsetTermID(&r1c.M[0])
offsetTermID(&r1c.M[1])
}

// we need to offset the ids in Logs & DebugInfo
for i := 0; i < len(cs.Logs); i++ {
for j := 0; j < len(res.Logs[i].ToResolve); j++ {
offsetTermID(&res.Logs[i].ToResolve[j])
}
// sanity check
if res.NbPublicVariables != len(cs.Public) || res.NbPublicVariables != cs.Schema.NbPublic {
panic("number of public variables is inconsitent") // it grew after the schema parsing?
}
for i := 0; i < len(cs.DebugInfo); i++ {
for j := 0; j < len(res.DebugInfo[i].ToResolve); j++ {
offsetTermID(&res.DebugInfo[i].ToResolve[j])
}
}

// we need to offset the ids in the hints
shiftedMap := make(map[int]*compiled.Hint)
HINTLOOP:
for _, hint := range cs.MHints {
ws := make([]int, len(hint.Wires))
// we set for all outputs in shiftedMap. If one shifted output
// is in shiftedMap, then all are
for i, vID := range hint.Wires {
ws[i] = shiftVID(vID, schema.Internal)
if _, ok := shiftedMap[ws[i]]; i == 0 && ok {
continue HINTLOOP
}
}
inputs := make([]interface{}, len(hint.Inputs))
copy(inputs, hint.Inputs)
for j := 0; j < len(inputs); j++ {
switch t := inputs[j].(type) {
case compiled.Term:
offsetTermID(&t)
inputs[j] = t // TODO check if we can remove it
default:
inputs[j] = t
}
}
ch := &compiled.Hint{ID: hint.ID, Inputs: inputs, Wires: ws}
for _, vID := range ws {
shiftedMap[vID] = ch
}
if res.NbSecretVariables != len(cs.Secret) || res.NbSecretVariables != cs.Schema.NbSecret {
panic("number of secret variables is inconsitent") // it grew after the schema parsing?
}
res.MHints = shiftedMap

// build levels
res.Levels = buildLevels(res)
Expand Down Expand Up @@ -409,6 +341,8 @@ func (cs *scs) SetSchema(s *schema.Schema) {
panic("SetSchema called multiple times")
}
cs.Schema = s
cs.NbPublicVariables = s.NbPublic
cs.NbSecretVariables = s.NbSecret
}

func buildLevels(ccs compiled.SparseR1CS) [][]int {
Expand Down

0 comments on commit 121b111

Please sign in to comment.