Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
f4c226e
Update test programs
ilitteri Mar 17, 2023
c34d2a0
Remove test program
ilitteri Mar 17, 2023
84168be
Merge branch 'main' of github.com:lambdaclass/noir_backend_using_gnar…
ilitteri Mar 17, 2023
db02fac
Remove test program
ilitteri Mar 17, 2023
5da78de
Remove test program
ilitteri Mar 17, 2023
0fe4cba
Remove test program
ilitteri Mar 17, 2023
a0fa660
Handle Directive opcodes correctly
ilitteri Mar 17, 2023
e52ea33
Handle `BlackBoxFunction` opcodes unmarshal
ilitteri Mar 17, 2023
aa0fe58
Refactor `Arithmetic` opcode unmarshaling
ilitteri Mar 17, 2023
ce7aed3
Change types visibility
ilitteri Mar 17, 2023
bef6ec9
`handleBlackBoxFunctionOpcode`
ilitteri Mar 17, 2023
1d17777
Abstract `ArithmeticOpcode` handling
ilitteri Mar 17, 2023
63d2dcf
Reorder functions
ilitteri Mar 17, 2023
f094f24
Handle each black box function case
ilitteri Mar 17, 2023
b93b61d
Handle some black box functions
ilitteri Mar 20, 2023
2996fa1
cargo fmt
ilitteri Mar 20, 2023
292f6d3
Update which black box functions we support
ilitteri Mar 21, 2023
89f2ce9
Separate local imports from std imports
ilitteri Mar 21, 2023
34a828b
Fix `BlackBoxFunction`'s `UnmarshalJSON`
ilitteri Mar 21, 2023
0cfb20c
Fix `Opcode`'s `UnmarshalJSON`
ilitteri Mar 21, 2023
c55ccfc
Update components
ilitteri Mar 21, 2023
ff46497
`FixedBaseScalarMul` is not supported yet
ilitteri Mar 22, 2023
56f8e93
`assertIsBoolean` component (#71)
ilitteri Mar 27, 2023
a100932
`And` component (#72)
ilitteri Mar 30, 2023
69ccd6f
`Xor` component (#73)
ilitteri Mar 30, 2023
0c97afe
Integrate `AND` and `XOR` black box functions (#75)
ilitteri Mar 30, 2023
d91495c
`assertIsInRange` component (#79)
ilitteri Mar 31, 2023
15fb7d4
Merge branch 'main' of github.com:lambdaclass/noir_backend_using_gnar…
ilitteri Mar 8, 2024
7aeec13
Fix merge error
ilitteri Mar 8, 2024
0aabeb0
Fix merge error
ilitteri Mar 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ build-go:
# Temporary solution for testing the only tests we have. We should test recurively.
test-go:
$ cd ${FFI_LIB_PATH}; \
go test -run '' gnark_backend_ffi/backend/groth16; \
go test -run '' gnark_backend_ffi/backend/plonk
go test -run '' gnark_backend_ffi/backend/plonk/components

build: build-go
$ RUSTFLAGS="-L${FFI_LIB_PATH}" cargo build
Expand Down
44 changes: 39 additions & 5 deletions gnark_backend_ffi/backend/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import (
"crypto/rand"
"encoding/hex"
"fmt"
"gnark_backend_ffi/acir"
"io/ioutil"
"log"
"math/big"
"os"

"gnark_backend_ffi/acir"

"github.com/consensys/gnark-crypto/ecc"
fr_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/fr"
"github.com/consensys/gnark-crypto/ecc/bn254/fr/kzg"
Expand All @@ -19,6 +20,35 @@ import (
"github.com/consensys/gnark/constraint"
)

type Context struct {
Circuit acir.ACIR
// TODO: this should probably be a constraint.System in order to be able to
// use more backends.
ConstraintSystem constraint.SparseR1CS
PublicVariables fr_bn254.Vector
SecretVariables fr_bn254.Vector
Variables fr_bn254.Vector
VariablesMap map[string]int
}

func NewContext(circuit acir.ACIR, cs constraint.SparseR1CS, publicVariables fr_bn254.Vector, secretVariables fr_bn254.Vector, variables fr_bn254.Vector, variablesMap map[string]int) *Context {
return &Context{
Circuit: circuit,
ConstraintSystem: cs,
PublicVariables: publicVariables,
SecretVariables: secretVariables,
Variables: variables,
VariablesMap: variablesMap,
}
}

func (ctx *Context) AddSecretVariable(name string, value fr_bn254.Element) (variableIndex int) {
variableIndex = ctx.ConstraintSystem.AddSecretVariable(name)
ctx.SecretVariables = append(ctx.SecretVariables, value)
ctx.Variables = append(ctx.Variables, value)
return
}

func BuildWitnesses(scalarField *big.Int, publicVariables fr_bn254.Vector, privateVariables fr_bn254.Vector, nbPublicVariables int, nbSecretVariables int) witness.Witness {
witnessValues := make(chan any)

Expand All @@ -42,12 +72,12 @@ func BuildWitnesses(scalarField *big.Int, publicVariables fr_bn254.Vector, priva
return witness
}

func HandleValues(a acir.ACIR, cs constraint.ConstraintSystem, values fr_bn254.Vector) (publicVariables fr_bn254.Vector, secretVariables fr_bn254.Vector, indexMap map[string]int) {
func HandleValues(cs constraint.ConstraintSystem, values fr_bn254.Vector, publicInputsIndices []uint32) (publicVariables fr_bn254.Vector, secretVariables fr_bn254.Vector, variables fr_bn254.Vector, indexMap map[string]int) {
indexMap = make(map[string]int)
var index int
for i, value := range values {
i++
for _, publicInput := range a.PublicInputs {
for _, publicInput := range publicInputsIndices {
if uint32(i) == publicInput {
index = cs.AddPublicVariable(fmt.Sprintf("public_%d", i))
publicVariables = append(publicVariables, value)
Expand All @@ -58,8 +88,8 @@ func HandleValues(a acir.ACIR, cs constraint.ConstraintSystem, values fr_bn254.V
}
for i, value := range values {
i++
if len(a.PublicInputs) > 0 {
for _, publicInput := range a.PublicInputs {
if len(publicInputsIndices) > 0 {
for _, publicInput := range publicInputsIndices {
if uint32(i) != publicInput {
index = cs.AddSecretVariable(fmt.Sprintf("secret_%d", i))
secretVariables = append(secretVariables, value)
Expand All @@ -72,6 +102,10 @@ func HandleValues(a acir.ACIR, cs constraint.ConstraintSystem, values fr_bn254.V
indexMap[fmt.Sprint(i)] = index
}
}

variables = append(variables, publicVariables...)
variables = append(variables, secretVariables...)

return
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,35 @@
package plonk_backend

import (
acir_opcode "gnark_backend_ffi/acir/opcode"
"gnark_backend_ffi/backend"
)

// AES black box function call is not handled
func AES() {}

// AND black box function call is not handled
func AND() {}
func AND(ctx *backend.Context, bbf *acir_opcode.BlackBoxFunction) {
lhs := int(bbf.Inputs[0].Witness)
rhs := int(bbf.Inputs[1].Witness)
bits := int(bbf.Inputs[0].NumBits)

And(lhs, rhs, bits, ctx)
}

func XOR(ctx *backend.Context, bbf *acir_opcode.BlackBoxFunction) {
lhs := int(bbf.Inputs[0].Witness)
rhs := int(bbf.Inputs[1].Witness)
bits := int(bbf.Inputs[0].NumBits)

Xor(lhs, rhs, bits, ctx)
}

// XOR black box function call is not handled
func XOR() {}
func Range(ctx *backend.Context, bbf *acir_opcode.BlackBoxFunction) {
felt := int(bbf.Inputs[0].Witness)
bits := int(bbf.Inputs[0].NumBits)

// RANGE black box function call is not handled
func Range() {}
assertIsInRange(felt, bits, ctx)
}

// SHA256 black box function call is not handled
func SHA256() {}
Expand Down
127 changes: 127 additions & 0 deletions gnark_backend_ffi/backend/plonk/components/arithmetic_operations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package components

import (
"fmt"
"gnark_backend_ffi/backend"

fr_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/fr"
"github.com/consensys/gnark/constraint"
cs_bn254 "github.com/consensys/gnark/constraint/bn254"
)

// Generates constraints for adding two values.
//
// It generates one Plonk constraint.
//
// augend is the index of the augend in the values vector.
// addend is the index of the addend in the values vector.
// sparseR1CS is the constraint system being mutated.
// secretVariables is the values vector.
//
// Returns a tuple with the index of the result of the operation in the values
// vector and the updated values vector.
func add(augend int, addend int, ctx *backend.Context) int {
var xa, xb, xc int
var qL, qR, qO, qM1, qM2 constraint.Coeff

qL = ctx.ConstraintSystem.One()
xa = augend
qR = ctx.ConstraintSystem.One()
xb = addend
qO = ctx.ConstraintSystem.FromInterface(-1)
var sum fr_bn254.Element
sum.Add(&ctx.Variables[augend], &ctx.Variables[addend])
// TODO: Remove the interface casting.
variableName := fmt.Sprintf("(%s+%s)", ctx.ConstraintSystem.(*cs_bn254.SparseR1CS).VariableToString(augend), ctx.ConstraintSystem.(*cs_bn254.SparseR1CS).VariableToString(addend))
xc = ctx.AddSecretVariable(variableName, sum)

addConstraint := constraint.SparseR1C{
L: ctx.ConstraintSystem.MakeTerm(&qL, xa),
R: ctx.ConstraintSystem.MakeTerm(&qR, xb),
O: ctx.ConstraintSystem.MakeTerm(&qO, xc),
M: [2]constraint.Term{ctx.ConstraintSystem.MakeTerm(&qM1, xa), ctx.ConstraintSystem.MakeTerm(&qM2, xb)},
K: constraint.CoeffIdZero,
}

ctx.ConstraintSystem.AddConstraint(addConstraint)

return xc
}

// Generates constraints for multiplying two values.
//
// It generates one Plonk constraint.
//
// augend is the index of the augend in the values vector.
// addend is the index of the addend in the values vector.
// sparseR1CS is the constraint system being mutated.
// secretVariables is the values vector.
//
// Returns a tuple with the index of the result of the operation in the values
// vector and the updated values vector.
func mul(multiplicand int, multiplier int, ctx *backend.Context) int {
var xa, xb, xc int
var qL, qR, qO, qM1, qM2 constraint.Coeff

qM1 = ctx.ConstraintSystem.One()
qM2 = ctx.ConstraintSystem.One()
xa = multiplicand
xb = multiplier
qO = ctx.ConstraintSystem.FromInterface(-1)
var product fr_bn254.Element
product.Mul(&ctx.Variables[multiplicand], &ctx.Variables[multiplier])
// TODO: Remove the interface casting.
variableName := fmt.Sprintf("(%s*%s)", ctx.ConstraintSystem.(*cs_bn254.SparseR1CS).VariableToString(multiplicand), ctx.ConstraintSystem.(*cs_bn254.SparseR1CS).VariableToString(multiplier))
xc = ctx.AddSecretVariable(variableName, product)

mulConstraint := constraint.SparseR1C{
L: ctx.ConstraintSystem.MakeTerm(&qL, xa),
R: ctx.ConstraintSystem.MakeTerm(&qR, xb),
O: ctx.ConstraintSystem.MakeTerm(&qO, xc),
M: [2]constraint.Term{ctx.ConstraintSystem.MakeTerm(&qM1, xa), ctx.ConstraintSystem.MakeTerm(&qM2, xb)},
K: constraint.CoeffIdZero,
}

ctx.ConstraintSystem.AddConstraint(mulConstraint)

return xc
}

// Generates constraints for subtracting two values.
//
// It generates one Plonk constraint.
//
// minuend is the index of the minuend in the values vector.
// subtrahend is the index of the subtrahend in the values vector.
// sparseR1CS is the constraint system being mutated.
// secretVariables is the values vector.
//
// Returns a tuple with the index of the result of the operation in the values
// vector and the updated values vector.
func sub(minuend int, subtrahend int, ctx *backend.Context) int {
var xa, xb, xc int
var qL, qR, qO, qM1, qM2 constraint.Coeff

qL = ctx.ConstraintSystem.One()
xa = minuend
qR = ctx.ConstraintSystem.FromInterface(-1)
xb = subtrahend
qO = ctx.ConstraintSystem.FromInterface(-1)
var difference fr_bn254.Element
difference.Sub(&ctx.Variables[minuend], &ctx.Variables[subtrahend])
// TODO: Remove the interface casting.
variableName := fmt.Sprintf("(%s-%s)", ctx.ConstraintSystem.(*cs_bn254.SparseR1CS).VariableToString(minuend), ctx.ConstraintSystem.(*cs_bn254.SparseR1CS).VariableToString(subtrahend))
xc = ctx.AddSecretVariable(variableName, difference)

addConstraint := constraint.SparseR1C{
L: ctx.ConstraintSystem.MakeTerm(&qL, xa),
R: ctx.ConstraintSystem.MakeTerm(&qR, xb),
O: ctx.ConstraintSystem.MakeTerm(&qO, xc),
M: [2]constraint.Term{ctx.ConstraintSystem.MakeTerm(&qM1, xa), ctx.ConstraintSystem.MakeTerm(&qM2, xb)},
K: constraint.CoeffIdZero,
}

ctx.ConstraintSystem.AddConstraint(addConstraint)

return xc
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package components

import (
"gnark_backend_ffi/acir"
"gnark_backend_ffi/backend"
"testing"

fr_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/fr"
cs_bn254 "github.com/consensys/gnark/constraint/bn254"
"github.com/stretchr/testify/assert"
)

func TestAddComponent(t *testing.T) {
values := fr_bn254.Vector{fr_bn254.NewElement(3), fr_bn254.NewElement(2)}
sparseR1CS := cs_bn254.NewSparseR1CS(1)
expectedResult := fr_bn254.NewElement(5)

publicVariables, secretVariables, variables, variablesMap := backend.HandleValues(sparseR1CS, values, []uint32{})
ctx := backend.NewContext(acir.ACIR{}, sparseR1CS, publicVariables, secretVariables, variables, variablesMap)

result := add(0, 1, ctx)
assert.Equal(t, expectedResult, ctx.Variables[result])
result = add(1, 0, ctx)
assert.Equal(t, expectedResult, ctx.Variables[result])

assertThatProvingAndVerifyingSucceeds(t, ctx)
}

func TestMulComponent(t *testing.T) {
values := fr_bn254.Vector{fr_bn254.NewElement(2), fr_bn254.NewElement(3)}
sparseR1CS := cs_bn254.NewSparseR1CS(1)
expectedResult := fr_bn254.NewElement(6)

publicVariables, secretVariables, variables, variablesMap := backend.HandleValues(sparseR1CS, values, []uint32{})
ctx := backend.NewContext(acir.ACIR{}, sparseR1CS, publicVariables, secretVariables, variables, variablesMap)

result := mul(0, 1, ctx)
assert.Equal(t, expectedResult, ctx.Variables[result])
result = mul(1, 0, ctx)
assert.Equal(t, expectedResult, ctx.Variables[result])

assertThatProvingAndVerifyingSucceeds(t, ctx)
}

func TestSubComponent(t *testing.T) {
values := fr_bn254.Vector{fr_bn254.NewElement(3), fr_bn254.NewElement(2)}
sparseR1CS := cs_bn254.NewSparseR1CS(1)
negativeOne := fr_bn254.Element{10902020042510041094, 17381486299841078119, 5900175412809962030, 2475245527108272378}

publicVariables, secretVariables, variables, variablesMap := backend.HandleValues(sparseR1CS, values, []uint32{})
ctx := backend.NewContext(acir.ACIR{}, sparseR1CS, publicVariables, secretVariables, variables, variablesMap)

// 3 - 2 = 1
result := sub(0, 1, ctx)
assert.Equal(t, fr_bn254.One(), ctx.Variables[result])
// 2 - 2 = 0
result = sub(0, 0, ctx)
assert.Equal(t, fr_bn254.NewElement(0), ctx.Variables[result])
// 2 - 3 = -1
result = sub(1, 0, ctx)
assert.Equal(t, negativeOne, ctx.Variables[result])

assertThatProvingAndVerifyingSucceeds(t, ctx)
}
Loading