diff --git a/integration_tests/cairo_vm_test.go b/integration_tests/cairo_vm_test.go index 1ae4e157..d6822065 100644 --- a/integration_tests/cairo_vm_test.go +++ b/integration_tests/cairo_vm_test.go @@ -180,6 +180,7 @@ func TestCairoFiles(t *testing.T) { {"./cairo_zero_file_tests/", true}, {"./builtin_tests/", true}, // {"./cairo_1_programs/", false}, + // {"./cairo_1_programs/dict_non_squashed", false}, } // filter is for debugging purposes diff --git a/pkg/hintrunner/core/hint.go b/pkg/hintrunner/core/hint.go index d1540ae0..6667335b 100644 --- a/pkg/hintrunner/core/hint.go +++ b/pkg/hintrunner/core/hint.go @@ -1143,7 +1143,8 @@ func (hint *Felt252DictEntryInit) Execute(vm *VM.VirtualMachine, ctx *hinter.Hin prevValue, err := ctx.DictionaryManager.At(dictPtr, key) if err != nil { - return fmt.Errorf("get dictionary entry: %w", err) + mv := mem.MemoryValueFromFieldElement(&utils.FeltZero) + prevValue = &mv } if prevValue == nil { mv := mem.EmptyMemoryValueAsFelt() @@ -1234,10 +1235,10 @@ func (hint *InitSquashData) String() string { } func (hint *InitSquashData) Execute(vm *VM.VirtualMachine, ctx *hinter.HintRunnerContext) error { - // todo(rodro): Don't know if it could be called multiple times, or err := hinter.InitializeSquashedDictionaryManager(ctx) if err != nil { - return err + ctx.SquashedDictionaryManager = hinter.SquashedDictionaryManager{} + _ = hinter.InitializeSquashedDictionaryManager(ctx) } dictAccessPtr, err := hinter.ResolveAsAddress(vm, hint.DictAccesses) @@ -1272,7 +1273,7 @@ func (hint *InitSquashData) Execute(vm *VM.VirtualMachine, ctx *hinter.HintRunne // sort the keys in descending order sort.Slice(ctx.SquashedDictionaryManager.Keys, func(i, j int) bool { - return ctx.SquashedDictionaryManager.Keys[i].Cmp(&ctx.SquashedDictionaryManager.Keys[j]) < 0 + return ctx.SquashedDictionaryManager.Keys[i].Cmp(&ctx.SquashedDictionaryManager.Keys[j]) > 0 }) // if the first key is bigger than 2^128, signal it @@ -1401,11 +1402,15 @@ func (hint *ShouldContinueSquashLoop) Execute(vm *VM.VirtualMachine, ctx *hinter } var shouldContinueLoop f.Element - if lastIndices, err := ctx.SquashedDictionaryManager.LastIndices(); err == nil && len(lastIndices) <= 1 { - shouldContinueLoop.SetOne() - } else if err != nil { + lastIndices, err := ctx.SquashedDictionaryManager.LastIndices() + if err != nil { return fmt.Errorf("get last indices: %w", err) } + if len(lastIndices) > 1 { + shouldContinueLoop.SetOne() + } else { + shouldContinueLoop.SetZero() + } mv := mem.MemoryValueFromFieldElement(&shouldContinueLoop) return vm.Memory.WriteToAddress(&shouldContinuePtr, &mv) @@ -1425,11 +1430,15 @@ func (hint *GetNextDictKey) Execute(vm *VM.VirtualMachine, ctx *hinter.HintRunne return fmt.Errorf("get next key address: %w", err) } - nextKey, err := ctx.SquashedDictionaryManager.PopKey() + _, err = ctx.SquashedDictionaryManager.PopKey() if err != nil { return fmt.Errorf("pop key: %w", err) } + nextKey, err := ctx.SquashedDictionaryManager.LastKey() + if err != nil { + return fmt.Errorf("get last key: %w", err) + } mv := mem.MemoryValueFromFieldElement(&nextKey) return vm.Memory.WriteToAddress(&nextKeyAddr, &mv) } diff --git a/pkg/runner/gas.go b/pkg/runner/gas.go index 57446b8a..f825cd7a 100644 --- a/pkg/runner/gas.go +++ b/pkg/runner/gas.go @@ -50,8 +50,8 @@ func gasInitialization(memory *mem.Memory) error { if err != nil { return err } - - preCostTokenTypes := []TokenGasCost{PedersenToken, BitwiseToken, EcOpToken, PoseidonToken, AddModToken, MulModToken} + // The order of the tokens is relevant, source: https://github.com/starkware-libs/cairo/blob/f6aaaa306804257bfc15d65b5ab6b90e141b54ec/crates/cairo-lang-sierra/src/extensions/modules/gas.rs#L194 + preCostTokenTypes := []TokenGasCost{PedersenToken, PoseidonToken, BitwiseToken, EcOpToken, AddModToken, MulModToken} for _, token := range preCostTokenTypes { cost, err := getTokenGasCost(token) diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index b5cfa851..225f9266 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -541,13 +541,47 @@ func GetEntryCodeInstructions(function starknet.EntryPointByFunction, finalizeFo } ctx := &InlineCasmContext{} + + gotSegmentArena := false + for _, builtin := range function.Builtins { + if builtin == builtins.SegmentArenaType { + gotSegmentArena = true + } + } + + hints := make(map[uint64][]hinter.Hinter) + + if gotSegmentArena { + hints[uint64(ctx.currentCodeOffset)] = []hinter.Hinter{ + &core.AllocSegment{ + Dst: hinter.ApCellRef(0), + }, + &core.AllocSegment{ + Dst: hinter.ApCellRef(1), + }, + } + ctx.AddInlineCASM( + "[ap+2] = 0, ap++;", + ) + ctx.AddInlineCASM( + "[ap] = [[ap-1]], ap++;", + ) + ctx.AddInlineCASM( + ` + [ap] = [[ap-2]+1], ap++; + [ap-1] = [[ap-3]+2]; + `, + ) + apOffset += 3 + } + paramsSize := 0 for _, param := range paramTypes { paramsSize += param.Size } apOffset += paramsSize usedArgs := 0 - var hints map[uint64][]hinter.Hinter + for _, builtin := range function.Builtins { if offset, isBuiltin := builtinsOffsetsMap[builtin]; isBuiltin { ctx.AddInlineCASM( @@ -561,10 +595,8 @@ func GetEntryCodeInstructions(function starknet.EntryPointByFunction, finalizeFo ) apOffset += 1 } else if builtin == builtins.GasBuiltinType { - hints = map[uint64][]hinter.Hinter{ - uint64(ctx.currentCodeOffset): { - &core.ExternalWriteArgsToMemory{}, - }, + hints[uint64(ctx.currentCodeOffset)] = []hinter.Hinter{ + &core.ExternalWriteArgsToMemory{}, } ctx.AddInlineCASM("ap += 1;") apOffset += 1