Skip to content

Commit

Permalink
RandomEcPoint Hint Implementation (#177)
Browse files Browse the repository at this point in the history
* added UpdatePc tests and fixed a bug in UpdatePc

* Fixed accessing field value without Read()

* fixed failing tests

* small refactor for TestUpdatePcJump

* randomEcPoint done

* move comment

* move randomizers into utils.go

* address PR comments
  • Loading branch information
mmk-1 authored Dec 5, 2023
1 parent cbad665 commit 54a1d21
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 23 deletions.
59 changes: 58 additions & 1 deletion pkg/hintrunner/hint.go
Original file line number Diff line number Diff line change
Expand Up @@ -1230,7 +1230,6 @@ func (hint *AssertLeFindSmallArc) Execute(vm *VM.VirtualMachine, ctx *HintRunner
return nil
}


type AssertLeIsFirstArcExcluded struct {
skipExcludeAFlag CellRefer
}
Expand Down Expand Up @@ -1278,3 +1277,61 @@ func (hint *AssertLeIsSecondArcExcluded) Execute(vm *VM.VirtualMachine, ctx *Hin

return vm.Memory.WriteToAddress(&addr, &writeValue)
}

type RandomEcPoint struct {
x CellRefer
y CellRefer
}

func (hint *RandomEcPoint) String() string {
return "RandomEc"
}

func (hint *RandomEcPoint) Execute(vm *VM.VirtualMachine) error {
// Keep sampling a random field element `X` until `X^3 + X + beta` is a quadratic residue.

// Starkware's elliptic curve Beta value https://docs.starkware.co/starkex/crypto/stark-curve.html
betaFelt := f.Element{3863487492851900874, 7432612994240712710, 12360725113329547591, 88155977965380735}

var randomX, randomYSquared f.Element
rand := defaultRandGenerator()
for {
randomX = randomFeltElement(rand)
randomYSquared = f.Element{}
randomYSquared.Square(&randomX)
randomYSquared.Mul(&randomYSquared, &randomX)
randomYSquared.Add(&randomYSquared, &randomX)
randomYSquared.Add(&randomYSquared, &betaFelt)
// Legendre == 1 -> Quadratic residue
// Legendre == -1 -> Quadratic non-residue
// Legendre == 0 -> Zero
if randomYSquared.Legendre() == 1 {
break
}
}

xVal := mem.MemoryValueFromFieldElement(&randomX)
yVal := mem.MemoryValueFromFieldElement(randomYSquared.Square(&randomYSquared))

xAddr, err := hint.x.Get(vm)
if err != nil {
return fmt.Errorf("get register x %s: %w", hint.x, err)
}

err = vm.Memory.WriteToAddress(&xAddr, &xVal)
if err != nil {
return fmt.Errorf("write to address x %s: %w", xVal, err)
}

yAddr, err := hint.y.Get(vm)
if err != nil {
return fmt.Errorf("get register y %s: %w", hint.y, err)
}

err = vm.Memory.WriteToAddress(&yAddr, &yVal)
if err != nil {
return fmt.Errorf("write to address y %s: %w", yVal, err)
}

return nil
}
40 changes: 18 additions & 22 deletions pkg/hintrunner/hint_bechmark_test.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
package hintrunner

import (
"encoding/binary"
"math/rand"
"testing"

VM "github.com/NethermindEth/cairo-vm-go/pkg/vm"
"github.com/NethermindEth/cairo-vm-go/pkg/vm/builtins"
"github.com/NethermindEth/cairo-vm-go/pkg/vm/memory"
f "github.com/consensys/gnark-crypto/ecc/stark-curve/fp"
"github.com/stretchr/testify/assert"
)

Expand Down Expand Up @@ -338,25 +335,24 @@ func BenchmarkAssertLeFindSmallArc(b *testing.B) {

}

func randomFeltElement(rand *rand.Rand) f.Element {
b := [32]byte{}
binary.BigEndian.PutUint64(b[24:32], rand.Uint64())
binary.BigEndian.PutUint64(b[16:24], rand.Uint64())
binary.BigEndian.PutUint64(b[8:16], rand.Uint64())
//Limit to 59 bits so at max we have a 251 bit number
binary.BigEndian.PutUint64(b[0:8], rand.Uint64()>>5)
f, _ := f.BigEndian.Element(&b)
return f
}
func BenchmarkRandomEcPoint(b *testing.B) {
vm := defaultVirtualMachine()

func randomFeltElementU128(rand *rand.Rand) f.Element {
b := [32]byte{}
binary.BigEndian.PutUint64(b[24:32], rand.Uint64())
binary.BigEndian.PutUint64(b[16:24], rand.Uint64())
f, _ := f.BigEndian.Element(&b)
return f
}
b.ResetTimer()
for i := 0; i < b.N; i++ {

hint := RandomEcPoint{
x: ApCellRef(0),
y: ApCellRef(1),
}

err := hint.Execute(vm)
if err != nil {
b.Error(err)
break
}

vm.Context.Ap += 2
}

func defaultRandGenerator() *rand.Rand {
return rand.New(rand.NewSource(0))
}
28 changes: 28 additions & 0 deletions pkg/hintrunner/hint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -834,3 +834,31 @@ func TestAssertLeIsSecondArcExcluded(t *testing.T) {

require.Equal(t, expected, actual)
}

func TestRandomEcPoint(t *testing.T) {
vm := defaultVirtualMachine()
vm.Context.Ap = 0
vm.Context.Fp = 0

hint := RandomEcPoint{
x: ApCellRef(0),
y: ApCellRef(1),
}

err := hint.Execute(vm)

require.NoError(t, err)

expectedX := mem.MemoryValueFromFieldElement(
&f.Element{12217889558999792019, 3067322962467879919, 3160430244162662030, 474947714424245026},
)
expectedY := mem.MemoryValueFromFieldElement(
&f.Element{12193331470568888984, 1737428559173019240, 11500517745011090163, 245183001587853482},
)

actualX := readFrom(vm, VM.ExecutionSegment, 0)
actualY := readFrom(vm, VM.ExecutionSegment, 1)

require.Equal(t, expectedX, actualX)
require.Equal(t, expectedY, actualY)
}
25 changes: 25 additions & 0 deletions pkg/hintrunner/utils.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package hintrunner

import (
"encoding/binary"
"fmt"
"math/rand"

VM "github.com/NethermindEth/cairo-vm-go/pkg/vm"
mem "github.com/NethermindEth/cairo-vm-go/pkg/vm/memory"
Expand Down Expand Up @@ -49,3 +51,26 @@ func ResolveAsUint64(vm *VM.VirtualMachine, op ResOperander) (uint64, error) {

return uint64Value, nil
}

func randomFeltElement(rand *rand.Rand) f.Element {
b := [32]byte{}
binary.BigEndian.PutUint64(b[24:32], rand.Uint64())
binary.BigEndian.PutUint64(b[16:24], rand.Uint64())
binary.BigEndian.PutUint64(b[8:16], rand.Uint64())
//Limit to 59 bits so at max we have a 251 bit number
binary.BigEndian.PutUint64(b[0:8], rand.Uint64()>>5)
f, _ := f.BigEndian.Element(&b)
return f
}

func randomFeltElementU128(rand *rand.Rand) f.Element {
b := [32]byte{}
binary.BigEndian.PutUint64(b[24:32], rand.Uint64())
binary.BigEndian.PutUint64(b[16:24], rand.Uint64())
f, _ := f.BigEndian.Element(&b)
return f
}

func defaultRandGenerator() *rand.Rand {
return rand.New(rand.NewSource(0))
}

0 comments on commit 54a1d21

Please sign in to comment.