Skip to content

Commit fc09d7f

Browse files
committed
fix bugs
1 parent be09523 commit fc09d7f

File tree

17 files changed

+98
-75
lines changed

17 files changed

+98
-75
lines changed

ecgo/builder/api.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ func (builder *builder) MulAcc(a, b, c frontend.Variable) frontend.Variable {
4545
}
4646

4747
// Sub computes the difference between the given variables.
48+
// When more than two variables are provided, the difference is computed as i1 - Σ(i2...).
4849
func (builder *builder) Sub(i1, i2 frontend.Variable, in ...frontend.Variable) frontend.Variable {
4950
vars := builder.toVariableIds(append([]frontend.Variable{i1, i2}, in...)...)
5051
return builder.add(vars, true)
@@ -142,6 +143,8 @@ func (builder *builder) ToBinary(i1 frontend.Variable, n ...int) []frontend.Vari
142143
if nbBits < 0 {
143144
panic("invalid n")
144145
}
146+
} else {
147+
panic("only one argument is supported")
145148
}
146149

147150
return bits.ToBinary(builder, i1, bits.WithNbDigits(nbBits))

ecgo/builder/builder.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ func (builder *builder) Compile() (constraint.ConstraintSystem, error) {
104104
return nil, nil
105105
}
106106

107-
// ConstantValue returns the big.Int value of v and panics if v is not a constant.
107+
// ConstantValue returns always returns (nil, false) now, since the Golang frontend doesn't know the values of variables.
108108
func (builder *builder) ConstantValue(v frontend.Variable) (*big.Int, bool) {
109109
return nil, false
110110
}
@@ -154,8 +154,6 @@ func (builder *builder) toVariableIds(in ...frontend.Variable) []int {
154154
v := builder.toVariableId(i)
155155
r = append(r, v)
156156
}
157-
// e(i1)
158-
// e(i2)
159157
for i := 0; i < len(in); i++ {
160158
e(in[i])
161159
}

ecgo/builder/finalize.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package builder
22

33
import (
4+
"fmt"
5+
46
"github.com/PolyhedraZK/ExpanderCompilerCollection/ecgo/irsource"
57
)
68

@@ -25,7 +27,7 @@ func (builder *builder) Finalize() *irsource.Circuit {
2527
cb := builder.defers[i]
2628
err := cb(builder)
2729
if err != nil {
28-
panic(err)
30+
panic(fmt.Sprintf("deferred function failed: %v", err))
2931
}
3032
}
3133

ecgo/builder/sub_circuit.go

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ type SubCircuit struct {
3232
type SubCircuitRegistry struct {
3333
m map[uint64]*SubCircuit
3434
outputStructure map[uint64]*sliceStructure
35+
fullHash map[uint64][32]byte
3536
}
3637

3738
// SubCircuitAPI defines methods for working with subcircuits.
@@ -44,9 +45,22 @@ func newSubCircuitRegistry() *SubCircuitRegistry {
4445
return &SubCircuitRegistry{
4546
m: make(map[uint64]*SubCircuit),
4647
outputStructure: make(map[uint64]*sliceStructure),
48+
fullHash: make(map[uint64][32]byte),
4749
}
4850
}
4951

52+
func (sr *SubCircuitRegistry) getFullHashId(h [32]byte) uint64 {
53+
id := binary.LittleEndian.Uint64(h[:8])
54+
if v, ok := sr.fullHash[id]; ok {
55+
if v != h {
56+
panic("subcircuit id collision")
57+
}
58+
return id
59+
}
60+
sr.fullHash[id] = h
61+
return id
62+
}
63+
5064
func (parent *builder) callSubCircuit(
5165
circuitId uint64,
5266
input_ []frontend.Variable,
@@ -93,7 +107,7 @@ func (parent *builder) callSubCircuit(
93107
func (parent *builder) MemorizedSimpleCall(f SubCircuitSimpleFunc, input []frontend.Variable) []frontend.Variable {
94108
name := GetFuncName(f)
95109
h := sha256.Sum256([]byte(fmt.Sprintf("simple_%d(%s)_%d", len(name), name, len(input))))
96-
circuitId := binary.LittleEndian.Uint64(h[:8])
110+
circuitId := parent.root.registry.getFullHashId(h)
97111
return parent.callSubCircuit(circuitId, input, f)
98112
}
99113

@@ -205,13 +219,10 @@ func rebuildSliceVariables(vars []frontend.Variable, s *sliceStructure) reflect.
205219
func isTypeSimple(t reflect.Type) bool {
206220
k := t.Kind()
207221
switch k {
208-
case reflect.Bool:
209-
return true
210-
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
211-
return true
212-
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
213-
return true
214-
case reflect.String:
222+
case reflect.Bool,
223+
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
224+
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
225+
reflect.String:
215226
return true
216227
default:
217228
return false
@@ -310,7 +321,9 @@ func (parent *builder) MemorizedCall(fn SubCircuitFunc, inputs ...interface{}) i
310321
vs := inputVals[i].String()
311322
h.Write([]byte(strconv.Itoa(len(vs)) + vs))
312323
}
313-
circuitId := binary.LittleEndian.Uint64(h.Sum(nil)[:8])
324+
var tmp [32]byte
325+
copy(tmp[:], h.Sum(nil))
326+
circuitId := parent.root.registry.getFullHashId(tmp)
314327

315328
// sub-circuit caller
316329
fnInner := func(api frontend.API, input []frontend.Variable) []frontend.Variable {

ecgo/field/bn254/field_wrapper.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,16 @@ func (engine *Field) Inverse(a constraint.Element) (constraint.Element, bool) {
8080
return a, false
8181
} else if e.IsOne() {
8282
return a, true
83-
}
84-
var t fr.Element
85-
t.Neg(e)
86-
if t.IsOne() {
83+
} else {
84+
var t fr.Element
85+
t.Neg(e)
86+
if t.IsOne() {
87+
return a, true
88+
}
89+
90+
e.Inverse(e)
8791
return a, true
8892
}
89-
90-
e.Inverse(e)
91-
return a, true
9293
}
9394

9495
func (engine *Field) IsOne(a constraint.Element) bool {

ecgo/field/m31/field.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
"github.com/consensys/gnark/constraint"
99
)
1010

11-
const P = 2147483647
11+
const P = 0x7fffffff
1212

1313
var Pbig = big.NewInt(P)
1414
var ScalarField = Pbig

ecgo/irwg/witness_gen.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,9 @@ func (rc *RootCircuit) evalSub(circuitId uint64, inputs []constraint.Element, pu
194194
func callHint(hintId uint64, field *big.Int, inputs []*big.Int, outputs []*big.Int) error {
195195
// The only required builtin hint (Div)
196196
if hintId == 0xCCC000000001 {
197+
if len(inputs) != 2 || len(outputs) != 1 {
198+
return errors.New("Div hint requires 2 inputs and 1 output")
199+
}
197200
x := (&big.Int{}).Mod(inputs[0], field)
198201
y := (&big.Int{}).Mod(inputs[1], field)
199202
if y.Cmp(big.NewInt(0)) == 0 {

ecgo/layered/serialize.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"github.com/PolyhedraZK/ExpanderCompilerCollection/ecgo/utils"
99
)
1010

11+
const MAGIC = 3914834606642317635
12+
1113
func serializeCoef(o *utils.OutputBuf, bnlen int, coef *big.Int, coefType uint8, publicInputId uint64) {
1214
if coefType == 1 {
1315
o.AppendUint8(1)
@@ -35,7 +37,7 @@ func deserializeCoef(in *utils.InputBuf, bnlen int) (*big.Int, uint8, uint64) {
3537
func (rc *RootCircuit) Serialize() []byte {
3638
bnlen := field.GetFieldFromOrder(rc.Field).SerializedLen()
3739
o := utils.OutputBuf{}
38-
o.AppendUint64(3914834606642317635)
40+
o.AppendUint64(MAGIC)
3941
o.AppendBigInt(32, rc.Field)
4042
o.AppendUint64(uint64(rc.NumPublicInputs))
4143
o.AppendUint64(uint64(rc.NumActualOutputs))
@@ -91,7 +93,7 @@ func (rc *RootCircuit) Serialize() []byte {
9193

9294
func DeserializeRootCircuit(buf []byte) *RootCircuit {
9395
in := utils.NewInputBuf(buf)
94-
if in.ReadUint64() != 3914834606642317635 {
96+
if in.ReadUint64() != MAGIC {
9597
panic("invalid file header")
9698
}
9799
rc := &RootCircuit{}
@@ -178,7 +180,7 @@ func DetectFieldIdFromFile(fn string) uint64 {
178180
panic(err)
179181
}
180182
in := utils.NewInputBuf(buf)
181-
if in.ReadUint64() != 3914834606642317635 {
183+
if in.ReadUint64() != MAGIC {
182184
panic("invalid file header")
183185
}
184186
f := in.ReadBigInt(32)

ecgo/utils/buf.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package utils
22

33
import (
44
"encoding/binary"
5+
"fmt"
56
"math/big"
67

78
"github.com/consensys/gnark/constraint"
@@ -20,12 +21,12 @@ type SimpleField interface {
2021
func (o *OutputBuf) AppendBigInt(n int, x *big.Int) {
2122
zbuf := make([]byte, n)
2223
b := x.Bytes()
24+
if len(b) > n {
25+
panic(fmt.Sprintf("big.Int is too large to serialize: %d > %d", len(b), n))
26+
}
2327
for i := 0; i < len(b); i++ {
2428
zbuf[i] = b[len(b)-i-1]
2529
}
26-
for i := len(b); i < n; i++ {
27-
zbuf[i] = 0
28-
}
2930
o.buf = append(o.buf, zbuf...)
3031
}
3132

@@ -53,7 +54,9 @@ func (o *OutputBuf) AppendIntSlice(x []int) {
5354
}
5455

5556
func (o *OutputBuf) Bytes() []byte {
56-
return o.buf
57+
res := o.buf
58+
o.buf = nil
59+
return res
5760
}
5861

5962
type InputBuf struct {

ecgo/utils/map.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func (m Map) Set(e Hashable, v interface{}) {
4646
})
4747
}
4848

49-
// adds (e, v) to the map, does nothing when e already exists
49+
// adds (e, v) to the map, returns the current value when e already exists
5050
func (m Map) Add(e Hashable, v interface{}) interface{} {
5151
h := e.HashCode()
5252
s, ok := m[h]
@@ -66,7 +66,7 @@ func (m Map) Add(e Hashable, v interface{}) interface{} {
6666
return v
6767
}
6868

69-
// filter keys in the map using the given function
69+
// filter (e, v) in the map using f(v), returns the keys
7070
func (m Map) FilterKeys(f func(interface{}) bool) []Hashable {
7171
keys := []Hashable{}
7272
for _, s := range m {

0 commit comments

Comments
 (0)