66static_assert(
sizeof(
VMSettings) == 4,
"VMSettings must be exactly 4 bytes");
152 static constexpr bool LARGE_MODULUS = (Field::modulus.data[3] >= 0x4000000000000000ULL);
160 if constexpr (
requires { Field::primitive_root_log_size(); }) {
162 return Field::primitive_root_log_size() >= 6;
267 auto get_index = [&](
const unsigned char* data_ptr_index,
size_t offset) ->
size_t {
272 constexpr size_t NUM_INSTRUCTIONS =
274 uint8_t original_instruction = *data_ptr;
277 const char* instruction_names[] = {
"SET_VALUE",
"ADD",
"ADD_ASSIGN",
278 "INCREMENT",
"MUL",
"MUL_ASSIGN",
279 "SUB",
"SUB_ASSIGN",
"DIV",
280 "DIV_ASSIGN",
"INV",
"NEG",
281 "SQR",
"SQR_ASSIGN",
"POW",
282 "SQRT",
"IS_ZERO",
"EQUAL",
283 "NOT_EQUAL",
"TO_MONTGOMERY",
"FROM_MONTGOMERY",
284 "REDUCE_ONCE",
"SELF_REDUCE",
"BATCH_INVERT" };
285 const char* instruction_name =
288 static_cast<int>(
sizeof(instruction_names) /
sizeof(instruction_names[0])))
291 std::cout <<
"Executing instruction: " << instruction_name <<
" (" <<
static_cast<int>(
instruction)
304 for (
size_t i = 0; i < 4; i++) {
305 limbs[i] = *
reinterpret_cast<const uint64_t*
>(data_ptr_value +
offset + i * 8);
317 auto get_uint64 = [&](
const unsigned char* data_ptr_value,
size_t offset) -> uint64_t {
318 return *
reinterpret_cast<const uint64_t*
>(data_ptr_value +
offset);
333 info(
"SET_VALUE: index: ", index,
" value: ",
value);
356 info(
"ADD: index1: ",
426 info(
"MUL: index1: ",
476 info(
"SUB: index1: ",
531 info(
"DIV: index1: ",
557 static_cast<uint512_t>(Field::modulus) ==
565 info(
"DIV_ASSIGN: index1: ",
591 static_cast<uint512_t>(Field::modulus) ==
600 info(
"INV: index1: ",
693 auto current =
static_cast<uint512_t>(1);
694 while (exponent > 0) {
696 current = (current * multiplicand) %
static_cast<uint512_t>(Field::modulus);
698 multiplicand = (multiplicand * multiplicand) %
static_cast<uint512_t>(Field::modulus);
703 info(
"POW: index1: ",
729 static_cast<uint512_t>(Field::modulus)) ==
734 info(
"SQRT: index1: ",
770 info(
"EQUAL: index1: ",
790 info(
"NOT_EQUAL: index1: ",
813 info(
"TO_MONTGOMERY: index1: ",
834 for (
size_t i = 0; i < 256; i++) {
844 for (
size_t i = 0; i < 256; i++) {
852 info(
"FROM_MONTGOMERY: index1: ",
873 "REDUCE_ONCE: index1: ", index1,
" index2: ", index2,
" value: ",
field_internal_state[index2]);
909 std::vector<size_t> valid_indices;
911 for (
size_t i = 0; i < count; i++) {
912 size_t idx = start_index + i;
915 valid_indices.push_back(idx);
921 for (
size_t idx : valid_indices) {
924 individual_inverses.push_back(inv);
927 individual_inverses.push_back(Field::zero());
934 std::vector<size_t> non_zero_indices;
935 for (
size_t i = 0; i < count; i++) {
936 size_t idx = start_index + i;
939 non_zero_indices.push_back(idx);
943 if (!non_zero_elements.empty()) {
945 Field::batch_invert(non_zero_elements);
948 for (
size_t i = 0; i < non_zero_indices.size(); i++) {
949 size_t idx = non_zero_indices[i];
956 for (
size_t i = 0; i < valid_indices.size(); i++) {
957 size_t idx = valid_indices[i];
958 if (!original_elements[i].is_zero()) {
965 assert(product == Field::one());
968 auto uint_product = (
static_cast<uint512_t>(original_uint_elements[i]) *
971 assert(uint_product ==
static_cast<uint512_t>(1));
980 info(
"BATCH_INVERT: start_index: ",
985 non_zero_elements.size());
1021 size_t data_offset = 0;
1022 size_t steps_parsed = 0;
1031 while (data_offset < Size && steps_parsed <
max_steps) {
1032 if (data_offset >= Size) {
1037 size_t instruction_size = 0;
1040 constexpr size_t NUM_INSTRUCTIONS =
1042 uint8_t original_instruction = Data[data_offset];
1122 if (data_offset + instruction_size > Size) {
1129 parsed.
size = instruction_size;
1130 parsed.
data.resize(instruction_size);
1133 size_t data_to_copy = std::min(instruction_size, Size - data_offset);
1137 if (data_to_copy < instruction_size) {
1138 std::memset(parsed.
data.data() + data_to_copy, 0, instruction_size - data_to_copy);
1141 instructions.push_back(parsed);
1143 data_offset += instruction_size;
1147 return { instructions, data_offset };
1162 const char* instruction_names[] = {
"SET_VALUE",
"ADD",
"ADD_ASSIGN",
1163 "INCREMENT",
"MUL",
"MUL_ASSIGN",
1164 "SUB",
"SUB_ASSIGN",
"DIV",
1165 "DIV_ASSIGN",
"INV",
"NEG",
1166 "SQR",
"SQR_ASSIGN",
"POW",
1167 "SQRT",
"IS_ZERO",
"EQUAL",
1168 "NOT_EQUAL",
"TO_MONTGOMERY",
"FROM_MONTGOMERY",
1169 "REDUCE_ONCE",
"SELF_REDUCE",
"BATCH_INVERT" };
1170 const char* instruction_name =
1173 static_cast<int>(
sizeof(instruction_names) /
sizeof(instruction_names[0])))
1174 ? instruction_names[
static_cast<int>(parsed.
instruction)]
1176 std::cout <<
"Executing instruction: " << instruction_name <<
" (" <<
static_cast<int>(parsed.
instruction)
1182 return consumed > 0;
1197 size_t run(
const unsigned char* Data,
size_t Size,
bool reset_steps =
true)
1211 std::cout <<
"Parsed " << instructions.size() <<
" instructions, consumed " << bytes_consumed <<
" bytes"
1228 return bytes_consumed;
1326 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.