Skip to content

Implement system call for keccak #698

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pkg/hintrunner/core/cairo_hintparser.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,11 @@ func GetHintByName(hint starknet.Hint) (hinter.Hinter, error) {
val: parseResOperand(args.Val),
sqrt: parseCellRefer(args.Sqrt),
}, nil
case starknet.SystemCallName:
args := hint.Args.(*starknet.SystemCall)
return &SystemCall{
system: parseResOperand(args.System),
}, nil
default:
return nil, fmt.Errorf("unknown hint: %v", hint.Name)
}
Expand Down
138 changes: 138 additions & 0 deletions pkg/hintrunner/core/hint.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"fmt"
"math/big"
"sort"
"strings"

"github.com/holiman/uint256"

Expand Down Expand Up @@ -2024,3 +2025,140 @@
ctx.DictionaryManager.RelocateAllDictionaries(vm)
return nil
}

type SystemCall struct {
system hinter.Reference
}

func (hint *SystemCall) String() string {
return "SystemCall"
}

func (hint *SystemCall) Execute(vm *VM.VirtualMachine, ctx *hinter.HintRunnerContext) error {
systemPtrMv, err := hint.system.Resolve(vm)
if err != nil {
return fmt.Errorf("resolve system pointer: %w", err)
}
systemPtr, err := systemPtrMv.MemoryAddress()
if err != nil {
return fmt.Errorf("expected system pointer to be an address: %w", err)
}
systemPtr.Offset += 1
if err != nil {
return fmt.Errorf("add offset to system pointer: %w", err)
}
selector, err := vm.Memory.ReadFromAddressAsElement(systemPtr)
if err != nil {
return fmt.Errorf("read selector: %w", err)
}
systemPtr.Offset += 1
gasCounterFelt, err := vm.Memory.ReadFromAddressAsElement(systemPtr)
if err != nil {
return fmt.Errorf("read gas counter: %w", err)
}
gasCounter := gasCounterFelt.Uint64()
systemPtr.Offset += 1

executeHandler := func(values []mem.MemoryValue, revertReason []fp.Element, err error) error {
if err != nil {
gasCounterMv := mem.MemoryValueFromUint(gasCounter)
vm.Memory.WriteToAddress(systemPtr, &gasCounterMv)

Check failure on line 2065 in pkg/hintrunner/core/hint.go

View workflow job for this annotation

GitHub Actions / lint

Error return value of `vm.Memory.WriteToAddress` is not checked (errcheck)
systemPtr.Offset += 1
zeroMv := mem.MemoryValueFromInt(0)
vm.Memory.WriteToAddress(systemPtr, &zeroMv)

Check failure on line 2068 in pkg/hintrunner/core/hint.go

View workflow job for this annotation

GitHub Actions / lint

Error return value of `vm.Memory.WriteToAddress` is not checked (errcheck)
systemPtr.Offset += 1
for _, value := range values {
err = vm.Memory.WriteToAddress(systemPtr, &value)
if err != nil {
return fmt.Errorf("write return value: %w", err)
}
systemPtr.Offset += 1
}

} else {
gasCounterMv := mem.MemoryValueFromUint(gasCounter)
vm.Memory.WriteToAddress(systemPtr, &gasCounterMv)

Check failure on line 2080 in pkg/hintrunner/core/hint.go

View workflow job for this annotation

GitHub Actions / lint

Error return value of `vm.Memory.WriteToAddress` is not checked (errcheck)
systemPtr.Offset += 1
oneMv := mem.MemoryValueFromInt(1)
vm.Memory.WriteToAddress(systemPtr, &oneMv)
systemPtr.Offset += 1
for _, value := range revertReason {
valMv := mem.MemoryValueFromFieldElement(&value)
err = vm.Memory.WriteToAddress(systemPtr, &valMv)
if err != nil {
return fmt.Errorf("write revert reason: %w", err)
}
systemPtr.Offset += 1
}

}
return nil
}

selectorStr := string(selector.Bytes()[8])
selectorStr = strings.TrimLeft(selectorStr, "\x00")

switch selectorStr {
case "Keccak":
startPtrMv, err := vm.Memory.ReadFromAddress(systemPtr)
if err != nil {
return fmt.Errorf("read start pointer: %w", err)
}
startPtr, err := startPtrMv.MemoryAddress()
if err != nil {
return fmt.Errorf("expected start pointer to be an address: %w", err)
}
systemPtr.Offset += 1
endPtrMv, err := vm.Memory.ReadFromAddress(systemPtr)
if err != nil {
return fmt.Errorf("read end pointer: %w", err)
}
endPtr, err := endPtrMv.MemoryAddress()
if err != nil {
return fmt.Errorf("expected end pointer to be an address: %w", err)
}
systemPtr.Offset += 1
arraySize := endPtr.Offset - startPtr.Offset
valuesArrayFelt, err := vm.Memory.GetConsecutiveMemoryValues(*startPtr, arraySize)
if err != nil {
return fmt.Errorf("get consecutive memory values: %w", err)
}

if len(valuesArrayFelt)%17 != 0 {
return fmt.Errorf("invalid keccak input size")
}

valuesArray := make([]uint64, len(valuesArrayFelt))
for i, valueMemoryValue := range valuesArrayFelt {
valuesArray[i], err = valueMemoryValue.Uint64()
if err != nil {
return err
}
}
fmt.Println(valuesArray)
var state [25]uint64

for i := 0; i < len(valuesArray); i += 17 {
gasCounter -= 180000

for j := 0; j < 17 && i+j < len(valuesArray); j++ {
state[j] ^= valuesArray[i+j]
}

builtins.KeccakF1600(&state)
}

res1 := new(big.Int).Lsh(big.NewInt(int64(state[1])), 64)
res1 = res1.Add(res1, big.NewInt(int64(state[0])))

res2 := new(big.Int).Lsh(big.NewInt(int64(state[3])), 64)
res2 = res2.Add(res2, big.NewInt(int64(state[2])))

executeHandler([]mem.MemoryValue{

Check failure on line 2157 in pkg/hintrunner/core/hint.go

View workflow job for this annotation

GitHub Actions / lint

Error return value is not checked (errcheck)
mem.MemoryValueFromUint(res1.Uint64()),
mem.MemoryValueFromUint(res2.Uint64()),
}, []fp.Element{}, nil)
}

return nil
}
Loading