Skip to content

Commit

Permalink
NondetElementsOverTwo + NondetElementsOverTen( poseidon builtin r…
Browse files Browse the repository at this point in the history
…elated hints) (#493)

* NondetElementsOverTwo + NondetElementsOverTen

* fix hintcode

* fix hintcodes and bugs

* add unit tests

* Update poseidon.starknet_with_keccak.cairo

---------

Co-authored-by: Shourya Goel <shouryagoel10000@gmail.com>
  • Loading branch information
TAdev0 and Sh0g0-1758 committed Jun 28, 2024
1 parent 598576d commit 45da4d0
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
%builtins poseidon
from starkware.cairo.common.cairo_builtins import PoseidonBuiltin
from starkware.cairo.common.poseidon_state import PoseidonBuiltinState
from starkware.cairo.common.builtin_poseidon.poseidon import (
poseidon_hash,
poseidon_hash_single,
poseidon_hash_many,
)
from starkware.cairo.common.alloc import alloc

func main{poseidon_ptr: PoseidonBuiltin*}() {
// Hash one
let (x) = poseidon_hash_single(
218676008889449692916464780911713710628115973574242889792891157041292792362
);
assert x = 2835120893146788752888137145656423078969524407843035783270702964188823073934;
// Hash two
let (y) = poseidon_hash(1253795, 18540013156130945068);
assert y = 37282360750367388068593128053386029947772104009544220786084510532118246655;
// Hash five
let felts: felt* = alloc();
assert felts[0] = 84175983715088675913672849362079546;
assert felts[1] = 9384720329467203286234076408512594689579283578028960384690;
assert felts[2] = 291883989128409324823849293040390493094093;
assert felts[3] = 5849589438543859348593485948598349584395839402940940290490324;
assert felts[4] = 1836254780028456372728992049476335424263474849;
let (z) = poseidon_hash_many(5, felts);
assert z = 47102513329160951064697157194713013753695317629154835326726810042406974264;
return ();
}
2 changes: 2 additions & 0 deletions pkg/hintrunner/zero/hintcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ ids.multiplicities = segments.gen_arg([len(positions_dict[k]) for k in output])`
vmEnterScopeCode string = "vm_enter_scope()"
vmExitScopeCode string = "vm_exit_scope()"
findElementCode string = "array_ptr = ids.array_ptr\nelm_size = ids.elm_size\nassert isinstance(elm_size, int) and elm_size > 0, \\\n f'Invalid value for elm_size. Got: {elm_size}.'\nkey = ids.key\n\nif '__find_element_index' in globals():\n ids.index = __find_element_index\n found_key = memory[array_ptr + elm_size * __find_element_index]\n assert found_key == key, \\\n f'Invalid index found in __find_element_index. index: {__find_element_index}, ' \\\n f'expected key {key}, found key: {found_key}.'\n # Delete __find_element_index to make sure it's not used for the next calls.\n del __find_element_index\nelse:\n n_elms = ids.n_elms\n assert isinstance(n_elms, int) and n_elms >= 0, \\\n f'Invalid value for n_elms. Got: {n_elms}.'\n if '__find_element_max_size' in globals():\n assert n_elms <= __find_element_max_size, \\\n f'find_element() can only be used with n_elms<={__find_element_max_size}. ' \\\n f'Got: n_elms={n_elms}.'\n\n for i in range(n_elms):\n if memory[array_ptr + elm_size * i] == key:\n ids.index = i\n break\n else:\n raise ValueError(f'Key {key} was not found.')"
nondetElementsOverTWoCode string = "memory[ap] = to_felt_or_relocatable(ids.n >= 2)"
nondetElementsOverTenCode string = "memory[ap] = to_felt_or_relocatable(ids.n >= 10)"
setAddCode string = "assert ids.elm_size > 0\nassert ids.set_ptr <= ids.set_end_ptr\nelm_list = memory.get_range(ids.elm_ptr, ids.elm_size)\nfor i in range(0, ids.set_end_ptr - ids.set_ptr, ids.elm_size):\n if memory.get_range(ids.set_ptr + i, ids.elm_size) == elm_list:\n ids.index = i // ids.elm_size\n ids.is_elm_in_set = 1\n break\nelse:\n ids.is_elm_in_set = 0"
searchSortedLowerCode string = `array_ptr = ids.array_ptr
elm_size = ids.elm_size
Expand Down
4 changes: 4 additions & 0 deletions pkg/hintrunner/zero/zerohint.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,10 @@ func GetHintFromCode(program *zero.ZeroProgram, rawHint zero.Hint, hintPC uint64
return createTestAssignHinter(resolver)
case findElementCode:
return createFindElementHinter(resolver)
case nondetElementsOverTWoCode:
return createNondetElementsOverTWoHinter(resolver)
case nondetElementsOverTenCode:
return createNondetElementsOverTenHinter(resolver)
default:
return nil, fmt.Errorf("not identified hint")
}
Expand Down
84 changes: 84 additions & 0 deletions pkg/hintrunner/zero/zerohint_others.go
Original file line number Diff line number Diff line change
Expand Up @@ -608,3 +608,87 @@ func createSearchSortedLowerHinter(resolver hintReferenceResolver) (hinter.Hinte

return newSearchSortedLowerHint(arrayPtr, elmSize, nElms, key, index), nil
}

// NondetElementsOverTWo hint compares the offset difference between two memory address and
// writes 1 or 0 at `ap` memory address, depending on whether the difference is greater or
// equal to 2 or not
//
// `newNondetElementsOverTWoHint` takes 2 operanders as arguments
// - `elementsEnd` represents the address in memory right after the last element of the array
// - `elements` represents the address in memory of the first element of the array
func newNondetElementsOverTWoHint(n hinter.ResOperander) hinter.Hinter {
return &GenericZeroHinter{
Name: "NondetElementsOverTWo",
Op: func(vm *VM.VirtualMachine, ctx *hinter.HintRunnerContext) error {
//> python hint in cairo file: "ids.elements_end - ids.elements >= 2"
//> python hint in whitelist: "memory[ap] = to_felt_or_relocatable(ids.elements_end - ids.elements >= 2)"
//> compiled file hint: "memory[ap] = to_felt_or_relocatable(ids.n >= 2)"

n, err := hinter.ResolveAsUint64(vm, n)
if err != nil {
return err
}

apAddr := vm.Context.AddressAp()
var resultMv memory.MemoryValue
if n >= uint64(2) {
resultMv = memory.MemoryValueFromFieldElement(&utils.FeltOne)
} else {
resultMv = memory.MemoryValueFromFieldElement(&utils.FeltZero)
}

return vm.Memory.WriteToAddress(&apAddr, &resultMv)
},
}
}

func createNondetElementsOverTWoHinter(resolver hintReferenceResolver) (hinter.Hinter, error) {
n, err := resolver.GetResOperander("n")
if err != nil {
return nil, err
}

return newNondetElementsOverTWoHint(n), nil
}

// NondetElementsOverTen hint compares the offset difference between two memory address and
// writes 1 or 0 at `ap` memory address, depending on whether the difference is greater or
// esual to 10 or not
//
// `newNondetElementsOverTenHint` takes 2 operanders as arguments
// - `elementsEnd` represents the address in memory right after the last element of the array
// - `elements` represents the address in memory of the first element of the array
func newNondetElementsOverTenHint(n hinter.ResOperander) hinter.Hinter {
return &GenericZeroHinter{
Name: "NondetElementsOverTen",
Op: func(vm *VM.VirtualMachine, ctx *hinter.HintRunnerContext) error {
//> python hint in cairo file: "ids.elements_end - ids.elements >= 10"
//> python hint in whitelist: "memory[ap] = to_felt_or_relocatable(ids.elements_end - ids.elements >= 10)"
//> compiled file hint: "memory[ap] = to_felt_or_relocatable(ids.n >= 10)"

n, err := hinter.ResolveAsUint64(vm, n)
if err != nil {
return err
}

apAddr := vm.Context.AddressAp()
var resultMv memory.MemoryValue
if n >= uint64(10) {
resultMv = memory.MemoryValueFromFieldElement(&utils.FeltOne)
} else {
resultMv = memory.MemoryValueFromFieldElement(&utils.FeltZero)
}

return vm.Memory.WriteToAddress(&apAddr, &resultMv)
},
}
}

func createNondetElementsOverTenHinter(resolver hintReferenceResolver) (hinter.Hinter, error) {
n, err := resolver.GetResOperander("n")
if err != nil {
return nil, err
}

return newNondetElementsOverTenHint(n), nil
}
48 changes: 48 additions & 0 deletions pkg/hintrunner/zero/zerohint_others_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -531,5 +531,53 @@ func TestZeroHintOthers(t *testing.T) {
}),
},
},
"NondetElementsOverTwo": {
{
operanders: []*hintOperander{
{Name: "n", Kind: apRelative, Value: feltUint64(1)},
},
makeHinter: func(ctx *hintTestContext) hinter.Hinter {
return newNondetElementsOverTWoHint(
ctx.operanders["n"],
)
},
check: apValueEquals(feltUint64(0)),
},
{
operanders: []*hintOperander{
{Name: "n", Kind: apRelative, Value: feltUint64(2)},
},
makeHinter: func(ctx *hintTestContext) hinter.Hinter {
return newNondetElementsOverTWoHint(
ctx.operanders["n"],
)
},
check: apValueEquals(feltUint64(1)),
},
},
"NondetElementsOverTen": {
{
operanders: []*hintOperander{
{Name: "n", Kind: apRelative, Value: feltUint64(9)},
},
makeHinter: func(ctx *hintTestContext) hinter.Hinter {
return newNondetElementsOverTenHint(
ctx.operanders["n"],
)
},
check: apValueEquals(feltUint64(0)),
},
{
operanders: []*hintOperander{
{Name: "n", Kind: apRelative, Value: feltUint64(10)},
},
makeHinter: func(ctx *hintTestContext) hinter.Hinter {
return newNondetElementsOverTenHint(
ctx.operanders["n"],
)
},
check: apValueEquals(feltUint64(1)),
},
},
})
}

0 comments on commit 45da4d0

Please sign in to comment.