Skip to content

Commit 0ca5388

Browse files
authored
feat: merge-train/avm (#16986)
BEGIN_COMMIT_OVERRIDE feat(avm!): Bytecode Hashing (#16756) chore(avm)!: gas gt migrations optimized (#16989) END_COMMIT_OVERRIDE
2 parents 50b0c1d + 915b603 commit 0ca5388

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1674
-729
lines changed

barretenberg/cpp/pil/vm2/bytecode/bc_hashing.pil

Lines changed: 179 additions & 47 deletions
Large diffs are not rendered by default.

barretenberg/cpp/pil/vm2/bytecode/bc_retrieval.pil

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,9 @@ should_retrieve {
153153
retrieved_bytecodes_tree_check.tree_size_after_write
154154
};
155155

156-
// TODO(dbanks12): re-enable once C++ and PIL use standard poseidon2 hashing for bytecode commitments.
157156
// Note: only need to hash the bytecode if there is no error. Otherwise there is nothing to hash!
158-
//#[BYTECODE_HASH_IS_CORRECT]
159-
//should_retrieve { bytecode_id, /*public_bytecode_commitment=*/ bytecode_id } in bc_hashing.latch { bc_hashing.bytecode_id, bc_hashing.output_hash };
157+
#[BYTECODE_HASH_IS_CORRECT]
158+
should_retrieve { bytecode_id, /*public_bytecode_commitment=*/ bytecode_id } in bc_hashing.latch { bc_hashing.bytecode_id, bc_hashing.output_hash };
160159

161160
// If instance does not exist, force current_class_id to 0.
162161
#[CURRENT_CLASS_ID_IS_ZERO_IF_INSTANCE_DOES_NOT_EXIST]

barretenberg/cpp/pil/vm2/context.pil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -485,8 +485,8 @@ namespace execution;
485485

486486
// If any error happened during execution (i.e., sel_error=1), all gas should be consumed.
487487
pol SEL_CONSUMED_ALL_GAS = sel_error;
488-
(l2_gas_limit - PREV_GAS_PLUS_USAGE_L2) * SEL_CONSUMED_ALL_GAS + PREV_GAS_PLUS_USAGE_L2 - l2_gas_used = 0;
489-
(da_gas_limit - PREV_GAS_PLUS_USAGE_DA) * SEL_CONSUMED_ALL_GAS + PREV_GAS_PLUS_USAGE_DA - da_gas_used = 0;
488+
(l2_gas_limit - total_gas_l2) * SEL_CONSUMED_ALL_GAS + total_gas_l2 - l2_gas_used = 0;
489+
(da_gas_limit - total_gas_da) * SEL_CONSUMED_ALL_GAS + total_gas_da - da_gas_used = 0;
490490

491491
// nested_exit_call = 1 <==> prev_gas_used' = parent_gas_used + gas_used
492492
// sel_enter_call = 1 <==> prev_gas_used' = 0

barretenberg/cpp/pil/vm2/execution/gas.pil

Lines changed: 21 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
include "../precomputed.pil";
2-
include "../range_check.pil";
2+
include "../gt.pil";
33

44
// This is a virtual gadget, which is part of the execution trace.
55
// https://excalidraw.com/#json=-fkwtFjYVOq2Z69Q351AE,O3SbjwK5eHX7-Oz2OH8RqQ
@@ -49,8 +49,8 @@ namespace execution;
4949
// ==== COMPARISON AGAINST THE LIMITS ====
5050

5151
// We will sum up all the gas used (base and dynamic) and compare just once.
52-
pol TOTAL_L2_GAS_USED = BASE_L2_GAS + DYNAMIC_L2_GAS_USED;
53-
pol TOTAL_DA_GAS_USED = base_da_gas + DYNAMIC_DA_GAS_USED;
52+
pol L2_GAS_USED = BASE_L2_GAS + DYNAMIC_L2_GAS_USED;
53+
pol DA_GAS_USED = base_da_gas + DYNAMIC_DA_GAS_USED;
5454

5555
// We are going to do 64 bit comparisons. If we assume:
5656
// prev_l2_gas_used to be u32::MAX_VALUE
@@ -59,43 +59,24 @@ namespace execution;
5959
// dynamic_da_gas to be u32::MAX_VALUE
6060
// Then prev_l2_gas_used + BASE_L2_GAS + dynamic_l2_gas_factor*dynamic_da_gas is exactly u64::MAX_VALUE.
6161

62-
pol commit constant_64;
63-
sel_should_check_gas * (64 - constant_64) = 0;
64-
65-
pol commit out_of_gas_l2;
66-
out_of_gas_l2 * (1 - out_of_gas_l2) = 0;
67-
pol commit out_of_gas_da;
68-
out_of_gas_da * (1 - out_of_gas_da) = 0;
69-
70-
pol PREV_GAS_PLUS_USAGE_L2 = prev_l2_gas_used + TOTAL_L2_GAS_USED;
71-
// Assumes l2_gas_limit is 32 bit and PREV_GAS_PLUS_USAGE_L2 is 64 bit
72-
// So we perform a 64 bit comparison
73-
pol LIMIT_GTE_USED_L2 = l2_gas_limit - PREV_GAS_PLUS_USAGE_L2;
74-
pol LIMIT_LT_USED_L2 = PREV_GAS_PLUS_USAGE_L2 - l2_gas_limit - 1;
75-
pol commit limit_used_l2_cmp_diff;
76-
// We multiply by sel_should_check_gas to force a 0 if we shouldn't check the gas.
77-
#[L2_CMP_DIFF]
78-
limit_used_l2_cmp_diff = sel_should_check_gas * ((LIMIT_LT_USED_L2 - LIMIT_GTE_USED_L2) * out_of_gas_l2 + LIMIT_GTE_USED_L2);
79-
80-
#[LIMIT_USED_L2_RANGE]
81-
sel_should_check_gas { limit_used_l2_cmp_diff, constant_64 }
82-
in
83-
range_check.sel { range_check.value, range_check.rng_chk_bits };
84-
85-
pol PREV_GAS_PLUS_USAGE_DA = prev_da_gas_used + TOTAL_DA_GAS_USED;
86-
// Assumes da_gas_limit is 32 bit and PREV_GAS_PLUS_USAGE_DA is 64 bit
87-
// So we perform a 64 bit comparison
88-
pol LIMIT_GTE_USED_DA = da_gas_limit - PREV_GAS_PLUS_USAGE_DA;
89-
pol LIMIT_LT_USED_DA = PREV_GAS_PLUS_USAGE_DA - da_gas_limit - 1;
90-
pol commit limit_used_da_cmp_diff;
91-
// We multiply by sel_should_check_gas to force a 0 if we shouldn't check the gas.
92-
#[DA_CMP_DIFF]
93-
limit_used_da_cmp_diff = sel_should_check_gas * ((LIMIT_LT_USED_DA - LIMIT_GTE_USED_DA) * out_of_gas_da + LIMIT_GTE_USED_DA);
94-
95-
#[LIMIT_USED_DA_RANGE]
96-
sel_should_check_gas { limit_used_da_cmp_diff, constant_64 }
97-
in
98-
range_check.sel { range_check.value, range_check.rng_chk_bits };
62+
pol commit out_of_gas_l2; // Boolean constraint enforced through lookup into gt.
63+
pol commit out_of_gas_da; // Boolean constraint enforced through lookup into gt.
64+
65+
// TODO: Once we support expression in lookup, we can replace this column by an alias.
66+
pol commit total_gas_l2;
67+
total_gas_l2 = prev_l2_gas_used + L2_GAS_USED;
68+
// Assumes l2_gas_limit is 32 bit and total_gas_l2 is 64 bit.
69+
70+
#[IS_OUT_OF_GAS_L2]
71+
sel_should_check_gas { total_gas_l2, l2_gas_limit, out_of_gas_l2 } in gt.sel_gas { gt.input_a, gt.input_b, gt.res };
72+
73+
// TODO: Once we support expression in lookup, we can replace this column by an alias.
74+
pol commit total_gas_da;
75+
total_gas_da = prev_da_gas_used + DA_GAS_USED;
76+
// Assumes da_gas_limit is 32 bit and total_gas_da is 64 bit.
77+
78+
#[IS_OUT_OF_GAS_DA]
79+
sel_should_check_gas { total_gas_da, da_gas_limit, out_of_gas_da } in gt.sel_gas { gt.input_a, gt.input_b, gt.res };
9980

10081
pol commit sel_out_of_gas;
10182
sel_out_of_gas = 1 - (1 - out_of_gas_l2) * (1 - out_of_gas_da);

barretenberg/cpp/pil/vm2/ff_gt.pil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ namespace ff_gt;
4646
pol commit a;
4747
pol commit b;
4848
pol commit result;
49-
(result * (1 - result)) = 0;
49+
result * (1 - result) = 0;
5050

5151
// Should be looked up based on this selector
5252
// This will be off when doing the shifts for the remaning range constraints.

barretenberg/cpp/pil/vm2/gt.pil

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@ namespace gt;
2121
pol commit sel_sha256;
2222
pol commit sel_addressing;
2323
pol commit sel_alu;
24+
pol commit sel_gas;
2425
pol commit sel_others; // Any other lookup into this trace.
2526
sel_sha256 * (1 - sel_sha256) = 0;
2627
sel_addressing * (1 - sel_addressing) = 0;
2728
sel_alu * (1 - sel_alu) = 0;
29+
sel_gas * (1 - sel_gas) = 0;
2830
sel_others * (1 - sel_others) = 0;
2931
// If any of the above selectors is 1, then sel must be 1.
30-
(sel_sha256 + sel_addressing + sel_alu + sel_others) * (1 - sel) = 0;
32+
(sel_sha256 + sel_addressing + sel_alu + sel_gas + sel_others) * (1 - sel) = 0;
3133

3234
#[skippable_if]
3335
sel = 0;

barretenberg/cpp/pil/vm2/opcodes/external_call.pil

Lines changed: 19 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,55 +8,39 @@ namespace execution;
88
#[skippable_if]
99
sel_enter_call = 0;
1010

11-
// TODO: Remove this as a column when we can lookup with constants
12-
pol commit constant_32;
13-
sel_enter_call * (32 - constant_32) = 0;
14-
1511
// ==== GAS CLAMPING ====
1612
// Guaranteed not to wrap since we never put a gas used > gas limit
17-
pol L2_GAS_LEFT = l2_gas_limit - l2_gas_used;
18-
pol DA_GAS_LEFT = da_gas_limit - da_gas_used;
13+
14+
// TODO: Once we support expression in lookup, we can replace this column by an alias.
15+
pol commit l2_gas_left;
16+
l2_gas_left = sel_enter_call * (l2_gas_limit - l2_gas_used);
17+
18+
// TODO: Once we support expression in lookup, we can replace this column by an alias.
19+
pol commit da_gas_left;
20+
da_gas_left = sel_enter_call * (da_gas_limit - da_gas_used);
21+
1922

2023
// L2 gas clamping
2124

2225
// Compare the gas allocated to the call by the user, with the gas left.
2326
// Helper column containing whether the allocated gas is less than the left gas
24-
pol commit call_is_l2_gas_allocated_lt_left;
25-
call_is_l2_gas_allocated_lt_left * (1 - call_is_l2_gas_allocated_lt_left) = 0;
27+
pol commit call_is_l2_gas_allocated_lt_left; // Guaranteed to be boolean through the gt lookup. (provided that sel_enter_call == 1)
2628

29+
#[CALL_IS_L2_GAS_ALLOCATED_LT_LEFT]
30+
sel_enter_call { l2_gas_left, register[0], call_is_l2_gas_allocated_lt_left } in gt.sel_others { gt.input_a, gt.input_b, gt.res };
2731

28-
pol ALLOCATED_GTE_LEFT_L2 = register[0] - L2_GAS_LEFT;
29-
pol ALLOCATED_LT_LEFT_L2 = L2_GAS_LEFT - register[0] - 1;
30-
pol commit call_allocated_left_l2_cmp_diff;
31-
sel_enter_call * ((ALLOCATED_LT_LEFT_L2 - ALLOCATED_GTE_LEFT_L2) * call_is_l2_gas_allocated_lt_left + ALLOCATED_GTE_LEFT_L2 - call_allocated_left_l2_cmp_diff) = 0;
32+
// next row's l2_gas_limit = if call_is_l2_gas_allocated_lt_left { register[0] } else { l2_gas_left }
33+
sel_enter_call * ((register[0] - l2_gas_left) * call_is_l2_gas_allocated_lt_left + l2_gas_left - l2_gas_limit') = 0;
3234

33-
#[CALL_ALLOCATED_LEFT_L2_RANGE]
34-
sel_enter_call { call_allocated_left_l2_cmp_diff, constant_32 }
35-
in
36-
range_check.sel
37-
{ range_check.value, range_check.rng_chk_bits };
38-
39-
// next row's l2_gas_limit = if call_is_l2_gas_allocated_lt_left { register[0] } else { L2_GAS_LEFT }
40-
sel_enter_call * ((register[0] - L2_GAS_LEFT) * call_is_l2_gas_allocated_lt_left + L2_GAS_LEFT - l2_gas_limit') = 0;
4135

4236
// DA gas clamping
4337

4438
// Compare the gas allocated to the call by the user, with the gas left.
4539
// Helper column containing whether the allocated gas is less than the left gas
46-
pol commit call_is_da_gas_allocated_lt_left;
47-
call_is_da_gas_allocated_lt_left * (1 - call_is_da_gas_allocated_lt_left) = 0;
48-
49-
pol ALLOCATED_GTE_LEFT_DA = register[1] - DA_GAS_LEFT;
50-
pol ALLOCATED_LT_LEFT_DA = DA_GAS_LEFT - register[1] - 1;
51-
pol commit call_allocated_left_da_cmp_diff;
52-
sel_enter_call * ((ALLOCATED_LT_LEFT_DA - ALLOCATED_GTE_LEFT_DA) * call_is_da_gas_allocated_lt_left + ALLOCATED_GTE_LEFT_DA - call_allocated_left_da_cmp_diff) = 0;
53-
54-
#[CALL_ALLOCATED_LEFT_DA_RANGE]
55-
sel_enter_call { call_allocated_left_da_cmp_diff, constant_32 }
56-
in
57-
range_check.sel
58-
{ range_check.value, range_check.rng_chk_bits };
40+
pol commit call_is_da_gas_allocated_lt_left; // Guaranteed to be boolean through the gt lookup. (provided that sel_enter_call == 1)
5941

60-
// next row's da_gas_limit = if call_is_da_gas_allocated_lt_left { reg2 } else { DA_GAS_LEFT }
61-
sel_enter_call * ((register[1] - DA_GAS_LEFT) * call_is_da_gas_allocated_lt_left + DA_GAS_LEFT - da_gas_limit') = 0;
42+
#[CALL_IS_DA_GAS_ALLOCATED_LT_LEFT]
43+
sel_enter_call { da_gas_left, register[1], call_is_da_gas_allocated_lt_left } in gt.sel_others { gt.input_a, gt.input_b, gt.res };
6244

45+
// next row's da_gas_limit = if call_is_da_gas_allocated_lt_left { register[1] } else { da_gas_left }
46+
sel_enter_call * ((register[1] - da_gas_left) * call_is_da_gas_allocated_lt_left + da_gas_left - da_gas_limit') = 0;

barretenberg/cpp/src/barretenberg/vm2/common/instruction_spec.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212
namespace bb::avm2 {
1313

1414
constexpr size_t NUM_OP_DC_SELECTORS = 18;
15+
constexpr uint32_t DECOMPOSE_WINDOW_SIZE = 37; // Max size of instruction in bytes.
16+
// We do not use a static constant to compute this value from WIRE_INSTRUCTION_SPEC
17+
// because we do not want it to be changed transparently. Namely, if this constant
18+
// is changed, we need to make significant changes in pil/vm2/bytecode/bc_decomposition.pil
19+
// and pil/vm2/bytecode/instr_fetching.pil.
20+
// We rely on the unit test InstructionSpecTest.CheckDecomposeWindowSize to detect if this constant is changed.
1521

1622
struct ExecInstructionSpec {
1723
struct GasInfo {

barretenberg/cpp/src/barretenberg/vm2/common/instruction_spec.test.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,19 @@ TEST(InstructionSpecTest, CheckAllInstructionsTagInformation)
6060
}
6161
}
6262

63+
// Compute the maximum size of instruction in bytes and enforces it to be equal to DECOMPOSE_WINDOW_SIZE.
64+
TEST(InstructionSpecTest, CheckDecomposeWindowSize)
65+
{
66+
// We cannot use a static assert in the code as MAX_INSTRUCTION_SIZE is not a constexpr.
67+
static const uint32_t MAX_INSTRUCTION_SIZE =
68+
std::ranges::max_element(
69+
WIRE_INSTRUCTION_SPEC.begin(),
70+
WIRE_INSTRUCTION_SPEC.end(),
71+
[](const auto& a, const auto& b) { return a.second.size_in_bytes < b.second.size_in_bytes; })
72+
->second.size_in_bytes;
73+
74+
EXPECT_EQ(DECOMPOSE_WINDOW_SIZE, MAX_INSTRUCTION_SIZE);
75+
}
76+
6377
} // namespace
6478
} // namespace bb::avm2

barretenberg/cpp/src/barretenberg/vm2/constraining/relations/addressing.test.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
#include <cstdint>
55

6-
#include "barretenberg/common/serialize.hpp"
76
#include "barretenberg/vm2/common/memory_types.hpp"
87
#include "barretenberg/vm2/constraining/flavor_settings.hpp"
98
#include "barretenberg/vm2/constraining/testing/check_relation.hpp"

0 commit comments

Comments
 (0)