From 596083157fd09d04e4b1e068b0bb011dd0a87b29 Mon Sep 17 00:00:00 2001 From: TAdev0 Date: Sat, 29 Jun 2024 16:17:57 +0200 Subject: [PATCH] SplitInput3 --- pkg/hintrunner/zero/hintcode.go | 1 + pkg/hintrunner/zero/zerohint.go | 2 + pkg/hintrunner/zero/zerohint_keccak.go | 89 +++++++++++++++++++++++++- 3 files changed, 91 insertions(+), 1 deletion(-) diff --git a/pkg/hintrunner/zero/hintcode.go b/pkg/hintrunner/zero/hintcode.go index c0c27b896..b627165c3 100644 --- a/pkg/hintrunner/zero/hintcode.go +++ b/pkg/hintrunner/zero/hintcode.go @@ -127,6 +127,7 @@ ids.multiplicities = segments.gen_arg([len(positions_dict[k]) for k in output])` 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)" + splintInput3Code string = "ids.high3, ids.low3 = divmod(memory[ids.inputs + 3], 256)" // ------ 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 4ec0f0b62..def6f6d05 100644 --- a/pkg/hintrunner/zero/zerohint.go +++ b/pkg/hintrunner/zero/zerohint.go @@ -173,6 +173,8 @@ func GetHintFromCode(program *zero.ZeroProgram, rawHint zero.Hint, hintPC uint64 return createBlockPermutationHinter(resolver) case compareBytesInWordCode: return createCompareBytesInWordNondetHinter(resolver) + case splintInput3Code: + return createSplitInput3Hinter(resolver) // Usort hints case usortEnterScopeCode: return createUsortEnterScopeHinter() diff --git a/pkg/hintrunner/zero/zerohint_keccak.go b/pkg/hintrunner/zero/zerohint_keccak.go index c5c099d87..37a5cc3e5 100644 --- a/pkg/hintrunner/zero/zerohint_keccak.go +++ b/pkg/hintrunner/zero/zerohint_keccak.go @@ -3,6 +3,7 @@ package zero import ( "fmt" "math" + "math/big" "github.com/NethermindEth/cairo-vm-go/pkg/hintrunner/hinter" "github.com/NethermindEth/cairo-vm-go/pkg/utils" @@ -538,7 +539,7 @@ func createBlockPermutationHinter(resolver hintReferenceResolver) (hinter.Hinter // `n_bytes` is lower than BYTES_IN_WORD or not func newCompareBytesInWordHint(nBytes hinter.ResOperander) hinter.Hinter { return &GenericZeroHinter{ - Name: "CompareBytesInWordHint", + Name: "CompareBytesInWord", 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) @@ -572,3 +573,89 @@ func createCompareBytesInWordNondetHinter(resolver hintReferenceResolver) (hinte return newCompareBytesInWordHint(nBytes), nil } + +// SplitInput3 hint writes at address `ids.high3` and `ids.low3` in memory +// the quotient and remainder of the division of the value at memory address +// `ids.inputs + 3` by 256 +// +// `newSplitInput3Hint` takes 3 operanders as arguments +// - `high3` is the address in memory where to store the quotient of the division +// - `low3` is the address in memory where to store the remainder of the division +// - `inputs` is the address in memory to which we add an offset of 3 and read that value +func newSplitInput3Hint(high3, low3, inputs hinter.ResOperander) hinter.Hinter { + return &GenericZeroHinter{ + Name: "SplitInput3", + Op: func(vm *VM.VirtualMachine, _ *hinter.HintRunnerContext) error { + //> ids.high3, ids.low3 = divmod(memory[ids.inputs + 3], 256) + + high3Addr, err := hinter.ResolveAsAddress(vm, high3) + if err != nil { + return err + } + + low3Addr, err := hinter.ResolveAsAddress(vm, low3) + if err != nil { + return err + } + + inputsAddr, err := hinter.ResolveAsAddress(vm, inputs) + if err != nil { + return err + } + + *inputsAddr, err = inputsAddr.AddOffset(3) + if err != nil { + return err + } + + inputValue, err := vm.Memory.ReadFromAddress(inputsAddr) + if err != nil { + return err + } + + var inputBigInt big.Int + inputValue.Felt.BigInt(&inputBigInt) + + divisor := big.NewInt(256) + + high3BigInt := new(big.Int) + low3BigInt := new(big.Int) + + high3BigInt.DivMod(&inputBigInt, divisor, low3BigInt) + + var high3Felt fp.Element + high3Felt.SetBigInt(high3BigInt) + high3Mv := memory.MemoryValueFromFieldElement(&high3Felt) + + var low3Felt fp.Element + high3Felt.SetBigInt(low3BigInt) + low3Mv := memory.MemoryValueFromFieldElement(&low3Felt) + + err = vm.Memory.WriteToAddress(low3Addr, &high3Mv) + if err != nil { + return err + } + + return vm.Memory.WriteToAddress(high3Addr, &low3Mv) + }, + } +} + +func createSplitInput3Hinter(resolver hintReferenceResolver) (hinter.Hinter, error) { + high3, err := resolver.GetResOperander("high3") + if err != nil { + return nil, err + } + + low3, err := resolver.GetResOperander("low3") + if err != nil { + return nil, err + } + + inputs, err := resolver.GetResOperander("inputs") + if err != nil { + return nil, err + } + + return newSplitInput3Hint(high3, low3, inputs), nil +}