67static_assert(
sizeof(
VMSettings) == 4,
"VMSettings must be exactly 4 bytes");
153 static constexpr bool LARGE_MODULUS = (Field::modulus.data[3] >= MODULUS_TOP_LIMB_LARGE_THRESHOLD);
161 if constexpr (
requires { Field::primitive_root_log_size(); }) {
163 return Field::primitive_root_log_size() >= 6;
268 auto get_index = [&](
const unsigned char* data_ptr_index,
size_t offset) ->
size_t {
273 constexpr size_t NUM_INSTRUCTIONS =
275 uint8_t original_instruction = *data_ptr;
278 const char* instruction_names[] = {
"SET_VALUE",
"ADD",
"ADD_ASSIGN",
279 "INCREMENT",
"MUL",
"MUL_ASSIGN",
280 "SUB",
"SUB_ASSIGN",
"DIV",
281 "DIV_ASSIGN",
"INV",
"NEG",
282 "SQR",
"SQR_ASSIGN",
"POW",
283 "SQRT",
"IS_ZERO",
"EQUAL",
284 "NOT_EQUAL",
"TO_MONTGOMERY",
"FROM_MONTGOMERY",
285 "REDUCE_ONCE",
"SELF_REDUCE",
"BATCH_INVERT" };
286 const char* instruction_name =
289 static_cast<int>(
sizeof(instruction_names) /
sizeof(instruction_names[0])))
292 std::cout <<
"Executing instruction: " << instruction_name <<
" (" <<
static_cast<int>(
instruction)
305 for (
size_t i = 0; i < 4; i++) {
306 limbs[i] = *
reinterpret_cast<const uint64_t*
>(data_ptr_value +
offset + i * 8);
318 auto get_uint64 = [&](
const unsigned char* data_ptr_value,
size_t offset) -> uint64_t {
319 return *
reinterpret_cast<const uint64_t*
>(data_ptr_value +
offset);
357 info(
"ADD: index1: ",
427 info(
"MUL: index1: ",
477 info(
"SUB: index1: ",
532 info(
"DIV: index1: ",
558 static_cast<uint512_t>(Field::modulus) ==
566 info(
"DIV_ASSIGN: index1: ",
592 static_cast<uint512_t>(Field::modulus) ==
601 info(
"INV: index1: ",
694 auto current =
static_cast<uint512_t>(1);
695 while (exponent > 0) {
697 current = (current * multiplicand) %
static_cast<uint512_t>(Field::modulus);
699 multiplicand = (multiplicand * multiplicand) %
static_cast<uint512_t>(Field::modulus);
704 info(
"POW: index1: ",
730 static_cast<uint512_t>(Field::modulus)) ==
735 info(
"SQRT: index1: ",
771 info(
"EQUAL: index1: ",
791 info(
"NOT_EQUAL: index1: ",
814 info(
"TO_MONTGOMERY: index1: ",
835 for (
size_t i = 0; i < 256; i++) {
845 for (
size_t i = 0; i < 256; i++) {
853 info(
"FROM_MONTGOMERY: index1: ",
874 "REDUCE_ONCE: index1: ", index1,
" index2: ", index2,
" value: ",
field_internal_state[index2]);
910 std::vector<size_t> valid_indices;
912 for (
size_t i = 0; i < count; i++) {
913 size_t idx = start_index + i;
916 valid_indices.push_back(idx);
922 for (
size_t idx : valid_indices) {
925 individual_inverses.push_back(inv);
928 individual_inverses.push_back(Field::zero());
935 std::vector<size_t> non_zero_indices;
936 for (
size_t i = 0; i < count; i++) {
937 size_t idx = start_index + i;
940 non_zero_indices.push_back(idx);
944 if (!non_zero_elements.empty()) {
946 Field::batch_invert(non_zero_elements);
949 for (
size_t i = 0; i < non_zero_indices.size(); i++) {
950 size_t idx = non_zero_indices[i];
957 for (
size_t i = 0; i < valid_indices.size(); i++) {
958 size_t idx = valid_indices[i];
959 if (!original_elements[i].is_zero()) {
966 assert(product == Field::one());
969 [[maybe_unused]]
auto uint_product = (
static_cast<uint512_t>(original_uint_elements[i]) *
972 assert(uint_product ==
static_cast<uint512_t>(1));
981 info(
"BATCH_INVERT: start_index: ",
986 non_zero_elements.size());
1022 size_t data_offset = 0;
1023 size_t steps_parsed = 0;
1032 while (data_offset < Size && steps_parsed <
max_steps) {
1033 if (data_offset >= Size) {
1038 size_t instruction_size = 0;
1041 constexpr size_t NUM_INSTRUCTIONS =
1043 uint8_t original_instruction = Data[data_offset];
1123 if (data_offset + instruction_size > Size) {
1130 parsed.
size = instruction_size;
1131 parsed.
data.resize(instruction_size);
1134 size_t data_to_copy = std::min(instruction_size, Size - data_offset);
1138 if (data_to_copy < instruction_size) {
1139 std::memset(parsed.
data.data() + data_to_copy, 0, instruction_size - data_to_copy);
1142 instructions.push_back(parsed);
1144 data_offset += instruction_size;
1148 return { instructions, data_offset };
1163 const char* instruction_names[] = {
"SET_VALUE",
"ADD",
"ADD_ASSIGN",
1164 "INCREMENT",
"MUL",
"MUL_ASSIGN",
1165 "SUB",
"SUB_ASSIGN",
"DIV",
1166 "DIV_ASSIGN",
"INV",
"NEG",
1167 "SQR",
"SQR_ASSIGN",
"POW",
1168 "SQRT",
"IS_ZERO",
"EQUAL",
1169 "NOT_EQUAL",
"TO_MONTGOMERY",
"FROM_MONTGOMERY",
1170 "REDUCE_ONCE",
"SELF_REDUCE",
"BATCH_INVERT" };
1171 const char* instruction_name =
1174 static_cast<int>(
sizeof(instruction_names) /
sizeof(instruction_names[0])))
1175 ? instruction_names[
static_cast<int>(parsed.
instruction)]
1177 std::cout <<
"Executing instruction: " << instruction_name <<
" (" <<
static_cast<int>(parsed.
instruction)
1183 return consumed > 0;
1198 size_t run(
const unsigned char* Data,
size_t Size,
bool reset_steps =
true)
1212 std::cout <<
"Parsed " << instructions.size() <<
" instructions, consumed " << bytes_consumed <<
" bytes"
1229 return bytes_consumed;
1327 return value % Field::modulus;
uint64_t get_index(uint64_t max_index=0)
uintx< uint256_t > uint512_t
Entry point for Barretenberg command-line interface.
const size_t SET_VALUE_SIZE
Size of SET_VALUE instruction.
const size_t MUL_SIZE
Size of MUL instruction.
const size_t SETTINGS_SIZE
const size_t INTERNAL_STATE_SIZE
Constant defining the number of elements in the VM's internal state.
const size_t INCREMENT_SIZE
Size of INCREMENT instruction.
const size_t SQR_ASSIGN_SIZE
Size of SQR_ASSIGN instruction.
const size_t NOT_EQUAL_SIZE
Size of NOT_EQUAL instruction.
const size_t DIV_SIZE
Size of DIV instruction.
const size_t ADD_SIZE
Size of ADD instruction.
const size_t INV_SIZE
Size of INV instruction.
const size_t DIV_ASSIGN_SIZE
Size of DIV_ASSIGN instruction.
Instruction
Enumeration of VM instructions that can be executed.
@ POW
Raise a field element to a power.
@ SQR
Square a field element.
@ TO_MONTGOMERY
Convert to Montgomery form.
@ SUB
Subtract two field elements.
@ FROM_MONTGOMERY
Convert from Montgomery form.
@ DIV
Divide two field elements.
@ INV
Invert a field element.
@ MUL
Multiply two field elements.
@ SQRT
Compute square root of a field element.
@ IS_ZERO
Check if a field element is zero.
@ NOT_EQUAL
Check if two field elements are not equal.
@ REDUCE_ONCE
Reduce a field element once.
@ ADD_ASSIGN
Add-assign operation.
@ DIV_ASSIGN
Divide-assign operation.
@ NEG
Negate a field element.
@ MUL_ASSIGN
Multiply-assign operation.
@ BATCH_INVERT
Batch invert multiple field elements.
@ SET_VALUE
Set a field element to a specific value.
@ INCREMENT
Increment a field element by 1.
@ EQUAL
Check if two field elements are equal.
@ ADD
Add two field elements.
@ SELF_REDUCE
Self-reduce a field element.
@ SUB_ASSIGN
Subtract-assign operation.
@ SQR_ASSIGN
Square-assign operation.
const size_t FROM_MONTGOMERY_SIZE
Size of FROM_MONTGOMERY instruction.
const size_t INSTRUCTION_HEADER_SIZE
Size of instruction header in bytes.
const size_t SELF_REDUCE_SIZE
Size of SELF_REDUCE instruction.
const size_t BATCH_INVERT_SIZE
Size of BATCH_INVERT instruction.
const size_t MUL_ASSIGN_SIZE
Size of MUL_ASSIGN instruction.
const size_t NEG_SIZE
Size of NEG instruction.
const size_t IS_ZERO_SIZE
Size of IS_ZERO instruction.
const size_t EQUAL_SIZE
Size of EQUAL instruction.
const size_t POW_SIZE
Size of POW instruction.
const size_t SUB_SIZE
Size of SUB instruction.
const size_t TO_MONTGOMERY_SIZE
Size of TO_MONTGOMERY instruction.
const size_t REDUCE_ONCE_SIZE
Size of REDUCE_ONCE instruction.
const size_t SQRT_SIZE
Size of SQRT instruction.
const size_t ADD_ASSIGN_SIZE
Size of ADD_ASSIGN instruction.
const size_t INDEX_SIZE
Size of index field in bytes.
const size_t SUB_ASSIGN_SIZE
Size of SUB_ASSIGN instruction.
const size_t SQR_SIZE
Size of SQR instruction.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Structure to hold parsed instruction data.
Instruction instruction
The instruction type.
std::vector< uint8_t > data
The instruction data.
size_t size
The size of the instruction data.
Virtual machine for field arithmetic operations.
size_t run(const unsigned char *Data, size_t Size, bool reset_steps=true)
Run the VM on input data.
std::vector< numeric::uint256_t > export_uint_state() const
Export the final uint state as a vector of uint256_t values.
std::array< numeric::uint256_t, INTERNAL_STATE_SIZE > uint_internal_state
Internal state array of uint256_t values.
void set_max_steps(size_t new_max_steps)
Set a new step limit for the VM.
void reset_step_count()
Reset the step counter to 0.
std::array< Field, INTERNAL_STATE_SIZE > field_internal_state
Internal state array of field elements.
bool with_debug
Flag to enable debug output.
std::pair< std::vector< ParsedInstruction >, size_t > parse_instructions(const unsigned char *Data, size_t Size, size_t max_steps)
Parse instructions from data buffer into a vector.
VMSettings settings
VM settings controlling which operations are enabled.
static numeric::uint256_t reduce_to_modulus(const numeric::uint256_t &value)
Reduce a uint256_t value to the field's modulus.
size_t max_steps
Maximum number of steps the VM can execute.
size_t get_step_count() const
Get the number of steps executed.
bool was_stopped_by_max_steps() const
Check if the VM was stopped due to reaching max steps.
size_t execute_instruction(const unsigned char *data_ptr)
Execute a single VM instruction.
static constexpr bool SUPPORTS_SQRT
Flag indicating if the field supports square root operations.
bool verify_initial_state(const std::vector< numeric::uint256_t > &state) const
Verify that the initial state is correctly loaded.
static constexpr bool LARGE_MODULUS
Flag indicating if the field has a large modulus requiring uint512_t for arithmetic.
size_t step_count
Number of steps executed so far.
FieldVM(bool with_debug=false, size_t max_steps=SIZE_MAX)
Constructor for FieldVM.
bool has_remaining_steps() const
Check if there are remaining steps available.
bool check_internal_state() const
Check internal state consistency between field and uint256_t representations.
bool execute_parsed_instruction(const ParsedInstruction &parsed)
Execute a parsed instruction.
size_t get_max_steps() const
Get the current step limit.
Settings structure to control which operations are enabled in the VM.
bool enable_to_montgomery
Enable TO_MONTGOMERY operations.
bool enable_inv
Enable INV operations.
bool enable_neg
Enable NEG operations.
bool enable_mul_assign
Enable MUL_ASSIGN operations.
uint8_t reserved
Reserved for future use.
bool enable_mul
Enable MUL operations.
bool enable_equal
Enable EQUAL operations.
bool enable_sqr_assign
Enable SQR_ASSIGN operations.
bool enable_self_reduce
Enable SELF_REDUCE operations.
bool enable_batch_invert
Enable BATCH_INVERT operations.
bool enable_div
Enable DIV operations.
bool enable_sub_assign
Enable SUB_ASSIGN operations.
bool enable_set_value
Enable SET_VALUE operations.
bool enable_div_assign
Enable DIV_ASSIGN operations.
bool enable_from_montgomery
Enable FROM_MONTGOMERY operations.
bool enable_add
Enable ADD operations.
bool enable_reduce_once
Enable REDUCE_ONCE operations.
bool enable_not_equal
Enable NOT_EQUAL operations.
bool enable_sqrt
Enable SQRT operations.
bool enable_add_assign
Enable ADD_ASSIGN operations.
bool enable_sub
Enable SUB operations.
bool enable_is_zero
Enable IS_ZERO operations.
bool enable_increment
Enable INCREMENT operations.
bool enable_sqr
Enable SQR operations.
bool enable_pow
Enable POW operations.