-
Notifications
You must be signed in to change notification settings - Fork 52
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
Implement proof_mode
functionalities
#682
base: main
Are you sure you want to change the base?
Conversation
…arguments and initial gas to the memory
* Add parsing logic for input user args * Add flags for available gas, input user args, writing args to memory * Fix unit tests for user arguments parsing * Lint the PR * Add user args to hint context * Refactor the code * Fix unconditional append of ExternalWriteArgsToMemory, bug fixes in integration tests * Add fixes of the call size calculation and include ExternalWriteArgsToMemory hint when gas present * Add layouts for integration tests * Add error handling * Fixes in entry code generation * Address changes mentioned in a discussion * Add comment regarding writing to memory in a hint for the future reference in the integration tests with args * Changes in calculations of the initial PC offset, CALL opcode offset incremented by mainFuncOffset, writing user args to the AP in the hint * Turn back VM config to private field * Add error handling on assign of `userArgs` to the initial scope * Lint project * Bump go version from 1.20 -> 1.21 (#678) * Bump go version from 1.20 -> 1.21 * Update golangci-lint * Simplify the Makefile * Correction in the makefile
…ration tests pipeline
"./cairo_1_programs/", | ||
"./cairo_1_programs/dict_non_squashed", | ||
"./cairo_1_programs/with_input", | ||
"./cairo_1_programs/serialized_output", | ||
"./cairo_1_programs/serialized_output/with_input", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed in the daily today, it would be nice to refactor the code below to run the tests recursively in the same folder, instead of having to pass all the subdirectories as roots as well. This could be solved in a separate PR, as this already has a lot of things. Let's just link the issue to this comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I cannot comment on lines that haven't been changed, but looking into the refactor I noticed in line 195 (before this changes) the last argument should be false
, as discussed today as well
@@ -191,6 +191,8 @@ func (segment *Segment) String() string { | |||
// Represents the whole VM memory divided into segments | |||
type Memory struct { | |||
Segments []*Segment | |||
// TemporarySegments is a map of temporary segments, key is the segment index, value is the segment | |||
TemporarySegments map[uint64]*Segment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure why we need to use a map here. As far as I see, the only place where this is updated is in AllocateEmptyTemporarySegment
function in line:
memory.TemporarySegments[uint64(len(memory.TemporarySegments))] = EmptySegment()
This looks like you could just use an array and append an EmptySegment
instead.
Am I missing something?
@@ -227,6 +229,15 @@ func (memory *Memory) AllocateEmptySegment() MemoryAddress { | |||
} | |||
} | |||
|
|||
// Allocates an empty temporary segment and returns its index | |||
func (memory *Memory) AllocateEmptyTemporarySegment() MemoryAddress { | |||
memory.TemporarySegments[uint64(len(memory.TemporarySegments))] = EmptySegment() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is what I commented above regarding TemporarySegments
structure
func (memory *Memory) AllocateEmptyTemporarySegment() MemoryAddress { | ||
memory.TemporarySegments[uint64(len(memory.TemporarySegments))] = EmptySegment() | ||
return MemoryAddress{ | ||
SegmentIndex: uint64(len(memory.TemporarySegments)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the correct SegmentIndex
? After the previous line the length of the map increased by 1, so the index you are returning here is different from the one you used as key
@@ -38,19 +38,27 @@ func (d *Dictionary) InitNumber() uint64 { | |||
type DictionaryManager struct { | |||
// a map that links a segment index to a dictionary | |||
dictionaries map[uint64]Dictionary | |||
// useTemporarySegments is a flag that indicates if the dictionaries should located in temporary segments, and later relocated to memory segments |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing word in comment, it should be: "the dictionaries should be located in temporary segments"
case ExecutionModeZero, ExecutionModeCairo: | ||
returnFp := memory.AllocateEmptySegment() | ||
mvReturnFp := mem.MemoryValueFromMemoryAddress(&returnFp) | ||
if runner.runnerMode == ProofModeCairo { | ||
// In Cairo mainPCOffset is equal to the offset of program segment base | ||
return runner.initializeEntrypoint(uint64(0), nil, &mvReturnFp, memory, stack, 2) | ||
} else if runner.runnerMode == ExecutionModeCairo { | ||
return runner.initializeEntrypoint(uint64(0), nil, &mvReturnFp, memory, stack, 0) | ||
if runner.runnerMode == ExecutionModeCairo { | ||
return runner.initializeEntrypoint(uint64(0), nil, &mvReturnFp, memory, stack) | ||
} else { | ||
mainPCOffset, ok := runner.program.Entrypoints["main"] | ||
if !ok { | ||
return mem.UnknownAddress, errors.New("can't find an entrypoint for main") | ||
} | ||
return runner.initializeEntrypoint(mainPCOffset, nil, &mvReturnFp, memory, stack, 0) | ||
return runner.initializeEntrypoint(mainPCOffset, nil, &mvReturnFp, memory, stack) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps it's better to separate these two, at the end you have the logic in different branches already. I think it will be more readable this way. Should we re-add the comment regarding mainPCOffset
in Cairo?
for _, builtin := range function.Builtins { | ||
adjustedRetOffset += 1 | ||
_, ok := builtinsOffsetsMap[builtin] | ||
if ok { | ||
builtinsOffsetsMap[builtin] = adjustedRetOffset | ||
} else { | ||
continue | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for _, builtin := range function.Builtins { | |
adjustedRetOffset += 1 | |
_, ok := builtinsOffsetsMap[builtin] | |
if ok { | |
builtinsOffsetsMap[builtin] = adjustedRetOffset | |
} else { | |
continue | |
} | |
} | |
for _, builtin := range function.Builtins { | |
adjustedRetOffset += 1 | |
if _, ok := builtinsOffsetsMap[builtin]; ok { | |
builtinsOffsetsMap[builtin] = adjustedRetOffset | |
} | |
} |
ctx.AddInlineCASM(fmt.Sprintf("call rel %d; ret;", int(totalSize))) | ||
return ctx.instructions, hints, nil | ||
ctx.instructions[callRelArgLocation] = new(fp.Element).SetUint64(uint64(ctx.currentCodeOffset) + codeOffsetBeforeCallRel) | ||
return ctx.instructions, hints, ctx.currentCodeOffset, programBuiltins, gotGasBuiltin, gotSegmentArena, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this function returning an error ever?
// Check if return type is either: | ||
// 1. PanicResult with inner type of Array<felt252> with size 2 | ||
// 2. Array<felt252> with size 2 | ||
isPanicResultFeltArray := false | ||
if strings.Contains(mainFunc.ReturnArgs[0].DebugName, "core::panics::PanicResult::") { | ||
isPanicResultFeltArray = strings.Contains(mainFunc.ReturnArgs[0].PanicInnerType.DebugName, "Array<felt252>") | ||
} | ||
isFeltArray := mainFunc.ReturnArgs[0].DebugName == "Array<felt252>" && | ||
mainFunc.ReturnArgs[0].Size == 2 | ||
|
||
if !isPanicResultFeltArray && !isFeltArray { | ||
return fmt.Errorf("main function return argument should be either PanicResult of size 3 or Felt Array of size 2") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there is a mismatch between the comment point 1 for PanicResult and the error at the end regarding the size: in the first case it says 2 but in the error it says 3, what's the correct one?
// 2. Array<felt252> with size 2 | ||
isPanicResultFeltArray := false | ||
if strings.Contains(mainFunc.ReturnArgs[0].DebugName, "core::panics::PanicResult::") { | ||
isPanicResultFeltArray = strings.Contains(mainFunc.ReturnArgs[0].PanicInnerType.DebugName, "Array<felt252>") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't you have to check for the size here?
No description provided.