-
Notifications
You must be signed in to change notification settings - Fork 160
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
feat: DYN
takes a memory address instead of digest on stack
#1535
base: next
Are you sure you want to change the base?
Conversation
Ah yes - good point! I didn't think of this. Indeed, we may need to do #1478 first. |
398ec10
to
b83bb5c
Compare
b83bb5c
to
26f33fa
Compare
26f33fa
to
328ac68
Compare
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.
Looks great! Thank you! I left some comments inline - but nothing major.
The complexity in the stack resulting from having to do a left shift and a context switch at the same time is a bit unfortunate - but I'm not seeing a better way to do it. We should probably create an issue to come back to this later and try to make the constraints a bit more uniform.
@@ -111,6 +111,7 @@ pub(super) mod opcode_constants { | |||
pub const OPCODE_RCOMBBASE: u8 = 0b0101_1001; | |||
pub const OPCODE_EMIT: u8 = 0b0101_1010; | |||
pub const OPCODE_PUSH: u8 = 0b0101_1011; | |||
pub const OPCODE_DYNCALL: u8 = 0b0101_1100; |
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.
Depending on where we end up in #1536 (comment), we might need to move this to a "very-high-degree" operation bucket (i.e., line 117 below).
/// Returns the memory word at address `addr`. | ||
pub(crate) fn read_mem_word(&mut self, addr: Felt) -> Result<Word, ExecutionError> { |
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.
nit: I'd maybe clarify the comment to be "Returns the memory word at address addr
in the current context."
// make sure execution context was provided for CALL and SYSCALL blocks | ||
if block_type == BlockType::Call || block_type == BlockType::SysCall { | ||
if block_type == BlockType::Call | ||
|| block_type == BlockType::SysCall | ||
|| block_type == BlockType::Dyncall |
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.
nit: let's mention DYNCALL
in the comment as well (may also be relevant for the comment on line 22 above).
pub fn decoder_hasher_state_element(&self, element: usize, i: RowIndex) -> Felt { | ||
self.columns.get_column(DECODER_TRACE_OFFSET + HASHER_STATE_OFFSET + element)[i + 1] | ||
self.columns.get_column(DECODER_TRACE_OFFSET + HASHER_STATE_OFFSET + element)[i] | ||
} |
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.
Was this a bug previously?
@@ -77,13 +78,15 @@ pub fn enforce_stack_depth_constraints<E: FieldElement>( | |||
let depth = frame.stack_depth(); | |||
let depth_next = frame.stack_depth_next(); | |||
|
|||
let call_or_syscall = op_flag.call() + op_flag.syscall(); | |||
let call_or_syscall_end = op_flag.end() * (frame.is_call_end() + frame.is_syscall_end()); | |||
let call_or_syscall_or_dyncall = op_flag.call() + op_flag.syscall() + op_flag.dyncall(); |
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.
nit: I'd call it call_or_dyncall_or_syscall
// Dyncall's effect on the trace can't be written in terms of any other operation, and | ||
// therefore can't follow this framework. Hence, we do it "manually". It's probably worth | ||
// refactoring the decoder though to remove this Noop execution pattern. |
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.
Let's create an issue for this.
// Note: we need to read these values before `start_dyn_node()`, since `start_dyn_node()` | ||
// advances the clock. | ||
let mem_addr = self.stack.get(0); | ||
// The callee hash is stored in memory, and the address is specified on the top of the | ||
// stack. | ||
let callee_hash = self.read_mem_word(mem_addr)?; |
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.
Technically, we could move these inside start_dyn_nod()
and start_dyncall_node()
since we don't advance the clock until the very end of these functions - right?
|
||
let memory_req = { | ||
let mem_addr = main_trace.stack_element(0, row); | ||
let word = main_trace.decoder_hasher_state_first_half(row); |
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.
nit: would mem_value
be a better name here (instead of word
)?
match self.active_depth { | ||
0..=MAX_TOP_IDX => unreachable!("stack underflow"), | ||
MIN_STACK_DEPTH => { | ||
// Shift in a ZERO, to prevent depth shrinking below the minimum stack depth. | ||
self.trace.stack_shift_left_no_helpers(self.clk, START_POSITION, ZERO, None); | ||
}, | ||
_ => { | ||
// Update the stack & overflow table. | ||
let from_overflow = self.overflow.pop(u64::from(self.clk)); | ||
self.trace.stack_shift_left_no_helpers( | ||
self.clk, | ||
START_POSITION, | ||
from_overflow, | ||
Some(self.overflow.last_row_addr()), | ||
); | ||
|
||
// Stack depth only decreases when it is greater than the minimum stack depth. | ||
self.active_depth -= 1; | ||
self.full_depth -= 1; | ||
}, |
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 code is basically the same as shift_left()
function (except for lines 269 - 273). I wonder if there is a way use the same code. Though, if it complicates things too much, I'd probably just leave a comment here so that we know that these blocks of code need to be kept in sync.
Felt::from(self.active_depth as u32), | ||
self.overflow.last_row_addr(), |
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.
self.active_depth
should be 16 and self.overlfow.last_row_addr()
should zero here, right? Maybe worth adding a comment to mention this.
Closes #1091
Closes #1478
Left to do: