From 9e0187498c47ced0d53060ba4a61d494b38deb64 Mon Sep 17 00:00:00 2001 From: Tristan <122918260+TAdev0@users.noreply.github.com> Date: Fri, 28 Jun 2024 17:16:35 +0200 Subject: [PATCH] `CompareKeccakFullRateInBytes` keccak hint (#482) * CompareKeccakFullRateInBytes * fmt * fmt * improve comment * add comment * update comment --------- Co-authored-by: Shourya Goel --- pkg/hintrunner/zero/hintcode.go | 5 ++- pkg/hintrunner/zero/zerohint.go | 2 + pkg/hintrunner/zero/zerohint_keccak.go | 43 +++++++++++++++++++++ pkg/hintrunner/zero/zerohint_keccak_test.go | 29 ++++++++++++++ 4 files changed, 77 insertions(+), 2 deletions(-) diff --git a/pkg/hintrunner/zero/hintcode.go b/pkg/hintrunner/zero/hintcode.go index 45b54588..01363f81 100644 --- a/pkg/hintrunner/zero/hintcode.go +++ b/pkg/hintrunner/zero/hintcode.go @@ -123,8 +123,9 @@ ids.multiplicities = segments.gen_arg([len(positions_dict[k]) for k in output])` inp = [0] * _keccak_state_size_felts padding = (inp + keccak_func(inp)) * _block_size segments.write_arg(ids.keccak_ptr_end, padding)` - keccakWriteArgsCode string = "segments.write_arg(ids.inputs, [ids.low % 2 ** 64, ids.low // 2 ** 64])\nsegments.write_arg(ids.inputs + 2, [ids.high % 2 ** 64, ids.high // 2 ** 64])" - blockPermutationCode string = "from starkware.cairo.common.keccak_utils.keccak_utils import keccak_func\n_keccak_state_size_felts = int(ids.KECCAK_STATE_SIZE_FELTS)\nassert 0 <= _keccak_state_size_felts < 100\noutput_values = keccak_func(memory.get_range(\nids.keccak_ptr - _keccak_state_size_felts, _keccak_state_size_felts))\nsegments.write_arg(ids.keccak_ptr, output_values)" + keccakWriteArgsCode string = "segments.write_arg(ids.inputs, [ids.low % 2 ** 64, ids.low // 2 ** 64])\nsegments.write_arg(ids.inputs + 2, [ids.high % 2 ** 64, ids.high // 2 ** 64])" + compareKeccakFullRateInBytesCode string = "memory[ap] = to_felt_or_relocatable(ids.n_bytes >= ids.KECCAK_FULL_RATE_IN_BYTES)" + blockPermutationCode string = "from starkware.cairo.common.keccak_utils.keccak_utils import keccak_func\n_keccak_state_size_felts = int(ids.KECCAK_STATE_SIZE_FELTS)\nassert 0 <= _keccak_state_size_felts < 100\noutput_values = keccak_func(memory.get_range(\nids.keccak_ptr - _keccak_state_size_felts, _keccak_state_size_felts))\nsegments.write_arg(ids.keccak_ptr, output_values)" // ------ Dictionaries hints related code ------ dictNewCode string = "if '__dict_manager' not in globals():\n from starkware.cairo.common.dict import DictManager\n __dict_manager = DictManager()\n\nmemory[ap] = __dict_manager.new_dict(segments, initial_dict)\ndel initial_dict" diff --git a/pkg/hintrunner/zero/zerohint.go b/pkg/hintrunner/zero/zerohint.go index 34b84e8b..6399e7f8 100644 --- a/pkg/hintrunner/zero/zerohint.go +++ b/pkg/hintrunner/zero/zerohint.go @@ -167,6 +167,8 @@ func GetHintFromCode(program *zero.ZeroProgram, rawHint zero.Hint, hintPC uint64 return createUnsafeKeccakHinter(resolver) case unsafeKeccakFinalizeCode: return createUnsafeKeccakFinalizeHinter(resolver) + case compareKeccakFullRateInBytesCode: + return createCompareKeccakFullRateInBytesNondetHinter(resolver) case blockPermutationCode: return createBlockPermutationHinter(resolver) // Usort hints diff --git a/pkg/hintrunner/zero/zerohint_keccak.go b/pkg/hintrunner/zero/zerohint_keccak.go index c784223a..8c27a445 100644 --- a/pkg/hintrunner/zero/zerohint_keccak.go +++ b/pkg/hintrunner/zero/zerohint_keccak.go @@ -407,6 +407,49 @@ func createKeccakWriteArgsHinter(resolver hintReferenceResolver) (hinter.Hinter, return newKeccakWriteArgsHint(inputs, low, high), nil } +// CompareKeccakFullRateInBytes hint compares a value to KECCAK_FULL_RATE_IN_BYTES constant, i.e., 136 +// +// `newKeccakWriteArgsHint` takes 1 operander as argument +// - `nBytes` is the value to be compared with KECCAK_FULL_RATE_IN_BYTES +// +// `newKeccakWriteArgsHint` writes 1 or 0 to `ap` memory address depending on whether +// `n_bytes` is greater or equal to KECCAK_FULL_RATE_IN_BYTES or not +func newCompareKeccakFullRateInBytesHint(nBytes hinter.ResOperander) hinter.Hinter { + return &GenericZeroHinter{ + Name: "CompareKeccakFullRateInBytes", + Op: func(vm *VM.VirtualMachine, _ *hinter.HintRunnerContext) error { + //> python hint: ids.n_bytes >= ids.KECCAK_FULL_RATE_IN_BYTES + //> JSON file hint: memory[ap] = to_felt_or_relocatable(ids.n_bytes >= ids.KECCAK_FULL_RATE_IN_BYTES) + + // n_bytes should fit into a uint64 + // we cannot 100% exclude the possibility that it doesn't + nBytesVal, err := hinter.ResolveAsUint64(vm, nBytes) + if err != nil { + return err + } + + apAddr := vm.Context.AddressAp() + var resultMv memory.MemoryValue + if nBytesVal >= uint64(utils.KECCAK_FULL_RATE_IN_BYTES) { + resultMv = memory.MemoryValueFromFieldElement(&utils.FeltOne) + } else { + resultMv = memory.MemoryValueFromFieldElement(&utils.FeltZero) + } + + return vm.Memory.WriteToAddress(&apAddr, &resultMv) + }, + } +} + +func createCompareKeccakFullRateInBytesNondetHinter(resolver hintReferenceResolver) (hinter.Hinter, error) { + nBytes, err := resolver.GetResOperander("n_bytes") + if err != nil { + return nil, err + } + + return newCompareKeccakFullRateInBytesHint(nBytes), nil +} + // BlockPermutation hint executes the Keccak block permutation function to a segment of memory // // `newBlockPermutationHint` takes 1 operander as argument diff --git a/pkg/hintrunner/zero/zerohint_keccak_test.go b/pkg/hintrunner/zero/zerohint_keccak_test.go index 996d1eb7..462d7864 100644 --- a/pkg/hintrunner/zero/zerohint_keccak_test.go +++ b/pkg/hintrunner/zero/zerohint_keccak_test.go @@ -430,6 +430,35 @@ func TestZeroHintKeccak(t *testing.T) { }, }, }, + "CompareKeccakFullRateInBytes": { + { + operanders: []*hintOperander{ + {Name: "n_bytes", Kind: fpRelative, Value: feltUint64(137)}, + }, + makeHinter: func(ctx *hintTestContext) hinter.Hinter { + return newCompareKeccakFullRateInBytesHint(ctx.operanders["n_bytes"]) + }, + check: apValueEquals(feltUint64(1)), + }, + { + operanders: []*hintOperander{ + {Name: "n_bytes", Kind: fpRelative, Value: feltUint64(136)}, + }, + makeHinter: func(ctx *hintTestContext) hinter.Hinter { + return newCompareKeccakFullRateInBytesHint(ctx.operanders["n_bytes"]) + }, + check: apValueEquals(feltUint64(1)), + }, + { + operanders: []*hintOperander{ + {Name: "n_bytes", Kind: fpRelative, Value: feltUint64(135)}, + }, + makeHinter: func(ctx *hintTestContext) hinter.Hinter { + return newCompareKeccakFullRateInBytesHint(ctx.operanders["n_bytes"]) + }, + check: apValueEquals(feltUint64(0)), + }, + }, "BlockPermutation": { { operanders: []*hintOperander{