Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add CairoRunner & CairoRunner.Initialize() #14

Merged
merged 37 commits into from
Aug 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
1c9c9d1
Switch memory structure to map
fmoletta Jul 28, 2023
9d3e690
Remove uneeded fns
fmoletta Jul 28, 2023
f0463c2
Fix Memory initialization in tests + remove implementation-specific c…
fmoletta Jul 28, 2023
400eaac
Add tests
fmoletta Jul 28, 2023
281f2f6
Fix test assertion
fmoletta Jul 28, 2023
17ec0d0
Add load_data fn
fmoletta Jul 28, 2023
06d71a7
Add tests
fmoletta Jul 28, 2023
a177342
Add test
fmoletta Jul 28, 2023
0a68fb3
Rename Add to AddSegment
fmoletta Jul 28, 2023
28d1f3a
Merge branch 'switch-memory-to-map' into load_data
fmoletta Jul 28, 2023
d3ee261
Update name
fmoletta Jul 28, 2023
db5436c
Expose relocatable fields
fmoletta Jul 31, 2023
b235f23
Add method NewMaybeRelocatableRelocatable to complete MaybeRelocatabl…
fmoletta Jul 31, 2023
077c701
Merge branch 'main' of github.com:lambdaclass/cairo_vm.go into expose…
fmoletta Jul 31, 2023
7c0ca40
Merge branch 'main' of github.com:lambdaclass/cairo_vm.go into load_data
fmoletta Jul 31, 2023
cfd9ebd
Make RunContext registers public & Relocatable
fmoletta Jul 31, 2023
8eb12b7
Make segments a public field of the vm
fmoletta Jul 31, 2023
8f4e24f
Add CairoRunner + InitializeSegments method
fmoletta Jul 31, 2023
d372a1b
Add initialize_state
fmoletta Jul 31, 2023
aa833c4
Merge branch 'load_data' into add-cairo-runner
fmoletta Jul 31, 2023
0c78ebe
fixes
fmoletta Jul 31, 2023
29650c8
Merge branch 'expose-relocatable-fields' into add-cairo-runner
fmoletta Jul 31, 2023
26f5f2d
fixes
fmoletta Jul 31, 2023
f0b639c
Implement InitializeFunctionEntryPoint
fmoletta Jul 31, 2023
30c434b
Add InitializeMainEntrypoint
fmoletta Jul 31, 2023
767d407
Add NewVirtualMachine & NewCairoRunner
fmoletta Jul 31, 2023
a1b37bc
Add InitializeVm
fmoletta Jul 31, 2023
97b62c4
Merge remote-tracking branch 'origin/fix-run-context-members' into ad…
fmoletta Jul 31, 2023
dc4d4fe
Add Initialize
fmoletta Jul 31, 2023
c38d6ca
Make methods and variables private
fmoletta Jul 31, 2023
222f3af
Merge branch 'main' of github.com:lambdaclass/cairo_vm.go into add-ca…
fmoletta Jul 31, 2023
f3149ac
Fix bug
fmoletta Jul 31, 2023
40a8a32
make Felt within Int public for testing
fmoletta Jul 31, 2023
ec7e246
Add test
fmoletta Jul 31, 2023
770282e
Fix test
fmoletta Jul 31, 2023
a346995
Remove uneeded dependencies
fmoletta Jul 31, 2023
e544921
Merge branch 'main' of github.com:lambdaclass/cairo_vm.go into add-ca…
fmoletta Aug 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions pkg/runners/cairo_runner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package runners

import (
"github.com/lambdaclass/cairo-vm.go/pkg/vm"
"github.com/lambdaclass/cairo-vm.go/pkg/vm/memory"
)

type CairoRunner struct {
Program vm.Program
Vm vm.VirtualMachine
ProgramBase memory.Relocatable
executionBase memory.Relocatable
initialPc memory.Relocatable
initialAp memory.Relocatable
initialFp memory.Relocatable
finalPc memory.Relocatable
mainOffset uint
}

func NewCairoRunner(program vm.Program) *CairoRunner {
// TODO: Fetch main entrypoint offset from program identifiers
// Placeholder
main_offset := uint(0)
return &CairoRunner{Program: program, Vm: *vm.NewVirtualMachine(), mainOffset: main_offset}

}

// Performs the initialization step, returns the end pointer (pc upon which execution should stop)
func (r *CairoRunner) Initialize() (memory.Relocatable, error) {
r.initializeSegments()
end, err := r.initializeMainEntrypoint()
r.initializeVM()
return end, err
}

// Creates program, execution and builtin segments
func (r *CairoRunner) initializeSegments() {
// Program Segment
r.ProgramBase = r.Vm.Segments.AddSegment()
// Execution Segment
r.executionBase = r.Vm.Segments.AddSegment()
// Initialize builtin segments
}

// Initializes the program segment & initial pc
func (r *CairoRunner) initializeState(entrypoint uint, stack *[]memory.MaybeRelocatable) error {
r.initialPc = r.ProgramBase
r.initialPc.Offset += entrypoint
// Load program data
_, err := r.Vm.Segments.LoadData(r.ProgramBase, &r.Program.Data)
if err == nil {
_, err = r.Vm.Segments.LoadData(r.executionBase, stack)
}
// Mark data segment as accessed
return err
}

// Initializes memory, initial register values & returns the end pointer (final pc) to run from a given pc offset
// (entrypoint)
func (r *CairoRunner) initializeFunctionEntrypoint(entrypoint uint, stack *[]memory.MaybeRelocatable, return_fp memory.Relocatable) (memory.Relocatable, error) {
end := r.Vm.Segments.AddSegment()
*stack = append(*stack, *memory.NewMaybeRelocatableRelocatable(end), *memory.NewMaybeRelocatableRelocatable(return_fp))
r.initialFp = r.executionBase
r.initialFp.Offset += uint(len(*stack))
r.initialAp = r.initialFp
r.finalPc = end
return end, r.initializeState(entrypoint, stack)
}

// Initializes memory, initial register values & returns the end pointer (final pc) to run from the main entrypoint
func (r *CairoRunner) initializeMainEntrypoint() (memory.Relocatable, error) {
// When running from main entrypoint, only up to 11 values will be written (9 builtin bases + end + return_fp)
stack := make([]memory.MaybeRelocatable, 0, 11)
// Append builtins initial stack to stack
// Handle proof-mode specific behaviour
return_fp := r.Vm.Segments.AddSegment()
return r.initializeFunctionEntrypoint(r.mainOffset, &stack, return_fp)
}

// Initializes the vm's run_context, adds builtin validation rules & validates memory
func (r *CairoRunner) initializeVM() {
r.Vm.RunContext.Ap = r.initialAp
r.Vm.RunContext.Fp = r.initialFp
r.Vm.RunContext.Pc = r.initialPc
// Add validation rules
// Apply validation rules to memory
}
136 changes: 136 additions & 0 deletions pkg/runners/cairo_runner_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package runners_test

import (
"testing"

"github.com/lambdaclass/cairo-vm.go/pkg/runners"
"github.com/lambdaclass/cairo-vm.go/pkg/vm"
"github.com/lambdaclass/cairo-vm.go/pkg/vm/memory"
)

func TestInitializeRunnerNoBuiltinsNoProofModeEmptyProgram(t *testing.T) {
// Create a Program with empty data
program_data := make([]memory.MaybeRelocatable, 0)
program := vm.Program{Data: program_data}
// Create CairoRunner
runner := runners.NewCairoRunner(program)
// Initialize the runner
end_ptr, err := runner.Initialize()
if err != nil {
t.Errorf("Initialize error in test: %s", err)
}
if end_ptr.SegmentIndex != 3 || end_ptr.Offset != 0 {
t.Errorf("Wrong end ptr value, got %+v", end_ptr)
}

// Check CairoRunner values
if runner.ProgramBase.SegmentIndex != 0 || runner.ProgramBase.Offset != 0 {
t.Errorf("Wrong ProgramBase value, got %+v", runner.ProgramBase)
}

// Check Vm's RunContext values
if runner.Vm.RunContext.Pc.SegmentIndex != 0 || runner.Vm.RunContext.Pc.Offset != 0 {
t.Errorf("Wrong Pc value, got %+v", runner.Vm.RunContext.Pc)
}
if runner.Vm.RunContext.Ap.SegmentIndex != 1 || runner.Vm.RunContext.Ap.Offset != 2 {
t.Errorf("Wrong Ap value, got %+v", runner.Vm.RunContext.Ap)
}
if runner.Vm.RunContext.Fp.SegmentIndex != 1 || runner.Vm.RunContext.Fp.Offset != 2 {
t.Errorf("Wrong Fp value, got %+v", runner.Vm.RunContext.Fp)
}

// Check memory

// Program segment
// 0:0 program_data[0] should be empty
value, err := runner.Vm.Segments.Memory.Get(memory.Relocatable{SegmentIndex: 0, Offset: 0})
if err == nil {
t.Errorf("Expected addr 0:0 to be empty for empty program, got: %+v", value)
}

// Execution segment
// 1:0 end_ptr
value, err = runner.Vm.Segments.Memory.Get(memory.Relocatable{SegmentIndex: 1, Offset: 0})
if err != nil {
t.Errorf("Memory Get error in test: %s", err)
}
rel, ok := value.GetRelocatable()
if !ok || rel.SegmentIndex != 3 || rel.Offset != 0 {
t.Errorf("Wrong value for address 1:0: %d", rel)
}
// 1:1 return_fp
value, err = runner.Vm.Segments.Memory.Get(memory.Relocatable{SegmentIndex: 1, Offset: 1})
if err != nil {
t.Errorf("Memory Get error in test: %s", err)
}
rel, ok = value.GetRelocatable()
if !ok || rel.SegmentIndex != 2 || rel.Offset != 0 {
t.Errorf("Wrong value for address 1:0: %d", rel)
}
}

func TestInitializeRunnerNoBuiltinsNoProofModeNonEmptyProgram(t *testing.T) {
// Create a Program with one fake instruction
program_data := make([]memory.MaybeRelocatable, 1)
program_data[0] = *memory.NewMaybeRelocatableInt(1)
program := vm.Program{Data: program_data}
// Create CairoRunner
runner := runners.NewCairoRunner(program)
// Initialize the runner
end_ptr, err := runner.Initialize()
if err != nil {
t.Errorf("Initialize error in test: %s", err)
}
if end_ptr.SegmentIndex != 3 || end_ptr.Offset != 0 {
t.Errorf("Wrong end ptr value, got %+v", end_ptr)
}

// Check CairoRunner values
if runner.ProgramBase.SegmentIndex != 0 || runner.ProgramBase.Offset != 0 {
t.Errorf("Wrong ProgramBase value, got %+v", runner.ProgramBase)
}

// Check Vm's RunContext values
if runner.Vm.RunContext.Pc.SegmentIndex != 0 || runner.Vm.RunContext.Pc.Offset != 0 {
t.Errorf("Wrong Pc value, got %+v", runner.Vm.RunContext.Pc)
}
if runner.Vm.RunContext.Ap.SegmentIndex != 1 || runner.Vm.RunContext.Ap.Offset != 2 {
t.Errorf("Wrong Ap value, got %+v", runner.Vm.RunContext.Ap)
}
if runner.Vm.RunContext.Fp.SegmentIndex != 1 || runner.Vm.RunContext.Fp.Offset != 2 {
t.Errorf("Wrong Fp value, got %+v", runner.Vm.RunContext.Fp)
}

// Check memory

// Program segment
// 0:0 program_data[0]
value, err := runner.Vm.Segments.Memory.Get(memory.Relocatable{SegmentIndex: 0, Offset: 0})
if err != nil {
t.Errorf("Memory Get error in test: %s", err)
}
int, ok := value.GetInt()
if !ok || int.Felt != 1 {
t.Errorf("Wrong value for address 0:0: %d", int)
}

// Execution segment
// 1:0 end_ptr
value, err = runner.Vm.Segments.Memory.Get(memory.Relocatable{SegmentIndex: 1, Offset: 0})
if err != nil {
t.Errorf("Memory Get error in test: %s", err)
}
rel, ok := value.GetRelocatable()
if !ok || rel.SegmentIndex != 3 || rel.Offset != 0 {
t.Errorf("Wrong value for address 1:0: %d", rel)
}
// 1:1 return_fp
value, err = runner.Vm.Segments.Memory.Get(memory.Relocatable{SegmentIndex: 1, Offset: 1})
if err != nil {
t.Errorf("Memory Get error in test: %s", err)
}
rel, ok = value.GetRelocatable()
if !ok || rel.SegmentIndex != 2 || rel.Offset != 0 {
t.Errorf("Wrong value for address 1:0: %d", rel)
}
}
4 changes: 2 additions & 2 deletions pkg/vm/memory/relocatable.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func (r *Relocatable) RelocateAddress(relocationTable *[]uint) uint {
type Int struct {
// FIXME: Here we should use Lambdaworks felt, just mocking
// this for now.
felt uint
Felt uint
}

// MaybeRelocatable is the type of the memory cells in the Cairo
Expand Down Expand Up @@ -69,7 +69,7 @@ func (m *MaybeRelocatable) GetRelocatable() (Relocatable, bool) {
func (m *MaybeRelocatable) RelocateValue(relocationTable *[]uint) (uint, error) {
inner_int, ok := m.GetInt()
if ok {
return inner_int.felt, nil
return inner_int.Felt, nil
}

inner_relocatable, ok := m.GetRelocatable()
Expand Down
4 changes: 3 additions & 1 deletion pkg/vm/program.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package vm

import "github.com/lambdaclass/cairo-vm.go/pkg/vm/memory"

type Program struct {
Data []uint
Data []memory.MaybeRelocatable
}
8 changes: 3 additions & 5 deletions pkg/vm/vm_core.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@ import "github.com/lambdaclass/cairo-vm.go/pkg/vm/memory"
// VirtualMachine represents the Cairo VM.
// Runs Cairo assembly and produces an execution trace.
type VirtualMachine struct {
runContext RunContext
RunContext RunContext
currentStep uint
Segments *memory.MemorySegmentManager
Segments memory.MemorySegmentManager
}

func NewVirtualMachine() *VirtualMachine {
segments := memory.NewMemorySegmentManager()

return &VirtualMachine{Segments: segments}
return &VirtualMachine{Segments: *memory.NewMemorySegmentManager()}
}
Loading