52static constexpr size_t NUM_FIELD_TYPES = 2;
53static constexpr size_t MAX_STEPS = 64;
54static constexpr size_t PHASE_HEADER_SIZE = 2;
60static_assert(
sizeof(
VMPhaseHeader) == 2,
"VMPhaseHeader must be 2 bytes");
67template <
typename Field>
82template <
typename Field>
static Field raw_to_montgomery(
const uint256_t& raw)
85 f.self_to_montgomery_form();
89static void print_limbs(
const char* label,
const uint256_t& v)
92 " %s = 0x%016lx%016lx%016lx%016lx\n",
94 (
unsigned long)v.
data[3],
95 (
unsigned long)v.
data[2],
96 (
unsigned long)v.
data[1],
97 (
unsigned long)v.
data[0]);
100template <
typename Field>
static void differential_check_inverse(
const Field& a_mont,
const uint256_t& a_raw)
109 Field fermat_inv = a_mont.pow(Field::modulus_minus_two);
114 constexpr uint256_t p_uint = Field::modulus;
115 constexpr uint64_t p_inv_native =
119 uint256_t native_inv_raw = bernstein_yang::invert_vartime<bernstein_yang::Native5x64>(a_raw, p_uint, p_inv_native);
120 uint256_t wasm_inv_raw = bernstein_yang::invert_vartime<bernstein_yang::Wasm9x29>(a_raw, p_uint, p_inv_wasm);
122 Field native_inv = raw_to_montgomery<Field>(native_inv_raw);
123 Field wasm_inv = raw_to_montgomery<Field>(wasm_inv_raw);
125 const bool native_ok = (fermat_inv == native_inv);
126 const bool wasm_ok = (fermat_inv == wasm_inv);
127 if (native_ok && wasm_ok) {
131 std::fprintf(stderr,
"\n[invert_differential.fuzzer] MISMATCH\n");
132 std::fprintf(stderr,
" field: %s\n",
typeid(Field).name());
133 std::fprintf(stderr,
" native_ok: %s\n", native_ok ?
"yes" :
"NO");
134 std::fprintf(stderr,
" wasm_ok: %s\n", wasm_ok ?
"yes" :
"NO");
135 print_limbs(
"a_raw ", a_raw);
136 print_limbs(
"fermat ",
static_cast<uint256_t>(fermat_inv));
137 print_limbs(
"BY native ",
static_cast<uint256_t>(native_inv));
138 print_limbs(
"BY wasm ",
static_cast<uint256_t>(wasm_inv));
139 print_limbs(
"a*fermat ",
static_cast<uint256_t>(a_mont * fermat_inv));
140 print_limbs(
"a*native ",
static_cast<uint256_t>(a_mont * native_inv));
141 print_limbs(
"a*wasm ",
static_cast<uint256_t>(a_mont * wasm_inv));
150 for (
size_t i = state.size(); i > 0; --i) {
158template <
typename Field>
160 const unsigned char*
data,
166 if (!current_state.empty()) {
167 import_state_with_reduction<Field>(vm, current_state);
170 size_t bytes_consumed = vm.
run(
data + data_offset, size - data_offset,
true);
171 if (bytes_consumed == 0) {
178 std::fprintf(stderr,
"[invert_differential.fuzzer] VM internal state check failed\n");
185 size_t last_idx = last_element_index(uint_state);
190 for (
size_t i = 0; i < uint_state.size(); ++i) {
191 if (i != last_idx && uint_state[i] !=
uint256_t(0)) {
196 current_state = uint_state;
197 data_offset += bytes_consumed;
203 if (size < PHASE_HEADER_SIZE) {
208 size_t data_offset = 0;
210 while (data_offset + PHASE_HEADER_SIZE <= size) {
215 uint8_t selected_steps = header.
steps % MAX_STEPS;
216 if (selected_steps == 0) {
219 header.
field_type =
static_cast<uint8_t
>(selected_field_type);
220 header.
steps = selected_steps;
223 switch (selected_field_type) {
225 r = run_phase_and_diff<fq>(header,
data, size, data_offset, current_state);
228 r = run_phase_and_diff<fr>(header,
data, size, data_offset, current_state);
static constexpr u64 p_inv_mod_2k_from_montgomery_r_inv(u64 r_inv) noexcept
static constexpr u64 p_inv_mod_2k_from_montgomery_r_inv(u64 r_inv) noexcept
Field arithmetic fuzzer for testing cryptographic field operations.
int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size)
Entry point for Barretenberg command-line interface.
const size_t INTERNAL_STATE_SIZE
Constant defining the number of elements in the VM's internal state.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
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.
std::array< Field, INTERNAL_STATE_SIZE > field_internal_state
Internal state array of field elements.
bool check_internal_state() const
Check internal state consistency between field and uint256_t representations.