diff --git a/pkg/vm/builtins/modulo.go b/pkg/vm/builtins/modulo.go index 0acbf38a..795af540 100644 --- a/pkg/vm/builtins/modulo.go +++ b/pkg/vm/builtins/modulo.go @@ -412,13 +412,24 @@ func (m *ModBuiltin) fillValue(mem *memory.Memory, inputs ModBuiltinInputs, inde } } else { x, _, gcd := utils.Igcdex(b, &inputs.p) + // if gcd != 1, the known value is 0, in which case the res must be 0 if gcd.Cmp(big.NewInt(1)) != 0 { value = *new(big.Int).Div(&inputs.p, &gcd) } else { value = *new(big.Int).Mul(c, &x) value = *value.Mod(&value, &inputs.p) + tmpK, err := utils.SafeDiv(new(big.Int).Sub(new(big.Int).Mul(b, &value), c), &inputs.p) + if err != nil { + return false, err + } + if tmpK.Cmp(kBound) >= 0 { + return false, fmt.Errorf("%s builtin: ((%d * q) - %d) / %d > %d for any q > 0, such that %d * q = %d (mod %d) ", m.String(), b, c, &inputs.p, kBound, b, c, &inputs.p) + } + if tmpK.Cmp(big.NewInt(0)) < 0 { + // tmp_val + p * ((known - 1 - tmp_k) // known) + value = *value.Add(&value, new(big.Int).Mul(&inputs.p, new(big.Int).Div(new(big.Int).Sub(b, new(big.Int).Sub(&tmpK, big.NewInt(1))), b))) + } } - value = *new(big.Int).Div(c, b) } if err := m.writeNWordsValue(mem, addresses[0], value); err != nil { return false, err diff --git a/pkg/vm/builtins/modulo_test.go b/pkg/vm/builtins/modulo_test.go index 56f84bd0..d932bc82 100644 --- a/pkg/vm/builtins/modulo_test.go +++ b/pkg/vm/builtins/modulo_test.go @@ -43,7 +43,6 @@ func TestModuloBuiltin(t *testing.T) { // TODO: Once Checkwrite and InferValue are implemented, uncomment this // k, err := segment.Read(9) // require.NoError(t, err) - // fmt.Println(k) // ans, err := k.FieldElement() // require.NoError(t, err) // expected := fp.NewElement(0) @@ -185,7 +184,16 @@ func TestMulModBuiltinRunnerDivision(t *testing.T) { res1, err := checkResult(*runner, true, *big.NewInt(67), *big.NewInt(36), *big.NewInt(9)) require.NoError(t, err) require.Equal(t, big.NewInt(4), res1) - // res2, err := checkResult(*runner, true, *big.NewInt(67), *big.NewInt(138), *big.NewInt(41)) - // require.NoError(t, err) - // require.Equal(t, big.NewInt(5), res2) + res2, err := checkResult(*runner, true, *big.NewInt(67), *big.NewInt(138), *big.NewInt(41)) + require.NoError(t, err) + require.Equal(t, big.NewInt(5), res2) + res3, err := checkResult(*runner, true, *big.NewInt(67), *big.NewInt(272), *big.NewInt(41)) + require.NoError(t, err) + require.Equal(t, big.NewInt(72), res3) + res4, err := checkResult(*runner, true, *big.NewInt(67), *big.NewInt(0), *big.NewInt(0)) + require.NoError(t, err) + require.Equal(t, big.NewInt(1), res4) + res5, err := checkResult(*runner, true, *big.NewInt(66), *big.NewInt(6), *big.NewInt(3)) + require.NoError(t, err) + require.Equal(t, big.NewInt(22), res5) } diff --git a/pkg/vm/memory/memory.go b/pkg/vm/memory/memory.go index 0547752c..944c5eec 100644 --- a/pkg/vm/memory/memory.go +++ b/pkg/vm/memory/memory.go @@ -244,7 +244,6 @@ func (memory *Memory) Write(segmentIndex uint64, offset uint64, value *MemoryVal return fmt.Errorf("segment %d: unallocated", segmentIndex) } if err := memory.Segments[segmentIndex].Write(offset, value); err != nil { - fmt.Println("error in write") return fmt.Errorf("segment %d, offset %d: %w", segmentIndex, offset, err) } return nil @@ -264,7 +263,6 @@ func (memory *Memory) Read(segmentIndex uint64, offset uint64) (MemoryValue, err } mv, err := memory.Segments[segmentIndex].Read(offset) if err != nil { - fmt.Println(err) return MemoryValue{}, fmt.Errorf("segment %d, offset %d: %w", segmentIndex, offset, err) } return mv, nil