Skip to content

Commit

Permalink
SplitInput3 + SplitInput6 + SplitInput9 hints (#507)
Browse files Browse the repository at this point in the history
* SplitInput3

* SplitInt6

* SplitInt9

* fix

* add unit tests

* complete unit tests

* fmt

* fmt

* fmt
  • Loading branch information
TAdev0 authored Jul 4, 2024
1 parent a86cb4b commit 9c16333
Show file tree
Hide file tree
Showing 4 changed files with 500 additions and 0 deletions.
3 changes: 3 additions & 0 deletions pkg/hintrunner/zero/hintcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ 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)"
splintInput6Code string = "ids.high6, ids.low6 = divmod(memory[ids.inputs + 6], 256 ** 2)"
splintInput9Code string = "ids.high9, ids.low9 = divmod(memory[ids.inputs + 9], 256 ** 3)"
splitOutputMidLowHighCode string = "tmp, ids.output1_low = divmod(ids.output1, 256 ** 7)\nids.output1_high, ids.output1_mid = divmod(tmp, 2 ** 128)"
SplitNBytesCode string = "ids.n_words_to_copy, ids.n_bytes_left = divmod(ids.n_bytes, ids.BYTES_IN_WORD)"

Expand Down
6 changes: 6 additions & 0 deletions pkg/hintrunner/zero/zerohint.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,12 @@ func GetHintFromCode(program *zero.ZeroProgram, rawHint zero.Hint, hintPC uint64
return createBlockPermutationHinter(resolver)
case compareBytesInWordCode:
return createCompareBytesInWordNondetHinter(resolver)
case splintInput3Code:
return createSplitInput3Hinter(resolver)
case splintInput6Code:
return createSplitInput6Hinter(resolver)
case splintInput9Code:
return createSplitInput9Hinter(resolver)
case splitOutputMidLowHighCode:
return createSplitOutputMidLowHighHinter(resolver)
case SplitNBytesCode:
Expand Down
260 changes: 260 additions & 0 deletions pkg/hintrunner/zero/zerohint_keccak.go
Original file line number Diff line number Diff line change
Expand Up @@ -749,3 +749,263 @@ func createSplitNBytesHinter(resolver hintReferenceResolver) (hinter.Hinter, err

return newSplitNBytesHint(nBytes, nWordsToCopy, nBytesLeft), nil
}

// SplitInput3 hint assigns to `ids.high3` and `ids.low3` variables
// 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 variable that will store the quotient of the division
// - `low3` is the variable that will 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 := high3.GetAddress(vm)
if err != nil {
return err
}

low3Addr, err := low3.GetAddress(vm)
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
low3Felt.SetBigInt(low3BigInt)
low3Mv := memory.MemoryValueFromFieldElement(&low3Felt)

err = vm.Memory.WriteToAddress(&low3Addr, &low3Mv)
if err != nil {
return err
}

return vm.Memory.WriteToAddress(&high3Addr, &high3Mv)
},
}
}

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
}

// SplitInput6 hint assigns to `ids.high6` and `ids.low6` variables
// the quotient and remainder of the division of the value at memory address
// `ids.inputs + 6` by 256 ** 2
//
// `newSplitInput6Hint` takes 3 operanders as arguments
// - `high6` is the variable that will store the quotient of the division
// - `low6` is the variable that will store the remainder of the division
// - `inputs` is the address in memory to which we add an offset of 6 and read that value
func newSplitInput6Hint(high6, low6, inputs hinter.ResOperander) hinter.Hinter {
return &GenericZeroHinter{
Name: "SplitInput6",
Op: func(vm *VM.VirtualMachine, _ *hinter.HintRunnerContext) error {
//> ids.high6, ids.low6 = divmod(memory[ids.inputs + 6], 256 ** 2)

high6Addr, err := high6.GetAddress(vm)
if err != nil {
return err
}

low6Addr, err := low6.GetAddress(vm)
if err != nil {
return err
}

inputsAddr, err := hinter.ResolveAsAddress(vm, inputs)
if err != nil {
return err
}

*inputsAddr, err = inputsAddr.AddOffset(6)
if err != nil {
return err
}

inputValue, err := vm.Memory.ReadFromAddress(inputsAddr)
if err != nil {
return err
}

var inputBigInt big.Int
inputValue.Felt.BigInt(&inputBigInt)

// 256 ** 2
divisor := big.NewInt(65536)

high6BigInt := new(big.Int)
low6BigInt := new(big.Int)

high6BigInt.DivMod(&inputBigInt, divisor, low6BigInt)

var high6Felt fp.Element
high6Felt.SetBigInt(high6BigInt)
high6Mv := memory.MemoryValueFromFieldElement(&high6Felt)

var low6Felt fp.Element
low6Felt.SetBigInt(low6BigInt)
low6Mv := memory.MemoryValueFromFieldElement(&low6Felt)

err = vm.Memory.WriteToAddress(&low6Addr, &low6Mv)
if err != nil {
return err
}

return vm.Memory.WriteToAddress(&high6Addr, &high6Mv)
},
}
}

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

low6, err := resolver.GetResOperander("low6")
if err != nil {
return nil, err
}

inputs, err := resolver.GetResOperander("inputs")
if err != nil {
return nil, err
}

return newSplitInput6Hint(high6, low6, inputs), nil
}

// SplitInput9 hint assigns to `ids.high9` and `ids.low9` variables
// the quotient and remainder of the division of the value at memory address
// `ids.inputs + 9` by 256 ** 3
//
// `newSplitInput9Hint` takes 3 operanders as arguments
// - `high9` is the variable that will store the quotient of the division
// - `low9` is the variable that will store the remainder of the division
// - `inputs` is the address in memory to which we add an offset of 9 and read that value
func newSplitInput9Hint(high9, low9, inputs hinter.ResOperander) hinter.Hinter {
return &GenericZeroHinter{
Name: "SplitInput9",
Op: func(vm *VM.VirtualMachine, _ *hinter.HintRunnerContext) error {
//> ids.high9, ids.low9 = divmod(memory[ids.inputs + 9], 256 ** 3)

high9Addr, err := high9.GetAddress(vm)
if err != nil {
return err
}

low9Addr, err := low9.GetAddress(vm)
if err != nil {
return err
}

inputsAddr, err := hinter.ResolveAsAddress(vm, inputs)
if err != nil {
return err
}

*inputsAddr, err = inputsAddr.AddOffset(9)
if err != nil {
return err
}

inputValue, err := vm.Memory.ReadFromAddress(inputsAddr)
if err != nil {
return err
}

var inputBigInt big.Int
inputValue.Felt.BigInt(&inputBigInt)

// 256 ** 3
divisor := big.NewInt(16777216)

high9BigInt := new(big.Int)
low9BigInt := new(big.Int)

high9BigInt.DivMod(&inputBigInt, divisor, low9BigInt)

var high9Felt fp.Element
high9Felt.SetBigInt(high9BigInt)
high9Mv := memory.MemoryValueFromFieldElement(&high9Felt)

var low9Felt fp.Element
low9Felt.SetBigInt(low9BigInt)
low9Mv := memory.MemoryValueFromFieldElement(&low9Felt)

err = vm.Memory.WriteToAddress(&low9Addr, &low9Mv)
if err != nil {
return err
}

return vm.Memory.WriteToAddress(&high9Addr, &high9Mv)
},
}
}

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

low9, err := resolver.GetResOperander("low9")
if err != nil {
return nil, err
}

inputs, err := resolver.GetResOperander("inputs")
if err != nil {
return nil, err
}

return newSplitInput9Hint(high9, low9, inputs), nil
}
Loading

0 comments on commit 9c16333

Please sign in to comment.