-
Notifications
You must be signed in to change notification settings - Fork 295
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(avm): kernel output opcodes #6416
Changes from 70 commits
8853132
abc3cba
8b88dcd
c8d9601
c695905
40eeb8f
619175b
65c3159
61d10f6
7e84550
c054aca
f38773f
a4262dc
cf4bb86
12a9789
14d15cc
b0f8041
d5813a2
6265c61
59b221c
b613cf5
81a2500
c934c61
a8ceaf8
af343db
9388ecc
9e7aad0
859a3df
b4a47b3
79cf849
faac5b1
7e70e7d
4bb42b8
bccfd67
2a74110
1285ccf
60836ca
e2bcca8
7bff191
115f17c
de663f1
c910000
fd728c7
66f958e
ecdf742
3f31357
d6aeda8
ea48aca
e1e2cb8
3be1242
bee84aa
449f3da
a6470d7
94269ae
3d6633b
25e31bd
963dbf6
d465a04
c45c666
036910e
9774d95
c1c4f21
c88d5ef
c5847b2
70a6e86
f8e8349
289c302
17640ef
7e120ad
0dc2c58
6b2bfd6
3e85832
1922ccb
9dca2e2
f9cf428
cb1f006
1bdb64f
17c216b
c714d7f
b95b838
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,12 @@ include "avm_kernel.pil"; | |
include "gadgets/avm_conversion.pil"; | ||
|
||
namespace avm_main(256); | ||
//===== CONSTANT POLYNOMIALS ================================================== | ||
pol constant clk(i) { i }; | ||
pol constant first = [1] + [0]*; // Used mostly to toggle off the first row consisting | ||
// only in first element of shifted polynomials. | ||
|
||
//===== KERNEL INPUTS ========================================================= | ||
// Kernel lookup selector opcodes | ||
pol commit q_kernel_lookup; | ||
|
||
|
@@ -26,14 +32,23 @@ namespace avm_main(256); | |
pol commit sel_op_coinbase; | ||
pol commit sel_op_timestamp; | ||
|
||
//===== KERNEL OUTPUTS ======================================================== | ||
pol commit q_kernel_output_lookup; | ||
|
||
pol commit sel_op_note_hash_exists; | ||
pol commit sel_op_emit_note_hash; | ||
pol commit sel_op_nullifier_exists; | ||
pol commit sel_op_emit_nullifier; | ||
pol commit sel_op_l1_to_l2_msg_exists; | ||
pol commit sel_op_emit_unencrypted_log; | ||
pol commit sel_op_emit_l2_to_l1_msg; | ||
|
||
pol commit sel_op_sload; | ||
pol commit sel_op_sstore; | ||
|
||
//===== Gadget Selectors ====================================================== | ||
pol commit sel_op_radix_le; | ||
|
||
//===== CONSTANT POLYNOMIALS ================================================== | ||
pol constant clk(i) { i }; | ||
pol constant first = [1] + [0]*; // Used mostly to toggle off the first row consisting | ||
// only in first element of shifted polynomials. | ||
|
||
//===== Fix Range Checks Selectors============================================= | ||
// We re-use the clk column for the lookup values of 8-bit resp. 16-bit range check. | ||
pol commit sel_rng_8; // Boolean selector for the 8-bit range check lookup | ||
|
@@ -171,6 +186,17 @@ namespace avm_main(256); | |
sel_op_fee_per_da_gas * (1 - sel_op_fee_per_da_gas) = 0; | ||
sel_op_transaction_fee * (1 - sel_op_transaction_fee) = 0; | ||
|
||
sel_op_note_hash_exists * (1 - sel_op_note_hash_exists) = 0; | ||
sel_op_emit_note_hash * (1 - sel_op_emit_note_hash) = 0; | ||
sel_op_nullifier_exists * (1 - sel_op_nullifier_exists) = 0; | ||
sel_op_emit_nullifier * (1 - sel_op_emit_nullifier) = 0; | ||
sel_op_l1_to_l2_msg_exists * (1 - sel_op_l1_to_l2_msg_exists) = 0; | ||
sel_op_emit_unencrypted_log * (1 - sel_op_emit_unencrypted_log) = 0; | ||
sel_op_emit_l2_to_l1_msg * (1 - sel_op_emit_l2_to_l1_msg) = 0; | ||
|
||
sel_op_sload * (1 - sel_op_sload) = 0; | ||
sel_op_sstore * (1 - sel_op_sstore) = 0; | ||
|
||
sel_op_radix_le * (1 - sel_op_radix_le) = 0; | ||
|
||
sel_op_add * (1 - sel_op_add) = 0; | ||
|
@@ -275,13 +301,20 @@ namespace avm_main(256); | |
// Drawback is the need to paralllelize the latter. | ||
|
||
//===== KERNEL LOOKUPS ======================================================= | ||
pol KERNEL_SELECTORS = ( | ||
sel_op_sender + sel_op_address + sel_op_portal + sel_op_chain_id + sel_op_version + sel_op_block_number + | ||
sel_op_coinbase + sel_op_timestamp + sel_op_fee_per_l2_gas + sel_op_fee_per_da_gas + sel_op_transaction_fee | ||
pol KERNEL_INPUT_SELECTORS = ( | ||
sel_op_sender + sel_op_address + sel_op_portal + sel_op_chain_id + sel_op_version + sel_op_block_number + sel_op_coinbase + | ||
sel_op_timestamp + sel_op_fee_per_l2_gas + sel_op_fee_per_da_gas + sel_op_transaction_fee | ||
); | ||
// Ensure that only one kernel lookup is active when the kernel_sel is active | ||
#[KERNEL_ACTIVE_CHECK] | ||
KERNEL_SELECTORS * (1 - q_kernel_lookup) = 0; | ||
#[KERNEL_INPUT_ACTIVE_CHECK] | ||
KERNEL_INPUT_SELECTORS * (1 - q_kernel_lookup) = 0; | ||
|
||
pol KERNEL_OUTPUT_SELECTORS = ( | ||
sel_op_note_hash_exists + sel_op_emit_note_hash + sel_op_nullifier_exists + sel_op_emit_nullifier + sel_op_l1_to_l2_msg_exists + | ||
sel_op_emit_unencrypted_log + sel_op_emit_l2_to_l1_msg + sel_op_sload + sel_op_sstore | ||
); | ||
#[KERNEL_OUTPUT_ACTIVE_CHECK] | ||
KERNEL_OUTPUT_SELECTORS * (1 - q_kernel_output_lookup) = 0; | ||
|
||
//===== CONTROL FLOW ======================================================= | ||
//===== JUMP =============================================================== | ||
|
@@ -318,7 +351,7 @@ namespace avm_main(256); | |
//===== CONTROL_FLOW_CONSISTENCY ============================================ | ||
pol INTERNAL_CALL_STACK_SELECTORS = (first + sel_internal_call + sel_internal_return + sel_halt); | ||
pol OPCODE_SELECTORS = (sel_op_add + sel_op_sub + sel_op_div + sel_op_fdiv + sel_op_mul + sel_op_not | ||
+ sel_op_eq + sel_op_and + sel_op_or + sel_op_xor + sel_op_cast + KERNEL_SELECTORS); | ||
+ sel_op_eq + sel_op_and + sel_op_or + sel_op_xor + sel_op_cast + KERNEL_INPUT_SELECTORS + KERNEL_OUTPUT_SELECTORS); | ||
|
||
// Program counter must increment if not jumping or returning | ||
#[PC_INCREMENT] | ||
|
@@ -419,6 +452,42 @@ namespace avm_main(256); | |
#[TIMESTAMP_KERNEL] | ||
sel_op_timestamp * (avm_kernel.kernel_sel - constants.TIMESTAMP_SELECTOR) = 0; | ||
|
||
// OUTPUTS LOOKUPS | ||
// Constrain the value of kernel_out_sel to be the correct offset for the operation being performed | ||
#[NOTE_HASH_KERNEL_OUTPUT] | ||
sel_op_note_hash_exists * (avm_kernel.kernel_out_sel - (avm_kernel.START_NOTE_HASH_EXISTS_WRITE_OFFSET + avm_kernel.note_hash_exist_write_offset)) = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. avm_kernel.note_hash_exist_write_offset should be constrained to be initialized to zero. (maybe on first line?) Same holds for all other offsets. |
||
|
||
#[EMIT_NOTE_HASH_KERNEL_OUTPUT] | ||
sel_op_emit_note_hash * (avm_kernel.kernel_out_sel - (avm_kernel.START_EMIT_NOTE_HASH_WRITE_OFFSET + avm_kernel.emit_note_hash_write_offset)) = 0; | ||
|
||
#[NULLIFIER_EXISTS_KERNEL_OUTPUT] | ||
sel_op_nullifier_exists * (avm_kernel.kernel_out_sel - (avm_kernel.START_NULLIFIER_EXISTS_OFFSET + avm_kernel.nullifier_exists_write_offset)) = 0; | ||
|
||
#[EMIT_NULLIFIER_KERNEL_OUTPUT] | ||
sel_op_emit_nullifier * (avm_kernel.kernel_out_sel - (avm_kernel.START_EMIT_NULLIFIER_WRITE_OFFSET + avm_kernel.emit_nullifier_write_offset)) = 0; | ||
|
||
#[L1_TO_L2_MSG_EXISTS_KERNEL_OUTPUT] | ||
sel_op_l1_to_l2_msg_exists * (avm_kernel.kernel_out_sel - (avm_kernel.START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET + avm_kernel.l1_to_l2_msg_exists_write_offset)) = 0; | ||
|
||
#[EMIT_UNENCRYPTED_LOG_KERNEL_OUTPUT] | ||
sel_op_emit_unencrypted_log * (avm_kernel.kernel_out_sel - (avm_kernel.START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET + avm_kernel.emit_unencrypted_log_write_offset)) = 0; | ||
|
||
#[EMIT_L2_TO_L1_MSGS_KERNEL_OUTPUT] | ||
sel_op_emit_l2_to_l1_msg * (avm_kernel.kernel_out_sel - (avm_kernel.START_EMIT_L2_TO_l1_MSG + avm_kernel.emit_l2_to_l1_msg_write_offset)) = 0; | ||
|
||
#[SLOAD_KERNEL_OUTPUT] | ||
sel_op_sload * (avm_kernel.kernel_out_sel - (avm_kernel.START_SLOAD_WRITE_OFFSET + avm_kernel.sload_write_offset)) = 0; | ||
|
||
#[SSTORE_KERNEL_OUTPUT] | ||
sel_op_sstore * (avm_kernel.kernel_out_sel - (avm_kernel.START_SSTORE_WRITE_OFFSET + avm_kernel.sstore_write_offset)) = 0; | ||
|
||
// When we encounter a state writing opcode | ||
// We increment the side effect counter by 1 | ||
KERNEL_OUTPUT_SELECTORS * (avm_kernel.side_effect_counter' - (avm_kernel.side_effect_counter + 1)) = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this crucial to start at zero? (Probably, otherwise a malicious prover might choose a huge value and then you get overflow/wraparound. Not sure about what the kernel is expecting.) If yes, then we should have a constraint to enforce the initial value to be zero. (maybe sthg like: first * avm_kernel.side_effect_counter =0 ) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Side effect counter will be required to be constrained to the value of the start_side_effect_counter in the public inputs - this can be done with a copy constraint or via a lookup |
||
|
||
#[KERNEL_OUTPUT_LOOKUP] | ||
q_kernel_output_lookup {avm_kernel.kernel_out_sel, ia, avm_kernel.side_effect_counter, ib} in avm_kernel.q_public_input_kernel_out_add_to_table {clk, avm_kernel.kernel_value_out__is_public, avm_kernel.kernel_side_effect_out__is_public, avm_kernel.kernel_metadata_out__is_public}; | ||
|
||
#[LOOKUP_INTO_KERNEL] | ||
// TODO: FIX not having the trailing is_public breaking compilation :( | ||
q_kernel_lookup { avm_main.ia, avm_kernel.kernel_sel } in avm_kernel.q_public_input_kernel_add_to_table { avm_kernel.kernel_inputs__is_public, clk }; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
|
||
#pragma once | ||
#include "../../relation_parameters.hpp" | ||
#include "../../relation_types.hpp" | ||
#include "./declare_views.hpp" | ||
|
||
namespace bb::Avm_vm { | ||
|
||
template <typename FF> struct Avm_kernelRow { | ||
FF avm_kernel_emit_l2_to_l1_msg_write_offset{}; | ||
FF avm_kernel_emit_l2_to_l1_msg_write_offset_shift{}; | ||
FF avm_kernel_emit_note_hash_write_offset{}; | ||
FF avm_kernel_emit_note_hash_write_offset_shift{}; | ||
FF avm_kernel_emit_nullifier_write_offset{}; | ||
FF avm_kernel_emit_nullifier_write_offset_shift{}; | ||
FF avm_kernel_emit_unencrypted_log_write_offset{}; | ||
FF avm_kernel_emit_unencrypted_log_write_offset_shift{}; | ||
FF avm_kernel_l1_to_l2_msg_exists_write_offset{}; | ||
FF avm_kernel_l1_to_l2_msg_exists_write_offset_shift{}; | ||
FF avm_kernel_note_hash_exist_write_offset{}; | ||
FF avm_kernel_note_hash_exist_write_offset_shift{}; | ||
FF avm_kernel_nullifier_exists_write_offset{}; | ||
FF avm_kernel_nullifier_exists_write_offset_shift{}; | ||
FF avm_kernel_sload_write_offset{}; | ||
FF avm_kernel_sload_write_offset_shift{}; | ||
FF avm_kernel_sstore_write_offset{}; | ||
FF avm_kernel_sstore_write_offset_shift{}; | ||
FF avm_main_last{}; | ||
FF avm_main_sel_op_emit_l2_to_l1_msg{}; | ||
FF avm_main_sel_op_emit_note_hash{}; | ||
FF avm_main_sel_op_emit_nullifier{}; | ||
FF avm_main_sel_op_emit_unencrypted_log{}; | ||
FF avm_main_sel_op_l1_to_l2_msg_exists{}; | ||
FF avm_main_sel_op_note_hash_exists{}; | ||
FF avm_main_sel_op_nullifier_exists{}; | ||
FF avm_main_sel_op_sload{}; | ||
FF avm_main_sel_op_sstore{}; | ||
}; | ||
|
||
inline std::string get_relation_label_avm_kernel(int index) | ||
{ | ||
switch (index) { | ||
case 0: | ||
return "NOTE_HASH_EXISTS_INC_CONSISTENCY_CHECK"; | ||
|
||
case 1: | ||
return "EMIT_NOTE_HASH_INC_CONSISTENCY_CHECK"; | ||
|
||
case 2: | ||
return "NULLIFIER_EXISTS_INC_CONSISTENCY_CHECK"; | ||
|
||
case 3: | ||
return "EMIT_NULLIFIER_INC_CONSISTENCY_CHECK"; | ||
|
||
case 4: | ||
return "L1_TO_L2_MSG_EXISTS_INC_CONSISTENCY_CHECK"; | ||
|
||
case 5: | ||
return "EMIT_UNENCRYPTED_LOG_INC_CONSISTENCY_CHECK"; | ||
|
||
case 6: | ||
return "EMIT_L2_TO_L1_MSG_INC_CONSISTENCY_CHECK"; | ||
|
||
case 7: | ||
return "SLOAD_INC_CONSISTENCY_CHECK"; | ||
|
||
case 8: | ||
return "SSTORE_INC_CONSISTENCY_CHECK"; | ||
} | ||
return std::to_string(index); | ||
} | ||
|
||
template <typename FF_> class avm_kernelImpl { | ||
public: | ||
using FF = FF_; | ||
|
||
static constexpr std::array<size_t, 9> SUBRELATION_PARTIAL_LENGTHS{ | ||
3, 3, 3, 3, 3, 3, 3, 3, 3, | ||
}; | ||
|
||
template <typename ContainerOverSubrelations, typename AllEntities> | ||
void static accumulate(ContainerOverSubrelations& evals, | ||
const AllEntities& new_term, | ||
[[maybe_unused]] const RelationParameters<FF>&, | ||
[[maybe_unused]] const FF& scaling_factor) | ||
{ | ||
|
||
// Contribution 0 | ||
{ | ||
Avm_DECLARE_VIEWS(0); | ||
|
||
auto tmp = ((-avm_main_last + FF(1)) * | ||
(avm_kernel_note_hash_exist_write_offset_shift - | ||
(avm_kernel_note_hash_exist_write_offset + avm_main_sel_op_note_hash_exists))); | ||
tmp *= scaling_factor; | ||
std::get<0>(evals) += tmp; | ||
} | ||
// Contribution 1 | ||
{ | ||
Avm_DECLARE_VIEWS(1); | ||
|
||
auto tmp = ((-avm_main_last + FF(1)) * | ||
(avm_kernel_emit_note_hash_write_offset_shift - | ||
(avm_kernel_emit_note_hash_write_offset + avm_main_sel_op_emit_note_hash))); | ||
tmp *= scaling_factor; | ||
std::get<1>(evals) += tmp; | ||
} | ||
// Contribution 2 | ||
{ | ||
Avm_DECLARE_VIEWS(2); | ||
|
||
auto tmp = ((-avm_main_last + FF(1)) * | ||
(avm_kernel_nullifier_exists_write_offset_shift - | ||
(avm_kernel_nullifier_exists_write_offset + avm_main_sel_op_nullifier_exists))); | ||
tmp *= scaling_factor; | ||
std::get<2>(evals) += tmp; | ||
} | ||
// Contribution 3 | ||
{ | ||
Avm_DECLARE_VIEWS(3); | ||
|
||
auto tmp = ((-avm_main_last + FF(1)) * | ||
(avm_kernel_emit_nullifier_write_offset_shift - | ||
(avm_kernel_emit_nullifier_write_offset + avm_main_sel_op_emit_nullifier))); | ||
tmp *= scaling_factor; | ||
std::get<3>(evals) += tmp; | ||
} | ||
// Contribution 4 | ||
{ | ||
Avm_DECLARE_VIEWS(4); | ||
|
||
auto tmp = ((-avm_main_last + FF(1)) * | ||
(avm_kernel_l1_to_l2_msg_exists_write_offset_shift - | ||
(avm_kernel_l1_to_l2_msg_exists_write_offset + avm_main_sel_op_l1_to_l2_msg_exists))); | ||
tmp *= scaling_factor; | ||
std::get<4>(evals) += tmp; | ||
} | ||
// Contribution 5 | ||
{ | ||
Avm_DECLARE_VIEWS(5); | ||
|
||
auto tmp = ((-avm_main_last + FF(1)) * | ||
(avm_kernel_emit_unencrypted_log_write_offset_shift - | ||
(avm_kernel_emit_unencrypted_log_write_offset + avm_main_sel_op_emit_unencrypted_log))); | ||
tmp *= scaling_factor; | ||
std::get<5>(evals) += tmp; | ||
} | ||
// Contribution 6 | ||
{ | ||
Avm_DECLARE_VIEWS(6); | ||
|
||
auto tmp = ((-avm_main_last + FF(1)) * | ||
(avm_kernel_emit_l2_to_l1_msg_write_offset_shift - | ||
(avm_kernel_emit_l2_to_l1_msg_write_offset + avm_main_sel_op_emit_l2_to_l1_msg))); | ||
tmp *= scaling_factor; | ||
std::get<6>(evals) += tmp; | ||
} | ||
// Contribution 7 | ||
{ | ||
Avm_DECLARE_VIEWS(7); | ||
|
||
auto tmp = ((-avm_main_last + FF(1)) * (avm_kernel_sload_write_offset_shift - | ||
(avm_kernel_sload_write_offset + avm_main_sel_op_sload))); | ||
tmp *= scaling_factor; | ||
std::get<7>(evals) += tmp; | ||
} | ||
// Contribution 8 | ||
{ | ||
Avm_DECLARE_VIEWS(8); | ||
|
||
auto tmp = ((-avm_main_last + FF(1)) * (avm_kernel_sstore_write_offset_shift - | ||
(avm_kernel_sstore_write_offset + avm_main_sel_op_sstore))); | ||
tmp *= scaling_factor; | ||
std::get<8>(evals) += tmp; | ||
} | ||
} | ||
}; | ||
|
||
template <typename FF> using avm_kernel = Relation<avm_kernelImpl<FF>>; | ||
|
||
} // namespace bb::Avm_vm |
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.
The suffix "sel" makes us think it is a boolean. I think "offset" suffix might be better,