From 0baa5b47d0ee91292c8142897eec99fcc11e14b3 Mon Sep 17 00:00:00 2001 From: toni-calvin Date: Mon, 18 Sep 2023 11:55:21 +0200 Subject: [PATCH 01/23] add is_positive felt method --- pkg/lambdaworks/lambdaworks.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/lambdaworks/lambdaworks.go b/pkg/lambdaworks/lambdaworks.go index e5c36bd3..66b40b81 100644 --- a/pkg/lambdaworks/lambdaworks.go +++ b/pkg/lambdaworks/lambdaworks.go @@ -148,6 +148,10 @@ func (f Felt) IsZero() bool { return f == FeltZero() } +func (f Felt) IsPositive() bool { + return !f.IsZero() +} + // Writes the result variable with the sum of a and b felts. func (a Felt) Add(b Felt) Felt { var result C.felt_t From c74637489d8b617c631e54d353e8a396ae190b53 Mon Sep 17 00:00:00 2001 From: toni-calvin Date: Mon, 18 Sep 2023 12:05:01 +0200 Subject: [PATCH 02/23] implement memcpy_continue_copying hint --- pkg/hints/hint_processor.go | 6 ++++-- pkg/hints/memcpy_hint_codes.go | 1 + pkg/hints/memcpy_hints.go | 37 ++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/pkg/hints/hint_processor.go b/pkg/hints/hint_processor.go index 47da4dfb..ccb73aa0 100644 --- a/pkg/hints/hint_processor.go +++ b/pkg/hints/hint_processor.go @@ -55,14 +55,16 @@ func (p *CairoVmHintProcessor) ExecuteHint(vm *vm.VirtualMachine, hintData *any, return dictWrite(data.Ids, execScopes, vm) case DICT_UPDATE: return dictUpdate(data.Ids, execScopes, vm) + case VM_ENTER_SCOPE: + return vm_enter_scope(execScopes) case VM_EXIT_SCOPE: return vm_exit_scope(execScopes) case ASSERT_NOT_EQUAL: return assert_not_equal(data.Ids, vm) case MEMCPY_ENTER_SCOPE: return memcpy_enter_scope(data.Ids, vm, execScopes) - case VM_ENTER_SCOPE: - return vm_enter_scope(execScopes) + case MEMCPY_CONTINUE_COPYING: + return memset_step_loop(data.Ids, vm, execScopes, "continur_copying") default: return errors.Errorf("Unknown Hint: %s", data.Code) } diff --git a/pkg/hints/memcpy_hint_codes.go b/pkg/hints/memcpy_hint_codes.go index e2e52ffe..0340ead2 100644 --- a/pkg/hints/memcpy_hint_codes.go +++ b/pkg/hints/memcpy_hint_codes.go @@ -4,3 +4,4 @@ const ADD_SEGMENT = "memory[ap] = segments.add()" const VM_EXIT_SCOPE = "vm_exit_scope()" const VM_ENTER_SCOPE = "vm_enter_scope()" const MEMCPY_ENTER_SCOPE = "vm_enter_scope({'n': ids.len})" +const MEMCPY_CONTINUE_COPYING = "n -= 1 ids.continue_copying = 1 if n > 0 else 0" diff --git a/pkg/hints/memcpy_hints.go b/pkg/hints/memcpy_hints.go index 1c65f102..af07ad67 100644 --- a/pkg/hints/memcpy_hints.go +++ b/pkg/hints/memcpy_hints.go @@ -2,6 +2,7 @@ package hints import ( . "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_utils" + "github.com/lambdaclass/cairo-vm.go/pkg/lambdaworks" "github.com/lambdaclass/cairo-vm.go/pkg/types" . "github.com/lambdaclass/cairo-vm.go/pkg/vm" . "github.com/lambdaclass/cairo-vm.go/pkg/vm/memory" @@ -31,6 +32,42 @@ func memcpy_enter_scope(ids IdsManager, vm *VirtualMachine, execScopes *types.Ex return nil } +/* + Implements hint: + + %{ + n -= 1 + ids.`i_name` = 1 if n > 0 else 0 + +%} +*/ +func memset_step_loop(ids IdsManager, vm *VirtualMachine, execScoes *types.ExecutionScopes, i_name string) error { + // get `n` variable from vm scope + n, err := execScoes.GetRef("n") + if err != nil { + return err + } + // this variable will hold the value of `n - 1` + *n = (*n).(lambdaworks.Felt).Sub(lambdaworks.FeltOne()) + // if `new_n` is positive, insert 1 in the address of `continue_loop` + // else, insert 0 + var flag *MaybeRelocatable + if (*n).(lambdaworks.Felt).IsPositive() { + flag = NewMaybeRelocatableFelt(lambdaworks.FeltOne()) + } else { + flag = NewMaybeRelocatableFelt(lambdaworks.FeltZero()) + } + addr, err := ids.GetAddr(i_name, vm) + if err != nil { + return err + } + err = vm.Segments.Memory.Insert(addr, flag) + if err != nil { + return err + } + return nil +} + // Implements hint: vm_enter_scope() func vm_enter_scope(executionScopes *types.ExecutionScopes) error { executionScopes.EnterScope(make(map[string]interface{})) From 5a8bd0957dbab63a2ebc0c7eae32cd4d10ec5e5a Mon Sep 17 00:00:00 2001 From: toni-calvin Date: Mon, 18 Sep 2023 12:06:27 +0200 Subject: [PATCH 03/23] fix test --- pkg/hints/memcpy_hints_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/hints/memcpy_hints_test.go b/pkg/hints/memcpy_hints_test.go index 0fd7cb0f..13c4369d 100644 --- a/pkg/hints/memcpy_hints_test.go +++ b/pkg/hints/memcpy_hints_test.go @@ -12,7 +12,7 @@ import ( . "github.com/lambdaclass/cairo-vm.go/pkg/vm/memory" ) -func AddSegmentHintOk(t *testing.T) { +func TestAddSegmentHintOk(t *testing.T) { vm := NewVirtualMachine() initial_segments := vm.Segments.Memory.NumSegments() hintProcessor := CairoVmHintProcessor{} From 737eee67f696ad534d02172c55a43867546a6fb4 Mon Sep 17 00:00:00 2001 From: toni-calvin Date: Mon, 18 Sep 2023 15:21:31 +0200 Subject: [PATCH 04/23] fix hint --- pkg/hints/hint_processor.go | 2 +- pkg/hints/memcpy_hints.go | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/pkg/hints/hint_processor.go b/pkg/hints/hint_processor.go index ccb73aa0..09228826 100644 --- a/pkg/hints/hint_processor.go +++ b/pkg/hints/hint_processor.go @@ -64,7 +64,7 @@ func (p *CairoVmHintProcessor) ExecuteHint(vm *vm.VirtualMachine, hintData *any, case MEMCPY_ENTER_SCOPE: return memcpy_enter_scope(data.Ids, vm, execScopes) case MEMCPY_CONTINUE_COPYING: - return memset_step_loop(data.Ids, vm, execScopes, "continur_copying") + return memset_step_loop(data.Ids, vm, execScopes, "continue_copying") default: return errors.Errorf("Unknown Hint: %s", data.Code) } diff --git a/pkg/hints/memcpy_hints.go b/pkg/hints/memcpy_hints.go index af07ad67..90ba89f6 100644 --- a/pkg/hints/memcpy_hints.go +++ b/pkg/hints/memcpy_hints.go @@ -57,11 +57,7 @@ func memset_step_loop(ids IdsManager, vm *VirtualMachine, execScoes *types.Execu } else { flag = NewMaybeRelocatableFelt(lambdaworks.FeltZero()) } - addr, err := ids.GetAddr(i_name, vm) - if err != nil { - return err - } - err = vm.Segments.Memory.Insert(addr, flag) + err = ids.Insert(i_name, flag, vm) if err != nil { return err } From 53bc048a3bd99d03919534d7c6daa29d7e69e436 Mon Sep 17 00:00:00 2001 From: toni-calvin Date: Mon, 18 Sep 2023 16:00:41 +0200 Subject: [PATCH 05/23] add failing test --- pkg/hints/memcpy_hints_test.go | 120 +++++++++++++++++++++++++++++++++ pkg/vm/memory/memory.go | 13 +++- 2 files changed, 132 insertions(+), 1 deletion(-) diff --git a/pkg/hints/memcpy_hints_test.go b/pkg/hints/memcpy_hints_test.go index 13c4369d..632ac66e 100644 --- a/pkg/hints/memcpy_hints_test.go +++ b/pkg/hints/memcpy_hints_test.go @@ -155,3 +155,123 @@ func TestEnterScope(t *testing.T) { t.Errorf("TestEnterScopeHint failed with error %s", err) } } + +func TestMemcpyContinueCopyingValid(t *testing.T) { + vm := NewVirtualMachine() + vm.Segments.AddSegment() + vm.Segments.AddSegment() + vm.Segments.AddSegment() + vm.RunContext.Fp = NewRelocatable(2, 0) + vm.Segments.Memory.Data[NewRelocatable(1, 2)] = *NewMaybeRelocatableFelt(lambdaworks.FeltFromUint64(5)) + + executionScopes := NewExecutionScopes() + scope := make(map[string]interface{}) + scope["n"] = lambdaworks.FeltOne() + executionScopes.EnterScope(scope) + + idsManager := SetupIdsForTest( + map[string][]*MaybeRelocatable{ + "continue_copying": nil, + }, + vm, + ) + hintProcessor := CairoVmHintProcessor{} + hintData := any(HintData{ + Ids: idsManager, + Code: MEMCPY_CONTINUE_COPYING, + }) + + err := hintProcessor.ExecuteHint(vm, &hintData, nil, executionScopes) + if err != nil { + t.Errorf("TestMemsetContinueLoopValidEqual1 failed with error %s", err) + } +} + +func TestMemcpyContinueCopyingVarNotInScope(t *testing.T) { + vm := NewVirtualMachine() + vm.Segments.AddSegment() + vm.RunContext.Fp = NewRelocatable(3, 0) + vm.Segments.Memory.Insert(NewRelocatable(0, 2), NewMaybeRelocatableFelt(lambdaworks.FeltFromUint64(5))) + + executionScopes := NewExecutionScopes() + + idsManager := SetupIdsForTest( + map[string][]*MaybeRelocatable{ + "continue_copying": nil, + }, + vm, + ) + hintProcessor := CairoVmHintProcessor{} + hintData := any(HintData{ + Ids: idsManager, + Code: MEMCPY_CONTINUE_COPYING, + }) + + err := hintProcessor.ExecuteHint(vm, &hintData, nil, executionScopes) + if err.Error() != ErrVariableNotInScope("n").Error() { + t.Errorf("TestMemcpyContinueCopyingVarNotInScope should fail with error %s", ErrVariableNotInScope("n")) + } +} + +func TestMemcpyContinueCopyingInsertError(t *testing.T) { + vm := NewVirtualMachine() + vm.Segments.AddSegment() + vm.Segments.AddSegment() + vm.RunContext.Fp = NewRelocatable(2, 0) + vm.Segments.Memory.Insert(NewRelocatable(1, 1), NewMaybeRelocatableFelt(lambdaworks.FeltFromUint64(5))) + executionScopes := NewExecutionScopes() + + scope := make(map[string]interface{}) + scope["n"] = lambdaworks.FeltOne() + executionScopes.EnterScope(scope) + + idsManager := SetupIdsForTest( + map[string][]*MaybeRelocatable{ + "continue_copying": nil, + }, + vm, + ) + hintProcessor := CairoVmHintProcessor{} + hintData := any(HintData{ + Ids: idsManager, + Code: MEMCPY_CONTINUE_COPYING, + }) + + err := hintProcessor.ExecuteHint(vm, &hintData, nil, executionScopes) + if err != nil { + t.Errorf("TestMemcpyContinueCopyingInsertError failed with error %s", err) + } +} + +// func TestMemsetContinueCopyingValidEqual5Hint(t *testing.T) { +// vm := NewVirtualMachine() +// vm.RunContext.Fp = NewRelocatable(1, 0) +// vm.Segments.Memory.Data[NewRelocatable(1, 2)] = *NewMaybeRelocatableFelt(lambdaworks.FeltFromUint64(5)) +// idsManager := SetupIdsForTest( +// map[string][]*MaybeRelocatable{ +// "continue_copying": nil, +// }, +// vm, +// ) +// hintProcessor := CairoVmHintProcessor{} +// hintData := any(HintData{ +// Ids: idsManager, +// Code: MEMCPY_CONTINUE_COPYING, +// }) + +// executionScopes := NewExecutionScopes() +// scope := make(map[string]interface{}) +// scope["n"] = lambdaworks.FeltFromUint64(5) +// executionScopes.EnterScope(scope) +// err := hintProcessor.ExecuteHint(vm, &hintData, nil, executionScopes) +// if err != nil { +// t.Errorf("TestMemsetContinueCopyingValidEqual5Hint failed with error %s", err) +// } +// val, err := vm.Segments.Memory.GetFelt(NewRelocatable(1, 0)) +// if err != nil { +// t.Errorf("TestMemsetContinueCopyingValidEqual5Hint failed with error %s", err) +// } +// if val != FeltZero() { +// t.Errorf("TestMemsetContinueCopyingValidEqual5Hint failed, expected %d, got: %d", lambdaworks.FeltZero(), val) +// } +// } diff --git a/pkg/vm/memory/memory.go b/pkg/vm/memory/memory.go index 4c7f2bac..485fb1b3 100644 --- a/pkg/vm/memory/memory.go +++ b/pkg/vm/memory/memory.go @@ -10,6 +10,17 @@ import ( // A Set to store Relocatable values type AddressSet map[Relocatable]bool +// func MemoryError(err error) error { +// return errors.Wrapf(err, "Memory error") +// } + +// func ErrInconsistentMemory(addr Relocatable, val MaybeRelocatable) error { +// valStr := val.ToString() +// addrStr := addr.ToString() + +// return MemoryError(errors.Errorf("Inserting %s into a non allocated segment %s.", valStr, addrStr)) +// } + func NewAddressSet() AddressSet { return make(map[Relocatable]bool) } @@ -76,7 +87,7 @@ func (m *Memory) Insert(addr Relocatable, val *MaybeRelocatable) error { // Check that insertions are preformed within the memory bounds if addr.SegmentIndex >= int(m.numSegments) { - return errors.New("Error: Inserting into a non allocated segment") + return errors.Errorf("Error: Inserting into a non allocated segment %s", addr.ToString()) } // Check for possible overwrites From 364470d2b8c8367b1d49761628bb1373277c5f6c Mon Sep 17 00:00:00 2001 From: toni-calvin Date: Mon, 18 Sep 2023 16:27:00 +0200 Subject: [PATCH 06/23] add hint --- pkg/hints/hint_processor.go | 2 ++ pkg/hints/memset_hint_codes.go | 3 +++ pkg/hints/memset_hints.go | 19 +++++++++++++++++++ pkg/hints/memset_hints_test.go | 1 + 4 files changed, 25 insertions(+) create mode 100644 pkg/hints/memset_hint_codes.go create mode 100644 pkg/hints/memset_hints.go create mode 100644 pkg/hints/memset_hints_test.go diff --git a/pkg/hints/hint_processor.go b/pkg/hints/hint_processor.go index 6ccf8f38..3b932e25 100644 --- a/pkg/hints/hint_processor.go +++ b/pkg/hints/hint_processor.go @@ -67,6 +67,8 @@ func (p *CairoVmHintProcessor) ExecuteHint(vm *vm.VirtualMachine, hintData *any, return sqrt(data.Ids, vm) case MEMCPY_ENTER_SCOPE: return memcpy_enter_scope(data.Ids, vm, execScopes) + case MEMSET_ENTER_SCOPE: + return memset_enter_scope(data.Ids, vm, execScopes) case MEMCPY_CONTINUE_COPYING: return memset_step_loop(data.Ids, vm, execScopes, "continue_copying") default: diff --git a/pkg/hints/memset_hint_codes.go b/pkg/hints/memset_hint_codes.go new file mode 100644 index 00000000..98489424 --- /dev/null +++ b/pkg/hints/memset_hint_codes.go @@ -0,0 +1,3 @@ +package hints + +const MEMSET_ENTER_SCOPE = "vm_enter_scope({'n': ids.n})" diff --git a/pkg/hints/memset_hints.go b/pkg/hints/memset_hints.go new file mode 100644 index 00000000..8df404b5 --- /dev/null +++ b/pkg/hints/memset_hints.go @@ -0,0 +1,19 @@ +package hints + +import ( + . "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_utils" + "github.com/lambdaclass/cairo-vm.go/pkg/types" + . "github.com/lambdaclass/cairo-vm.go/pkg/vm" + . "github.com/lambdaclass/cairo-vm.go/pkg/vm/memory" +) + +// Implements hint: +// %{ vm_enter_scope({'n': ids.n}) %} +func memset_enter_scope(ids IdsManager, vm *VirtualMachine, execScopes *types.ExecutionScopes) error { + n, err := ids.Get("n") + if err != nil { + return err + } + execScopes.EnterScope(map[string]interface{}{"n": n}) + return nil +} diff --git a/pkg/hints/memset_hints_test.go b/pkg/hints/memset_hints_test.go new file mode 100644 index 00000000..a21420aa --- /dev/null +++ b/pkg/hints/memset_hints_test.go @@ -0,0 +1 @@ +package hints_test From e3c654677a933334c32dcf2ff56043687db4dfbe Mon Sep 17 00:00:00 2001 From: toni-calvin Date: Mon, 18 Sep 2023 16:47:43 +0200 Subject: [PATCH 07/23] add test to memcpy_continue_copying hint --- pkg/hints/memcpy_hints_test.go | 9 ++++----- pkg/vm/memory/memory.go | 19 ++++++++++--------- pkg/vm/memory/relocatable.go | 5 +++++ 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/pkg/hints/memcpy_hints_test.go b/pkg/hints/memcpy_hints_test.go index 632ac66e..470e880f 100644 --- a/pkg/hints/memcpy_hints_test.go +++ b/pkg/hints/memcpy_hints_test.go @@ -217,8 +217,6 @@ func TestMemcpyContinueCopyingInsertError(t *testing.T) { vm := NewVirtualMachine() vm.Segments.AddSegment() vm.Segments.AddSegment() - vm.RunContext.Fp = NewRelocatable(2, 0) - vm.Segments.Memory.Insert(NewRelocatable(1, 1), NewMaybeRelocatableFelt(lambdaworks.FeltFromUint64(5))) executionScopes := NewExecutionScopes() scope := make(map[string]interface{}) @@ -227,7 +225,7 @@ func TestMemcpyContinueCopyingInsertError(t *testing.T) { idsManager := SetupIdsForTest( map[string][]*MaybeRelocatable{ - "continue_copying": nil, + "continue_copying": {NewMaybeRelocatableFelt(FeltFromUint64(5))}, }, vm, ) @@ -238,8 +236,9 @@ func TestMemcpyContinueCopyingInsertError(t *testing.T) { }) err := hintProcessor.ExecuteHint(vm, &hintData, nil, executionScopes) - if err != nil { - t.Errorf("TestMemcpyContinueCopyingInsertError failed with error %s", err) + expected := ErrMemoryWriteOnce(NewRelocatable(0, 0), *NewMaybeRelocatableFeltFromUint64(5), *NewMaybeRelocatableFeltFromUint64(0)) + if err.Error() != expected.Error() { + t.Errorf("TestMemcpyContinueCopyingInsertError should fail with error %s", expected) } } diff --git a/pkg/vm/memory/memory.go b/pkg/vm/memory/memory.go index 485fb1b3..9985bc44 100644 --- a/pkg/vm/memory/memory.go +++ b/pkg/vm/memory/memory.go @@ -10,16 +10,17 @@ import ( // A Set to store Relocatable values type AddressSet map[Relocatable]bool -// func MemoryError(err error) error { -// return errors.Wrapf(err, "Memory error") -// } +func MemoryError(err error) error { + return errors.Wrapf(err, "Memory error") +} -// func ErrInconsistentMemory(addr Relocatable, val MaybeRelocatable) error { -// valStr := val.ToString() -// addrStr := addr.ToString() +func ErrMemoryWriteOnce(addr Relocatable, prevVal MaybeRelocatable, newVal MaybeRelocatable) error { + addrStr := addr.ToString() + prevValStr := prevVal.ToString() + newValStr := newVal.ToString() -// return MemoryError(errors.Errorf("Inserting %s into a non allocated segment %s.", valStr, addrStr)) -// } + return MemoryError(errors.Errorf("Memory is write-once, cannot overwrite memory value in %s. %s != %s", addrStr, prevValStr, newValStr)) +} func NewAddressSet() AddressSet { return make(map[Relocatable]bool) @@ -93,7 +94,7 @@ func (m *Memory) Insert(addr Relocatable, val *MaybeRelocatable) error { // Check for possible overwrites prev_elem, ok := m.Data[addr] if ok && prev_elem != *val { - return errors.New("Memory is write-once, cannot overwrite memory value") + return ErrMemoryWriteOnce(addr, prev_elem, *val) } m.Data[addr] = *val return m.validateAddress(addr) diff --git a/pkg/vm/memory/relocatable.go b/pkg/vm/memory/relocatable.go index 756f5afb..557cefb0 100644 --- a/pkg/vm/memory/relocatable.go +++ b/pkg/vm/memory/relocatable.go @@ -107,6 +107,11 @@ func NewMaybeRelocatableFelt(felt lambdaworks.Felt) *MaybeRelocatable { return &MaybeRelocatable{inner: felt} } +// Creates a new MaybeRelocatable from a uint64 value +func NewMaybeRelocatableFeltFromUint64(val uint64) *MaybeRelocatable { + return NewMaybeRelocatableFelt(lambdaworks.FeltFromUint64(val)) +} + // Creates a new MaybeRelocatable with a Relocatable inner value func NewMaybeRelocatableRelocatable(relocatable Relocatable) *MaybeRelocatable { return &MaybeRelocatable{inner: relocatable} From 7f083b95e0ffaad41851a89d9ae5c5e716477672 Mon Sep 17 00:00:00 2001 From: toni-calvin Date: Mon, 18 Sep 2023 16:52:29 +0200 Subject: [PATCH 08/23] improve imports in hints --- pkg/hints/memcpy_hints.go | 20 ++++++++++---------- pkg/hints/memcpy_hints_test.go | 19 +++++++++---------- pkg/hints/memset_hints.go | 7 +++---- 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/pkg/hints/memcpy_hints.go b/pkg/hints/memcpy_hints.go index 90ba89f6..14fb4760 100644 --- a/pkg/hints/memcpy_hints.go +++ b/pkg/hints/memcpy_hints.go @@ -2,8 +2,8 @@ package hints import ( . "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_utils" - "github.com/lambdaclass/cairo-vm.go/pkg/lambdaworks" - "github.com/lambdaclass/cairo-vm.go/pkg/types" + . "github.com/lambdaclass/cairo-vm.go/pkg/lambdaworks" + . "github.com/lambdaclass/cairo-vm.go/pkg/types" . "github.com/lambdaclass/cairo-vm.go/pkg/vm" . "github.com/lambdaclass/cairo-vm.go/pkg/vm/memory" ) @@ -16,13 +16,13 @@ func add_segment(vm *VirtualMachine) error { // Implements hint: // %{ vm_exit_scope() %} -func vm_exit_scope(executionScopes *types.ExecutionScopes) error { +func vm_exit_scope(executionScopes *ExecutionScopes) error { return executionScopes.ExitScope() } // Implements hint: // %{ vm_enter_scope({'n': ids.len}) %} -func memcpy_enter_scope(ids IdsManager, vm *VirtualMachine, execScopes *types.ExecutionScopes) error { +func memcpy_enter_scope(ids IdsManager, vm *VirtualMachine, execScopes *ExecutionScopes) error { len, err := ids.GetFelt("len", vm) if err != nil { return err @@ -41,21 +41,21 @@ func memcpy_enter_scope(ids IdsManager, vm *VirtualMachine, execScopes *types.Ex %} */ -func memset_step_loop(ids IdsManager, vm *VirtualMachine, execScoes *types.ExecutionScopes, i_name string) error { +func memset_step_loop(ids IdsManager, vm *VirtualMachine, execScoes *ExecutionScopes, i_name string) error { // get `n` variable from vm scope n, err := execScoes.GetRef("n") if err != nil { return err } // this variable will hold the value of `n - 1` - *n = (*n).(lambdaworks.Felt).Sub(lambdaworks.FeltOne()) + *n = (*n).(Felt).Sub(FeltOne()) // if `new_n` is positive, insert 1 in the address of `continue_loop` // else, insert 0 var flag *MaybeRelocatable - if (*n).(lambdaworks.Felt).IsPositive() { - flag = NewMaybeRelocatableFelt(lambdaworks.FeltOne()) + if (*n).(Felt).IsPositive() { + flag = NewMaybeRelocatableFelt(FeltOne()) } else { - flag = NewMaybeRelocatableFelt(lambdaworks.FeltZero()) + flag = NewMaybeRelocatableFelt(FeltZero()) } err = ids.Insert(i_name, flag, vm) if err != nil { @@ -65,7 +65,7 @@ func memset_step_loop(ids IdsManager, vm *VirtualMachine, execScoes *types.Execu } // Implements hint: vm_enter_scope() -func vm_enter_scope(executionScopes *types.ExecutionScopes) error { +func vm_enter_scope(executionScopes *ExecutionScopes) error { executionScopes.EnterScope(make(map[string]interface{})) return nil } diff --git a/pkg/hints/memcpy_hints_test.go b/pkg/hints/memcpy_hints_test.go index 470e880f..4005b51a 100644 --- a/pkg/hints/memcpy_hints_test.go +++ b/pkg/hints/memcpy_hints_test.go @@ -5,7 +5,6 @@ import ( . "github.com/lambdaclass/cairo-vm.go/pkg/hints" . "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_utils" - "github.com/lambdaclass/cairo-vm.go/pkg/lambdaworks" . "github.com/lambdaclass/cairo-vm.go/pkg/lambdaworks" . "github.com/lambdaclass/cairo-vm.go/pkg/types" . "github.com/lambdaclass/cairo-vm.go/pkg/vm" @@ -106,8 +105,8 @@ func TestMemcpyEnterScopeHintValid(t *testing.T) { if err != nil { t.Errorf("TestMemcpyEnterScopeHintValid failed with error %s", err) } - if res.(lambdaworks.Felt) != lambdaworks.FeltFromDecString("45") { - t.Errorf("TestMemcpyEnterScopeHintValid failed, expected len: %d, got: %d", lambdaworks.FeltFromDecString("45"), res.(lambdaworks.Felt)) + if res.(Felt) != FeltFromDecString("45") { + t.Errorf("TestMemcpyEnterScopeHintValid failed, expected len: %d, got: %d", FeltFromDecString("45"), res.(Felt)) } } @@ -162,11 +161,11 @@ func TestMemcpyContinueCopyingValid(t *testing.T) { vm.Segments.AddSegment() vm.Segments.AddSegment() vm.RunContext.Fp = NewRelocatable(2, 0) - vm.Segments.Memory.Data[NewRelocatable(1, 2)] = *NewMaybeRelocatableFelt(lambdaworks.FeltFromUint64(5)) + vm.Segments.Memory.Data[NewRelocatable(1, 2)] = *NewMaybeRelocatableFelt(FeltFromUint64(5)) executionScopes := NewExecutionScopes() scope := make(map[string]interface{}) - scope["n"] = lambdaworks.FeltOne() + scope["n"] = FeltOne() executionScopes.EnterScope(scope) idsManager := SetupIdsForTest( @@ -191,7 +190,7 @@ func TestMemcpyContinueCopyingVarNotInScope(t *testing.T) { vm := NewVirtualMachine() vm.Segments.AddSegment() vm.RunContext.Fp = NewRelocatable(3, 0) - vm.Segments.Memory.Insert(NewRelocatable(0, 2), NewMaybeRelocatableFelt(lambdaworks.FeltFromUint64(5))) + vm.Segments.Memory.Insert(NewRelocatable(0, 2), NewMaybeRelocatableFelt(FeltFromUint64(5))) executionScopes := NewExecutionScopes() @@ -220,7 +219,7 @@ func TestMemcpyContinueCopyingInsertError(t *testing.T) { executionScopes := NewExecutionScopes() scope := make(map[string]interface{}) - scope["n"] = lambdaworks.FeltOne() + scope["n"] = FeltOne() executionScopes.EnterScope(scope) idsManager := SetupIdsForTest( @@ -245,7 +244,7 @@ func TestMemcpyContinueCopyingInsertError(t *testing.T) { // func TestMemsetContinueCopyingValidEqual5Hint(t *testing.T) { // vm := NewVirtualMachine() // vm.RunContext.Fp = NewRelocatable(1, 0) -// vm.Segments.Memory.Data[NewRelocatable(1, 2)] = *NewMaybeRelocatableFelt(lambdaworks.FeltFromUint64(5)) +// vm.Segments.Memory.Data[NewRelocatable(1, 2)] = *NewMaybeRelocatableFelt(FeltFromUint64(5)) // idsManager := SetupIdsForTest( // map[string][]*MaybeRelocatable{ // "continue_copying": nil, @@ -260,7 +259,7 @@ func TestMemcpyContinueCopyingInsertError(t *testing.T) { // executionScopes := NewExecutionScopes() // scope := make(map[string]interface{}) -// scope["n"] = lambdaworks.FeltFromUint64(5) +// scope["n"] = FeltFromUint64(5) // executionScopes.EnterScope(scope) // err := hintProcessor.ExecuteHint(vm, &hintData, nil, executionScopes) // if err != nil { @@ -271,6 +270,6 @@ func TestMemcpyContinueCopyingInsertError(t *testing.T) { // t.Errorf("TestMemsetContinueCopyingValidEqual5Hint failed with error %s", err) // } // if val != FeltZero() { -// t.Errorf("TestMemsetContinueCopyingValidEqual5Hint failed, expected %d, got: %d", lambdaworks.FeltZero(), val) +// t.Errorf("TestMemsetContinueCopyingValidEqual5Hint failed, expected %d, got: %d", FeltZero(), val) // } // } diff --git a/pkg/hints/memset_hints.go b/pkg/hints/memset_hints.go index 8df404b5..235d2c91 100644 --- a/pkg/hints/memset_hints.go +++ b/pkg/hints/memset_hints.go @@ -2,15 +2,14 @@ package hints import ( . "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_utils" - "github.com/lambdaclass/cairo-vm.go/pkg/types" + . "github.com/lambdaclass/cairo-vm.go/pkg/types" . "github.com/lambdaclass/cairo-vm.go/pkg/vm" - . "github.com/lambdaclass/cairo-vm.go/pkg/vm/memory" ) // Implements hint: // %{ vm_enter_scope({'n': ids.n}) %} -func memset_enter_scope(ids IdsManager, vm *VirtualMachine, execScopes *types.ExecutionScopes) error { - n, err := ids.Get("n") +func memset_enter_scope(ids IdsManager, vm *VirtualMachine, execScopes *ExecutionScopes) error { + n, err := ids.Get("n", vm) if err != nil { return err } From 8b0891826cc6697c54d176216e24eee26f35d59c Mon Sep 17 00:00:00 2001 From: toni-calvin Date: Tue, 19 Sep 2023 12:12:13 +0200 Subject: [PATCH 09/23] abstract error --- pkg/hints/hint_utils/ids_manager.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/hints/hint_utils/ids_manager.go b/pkg/hints/hint_utils/ids_manager.go index 06ed7d33..ac7e8bd9 100644 --- a/pkg/hints/hint_utils/ids_manager.go +++ b/pkg/hints/hint_utils/ids_manager.go @@ -24,6 +24,10 @@ func ErrUnknownIdentifier(name string) error { return ErrIdsManager(errors.Errorf("Unknow identifier %s", name)) } +func ErrIdentifierNotFelt(name string) error { + return ErrIdsManager(errors.Errorf("Identifier %s is not a Felt", name)) +} + func NewIdsManager(references map[string]HintReference, hintApTracking parser.ApTrackingData) IdsManager { return IdsManager{ References: references, @@ -49,7 +53,7 @@ func (ids *IdsManager) GetFelt(name string, vm *VirtualMachine) (lambdaworks.Fel } felt, is_felt := val.GetFelt() if !is_felt { - return lambdaworks.Felt{}, errors.Errorf("Identifier %s is not a Felt", name) + return lambdaworks.Felt{}, ErrIdentifierNotFelt(name) } return felt, nil } From 3ceeae8279d61271c884b4ea972be6bc9168c227 Mon Sep 17 00:00:00 2001 From: toni-calvin Date: Tue, 19 Sep 2023 12:12:46 +0200 Subject: [PATCH 10/23] add aux utils methods --- pkg/utils/utils.go | 19 +++++++++++++++++++ pkg/vm/memory/relocatable.go | 5 ----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 6e7ee63a..52a114e2 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -1,6 +1,9 @@ package utils import ( + . "github.com/lambdaclass/cairo-vm.go/pkg/lambdaworks" + . "github.com/lambdaclass/cairo-vm.go/pkg/vm/memory" + "github.com/pkg/errors" ) @@ -38,3 +41,19 @@ func CheckBuiltinsSubsequence(programBuiltins []string) error { } return nil } + +// Creates a new MaybeRelocatable from a uint64 value +func NewMaybeRelocatableFeltFromUint64(val uint64) *MaybeRelocatable { + return NewMaybeRelocatableFelt(FeltFromUint64(val)) +} + +func NewMaybeRelocatableRelocatableParams(segment_idx int, offset uint) *MaybeRelocatable { + return NewMaybeRelocatableRelocatable(NewRelocatable(segment_idx, offset)) +} + +func AddNSegments(segments MemorySegmentManager, nSegments int) MemorySegmentManager { + for i := 0; i < nSegments; i++ { + segments.AddSegment() + } + return segments +} diff --git a/pkg/vm/memory/relocatable.go b/pkg/vm/memory/relocatable.go index 557cefb0..756f5afb 100644 --- a/pkg/vm/memory/relocatable.go +++ b/pkg/vm/memory/relocatable.go @@ -107,11 +107,6 @@ func NewMaybeRelocatableFelt(felt lambdaworks.Felt) *MaybeRelocatable { return &MaybeRelocatable{inner: felt} } -// Creates a new MaybeRelocatable from a uint64 value -func NewMaybeRelocatableFeltFromUint64(val uint64) *MaybeRelocatable { - return NewMaybeRelocatableFelt(lambdaworks.FeltFromUint64(val)) -} - // Creates a new MaybeRelocatable with a Relocatable inner value func NewMaybeRelocatableRelocatable(relocatable Relocatable) *MaybeRelocatable { return &MaybeRelocatable{inner: relocatable} From a1c199024502fa0f104288db3eaaf1e3ba2742be Mon Sep 17 00:00:00 2001 From: toni-calvin Date: Tue, 19 Sep 2023 12:14:05 +0200 Subject: [PATCH 11/23] change from MaybeRelocatable to Felt when returning n identifier --- pkg/hints/memset_hints.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/hints/memset_hints.go b/pkg/hints/memset_hints.go index 235d2c91..19a2c39a 100644 --- a/pkg/hints/memset_hints.go +++ b/pkg/hints/memset_hints.go @@ -9,7 +9,7 @@ import ( // Implements hint: // %{ vm_enter_scope({'n': ids.n}) %} func memset_enter_scope(ids IdsManager, vm *VirtualMachine, execScopes *ExecutionScopes) error { - n, err := ids.Get("n", vm) + n, err := ids.GetFelt("n", vm) if err != nil { return err } From 5d9c089818b0b4bd8e65d2b8fbea094f6bf3e17b Mon Sep 17 00:00:00 2001 From: toni-calvin Date: Tue, 19 Sep 2023 12:14:19 +0200 Subject: [PATCH 12/23] add tests --- pkg/hints/memset_hints_test.go | 75 ++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/pkg/hints/memset_hints_test.go b/pkg/hints/memset_hints_test.go index a21420aa..5be53d8c 100644 --- a/pkg/hints/memset_hints_test.go +++ b/pkg/hints/memset_hints_test.go @@ -1 +1,76 @@ package hints_test + +import ( + "testing" + + . "github.com/lambdaclass/cairo-vm.go/pkg/hints" + . "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_utils" + . "github.com/lambdaclass/cairo-vm.go/pkg/lambdaworks" + + . "github.com/lambdaclass/cairo-vm.go/pkg/types" + + . "github.com/lambdaclass/cairo-vm.go/pkg/vm" + + . "github.com/lambdaclass/cairo-vm.go/pkg/utils" + + . "github.com/lambdaclass/cairo-vm.go/pkg/vm/memory" +) + +func TestMemsetEnterScopeValid(t *testing.T) { + vm := NewVirtualMachine() + vm.Segments = AddNSegments(vm.Segments, 2) + vm.RunContext.Fp = NewRelocatable(1, 2) + vm.Segments.Memory.Insert(NewRelocatable(1, 1), NewMaybeRelocatableFeltFromUint64(5)) + idsManager := SetupIdsForTest( + map[string][]*MaybeRelocatable{ + "n": {NewMaybeRelocatableFeltFromUint64(4)}, + }, + vm, + ) + hintProcessor := CairoVmHintProcessor{} + hintData := any(HintData{ + Ids: idsManager, + Code: MEMSET_ENTER_SCOPE, + }) + + executionScopes := NewExecutionScopes() + err := hintProcessor.ExecuteHint(vm, &hintData, nil, executionScopes) + if err != nil { + t.Errorf("failed with error %s", err) + } + val, err := executionScopes.Get("n") + if err != nil { + t.Errorf("failed with error %s", err) + } + + if val.(Felt) != FeltFromUint64(4) { + t.Errorf("failed, expected value: %s, got: %s", FeltFromUint64(4).ToSignedFeltString(), val.(Felt).ToSignedFeltString()) + + } +} + +func TestMemsetEnterScopeInvalid(t *testing.T) { + vm := NewVirtualMachine() + vm.Segments = AddNSegments(vm.Segments, 2) + vm.RunContext.Fp = NewRelocatable(1, 1) + // insert a relocatable value in the address of ids.len so that it raises an error. + vm.Segments.Memory.Insert(NewRelocatable(1, 1), NewMaybeRelocatableRelocatableParams(1, 0)) + idsManager := SetupIdsForTest( + map[string][]*MaybeRelocatable{ + "n": {NewMaybeRelocatableRelocatableParams(3, 4)}, + }, + vm, + ) + hintProcessor := CairoVmHintProcessor{} + hintData := any(HintData{ + Ids: idsManager, + Code: MEMSET_ENTER_SCOPE, + }) + + executionScopes := NewExecutionScopes() + err := hintProcessor.ExecuteHint(vm, &hintData, nil, executionScopes) + if err.Error() != ErrIdentifierNotFelt("n").Error() { + t.Errorf("should fail with: %s", ErrIdentifierNotFelt("n").Error()) + } + +} From 65b8ce6d632b4b4306f950b0f2a318a3dfdaf346 Mon Sep 17 00:00:00 2001 From: toni-calvin Date: Tue, 19 Sep 2023 13:46:23 +0200 Subject: [PATCH 13/23] add continue loop hint --- pkg/hints/hint_processor.go | 2 + pkg/hints/memcpy_hints_test.go | 33 ---------- pkg/hints/memset_hint_codes.go | 1 + pkg/hints/memset_hints_test.go | 107 +++++++++++++++++++++++++++++++++ pkg/types/exec_scope_utils.go | 7 +++ 5 files changed, 117 insertions(+), 33 deletions(-) create mode 100644 pkg/types/exec_scope_utils.go diff --git a/pkg/hints/hint_processor.go b/pkg/hints/hint_processor.go index 63c78a8a..d5950744 100644 --- a/pkg/hints/hint_processor.go +++ b/pkg/hints/hint_processor.go @@ -73,6 +73,8 @@ func (p *CairoVmHintProcessor) ExecuteHint(vm *vm.VirtualMachine, hintData *any, return memset_enter_scope(data.Ids, vm, execScopes) case MEMCPY_CONTINUE_COPYING: return memset_step_loop(data.Ids, vm, execScopes, "continue_copying") + case MEMSET_CONTINUE_LOOP: + return memset_step_loop(data.Ids, vm, execScopes, "continue_loop") default: return errors.Errorf("Unknown Hint: %s", data.Code) } diff --git a/pkg/hints/memcpy_hints_test.go b/pkg/hints/memcpy_hints_test.go index 941216f3..eb5d159d 100644 --- a/pkg/hints/memcpy_hints_test.go +++ b/pkg/hints/memcpy_hints_test.go @@ -241,36 +241,3 @@ func TestMemcpyContinueCopyingInsertError(t *testing.T) { t.Errorf("TestMemcpyContinueCopyingInsertError should fail with error %s", expected) } } - -// func TestMemsetContinueCopyingValidEqual5Hint(t *testing.T) { -// vm := NewVirtualMachine() -// vm.RunContext.Fp = NewRelocatable(1, 0) -// vm.Segments.Memory.Data[NewRelocatable(1, 2)] = *NewMaybeRelocatableFelt(FeltFromUint64(5)) -// idsManager := SetupIdsForTest( -// map[string][]*MaybeRelocatable{ -// "continue_copying": nil, -// }, -// vm, -// ) -// hintProcessor := CairoVmHintProcessor{} -// hintData := any(HintData{ -// Ids: idsManager, -// Code: MEMCPY_CONTINUE_COPYING, -// }) - -// executionScopes := NewExecutionScopes() -// scope := make(map[string]interface{}) -// scope["n"] = FeltFromUint64(5) -// executionScopes.EnterScope(scope) -// err := hintProcessor.ExecuteHint(vm, &hintData, nil, executionScopes) -// if err != nil { -// t.Errorf("TestMemsetContinueCopyingValidEqual5Hint failed with error %s", err) -// } -// val, err := vm.Segments.Memory.GetFelt(NewRelocatable(1, 0)) -// if err != nil { -// t.Errorf("TestMemsetContinueCopyingValidEqual5Hint failed with error %s", err) -// } -// if val != FeltZero() { -// t.Errorf("TestMemsetContinueCopyingValidEqual5Hint failed, expected %d, got: %d", FeltZero(), val) -// } -// } diff --git a/pkg/hints/memset_hint_codes.go b/pkg/hints/memset_hint_codes.go index 98489424..270f621c 100644 --- a/pkg/hints/memset_hint_codes.go +++ b/pkg/hints/memset_hint_codes.go @@ -1,3 +1,4 @@ package hints const MEMSET_ENTER_SCOPE = "vm_enter_scope({'n': ids.n})" +const MEMSET_CONTINUE_LOOP = "n -= 1 ids.continue_loop = 1 if n > 0 else 0" diff --git a/pkg/hints/memset_hints_test.go b/pkg/hints/memset_hints_test.go index 5be53d8c..7e6e585e 100644 --- a/pkg/hints/memset_hints_test.go +++ b/pkg/hints/memset_hints_test.go @@ -74,3 +74,110 @@ func TestMemsetEnterScopeInvalid(t *testing.T) { } } + +func TestMemsetContinueLoopValidEqual1Hint(t *testing.T) { + vm := NewVirtualMachine() + vm.RunContext.Fp = NewRelocatable(1, 0) + vm.Segments = AddNSegments(vm.Segments, 2) + executionScopes := NewExecutionScopesWithInitValue("n", FeltFromUint64(1)) + + idsManager := SetupIdsForTest( + map[string][]*MaybeRelocatable{ + "continue_loop": {NewMaybeRelocatableFeltFromUint64(0)}, + }, + vm, + ) + hintProcessor := CairoVmHintProcessor{} + hintData := any(HintData{ + Ids: idsManager, + Code: MEMSET_CONTINUE_LOOP, + }) + + err := hintProcessor.ExecuteHint(vm, &hintData, nil, executionScopes) + if err != nil { + t.Errorf("failed with error %s", err) + } + val, err := vm.Segments.Memory.GetFelt(NewRelocatable(1, 0)) + if err != nil { + t.Errorf("failed with error %s", err) + } + if val != FeltZero() { + t.Errorf("failed, expected %d, got: %d", FeltZero(), val) + } +} + +func TestMemsetContinueLoopValidEqual5Hint(t *testing.T) { + vm := NewVirtualMachine() + vm.RunContext.Fp = NewRelocatable(1, 0) + vm.Segments = AddNSegments(vm.Segments, 2) + executionScopes := NewExecutionScopesWithInitValue("n", FeltFromUint64(5)) + + idsManager := SetupIdsForTest( + map[string][]*MaybeRelocatable{ + "continue_loop": {NewMaybeRelocatableFeltFromUint64(1)}, + }, + vm, + ) + hintProcessor := CairoVmHintProcessor{} + hintData := any(HintData{ + Ids: idsManager, + Code: MEMSET_CONTINUE_LOOP, + }) + + err := hintProcessor.ExecuteHint(vm, &hintData, nil, executionScopes) + if err != nil { + t.Errorf("failed with error %s", err) + } + val, err := vm.Segments.Memory.GetFelt(NewRelocatable(1, 0)) + if err != nil { + t.Errorf("failed with error %s", err) + } + if val != FeltOne() { + t.Errorf("failed, expected %d, got: %d", FeltOne(), val) + } +} + +func TestMemsetContinueLoopVarNotInScope(t *testing.T) { + vm := NewVirtualMachine() + vm.Segments.AddSegment() + executionScopes := NewExecutionScopes() + idsManager := SetupIdsForTest( + map[string][]*MaybeRelocatable{ + "continue_loop": {NewMaybeRelocatableFeltFromUint64(1)}, + }, + vm, + ) + hintProcessor := CairoVmHintProcessor{} + hintData := any(HintData{ + Ids: idsManager, + Code: MEMSET_CONTINUE_LOOP, + }) + + err := hintProcessor.ExecuteHint(vm, &hintData, nil, executionScopes) + if err.Error() != ErrVariableNotInScope("n").Error() { + t.Errorf("should fail with error %s", ErrVariableNotInScope("n")) + } +} + +func TestMemsetContinueLoopInsertError(t *testing.T) { + vm := NewVirtualMachine() + vm.Segments = AddNSegments(vm.Segments, 2) + executionScopes := NewExecutionScopesWithInitValue("n", FeltOne()) + idsManager := SetupIdsForTest( + map[string][]*MaybeRelocatable{ + "continue_loop": {NewMaybeRelocatableFelt(FeltFromUint64(5))}, + }, + vm, + ) + hintProcessor := CairoVmHintProcessor{} + hintData := any(HintData{ + Ids: idsManager, + Code: MEMSET_CONTINUE_LOOP, + }) + + err := hintProcessor.ExecuteHint(vm, &hintData, nil, executionScopes) + expected := ErrMemoryWriteOnce(NewRelocatable(0, 0), *NewMaybeRelocatableFeltFromUint64(5), *NewMaybeRelocatableFeltFromUint64(0)) + if err.Error() != expected.Error() { + t.Errorf("should fail with error %s", expected) + } +} diff --git a/pkg/types/exec_scope_utils.go b/pkg/types/exec_scope_utils.go new file mode 100644 index 00000000..4a6cab69 --- /dev/null +++ b/pkg/types/exec_scope_utils.go @@ -0,0 +1,7 @@ +package types + +func NewExecutionScopesWithInitValue(key string, val interface{}) *ExecutionScopes { + scopes := NewExecutionScopes() + scopes.EnterScope(map[string]interface{}{key: val}) + return scopes +} From 88ae47ab19500e301b2228aa07c184b6b4182f53 Mon Sep 17 00:00:00 2001 From: toni-calvin Date: Tue, 19 Sep 2023 14:24:21 +0200 Subject: [PATCH 14/23] use utils method for adding segments --- pkg/hints/memcpy_hints_test.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pkg/hints/memcpy_hints_test.go b/pkg/hints/memcpy_hints_test.go index eb5d159d..27aeea9a 100644 --- a/pkg/hints/memcpy_hints_test.go +++ b/pkg/hints/memcpy_hints_test.go @@ -158,9 +158,7 @@ func TestEnterScope(t *testing.T) { func TestMemcpyContinueCopyingValid(t *testing.T) { vm := NewVirtualMachine() - vm.Segments.AddSegment() - vm.Segments.AddSegment() - vm.Segments.AddSegment() + vm.Segments = AddNSegments(vm.Segments, 3) vm.RunContext.Fp = NewRelocatable(2, 0) vm.Segments.Memory.Data[NewRelocatable(1, 2)] = *NewMaybeRelocatableFelt(FeltFromUint64(5)) @@ -215,8 +213,7 @@ func TestMemcpyContinueCopyingVarNotInScope(t *testing.T) { func TestMemcpyContinueCopyingInsertError(t *testing.T) { vm := NewVirtualMachine() - vm.Segments.AddSegment() - vm.Segments.AddSegment() + vm.Segments = AddNSegments(vm.Segments, 2) executionScopes := NewExecutionScopes() scope := make(map[string]interface{}) From 4889d5351802703cda3353030ec3e4883cb5d225 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Calv=C3=ADn=20Garc=C3=ADa?= Date: Tue, 19 Sep 2023 16:57:35 +0200 Subject: [PATCH 15/23] fix memcpy_continue_coding hint code Co-authored-by: Juan-M-V <102986292+Juan-M-V@users.noreply.github.com> --- pkg/hints/memcpy_hint_codes.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/hints/memcpy_hint_codes.go b/pkg/hints/memcpy_hint_codes.go index 0340ead2..d732c38f 100644 --- a/pkg/hints/memcpy_hint_codes.go +++ b/pkg/hints/memcpy_hint_codes.go @@ -4,4 +4,4 @@ const ADD_SEGMENT = "memory[ap] = segments.add()" const VM_EXIT_SCOPE = "vm_exit_scope()" const VM_ENTER_SCOPE = "vm_enter_scope()" const MEMCPY_ENTER_SCOPE = "vm_enter_scope({'n': ids.len})" -const MEMCPY_CONTINUE_COPYING = "n -= 1 ids.continue_copying = 1 if n > 0 else 0" +const MEMCPY_CONTINUE_COPYING = "n -= 1\nids.continue_copying = 1 if n > 0 else 0" From 556cf70e663bc6d49e3c38a59c823e72e70b3659 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Calv=C3=ADn=20Garc=C3=ADa?= Date: Tue, 19 Sep 2023 16:58:58 +0200 Subject: [PATCH 16/23] improve returned value in memset_step_loop method Co-authored-by: fmoletta <99273364+fmoletta@users.noreply.github.com> --- pkg/hints/memcpy_hints.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pkg/hints/memcpy_hints.go b/pkg/hints/memcpy_hints.go index 14fb4760..a9a12008 100644 --- a/pkg/hints/memcpy_hints.go +++ b/pkg/hints/memcpy_hints.go @@ -57,11 +57,7 @@ func memset_step_loop(ids IdsManager, vm *VirtualMachine, execScoes *ExecutionSc } else { flag = NewMaybeRelocatableFelt(FeltZero()) } - err = ids.Insert(i_name, flag, vm) - if err != nil { - return err - } - return nil + return ids.Insert(i_name, flag, vm) } // Implements hint: vm_enter_scope() From 9efe91fc0914b9aee9ecaa04f11e4af58255c604 Mon Sep 17 00:00:00 2001 From: toni-calvin Date: Tue, 19 Sep 2023 17:12:26 +0200 Subject: [PATCH 17/23] delete GetRef method fromexecScopes --- pkg/hints/memcpy_hints.go | 14 ++++++++++---- pkg/types/exec_scope_test.go | 20 -------------------- pkg/types/exec_scopes.go | 8 -------- 3 files changed, 10 insertions(+), 32 deletions(-) diff --git a/pkg/hints/memcpy_hints.go b/pkg/hints/memcpy_hints.go index a9a12008..8b7cb7b1 100644 --- a/pkg/hints/memcpy_hints.go +++ b/pkg/hints/memcpy_hints.go @@ -43,16 +43,22 @@ func memcpy_enter_scope(ids IdsManager, vm *VirtualMachine, execScopes *Executio */ func memset_step_loop(ids IdsManager, vm *VirtualMachine, execScoes *ExecutionScopes, i_name string) error { // get `n` variable from vm scope - n, err := execScoes.GetRef("n") + n, err := execScoes.Get("n") if err != nil { return err } // this variable will hold the value of `n - 1` - *n = (*n).(Felt).Sub(FeltOne()) - // if `new_n` is positive, insert 1 in the address of `continue_loop` + newN, ok := n.(Felt) + if !ok { + return ConversionError(n, "felt") + } + newN = newN.Sub(FeltOne()) + execScoes.AssignOrUpdateVariable("n", newN) + + // if `newN` is positive, insert 1 in the address of `continue_loop` // else, insert 0 var flag *MaybeRelocatable - if (*n).(Felt).IsPositive() { + if newN.IsPositive() { flag = NewMaybeRelocatableFelt(FeltOne()) } else { flag = NewMaybeRelocatableFelt(FeltZero()) diff --git a/pkg/types/exec_scope_test.go b/pkg/types/exec_scope_test.go index 1ee54fd9..119f266d 100644 --- a/pkg/types/exec_scope_test.go +++ b/pkg/types/exec_scope_test.go @@ -26,26 +26,6 @@ func TestGetLocalVariables(t *testing.T) { } } -func TestGetRefLocalVariables(t *testing.T) { - scope := make(map[string]interface{}) - scope["k"] = lambdaworks.FeltOne() - - scopes := types.NewExecutionScopes() - scopes.EnterScope(scope) - - result, err := scopes.GetRef("k") - if err != nil { - t.Errorf("TestGetRefLocalVariables failed with error: %s", err) - - } - f_one := lambdaworks.FeltOne() - f_res := (*result).(lambdaworks.Felt) - expected := &f_one - if *expected != f_res { - t.Errorf("TestGetRefLocalVariables failed, expected: %d, got: %d", expected, &f_res) - } -} - func TestEnterNewScope(t *testing.T) { scope := make(map[string]interface{}) scope["a"] = lambdaworks.FeltOne() diff --git a/pkg/types/exec_scopes.go b/pkg/types/exec_scopes.go index 50f15213..357a1cec 100644 --- a/pkg/types/exec_scopes.go +++ b/pkg/types/exec_scopes.go @@ -82,11 +82,3 @@ func (es *ExecutionScopes) Get(varName string) (interface{}, error) { } return val, nil } - -func (es *ExecutionScopes) GetRef(varName string) (*interface{}, error) { - val, err := es.Get(varName) - if err != nil { - return nil, err - } - return &val, err -} From ad0c5630e39ae0b1b643833ad672b853e2ee1f04 Mon Sep 17 00:00:00 2001 From: toni-calvin Date: Tue, 19 Sep 2023 17:13:10 +0200 Subject: [PATCH 18/23] Revert "delete GetRef method fromexecScopes" This reverts commit 9efe91fc0914b9aee9ecaa04f11e4af58255c604. --- pkg/hints/memcpy_hints.go | 14 ++++---------- pkg/types/exec_scope_test.go | 20 ++++++++++++++++++++ pkg/types/exec_scopes.go | 8 ++++++++ 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/pkg/hints/memcpy_hints.go b/pkg/hints/memcpy_hints.go index 8b7cb7b1..a9a12008 100644 --- a/pkg/hints/memcpy_hints.go +++ b/pkg/hints/memcpy_hints.go @@ -43,22 +43,16 @@ func memcpy_enter_scope(ids IdsManager, vm *VirtualMachine, execScopes *Executio */ func memset_step_loop(ids IdsManager, vm *VirtualMachine, execScoes *ExecutionScopes, i_name string) error { // get `n` variable from vm scope - n, err := execScoes.Get("n") + n, err := execScoes.GetRef("n") if err != nil { return err } // this variable will hold the value of `n - 1` - newN, ok := n.(Felt) - if !ok { - return ConversionError(n, "felt") - } - newN = newN.Sub(FeltOne()) - execScoes.AssignOrUpdateVariable("n", newN) - - // if `newN` is positive, insert 1 in the address of `continue_loop` + *n = (*n).(Felt).Sub(FeltOne()) + // if `new_n` is positive, insert 1 in the address of `continue_loop` // else, insert 0 var flag *MaybeRelocatable - if newN.IsPositive() { + if (*n).(Felt).IsPositive() { flag = NewMaybeRelocatableFelt(FeltOne()) } else { flag = NewMaybeRelocatableFelt(FeltZero()) diff --git a/pkg/types/exec_scope_test.go b/pkg/types/exec_scope_test.go index 119f266d..1ee54fd9 100644 --- a/pkg/types/exec_scope_test.go +++ b/pkg/types/exec_scope_test.go @@ -26,6 +26,26 @@ func TestGetLocalVariables(t *testing.T) { } } +func TestGetRefLocalVariables(t *testing.T) { + scope := make(map[string]interface{}) + scope["k"] = lambdaworks.FeltOne() + + scopes := types.NewExecutionScopes() + scopes.EnterScope(scope) + + result, err := scopes.GetRef("k") + if err != nil { + t.Errorf("TestGetRefLocalVariables failed with error: %s", err) + + } + f_one := lambdaworks.FeltOne() + f_res := (*result).(lambdaworks.Felt) + expected := &f_one + if *expected != f_res { + t.Errorf("TestGetRefLocalVariables failed, expected: %d, got: %d", expected, &f_res) + } +} + func TestEnterNewScope(t *testing.T) { scope := make(map[string]interface{}) scope["a"] = lambdaworks.FeltOne() diff --git a/pkg/types/exec_scopes.go b/pkg/types/exec_scopes.go index 357a1cec..50f15213 100644 --- a/pkg/types/exec_scopes.go +++ b/pkg/types/exec_scopes.go @@ -82,3 +82,11 @@ func (es *ExecutionScopes) Get(varName string) (interface{}, error) { } return val, nil } + +func (es *ExecutionScopes) GetRef(varName string) (*interface{}, error) { + val, err := es.Get(varName) + if err != nil { + return nil, err + } + return &val, err +} From a4d467c88e98c3208d05b32f512cd07ba14f1916 Mon Sep 17 00:00:00 2001 From: toni-calvin Date: Tue, 19 Sep 2023 17:14:20 +0200 Subject: [PATCH 19/23] Revert "Revert "delete GetRef method fromexecScopes"" This reverts commit ad0c5630e39ae0b1b643833ad672b853e2ee1f04. --- pkg/hints/memcpy_hints.go | 14 ++++++++++---- pkg/types/exec_scope_test.go | 20 -------------------- pkg/types/exec_scopes.go | 8 -------- 3 files changed, 10 insertions(+), 32 deletions(-) diff --git a/pkg/hints/memcpy_hints.go b/pkg/hints/memcpy_hints.go index a9a12008..8b7cb7b1 100644 --- a/pkg/hints/memcpy_hints.go +++ b/pkg/hints/memcpy_hints.go @@ -43,16 +43,22 @@ func memcpy_enter_scope(ids IdsManager, vm *VirtualMachine, execScopes *Executio */ func memset_step_loop(ids IdsManager, vm *VirtualMachine, execScoes *ExecutionScopes, i_name string) error { // get `n` variable from vm scope - n, err := execScoes.GetRef("n") + n, err := execScoes.Get("n") if err != nil { return err } // this variable will hold the value of `n - 1` - *n = (*n).(Felt).Sub(FeltOne()) - // if `new_n` is positive, insert 1 in the address of `continue_loop` + newN, ok := n.(Felt) + if !ok { + return ConversionError(n, "felt") + } + newN = newN.Sub(FeltOne()) + execScoes.AssignOrUpdateVariable("n", newN) + + // if `newN` is positive, insert 1 in the address of `continue_loop` // else, insert 0 var flag *MaybeRelocatable - if (*n).(Felt).IsPositive() { + if newN.IsPositive() { flag = NewMaybeRelocatableFelt(FeltOne()) } else { flag = NewMaybeRelocatableFelt(FeltZero()) diff --git a/pkg/types/exec_scope_test.go b/pkg/types/exec_scope_test.go index 1ee54fd9..119f266d 100644 --- a/pkg/types/exec_scope_test.go +++ b/pkg/types/exec_scope_test.go @@ -26,26 +26,6 @@ func TestGetLocalVariables(t *testing.T) { } } -func TestGetRefLocalVariables(t *testing.T) { - scope := make(map[string]interface{}) - scope["k"] = lambdaworks.FeltOne() - - scopes := types.NewExecutionScopes() - scopes.EnterScope(scope) - - result, err := scopes.GetRef("k") - if err != nil { - t.Errorf("TestGetRefLocalVariables failed with error: %s", err) - - } - f_one := lambdaworks.FeltOne() - f_res := (*result).(lambdaworks.Felt) - expected := &f_one - if *expected != f_res { - t.Errorf("TestGetRefLocalVariables failed, expected: %d, got: %d", expected, &f_res) - } -} - func TestEnterNewScope(t *testing.T) { scope := make(map[string]interface{}) scope["a"] = lambdaworks.FeltOne() diff --git a/pkg/types/exec_scopes.go b/pkg/types/exec_scopes.go index 50f15213..357a1cec 100644 --- a/pkg/types/exec_scopes.go +++ b/pkg/types/exec_scopes.go @@ -82,11 +82,3 @@ func (es *ExecutionScopes) Get(varName string) (interface{}, error) { } return val, nil } - -func (es *ExecutionScopes) GetRef(varName string) (*interface{}, error) { - val, err := es.Get(varName) - if err != nil { - return nil, err - } - return &val, err -} From b4cdeca3f2bcb20977afbd941da04ad276c2304e Mon Sep 17 00:00:00 2001 From: toni-calvin Date: Tue, 19 Sep 2023 17:15:46 +0200 Subject: [PATCH 20/23] improve error message --- pkg/lambdaworks/lambdaworks.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/lambdaworks/lambdaworks.go b/pkg/lambdaworks/lambdaworks.go index 475f2717..6f478556 100644 --- a/pkg/lambdaworks/lambdaworks.go +++ b/pkg/lambdaworks/lambdaworks.go @@ -9,6 +9,7 @@ import "C" import ( "math/big" + "reflect" "strings" "unsafe" @@ -29,8 +30,8 @@ func LambdaworksError(err error) error { return errors.Wrapf(err, "Lambdaworks Error") } -func ConversionError(felt Felt, targetType string) error { - return LambdaworksError(errors.Errorf("Cannot convert felt: %d to %s", felt, targetType)) +func ConversionError(val interface{}, targetType string) error { + return LambdaworksError(errors.Errorf("Cannot convert %s: %d to %s", reflect.TypeOf(val), val, targetType)) } // Converts a Go Felt to a C felt_t. From 3611a3843231bbe99ccd79f8f1cdbb555b86a6c5 Mon Sep 17 00:00:00 2001 From: toni-calvin Date: Tue, 19 Sep 2023 18:03:07 +0200 Subject: [PATCH 21/23] improve tests --- pkg/hints/memcpy_hints_test.go | 71 +++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/pkg/hints/memcpy_hints_test.go b/pkg/hints/memcpy_hints_test.go index 27aeea9a..8753f1a8 100644 --- a/pkg/hints/memcpy_hints_test.go +++ b/pkg/hints/memcpy_hints_test.go @@ -50,7 +50,7 @@ func TestExitScopeHintValid(t *testing.T) { err := hintProcessor.ExecuteHint(vm, &hintData, nil, executionScopes) if err != nil { - t.Errorf("TestExitScopeHintValid failed with error %s", err) + t.Errorf("failed with error %s", err) } } @@ -76,7 +76,7 @@ func TestExitScopeHintInvalid(t *testing.T) { err := hintProcessor.ExecuteHint(vm, &hintData, nil, executionScopes) if err.Error() != ErrCannotExitMainScop.Error() { - t.Errorf("TestExitScopeHintInvalid should fail with error %s", ErrCannotExitMainScop) + t.Errorf("should fail with error %s", ErrCannotExitMainScop) } } @@ -100,14 +100,14 @@ func TestMemcpyEnterScopeHintValid(t *testing.T) { executionScopes := NewExecutionScopes() err := hintProcessor.ExecuteHint(vm, &hintData, nil, executionScopes) if err != nil { - t.Errorf("TestMemcpyEnterScopeHintValid failed with error %s", err) + t.Errorf("failed with error %s", err) } res, err := executionScopes.Get("n") if err != nil { - t.Errorf("TestMemcpyEnterScopeHintValid failed with error %s", err) + t.Errorf("failed with error %s", err) } if res.(Felt) != FeltFromDecString("45") { - t.Errorf("TestMemcpyEnterScopeHintValid failed, expected len: %d, got: %d", FeltFromDecString("45"), res.(Felt)) + t.Errorf("failed, expected len: %d, got: %d", FeltFromDecString("45"), res.(Felt)) } } @@ -129,7 +129,7 @@ func TestMemcpyEnterScopeHintInvalid(t *testing.T) { executionScopes := NewExecutionScopes() err := hintProcessor.ExecuteHint(vm, &hintData, nil, executionScopes) if err.Error() != ErrUnknownIdentifier("len").Error() { - t.Errorf("TestMemcpyEnterScopeHintInvalid should fail with error %s", ErrUnknownIdentifier("len")) + t.Errorf("should fail with error %s", ErrUnknownIdentifier("len")) } } @@ -152,20 +152,47 @@ func TestEnterScope(t *testing.T) { err := hintProcessor.ExecuteHint(vm, &hintData, nil, executionScopes) if err != nil { - t.Errorf("TestEnterScopeHint failed with error %s", err) + t.Errorf("failed with error %s", err) } } -func TestMemcpyContinueCopyingValid(t *testing.T) { +func TestMemcpyContinueCopyingValid1(t *testing.T) { vm := NewVirtualMachine() - vm.Segments = AddNSegments(vm.Segments, 3) - vm.RunContext.Fp = NewRelocatable(2, 0) - vm.Segments.Memory.Data[NewRelocatable(1, 2)] = *NewMaybeRelocatableFelt(FeltFromUint64(5)) + vm.Segments = AddNSegments(vm.Segments, 2) + vm.RunContext.Fp = NewRelocatable(1, 2) + executionScopes := NewExecutionScopesWithInitValue("n", FeltOne()) - executionScopes := NewExecutionScopes() - scope := make(map[string]interface{}) - scope["n"] = FeltOne() - executionScopes.EnterScope(scope) + idsManager := SetupIdsForTest( + map[string][]*MaybeRelocatable{ + "continue_copying": nil, + }, + vm, + ) + hintProcessor := CairoVmHintProcessor{} + hintData := any(HintData{ + Ids: idsManager, + Code: MEMCPY_CONTINUE_COPYING, + }) + + err := hintProcessor.ExecuteHint(vm, &hintData, nil, executionScopes) + if err != nil { + t.Errorf("failed with error %s", err) + } + + val, err := idsManager.GetFelt("continue_copying", vm) + if err != nil { + t.Errorf("failed with error %s", err) + } + if val != FeltZero() { + t.Errorf("failed, expected val: %d, got: %d", FeltZero(), val) + } +} + +func TestMemcpyContinueCopyingValidNeg1(t *testing.T) { + vm := NewVirtualMachine() + vm.Segments = AddNSegments(vm.Segments, 2) + vm.RunContext.Fp = NewRelocatable(1, 2) + executionScopes := NewExecutionScopesWithInitValue("n", FeltFromDecString("-1")) idsManager := SetupIdsForTest( map[string][]*MaybeRelocatable{ @@ -181,7 +208,15 @@ func TestMemcpyContinueCopyingValid(t *testing.T) { err := hintProcessor.ExecuteHint(vm, &hintData, nil, executionScopes) if err != nil { - t.Errorf("TestMemsetContinueLoopValidEqual1 failed with error %s", err) + t.Errorf("failed with error %s", err) + } + + val, err := idsManager.GetFelt("continue_copying", vm) + if err != nil { + t.Errorf("failed with error %s", err) + } + if val != FeltOne() { + t.Errorf("failed, expected val: %d, got: %d", FeltOne(), val) } } @@ -207,7 +242,7 @@ func TestMemcpyContinueCopyingVarNotInScope(t *testing.T) { err := hintProcessor.ExecuteHint(vm, &hintData, nil, executionScopes) if err.Error() != ErrVariableNotInScope("n").Error() { - t.Errorf("TestMemcpyContinueCopyingVarNotInScope should fail with error %s", ErrVariableNotInScope("n")) + t.Errorf("should fail with error %s", ErrVariableNotInScope("n")) } } @@ -235,6 +270,6 @@ func TestMemcpyContinueCopyingInsertError(t *testing.T) { err := hintProcessor.ExecuteHint(vm, &hintData, nil, executionScopes) expected := ErrMemoryWriteOnce(NewRelocatable(0, 0), *NewMaybeRelocatableFeltFromUint64(5), *NewMaybeRelocatableFeltFromUint64(0)) if err.Error() != expected.Error() { - t.Errorf("TestMemcpyContinueCopyingInsertError should fail with error %s", expected) + t.Errorf("should fail with error %s", expected) } } From 52a7a4463f5016a547020aa6111c96eebf752416 Mon Sep 17 00:00:00 2001 From: toni-calvin Date: Tue, 19 Sep 2023 18:11:11 +0200 Subject: [PATCH 22/23] add integration tests --- cairo_programs/memcpy_test.cairo | 21 +++++++++++++++++++++ cairo_programs/memset.cairo | 30 ++++++++++++++++++++++++++++++ pkg/hints/memset_hint_codes.go | 2 +- pkg/vm/cairo_run/cairo_run_test.go | 16 ++++++++++++++++ 4 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 cairo_programs/memcpy_test.cairo create mode 100644 cairo_programs/memset.cairo diff --git a/cairo_programs/memcpy_test.cairo b/cairo_programs/memcpy_test.cairo new file mode 100644 index 00000000..cca8d6e4 --- /dev/null +++ b/cairo_programs/memcpy_test.cairo @@ -0,0 +1,21 @@ +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.memcpy import memcpy +from starkware.cairo.common.registers import get_fp_and_pc + +func main() { + alloc_locals; + + let (__fp__, _) = get_fp_and_pc(); + + local numbers: (felt, felt, felt) = (1, 2, 3); + + let dest: felt* = alloc(); + + memcpy(dst=dest, src=&numbers, len=3); + + assert numbers[0] = dest[0]; + assert numbers[1] = dest[1]; + assert numbers[2] = dest[2]; + + return (); +} diff --git a/cairo_programs/memset.cairo b/cairo_programs/memset.cairo new file mode 100644 index 00000000..6f0b3341 --- /dev/null +++ b/cairo_programs/memset.cairo @@ -0,0 +1,30 @@ +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.memset import memset +from starkware.cairo.common.bool import TRUE, FALSE + +func check_array(array: felt*, value: felt, array_length: felt, iterator: felt) -> (r: felt) { + if (iterator == array_length) { + return (TRUE,); + } + if (array[iterator] != value) { + return (FALSE,); + } + return check_array(array, value, array_length, iterator + 1); +} + +func main() { + alloc_locals; + let (local strings: felt*) = alloc(); + memset(strings, 'Lambda', 20); + let check_string: felt = check_array(strings, 'Lambda', 20, 0); + assert check_string = TRUE; + assert strings[20] = 'can insert new value'; + + let numbers: felt* = alloc(); + memset(numbers, 10, 100); + let check_string: felt = check_array(numbers, 10, 100, 0); + assert check_string = TRUE; + assert numbers[100] = 11; + + return (); +} diff --git a/pkg/hints/memset_hint_codes.go b/pkg/hints/memset_hint_codes.go index 270f621c..2425ad41 100644 --- a/pkg/hints/memset_hint_codes.go +++ b/pkg/hints/memset_hint_codes.go @@ -1,4 +1,4 @@ package hints const MEMSET_ENTER_SCOPE = "vm_enter_scope({'n': ids.n})" -const MEMSET_CONTINUE_LOOP = "n -= 1 ids.continue_loop = 1 if n > 0 else 0" +const MEMSET_CONTINUE_LOOP = "n -= 1\nids.continue_loop = 1 if n > 0 else 0" diff --git a/pkg/vm/cairo_run/cairo_run_test.go b/pkg/vm/cairo_run/cairo_run_test.go index 3182e252..21876bd1 100644 --- a/pkg/vm/cairo_run/cairo_run_test.go +++ b/pkg/vm/cairo_run/cairo_run_test.go @@ -202,3 +202,19 @@ func TestSqrtHint(t *testing.T) { t.Errorf("Program execution failed with error: %s", err) } } + +func TestMemcpyHint(t *testing.T) { + cairoRunConfig := cairo_run.CairoRunConfig{DisableTracePadding: false, Layout: "all_cairo", ProofMode: false} + _, err := cairo_run.CairoRun("../../../cairo_programs/memcpy_test.json", cairoRunConfig) + if err != nil { + t.Errorf("Program execution failed with error: %s", err) + } +} + +func TestMemsetHint(t *testing.T) { + cairoRunConfig := cairo_run.CairoRunConfig{DisableTracePadding: false, Layout: "all_cairo", ProofMode: false} + _, err := cairo_run.CairoRun("../../../cairo_programs/memset.json", cairoRunConfig) + if err != nil { + t.Errorf("Program execution failed with error: %s", err) + } +} From 522ffafa510517de3b3993d631d4bf0b41a5f41a Mon Sep 17 00:00:00 2001 From: toni-calvin Date: Tue, 19 Sep 2023 21:28:44 +0200 Subject: [PATCH 23/23] Merge branch 'main' of github.com:lambdaclass/cairo-vm.go into memcpy-hints --- .../assert_250_bit_element_array.cairo | 31 ++ cairo_programs/common_signature.cairo | 13 + cairo_programs/split_felt.cairo | 42 +++ pkg/builtins/signature.go | 7 +- pkg/hints/dict_hints_test.go | 1 + pkg/hints/ec_hint.go | 116 +++++++ pkg/hints/ec_hint_test.go | 134 ++++++++ pkg/hints/{ => hint_codes}/dict_hint_codes.go | 2 +- pkg/hints/hint_codes/ec_op_hints.go | 4 + pkg/hints/{ => hint_codes}/math_hint_codes.go | 8 +- .../{ => hint_codes}/memcpy_hint_codes.go | 2 +- pkg/hints/{ => hint_codes}/pow_hint_codes.go | 2 +- pkg/hints/hint_processor.go | 11 + pkg/hints/math_hints.go | 128 ++++++++ pkg/hints/math_hints_test.go | 306 ++++++++++++++++++ pkg/hints/memcpy_hints_test.go | 1 + pkg/hints/pow_hints.go | 10 +- pkg/hints/pow_hints_test.go | 41 ++- pkg/parser/parser.go | 2 +- pkg/vm/cairo_run/cairo_run_test.go | 23 +- pkg/vm/memory/memory_test.go | 2 +- pkg/vm/program.go | 2 +- pkg/vm/program_test.go | 4 +- 23 files changed, 871 insertions(+), 21 deletions(-) create mode 100644 cairo_programs/assert_250_bit_element_array.cairo create mode 100644 cairo_programs/common_signature.cairo create mode 100644 cairo_programs/split_felt.cairo create mode 100644 pkg/hints/ec_hint.go create mode 100644 pkg/hints/ec_hint_test.go rename pkg/hints/{ => hint_codes}/dict_hint_codes.go (98%) create mode 100644 pkg/hints/hint_codes/ec_op_hints.go rename pkg/hints/{ => hint_codes}/math_hint_codes.go (68%) rename pkg/hints/{ => hint_codes}/memcpy_hint_codes.go (93%) rename pkg/hints/{ => hint_codes}/pow_hint_codes.go (76%) diff --git a/cairo_programs/assert_250_bit_element_array.cairo b/cairo_programs/assert_250_bit_element_array.cairo new file mode 100644 index 00000000..b4307e26 --- /dev/null +++ b/cairo_programs/assert_250_bit_element_array.cairo @@ -0,0 +1,31 @@ +%builtins range_check + +from starkware.cairo.common.math import assert_250_bit +from starkware.cairo.common.alloc import alloc + +func assert_250_bit_element_array{range_check_ptr: felt}( + array: felt*, array_length: felt, iterator: felt +) { + if (iterator == array_length) { + return (); + } + assert_250_bit(array[iterator]); + return assert_250_bit_element_array(array, array_length, iterator + 1); +} + +func fill_array(array: felt*, base: felt, step: felt, array_length: felt, iterator: felt) { + if (iterator == array_length) { + return (); + } + assert array[iterator] = base + step * iterator; + return fill_array(array, base, step, array_length, iterator + 1); +} + +func main{range_check_ptr: felt}() { + alloc_locals; + tempvar array_length = 10; + let (array: felt*) = alloc(); + fill_array(array, 70000000000000000000, 300000000000000000, array_length, 0); + assert_250_bit_element_array(array, array_length, 0); + return (); +} diff --git a/cairo_programs/common_signature.cairo b/cairo_programs/common_signature.cairo new file mode 100644 index 00000000..f9243948 --- /dev/null +++ b/cairo_programs/common_signature.cairo @@ -0,0 +1,13 @@ +%builtins ecdsa +from starkware.cairo.common.cairo_builtins import SignatureBuiltin +from starkware.cairo.common.signature import verify_ecdsa_signature + +func main{ecdsa_ptr: SignatureBuiltin*}() { + verify_ecdsa_signature( + 2718, + 1735102664668487605176656616876767369909409133946409161569774794110049207117, + 3086480810278599376317923499561306189851900463386393948998357832163236918254, + 598673427589502599949712887611119751108407514580626464031881322743364689811, + ); + return (); +} diff --git a/cairo_programs/split_felt.cairo b/cairo_programs/split_felt.cairo new file mode 100644 index 00000000..3790297d --- /dev/null +++ b/cairo_programs/split_felt.cairo @@ -0,0 +1,42 @@ +%builtins range_check + +from starkware.cairo.common.math import assert_le +from starkware.cairo.common.math import split_felt + +func split_felt_manual_implemetation{range_check_ptr}(value) -> (high: felt, low: felt) { + // Note: the following code works because PRIME - 1 is divisible by 2**128. + const MAX_HIGH = (-1) / 2 ** 128; + const MAX_LOW = 0; + + // Guess the low and high parts of the integer. + let low = [range_check_ptr]; + let high = [range_check_ptr + 1]; + let range_check_ptr = range_check_ptr + 2; + + %{ + from starkware.cairo.common.math_utils import assert_integer + assert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128 + assert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW + assert_integer(ids.value) + ids.low = ids.value & ((1 << 128) - 1) + ids.high = ids.value >> 128 + %} + + assert value = high * (2 ** 128) + low; + if (high == MAX_HIGH) { + assert_le(low, MAX_LOW); + } else { + assert_le(high, MAX_HIGH - 1); + } + return (high=high, low=low); +} + +func main{range_check_ptr: felt}() { + let (m, n) = split_felt_manual_implemetation(5784800237655953878877368326340059594760); + assert m = 17; + assert n = 8; + let (x, y) = split_felt(5784800237655953878877368326340059594760); + assert x = 17; + assert y = 8; + return (); +} diff --git a/pkg/builtins/signature.go b/pkg/builtins/signature.go index e068500b..5e577b61 100644 --- a/pkg/builtins/signature.go +++ b/pkg/builtins/signature.go @@ -8,7 +8,7 @@ import ( "github.com/pkg/errors" ) -const SIGNATURE_BUILTIN_NAME = "signature" +const SIGNATURE_BUILTIN_NAME = "ecdsa" // Notice changing this to any other number breaks the code const SIGNATURE_CELLS_PER_INSTANCE = 2 @@ -166,12 +166,11 @@ func (r *SignatureBuiltinRunner) AddValidationRule(mem *memory.Memory) { } // Helper function to AddSignature -func AddSignature( - signatureBuiltin *SignatureBuiltinRunner, +func (r *SignatureBuiltinRunner) AddSignature( address memory.Relocatable, signature Signature, ) { - signatureBuiltin.signatures[address] = signature + r.signatures[address] = signature } func (runner *SignatureBuiltinRunner) GetMemoryAccesses(manager *memory.MemorySegmentManager) ([]memory.Relocatable, error) { diff --git a/pkg/hints/dict_hints_test.go b/pkg/hints/dict_hints_test.go index 76e5de9d..b70b47dc 100644 --- a/pkg/hints/dict_hints_test.go +++ b/pkg/hints/dict_hints_test.go @@ -5,6 +5,7 @@ import ( . "github.com/lambdaclass/cairo-vm.go/pkg/hints" "github.com/lambdaclass/cairo-vm.go/pkg/hints/dict_manager" + . "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_codes" . "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_utils" . "github.com/lambdaclass/cairo-vm.go/pkg/lambdaworks" "github.com/lambdaclass/cairo-vm.go/pkg/types" diff --git a/pkg/hints/ec_hint.go b/pkg/hints/ec_hint.go new file mode 100644 index 00000000..8c83ff07 --- /dev/null +++ b/pkg/hints/ec_hint.go @@ -0,0 +1,116 @@ +package hints + +import ( + "errors" + "math/big" + + "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_utils" + "github.com/lambdaclass/cairo-vm.go/pkg/lambdaworks" + "github.com/lambdaclass/cairo-vm.go/pkg/types" + "github.com/lambdaclass/cairo-vm.go/pkg/vm" + "github.com/lambdaclass/cairo-vm.go/pkg/vm/memory" +) + +type BigInt3 struct { + Limbs []lambdaworks.Felt +} + +type EcPoint struct { + X BigInt3 + Y BigInt3 +} + +func (val *BigInt3) Pack86() big.Int { + sum := big.NewInt(0) + for i := 0; i < 3; i++ { + felt := val.Limbs[i] + signed := felt.ToSigned() + shifed := new(big.Int).Lsh(signed, uint(i*86)) + sum.Add(sum, shifed) + } + return *sum +} + +func BigInt3FromBaseAddr(addr memory.Relocatable, virtual_machine vm.VirtualMachine) (BigInt3, error) { + limbs := make([]lambdaworks.Felt, 0) + for i := 0; i < 3; i++ { + felt, err := virtual_machine.Segments.Memory.GetFelt(addr.AddUint(uint(i))) + if err == nil { + limbs = append(limbs, felt) + } else { + return BigInt3{}, errors.New("Identifier has no member") + } + } + return BigInt3{Limbs: limbs}, nil +} + +func BigInt3FromVarName(name string, virtual_machine vm.VirtualMachine, ids_data hint_utils.IdsManager) (EcPoint, error) { + point_addr, err := ids_data.GetAddr(name, &virtual_machine) + if err != nil { + return EcPoint{}, err + } + + x, err := BigInt3FromBaseAddr(point_addr, virtual_machine) + if err != nil { + return EcPoint{}, err + } + + y, err := BigInt3FromBaseAddr(point_addr.AddUint(3), virtual_machine) + if err != nil { + return EcPoint{}, err + } + + return EcPoint{X: x, Y: y}, nil +} + +/* +Implements main logic for `EC_NEGATE` and `EC_NEGATE_EMBEDDED_SECP` hints +*/ +func ecNegate(virtual_machine vm.VirtualMachine, exec_scopes types.ExecutionScopes, ids_data hint_utils.IdsManager, secp_p big.Int) error { + point, err := ids_data.GetRelocatable("point", &virtual_machine) + if err != nil { + return err + } + + point_y, err := point.AddInt(3) + if err != nil { + return err + } + + y_bigint3, err := BigInt3FromBaseAddr(point_y, virtual_machine) + if err != nil { + return err + } + + y := y_bigint3.Pack86() + value := new(big.Int).Neg(&y) + value.Mod(value, &secp_p) + + exec_scopes.AssignOrUpdateVariable("value", value) + exec_scopes.AssignOrUpdateVariable("SECP_P", secp_p) + return nil +} + +func ecNegateImportSecpP(virtual_machine vm.VirtualMachine, exec_scopes types.ExecutionScopes, ids_data hint_utils.IdsManager) error { + secp_p, _ := new(big.Int).SetString("115792089237316195423570985008687907853269984665640564039457584007908834671663", 10) + return ecNegate(virtual_machine, exec_scopes, ids_data, *secp_p) +} + +/* +Implements hint: +%{ + from starkware.cairo.common.cairo_secp.secp_utils import pack + SECP_P = 2**255-19 + + y = pack(ids.point.y, PRIME) % SECP_P + # The modulo operation in python always returns a nonnegative number. + value = (-y) % SECP_P +%} +*/ + +func ecNegateEmbeddedSecpP(virtual_machine vm.VirtualMachine, exec_scopes types.ExecutionScopes, ids_data hint_utils.IdsManager) error { + secp_p := big.NewInt(1) + secp_p.Lsh(secp_p, 255) + secp_p.Sub(secp_p, big.NewInt(19)) + return ecNegate(virtual_machine, exec_scopes, ids_data, *secp_p) +} diff --git a/pkg/hints/ec_hint_test.go b/pkg/hints/ec_hint_test.go new file mode 100644 index 00000000..bed5fbe3 --- /dev/null +++ b/pkg/hints/ec_hint_test.go @@ -0,0 +1,134 @@ +package hints_test + +import ( + "fmt" + "math/big" + "testing" + + . "github.com/lambdaclass/cairo-vm.go/pkg/hints" + . "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_codes" + . "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_utils" + . "github.com/lambdaclass/cairo-vm.go/pkg/lambdaworks" + "github.com/lambdaclass/cairo-vm.go/pkg/types" + . "github.com/lambdaclass/cairo-vm.go/pkg/vm" + . "github.com/lambdaclass/cairo-vm.go/pkg/vm/memory" +) + +func TestBigInt3Pack86(t *testing.T) { + limbs1 := []Felt{FeltFromUint64(10), FeltFromUint64(10), FeltFromUint64(10)} + bigint := BigInt3{Limbs: limbs1} + pack1 := bigint.Pack86() + + expected, _ := new(big.Int).SetString("59863107065073783529622931521771477038469668772249610", 10) + + if pack1.Cmp(expected) != 0 { + t.Errorf("Different pack from expected") + } + + limbs2 := []Felt{FeltFromDecString("773712524553362"), FeltFromDecString("57408430697461422066401280"), FeltFromDecString("1292469707114105")} + bigint2 := BigInt3{Limbs: limbs2} + pack2 := bigint2.Pack86() + + expected2, _ := new(big.Int).SetString("7737125245533626718119526477371252455336267181195264773712524553362", 10) + + if pack2.Cmp(expected2) != 0 { + t.Errorf("Different pack from expected2") + } +} + +func TestRunEcNegateOk(t *testing.T) { + vm := NewVirtualMachine() + vm.Segments.AddSegment() + vm.Segments.AddSegment() + vm.Segments.Memory.Insert(NewRelocatable(1, 3), NewMaybeRelocatableFelt(FeltFromUint64(2645))) + vm.Segments.Memory.Insert(NewRelocatable(1, 4), NewMaybeRelocatableFelt(FeltFromUint64(454))) + vm.Segments.Memory.Insert(NewRelocatable(1, 5), NewMaybeRelocatableFelt(FeltFromUint64(206))) + + idsManager := SetupIdsForTest( + map[string][]*MaybeRelocatable{ + "point": {NewMaybeRelocatableRelocatable(NewRelocatable(1, 0))}, + "ec_negative": {nil}, + }, + vm, + ) + + point, _ := idsManager.Get("point", vm) + fmt.Println("Ids manager: ", point) + hintProcessor := CairoVmHintProcessor{} + hintData := any(HintData{ + Ids: idsManager, + Code: EC_NEGATE, + }) + exec_scopes := types.NewExecutionScopes() + err := hintProcessor.ExecuteHint(vm, &hintData, nil, exec_scopes) + if err != nil { + t.Errorf("Ec Negative hint test failed with error %s", err) + } else { + // Check ids.is_positive + value, err := exec_scopes.Get("value") + val := value.(*big.Int) + expected, _ := new(big.Int).SetString("115792089237316195423569751828682367333329274433232027476421668138471189901786", 10) + + if err != nil || expected.Cmp(val) != 0 { + t.Errorf("Ec Negative hint test incorrect value for exec_scopes.value") + } + } +} + +func TestRunEcEmbeddedSecpOk(t *testing.T) { + vm := NewVirtualMachine() + vm.Segments.AddSegment() + vm.Segments.AddSegment() + vm.Segments.Memory.Insert(NewRelocatable(1, 3), NewMaybeRelocatableFelt(FeltFromUint64(2645))) + vm.Segments.Memory.Insert(NewRelocatable(1, 4), NewMaybeRelocatableFelt(FeltFromUint64(454))) + vm.Segments.Memory.Insert(NewRelocatable(1, 5), NewMaybeRelocatableFelt(FeltFromUint64(206))) + + y2 := big.NewInt(206) + y2.Lsh(y2, 86*2) + + y1 := big.NewInt(454) + y1.Lsh(y1, 86) + + y0 := big.NewInt(2645) + + y := new(big.Int) + y.Add(y, y2) + y.Add(y, y1) + y.Add(y, y0) + + vm.RunContext.Fp = NewRelocatable(1, 1) + + idsManager := SetupIdsForTest( + map[string][]*MaybeRelocatable{ + "point": {NewMaybeRelocatableRelocatable(NewRelocatable(1, 0))}, + "ec_negative": {nil}, + }, + vm, + ) + + hintProcessor := CairoVmHintProcessor{} + hintData := any(HintData{ + Ids: idsManager, + Code: EC_NEGATE_EMBEDDED_SECP, + }) + exec_scopes := types.NewExecutionScopes() + err := hintProcessor.ExecuteHint(vm, &hintData, nil, exec_scopes) + if err != nil { + t.Errorf("Ec Negative Embedded Sec hint test failed with error %s", err) + } else { + // Check ids.is_positive + value, err := exec_scopes.Get("value") + val := value.(*big.Int) + + // expected value + minus_y := big.NewInt(1) + minus_y.Lsh(minus_y, 255) + minus_y.Sub(minus_y, big.NewInt(19)) + minus_y.Sub(minus_y, y) + + if err != nil || minus_y.Cmp(val) != 0 { + t.Errorf("Ec Negative hint test incorrect value for exec_scopes.value") + } + } + +} diff --git a/pkg/hints/dict_hint_codes.go b/pkg/hints/hint_codes/dict_hint_codes.go similarity index 98% rename from pkg/hints/dict_hint_codes.go rename to pkg/hints/hint_codes/dict_hint_codes.go index 88445b9a..b8942a2f 100644 --- a/pkg/hints/dict_hint_codes.go +++ b/pkg/hints/hint_codes/dict_hint_codes.go @@ -1,4 +1,4 @@ -package hints +package hint_codes const DEFAULT_DICT_NEW = "if '__dict_manager' not in globals():\n from starkware.cairo.common.dict import DictManager\n __dict_manager = DictManager()\n\nmemory[ap] = __dict_manager.new_default_dict(segments, ids.default_value)" diff --git a/pkg/hints/hint_codes/ec_op_hints.go b/pkg/hints/hint_codes/ec_op_hints.go new file mode 100644 index 00000000..c2092a7f --- /dev/null +++ b/pkg/hints/hint_codes/ec_op_hints.go @@ -0,0 +1,4 @@ +package hint_codes + +const EC_NEGATE = "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack\n\ny = pack(ids.point.y, PRIME) % SECP_P\n# The modulo operation in python always returns a nonnegative number.\nvalue = (-y) % SECP_P" +const EC_NEGATE_EMBEDDED_SECP = "from starkware.cairo.common.cairo_secp.secp_utils import pack\nSECP_P = 2**255-19\n\ny = pack(ids.point.y, PRIME) % SECP_P\n# The modulo operation in python always returns a nonnegative number.\nvalue = (-y) % SECP_P" diff --git a/pkg/hints/math_hint_codes.go b/pkg/hints/hint_codes/math_hint_codes.go similarity index 68% rename from pkg/hints/math_hint_codes.go rename to pkg/hints/hint_codes/math_hint_codes.go index 553bcde1..803e5626 100644 --- a/pkg/hints/math_hint_codes.go +++ b/pkg/hints/hint_codes/math_hint_codes.go @@ -1,7 +1,9 @@ -package hints +package hint_codes const ASSERT_NN = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert 0 <= ids.a % PRIME < range_check_builtin.bound, f'a = {ids.a} is out of range.'" +const VERIFY_ECDSA_SIGNATURE = "ecdsa_builtin.add_signature(ids.ecdsa_ptr.address_, (ids.signature_r, ids.signature_s))" + const IS_POSITIVE = "from starkware.cairo.common.math_utils import is_positive\nids.is_positive = 1 if is_positive(\n value=ids.value, prime=PRIME, rc_bound=range_check_builtin.bound) else 0" const ASSERT_NOT_ZERO = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.value)\nassert ids.value % PRIME != 0, f'assert_not_zero failed: {ids.value} = 0.'" @@ -18,3 +20,7 @@ else: const ASSERT_NOT_EQUAL = "from starkware.cairo.lang.vm.relocatable import RelocatableValue\nboth_ints = isinstance(ids.a, int) and isinstance(ids.b, int)\nboth_relocatable = (\n isinstance(ids.a, RelocatableValue) and isinstance(ids.b, RelocatableValue) and\n ids.a.segment_index == ids.b.segment_index)\nassert both_ints or both_relocatable, \\\n f'assert_not_equal failed: non-comparable values: {ids.a}, {ids.b}.'\nassert (ids.a - ids.b) % PRIME != 0, f'assert_not_equal failed: {ids.a} = {ids.b}.'" const SQRT = "from starkware.python.math_utils import isqrt\nvalue = ids.value % PRIME\nassert value < 2 ** 250, f\"value={value} is outside of the range [0, 2**250).\"\nassert 2 ** 250 < PRIME\nids.root = isqrt(value)" + +const ASSERT_250_BITS = "from starkware.cairo.common.math_utils import as_int\n\n# Correctness check.\nvalue = as_int(ids.value, PRIME) % PRIME\nassert value < ids.UPPER_BOUND, f'{value} is outside of the range [0, 2**250).'\n\n# Calculation for the assertion.\nids.high, ids.low = divmod(ids.value, ids.SHIFT)" + +const SPLIT_FELT = "from starkware.cairo.common.math_utils import assert_integer\nassert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128\nassert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW\nassert_integer(ids.value)\nids.low = ids.value & ((1 << 128) - 1)\nids.high = ids.value >> 128" diff --git a/pkg/hints/memcpy_hint_codes.go b/pkg/hints/hint_codes/memcpy_hint_codes.go similarity index 93% rename from pkg/hints/memcpy_hint_codes.go rename to pkg/hints/hint_codes/memcpy_hint_codes.go index d732c38f..d6b671c4 100644 --- a/pkg/hints/memcpy_hint_codes.go +++ b/pkg/hints/hint_codes/memcpy_hint_codes.go @@ -1,4 +1,4 @@ -package hints +package hint_codes const ADD_SEGMENT = "memory[ap] = segments.add()" const VM_EXIT_SCOPE = "vm_exit_scope()" diff --git a/pkg/hints/pow_hint_codes.go b/pkg/hints/hint_codes/pow_hint_codes.go similarity index 76% rename from pkg/hints/pow_hint_codes.go rename to pkg/hints/hint_codes/pow_hint_codes.go index 523a4356..ae7bd962 100644 --- a/pkg/hints/pow_hint_codes.go +++ b/pkg/hints/hint_codes/pow_hint_codes.go @@ -1,3 +1,3 @@ -package hints +package hint_codes const POW = "ids.locs.bit = (ids.prev_locs.exp % PRIME) & 1" diff --git a/pkg/hints/hint_processor.go b/pkg/hints/hint_processor.go index d5950744..1dddd5ab 100644 --- a/pkg/hints/hint_processor.go +++ b/pkg/hints/hint_processor.go @@ -3,6 +3,7 @@ package hints import ( "strings" + . "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_codes" . "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_utils" . "github.com/lambdaclass/cairo-vm.go/pkg/lambdaworks" "github.com/lambdaclass/cairo-vm.go/pkg/parser" @@ -43,6 +44,8 @@ func (p *CairoVmHintProcessor) ExecuteHint(vm *vm.VirtualMachine, hintData *any, return add_segment(vm) case ASSERT_NN: return assert_nn(data.Ids, vm) + case VERIFY_ECDSA_SIGNATURE: + return verify_ecdsa_signature(data.Ids, vm) case IS_POSITIVE: return is_positive(data.Ids, vm) case ASSERT_NOT_ZERO: @@ -63,6 +66,10 @@ func (p *CairoVmHintProcessor) ExecuteHint(vm *vm.VirtualMachine, hintData *any, return vm_exit_scope(execScopes) case ASSERT_NOT_EQUAL: return assert_not_equal(data.Ids, vm) + case EC_NEGATE: + return ecNegateImportSecpP(*vm, *execScopes, data.Ids) + case EC_NEGATE_EMBEDDED_SECP: + return ecNegateEmbeddedSecpP(*vm, *execScopes, data.Ids) case POW: return pow(data.Ids, vm) case SQRT: @@ -75,6 +82,10 @@ func (p *CairoVmHintProcessor) ExecuteHint(vm *vm.VirtualMachine, hintData *any, return memset_step_loop(data.Ids, vm, execScopes, "continue_copying") case MEMSET_CONTINUE_LOOP: return memset_step_loop(data.Ids, vm, execScopes, "continue_loop") + case ASSERT_250_BITS: + return Assert250Bit(data.Ids, vm, constants) + case SPLIT_FELT: + return SplitFelt(data.Ids, vm, constants) default: return errors.Errorf("Unknown Hint: %s", data.Code) } diff --git a/pkg/hints/math_hints.go b/pkg/hints/math_hints.go index c56c0a18..3c963ee0 100644 --- a/pkg/hints/math_hints.go +++ b/pkg/hints/math_hints.go @@ -55,6 +55,7 @@ func is_positive(ids IdsManager, vm *VirtualMachine) error { // assert ids.value % PRIME != 0, f'assert_not_zero failed: {ids.value} = 0.' // // %} + func assert_not_zero(ids IdsManager, vm *VirtualMachine) error { value, err := ids.GetFelt("value", vm) if err != nil { @@ -66,6 +67,37 @@ func assert_not_zero(ids IdsManager, vm *VirtualMachine) error { return nil } +func verify_ecdsa_signature(ids IdsManager, vm *VirtualMachine) error { + r, err_get_r := ids.GetFelt("signature_r", vm) + if err_get_r != nil { + return err_get_r + } + + s, err_get_s := ids.GetFelt("signature_s", vm) + if err_get_s != nil { + return err_get_s + } + + ecdsa_ptr, err_get_ecdsa := ids.GetAddr("ecdsa_ptr", vm) + if err_get_ecdsa != nil { + return err_get_ecdsa + } + + signature_builtin_interface, err_get_builtin := vm.GetBuiltinRunner(builtins.SIGNATURE_BUILTIN_NAME) + if err_get_builtin != nil { + return err_get_builtin + } + + signature_builtin := (*signature_builtin_interface).(*builtins.SignatureBuiltinRunner) + + signature := builtins.Signature{ + R: r, + S: s, + } + signature_builtin.AddSignature(ecdsa_ptr, signature) + return nil +} + // Implements hint:from starkware.cairo.common.math.cairo // // %{ @@ -151,3 +183,99 @@ func sqrt(ids IdsManager, vm *VirtualMachine) error { ids.Insert("root", NewMaybeRelocatableFelt(root_felt), vm) return nil } + +// Implements hint: +// +// from starkware.cairo.common.math_utils import as_int +// # Correctness check. +// value = as_int(ids.value, PRIME) % PRIME +// assert value < ids.UPPER_BOUND, f'{value} is outside of the range [0, 2**250).' +// # Calculation for the assertion. +// ids.high, ids.low = divmod(ids.value, ids.SHIFT) +func Assert250Bit(ids IdsManager, vm *VirtualMachine, constants *map[string]Felt) error { + upperBound, err := ids.GetConst("UPPER_BOUND", constants) + if err != nil { + return err + } + + shift, err := ids.GetConst("SHIFT", constants) + if err != nil { + return err + } + + value, err := ids.GetFelt("value", vm) + + if err != nil { + return err + } + + if Felt.Cmp(value, upperBound) == 1 { + return errors.New("Value outside of 250 bit Range") + } + + high, low := value.DivRem(shift) + + err = ids.Insert("high", NewMaybeRelocatableFelt(high), vm) + if err != nil { + return err + } + + err = ids.Insert("low", NewMaybeRelocatableFelt(low), vm) + if err != nil { + return err + } + + return nil +} + +// Implements hint: +// +// %{ +// from starkware.cairo.common.math_utils import assert_integer +// assert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128 +// assert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW +// assert_integer(ids.value) +// ids.low = ids.value & ((1 << 128) - 1) +// ids.high = ids.value >> 128 +// +// %} +func SplitFelt(ids IdsManager, vm *VirtualMachine, constants *map[string]Felt) error { + maxHigh, err := ids.GetConst("MAX_HIGH", constants) + if err != nil { + return err + } + + maxLow, err := ids.GetConst("MAX_LOW", constants) + if err != nil { + return err + } + + if maxHigh.Bits() > 128 || maxLow.Bits() > 128 { + return errors.New("Assertion Failed: assert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128") + } + + twoToTheOneTwentyEight := lambdaworks.FeltOne().Shl(128) + if lambdaworks.FeltFromDecString("-1") != maxHigh.Mul(twoToTheOneTwentyEight).Add(maxLow) { + return errors.New("Assertion Failed: assert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW") + } + + value, err := ids.GetFelt("value", vm) + if err != nil { + return err + } + + low := value.And(twoToTheOneTwentyEight.Sub(lambdaworks.FeltOne())) + high := value.Shr(128) + + err = ids.Insert("high", NewMaybeRelocatableFelt(high), vm) + if err != nil { + return err + } + + err = ids.Insert("low", NewMaybeRelocatableFelt(low), vm) + if err != nil { + return err + } + + return nil +} diff --git a/pkg/hints/math_hints_test.go b/pkg/hints/math_hints_test.go index 5dbd4e6a..55198cc1 100644 --- a/pkg/hints/math_hints_test.go +++ b/pkg/hints/math_hints_test.go @@ -3,10 +3,14 @@ package hints_test import ( "testing" + "github.com/lambdaclass/cairo-vm.go/pkg/builtins" . "github.com/lambdaclass/cairo-vm.go/pkg/hints" + . "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_codes" . "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_utils" + "github.com/lambdaclass/cairo-vm.go/pkg/lambdaworks" . "github.com/lambdaclass/cairo-vm.go/pkg/lambdaworks" . "github.com/lambdaclass/cairo-vm.go/pkg/vm" + "github.com/lambdaclass/cairo-vm.go/pkg/vm/memory" . "github.com/lambdaclass/cairo-vm.go/pkg/vm/memory" ) @@ -162,6 +166,80 @@ func TestAssertNotZeroHintFail(t *testing.T) { } } +func TestVerifyValidSignature(t *testing.T) { + vm := NewVirtualMachine() + vm.Segments.AddSegment() + signature_builtin := builtins.NewSignatureBuiltinRunner(2048) + vm.BuiltinRunners = append(vm.BuiltinRunners, signature_builtin) + + hintProcessor := CairoVmHintProcessor{} + vm.Segments.AddSegment() + + r_felt := lambdaworks.FeltFromDecString("3086480810278599376317923499561306189851900463386393948998357832163236918254") + s_felt := lambdaworks.FeltFromDecString("598673427589502599949712887611119751108407514580626464031881322743364689811") + r := memory.NewMaybeRelocatableFelt(r_felt) + s := memory.NewMaybeRelocatableFelt(s_felt) + + vm.RunContext.Fp = memory.NewRelocatable(1, 3) + + idsManager := SetupIdsForTest( + map[string][]*MaybeRelocatable{ + "ecdsa_ptr": {nil}, + "signature_r": {r}, + "signature_s": {s}, + }, + vm, + ) + + hintData := any(HintData{ + Ids: idsManager, + Code: VERIFY_ECDSA_SIGNATURE, + }) + + err := hintProcessor.ExecuteHint(vm, &hintData, nil, nil) + + if err != nil { + t.Errorf("Verify signature hint for correct signature failed with error: %s", err) + } +} + +func TestVerifySignatureInvalidEcdsaPointer(t *testing.T) { + vm := NewVirtualMachine() + signature_builtin := builtins.NewSignatureBuiltinRunner(2048) + vm.BuiltinRunners = append(vm.BuiltinRunners, signature_builtin) + + hintProcessor := CairoVmHintProcessor{} + vm.Segments.AddSegment() + + r_felt := lambdaworks.FeltFromDecString("3086480810278599376317923499561306189851900463386393948998357832163236918254") + s_felt := lambdaworks.FeltFromDecString("598673427589502599949712887611119751108407514580626464031881322743364689811") + three := memory.NewMaybeRelocatableFelt(lambdaworks.FeltFromUint64(3)) + r := memory.NewMaybeRelocatableFelt(r_felt) + s := memory.NewMaybeRelocatableFelt(s_felt) + + vm.RunContext.Fp = memory.NewRelocatable(1, 3) + + idsManager := SetupIdsForTest( + map[string][]*MaybeRelocatable{ + "ecdsa_ptr": {three}, + "signature_r": {r}, + "signature_s": {s}, + }, + vm, + ) + + hintData := any(HintData{ + Ids: idsManager, + Code: VERIFY_ECDSA_SIGNATURE, + }) + + err := hintProcessor.ExecuteHint(vm, &hintData, nil, nil) + + if err == nil { + t.Errorf("Verified a signature with an invalid pointer") + } +} + func TestAssertNotEqualHintNonComparableDiffType(t *testing.T) { vm := NewVirtualMachine() vm.Segments.AddSegment() @@ -316,3 +394,231 @@ func TestSqrtOk(t *testing.T) { t.Errorf("Expected sqrt(9) == 3. Got: %v", root) } } + +func TestAssert250BitHintSuccess(t *testing.T) { + vm := NewVirtualMachine() + vm.Segments.AddSegment() + idsManager := SetupIdsForTest( + map[string][]*MaybeRelocatable{ + "value": {NewMaybeRelocatableFelt(FeltFromUint64(3))}, + "high": {nil}, + "low": {nil}, + }, + vm, + ) + + hintProcessor := CairoVmHintProcessor{} + constants := SetupConstantsForTest(map[string]Felt{ + "UPPER_BOUND": lambdaworks.FeltFromUint64(10), + "SHIFT": lambdaworks.FeltFromUint64(1), + }, + &idsManager, + ) + + hintData := any(HintData{ + Ids: idsManager, + Code: ASSERT_250_BITS, + }) + + err := hintProcessor.ExecuteHint(vm, &hintData, &constants, nil) + if err != nil { + t.Errorf("ASSERT_250_BIT hint failed with error %s", err) + } + + high, err := idsManager.GetFelt("high", vm) + if err != nil { + t.Errorf("failed to get high: %s", err) + } + + low, err := idsManager.GetFelt("low", vm) + if err != nil { + t.Errorf("failed to get low: %s", err) + } + + if high != FeltFromUint64(3) { + t.Errorf("Expected high == 3. Got: %v", high) + } + + if low != FeltFromUint64(0) { + t.Errorf("Expected low == 0. Got: %v", low) + } +} + +func TestAssert250BitHintFail(t *testing.T) { + vm := NewVirtualMachine() + vm.Segments.AddSegment() + idsManager := SetupIdsForTest( + map[string][]*MaybeRelocatable{ + "value": {NewMaybeRelocatableFelt(FeltFromUint64(20))}, + "high": {nil}, + "low": {nil}, + }, + vm, + ) + + hintProcessor := CairoVmHintProcessor{} + constants := SetupConstantsForTest(map[string]Felt{ + "UPPER_BOUND": lambdaworks.FeltFromUint64(10), + "SHIFT": lambdaworks.FeltFromUint64(1), + }, + &idsManager, + ) + + hintData := any(HintData{ + Ids: idsManager, + Code: ASSERT_250_BITS, + }) + + err := hintProcessor.ExecuteHint(vm, &hintData, &constants, nil) + if err == nil { + t.Errorf("ASSERT_250_BIT hint should have failed with Value outside of 250 bit error") + } +} + +func TestSplitFeltAssertPrimeFailure(t *testing.T) { + vm := NewVirtualMachine() + vm.Segments.AddSegment() + idsManager := SetupIdsForTest( + map[string][]*MaybeRelocatable{ + "value": {NewMaybeRelocatableFelt(FeltFromUint64(1))}, + "high": {nil}, + "low": {nil}, + }, + vm, + ) + + hintProcessor := CairoVmHintProcessor{} + constants := SetupConstantsForTest(map[string]Felt{ + "MAX_HIGH": lambdaworks.FeltFromHex("0xffffffffffffffffffffffffffffffff"), + "MAX_LOW": lambdaworks.FeltFromHex("0xffffffffffffffffffffffffffffffff"), + }, + &idsManager, + ) + + hintData := any(HintData{ + Ids: idsManager, + Code: SPLIT_FELT, + }) + + err := hintProcessor.ExecuteHint(vm, &hintData, &constants, nil) + if err == nil { + t.Errorf("SPLIT_FELT hint should have failed with assert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW error") + } +} + +func TestSplitFeltAssertMaxHighFailedAssertion(t *testing.T) { + vm := NewVirtualMachine() + vm.Segments.AddSegment() + idsManager := SetupIdsForTest( + map[string][]*MaybeRelocatable{ + "value": {NewMaybeRelocatableFelt(FeltFromUint64(1))}, + "high": {nil}, + "low": {nil}, + }, + vm, + ) + + hintProcessor := CairoVmHintProcessor{} + constants := SetupConstantsForTest(map[string]Felt{ + "MAX_HIGH": lambdaworks.FeltFromHex("0xffffffffffffffffffffffffffffffffffff"), + "MAX_LOW": lambdaworks.FeltFromHex("0xffffffffffffffffffffffffffffffff"), + }, + &idsManager, + ) + + hintData := any(HintData{ + Ids: idsManager, + Code: SPLIT_FELT, + }) + + err := hintProcessor.ExecuteHint(vm, &hintData, &constants, nil) + if err == nil { + t.Errorf("SPLIT_FELT hint should have failed with assert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128") + } +} + +func TestSplitFeltAssertMaxLowFailedAssertion(t *testing.T) { + vm := NewVirtualMachine() + vm.Segments.AddSegment() + idsManager := SetupIdsForTest( + map[string][]*MaybeRelocatable{ + "value": {NewMaybeRelocatableFelt(FeltFromUint64(1))}, + "high": {nil}, + "low": {nil}, + }, + vm, + ) + + hintProcessor := CairoVmHintProcessor{} + constants := SetupConstantsForTest(map[string]Felt{ + "MAX_HIGH": lambdaworks.FeltFromHex("0xffffffffffffffffffffffffffffffff"), + "MAX_LOW": lambdaworks.FeltFromHex("0xffffffffffffffffffffffffffffffffffff"), + }, + &idsManager, + ) + + hintData := any(HintData{ + Ids: idsManager, + Code: SPLIT_FELT, + }) + + err := hintProcessor.ExecuteHint(vm, &hintData, &constants, nil) + if err == nil { + t.Errorf("SPLIT_FELT hint should have failed with assert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128") + } +} + +func TestSplitFeltSuccess(t *testing.T) { + vm := NewVirtualMachine() + vm.Segments.AddSegment() + + firstLimb := lambdaworks.FeltFromUint64(1) + secondLimb := lambdaworks.FeltFromUint64(2) + thirdLimb := lambdaworks.FeltFromUint64(3) + fourthLimb := lambdaworks.FeltFromUint64(4) + value := fourthLimb.Or(thirdLimb.Shl(64).Or(secondLimb.Shl(128).Or(firstLimb.Shl(192)))) + idsManager := SetupIdsForTest( + map[string][]*MaybeRelocatable{ + "value": {NewMaybeRelocatableFelt(value)}, + "high": {nil}, + "low": {nil}, + }, + vm, + ) + + hintProcessor := CairoVmHintProcessor{} + constants := SetupConstantsForTest(map[string]Felt{ + "MAX_HIGH": lambdaworks.FeltFromDecString("10633823966279327296825105735305134080"), + "MAX_LOW": lambdaworks.FeltFromUint64(0), + }, + &idsManager, + ) + + hintData := any(HintData{ + Ids: idsManager, + Code: SPLIT_FELT, + }) + + err := hintProcessor.ExecuteHint(vm, &hintData, &constants, nil) + if err != nil { + t.Errorf("SPLIT_FELT hint failed with error %s", err) + } + + high, err := idsManager.GetFelt("high", vm) + if err != nil { + t.Errorf("failed to get high: %s", err) + } + + low, err := idsManager.GetFelt("low", vm) + if err != nil { + t.Errorf("failed to get low: %s", err) + } + + if high != firstLimb.Shl(64).Or(secondLimb) { + t.Errorf("Expected high == 335438970432432812899076431678123043273. Got: %v", high) + } + + if low != thirdLimb.Shl(64).Or(fourthLimb) { + t.Errorf("Expected low == 0. Got: %v", low) + } +} diff --git a/pkg/hints/memcpy_hints_test.go b/pkg/hints/memcpy_hints_test.go index 8753f1a8..457fb574 100644 --- a/pkg/hints/memcpy_hints_test.go +++ b/pkg/hints/memcpy_hints_test.go @@ -4,6 +4,7 @@ import ( "testing" . "github.com/lambdaclass/cairo-vm.go/pkg/hints" + . "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_codes" . "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_utils" . "github.com/lambdaclass/cairo-vm.go/pkg/lambdaworks" . "github.com/lambdaclass/cairo-vm.go/pkg/types" diff --git a/pkg/hints/pow_hints.go b/pkg/hints/pow_hints.go index 5d60c510..bccc9786 100644 --- a/pkg/hints/pow_hints.go +++ b/pkg/hints/pow_hints.go @@ -10,13 +10,15 @@ import ( // Implements hint: // %{ ids.locs.bit = (ids.prev_locs.exp % PRIME) & 1 %} func pow(ids IdsManager, vm *VirtualMachine) error { - prev_locs_exp_addr, err := ids.GetAddr("prev_locs", vm) - prev_locs_exp, _ := vm.Segments.Memory.GetFelt(prev_locs_exp_addr.AddUint(4)) + prev_locs_exp_addr, err := ids.GetRelocatable("prev_locs", vm) + if err != nil { + return err + } + prev_locs_exp, err := vm.Segments.Memory.GetFelt(prev_locs_exp_addr.AddUint(4)) if err != nil { return err } - ids.Insert("locs", NewMaybeRelocatableFelt(prev_locs_exp.And(FeltOne())), vm) - return nil + return ids.Insert("locs", NewMaybeRelocatableFelt(prev_locs_exp.And(FeltOne())), vm) } diff --git a/pkg/hints/pow_hints_test.go b/pkg/hints/pow_hints_test.go index 13ce6285..0146e7c4 100644 --- a/pkg/hints/pow_hints_test.go +++ b/pkg/hints/pow_hints_test.go @@ -2,6 +2,7 @@ package hints_test import ( . "github.com/lambdaclass/cairo-vm.go/pkg/hints" + . "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_codes" . "github.com/lambdaclass/cairo-vm.go/pkg/hints/hint_utils" . "github.com/lambdaclass/cairo-vm.go/pkg/lambdaworks" . "github.com/lambdaclass/cairo-vm.go/pkg/vm" @@ -9,10 +10,11 @@ import ( "testing" ) -func TestPowHintOk(t *testing.T) { +func TestPowHintOddOk(t *testing.T) { vm := NewVirtualMachine() vm.Segments.AddSegment() - vm.Segments.Memory.Insert(NewRelocatable(0, 4), NewMaybeRelocatableFelt(FeltFromUint64(5))) + vm.Segments.Memory.Insert(NewRelocatable(0, 4), NewMaybeRelocatableFelt(FeltFromUint64(3))) + idsManager := SetupIdsForTest( map[string][]*MaybeRelocatable{ "prev_locs": {NewMaybeRelocatableRelocatable(NewRelocatable(0, 0))}, @@ -36,7 +38,40 @@ func TestPowHintOk(t *testing.T) { t.Errorf("Failed to get locs.bit with error: %s", err) } - if locs != FeltFromUint64(1) { + if locs != FeltOne() { t.Errorf("locs.bit: %d != 1", locs) } } + +func TestPowHintEvenOk(t *testing.T) { + vm := NewVirtualMachine() + vm.Segments.AddSegment() + vm.Segments.Memory.Insert(NewRelocatable(0, 4), NewMaybeRelocatableFelt(FeltFromUint64(2))) + + idsManager := SetupIdsForTest( + map[string][]*MaybeRelocatable{ + "prev_locs": {NewMaybeRelocatableRelocatable(NewRelocatable(0, 0))}, + "locs": {nil}, + }, + vm, + ) + hintProcessor := CairoVmHintProcessor{} + hintData := any(HintData{ + Ids: idsManager, + Code: POW, + }) + + err := hintProcessor.ExecuteHint(vm, &hintData, nil, nil) + if err != nil { + t.Errorf("POW hint test failed with error %s", err) + } + + locs, err := idsManager.GetFelt("locs", vm) + if err != nil { + t.Errorf("Failed to get locs.bit with error: %s", err) + } + + if locs != FeltZero() { + t.Errorf("locs.bit: %d != 0", locs) + } +} diff --git a/pkg/parser/parser.go b/pkg/parser/parser.go index 94e1f24e..46f9d415 100644 --- a/pkg/parser/parser.go +++ b/pkg/parser/parser.go @@ -72,7 +72,7 @@ type HintParams struct { } type CompiledJson struct { - Attributes []string `json:"attributes"` + Attributes interface{} `json:"attributes"` Builtins []string `json:"builtins"` CompilerVersion string `json:"compiler_version"` Data []string `json:"data"` diff --git a/pkg/vm/cairo_run/cairo_run_test.go b/pkg/vm/cairo_run/cairo_run_test.go index 21876bd1..10c0ab6c 100644 --- a/pkg/vm/cairo_run/cairo_run_test.go +++ b/pkg/vm/cairo_run/cairo_run_test.go @@ -123,6 +123,13 @@ func TestAbsValue(t *testing.T) { t.Errorf("Program execution failed with error: %s", err) } } +func TestCommonSignature(t *testing.T) { + cairoRunConfig := cairo_run.CairoRunConfig{DisableTracePadding: false, ProofMode: false, Layout: "all_cairo"} + _, err := cairo_run.CairoRun("../../../cairo_programs/common_signature.json", cairoRunConfig) + if err != nil { + t.Errorf("Program execution failed with error: %s", err) + } +} func TestAssertNotZeroHint(t *testing.T) { cairoRunConfig := cairo_run.CairoRunConfig{DisableTracePadding: false, ProofMode: false, Layout: "all_cairo"} _, err := cairo_run.CairoRun("../../../cairo_programs/assert_not_zero.json", cairoRunConfig) @@ -210,7 +217,6 @@ func TestMemcpyHint(t *testing.T) { t.Errorf("Program execution failed with error: %s", err) } } - func TestMemsetHint(t *testing.T) { cairoRunConfig := cairo_run.CairoRunConfig{DisableTracePadding: false, Layout: "all_cairo", ProofMode: false} _, err := cairo_run.CairoRun("../../../cairo_programs/memset.json", cairoRunConfig) @@ -218,3 +224,18 @@ func TestMemsetHint(t *testing.T) { t.Errorf("Program execution failed with error: %s", err) } } +func TestAssert250BitHint(t *testing.T) { + cairoRunConfig := cairo_run.CairoRunConfig{DisableTracePadding: false, Layout: "all_cairo", ProofMode: false} + _, err := cairo_run.CairoRun("../../../cairo_programs/assert_250_bit_element_array.json", cairoRunConfig) + if err != nil { + t.Errorf("Program execution failed with error: %s", err) + } +} + +func TestSplitFeltHint(t *testing.T) { + cairoRunConfig := cairo_run.CairoRunConfig{DisableTracePadding: false, Layout: "all_cairo", ProofMode: false} + _, err := cairo_run.CairoRun("../../../cairo_programs/split_felt.json", cairoRunConfig) + if err != nil { + t.Errorf("Program execution failed with error: %s", err) + } +} diff --git a/pkg/vm/memory/memory_test.go b/pkg/vm/memory/memory_test.go index 5df9d1d3..1cced856 100644 --- a/pkg/vm/memory/memory_test.go +++ b/pkg/vm/memory/memory_test.go @@ -437,7 +437,7 @@ func TestValidateMemoryForValidSignature(t *testing.T) { S: signature_s_felt, } - builtins.AddSignature(signature_builtin, signature_address, signature) + signature_builtin.AddSignature(signature_address, signature) pub_key_address := memory.NewRelocatable(1, 0) message_hash_address := memory.NewRelocatable(1, 1) diff --git a/pkg/vm/program.go b/pkg/vm/program.go index 125860fb..b72707ee 100644 --- a/pkg/vm/program.go +++ b/pkg/vm/program.go @@ -64,7 +64,7 @@ func DeserializeProgramJson(compiledProgram parser.CompiledJson) Program { func (p *Program) ExtractConstants() map[string]lambdaworks.Felt { constants := make(map[string]lambdaworks.Felt) for name, identifier := range p.Identifiers { - if identifier.Type == "constant" { + if identifier.Type == "const" { constants[name] = identifier.Value } } diff --git a/pkg/vm/program_test.go b/pkg/vm/program_test.go index 95371ce6..bf8d4fff 100644 --- a/pkg/vm/program_test.go +++ b/pkg/vm/program_test.go @@ -34,11 +34,11 @@ func TestExtractConstants(t *testing.T) { }, "A": { Value: lambdaworks.FeltFromUint64(7), - Type: "constant", + Type: "const", }, "B": { Value: lambdaworks.FeltFromUint64(17), - Type: "constant", + Type: "const", }, }, }