diff --git a/pkg/hintrunner/zero/hintcode.go b/pkg/hintrunner/zero/hintcode.go index 01363f815..c0c27b896 100644 --- a/pkg/hintrunner/zero/hintcode.go +++ b/pkg/hintrunner/zero/hintcode.go @@ -124,8 +124,9 @@ ids.multiplicities = segments.gen_arg([len(positions_dict[k]) for k in output])` 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])" - 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)" + compareBytesInWordCode string = "memory[ap] = to_felt_or_relocatable(ids.n_bytes < ids.BYTES_IN_WORD)" + compareKeccakFullRateInBytesCode string = "memory[ap] = to_felt_or_relocatable(ids.n_bytes >= ids.KECCAK_FULL_RATE_IN_BYTES)" // ------ 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 6399e7f8c..4ec0f0b62 100644 --- a/pkg/hintrunner/zero/zerohint.go +++ b/pkg/hintrunner/zero/zerohint.go @@ -171,6 +171,8 @@ func GetHintFromCode(program *zero.ZeroProgram, rawHint zero.Hint, hintPC uint64 return createCompareKeccakFullRateInBytesNondetHinter(resolver) case blockPermutationCode: return createBlockPermutationHinter(resolver) + case compareBytesInWordCode: + return createCompareBytesInWordNondetHinter(resolver) // Usort hints case usortEnterScopeCode: return createUsortEnterScopeHinter() diff --git a/pkg/hintrunner/zero/zerohint_keccak.go b/pkg/hintrunner/zero/zerohint_keccak.go index 8c27a445b..c5c099d87 100644 --- a/pkg/hintrunner/zero/zerohint_keccak.go +++ b/pkg/hintrunner/zero/zerohint_keccak.go @@ -528,3 +528,47 @@ func createBlockPermutationHinter(resolver hintReferenceResolver) (hinter.Hinter return newBlockPermutationHint(keccakPtr), nil } + +// CompareBytesInWord hint compares a value to BYTES_IN_WORD constant, i.e., 8 +// +// `newCompareBytesInWordHint` takes 1 operander as argument +// - `nBytes` is the value to be compared with BYTES_IN_WORD +// +// `newCompareBytesInWordHint` writes 1 or 0 to `ap` memory address depending on whether +// `n_bytes` is lower than BYTES_IN_WORD or not +func newCompareBytesInWordHint(nBytes hinter.ResOperander) hinter.Hinter { + return &GenericZeroHinter{ + Name: "CompareBytesInWordHint", + Op: func(vm *VM.VirtualMachine, _ *hinter.HintRunnerContext) error { + //> python hint: ids.n_bytes < ids.BYTES_IN_WORD + //> JSON file hint: memory[ap] = to_felt_or_relocatable(ids.n_bytes < ids.BYTES_IN_WORD) + + // 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 + } + + bytesInWord := uint64(8) + apAddr := vm.Context.AddressAp() + var resultMv memory.MemoryValue + if nBytesVal < bytesInWord { + resultMv = memory.MemoryValueFromFieldElement(&utils.FeltOne) + } else { + resultMv = memory.MemoryValueFromFieldElement(&utils.FeltZero) + } + + return vm.Memory.WriteToAddress(&apAddr, &resultMv) + }, + } +} + +func createCompareBytesInWordNondetHinter(resolver hintReferenceResolver) (hinter.Hinter, error) { + nBytes, err := resolver.GetResOperander("n_bytes") + if err != nil { + return nil, err + } + + return newCompareBytesInWordHint(nBytes), nil +} diff --git a/pkg/hintrunner/zero/zerohint_keccak_test.go b/pkg/hintrunner/zero/zerohint_keccak_test.go index 462d78648..8617d0cb0 100644 --- a/pkg/hintrunner/zero/zerohint_keccak_test.go +++ b/pkg/hintrunner/zero/zerohint_keccak_test.go @@ -585,5 +585,25 @@ func TestZeroHintKeccak(t *testing.T) { }), }, }, + "CompareBytesInWordHint": { + { + operanders: []*hintOperander{ + {Name: "n_bytes", Kind: fpRelative, Value: feltUint64(5)}, + }, + makeHinter: func(ctx *hintTestContext) hinter.Hinter { + return newCompareBytesInWordHint(ctx.operanders["n_bytes"]) + }, + check: apValueEquals(feltUint64(1)), + }, + { + operanders: []*hintOperander{ + {Name: "n_bytes", Kind: fpRelative, Value: feltUint64(10)}, + }, + makeHinter: func(ctx *hintTestContext) hinter.Hinter { + return newCompareBytesInWordHint(ctx.operanders["n_bytes"]) + }, + check: apValueEquals(feltUint64(0)), + }, + }, }) }