diff --git a/.github/workflows/continuous-integration-workflow.yml b/.github/workflows/continuous-integration-workflow.yml index 03924ba6..c8b35249 100644 --- a/.github/workflows/continuous-integration-workflow.yml +++ b/.github/workflows/continuous-integration-workflow.yml @@ -45,6 +45,7 @@ jobs: args: --all env: RUSTFLAGS: -Copt-level=3 -Cdebug-assertions -Coverflow-checks=y -Cdebuginfo=0 -Cprefer-dynamic=y + RUST_LOG: 1 CARGO_INCREMENTAL: 1 RUST_BACKTRACE: 1 diff --git a/Cargo.toml b/Cargo.toml index 5f079d40..dedc8209 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,13 +3,13 @@ members = ["evm", "field", "maybe_rayon", "plonky2", "starky", "util"] [profile.release] opt-level = 3 +incremental = true #lto = "fat" #codegen-units = 1 [profile.bench] opt-level = 3 - [patch.crates-io] plonky2_evm = { path = "evm" } plonky2_field = { path = "field" } diff --git a/evm/Cargo.toml b/evm/Cargo.toml index 45849283..63f4ec0c 100644 --- a/evm/Cargo.toml +++ b/evm/Cargo.toml @@ -13,7 +13,7 @@ edition = "2021" anyhow = "1.0.40" blake2 = "0.10.5" env_logger = "0.10.0" -eth_trie_utils = "0.5.0" +eth_trie_utils = "0.6.0" ethereum-types = "0.14.0" hex = { version = "0.4.3", optional = true } hex-literal = "0.3.4" @@ -36,6 +36,7 @@ serde = { version = "1.0.144", features = ["derive"] } static_assertions = "1.1.0" hashbrown = { version = "0.12.3" } tiny-keccak = "2.0.2" +serde_json = "1.0" [target.'cfg(not(target_env = "msvc"))'.dependencies] jemallocator = "0.5.0" diff --git a/evm/src/cpu/kernel/aggregator.rs b/evm/src/cpu/kernel/aggregator.rs index c529f5cf..32aeb8f6 100644 --- a/evm/src/cpu/kernel/aggregator.rs +++ b/evm/src/cpu/kernel/aggregator.rs @@ -16,6 +16,7 @@ pub(crate) fn combined_kernel() -> Kernel { include_str!("asm/bignum/add.asm"), include_str!("asm/bignum/addmul.asm"), include_str!("asm/bignum/cmp.asm"), + include_str!("asm/bignum/isone.asm"), include_str!("asm/bignum/iszero.asm"), include_str!("asm/bignum/modexp.asm"), include_str!("asm/bignum/modmul.asm"), @@ -54,15 +55,17 @@ pub(crate) fn combined_kernel() -> Kernel { include_str!("asm/curve/bn254/curve_arithmetic/constants.asm"), include_str!("asm/curve/bn254/curve_arithmetic/curve_add.asm"), include_str!("asm/curve/bn254/curve_arithmetic/curve_mul.asm"), + include_str!("asm/curve/bn254/curve_arithmetic/final_exponent.asm"), include_str!("asm/curve/bn254/curve_arithmetic/glv.asm"), - include_str!("asm/curve/bn254/curve_arithmetic/invariant_exponent.asm"), + include_str!("asm/curve/bn254/curve_arithmetic/miller_loop.asm"), include_str!("asm/curve/bn254/curve_arithmetic/msm.asm"), + include_str!("asm/curve/bn254/curve_arithmetic/pairing.asm"), include_str!("asm/curve/bn254/curve_arithmetic/precomputation.asm"), - include_str!("asm/curve/bn254/curve_arithmetic/tate_pairing.asm"), - include_str!("asm/curve/bn254/field_arithmetic/inverse.asm"), + include_str!("asm/curve/bn254/curve_arithmetic/twisted_curve.asm"), include_str!("asm/curve/bn254/field_arithmetic/degree_6_mul.asm"), include_str!("asm/curve/bn254/field_arithmetic/degree_12_mul.asm"), include_str!("asm/curve/bn254/field_arithmetic/frobenius.asm"), + include_str!("asm/curve/bn254/field_arithmetic/inverse.asm"), include_str!("asm/curve/bn254/field_arithmetic/util.asm"), include_str!("asm/curve/common.asm"), include_str!("asm/curve/secp256k1/curve_add.asm"), @@ -75,14 +78,15 @@ pub(crate) fn combined_kernel() -> Kernel { include_str!("asm/curve/wnaf.asm"), include_str!("asm/exp.asm"), include_str!("asm/halt.asm"), - include_str!("asm/hash/blake2b/addresses.asm"), - include_str!("asm/hash/blake2b/compression.asm"), - include_str!("asm/hash/blake2b/g_functions.asm"), - include_str!("asm/hash/blake2b/hash.asm"), - include_str!("asm/hash/blake2b/iv.asm"), - include_str!("asm/hash/blake2b/main.asm"), - include_str!("asm/hash/blake2b/ops.asm"), - include_str!("asm/hash/blake2b/permutations.asm"), + include_str!("asm/hash/blake2/addresses.asm"), + include_str!("asm/hash/blake2/blake2_f.asm"), + // include_str!("asm/hash/blake2/blake2b.asm"), + // include_str!("asm/hash/blake2/compression.asm"), + include_str!("asm/hash/blake2/g_functions.asm"), + include_str!("asm/hash/blake2/hash.asm"), + include_str!("asm/hash/blake2/iv.asm"), + include_str!("asm/hash/blake2/ops.asm"), + include_str!("asm/hash/blake2/permutations.asm"), include_str!("asm/hash/ripemd/box.asm"), include_str!("asm/hash/ripemd/compression.asm"), include_str!("asm/hash/ripemd/constants.asm"), diff --git a/evm/src/cpu/kernel/asm/bignum/isone.asm b/evm/src/cpu/kernel/asm/bignum/isone.asm new file mode 100644 index 00000000..69b2bfad --- /dev/null +++ b/evm/src/cpu/kernel/asm/bignum/isone.asm @@ -0,0 +1,35 @@ +// Arithmetic on little-endian integers represented with 128-bit limbs. +// All integers must be under a given length bound, and are padded with leading zeroes. + +global isone_bignum: + // stack: len, start_loc, retdest + DUP1 + // stack: len, len, start_loc, retdest + ISZERO + %jumpi(eqzero) + // stack: len, start_loc, retdest + DUP2 + // stack: start_loc, len, start_loc, retdest + %mload_kernel_general + // stack: start_val, len, start_loc, retdest + %eq_const(1) + %jumpi(starts_with_one) + // Does not start with one, so not equal to one. + // stack: len, start_loc, retdest + %stack (vals: 2, retdest) -> (retdest, 0) + JUMP +eqzero: + // Is zero, so not equal to one. + // stack: cur_loc, end_loc, retdest + %stack (vals: 2, retdest) -> (retdest, 0) + // stack: retdest, 0 + JUMP +starts_with_one: + // Starts with one, so check that the remaining limbs are zero. + // stack: len, start_loc, retdest + %decrement + SWAP1 + %increment + SWAP1 + // stack: len-1, start_loc+1, retdest + %jump(iszero_bignum) diff --git a/evm/src/cpu/kernel/asm/bignum/modexp.asm b/evm/src/cpu/kernel/asm/bignum/modexp.asm index a994b12b..f7799cf8 100644 --- a/evm/src/cpu/kernel/asm/bignum/modexp.asm +++ b/evm/src/cpu/kernel/asm/bignum/modexp.asm @@ -8,10 +8,55 @@ // All of scratch_2..scratch_5 must have size 2 * length and be initialized with zeroes. // Also, scratch_2..scratch_5 must be CONSECUTIVE in memory. global modexp_bignum: - // stack: len, b_loc, e_loc, m_loc, out_loc, s1 (=scratch_1), s2, s3, s4, s5, retdest - DUP1 - ISZERO - %jumpi(len_zero) + // Special input cases: + + // (1) Modulus is zero (also covers len=0 case). + PUSH modulus_zero_return + // stack: modulus_zero_return, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest + DUP5 + // stack: m_loc, modulus_zero_return, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest + DUP3 + // stack: len, m_loc, modulus_zero_return, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest + %jump(iszero_bignum) +modulus_zero_return: + // stack: m==0, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest + %jumpi(modulus_zero_or_one) + + // (2) Modulus is one. + PUSH modulus_one_return + // stack: modulus_one_return, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest + DUP5 + // stack: m_loc, modulus_one_return, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest + DUP3 + // stack: len, m_loc, modulus_one_return, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest + %jump(isone_bignum) +modulus_one_return: + // stack: m==1, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest + %jumpi(modulus_zero_or_one) + + // (3) Both b and e are zero. + PUSH b_zero_return + // stack: b_zero_return, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest + DUP3 + // stack: b_loc, b_zero_return, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest + DUP3 + // stack: len, b_loc, b_zero_return, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest + %jump(iszero_bignum) +b_zero_return: + // stack: b==0, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest + PUSH e_zero_return + // stack: e_zero_return, b==0, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest + DUP5 + // stack: e_loc, e_zero_return, b==0, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest + DUP4 + // stack: len, e_loc, e_zero_return, b==0, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest + %jump(iszero_bignum) +e_zero_return: + // stack: e==0, b==0, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest + MUL // logical and + %jumpi(b_and_e_zero) + + // End of special cases. // We store the repeated-squares accumulator x_i in scratch_1, starting with x_0 := b. DUP1 @@ -128,8 +173,18 @@ modexp_iszero_return: // stack: e != 0, len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest %jumpi(modexp_loop) // end of modexp_loop -len_zero: +modulus_zero_or_one: + // If modulus is zero or one, return 0. // stack: len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest %pop10 // stack: retdest JUMP +b_and_e_zero: + // If base and exponent are zero (and modulus > 1), return 1. + // stack: len, b_loc, e_loc, m_loc, out_loc, s1, s2, s3, s4, s5, retdest + PUSH 1 + DUP6 + %mstore_kernel_general + %pop10 + // stack: retdest + JUMP diff --git a/evm/src/cpu/kernel/asm/core/access_lists.asm b/evm/src/cpu/kernel/asm/core/access_lists.asm index 80d96e43..0c5e595e 100644 --- a/evm/src/cpu/kernel/asm/core/access_lists.asm +++ b/evm/src/cpu/kernel/asm/core/access_lists.asm @@ -54,49 +54,55 @@ insert_accessed_addresses_found: %macro insert_accessed_storage_keys - %stack (addr, key) -> (addr, key, %%after) + %stack (addr, key, value) -> (addr, key, value, %%after) %jump(insert_accessed_storage_keys) %%after: // stack: cold_access %endmacro -/// Inserts the storage key into the access list if it is not already present. -/// Return 1 if the storage key was inserted, 0 if it was already present. +/// Inserts the storage key and value into the access list if it is not already present. +/// `value` should be the current storage value at the slot `(addr, key)`. +/// Return `1, original_value` if the storage key was inserted, `0, original_value` if it was already present. global insert_accessed_storage_keys: - // stack: addr, key, retdest + // stack: addr, key, value, retdest %mload_global_metadata(@GLOBAL_METADATA_ACCESSED_STORAGE_KEYS_LEN) - // stack: len, addr, key, retdest + // stack: len, addr, key, value, retdest PUSH 0 insert_accessed_storage_keys_loop: - %stack (i, len, addr, key, retdest) -> (i, len, i, len, addr, key, retdest) + %stack (i, len, addr, key, value, retdest) -> (i, len, i, len, addr, key, value, retdest) EQ %jumpi(insert_storage_key) - // stack: i, len, addr, key, retdest + // stack: i, len, addr, key, value, retdest DUP1 %increment %mload_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS) - // stack: loaded_key, i, len, addr, key, retdest + // stack: loaded_key, i, len, addr, key, value, retdest DUP2 %mload_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS) - // stack: loaded_addr, loaded_key, i, len, addr, key, retdest + // stack: loaded_addr, loaded_key, i, len, addr, key, value, retdest DUP5 EQ - // stack: loaded_addr==addr, loaded_key, i, len, addr, key, retdest + // stack: loaded_addr==addr, loaded_key, i, len, addr, key, value, retdest SWAP1 DUP6 EQ - // stack: loaded_key==key, loaded_addr==addr, i, len, addr, key, retdest + // stack: loaded_key==key, loaded_addr==addr, i, len, addr, key, value, retdest MUL // AND %jumpi(insert_accessed_storage_keys_found) - // stack: i, len, addr, key, retdest - %add_const(2) + // stack: i, len, addr, key, value, retdest + %add_const(3) %jump(insert_accessed_storage_keys_loop) insert_storage_key: - // stack: i, len, addr, key, retdest + // stack: i, len, addr, key, value, retdest DUP1 %increment - %stack (i_plus_1, i, len, addr, key, retdest) -> (i, addr, i_plus_1, key, i_plus_1, retdest) + DUP1 %increment + %stack (i_plus_2, i_plus_1, i, len, addr, key, value) -> (i, addr, i_plus_1, key, i_plus_2, value, i_plus_2, value) %mstore_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS) // Store new address at the end of the array. %mstore_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS) // Store new key after that - // stack: i_plus_1, retdest + %mstore_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS) // Store new value after that + // stack: i_plus_2, value, retdest %increment - %mstore_global_metadata(@GLOBAL_METADATA_ACCESSED_STORAGE_KEYS_LEN) // Store new length in front of the array. - PUSH 1 // Return 1 to indicate that the storage key was inserted. - SWAP1 JUMP + %mstore_global_metadata(@GLOBAL_METADATA_ACCESSED_STORAGE_KEYS_LEN) // Store new length. + %stack (value, retdest) -> (retdest, 1, value) // Return 1 to indicate that the storage key was inserted. + JUMP insert_accessed_storage_keys_found: - %stack (i, len, addr, key, retdest) -> (retdest, 0) // Return 0 to indicate that the storage key was already present. + // stack: i, len, addr, key, value, retdest + %add_const(2) + %mload_kernel(@SEGMENT_ACCESSED_STORAGE_KEYS) + %stack (original_value, len, addr, key, value, retdest) -> (retdest, 0, original_value) // Return 0 to indicate that the storage key was already present. JUMP diff --git a/evm/src/cpu/kernel/asm/core/create.asm b/evm/src/cpu/kernel/asm/core/create.asm index 866e482c..2edd9bbe 100644 --- a/evm/src/cpu/kernel/asm/core/create.asm +++ b/evm/src/cpu/kernel/asm/core/create.asm @@ -5,8 +5,16 @@ // Post stack: address global sys_create: %check_static + + %stack (kexit_info, value, code_offset, code_len) -> (code_len, code_offset, kexit_info, value, code_offset, code_len) + %checked_mem_expansion // stack: kexit_info, value, code_offset, code_len - // TODO: Charge gas. + %charge_gas_const(@GAS_CREATE) + // stack: kexit_info, value, code_offset, code_len + DUP4 + // stack: code_len, kexit_info, value, code_offset, code_len + %check_initcode_size + %stack (kexit_info, value, code_offset, code_len) -> (sys_create_got_address, value, code_offset, code_len, kexit_info) %address @@ -27,8 +35,19 @@ sys_create_got_address: // Post stack: address global sys_create2: %check_static + // stack: kexit_info, value, code_offset, code_len, salt - // TODO: Charge gas. + %stack (kexit_info, value, code_offset, code_len) -> (code_len, code_offset, kexit_info, value, code_offset, code_len) + %checked_mem_expansion + // stack: kexit_info, value, code_offset, code_len, salt + DUP4 %num_bytes_to_num_words + %mul_const(@GAS_KECCAK256WORD) %add_const(@GAS_CREATE) %charge_gas + // stack: kexit_info, value, code_offset, code_len, salt + DUP4 + // stack: code_len, kexit_info, value, code_offset, code_len, salt + %check_initcode_size + + SWAP4 %stack (salt) -> (salt, create_common) // stack: salt, create_common, value, code_offset, code_len, kexit_info @@ -78,7 +97,10 @@ global create_common: GET_CONTEXT // stack: src_ctx, new_ctx, address, value, code_offset, code_len, kexit_info - // Copy the code from txdata to the new context's code segment. + %stack (src_ctx, new_ctx, address, value, code_offset, code_len) -> + (code_len, new_ctx, src_ctx, new_ctx, address, value, code_offset, code_len) + %set_new_ctx_code_size POP + // Copy the code from memory to the new context's code segment. %stack (src_ctx, new_ctx, address, value, code_offset, code_len) -> (new_ctx, @SEGMENT_CODE, 0, // DST src_ctx, @SEGMENT_MAIN_MEMORY, code_offset, // SRC @@ -113,7 +135,38 @@ after_constructor: // stack: success, leftover_gas, new_ctx, address, kexit_info SWAP2 // stack: new_ctx, leftover_gas, success, address, kexit_info - POP // TODO: Ignoring new_ctx for now, but we will need it to store code that was returned, if any. + POP + + + // TODO: Skip blocks below if success is false. + // EIP-3541: Reject new contract code starting with the 0xEF byte + PUSH 0 %mload_current(@SEGMENT_RETURNDATA) %eq_const(0xEF) %jumpi(fault_exception) + + // Charge gas for the code size. + SWAP3 + // stack: kexit_info, success, address, leftover_gas + %returndatasize // Size of the code. + // stack: code_size, kexit_info, success, address, leftover_gas + DUP1 %gt_const(@MAX_CODE_SIZE) + %jumpi(fault_exception) + // stack: code_size, kexit_info, success, address, leftover_gas + %mul_const(@GAS_CODEDEPOSIT) %charge_gas + SWAP3 + + // Store the code hash of the new contract. + GET_CONTEXT + %returndatasize + %stack (size, ctx) -> (ctx, @SEGMENT_RETURNDATA, 0, size) // context, segment, offset, len + KECCAK_GENERAL + // stack: codehash, leftover_gas, success, address, kexit_info + %observe_new_contract + DUP4 + // stack: address, codehash, leftover_gas, success, address, kexit_info + %set_codehash + + // Set the return data size to 0. + %mstore_context_metadata(@CTX_METADATA_RETURNDATA_SIZE, 0) + // stack: leftover_gas, success, address, kexit_info %shl_const(192) // stack: leftover_gas << 192, success, address, kexit_info @@ -123,6 +176,53 @@ after_constructor: // stack: address_if_success, leftover_gas << 192, kexit_info SWAP2 // stack: kexit_info, leftover_gas << 192, address_if_success - ADD + SUB // stack: kexit_info, address_if_success EXIT_KERNEL + +%macro set_codehash + %stack (addr, codehash) -> (addr, codehash, %%after) + %jump(set_codehash) +%%after: + // stack: (empty) +%endmacro + +// Pre stack: addr, codehash, redest +// Post stack: (empty) +// TODO: Should it be copy-on-write (with make_account_copy) instead of mutating the trie? +global set_codehash: + // stack: addr, codehash, retdest + %mpt_read_state_trie + // stack: account_ptr, codehash, retdest + %add_const(3) + // stack: codehash_ptr, codehash, retdest + %mstore_trie_data + // stack: retdest + JUMP + +// Check and charge gas cost for initcode size. See EIP-3860. +// Pre stack: code_size, kexit_info +// Post stack: kexit_info +%macro check_initcode_size + DUP1 %gt_const(@MAX_INITCODE_SIZE) %jumpi(fault_exception) + // stack: code_size, kexit_info + %num_bytes_to_num_words %mul_const(@INITCODE_WORD_COST) + %charge_gas +%endmacro + + +// This should be called whenever a new contract is created. +// It does nothing, but just provides a single hook where code can react to newly created contracts. +// When called, the code corresponding to `codehash` should be stored in the return data. +// Pre stack: codehash, retdest +// Post stack: codehash +global observe_new_contract: + // stack codehash, retdest + SWAP1 JUMP + +%macro observe_new_contract + %stack (codehash) -> (codehash, %%after) + %jump(observe_new_contract) +%%after: + // stack: codehash +%endmacro diff --git a/evm/src/cpu/kernel/asm/core/intrinsic_gas.asm b/evm/src/cpu/kernel/asm/core/intrinsic_gas.asm index 9e8a7f80..87737302 100644 --- a/evm/src/cpu/kernel/asm/core/intrinsic_gas.asm +++ b/evm/src/cpu/kernel/asm/core/intrinsic_gas.asm @@ -45,7 +45,21 @@ count_zeros_finish: // stack: gas_txndata, retdest %is_contract_creation + DUP1 %mul_const(@GAS_TXCREATE) + // stack: gas_creation, is_creation, gas_txndata, retdest + SWAP1 + // stack: is_creation, gas_creation, gas_txndata, retdest + DUP1 + // stack: is_creation, is_creation, gas_creation, gas_txndata, retdest + %mload_txn_field(@TXN_FIELD_DATA_LEN) %gt_const(@MAX_INITCODE_SIZE) + // stack: initcode_size > max, is_creation, is_creation, gas_creation, gas_txndata, retdest + MUL // Cheaper than AND + %assert_zero + // stack: is_creation, gas_creation, gas_txndata, retdest + %mload_txn_field(@TXN_FIELD_DATA_LEN) %num_bytes_to_num_words + // stack: initcode_words, is_creation, gas_creation, gas_txndata, retdest + %mul_const(@INITCODE_WORD_COST) MUL ADD // stack: gas_creation, gas_txndata, retdest PUSH @GAS_TRANSACTION diff --git a/evm/src/cpu/kernel/asm/core/precompiles/blake2_f.asm b/evm/src/cpu/kernel/asm/core/precompiles/blake2_f.asm index a10c9ba2..d5971a81 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/blake2_f.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/blake2_f.asm @@ -1,3 +1,136 @@ global precompile_blake2_f: - // TODO - PANIC + // stack: retdest, new_ctx, (old stack) + POP + // stack: new_ctx, (old stack) + DUP1 + SET_CONTEXT + // stack: (empty) + PUSH 0x100000000 // = 2^32 (is_kernel = true) + // stack: kexit_info + + PUSH blake2_f_contd + // stack: blake2_f_contd, kexit_info + + // Load inputs from calldata memory into stack. + + %calldatasize + // stack: calldatasize, blake2_f_contd, kexit_info + DUP1 + // stack: calldatasize, calldatasize, blake2_f_contd, kexit_info + %eq_const(213) ISZERO %jumpi(fault_exception) + // stack: calldatasize, blake2_f_contd, kexit_info + %decrement + // stack: flag_addr=212, blake2_f_contd, kexit_info + DUP1 + // stack: flag_addr, flag_addr, blake2_f_contd, kexit_info + PUSH @SEGMENT_CALLDATA + GET_CONTEXT + // stack: ctx, @SEGMENT_CALLDATA, flag_addr, flag_addr, blake2_f_contd, kexit_info + MLOAD_GENERAL + // stack: flag, flag_addr, blake2_f_contd, kexit_info + DUP1 + // stack: flag, flag, flag_addr, blake2_f_contd, kexit_info + %gt_const(1) %jumpi(fault_exception) // Check flag < 2 (flag = 0 or flag = 1) + // stack: flag, flag_addr, blake2_f_contd, kexit_info + SWAP1 + // stack: flag_addr, flag, blake2_f_contd, kexit_info + %sub_const(8) + // stack: t1_addr=flag_addr-8, flag, blake2_f_contd, kexit_info + + %stack (t1_addr) -> (@SEGMENT_CALLDATA, t1_addr, 8, t1_addr) + // stack: @SEGMENT_CALLDATA, t1_addr, 8, t1_addr, flag, blake2_f_contd, kexit_info + GET_CONTEXT + // stack: ctx, @SEGMENT_CALLDATA, t1_addr, 8, t1_addr, flag, blake2_f_contd, kexit_info + %mload_packing + // stack: t_1, t1_addr, flag, blake2_f_contd, kexit_info + SWAP1 + // stack: t1_addr, t_1, flag, blake2_f_contd, kexit_info + %sub_const(8) + // stack: t0_addr=t1_addr-8, t_1, flag, blake2_f_contd, kexit_info + + %stack (t0_addr) -> (@SEGMENT_CALLDATA, t0_addr, 8, t0_addr) + // stack: @SEGMENT_CALLDATA, t0_addr, 8, t0_addr, t_1, flag, blake2_f_contd, kexit_info + GET_CONTEXT + // stack: ctx, @SEGMENT_CALLDATA, t0_addr, 8, t0_addr, t_1, flag, blake2_f_contd, kexit_info + %mload_packing + // stack: t_0, t0_addr, t_1, flag, blake2_f_contd, kexit_info + SWAP1 + // stack: t0_addr, t_0, t_1, flag, blake2_f_contd, kexit_info + %sub_const(128) // 16 * 8 + // stack: m0_addr=t0_addr-128, t_0, t_1, flag, blake2_f_contd, kexit_info + + %rep 16 + // stack: 68 + 8 * i, m_(i-1), ..., m_0, t_0, t_1, flag, blake2_f_contd, kexit_info + PUSH 8 + // stack: 8, 68 + 8 * i, m_(i-1), ..., m_0, t_0, t_1, flag, blake2_f_contd, kexit_info + DUP2 + // stack: 68 + 8 * i, 8, 68 + 8 * i, m_(i-1), ..., m_0, t_0, t_1, flag, blake2_f_contd, kexit_info + PUSH @SEGMENT_CALLDATA + // stack: @SEGMENT_CALLDATA, 68 + 8 * i, 8, 68 + 8 * i, m_(i-1), ..., m_0, t_0, t_1, flag, blake2_f_contd, kexit_info + GET_CONTEXT + // stack: ctx, @SEGMENT_CALLDATA, 68 + 8 * i, 8, 68 + 8 * i, m_(i-1), ..., m_0, t_0, t_1, flag, blake2_f_contd, kexit_info + %mload_packing + // stack: m_i, 68 + 8 * i, m_(i-1), ..., m_0, t_0, t_1, flag, blake2_f_contd, kexit_info + SWAP1 + // stack: 68 + 8 * i, m_i, m_(i-1), ..., m_0, t_0, t_1, flag, blake2_f_contd, kexit_info + %add_const(8) + %endrep + // stack: 68 + 8 * 16 = 196, m_15, ..., m_0, t_0, t_1, flag, blake2_f_contd, kexit_info + %sub_const(192) // 16 * 8 (m values) + 8 * 8 (h values) + // stack: h0_addr, m_15, ..., m_0, t_0, t_1, flag, blake2_f_contd, kexit_info + + %rep 8 + // stack: 4 + 8 * i, h_(i-1), ..., h_0, m_15..m_0, t_0, t_1, flag, blake2_f_contd, kexit_info + PUSH 8 + // stack: 8, 4 + 8 * i, h_(i-1), ..., h_0, m_15..m_0, t_0, t_1, flag, blake2_f_contd, kexit_info + DUP2 + // stack: 4 + 8 * i, 8, 4 + 8 * i, h_(i-1), ..., h_0, m_15..m_0, t_0, t_1, flag, blake2_f_contd, kexit_info + PUSH @SEGMENT_CALLDATA + // stack: @SEGMENT_CALLDATA, 4 + 8 * i, 8, 4 + 8 * i, h_(i-1), ..., h_0, m_15..m_0, t_0, t_1, flag, blake2_f_contd, kexit_info + GET_CONTEXT + // stack: ctx, @SEGMENT_CALLDATA, 4 + 8 * i, 8, 4 + 8 * i, h_(i-1), ..., h_0, m_15..m_0, t_0, t_1, flag, blake2_f_contd, kexit_info + %mload_packing + // stack: h_i, 4 + 8 * i, h_(i-1), ..., h_0, m_15..m_0, t_0, t_1, flag, blake2_f_contd, kexit_info + SWAP1 + // stack: 4 + 8 * i, h_i, h_(i-1), ..., h_0, m_15..m_0, t_0, t_1, flag, blake2_f_contd, kexit_info + %add_const(8) + %endrep + // stack: 4 + 8 * 8 = 68, h_7, ..., h_0, m_15..m_0, t_0, t_1, flag, blake2_f_contd, kexit_info + POP + + %stack () -> (@SEGMENT_CALLDATA, 0, 4) + GET_CONTEXT + // stack: ctx, @SEGMENT_CALLDATA, 0, 4, h_7..h_0, m_15..m_0, t_0, t_1, flag, blake2_f_contd, kexit_info + %mload_packing + // stack: rounds, h_7..h_0, m_15..m_0, t_0, t_1, flag, blake2_f_contd, kexit_info + + DUP1 + // stack: rounds, rounds, h_7..h_0, m_15..m_0, t_0, t_1, flag, blake2_f_contd, kexit_info + %charge_gas + + // stack: rounds, h_7..h_0, m_15..m_0, t_0, t_1, flag, blake2_f_contd, kexit_info + %jump(blake2_f) +blake2_f_contd: + // stack: h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7', kexit_info + // Store the result hash to the parent's return data using `mstore_unpacking`. + + %mstore_parent_context_metadata(@CTX_METADATA_RETURNDATA_SIZE, 32) + PUSH 0 + // stack: addr_0=0, h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7', kexit_info + %mload_context_metadata(@CTX_METADATA_PARENT_CONTEXT) + // stack: parent_ctx, addr_0=0, h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7', kexit_info + + %rep 8 + // stack: parent_ctx, addr_i, h_i', ..., h_7', kexit_info + %stack (ctx, addr, h_i) -> (ctx, @SEGMENT_RETURNDATA, addr, h_i, 4, addr, ctx) + // stack: parent_ctx, @SEGMENT_RETURNDATA, addr_i, h_i', 4, addr_i, parent_ctx, h_(i+1)', ..., h_7', kexit_info + %mstore_unpacking + // stack: addr_i, parent_ctx, h_(i+1)', ..., h_7', kexit_info + %add_const(4) + // stack: addr_(i+1), parent_ctx, h_(i+1)', ..., h_7', kexit_info + SWAP1 + // stack: parent_ctx, addr_(i+1), h_(i+1)', ..., h_7', kexit_info + %endrep + + // stack: kexit_info + %jump(pop_and_return_success) diff --git a/evm/src/cpu/kernel/asm/core/precompiles/bn_add.asm b/evm/src/cpu/kernel/asm/core/precompiles/bn_add.asm index ca8bbb5a..1ab4093c 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/bn_add.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/bn_add.asm @@ -1,7 +1,7 @@ global precompile_bn_add: - // stack: address, retdest, new_ctx, kexit_info, ret_offset, ret_size + // stack: address, retdest, new_ctx, (old stack) %pop2 - // stack: new_ctx, kexit_info, ret_offset, ret_size + // stack: new_ctx, (old stack) DUP1 SET_CONTEXT // stack: (empty) @@ -11,25 +11,30 @@ global precompile_bn_add: %charge_gas_const(@BN_ADD_GAS) // Load x0, y0, x1, y1 from the call data using `mload_packing`. + PUSH bn_add_return + // stack: bn_add_return, kexit_info + %stack () -> (@SEGMENT_CALLDATA, 96, 32) GET_CONTEXT - %stack (ctx, kexit_info) -> (ctx, @SEGMENT_CALLDATA, 96, 32, bn_add_contd, kexit_info) - %jump(mload_packing) -bn_add_contd: + // stack: ctx, @SEGMENT_CALLDATA, 96, 32, bn_add_return, kexit_info + %mload_packing + // stack: y1, bn_add_return, kexit_info + %stack () -> (@SEGMENT_CALLDATA, 64, 32) GET_CONTEXT - %stack (ctx, y1, kexit_info) -> (ctx, @SEGMENT_CALLDATA, 64, 32, bn_add_contd2, y1, kexit_info) - %jump(mload_packing) -bn_add_contd2: + // stack: ctx, @SEGMENT_CALLDATA, 64, 32, y1, bn_add_return, kexit_info + %mload_packing + // stack: x1, y1, bn_add_return, kexit_info + %stack () -> (@SEGMENT_CALLDATA, 32, 32) GET_CONTEXT - %stack (ctx, x1, y1, kexit_info) -> (ctx, @SEGMENT_CALLDATA, 32, 32, bn_add_contd3, x1, y1, kexit_info) - %jump(mload_packing) -bn_add_contd3: + // stack: ctx, @SEGMENT_CALLDATA, 32, 32, x1, y1, bn_add_return, kexit_info + %mload_packing + // stack: y0, x1, y1, bn_add_return, kexit_info + %stack () -> (@SEGMENT_CALLDATA, 0, 32) GET_CONTEXT - %stack (ctx, y0, x1, y1, kexit_info) -> (ctx, @SEGMENT_CALLDATA, 0, 32, bn_add_contd4, y0, x1, y1, kexit_info) - %jump(mload_packing) -bn_add_contd4: - %stack (x0, y0, x1, y1, kexit_info) -> (x0, y0, x1, y1, bn_add_contd5, kexit_info) + // stack: ctx, @SEGMENT_CALLDATA, 0, 32, y0, x1, y1, bn_add_return, kexit_info + %mload_packing + // stack: x0, y0, x1, y1, bn_add_return, kexit_info %jump(bn_add) -bn_add_contd5: +bn_add_return: // stack: x, y, kexit_info DUP2 %eq_const(@U256_MAX) // bn_add returns (U256_MAX, U256_MAX) on bad input. DUP2 %eq_const(@U256_MAX) // bn_add returns (U256_MAX, U256_MAX) on bad input. diff --git a/evm/src/cpu/kernel/asm/core/precompiles/bn_mul.asm b/evm/src/cpu/kernel/asm/core/precompiles/bn_mul.asm index 554849ab..31cbbae0 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/bn_mul.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/bn_mul.asm @@ -1,7 +1,7 @@ global precompile_bn_mul: - // stack: address, retdest, new_ctx, kexit_info, ret_offset, ret_size + // stack: address, retdest, new_ctx, (old stack) %pop2 - // stack: new_ctx, kexit_info, ret_offset, ret_size + // stack: new_ctx, (old stack) DUP1 SET_CONTEXT // stack: (empty) @@ -11,21 +11,25 @@ global precompile_bn_mul: %charge_gas_const(@BN_MUL_GAS) // Load x, y, n from the call data using `mload_packing`. + PUSH bn_mul_return + // stack: bn_mul_return, kexit_info + %stack () -> (@SEGMENT_CALLDATA, 64, 32) GET_CONTEXT - %stack (ctx, kexit_info) -> (ctx, @SEGMENT_CALLDATA, 64, 32, bn_mul_contd, kexit_info) - %jump(mload_packing) -bn_mul_contd: + // stack: ctx, @SEGMENT_CALLDATA, 64, 32, bn_mul_return, kexit_info + %mload_packing + // stack: n, bn_mul_return, kexit_info + %stack () -> (@SEGMENT_CALLDATA, 32, 32) GET_CONTEXT - %stack (ctx, n, kexit_info) -> (ctx, @SEGMENT_CALLDATA, 32, 32, bn_mul_contd2, n, kexit_info) - %jump(mload_packing) -bn_mul_contd2: + // stack: ctx, @SEGMENT_CALLDATA, 32, 32, n, bn_mul_return, kexit_info + %mload_packing + // stack: y, n, bn_mul_return, kexit_info + %stack () -> (@SEGMENT_CALLDATA, 0, 32) GET_CONTEXT - %stack (ctx, y, n, kexit_info) -> (ctx, @SEGMENT_CALLDATA, 0, 32, bn_mul_contd3, y, n, kexit_info) - %jump(mload_packing) -bn_mul_contd3: - %stack (x, y, n, kexit_info) -> (x, y, n, bn_mul_contd4, kexit_info) + // stack: ctx, @SEGMENT_CALLDATA, 0, 32, y, n, bn_mul_return, kexit_info + %mload_packing + // stack: x, y, n, bn_mul_return, kexit_info %jump(bn_mul) -bn_mul_contd4: +bn_mul_return: // stack: Px, Py, kexit_info DUP2 %eq_const(@U256_MAX) // bn_mul returns (U256_MAX, U256_MAX) on bad input. DUP2 %eq_const(@U256_MAX) // bn_mul returns (U256_MAX, U256_MAX) on bad input. diff --git a/evm/src/cpu/kernel/asm/core/precompiles/ecrec.asm b/evm/src/cpu/kernel/asm/core/precompiles/ecrec.asm index e4a03a99..777a9f77 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/ecrec.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/ecrec.asm @@ -1,7 +1,7 @@ global precompile_ecrec: - // stack: address, retdest, new_ctx, kexit_info, ret_offset, ret_size + // stack: address, retdest, new_ctx, (old stack) %pop2 - // stack: new_ctx, kexit_info, ret_offset, ret_size + // stack: new_ctx, (old stack) DUP1 SET_CONTEXT // stack: (empty) @@ -11,25 +11,30 @@ global precompile_ecrec: %charge_gas_const(@ECREC_GAS) // Load hash, v, r, s from the call data using `mload_packing`. + PUSH ecrec_return + // stack: ecrec_return, kexit_info + %stack () -> (@SEGMENT_CALLDATA, 96, 32) GET_CONTEXT - %stack (ctx, kexit_info) -> (ctx, @SEGMENT_CALLDATA, 96, 32, ecrec_contd, kexit_info) - %jump(mload_packing) -ecrec_contd: + // stack: ctx, @SEGMENT_CALLDATA, 96, 32, ecrec_return, kexit_info + %mload_packing + // stack: s, ecrec_return, kexit_info + %stack () -> (@SEGMENT_CALLDATA, 64, 32) GET_CONTEXT - %stack (ctx, s, kexit_info) -> (ctx, @SEGMENT_CALLDATA, 64, 32, ecrec_contd2, s, kexit_info) - %jump(mload_packing) -ecrec_contd2: + // stack: ctx, @SEGMENT_CALLDATA, 64, 32, s, ecrec_return, kexit_info + %mload_packing + // stack: r, s, ecrec_return, kexit_info + %stack () -> (@SEGMENT_CALLDATA, 32, 32) GET_CONTEXT - %stack (ctx, r, s, kexit_info) -> (ctx, @SEGMENT_CALLDATA, 32, 32, ecrec_contd3, r, s, kexit_info) - %jump(mload_packing) -ecrec_contd3: + // stack: ctx, @SEGMENT_CALLDATA, 32, 32, r, s, ecrec_return, kexit_info + %mload_packing + // stack: v, r, s, ecrec_return, kexit_info + %stack () -> (@SEGMENT_CALLDATA, 0, 32) GET_CONTEXT - %stack (ctx, v, r, s, kexit_info) -> (ctx, @SEGMENT_CALLDATA, 0, 32, ecrec_contd4, v, r, s, kexit_info) - %jump(mload_packing) -ecrec_contd4: - %stack (hash, v, r, s, kexit_info) -> (hash, v, r, s, ecrec_contd5, kexit_info) + // stack: ctx, @SEGMENT_CALLDATA, 0, 32, v, r, s, ecrec_return, kexit_info + %mload_packing + // stack: hash, v, r, s, ecrec_return, kexit_info %jump(ecrecover) -ecrec_contd5: +ecrec_return: // stack: address, kexit_info DUP1 %eq_const(@U256_MAX) %jumpi(ecrec_bad_input) // ecrecover returns U256_MAX on bad input. diff --git a/evm/src/cpu/kernel/asm/core/precompiles/id.asm b/evm/src/cpu/kernel/asm/core/precompiles/id.asm index 167d99f5..7cfb6dfc 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/id.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/id.asm @@ -1,7 +1,7 @@ global precompile_id: - // stack: address, retdest, new_ctx, kexit_info, ret_offset, ret_size + // stack: address, retdest, new_ctx, (old stack) %pop2 - // stack: new_ctx, kexit_info, ret_offset, ret_size + // stack: new_ctx, (old stack) DUP1 SET_CONTEXT // stack: (empty) diff --git a/evm/src/cpu/kernel/asm/core/precompiles/main.asm b/evm/src/cpu/kernel/asm/core/precompiles/main.asm index edf53a13..ec33cea8 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/main.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/main.asm @@ -1,16 +1,16 @@ %macro handle_precompiles - // stack: address, new_ctx, kexit_info, ret_offset, ret_size + // stack: address, new_ctx, (old stack) PUSH %%after SWAP1 - // stack: address, %%after, new_ctx, kexit_info, ret_offset, ret_size + // stack: address, %%after, new_ctx, (old stack) %jump(handle_precompiles) %%after: - // stack: new_ctx, kexit_info, ret_offset, ret_size + // stack: new_ctx, (old stack) %pop4 %endmacro global handle_precompiles: - // stack: address, retdest, new_ctx, kexit_info, ret_offset, ret_size + // stack: address, retdest, new_ctx, (old stack) DUP1 %eq_const(@ECREC) %jumpi(precompile_ecrec) DUP1 %eq_const(@SHA256) %jumpi(precompile_sha256) DUP1 %eq_const(@RIP160) %jumpi(precompile_rip160) @@ -31,6 +31,36 @@ global pop_and_return_success: PUSH 1 // success %jump(terminate_common) +%macro handle_precompiles_from_eoa + // stack: retdest + %mload_txn_field(@TXN_FIELD_TO) + // stack: addr, retdest + DUP1 %is_precompile + %jumpi(handle_precompiles_from_eoa) + // stack: addr, retdest + POP +%endmacro + +global handle_precompiles_from_eoa: + // stack: addr, retdest + %create_context + // stack: new_ctx, addr, retdest + %set_new_ctx_parent_pc(process_message_txn_after_call) + %non_intrinisic_gas %set_new_ctx_gas_limit + // stack: new_ctx, addr, retdest + + // Set calldatasize and copy txn data to calldata. + %mload_txn_field(@TXN_FIELD_DATA_LEN) + %stack (calldata_size, new_ctx) -> (calldata_size, new_ctx, calldata_size) + %set_new_ctx_calldata_size + %stack (new_ctx, calldata_size) -> (new_ctx, @SEGMENT_CALLDATA, 0, 0, @SEGMENT_TXN_DATA, 0, calldata_size, handle_precompiles_from_eoa_finish, new_ctx) + %jump(memcpy) + +handle_precompiles_from_eoa_finish: + %stack (new_ctx, addr, retdest) -> (addr, new_ctx, retdest) + %handle_precompiles + PANIC // We already checked that a precompile is called, so this should be unreachable. + %macro zero_out_kernel_general PUSH 0 PUSH 0 %mstore_kernel_general PUSH 0 PUSH 1 %mstore_kernel_general diff --git a/evm/src/cpu/kernel/asm/core/precompiles/rip160.asm b/evm/src/cpu/kernel/asm/core/precompiles/rip160.asm index c7137f9b..70711234 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/rip160.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/rip160.asm @@ -1,7 +1,7 @@ global precompile_rip160: - // stack: address, retdest, new_ctx, kexit_info, ret_offset, ret_size + // stack: address, retdest, new_ctx, (old stack) %pop2 - // stack: new_ctx, kexit_info, ret_offset, ret_size + // stack: new_ctx, (old stack) DUP1 SET_CONTEXT // stack: (empty) @@ -20,13 +20,29 @@ global precompile_rip160: // Copy the call data to the kernel general segment (ripemd expects it there) and call ripemd. %calldatasize GET_CONTEXT - %stack (ctx, size) -> - ( - 0, @SEGMENT_KERNEL_GENERAL, 200, // DST - ctx, @SEGMENT_CALLDATA, 0, // SRC - size, ripemd, // count, retdest - 200, size, rip160_contd // ripemd input: virt, num_bytes, retdest - ) + + // The next block of code is equivalent to the following %stack macro call + // (unfortunately the macro call takes too long to expand dynamically). + // + // %stack (ctx, size) -> + // ( + // 0, @SEGMENT_KERNEL_GENERAL, 200, // DST + // ctx, @SEGMENT_CALLDATA, 0, // SRC + // size, ripemd, // count, retdest + // 200, size, rip160_contd // ripemd input: virt, num_bytes, retdest + // ) + PUSH 200 + PUSH ripemd + DUP4 + PUSH 0 + PUSH @SEGMENT_CALLDATA + PUSH rip160_contd + SWAP7 + SWAP6 + PUSH 200 + PUSH @SEGMENT_KERNEL_GENERAL + PUSH 0 + %jump(memcpy) rip160_contd: diff --git a/evm/src/cpu/kernel/asm/core/precompiles/sha256.asm b/evm/src/cpu/kernel/asm/core/precompiles/sha256.asm index 9bfd544e..e03574a1 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/sha256.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/sha256.asm @@ -1,7 +1,7 @@ global precompile_sha256: - // stack: address, retdest, new_ctx, kexit_info, ret_offset, ret_size + // stack: address, retdest, new_ctx, (old stack) %pop2 - // stack: new_ctx, kexit_info, ret_offset, ret_size + // stack: new_ctx, (old stack) DUP1 SET_CONTEXT // stack: (empty) @@ -23,13 +23,31 @@ global precompile_sha256: // Copy the call data to the kernel general segment (sha2 expects it there) and call sha2. %calldatasize GET_CONTEXT - %stack (ctx, size) -> - ( - 0, @SEGMENT_KERNEL_GENERAL, 1, // DST - ctx, @SEGMENT_CALLDATA, 0, // SRC - size, sha2, // count, retdest - 0, size, sha256_contd // sha2 input: virt, num_bytes, retdest - ) + // stack: ctx, size + + // The next block of code is equivalent to the following %stack macro call + // (unfortunately the macro call takes too long to expand dynamically). + // + // %stack (ctx, size) -> + // ( + // 0, @SEGMENT_KERNEL_GENERAL, 1, // DST + // ctx, @SEGMENT_CALLDATA, 0, // SRC + // size, sha2, // count, retdest + // 0, size, sha256_contd // sha2 input: virt, num_bytes, retdest + // ) + // + PUSH 0 + PUSH sha2 + DUP4 + PUSH 0 + PUSH @SEGMENT_CALLDATA + PUSH sha256_contd + SWAP7 + SWAP6 + PUSH 1 + PUSH @SEGMENT_KERNEL_GENERAL + PUSH 0 + %jump(memcpy) sha256_contd: diff --git a/evm/src/cpu/kernel/asm/core/precompiles/snarkv.asm b/evm/src/cpu/kernel/asm/core/precompiles/snarkv.asm index fbb46670..433186b5 100644 --- a/evm/src/cpu/kernel/asm/core/precompiles/snarkv.asm +++ b/evm/src/cpu/kernel/asm/core/precompiles/snarkv.asm @@ -1,3 +1,118 @@ global precompile_snarkv: - // TODO - PANIC + // stack: address, retdest, new_ctx, (old stack) + %pop2 + // stack: new_ctx, (old stack) + DUP1 + SET_CONTEXT + // stack: (empty) + PUSH 0x100000000 // = 2^32 (is_kernel = true) + // stack: kexit_info + + PUSH 192 %calldatasize DUP2 DUP2 + // stack: calldata_size, 192, calldata_size, 192, kexit_info + MOD %jumpi(fault_exception) // calldata_size should be a multiple of 192 + DIV + // stack: k, kexit_info + DUP1 %mul_const(@SNARKV_DYNAMIC_GAS) %add_const(@SNARKV_STATIC_GAS) + %stack (gas, k, kexit_info) -> (gas, kexit_info, k) + %charge_gas + SWAP1 + // stack: k, kexit_info + PUSH 0 +loading_loop: + // stack: i, k, kexit_info + DUP2 DUP2 EQ %jumpi(loading_done) + // stack: i, k, kexit_info + DUP1 %mul_const(192) + // stack: px, i, k, kexit_info + GET_CONTEXT + %stack (ctx, px) -> (ctx, @SEGMENT_CALLDATA, px, 32, loading_loop_contd, px) + %jump(mload_packing) +loading_loop_contd: + // stack: x, px, i, k, kexit_info + SWAP1 %add_const(32) + GET_CONTEXT + %stack (ctx, py) -> (ctx, @SEGMENT_CALLDATA, py, 32, loading_loop_contd2, py) + %jump(mload_packing) +loading_loop_contd2: + // stack: y, py, x, i, k, kexit_info + SWAP1 %add_const(32) + GET_CONTEXT + %stack (ctx, px_im) -> (ctx, @SEGMENT_CALLDATA, px_im, 32, loading_loop_contd3, px_im) + %jump(mload_packing) +loading_loop_contd3: + // stack: x_im, px_im, y, x, i, k, kexit_info + SWAP1 %add_const(32) + // stack: px_re, x_im, y, x, i, k, kexit_info + GET_CONTEXT + %stack (ctx, px_re) -> (ctx, @SEGMENT_CALLDATA, px_re, 32, loading_loop_contd4, px_re) + %jump(mload_packing) +loading_loop_contd4: + // stack: x_re, px_re, x_im, y, x, i, k, kexit_info + SWAP1 %add_const(32) + // stack: py_im, x_re, x_im, y, x, i, k, kexit_info + GET_CONTEXT + %stack (ctx, py_im) -> (ctx, @SEGMENT_CALLDATA, py_im, 32, loading_loop_contd5, py_im) + %jump(mload_packing) +loading_loop_contd5: + // stack: y_im, py_im, x_re, x_im, y, x, i, k, kexit_info + SWAP1 %add_const(32) + // stack: py_re, y_im, x_re, x_im, y, x, i, k, kexit_info + GET_CONTEXT + %stack (ctx, py_re) -> (ctx, @SEGMENT_CALLDATA, py_re, 32, loading_loop_contd6) + %jump(mload_packing) +loading_loop_contd6: + // stack: y_re, y_im, x_re, x_im, y, x, i, k, kexit_info + SWAP1 // the EVM serializes the imaginary part first + // stack: y_im, y_re, x_re, x_im, y, x, i, k, kexit_info + DUP7 + // stack: i, y_im, y_re, x_re, x_im, y, x, i, k, kexit_info + %mul_const(6) %add_const(@SNARKV_INP) + %add_const(5) + %mstore_kernel_bn254_pairing + // stack: y_re, x_re, x_im, y, x, i, k, kexit_info + DUP6 + // stack: i, y_re, x_re, x_im, y, x, i, k, kexit_info + %mul_const(6) %add_const(@SNARKV_INP) + %add_const(4) + %mstore_kernel_bn254_pairing + SWAP1 // the EVM serializes the imaginary part first + // stack: x_im, x_re, y, x, i, k, kexit_info + DUP5 + // stack: i, x_im, x_re, y, x, i, k, kexit_info + %mul_const(6) %add_const(@SNARKV_INP) + %add_const(3) + %mstore_kernel_bn254_pairing + // stack: x_re, y, x, i, k, kexit_info + DUP4 + // stack: i, x_re, y, x, i, k, kexit_info + %mul_const(6) %add_const(@SNARKV_INP) + %add_const(2) + %mstore_kernel_bn254_pairing + // stack: y, x, i, k, kexit_info + DUP3 + // stack: i, y, x, i, k, kexit_info + %mul_const(6) %add_const(@SNARKV_INP) + %add_const(1) + %mstore_kernel_bn254_pairing + // stack: x, i, k, kexit_info + DUP2 + // stack: i, x, i, k, kexit_info + %mul_const(6) %add_const(@SNARKV_INP) + %mstore_kernel_bn254_pairing + // stack: i, k, kexit_info + %increment + %jump(loading_loop) + +loading_done: + %stack (i, k) -> (k, @SNARKV_INP, @SNARKV_OUT, got_result) + %jump(bn254_pairing) +got_result: + // stack: result, kexit_info + DUP1 %eq_const(@U256_MAX) %jumpi(fault_exception) + // stack: result, kexit_info + // Store the result bool (repr. by a U256) to the parent's return data using `mstore_unpacking`. + %mstore_parent_context_metadata(@CTX_METADATA_RETURNDATA_SIZE, 32) + %mload_context_metadata(@CTX_METADATA_PARENT_CONTEXT) + %stack (parent_ctx, address) -> (parent_ctx, @SEGMENT_RETURNDATA, 0, address, 32, pop_and_return_success) + %jump(mstore_unpacking) diff --git a/evm/src/cpu/kernel/asm/core/process_txn.asm b/evm/src/cpu/kernel/asm/core/process_txn.asm index a626cd39..a7ccf864 100644 --- a/evm/src/cpu/kernel/asm/core/process_txn.asm +++ b/evm/src/cpu/kernel/asm/core/process_txn.asm @@ -144,6 +144,33 @@ process_contract_creation_txn_after_code_loaded: global process_contract_creation_txn_after_constructor: // stack: success, leftover_gas, new_ctx, address, retdest POP // TODO: Success will go into the receipt when we support that. + + // EIP-3541: Reject new contract code starting with the 0xEF byte + PUSH 0 %mload_current(@SEGMENT_RETURNDATA) %eq_const(0xEF) %assert_zero // TODO: need to revert changes here. + + // stack: leftover_gas, new_ctx, address, retdest + %returndatasize // Size of the code. + // stack: code_size, leftover_gas, new_ctx, address, retdest + DUP1 %gt_const(@MAX_CODE_SIZE) %jumpi(panic) // TODO: need to revert changes here. + // stack: code_size, leftover_gas, new_ctx, address, retdest + %mul_const(@GAS_CODEDEPOSIT) SWAP1 + // stack: leftover_gas, codedeposit_cost, new_ctx, address, retdest + DUP2 DUP2 LT %jumpi(panic) // TODO: need to revert changes here. + // stack: leftover_gas, codedeposit_cost, new_ctx, address, retdest + SUB + + // Store the code hash of the new contract. + // stack: leftover_gas, new_ctx, address, retdest + GET_CONTEXT + %returndatasize + %stack (size, ctx) -> (ctx, @SEGMENT_RETURNDATA, 0, size) // context, segment, offset, len + KECCAK_GENERAL + // stack: codehash, leftover_gas, new_ctx, address, retdest + %observe_new_contract + DUP4 + // stack: address, codehash, leftover_gas, new_ctx, address, retdest + %set_codehash + // stack: leftover_gas, new_ctx, address, retdest %pay_coinbase_and_refund_sender // TODO: Delete accounts in self-destruct list and empty touched addresses. @@ -165,6 +192,13 @@ global process_message_txn: %jumpi(process_message_txn_insufficient_balance) // stack: retdest + %handle_precompiles_from_eoa + + // If to's code is empty, return. + %mload_txn_field(@TXN_FIELD_TO) %ext_code_empty + // stack: code_empty, retdest + %jumpi(process_message_txn_return) + // Add precompiles to accessed addresses. PUSH @ECREC %insert_accessed_addresses_no_return PUSH @SHA256 %insert_accessed_addresses_no_return @@ -175,12 +209,6 @@ global process_message_txn: PUSH @BN_MUL %insert_accessed_addresses_no_return PUSH @SNARKV %insert_accessed_addresses_no_return PUSH @BLAKE2_F %insert_accessed_addresses_no_return - // TODO: Handle precompiles. - - // If to's code is empty, return. - %mload_txn_field(@TXN_FIELD_TO) %ext_code_empty - // stack: code_empty, retdest - %jumpi(process_message_txn_return) // Otherwise, load to's code and execute it in a new context. // stack: retdest diff --git a/evm/src/cpu/kernel/asm/core/util.asm b/evm/src/cpu/kernel/asm/core/util.asm index a8e41a7b..04989459 100644 --- a/evm/src/cpu/kernel/asm/core/util.asm +++ b/evm/src/cpu/kernel/asm/core/util.asm @@ -28,11 +28,24 @@ // stack: to == 0 %endmacro +%macro is_precompile + // stack: addr + DUP1 %ge_const(@ECREC) SWAP1 %le_const(@BLAKE2_F) + // stack: addr>=1, addr<=9 + MUL // Cheaper than AND +%endmacro + // Returns 1 if the account is non-existent, 0 otherwise. %macro is_non_existent // stack: addr - %mpt_read_state_trie - ISZERO + DUP1 + // stack: addr, addr + %mpt_read_state_trie ISZERO + SWAP1 + // stack: addr, zero_state_trie + %is_precompile ISZERO + // stack: not_precompile, zero_state_trie + MUL // Cheaper than AND %endmacro // Returns 1 if the account is empty, 0 otherwise. @@ -65,5 +78,5 @@ // stack: addr DUP1 %is_non_existent SWAP1 %is_empty - ADD // OR + OR %endmacro diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/curve_add.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/curve_add.asm index 499d88d5..a43c4047 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/curve_add.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/curve_add.asm @@ -201,8 +201,8 @@ global bn_double: %jump(bn_add_equal_points) // Check if (x,y) is a valid curve point. -// Returns (range & curve) || is_identity -// where +// Returns (range & curve) || ident +// where // range = (x < N) & (y < N) // curve = y^2 == (x^3 + 3) // ident = (x,y) == (0,0) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/final_exponent.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/final_exponent.asm new file mode 100644 index 00000000..f8e48807 --- /dev/null +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/final_exponent.asm @@ -0,0 +1,319 @@ +/// To make the Tate pairing an invariant, the final step is to exponentiate by +/// (p^12 - 1)/N = (p^6 - 1) * (p^2 + 1) * (p^4 - p^2 + 1)/N +/// and thus we can exponentiate by each factor sequentially. +/// +/// def bn254_final_exponent(y: Fp12): +/// y = first_exp(y) +/// y = second_exp(y) +/// return final_exp(y) + +global bn254_final_exponent: + +/// first, exponentiate by (p^6 - 1) via +/// def first_exp(y): +/// return y.frob(6) / y + // stack: k, inp, out, retdest {out: y} + %stack (k, inp, out) -> (out, 0, first_exp, out) + // stack: out, 0, first_exp, out, retdest {out: y} + %jump(inv_fp254_12) +first_exp: + // stack: out, retdest {out: y , 0: y^-1} + %frob_fp254_12_6 + // stack: out, retdest {out: y_6, 0: y^-1} + %stack (out) -> (out, 0, out, second_exp, out) + // stack: out, 0, out, second_exp, out, retdest {out: y_6, 0: y^-1} + %jump(mul_fp254_12) + +/// second, exponentiate by (p^2 + 1) via +/// def second_exp(y): +/// return y.frob(2) * y +second_exp: + // stack: out, retdest {out: y} + %stack (out) -> (out, 0, out, out, final_exp, out) + // stack: out, 0, out, out, final_exp, out, retdest {out: y} + %frob_fp254_12_2_ + // stack: 0, out, out, final_exp, out, retdest {out: y, 0: y_2} + %jump(mul_fp254_12) + +/// Finally, we must exponentiate by (p^4 - p^2 + 1)/N +/// To do so efficiently, we can express this power as +/// (p^4 - p^2 + 1)/N = p^3 + (a2)p^2 - (a1)p - a0 +/// and simultaneously compute y^a4, y^a2, y^a0 where +/// a1 = a4 + 2a2 - a0 +/// We first initialize these powers as 1 and then use +/// binary algorithms for exponentiation. +/// +/// def final_exp(y): +/// y4, y2, y0 = 1, 1, 1 +/// power_loop_4() +/// power_loop_2() +/// power_loop_0() +/// custom_powers() +/// final_power() + +final_exp: + // stack: val, retdest + %stack (val) -> (val, 0, val) + // stack: val, 0, val, retdest + %move_fp254_12 + // stack: 0, val, retdest {0: sqr} + %stack () -> (1, 1, 1) + // stack: 1, 1, 1, 0, val, retdest + %mstore_kernel_bn254_pairing(12) + %mstore_kernel_bn254_pairing(24) + %mstore_kernel_bn254_pairing(36) + // stack: 0, val, retdest {0: sqr, 12: y0, 24: y2, 36: y4} + %stack () -> (64, 62, 65) + // stack: 64, 62, 65, 0, val, retdest {0: sqr, 12: y0, 24: y2, 36: y4} + %jump(power_loop_4) + +/// After computing the powers +/// y^a4, y^a2, y^a0 +/// we would like to transform them to +/// y^a2, y^-a1, y^-a0 +/// +/// def custom_powers() +/// y0 = y0^{-1} +/// y1 = y4 * y2^2 * y0 +/// return y2, y1, y0 +/// +/// And finally, upon doing so, compute the final power +/// y^(p^3) * (y^a2)^(p^2) * (y^-a1)^p * (y^-a0) +/// +/// def final_power() +/// y = y.frob(3) +/// y2 = y2.frob(2) +/// y1 = y1.frob(1) +/// return y * y2 * y1 * y0 + +custom_powers: + // stack: val, retdest {12: y0, 24: y2, 36: y4} + %stack () -> (12, 48, make_term_1) + // stack: 12, 48, make_term_1, val, retdest {12: y0, 24: y2, 36: y4} + %jump(inv_fp254_12) +make_term_1: + // stack: val, retdest {24: y2, 36: y4, 48: y0^-1} + %stack () -> (24, 36, 36, make_term_2) + // stack: 24, 36, 36, make_term_2, val, retdest {24: y2, 36: y4, 48: y0^-1} + %jump(mul_fp254_12) +make_term_2: + // stack: val, retdest {24: y2, 36: y4 * y2, 48: y0^-1} + %stack () -> (24, 36, 36, make_term_3) + // stack: 24, 36, 36, make_term_3, val, retdest {24: y2, 36: y4 * y2, 48: y0^-1} + %jump(mul_fp254_12) +make_term_3: + // stack: val, retdest {24: y2, 36: y4 * y2^2, 48: y0^-1} + %stack () -> (48, 36, 36, final_power) + // stack: 48, 36, 36, final_power, val, retdest {24: y2, 36: y4 * y2^2, 48: y0^-1} + %jump(mul_fp254_12) +final_power: + // stack: val, retdest {val: y , 24: y^a2 , 36: y^a1 , 48: y^a0} + %frob_fp254_12_3 + // stack: val, retdest {val: y_3, 24: y^a2 , 36: y^a1 , 48: y^a0} + %stack () -> (24, 24) + %frob_fp254_12_2_ + POP + // stack: val, retdest {val: y_3, 24: (y^a2)_2, 36: y^a1 , 48: y^a0} + PUSH 36 + %frob_fp254_12_1 + POP + // stack: val, retdest {val: y_3, 24: (y^a2)_2, 36: (y^a1)_1, 48: y^a0} + %stack (val) -> (24, val, val, penult_mul, val) + // stack: 24, val, val, penult_mul, val, retdest {val: y_3, 24: (y^a2)_2, 36: (y^a1)_1, 48: y^a0} + %jump(mul_fp254_12) +penult_mul: + // stack: val, retdest {val: y_3 * (y^a2)_2, 36: (y^a1)_1, 48: y^a0} + %stack (val) -> (36, val, val, final_mul, val) + // stack: 36, val, val, final_mul, val, retdest {val: y_3 * (y^a2)_2, 36: (y^a1)_1, 48: y^a0} + %jump(mul_fp254_12) +final_mul: + // stack: val, retdest {val: y_3 * (y^a2)_2 * (y^a1)_1, 48: y^a0} + %stack (val) -> (48, val, val) + // stack: 48, val, val, retdest {val: y_3 * (y^a2)_2 * (y^a1)_1, 48: y^a0} + %jump(mul_fp254_12) + + +/// def power_loop_4(): +/// for i in range(64): +/// abc = load(i, power_data_4) +/// if a: +/// y4 *= acc +/// if b: +/// y2 *= acc +/// if c: +/// y0 *= acc +/// acc = square_fp254_12(acc) +/// y4 *= acc +/// +/// def power_loop_2(): +/// for i in range(62): +/// ab = load(i, power_data_2) +/// if a: +/// y2 *= acc +/// if b: +/// y0 *= acc +/// acc = square_fp254_12(acc) +/// y2 *= acc +/// +/// def power_loop_0(): +/// for i in range(65): +/// a = load(i, power_data_0) +/// if a: +/// y0 *= acc +/// acc = square_fp254_12(acc) +/// y0 *= acc + +power_loop_4: + // stack: i , j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + DUP1 + ISZERO + // stack: break?, i , j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %jumpi(power_loop_4_end) + // stack: i , j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %sub_const(1) + // stack: i-1, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + DUP1 + %mload_kernel_code(power_data_4) + // stack: abc, i-1, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + DUP1 + %lt_const(100) + // stack: skip?, abc, i-1, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %jumpi(power_loop_4_b) + // stack: abc, i-1, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %sub_const(100) + // stack: bc, i-1, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %stack () -> (36, 36, power_loop_4_b) + // stack: 36, 36, power_loop_4_b, bc, i-1, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + DUP8 + // stack: sqr, 36, 36, power_loop_4_b, bc, i-1, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %jump(mul_fp254_12) +power_loop_4_b: + // stack: bc, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + DUP1 + %lt_const(10) + // stack: skip?, bc, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %jumpi(power_loop_4_c) + // stack: bc, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %sub_const(10) + // stack: c, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %stack () -> (24, 24, power_loop_4_c) + // stack: 24, 24, power_loop_4_c, c, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + DUP8 + // stack: sqr, 24, 24, power_loop_4_c, c, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %jump(mul_fp254_12) +power_loop_4_c: + // stack: c, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + ISZERO + // stack: skip?, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %jumpi(power_loop_4_sq) + // stack: i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %stack () -> (12, 12, power_loop_4_sq) + // stack: 12, 12, power_loop_4_sq, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + DUP7 + // stack: sqr, 12, 12, power_loop_4_sq, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %jump(mul_fp254_12) +power_loop_4_sq: + // stack: i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + PUSH power_loop_4 + // stack: power_loop_4, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + DUP5 + DUP1 + // stack: sqr, sqr, power_loop_4, i, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %jump(square_fp254_12) +power_loop_4_end: + // stack: 0, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + POP + // stack: j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %stack () -> (36, 36, power_loop_2) + // stack: 36, 36, power_loop_2, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + DUP6 + // stack: sqr, 36, 36, power_loop_2, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %jump(mul_fp254_12) + +power_loop_2: + // stack: j , k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + DUP1 + ISZERO + // stack: break?, j , k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %jumpi(power_loop_2_end) + // stack: j , k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %sub_const(1) + // stack: j-1, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + DUP1 + %mload_kernel_code(power_data_2) + // stack: ab, j-1, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + DUP1 + %lt_const(10) + // stack: skip?, ab, j-1, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %jumpi(power_loop_2_b) + // stack: ab, j-1, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %sub_const(10) + // stack: b, j-1, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %stack () -> (24, 24, power_loop_2_b) + // stack: 24, 24, power_loop_2_b, b, j-1, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + DUP7 + // stack: sqr, 24, 24, power_loop_2_b, b, j-1, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %jump(mul_fp254_12) +power_loop_2_b: + // stack: b, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + ISZERO + // stack: skip?, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %jumpi(power_loop_2_sq) + // stack: j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %stack () -> (12, 12, power_loop_2_sq) + // stack: 12, 12, power_loop_2_sq, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + DUP6 + // stack: sqr, 12, 12, power_loop_2_sq, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %jump(mul_fp254_12) +power_loop_2_sq: + // stack: j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + PUSH power_loop_2 + // stack: power_loop_2, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + DUP4 + DUP1 + // stack: sqr, sqr, power_loop_2, j, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %jump(square_fp254_12) +power_loop_2_end: + // stack: 0, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + POP + // stack: k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %stack () -> (24, 24, power_loop_0) + // stack: 24, 24, power_loop_0, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + DUP5 + // stack: sqr, 24, 24, power_loop_0, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %jump(mul_fp254_12) + +power_loop_0: + // stack: k , sqr {0: sqr, 12: y0, 24: y2, 36: y4} + DUP1 + ISZERO + // stack: break?, k , sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %jumpi(power_loop_0_end) + // stack: k , sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %sub_const(1) + // stack: k-1, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + DUP1 + %mload_kernel_code(power_data_0) + // stack: a, k-1, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + ISZERO + // stack: skip?, k-1, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %jumpi(power_loop_0_sq) + // stack: k-1, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %stack () -> (12, 12, power_loop_0_sq) + // stack: 12, 12, power_loop_0_sq, k-1, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + DUP5 + // stack: sqr, 12, 12, power_loop_0_sq, k-1, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %jump(mul_fp254_12) +power_loop_0_sq: + // stack: k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + PUSH power_loop_0 + // stack: power_loop_0, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + DUP3 + DUP1 + // stack: sqr, sqr, power_loop_0, k, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %jump(square_fp254_12) +power_loop_0_end: + // stack: 0, sqr {0: sqr, 12: y0, 24: y2, 36: y4} + %stack (i, sqr) -> (12, sqr, 12, custom_powers) + // stack: 12, sqr, 12, custom_powers {0: sqr, 12: y0, 24: y2, 36: y4} + %jump(mul_fp254_12) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/invariant_exponent.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/invariant_exponent.asm deleted file mode 100644 index 2fcd5d2b..00000000 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/invariant_exponent.asm +++ /dev/null @@ -1,319 +0,0 @@ -/// To make the Tate pairing an invariant, the final step is to exponentiate by -/// (p^12 - 1)/N = (p^6 - 1) * (p^2 + 1) * (p^4 - p^2 + 1)/N -/// and thus we can exponentiate by each factor sequentially. -/// -/// def bn254_invariant_exponent(y: Fp12): -/// y = first_exp(y) -/// y = second_exp(y) -/// return final_exp(y) - -global bn254_invariant_exponent: - -/// first, exponentiate by (p^6 - 1) via -/// def first_exp(y): -/// return y.frob(6) / y - // stack: out, retdest {out: y} - %stack (out) -> (out, 0, first_exp, out) - // stack: out, 0, first_exp, out, retdest {out: y} - %jump(inv_fp254_12) -first_exp: - // stack: out, retdest {out: y , 0: y^-1} - %frob_fp254_12_6 - // stack: out, retdest {out: y_6, 0: y^-1} - %stack (out) -> (out, 0, out, second_exp, out) - // stack: out, 0, out, second_exp, out, retdest {out: y_6, 0: y^-1} - %jump(mul_fp254_12) - -/// second, exponentiate by (p^2 + 1) via -/// def second_exp(y): -/// return y.frob(2) * y -second_exp: - // stack: out, retdest {out: y} - %stack (out) -> (out, 0, out, out, final_exp, out) - // stack: out, 0, out, out, final_exp, out, retdest {out: y} - %frob_fp254_12_2_ - // stack: 0, out, out, final_exp, out, retdest {out: y, 0: y_2} - %jump(mul_fp254_12) - -/// Finally, we must exponentiate by (p^4 - p^2 + 1)/N -/// To do so efficiently, we can express this power as -/// (p^4 - p^2 + 1)/N = p^3 + (a2)p^2 - (a1)p - a0 -/// and simultaneously compute y^a4, y^a2, y^a0 where -/// a1 = a4 + 2a2 - a0 -/// We first initialize these powers as 1 and then use -/// binary algorithms for exponentiation. -/// -/// def final_exp(y): -/// y4, y2, y0 = 1, 1, 1 -/// power_loop_4() -/// power_loop_2() -/// power_loop_0() -/// custom_powers() -/// final_power() - -final_exp: - // stack: val, retdest - %stack (val) -> (val, 12, val) - // stack: val, 12, val, retdest - %move_fp254_12 - // stack: 12, val, retdest {12: sqr} - %stack () -> (1, 1, 1) - // stack: 1, 1, 1, 12, val, retdest - %mstore_kernel_bn254_pairing(24) - %mstore_kernel_bn254_pairing(36) - %mstore_kernel_bn254_pairing(48) - // stack: 12, val, retdest {12: sqr, 24: y0, 36: y2, 48: y4} - %stack () -> (64, 62, 65) - // stack: 64, 62, 65, 12, val, retdest {12: sqr, 24: y0, 36: y2, 48: y4} - %jump(power_loop_4) - -/// After computing the powers -/// y^a4, y^a2, y^a0 -/// we would like to transform them to -/// y^a2, y^-a1, y^-a0 -/// -/// def custom_powers() -/// y0 = y0^{-1} -/// y1 = y4 * y2^2 * y0 -/// return y2, y1, y0 -/// -/// And finally, upon doing so, compute the final power -/// y^(p^3) * (y^a2)^(p^2) * (y^-a1)^p * (y^-a0) -/// -/// def final_power() -/// y = y.frob(3) -/// y2 = y2.frob(2) -/// y1 = y1.frob(1) -/// return y * y2 * y1 * y0 - -custom_powers: - // stack: val, retdest {24: y0, 36: y2, 48: y4} - %stack () -> (24, 60, make_term_1) - // stack: 24, 60, make_term_1, val, retdest {24: y0, 36: y2, 48: y4} - %jump(inv_fp254_12) -make_term_1: - // stack: val, retdest {36: y2, 48: y4, 60: y0^-1} - %stack () -> (36, 48, 48, make_term_2) - // stack: 36, 48, 48, make_term_2, val, retdest {36: y2, 48: y4, 60: y0^-1} - %jump(mul_fp254_12) -make_term_2: - // stack: val, retdest {36: y2, 48: y4 * y2, 60: y0^-1} - %stack () -> (36, 48, 48, make_term_3) - // stack: 36, 48, 48, make_term_3, val, retdest {36: y2, 48: y4 * y2, 60: y0^-1} - %jump(mul_fp254_12) -make_term_3: - // stack: val, retdest {36: y2, 48: y4 * y2^2, 60: y0^-1} - %stack () -> (60, 48, 48, final_power) - // stack: 60, 48, 48, final_power, val, retdest {36: y2, 48: y4 * y2^2, 60: y0^-1} - %jump(mul_fp254_12) -final_power: - // stack: val, retdest {val: y , 36: y^a2 , 48: y^a1 , 60: y^a0} - %frob_fp254_12_3 - // stack: val, retdest {val: y_3, 36: y^a2 , 48: y^a1 , 60: y^a0} - %stack () -> (36, 36) - %frob_fp254_12_2_ - POP - // stack: val, retdest {val: y_3, 36: (y^a2)_2, 48: y^a1 , 60: y^a0} - PUSH 48 - %frob_fp254_12_1 - POP - // stack: val, retdest {val: y_3, 36: (y^a2)_2, 48: (y^a1)_1, 60: y^a0} - %stack (val) -> (36, val, val, penult_mul, val) - // stack: 36, val, val, penult_mul, val, retdest {val: y_3, 36: (y^a2)_2, 48: (y^a1)_1, 60: y^a0} - %jump(mul_fp254_12) -penult_mul: - // stack: val, retdest {val: y_3 * (y^a2)_2, 48: (y^a1)_1, 60: y^a0} - %stack (val) -> (48, val, val, final_mul, val) - // stack: 48, val, val, final_mul, val, retdest {val: y_3 * (y^a2)_2, 48: (y^a1)_1, 60: y^a0} - %jump(mul_fp254_12) -final_mul: - // stack: val, retdest {val: y_3 * (y^a2)_2 * (y^a1)_1, 60: y^a0} - %stack (val) -> (60, val, val) - // stack: 60, val, val, retdest {val: y_3 * (y^a2)_2 * (y^a1)_1, 60: y^a0} - %jump(mul_fp254_12) - - -/// def power_loop_4(): -/// for i in range(64): -/// abc = load(i, power_data_4) -/// if a: -/// y4 *= acc -/// if b: -/// y2 *= acc -/// if c: -/// y0 *= acc -/// acc = square_fp254_12(acc) -/// y4 *= acc -/// -/// def power_loop_2(): -/// for i in range(62): -/// ab = load(i, power_data_2) -/// if a: -/// y2 *= acc -/// if b: -/// y0 *= acc -/// acc = square_fp254_12(acc) -/// y2 *= acc -/// -/// def power_loop_0(): -/// for i in range(65): -/// a = load(i, power_data_0) -/// if a: -/// y0 *= acc -/// acc = square_fp254_12(acc) -/// y0 *= acc - -power_loop_4: - // stack: i , j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - DUP1 - ISZERO - // stack: break?, i , j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %jumpi(power_loop_4_end) - // stack: i , j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %sub_const(1) - // stack: i-1, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - DUP1 - %mload_kernel_code(power_data_4) - // stack: abc, i-1, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - DUP1 - %lt_const(100) - // stack: skip?, abc, i-1, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %jumpi(power_loop_4_b) - // stack: abc, i-1, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %sub_const(100) - // stack: bc, i-1, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %stack () -> (48, 48, power_loop_4_b) - // stack: 48, 48, power_loop_4_b, bc, i-1, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - DUP8 - // stack: sqr, 48, 48, power_loop_4_b, bc, i-1, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %jump(mul_fp254_12) -power_loop_4_b: - // stack: bc, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - DUP1 - %lt_const(10) - // stack: skip?, bc, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %jumpi(power_loop_4_c) - // stack: bc, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %sub_const(10) - // stack: c, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %stack () -> (36, 36, power_loop_4_c) - // stack: 36, 36, power_loop_4_c, c, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - DUP8 - // stack: sqr, 36, 36, power_loop_4_c, c, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %jump(mul_fp254_12) -power_loop_4_c: - // stack: c, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - ISZERO - // stack: skip?, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %jumpi(power_loop_4_sq) - // stack: i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %stack () -> (24, 24, power_loop_4_sq) - // stack: 24, 24, power_loop_4_sq, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - DUP7 - // stack: sqr, 24, 24, power_loop_4_sq, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %jump(mul_fp254_12) -power_loop_4_sq: - // stack: i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - PUSH power_loop_4 - // stack: power_loop_4, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - DUP5 - DUP1 - // stack: sqr, sqr, power_loop_4, i, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %jump(square_fp254_12) -power_loop_4_end: - // stack: 0, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - POP - // stack: j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %stack () -> (48, 48, power_loop_2) - // stack: 48, 48, power_loop_2, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - DUP6 - // stack: sqr, 48, 48, power_loop_2, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %jump(mul_fp254_12) - -power_loop_2: - // stack: j , k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - DUP1 - ISZERO - // stack: break?, j , k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %jumpi(power_loop_2_end) - // stack: j , k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %sub_const(1) - // stack: j-1, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - DUP1 - %mload_kernel_code(power_data_2) - // stack: ab, j-1, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - DUP1 - %lt_const(10) - // stack: skip?, ab, j-1, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %jumpi(power_loop_2_b) - // stack: ab, j-1, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %sub_const(10) - // stack: b, j-1, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %stack () -> (36, 36, power_loop_2_b) - // stack: 36, 36, power_loop_2_b, b, j-1, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - DUP7 - // stack: sqr, 36, 36, power_loop_2_b, b, j-1, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %jump(mul_fp254_12) -power_loop_2_b: - // stack: b, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - ISZERO - // stack: skip?, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %jumpi(power_loop_2_sq) - // stack: j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %stack () -> (24, 24, power_loop_2_sq) - // stack: 24, 24, power_loop_2_sq, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - DUP6 - // stack: sqr, 24, 24, power_loop_2_sq, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %jump(mul_fp254_12) -power_loop_2_sq: - // stack: j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - PUSH power_loop_2 - // stack: power_loop_2, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - DUP4 - DUP1 - // stack: sqr, sqr, power_loop_2, j, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %jump(square_fp254_12) -power_loop_2_end: - // stack: 0, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - POP - // stack: k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %stack () -> (36, 36, power_loop_0) - // stack: 36, 36, power_loop_0, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - DUP5 - // stack: sqr, 36, 36, power_loop_0, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %jump(mul_fp254_12) - -power_loop_0: - // stack: k , sqr {12: sqr, 24: y0, 36: y2, 48: y4} - DUP1 - ISZERO - // stack: break?, k , sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %jumpi(power_loop_0_end) - // stack: k , sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %sub_const(1) - // stack: k-1, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - DUP1 - %mload_kernel_code(power_data_0) - // stack: a, k-1, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - ISZERO - // stack: skip?, k-1, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %jumpi(power_loop_0_sq) - // stack: k-1, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %stack () -> (24, 24, power_loop_0_sq) - // stack: 24, 24, power_loop_0_sq, k-1, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - DUP5 - // stack: sqr, 24, 24, power_loop_0_sq, k-1, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %jump(mul_fp254_12) -power_loop_0_sq: - // stack: k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - PUSH power_loop_0 - // stack: power_loop_0, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - DUP3 - DUP1 - // stack: sqr, sqr, power_loop_0, k, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %jump(square_fp254_12) -power_loop_0_end: - // stack: 0, sqr {12: sqr, 24: y0, 36: y2, 48: y4} - %stack (i, sqr) -> (24, sqr, 24, custom_powers) - // stack: 24, sqr, 24, custom_powers {12: sqr, 24: y0, 36: y2, 48: y4} - %jump(mul_fp254_12) diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/tate_pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm similarity index 77% rename from evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/tate_pairing.asm rename to evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm index f09684bd..120365af 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/tate_pairing.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/miller_loop.asm @@ -1,12 +1,3 @@ -/// def tate(P: Curve, Q: TwistedCurve) -> Fp12: -/// out = miller_loop(P, Q) -/// return bn254_invariant_exponent(P, Q) -global bn254_tate: - // stack: inp, out, retdest - %stack (inp, out) -> (inp, out, bn254_invariant_exponent, out) - // stack: inp, out, bn254_invariant_exponent, out, retdest - %jump(bn254_miller) - /// def miller(P, Q): /// miller_init() /// miller_loop() @@ -35,13 +26,13 @@ global bn254_tate: /// mul_tangent() global bn254_miller: - // stack: ptr, out, retdest - %stack (ptr, out) -> (out, 1, ptr, out) - // stack: out, 1, ptr, out, retdest - %mstore_kernel_bn254_pairing - // stack: ptr, out, retdest + // stack: ptr, out, retdest + %stack (ptr, out) -> (out, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ptr, out) + // stack: out, unit, ptr, out, retdest + %store_fp254_12 + // stack: ptr, out, retdest %load_fp254_6 - // stack: P, Q, out, retdest + // stack: P, Q, out, retdest %stack (P: 2) -> (0, 53, P, P) // stack: 0, 53, O, P, Q, out, retdest // the head 0 lets miller_loop start with POP @@ -64,6 +55,7 @@ miller_return: // stack: times, O, P, Q, out, retdest %stack (times, O: 2, P: 2, Q: 4, out, retdest) -> (retdest) // stack: retdest + %clear_line JUMP miller_one: @@ -109,35 +101,35 @@ mul_tangent: // stack: out, out, mul_tangent_1, out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out %jump(square_fp254_12) mul_tangent_1: - // stack: out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out + // stack: out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out DUP13 DUP13 DUP13 DUP13 - // stack: Q, out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out + // stack: Q, out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out DUP11 DUP11 - // stack: O, Q, out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out + // stack: O, Q, out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out %tangent - // stack: out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out {0: line} - %stack (out) -> (out, 0, out) - // stack: out, 0, out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out {0: line} + // stack: out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out {12: line} + %stack (out) -> (out, 12, out) + // stack: out, 12, out, mul_tangent_2, retdest, 0xnm, times, O, P, Q, out {12: line} %jump(mul_fp254_12_sparse) mul_tangent_2: - // stack: retdest, 0xnm, times, O, P, Q, out {0: line} + // stack: retdest, 0xnm, times, O, P, Q, out {12: line} PUSH after_double - // stack: after_double, retdest, 0xnm, times, O, P, Q, out {0: line} + // stack: after_double, retdest, 0xnm, times, O, P, Q, out {12: line} DUP6 DUP6 - // stack: O, after_double, retdest, 0xnm, times, O, P, Q, out {0: line} + // stack: O, after_double, retdest, 0xnm, times, O, P, Q, out {12: line} %jump(bn_double) after_double: - // stack: 2*O, retdest, 0xnm, times, O, P, Q, out {0: line} + // stack: 2*O, retdest, 0xnm, times, O, P, Q, out {12: line} SWAP5 POP SWAP5 POP - // stack: retdest, 0xnm, times, 2*O, P, Q, out {0: line} + // stack: retdest, 0xnm, times, 2*O, P, Q, out {12: line} JUMP /// def mul_cord() @@ -146,26 +138,26 @@ after_double: /// O += P mul_cord: - // stack: 0xnm, times, O, P, Q, out + // stack: 0xnm, times, O, P, Q, out PUSH mul_cord_1 - // stack: mul_cord_1, 0xnm, times, O, P, Q, out + // stack: mul_cord_1, 0xnm, times, O, P, Q, out DUP11 DUP11 DUP11 DUP11 - // stack: Q, mul_cord_1, 0xnm, times, O, P, Q, out + // stack: Q, mul_cord_1, 0xnm, times, O, P, Q, out DUP9 DUP9 - // stack: O, Q, mul_cord_1, 0xnm, times, O, P, Q, out + // stack: O, Q, mul_cord_1, 0xnm, times, O, P, Q, out DUP13 DUP13 - // stack: P, O, Q, mul_cord_1, 0xnm, times, O, P, Q, out + // stack: P, O, Q, mul_cord_1, 0xnm, times, O, P, Q, out %cord - // stack: mul_cord_1, 0xnm, times, O, P, Q, out {0: line} + // stack: mul_cord_1, 0xnm, times, O, P, Q, out {12: line} DUP12 - // stack: out, mul_cord_1, 0xnm, times, O, P, Q, out {0: line} - %stack (out) -> (out, 0, out) - // stack: out, 0, out, mul_cord_1, 0xnm, times, O, P, Q, out {0: line} + // stack: out, mul_cord_1, 0xnm, times, O, P, Q, out {12: line} + %stack (out) -> (out, 12, out) + // stack: out, 12, out, mul_cord_1, 0xnm, times, O, P, Q, out {12: line} %jump(mul_fp254_12_sparse) mul_cord_1: // stack: 0xnm, times, O , P, Q, out @@ -202,7 +194,7 @@ after_add: // stack: py^2 , 9, px, py, qx, qx_, qy, qy_ SUBFP254 // stack: py^2 - 9, px, py, qx, qx_, qy, qy_ - %mstore_kernel_bn254_pairing(0) + %mstore_kernel_bn254_pairing(12) // stack: px, py, qx, qx_, qy, qy_ DUP1 MULFP254 @@ -218,7 +210,7 @@ after_add: DUP3 MULFP254 // stack: (-3*px^2)qx, py, -3px^2, qx_, qy, qy_ - %mstore_kernel_bn254_pairing(2) + %mstore_kernel_bn254_pairing(14) // stack: py, -3px^2, qx_, qy, qy_ PUSH 2 MULFP254 @@ -228,15 +220,15 @@ after_add: DUP4 MULFP254 // stack: (2py)qy, -3px^2, qx_, 2py, qy_ - %mstore_kernel_bn254_pairing(8) + %mstore_kernel_bn254_pairing(20) // stack: -3px^2, qx_, 2py, qy_ MULFP254 // stack: (-3px^2)*qx_, 2py, qy_ - %mstore_kernel_bn254_pairing(3) + %mstore_kernel_bn254_pairing(15) // stack: 2py, qy_ MULFP254 // stack: (2py)*qy_ - %mstore_kernel_bn254_pairing(9) + %mstore_kernel_bn254_pairing(21) %endmacro /// def cord(p1x, p1y, p2x, p2y, qx, qy): @@ -258,7 +250,7 @@ after_add: // stack: p1y*p2x , p2y*p1x, p1x , p1y, p2x , p2y, qx, qx_, qy, qy_ SUBFP254 // stack: p1y*p2x - p2y*p1x, p1x , p1y, p2x , p2y, qx, qx_, qy, qy_ - %mstore_kernel_bn254_pairing(0) + %mstore_kernel_bn254_pairing(12) // stack: p1x , p1y, p2x , p2y, qx, qx_, qy, qy_ SWAP3 // stack: p2y , p1y, p2x , p1x, qx, qx_, qy, qy_ @@ -273,20 +265,29 @@ after_add: DUP5 MULFP254 // stack: (p1x - p2x)qy, p2y - p1y, qx, qx_, p1x - p2x, qy_ - %mstore_kernel_bn254_pairing(8) + %mstore_kernel_bn254_pairing(20) // stack: p2y - p1y, qx, qx_, p1x - p2x, qy_ SWAP1 // stack: qx, p2y - p1y, qx_, p1x - p2x, qy_ DUP2 MULFP254 // stack: (p2y - p1y)qx, p2y - p1y, qx_, p1x - p2x, qy_ - %mstore_kernel_bn254_pairing(2) + %mstore_kernel_bn254_pairing(14) // stack: p2y - p1y, qx_, p1x - p2x, qy_ MULFP254 // stack: (p2y - p1y)qx_, p1x - p2x, qy_ - %mstore_kernel_bn254_pairing(3) + %mstore_kernel_bn254_pairing(15) // stack: p1x - p2x, qy_ MULFP254 // stack: (p1x - p2x)*qy_ - %mstore_kernel_bn254_pairing(9) + %mstore_kernel_bn254_pairing(21) +%endmacro + +%macro clear_line + %stack () -> (0, 0, 0, 0, 0) + %mstore_kernel_bn254_pairing(12) + %mstore_kernel_bn254_pairing(14) + %mstore_kernel_bn254_pairing(15) + %mstore_kernel_bn254_pairing(20) + %mstore_kernel_bn254_pairing(21) %endmacro diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm new file mode 100644 index 00000000..4479b965 --- /dev/null +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/pairing.asm @@ -0,0 +1,193 @@ +/// The input to the pairing script is a list of points +/// P_i = n_i*G: Curve, Q_i = m_i*H: TwistedCurve +/// where G, H are the respective generators, such that +/// sum_i n_i*m_i = 0 +/// and therefore, due to bilinearity of the pairing: +/// prod_i e(P_i, Q_i) +/// = prod_i e(n_i G, m_i H) +/// = prod_i e(G,H)^{n_i * m_i} +/// = e(G,H)^{sum_i n_i * m_i} +/// = e(G,H)^0 +/// = 1: Fp12 + +/// def bn254_pairing(pairs: List((Curve, TwistedCurve))) -> Bool: +/// +/// for P, Q in pairs: +/// if not (P.is_valid and Q.is_valid): +/// return @U256_MAX +/// +/// out = 1 +/// for P, Q in pairs: +/// if P != 0 and Q != 0: +/// out *= miller_loop(P, Q) +/// +/// result = bn254_final_exponent(out) +/// return result == unit_fp12 + +/// The following is a key to this API +/// +/// - k is the number of inputs +/// - each input given by a pair of points, one on the curve and one on the twisted curve +/// - each input consists of 6 stack terms---2 for the curve point and 4 for the twisted curve point +/// - the inputs are presumed to be placed on the kernel contiguously +/// - the output (as defined above) is an Fp12 element +/// - out and inp are the BnPairing segment offsets for the output element and input +/// - the assembly code currently uses offsets 0-78 for scratch space + +global bn254_pairing: + // stack: k, inp, out, retdest + DUP1 + +bn254_input_check: + // stack: j , k, inp + DUP1 + ISZERO + // stack: end?, j , k, inp + %jumpi(bn254_pairing_start) + // stack: j , k, inp + %sub_const(1) + // stack: j=j-1, k, inp + + %stack (j, k, inp) -> (j, inp, j, k, inp) + // stack: j, inp, j, k, inp + %mul_const(6) + ADD + // stack: inp_j=inp+6j, j, k, inp + DUP1 + // stack: inp_j, inp_j, j, k, inp + %load_fp254_2 + // stack: P_j, inp_j, j, k, inp + %bn_check + // stack: valid?, inp_j, j, k, inp + ISZERO + %jumpi(bn_pairing_invalid_input) + // stack: inp_j, j, k, inp + DUP1 + // stack: inp_j , inp_j, j, k, inp + %add_const(2) + // stack: inp_j', inp_j, j, k, inp + %load_fp254_4 + // stack: Q_j, inp_j, j, k, inp + %bn_check_twisted + // stack: valid?, inp_j, j, k, inp + ISZERO + %jumpi(bn_pairing_invalid_input) + // stack: inp_j, j, k, inp + POP + %jump(bn254_input_check) + +bn_pairing_invalid_input: + // stack: inp_j, j, k, inp, out, retdest + %stack (inp_j, j, k, inp, out, retdest) -> (retdest, inp_j) + JUMP + +bn254_pairing_start: + // stack: 0, k, inp, out, retdest + %stack (j, k, inp, out) -> (out, 1, k, inp, out, bn254_pairing_output_validation, out) + // stack: out, 1, k, inp, out, bn254_pairing_output_validation, out, retdest + %mstore_kernel_bn254_pairing + // stack: k, inp, out, bn254_pairing_output_validation, out, retdest + +bn254_pairing_loop: + // stack: k, inp, out, bn254_pairing_output_validation, out, retdest + DUP1 + ISZERO + // stack: end?, k, inp, out, bn254_pairing_output_validation, out, retdest + %jumpi(bn254_final_exponent) + // stack: k, inp, out, bn254_pairing_output_validation, out, retdest + %sub_const(1) + // stack: k=k-1, inp, out, bn254_pairing_output_validation, out, retdest + %stack (k, inp) -> (k, inp, k, inp) + // stack: k, inp, k, inp, out, bn254_pairing_output_validation, out, retdest + %mul_const(6) + ADD + // stack: inp_k, k, inp, out, bn254_pairing_output_validation, out, retdest + DUP1 + %load_fp254_6 + // stack: P, Q, inp_k, k, inp, out, bn254_pairing_output_validation, out, retdest + %neutral_input + // stack: skip?, inp_k, k, inp, out, bn254_pairing_output_validation, out, retdest + %jumpi(bn_skip_input) + // stack: inp_k, k, inp, out, bn254_pairing_output_validation, out, retdest + %stack (inp_k, k, inp, out) -> (bn254_miller, inp_k, 0, mul_fp254_12, 0, out, out, bn254_pairing_loop, k, inp, out) + // stack: bn254_miller, inp_k, 0, + // mul_fp254_12, 0, out, out, + // bn254_pairing_loop, k, inp, out, + // bn254_pairing_output_validation, out, retdest + JUMP + +bn_skip_input: + // stack: inp_k, k, inp, out, bn254_pairing_output_validation, out, retdest + POP + // stack: k, inp, out, bn254_pairing_output_validation, out, retdest + %jump(bn254_pairing_loop) + + +bn254_pairing_output_validation: + // stack: out, retdest + PUSH 1 + // stack: check, out, retdest + %check_output_term + %check_output_term(1) + %check_output_term(2) + %check_output_term(3) + %check_output_term(4) + %check_output_term(5) + %check_output_term(6) + %check_output_term(7) + %check_output_term(8) + %check_output_term(9) + %check_output_term(10) + %check_output_term(11) + // stack: check, out, retdest + %stack (check, out, retdest) -> (retdest, check) + JUMP + +%macro check_output_term + // stack: check, out + DUP2 + // stack: out0, check, out + %mload_kernel_bn254_pairing + // stack: f0, check, out + %eq_const(1) + // stack: check0, check, out + MUL + // stack: check, out +%endmacro + +%macro check_output_term(j) + // stack: check, out + DUP2 + %add_const($j) + // stack: outj, check, out + %mload_kernel_bn254_pairing + // stack: fj, check, out + ISZERO + // stack: checkj, check, out + MUL + // stack: check, out +%endmacro + +%macro neutral_input + // stack: P , Q + ISZERO + SWAP1 + ISZERO + MUL + // stack: P==0, Q + SWAP4 + // stack: Q , P==0 + ISZERO + SWAP1 + ISZERO + MUL + SWAP1 + ISZERO + MUL + SWAP1 + ISZERO + MUL + // stack: Q==0, P==0 + OR + // stack: Q==0||P==0 +%endmacro \ No newline at end of file diff --git a/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm new file mode 100644 index 00000000..859c45fe --- /dev/null +++ b/evm/src/cpu/kernel/asm/curve/bn254/curve_arithmetic/twisted_curve.asm @@ -0,0 +1,94 @@ +// Check if (X,Y) is a valid curve point. +// Returns (range & curve) || ident +// where +// range = (x < N) & (x_ < N) & (y < N) & (y_ < N) +// curve = Y^2 == X^3 + 3/(9+i) +// ident = (X,Y) == (0,0) + +%macro bn_check_twisted + // stack: x, x_, y, y_ + %bn_check_twisted_range + // stack: range, x, x_, y, y_ + %bn_check_twisted_curve + // stack: curve , range, x, x_, y, y_ + MUL // Cheaper than AND + // stack: curve & range, x, x_, y, y_ + SWAP4 + // stack: y_, x, x_, y, curve & range + %bn_check_twisted_ident + // stack: ident , curve & range + OR + // stack: ident || (curve & range) +%endmacro + +%macro bn_check_twisted_range + // stack: x, x_, y, y_ + PUSH @BN_BASE + // stack: N, x, x_, y, y_ + %stack (N) -> (N, N, N, N) + // stack: N, N, N, N, x, x_, y, y_ + DUP8 + // stack: y_ , N, N, N, N, x, x_, y, y_ + LT + // stack: y_ < N, N, N, N, x, x_, y, y_ + SWAP3 + // stack: N, N, N, y_ < N, x, x_, y, y_ + DUP7 + // stack: y , N, N, N, y_ < N, x, x_, y, y_ + LT + // stack: y < N, N, N, y_ < N, x, x_, y, y_ + SWAP2 + // stack: N, N, y < N, y_ < N, x, x_, y, y_ + DUP6 + // stack: x_ , N, N, y < N, y_ < N, x, x_, y, y_ + LT + // stack: x_ < N, N, y < N, y_ < N, x, x_, y, y_ + SWAP1 + // stack: N, x_ < N, y < N, y_ < N, x, x_, y, y_ + DUP5 + // stack: x , N, x_ < N, y < N, y_ < N, x, x_, y, y_ + LT + // stack: x < N, x_ < N, y < N, y_ < N, x, x_, y, y_ + MUL // Cheaper than AND + MUL // Cheaper than AND + MUL // Cheaper than AND + // stack: range, x, x_, y, y_ +%endmacro + +%macro bn_check_twisted_curve + // stack: range, X, Y + %stack (range, X: 2, Y: 2) -> (Y, Y, range, X, Y) + // stack: Y, Y, range, X, Y + %mul_fp254_2 + // stack: Y^2, range, X, Y + %stack () -> (@BN_TWISTED_RE, @BN_TWISTED_IM) + // stack: A, Y^2, range, X, Y + %stack (A: 2, Y2: 2, range, X: 2) -> (X, X, X, A, Y2, range, X) + // stack: X, X, X, A, Y^2, range, X, Y + %mul_fp254_2 + %mul_fp254_2 + // stack: X^3 , A, Y^2, range, X, Y + %add_fp254_2 + // stack: X^3 + A, Y^2, range, X, Y + %eq_fp254_2 + // stack: curve, range, X, Y +%endmacro + +%macro bn_check_twisted_ident + SWAP2 + // stack: a , b , c , d + ISZERO + SWAP3 + // stack: d , b , c , a==0 + ISZERO + SWAP2 + // stack: c , b , d==0, a==0 + ISZERO + SWAP1 + // stack: b , c==0, d==0, a==0 + ISZERO + // stack: b==0, c==0, d==0, a==0 + MUL // Cheaper than AND + MUL // Cheaper than AND + MUL // Cheaper than AND +%endmacro diff --git a/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/degree_12_mul.asm b/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/degree_12_mul.asm index 5fd47e80..ca32a30d 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/degree_12_mul.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/degree_12_mul.asm @@ -2,32 +2,6 @@ ///// GENERAL FP12 MULTIPLICATION ///// /////////////////////////////////////// -/// cost: 1063 - -/// fp254_6 functions: -/// fn | num | ops | cost -/// ------------------------- -/// load | 8 | 40 | 320 -/// store | 5 | 40 | 200 -/// dup | 5 | 6 | 30 -/// swap | 4 | 16 | 64 -/// add | 4 | 16 | 64 -/// subr | 1 | 17 | 17 -/// mul | 3 | 157 | 471 -/// i9 | 1 | 9 | 9 -/// -/// lone stack operations: -/// op | num -/// ------------ -/// ADD | 3 -/// SWAP | 2 -/// DUP | 6 -/// PUSH | 6 -/// POP | 2 -/// JUMP | 6 -/// -/// TOTAL: 1201 - /// inputs: /// F = f + f'z /// G = g + g'z @@ -66,73 +40,73 @@ mul_fp254_12_1: // stack: f'g', g' , f', inA, inB, out %dup_fp254_6_0 // stack: f'g', f'g', g' , f', inA, inB, out - %store_fp254_6_sh(84) - // stack: f'g', g' , f', inA, inB, out {84: sh(f'g')} - %store_fp254_6(90) - // stack: g' , f', inA, inB, out {84: sh(f'g'), 90: f'g'} + %store_fp254_6_sh(60) + // stack: f'g', g' , f', inA, inB, out {60: sh(f'g')} + %store_fp254_6(66) + // stack: g' , f', inA, inB, out {60: sh(f'g'), 66: f'g'} DUP13 - // stack: inA, g' , f', inA, inB, out {84: sh(f'g'), 90: f'g'} + // stack: inA, g' , f', inA, inB, out {60: sh(f'g'), 66: f'g'} DUP15 - // stack: inB, inA, g' , f', inA, inB, out {84: sh(f'g'), 90: f'g'} + // stack: inB, inA, g' , f', inA, inB, out {60: sh(f'g'), 66: f'g'} %load_fp254_6 - // stack: g , inA, g' , f', inA, inB, out {84: sh(f'g'), 90: f'g'} + // stack: g , inA, g' , f', inA, inB, out {60: sh(f'g'), 66: f'g'} %stack (f: 6, x, g: 6) -> (g, x, f) - // stack: g', inA, g , f', inA, inB, out {84: sh(f'g'), 90: f'g'} + // stack: g', inA, g , f', inA, inB, out {60: sh(f'g'), 66: f'g'} %dup_fp254_6_7 - // stack: g,g', inA, g , f', inA, inB, out {84: sh(f'g'), 90: f'g'} + // stack: g,g', inA, g , f', inA, inB, out {60: sh(f'g'), 66: f'g'} %add_fp254_6 - // stack: g+g', inA, g , f', inA, inB, out {84: sh(f'g'), 90: f'g'} + // stack: g+g', inA, g , f', inA, inB, out {60: sh(f'g'), 66: f'g'} %stack (f: 6, x, g: 6) -> (g, x, f) - // stack: g, inA, g+g', f', inA, inB, out {84: sh(f'g'), 90: f'g'} + // stack: g, inA, g+g', f', inA, inB, out {60: sh(f'g'), 66: f'g'} PUSH mul_fp254_12_2 - // stack: mul_fp254_12_2, g, inA, g+g', f', inA, inB, out {84: sh(f'g'), 90: f'g'} + // stack: mul_fp254_12_2, g, inA, g+g', f', inA, inB, out {60: sh(f'g'), 66: f'g'} SWAP7 - // stack: inA, g, mul_fp254_12_2, g+g', f', inA, inB, out {84: sh(f'g'), 90: f'g'} + // stack: inA, g, mul_fp254_12_2, g+g', f', inA, inB, out {60: sh(f'g'), 66: f'g'} %load_fp254_6 - // stack: f, g, mul_fp254_12_2, g+g', f', inA, inB, out {84: sh(f'g'), 90: f'g'} + // stack: f, g, mul_fp254_12_2, g+g', f', inA, inB, out {60: sh(f'g'), 66: f'g'} %jump(mul_fp254_6) mul_fp254_12_2: - // stack: fg, g+g', f', inA, inB, out {84: sh(f'g'), 90: f'g'} - %store_fp254_6(96) - // stack: g+g', f', inA, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: fg, g+g', f', inA, inB, out {60: sh(f'g'), 66: f'g'} + %store_fp254_6(72) + // stack: g+g', f', inA, inB, out {60: sh(f'g'), 66: f'g', 72: fg} %stack (x: 6, y: 6) -> (y, x) - // stack: f', g+g', inA, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: f', g+g', inA, inB, out {60: sh(f'g'), 66: f'g', 72: fg} PUSH mul_fp254_12_3 - // stack: mul_fp254_12_3, f', g+g', inA, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: mul_fp254_12_3, f', g+g', inA, inB, out {60: sh(f'g'), 66: f'g', 72: fg} SWAP13 - // stack: inA, f', g+g', mul_fp254_12_3, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: inA, f', g+g', mul_fp254_12_3, inB, out {60: sh(f'g'), 66: f'g', 72: fg} %load_fp254_6 - // stack: f,f', g+g', mul_fp254_12_3, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: f,f', g+g', mul_fp254_12_3, inB, out {60: sh(f'g'), 66: f'g', 72: fg} %add_fp254_6 - // stack: f+f', g+g', mul_fp254_12_3, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: f+f', g+g', mul_fp254_12_3, inB, out {60: sh(f'g'), 66: f'g', 72: fg} %jump(mul_fp254_6) mul_fp254_12_3: - // stack: (f+f')(g+g'), inB, out {84: sh(f'g'), 90: f'g', 96: fg} - %load_fp254_6(96) - // stack: fg, (f+f')(g+g'), inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: (f+f')(g+g'), inB, out {60: sh(f'g'), 66: f'g', 72: fg} + %load_fp254_6(72) + // stack: fg, (f+f')(g+g'), inB, out {60: sh(f'g'), 66: f'g', 72: fg} %stack (x: 6, y: 6) -> (y, x) - // stack: (f+f')(g+g'), fg, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: (f+f')(g+g'), fg, inB, out {60: sh(f'g'), 66: f'g', 72: fg} %dup_fp254_6_6 - // stack: fg, (f+f')(g+g'), fg, inB, out {84: sh(f'g'), 90: f'g', 96: fg} - %load_fp254_6(90) - // stack: f'g',fg, (f+f')(g+g'), fg, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: fg, (f+f')(g+g'), fg, inB, out {60: sh(f'g'), 66: f'g', 72: fg} + %load_fp254_6(66) + // stack: f'g',fg, (f+f')(g+g'), fg, inB, out {60: sh(f'g'), 66: f'g', 72: fg} %add_fp254_6 - // stack: f'g'+fg, (f+f')(g+g'), fg, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: f'g'+fg, (f+f')(g+g'), fg, inB, out {60: sh(f'g'), 66: f'g', 72: fg} %subr_fp254_6 - // stack: (f+f')(g+g') - (f'g'+fg), fg, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: (f+f')(g+g') - (f'g'+fg), fg, inB, out {60: sh(f'g'), 66: f'g', 72: fg} DUP14 %add_const(6) - // stack: out', (f+f')(g+g') - (f'g'+fg), fg, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: out', (f+f')(g+g') - (f'g'+fg), fg, inB, out {60: sh(f'g'), 66: f'g', 72: fg} %store_fp254_6 - // stack: fg, inB, out {84: sh(f'g'), 90: f'g', 96: fg} - %load_fp254_6(84) - // stack: sh(f'g') , fg, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: fg, inB, out {60: sh(f'g'), 66: f'g', 72: fg} + %load_fp254_6(60) + // stack: sh(f'g') , fg, inB, out {60: sh(f'g'), 66: f'g', 72: fg} %add_fp254_6 - // stack: sh(f'g') + fg, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: sh(f'g') + fg, inB, out {60: sh(f'g'), 66: f'g', 72: fg} DUP8 - // stack: out, sh(f'g') + fg, inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: out, sh(f'g') + fg, inB, out {60: sh(f'g'), 66: f'g', 72: fg} %store_fp254_6 - // stack: inB, out {84: sh(f'g'), 90: f'g', 96: fg} + // stack: inB, out {60: sh(f'g'), 66: f'g', 72: fg} %pop2 JUMP @@ -141,29 +115,6 @@ mul_fp254_12_3: ///// SPARSE FP12 MULTIPLICATION ///// ////////////////////////////////////// -/// cost: 645 - -/// fp254_6 functions: -/// fn | num | ops | cost -/// --------------------------- -/// load | 2 | 40 | 80 -/// store | 2 | 40 | 80 -/// dup | 4 | 6 | 24 -/// swap | 4 | 16 | 64 -/// add | 4 | 16 | 64 -/// mul_fp254_ | 2 | 21 | 42 -/// mul_fp254_2 | 4 | 59 | 236 -/// -/// lone stack operations: -/// op | num -/// ------------ -/// ADD | 6 -/// DUP | 9 -/// PUSH | 6 -/// POP | 5 -/// -/// TOTAL: 618 - /// input: /// F = f + f'z /// G = g0 + (G1)t + (G2)tz @@ -277,32 +228,6 @@ global mul_fp254_12_sparse: ///// FP12 SQUARING ///// ///////////////////////// -/// cost: 646 - -/// fp254_6 functions: -/// fn | num | ops | cost -/// ------------------------- -/// load | 2 | 40 | 80 -/// store | 2 | 40 | 80 -/// dup | 2 | 6 | 12 -/// swap | 2 | 16 | 32 -/// add | 1 | 16 | 16 -/// mul | 1 | 157 | 157 -/// sq | 2 | 101 | 202 -/// dbl | 1 | 13 | 13 -/// -/// lone stack operations: -/// op | num -/// ------------ -/// ADD | 3 -/// SWAP | 4 -/// DUP | 5 -/// PUSH | 6 -/// POP | 3 -/// JUMP | 4 -/// -/// TOTAL: - /// input: /// F = f + f'z /// diff --git a/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/inverse.asm b/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/inverse.asm index 6214f385..ce4602a9 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/inverse.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/inverse.asm @@ -32,16 +32,19 @@ global inv_fp254_12: // stack: out, f^-1, inp, out, retdest %store_fp254_12 // stack: inp, out, retdest - %stack (inp, out) -> (inp, out, 72, check_inv_fp254_12) - // stack: inp, out, 72, check_inv_fp254_12, retdest + %stack (inp, out) -> (inp, out, 60, check_inv_fp254_12) + // stack: inp, out, 60, check_inv_fp254_12, retdest %jump(mul_fp254_12) check_inv_fp254_12: // stack: retdest - PUSH 72 + PUSH 60 %load_fp254_12 // stack: unit?, retdest %assert_eq_unit_fp254_12 // stack: retdest + PUSH 0 + // stack: 0, retdest + %mstore_kernel_bn254_pairing(60) JUMP %macro prover_inv_fp254_12 diff --git a/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/util.asm b/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/util.asm index af074714..82617e8f 100644 --- a/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/util.asm +++ b/evm/src/cpu/kernel/asm/curve/bn254/field_arithmetic/util.asm @@ -67,6 +67,31 @@ // stack: cx, cy %endmacro +%macro eq_fp254_2 + // stack: x, x_, y, y_ + SWAP3 + // stack: y_, x_, y, x + EQ + // stack: y_==x_, y, x + SWAP2 + // stack: x, y, y_==x_ + EQ + // stack: x==y, y_==x_ + AND +%endmacro + +%macro add_fp254_2 + // stack: x, x_, y, y_ + SWAP3 + // stack: y_, x_, y, x + ADDFP254 + // stack: z_, y, x + SWAP2 + // stack: x, y, z_ + ADDFP254 + // stack: z, z_ +%endmacro + /// Given z = x + iy: Fp254_2, return complex conjugate z': Fp254_2 /// where input is represented z.re, z.im and output as z'.im, z'.re /// cost: 9; note this returns y, x for the output x + yi @@ -116,6 +141,31 @@ // stack: ac - bd, bc + ad %endmacro +// load twisted curve + +%macro load_fp254_4 + // stack: ptr + DUP1 + %add_const(2) + // stack: ind2, ptr + %mload_kernel_bn254_pairing + // stack: x2, ptr + DUP2 + %add_const(1) + // stack: ind1, x2, ptr + %mload_kernel_bn254_pairing + // stack: x1, x2, ptr + DUP3 + %add_const(3) + // stack: ind3, x1, x2, ptr + %mload_kernel_bn254_pairing + // stack: x3, x1, x2, ptr + SWAP3 + // stack: ind0, x1, x2, x3 + %mload_kernel_bn254_pairing + // stack: x0, x1, x2, x3 +%endmacro + // fp254_6 macros %macro load_fp254_6 diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/addresses.asm b/evm/src/cpu/kernel/asm/hash/blake2/addresses.asm similarity index 75% rename from evm/src/cpu/kernel/asm/hash/blake2b/addresses.asm rename to evm/src/cpu/kernel/asm/hash/blake2/addresses.asm index f1d7c3e9..50cb20fc 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/addresses.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2/addresses.asm @@ -1,5 +1,5 @@ // Address where the working version of the hash value is stored. -%macro blake2b_hash_value_addr +%macro blake2_hash_value_addr PUSH 0 // stack: 0 %mload_kernel_general @@ -10,14 +10,14 @@ %endmacro // Address where the working version of the compression internal state is stored. -%macro blake2b_internal_state_addr - %blake2b_hash_value_addr +%macro blake2_internal_state_addr + %blake2_hash_value_addr %add_const(8) %endmacro // Address where the current message block is stored. -%macro blake2b_message_addr - %blake2b_internal_state_addr +%macro blake2_message_addr + %blake2_internal_state_addr %add_const(16) %endmacro diff --git a/evm/src/cpu/kernel/asm/hash/blake2/blake2_f.asm b/evm/src/cpu/kernel/asm/hash/blake2/blake2_f.asm new file mode 100644 index 00000000..731a74c8 --- /dev/null +++ b/evm/src/cpu/kernel/asm/hash/blake2/blake2_f.asm @@ -0,0 +1,143 @@ +global blake2_f: + // stack: rounds, h0...h7, m0...m15, t0, t1, flag, retdest + + // Store the hash values. + %blake2_hash_value_addr + // stack: addr, rounds, h0...h7, m0...m15, t0, t1, flag, retdest + %rep 8 + // stack: addr, rounds, h_i, ... + %stack (addr, rounds, h_i) -> (addr, h_i, addr, rounds) + // stack: addr, h_i, addr, rounds, ... + %mstore_kernel_general + %increment + %endrep + + // stack: addr, rounds, m0...m15, t0, t1, flag, retdest + POP + // stack: rounds, m0...m15, t0, t1, flag, retdest + + // Save the message to the message working space. + %blake2_message_addr + // stack: message_addr, rounds, m0...m15, t0, t1, flag, retdest + %rep 16 + // stack: message_addr, rounds, m_i, ... + %stack (message_addr, rounds, m_i) -> (message_addr, m_i, message_addr, rounds) + // stack: message_addr, m_i, message_addr, rounds, ... + %mstore_kernel_general + %increment + %endrep + + // stack: message_addr, rounds, t0, t1, flag, retdest + POP + // stack: rounds, t0, t1, flag, retdest + + %blake2_hash_value_addr + %add_const(7) + %rep 8 + // stack: addr, ... + DUP1 + // stack: addr, addr, ... + %mload_kernel_general + // stack: val, addr, ... + SWAP1 + // stack: addr, val, ... + %decrement + %endrep + // stack: addr, h_0, ..., h_7, rounds, t0, t1, flag, retdest + POP + // stack: h_0, ..., h_7, rounds, t0, t1, flag, retdest + + // Store the initial 16 values of the internal state. + %blake2_internal_state_addr + // stack: start, h_0, ..., h_7, rounds, t0, t1, flag, retdest + + // First eight words of the internal state: current hash value h_0, ..., h_7. + %rep 8 + SWAP1 + DUP2 + %mstore_kernel_general + %increment + %endrep + // stack: start + 8, rounds, t0, t1, flag, retdest + + // Next four values of the internal state: first four IV values. + PUSH 0 + // stack: 0, start + 8, rounds, t0, t1, flag, retdest + %rep 4 + // stack: i, loc, ... + DUP1 + // stack: i, i, loc, ... + %blake2_iv + // stack: IV_i, i, loc, ... + DUP3 + // stack: loc, IV_i, i, loc, ... + %mstore_kernel_general + // stack: i, loc, ... + %increment + SWAP1 + %increment + SWAP1 + // stack: i + 1, loc + 1,... + %endrep + // stack: 4, start + 12, rounds, t0, t1, flag, retdest + POP + // stack: start + 12, rounds, t0, t1, flag, retdest + SWAP4 + // stack: flag, rounds, t0, t1, start + 12, retdest + %mul_const(0xFFFFFFFFFFFFFFFF) + // stack: invert_if_flag, rounds, t0, t1, start + 12, retdest + %stack (inv, r, t0, t1, s) -> (4, s, t0, t1, inv, 0, r) + // stack: 4, start + 12, t0, t1, invert_if_flag, 0, rounds, retdest + + // Last four values of the internal state: last four IV values, XOR'd with + // the values (t0, t1, invert_if_flag, 0). + %rep 4 + // stack: i, loc, val, next_val,... + DUP1 + // stack: i, i, loc, val, next_val,... + %blake2_iv + // stack: IV_i, i, loc, val, next_val,... + DUP4 + // stack: val, IV_i, i, loc, val, next_val,... + XOR + // stack: val ^ IV_i, i, loc, val, next_val,... + DUP3 + // stack: loc, val ^ IV_i, i, loc, val, next_val,... + %mstore_kernel_general + // stack: i, loc, val, next_val,... + %increment + // stack: i + 1, loc, val, next_val,... + SWAP2 + // stack: val, loc, i + 1, next_val,... + POP + // stack: loc, i + 1, next_val,... + %increment + // stack: loc + 1, i + 1, next_val,... + SWAP1 + // stack: i + 1, loc + 1, next_val,... + %endrep + // stack: 8, start + 16, rounds, retdest + %pop2 + // stack: rounds, retdest + + // Run rounds of G functions. + PUSH g_functions_return + // stack: g_functions_return, rounds, retdest + SWAP1 + // stack: rounds, g_functions_return, retdest + %blake2_internal_state_addr + // stack: start, rounds, g_functions_return, retdest + PUSH 0 + // stack: current_round=0, start, rounds, g_functions_return, retdest + %jump(run_rounds_g_function) +g_functions_return: + // Finalize hash value. + // stack: retdest + PUSH hash_generate_return + // stack: hash_generate_return, retdest + %jump(blake2_generate_all_hash_values) +hash_generate_return: + // stack: h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7', retdest + %stack (h: 8, retdest) -> (retdest, h) + // stack: retdest, h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7' + JUMP diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/main.asm b/evm/src/cpu/kernel/asm/hash/blake2/blake2b.asm similarity index 93% rename from evm/src/cpu/kernel/asm/hash/blake2b/main.asm rename to evm/src/cpu/kernel/asm/hash/blake2/blake2b.asm index 933de505..ffeb26a1 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/main.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2/blake2b.asm @@ -12,4 +12,4 @@ global blake2b: %add_const(1) %mstore_kernel_general // stack: retdest - %jump(blake2b_compression) + %jump(blake2_compression) diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm b/evm/src/cpu/kernel/asm/hash/blake2/compression.asm similarity index 95% rename from evm/src/cpu/kernel/asm/hash/blake2b/compression.asm rename to evm/src/cpu/kernel/asm/hash/blake2/compression.asm index 6e8cdb0a..a45bbbb5 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/compression.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2/compression.asm @@ -1,15 +1,15 @@ -global blake2b_compression: +global blake2_compression: // stack: retdest PUSH 0 // stack: cur_block = 0, retdest PUSH compression_loop // stack: compression_loop, cur_block, retdest - %jump(blake2b_initial_hash_value) + %jump(blake2_initial_hash_value) compression_loop: // stack: h_0, ..., h_7, cur_block, retdest // Store the hash values. - %blake2b_hash_value_addr + %blake2_hash_value_addr // stack: addr, h_0, ..., h_7, cur_block, retdest %rep 8 SWAP1 @@ -63,7 +63,7 @@ compression_loop: // stack: cur_block_start_byte, t, cur_block, is_last_block, retdest // Copy the message from the input space to the message working space. - %blake2b_message_addr + %blake2_message_addr // stack: message_addr, cur_block_start_byte, t, cur_block, is_last_block, retdest %rep 16 // stack: cur_message_addr, cur_block_byte, ... @@ -93,7 +93,7 @@ compression_loop: // stack: is_last_block, t, cur_block, retdest %mul_const(0xFFFFFFFFFFFFFFFF) // stack: invert_if_last_block, t, cur_block, retdest - %blake2b_hash_value_addr + %blake2_hash_value_addr %add_const(7) %rep 8 // stack: addr, ... @@ -110,7 +110,7 @@ compression_loop: // stack: h_0, ..., h_7, invert_if_last_block, t, cur_block, retdest // Store the initial 16 values of the internal state. - %blake2b_internal_state_addr + %blake2_internal_state_addr // stack: start, h_0, ..., h_7, invert_if_last_block, t, cur_block, retdest // First eight words of the internal state: current hash value h_0, ..., h_7. @@ -129,7 +129,7 @@ compression_loop: // stack: i, loc, ... DUP1 // stack: i, i, loc, ... - %blake2b_iv + %blake2_iv // stack: IV_i, i, loc, ... DUP3 // stack: loc, IV_i, i, loc, ... @@ -159,7 +159,7 @@ compression_loop: // stack: i, loc, val, next_val,... DUP1 // stack: i, i, loc, val, next_val,... - %blake2b_iv + %blake2_iv // stack: IV_i, i, loc, val, next_val,... DUP4 // stack: val, IV_i, i, loc, val, next_val,... @@ -187,15 +187,18 @@ compression_loop: // Run 12 rounds of G functions. PUSH g_functions_return // stack: g_functions_return, cur_block, retdest - %blake2b_internal_state_addr - // stack: start, g_functions_return, cur_block, retdest - %jump(run_12_rounds_g_function) + PUSH 12 + %blake2_internal_state_addr + // stack: start, 12, g_functions_return, cur_block, retdest + PUSH 0 + // stack: current_round=0, start, 12, g_functions_return, cur_block, retdest + %jump(run_rounds_g_function) g_functions_return: // Finalize hash value. // stack: cur_block, retdest PUSH hash_generate_return // stack: hash_generate_return, cur_block, retdest - %jump(blake2b_generate_all_hash_values) + %jump(blake2_generate_all_hash_values) hash_generate_return: // stack: h_0', h_1', h_2', h_3', h_4', h_5', h_6', h_7', cur_block, retdest DUP9 diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm b/evm/src/cpu/kernel/asm/hash/blake2/g_functions.asm similarity index 77% rename from evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm rename to evm/src/cpu/kernel/asm/hash/blake2/g_functions.asm index f2d3b1d2..f2540016 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/g_functions.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2/g_functions.asm @@ -1,4 +1,4 @@ -%macro blake2b_g_function +%macro blake2_g_function // Function to mix two input words, x and y, into the four words indexed by a, b, c, d (which // are in the range 0..16) in the internal state. // The internal state is stored in memory starting at the address start. @@ -104,23 +104,23 @@ %mstore_kernel_general %endmacro -%macro call_blake2b_g_function(a, b, c, d, x_idx, y_idx) +%macro call_blake2_g_function(a, b, c, d, x_idx, y_idx) // stack: round, start PUSH $y_idx DUP2 // stack: round, y_idx, round, start - %blake2b_permutation + %blake2_permutation // stack: s[y_idx], round, start - %blake2b_message_addr + %blake2_message_addr ADD %mload_kernel_general // stack: m[s[y_idx]], round, start PUSH $x_idx DUP3 // stack: round, 2, m[s[y_idx]], round, start - %blake2b_permutation + %blake2_permutation // stack: s[x_idx], m[s[y_idx]], round, start - %blake2b_message_addr + %blake2_message_addr ADD %mload_kernel_general // stack: m[s[x_idx]], m[s[y_idx]], round, start @@ -131,48 +131,45 @@ PUSH $b PUSH $a // stack: a, b, c, d, m[s[x_idx]], m[s[y_idx]], start, round, start - %blake2b_g_function + %blake2_g_function // stack: round, start %endmacro run_g_function_round: // stack: round, start, retdest - %call_blake2b_g_function(0, 4, 8, 12, 0, 1) - %call_blake2b_g_function(1, 5, 9, 13, 2, 3) - %call_blake2b_g_function(2, 6, 10, 14, 4, 5) - %call_blake2b_g_function(3, 7, 11, 15, 6, 7) - %call_blake2b_g_function(0, 5, 10, 15, 8, 9) - %call_blake2b_g_function(1, 6, 11, 12, 10, 11) - %call_blake2b_g_function(2, 7, 8, 13, 12, 13) - %call_blake2b_g_function(3, 4, 9, 14, 14, 15) + %call_blake2_g_function(0, 4, 8, 12, 0, 1) + %call_blake2_g_function(1, 5, 9, 13, 2, 3) + %call_blake2_g_function(2, 6, 10, 14, 4, 5) + %call_blake2_g_function(3, 7, 11, 15, 6, 7) + %call_blake2_g_function(0, 5, 10, 15, 8, 9) + %call_blake2_g_function(1, 6, 11, 12, 10, 11) + %call_blake2_g_function(2, 7, 8, 13, 12, 13) + %call_blake2_g_function(3, 4, 9, 14, 14, 15) %stack (r, s, ret) -> (ret, r, s) // stack: retdest, round, start JUMP -global run_12_rounds_g_function: - // stack: start, retdest - PUSH 0 - // stack: round=0, start, retdest -run_next_round_g_function: - // stack: round, start, retdest - PUSH run_next_round_g_function_return - // stack: run_next_round_g_function_return, round, start, retdest - SWAP2 - // stack: start, round, run_next_round_g_function_return, retdest - SWAP1 - // stack: round, start, run_next_round_g_function_return, retdest +global run_rounds_g_function: + // stack: current_round, start, rounds, retdest + DUP3 + // stack: rounds, current_round, start, rounds, retdest + DUP2 + // stack: current_round, rounds, current_round, start, rounds, retdest + EQ + %jumpi(run_rounds_g_function_end) + // stack: current_round, start, rounds, retdest + PUSH run_rounds_g_function_return + // stack: run_rounds_g_function_return, current_round, start, rounds, retdest + %stack (ret, r, s) -> (r, s, ret) + // stack: current_round, start, run_rounds_g_function_return, rounds, retdest %jump(run_g_function_round) -run_next_round_g_function_return: - // stack: round, start, retdest +run_rounds_g_function_return: + // stack: round, start, rounds, retdest %increment - // stack: round+1, start, retdest - DUP1 - // stack: round+1, round+1, start, retdest - %lt_const(12) - // stack: round+1 < 12, round+1, start, retdest - %jumpi(run_next_round_g_function) - // stack: round+1, start, retdest - %pop2 + // stack: round + 1, start, rounds, retdest + %jump(run_rounds_g_function) +run_rounds_g_function_end: + // stack: current_round, start, rounds, retdest + %pop3 // stack: retdest JUMP - diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm b/evm/src/cpu/kernel/asm/hash/blake2/hash.asm similarity index 64% rename from evm/src/cpu/kernel/asm/hash/blake2b/hash.asm rename to evm/src/cpu/kernel/asm/hash/blake2/hash.asm index 654b51b3..701adc27 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/hash.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2/hash.asm @@ -1,18 +1,19 @@ -blake2b_generate_new_hash_value: +// Generate a new hash value from the previous hash value and two elements of the internal state. +blake2_generate_new_hash_value: // stack: i, retdest - %blake2b_hash_value_addr + %blake2_hash_value_addr // stack: addr, i, retdest DUP2 ADD %mload_kernel_general // stack: h_i, i, retdest - %blake2b_internal_state_addr + %blake2_internal_state_addr // stack: addr, h_i, i, retdest DUP3 ADD %mload_kernel_general // stack: v_i, h_i, i, retdest - %blake2b_internal_state_addr + %blake2_internal_state_addr // stack: addr, v_i, h_i, i, retdest SWAP1 // stack: v_i, addr, h_i, i, retdest @@ -28,26 +29,26 @@ blake2b_generate_new_hash_value: SWAP1 JUMP -global blake2b_generate_all_hash_values: +global blake2_generate_all_hash_values: // stack: retdest PUSH 8 // stack: i=8, retdest -blake2b_generate_hash_loop: +blake2_generate_hash_loop: // stack: i, h_i', ..., h_7', retdest %decrement // stack: i-1, h_i', ..., h_7', retdest - PUSH blake2b_generate_hash_return - // stack: blake2b_generate_hash_return, i-1, h_i', ..., h_7', retdest + PUSH blake2_generate_hash_return + // stack: blake2_generate_hash_return, i-1, h_i', ..., h_7', retdest DUP2 - // stack: i-1, blake2b_generate_hash_return, i-1, h_i', ..., h_7', retdest - %jump(blake2b_generate_new_hash_value) -blake2b_generate_hash_return: + // stack: i-1, blake2_generate_hash_return, i-1, h_i', ..., h_7', retdest + %jump(blake2_generate_new_hash_value) +blake2_generate_hash_return: // stack: h_(i-1)', i-1, h_i', ..., h_7', retdest SWAP1 // stack: i-1, h_(i-1)', h_i', ..., h_7', retdest DUP1 // stack: i-1, i-1, h_(i-1)', ..., h_7', retdest - %jumpi(blake2b_generate_hash_loop) + %jumpi(blake2_generate_hash_loop) // stack: i-1=0, h_0', ..., h_7', retdest %stack (i, h: 8, ret) -> (ret, h) // stack: retdest, h_0'...h_7' diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/iv.asm b/evm/src/cpu/kernel/asm/hash/blake2/iv.asm similarity index 69% rename from evm/src/cpu/kernel/asm/hash/blake2b/iv.asm rename to evm/src/cpu/kernel/asm/hash/blake2/iv.asm index 48df86a3..72058ae4 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/iv.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2/iv.asm @@ -1,4 +1,4 @@ -global blake2b_iv_const: +global blake2_iv_const: // IV constants (big-endian) // IV_0 @@ -33,19 +33,19 @@ global blake2b_iv_const: BYTES 91, 224, 205, 25 BYTES 19, 126, 33, 121 -global blake2b_iv: +global blake2_iv: // stack: i, retdest - PUSH blake2b_iv_const - // stack: blake2b_iv_const, i, retdest + PUSH blake2_iv_const + // stack: blake2_iv_const, i, retdest SWAP1 - // stack: i, blake2b_iv_const, retdest + // stack: i, blake2_iv_const, retdest %mul_const(8) ADD - // stack: blake2b_iv_const + 2 * i, retdest + // stack: blake2_iv_const + 2 * i, retdest DUP1 - // stack: blake2b_iv_const + 2 * i, blake2b_iv_const + 2 * i, retdest + // stack: blake2_iv_const + 2 * i, blake2_iv_const + 2 * i, retdest %add_const(4) - // stack: blake2b_iv_const + 2 * i + 1, blake2b_iv_const + 2 * i, retdest + // stack: blake2_iv_const + 2 * i + 1, blake2_iv_const + 2 * i, retdest %mload_kernel_code_u32 SWAP1 %mload_kernel_code_u32 @@ -57,33 +57,33 @@ global blake2b_iv: SWAP1 JUMP -%macro blake2b_iv +%macro blake2_iv %stack (i) -> (i, %%after) - %jump(blake2b_iv) + %jump(blake2_iv) %%after: %endmacro // Load the initial hash value (the IV, but with params XOR'd into the first word). -global blake2b_initial_hash_value: +global blake2_initial_hash_value: // stack: retdest PUSH 8 // stack: i=8, retdest -blake2b_initial_hash_loop: +blake2_initial_hash_loop: // stack: i, IV_i, ..., IV_7, retdest %decrement // stack: i-1, IV_i, ..., IV_7, retdest - PUSH blake2b_initial_hash_return - // stack: blake2b_initial_hash_return, i-1, IV_i, ..., IV_7, retdest + PUSH blake2_initial_hash_return + // stack: blake2_initial_hash_return, i-1, IV_i, ..., IV_7, retdest DUP2 - // stack: i-1, blake2b_initial_hash_return, i-1, IV_i, ..., IV_7, retdest - %jump(blake2b_iv) -blake2b_initial_hash_return: + // stack: i-1, blake2_initial_hash_return, i-1, IV_i, ..., IV_7, retdest + %jump(blake2_iv) +blake2_initial_hash_return: // stack: IV_(i-1), i-1, IV_i, ..., IV_7, retdest SWAP1 // stack: i-1, IV_(i-1), IV_i, ..., IV_7, retdest DUP1 // stack: i-1, i-1, IV_(i-1), ..., IV_7, retdest - %jumpi(blake2b_initial_hash_loop) + %jumpi(blake2_initial_hash_loop) // stack: i-1=0, IV_0, ..., IV_7, retdest POP // stack: IV_0, ..., IV_7, retdest diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/ops.asm b/evm/src/cpu/kernel/asm/hash/blake2/ops.asm similarity index 100% rename from evm/src/cpu/kernel/asm/hash/blake2b/ops.asm rename to evm/src/cpu/kernel/asm/hash/blake2/ops.asm diff --git a/evm/src/cpu/kernel/asm/hash/blake2b/permutations.asm b/evm/src/cpu/kernel/asm/hash/blake2/permutations.asm similarity index 95% rename from evm/src/cpu/kernel/asm/hash/blake2b/permutations.asm rename to evm/src/cpu/kernel/asm/hash/blake2/permutations.asm index 1ef455f1..44070b7a 100644 --- a/evm/src/cpu/kernel/asm/hash/blake2b/permutations.asm +++ b/evm/src/cpu/kernel/asm/hash/blake2/permutations.asm @@ -58,7 +58,7 @@ global permutation_9_constants: BYTES 15, 11, 9, 14 BYTES 3, 12, 13, 0 -global blake2b_permutation: +global blake2_permutation: // stack: i, round, retdest PUSH permutation_0_constants // stack: permutation_0_constants, i, round, retdest @@ -74,12 +74,12 @@ global blake2b_permutation: SWAP1 JUMP -%macro blake2b_permutation +%macro blake2_permutation // stack: round, i PUSH %%after // stack: %%after, round, i SWAP2 // stack: i, round, %%after - %jump(blake2b_permutation) + %jump(blake2_permutation) %%after: %endmacro diff --git a/evm/src/cpu/kernel/asm/memory/metadata.asm b/evm/src/cpu/kernel/asm/memory/metadata.asm index c158718b..42a88957 100644 --- a/evm/src/cpu/kernel/asm/memory/metadata.asm +++ b/evm/src/cpu/kernel/asm/memory/metadata.asm @@ -34,6 +34,15 @@ // stack: (empty) %endmacro +// Store the given context metadata field to memory. +%macro mstore_context_metadata(field, value) + PUSH $value + PUSH $field + // stack: offset, value + %mstore_current(@SEGMENT_CONTEXT_METADATA) + // stack: (empty) +%endmacro + %macro mstore_parent_context_metadata(field) // stack: value %mload_context_metadata(@CTX_METADATA_PARENT_CONTEXT) diff --git a/evm/src/cpu/kernel/asm/memory/packing.asm b/evm/src/cpu/kernel/asm/memory/packing.asm index f12c7b17..a224fbb4 100644 --- a/evm/src/cpu/kernel/asm/memory/packing.asm +++ b/evm/src/cpu/kernel/asm/memory/packing.asm @@ -43,6 +43,12 @@ mload_packing_return: %stack (packed_value, addr: 3, len, retdest) -> (retdest, packed_value) JUMP +%macro mload_packing + %stack (addr: 3, len) -> (addr, len, %%after) + %jump(mload_packing) +%%after: +%endmacro + // Pre stack: context, segment, offset, value, len, retdest // Post stack: offset' global mstore_unpacking: @@ -82,3 +88,9 @@ mstore_unpacking_finish: %pop3 %stack (offset, value, len, retdest) -> (retdest, offset) JUMP + +%macro mstore_unpacking + %stack (addr: 3, value, len) -> (addr, value, len, %%after) + %jump(mstore_unpacking) +%%after: +%endmacro diff --git a/evm/src/cpu/kernel/asm/mpt/insert/insert.asm b/evm/src/cpu/kernel/asm/mpt/insert/insert.asm index 2830d376..e5ee1326 100644 --- a/evm/src/cpu/kernel/asm/mpt/insert/insert.asm +++ b/evm/src/cpu/kernel/asm/mpt/insert/insert.asm @@ -17,6 +17,7 @@ global mpt_insert: // There's still the MPT_NODE_HASH case, but if we hit a hash node, // it means the prover failed to provide necessary Merkle data, so panic. +global mpt_insert_hash_node: PANIC mpt_insert_empty: diff --git a/evm/src/cpu/kernel/asm/mpt/read.asm b/evm/src/cpu/kernel/asm/mpt/read.asm index 94cfbaf5..4a57dd4d 100644 --- a/evm/src/cpu/kernel/asm/mpt/read.asm +++ b/evm/src/cpu/kernel/asm/mpt/read.asm @@ -42,6 +42,7 @@ global mpt_read: // There's still the MPT_NODE_HASH case, but if we hit a hash node, // it means the prover failed to provide necessary Merkle data, so panic. +global mpt_read_hash_node: PANIC global mpt_read_empty: diff --git a/evm/src/cpu/kernel/asm/mpt/storage/storage_read.asm b/evm/src/cpu/kernel/asm/mpt/storage/storage_read.asm index edb63e2d..84d8d0ef 100644 --- a/evm/src/cpu/kernel/asm/mpt/storage/storage_read.asm +++ b/evm/src/cpu/kernel/asm/mpt/storage/storage_read.asm @@ -1,3 +1,34 @@ +%macro sload_current + %stack (slot) -> (slot, %%after) + %jump(sload_current) +%%after: +%endmacro + +global sload_current: + %stack (slot) -> (slot, after_storage_read) + %slot_to_storage_key + // stack: storage_key, after_storage_read + PUSH 64 // storage_key has 64 nibbles + %current_storage_trie + // stack: storage_root_ptr, 64, storage_key, after_storage_read + %jump(mpt_read) + +global after_storage_read: + // stack: value_ptr, retdest + DUP1 %jumpi(storage_key_exists) + + // Storage key not found. Return default value_ptr = 0, + // which derefs to 0 since @SEGMENT_TRIE_DATA[0] = 0. + %stack (value_ptr, retdest) -> (retdest, 0) + JUMP + +global storage_key_exists: + // stack: value_ptr, retdest + %mload_trie_data + // stack: value, retdest + SWAP1 + JUMP + // Read a word from the current account's storage trie. // // Pre stack: kexit_info, slot @@ -6,38 +37,20 @@ global sys_sload: // stack: kexit_info, slot SWAP1 - // stack: slot, kexit_info - DUP1 %address - // stack: addr, slot, slot, kexit_info - %insert_accessed_storage_keys PUSH @GAS_COLDSLOAD_MINUS_WARMACCESS - MUL - PUSH @GAS_WARMACCESS - ADD - %stack (gas, slot, kexit_info) -> (gas, kexit_info, slot) + DUP1 + // stack: slot, slot, kexit_info + %sload_current + + %stack (value, slot, kexit_info) -> (slot, value, kexit_info, value) + %address + // stack: addr, slot, value, kexit_info, value + %insert_accessed_storage_keys + // stack: cold_access, old_value, kexit_info, value + SWAP1 POP + // stack: cold_access, kexit_info, value + %mul_const(@GAS_COLDSLOAD_MINUS_WARMACCESS) + %add_const(@GAS_WARMACCESS) %charge_gas - // stack: kexit_info, slot - - SWAP1 - %stack (slot) -> (slot, after_storage_read) - %slot_to_storage_key - // stack: storage_key, after_storage_read, kexit_info - PUSH 64 // storage_key has 64 nibbles - %current_storage_trie - // stack: storage_root_ptr, 64, storage_key, after_storage_read, kexit_info - %jump(mpt_read) - -after_storage_read: - // stack: value_ptr, kexit_info - DUP1 %jumpi(storage_key_exists) - - // Storage key not found. Return default value_ptr = 0, - // which derefs to 0 since @SEGMENT_TRIE_DATA[0] = 0. - %stack (value_ptr, kexit_info) -> (kexit_info, 0) + // stack: kexit_info, value EXIT_KERNEL -storage_key_exists: - // stack: value_ptr, kexit_info - %mload_trie_data - // stack: value, kexit_info - SWAP1 - EXIT_KERNEL diff --git a/evm/src/cpu/kernel/asm/mpt/storage/storage_write.asm b/evm/src/cpu/kernel/asm/mpt/storage/storage_write.asm index 6da8f567..af8bc912 100644 --- a/evm/src/cpu/kernel/asm/mpt/storage/storage_write.asm +++ b/evm/src/cpu/kernel/asm/mpt/storage/storage_write.asm @@ -6,14 +6,42 @@ global sys_sstore: %check_static %stack (kexit_info, slot, value) -> (slot, kexit_info, slot, value) - %address %insert_accessed_storage_keys POP // TODO: Use return value in gas calculation. - // TODO: Assuming a cold zero -> nonzero write for now. - PUSH @GAS_COLDSLOAD - PUSH @GAS_SSET - ADD + %sload_current + %address + %stack (addr, current_value, kexit_info, slot, value) -> (addr, slot, current_value, current_value, kexit_info, slot, value) + %insert_accessed_storage_keys + // stack: cold_access, original_value, current_value, kexit_info, slot, value + %mul_const(@GAS_COLDSLOAD) + + // Check for warm access. + %stack (gas, original_value, current_value, kexit_info, slot, value) -> + (value, current_value, current_value, original_value, gas, original_value, current_value, kexit_info, slot, value) + EQ SWAP2 EQ ISZERO + // stack: current_value==original_value, value==current_value, gas, original_value, current_value, kexit_info, slot, value) + ADD // OR + %jumpi(sstore_warm) + + // Check for sset (set a zero storage slot to a non-zero value). + // stack: gas, original_value, current_value, kexit_info, slot, value + DUP2 ISZERO %mul_const(@GAS_SSET) ADD + + // Check for sreset (set a non-zero storage slot to a non-zero value). + // stack: gas, original_value, current_value, kexit_info, slot, value + DUP2 ISZERO ISZERO %mul_const(@GAS_SRESET) ADD + %jump(sstore_charge_gas) + +sstore_warm: + // stack: gas, original_value, current_value, kexit_info, slot, value) + %add_const(@GAS_WARMACCESS) + +sstore_charge_gas: + %stack (gas, original_value, current_value, kexit_info, slot, value) -> (gas, kexit_info, current_value, slot, value) %charge_gas - %stack (kexit_info, slot, value) -> (slot, value, kexit_info) + // Check if `value` is equal to `current_value`, and if so exit the kernel early. + %stack (kexit_info, current_value, slot, value) -> (value, current_value, slot, value, kexit_info) + EQ %jumpi(sstore_noop) + // TODO: If value = 0, delete the key instead of inserting 0. // stack: slot, value, kexit_info @@ -57,3 +85,8 @@ after_storage_insert: after_state_insert: // stack: kexit_info EXIT_KERNEL + +sstore_noop: + // stack: slot, value, kexit_info + %pop2 + EXIT_KERNEL diff --git a/evm/src/cpu/kernel/assembler.rs b/evm/src/cpu/kernel/assembler.rs index 2afd328f..ffa3caca 100644 --- a/evm/src/cpu/kernel/assembler.rs +++ b/evm/src/cpu/kernel/assembler.rs @@ -1,10 +1,12 @@ use std::collections::HashMap; +use std::fs; use std::time::Instant; use ethereum_types::U256; use itertools::{izip, Itertools}; use keccak_hash::keccak; use log::debug; +use serde::{Deserialize, Serialize}; use super::ast::PushTarget; use crate::cpu::kernel::ast::Item::LocalLabelDeclaration; @@ -20,7 +22,7 @@ use crate::generation::prover_input::ProverInputFn; /// nontrivial given the circular dependency between an offset and its size. pub(crate) const BYTES_PER_OFFSET: u8 = 3; -#[derive(PartialEq, Eq, Debug)] +#[derive(PartialEq, Eq, Debug, Serialize, Deserialize)] pub struct Kernel { pub(crate) code: Vec, @@ -60,6 +62,16 @@ impl Kernel { } } + pub fn to_file(&self, path: &str) { + let kernel_serialized = serde_json::to_string(self).unwrap(); + fs::write(path, kernel_serialized).expect("Unable to write kernel to file"); + } + + pub fn from_file(path: &str) -> Self { + let bytes = fs::read(path).expect("Unable to read kernel file"); + serde_json::from_slice(&bytes).unwrap() + } + /// Get a string representation of the current offset for debugging purposes. pub(crate) fn offset_name(&self, offset: usize) -> String { match self diff --git a/evm/src/cpu/kernel/constants/mod.rs b/evm/src/cpu/kernel/constants/mod.rs index 75a96403..b1486589 100644 --- a/evm/src/cpu/kernel/constants/mod.rs +++ b/evm/src/cpu/kernel/constants/mod.rs @@ -40,6 +40,14 @@ pub fn evm_constants() -> HashMap { c.insert(name.into(), U256::from(value)); } + for (name, value) in CODE_SIZE_LIMIT { + c.insert(name.into(), U256::from(value)); + } + + for (name, value) in SNARKV_POINTERS { + c.insert(name.into(), U256::from(value)); + } + for segment in Segment::all() { c.insert(segment.var_name().into(), (segment as u32).into()); } @@ -83,7 +91,7 @@ const HASH_CONSTANTS: [(&str, [u8; 32]); 2] = [ ), ]; -const EC_CONSTANTS: [(&str, [u8; 32]); 18] = [ +const EC_CONSTANTS: [(&str, [u8; 32]); 20] = [ ( "U256_MAX", hex!("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), @@ -92,6 +100,14 @@ const EC_CONSTANTS: [(&str, [u8; 32]); 18] = [ "BN_BASE", hex!("30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"), ), + ( + "BN_TWISTED_RE", + hex!("2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e5"), + ), + ( + "BN_TWISTED_IM", + hex!("009713b03af0fed4cd2cafadeed8fdf4a74fa084e52d1852e4a2bd0685c315d2"), + ), ( "BN_SCALAR", hex!("30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"), @@ -225,5 +241,13 @@ const PRECOMPILES_GAS: [(&str, u16); 13] = [ ("BN_MUL_GAS", 6_000), ("SNARKV_STATIC_GAS", 45_000), ("SNARKV_DYNAMIC_GAS", 34_000), - ("BLAKE2_F_DYNAMIC_GAS", 1), + ("BLAKE2_F__GAS", 1), +]; + +const SNARKV_POINTERS: [(&str, u64); 2] = [("SNARKV_INP", 112), ("SNARKV_OUT", 100)]; + +const CODE_SIZE_LIMIT: [(&str, u64); 3] = [ + ("MAX_CODE_SIZE", 0x6000), + ("MAX_INITCODE_SIZE", 0xc000), + ("INITCODE_WORD_COST", 2), ]; diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index fa3788cf..4f47c91f 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -332,21 +332,21 @@ impl<'a> Interpreter<'a> { 0x1d => self.run_sar(), // "SAR", 0x20 => self.run_keccak256(), // "KECCAK256", 0x21 => self.run_keccak_general(), // "KECCAK_GENERAL", - 0x30 => todo!(), // "ADDRESS", + 0x30 => self.run_address(), // "ADDRESS", 0x31 => todo!(), // "BALANCE", - 0x32 => todo!(), // "ORIGIN", - 0x33 => todo!(), // "CALLER", + 0x32 => self.run_origin(), // "ORIGIN", + 0x33 => self.run_caller(), // "CALLER", 0x34 => self.run_callvalue(), // "CALLVALUE", 0x35 => self.run_calldataload(), // "CALLDATALOAD", 0x36 => self.run_calldatasize(), // "CALLDATASIZE", 0x37 => self.run_calldatacopy(), // "CALLDATACOPY", - 0x38 => todo!(), // "CODESIZE", - 0x39 => todo!(), // "CODECOPY", - 0x3a => todo!(), // "GASPRICE", + 0x38 => self.run_codesize(), // "CODESIZE", + 0x39 => self.run_codecopy(), // "CODECOPY", + 0x3a => self.run_gasprice(), // "GASPRICE", 0x3b => todo!(), // "EXTCODESIZE", 0x3c => todo!(), // "EXTCODECOPY", - 0x3d => todo!(), // "RETURNDATASIZE", - 0x3e => todo!(), // "RETURNDATACOPY", + 0x3d => self.run_returndatasize(), // "RETURNDATASIZE", + 0x3e => self.run_returndatacopy(), // "RETURNDATACOPY", 0x3f => todo!(), // "EXTCODEHASH", 0x40 => todo!(), // "BLOCKHASH", 0x41 => self.run_coinbase(), // "COINBASE", @@ -734,6 +734,26 @@ impl<'a> Interpreter<'a> { self.push(U256::from_big_endian(hash.as_bytes())); } + fn run_address(&mut self) { + self.push( + self.generation_state.memory.contexts[self.context].segments + [Segment::ContextMetadata as usize] + .get(ContextMetadata::Address as usize), + ) + } + + fn run_origin(&mut self) { + self.push(self.get_txn_field(NormalizedTxnField::Origin)) + } + + fn run_caller(&mut self) { + self.push( + self.generation_state.memory.contexts[self.context].segments + [Segment::ContextMetadata as usize] + .get(ContextMetadata::Caller as usize), + ) + } + fn run_callvalue(&mut self) { self.push( self.generation_state.memory.contexts[self.context].segments @@ -784,6 +804,63 @@ impl<'a> Interpreter<'a> { } } + fn run_codesize(&mut self) { + self.push( + self.generation_state.memory.contexts[self.context].segments + [Segment::ContextMetadata as usize] + .get(ContextMetadata::CodeSize as usize), + ) + } + + fn run_codecopy(&mut self) { + let dest_offset = self.pop().as_usize(); + let offset = self.pop().as_usize(); + let size = self.pop().as_usize(); + for i in 0..size { + let code_byte = + self.generation_state + .memory + .mload_general(self.context, Segment::Code, offset + i); + self.generation_state.memory.mstore_general( + self.context, + Segment::MainMemory, + dest_offset + i, + code_byte, + ); + } + } + + fn run_gasprice(&mut self) { + self.push(self.get_txn_field(NormalizedTxnField::ComputedFeePerGas)) + } + + fn run_returndatasize(&mut self) { + self.push( + self.generation_state.memory.contexts[self.context].segments + [Segment::ContextMetadata as usize] + .get(ContextMetadata::ReturndataSize as usize), + ) + } + + fn run_returndatacopy(&mut self) { + let dest_offset = self.pop().as_usize(); + let offset = self.pop().as_usize(); + let size = self.pop().as_usize(); + for i in 0..size { + let returndata_byte = self.generation_state.memory.mload_general( + self.context, + Segment::Returndata, + offset + i, + ); + self.generation_state.memory.mstore_general( + self.context, + Segment::MainMemory, + dest_offset + i, + returndata_byte, + ); + } + } + fn run_coinbase(&mut self) { self.push(self.get_global_metadata_field(GlobalMetadata::BlockBeneficiary)) } diff --git a/evm/src/cpu/kernel/tests/bignum/mod.rs b/evm/src/cpu/kernel/tests/bignum/mod.rs index 259d5889..69474134 100644 --- a/evm/src/cpu/kernel/tests/bignum/mod.rs +++ b/evm/src/cpu/kernel/tests/bignum/mod.rs @@ -29,6 +29,7 @@ const TEST_DATA_ADDMUL_OUTPUTS: &str = "addmul_outputs"; const TEST_DATA_MUL_OUTPUTS: &str = "mul_outputs"; const TEST_DATA_MODMUL_OUTPUTS: &str = "modmul_outputs"; const TEST_DATA_MODEXP_OUTPUTS: &str = "modexp_outputs"; +const TEST_DATA_MODEXP_OUTPUTS_FULL: &str = "modexp_outputs_full"; const BIT_SIZES_TO_TEST: [usize; 15] = [ 0, 1, 2, 127, 128, 129, 255, 256, 257, 512, 1000, 1023, 1024, 1025, 31415, @@ -282,7 +283,7 @@ fn test_modexp_bignum(b: BigUint, e: BigUint, m: BigUint, expected_output: BigUi let scratch_3 = 7 * len; // size 2*len let scratch_4 = 9 * len; // size 2*len let scratch_5 = 11 * len; // size 2*len - let (new_memory, _new_stack) = run_test( + let (mut new_memory, _new_stack) = run_test( "modexp_bignum", memory, vec![ @@ -298,6 +299,10 @@ fn test_modexp_bignum(b: BigUint, e: BigUint, m: BigUint, expected_output: BigUi scratch_5.into(), ], )?; + new_memory.resize( + new_memory.len().max(output_start_loc + output_len), + 0.into(), + ); let output = mem_vec_to_biguint(&new_memory[output_start_loc..output_start_loc + output_len]); assert_eq!(output, expected_output); @@ -506,6 +511,47 @@ fn test_modmul_bignum_all() -> Result<()> { #[test] fn test_modexp_bignum_all() -> Result<()> { + let exp_bit_sizes = vec![2, 9, 11, 16]; + + for bit_size in &BIT_SIZES_TO_TEST[3..7] { + for exp_bit_size in &exp_bit_sizes { + let b = gen_bignum(*bit_size); + let e = gen_bignum(*exp_bit_size); + let m = gen_bignum(*bit_size); + if !m.is_zero() { + let output = b.clone().modpow(&e, &m); + test_modexp_bignum(b, e, m, output)?; + } + + let b = max_bignum(*bit_size); + let e = max_bignum(*exp_bit_size); + let m = max_bignum(*bit_size); + if !m.is_zero() { + let output = b.modpow(&e, &m); + test_modexp_bignum(b, e, m, output)?; + } + } + } + + let inputs = test_data_biguint(TEST_DATA_BIGNUM_INPUTS); + let modexp_outputs = test_data_biguint(TEST_DATA_MODEXP_OUTPUTS); + let mut modexp_outputs_iter = modexp_outputs.into_iter(); + for b in &inputs[..9] { + // Include only smaller exponents, to keep tests from becoming too slow. + for e in &inputs[..6] { + for m in &inputs[..9] { + let output = modexp_outputs_iter.next().unwrap(); + test_modexp_bignum(b.clone(), e.clone(), m.clone(), output)?; + } + } + } + + Ok(()) +} + +#[test] +#[ignore] // Too slow to run on CI. +fn test_modexp_bignum_all_full() -> Result<()> { // Only test smaller values for exponent. let exp_bit_sizes = vec![2, 100, 127, 128, 129]; @@ -530,13 +576,12 @@ fn test_modexp_bignum_all() -> Result<()> { } let inputs = test_data_biguint(TEST_DATA_BIGNUM_INPUTS); - let modexp_outputs = test_data_biguint(TEST_DATA_MODEXP_OUTPUTS); + let modexp_outputs = test_data_biguint(TEST_DATA_MODEXP_OUTPUTS_FULL); let mut modexp_outputs_iter = modexp_outputs.into_iter(); for b in &inputs { // Include only smaller exponents, to keep tests from becoming too slow. for e in &inputs[..7] { - // For m, skip the first input, which is zero. - for m in &inputs[1..] { + for m in &inputs { let output = modexp_outputs_iter.next().unwrap(); test_modexp_bignum(b.clone(), e.clone(), m.clone(), output)?; } diff --git a/evm/src/cpu/kernel/tests/bignum/test_data/modexp_outputs b/evm/src/cpu/kernel/tests/bignum/test_data/modexp_outputs index 543f2456..e744abfe 100644 --- a/evm/src/cpu/kernel/tests/bignum/test_data/modexp_outputs +++ b/evm/src/cpu/kernel/tests/bignum/test_data/modexp_outputs @@ -1,3 +1,5 @@ +0 +0 1 1 1 @@ -5,32 +7,6 @@ 1 1 1 -1 -1 -1 -1 -1 -1 -1 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 0 0 0 @@ -78,31 +54,6 @@ 0 0 0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -1 -1 -1 -1 -1 -1 -1 1 1 1 @@ -111,19 +62,6 @@ 1 1 0 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 1 @@ -132,26 +70,7 @@ 1 1 1 -1 -1 -1 -1 -1 -1 0 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 1 @@ -160,19 +79,8 @@ 1 1 1 -1 -1 -1 -1 -1 -1 0 -1 -1 -1 -1 -1 -1 +0 1 1 1 @@ -181,6 +89,7 @@ 1 1 0 +0 1 1 1 @@ -188,6 +97,8 @@ 1 1 1 +0 +0 1 1 1 @@ -195,6 +106,8 @@ 1 1 1 +0 +0 1 1 1 @@ -202,12 +115,7 @@ 1 1 1 -1 -1 -1 -1 -1 -1 +0 0 0 21 @@ -216,12 +124,7 @@ 21 21 21 -21 -21 -21 -21 -21 -21 +0 0 0 309 @@ -230,12 +133,7 @@ 5842587018385982521381124421 5842587018385982521381124421 5842587018385982521381124421 -5842587018385982521381124421 -5842587018385982521381124421 -5842587018385982521381124421 -5842587018385982521381124421 -5842587018385982521381124421 -5842587018385982521381124421 +0 0 0 169 @@ -244,12 +142,7 @@ 56424335153278151789523409664996995581162067431087086213061556134977632914449 28522822713801268588036943398667804191745915805046109428618723188679866502161 31706899640538131462557950751123123992423743151283050819612655945089903928361 -1626949887851522216050918195251855667936019233629512014857416262882459162506846482867598420124655122796334698879679058256496280388512107842122550266897 -3456644180256483296524124683106942480722843461305992677766332070622386105650335816178720659995652203171430416751945868032819203139048842456194585731900908 -6658621772694490037410881754126282754619191463278934006643576166056374826395321115677201742806056121601730868428249390651828408651815409287407418905560894 -2188719266686453452930405899199235044753192686954839466176162624683199938127424638750308949204554559166758220326224401920489333667474175603924673521175569 -6123795749220870070888957688126499811687439102580957107200324670516588221814874336490966980509479995815372272026912905873172415251713982723428918913460049360806724424126068570078686852874442462644585471618684175096178614463856372447395923736155404199722474001519774161213336837801565210105511353961489 -21733503076822274238215696841643994124465086209245797663103653662160183433375325239843496825811576935617701675430794656070743382504699894663869396198800858049123949931636855462200807567378261808374350727356914491895652225869425999023896449493174464626623879583913773127532285149008185808669981457659175411110681467646497612200879789944122607924142423967190374513947785974855081897919456043288039161362376188824242511311222201467365944959686354630547972 +0 0 0 501 @@ -258,12 +151,7 @@ 1950081577919450936472563652220396332042682835950151822696779432336405037057 89705076639198166424843052158202309145112564081865083245095301525986942648321 161580799869287829122678259656507339171378764462605635944908315838074450225541 -119111099232869461943255917709559971029471489246820147748389884283220680875449970114508127905572794881898139347855563980545398801715283004632963481601 -2340550614088062323035521333507933205420749928049240408457893198554975629380160875595843975025528241912895931129450956293623201875314056184463318790281141 -9658263392514739927662836103088426769134800307082054844647958520598804818351406352355729785509682250873421347556031006118797390529574721358615425274369903 -4647428455414528310735419222346137778331384012634538551014412602117023622880652353771726881116679285768237724443091476402706202263926819772616832419102721 -4105943439683327149496995432917731734349623330617416765444758819531334403459555965005600275959433826680513222328275949889828341311187920607090355380046540579908947040106371789193081113409035077098486792404385747715667974409598976733840748313362165044117491316370103556122704636978835764926194391187457 -28645769207390246795138025157012310806200949947458739337397211179141156343070918052774971042600619689369921890873698767518883214265612034430865062720501567943382208222029969252942575712244757709457154177152894494535042763023966349374143513752560929258976200745379909865727692592552226677876935892285307870731885285227994511501363645824725317338462104668462291125838004650196777287385052153407326433125418796527586257544647700218132360787318720777100831 +0 0 0 361 @@ -272,33 +160,8 @@ 16196520401421423385786338368215415982698439852342927927980513551465948892989 25448670785549471741073803593965176921136178751681542787519830340854942519101 208746275861806526568796522022506082930013066308764940459575687169043802837726 -1405046333573254154362728566205440659065789596162373947677922992002779706150301916091557545001891022758808422492046510466274149060187173986171371114301 -4109950494713993893142341968876859588899697995149574488387185284937507905151071268229544837244462536429462991654059099118254521939414590134998340719446475 -844468128021093833521017258842640197099986073495355910940365822372902152436005754957689228609364360833723273104884193579513808541852965164830299937335266 -4841490524461293458775865719630252706317774131797304941603107709106391551373400827563106022147424343461775948749633172375219539070706909069136692738510653 -7273173343143062730116325603650929579289657910222550340667872300408581237430197382410051906687144077202863842569199267502562443871512075909613158282763060439777587356925584672588460920490499485650537891223823337073005846524449165906099576249848470870580763810627114753982636643198831102678792829914941 -28046651509673296558629424584063249731669578718145238261130675472681779110268140721442904856558473621167727640615713345067811595168883183810857635560068796253449136272338112002671317203041266904678503071806393932350113469015095445921306266450082664767442783548486830460889239098543969021176454257806145698621983814164824010062639366791567674987083305882183188142795298379711201433370817683665471805353684719806585009665707704695044458674998071553291930 0 0 -625 -268138222663085878899055263745 -24352877979184920020466043837322220276 -34834821705580047870320807590104282154881192418891909778995311440625022271489 -107743694625338367548278288079708411290661245510293131426406157730911501680641 -118236082284243482508848267847953427609046466568857110070954823921881387042791 -314573941438267599881423465112523804707482828315168316649965301003974020258305280672271797781262619454377248842022918324247905069090181693176119558145 -1855138457669725370795603609175257635850787505475418783821961151316324964106211402480574231460442281436102848418947738954752184731638654925034081955953702 -540244355168038810439245856412365092477075663815074675095751794574495975677637107674742162091364766891790053303512224504116561928038681836474597949011431 -22981118609480295020302390537085998300920429526471726567398293023445956296114258286587907654003543675558782486527003079440548040281611791112262372611325953 -6951084942072485004602792642768728173731086340286788608361716458550264564967198485402397629024961093884371645054422216571333979237852755889053521204926773487912585360977600077358240969038752377614031729154197921202596341838056184283438478913472604440906205314054471964590715571751484579200485577195521 -33110177016061425855873050546700017053104395816945007989361323145125706671247445069352845357430211170094709814842881235921295997550815440918489134011703431383697905373158706778267396782608658244538288231998579363509402374934461434235027334113339168112113235815389810790459912467851237692233387577938141749136860402850772218835907235676691685574301095898691939348359786379380091090548413315980192736618829302554133559996331787700989395178469522588716520 -1 -1 -1 -1 -1 -1 -1 1 1 1 @@ -307,6 +170,7 @@ 1 1 0 +0 5 0 908 @@ -314,12 +178,7 @@ 908 908 908 -908 -908 -908 -908 -908 -908 +0 0 20 0 @@ -328,12 +187,7 @@ 131765835135960660552807451524089028158233849469678584969822208 131765835135960660552807451524089028158233849469678584969822208 131765835135960660552807451524089028158233849469678584969822208 -131765835135960660552807451524089028158233849469678584969822208 -131765835135960660552807451524089028158233849469678584969822208 -131765835135960660552807451524089028158233849469678584969822208 -131765835135960660552807451524089028158233849469678584969822208 -131765835135960660552807451524089028158233849469678584969822208 -131765835135960660552807451524089028158233849469678584969822208 +0 0 4 0 @@ -342,12 +196,7 @@ 39622934661811821553763744630506213929196932096668444518123439737845028225024 11662422067291787594026815204283885427659195788081136348012846295902003920896 196850617542733211416217278410575369737876420896781853126317893743949824168141 -2683172422101341871005722746258376340307644953044191751444605309114182348157085796971409744620711498580309302182985308212586435414886374286350975238144 -3484767657771443762420853002633790658478025026595023030399445962591501743459655114168018705061836715787328457528577115561192630399480939905028160741471812 -826369288885297875981086985856579353870084500166446900173411432842694716669231467968748002518734902939451616083284004742033317955616293179658208664891021 -22202087655311450647135419149250531087927146350676835345655785380157598138557194753184373294689489916297473124960377821312544654416163136210039001929744384 -5867290145612847972373997073309915340902862989135230389100858222930181445218524888102172986857355110271349287326639814908840476463002707271202642441777343076399506363351555575169003649515921567023847735339868023560115487675698958077623452675911334000167018425794800395206246266829715066932889888227328 -6613183629137681279087117062720950270493246965665653353814545527865422606963860172688377962562995370224937823909402574900579151120138866568996446233013596125260317722731462888479963743727090415264356847381807593700110142796538796057208396283278444005900325957636550564820775653606338375016287872257899328947954420594292130424139307631549548532332505581708062755002798299585128036685598543159971540741219646857517061331622628267531564244017650020495747 +0 0 16 0 @@ -356,12 +205,7 @@ 12836249910756408599207651670402691470189457253048470571408310293697570799616 89957821137359056393801843026144645477720961240687064113356371611922523488256 186628143002875342454100646575613221588500043779267673627434610024013060416436 -57810819572866260801492155256759413876483749626656973452292976127618654522846001818070108358802224938885657621123322444739974859616822961140014252032 -3586935919752527353984027215088868451772937854013928716747601409083300019440067660008036473811750553056666280422401084064457379199486614970622678033275267 -11435172354316143741773241295887896087133672859698695578907055835282817586890921066517171600518967766241323412371609567006600523639894522363112407210324509 -15149040910228070805694652326182650730845401534077532391632591405118117144643051256922675471878552887101021773709591676502861584900921169634374950540279808 -4352157484305171917414400736736974322230700579288245632185873247491184195730898991437344106792548923888580847271187361373793947913900504263300740461685586606358268444829299316120497158281612307205034189058550655426163375786508423319573157431875873496129188997627673849109716799860744235677774874935296 -24655669188850607011881278212500400404795975111909544352042335778191251712079013936428534764805902649880208931889745231758199080159268053714657146238568540885026847910322826747799581068534312565470606227666766265055047378610529765358823154325332792516751882522879055713682140011583363538951298044003038164972718406208736221386819603161486554136555558914468701937507614273119563961498468609340048830696861579728696267046957787891673696324284268296592010 +0 0 20 0 @@ -370,33 +214,8 @@ 6919681730812989105961680682293875199438003339556752544938537021004054528000 111415284413375575279069783743044849713138799010818236990829948938800785784832 2671371225382503991550810752302543668307773911036096851249073522360117594907 -3196717805164369921128204528085730572110803813535280667544983013152498020676968653158980718912649444544541678773084521623843027455344890340658923962368 -1238216679956500444264616028232887647747940490327785007262817775307688862239704307927037312429375849475227131933476467593816834523153314124523020288669761 -11027839566584582470519059073521721670466350661122931561173065258823257321580571220589430064206794766082774897831215317085884716390531116370426677289293467 -2022634134337910980433929460688286697109516578140587883097911933500075648632085115589857581520940210394331242638360018211669767050461136520845948293742592 -10563633569776338863997290139173141475448369840952853889830314442522523629045149771574493906944834062931170774068081579834010118509008087930549452650473545745495642812824093639365842736796360564731533873032609439082530461159518786091690259460722677617446344350444358408993792066302845337558798580056064 -12824372483412385861669199400205004566724858538474303800494747762440269818404951059835352877380356415578282393020015717678870100435248949572316256128400151457357751827937645568676301032707345577683626030686702589840795543017433728119877924868065460364994171679438527788229515928801213836621134264837100427090704057536254578168099404041165838330491183445948965724854110273982983705590693431410760655261855587976233430383255504302646591767978918856150863 0 -16 0 -1074929557660986703509960261632 -310308103079793704575757950092990989086 -45830377016999964195415645114843325971494172471228418297876829545637299093504 -101060401631390047762632218125084929475187708866471415222687033363449381912576 -130474939331530224408995396282441784260419370120207375947563617259552477561186 -2355941672152922857080918796873312219472407301725598088408859346047953344326591361786096096705419672944173727217808802505470853131296892573634755821568 -1316454184270635300204354290028403652975569924791362044247281669809677739990181839549155145392827806973474851174980544451539377747682379975465127356763282 -1438923259930704879657001108769207409876637192084506601145086731796010515496862959970405934371385188574753305943073462813023599491372378876317837370133527 -3751312292780009820304966556683277538490745683704566160236438372682961982986048670343223416367070064938538731816396930813426231559274819821553090255912960 -1940812635972614747466109277992726340848630072707912304640929127912329064087768370597314351590495738864766600213011565689114652892971392013558976325205708385347610787529794002191911334996478270010718764337052847791754345043741034784083083057127201125434592632894903882614831512194082202201086343774208 -18021429550902313767357511567759601756356647595430959756983217203030344977480124379576430774082535283607744829695070380577186356624450300463936384113907659808083311741619551253897275613952178963423684191041978549151808016907300923588567042148170623295160006737511147422878843457848402746737171046772562256330802876792353279038296767776587843369343160581335263159088902098345089167246852603087883635586088364841422928542822495523562426663120058625130224 -1 -1 -1 -1 -1 -1 -1 1 1 1 @@ -405,6 +224,7 @@ 1 1 0 +0 1 160 0 @@ -412,12 +232,7 @@ 1267650597867046177654064545792 1267650597867046177654064545792 1267650597867046177654064545792 -1267650597867046177654064545792 -1267650597867046177654064545792 -1267650597867046177654064545792 -1267650597867046177654064545792 -1267650597867046177654064545792 -1267650597867046177654064545792 +0 0 1 312 @@ -426,12 +241,7 @@ 43179616752915754651548109831528453372307533305539601542967080491130306953216 17577324162381258630474635337405333643146914114762554675606397827067886436352 24302243256145833886805174285503224697924343810958724170274784478667392432942 -2455073261000987918671945239574537486815749129964150471432702836905807585811396531610253905941293957332101512899044268740293992626007607127083491262464 -1077242566599992264249169571444336551411248487528972966637628471569432402384081668659908518747150256909990581460430565820193233307152827275575539899170758 -13073126603118771003805243197447306343271660677454831683154753707889268850436361661628016500641989777790467968280342772010149753216162050495370020985042625 -20998284069276981893190892536141895412205721732777582241948778013718640245971369156599887283883776856426273476192138787335689583588114031186267728857006080 -9895687224941938536992396259410735585498593485949826080868857632522617767715344081138466212990213054852400162837201310103538489800752934384336855267244623540847988822661005638222750684585548680702427543946047149085737687298331380026993105619948605279977576581565502199750299350287074957960820551581696 -20330471440166965706846550975654713890652417870226965905923146732405275304116721701265925830155132264142742283294001589707864787012405943213404119056019767248830063561795881859861133225475226440778669219796000363700993800365618586534090055278009338085683400928935050079339354878794718829630509418239605013719652286315425501679172072558159972643172621667859406242995437705040600030465945478758984414424005354845660305153595541783513391622742931412397213 +0 0 1 104 @@ -440,12 +250,7 @@ 55518020932873470218319288289245721296726991639699521321270937184899723952128 112628490590563884833405386435939751658584809004247538619207709896844158959616 5922841801814876533914360761483372163277450765372489528717658348886181069591 -2564817866139487541320504390805327358442199437592476952716613284652304314970931783459808490723737608880437784464822337666800292869999879039669023801344 -398463165885851265042497914635418511071393473395199568610621293995767308754233006664812655610002899538162554806154059048581305437649155727562069976883240 -11845528388829065193137342380492024118612741433871500160171557205928409375950091328760923663375034610212896359622832576619866946421226527978810823517767195 -14358105553296630195074581259093482904061967322039003650287242246847189245898106579740731184467142158444184654938258232190794449000467281976153220954718208 -8724046093635123581045526611633144774030370511834937151107124782757791671626741053594651970417496109952491903631645243345303037829497694196648996824200842520327610130549622341880795147265298435073802163280558766387420771897374896142381275499545438532579692773311139765116038449092364593363996255453184 -7405751147045042170442233630583323728853684512846881489652126352481138580343808254155794109418214211938178940574968048906922983783473775456657957578956020062439863911134378708160968666080910153080712910213618483308281268671163181505833074812656056876069748103205570600234366976045578890131475420080402034328956554170169080621020401502037844882798216390950223171848402002782939936087102304599378409563146797567777945011228369651410924564026853389623899 +0 0 1 820 @@ -454,12 +259,7 @@ 30966933304654384056562480896427815565136977421206545694335698204395214733312 82119970857858981914834549178898483174623261423734314091990446749364630061056 17335345295685259772267515166522970642719156121663286480022840319361908909536 -2314109225631884097329071519390891278705119245506353961085436228554532183298397816728391508885600113143907388260489256179338412441709786163323932246016 -4631405091549513365618104032938964387036004178571962489969520427453823044584554995003585135178458975230639830757208179222570849484879646249622084312888560 -3444397905407459769678888603161852413323651620442902175963208412202586537665061311535470334927067187735566811052881866689633902610439151941964220310971721 -11022665256141102472940378463699540949238908279778600071282259749712264960911250408144499157327170064963756957223649027433072458668570655608803856874471424 -1149493853622624808951893133000311601994554292143458692563726487021442743023464156391272602913618081421849882373383362805133207036962919354651311719256865291542887462144185133870512659168195548443958858491083766172641138569350640961793151838633119997925593177565959971136032627767125937725101431586816 -33826235027620277221304225387441637043664748422971678909986538422912010422112157161893624219767292791117193745224367096503738217947106120516761159479154541434507081629430040858090956433405889392516115304242345520261752268880565405366762142190916629498630348949119250396008683103444433062400285561745138697466209715485695816216568719770239333912527091815214766386375891923409276947021071960719444492160160428059721106325731604292930332234337842204147864 +0 0 1 556 @@ -468,40 +268,16 @@ 26118405364148793884093212339004353321168506206731428575114534916913543249920 57371932048380839143645765917598495087491748880125189544237269309841806983168 21907868082798520198592834325003250611892002016702940923441999346792832444518 -1983010347367670533586158746720918426725859238638826101738778473039940830888567731427474683445100376144146431698278643920358008341796317600412673769472 -2606640266791684811701307747992020704987556721798189736831558708134786779427826595516656788456057404569214323026273791700577064277010116095681833143649967 -13236721874325271723025473459287198396620022329708721480674722710511848773677038674125983763343329458361710367424043866874114509274517527946107266648826241 -2194764262264585667059858125941452105865892742975859841108712998947329687982788884647082000066632025028061458492389933022294535208755309187928296471396352 -204309344949056669756457560943541502699162518130681389120968275752795085274348261696673034188427085066909553427932479215637901119300398120607913517490261871972031537818140203177045230095689669755307530773417745785587153318345703950240765166902545254968306769674012995910371703479321012180805203525632 -10264690826749513230358184346151757544435920255861917426522952736046646856221133004608608156420505462277842900802805838197750732768067254277504971522375036317591854497981434809048391519641178668320883274044427240323533445722232511793549340418570864089915044452302975506872587143937799291446332426997988486186420527441812688737993113263455373353444533552218632449194597995340604827994474495437980620590990737309478013598033891846127947111075468737667005 +0 0 1 -340 +1 +1 +1 +1 +1 +1 0 -998905004448329441454522467488976926 -4927413081688125725138099137632369118723706439675800220006419132836783063040 -84352496855087273591478468036086052663893064063467212113548648838828702826496 -107903726561082941806970174768933557491971859433891364382659859844852394460986 -2319608449060187999684790351453024136538626650066803987926996295704247719880909540662904401039557482146640056079214446055684288473572080013990468517888 -3229174536762564836328011009025477898799910197080321024421312234854337921760217907684033379377552188666880062823173769265434474194314757844200157057703739 -1423443399352876324872592588473564301454095472277230446652620290446968276830664095418889947537872334002573975742103104497418388304230155249816071500187318 -13271987893729173924722826693052254951121133786126776376721905614595108288958742926463506237918989779603882913708829786515628223071604050168421092211818496 -4601804950488826494167685270760036664893236871832882663322149997831635784436681349022970436277158840767511957327023782099178816414168280990846944956415328077143836700852459969097230280911772452313608645578171031885121285719728944681182534906015347671757933737842458574792144739909126764366189368967168 -857479341893762723161505496595417165049229108770456259194779683064981414515307526837194732925160817384742675728910002446344631831783238186297049084225178616281383135711434226661298337670136802627018979396403252157951565007991996142431686702381810961834168285921445713777780679851079387977357401452731948432492393075599084080144393344786427912661179463547435908489113931675491545959285551896625752610448451638448866450487107364387582471184159571074175 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 3 827 @@ -510,12 +286,7 @@ 340282366920938463463374607431768211455 340282366920938463463374607431768211455 340282366920938463463374607431768211455 -340282366920938463463374607431768211455 -340282366920938463463374607431768211455 -340282366920938463463374607431768211455 -340282366920938463463374607431768211455 -340282366920938463463374607431768211455 -340282366920938463463374607431768211455 +0 0 6 883 @@ -524,12 +295,7 @@ 46236487016914252810359942606653565611806735985113905556189104784313205915647 10141063897320778511376522974043618320650062159021091584566880470490557710335 78190442020038551706136595408815344419350554279639655464038299447602848702950 -5264101363851496851433282540836956541101368807777991293344941388857765825339723752116476539712642325105142882152577944513410405922445245546495 -4274984277410983807532089925150768740931153586735292491383528412859129258433112273099949231101888023707157602612028830310955239728286706980227996295680904 -4270974226494341897280469825731968602385022467387106892501039803249858350601697035152008485439522684257776791254316572547412071137653017182505839419643661 -13396349486729820333578617551105577176007659045388305976467765207187599750765003306881228272040491956095560694041316948995285357929407282941862450720407551 -7272107039633935551591400893562218992924676126105717460127870788013015797432989950658439810996946118473016444182279548084821341534588106843981486932573866517856077154029000374861836839944939375168692527383494491021504979898639557323084128794258468279454347871141949852954622679013053097034606228537343 -4024681230464577896473641062977638052721373802614679861781599094800123563495932827294337297078407941193782141971643023681636515761542479169594195464691208343312685562380387487284859733536618386758347477945214430213026727223935953464725954742778965827480842612641410510935813810716514672572547641952771526945317395473564193078364064275666028733643505934945383834412116242058173431754061071146756970189972698298803191543547137198977609076610984071659602 +0 0 9 257 @@ -538,12 +304,7 @@ 15737081446634197346448238543290111090647984834849920547563580853437339795457 17796349368611048392083206935955698801625485975991150886750776582747396767745 87042183171820405426823900509602437553981065786933287231059322442248803404950 -1872579959911606123270219006911173139292436983412774739613566899721054729108647438934586909747652198625290890899088832075544795394544595455034418790401 -1412681115817651652595578657596182058840351787817337255523617847758399731969803154217604617416738018019082279140815098858103221944816565427541047989874575 -4658367006324170812599422256080523502806559591300942419231897265664273942632706886970881430455450954648568107656318501922464893981721336262565505150036230 -14176910549874618607407657930219555895908368234965503682114333452984200436110890119648814677868732070859714001297650338292337460853941658691514163789824001 -10406141366637179727319354575345523585198131445101199614041074944321283006099873985593501657875961054722659983805551437203724122242706464697758320434979188004227317962713115722036138880945569626619984608791769942492732939213456452058202944264921993463328233802720857330376187422666409410692321365721089 -10395612500766716889498607750936120296402196259538392550447369284462443521703220089793251095458371323061297217472250908800671528775762556075103359185483070524957305359923584052804148040373365959462663236012867000124244297047788081721144621971838346991977347509145949856725062202597193816565726641315796367190832625962761358471335171016260228986247896685407131636015822155281779300035844200755378496158753851995591046914832248761433986938772195242877368 +0 0 18 33 @@ -552,12 +313,7 @@ 3229040287801688211109538153528907359157521678782897421936034456493449281537 43674379635609232592374808570316762057057239464140599073454048485319171375105 206574116687852983759940670284339037133974987477578735810964428283965343595925 -992419486452661222145984173974299929589195994084254138342964889584701966790230864615423021215758227245793655600475560820231442393114209491163228930049 -867054567978498531065761454390276935399048293801759280371014301861063097032842313817626802406894612171009202210526526325159367606967184116106222709354994 -1139630468367775490336631812613571548165746938068725127033848437473514644842035232747054391798198457303514508910901267746988126523368144746838663920634335 -23229321847788976756725283113649930370792069582610592470231250035730463613494249923319913356844479204498929051652932802538286625056745478043326957712572417 -9736393711512156676697476147793419950291123704462141453822865116456122510755024608271599163197384361427364997715319701954677607307667967970314752567786721165005692082957947082637259982017311319355343061387874272954404686630047193927081844593179586832512413662625777018863736941974537158057318938574849 -29060966502289446762773527309129862532230651461433207672335349512468314509838153919700009183613587271911577714742576064666717735555966747507902189346161650683338259890112722032957837515796161015553488353420265757652831337573527786397820733107579265093849101520705267722311390949184609843752198524487159831619663983822993580005359239978622465631388243890591655090541561296753761373713020979145034193471076120681878728773637249747647754915387598872616720 +0 0 6 515 @@ -566,33 +322,8 @@ 51292049059523452610506083592610024599583816874803914322375719502751486443519 27936184963965071766976378876421641742859886164075202272073313001233759338495 13449010363647692703508349667378797433516756740069562881064298383864033242575 -3007865154522879628838942692472346158555510514358321404385880396123667658951604878264737502736736088022367734668256726008347601098598257350026528292863 -4592124389902639952157884879500633941880823326525745966966661569784155220592348399170518240885296517746840773500441608980855453698091666787607843899145829 -2534000532084385254011173048792691142730414486367806853286959714601853302234763393270798424710144792599095332446397093107565422159020315343985501774159892 -15542028513463832582045168836396386001625310864606581833373826691519685781220976702479707834361513658452848273358428791133185408252751328679278502490406911 -8412092699337531037787046468081884678528099171920466557150153840517555441701513747481625075399369031563363890720070512929533552898722630769019938157826781770070834212210476738149888508884995219178808489342005439633046794302879951435958690454691212867490392351796728559169919328744714016812403628441599 -33830106619343559855814362535589211924203444187711545573142435195593086511328847987971132905556265209639736610793615201190028737913698317064723958072416856829114676871668002147741395866264126547513200446705626505358831619201264825403452572963238108829829155602404009157481163421152595415563917960605621467418213148184629070795051181898610631600475141956877575705748780551030079535279390822434842453037166286438591706030638299501460332593582408355701860 0 -18 -793 -197025322184063122457151668225 0 -2920290130103280979299916267396345225782651892499153454132172827501589954561 -13539515947035890751742634672716012403055571371579065400912721307212126879745 -158307368218366335347174104263331952261761856873568291783365034272918926713725 -1815215034323212852396070290108011856137567892027865591453387561513196098766849400352437123459701948446227688759510102669983999161585665721657907478529 -1313998427018914497731975785557000192540482097274033470133500010806607846954570954898528158955314391602627353029912678650049483923494107529991028097123237 -3558766711272482011504448167665545486379425587311683496485361619290623375415884515332307272266520310480366471739749365076632262898225547952923293595733728 -12553285567146229581143238572266763310070996960196734618418238189114111487087176302379917708160855599798506766652438515952406574783180790667512374443900929 -7334817924922815993844247909475070087281744359403537502526299289084906210615638233675595384256475356219608076645306747447902878463733829119335042011404584250731670549991672963716637969622660364460577985065151746629898564582075539489021571565895740532432194811300868623563387061791622447110534725632001 -23782765486299170619653377638001085226491596574584464898704365460889585549109410835130873109130617681428671842761358877647827448636728589051462502446489865488918684639573926641287700719325755142839567735191800755724523772975690463187286534957742763295127666200814136161150077106827630178598134515070629372319788894871157470118252128383759870860296840401062420257746959094446951505893201604983152709936368275205715331071029074242829807922867113197544311 -1 -1 -1 -1 -1 -1 -1 1 1 1 @@ -601,6 +332,7 @@ 1 1 0 +0 13 120 145483342680740634262446800896 @@ -608,12 +340,7 @@ 0 57896044618658097611351864738157061705262361561497619362091104892532012613632 57896044618658097611351864738157061705262361561497619362091104892532012613632 -57896044618658097611351864738157061705262361561497619362091104892532012613632 -57896044618658097611351864738157061705262361561497619362091104892532012613632 -57896044618658097611351864738157061705262361561497619362091104892532012613632 -57896044618658097611351864738157061705262361561497619362091104892532012613632 -57896044618658097611351864738157061705262361561497619362091104892532012613632 -57896044618658097611351864738157061705262361561497619362091104892532012613632 +0 0 13 588 @@ -622,12 +349,7 @@ 0 110892457497452005403581430237946183767136503117162566153549053970000476372992 189155222634588421211288058609537932434095476696578287565656039885444474631257 -2273620924019535126443377586964826655364563651525119527623848142652704686460888155148600115764101538394624015930243455367013584122475807191504328327168 -4718242244578560577933620411853546035676043730739668011742858611491785678155178214146108560032528947886096115390359535573786208426628238424552910518225609 -5354055707309912886614410393569876624773886934053676926684306993550773407750553762949175437211369217571333055727536737153756343047932603108461352921558471 -25365469084896632438831937795363726978720559453448504867481253590410035300967847867532559492662554029011867176416570131146842894254418120377083085899956224 -3757578315429890131235493992649120836389777957623924867570462633554550213501972098599500200214418806050260619389176706179192857127356531256489639401245300261047944289856878017480929565003165920312519588880225017152460044735034054827437950584392201188531715789576969371957511327370055692497232100065280 -15253647830407583141547363309274688061512324567554978156617633130357138545424717528865172974543531851717065650176201323923438841684204225724333600965120694028156933393649297273989140526164630013338776321111358526273453216724232977621477413581907629724731139256634361519074694441451017597636834753579301989604484256575167632226812528730857727215779131743352342648896678763239802119364145369163238668734832577049562494126042421431166789603595812731097644 +0 0 1 40 @@ -636,12 +358,7 @@ 0 80370191198978495857548168233658974342470488197481929432131097469881528877056 57378722967569161858531872288267370459698099854972954033385237027489681458401 -1266685019038549670156131957936105569332778969355417709861995585153701875900859319531983550779488151228898464900331805671022343202096261388828403564544 -4007316844468480444786209097240877242135343232573279363036730296408578470321526904806238868824798952651885510964017728127623908601645102032546751410140438 -10809419853862469069424671860661466104583061712836069230246390212316112130066125544420392691125603322947467815628376833408555549515946984480656880021651380 -1850019664799561828446887689859810128523634383437118940053115370804552962470182093340221950762057683211340120378944062888849213207787569638787758996586496 -10601990121875444106767485014957569656736374682760746624229897705443065241696873816254196776531479775231519679842263077569364013222740741226981954932170832015958461515448934122357561377336766895492078707171525168572538566552146347786295929420700117193632141413315523494643262931844585426006586863648768 -28508439658852678107665155972792842206287661263432505699726272954607239927480675380840437519995918207158667265234219975518214394765767765060644972734142492559569055673270149098731414835043509095821925810223271993800625817447425850539568468486314744453634053786991467939161412382560926663037539162059349437789487898945599562092125838900291727653251158883415512092048307124528711465011479916269612248338449949978973514357464893125428777863416659679547856 +0 0 1 412 @@ -650,12 +367,7 @@ 0 83509925808939041219467836468971382374645162274742749382395185649452566183936 130737775035935455315064283330339683168756409303633081183629254780389959201676 -1434569753988477104238938016621393717922537334575046291954564311951618243596601987643360144150294172150115473086916074540367171462792383909655650238464 -1628053801365026402929640374014765553703071179544257678606217838338537677419257865674757673512650450839264317003577960931228650240349967706184064403237564 -9528330235712431695508651348872596587940214388314172729001944199117139203073649460506789237728120154262303033791074115687461447137304611451019062450033166 -4143685306341548231504887338288660968707624803700705709343351955022110657856432837240377395875927501705908299984063250507069218496972459859740452129341440 -7458796787007837004712235977661789416985633116148918114280732607368491371782197880736806507445402383850766124164590251775004743970419719155659219708540227384445648790605201658248003617820791276119099869395011354078111731072541949883562883648840249249510616061917989297687935201755531527627290779320320 -32562067415072239193840246016716096268985518768069377976952382448190013331748839889139882498448289400400757853808819969655477710609459023410834554011819177127950022030097667847290699738778525902043243023637500887645421123275436342796803206335835309725086671594130477830499317959884237607103504253659374293236168368765551370942719124768927841271066850440350466143929412219292019549741670650796223584473716652795660385114766444013731211424652116447263871 +0 0 13 172 @@ -664,40 +376,16 @@ 0 16620630689278877851873420518904814002737213549417357007588250730268341567488 135713742926877628027400301750580746786742856540376082400065882631878268256343 -2763703332326056666675771568612443973251095331788999459280007079557401109082037332230846287789955462113928953782310527076648915665904957779729505583104 -2824436745521083250434559952136747236272578919613634664272602203887075383079538439468738841849895882276490589513884561192461063598286468221544075155317742 -5573805721606072201024464091196637283572352485715830551875562715416314364897955988150179092473897788638830452265884540199145584775259028641318262487547968 -4057677748936070618844094810747404761610038515502652344029344965685330894561953958031306249055086692013728933315233447834639061360828462307224389794398208 -5784796441501303882265576458065577676796946906096587650440461985290957058829054847129274276669244130440701590711328886296578934710291199277222000695005904568910944144582690667672945892139302539970077461280831973659874645207539604298268246794000404198399473879519441764495134256354634643900506642055168 -27926326319599679689321531260972663838094871826824944182829437453915195129091090522882499755811750977000485175430688110045958476439969398119085050907218285133398254355136892348358892640344189516520338960373270419222146816179324538294913966113727777599048121837592524129719217066985421105982471108005619786655759673241565670064548335049859971927753583710716463045164399494432220069188699341199218886010208466355717064435978272444257082416306333129756637 +0 0 1 -316 -71681696331238174643235848192 -237948749361170373273798232100232473131 +1 +1 +1 +1 +1 +1 0 -83778207020986728476145484258908144082269934037053254715152909632561590829056 -221509419269785716227233899606918240392102327497753358712085651922766861983551 -79315321146264542418544101067771002872575912085812381774279752184308118738724006743714953988893825146071572131840361116250475308904572550776268783616 -3141911224089662508005439140547996848411545433412668670184330989833051246389721569721933639157984163331306326586989550527910321306108944965118472936437373 -7056836934790078890629897242686908388561326030807269602244791722619134700685270860402176255162872248124156286310896170748542196945067054699971451991857017 -19653627676393504480845906820110557077219860495796321885850081681411361274754697849285945541928921052518914208933686885858752894441356909201046802838585344 -9683163169799910671354293907568672381107851254294002957127298074004784481037839670632521780649121780401926430183897832969166328037150107405373952334255388250551814999528496252119738140300795402325170176550137471892883221550198049424126188627968546323114246254076277484385665176149283033551751023165440 -16624156320060803479105655673708019093724859687856669901597323414016554716036267842673966767033477560761233327486461318339447602081002795923903537066139452947433702150477385673218681847304679734427371239598965310386307842392299911576146706135987880533258592628104184356529185963203696378503916725011966153849031868468134727041450767305498104186987445591841485782186937410888737747186818628076918609180767095586934198055427262999789790553748249680495030 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 296 @@ -706,12 +394,7 @@ 57896044618447473228882389021020048158893283581286713298429387432951596187648 0 115792089237105570840234253759177109864155645142784332660520492325483608801280 -115792089237105570840234253759177109864155645142784332660520492325483608801280 -115792089237105570840234253759177109864155645142784332660520492325483608801280 -115792089237105570840234253759177109864155645142784332660520492325483608801280 -115792089237105570840234253759177109864155645142784332660520492325483608801280 -115792089237105570840234253759177109864155645142784332660520492325483608801280 -115792089237105570840234253759177109864155645142784332660520492325483608801280 +0 0 1 576 @@ -720,12 +403,7 @@ 19171508671161797156614710182257630792593514679646789380628699765537557708800 0 83428280595193522049620352001877162940388365577102322638744416599597810157500 -2383427170914810336472146115059610133938440685431786051901133872674812685256214433004766571822808713024702089068992214313240618263661712821448505032704 -3543131743813569641335946273683240931826614024019546282265784836005828417893383322228810942263163410646159776819689834231870373605456177912242267705525812 -3201888256116239379504709172928241207634570507519243666267842079354934745091409880730742354222322722404797424377578771802961012486596039415971972097760189 -4721437724763666216912653616574178996088489462586407187533602132486864388960603129501403388719024042140502457650359696753171122610737975161314352895623168 -4837005771188282971935407089657043487019168586830902406943047384547231889109685650839979581515180335872804870881921663586570464571734302300526117404207560436370497430406529093043461008746914986949167798918225893839078999027089145630276892534029320307629830535688150128766532774699466359036038881476608 -14649538351459906058741226567249552783659862553950272384082762918585814063949755926925837749924987768515640556340283222177993507623584971708636450851372760248421615193323790004038285247571226256925988926564345592560305885533717028697892048480537531768156992921912334188996185887209116041579498773878589854193709529378983879403351880522010001304035516272695800246073052875655027404371065192473535905888797416623200692032732055359224565770757807776402248 +0 0 1 36 @@ -734,12 +412,7 @@ 30121405346709427309695531890582421791203074728165296179965859962342252478464 0 42435402933391614285072618340065308663204835805291910450325661435301593697950 -2723474109035793261196285209480520006576094880312369272827686699655845402902440783445003022414244095338650103254192634946547862282922709256827062714368 -2366345409847035124374650448074879585773647708631341355179263252964806807879670158353217088899380315556678858307117619065167384939975455280949447515369567 -13191762144369989130760985435688757812828881793396707694471183793997116204175863881278765015080350072806582669305591779418584954819749146010893985699341570 -13301718048073450430547712527884367748161420561064642294015103641915503834019416126543999762601710015216018615418920000282926562454589067268249095837319168 -9391084627976509998795459430240744148278054341930566001679916095435726828423076214248815541128823696135595365039592549569884022180775653333743792501900544596968163878667412922650434328739761497861462359470427289461508215509253714046614049256486535514319610185904255475081934449011049104472856091164672 -7354519734624006876179435352514087233297298809165790925922795673494116116655759843604125047003991533731435264281192336103815636919140214933167210447579405287498010619153112075099093006295245714725499708200955637344617781547142646463544824911616543471784407538549422907647454757217835547791373749159887064306770673576013161274312701154428403688789455533688700894782342280314573076414570285083813175010660748552095076178542404200729953294305533949916369 +0 0 1 440 @@ -748,12 +421,7 @@ 2219279707535425826019993588723715376924609733291444929791090369095624818688 0 125210688265252194710996471277583934881834379414003707914695928587186801398100 -2487150548049686483577986346486345896197470598544823109842683510353284256291612496904302366730404150860292761990843784069916754136788389949069787660288 -4665596396220733640168649174535027159196397070342267963244347648666006311146611981668674060621225920926771133113452576288300091774874699771692345174655000 -3321497911172409553001804903171022673679565313946048256955779288266740305599386551480119034076080803092083102364750364882135550956683614114559617436903767 -12793018574047350137248079672509016968931556367756809163171704828712247163091906244764359814474025125944855607579655662889196220595429789208504167192068096 -53376332098238942237058265874185808937843825750519948116793606680215516009579250363703665595580229234392378617881585484051555178971860102930997202131537779988926409286598509132127582039147943382149262722075187323524856262926753691304631056792968823860069761025941851259838112955696975940302445477888 -19923611385063419051384812211007230050060207617704483913568487020386612675099470773370717657374861044992939563075540978208277455783654511878538950291808744228334204522554009216806163343973548097843046243549174022328700851586804159313601461216565391487177684815873717679059019796761667669491458419882506144601791158476320022142436392910265642137030624038589331580844312683788761159106773836049440285100183481918534526738945630197824116914691687618255349 +0 0 1 192 @@ -762,40 +430,16 @@ 53535005721204496876936515275724889845817409334527168350061458281042045566976 0 35340054082346922390131417025011886439703502295343037882213639103251549897900 -1009118888395535762047061721180456806194166614565541999396274651526674300640202434640874659775936931364083317600665242264448090018723165449003588386816 -2392526284157188505188392690013448960986950491375028571859495919060981215979514074503662055648827708202314679184721591212604079491336362235307206391833426 -4218798631160832202661168847672965043016773529025064083427701368151868437320716279368190139450621334670500868570495563594616568204374854957138784941027870 -483959849385694416988953239395437763233014877575377690428602005170645490229330810160206389562974522706669622381302406569004289640692782430642495811485696 -5378187878649244049653816422966231411527819255785030355895748698860605699359864142748498411935665392420582096163286983444186194198233107257177496094195107895074872712441771334893808547355079651652051885242856910759791626223884287793085982216148604993192657336251775590261767563683353789243163725004800 -32818464130850205246467682789169918339482637627874185171064672905340879331577799944668821853359894806536530578739275748702344346513314541480359830789085211784100573835252933274724858360731614753176374779056545876405547001284878778829435612577133895639650041742079621450894836820613872672377867785376695923853094317140137484881752383755066269670040095376107209776772131790659671001065420513961226520376690403010625950002651054751819424823637290081472387 +0 0 1 -532 -1054096356549212854433844559872 -295167673194252499689312720648542539285 -18569052254320792886536065199102429830591425911674802887337142847422563614720 +1 +1 +1 +1 +1 +1 0 -97896720708781798801687131335879227111506109430789223376551280139659913587350 -1634009508410887242647804687779058371050929112656850452045994095398157878806417902701340267267910135426243622542827304902620893278343438781078703177728 -862159323782353319562779470318789629705961090965297342320245925680889441369443314188948203254697918300615698372425403937959274851949640461887703447193841 -7173051967940195554257280536479042043827601659905799457098258573897554700956880589901442356513658795342086705483095145011273200575189131337241532322688171 -14778026829432832620717758207920676238440861869481283376192906681351851826811501922740289231253685732115671799215873523794595875524613727991318894568538112 -9743687940329798123999941212290764982687335446528161500746427614131976390988057307286128146303396660476408358788140586545951034783015956845304363388199684637129690259093248015713809461202981476094156748203762337562483089253099990690430154929727318541968412839173701447769414174975320032013797193416704 -11665082978646551184396197271822834154968679459301162080769250076458812934480608734582177152703187939426687223961976274547227366150916137584109379949067630208858792329939845114289322648585580755616610302258512584989884644997352747262852786631806253344305668062922039579812843505258327167494097412319071183014601014647063034669866001123270058546336028496149434886023941746932012392894414262845484462335477059377413559348424920746843432610014073597213636 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 4 771 @@ -804,12 +448,7 @@ 57895602960811796650871631801676582813791887579127636891104569893774562426879 115791647579680518644692972256970658065423327120836162316857392245886991466495 0 -231583736816786089484927226016147767929578972263620494977377884571370600267775 -231583736816786089484927226016147767929578972263620494977377884571370600267775 -231583736816786089484927226016147767929578972263620494977377884571370600267775 -231583736816786089484927226016147767929578972263620494977377884571370600267775 -231583736816786089484927226016147767929578972263620494977377884571370600267775 -231583736816786089484927226016147767929578972263620494977377884571370600267775 +0 0 1 43 @@ -818,12 +457,7 @@ 4960875119562861993119998040929006214931859756877807299872704131313015193599 83869314384839239184918994159181415456293389193220202757469792852202756243455 0 -446851339107039186419289111745794461503166996177271801631416983378126123568718875224988495884755883200400258616355472950696139342262717961597794385919 -2457416883750494183832570853589468397031071769924709837931117427688509339888648917495080941417107639148560803684251898538275596934697939251488325371868124 -4104295260045454815975181617904063417540583687524096503951973213007375671429493052370291608008405377354342405201451646421020861407202042797591936611216757 -5398900427668751217850873803494875937404578551752982184373461962988643267134263496913051856036153441820443871129747572123078186712219756428262779956232191 -1007218583726087024268446200406511915539475815058077584580036382202886749107233498655574150289262240696650047786995708501433958989054102047792490904760349592902261758650729430923763743863222004063022441814082480599888346140582423150899204609625387915667741403853025291774074147108688932055983390195711 -23380145599663018538794334849478795685367611191421527490464557496763254711125422173670092394177895709559935294769976819952372348766078401488089491379204849818544542158134496224979987816433965631446790943462305235568068590323956450149969681186862262029930095126068867520361231472357215498730835672433665458819876311608479695607535070166435960898021320714467950701155806239822554229659277947203115399804129178780683995750006285527204806890220566457893817 +0 0 16 417 @@ -832,12 +466,7 @@ 49219110417420231511113764378238860427237875311237523872333835875498405658625 102059959947892163134217117691190804610012473033509494849327043219849901768705 0 -294741958829571476136926871256484717091819171292816858794352010629523393545452840612410539842221513608737007525936314033110034418127477704314176143361 -3610022075817249902604614007613923579547402226882542852635039392814912818785402413253274269359316403441885507203823787712636067696281764519975647585808036 -3482683400560148150354019097545843271463498486574340530929160498845628623564983594731900657921818042087045491261078134766035389271551015123919424955561779 -2250865723942111784039421608251851432625547218473942867505887413831061852377508665133755951631672797483190995230665622102487996363019684093932899173138433 -10365393947735305013406914790529970011789937562186538656086799243490315444313309044458058836146192026472268081854266767322163579707977712683519957790124192466318755078159491340837738702367012687896445047003782661660364048868352982928925323993821529472941240126796375997530714377580986794001906926616577 -14333822648693704865076879128906075720499136539069158690685854059407099164825884209184916036182302301395671457986593271682838667112004613576105840990149035878508820984562415792148035482874225110645395684214966452961820472792442602064243527154948068695736851229344379321130087114111462740896607157184206550890192589389891097286967351231550279425607394341507476319668354155045448922078367672145026743791767604387213710928364307934410387263608077250700922 +0 0 4 857 @@ -846,12 +475,7 @@ 49306867245429292665712135123169680084542437782148851479415184718925278478337 25169675183049498057756995668265957449819867477380947926503567596715595792385 0 -1542102799772537760963096697799266983934002048485565532539213661192226994429815251647197396526306187090160124800082409862575273365902118268755683311617 -2878686104109625229862354165402805665509620736230260577444969531934998053988812440085505116849926944621437581036715525742444317675163909046866434002617548 -1408524625048880495289336975458683532829516256219036238078109087870567897704916529748103852417398524574297919263661719753670147382638802928308999469587009 -4742693590966914277133482345622645931210627503968707620206733070482049794927860629080377711683265908227819055370520162972241526589942916768449868513411073 -5553130642134937791530098743023191297911732972994212582055485264717254209908250004950803382001574291176411334745038178232430168856024215688613524818989709760819986306959630308890022984882592785783047391490235914166320765169341522983194375620252621448545812049279764384555916944408353668680790336077825 -4723927638618295083690092755463316838498918330240796682728223697622545893312048720733281849001727094418300588431465926349278460120916795941753250274668142622894086165783902042659225253028435298371078758268910795425148305403592272806883261778790469890737429382002305486407398555872939312784693343967014010596526975636760014820772215746889139520167274303379900890377661917715485803657804374133841224806618394107058611468658108088260131560551896063029806 +0 0 1 339 @@ -860,611 +484,3 @@ 36694329931173559945696159169023191810080707655034316545018050435414281420799 28634157081599137704071405870600522487246030369305940433755254306653996056575 0 -1843618193774705784137956843790595835260885788482623306691425639970821561161960610834735278405087149627169615102857943696661773073162375892056240291839 -1170950137596410394079556452052007744667922551742356085549311726107104621063174324321159198410238181081409377899289339696505183364108241398143346683397274 -6266577599180715272643179829794667116364415231701874317566806045550798989424764451453171897199722686363150830763178386494247478884029147366386550475745174 -19499454418662965629802092201099350207580257918576731805737028058666848388525076659636862212534884659279639848323707620894715396779028548909594207393415167 -7491310775427379205451275241696534198775207876533479087995103252323137907742560676206102526955127596768143236592364563919391365130622631807244861360530642258721353802216367646769792844931749654022069462592705831533949527241530587573297737411586728906086303832296331156380881819739166686878092144672767 -18796502162760160226250152204618694839807906286113092800003110777883789218842243583036064249900793594494008242546403509188567430371285061255161460873411492857908336448904619340775306266718509033743784612836222680866203517611201799111354771581380221437368528919952566186512228630174278700984373922250123310919722657324347467475261738175114760435522588005390001769791388961028828314032397203388180386644894795950381375883062194583758183135747713996158476 -0 -4 -729 -828471727968036044453779079169 -246763246873648168750114309847746005595 -14797796466515082470342263148884814370442076847061299435927018837432355258369 -53523753874056411494904927181451501266586517086289761739581598242912772030465 -0 -1610256322768663008681400364814073486033869865214932600830364116109232945229182624979010068028626424299039929917408136658184480247613110744087848288257 -4982989173773022649022397963184917180752190882657662748886552370901797910421968943370653256257967628629024664151919676967847090084950251857702290490980262 -12148110333218384648436139282566844904693423767379435822469549432550659540325752661673352721491851141598081552703324243494124595306618572675953315479573797 -11028869767950066853862903870251721369434866526464337153519928986032553183047292589177288689002878431824162808354999536746934113300550015294401283448897537 -5564677243506565432840796326485830517108613266274939211083439123715117854386689205611896780808790236784879267345611559615161743402643098893029929273758889773892627347825037932396714085133601074675261736569510119123888317868706628104410262093816075912392494216258946925258732634257705061191794611453953 -12832448199509312748037695466110344603691973686346158577275697531431038398255234604164046550781119126216534644040340178530673012471457078814611960997016443056894042854161746711315668268536386219382705407726308690881678952673969590544355499320160817266809347245168990155961021732027075310147074025336573553132150745598676058388830602694665869887746332618578258133919549090512076129869049818309689542631433818773293308811803158552451157660610127239822650 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -0 -10 -348 -734763819450510610632565325824 -83076749736557242049732541826465792 -56086793224325083479877516880625996376700331315327416568653997679101469523968 -43066253535244233026187978142387001755402803069145978156050831917314998272 -201496559500976655734260440277137434576370058288390243702942488773257463333742 -0 -3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 -3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 -3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 -3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 -3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 -0 -13 -684 -887995200883511538239500451840 -185744035486811956755421374818265305947 -28022724762678085694347421423886262818477620187692930983847526359050708058112 -60066058720019429804858835809980860963604546002890479581904231770820593057792 -140726188198724864302983488206145216978022023086026367060204697866126599261742 -0 -1306435882293703054785864617754127645947981008635081515972982328252373992773175682602366698784049948578438144756464452476167658757197266011674411590215624 -3418924933199934873321329948743314146142040692630731923496865500679236033474734183436540120875605867521473258874285532970466381831296084581446997731696468 -3109273453047763295057753183837237869395959180214923717206774456268927599702732452171437824488600294111292564013762251960507352853270412970588497512497152 -286731836186446095857785724442739726555989697273304519023165182400415887707383423935925307951900182657313805119211164740403675553245412634677881978590896153075228565724249371402865963565486212287922871904886718220392004596796756145262329924195978312198219275306469037658944155791679821415216932978688 -23705763208580774588928458369265619438916460021945211232193047627926603512005878931377912938311419163243403002660952903410656586223538662133420783063393034282975381898012298576963467515440532649689328334345780681671723172171010972029952896075198416960048234210840439701334495379764884464832012212719290831505340271260696067947540265478850247171084561966330905870702345126530017405343636921534310353745046761481665427795564834777302251191884558790364186 -0 -16 -284 -923020903585570222185243475968 -134595118892137229728955299113857603251 -12517788472856075617475369492923779675790060603142796585343152963486180442112 -21278317616479394781203625492118767183546382422255138071596449473207327522816 -37333224946615587454531558429668776609410791968643457941551824417764439077616 -0 -4365216629959533172982077795378474518196312747569830926192625581814797043834797277039496659650371970445843961712911189437934023902885370155197127447599587 -7786275362280256985096504919805326940788214494037837259488750879599254096754641518066648702992692840392471672645638933505566197966897842107066681649920912 -8618362445903795498495298150872761763162723533326999016941555427533106887247180867507912332927251479902784257469217137485980295377407380260430728522629120 -7982146058423899625168899480055973629935142133954608148082398488598972256455265091746814757927002125120326401286119392678755814780700585901254416951099507381124434116044162971886485060919796269087997434118497014919733636378546760466317072097028651097132741041399433702808164954962506455701888258015232 -21989330961427482320873414443063015928257919942443821711178892798696487896352353009088507622971045148342817299121972243674879166058756712149437499808420544292407293376143293804754263654378017796839550542953209140796361828649433680420247205870246799908001987021274080200394165262473622337823240257874872815088714497275294574219657771744609557582141606487864476140423350129460552762119376149626806864803509401361323064126501267414575167852478576633701103 -0 -4 -192 -132781846299563114295034118144 -287795638097315923177133982791898021661 -41260134549646540530567879497450034797936197027784201139228793125077872803840 -26725487537631090553213382951117408090775065651640692466752663021330299355136 -17991000660342902270761827603753917202037974525700770708412111282505637002686 -0 -3944008675763809747015020665178678882677044257366818833894853057097872891661745300374363390097768393910140535804055885471681266094856681311889793405842943 -10432168002169925309120503644722046609224368185326214525537866102657473676610157919783033661419495704812662343601179229565468596161053474859566232729971168 -4434125550755468286273915949559378521845137875362780075693690876557539422008078027298618389135234122502995076657800647221775819541243724097410850717958144 -10544028428859860647631953921720386323000119376125885681800950423087768127297571058267839503395689317829039753434382369495774320720145371495400808557366564483951610047346873818659355869536197251947067485092374284236784198628790721882722429857933128554802811282519317048898934233902279839985805232701440 -18440345941730146769481994533733567141044993718475504938583318912857102648847047027910392382495051573769813528456979411954962447707741851707281536897396641672916772895898381890381674089051912642497004147872377088851984352979390381063683748636451983558056315085668918214320300476071304869797011014426609032047214117423653962127333957708782154126828418118548172708012943197384144043383315600410200355075913830695186216882152046505722142344944887793337854 -0 -13 -848 -582024649450436441833425862656 -96569028480694229617495306964621095513 -51864362273957721702450812674007399695894707256635407766080228745350205145088 -42338700632985114555032701713036006818320082283349136714641228033327395504128 -215954730055182411688222939177706107427072066045627310771072503279957579162468 -0 -564120810776501871547030068641973310984074415468950923614458445915309234305596816720344025395793468749961903973331424982658487492675732875715746581881639 -9512030017005233270085163286414408214444876161604376761868292912053847917535106665754020297449298958739630340441868032179720694634048588859831514895174004 -3424474661482523359099400350868558228999347406743051468541630110333927244078257761445483195343636488588952518919760460591527948463291377508337491634028544 -1908744027142267160255992222033230928186240062062564360139414061079951535468660083714712566829573866331135382316682210055579103865954047482673249785878901884126518352007886346248743951305036458287883359238321077240214116300549133893047140060961188058073853208070901174162050948796606119057608052572160 -533753182221943739411515817506559992144353474201345586358967700583566469936103300520749166184587887860573873190047587658861707366381179609208438444812890854907402119224883354291361848266886930865694292240182736475266290660159879661714355945901578730736360959787897025448543671196789177297617755152629881870393271660514425363164245734715462258579427757199028980848704112940977349320451917649697374845997311260177033885249436939940782382383929118269489 -0 -4 -524 -580845881975944426787514089472 -247672215531302623220114886854143351291 -37388457217608581848439794961125547405280755409544281555421884293853562798080 -6867524968084435742227914739535272191184841314026237436198416499210501226496 -37084585770552631634036071894836390875870489411136211932476363892010270509161 -0 -2060718003102261095469378358151405280518660285538331953442371394551388847723544748074563153067316177877347237081738459763835643097859427740490945401065896 -2427597878315108052588416153186371822454229878691660809974423528713640874637568365876246285814256304894224389434236414966957500210729605332124313726402355 -17899117585006203601483637166090154016991728785619486538375724587636009980913873117460186227173247676970981855052572465455831400785016798907992702502043648 -1871601166577895913665863813882743743306248246207644360499054669218177312807383799762174801630805340092267502315367248573627278277545825513989809282952455822056852517152157679111824332559476177533337546335447972701488371422446112963735366800940695179512495443184058856851596498196420939445759478071296 -10550306778399659975487897356875358924973318622498728253620155978576923389364488120390171602550388451242602890206431322088607185746985283921168954364764596976217073705682936664824865112089874261838527911965608302408800742105060068062502398384764473486663935558909957592004243003066730197686300227260257298269425658277997389598475973630768006422518890534069851801433726348188900604318019697404931564408067035791107685741964005839508900413176154475821036 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -0 -1 -455 -12835319081690733822122917887 -127603331931914074262646774143133941767 -57894298449951398757252466847559442906950400042978305056517893187912714944511 -82474589191995733226059000413673369947276401483368126437014470136553367666687 -1725367873614246661397681099761093360336884063153660970896243052915304594387 -762145642166990121634319750876330910924084988636669303246807590962648009181396757661856053558136824594202566053704052044355748404436481867775 -0 -5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 -5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 -5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 -5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 -0 -1 -455 -346299262836863942390852878335 -124566106711135523024142034815609358702 -44045214583669272699005754870852537422943743579723467162109618579770773078015 -47191182087471614723727659086024420134442459808826251007744893899083683463167 -149345394318679384540349467866290540580664685942593858325103856164763257832712 -328659738499559851395369286572775271201389799649696769367887874387602713649950541005767198083760164244451135081042951771979928777420726556841593536511 -0 -6499574949616620637580116906143754514426259529884439117780273025054849187451370731789917263550769050214853609122367946205434263410894715910936878759479861 -10124369117566771149603816821574722189892029783289052707167197978669109873476852672835440349606345261291423564961708638702389275798144171277206026719330303 -5383941699543092305623443842804493263947292181555684893992973883142751498900796716464867906615276957493629319704781718428057228609756150862864742004037399095952297373496665788422781648005837085478113966408640459815231657886564133913536806437981143729147690610590905694337501640066370356251688307785727 -6310918068059471764026319883889981132676900864298663494645342741409042787564204104397616974568887642296873516370780274089671686771704841938229887196137460632598595783254274133337225772320128927921843666172747542030026661734330465262950674563868305274037519191385934219987327624738988091242143029337066541173427000341834616390107777280313836624864077607937735030229348205663463578720868333899592726387334113240438244508441849656170478117348105420506878 -0 -1 -1 -1081180894199368861240340250625 -276904095316794738679647588766540076161 -18514213011776190595773191080849496970028811091221965026218765069756819046401 -95073983698370028065196578355547349954385319767423967546472360718799690792961 -6693017956846532764960681557697229863590470801886832055562479247632768202596 -2629164625513944344764393375912545052754690348620826079674933659671918850737622014550902801880361819290452858809500518180554683024947040651570430607361 -0 -4137577240563885180314014646510639308253117303602681600936018963727274657401877961996913350454564200277844605264306113013779943962820037004955398417119598 -6012634743225204725211101132320048969685865768619552174466530181728480133292301029875548285114373185900664580122272341980596861811413330588763908353294337 -254535129586580270548521975414349752244526806343151862080007760571223205791187472902044998439332623334230660834529731711989369170257700618020245017747639011641677093780420045542350067272071826391827216607645254644193288995966198490603503031365625040118877912466523642200661116519635298806043651342337 -8385908846676081908370043980559351677127770716607791744592576475690297800091571658800512758412511961004663163941376701719082333294800426334317916965716031020176657167014768130949406498916053374967901129501825532754676652724685176412371614884225185706503174134155152063944407927152995929183429819648489312242513817944158673167844009257444561330167132349514611454316120198401977968656265677200605323359155355731762973826116236680898629609918324923846369 -0 -1 -1 -324956523760712896376838553601 -47627363697928134504927977366887218436 -33434307187530355896632894137563272179790850372650630159758741607677205413889 -104315921941200306811166882397908923183277873670404242656007610443530523115521 -205533708257112897495155981027938658151590718760836138711462112141640293797081 -1107909686739446306967869518645944435031236156727422752526394105581762893921951275569530192146029955926564787705997591876292833451590952315825059528705 -0 -308755345928398507077827126197262399264414124207949539753718673573534243084848112587571000480595914906260398850382596175138781946603416961836963870626141 -18244350893087399850665188670118991037975220133032205465990746245721929325028153136705422106519390226837480732385191993725441112016188775082810504002928641 -3665588193601842217160462892006519794441699353581412583510916962644156398320556835171594452576616053963810443333586339255795973680000246325868129939290031865642638045425971867009672427500503914468057445618838753197439907968265469989645596428647594500319536081932047598179754671610950943455199214174209 -22186396831654097227986496390728371980330693530332007779166541519242688898973938381447063194690736625552685027691280623961530978041318772892810396870809949339891780432739513792778708087762348742046586160063394433346940941101035727747372800903757578028991776450199349428475680885800121505072160076081825165777670772329510069207190667831629973354820426821121553497181841257104073871622072935426694421062659417600761519902665044177543487193516620418169098 -0 -1 -455 -1168225574662879022832991338495 -57044890746169261651982104206166026733 -24779217388362851886903530808112954986166879528618678581940026232185554993151 -55591006844159235471682881367005599231961414654778243528698592315005808410623 -196546087471840559446390920880856282064404926864490466841380522742929941658568 -1917639872072259012937469746034134309612115999398820982521714520910586889626920621215182691543587130631234794290116996439471618261125269461687047553023 -0 -560629320288680383605194363023384807151678143098424596613421718363041709472766750167486947243276747104145109416759625120625677741081131727837587049341019 -21759673470171209133072662941401074809641596506044027427359195245599749269615278218888544963788731822407161900052925229605030503595641862078189438914002943 -8222674955398877316557535473602868565827602242812253563419515952040766275770537334852962079852348771177051126858608391846792829268299315517383515972974712379197466243571886838842455021350337318953242740755305732748699335134286099636570483789761728214215928903659103496254292223405306563391980052676607 -6704878406080177707560203655054736070477248576489688306407842672251903096919006312415980371154994403260429964471609192482935456676801001230508899453034708688807610209409717279310365716437632450197121589568242633422750297260272378736694314947182768068352565076127017290514776717356480481674630872849763970700450069226388331363736946106411055783778057065098928098706626638969150760900186745176895660013716070551573583271188993227435662677589978033750659 -0 -1 -1 -87563840629716667648756940801 -32581458921182292884541920892394116196 -36836091762090661553341041736371299478161889753078991612037085885874369986561 -103386798190572160839245264014111757730316335866975469301775408799589041438721 -230979096632485379690874166782108500616204584679462971821585472432375012098081 -1175849592681947186381704220573745682736611171788630769140595898826048744669637879095677970676093415500222347357756142334095120061003014283574860840961 -0 -11889537611764019713474395414522017738805331131412830425961734413527746223621889642851856767739924676858324754442498238690013743634420772752231361918208575 -10100837533498068062116682421711269237464416549039194254318934545331492474511664814492105364025928254622293940722169331634657785497327849544082846163927041 -1369148440215267019286304149733761118056665924873961991411630969747965209899998790716499635578218937487656801015714762781120580385002698505340071100124982713842184248347860416733386896580942622009293934979960183456583184237569483817916647944103549712738217905254990813029611090034738596009778303991809 -14470891946382593133261871975556948917962250576470186541215002308627316792841475378647804951570288535703522370652296694295712464047904010907340184090003647914959531499893292863053894273874528256748420135416037596722727653113848255103464219786106388140414129037919023044763659100696777268559628822671794913188044005920185870352459166957980274030642096976079120265889000691672667107327976040012293388052690990946304488345186187456257606086924331607962389 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -0 -20 -595 -182776107722364003135434784767 -281466386776064 -57894277771803943810359491595023458960167522338927730828258057680034478424063 -89555305827206481420887328961785203324625996138257453019240897699860153630719 -31072229483910585358509303280765563029411398133731077240605874038996845471709 -3273390607896141870013189358366943131609359382662427080975450085374873026606564249289725539410814263596351691407518053929870103702401568479817676881919 -3351951982484124983609172268969732236347481510662869536744042230485685559782341996467619926017805728755414692283401971053259449792684445385138897718083585 -0 -13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 -13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 -13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 -0 -20 -99 -959889322504300279480128110591 -226336563431145028687618637822844548759 -8191728281812111000214169178820381725838839982899041198234467802159092072447 -89010858809825214210137289255494412179471657721652615002925377757309556490239 -28296599574001589588954577695238704244097106391390255507549917926893049677184 -1143685232425095012373289446686042380253702819534317091382577237068099768813347351859388607019602275279637030972001139645555685678576527645905260642303 -2104386984118747727716517063913738816025890811467756992449715776590348174368338808503581044664946651173257522380822233775261192222343142632013731451133938 -0 -3245766926972643552330628549049705392854964955772154252338528686239084242071182385973867724746592501989847967320150395945141828002524173519974765401473023 -6907648306248975720047253807553315878303563975921476580151692887533957733952838913222178155862261045104101262891677093360305327510435202370854866877221225386828546336285443261625103246327521271905514699410432996107397381514692809796698965099058352936055010684764360915671953963860003695683345510825983 -26447750664679572972311511491346762878392092007822795854735091849389623944255827031514453721868656369736370805514656452589804235525013818434397127292257036933491312808959509859350482891134824058764033024690355796359079598096947363393151627873770672958867270537674600576785634138230894329775351387231396268146781903236645159728891454367132969379219264931998221585031609847512363429272555066238888068880222596086485264677276997340726172359858551867347999 -0 -1 -853 -801006859139436247401554247681 -142225711339612348039388698959539597716 -35410378673742450051313678883687618704562356389379983514233123876029687922689 -38091574202374902858714012832961735959144676797295175057041826999843956981761 -35509638606720435404002212308149594900713246317816589861892489724156349420746 -947006889763449443971526094184752460089916877997363377410340189611125125701316093754306776646584059092783200306323088027637258553889934093760610697217 -4220939006243733889354999574941943865608293932174863319944209124029612039884827143990223224550002012724043690083235647740267932838159837905350721905177008 -0 -9819440398814080363130785191409752685155104538075120057014007750225191492119731772827023591993721591147390320845851382883568011993500439254883415399333889 -9655632408759825233958611797456496067063588648590435065602226373676034823927066598142456746083088436655720971023229982832504728539123316354948596655920694029523232211427760301619988760938379731840724545418059474244039925314243108598463317618776112331037188490273232491842485947576029350960119525933057 -19168469482771522387361980195401090898697209536327388812153014901529211406007624393592650590928364242770484062532946351666565045957764391288622530585296240046291185627706970869937489824896647625260613504074528292679224168776865581606886288126591395731294608037126460284763239262254718080804765957557128258706900873267005249160304719047478911756155253168469506131790620297150118426293519712473869983955423743730285845904324583142963587786011293140146359 -0 -1 -673 -715561516884788010108823011329 -286119718739330631910267662147206086291 -4077367256260361378876724861054846658815066802262232907668922921382880215041 -100388196731105783095258894359755309057443209346921752384716203296701221437441 -161978619973690354040532742933073207830461397640286489633556474311275198068706 -295808498796001041580957434812431144336907268953236122391222657342664931238894722072411794573977944314328249736260072780418263762201867190982817087489 -97407145078903878701182151565338220720952838018650765330450334535905937357373611965592469739325221569980257894281512858606923275277875824669884901395310 -0 -25619912338425179981237074026942021799265536991310528535894660424287880718210785582129672576271686161615856398250702958965821900733894974363009685894725633 -7671522909468965446688811864997649775732139334764200965671339202409525004787427756456574114546598384573443159084990772200209956297641268137668960261240194749599773379609102037525886640588454985746187171015912121459949370747421414640087855414458925160365198194096646399383154836512890554710890718953473 -10293884923205428378666956554848182142244715690619212169171170546179865224723565444900771453248701102868483061985574173559709761183179067864659447677846955231286308377671525004854738789280605580119191885659203370511449399894078589757295087079227410959307116809855467581150399434097595488801159507371338585214103760300181569615667928415747705672332480417684601788700985353510796076482470500651763753290405004222433976439506565358025254851862958596926224 -0 -20 -319 -798574734973800499883498536959 -119319092661737199044961145581817753859 -41294191017998785012725086702072135678398504724859270409452353997253994610687 -110624822424825875387330825570332783320826449688572761060969648171618999992319 -60004897054289201390963390115257285329375358987352500183853788324442296431274 -2150478234121502140094205664847123566690038384648319032584399902322112031029827710253123600637285764878597164636106830261747369442317038978555055177727 -2286371016578508441121921294709678407693328940913329697268533575124016682365838296403222603898047913087019704067878310158113313849417316810388464204629572 -0 -25671226303654754146969894507457657987204391426702541645624778236755811429128127378887919394161592482970532540809070418766878887011243610093297304929828863 -4785525495332916713108346669310355883208597124913721653495570548939574646651963675833362058107793696545444101958156033302876198568608530737409310207901760770957083322440752303097212064072393248697788251227338207068162143919875155956848187111766304706403350196933167632508223394324726953817363397476351 -32094431582633234807734495384819130272063712020829901878525215417797644447839755174060744776726644205182311880852974878748451402374419467270518797046912443530456212016605470991508907045276371141670695248538943422952924891445929100158107096854447459717681547826391098044944416207597160685051923871604127853310380648807504003049978615375745963324507225789653536595005326797804437482047876186051782235982636836244442075633553513047827811973923415770476767 -0 -1 -337 -1188247491006021359695801876481 -11358522768134003317334293217035462861 -6973218261549576848638199934276587054115075947565903430900153448684127780865 -45591291715308727736165915509600830342618838112033396612024233841157189140481 -40977506359948200822020517638847374989428006593590887799032148830447784766831 -3158526125081113331509898514788313887509900397230108802808242305275074329114995683632326747175671847567894522724549111521860848666266947552987433664513 -4584447565436503172316825244033692918247702864479587471557460110462846155092582971475613387484731203139053010262859517492416070493565968167184179196803079 -0 -17855886664960195299137683256225599460539695469189441741138167148311674787837063586188982923974069115198316431121434733749422291458227574255634138536083457 -1374356246318253574025982110729726842105081842171225422931088363015788466146368528015009583509706677602458662747215994780981399824925913453782201779377138318045172999325810798864144189015648497899487658934661306497156780183553405477807924063800170898266248650878103340616913829333509130538752749338625 -1640563579891112614924709605958688587289742793630758509110339884654417246046905788570037457484399424416760895124676877531011891636277126802773558750473620855831931500866708684883937438953118514443126192930877064490752020898747438980089537975395182532494013272495476219349907646220024050095700438285617434068609057901263757996869152424637406600611987744170919997651080917069478242122542753946615128758176926986841759042912203967255896726167421198572976 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -0 -3 -780 -899245128272588436190215012352 -79382824738944801807794176002 -57892510978869681736730162220291002611042557329170362915611609916721313349632 -63318549916452990938470040291368379201286383559458191806845672058759835287552 -174649700752953765434988902296252491183916410461948522823307150782111144039507 -3273390607896141870013189019906287111002076719299707330406074198757955051929170942113619750485120149822099821188584330248544763114365430245700361256960 -1675975991239013909235918173490637855139324507692685389812651662983087942796182042459207730713681429512584287523480954202975430917613169254383951955361797 -17917957937422433684459538244547554224973162370938960458267029029640947834979519339152474433150005542914 -0 -26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 -26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 -0 -6 -704 -1177162594896717752709689638912 -96077425054455585888525548032358255307 -32860001485564213363245573215878063920603649509172460851204817722599339458560 -60109254545096573330255392159285415923549233358667844961269905663499962417152 -3073211245680220492517146661351308979695018043393915095083610251485928253557 -1196437601768571072681596644798276004178149983088278508148600069149523733201731793704103372368213233390444497494452110276684749064047644093326087421952 -2038636880556966905914764363156480651959910168504797327228316486248128297682164213768446666903998086070536989636186162862522556977670168122610463846604180 -10761508670374291972420269797715021028414464448240558938464987728552613552119689435329519427607648808039987095579973579961133046464353196386286909020663497 -0 -40984697395123061397847385885955617731982529976694509690496120168455541366383914951564162858485528121548558319374726064139914899078481865279546572464299479360080901581918627814605543248487499283343493082927078480873799428963538897690536507270633025904660571444960128829640263091486837879144125038592 -8909946412269299572792850981460782799532037067275283441188867265579333027637974855653738811158117573684759311560589042257190296847643010765802475698723405320867966475350089536733110413273085947267298794710610764685212306019986582674496969299883756072077594732387268624852957690791194886450004295782387045096350267854332914068470074912878717285439467272539570799182006042059497909029848272463040589609458879066125823035788194404021371601097559221551987 -0 -9 -692 -76435178552732951009197817856 -231982479817395379926203139743231669376 -47577898445412852300055548317787946557302802230354890877227185969553614045184 -94970241355010768267008081913617218797759253919929280496382103858739366854656 -14056327310363451370485055691408505290446120500764073466549198485574965172326 -2766964662182057386500329725111256292868978381151632013212396637813257618816895179949288796855976654014890661438562190344471725761340854297277946134528 -1329225061763580875918533781650822376275620990297295670554223160059148641553029627129765204098380667668821227128123235735809087554397139852326517131173276 -11097141842847614394079602992178709247589894415852402133624794662338776078636709858667481909108996684238974927213647046033793578164937980468332310219323018 -0 -8071735877529897797164814472711670751575699750650911010717417970127274646674179517149969617423521215633934503699616678817716843715742637948946050252837432727686220974468561142882832356080149399758341834298569043889563654149450777405007560189562518343814488242871896319575202397519320214473602582446080 -6694616185800266287626591614740434614172450545677003882600376830829359762042179214842368391192674719407443643400544441630973206517018113283369936295245057174712933556994499956071283288989464799795553730151588182776157104143243273082778860642399792205046014812501849329466277700807982917596823152488508302015315461955865789728769054751228692423119905880893937895064193158759226982592756051890511086607781198053342618530824939847343739509034244875431247 -0 -18 -856 -672949534961130560651949768704 -232952537159279159427935901397589147661 -53562723566230157237791876909273765997707933576810908258367261806129122902016 -31550994824562540598335530352687292695019428977242991470692369974431355764736 -152032362650815553704368562568087238407459967027457421226225849525712097091101 -45958219062793756897818223297329408371898301258718170247988696901754793869347716750803095228248960915336985565984017868792052415880945925312017858560 -2138965005429346794405216904139045984058362385566693925431000008613749092589355018622253069902180893858672397449645385554064735573191661559383999731945459 -5599082768478558353474373621584847716101862099962719911376003810521845817678124356992801556560959828813284665370289254359505555309567567683413487963442538 -0 -8505562198751426520419753868937928657815376861050869644650730877638862873089958249260761602153572619531088220914388128107806730704564885365227693238095778773347289827488140170092404396918489146978219366997692666431664422833499810391011971777952027507988195640695475217721220156144534273026766902657024 -13258845752058319557761867621646364193350685009107763072613748715545508884518792435165640060432501692620709571169303323832489898753595064750109814688579187658973115795780901167999045757923357842908980476028181042805278133908688854546483149229843751393689435259677649157449342132761603805685178078740303455039238350459994854784015714248007648831119423734010949858462504093063563879993972734732657191983776886556653813278840564588343475007599515963220807 -0 -6 -528 -754710143931888045283579265024 -287963055808859601191421471911256637338 -31470892304589511166080140750820995558894235651868644947081847455352142954496 -20368885260017261654021615802767195047009744205269123887896635371822470135808 -142720835682631691219581295413272156653298972135487346569310533961626415868843 -634034310188921143352280112839185376851989590898296042925196037660929073594178058676330909116314511976492745895031863182439397264248057241967936929792 -3536260655104985228570598047629889621504635464480007413999695872026244668858612074261286775235489798011926649959578184502755418831731290347207977473778761 -2287281553939530956352194620419013279616295380484047525310562106105104280173822770723063903213369365468416110828105561770407010047970222328014275531881062 -0 -8975406365256287079502146141544330687925839285578604542063444104478512627003244297195048898182515489030820157009675126108192822666606148894492389023997343919294064572180355360315826219274413911422788253153439868196680254069763329891225781141566431534338291820281857844001159772664584722309392818503680 -7627895627796776336034103253504663513973127224674837000702424659700877395432210192501491531145025624704509245843631295415207650789564811514832835249177414395254574557066114110734069582082204595410051869299928733226428505155385671730599432801289079265733997957718465603964310879479766099831516659589939704922842510148318960095699074620514977940993795465684303075866898594805143270298319852548800656967084658804532267409910838781960922542128682794059262 -0 -18 -884 -269006938810274604690777833472 -101610588522779797032951766648409694306 -40658360805639445426216385690775372728200090304603522756100519340351932071936 -91802138973420634587973914099224098988335694649088995732701581040017689542656 -160395547580151362819010763928022387697275046750539372389069219756723503990401 -2233124152381198796145991717823834504772859747063952845191626176084833539989086207836671472551515196170555448158422751623837827519669626403644933931008 -1919252284176976160011289332010981490746074225906227007498726993112622893994450491566696784468278809972885041734059388168593055735985280406694325759910450 -2289668776080774022092664264319203559647600991451909561040327250000009538496148645073308529369889500343496260137733562205719817974360067449226154885838315 -0 -8759003555859924455289792006122150340086642892965675685066523367563039345030166298894450331668432839835781802150906003659255941165890838655350310430355795467012027286822624520715979773959322702857888683940335230551215550420172560712753155144372559458294216901317555971294843609695973013254603739758592 -10233986988627486160165893250925551838419499341074966949334890607408070394472982377098453235058445034249828511040640776640636214044010669184255119316736950277091273009417324454157384181382413000016000601683912644163946480527308355567900081185611244964219361614299468279593357197464317206904586553970296516293220670021691347612227687198102745489374326883191094857906024566921950771760071555266307078912566589261856641951389747392777294648176011723094938 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -0 -11 -372 -21559839277448701880456708096 -5316932265549267143283400319839567616 -16282337714987120045892153486177165723161016453744476162789802658371874062336 -88537159989150876890408569427587371627685568624275408353614000822051296772096 -117153649598454680903779921606971322936867216714956963589387307178373077018966 -2451846285358576582757929577719947826359368522202829009982370031469538161149259226929244677345525601309596834316982200231651181236759995889790497062912 -3757219424385931343692363754866841943466352992489416825487678472853020775555494604110835156534238535884545156565469882173219151445924025758587329876446051 -1637494313049913248505508525988843145443777840250318553676797222770022673451141317105487157651955800518089884835975451904017985829916792949984404185120 -10058766516776922387083424546997939506014390161211981301999104219673036875504700741486695698194962976600388399803269774949866748354955056527082238634885120 -0 -10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 -0 -8 -788 -946214455905379764424855781376 -249640706902979523796329170594729366801 -16258878864784814636110793294682776772576083739386883456710601266131116228608 -94078769493157252401658832572786963194593512892920809466055866983486739972096 -195490272915595318817582071325338439133008656712282569735706902622916446459266 -774359154233456237796402928872914317257521270747766957039349342659625972382672493574510375099070233552293990548180408226281598743426255631871050252288 -3324275818746059767372921081282057650219072022078335429667273973120625111543946446086475227802464005339069654858828935205186959839930518363496383948716964 -9690305591136628284730559742274731850602666195501871310082095979151178872403510613019650261986889225542227473459970356781573066183889915340294060566934540 -18854688550460679120040977419238299860098014817785306576788948091134630080082228033258246996685817245124205310980844728342008317740737273944965604408557568 -0 -21535908620540850229409686341283386471970416340429967737238370022240247758101364064839301635897318433287340370763594753912136240228661108354045783804012930997208048017799043921041828011421457343668782820520536104076035026053782745857307697762578688266768524636747474268145327146906132830376635108519593754580661809442020459403107922707419305832717345589771811762862349427813533987428011905051344117484841279401140909699065164456004599224024146858711124 -0 -16 -132 -980393085630777633795127377920 -43821595176334581224008514546980603456 -52058795012750249675444812857939886156709846064922449115753994933360369074176 -14561123691201700806224839696324937581522964314772521776090379875080644591616 -175349175863053101686937135303271674300289639455959650994302374762982917881921 -1131906497036762609639522228534153459919865408591834031873180959858521631664870050151451799898073343006753689509175537114042334594659610848703981551616 -1350536895369391632569184447114500324766670158350291610958967597949326028999359576936432279782089126385784555900383659506910365560510605065726285256239859 -9451728608924473583394143032579162808176109643324961089109032935808751128466005303662886867241622116000970585797391055402890609702666479416682290459195799 -9869891012844468185531924549366273911251756943322915384954636117410087675117010026464336911857990363996496352787552233421136612436976661888444063719358464 -0 -29160913186613439708872461352513122879764789952607298290885068203114782142216922372207081593038688735241042977627651978016800109665004648282579021506383793652512992091245080903136500261598244223396601485010319512598372184283395628393048826477026318554363070339145452721174808395510502917485184825084502201409114714736758473035605478534635042521922391709556430295750595675343883087393107990838077832220859144502660929828804609103025888309324882798051740 -0 -4 -484 -1089134261820156880321423343616 -145538748117878092352760460206159211126 -33511658511802278583722924194874647566922276789108093402830459143321542459392 -101058486350009815877613019026909063961257758922502987153303461721695947063296 -55893599922312747075336422508333078260508029486824190273117160196130533025956 -2458978570716352272715788097961829640376943254320968964331207836957962374258773872920562816268264474274565514907090130109741585328325854023827972947968 -2334497061062585013441347827924568919650652349786907365392347487262095082662967762597898425035389335443705851967166882197635071826354135997079594483994794 -4739636748710839604647340865523976068039985893121701111166740470358505579292913487988032483975449672818248784390230013345327930989784690681998862554218456 -9268358303535012104892996424126494308898855298485453509135477774190853103484671018397846744502851397110775756567946279667738536399988345534648240817831936 -0 -1823333014513972248453863033569237311230812126130506337878885326530740596368720446811271380284232373400475839583564476423453964756030828084801793759122506966503712459173121792772565318978814203256490836178101826827909880676810922045422401824859785223968311017274407457720180425066972434143458217681896098086428204645340725330308523442939629221459319570158112385542686278442818549344024940355939362383436777208099871277202253431959816109988249138938651 -0 -8 -268 -345705300287849490539146641408 -28619945476059463819047280294135199591 -50097187803714017428498902612256509194829161297911658170445563991107297083392 -85421690222206289410508936520273729553730897899163659208114955446435945906176 -23541147492225259737409530414900909030720627244427625246343510574225863591276 -811358695156145842831903450818927915525548089569942629196406351050494125902340038663677284364719310507462367292228961985914579995483031930887980711936 -2753993259413215653375383555168520262036721258923608032707398699340884867309124328134824761429544678847308130542242013461361725575679679273117130844404184 -6291784738152052628532475385001151529792773731941954632670769788526762258081592087250332058353673371670605911117825763975584603160350868362121314372190208 -8246304950196854775397532690840382052681504659869650088188493089155770401666344769741621508722408724512112431250395089366004560986597746949833784645648384 -0 -33536828490723711025794383275603096340930562958525566355063509107668073876964224976171882248532778409771216997252213433993697133630589947644361952834437975121876157813462137576683247086121046784363938117600983461647174331186404053947864440728674994199031341263900784628270176815603173354730641751334159968196129982738215961466145470666104403167324840397876006086216517663581877927694551780431366423367588590449610474198496508322115190229617947779491804 -0 -4 -744 -285597678780049650206757617664 -183060435302525962072268027628016111021 -7217761771929207302500684142267832220669089126781480397245769148255541657600 -79477460217247376097886641006546273302212937742057604494280155910320628432896 -158450537078399418888641617303234395161356907531049363529305739478391665140056 -560479410674256955928059381764241238133905670084218664847601259116454401923250286188028355182665809615792144602857372046658783886046707955042334277632 -3683866358503387723371342100656401419267927238139401708364406415400694153274197402996715954111156399475059634029565264927949827386724995677572872987734714 -12590844567997964881164942256818297297627752677819872355996517914899426206584352337319457485189429758905990389059981412286350729613199131538807367459067873 -14260854143752552717856629622964902246009611015390566846603377483401216738344769373127606724470825630558473764635392820940186579136492501381274523880390656 -0 -21800320263537007047472351208796015562335481192952840431265409041550951526374116630066499902549548119697525627775845229207308993284066362779188144732297218576386880741913758964084484707758910160792538754632482272801417299710417022721348611414238310143561872419421028837234898971823910500714741024986033307017463050796451118315775556231911389073082154651438223368297410117325974472883309213628390772734914681877034242596184674973753688803388293273496715 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -0 -0 -303 -1157847834746177602004396802047 -339617671798359351079692875821060456446 -57867775067306645753843239588701162944294645608219998114893217643713234206719 -26369455828243150957066923597651481411694301395220676885210503666274163228671 -11817720390503827648781894443752171196964219125141796458180108788425643579396 -7804371375807015860240250407429415282553584425143433436919818048882206801446222314107580658597196283229772192970700820967091727381696957189718015 -941081632068259047813718693871170463934954812652267338340003979702879896717377687462914527089361639645292415086148993612559161291073345891219533759743345 -13407795142668967188561258511782701242040321017549139392778624385515507058390936234830335193232662892196414947249258255251754028773259240421675666352640010 -18030219496951436955703469321804144806589781292361309272091751131804808417784938468039344100394760314581363716192040882359255669821551713959394630176866303 -20764409093138106714694669222174000783080657450980639056024872831998438690744740872244449057340558976478438798965361453061982147397763104606367603575189606869434278459569124428885756214636676791959099839519692515219337740131125546138808227180751694999895383762073154332479036368513723304712662417407 -0 -0 -0 -131 -1049832718450901370153113485311 -123743968547971240881793449350717343096 -54247495121211160361188037929436149205783261053517263337868798039971357261823 -43780720696046181429968922798344646336098289195769104725971763934578188746751 -8569638876184228017621190554815028317573269823425357131497263831998166914171 -2590756693431741009163041429286398894656679441703939344261083891915266425352426310916864582943630782192228522635328133722758329149109900984640654540799 -1922792972978790663157142765037754247364399993465703829196794167418278912188407110331170404215500826901691954309618913442459626285713809675553469719932485 -2247688179853902828346517371756160939505222414700682406758025105256274372769418491926470116598950917484231339173818993910715883012571037685660436398094565 -14071886071206496987190907766460338856608548573141424962453698818757002916637223518158300237915282267942872621643500179521389478132153075114062917306155007 -6980263492707976602733081771294983285805560539203752519918453497642718603261557999924227728869489680883742630490486041372040492077056076650919876897423133050548479425912646008193088180932733170859088326636344779595580028567634175375390724080269085084386954408009560789015111093719791523327272483291135 -0 -0 -0 -213 -624277807757669988326564691969 -308806362863810512481109604679086238721 -7575495667463650924420531623779877444872078518414758729895107613392445112321 -71383655898197942633634404834290712896942744228408684751177316467115735121921 -47122958114890946067870921450228790803155389424276201823055498825762056188186 -1994424534807216528160042697004302546045534768650260352155667756798588514332350607215428085715884919952309860849179354235231346459029751145877699821569 -3146301561202581022604671318145679315132240673197187143392208577019128708207517211248787901932425426040980775091796171281106110880987357700982231152858994 -13344055815468537346229177929721616555294581393221545616480099523908865321613366395170905103332895603014771880154289842243792973144146321750132365948266313 -25653689183378345635977168873503678049300684399452321461457658485062084019322850001321503409853791883406838755199097647132019767454780407950907465283928065 -229130338950058715207075928314567718431940966481184952335048896861640341691504660128894140126073639123936931770837384336344695028165941321264091705246687393301105660309858229907321110227251032801854835879822879826073555284111211015122519313114936258162164556856278990251776549227306961333644609716225 -0 -0 -0 -141 -119107286127314199610661011457 -208956661746708815346102549108455455236 -9304183766217687257009318351289386378056338413009755635813258086246793609217 -37346116786925829034687685788004865887841441332555982208115369087891606077441 -142686669406791276574941284020696419378508583519717415488223479096553530067216 -1022103513376169960952043514852766564406369544025973264953283529967298973963692347373601150129718093616182401830320452020826518193269025639232195002369 -1255461492445777082599853012891109353852057873636592494368775587155748628015369099916821369435584805024717479183629939627196544920025710945751532635492024 -1189975803267431345957974690102770165991401096160981798863264688637086156816693253154715236752646520545321786646254224097289874096394507609482395432557936 -2038989167013368656643873390716729359930711113157962588962483025137830789336536213929010174321600155153011333126258568329562186707136497102974740273823745 -9084986068063143759355885696834360372551159629320665871137722600252611748073183150082604901064288041886108395689572588307893872058553059179847191635406482453723540265118257106957652545879445444515005992515527078762521603272600432053705760074646655367876806955197570127991703691485644599174058580377601 -0 -0 -0 -243 -699092340274526400217322881023 -38592925135126088279952503537704324536 -24069098860725904074101863281316659899407559169599337507189559069499782594559 -31845123066004062045091085308083188950704500797090491164647969353944050696191 -118305855347934305358536379357165472350660178373988900770159391774566491848801 -2008713282085666284652556551621962437401356361830493232520690122524894627206383197505895885671920146557265344301589773021846167435240002500658026512383 -323133594322353610393135271506551759249338578228327732110434346721529507354177413565941533352573023280770193553578703771044066939448141422832699655754215 -8866309339762256938205367118241359468285084241706741644373897192876383324845891938408677922953893394868024823096760328985859074426231649039808204582908518 -10592335116562605574859104705966049302824382333355134511227046941609708791279611163990078774097256277263081299114817404233848814642481057406588005371609087 -7409638199867804511590556491020804147437821443902201231464956650918710757587485835871076220513184441280932875327658339055507870288640330135470374231086564968802510793220658631244921907134557333508582119960035628956742572301380943132749810700571732870307187030378399921152414041403031737491047579647999 -0 -0 -0 -361 -1098223571363824020337471782913 -73118673265328369333869451006373159426 -12612570963041677221068251937087603519725683816332068400361871614991377891329 -44757643964492500248872741260097920363273353321461345189639693578247602176001 -3942245179751587580113754740041160627070588205547869974769586858647333898741 -2612294559420208791815554010100531022826670009294237097218906452805851976960451833971257091500484048552506300644536870798907627346813539746460119072769 -4886652767199484464651425905879582096234981128410546139257549524800652233964932550117395659883947428238070691107034177061699574595056075593731862734910922 -476948687153533538165001293464509838331769398407122530531483520520031422134660870238181672367938291384232556352408026637315514098467464396275313797141550 -4019828793218805646023303231154957746362032987800527539184202417766187717897646394634196457153911354739604912893653289014782783880263859608454097188945921 -4075360670358372722795335962773428342675661975784760871564112696474315403655585860035546105060954687834105799318439691150952278271480480434794674741133762365172004076850361918268011359368504306942773658004160938910939812513459072944161883845284706441576028699349927725653931250854074869857900046581761 -0 diff --git a/evm/src/cpu/kernel/tests/bignum/test_data/modexp_outputs_full b/evm/src/cpu/kernel/tests/bignum/test_data/modexp_outputs_full new file mode 100644 index 00000000..c1626f99 --- /dev/null +++ b/evm/src/cpu/kernel/tests/bignum/test_data/modexp_outputs_full @@ -0,0 +1,1575 @@ +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +0 +21 +21 +21 +21 +21 +21 +21 +21 +21 +21 +21 +21 +0 +0 +0 +309 +5842587018385982521381124421 +5842587018385982521381124421 +5842587018385982521381124421 +5842587018385982521381124421 +5842587018385982521381124421 +5842587018385982521381124421 +5842587018385982521381124421 +5842587018385982521381124421 +5842587018385982521381124421 +5842587018385982521381124421 +5842587018385982521381124421 +0 +0 +0 +169 +1232997389102826268860991065105 +18618193491623480687965778108529490131 +56424335153278151789523409664996995581162067431087086213061556134977632914449 +28522822713801268588036943398667804191745915805046109428618723188679866502161 +31706899640538131462557950751123123992423743151283050819612655945089903928361 +1626949887851522216050918195251855667936019233629512014857416262882459162506846482867598420124655122796334698879679058256496280388512107842122550266897 +3456644180256483296524124683106942480722843461305992677766332070622386105650335816178720659995652203171430416751945868032819203139048842456194585731900908 +6658621772694490037410881754126282754619191463278934006643576166056374826395321115677201742806056121601730868428249390651828408651815409287407418905560894 +2188719266686453452930405899199235044753192686954839466176162624683199938127424638750308949204554559166758220326224401920489333667474175603924673521175569 +6123795749220870070888957688126499811687439102580957107200324670516588221814874336490966980509479995815372272026912905873172415251713982723428918913460049360806724424126068570078686852874442462644585471618684175096178614463856372447395923736155404199722474001519774161213336837801565210105511353961489 +21733503076822274238215696841643994124465086209245797663103653662160183433375325239843496825811576935617701675430794656070743382504699894663869396198800858049123949931636855462200807567378261808374350727356914491895652225869425999023896449493174464626623879583913773127532285149008185808669981457659175411110681467646497612200879789944122607924142423967190374513947785974855081897919456043288039161362376188824242511311222201467365944959686354630547972 +0 +0 +0 +501 +163832143645086957897416441857 +130403518609156362105805396406315208861 +1950081577919450936472563652220396332042682835950151822696779432336405037057 +89705076639198166424843052158202309145112564081865083245095301525986942648321 +161580799869287829122678259656507339171378764462605635944908315838074450225541 +119111099232869461943255917709559971029471489246820147748389884283220680875449970114508127905572794881898139347855563980545398801715283004632963481601 +2340550614088062323035521333507933205420749928049240408457893198554975629380160875595843975025528241912895931129450956293623201875314056184463318790281141 +9658263392514739927662836103088426769134800307082054844647958520598804818351406352355729785509682250873421347556031006118797390529574721358615425274369903 +4647428455414528310735419222346137778331384012634538551014412602117023622880652353771726881116679285768237724443091476402706202263926819772616832419102721 +4105943439683327149496995432917731734349623330617416765444758819531334403459555965005600275959433826680513222328275949889828341311187920607090355380046540579908947040106371789193081113409035077098486792404385747715667974409598976733840748313362165044117491316370103556122704636978835764926194391187457 +28645769207390246795138025157012310806200949947458739337397211179141156343070918052774971042600619689369921890873698767518883214265612034430865062720501567943382208222029969252942575712244757709457154177152894494535042763023966349374143513752560929258976200745379909865727692592552226677876935892285307870731885285227994511501363645824725317338462104668462291125838004650196777287385052153407326433125418796527586257544647700218132360787318720777100831 +0 +0 +0 +361 +349605011617414033395053481789 +245857331472368514819046594566028058751 +16196520401421423385786338368215415982698439852342927927980513551465948892989 +25448670785549471741073803593965176921136178751681542787519830340854942519101 +208746275861806526568796522022506082930013066308764940459575687169043802837726 +1405046333573254154362728566205440659065789596162373947677922992002779706150301916091557545001891022758808422492046510466274149060187173986171371114301 +4109950494713993893142341968876859588899697995149574488387185284937507905151071268229544837244462536429462991654059099118254521939414590134998340719446475 +844468128021093833521017258842640197099986073495355910940365822372902152436005754957689228609364360833723273104884193579513808541852965164830299937335266 +4841490524461293458775865719630252706317774131797304941603107709106391551373400827563106022147424343461775948749633172375219539070706909069136692738510653 +7273173343143062730116325603650929579289657910222550340667872300408581237430197382410051906687144077202863842569199267502562443871512075909613158282763060439777587356925584672588460920490499485650537891223823337073005846524449165906099576249848470870580763810627114753982636643198831102678792829914941 +28046651509673296558629424584063249731669578718145238261130675472681779110268140721442904856558473621167727640615713345067811595168883183810857635560068796253449136272338112002671317203041266904678503071806393932350113469015095445921306266450082664767442783548486830460889239098543969021176454257806145698621983814164824010062639366791567674987083305882183188142795298379711201433370817683665471805353684719806585009665707704695044458674998071553291930 +0 +0 +0 +625 +268138222663085878899055263745 +24352877979184920020466043837322220276 +34834821705580047870320807590104282154881192418891909778995311440625022271489 +107743694625338367548278288079708411290661245510293131426406157730911501680641 +118236082284243482508848267847953427609046466568857110070954823921881387042791 +314573941438267599881423465112523804707482828315168316649965301003974020258305280672271797781262619454377248842022918324247905069090181693176119558145 +1855138457669725370795603609175257635850787505475418783821961151316324964106211402480574231460442281436102848418947738954752184731638654925034081955953702 +540244355168038810439245856412365092477075663815074675095751794574495975677637107674742162091364766891790053303512224504116561928038681836474597949011431 +22981118609480295020302390537085998300920429526471726567398293023445956296114258286587907654003543675558782486527003079440548040281611791112262372611325953 +6951084942072485004602792642768728173731086340286788608361716458550264564967198485402397629024961093884371645054422216571333979237852755889053521204926773487912585360977600077358240969038752377614031729154197921202596341838056184283438478913472604440906205314054471964590715571751484579200485577195521 +33110177016061425855873050546700017053104395816945007989361323145125706671247445069352845357430211170094709814842881235921295997550815440918489134011703431383697905373158706778267396782608658244538288231998579363509402374934461434235027334113339168112113235815389810790459912467851237692233387577938141749136860402850772218835907235676691685574301095898691939348359786379380091090548413315980192736618829302554133559996331787700989395178469522588716520 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +5 +0 +908 +908 +908 +908 +908 +908 +908 +908 +908 +908 +908 +0 +0 +20 +0 +444539926163396060618371891200 +265738677898336061407141787570363252093 +131765835135960660552807451524089028158233849469678584969822208 +131765835135960660552807451524089028158233849469678584969822208 +131765835135960660552807451524089028158233849469678584969822208 +131765835135960660552807451524089028158233849469678584969822208 +131765835135960660552807451524089028158233849469678584969822208 +131765835135960660552807451524089028158233849469678584969822208 +131765835135960660552807451524089028158233849469678584969822208 +131765835135960660552807451524089028158233849469678584969822208 +131765835135960660552807451524089028158233849469678584969822208 +0 +0 +4 +0 +458477653689271929750159360000 +25471671292789986475502298488957923576 +39622934661811821553763744630506213929196932096668444518123439737845028225024 +11662422067291787594026815204283885427659195788081136348012846295902003920896 +196850617542733211416217278410575369737876420896781853126317893743949824168141 +2683172422101341871005722746258376340307644953044191751444605309114182348157085796971409744620711498580309302182985308212586435414886374286350975238144 +3484767657771443762420853002633790658478025026595023030399445962591501743459655114168018705061836715787328457528577115561192630399480939905028160741471812 +826369288885297875981086985856579353870084500166446900173411432842694716669231467968748002518734902939451616083284004742033317955616293179658208664891021 +22202087655311450647135419149250531087927146350676835345655785380157598138557194753184373294689489916297473124960377821312544654416163136210039001929744384 +5867290145612847972373997073309915340902862989135230389100858222930181445218524888102172986857355110271349287326639814908840476463002707271202642441777343076399506363351555575169003649515921567023847735339868023560115487675698958077623452675911334000167018425794800395206246266829715066932889888227328 +6613183629137681279087117062720950270493246965665653353814545527865422606963860172688377962562995370224937823909402574900579151120138866568996446233013596125260317722731462888479963743727090415264356847381807593700110142796538796057208396283278444005900325957636550564820775653606338375016287872257899328947954420594292130424139307631549548532332505581708062755002798299585128036685598543159971540741219646857517061331622628267531564244017650020495747 +0 +0 +16 +0 +491348889049443876707510517760 +26309649457780133338343455840727251651 +12836249910756408599207651670402691470189457253048470571408310293697570799616 +89957821137359056393801843026144645477720961240687064113356371611922523488256 +186628143002875342454100646575613221588500043779267673627434610024013060416436 +57810819572866260801492155256759413876483749626656973452292976127618654522846001818070108358802224938885657621123322444739974859616822961140014252032 +3586935919752527353984027215088868451772937854013928716747601409083300019440067660008036473811750553056666280422401084064457379199486614970622678033275267 +11435172354316143741773241295887896087133672859698695578907055835282817586890921066517171600518967766241323412371609567006600523639894522363112407210324509 +15149040910228070805694652326182650730845401534077532391632591405118117144643051256922675471878552887101021773709591676502861584900921169634374950540279808 +4352157484305171917414400736736974322230700579288245632185873247491184195730898991437344106792548923888580847271187361373793947913900504263300740461685586606358268444829299316120497158281612307205034189058550655426163375786508423319573157431875873496129188997627673849109716799860744235677774874935296 +24655669188850607011881278212500400404795975111909544352042335778191251712079013936428534764805902649880208931889745231758199080159268053714657146238568540885026847910322826747799581068534312565470606227666766265055047378610529765358823154325332792516751882522879055713682140011583363538951298044003038164972718406208736221386819603161486554136555558914468701937507614273119563961498468609340048830696861579728696267046957787891673696324284268296592010 +0 +0 +20 +0 +995158961158262555374402928640 +134121906180378853498930390838142450437 +6919681730812989105961680682293875199438003339556752544938537021004054528000 +111415284413375575279069783743044849713138799010818236990829948938800785784832 +2671371225382503991550810752302543668307773911036096851249073522360117594907 +3196717805164369921128204528085730572110803813535280667544983013152498020676968653158980718912649444544541678773084521623843027455344890340658923962368 +1238216679956500444264616028232887647747940490327785007262817775307688862239704307927037312429375849475227131933476467593816834523153314124523020288669761 +11027839566584582470519059073521721670466350661122931561173065258823257321580571220589430064206794766082774897831215317085884716390531116370426677289293467 +2022634134337910980433929460688286697109516578140587883097911933500075648632085115589857581520940210394331242638360018211669767050461136520845948293742592 +10563633569776338863997290139173141475448369840952853889830314442522523629045149771574493906944834062931170774068081579834010118509008087930549452650473545745495642812824093639365842736796360564731533873032609439082530461159518786091690259460722677617446344350444358408993792066302845337558798580056064 +12824372483412385861669199400205004566724858538474303800494747762440269818404951059835352877380356415578282393020015717678870100435248949572316256128400151457357751827937645568676301032707345577683626030686702589840795543017433728119877924868065460364994171679438527788229515928801213836621134264837100427090704057536254578168099404041165838330491183445948965724854110273982983705590693431410760655261855587976233430383255504302646591767978918856150863 +0 +0 +16 +0 +1074929557660986703509960261632 +310308103079793704575757950092990989086 +45830377016999964195415645114843325971494172471228418297876829545637299093504 +101060401631390047762632218125084929475187708866471415222687033363449381912576 +130474939331530224408995396282441784260419370120207375947563617259552477561186 +2355941672152922857080918796873312219472407301725598088408859346047953344326591361786096096705419672944173727217808802505470853131296892573634755821568 +1316454184270635300204354290028403652975569924791362044247281669809677739990181839549155145392827806973474851174980544451539377747682379975465127356763282 +1438923259930704879657001108769207409876637192084506601145086731796010515496862959970405934371385188574753305943073462813023599491372378876317837370133527 +3751312292780009820304966556683277538490745683704566160236438372682961982986048670343223416367070064938538731816396930813426231559274819821553090255912960 +1940812635972614747466109277992726340848630072707912304640929127912329064087768370597314351590495738864766600213011565689114652892971392013558976325205708385347610787529794002191911334996478270010718764337052847791754345043741034784083083057127201125434592632894903882614831512194082202201086343774208 +18021429550902313767357511567759601756356647595430959756983217203030344977480124379576430774082535283607744829695070380577186356624450300463936384113907659808083311741619551253897275613952178963423684191041978549151808016907300923588567042148170623295160006737511147422878843457848402746737171046772562256330802876792353279038296767776587843369343160581335263159088902098345089167246852603087883635586088364841422928542822495523562426663120058625130224 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +1 +160 +0 +1267650597867046177654064545792 +1267650597867046177654064545792 +1267650597867046177654064545792 +1267650597867046177654064545792 +1267650597867046177654064545792 +1267650597867046177654064545792 +1267650597867046177654064545792 +1267650597867046177654064545792 +1267650597867046177654064545792 +1267650597867046177654064545792 +0 +0 +1 +312 +0 +305764342221524799935332959201681860527 +43179616752915754651548109831528453372307533305539601542967080491130306953216 +17577324162381258630474635337405333643146914114762554675606397827067886436352 +24302243256145833886805174285503224697924343810958724170274784478667392432942 +2455073261000987918671945239574537486815749129964150471432702836905807585811396531610253905941293957332101512899044268740293992626007607127083491262464 +1077242566599992264249169571444336551411248487528972966637628471569432402384081668659908518747150256909990581460430565820193233307152827275575539899170758 +13073126603118771003805243197447306343271660677454831683154753707889268850436361661628016500641989777790467968280342772010149753216162050495370020985042625 +20998284069276981893190892536141895412205721732777582241948778013718640245971369156599887283883776856426273476192138787335689583588114031186267728857006080 +9895687224941938536992396259410735585498593485949826080868857632522617767715344081138466212990213054852400162837201310103538489800752934384336855267244623540847988822661005638222750684585548680702427543946047149085737687298331380026993105619948605279977576581565502199750299350287074957960820551581696 +20330471440166965706846550975654713890652417870226965905923146732405275304116721701265925830155132264142742283294001589707864787012405943213404119056019767248830063561795881859861133225475226440778669219796000363700993800365618586534090055278009338085683400928935050079339354878794718829630509418239605013719652286315425501679172072558159972643172621667859406242995437705040600030465945478758984414424005354845660305153595541783513391622742931412397213 +0 +0 +1 +104 +0 +308509185836607975341692036936651238716 +55518020932873470218319288289245721296726991639699521321270937184899723952128 +112628490590563884833405386435939751658584809004247538619207709896844158959616 +5922841801814876533914360761483372163277450765372489528717658348886181069591 +2564817866139487541320504390805327358442199437592476952716613284652304314970931783459808490723737608880437784464822337666800292869999879039669023801344 +398463165885851265042497914635418511071393473395199568610621293995767308754233006664812655610002899538162554806154059048581305437649155727562069976883240 +11845528388829065193137342380492024118612741433871500160171557205928409375950091328760923663375034610212896359622832576619866946421226527978810823517767195 +14358105553296630195074581259093482904061967322039003650287242246847189245898106579740731184467142158444184654938258232190794449000467281976153220954718208 +8724046093635123581045526611633144774030370511834937151107124782757791671626741053594651970417496109952491903631645243345303037829497694196648996824200842520327610130549622341880795147265298435073802163280558766387420771897374896142381275499545438532579692773311139765116038449092364593363996255453184 +7405751147045042170442233630583323728853684512846881489652126352481138580343808254155794109418214211938178940574968048906922983783473775456657957578956020062439863911134378708160968666080910153080712910213618483308281268671163181505833074812656056876069748103205570600234366976045578890131475420080402034328956554170169080621020401502037844882798216390950223171848402002782939936087102304599378409563146797567777945011228369651410924564026853389623899 +0 +0 +1 +820 +0 +92377192736350021881806334564236622586 +30966933304654384056562480896427815565136977421206545694335698204395214733312 +82119970857858981914834549178898483174623261423734314091990446749364630061056 +17335345295685259772267515166522970642719156121663286480022840319361908909536 +2314109225631884097329071519390891278705119245506353961085436228554532183298397816728391508885600113143907388260489256179338412441709786163323932246016 +4631405091549513365618104032938964387036004178571962489969520427453823044584554995003585135178458975230639830757208179222570849484879646249622084312888560 +3444397905407459769678888603161852413323651620442902175963208412202586537665061311535470334927067187735566811052881866689633902610439151941964220310971721 +11022665256141102472940378463699540949238908279778600071282259749712264960911250408144499157327170064963756957223649027433072458668570655608803856874471424 +1149493853622624808951893133000311601994554292143458692563726487021442743023464156391272602913618081421849882373383362805133207036962919354651311719256865291542887462144185133870512659168195548443958858491083766172641138569350640961793151838633119997925593177565959971136032627767125937725101431586816 +33826235027620277221304225387441637043664748422971678909986538422912010422112157161893624219767292791117193745224367096503738217947106120516761159479154541434507081629430040858090956433405889392516115304242345520261752268880565405366762142190916629498630348949119250396008683103444433062400285561745138697466209715485695816216568719770239333912527091815214766386375891923409276947021071960719444492160160428059721106325731604292930332234337842204147864 +0 +0 +1 +556 +0 +132190390248470898896680912765144782208 +26118405364148793884093212339004353321168506206731428575114534916913543249920 +57371932048380839143645765917598495087491748880125189544237269309841806983168 +21907868082798520198592834325003250611892002016702940923441999346792832444518 +1983010347367670533586158746720918426725859238638826101738778473039940830888567731427474683445100376144146431698278643920358008341796317600412673769472 +2606640266791684811701307747992020704987556721798189736831558708134786779427826595516656788456057404569214323026273791700577064277010116095681833143649967 +13236721874325271723025473459287198396620022329708721480674722710511848773677038674125983763343329458361710367424043866874114509274517527946107266648826241 +2194764262264585667059858125941452105865892742975859841108712998947329687982788884647082000066632025028061458492389933022294535208755309187928296471396352 +204309344949056669756457560943541502699162518130681389120968275752795085274348261696673034188427085066909553427932479215637901119300398120607913517490261871972031537818140203177045230095689669755307530773417745785587153318345703950240765166902545254968306769674012995910371703479321012180805203525632 +10264690826749513230358184346151757544435920255861917426522952736046646856221133004608608156420505462277842900802805838197750732768067254277504971522375036317591854497981434809048391519641178668320883274044427240323533445722232511793549340418570864089915044452302975506872587143937799291446332426997988486186420527441812688737993113263455373353444533552218632449194597995340604827994474495437980620590990737309478013598033891846127947111075468737667005 +0 +0 +1 +340 +0 +998905004448329441454522467488976926 +4927413081688125725138099137632369118723706439675800220006419132836783063040 +84352496855087273591478468036086052663893064063467212113548648838828702826496 +107903726561082941806970174768933557491971859433891364382659859844852394460986 +2319608449060187999684790351453024136538626650066803987926996295704247719880909540662904401039557482146640056079214446055684288473572080013990468517888 +3229174536762564836328011009025477898799910197080321024421312234854337921760217907684033379377552188666880062823173769265434474194314757844200157057703739 +1423443399352876324872592588473564301454095472277230446652620290446968276830664095418889947537872334002573975742103104497418388304230155249816071500187318 +13271987893729173924722826693052254951121133786126776376721905614595108288958742926463506237918989779603882913708829786515628223071604050168421092211818496 +4601804950488826494167685270760036664893236871832882663322149997831635784436681349022970436277158840767511957327023782099178816414168280990846944956415328077143836700852459969097230280911772452313608645578171031885121285719728944681182534906015347671757933737842458574792144739909126764366189368967168 +857479341893762723161505496595417165049229108770456259194779683064981414515307526837194732925160817384742675728910002446344631831783238186297049084225178616281383135711434226661298337670136802627018979396403252157951565007991996142431686702381810961834168285921445713777780679851079387977357401452731948432492393075599084080144393344786427912661179463547435908489113931675491545959285551896625752610448451638448866450487107364387582471184159571074175 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +3 +827 +633825295391748780828659810303 +0 +340282366920938463463374607431768211455 +340282366920938463463374607431768211455 +340282366920938463463374607431768211455 +340282366920938463463374607431768211455 +340282366920938463463374607431768211455 +340282366920938463463374607431768211455 +340282366920938463463374607431768211455 +340282366920938463463374607431768211455 +340282366920938463463374607431768211455 +0 +0 +6 +883 +1151402479073526177054249189375 +0 +46236487016914252810359942606653565611806735985113905556189104784313205915647 +10141063897320778511376522974043618320650062159021091584566880470490557710335 +78190442020038551706136595408815344419350554279639655464038299447602848702950 +5264101363851496851433282540836956541101368807777991293344941388857765825339723752116476539712642325105142882152577944513410405922445245546495 +4274984277410983807532089925150768740931153586735292491383528412859129258433112273099949231101888023707157602612028830310955239728286706980227996295680904 +4270974226494341897280469825731968602385022467387106892501039803249858350601697035152008485439522684257776791254316572547412071137653017182505839419643661 +13396349486729820333578617551105577176007659045388305976467765207187599750765003306881228272040491956095560694041316948995285357929407282941862450720407551 +7272107039633935551591400893562218992924676126105717460127870788013015797432989950658439810996946118473016444182279548084821341534588106843981486932573866517856077154029000374861836839944939375168692527383494491021504979898639557323084128794258468279454347871141949852954622679013053097034606228537343 +4024681230464577896473641062977638052721373802614679861781599094800123563495932827294337297078407941193782141971643023681636515761542479169594195464691208343312685562380387487284859733536618386758347477945214430213026727223935953464725954742778965827480842612641410510935813810716514672572547641952771526945317395473564193078364064275666028733643505934945383834412116242058173431754061071146756970189972698298803191543547137198977609076610984071659602 +0 +0 +9 +257 +148913685258606776538030407681 +0 +15737081446634197346448238543290111090647984834849920547563580853437339795457 +17796349368611048392083206935955698801625485975991150886750776582747396767745 +87042183171820405426823900509602437553981065786933287231059322442248803404950 +1872579959911606123270219006911173139292436983412774739613566899721054729108647438934586909747652198625290890899088832075544795394544595455034418790401 +1412681115817651652595578657596182058840351787817337255523617847758399731969803154217604617416738018019082279140815098858103221944816565427541047989874575 +4658367006324170812599422256080523502806559591300942419231897265664273942632706886970881430455450954648568107656318501922464893981721336262565505150036230 +14176910549874618607407657930219555895908368234965503682114333452984200436110890119648814677868732070859714001297650338292337460853941658691514163789824001 +10406141366637179727319354575345523585198131445101199614041074944321283006099873985593501657875961054722659983805551437203724122242706464697758320434979188004227317962713115722036138880945569626619984608791769942492732939213456452058202944264921993463328233802720857330376187422666409410692321365721089 +10395612500766716889498607750936120296402196259538392550447369284462443521703220089793251095458371323061297217472250908800671528775762556075103359185483070524957305359923584052804148040373365959462663236012867000124244297047788081721144621971838346991977347509145949856725062202597193816565726641315796367190832625962761358471335171016260228986247896685407131636015822155281779300035844200755378496158753851995591046914832248761433986938772195242877368 +0 +0 +18 +33 +501502021891302937219905355777 +0 +3229040287801688211109538153528907359157521678782897421936034456493449281537 +43674379635609232592374808570316762057057239464140599073454048485319171375105 +206574116687852983759940670284339037133974987477578735810964428283965343595925 +992419486452661222145984173974299929589195994084254138342964889584701966790230864615423021215758227245793655600475560820231442393114209491163228930049 +867054567978498531065761454390276935399048293801759280371014301861063097032842313817626802406894612171009202210526526325159367606967184116106222709354994 +1139630468367775490336631812613571548165746938068725127033848437473514644842035232747054391798198457303514508910901267746988126523368144746838663920634335 +23229321847788976756725283113649930370792069582610592470231250035730463613494249923319913356844479204498929051652932802538286625056745478043326957712572417 +9736393711512156676697476147793419950291123704462141453822865116456122510755024608271599163197384361427364997715319701954677607307667967970314752567786721165005692082957947082637259982017311319355343061387874272954404686630047193927081844593179586832512413662625777018863736941974537158057318938574849 +29060966502289446762773527309129862532230651461433207672335349512468314509838153919700009183613587271911577714742576064666717735555966747507902189346161650683338259890112722032957837515796161015553488353420265757652831337573527786397820733107579265093849101520705267722311390949184609843752198524487159831619663983822993580005359239978622465631388243890591655090541561296753761373713020979145034193471076120681878728773637249747647754915387598872616720 +0 +0 +6 +515 +140262897948655524553823354879 +0 +51292049059523452610506083592610024599583816874803914322375719502751486443519 +27936184963965071766976378876421641742859886164075202272073313001233759338495 +13449010363647692703508349667378797433516756740069562881064298383864033242575 +3007865154522879628838942692472346158555510514358321404385880396123667658951604878264737502736736088022367734668256726008347601098598257350026528292863 +4592124389902639952157884879500633941880823326525745966966661569784155220592348399170518240885296517746840773500441608980855453698091666787607843899145829 +2534000532084385254011173048792691142730414486367806853286959714601853302234763393270798424710144792599095332446397093107565422159020315343985501774159892 +15542028513463832582045168836396386001625310864606581833373826691519685781220976702479707834361513658452848273358428791133185408252751328679278502490406911 +8412092699337531037787046468081884678528099171920466557150153840517555441701513747481625075399369031563363890720070512929533552898722630769019938157826781770070834212210476738149888508884995219178808489342005439633046794302879951435958690454691212867490392351796728559169919328744714016812403628441599 +33830106619343559855814362535589211924203444187711545573142435195593086511328847987971132905556265209639736610793615201190028737913698317064723958072416856829114676871668002147741395866264126547513200446705626505358831619201264825403452572963238108829829155602404009157481163421152595415563917960605621467418213148184629070795051181898610631600475141956877575705748780551030079535279390822434842453037166286438591706030638299501460332593582408355701860 +0 +0 +18 +793 +197025322184063122457151668225 +0 +2920290130103280979299916267396345225782651892499153454132172827501589954561 +13539515947035890751742634672716012403055571371579065400912721307212126879745 +158307368218366335347174104263331952261761856873568291783365034272918926713725 +1815215034323212852396070290108011856137567892027865591453387561513196098766849400352437123459701948446227688759510102669983999161585665721657907478529 +1313998427018914497731975785557000192540482097274033470133500010806607846954570954898528158955314391602627353029912678650049483923494107529991028097123237 +3558766711272482011504448167665545486379425587311683496485361619290623375415884515332307272266520310480366471739749365076632262898225547952923293595733728 +12553285567146229581143238572266763310070996960196734618418238189114111487087176302379917708160855599798506766652438515952406574783180790667512374443900929 +7334817924922815993844247909475070087281744359403537502526299289084906210615638233675595384256475356219608076645306747447902878463733829119335042011404584250731670549991672963716637969622660364460577985065151746629898564582075539489021571565895740532432194811300868623563387061791622447110534725632001 +23782765486299170619653377638001085226491596574584464898704365460889585549109410835130873109130617681428671842761358877647827448636728589051462502446489865488918684639573926641287700719325755142839567735191800755724523772975690463187286534957742763295127666200814136161150077106827630178598134515070629372319788894871157470118252128383759870860296840401062420257746959094446951505893201604983152709936368275205715331071029074242829807922867113197544311 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +13 +120 +145483342680740634262446800896 +170141183460469231436539398536531279872 +0 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +57896044618658097611351864738157061705262361561497619362091104892532012613632 +0 +0 +13 +588 +242981830122332196998498746368 +141543884952374228579411301124356217882 +0 +110892457497452005403581430237946183767136503117162566153549053970000476372992 +189155222634588421211288058609537932434095476696578287565656039885444474631257 +2273620924019535126443377586964826655364563651525119527623848142652704686460888155148600115764101538394624015930243455367013584122475807191504328327168 +4718242244578560577933620411853546035676043730739668011742858611491785678155178214146108560032528947886096115390359535573786208426628238424552910518225609 +5354055707309912886614410393569876624773886934053676926684306993550773407750553762949175437211369217571333055727536737153756343047932603108461352921558471 +25365469084896632438831937795363726978720559453448504867481253590410035300967847867532559492662554029011867176416570131146842894254418120377083085899956224 +3757578315429890131235493992649120836389777957623924867570462633554550213501972098599500200214418806050260619389176706179192857127356531256489639401245300261047944289856878017480929565003165920312519588880225017152460044735034054827437950584392201188531715789576969371957511327370055692497232100065280 +15253647830407583141547363309274688061512324567554978156617633130357138545424717528865172974543531851717065650176201323923438841684204225724333600965120694028156933393649297273989140526164630013338776321111358526273453216724232977621477413581907629724731139256634361519074694441451017597636834753579301989604484256575167632226812528730857727215779131743352342648896678763239802119364145369163238668734832577049562494126042421431166789603595812731097644 +0 +0 +1 +40 +447233008701926529533965500416 +293158325512187360695470417449441151016 +0 +80370191198978495857548168233658974342470488197481929432131097469881528877056 +57378722967569161858531872288267370459698099854972954033385237027489681458401 +1266685019038549670156131957936105569332778969355417709861995585153701875900859319531983550779488151228898464900331805671022343202096261388828403564544 +4007316844468480444786209097240877242135343232573279363036730296408578470321526904806238868824798952651885510964017728127623908601645102032546751410140438 +10809419853862469069424671860661466104583061712836069230246390212316112130066125544420392691125603322947467815628376833408555549515946984480656880021651380 +1850019664799561828446887689859810128523634383437118940053115370804552962470182093340221950762057683211340120378944062888849213207787569638787758996586496 +10601990121875444106767485014957569656736374682760746624229897705443065241696873816254196776531479775231519679842263077569364013222740741226981954932170832015958461515448934122357561377336766895492078707171525168572538566552146347786295929420700117193632141413315523494643262931844585426006586863648768 +28508439658852678107665155972792842206287661263432505699726272954607239927480675380840437519995918207158667265234219975518214394765767765060644972734142492559569055673270149098731414835043509095821925810223271993800625817447425850539568468486314744453634053786991467939161412382560926663037539162059349437789487898945599562092125838900291727653251158883415512092048307124528711465011479916269612248338449949978973514357464893125428777863416659679547856 +0 +0 +1 +412 +442771250107780063583096799232 +154158747942568048877474815599350831266 +0 +83509925808939041219467836468971382374645162274742749382395185649452566183936 +130737775035935455315064283330339683168756409303633081183629254780389959201676 +1434569753988477104238938016621393717922537334575046291954564311951618243596601987643360144150294172150115473086916074540367171462792383909655650238464 +1628053801365026402929640374014765553703071179544257678606217838338537677419257865674757673512650450839264317003577960931228650240349967706184064403237564 +9528330235712431695508651348872596587940214388314172729001944199117139203073649460506789237728120154262303033791074115687461447137304611451019062450033166 +4143685306341548231504887338288660968707624803700705709343351955022110657856432837240377395875927501705908299984063250507069218496972459859740452129341440 +7458796787007837004712235977661789416985633116148918114280732607368491371782197880736806507445402383850766124164590251775004743970419719155659219708540227384445648790605201658248003617820791276119099869395011354078111731072541949883562883648840249249510616061917989297687935201755531527627290779320320 +32562067415072239193840246016716096268985518768069377976952382448190013331748839889139882498448289400400757853808819969655477710609459023410834554011819177127950022030097667847290699738778525902043243023637500887645421123275436342796803206335835309725086671594130477830499317959884237607103504253659374293236168368765551370942719124768927841271066850440350466143929412219292019549741670650796223584473716652795660385114766444013731211424652116447263871 +0 +0 +13 +172 +791101013288846030830655504384 +153476591093627709272587559525863637788 +0 +16620630689278877851873420518904814002737213549417357007588250730268341567488 +135713742926877628027400301750580746786742856540376082400065882631878268256343 +2763703332326056666675771568612443973251095331788999459280007079557401109082037332230846287789955462113928953782310527076648915665904957779729505583104 +2824436745521083250434559952136747236272578919613634664272602203887075383079538439468738841849895882276490589513884561192461063598286468221544075155317742 +5573805721606072201024464091196637283572352485715830551875562715416314364897955988150179092473897788638830452265884540199145584775259028641318262487547968 +4057677748936070618844094810747404761610038515502652344029344965685330894561953958031306249055086692013728933315233447834639061360828462307224389794398208 +5784796441501303882265576458065577676796946906096587650440461985290957058829054847129274276669244130440701590711328886296578934710291199277222000695005904568910944144582690667672945892139302539970077461280831973659874645207539604298268246794000404198399473879519441764495134256354634643900506642055168 +27926326319599679689321531260972663838094871826824944182829437453915195129091090522882499755811750977000485175430688110045958476439969398119085050907218285133398254355136892348358892640344189516520338960373270419222146816179324538294913966113727777599048121837592524129719217066985421105982471108005619786655759673241565670064548335049859971927753583710716463045164399494432220069188699341199218886010208466355717064435978272444257082416306333129756637 +0 +0 +1 +316 +71681696331238174643235848192 +237948749361170373273798232100232473131 +0 +83778207020986728476145484258908144082269934037053254715152909632561590829056 +221509419269785716227233899606918240392102327497753358712085651922766861983551 +79315321146264542418544101067771002872575912085812381774279752184308118738724006743714953988893825146071572131840361116250475308904572550776268783616 +3141911224089662508005439140547996848411545433412668670184330989833051246389721569721933639157984163331306326586989550527910321306108944965118472936437373 +7056836934790078890629897242686908388561326030807269602244791722619134700685270860402176255162872248124156286310896170748542196945067054699971451991857017 +19653627676393504480845906820110557077219860495796321885850081681411361274754697849285945541928921052518914208933686885858752894441356909201046802838585344 +9683163169799910671354293907568672381107851254294002957127298074004784481037839670632521780649121780401926430183897832969166328037150107405373952334255388250551814999528496252119738140300795402325170176550137471892883221550198049424126188627968546323114246254076277484385665176149283033551751023165440 +16624156320060803479105655673708019093724859687856669901597323414016554716036267842673966767033477560761233327486461318339447602081002795923903537066139452947433702150477385673218681847304679734427371239598965310386307842392299911576146706135987880533258592628104184356529185963203696378503916725011966153849031868468134727041450767305498104186987445591841485782186937410888737747186818628076918609180767095586934198055427262999789790553748249680495030 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +1 +296 +920477174324206192629261533184 +9284550294641477953059815425 +57896044618447473228882389021020048158893283581286713298429387432951596187648 +0 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +115792089237105570840234253759177109864155645142784332660520492325483608801280 +0 +0 +1 +576 +394649121464702711197113253888 +330655358119337089933926862882373999920 +19171508671161797156614710182257630792593514679646789380628699765537557708800 +0 +83428280595193522049620352001877162940388365577102322638744416599597810157500 +2383427170914810336472146115059610133938440685431786051901133872674812685256214433004766571822808713024702089068992214313240618263661712821448505032704 +3543131743813569641335946273683240931826614024019546282265784836005828417893383322228810942263163410646159776819689834231870373605456177912242267705525812 +3201888256116239379504709172928241207634570507519243666267842079354934745091409880730742354222322722404797424377578771802961012486596039415971972097760189 +4721437724763666216912653616574178996088489462586407187533602132486864388960603129501403388719024042140502457650359696753171122610737975161314352895623168 +4837005771188282971935407089657043487019168586830902406943047384547231889109685650839979581515180335872804870881921663586570464571734302300526117404207560436370497430406529093043461008746914986949167798918225893839078999027089145630276892534029320307629830535688150128766532774699466359036038881476608 +14649538351459906058741226567249552783659862553950272384082762918585814063949755926925837749924987768515640556340283222177993507623584971708636450851372760248421615193323790004038285247571226256925988926564345592560305885533717028697892048480537531768156992921912334188996185887209116041579498773878589854193709529378983879403351880522010001304035516272695800246073052875655027404371065192473535905888797416623200692032732055359224565770757807776402248 +0 +0 +1 +36 +459149829216013907374855159808 +212514946886893049623689635030161573600 +30121405346709427309695531890582421791203074728165296179965859962342252478464 +0 +42435402933391614285072618340065308663204835805291910450325661435301593697950 +2723474109035793261196285209480520006576094880312369272827686699655845402902440783445003022414244095338650103254192634946547862282922709256827062714368 +2366345409847035124374650448074879585773647708631341355179263252964806807879670158353217088899380315556678858307117619065167384939975455280949447515369567 +13191762144369989130760985435688757812828881793396707694471183793997116204175863881278765015080350072806582669305591779418584954819749146010893985699341570 +13301718048073450430547712527884367748161420561064642294015103641915503834019416126543999762601710015216018615418920000282926562454589067268249095837319168 +9391084627976509998795459430240744148278054341930566001679916095435726828423076214248815541128823696135595365039592549569884022180775653333743792501900544596968163878667412922650434328739761497861462359470427289461508215509253714046614049256486535514319610185904255475081934449011049104472856091164672 +7354519734624006876179435352514087233297298809165790925922795673494116116655759843604125047003991533731435264281192336103815636919140214933167210447579405287498010619153112075099093006295245714725499708200955637344617781547142646463544824911616543471784407538549422907647454757217835547791373749159887064306770673576013161274312701154428403688789455533688700894782342280314573076414570285083813175010660748552095076178542404200729953294305533949916369 +0 +0 +1 +440 +111480890522555005842506121216 +169821875159927040016519827500463371995 +2219279707535425826019993588723715376924609733291444929791090369095624818688 +0 +125210688265252194710996471277583934881834379414003707914695928587186801398100 +2487150548049686483577986346486345896197470598544823109842683510353284256291612496904302366730404150860292761990843784069916754136788389949069787660288 +4665596396220733640168649174535027159196397070342267963244347648666006311146611981668674060621225920926771133113452576288300091774874699771692345174655000 +3321497911172409553001804903171022673679565313946048256955779288266740305599386551480119034076080803092083102364750364882135550956683614114559617436903767 +12793018574047350137248079672509016968931556367756809163171704828712247163091906244764359814474025125944855607579655662889196220595429789208504167192068096 +53376332098238942237058265874185808937843825750519948116793606680215516009579250363703665595580229234392378617881585484051555178971860102930997202131537779988926409286598509132127582039147943382149262722075187323524856262926753691304631056792968823860069761025941851259838112955696975940302445477888 +19923611385063419051384812211007230050060207617704483913568487020386612675099470773370717657374861044992939563075540978208277455783654511878538950291808744228334204522554009216806163343973548097843046243549174022328700851586804159313601461216565391487177684815873717679059019796761667669491458419882506144601791158476320022142436392910265642137030624038589331580844312683788761159106773836049440285100183481918534526738945630197824116914691687618255349 +0 +0 +1 +192 +973066898438133470773494415360 +61333559381831070683658258698802878545 +53535005721204496876936515275724889845817409334527168350061458281042045566976 +0 +35340054082346922390131417025011886439703502295343037882213639103251549897900 +1009118888395535762047061721180456806194166614565541999396274651526674300640202434640874659775936931364083317600665242264448090018723165449003588386816 +2392526284157188505188392690013448960986950491375028571859495919060981215979514074503662055648827708202314679184721591212604079491336362235307206391833426 +4218798631160832202661168847672965043016773529025064083427701368151868437320716279368190139450621334670500868570495563594616568204374854957138784941027870 +483959849385694416988953239395437763233014877575377690428602005170645490229330810160206389562974522706669622381302406569004289640692782430642495811485696 +5378187878649244049653816422966231411527819255785030355895748698860605699359864142748498411935665392420582096163286983444186194198233107257177496094195107895074872712441771334893808547355079651652051885242856910759791626223884287793085982216148604993192657336251775590261767563683353789243163725004800 +32818464130850205246467682789169918339482637627874185171064672905340879331577799944668821853359894806536530578739275748702344346513314541480359830789085211784100573835252933274724858360731614753176374779056545876405547001284878778829435612577133895639650041742079621450894836820613872672377867785376695923853094317140137484881752383755066269670040095376107209776772131790659671001065420513961226520376690403010625950002651054751819424823637290081472387 +0 +0 +1 +532 +1054096356549212854433844559872 +295167673194252499689312720648542539285 +18569052254320792886536065199102429830591425911674802887337142847422563614720 +0 +97896720708781798801687131335879227111506109430789223376551280139659913587350 +1634009508410887242647804687779058371050929112656850452045994095398157878806417902701340267267910135426243622542827304902620893278343438781078703177728 +862159323782353319562779470318789629705961090965297342320245925680889441369443314188948203254697918300615698372425403937959274851949640461887703447193841 +7173051967940195554257280536479042043827601659905799457098258573897554700956880589901442356513658795342086705483095145011273200575189131337241532322688171 +14778026829432832620717758207920676238440861869481283376192906681351851826811501922740289231253685732115671799215873523794595875524613727991318894568538112 +9743687940329798123999941212290764982687335446528161500746427614131976390988057307286128146303396660476408358788140586545951034783015956845304363388199684637129690259093248015713809461202981476094156748203762337562483089253099990690430154929727318541968412839173701447769414174975320032013797193416704 +11665082978646551184396197271822834154968679459301162080769250076458812934480608734582177152703187939426687223961976274547227366150916137584109379949067630208858792329939845114289322648585580755616610302258512584989884644997352747262852786631806253344305668062922039579812843505258327167494097412319071183014601014647063034669866001123270058546336028496149434886023941746932012392894414262845484462335477059377413559348424920746843432610014073597213636 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +4 +771 +891784777631246170114448424959 +1327929446201306785262743695648620545 +57895602960811796650871631801676582813791887579127636891104569893774562426879 +115791647579680518644692972256970658065423327120836162316857392245886991466495 +0 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +231583736816786089484927226016147767929578972263620494977377884571370600267775 +0 +0 +1 +43 +597446603600272666897934188543 +335986975837048587653674597853034419125 +4960875119562861993119998040929006214931859756877807299872704131313015193599 +83869314384839239184918994159181415456293389193220202757469792852202756243455 +0 +446851339107039186419289111745794461503166996177271801631416983378126123568718875224988495884755883200400258616355472950696139342262717961597794385919 +2457416883750494183832570853589468397031071769924709837931117427688509339888648917495080941417107639148560803684251898538275596934697939251488325371868124 +4104295260045454815975181617904063417540583687524096503951973213007375671429493052370291608008405377354342405201451646421020861407202042797591936611216757 +5398900427668751217850873803494875937404578551752982184373461962988643267134263496913051856036153441820443871129747572123078186712219756428262779956232191 +1007218583726087024268446200406511915539475815058077584580036382202886749107233498655574150289262240696650047786995708501433958989054102047792490904760349592902261758650729430923763743863222004063022441814082480599888346140582423150899204609625387915667741403853025291774074147108688932055983390195711 +23380145599663018538794334849478795685367611191421527490464557496763254711125422173670092394177895709559935294769976819952372348766078401488089491379204849818544542158134496224979987816433965631446790943462305235568068590323956450149969681186862262029930095126068867520361231472357215498730835672433665458819876311608479695607535070166435960898021320714467950701155806239822554229659277947203115399804129178780683995750006285527204806890220566457893817 +0 +0 +16 +417 +51915870197464503363519381505 +252258564697022016064972069604476995730 +49219110417420231511113764378238860427237875311237523872333835875498405658625 +102059959947892163134217117691190804610012473033509494849327043219849901768705 +0 +294741958829571476136926871256484717091819171292816858794352010629523393545452840612410539842221513608737007525936314033110034418127477704314176143361 +3610022075817249902604614007613923579547402226882542852635039392814912818785402413253274269359316403441885507203823787712636067696281764519975647585808036 +3482683400560148150354019097545843271463498486574340530929160498845628623564983594731900657921818042087045491261078134766035389271551015123919424955561779 +2250865723942111784039421608251851432625547218473942867505887413831061852377508665133755951631672797483190995230665622102487996363019684093932899173138433 +10365393947735305013406914790529970011789937562186538656086799243490315444313309044458058836146192026472268081854266767322163579707977712683519957790124192466318755078159491340837738702367012687896445047003782661660364048868352982928925323993821529472941240126796375997530714377580986794001906926616577 +14333822648693704865076879128906075720499136539069158690685854059407099164825884209184916036182302301395671457986593271682838667112004613576105840990149035878508820984562415792148035482874225110645395684214966452961820472792442602064243527154948068695736851229344379321130087114111462740896607157184206550890192589389891097286967351231550279425607394341507476319668354155045448922078367672145026743791767604387213710928364307934410387263608077250700922 +0 +0 +4 +857 +1131685075580794109740493832193 +5591051640426086522729162377581522820 +49306867245429292665712135123169680084542437782148851479415184718925278478337 +25169675183049498057756995668265957449819867477380947926503567596715595792385 +0 +1542102799772537760963096697799266983934002048485565532539213661192226994429815251647197396526306187090160124800082409862575273365902118268755683311617 +2878686104109625229862354165402805665509620736230260577444969531934998053988812440085505116849926944621437581036715525742444317675163909046866434002617548 +1408524625048880495289336975458683532829516256219036238078109087870567897704916529748103852417398524574297919263661719753670147382638802928308999469587009 +4742693590966914277133482345622645931210627503968707620206733070482049794927860629080377711683265908227819055370520162972241526589942916768449868513411073 +5553130642134937791530098743023191297911732972994212582055485264717254209908250004950803382001574291176411334745038178232430168856024215688613524818989709760819986306959630308890022984882592785783047391490235914166320765169341522983194375620252621448545812049279764384555916944408353668680790336077825 +4723927638618295083690092755463316838498918330240796682728223697622545893312048720733281849001727094418300588431465926349278460120916795941753250274668142622894086165783902042659225253028435298371078758268910795425148305403592272806883261778790469890737429382002305486407398555872939312784693343967014010596526975636760014820772215746889139520167274303379900890377661917715485803657804374133841224806618394107058611468658108088260131560551896063029806 +0 +0 +1 +339 +813911142051622544908469927935 +4998080979218566999874015281917916555 +36694329931173559945696159169023191810080707655034316545018050435414281420799 +28634157081599137704071405870600522487246030369305940433755254306653996056575 +0 +1843618193774705784137956843790595835260885788482623306691425639970821561161960610834735278405087149627169615102857943696661773073162375892056240291839 +1170950137596410394079556452052007744667922551742356085549311726107104621063174324321159198410238181081409377899289339696505183364108241398143346683397274 +6266577599180715272643179829794667116364415231701874317566806045550798989424764451453171897199722686363150830763178386494247478884029147366386550475745174 +19499454418662965629802092201099350207580257918576731805737028058666848388525076659636862212534884659279639848323707620894715396779028548909594207393415167 +7491310775427379205451275241696534198775207876533479087995103252323137907742560676206102526955127596768143236592364563919391365130622631807244861360530642258721353802216367646769792844931749654022069462592705831533949527241530587573297737411586728906086303832296331156380881819739166686878092144672767 +18796502162760160226250152204618694839807906286113092800003110777883789218842243583036064249900793594494008242546403509188567430371285061255161460873411492857908336448904619340775306266718509033743784612836222680866203517611201799111354771581380221437368528919952566186512228630174278700984373922250123310919722657324347467475261738175114760435522588005390001769791388961028828314032397203388180386644894795950381375883062194583758183135747713996158476 +0 +0 +4 +729 +828471727968036044453779079169 +246763246873648168750114309847746005595 +14797796466515082470342263148884814370442076847061299435927018837432355258369 +53523753874056411494904927181451501266586517086289761739581598242912772030465 +0 +1610256322768663008681400364814073486033869865214932600830364116109232945229182624979010068028626424299039929917408136658184480247613110744087848288257 +4982989173773022649022397963184917180752190882657662748886552370901797910421968943370653256257967628629024664151919676967847090084950251857702290490980262 +12148110333218384648436139282566844904693423767379435822469549432550659540325752661673352721491851141598081552703324243494124595306618572675953315479573797 +11028869767950066853862903870251721369434866526464337153519928986032553183047292589177288689002878431824162808354999536746934113300550015294401283448897537 +5564677243506565432840796326485830517108613266274939211083439123715117854386689205611896780808790236784879267345611559615161743402643098893029929273758889773892627347825037932396714085133601074675261736569510119123888317868706628104410262093816075912392494216258946925258732634257705061191794611453953 +12832448199509312748037695466110344603691973686346158577275697531431038398255234604164046550781119126216534644040340178530673012471457078814611960997016443056894042854161746711315668268536386219382705407726308690881678952673969590544355499320160817266809347245168990155961021732027075310147074025336573553132150745598676058388830602694665869887746332618578258133919549090512076129869049818309689542631433818773293308811803158552451157660610127239822650 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +10 +348 +734763819450510610632565325824 +83076749736557242049732541826465792 +56086793224325083479877516880625996376700331315327416568653997679101469523968 +43066253535244233026187978142387001755402803069145978156050831917314998272 +201496559500976655734260440277137434576370058288390243702942488773257463333742 +0 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +3273390607896141870013189696827599152216642046043064789482248405676250539528505110690804490707447337828870590656092725446174963629590181147084998049792 +0 +0 +13 +684 +887995200883511538239500451840 +185744035486811956755421374818265305947 +28022724762678085694347421423886262818477620187692930983847526359050708058112 +60066058720019429804858835809980860963604546002890479581904231770820593057792 +140726188198724864302983488206145216978022023086026367060204697866126599261742 +0 +1306435882293703054785864617754127645947981008635081515972982328252373992773175682602366698784049948578438144756464452476167658757197266011674411590215624 +3418924933199934873321329948743314146142040692630731923496865500679236033474734183436540120875605867521473258874285532970466381831296084581446997731696468 +3109273453047763295057753183837237869395959180214923717206774456268927599702732452171437824488600294111292564013762251960507352853270412970588497512497152 +286731836186446095857785724442739726555989697273304519023165182400415887707383423935925307951900182657313805119211164740403675553245412634677881978590896153075228565724249371402865963565486212287922871904886718220392004596796756145262329924195978312198219275306469037658944155791679821415216932978688 +23705763208580774588928458369265619438916460021945211232193047627926603512005878931377912938311419163243403002660952903410656586223538662133420783063393034282975381898012298576963467515440532649689328334345780681671723172171010972029952896075198416960048234210840439701334495379764884464832012212719290831505340271260696067947540265478850247171084561966330905870702345126530017405343636921534310353745046761481665427795564834777302251191884558790364186 +0 +0 +16 +284 +923020903585570222185243475968 +134595118892137229728955299113857603251 +12517788472856075617475369492923779675790060603142796585343152963486180442112 +21278317616479394781203625492118767183546382422255138071596449473207327522816 +37333224946615587454531558429668776609410791968643457941551824417764439077616 +0 +4365216629959533172982077795378474518196312747569830926192625581814797043834797277039496659650371970445843961712911189437934023902885370155197127447599587 +7786275362280256985096504919805326940788214494037837259488750879599254096754641518066648702992692840392471672645638933505566197966897842107066681649920912 +8618362445903795498495298150872761763162723533326999016941555427533106887247180867507912332927251479902784257469217137485980295377407380260430728522629120 +7982146058423899625168899480055973629935142133954608148082398488598972256455265091746814757927002125120326401286119392678755814780700585901254416951099507381124434116044162971886485060919796269087997434118497014919733636378546760466317072097028651097132741041399433702808164954962506455701888258015232 +21989330961427482320873414443063015928257919942443821711178892798696487896352353009088507622971045148342817299121972243674879166058756712149437499808420544292407293376143293804754263654378017796839550542953209140796361828649433680420247205870246799908001987021274080200394165262473622337823240257874872815088714497275294574219657771744609557582141606487864476140423350129460552762119376149626806864803509401361323064126501267414575167852478576633701103 +0 +0 +4 +192 +132781846299563114295034118144 +287795638097315923177133982791898021661 +41260134549646540530567879497450034797936197027784201139228793125077872803840 +26725487537631090553213382951117408090775065651640692466752663021330299355136 +17991000660342902270761827603753917202037974525700770708412111282505637002686 +0 +3944008675763809747015020665178678882677044257366818833894853057097872891661745300374363390097768393910140535804055885471681266094856681311889793405842943 +10432168002169925309120503644722046609224368185326214525537866102657473676610157919783033661419495704812662343601179229565468596161053474859566232729971168 +4434125550755468286273915949559378521845137875362780075693690876557539422008078027298618389135234122502995076657800647221775819541243724097410850717958144 +10544028428859860647631953921720386323000119376125885681800950423087768127297571058267839503395689317829039753434382369495774320720145371495400808557366564483951610047346873818659355869536197251947067485092374284236784198628790721882722429857933128554802811282519317048898934233902279839985805232701440 +18440345941730146769481994533733567141044993718475504938583318912857102648847047027910392382495051573769813528456979411954962447707741851707281536897396641672916772895898381890381674089051912642497004147872377088851984352979390381063683748636451983558056315085668918214320300476071304869797011014426609032047214117423653962127333957708782154126828418118548172708012943197384144043383315600410200355075913830695186216882152046505722142344944887793337854 +0 +0 +13 +848 +582024649450436441833425862656 +96569028480694229617495306964621095513 +51864362273957721702450812674007399695894707256635407766080228745350205145088 +42338700632985114555032701713036006818320082283349136714641228033327395504128 +215954730055182411688222939177706107427072066045627310771072503279957579162468 +0 +564120810776501871547030068641973310984074415468950923614458445915309234305596816720344025395793468749961903973331424982658487492675732875715746581881639 +9512030017005233270085163286414408214444876161604376761868292912053847917535106665754020297449298958739630340441868032179720694634048588859831514895174004 +3424474661482523359099400350868558228999347406743051468541630110333927244078257761445483195343636488588952518919760460591527948463291377508337491634028544 +1908744027142267160255992222033230928186240062062564360139414061079951535468660083714712566829573866331135382316682210055579103865954047482673249785878901884126518352007886346248743951305036458287883359238321077240214116300549133893047140060961188058073853208070901174162050948796606119057608052572160 +533753182221943739411515817506559992144353474201345586358967700583566469936103300520749166184587887860573873190047587658861707366381179609208438444812890854907402119224883354291361848266886930865694292240182736475266290660159879661714355945901578730736360959787897025448543671196789177297617755152629881870393271660514425363164245734715462258579427757199028980848704112940977349320451917649697374845997311260177033885249436939940782382383929118269489 +0 +0 +4 +524 +580845881975944426787514089472 +247672215531302623220114886854143351291 +37388457217608581848439794961125547405280755409544281555421884293853562798080 +6867524968084435742227914739535272191184841314026237436198416499210501226496 +37084585770552631634036071894836390875870489411136211932476363892010270509161 +0 +2060718003102261095469378358151405280518660285538331953442371394551388847723544748074563153067316177877347237081738459763835643097859427740490945401065896 +2427597878315108052588416153186371822454229878691660809974423528713640874637568365876246285814256304894224389434236414966957500210729605332124313726402355 +17899117585006203601483637166090154016991728785619486538375724587636009980913873117460186227173247676970981855052572465455831400785016798907992702502043648 +1871601166577895913665863813882743743306248246207644360499054669218177312807383799762174801630805340092267502315367248573627278277545825513989809282952455822056852517152157679111824332559476177533337546335447972701488371422446112963735366800940695179512495443184058856851596498196420939445759478071296 +10550306778399659975487897356875358924973318622498728253620155978576923389364488120390171602550388451242602890206431322088607185746985283921168954364764596976217073705682936664824865112089874261838527911965608302408800742105060068062502398384764473486663935558909957592004243003066730197686300227260257298269425658277997389598475973630768006422518890534069851801433726348188900604318019697404931564408067035791107685741964005839508900413176154475821036 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +1 +455 +12835319081690733822122917887 +127603331931914074262646774143133941767 +57894298449951398757252466847559442906950400042978305056517893187912714944511 +82474589191995733226059000413673369947276401483368126437014470136553367666687 +1725367873614246661397681099761093360336884063153660970896243052915304594387 +762145642166990121634319750876330910924084988636669303246807590962648009181396757661856053558136824594202566053704052044355748404436481867775 +0 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +5027927973729236057982426364448826617555638513633071601633370220421967636306746498030257094484300966958703364072352628851378448187094873990326993486348287 +0 +0 +1 +455 +346299262836863942390852878335 +124566106711135523024142034815609358702 +44045214583669272699005754870852537422943743579723467162109618579770773078015 +47191182087471614723727659086024420134442459808826251007744893899083683463167 +149345394318679384540349467866290540580664685942593858325103856164763257832712 +328659738499559851395369286572775271201389799649696769367887874387602713649950541005767198083760164244451135081042951771979928777420726556841593536511 +0 +6499574949616620637580116906143754514426259529884439117780273025054849187451370731789917263550769050214853609122367946205434263410894715910936878759479861 +10124369117566771149603816821574722189892029783289052707167197978669109873476852672835440349606345261291423564961708638702389275798144171277206026719330303 +5383941699543092305623443842804493263947292181555684893992973883142751498900796716464867906615276957493629319704781718428057228609756150862864742004037399095952297373496665788422781648005837085478113966408640459815231657886564133913536806437981143729147690610590905694337501640066370356251688307785727 +6310918068059471764026319883889981132676900864298663494645342741409042787564204104397616974568887642296873516370780274089671686771704841938229887196137460632598595783254274133337225772320128927921843666172747542030026661734330465262950674563868305274037519191385934219987327624738988091242143029337066541173427000341834616390107777280313836624864077607937735030229348205663463578720868333899592726387334113240438244508441849656170478117348105420506878 +0 +0 +1 +1 +1081180894199368861240340250625 +276904095316794738679647588766540076161 +18514213011776190595773191080849496970028811091221965026218765069756819046401 +95073983698370028065196578355547349954385319767423967546472360718799690792961 +6693017956846532764960681557697229863590470801886832055562479247632768202596 +2629164625513944344764393375912545052754690348620826079674933659671918850737622014550902801880361819290452858809500518180554683024947040651570430607361 +0 +4137577240563885180314014646510639308253117303602681600936018963727274657401877961996913350454564200277844605264306113013779943962820037004955398417119598 +6012634743225204725211101132320048969685865768619552174466530181728480133292301029875548285114373185900664580122272341980596861811413330588763908353294337 +254535129586580270548521975414349752244526806343151862080007760571223205791187472902044998439332623334230660834529731711989369170257700618020245017747639011641677093780420045542350067272071826391827216607645254644193288995966198490603503031365625040118877912466523642200661116519635298806043651342337 +8385908846676081908370043980559351677127770716607791744592576475690297800091571658800512758412511961004663163941376701719082333294800426334317916965716031020176657167014768130949406498916053374967901129501825532754676652724685176412371614884225185706503174134155152063944407927152995929183429819648489312242513817944158673167844009257444561330167132349514611454316120198401977968656265677200605323359155355731762973826116236680898629609918324923846369 +0 +0 +1 +1 +324956523760712896376838553601 +47627363697928134504927977366887218436 +33434307187530355896632894137563272179790850372650630159758741607677205413889 +104315921941200306811166882397908923183277873670404242656007610443530523115521 +205533708257112897495155981027938658151590718760836138711462112141640293797081 +1107909686739446306967869518645944435031236156727422752526394105581762893921951275569530192146029955926564787705997591876292833451590952315825059528705 +0 +308755345928398507077827126197262399264414124207949539753718673573534243084848112587571000480595914906260398850382596175138781946603416961836963870626141 +18244350893087399850665188670118991037975220133032205465990746245721929325028153136705422106519390226837480732385191993725441112016188775082810504002928641 +3665588193601842217160462892006519794441699353581412583510916962644156398320556835171594452576616053963810443333586339255795973680000246325868129939290031865642638045425971867009672427500503914468057445618838753197439907968265469989645596428647594500319536081932047598179754671610950943455199214174209 +22186396831654097227986496390728371980330693530332007779166541519242688898973938381447063194690736625552685027691280623961530978041318772892810396870809949339891780432739513792778708087762348742046586160063394433346940941101035727747372800903757578028991776450199349428475680885800121505072160076081825165777670772329510069207190667831629973354820426821121553497181841257104073871622072935426694421062659417600761519902665044177543487193516620418169098 +0 +0 +1 +455 +1168225574662879022832991338495 +57044890746169261651982104206166026733 +24779217388362851886903530808112954986166879528618678581940026232185554993151 +55591006844159235471682881367005599231961414654778243528698592315005808410623 +196546087471840559446390920880856282064404926864490466841380522742929941658568 +1917639872072259012937469746034134309612115999398820982521714520910586889626920621215182691543587130631234794290116996439471618261125269461687047553023 +0 +560629320288680383605194363023384807151678143098424596613421718363041709472766750167486947243276747104145109416759625120625677741081131727837587049341019 +21759673470171209133072662941401074809641596506044027427359195245599749269615278218888544963788731822407161900052925229605030503595641862078189438914002943 +8222674955398877316557535473602868565827602242812253563419515952040766275770537334852962079852348771177051126858608391846792829268299315517383515972974712379197466243571886838842455021350337318953242740755305732748699335134286099636570483789761728214215928903659103496254292223405306563391980052676607 +6704878406080177707560203655054736070477248576489688306407842672251903096919006312415980371154994403260429964471609192482935456676801001230508899453034708688807610209409717279310365716437632450197121589568242633422750297260272378736694314947182768068352565076127017290514776717356480481674630872849763970700450069226388331363736946106411055783778057065098928098706626638969150760900186745176895660013716070551573583271188993227435662677589978033750659 +0 +0 +1 +1 +87563840629716667648756940801 +32581458921182292884541920892394116196 +36836091762090661553341041736371299478161889753078991612037085885874369986561 +103386798190572160839245264014111757730316335866975469301775408799589041438721 +230979096632485379690874166782108500616204584679462971821585472432375012098081 +1175849592681947186381704220573745682736611171788630769140595898826048744669637879095677970676093415500222347357756142334095120061003014283574860840961 +0 +11889537611764019713474395414522017738805331131412830425961734413527746223621889642851856767739924676858324754442498238690013743634420772752231361918208575 +10100837533498068062116682421711269237464416549039194254318934545331492474511664814492105364025928254622293940722169331634657785497327849544082846163927041 +1369148440215267019286304149733761118056665924873961991411630969747965209899998790716499635578218937487656801015714762781120580385002698505340071100124982713842184248347860416733386896580942622009293934979960183456583184237569483817916647944103549712738217905254990813029611090034738596009778303991809 +14470891946382593133261871975556948917962250576470186541215002308627316792841475378647804951570288535703522370652296694295712464047904010907340184090003647914959531499893292863053894273874528256748420135416037596722727653113848255103464219786106388140414129037919023044763659100696777268559628822671794913188044005920185870352459166957980274030642096976079120265889000691672667107327976040012293388052690990946304488345186187456257606086924331607962389 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +20 +595 +182776107722364003135434784767 +281466386776064 +57894277771803943810359491595023458960167522338927730828258057680034478424063 +89555305827206481420887328961785203324625996138257453019240897699860153630719 +31072229483910585358509303280765563029411398133731077240605874038996845471709 +3273390607896141870013189358366943131609359382662427080975450085374873026606564249289725539410814263596351691407518053929870103702401568479817676881919 +3351951982484124983609172268969732236347481510662869536744042230485685559782341996467619926017805728755414692283401971053259449792684445385138897718083585 +0 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +13407807929942597099574024997867385471458758537929012740010782671329620832395834992528134114986407662672821420428107228756016346166874193365792884690780159 +0 +0 +20 +99 +959889322504300279480128110591 +226336563431145028687618637822844548759 +8191728281812111000214169178820381725838839982899041198234467802159092072447 +89010858809825214210137289255494412179471657721652615002925377757309556490239 +28296599574001589588954577695238704244097106391390255507549917926893049677184 +1143685232425095012373289446686042380253702819534317091382577237068099768813347351859388607019602275279637030972001139645555685678576527645905260642303 +2104386984118747727716517063913738816025890811467756992449715776590348174368338808503581044664946651173257522380822233775261192222343142632013731451133938 +0 +3245766926972643552330628549049705392854964955772154252338528686239084242071182385973867724746592501989847967320150395945141828002524173519974765401473023 +6907648306248975720047253807553315878303563975921476580151692887533957733952838913222178155862261045104101262891677093360305327510435202370854866877221225386828546336285443261625103246327521271905514699410432996107397381514692809796698965099058352936055010684764360915671953963860003695683345510825983 +26447750664679572972311511491346762878392092007822795854735091849389623944255827031514453721868656369736370805514656452589804235525013818434397127292257036933491312808959509859350482891134824058764033024690355796359079598096947363393151627873770672958867270537674600576785634138230894329775351387231396268146781903236645159728891454367132969379219264931998221585031609847512363429272555066238888068880222596086485264677276997340726172359858551867347999 +0 +0 +1 +853 +801006859139436247401554247681 +142225711339612348039388698959539597716 +35410378673742450051313678883687618704562356389379983514233123876029687922689 +38091574202374902858714012832961735959144676797295175057041826999843956981761 +35509638606720435404002212308149594900713246317816589861892489724156349420746 +947006889763449443971526094184752460089916877997363377410340189611125125701316093754306776646584059092783200306323088027637258553889934093760610697217 +4220939006243733889354999574941943865608293932174863319944209124029612039884827143990223224550002012724043690083235647740267932838159837905350721905177008 +0 +9819440398814080363130785191409752685155104538075120057014007750225191492119731772827023591993721591147390320845851382883568011993500439254883415399333889 +9655632408759825233958611797456496067063588648590435065602226373676034823927066598142456746083088436655720971023229982832504728539123316354948596655920694029523232211427760301619988760938379731840724545418059474244039925314243108598463317618776112331037188490273232491842485947576029350960119525933057 +19168469482771522387361980195401090898697209536327388812153014901529211406007624393592650590928364242770484062532946351666565045957764391288622530585296240046291185627706970869937489824896647625260613504074528292679224168776865581606886288126591395731294608037126460284763239262254718080804765957557128258706900873267005249160304719047478911756155253168469506131790620297150118426293519712473869983955423743730285845904324583142963587786011293140146359 +0 +0 +1 +673 +715561516884788010108823011329 +286119718739330631910267662147206086291 +4077367256260361378876724861054846658815066802262232907668922921382880215041 +100388196731105783095258894359755309057443209346921752384716203296701221437441 +161978619973690354040532742933073207830461397640286489633556474311275198068706 +295808498796001041580957434812431144336907268953236122391222657342664931238894722072411794573977944314328249736260072780418263762201867190982817087489 +97407145078903878701182151565338220720952838018650765330450334535905937357373611965592469739325221569980257894281512858606923275277875824669884901395310 +0 +25619912338425179981237074026942021799265536991310528535894660424287880718210785582129672576271686161615856398250702958965821900733894974363009685894725633 +7671522909468965446688811864997649775732139334764200965671339202409525004787427756456574114546598384573443159084990772200209956297641268137668960261240194749599773379609102037525886640588454985746187171015912121459949370747421414640087855414458925160365198194096646399383154836512890554710890718953473 +10293884923205428378666956554848182142244715690619212169171170546179865224723565444900771453248701102868483061985574173559709761183179067864659447677846955231286308377671525004854738789280605580119191885659203370511449399894078589757295087079227410959307116809855467581150399434097595488801159507371338585214103760300181569615667928415747705672332480417684601788700985353510796076482470500651763753290405004222433976439506565358025254851862958596926224 +0 +0 +20 +319 +798574734973800499883498536959 +119319092661737199044961145581817753859 +41294191017998785012725086702072135678398504724859270409452353997253994610687 +110624822424825875387330825570332783320826449688572761060969648171618999992319 +60004897054289201390963390115257285329375358987352500183853788324442296431274 +2150478234121502140094205664847123566690038384648319032584399902322112031029827710253123600637285764878597164636106830261747369442317038978555055177727 +2286371016578508441121921294709678407693328940913329697268533575124016682365838296403222603898047913087019704067878310158113313849417316810388464204629572 +0 +25671226303654754146969894507457657987204391426702541645624778236755811429128127378887919394161592482970532540809070418766878887011243610093297304929828863 +4785525495332916713108346669310355883208597124913721653495570548939574646651963675833362058107793696545444101958156033302876198568608530737409310207901760770957083322440752303097212064072393248697788251227338207068162143919875155956848187111766304706403350196933167632508223394324726953817363397476351 +32094431582633234807734495384819130272063712020829901878525215417797644447839755174060744776726644205182311880852974878748451402374419467270518797046912443530456212016605470991508907045276371141670695248538943422952924891445929100158107096854447459717681547826391098044944416207597160685051923871604127853310380648807504003049978615375745963324507225789653536595005326797804437482047876186051782235982636836244442075633553513047827811973923415770476767 +0 +0 +1 +337 +1188247491006021359695801876481 +11358522768134003317334293217035462861 +6973218261549576848638199934276587054115075947565903430900153448684127780865 +45591291715308727736165915509600830342618838112033396612024233841157189140481 +40977506359948200822020517638847374989428006593590887799032148830447784766831 +3158526125081113331509898514788313887509900397230108802808242305275074329114995683632326747175671847567894522724549111521860848666266947552987433664513 +4584447565436503172316825244033692918247702864479587471557460110462846155092582971475613387484731203139053010262859517492416070493565968167184179196803079 +0 +17855886664960195299137683256225599460539695469189441741138167148311674787837063586188982923974069115198316431121434733749422291458227574255634138536083457 +1374356246318253574025982110729726842105081842171225422931088363015788466146368528015009583509706677602458662747215994780981399824925913453782201779377138318045172999325810798864144189015648497899487658934661306497156780183553405477807924063800170898266248650878103340616913829333509130538752749338625 +1640563579891112614924709605958688587289742793630758509110339884654417246046905788570037457484399424416760895124676877531011891636277126802773558750473620855831931500866708684883937438953118514443126192930877064490752020898747438980089537975395182532494013272495476219349907646220024050095700438285617434068609057901263757996869152424637406600611987744170919997651080917069478242122542753946615128758176926986841759042912203967255896726167421198572976 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +3 +780 +899245128272588436190215012352 +79382824738944801807794176002 +57892510978869681736730162220291002611042557329170362915611609916721313349632 +63318549916452990938470040291368379201286383559458191806845672058759835287552 +174649700752953765434988902296252491183916410461948522823307150782111144039507 +3273390607896141870013189019906287111002076719299707330406074198757955051929170942113619750485120149822099821188584330248544763114365430245700361256960 +1675975991239013909235918173490637855139324507692685389812651662983087942796182042459207730713681429512584287523480954202975430917613169254383951955361797 +17917957937422433684459538244547554224973162370938960458267029029640947834979519339152474433150005542914 +0 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +26815615859885194199148049995734770942917517075858043397979502765092926124329914532610493203135186264306101107885244098459867671853087539206018919387103232 +0 +0 +6 +704 +1177162594896717752709689638912 +96077425054455585888525548032358255307 +32860001485564213363245573215878063920603649509172460851204817722599339458560 +60109254545096573330255392159285415923549233358667844961269905663499962417152 +3073211245680220492517146661351308979695018043393915095083610251485928253557 +1196437601768571072681596644798276004178149983088278508148600069149523733201731793704103372368213233390444497494452110276684749064047644093326087421952 +2038636880556966905914764363156480651959910168504797327228316486248128297682164213768446666903998086070536989636186162862522556977670168122610463846604180 +10761508670374291972420269797715021028414464448240558938464987728552613552119689435329519427607648808039987095579973579961133046464353196386286909020663497 +0 +40984697395123061397847385885955617731982529976694509690496120168455541366383914951564162858485528121548558319374726064139914899078481865279546572464299479360080901581918627814605543248487499283343493082927078480873799428963538897690536507270633025904660571444960128829640263091486837879144125038592 +8909946412269299572792850981460782799532037067275283441188867265579333027637974855653738811158117573684759311560589042257190296847643010765802475698723405320867966475350089536733110413273085947267298794710610764685212306019986582674496969299883756072077594732387268624852957690791194886450004295782387045096350267854332914068470074912878717285439467272539570799182006042059497909029848272463040589609458879066125823035788194404021371601097559221551987 +0 +0 +9 +692 +76435178552732951009197817856 +231982479817395379926203139743231669376 +47577898445412852300055548317787946557302802230354890877227185969553614045184 +94970241355010768267008081913617218797759253919929280496382103858739366854656 +14056327310363451370485055691408505290446120500764073466549198485574965172326 +2766964662182057386500329725111256292868978381151632013212396637813257618816895179949288796855976654014890661438562190344471725761340854297277946134528 +1329225061763580875918533781650822376275620990297295670554223160059148641553029627129765204098380667668821227128123235735809087554397139852326517131173276 +11097141842847614394079602992178709247589894415852402133624794662338776078636709858667481909108996684238974927213647046033793578164937980468332310219323018 +0 +8071735877529897797164814472711670751575699750650911010717417970127274646674179517149969617423521215633934503699616678817716843715742637948946050252837432727686220974468561142882832356080149399758341834298569043889563654149450777405007560189562518343814488242871896319575202397519320214473602582446080 +6694616185800266287626591614740434614172450545677003882600376830829359762042179214842368391192674719407443643400544441630973206517018113283369936295245057174712933556994499956071283288989464799795553730151588182776157104143243273082778860642399792205046014812501849329466277700807982917596823152488508302015315461955865789728769054751228692423119905880893937895064193158759226982592756051890511086607781198053342618530824939847343739509034244875431247 +0 +0 +18 +856 +672949534961130560651949768704 +232952537159279159427935901397589147661 +53562723566230157237791876909273765997707933576810908258367261806129122902016 +31550994824562540598335530352687292695019428977242991470692369974431355764736 +152032362650815553704368562568087238407459967027457421226225849525712097091101 +45958219062793756897818223297329408371898301258718170247988696901754793869347716750803095228248960915336985565984017868792052415880945925312017858560 +2138965005429346794405216904139045984058362385566693925431000008613749092589355018622253069902180893858672397449645385554064735573191661559383999731945459 +5599082768478558353474373621584847716101862099962719911376003810521845817678124356992801556560959828813284665370289254359505555309567567683413487963442538 +0 +8505562198751426520419753868937928657815376861050869644650730877638862873089958249260761602153572619531088220914388128107806730704564885365227693238095778773347289827488140170092404396918489146978219366997692666431664422833499810391011971777952027507988195640695475217721220156144534273026766902657024 +13258845752058319557761867621646364193350685009107763072613748715545508884518792435165640060432501692620709571169303323832489898753595064750109814688579187658973115795780901167999045757923357842908980476028181042805278133908688854546483149229843751393689435259677649157449342132761603805685178078740303455039238350459994854784015714248007648831119423734010949858462504093063563879993972734732657191983776886556653813278840564588343475007599515963220807 +0 +0 +6 +528 +754710143931888045283579265024 +287963055808859601191421471911256637338 +31470892304589511166080140750820995558894235651868644947081847455352142954496 +20368885260017261654021615802767195047009744205269123887896635371822470135808 +142720835682631691219581295413272156653298972135487346569310533961626415868843 +634034310188921143352280112839185376851989590898296042925196037660929073594178058676330909116314511976492745895031863182439397264248057241967936929792 +3536260655104985228570598047629889621504635464480007413999695872026244668858612074261286775235489798011926649959578184502755418831731290347207977473778761 +2287281553939530956352194620419013279616295380484047525310562106105104280173822770723063903213369365468416110828105561770407010047970222328014275531881062 +0 +8975406365256287079502146141544330687925839285578604542063444104478512627003244297195048898182515489030820157009675126108192822666606148894492389023997343919294064572180355360315826219274413911422788253153439868196680254069763329891225781141566431534338291820281857844001159772664584722309392818503680 +7627895627796776336034103253504663513973127224674837000702424659700877395432210192501491531145025624704509245843631295415207650789564811514832835249177414395254574557066114110734069582082204595410051869299928733226428505155385671730599432801289079265733997957718465603964310879479766099831516659589939704922842510148318960095699074620514977940993795465684303075866898594805143270298319852548800656967084658804532267409910838781960922542128682794059262 +0 +0 +18 +884 +269006938810274604690777833472 +101610588522779797032951766648409694306 +40658360805639445426216385690775372728200090304603522756100519340351932071936 +91802138973420634587973914099224098988335694649088995732701581040017689542656 +160395547580151362819010763928022387697275046750539372389069219756723503990401 +2233124152381198796145991717823834504772859747063952845191626176084833539989086207836671472551515196170555448158422751623837827519669626403644933931008 +1919252284176976160011289332010981490746074225906227007498726993112622893994450491566696784468278809972885041734059388168593055735985280406694325759910450 +2289668776080774022092664264319203559647600991451909561040327250000009538496148645073308529369889500343496260137733562205719817974360067449226154885838315 +0 +8759003555859924455289792006122150340086642892965675685066523367563039345030166298894450331668432839835781802150906003659255941165890838655350310430355795467012027286822624520715979773959322702857888683940335230551215550420172560712753155144372559458294216901317555971294843609695973013254603739758592 +10233986988627486160165893250925551838419499341074966949334890607408070394472982377098453235058445034249828511040640776640636214044010669184255119316736950277091273009417324454157384181382413000016000601683912644163946480527308355567900081185611244964219361614299468279593357197464317206904586553970296516293220670021691347612227687198102745489374326883191094857906024566921950771760071555266307078912566589261856641951389747392777294648176011723094938 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +11 +372 +21559839277448701880456708096 +5316932265549267143283400319839567616 +16282337714987120045892153486177165723161016453744476162789802658371874062336 +88537159989150876890408569427587371627685568624275408353614000822051296772096 +117153649598454680903779921606971322936867216714956963589387307178373077018966 +2451846285358576582757929577719947826359368522202829009982370031469538161149259226929244677345525601309596834316982200231651181236759995889790497062912 +3757219424385931343692363754866841943466352992489416825487678472853020775555494604110835156534238535884545156565469882173219151445924025758587329876446051 +1637494313049913248505508525988843145443777840250318553676797222770022673451141317105487157651955800518089884835975451904017985829916792949984404185120 +10058766516776922387083424546997939506014390161211981301999104219673036875504700741486695698194962976600388399803269774949866748354955056527082238634885120 +0 +10715086071862672019870723708373567867164049597134887969429342556289689092328893032953381579589338312602609246283412714238525362926688916032991604094856600340922050198587112063568778839323187143820237543594206457218073322356882436956454658807341118763364007714359232059366253413058442519879029375369216 +0 +0 +8 +788 +946214455905379764424855781376 +249640706902979523796329170594729366801 +16258878864784814636110793294682776772576083739386883456710601266131116228608 +94078769493157252401658832572786963194593512892920809466055866983486739972096 +195490272915595318817582071325338439133008656712282569735706902622916446459266 +774359154233456237796402928872914317257521270747766957039349342659625972382672493574510375099070233552293990548180408226281598743426255631871050252288 +3324275818746059767372921081282057650219072022078335429667273973120625111543946446086475227802464005339069654858828935205186959839930518363496383948716964 +9690305591136628284730559742274731850602666195501871310082095979151178872403510613019650261986889225542227473459970356781573066183889915340294060566934540 +18854688550460679120040977419238299860098014817785306576788948091134630080082228033258246996685817245124205310980844728342008317740737273944965604408557568 +0 +21535908620540850229409686341283386471970416340429967737238370022240247758101364064839301635897318433287340370763594753912136240228661108354045783804012930997208048017799043921041828011421457343668782820520536104076035026053782745857307697762578688266768524636747474268145327146906132830376635108519593754580661809442020459403107922707419305832717345589771811762862349427813533987428011905051344117484841279401140909699065164456004599224024146858711124 +0 +0 +16 +132 +980393085630777633795127377920 +43821595176334581224008514546980603456 +52058795012750249675444812857939886156709846064922449115753994933360369074176 +14561123691201700806224839696324937581522964314772521776090379875080644591616 +175349175863053101686937135303271674300289639455959650994302374762982917881921 +1131906497036762609639522228534153459919865408591834031873180959858521631664870050151451799898073343006753689509175537114042334594659610848703981551616 +1350536895369391632569184447114500324766670158350291610958967597949326028999359576936432279782089126385784555900383659506910365560510605065726285256239859 +9451728608924473583394143032579162808176109643324961089109032935808751128466005303662886867241622116000970585797391055402890609702666479416682290459195799 +9869891012844468185531924549366273911251756943322915384954636117410087675117010026464336911857990363996496352787552233421136612436976661888444063719358464 +0 +29160913186613439708872461352513122879764789952607298290885068203114782142216922372207081593038688735241042977627651978016800109665004648282579021506383793652512992091245080903136500261598244223396601485010319512598372184283395628393048826477026318554363070339145452721174808395510502917485184825084502201409114714736758473035605478534635042521922391709556430295750595675343883087393107990838077832220859144502660929828804609103025888309324882798051740 +0 +0 +4 +484 +1089134261820156880321423343616 +145538748117878092352760460206159211126 +33511658511802278583722924194874647566922276789108093402830459143321542459392 +101058486350009815877613019026909063961257758922502987153303461721695947063296 +55893599922312747075336422508333078260508029486824190273117160196130533025956 +2458978570716352272715788097961829640376943254320968964331207836957962374258773872920562816268264474274565514907090130109741585328325854023827972947968 +2334497061062585013441347827924568919650652349786907365392347487262095082662967762597898425035389335443705851967166882197635071826354135997079594483994794 +4739636748710839604647340865523976068039985893121701111166740470358505579292913487988032483975449672818248784390230013345327930989784690681998862554218456 +9268358303535012104892996424126494308898855298485453509135477774190853103484671018397846744502851397110775756567946279667738536399988345534648240817831936 +0 +1823333014513972248453863033569237311230812126130506337878885326530740596368720446811271380284232373400475839583564476423453964756030828084801793759122506966503712459173121792772565318978814203256490836178101826827909880676810922045422401824859785223968311017274407457720180425066972434143458217681896098086428204645340725330308523442939629221459319570158112385542686278442818549344024940355939362383436777208099871277202253431959816109988249138938651 +0 +0 +8 +268 +345705300287849490539146641408 +28619945476059463819047280294135199591 +50097187803714017428498902612256509194829161297911658170445563991107297083392 +85421690222206289410508936520273729553730897899163659208114955446435945906176 +23541147492225259737409530414900909030720627244427625246343510574225863591276 +811358695156145842831903450818927915525548089569942629196406351050494125902340038663677284364719310507462367292228961985914579995483031930887980711936 +2753993259413215653375383555168520262036721258923608032707398699340884867309124328134824761429544678847308130542242013461361725575679679273117130844404184 +6291784738152052628532475385001151529792773731941954632670769788526762258081592087250332058353673371670605911117825763975584603160350868362121314372190208 +8246304950196854775397532690840382052681504659869650088188493089155770401666344769741621508722408724512112431250395089366004560986597746949833784645648384 +0 +33536828490723711025794383275603096340930562958525566355063509107668073876964224976171882248532778409771216997252213433993697133630589947644361952834437975121876157813462137576683247086121046784363938117600983461647174331186404053947864440728674994199031341263900784628270176815603173354730641751334159968196129982738215961466145470666104403167324840397876006086216517663581877927694551780431366423367588590449610474198496508322115190229617947779491804 +0 +0 +4 +744 +285597678780049650206757617664 +183060435302525962072268027628016111021 +7217761771929207302500684142267832220669089126781480397245769148255541657600 +79477460217247376097886641006546273302212937742057604494280155910320628432896 +158450537078399418888641617303234395161356907531049363529305739478391665140056 +560479410674256955928059381764241238133905670084218664847601259116454401923250286188028355182665809615792144602857372046658783886046707955042334277632 +3683866358503387723371342100656401419267927238139401708364406415400694153274197402996715954111156399475059634029565264927949827386724995677572872987734714 +12590844567997964881164942256818297297627752677819872355996517914899426206584352337319457485189429758905990389059981412286350729613199131538807367459067873 +14260854143752552717856629622964902246009611015390566846603377483401216738344769373127606724470825630558473764635392820940186579136492501381274523880390656 +0 +21800320263537007047472351208796015562335481192952840431265409041550951526374116630066499902549548119697525627775845229207308993284066362779188144732297218576386880741913758964084484707758910160792538754632482272801417299710417022721348611414238310143561872419421028837234898971823910500714741024986033307017463050796451118315775556231911389073082154651438223368297410117325974472883309213628390772734914681877034242596184674973753688803388293273496715 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +0 +303 +1157847834746177602004396802047 +339617671798359351079692875821060456446 +57867775067306645753843239588701162944294645608219998114893217643713234206719 +26369455828243150957066923597651481411694301395220676885210503666274163228671 +11817720390503827648781894443752171196964219125141796458180108788425643579396 +7804371375807015860240250407429415282553584425143433436919818048882206801446222314107580658597196283229772192970700820967091727381696957189718015 +941081632068259047813718693871170463934954812652267338340003979702879896717377687462914527089361639645292415086148993612559161291073345891219533759743345 +13407795142668967188561258511782701242040321017549139392778624385515507058390936234830335193232662892196414947249258255251754028773259240421675666352640010 +18030219496951436955703469321804144806589781292361309272091751131804808417784938468039344100394760314581363716192040882359255669821551713959394630176866303 +20764409093138106714694669222174000783080657450980639056024872831998438690744740872244449057340558976478438798965361453061982147397763104606367603575189606869434278459569124428885756214636676791959099839519692515219337740131125546138808227180751694999895383762073154332479036368513723304712662417407 +0 +0 +0 +0 +131 +1049832718450901370153113485311 +123743968547971240881793449350717343096 +54247495121211160361188037929436149205783261053517263337868798039971357261823 +43780720696046181429968922798344646336098289195769104725971763934578188746751 +8569638876184228017621190554815028317573269823425357131497263831998166914171 +2590756693431741009163041429286398894656679441703939344261083891915266425352426310916864582943630782192228522635328133722758329149109900984640654540799 +1922792972978790663157142765037754247364399993465703829196794167418278912188407110331170404215500826901691954309618913442459626285713809675553469719932485 +2247688179853902828346517371756160939505222414700682406758025105256274372769418491926470116598950917484231339173818993910715883012571037685660436398094565 +14071886071206496987190907766460338856608548573141424962453698818757002916637223518158300237915282267942872621643500179521389478132153075114062917306155007 +6980263492707976602733081771294983285805560539203752519918453497642718603261557999924227728869489680883742630490486041372040492077056076650919876897423133050548479425912646008193088180932733170859088326636344779595580028567634175375390724080269085084386954408009560789015111093719791523327272483291135 +0 +0 +0 +0 +213 +624277807757669988326564691969 +308806362863810512481109604679086238721 +7575495667463650924420531623779877444872078518414758729895107613392445112321 +71383655898197942633634404834290712896942744228408684751177316467115735121921 +47122958114890946067870921450228790803155389424276201823055498825762056188186 +1994424534807216528160042697004302546045534768650260352155667756798588514332350607215428085715884919952309860849179354235231346459029751145877699821569 +3146301561202581022604671318145679315132240673197187143392208577019128708207517211248787901932425426040980775091796171281106110880987357700982231152858994 +13344055815468537346229177929721616555294581393221545616480099523908865321613366395170905103332895603014771880154289842243792973144146321750132365948266313 +25653689183378345635977168873503678049300684399452321461457658485062084019322850001321503409853791883406838755199097647132019767454780407950907465283928065 +229130338950058715207075928314567718431940966481184952335048896861640341691504660128894140126073639123936931770837384336344695028165941321264091705246687393301105660309858229907321110227251032801854835879822879826073555284111211015122519313114936258162164556856278990251776549227306961333644609716225 +0 +0 +0 +0 +141 +119107286127314199610661011457 +208956661746708815346102549108455455236 +9304183766217687257009318351289386378056338413009755635813258086246793609217 +37346116786925829034687685788004865887841441332555982208115369087891606077441 +142686669406791276574941284020696419378508583519717415488223479096553530067216 +1022103513376169960952043514852766564406369544025973264953283529967298973963692347373601150129718093616182401830320452020826518193269025639232195002369 +1255461492445777082599853012891109353852057873636592494368775587155748628015369099916821369435584805024717479183629939627196544920025710945751532635492024 +1189975803267431345957974690102770165991401096160981798863264688637086156816693253154715236752646520545321786646254224097289874096394507609482395432557936 +2038989167013368656643873390716729359930711113157962588962483025137830789336536213929010174321600155153011333126258568329562186707136497102974740273823745 +9084986068063143759355885696834360372551159629320665871137722600252611748073183150082604901064288041886108395689572588307893872058553059179847191635406482453723540265118257106957652545879445444515005992515527078762521603272600432053705760074646655367876806955197570127991703691485644599174058580377601 +0 +0 +0 +0 +243 +699092340274526400217322881023 +38592925135126088279952503537704324536 +24069098860725904074101863281316659899407559169599337507189559069499782594559 +31845123066004062045091085308083188950704500797090491164647969353944050696191 +118305855347934305358536379357165472350660178373988900770159391774566491848801 +2008713282085666284652556551621962437401356361830493232520690122524894627206383197505895885671920146557265344301589773021846167435240002500658026512383 +323133594322353610393135271506551759249338578228327732110434346721529507354177413565941533352573023280770193553578703771044066939448141422832699655754215 +8866309339762256938205367118241359468285084241706741644373897192876383324845891938408677922953893394868024823096760328985859074426231649039808204582908518 +10592335116562605574859104705966049302824382333355134511227046941609708791279611163990078774097256277263081299114817404233848814642481057406588005371609087 +7409638199867804511590556491020804147437821443902201231464956650918710757587485835871076220513184441280932875327658339055507870288640330135470374231086564968802510793220658631244921907134557333508582119960035628956742572301380943132749810700571732870307187030378399921152414041403031737491047579647999 +0 +0 +0 +0 +361 +1098223571363824020337471782913 +73118673265328369333869451006373159426 +12612570963041677221068251937087603519725683816332068400361871614991377891329 +44757643964492500248872741260097920363273353321461345189639693578247602176001 +3942245179751587580113754740041160627070588205547869974769586858647333898741 +2612294559420208791815554010100531022826670009294237097218906452805851976960451833971257091500484048552506300644536870798907627346813539746460119072769 +4886652767199484464651425905879582096234981128410546139257549524800652233964932550117395659883947428238070691107034177061699574595056075593731862734910922 +476948687153533538165001293464509838331769398407122530531483520520031422134660870238181672367938291384232556352408026637315514098467464396275313797141550 +4019828793218805646023303231154957746362032987800527539184202417766187717897646394634196457153911354739604912893653289014782783880263859608454097188945921 +4075360670358372722795335962773428342675661975784760871564112696474315403655585860035546105060954687834105799318439691150952278271480480434794674741133762365172004076850361918268011359368504306942773658004160938910939812513459072944161883845284706441576028699349927725653931250854074869857900046581761 +0 diff --git a/evm/src/cpu/kernel/tests/blake2_f.rs b/evm/src/cpu/kernel/tests/blake2_f.rs new file mode 100644 index 00000000..1b465bed --- /dev/null +++ b/evm/src/cpu/kernel/tests/blake2_f.rs @@ -0,0 +1,132 @@ +use anyhow::Result; + +use crate::cpu::kernel::interpreter::{ + run_interpreter_with_memory, InterpreterMemoryInitialization, +}; +use crate::memory::segments::Segment::KernelGeneral; + +fn reverse_bytes_u64(input: u64) -> u64 { + let mut result = 0; + for i in 0..8 { + result |= ((input >> (i * 8)) & 0xff) << ((7 - i) * 8); + } + result +} + +fn convert_input(input: &str) -> Result<(u32, [u64; 8], [u64; 16], u64, u64, bool)> { + let rounds = u32::from_str_radix(&input[..8], 16).unwrap(); + + let mut h = [0u64; 8]; + for i in 0..8 { + h[i] = reverse_bytes_u64( + u64::from_str_radix(&input[8 + i * 16..8 + (i + 1) * 16], 16).unwrap(), + ); + } + + let mut m = [0u64; 16]; + for i in 0..16 { + m[i] = reverse_bytes_u64( + u64::from_str_radix(&input[136 + i * 16..136 + (i + 1) * 16], 16).unwrap(), + ); + } + + let t_0 = reverse_bytes_u64(u64::from_str_radix(&input[392..408], 16).unwrap()); + let t_1 = reverse_bytes_u64(u64::from_str_radix(&input[408..424], 16).unwrap()); + let flag = u8::from_str_radix(&input[424..426], 16).unwrap() != 0; + + Ok((rounds, h, m, t_0, t_1, flag)) +} + +fn convert_output(output: [u64; 8]) -> String { + output + .iter() + .map(|&x| format!("{:016x}", reverse_bytes_u64(x))) + .collect::>() + .join("") +} + +fn run_blake2_f( + rounds: u32, + h: [u64; 8], + m: [u64; 16], + t_0: u64, + t_1: u64, + flag: bool, +) -> Result<[u64; 8]> { + let mut stack = vec![]; + stack.push(rounds.into()); + stack.append(&mut h.iter().map(|&x| x.into()).collect()); + stack.append(&mut m.iter().map(|&x| x.into()).collect()); + stack.push(t_0.into()); + stack.push(t_1.into()); + stack.push(u8::from(flag).into()); + stack.push(0xDEADBEEFu32.into()); + + let interpreter_setup = InterpreterMemoryInitialization { + label: "blake2_f".to_string(), + stack, + segment: KernelGeneral, + memory: vec![], + }; + + let result = run_interpreter_with_memory(interpreter_setup).unwrap(); + let mut hash = result.stack().to_vec(); + hash.reverse(); + + Ok(hash + .iter() + .map(|&x| x.as_u64()) + .collect::>() + .try_into() + .unwrap()) +} + +// Test data from EIP-152. + +fn test_blake2_f_eip(input: &str, output: &str) -> Result<()> { + let (rounds, h, m, t_0, t_1, flag) = convert_input(input).unwrap(); + let result = run_blake2_f(rounds, h, m, t_0, t_1, flag).unwrap(); + assert_eq!(convert_output(result), output); + Ok(()) +} + +#[test] +fn test_blake2_f_4() -> Result<()> { + test_blake2_f_eip( + "0000000048c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", + "08c9bcf367e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d282e6ad7f520e511f6c3e2b8c68059b9442be0454267ce079217e1319cde05b", + ) +} + +#[test] +fn test_blake2_f_5() -> Result<()> { + test_blake2_f_eip( + "0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", + "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923", + ) +} + +#[test] +fn test_blake2_f_6() -> Result<()> { + test_blake2_f_eip( + "0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000", + "75ab69d3190a562c51aef8d88f1c2775876944407270c42c9844252c26d2875298743e7f6d5ea2f2d3e8d226039cd31b4e426ac4f2d3d666a610c2116fde4735", + ) +} + +#[test] +fn test_blake2_f_7() -> Result<()> { + test_blake2_f_eip( + "0000000148c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", + "b63a380cb2897d521994a85234ee2c181b5f844d2c624c002677e9703449d2fba551b3a8333bcdf5f2f7e08993d53923de3d64fcc68c034e717b9293fed7a421", + ) +} + +#[ignore] +#[test] +fn test_blake2_f_8() -> Result<()> { + test_blake2_f_eip( + "ffffffff48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", + "fc59093aafa9ab43daae0e914c57635c5402d8e3d2130eb9b3cc181de7f0ecf9b22bf99a7815ce16419e200e01846e6b5df8cc7703041bbceb571de6631d2615", + ) +} diff --git a/evm/src/cpu/kernel/tests/bn254.rs b/evm/src/cpu/kernel/tests/bn254.rs index 4bd336b9..d9a798b7 100644 --- a/evm/src/cpu/kernel/tests/bn254.rs +++ b/evm/src/cpu/kernel/tests/bn254.rs @@ -2,17 +2,26 @@ use anyhow::Result; use ethereum_types::U256; use rand::Rng; -use crate::bn254_pairing::{ - gen_fp12_sparse, invariant_exponent, miller_loop, tate, Curve, TwistedCurve, -}; use crate::cpu::kernel::interpreter::{ run_interpreter_with_memory, Interpreter, InterpreterMemoryInitialization, }; +use crate::curve_pairings::{ + bn_final_exponent, bn_miller_loop, gen_bn_fp12_sparse, Curve, CyclicGroup, +}; use crate::extension_tower::{FieldExt, Fp12, Fp2, Fp6, Stack, BN254}; use crate::memory::segments::Segment::BnPairing; -fn run_bn_mul_fp6(f: Fp6, g: Fp6, label: &str) -> Fp6 { - let mut stack = f.to_stack().to_vec(); +fn extract_stack(interpreter: Interpreter<'static>) -> Vec { + interpreter + .stack() + .iter() + .rev() + .cloned() + .collect::>() +} + +fn run_bn_mul_fp6(f: Fp6, g: Fp6, label: &str) -> Vec { + let mut stack = f.to_stack(); if label == "mul_fp254_6" { stack.extend(g.to_stack().to_vec()); } @@ -43,10 +52,10 @@ fn test_bn_mul_fp6() -> Result<()> { Ok(()) } -fn run_bn_mul_fp12(f: Fp12, g: Fp12, label: &str) -> Fp12 { - let in0: usize = 200; - let in1: usize = 212; - let out: usize = 224; +fn run_bn_mul_fp12(f: Fp12, g: Fp12, label: &str) -> Vec { + let in0: usize = 100; + let in1: usize = 112; + let out: usize = 124; let mut stack = vec![ U256::from(in0), @@ -73,7 +82,7 @@ fn test_bn_mul_fp12() -> Result<()> { let mut rng = rand::thread_rng(); let f: Fp12 = rng.gen::>(); let g: Fp12 = rng.gen::>(); - let h: Fp12 = gen_fp12_sparse(&mut rng); + let h: Fp12 = gen_bn_fp12_sparse(&mut rng); let output_normal = run_bn_mul_fp12(f, g, "mul_fp254_12"); let output_sparse = run_bn_mul_fp12(f, h, "mul_fp254_12_sparse"); @@ -109,8 +118,8 @@ fn test_bn_frob_fp6() -> Result<()> { Ok(()) } -fn run_bn_frob_fp12(n: usize, f: Fp12) -> Fp12 { - let ptr: usize = 200; +fn run_bn_frob_fp12(f: Fp12, n: usize) -> Vec { + let ptr: usize = 100; let setup = InterpreterMemoryInitialization { label: format!("test_frob_fp254_12_{}", n), stack: vec![U256::from(ptr)], @@ -126,8 +135,9 @@ fn run_bn_frob_fp12(n: usize, f: Fp12) -> Fp12 { fn test_frob_fp12() -> Result<()> { let mut rng = rand::thread_rng(); let f: Fp12 = rng.gen::>(); + for n in [1, 2, 3, 6] { - let output = run_bn_frob_fp12(n, f); + let output = run_bn_frob_fp12(f, n); assert_eq!(output, f.frob(n)); } Ok(()) @@ -135,8 +145,8 @@ fn test_frob_fp12() -> Result<()> { #[test] fn test_bn_inv_fp12() -> Result<()> { - let ptr: usize = 200; - let inv: usize = 212; + let ptr: usize = 100; + let inv: usize = 112; let mut rng = rand::thread_rng(); let f: Fp12 = rng.gen::>(); @@ -156,103 +166,54 @@ fn test_bn_inv_fp12() -> Result<()> { } #[test] -fn test_bn_final_exponentiation() -> Result<()> { - let ptr: usize = 200; +fn test_bn_final_exponent() -> Result<()> { + let ptr: usize = 100; + let mut rng = rand::thread_rng(); let f: Fp12 = rng.gen::>(); let setup = InterpreterMemoryInitialization { - label: "bn254_invariant_exponent".to_string(), - stack: vec![U256::from(ptr), U256::from(0xdeadbeefu32)], + label: "bn254_final_exponent".to_string(), + stack: vec![ + U256::zero(), + U256::zero(), + U256::from(ptr), + U256::from(0xdeadbeefu32), + ], segment: BnPairing, memory: vec![(ptr, f.to_stack().to_vec())], }; let interpreter: Interpreter = run_interpreter_with_memory(setup).unwrap(); let output: Vec = interpreter.extract_kernel_memory(BnPairing, ptr..ptr + 12); - let expected: Vec = invariant_exponent(f).to_stack().to_vec(); + let expected: Vec = bn_final_exponent(f).to_stack(); assert_eq!(output, expected); Ok(()) } -// The curve is cyclic with generator (1, 2) -pub const CURVE_GENERATOR: Curve = { - Curve { - x: BN254 { val: U256::one() }, - y: BN254 { - val: U256([2, 0, 0, 0]), - }, - } -}; - -// The twisted curve is cyclic with generator (x, y) as follows -pub const TWISTED_GENERATOR: TwistedCurve = { - TwistedCurve { - x: Fp2 { - re: BN254 { - val: U256([ - 0x46debd5cd992f6ed, - 0x674322d4f75edadd, - 0x426a00665e5c4479, - 0x1800deef121f1e76, - ]), - }, - im: BN254 { - val: U256([ - 0x97e485b7aef312c2, - 0xf1aa493335a9e712, - 0x7260bfb731fb5d25, - 0x198e9393920d483a, - ]), - }, - }, - y: Fp2 { - re: BN254 { - val: U256([ - 0x4ce6cc0166fa7daa, - 0xe3d1e7690c43d37b, - 0x4aab71808dcb408f, - 0x12c85ea5db8c6deb, - ]), - }, - im: BN254 { - val: U256([ - 0x55acdadcd122975b, - 0xbc4b313370b38ef3, - 0xec9e99ad690c3395, - 0x090689d0585ff075, - ]), - }, - }, - } -}; - #[test] -fn test_bn_miller_loop() -> Result<()> { - let ptr: usize = 200; - let out: usize = 206; - let inputs: Vec = vec![ - CURVE_GENERATOR.x.val, - CURVE_GENERATOR.y.val, - TWISTED_GENERATOR.x.re.val, - TWISTED_GENERATOR.x.im.val, - TWISTED_GENERATOR.y.re.val, - TWISTED_GENERATOR.y.im.val, - ]; +fn test_bn_miller() -> Result<()> { + let ptr: usize = 100; + let out: usize = 106; + + let mut rng = rand::thread_rng(); + let p: Curve = rng.gen::>(); + let q: Curve> = rng.gen::>>(); + + let mut input = p.to_stack(); + input.extend(q.to_stack()); let setup = InterpreterMemoryInitialization { label: "bn254_miller".to_string(), stack: vec![U256::from(ptr), U256::from(out), U256::from(0xdeadbeefu32)], segment: BnPairing, - memory: vec![(ptr, inputs)], + memory: vec![(ptr, input)], }; let interpreter = run_interpreter_with_memory(setup).unwrap(); let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); - let expected = miller_loop(CURVE_GENERATOR, TWISTED_GENERATOR) - .to_stack() - .to_vec(); + let expected = bn_miller_loop(p, q).to_stack(); assert_eq!(output, expected); @@ -260,29 +221,41 @@ fn test_bn_miller_loop() -> Result<()> { } #[test] -fn test_bn_tate_pairing() -> Result<()> { - let ptr: usize = 200; - let out: usize = 206; - let inputs: Vec = vec![ - CURVE_GENERATOR.x.val, - CURVE_GENERATOR.y.val, - TWISTED_GENERATOR.x.re.val, - TWISTED_GENERATOR.x.im.val, - TWISTED_GENERATOR.y.re.val, - TWISTED_GENERATOR.y.im.val, - ]; +fn test_bn_pairing() -> Result<()> { + let out: usize = 100; + let ptr: usize = 112; + + let mut rng = rand::thread_rng(); + let k: usize = rng.gen_range(1..10); + let mut acc: i32 = 0; + let mut input: Vec = vec![]; + for _ in 1..k { + let m: i32 = rng.gen_range(-8..8); + let n: i32 = rng.gen_range(-8..8); + acc -= m * n; + + let p: Curve = Curve::::int(m); + let q: Curve> = Curve::>::int(n); + input.extend(p.to_stack()); + input.extend(q.to_stack()); + } + let p: Curve = Curve::::int(acc); + let q: Curve> = Curve::>::GENERATOR; + input.extend(p.to_stack()); + input.extend(q.to_stack()); let setup = InterpreterMemoryInitialization { - label: "bn254_tate".to_string(), - stack: vec![U256::from(ptr), U256::from(out), U256::from(0xdeadbeefu32)], + label: "bn254_pairing".to_string(), + stack: vec![ + U256::from(k), + U256::from(ptr), + U256::from(out), + U256::from(0xdeadbeefu32), + ], segment: BnPairing, - memory: vec![(ptr, inputs)], + memory: vec![(ptr, input)], }; let interpreter = run_interpreter_with_memory(setup).unwrap(); - let output: Vec = interpreter.extract_kernel_memory(BnPairing, out..out + 12); - let expected = tate(CURVE_GENERATOR, TWISTED_GENERATOR).to_stack().to_vec(); - - assert_eq!(output, expected); - + assert_eq!(interpreter.stack()[0], U256::one()); Ok(()) } diff --git a/evm/src/cpu/kernel/tests/core/access_lists.rs b/evm/src/cpu/kernel/tests/core/access_lists.rs index 2b647811..c62d4865 100644 --- a/evm/src/cpu/kernel/tests/core/access_lists.rs +++ b/evm/src/cpu/kernel/tests/core/access_lists.rs @@ -99,12 +99,12 @@ fn test_insert_accessed_storage_keys() -> Result<()> { let mut rng = thread_rng(); let n = rng.gen_range(1..10); let storage_keys = (0..n) - .map(|_| (rng.gen::
(), U256(rng.gen()))) + .map(|_| (rng.gen::
(), U256(rng.gen()), U256(rng.gen()))) .collect::>() .into_iter() - .collect::>(); + .collect::>(); let storage_key_in_list = storage_keys[rng.gen_range(0..n)]; - let storage_key_not_in_list = (rng.gen::
(), U256(rng.gen())); + let storage_key_not_in_list = (rng.gen::
(), U256(rng.gen()), U256(rng.gen())); assert!( !storage_keys.contains(&storage_key_not_in_list), "Cosmic luck or bad RNG?" @@ -113,6 +113,7 @@ fn test_insert_accessed_storage_keys() -> Result<()> { // Test for storage key already in list. let initial_stack = vec![ retaddr, + storage_key_in_list.2, storage_key_in_list.1, U256::from(storage_key_in_list.0 .0.as_slice()), ]; @@ -122,30 +123,35 @@ fn test_insert_accessed_storage_keys() -> Result<()> { interpreter .generation_state .memory - .set(MemoryAddress::new(0, AccessedStorageKeys, 2 * i), addr); + .set(MemoryAddress::new(0, AccessedStorageKeys, 3 * i), addr); interpreter.generation_state.memory.set( - MemoryAddress::new(0, AccessedStorageKeys, 2 * i + 1), + MemoryAddress::new(0, AccessedStorageKeys, 3 * i + 1), storage_keys[i].1, ); + interpreter.generation_state.memory.set( + MemoryAddress::new(0, AccessedStorageKeys, 3 * i + 2), + storage_keys[i].2, + ); } interpreter.generation_state.memory.set( MemoryAddress::new(0, GlobalMetadata, AccessedStorageKeysLen as usize), - U256::from(2 * n), + U256::from(3 * n), ); interpreter.run()?; - assert_eq!(interpreter.stack(), &[U256::zero()]); + assert_eq!(interpreter.stack(), &[storage_key_in_list.2, U256::zero()]); assert_eq!( interpreter.generation_state.memory.get(MemoryAddress::new( 0, GlobalMetadata, AccessedStorageKeysLen as usize )), - U256::from(2 * n) + U256::from(3 * n) ); // Test for storage key not in list. let initial_stack = vec![ retaddr, + storage_key_not_in_list.2, storage_key_not_in_list.1, U256::from(storage_key_not_in_list.0 .0.as_slice()), ]; @@ -155,41 +161,56 @@ fn test_insert_accessed_storage_keys() -> Result<()> { interpreter .generation_state .memory - .set(MemoryAddress::new(0, AccessedStorageKeys, 2 * i), addr); + .set(MemoryAddress::new(0, AccessedStorageKeys, 3 * i), addr); interpreter.generation_state.memory.set( - MemoryAddress::new(0, AccessedStorageKeys, 2 * i + 1), + MemoryAddress::new(0, AccessedStorageKeys, 3 * i + 1), storage_keys[i].1, ); + interpreter.generation_state.memory.set( + MemoryAddress::new(0, AccessedStorageKeys, 3 * i + 2), + storage_keys[i].2, + ); } interpreter.generation_state.memory.set( MemoryAddress::new(0, GlobalMetadata, AccessedStorageKeysLen as usize), - U256::from(2 * n), + U256::from(3 * n), ); interpreter.run()?; - assert_eq!(interpreter.stack(), &[U256::one()]); + assert_eq!( + interpreter.stack(), + &[storage_key_not_in_list.2, U256::one()] + ); assert_eq!( interpreter.generation_state.memory.get(MemoryAddress::new( 0, GlobalMetadata, AccessedStorageKeysLen as usize )), - U256::from(2 * (n + 1)) + U256::from(3 * (n + 1)) ); assert_eq!( interpreter .generation_state .memory - .get(MemoryAddress::new(0, AccessedStorageKeys, 2 * n,)), + .get(MemoryAddress::new(0, AccessedStorageKeys, 3 * n,)), U256::from(storage_key_not_in_list.0 .0.as_slice()) ); assert_eq!( interpreter.generation_state.memory.get(MemoryAddress::new( 0, AccessedStorageKeys, - 2 * n + 1, + 3 * n + 1, )), storage_key_not_in_list.1 ); + assert_eq!( + interpreter.generation_state.memory.get(MemoryAddress::new( + 0, + AccessedStorageKeys, + 3 * n + 2, + )), + storage_key_not_in_list.2 + ); Ok(()) } diff --git a/evm/src/cpu/kernel/tests/hash.rs b/evm/src/cpu/kernel/tests/hash.rs index bc73ecd5..9b96de91 100644 --- a/evm/src/cpu/kernel/tests/hash.rs +++ b/evm/src/cpu/kernel/tests/hash.rs @@ -1,6 +1,6 @@ use anyhow::Result; -use blake2::Blake2b512; -use ethereum_types::{U256, U512}; +// use blake2::Blake2b512; +use ethereum_types::U256; use rand::{thread_rng, Rng}; use ripemd::{Digest, Ripemd160}; use sha2::Sha256; @@ -10,13 +10,6 @@ use crate::cpu::kernel::interpreter::{ }; use crate::memory::segments::Segment::KernelGeneral; -/// Standard Blake2b implementation. -fn blake2b(input: Vec) -> U512 { - let mut hasher = Blake2b512::new(); - hasher.update(input); - U512::from(&hasher.finalize()[..]) -} - /// Standard RipeMD implementation. fn ripemd(input: Vec) -> U256 { let mut hasher = Ripemd160::new(); @@ -58,10 +51,6 @@ fn make_interpreter_setup( } } -fn combine_u256s(hi: U256, lo: U256) -> U512 { - U512::from(lo) + (U512::from(hi) << 256) -} - fn prepare_test( hash_fn_label: &str, hash_input_virt: (usize, usize), @@ -99,28 +88,6 @@ fn test_hash_256( Ok(()) } -fn test_hash_512( - hash_fn_label: &str, - hash_input_virt: (usize, usize), - standard_implementation: &dyn Fn(Vec) -> U512, -) -> Result<()> { - let (expected, result_stack) = - prepare_test(hash_fn_label, hash_input_virt, standard_implementation).unwrap(); - - // Extract the final output. - let actual = combine_u256s(result_stack[0], result_stack[1]); - - // Check that the result is correct. - assert_eq!(expected, actual); - - Ok(()) -} - -#[test] -fn test_blake2b() -> Result<()> { - test_hash_512("blake2b", (0, 2), &blake2b) -} - #[test] fn test_ripemd() -> Result<()> { test_hash_256("ripemd", (200, 200), &ripemd) @@ -130,3 +97,40 @@ fn test_ripemd() -> Result<()> { fn test_sha2() -> Result<()> { test_hash_256("sha2", (0, 1), &sha2) } + +// Since the Blake precompile requires only the blake2_f compression function instead of the full blake2b hash, +// the full hash function is not included in the kernel. To include it, blake2/compression.asm and blake2/main.asm +// must be added to the kernel. + +// /// Standard Blake2b implementation. +// fn blake2b(input: Vec) -> U512 { +// let mut hasher = Blake2b512::new(); +// hasher.update(input); +// U512::from(&hasher.finalize()[..]) +// } + +// fn combine_u256s(hi: U256, lo: U256) -> U512 { +// U512::from(lo) + (U512::from(hi) << 256) +// } + +// fn test_hash_512( +// hash_fn_label: &str, +// hash_input_virt: (usize, usize), +// standard_implementation: &dyn Fn(Vec) -> U512, +// ) -> Result<()> { +// let (expected, result_stack) = +// prepare_test(hash_fn_label, hash_input_virt, standard_implementation).unwrap(); + +// // Extract the final output. +// let actual = combine_u256s(result_stack[0], result_stack[1]); + +// // Check that the result is correct. +// assert_eq!(expected, actual); + +// Ok(()) +// } + +// #[test] +// fn test_blake2b() -> Result<()> { +// test_hash_512("blake2b", (0, 2), &blake2b) +// } diff --git a/evm/src/cpu/kernel/tests/mod.rs b/evm/src/cpu/kernel/tests/mod.rs index 83ded791..8f691161 100644 --- a/evm/src/cpu/kernel/tests/mod.rs +++ b/evm/src/cpu/kernel/tests/mod.rs @@ -1,6 +1,7 @@ mod account_code; mod balance; mod bignum; +mod blake2_f; mod bls381; mod bn254; mod core; diff --git a/evm/src/bn254_pairing.rs b/evm/src/curve_pairings.rs similarity index 63% rename from evm/src/bn254_pairing.rs rename to evm/src/curve_pairings.rs index 7277c2a8..708e7fb2 100644 --- a/evm/src/bn254_pairing.rs +++ b/evm/src/curve_pairings.rs @@ -1,25 +1,75 @@ -use std::ops::Add; +use std::ops::{Add, Mul, Neg}; +use ethereum_types::U256; +use rand::distributions::Standard; +use rand::prelude::Distribution; use rand::Rng; -use crate::extension_tower::{FieldExt, Fp12, Fp2, Fp6, BN254}; +use crate::extension_tower::{FieldExt, Fp12, Fp2, Fp6, Stack, BN254}; -// The curve consists of pairs (x, y): (BN254, BN254) | y^2 = x^3 + 2 #[derive(Debug, Copy, Clone, PartialEq)] -pub struct Curve { - pub x: BN254, - pub y: BN254, +pub struct Curve +where + T: FieldExt, +{ + pub x: T, + pub y: T, +} + +impl Curve { + pub fn unit() -> Self { + Curve { + x: T::ZERO, + y: T::ZERO, + } + } +} + +impl Curve { + pub fn on_stack(self) -> Vec { + let mut stack = self.x.on_stack(); + stack.extend(self.y.on_stack()); + stack + } +} + +impl Curve +where + T: FieldExt, + Curve: CyclicGroup, +{ + pub fn int(z: i32) -> Self { + Curve::::GENERATOR * z + } +} + +impl Distribution> for Standard +where + T: FieldExt, + Curve: CyclicGroup, +{ + fn sample(&self, rng: &mut R) -> Curve { + Curve::::GENERATOR * rng.gen::() + } } /// Standard addition formula for elliptic curves, restricted to the cases -/// where neither inputs nor output would ever be the identity O. source: /// https://en.wikipedia.org/wiki/Elliptic_curve#Algebraic_interpretation -impl Add for Curve { +impl Add for Curve { type Output = Self; fn add(self, other: Self) -> Self { + if self == Curve::::unit() { + return other; + } + if other == Curve::::unit() { + return self; + } + if self == -other { + return Curve::::unit(); + } let m = if self == other { - BN254::new(3) * self.x * self.x / (BN254::new(2) * self.y) + T::new(3) * self.x * self.x / (T::new(2) * self.y) } else { (other.y - self.y) / (other.x - self.x) }; @@ -31,33 +81,130 @@ impl Add for Curve { } } -// The twisted curve consists of pairs (x, y): (Fp2, Fp2) | y^2 = x^3 + 3/(9 + i) -#[derive(Debug, Copy, Clone, PartialEq)] -pub struct TwistedCurve { - pub x: Fp2, - pub y: Fp2, +impl Neg for Curve { + type Output = Curve; + + fn neg(self) -> Self { + Curve { + x: self.x, + y: -self.y, + } + } +} + +pub trait CyclicGroup { + const GENERATOR: Self; +} + +/// The BN curve consists of pairs +/// (x, y): (BN254, BN254) | y^2 = x^3 + 2 +// with generator given by (1, 2) +impl CyclicGroup for Curve { + const GENERATOR: Curve = Curve { + x: BN254 { val: U256::one() }, + y: BN254 { + val: U256([2, 0, 0, 0]), + }, + }; +} + +impl Mul for Curve +where + T: FieldExt, + Curve: CyclicGroup, +{ + type Output = Curve; + + fn mul(self, other: i32) -> Self { + if other == 0 { + return Curve::::unit(); + } + if self == Curve::::unit() { + return Curve::::unit(); + } + + let mut x: Curve = self; + if other.is_negative() { + x = -x; + } + let mut result = Curve::::unit(); + + let mut exp = other.unsigned_abs() as usize; + while exp > 0 { + if exp % 2 == 1 { + result = result + x; + } + exp >>= 1; + x = x + x; + } + result + } +} + +/// The twisted curve consists of pairs +/// (x, y): (Fp2, Fp2) | y^2 = x^3 + 3/(9 + i) +/// with generator given as follows +impl CyclicGroup for Curve> { + const GENERATOR: Curve> = Curve { + x: Fp2 { + re: BN254 { + val: U256([ + 0x46debd5cd992f6ed, + 0x674322d4f75edadd, + 0x426a00665e5c4479, + 0x1800deef121f1e76, + ]), + }, + im: BN254 { + val: U256([ + 0x97e485b7aef312c2, + 0xf1aa493335a9e712, + 0x7260bfb731fb5d25, + 0x198e9393920d483a, + ]), + }, + }, + y: Fp2 { + re: BN254 { + val: U256([ + 0x4ce6cc0166fa7daa, + 0xe3d1e7690c43d37b, + 0x4aab71808dcb408f, + 0x12c85ea5db8c6deb, + ]), + }, + im: BN254 { + val: U256([ + 0x55acdadcd122975b, + 0xbc4b313370b38ef3, + 0xec9e99ad690c3395, + 0x090689d0585ff075, + ]), + }, + }, + }; } // The tate pairing takes a point each from the curve and its twist and outputs an Fp12 element -pub fn tate(p: Curve, q: TwistedCurve) -> Fp12 { - let miller_output = miller_loop(p, q); - invariant_exponent(miller_output) +pub fn bn_tate(p: Curve, q: Curve>) -> Fp12 { + let miller_output = bn_miller_loop(p, q); + bn_final_exponent(miller_output) } /// Standard code for miller loop, can be found on page 99 at this url: /// https://static1.squarespace.com/static/5fdbb09f31d71c1227082339/t/5ff394720493bd28278889c6/1609798774687/PairingsForBeginners.pdf#page=107 -/// where EXP is a hardcoding of the array of Booleans that the loop traverses -pub fn miller_loop(p: Curve, q: TwistedCurve) -> Fp12 { +/// where BN_EXP is a hardcoding of the array of Booleans that the loop traverses +pub fn bn_miller_loop(p: Curve, q: Curve>) -> Fp12 { let mut r = p; let mut acc: Fp12 = Fp12::::UNIT; let mut line: Fp12; - for i in EXP { - line = tangent(r, q); + for i in BN_EXP { + line = bn_tangent(r, q); r = r + r; acc = line * acc * acc; if i { - line = cord(p, r, q); + line = bn_cord(p, r, q); r = r + p; acc = line * acc; } @@ -66,22 +213,22 @@ pub fn miller_loop(p: Curve, q: TwistedCurve) -> Fp12 { } /// The sloped line function for doubling a point -pub fn tangent(p: Curve, q: TwistedCurve) -> Fp12 { +pub fn bn_tangent(p: Curve, q: Curve>) -> Fp12 { let cx = -BN254::new(3) * p.x * p.x; let cy = BN254::new(2) * p.y; - sparse_embed(p.y * p.y - BN254::new(9), q.x * cx, q.y * cy) + bn_sparse_embed(p.y * p.y - BN254::new(9), q.x * cx, q.y * cy) } /// The sloped line function for adding two points -pub fn cord(p1: Curve, p2: Curve, q: TwistedCurve) -> Fp12 { +pub fn bn_cord(p1: Curve, p2: Curve, q: Curve>) -> Fp12 { let cx = p2.y - p1.y; let cy = p1.x - p2.x; - sparse_embed(p1.y * p2.x - p2.y * p1.x, q.x * cx, q.y * cy) + bn_sparse_embed(p1.y * p2.x - p2.y * p1.x, q.x * cx, q.y * cy) } /// The tangent and cord functions output sparse Fp12 elements. /// This map embeds the nonzero coefficients into an Fp12. -pub fn sparse_embed(g000: BN254, g01: Fp2, g11: Fp2) -> Fp12 { +pub fn bn_sparse_embed(g000: BN254, g01: Fp2, g11: Fp2) -> Fp12 { let g0 = Fp6 { t0: Fp2 { re: g000, @@ -100,8 +247,8 @@ pub fn sparse_embed(g000: BN254, g01: Fp2, g11: Fp2) -> Fp12(rng: &mut R) -> Fp12 { - sparse_embed( +pub fn gen_bn_fp12_sparse(rng: &mut R) -> Fp12 { + bn_sparse_embed( rng.gen::(), rng.gen::>(), rng.gen::>(), @@ -120,10 +267,10 @@ pub fn gen_fp12_sparse(rng: &mut R) -> Fp12 { /// (p^4 - p^2 + 1)/N = p^3 + (a2)p^2 - (a1)p - a0 /// where 0 < a0, a1, a2 < p. Then the final power is given by /// y = y_3 * (y^a2)_2 * (y^-a1)_1 * (y^-a0) -pub fn invariant_exponent(f: Fp12) -> Fp12 { +pub fn bn_final_exponent(f: Fp12) -> Fp12 { let mut y = f.frob(6) / f; y = y.frob(2) * y; - let (y_a2, y_a1, y_a0) = get_custom_powers(y); + let (y_a2, y_a1, y_a0) = get_bn_custom_powers(y); y.frob(3) * y_a2.frob(2) * y_a1.frob(1) * y_a0 } @@ -135,10 +282,10 @@ pub fn invariant_exponent(f: Fp12) -> Fp12 { /// y^a2, y^a1 = y^a4 * y^a2 * y^a2 * y^(-a0), y^(-a0) /// /// Representing a4, a2, a0 in *little endian* binary, define -/// EXPS4 = [(a4[i], a2[i], a0[i]) for i in 0..len(a4)] -/// EXPS2 = [ (a2[i], a0[i]) for i in len(a4)..len(a2)] -/// EXPS0 = [ a0[i] for i in len(a2)..len(a0)] -fn get_custom_powers(f: Fp12) -> (Fp12, Fp12, Fp12) { +/// BN_EXPS4 = [(a4[i], a2[i], a0[i]) for i in 0..len(a4)] +/// BN_EXPS2 = [ (a2[i], a0[i]) for i in len(a4)..len(a2)] +/// BN_EXPS0 = [ a0[i] for i in len(a2)..len(a0)] +fn get_bn_custom_powers(f: Fp12) -> (Fp12, Fp12, Fp12) { let mut sq: Fp12 = f; let mut y0: Fp12 = Fp12::::UNIT; let mut y2: Fp12 = Fp12::::UNIT; @@ -147,7 +294,7 @@ fn get_custom_powers(f: Fp12) -> (Fp12, Fp12, Fp12) // proceed via standard squaring algorithm for exponentiation // must keep multiplying all three values: a4, a2, a0 - for (a, b, c) in EXPS4 { + for (a, b, c) in BN_EXPS4 { if a { y4 = y4 * sq; } @@ -163,7 +310,7 @@ fn get_custom_powers(f: Fp12) -> (Fp12, Fp12, Fp12) y4 = y4 * sq; // must keep multiplying remaining two values: a2, a0 - for (a, b) in EXPS2 { + for (a, b) in BN_EXPS2 { if a { y2 = y2 * sq; } @@ -176,7 +323,7 @@ fn get_custom_powers(f: Fp12) -> (Fp12, Fp12, Fp12) y2 = y2 * sq; // must keep multiplying final remaining value: a0 - for a in EXPS0 { + for a in BN_EXPS0 { if a { y0 = y0 * sq; } @@ -192,7 +339,7 @@ fn get_custom_powers(f: Fp12) -> (Fp12, Fp12, Fp12) (y2, y4 * y2 * y2 * y0_inv, y0_inv) } -const EXP: [bool; 253] = [ +const BN_EXP: [bool; 253] = [ true, false, false, false, false, false, true, true, false, false, true, false, false, false, true, false, false, true, true, true, false, false, true, true, true, false, false, true, false, true, true, true, false, false, false, false, true, false, false, true, true, false, @@ -216,7 +363,7 @@ const EXP: [bool; 253] = [ // The folowing constants are defined above get_custom_powers -const EXPS4: [(bool, bool, bool); 64] = [ +const BN_EXPS4: [(bool, bool, bool); 64] = [ (true, true, false), (true, true, true), (true, true, true), @@ -283,7 +430,7 @@ const EXPS4: [(bool, bool, bool); 64] = [ (true, true, true), ]; -const EXPS2: [(bool, bool); 62] = [ +const BN_EXPS2: [(bool, bool); 62] = [ (true, false), (true, true), (false, false), @@ -348,7 +495,7 @@ const EXPS2: [(bool, bool); 62] = [ (true, true), ]; -const EXPS0: [bool; 65] = [ +const BN_EXPS0: [bool; 65] = [ false, false, true, false, false, true, true, false, true, false, true, true, true, false, true, false, false, false, true, false, false, true, false, true, false, true, true, false, false, false, false, false, true, false, true, false, true, true, true, false, false, true, diff --git a/evm/src/extension_tower.rs b/evm/src/extension_tower.rs index a54e4d16..f7c076e2 100644 --- a/evm/src/extension_tower.rs +++ b/evm/src/extension_tower.rs @@ -1,3 +1,4 @@ +use std::fmt::Debug; use std::ops::{Add, Div, Mul, Neg, Sub}; use ethereum_types::{U256, U512}; @@ -6,6 +7,8 @@ use rand::Rng; pub trait FieldExt: Copy + + std::fmt::Debug + + std::cmp::PartialEq + std::ops::Add + std::ops::Neg + std::ops::Sub @@ -14,6 +17,7 @@ pub trait FieldExt: { const ZERO: Self; const UNIT: Self; + fn new(val: usize) -> Self; fn inv(self) -> Self; } @@ -29,14 +33,6 @@ pub struct BN254 { pub val: U256, } -impl BN254 { - pub fn new(val: usize) -> BN254 { - BN254 { - val: U256::from(val), - } - } -} - impl Distribution for Standard { fn sample(&self, rng: &mut R) -> BN254 { let xs = rng.gen::<[u64; 4]>(); @@ -90,6 +86,11 @@ impl Mul for BN254 { impl FieldExt for BN254 { const ZERO: Self = BN254 { val: U256::zero() }; const UNIT: Self = BN254 { val: U256::one() }; + fn new(val: usize) -> BN254 { + BN254 { + val: U256::from(val), + } + } fn inv(self) -> BN254 { let exp = BN_BASE - 2; let mut current = self; @@ -130,12 +131,6 @@ pub struct BLS381 { } impl BLS381 { - pub fn new(val: usize) -> BLS381 { - BLS381 { - val: U512::from(val), - } - } - pub fn lo(self) -> U256 { U256(self.val.0[..4].try_into().unwrap()) } @@ -233,6 +228,11 @@ impl Mul for BLS381 { impl FieldExt for BLS381 { const ZERO: Self = BLS381 { val: U512::zero() }; const UNIT: Self = BLS381 { val: U512::one() }; + fn new(val: usize) -> BLS381 { + BLS381 { + val: U512::from(val), + } + } fn inv(self) -> BLS381 { let exp = BLS_BASE - 2; let mut current = self; @@ -364,6 +364,14 @@ impl FieldExt for Fp2 { re: T::UNIT, im: T::ZERO, }; + + fn new(val: usize) -> Fp2 { + Fp2 { + re: T::new(val), + im: T::ZERO, + } + } + /// The inverse of z is given by z'/||z||^2 since ||z||^2 = zz' fn inv(self) -> Fp2 { let norm_sq = self.norm_sq(); @@ -974,6 +982,14 @@ where t2: Fp2::::ZERO, }; + fn new(val: usize) -> Fp6 { + Fp6 { + t0: Fp2::::new(val), + t1: Fp2::::ZERO, + t2: Fp2::::ZERO, + } + } + /// Let x_n = x^(p^n) and note that /// x_0 = x^(p^0) = x^1 = x /// (x_n)_m = (x^(p^n))^(p^m) = x^(p^n * p^m) = x^(p^(n+m)) = x_{n+m} @@ -1039,6 +1055,13 @@ where z1: Fp6::::ZERO, }; + fn new(val: usize) -> Fp12 { + Fp12 { + z0: Fp6::::new(val), + z1: Fp6::::ZERO, + } + } + /// By Galois Theory, given x: Fp12, the product /// phi = Prod_{i=0}^11 x_i /// lands in BN254, and hence the inverse of x is given by @@ -1220,6 +1243,12 @@ impl Stack for BN254 { } } +impl Stack for BN254 { + fn on_stack(self) -> Vec { + vec![self.val] + } +} + impl Stack for BLS381 { const SIZE: usize = 2; diff --git a/evm/src/fixed_recursive_verifier.rs b/evm/src/fixed_recursive_verifier.rs index 2dcd1824..2e6f01aa 100644 --- a/evm/src/fixed_recursive_verifier.rs +++ b/evm/src/fixed_recursive_verifier.rs @@ -1,3 +1,4 @@ +use core::mem::{self, MaybeUninit}; use std::collections::BTreeMap; use std::ops::Range; @@ -19,6 +20,9 @@ use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, Hasher}; use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget}; use plonky2::recursion::cyclic_recursion::check_cyclic_proof_verifier_data; use plonky2::recursion::dummy_circuit::cyclic_base_proof; +use plonky2::util::serialization::{ + Buffer, GateSerializer, IoResult, Read, WitnessGeneratorSerializer, Write, +}; use plonky2::util::timing::TimingTree; use plonky2_util::log2_ceil; @@ -47,6 +51,7 @@ const THRESHOLD_DEGREE_BITS: usize = 13; /// `degree_bits`, this contains a chain of recursive circuits for shrinking that STARK from /// `degree_bits` to a constant `THRESHOLD_DEGREE_BITS`. It also contains a special root circuit /// for combining each STARK's shrunk wrapper proof into a single proof. +#[derive(Eq, PartialEq, Debug)] pub struct AllRecursiveCircuits where F: RichField + Extendable, @@ -64,12 +69,13 @@ where /// Data for the EVM root circuit, which is used to combine each STARK's shrunk wrapper proof /// into a single proof. +#[derive(Eq, PartialEq, Debug)] pub struct RootCircuitData where F: RichField + Extendable, C: GenericConfig, { - circuit: CircuitData, + pub circuit: CircuitData, proof_with_pis: [ProofWithPublicInputsTarget; NUM_TABLES], /// For each table, various inner circuits may be used depending on the initial table size. /// This target holds the index of the circuit (within `final_circuits()`) that was used. @@ -79,37 +85,182 @@ where cyclic_vk: VerifierCircuitTarget, } +impl RootCircuitData +where + F: RichField + Extendable, + C: GenericConfig, +{ + pub fn to_buffer( + &self, + buffer: &mut Vec, + gate_serializer: &dyn GateSerializer, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult<()> { + buffer.write_circuit_data(&self.circuit, gate_serializer, generator_serializer)?; + for proof in &self.proof_with_pis { + buffer.write_target_proof_with_public_inputs(proof)?; + } + for index in self.index_verifier_data { + buffer.write_target(index)?; + } + buffer.write_target_verifier_circuit(&self.cyclic_vk)?; + Ok(()) + } + + pub fn from_buffer( + buffer: &mut Buffer, + gate_serializer: &dyn GateSerializer, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult { + let circuit = buffer.read_circuit_data(gate_serializer, generator_serializer)?; + let mut proof_with_pis = Vec::with_capacity(NUM_TABLES); + for _ in 0..NUM_TABLES { + proof_with_pis.push(buffer.read_target_proof_with_public_inputs()?); + } + let mut index_verifier_data = Vec::with_capacity(NUM_TABLES); + for _ in 0..NUM_TABLES { + index_verifier_data.push(buffer.read_target()?); + } + let cyclic_vk = buffer.read_target_verifier_circuit()?; + + Ok(Self { + circuit, + proof_with_pis: proof_with_pis.try_into().unwrap(), + index_verifier_data: index_verifier_data.try_into().unwrap(), + cyclic_vk, + }) + } +} + /// Data for the aggregation circuit, which is used to compress two proofs into one. Each inner /// proof can be either an EVM root proof or another aggregation proof. +#[derive(Eq, PartialEq, Debug)] pub struct AggregationCircuitData where F: RichField + Extendable, C: GenericConfig, { - circuit: CircuitData, + pub circuit: CircuitData, lhs: AggregationChildTarget, rhs: AggregationChildTarget, cyclic_vk: VerifierCircuitTarget, } +impl AggregationCircuitData +where + F: RichField + Extendable, + C: GenericConfig, +{ + pub fn to_buffer( + &self, + buffer: &mut Vec, + gate_serializer: &dyn GateSerializer, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult<()> { + buffer.write_circuit_data(&self.circuit, gate_serializer, generator_serializer)?; + buffer.write_target_verifier_circuit(&self.cyclic_vk)?; + self.lhs.to_buffer(buffer)?; + self.rhs.to_buffer(buffer)?; + Ok(()) + } + + pub fn from_buffer( + buffer: &mut Buffer, + gate_serializer: &dyn GateSerializer, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult { + let circuit = buffer.read_circuit_data(gate_serializer, generator_serializer)?; + let cyclic_vk = buffer.read_target_verifier_circuit()?; + let lhs = AggregationChildTarget::from_buffer(buffer)?; + let rhs = AggregationChildTarget::from_buffer(buffer)?; + Ok(Self { + circuit, + lhs, + rhs, + cyclic_vk, + }) + } +} + +#[derive(Eq, PartialEq, Debug)] pub struct AggregationChildTarget { is_agg: BoolTarget, agg_proof: ProofWithPublicInputsTarget, evm_proof: ProofWithPublicInputsTarget, } +impl AggregationChildTarget { + pub fn to_buffer(&self, buffer: &mut Vec) -> IoResult<()> { + buffer.write_target_bool(self.is_agg)?; + buffer.write_target_proof_with_public_inputs(&self.agg_proof)?; + buffer.write_target_proof_with_public_inputs(&self.evm_proof)?; + Ok(()) + } + + pub fn from_buffer(buffer: &mut Buffer) -> IoResult { + let is_agg = buffer.read_target_bool()?; + let agg_proof = buffer.read_target_proof_with_public_inputs()?; + let evm_proof = buffer.read_target_proof_with_public_inputs()?; + Ok(Self { + is_agg, + agg_proof, + evm_proof, + }) + } +} + +#[derive(Eq, PartialEq, Debug)] pub struct BlockCircuitData where F: RichField + Extendable, C: GenericConfig, { - circuit: CircuitData, + pub circuit: CircuitData, has_parent_block: BoolTarget, parent_block_proof: ProofWithPublicInputsTarget, agg_root_proof: ProofWithPublicInputsTarget, cyclic_vk: VerifierCircuitTarget, } +impl BlockCircuitData +where + F: RichField + Extendable, + C: GenericConfig, +{ + pub fn to_buffer( + &self, + buffer: &mut Vec, + gate_serializer: &dyn GateSerializer, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult<()> { + buffer.write_circuit_data(&self.circuit, gate_serializer, generator_serializer)?; + buffer.write_target_bool(self.has_parent_block)?; + buffer.write_target_proof_with_public_inputs(&self.parent_block_proof)?; + buffer.write_target_proof_with_public_inputs(&self.agg_root_proof)?; + buffer.write_target_verifier_circuit(&self.cyclic_vk)?; + Ok(()) + } + + pub fn from_buffer( + buffer: &mut Buffer, + gate_serializer: &dyn GateSerializer, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult { + let circuit = buffer.read_circuit_data(gate_serializer, generator_serializer)?; + let has_parent_block = buffer.read_target_bool()?; + let parent_block_proof = buffer.read_target_proof_with_public_inputs()?; + let agg_root_proof = buffer.read_target_proof_with_public_inputs()?; + let cyclic_vk = buffer.read_target_verifier_circuit()?; + Ok(Self { + circuit, + has_parent_block, + parent_block_proof, + agg_root_proof, + cyclic_vk, + }) + } +} + impl AllRecursiveCircuits where F: RichField + Extendable, @@ -124,44 +275,105 @@ where [(); C::HCO::WIDTH]:, [(); C::HCI::WIDTH]:, { + pub fn to_bytes( + &self, + gate_serializer: &dyn GateSerializer, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult> { + // TODO: would be better to initialize it dynamically based on the supported max degree. + let mut buffer = Vec::with_capacity(1 << 34); + self.root + .to_buffer(&mut buffer, gate_serializer, generator_serializer)?; + self.aggregation + .to_buffer(&mut buffer, gate_serializer, generator_serializer)?; + self.block + .to_buffer(&mut buffer, gate_serializer, generator_serializer)?; + for table in &self.by_table { + table.to_buffer(&mut buffer, gate_serializer, generator_serializer)?; + } + Ok(buffer) + } + + pub fn from_bytes( + bytes: &[u8], + gate_serializer: &dyn GateSerializer, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult { + let mut buffer = Buffer::new(bytes.to_vec()); + let root = + RootCircuitData::from_buffer(&mut buffer, gate_serializer, generator_serializer)?; + let aggregation = AggregationCircuitData::from_buffer( + &mut buffer, + gate_serializer, + generator_serializer, + )?; + let block = + BlockCircuitData::from_buffer(&mut buffer, gate_serializer, generator_serializer)?; + + // Tricky use of MaybeUninit to remove the need for implementing Debug + // for all underlying types, necessary to convert a by_table Vec to an array. + let by_table = { + let mut by_table: [MaybeUninit>; NUM_TABLES] = + unsafe { MaybeUninit::uninit().assume_init() }; + for table in &mut by_table[..] { + let value = RecursiveCircuitsForTable::from_buffer( + &mut buffer, + gate_serializer, + generator_serializer, + )?; + *table = MaybeUninit::new(value); + } + unsafe { + mem::transmute::<_, [RecursiveCircuitsForTable; NUM_TABLES]>(by_table) + } + }; + + Ok(Self { + root, + aggregation, + block, + by_table, + }) + } + /// Preprocess all recursive circuits used by the system. pub fn new( all_stark: &AllStark, - degree_bits_range: Range, + degree_bits_ranges: &[Range; NUM_TABLES], stark_config: &StarkConfig, ) -> Self { let cpu = RecursiveCircuitsForTable::new( Table::Cpu, &all_stark.cpu_stark, - degree_bits_range.clone(), + degree_bits_ranges[0].clone(), &all_stark.cross_table_lookups, stark_config, ); let keccak = RecursiveCircuitsForTable::new( Table::Keccak, &all_stark.keccak_stark, - degree_bits_range.clone(), + degree_bits_ranges[1].clone(), &all_stark.cross_table_lookups, stark_config, ); let keccak_sponge = RecursiveCircuitsForTable::new( Table::KeccakSponge, &all_stark.keccak_sponge_stark, - degree_bits_range.clone(), + degree_bits_ranges[2].clone(), &all_stark.cross_table_lookups, stark_config, ); let logic = RecursiveCircuitsForTable::new( Table::Logic, &all_stark.logic_stark, - degree_bits_range.clone(), + degree_bits_ranges[3].clone(), &all_stark.cross_table_lookups, stark_config, ); let memory = RecursiveCircuitsForTable::new( Table::Memory, &all_stark.memory_stark, - degree_bits_range, + degree_bits_ranges[4].clone(), &all_stark.cross_table_lookups, stark_config, ); @@ -484,7 +696,8 @@ where } } -struct RecursiveCircuitsForTable +#[derive(Eq, PartialEq, Debug)] +pub struct RecursiveCircuitsForTable where F: RichField + Extendable, C: GenericConfig, @@ -504,6 +717,39 @@ where [(); C::HCO::WIDTH]:, [(); C::HCI::WIDTH]:, { + pub fn to_buffer( + &self, + buffer: &mut Vec, + gate_serializer: &dyn GateSerializer, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult<()> { + buffer.write_usize(self.by_stark_size.len())?; + for (&size, table) in &self.by_stark_size { + buffer.write_usize(size)?; + table.to_buffer(buffer, gate_serializer, generator_serializer)?; + } + Ok(()) + } + + pub fn from_buffer( + buffer: &mut Buffer, + gate_serializer: &dyn GateSerializer, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult { + let length = buffer.read_usize()?; + let mut by_stark_size = BTreeMap::new(); + for _ in 0..length { + let key = buffer.read_usize()?; + let table = RecursiveCircuitsForTableSize::from_buffer( + buffer, + gate_serializer, + generator_serializer, + )?; + by_stark_size.insert(key, table); + } + Ok(Self { by_stark_size }) + } + fn new>( table: Table, stark: &S, @@ -549,6 +795,7 @@ where /// A chain of shrinking wrapper circuits, ending with a final circuit with `degree_bits` /// `THRESHOLD_DEGREE_BITS`. +#[derive(Eq, PartialEq, Debug)] struct RecursiveCircuitsForTableSize where F: RichField + Extendable, @@ -568,6 +815,67 @@ where [(); C::HCO::WIDTH]:, [(); C::HCI::WIDTH]:, { + pub fn to_buffer( + &self, + buffer: &mut Vec, + gate_serializer: &dyn GateSerializer, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult<()> { + buffer.write_usize(self.shrinking_wrappers.len())?; + if !self.shrinking_wrappers.is_empty() { + buffer.write_common_circuit_data( + &self.shrinking_wrappers[0].circuit.common, + gate_serializer, + )?; + } + for wrapper in &self.shrinking_wrappers { + buffer.write_prover_only_circuit_data( + &wrapper.circuit.prover_only, + generator_serializer, + )?; + buffer.write_verifier_only_circuit_data(&wrapper.circuit.verifier_only)?; + buffer.write_target_proof_with_public_inputs(&wrapper.proof_with_pis_target)?; + } + self.initial_wrapper + .to_buffer(buffer, gate_serializer, generator_serializer)?; + Ok(()) + } + + pub fn from_buffer( + buffer: &mut Buffer, + gate_serializer: &dyn GateSerializer, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult { + let length = buffer.read_usize()?; + let mut shrinking_wrappers = Vec::with_capacity(length); + if length != 0 { + let common = buffer.read_common_circuit_data(gate_serializer)?; + + for _ in 0..length { + let prover_only = + buffer.read_prover_only_circuit_data(generator_serializer, &common)?; + let verifier_only = buffer.read_verifier_only_circuit_data()?; + let proof_with_pis_target = buffer.read_target_proof_with_public_inputs()?; + shrinking_wrappers.push(PlonkWrapperCircuit { + circuit: CircuitData { + common: common.clone(), + prover_only, + verifier_only, + }, + proof_with_pis_target, + }) + } + }; + + let initial_wrapper = + StarkWrapperCircuit::from_buffer(buffer, gate_serializer, generator_serializer)?; + + Ok(Self { + initial_wrapper, + shrinking_wrappers, + }) + } + fn new>( table: Table, stark: &S, diff --git a/evm/src/generation/prover_input.rs b/evm/src/generation/prover_input.rs index 28380f7e..712c51fe 100644 --- a/evm/src/generation/prover_input.rs +++ b/evm/src/generation/prover_input.rs @@ -5,6 +5,7 @@ use anyhow::{bail, Error}; use ethereum_types::{BigEndianHash, H256, U256, U512}; use itertools::Itertools; use plonky2::field::types::Field; +use serde::{Deserialize, Serialize}; use crate::extension_tower::{FieldExt, Fp12, BLS381, BN254}; use crate::generation::prover_input::EvmField::{ @@ -19,7 +20,7 @@ use crate::witness::util::{kernel_peek, stack_peek}; /// Prover input function represented as a scoped function name. /// Example: `PROVER_INPUT(ff::bn254_base::inverse)` is represented as `ProverInputFn([ff, bn254_base, inverse])`. -#[derive(PartialEq, Eq, Debug, Clone)] +#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)] pub struct ProverInputFn(Vec); impl From> for ProverInputFn { diff --git a/evm/src/generation/state.rs b/evm/src/generation/state.rs index 49c11611..c0c03e28 100644 --- a/evm/src/generation/state.rs +++ b/evm/src/generation/state.rs @@ -5,10 +5,12 @@ use keccak_hash::keccak; use plonky2::field::types::Field; use crate::cpu::kernel::aggregator::KERNEL; +use crate::cpu::kernel::constants::context_metadata::ContextMetadata; use crate::generation::mpt::all_mpt_prover_inputs_reversed; use crate::generation::rlp::all_rlp_prover_inputs_reversed; use crate::generation::GenerationInputs; -use crate::witness::memory::MemoryState; +use crate::memory::segments::Segment; +use crate::witness::memory::{MemoryAddress, MemoryState}; use crate::witness::state::RegistersState; use crate::witness::traces::{TraceCheckpoint, Traces}; use crate::witness::util::stack_peek; @@ -83,6 +85,10 @@ impl GenerationState { let tip_h256 = H256::from_uint(&tip_u256); let tip_h160 = H160::from(tip_h256); self.observe_address(tip_h160); + } else if dst == KERNEL.global_labels["observe_new_contract"] { + let tip_u256 = stack_peek(self, 0).expect("Empty stack"); + let tip_h256 = H256::from_uint(&tip_u256); + self.observe_contract(tip_h256); } } @@ -93,6 +99,30 @@ impl GenerationState { self.state_key_to_address.insert(state_key, address); } + /// Observe the given code hash and store the associated code. + /// When called, the code corresponding to `codehash` should be stored in the return data. + pub fn observe_contract(&mut self, codehash: H256) { + if self.inputs.contract_code.contains_key(&codehash) { + return; // Return early if the code hash has already been observed. + } + + let ctx = self.registers.context; + let returndata_size_addr = MemoryAddress::new( + ctx, + Segment::ContextMetadata, + ContextMetadata::ReturndataSize as usize, + ); + let returndata_size = self.memory.get(returndata_size_addr).as_usize(); + let code = self.memory.contexts[ctx].segments[Segment::Returndata as usize].content + [..returndata_size] + .iter() + .map(|x| x.as_u32() as u8) + .collect::>(); + debug_assert_eq!(keccak(&code), codehash); + + self.inputs.contract_code.insert(codehash, code); + } + pub fn checkpoint(&self) -> GenerationStateCheckpoint { GenerationStateCheckpoint { registers: self.registers, diff --git a/evm/src/lib.rs b/evm/src/lib.rs index dc07d233..02730321 100644 --- a/evm/src/lib.rs +++ b/evm/src/lib.rs @@ -9,11 +9,11 @@ pub mod all_stark; pub mod arithmetic; -pub mod bn254_pairing; pub mod config; pub mod constraint_consumer; pub mod cpu; pub mod cross_table_lookup; +pub mod curve_pairings; pub mod extension_tower; pub mod fixed_recursive_verifier; pub mod generation; diff --git a/evm/src/permutation.rs b/evm/src/permutation.rs index 7dc21871..72078c93 100644 --- a/evm/src/permutation.rs +++ b/evm/src/permutation.rs @@ -17,6 +17,7 @@ use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::config::{AlgebraicHasher, Hasher}; use plonky2::plonk::plonk_common::{reduce_with_powers, reduce_with_powers_ext_circuit}; use plonky2::util::reducing::{ReducingFactor, ReducingFactorTarget}; +use plonky2::util::serialization::{Buffer, IoResult, Read, Write}; use plonky2_maybe_rayon::*; use crate::config::StarkConfig; @@ -89,6 +90,30 @@ pub(crate) struct GrandProductChallengeSet { pub(crate) challenges: Vec>, } +impl GrandProductChallengeSet { + pub fn to_buffer(&self, buffer: &mut Vec) -> IoResult<()> { + buffer.write_usize(self.challenges.len())?; + for challenge in &self.challenges { + buffer.write_target(challenge.beta)?; + buffer.write_target(challenge.gamma)?; + } + Ok(()) + } + + pub fn from_buffer(buffer: &mut Buffer) -> IoResult { + let length = buffer.read_usize()?; + let mut challenges = Vec::with_capacity(length); + for _ in 0..length { + challenges.push(GrandProductChallenge { + beta: buffer.read_target()?, + gamma: buffer.read_target()?, + }); + } + + Ok(GrandProductChallengeSet { challenges }) + } +} + /// Compute all Z polynomials (for permutation arguments). pub(crate) fn compute_permutation_z_polys( stark: &S, diff --git a/evm/src/proof.rs b/evm/src/proof.rs index b243c9be..0fefcc0c 100644 --- a/evm/src/proof.rs +++ b/evm/src/proof.rs @@ -12,6 +12,7 @@ use plonky2::hash::merkle_tree::MerkleCap; use plonky2::iop::ext_target::ExtensionTarget; use plonky2::iop::target::Target; use plonky2::plonk::config::GenericConfig; +use plonky2::util::serialization::{Buffer, IoResult, Read, Write}; use plonky2_maybe_rayon::*; use serde::{Deserialize, Serialize}; @@ -148,6 +149,7 @@ impl, C: GenericConfig, const D: usize> S } } +#[derive(Eq, PartialEq, Debug)] pub struct StarkProofTarget { pub trace_cap: MerkleCapTarget, pub permutation_ctl_zs_cap: MerkleCapTarget, @@ -157,6 +159,31 @@ pub struct StarkProofTarget { } impl StarkProofTarget { + pub fn to_buffer(&self, buffer: &mut Vec) -> IoResult<()> { + buffer.write_target_merkle_cap(&self.trace_cap)?; + buffer.write_target_merkle_cap(&self.permutation_ctl_zs_cap)?; + buffer.write_target_merkle_cap(&self.quotient_polys_cap)?; + buffer.write_target_fri_proof(&self.opening_proof)?; + self.openings.to_buffer(buffer)?; + Ok(()) + } + + pub fn from_buffer(buffer: &mut Buffer) -> IoResult { + let trace_cap = buffer.read_target_merkle_cap()?; + let permutation_ctl_zs_cap = buffer.read_target_merkle_cap()?; + let quotient_polys_cap = buffer.read_target_merkle_cap()?; + let opening_proof = buffer.read_target_fri_proof()?; + let openings = StarkOpeningSetTarget::from_buffer(buffer)?; + + Ok(Self { + trace_cap, + permutation_ctl_zs_cap, + quotient_polys_cap, + openings, + opening_proof, + }) + } + /// Recover the length of the trace from a STARK proof and a STARK config. pub fn recover_degree_bits(&self, config: &StarkConfig) -> usize { let initial_merkle_proof = &self.opening_proof.query_round_proofs[0] @@ -276,6 +303,7 @@ impl, const D: usize> StarkOpeningSet { } } +#[derive(Eq, PartialEq, Debug)] pub struct StarkOpeningSetTarget { pub local_values: Vec>, pub next_values: Vec>, @@ -286,6 +314,34 @@ pub struct StarkOpeningSetTarget { } impl StarkOpeningSetTarget { + pub fn to_buffer(&self, buffer: &mut Vec) -> IoResult<()> { + buffer.write_target_ext_vec(&self.local_values)?; + buffer.write_target_ext_vec(&self.next_values)?; + buffer.write_target_ext_vec(&self.permutation_ctl_zs)?; + buffer.write_target_ext_vec(&self.permutation_ctl_zs_next)?; + buffer.write_target_vec(&self.ctl_zs_last)?; + buffer.write_target_ext_vec(&self.quotient_polys)?; + Ok(()) + } + + pub fn from_buffer(buffer: &mut Buffer) -> IoResult { + let local_values = buffer.read_target_ext_vec::()?; + let next_values = buffer.read_target_ext_vec::()?; + let permutation_ctl_zs = buffer.read_target_ext_vec::()?; + let permutation_ctl_zs_next = buffer.read_target_ext_vec::()?; + let ctl_zs_last = buffer.read_target_vec()?; + let quotient_polys = buffer.read_target_ext_vec::()?; + + Ok(Self { + local_values, + next_values, + permutation_ctl_zs, + permutation_ctl_zs_next, + ctl_zs_last, + quotient_polys, + }) + } + pub(crate) fn to_fri_openings(&self, zero: Target) -> FriOpeningsTarget { let zeta_batch = FriOpeningBatchTarget { values: self diff --git a/evm/src/recursive_verifier.rs b/evm/src/recursive_verifier.rs index 14e31341..9da9281a 100644 --- a/evm/src/recursive_verifier.rs +++ b/evm/src/recursive_verifier.rs @@ -19,6 +19,9 @@ use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData, VerifierCircuitDa use plonky2::plonk::config::{AlgebraicHasher, GenericConfig}; use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget}; use plonky2::util::reducing::ReducingFactorTarget; +use plonky2::util::serialization::{ + Buffer, GateSerializer, IoResult, Read, WitnessGeneratorSerializer, Write, +}; use plonky2::with_context; use plonky2_util::log2_ceil; @@ -157,6 +160,7 @@ impl, C: GenericConfig, const D: usize> } /// Represents a circuit which recursively verifies a STARK proof. +#[derive(Eq, PartialEq, Debug)] pub(crate) struct StarkWrapperCircuit where F: RichField + Extendable, @@ -178,6 +182,39 @@ where [(); C::HCO::WIDTH]:, [(); C::HCI::WIDTH]:, { + pub fn to_buffer( + &self, + buffer: &mut Vec, + gate_serializer: &dyn GateSerializer, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult<()> { + buffer.write_circuit_data(&self.circuit, gate_serializer, generator_serializer)?; + buffer.write_target_vec(&self.init_challenger_state_target)?; + buffer.write_target(self.zero_target)?; + self.stark_proof_target.to_buffer(buffer)?; + self.ctl_challenges_target.to_buffer(buffer)?; + Ok(()) + } + + pub fn from_buffer( + buffer: &mut Buffer, + gate_serializer: &dyn GateSerializer, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult { + let circuit = buffer.read_circuit_data(gate_serializer, generator_serializer)?; + let init_challenger_state_target = buffer.read_target_vec()?; + let zero_target = buffer.read_target()?; + let stark_proof_target = StarkProofTarget::from_buffer(buffer)?; + let ctl_challenges_target = GrandProductChallengeSet::from_buffer(buffer)?; + Ok(Self { + circuit, + stark_proof_target, + ctl_challenges_target, + init_challenger_state_target: init_challenger_state_target.try_into().unwrap(), + zero_target, + }) + } + pub(crate) fn prove( &self, proof_with_metadata: &StarkProofWithMetadata, @@ -212,6 +249,7 @@ where } /// Represents a circuit which recursively verifies a PLONK proof. +#[derive(Eq, PartialEq, Debug)] pub(crate) struct PlonkWrapperCircuit where F: RichField + Extendable, diff --git a/evm/src/witness/util.rs b/evm/src/witness/util.rs index a5ebf2ac..94e13e50 100644 --- a/evm/src/witness/util.rs +++ b/evm/src/witness/util.rs @@ -45,9 +45,7 @@ pub(crate) fn kernel_peek( segment: Segment, virt: usize, ) -> U256 { - state - .memory - .get(MemoryAddress::new(state.registers.context, segment, virt)) + state.memory.get(MemoryAddress::new(0, segment, virt)) } pub(crate) fn mem_read_with_log( diff --git a/evm/tests/basic_smart_contract.rs b/evm/tests/basic_smart_contract.rs index b93f48ec..434ef8c2 100644 --- a/evm/tests/basic_smart_contract.rs +++ b/evm/tests/basic_smart_contract.rs @@ -28,6 +28,7 @@ type C = PoseidonGoldilocksConfig; /// Test a simple token transfer to a new address. #[test] +#[ignore] // Too slow to run on CI. fn test_basic_smart_contract() -> anyhow::Result<()> { init_logger(); diff --git a/evm/tests/empty_txn_list.rs b/evm/tests/empty_txn_list.rs index 9a4eb5e0..ec2d999b 100644 --- a/evm/tests/empty_txn_list.rs +++ b/evm/tests/empty_txn_list.rs @@ -1,13 +1,16 @@ #![allow(clippy::upper_case_acronyms)] use std::collections::HashMap; +use std::marker::PhantomData; use std::time::Duration; use env_logger::{try_init_from_env, Env, DEFAULT_FILTER_ENV}; use eth_trie_utils::partial_trie::{HashedPartialTrie, PartialTrie}; use keccak_hash::keccak; +use log::info; use plonky2::field::goldilocks_field::GoldilocksField; use plonky2::plonk::config::PoseidonGoldilocksConfig; +use plonky2::util::serialization::{DefaultGateSerializer, DefaultGeneratorSerializer}; use plonky2::util::timing::TimingTree; use plonky2_evm::all_stark::AllStark; use plonky2_evm::config::StarkConfig; @@ -92,8 +95,43 @@ fn test_empty_txn_list() -> anyhow::Result<()> { verify_proof(&all_stark, proof, &config)?; - let all_circuits = AllRecursiveCircuits::::new(&all_stark, 9..19, &config); + let all_circuits = AllRecursiveCircuits::::new( + &all_stark, + &[9..15, 9..15, 9..10, 9..12, 9..18], // Minimal ranges to prove an empty list + &config, + ); + + { + let gate_serializer = DefaultGateSerializer; + let generator_serializer = DefaultGeneratorSerializer { + _phantom: PhantomData::, + }; + + let timing = TimingTree::new("serialize AllRecursiveCircuits", log::Level::Info); + let all_circuits_bytes = all_circuits + .to_bytes(&gate_serializer, &generator_serializer) + .map_err(|_| anyhow::Error::msg("AllRecursiveCircuits serialization failed."))?; + timing.filter(Duration::from_millis(100)).print(); + info!( + "AllRecursiveCircuits length: {} bytes", + all_circuits_bytes.len() + ); + + let timing = TimingTree::new("deserialize AllRecursiveCircuits", log::Level::Info); + let all_circuits_from_bytes = AllRecursiveCircuits::::from_bytes( + &all_circuits_bytes, + &gate_serializer, + &generator_serializer, + ) + .map_err(|_| anyhow::Error::msg("AllRecursiveCircuits deserialization failed."))?; + timing.filter(Duration::from_millis(100)).print(); + + assert_eq!(all_circuits, all_circuits_from_bytes); + } + + let mut timing = TimingTree::new("prove", log::Level::Info); let root_proof = all_circuits.prove_root(&all_stark, &config, inputs, &mut timing)?; + timing.filter(Duration::from_millis(100)).print(); all_circuits.verify_root(root_proof.clone())?; let agg_proof = all_circuits.prove_aggregation(false, &root_proof, false, &root_proof)?; diff --git a/evm/tests/self_balance_gas_cost.rs b/evm/tests/self_balance_gas_cost.rs index d38c066b..a970524f 100644 --- a/evm/tests/self_balance_gas_cost.rs +++ b/evm/tests/self_balance_gas_cost.rs @@ -26,6 +26,7 @@ type C = PoseidonGoldilocksConfig; /// The `selfBalanceGasCost` test case from https://github.com/ethereum/tests #[test] +#[ignore] // Too slow to run on CI. fn self_balance_gas_cost() -> anyhow::Result<()> { init_logger(); diff --git a/field/src/goldilocks_field.rs b/field/src/goldilocks_field.rs index 8c8d8bc3..e10d0c74 100644 --- a/field/src/goldilocks_field.rs +++ b/field/src/goldilocks_field.rs @@ -46,13 +46,13 @@ impl Hash for GoldilocksField { impl Display for GoldilocksField { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - Display::fmt(&self.0, f) + Display::fmt(&self.to_canonical_u64(), f) } } impl Debug for GoldilocksField { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - Debug::fmt(&self.0, f) + Debug::fmt(&self.to_canonical_u64(), f) } } diff --git a/plonky2/Cargo.toml b/plonky2/Cargo.toml index 6df46060..39b95f21 100644 --- a/plonky2/Cargo.toml +++ b/plonky2/Cargo.toml @@ -31,6 +31,7 @@ plonky2_util = { version = "0.1.0", default-features = false } rand = { version = "0.8.4", default-features = false } rand_chacha = { version = "0.3.1", optional = true, default-features = false } serde = { version = "1.0", default-features = false, features = ["derive"] } +serde_json = "1.0" static_assertions = { version = "1.1.0", default-features = false } unroll = { version = "0.1.5", default-features = false } diff --git a/plonky2/examples/bench_recursion.rs b/plonky2/examples/bench_recursion.rs index bb1ff9d1..a6fe9c37 100644 --- a/plonky2/examples/bench_recursion.rs +++ b/plonky2/examples/bench_recursion.rs @@ -4,6 +4,7 @@ // `[dev-dependencies]`. #![feature(generic_const_exprs)] +#![allow(incomplete_features)] #![allow(clippy::upper_case_acronyms)] use core::num::ParseIntError; @@ -21,6 +22,7 @@ use plonky2::plonk::circuit_data::{CircuitConfig, CommonCircuitData, VerifierOnl use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, PoseidonGoldilocksConfig}; use plonky2::plonk::proof::{CompressedProofWithPublicInputs, ProofWithPublicInputs}; use plonky2::plonk::prover::prove; +use plonky2::util::serialization::DefaultGateSerializer; use plonky2::util::timing::TimingTree; use plonky2_field::extension::Extendable; use plonky2_maybe_rayon::rayon; @@ -180,6 +182,19 @@ where CompressedProofWithPublicInputs::from_bytes(compressed_proof_bytes, cd)?; assert_eq!(compressed_proof, compressed_proof_from_bytes); + let gate_serializer = DefaultGateSerializer; + let common_data_bytes = cd + .to_bytes(&gate_serializer) + .map_err(|_| anyhow::Error::msg("CommonCircuitData serialization failed."))?; + info!( + "Common circuit data length: {} bytes", + common_data_bytes.len() + ); + let common_data_from_bytes = + CommonCircuitData::::from_bytes(common_data_bytes, &gate_serializer) + .map_err(|_| anyhow::Error::msg("CommonCircuitData deserialization failed."))?; + assert_eq!(cd, &common_data_from_bytes); + Ok(()) } diff --git a/plonky2/examples/fibonacci_serialization.rs b/plonky2/examples/fibonacci_serialization.rs new file mode 100644 index 00000000..68943457 --- /dev/null +++ b/plonky2/examples/fibonacci_serialization.rs @@ -0,0 +1,79 @@ +#![allow(clippy::upper_case_acronyms)] + +use std::fs; + +use anyhow::Result; +use plonky2::field::types::Field; +use plonky2::iop::witness::{PartialWitness, WitnessWrite}; +use plonky2::plonk::circuit_builder::CircuitBuilder; +use plonky2::plonk::circuit_data::CircuitConfig; +use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; + +/// An example of using Plonky2 to prove a statement of the form +/// "I know the 100th element of the Fibonacci sequence, starting with constants a and b." +/// When a == 0 and b == 1, this is proving knowledge of the 100th (standard) Fibonacci number. +/// This example also serializes the circuit data and proof to JSON files. +fn main() -> Result<()> { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + + let config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(config); + + // The arithmetic circuit. + let initial_a = builder.add_virtual_target(); + let initial_b = builder.add_virtual_target(); + let mut prev_target = initial_a; + let mut cur_target = initial_b; + for _ in 0..99 { + let temp = builder.add(prev_target, cur_target); + prev_target = cur_target; + cur_target = temp; + } + + // Public inputs are the two initial values (provided below) and the result (which is generated). + builder.register_public_input(initial_a); + builder.register_public_input(initial_b); + builder.register_public_input(cur_target); + + // Provide initial values. + let mut pw = PartialWitness::new(); + pw.set_target(initial_a, F::ZERO); + pw.set_target(initial_b, F::ONE); + + let data = builder.build::(); + + let common_circuit_data_serialized = serde_json::to_string(&data.common).unwrap(); + fs::write("common_circuit_data.json", common_circuit_data_serialized) + .expect("Unable to write file"); + + let verifier_only_circuit_data_serialized = serde_json::to_string(&data.verifier_only).unwrap(); + fs::write( + "verifier_only_circuit_data.json", + verifier_only_circuit_data_serialized, + ) + .expect("Unable to write file"); + + let proof = data.prove(pw)?; + + let proof_serialized = serde_json::to_string(&proof).unwrap(); + fs::write("proof_with_public_inputs.json", proof_serialized).expect("Unable to write file"); + + let proof_challenges = proof + .get_challenges( + proof.get_public_inputs_hash(), + &data.verifier_only.circuit_digest, + &data.common, + ) + .unwrap(); + let proof_challenges_serialized = serde_json::to_string(&proof_challenges).unwrap(); + fs::write("proof_challenges.json", proof_challenges_serialized).expect("Unable to write file"); + + println!( + "100th Fibonacci number mod |F| (starting with {}, {}) is: {}", + proof.public_inputs[0], proof.public_inputs[1], proof.public_inputs[2] + ); + + data.verify(proof) +} diff --git a/plonky2/examples/square_root.rs b/plonky2/examples/square_root.rs index 9c253b69..6ac9eddd 100644 --- a/plonky2/examples/square_root.rs +++ b/plonky2/examples/square_root.rs @@ -4,18 +4,28 @@ use core::marker::PhantomData; use anyhow::Result; use plonky2::field::types::{PrimeField, Sample}; +use plonky2::gates::arithmetic_base::ArithmeticBaseGenerator; +use plonky2::gates::poseidon::PoseidonGenerator; +use plonky2::gates::poseidon_mds::PoseidonMdsGenerator; use plonky2::hash::hash_types::RichField; -use plonky2::iop::generator::{GeneratedValues, SimpleGenerator}; +use plonky2::iop::generator::{ + ConstantGenerator, GeneratedValues, RandomValueGenerator, SimpleGenerator, +}; use plonky2::iop::target::Target; use plonky2::iop::witness::{PartialWitness, PartitionWitness, Witness, WitnessWrite}; use plonky2::plonk::circuit_builder::CircuitBuilder; -use plonky2::plonk::circuit_data::CircuitConfig; -use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig}; +use plonky2::plonk::circuit_data::{CircuitConfig, CircuitData}; +use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, PoseidonGoldilocksConfig}; +use plonky2::recursion::dummy_circuit::DummyProofGenerator; +use plonky2::util::serialization::{ + Buffer, DefaultGateSerializer, IoResult, Read, WitnessGeneratorSerializer, Write, +}; +use plonky2::{get_generator_tag_impl, impl_generator_serializer, read_generator_impl}; use plonky2_field::extension::Extendable; /// A generator used by the prover to calculate the square root (`x`) of a given value /// (`x_squared`), outside of the circuit, in order to supply it as an additional public input. -#[derive(Debug)] +#[derive(Debug, Default)] struct SquareRootGenerator, const D: usize> { x: Target, x_squared: Target, @@ -25,6 +35,10 @@ struct SquareRootGenerator, const D: usize> { impl, const D: usize> SimpleGenerator for SquareRootGenerator { + fn id(&self) -> String { + "SquareRootGenerator".to_string() + } + fn dependencies(&self) -> Vec { vec![self.x_squared] } @@ -37,6 +51,43 @@ impl, const D: usize> SimpleGenerator out_buffer.set_target(self.x, x); } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_target(self.x)?; + dst.write_target(self.x_squared) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let x = src.read_target()?; + let x_squared = src.read_target()?; + Ok(Self { + x, + x_squared, + _phantom: PhantomData, + }) + } +} + +pub struct CustomGeneratorSerializer, const D: usize> { + pub _phantom: PhantomData, +} + +impl WitnessGeneratorSerializer for CustomGeneratorSerializer +where + F: RichField + Extendable, + C: GenericConfig + 'static, + C::Hasher: AlgebraicHasher, +{ + impl_generator_serializer! { + CustomGeneratorSerializer, + DummyProofGenerator, + ArithmeticBaseGenerator, + ConstantGenerator, + PoseidonGenerator, + PoseidonMdsGenerator, + RandomValueGenerator, + SquareRootGenerator + } } /// An example of using Plonky2 to prove a statement of the form @@ -79,5 +130,26 @@ fn main() -> Result<()> { let x_squared_actual = proof.public_inputs[0]; println!("Field element (square): {x_squared_actual}"); + // Test serialization + { + let gate_serializer = DefaultGateSerializer; + let generator_serializer = CustomGeneratorSerializer { + _phantom: PhantomData::, + }; + + let data_bytes = data + .to_bytes(&gate_serializer, &generator_serializer) + .map_err(|_| anyhow::Error::msg("CircuitData serialization failed."))?; + + let data_from_bytes = CircuitData::::from_bytes( + &data_bytes, + &gate_serializer, + &generator_serializer, + ) + .map_err(|_| anyhow::Error::msg("CircuitData deserialization failed."))?; + + assert_eq!(data, data_from_bytes); + } + data.verify(proof) } diff --git a/plonky2/src/fri/mod.rs b/plonky2/src/fri/mod.rs index ca800b98..5121d755 100644 --- a/plonky2/src/fri/mod.rs +++ b/plonky2/src/fri/mod.rs @@ -1,5 +1,7 @@ use alloc::vec::Vec; +use serde::Serialize; + use crate::fri::reduction_strategies::FriReductionStrategy; mod challenges; @@ -13,7 +15,7 @@ mod validate_shape; pub mod verifier; pub mod witness_util; -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, Serialize)] pub struct FriConfig { /// `rate = 2^{-rate_bits}`. pub rate_bits: usize, @@ -56,7 +58,7 @@ impl FriConfig { /// FRI parameters, including generated parameters which are specific to an instance size, in /// contrast to `FriConfig` which is user-specified and independent of instance size. -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, Serialize)] pub struct FriParams { /// User-specified FRI configuration. pub config: FriConfig, diff --git a/plonky2/src/fri/oracle.rs b/plonky2/src/fri/oracle.rs index 7855167a..bb0421fe 100644 --- a/plonky2/src/fri/oracle.rs +++ b/plonky2/src/fri/oracle.rs @@ -27,6 +27,7 @@ use crate::util::{log2_strict, reverse_bits, reverse_index_bits_in_place, transp pub const SALT_SIZE: usize = 4; /// Represents a FRI oracle, i.e. a batch of polynomials which have been Merklized. +#[derive(Eq, PartialEq, Debug)] pub struct PolynomialBatch, C: GenericConfig, const D: usize> { pub polynomials: Vec>, diff --git a/plonky2/src/fri/proof.rs b/plonky2/src/fri/proof.rs index cf1a60d1..d00feb4c 100644 --- a/plonky2/src/fri/proof.rs +++ b/plonky2/src/fri/proof.rs @@ -33,7 +33,7 @@ pub struct FriQueryStep< pub merkle_proof: MerkleProof, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct FriQueryStepTarget { pub evals: Vec>, pub merkle_proof: MerkleProofTarget, @@ -58,7 +58,7 @@ impl> FriInitialTreeProof, MerkleProofTarget)>, } @@ -92,7 +92,7 @@ pub struct FriQueryRound< pub steps: Vec>, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct FriQueryRoundTarget { pub initial_trees_proof: FriInitialTreeProofTarget, pub steps: Vec>, @@ -129,7 +129,7 @@ pub struct FriProof, HC: HashConfig, H: Hasher { pub commit_phase_merkle_caps: Vec, pub query_round_proofs: Vec>, @@ -393,6 +393,7 @@ impl, HCO: HashConfig, H: Hasher, const D: } } +#[derive(Serialize)] pub struct FriChallenges, const D: usize> { // Scaling factor to combine polynomials. pub fri_alpha: F::Extension, diff --git a/plonky2/src/fri/reduction_strategies.rs b/plonky2/src/fri/reduction_strategies.rs index 409a0224..df273eea 100644 --- a/plonky2/src/fri/reduction_strategies.rs +++ b/plonky2/src/fri/reduction_strategies.rs @@ -4,9 +4,10 @@ use alloc::vec::Vec; use std::time::Instant; use log::debug; +use serde::Serialize; /// A method for deciding what arity to use at each reduction layer. -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, Serialize)] pub enum FriReductionStrategy { /// Specifies the exact sequence of arities (expressed in bits) to use. Fixed(Vec), diff --git a/plonky2/src/gadgets/arithmetic.rs b/plonky2/src/gadgets/arithmetic.rs index 6bff79d1..ed9e7c4a 100644 --- a/plonky2/src/gadgets/arithmetic.rs +++ b/plonky2/src/gadgets/arithmetic.rs @@ -11,6 +11,7 @@ use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::{BoolTarget, Target}; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::plonk::circuit_builder::CircuitBuilder; +use crate::util::serialization::{Buffer, IoResult, Read, Write}; impl, const D: usize> CircuitBuilder { /// Computes `-x`. @@ -370,8 +371,8 @@ impl, const D: usize> CircuitBuilder { } } -#[derive(Debug)] -struct EqualityGenerator { +#[derive(Debug, Default)] +pub struct EqualityGenerator { x: Target, y: Target, equal: BoolTarget, @@ -379,6 +380,10 @@ struct EqualityGenerator { } impl SimpleGenerator for EqualityGenerator { + fn id(&self) -> String { + "EqualityGenerator".to_string() + } + fn dependencies(&self) -> Vec { vec![self.x, self.y] } @@ -392,6 +397,21 @@ impl SimpleGenerator for EqualityGenerator { out_buffer.set_bool_target(self.equal, x == y); out_buffer.set_target(self.inv, inv); } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_target(self.x)?; + dst.write_target(self.y)?; + dst.write_target_bool(self.equal)?; + dst.write_target(self.inv) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let x = src.read_target()?; + let y = src.read_target()?; + let equal = src.read_target_bool()?; + let inv = src.read_target()?; + Ok(Self { x, y, equal, inv }) + } } /// Represents a base arithmetic operation in the circuit. Used to memoize results. diff --git a/plonky2/src/gadgets/arithmetic_extension.rs b/plonky2/src/gadgets/arithmetic_extension.rs index 6fcab718..ccb84a40 100644 --- a/plonky2/src/gadgets/arithmetic_extension.rs +++ b/plonky2/src/gadgets/arithmetic_extension.rs @@ -13,6 +13,7 @@ use crate::iop::target::Target; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::bits_u64; +use crate::util::serialization::{Buffer, IoResult, Read, Write}; impl, const D: usize> CircuitBuilder { pub fn arithmetic_extension( @@ -493,8 +494,8 @@ impl, const D: usize> CircuitBuilder { } } -#[derive(Debug)] -struct QuotientGeneratorExtension { +#[derive(Debug, Default)] +pub struct QuotientGeneratorExtension { numerator: ExtensionTarget, denominator: ExtensionTarget, quotient: ExtensionTarget, @@ -503,6 +504,10 @@ struct QuotientGeneratorExtension { impl, const D: usize> SimpleGenerator for QuotientGeneratorExtension { + fn id(&self) -> String { + "QuotientGeneratorExtension".to_string() + } + fn dependencies(&self) -> Vec { let mut deps = self.numerator.to_target_array().to_vec(); deps.extend(self.denominator.to_target_array()); @@ -515,6 +520,23 @@ impl, const D: usize> SimpleGenerator let quotient = num / dem; out_buffer.set_extension_target(self.quotient, quotient) } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_target_ext(self.numerator)?; + dst.write_target_ext(self.denominator)?; + dst.write_target_ext(self.quotient) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let numerator = src.read_target_ext()?; + let denominator = src.read_target_ext()?; + let quotient = src.read_target_ext()?; + Ok(Self { + numerator, + denominator, + quotient, + }) + } } /// An iterator over the powers of a certain base element `b`: `b^0, b^1, b^2, ...`. diff --git a/plonky2/src/gadgets/mod.rs b/plonky2/src/gadgets/mod.rs index 6309eb3d..bac94475 100644 --- a/plonky2/src/gadgets/mod.rs +++ b/plonky2/src/gadgets/mod.rs @@ -7,4 +7,4 @@ pub mod random_access; pub mod range_check; pub mod select; pub mod split_base; -pub(crate) mod split_join; +pub mod split_join; diff --git a/plonky2/src/gadgets/polynomial.rs b/plonky2/src/gadgets/polynomial.rs index 80beb62f..d43d99c2 100644 --- a/plonky2/src/gadgets/polynomial.rs +++ b/plonky2/src/gadgets/polynomial.rs @@ -7,7 +7,7 @@ use crate::iop::target::Target; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::reducing::ReducingFactorTarget; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct PolynomialCoeffsExtTarget(pub Vec>); impl PolynomialCoeffsExtTarget { diff --git a/plonky2/src/gadgets/range_check.rs b/plonky2/src/gadgets/range_check.rs index 4c22009d..bdd1942c 100644 --- a/plonky2/src/gadgets/range_check.rs +++ b/plonky2/src/gadgets/range_check.rs @@ -7,6 +7,7 @@ use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::{BoolTarget, Target}; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::plonk::circuit_builder::CircuitBuilder; +use crate::util::serialization::{Buffer, IoResult, Read, Write}; impl, const D: usize> CircuitBuilder { /// Checks that `x < 2^n_log` using a `BaseSumGate`. @@ -51,8 +52,8 @@ impl, const D: usize> CircuitBuilder { } } -#[derive(Debug)] -struct LowHighGenerator { +#[derive(Debug, Default)] +pub struct LowHighGenerator { integer: Target, n_log: usize, low: Target, @@ -60,6 +61,10 @@ struct LowHighGenerator { } impl SimpleGenerator for LowHighGenerator { + fn id(&self) -> String { + "LowHighGenerator".to_string() + } + fn dependencies(&self) -> Vec { vec![self.integer] } @@ -72,4 +77,24 @@ impl SimpleGenerator for LowHighGenerator { out_buffer.set_target(self.low, F::from_canonical_u64(low)); out_buffer.set_target(self.high, F::from_canonical_u64(high)); } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_target(self.integer)?; + dst.write_usize(self.n_log)?; + dst.write_target(self.low)?; + dst.write_target(self.high) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let integer = src.read_target()?; + let n_log = src.read_usize()?; + let low = src.read_target()?; + let high = src.read_target()?; + Ok(Self { + integer, + n_log, + low, + high, + }) + } } diff --git a/plonky2/src/gadgets/split_base.rs b/plonky2/src/gadgets/split_base.rs index dd0edf5d..c2919315 100644 --- a/plonky2/src/gadgets/split_base.rs +++ b/plonky2/src/gadgets/split_base.rs @@ -13,6 +13,7 @@ use crate::iop::target::{BoolTarget, Target}; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::log_floor; +use crate::util::serialization::{Buffer, IoResult, Read, Write}; impl, const D: usize> CircuitBuilder { /// Split the given element into a list of targets, where each one represents a @@ -79,13 +80,17 @@ impl, const D: usize> CircuitBuilder { } } -#[derive(Debug)] -struct BaseSumGenerator { +#[derive(Debug, Default)] +pub struct BaseSumGenerator { row: usize, limbs: Vec, } impl SimpleGenerator for BaseSumGenerator { + fn id(&self) -> String { + "BaseSumGenerator".to_string() + } + fn dependencies(&self) -> Vec { self.limbs.iter().map(|b| b.target).collect() } @@ -102,6 +107,17 @@ impl SimpleGenerator for BaseSumGenerator { out_buffer.set_target(Target::wire(self.row, BaseSumGate::::WIRE_SUM), sum); } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_usize(self.row)?; + dst.write_target_bool_vec(&self.limbs) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let row = src.read_usize()?; + let limbs = src.read_target_bool_vec()?; + Ok(Self { row, limbs }) + } } #[cfg(test)] diff --git a/plonky2/src/gadgets/split_join.rs b/plonky2/src/gadgets/split_join.rs index 56e469b9..e3eda241 100644 --- a/plonky2/src/gadgets/split_join.rs +++ b/plonky2/src/gadgets/split_join.rs @@ -9,6 +9,7 @@ use crate::iop::target::{BoolTarget, Target}; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::util::ceil_div_usize; +use crate::util::serialization::{Buffer, IoResult, Read, Write}; impl, const D: usize> CircuitBuilder { /// Split the given integer into a list of wires, where each one represents a @@ -55,13 +56,17 @@ impl, const D: usize> CircuitBuilder { } } -#[derive(Debug)] -struct SplitGenerator { +#[derive(Debug, Default)] +pub struct SplitGenerator { integer: Target, bits: Vec, } impl SimpleGenerator for SplitGenerator { + fn id(&self) -> String { + "SplitGenerator".to_string() + } + fn dependencies(&self) -> Vec { vec![self.integer] } @@ -80,16 +85,31 @@ impl SimpleGenerator for SplitGenerator { "Integer too large to fit in given number of bits" ); } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_target(self.integer)?; + dst.write_target_vec(&self.bits) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let integer = src.read_target()?; + let bits = src.read_target_vec()?; + Ok(Self { integer, bits }) + } } -#[derive(Debug)] -struct WireSplitGenerator { +#[derive(Debug, Default)] +pub struct WireSplitGenerator { integer: Target, gates: Vec, num_limbs: usize, } impl SimpleGenerator for WireSplitGenerator { + fn id(&self) -> String { + "WireSplitGenerator".to_string() + } + fn dependencies(&self) -> Vec { vec![self.integer] } @@ -120,4 +140,21 @@ impl SimpleGenerator for WireSplitGenerator { self.gates.len() ); } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_target(self.integer)?; + dst.write_usize_vec(&self.gates)?; + dst.write_usize(self.num_limbs) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let integer = src.read_target()?; + let gates = src.read_usize_vec()?; + let num_limbs = src.read_usize()?; + Ok(Self { + integer, + gates, + num_limbs, + }) + } } diff --git a/plonky2/src/gates/arithmetic_base.rs b/plonky2/src/gates/arithmetic_base.rs index 13b4a2c5..7ed25328 100644 --- a/plonky2/src/gates/arithmetic_base.rs +++ b/plonky2/src/gates/arithmetic_base.rs @@ -1,4 +1,3 @@ -use alloc::boxed::Box; use alloc::format; use alloc::string::String; use alloc::vec::Vec; @@ -10,7 +9,7 @@ use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef}; use crate::iop::target::Target; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::plonk::circuit_builder::CircuitBuilder; @@ -19,6 +18,7 @@ use crate::plonk::vars::{ EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, EvaluationVarsBasePacked, }; +use crate::util::serialization::{Buffer, IoResult, Read, Write}; /// A gate which can perform a weighted multiply-add, i.e. `result = c0 x y + c1 z`. If the config /// supports enough routed wires, it can support several such operations in one gate. @@ -60,6 +60,15 @@ impl, const D: usize> Gate for ArithmeticGate format!("{self:?}") } + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_usize(self.num_ops) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let num_ops = src.read_usize()?; + Ok(Self { num_ops }) + } + fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { let const_0 = vars.local_constants[0]; let const_1 = vars.local_constants[1]; @@ -117,10 +126,10 @@ impl, const D: usize> Gate for ArithmeticGate constraints } - fn generators(&self, row: usize, local_constants: &[F]) -> Vec>> { + fn generators(&self, row: usize, local_constants: &[F]) -> Vec> { (0..self.num_ops) .map(|i| { - let g: Box> = Box::new( + WitnessGeneratorRef::new( ArithmeticBaseGenerator { row, const_0: local_constants[0], @@ -128,8 +137,7 @@ impl, const D: usize> Gate for ArithmeticGate i, } .adapter(), - ); - g + ) }) .collect() } @@ -172,8 +180,8 @@ impl, const D: usize> PackedEvaluableBase for } } -#[derive(Clone, Debug)] -struct ArithmeticBaseGenerator, const D: usize> { +#[derive(Clone, Debug, Default)] +pub struct ArithmeticBaseGenerator, const D: usize> { row: usize, const_0: F, const_1: F, @@ -183,6 +191,10 @@ struct ArithmeticBaseGenerator, const D: usize> { impl, const D: usize> SimpleGenerator for ArithmeticBaseGenerator { + fn id(&self) -> String { + "ArithmeticBaseGenerator".to_string() + } + fn dependencies(&self) -> Vec { [ ArithmeticGate::wire_ith_multiplicand_0(self.i), @@ -208,6 +220,26 @@ impl, const D: usize> SimpleGenerator out_buffer.set_target(output_target, computed_output) } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_usize(self.row)?; + dst.write_field(self.const_0)?; + dst.write_field(self.const_1)?; + dst.write_usize(self.i) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let row = src.read_usize()?; + let const_0 = src.read_field()?; + let const_1 = src.read_field()?; + let i = src.read_usize()?; + Ok(Self { + row, + const_0, + const_1, + i, + }) + } } #[cfg(test)] diff --git a/plonky2/src/gates/arithmetic_extension.rs b/plonky2/src/gates/arithmetic_extension.rs index 4632dbd4..ebe7a650 100644 --- a/plonky2/src/gates/arithmetic_extension.rs +++ b/plonky2/src/gates/arithmetic_extension.rs @@ -1,4 +1,3 @@ -use alloc::boxed::Box; use alloc::format; use alloc::string::String; use alloc::vec::Vec; @@ -9,12 +8,13 @@ use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef}; use crate::iop::target::Target; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; +use crate::util::serialization::{Buffer, IoResult, Read, Write}; /// A gate which can perform a weighted multiply-add, i.e. `result = c0 x y + c1 z`. If the config /// supports enough routed wires, it can support several such operations in one gate. @@ -56,6 +56,15 @@ impl, const D: usize> Gate for ArithmeticExte format!("{self:?}") } + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_usize(self.num_ops) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let num_ops = src.read_usize()?; + Ok(Self { num_ops }) + } + fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { let const_0 = vars.local_constants[0]; let const_1 = vars.local_constants[1]; @@ -122,10 +131,10 @@ impl, const D: usize> Gate for ArithmeticExte constraints } - fn generators(&self, row: usize, local_constants: &[F]) -> Vec>> { + fn generators(&self, row: usize, local_constants: &[F]) -> Vec> { (0..self.num_ops) .map(|i| { - let g: Box> = Box::new( + WitnessGeneratorRef::new( ArithmeticExtensionGenerator { row, const_0: local_constants[0], @@ -133,8 +142,7 @@ impl, const D: usize> Gate for ArithmeticExte i, } .adapter(), - ); - g + ) }) .collect() } @@ -156,8 +164,8 @@ impl, const D: usize> Gate for ArithmeticExte } } -#[derive(Clone, Debug)] -struct ArithmeticExtensionGenerator, const D: usize> { +#[derive(Clone, Debug, Default)] +pub struct ArithmeticExtensionGenerator, const D: usize> { row: usize, const_0: F, const_1: F, @@ -167,6 +175,10 @@ struct ArithmeticExtensionGenerator, const D: usize impl, const D: usize> SimpleGenerator for ArithmeticExtensionGenerator { + fn id(&self) -> String { + "ArithmeticExtensionGenerator".to_string() + } + fn dependencies(&self) -> Vec { ArithmeticExtensionGate::::wires_ith_multiplicand_0(self.i) .chain(ArithmeticExtensionGate::::wires_ith_multiplicand_1( @@ -201,6 +213,26 @@ impl, const D: usize> SimpleGenerator out_buffer.set_extension_target(output_target, computed_output) } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_usize(self.row)?; + dst.write_field(self.const_0)?; + dst.write_field(self.const_1)?; + dst.write_usize(self.i) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let row = src.read_usize()?; + let const_0 = src.read_field()?; + let const_1 = src.read_field()?; + let i = src.read_usize()?; + Ok(Self { + row, + const_0, + const_1, + i, + }) + } } #[cfg(test)] diff --git a/plonky2/src/gates/base_sum.rs b/plonky2/src/gates/base_sum.rs index 5883d71c..fee50c66 100644 --- a/plonky2/src/gates/base_sum.rs +++ b/plonky2/src/gates/base_sum.rs @@ -1,4 +1,3 @@ -use alloc::boxed::Box; use alloc::string::String; use alloc::vec::Vec; use alloc::{format, vec}; @@ -12,7 +11,7 @@ use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef}; use crate::iop::target::Target; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::plonk::circuit_builder::CircuitBuilder; @@ -23,6 +22,7 @@ use crate::plonk::vars::{ EvaluationVarsBasePacked, }; use crate::util::log_floor; +use crate::util::serialization::{Buffer, IoResult, Read, Write}; /// A gate which can decompose a number into base B little-endian limbs. #[derive(Copy, Clone, Debug)] @@ -55,6 +55,15 @@ impl, const D: usize, const B: usize> Gate fo format!("{self:?} + Base: {B}") } + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_usize(self.num_limbs) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let num_limbs = src.read_usize()?; + Ok(Self { num_limbs }) + } + fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { let sum = vars.local_wires[Self::WIRE_SUM]; let limbs = vars.local_wires[self.limbs()].to_vec(); @@ -109,12 +118,12 @@ impl, const D: usize, const B: usize> Gate fo constraints } - fn generators(&self, row: usize, _local_constants: &[F]) -> Vec>> { + fn generators(&self, row: usize, _local_constants: &[F]) -> Vec> { let gen = BaseSplitGenerator:: { row, num_limbs: self.num_limbs, }; - vec![Box::new(gen.adapter())] + vec![WitnessGeneratorRef::new(gen.adapter())] } // 1 for the sum then `num_limbs` for the limbs. @@ -160,13 +169,17 @@ impl, const D: usize, const B: usize> PackedEvaluab } } -#[derive(Debug)] +#[derive(Debug, Default)] pub struct BaseSplitGenerator { row: usize, num_limbs: usize, } impl SimpleGenerator for BaseSplitGenerator { + fn id(&self) -> String { + "BaseSplitGenerator".to_string() + } + fn dependencies(&self) -> Vec { vec![Target::wire(self.row, BaseSumGate::::WIRE_SUM)] } @@ -195,6 +208,17 @@ impl SimpleGenerator for BaseSplitGenerator out_buffer.set_target(b, b_value); } } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_usize(self.row)?; + dst.write_usize(self.num_limbs) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let row = src.read_usize()?; + let num_limbs = src.read_usize()?; + Ok(Self { row, num_limbs }) + } } #[cfg(test)] diff --git a/plonky2/src/gates/constant.rs b/plonky2/src/gates/constant.rs index bf365b04..5fac1f00 100644 --- a/plonky2/src/gates/constant.rs +++ b/plonky2/src/gates/constant.rs @@ -1,8 +1,9 @@ -use alloc::boxed::Box; use alloc::string::String; use alloc::vec::Vec; use alloc::{format, vec}; +use serde::{Deserialize, Serialize}; + use crate::field::extension::Extendable; use crate::field::packed::PackedField; use crate::gates::gate::Gate; @@ -10,15 +11,16 @@ use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; -use crate::iop::generator::WitnessGenerator; +use crate::iop::generator::WitnessGeneratorRef; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{ EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, EvaluationVarsBasePacked, }; +use crate::util::serialization::{Buffer, IoResult, Read, Write}; /// A gate which takes a single constant parameter and outputs that value. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub struct ConstantGate { pub(crate) num_consts: usize, } @@ -40,6 +42,15 @@ impl, const D: usize> Gate for ConstantGate { format!("{self:?}") } + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_usize(self.num_consts) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let num_consts = src.read_usize()?; + Ok(Self { num_consts }) + } + fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { (0..self.num_consts) .map(|i| { @@ -75,7 +86,7 @@ impl, const D: usize> Gate for ConstantGate { .collect() } - fn generators(&self, _row: usize, _local_constants: &[F]) -> Vec>> { + fn generators(&self, _row: usize, _local_constants: &[F]) -> Vec> { vec![] } diff --git a/plonky2/src/gates/coset_interpolation.rs b/plonky2/src/gates/coset_interpolation.rs index da94d1c0..ff6d9918 100644 --- a/plonky2/src/gates/coset_interpolation.rs +++ b/plonky2/src/gates/coset_interpolation.rs @@ -1,4 +1,3 @@ -use alloc::boxed::Box; use alloc::string::String; use alloc::vec::Vec; use alloc::{format, vec}; @@ -13,12 +12,13 @@ use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; use crate::iop::ext_target::{ExtensionAlgebraTarget, ExtensionTarget}; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef}; use crate::iop::target::Target; use crate::iop::wire::Wire; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; +use crate::util::serialization::{Buffer, IoResult, Read, Write}; /// One of the instantiations of `InterpolationGate`: allows constraints of variable /// degree, up to `1<, const D: usize> { pub subgroup_bits: usize, pub degree: usize, @@ -168,6 +168,26 @@ impl, const D: usize> Gate for CosetInterpola format!("{self:?}") } + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_usize(self.subgroup_bits)?; + dst.write_usize(self.degree)?; + dst.write_usize(self.barycentric_weights.len())?; + dst.write_field_vec(&self.barycentric_weights) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let subgroup_bits = src.read_usize()?; + let degree = src.read_usize()?; + let length = src.read_usize()?; + let barycentric_weights: Vec = src.read_field_vec(length)?; + Ok(Self { + subgroup_bits, + degree, + barycentric_weights, + _phantom: PhantomData, + }) + } + fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { let mut constraints = Vec::with_capacity(self.num_constraints()); @@ -342,9 +362,9 @@ impl, const D: usize> Gate for CosetInterpola constraints } - fn generators(&self, row: usize, _local_constants: &[F]) -> Vec>> { + fn generators(&self, row: usize, _local_constants: &[F]) -> Vec> { let gen = InterpolationGenerator::::new(row, self.clone()); - vec![Box::new(gen.adapter())] + vec![WitnessGeneratorRef::new(gen.adapter())] } fn num_wires(&self) -> usize { @@ -366,8 +386,8 @@ impl, const D: usize> Gate for CosetInterpola } } -#[derive(Debug)] -struct InterpolationGenerator, const D: usize> { +#[derive(Debug, Default)] +pub struct InterpolationGenerator, const D: usize> { row: usize, gate: CosetInterpolationGate, interpolation_domain: Vec, @@ -389,6 +409,10 @@ impl, const D: usize> InterpolationGenerator impl, const D: usize> SimpleGenerator for InterpolationGenerator { + fn id(&self) -> String { + "InterpolationGenerator".to_string() + } + fn dependencies(&self) -> Vec { let local_target = |column| { Target::Wire(Wire { @@ -471,6 +495,17 @@ impl, const D: usize> SimpleGenerator let evaluation_value_wires = self.gate.wires_evaluation_value().map(local_wire); out_buffer.set_ext_wires(evaluation_value_wires, computed_eval); } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_usize(self.row)?; + self.gate.serialize(dst) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let row = src.read_usize()?; + let gate = CosetInterpolationGate::deserialize(src)?; + Ok(Self::new(row, gate)) + } } /// Interpolate the polynomial defined by its values on an arbitrary domain at the given point `x`. diff --git a/plonky2/src/gates/exponentiation.rs b/plonky2/src/gates/exponentiation.rs index 218f77e8..eefc7ba7 100644 --- a/plonky2/src/gates/exponentiation.rs +++ b/plonky2/src/gates/exponentiation.rs @@ -1,4 +1,3 @@ -use alloc::boxed::Box; use alloc::string::String; use alloc::vec::Vec; use alloc::{format, vec}; @@ -13,7 +12,7 @@ use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef}; use crate::iop::target::Target; use crate::iop::wire::Wire; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; @@ -23,9 +22,10 @@ use crate::plonk::vars::{ EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, EvaluationVarsBasePacked, }; +use crate::util::serialization::{Buffer, IoResult, Read, Write}; /// A gate for raising a value to a power. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Default)] pub struct ExponentiationGate, const D: usize> { pub num_power_bits: usize, pub _phantom: PhantomData, @@ -76,6 +76,15 @@ impl, const D: usize> Gate for Exponentiation format!("{self:?}") } + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_usize(self.num_power_bits) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let num_power_bits = src.read_usize()?; + Ok(Self::new(num_power_bits)) + } + fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { let base = vars.local_wires[self.wire_base()]; @@ -164,12 +173,12 @@ impl, const D: usize> Gate for Exponentiation constraints } - fn generators(&self, row: usize, _local_constants: &[F]) -> Vec>> { + fn generators(&self, row: usize, _local_constants: &[F]) -> Vec> { let gen = ExponentiationGenerator:: { row, gate: self.clone(), }; - vec![Box::new(gen.adapter())] + vec![WitnessGeneratorRef::new(gen.adapter())] } fn num_wires(&self) -> usize { @@ -228,8 +237,8 @@ impl, const D: usize> PackedEvaluableBase } } -#[derive(Debug)] -struct ExponentiationGenerator, const D: usize> { +#[derive(Debug, Default)] +pub struct ExponentiationGenerator, const D: usize> { row: usize, gate: ExponentiationGate, } @@ -237,6 +246,10 @@ struct ExponentiationGenerator, const D: usize> { impl, const D: usize> SimpleGenerator for ExponentiationGenerator { + fn id(&self) -> String { + "ExponentiationGenerator".to_string() + } + fn dependencies(&self) -> Vec { let local_target = |column| Target::wire(self.row, column); @@ -281,6 +294,17 @@ impl, const D: usize> SimpleGenerator let output_wire = local_wire(self.gate.wire_output()); out_buffer.set_wire(output_wire, intermediate_values[num_power_bits - 1]); } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_usize(self.row)?; + self.gate.serialize(dst) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let row = src.read_usize()?; + let gate = ExponentiationGate::deserialize(src)?; + Ok(Self { row, gate }) + } } #[cfg(test)] diff --git a/plonky2/src/gates/gate.rs b/plonky2/src/gates/gate.rs index 34950b76..1dbc4f57 100644 --- a/plonky2/src/gates/gate.rs +++ b/plonky2/src/gates/gate.rs @@ -1,13 +1,14 @@ -use alloc::boxed::Box; use alloc::string::String; use alloc::sync::Arc; use alloc::vec; use alloc::vec::Vec; +use core::any::Any; use core::fmt::{Debug, Error, Formatter}; use core::hash::{Hash, Hasher}; use core::ops::Range; use hashbrown::HashMap; +use serde::{Serialize, Serializer}; use crate::field::batch_util::batch_multiply_inplace; use crate::field::extension::{Extendable, FieldExtension}; @@ -16,16 +17,23 @@ use crate::gates::selectors::UNUSED_SELECTOR; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; -use crate::iop::generator::WitnessGenerator; +use crate::iop::generator::WitnessGeneratorRef; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{ EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, }; +use crate::util::serialization::{Buffer, IoResult}; /// A custom gate. pub trait Gate, const D: usize>: 'static + Send + Sync { fn id(&self) -> String; + fn serialize(&self, dst: &mut Vec) -> IoResult<()>; + + fn deserialize(src: &mut Buffer) -> IoResult + where + Self: Sized; + fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec; /// Like `eval_unfiltered`, but specialized for points in the base field. @@ -162,7 +170,7 @@ pub trait Gate, const D: usize>: 'static + Send + S /// The generators used to populate the witness. /// Note: This should return exactly 1 generator per operation in the gate. - fn generators(&self, row: usize, local_constants: &[F]) -> Vec>>; + fn generators(&self, row: usize, local_constants: &[F]) -> Vec>; /// The number of wires used by this gate. fn num_wires(&self) -> usize; @@ -191,9 +199,20 @@ pub trait Gate, const D: usize>: 'static + Send + S } } -/// A wrapper around an `Rc` which implements `PartialEq`, `Eq` and `Hash` based on gate IDs. +/// A wrapper trait over a `Gate`, to allow for gate serialization. +pub trait AnyGate, const D: usize>: Gate { + fn as_any(&self) -> &dyn Any; +} + +impl, F: RichField + Extendable, const D: usize> AnyGate for T { + fn as_any(&self) -> &dyn Any { + self + } +} + +/// A wrapper around an `Arc` which implements `PartialEq`, `Eq` and `Hash` based on gate IDs. #[derive(Clone)] -pub struct GateRef, const D: usize>(pub(crate) Arc>); +pub struct GateRef, const D: usize>(pub(crate) Arc>); impl, const D: usize> GateRef { pub fn new>(gate: G) -> GateRef { @@ -221,6 +240,12 @@ impl, const D: usize> Debug for GateRef { } } +impl, const D: usize> Serialize for GateRef { + fn serialize(&self, serializer: S) -> Result { + serializer.serialize_str(&self.0.id()) + } +} + /// Map between gate parameters and available slots. /// An available slot is of the form `(row, op)`, meaning the current available slot /// is at gate index `row` in the `op`-th operation. diff --git a/plonky2/src/gates/multiplication_extension.rs b/plonky2/src/gates/multiplication_extension.rs index 1f900441..7e1c1924 100644 --- a/plonky2/src/gates/multiplication_extension.rs +++ b/plonky2/src/gates/multiplication_extension.rs @@ -1,4 +1,3 @@ -use alloc::boxed::Box; use alloc::format; use alloc::string::String; use alloc::vec::Vec; @@ -9,12 +8,13 @@ use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef}; use crate::iop::target::Target; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::CircuitConfig; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; +use crate::util::serialization::{Buffer, IoResult, Read, Write}; /// A gate which can perform a weighted multiplication, i.e. `result = c0 x y`. If the config /// supports enough routed wires, it can support several such operations in one gate. @@ -53,6 +53,15 @@ impl, const D: usize> Gate for MulExtensionGa format!("{self:?}") } + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_usize(self.num_ops) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let num_ops = src.read_usize()?; + Ok(Self { num_ops }) + } + fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { let const_0 = vars.local_constants[0]; @@ -110,18 +119,17 @@ impl, const D: usize> Gate for MulExtensionGa constraints } - fn generators(&self, row: usize, local_constants: &[F]) -> Vec>> { + fn generators(&self, row: usize, local_constants: &[F]) -> Vec> { (0..self.num_ops) .map(|i| { - let g: Box> = Box::new( + WitnessGeneratorRef::new( MulExtensionGenerator { row, const_0: local_constants[0], i, } .adapter(), - ); - g + ) }) .collect() } @@ -143,8 +151,8 @@ impl, const D: usize> Gate for MulExtensionGa } } -#[derive(Clone, Debug)] -struct MulExtensionGenerator, const D: usize> { +#[derive(Clone, Debug, Default)] +pub struct MulExtensionGenerator, const D: usize> { row: usize, const_0: F, i: usize, @@ -153,6 +161,10 @@ struct MulExtensionGenerator, const D: usize> { impl, const D: usize> SimpleGenerator for MulExtensionGenerator { + fn id(&self) -> String { + "MulExtensionGenerator".to_string() + } + fn dependencies(&self) -> Vec { MulExtensionGate::::wires_ith_multiplicand_0(self.i) .chain(MulExtensionGate::::wires_ith_multiplicand_1(self.i)) @@ -178,6 +190,19 @@ impl, const D: usize> SimpleGenerator out_buffer.set_extension_target(output_target, computed_output) } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_usize(self.row)?; + dst.write_field(self.const_0)?; + dst.write_usize(self.i) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let row = src.read_usize()?; + let const_0 = src.read_field()?; + let i = src.read_usize()?; + Ok(Self { row, const_0, i }) + } } #[cfg(test)] diff --git a/plonky2/src/gates/noop.rs b/plonky2/src/gates/noop.rs index f6f9853a..cfcfb912 100644 --- a/plonky2/src/gates/noop.rs +++ b/plonky2/src/gates/noop.rs @@ -1,4 +1,3 @@ -use alloc::boxed::Box; use alloc::string::String; use alloc::vec::Vec; @@ -6,9 +5,10 @@ use crate::field::extension::Extendable; use crate::gates::gate::Gate; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; -use crate::iop::generator::WitnessGenerator; +use crate::iop::generator::WitnessGeneratorRef; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBaseBatch}; +use crate::util::serialization::{Buffer, IoResult}; /// A gate which does nothing. pub struct NoopGate; @@ -18,6 +18,14 @@ impl, const D: usize> Gate for NoopGate { "NoopGate".into() } + fn serialize(&self, _dst: &mut Vec) -> IoResult<()> { + Ok(()) + } + + fn deserialize(_src: &mut Buffer) -> IoResult { + Ok(Self) + } + fn eval_unfiltered(&self, _vars: EvaluationVars) -> Vec { Vec::new() } @@ -34,7 +42,7 @@ impl, const D: usize> Gate for NoopGate { Vec::new() } - fn generators(&self, _row: usize, _local_constants: &[F]) -> Vec>> { + fn generators(&self, _row: usize, _local_constants: &[F]) -> Vec> { Vec::new() } diff --git a/plonky2/src/gates/poseidon.rs b/plonky2/src/gates/poseidon.rs index 80184797..caab7faf 100644 --- a/plonky2/src/gates/poseidon.rs +++ b/plonky2/src/gates/poseidon.rs @@ -1,4 +1,3 @@ -use alloc::boxed::Box; use alloc::string::String; use alloc::vec::Vec; use alloc::{format, vec}; @@ -13,12 +12,13 @@ use crate::hash::hash_types::RichField; use crate::hash::poseidon; use crate::hash::poseidon::{Poseidon, SPONGE_WIDTH}; use crate::iop::ext_target::ExtensionTarget; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef}; use crate::iop::target::Target; use crate::iop::wire::Wire; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; +use crate::util::serialization::{Buffer, IoResult, Read, Write}; /// Evaluates a full Poseidon permutation with 12 state elements. /// @@ -99,6 +99,14 @@ impl, const D: usize> Gate for PoseidonGate") } + fn serialize(&self, _dst: &mut Vec) -> IoResult<()> { + Ok(()) + } + + fn deserialize(_src: &mut Buffer) -> IoResult { + Ok(PoseidonGate::new()) + } + fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { let mut constraints = Vec::with_capacity(self.num_constraints()); @@ -372,12 +380,12 @@ impl, const D: usize> Gate for PoseidonGate Vec>> { + fn generators(&self, row: usize, _local_constants: &[F]) -> Vec> { let gen = PoseidonGenerator:: { row, _phantom: PhantomData, }; - vec![Box::new(gen.adapter())] + vec![WitnessGeneratorRef::new(gen.adapter())] } fn num_wires(&self) -> usize { @@ -401,8 +409,8 @@ impl, const D: usize> Gate for PoseidonGate + Poseidon, const D: usize> { +#[derive(Debug, Default)] +pub struct PoseidonGenerator + Poseidon, const D: usize> { row: usize, _phantom: PhantomData, } @@ -410,6 +418,10 @@ struct PoseidonGenerator + Poseidon, const D: usize impl + Poseidon, const D: usize> SimpleGenerator for PoseidonGenerator { + fn id(&self) -> String { + "PoseidonGenerator".to_string() + } + fn dependencies(&self) -> Vec { (0..SPONGE_WIDTH) .map(|i| PoseidonGate::::wire_input(i)) @@ -499,6 +511,18 @@ impl + Poseidon, const D: usize> SimpleGenerator out_buffer.set_wire(local_wire(PoseidonGate::::wire_output(i)), state[i]); } } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_usize(self.row) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let row = src.read_usize()?; + Ok(Self { + row, + _phantom: PhantomData, + }) + } } #[cfg(test)] diff --git a/plonky2/src/gates/poseidon_mds.rs b/plonky2/src/gates/poseidon_mds.rs index cddd0f9e..a3b4c927 100644 --- a/plonky2/src/gates/poseidon_mds.rs +++ b/plonky2/src/gates/poseidon_mds.rs @@ -1,4 +1,3 @@ -use alloc::boxed::Box; use alloc::string::String; use alloc::vec::Vec; use alloc::{format, vec}; @@ -13,11 +12,12 @@ use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; use crate::hash::poseidon::{Poseidon, SPONGE_WIDTH}; use crate::iop::ext_target::{ExtensionAlgebraTarget, ExtensionTarget}; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef}; use crate::iop::target::Target; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; +use crate::util::serialization::{Buffer, IoResult, Read, Write}; /// Poseidon MDS Gate #[derive(Debug, Default)] @@ -118,6 +118,14 @@ impl + Poseidon, const D: usize> Gate for Pos format!("{self:?}") } + fn serialize(&self, _dst: &mut Vec) -> IoResult<()> { + Ok(()) + } + + fn deserialize(_src: &mut Buffer) -> IoResult { + Ok(PoseidonMdsGate::new()) + } + fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { let inputs: [_; SPONGE_WIDTH] = (0..SPONGE_WIDTH) .map(|i| vars.get_local_ext_algebra(Self::wires_input(i))) @@ -179,9 +187,9 @@ impl + Poseidon, const D: usize> Gate for Pos .collect() } - fn generators(&self, row: usize, _local_constants: &[F]) -> Vec>> { + fn generators(&self, row: usize, _local_constants: &[F]) -> Vec> { let gen = PoseidonMdsGenerator:: { row }; - vec![Box::new(gen.adapter())] + vec![WitnessGeneratorRef::new(gen.adapter())] } fn num_wires(&self) -> usize { @@ -201,14 +209,18 @@ impl + Poseidon, const D: usize> Gate for Pos } } -#[derive(Clone, Debug)] -struct PoseidonMdsGenerator { +#[derive(Clone, Debug, Default)] +pub struct PoseidonMdsGenerator { row: usize, } impl + Poseidon, const D: usize> SimpleGenerator for PoseidonMdsGenerator { + fn id(&self) -> String { + "PoseidonMdsGenerator".to_string() + } + fn dependencies(&self) -> Vec { (0..SPONGE_WIDTH) .flat_map(|i| { @@ -237,6 +249,15 @@ impl + Poseidon, const D: usize> SimpleGenerator ); } } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_usize(self.row) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let row = src.read_usize()?; + Ok(Self { row }) + } } #[cfg(test)] diff --git a/plonky2/src/gates/public_input.rs b/plonky2/src/gates/public_input.rs index 10c42f00..2c3e2428 100644 --- a/plonky2/src/gates/public_input.rs +++ b/plonky2/src/gates/public_input.rs @@ -1,4 +1,3 @@ -use alloc::boxed::Box; use alloc::string::String; use alloc::vec::Vec; use core::ops::Range; @@ -10,12 +9,13 @@ use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; -use crate::iop::generator::WitnessGenerator; +use crate::iop::generator::WitnessGeneratorRef; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{ EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, EvaluationVarsBasePacked, }; +use crate::util::serialization::{Buffer, IoResult}; /// A gate whose first four wires will be equal to a hash of public inputs. pub struct PublicInputGate; @@ -31,6 +31,14 @@ impl, const D: usize> Gate for PublicInputGat "PublicInputGate".into() } + fn serialize(&self, _dst: &mut Vec) -> IoResult<()> { + Ok(()) + } + + fn deserialize(_src: &mut Buffer) -> IoResult { + Ok(Self) + } + fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { Self::wires_public_inputs_hash() .zip(vars.public_inputs_hash.elements) @@ -64,7 +72,7 @@ impl, const D: usize> Gate for PublicInputGat .collect() } - fn generators(&self, _row: usize, _local_constants: &[F]) -> Vec>> { + fn generators(&self, _row: usize, _local_constants: &[F]) -> Vec> { Vec::new() } diff --git a/plonky2/src/gates/random_access.rs b/plonky2/src/gates/random_access.rs index 80874505..7f651bab 100644 --- a/plonky2/src/gates/random_access.rs +++ b/plonky2/src/gates/random_access.rs @@ -1,4 +1,3 @@ -use alloc::boxed::Box; use alloc::string::String; use alloc::vec::Vec; use alloc::{format, vec}; @@ -14,7 +13,7 @@ use crate::gates::packed_util::PackedEvaluableBase; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef}; use crate::iop::target::Target; use crate::iop::wire::Wire; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; @@ -24,9 +23,10 @@ use crate::plonk::vars::{ EvaluationTargets, EvaluationVars, EvaluationVarsBase, EvaluationVarsBaseBatch, EvaluationVarsBasePacked, }; +use crate::util::serialization::{Buffer, IoResult, Read, Write}; /// A gate for checking that a particular element of a list matches a given value. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Default)] pub struct RandomAccessGate, const D: usize> { /// Number of bits in the index (log2 of the list size). pub bits: usize, @@ -122,6 +122,20 @@ impl, const D: usize> Gate for RandomAccessGa format!("{self:?}") } + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_usize(self.bits)?; + dst.write_usize(self.num_copies)?; + dst.write_usize(self.num_extra_constants)?; + Ok(()) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let bits = src.read_usize()?; + let num_copies = src.read_usize()?; + let num_extra_constants = src.read_usize()?; + Ok(Self::new(num_copies, bits, num_extra_constants)) + } + fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { let mut constraints = Vec::with_capacity(self.num_constraints()); @@ -238,18 +252,17 @@ impl, const D: usize> Gate for RandomAccessGa constraints } - fn generators(&self, row: usize, _local_constants: &[F]) -> Vec>> { + fn generators(&self, row: usize, _local_constants: &[F]) -> Vec> { (0..self.num_copies) .map(|copy| { - let g: Box> = Box::new( + WitnessGeneratorRef::new( RandomAccessGenerator { row, gate: *self, copy, } .adapter(), - ); - g + ) }) .collect() } @@ -325,8 +338,8 @@ impl, const D: usize> PackedEvaluableBase } } -#[derive(Debug)] -struct RandomAccessGenerator, const D: usize> { +#[derive(Debug, Default)] +pub struct RandomAccessGenerator, const D: usize> { row: usize, gate: RandomAccessGate, copy: usize, @@ -335,6 +348,10 @@ struct RandomAccessGenerator, const D: usize> { impl, const D: usize> SimpleGenerator for RandomAccessGenerator { + fn id(&self) -> String { + "RandomAccessGenerator".to_string() + } + fn dependencies(&self) -> Vec { let local_target = |column| Target::wire(self.row, column); @@ -376,6 +393,19 @@ impl, const D: usize> SimpleGenerator set_local_wire(self.gate.wire_bit(i, copy), bit); } } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_usize(self.row)?; + dst.write_usize(self.copy)?; + self.gate.serialize(dst) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let row = src.read_usize()?; + let copy = src.read_usize()?; + let gate = RandomAccessGate::::deserialize(src)?; + Ok(Self { row, gate, copy }) + } } #[cfg(test)] diff --git a/plonky2/src/gates/reducing.rs b/plonky2/src/gates/reducing.rs index 9bdadce8..b9bd025a 100644 --- a/plonky2/src/gates/reducing.rs +++ b/plonky2/src/gates/reducing.rs @@ -1,4 +1,3 @@ -use alloc::boxed::Box; use alloc::string::String; use alloc::vec::Vec; use alloc::{format, vec}; @@ -9,14 +8,15 @@ use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef}; use crate::iop::target::Target; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; +use crate::util::serialization::{Buffer, IoResult, Read, Write}; /// Computes `sum alpha^i c_i` for a vector `c_i` of `num_coeffs` elements of the base field. -#[derive(Debug, Clone)] +#[derive(Debug, Default, Clone)] pub struct ReducingGate { pub num_coeffs: usize, } @@ -60,6 +60,19 @@ impl, const D: usize> Gate for ReducingGate) -> IoResult<()> { + dst.write_usize(self.num_coeffs)?; + Ok(()) + } + + fn deserialize(src: &mut Buffer) -> IoResult + where + Self: Sized, + { + let num_coeffs = src.read_usize()?; + Ok(Self::new(num_coeffs)) + } + fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { let alpha = vars.get_local_ext_algebra(Self::wires_alpha()); let old_acc = vars.get_local_ext_algebra(Self::wires_old_acc()); @@ -137,8 +150,8 @@ impl, const D: usize> Gate for ReducingGate Vec>> { - vec![Box::new( + fn generators(&self, row: usize, _local_constants: &[F]) -> Vec> { + vec![WitnessGeneratorRef::new( ReducingGenerator { row, gate: self.clone(), @@ -164,13 +177,17 @@ impl, const D: usize> Gate for ReducingGate { +#[derive(Debug, Default)] +pub struct ReducingGenerator { row: usize, gate: ReducingGate, } impl, const D: usize> SimpleGenerator for ReducingGenerator { + fn id(&self) -> String { + "ReducingGenerator".to_string() + } + fn dependencies(&self) -> Vec { ReducingGate::::wires_alpha() .chain(ReducingGate::::wires_old_acc()) @@ -207,6 +224,17 @@ impl, const D: usize> SimpleGenerator for Reduci } out_buffer.set_extension_target(output, acc); } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_usize(self.row)?; + as Gate>::serialize(&self.gate, dst) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let row = src.read_usize()?; + let gate = as Gate>::deserialize(src)?; + Ok(Self { row, gate }) + } } #[cfg(test)] diff --git a/plonky2/src/gates/reducing_extension.rs b/plonky2/src/gates/reducing_extension.rs index 0ad48bb0..11541ec2 100644 --- a/plonky2/src/gates/reducing_extension.rs +++ b/plonky2/src/gates/reducing_extension.rs @@ -1,4 +1,3 @@ -use alloc::boxed::Box; use alloc::string::String; use alloc::vec::Vec; use alloc::{format, vec}; @@ -9,14 +8,15 @@ use crate::gates::gate::Gate; use crate::gates::util::StridedConstraintConsumer; use crate::hash::hash_types::RichField; use crate::iop::ext_target::ExtensionTarget; -use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGenerator}; +use crate::iop::generator::{GeneratedValues, SimpleGenerator, WitnessGeneratorRef}; use crate::iop::target::Target; use crate::iop::witness::{PartitionWitness, Witness, WitnessWrite}; use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::vars::{EvaluationTargets, EvaluationVars, EvaluationVarsBase}; +use crate::util::serialization::{Buffer, IoResult, Read, Write}; /// Computes `sum alpha^i c_i` for a vector `c_i` of `num_coeffs` elements of the extension field. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default)] pub struct ReducingExtensionGate { pub num_coeffs: usize, } @@ -63,6 +63,19 @@ impl, const D: usize> Gate for ReducingExtens format!("{self:?}") } + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_usize(self.num_coeffs)?; + Ok(()) + } + + fn deserialize(src: &mut Buffer) -> IoResult + where + Self: Sized, + { + let num_coeffs = src.read_usize()?; + Ok(Self::new(num_coeffs)) + } + fn eval_unfiltered(&self, vars: EvaluationVars) -> Vec { let alpha = vars.get_local_ext_algebra(Self::wires_alpha()); let old_acc = vars.get_local_ext_algebra(Self::wires_old_acc()); @@ -137,8 +150,8 @@ impl, const D: usize> Gate for ReducingExtens .collect() } - fn generators(&self, row: usize, _local_constants: &[F]) -> Vec>> { - vec![Box::new( + fn generators(&self, row: usize, _local_constants: &[F]) -> Vec> { + vec![WitnessGeneratorRef::new( ReducingGenerator { row, gate: self.clone(), @@ -164,13 +177,17 @@ impl, const D: usize> Gate for ReducingExtens } } -#[derive(Debug)] -struct ReducingGenerator { +#[derive(Debug, Default)] +pub struct ReducingGenerator { row: usize, gate: ReducingExtensionGate, } impl, const D: usize> SimpleGenerator for ReducingGenerator { + fn id(&self) -> String { + "ReducingExtensionGenerator".to_string() + } + fn dependencies(&self) -> Vec { ReducingExtensionGate::::wires_alpha() .chain(ReducingExtensionGate::::wires_old_acc()) @@ -201,6 +218,17 @@ impl, const D: usize> SimpleGenerator for Reduci acc = computed_acc; } } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_usize(self.row)?; + as Gate>::serialize(&self.gate, dst) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let row = src.read_usize()?; + let gate = as Gate>::deserialize(src)?; + Ok(Self { row, gate }) + } } #[cfg(test)] diff --git a/plonky2/src/gates/selectors.rs b/plonky2/src/gates/selectors.rs index 7217de2f..0e690c6d 100644 --- a/plonky2/src/gates/selectors.rs +++ b/plonky2/src/gates/selectors.rs @@ -2,6 +2,8 @@ use alloc::vec; use alloc::vec::Vec; use core::ops::Range; +use serde::Serialize; + use crate::field::extension::Extendable; use crate::field::polynomial::PolynomialValues; use crate::gates::gate::{GateInstance, GateRef}; @@ -10,7 +12,7 @@ use crate::hash::hash_types::RichField; /// Placeholder value to indicate that a gate doesn't use a selector polynomial. pub(crate) const UNUSED_SELECTOR: usize = u32::MAX as usize; -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, Serialize)] pub struct SelectorsInfo { pub(crate) selector_indices: Vec, pub(crate) groups: Vec>, diff --git a/plonky2/src/hash/hash_types.rs b/plonky2/src/hash/hash_types.rs index c725c45c..c16092a8 100644 --- a/plonky2/src/hash/hash_types.rs +++ b/plonky2/src/hash/hash_types.rs @@ -110,7 +110,7 @@ impl Default for HashOut { } /// Represents a ~256 bit hash output. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct HashOutTarget { pub elements: [Target; 4], } @@ -148,7 +148,7 @@ impl TryFrom<&[Target]> for HashOutTarget { } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct MerkleCapTarget(pub Vec); /// Hash consisting of a byte array. diff --git a/plonky2/src/hash/merkle_proofs.rs b/plonky2/src/hash/merkle_proofs.rs index 3d523312..240e6cd2 100644 --- a/plonky2/src/hash/merkle_proofs.rs +++ b/plonky2/src/hash/merkle_proofs.rs @@ -31,7 +31,7 @@ impl> MerkleProof { } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct MerkleProofTarget { /// The Merkle digest of each sibling subtree, staying from the bottommost layer. pub siblings: Vec, diff --git a/plonky2/src/hash/merkle_tree.rs b/plonky2/src/hash/merkle_tree.rs index f49d9f19..67fe7968 100644 --- a/plonky2/src/hash/merkle_tree.rs +++ b/plonky2/src/hash/merkle_tree.rs @@ -36,7 +36,7 @@ impl> MerkleCap { } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct MerkleTree> { /// The data in the leaves of the Merkle tree. pub leaves: Vec>, diff --git a/plonky2/src/iop/ext_target.rs b/plonky2/src/iop/ext_target.rs index 08bdcba0..21eb3e55 100644 --- a/plonky2/src/iop/ext_target.rs +++ b/plonky2/src/iop/ext_target.rs @@ -12,6 +12,12 @@ use crate::plonk::circuit_builder::CircuitBuilder; #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct ExtensionTarget(pub [Target; D]); +impl Default for ExtensionTarget { + fn default() -> Self { + Self([Target::default(); D]) + } +} + impl ExtensionTarget { pub fn to_target_array(&self) -> [Target; D] { self.0 diff --git a/plonky2/src/iop/generator.rs b/plonky2/src/iop/generator.rs index a65d1748..16a23e26 100644 --- a/plonky2/src/iop/generator.rs +++ b/plonky2/src/iop/generator.rs @@ -12,6 +12,7 @@ use crate::iop::wire::Wire; use crate::iop::witness::{PartialWitness, PartitionWitness, Witness, WitnessWrite}; use crate::plonk::circuit_data::{CommonCircuitData, ProverOnlyCircuitData}; use crate::plonk::config::GenericConfig; +use crate::util::serialization::{Buffer, IoResult, Read, Write}; /// Given a `PartitionWitness` that has only inputs set, populates the rest of the witness using the /// given set of generators. @@ -58,7 +59,7 @@ pub(crate) fn generate_partial_witness< continue; } - let finished = generators[generator_idx].run(&witness, &mut buffer); + let finished = generators[generator_idx].0.run(&witness, &mut buffer); if finished { generator_is_expired[generator_idx] = true; remaining_generators -= 1; @@ -98,6 +99,8 @@ pub(crate) fn generate_partial_witness< /// A generator participates in the generation of the witness. pub trait WitnessGenerator: 'static + Send + Sync + Debug { + fn id(&self) -> String; + /// Targets to be "watched" by this generator. Whenever a target in the watch list is populated, /// the generator will be queued to run. fn watch_list(&self) -> Vec; @@ -106,6 +109,36 @@ pub trait WitnessGenerator: 'static + Send + Sync + Debug { /// flag is true, the generator will never be run again, otherwise it will be queued for another /// run next time a target in its watch list is populated. fn run(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues) -> bool; + + fn serialize(&self, dst: &mut Vec) -> IoResult<()>; + + fn deserialize(src: &mut Buffer) -> IoResult + where + Self: Sized; +} + +/// A wrapper around an `Box` which implements `PartialEq` +/// and `Eq` based on generator IDs. +pub struct WitnessGeneratorRef(pub Box>); + +impl WitnessGeneratorRef { + pub fn new>(generator: G) -> WitnessGeneratorRef { + WitnessGeneratorRef(Box::new(generator)) + } +} + +impl PartialEq for WitnessGeneratorRef { + fn eq(&self, other: &Self) -> bool { + self.0.id() == other.0.id() + } +} + +impl Eq for WitnessGeneratorRef {} + +impl Debug for WitnessGeneratorRef { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.0.id()) + } } /// Values generated by a generator invocation. @@ -158,6 +191,8 @@ impl GeneratedValues { /// A generator which runs once after a list of dependencies is present in the witness. pub trait SimpleGenerator: 'static + Send + Sync + Debug { + fn id(&self) -> String; + fn dependencies(&self) -> Vec; fn run_once(&self, witness: &PartitionWitness, out_buffer: &mut GeneratedValues); @@ -171,6 +206,12 @@ pub trait SimpleGenerator: 'static + Send + Sync + Debug { _phantom: PhantomData, } } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()>; + + fn deserialize(src: &mut Buffer) -> IoResult + where + Self: Sized; } #[derive(Debug)] @@ -180,6 +221,10 @@ pub struct SimpleGeneratorAdapter + ?Sized> { } impl> WitnessGenerator for SimpleGeneratorAdapter { + fn id(&self) -> String { + self.inner.id() + } + fn watch_list(&self) -> Vec { self.inner.dependencies() } @@ -192,16 +237,31 @@ impl> WitnessGenerator for SimpleGeneratorAd false } } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + self.inner.serialize(dst) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + Ok(Self { + inner: SG::deserialize(src)?, + _phantom: PhantomData, + }) + } } /// A generator which copies one wire to another. -#[derive(Debug)] -pub(crate) struct CopyGenerator { +#[derive(Debug, Default)] +pub struct CopyGenerator { pub(crate) src: Target, pub(crate) dst: Target, } impl SimpleGenerator for CopyGenerator { + fn id(&self) -> String { + "CopyGenerator".to_string() + } + fn dependencies(&self) -> Vec { vec![self.src] } @@ -210,15 +270,30 @@ impl SimpleGenerator for CopyGenerator { let value = witness.get_target(self.src); out_buffer.set_target(self.dst, value); } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_target(self.src)?; + dst.write_target(self.dst) + } + + fn deserialize(source: &mut Buffer) -> IoResult { + let src = source.read_target()?; + let dst = source.read_target()?; + Ok(Self { src, dst }) + } } /// A generator for including a random value -#[derive(Debug)] -pub(crate) struct RandomValueGenerator { +#[derive(Debug, Default)] +pub struct RandomValueGenerator { pub(crate) target: Target, } impl SimpleGenerator for RandomValueGenerator { + fn id(&self) -> String { + "RandomValueGenerator".to_string() + } + fn dependencies(&self) -> Vec { Vec::new() } @@ -227,16 +302,29 @@ impl SimpleGenerator for RandomValueGenerator { let random_value = F::rand(); out_buffer.set_target(self.target, random_value); } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_target(self.target) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let target = src.read_target()?; + Ok(Self { target }) + } } /// A generator for testing if a value equals zero -#[derive(Debug)] -pub(crate) struct NonzeroTestGenerator { +#[derive(Debug, Default)] +pub struct NonzeroTestGenerator { pub(crate) to_test: Target, pub(crate) dummy: Target, } impl SimpleGenerator for NonzeroTestGenerator { + fn id(&self) -> String { + "NonzeroTestGenerator".to_string() + } + fn dependencies(&self) -> Vec { vec![self.to_test] } @@ -252,11 +340,22 @@ impl SimpleGenerator for NonzeroTestGenerator { out_buffer.set_target(self.dummy, dummy_value); } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_target(self.to_test)?; + dst.write_target(self.dummy) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let to_test = src.read_target()?; + let dummy = src.read_target()?; + Ok(Self { to_test, dummy }) + } } /// Generator used to fill an extra constant. -#[derive(Debug, Clone)] -pub(crate) struct ConstantGenerator { +#[derive(Debug, Clone, Default)] +pub struct ConstantGenerator { pub row: usize, pub constant_index: usize, pub wire_index: usize, @@ -269,7 +368,11 @@ impl ConstantGenerator { } } -impl SimpleGenerator for ConstantGenerator { +impl SimpleGenerator for ConstantGenerator { + fn id(&self) -> String { + "ConstantGenerator".to_string() + } + fn dependencies(&self) -> Vec { vec![] } @@ -277,4 +380,24 @@ impl SimpleGenerator for ConstantGenerator { fn run_once(&self, _witness: &PartitionWitness, out_buffer: &mut GeneratedValues) { out_buffer.set_target(Target::wire(self.row, self.wire_index), self.constant); } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_usize(self.row)?; + dst.write_usize(self.constant_index)?; + dst.write_usize(self.wire_index)?; + dst.write_field(self.constant) + } + + fn deserialize(src: &mut Buffer) -> IoResult { + let row = src.read_usize()?; + let constant_index = src.read_usize()?; + let wire_index = src.read_usize()?; + let constant = src.read_field()?; + Ok(Self { + row, + constant_index, + wire_index, + constant, + }) + } } diff --git a/plonky2/src/iop/target.rs b/plonky2/src/iop/target.rs index 15be6943..9f1ab96b 100644 --- a/plonky2/src/iop/target.rs +++ b/plonky2/src/iop/target.rs @@ -17,6 +17,12 @@ pub enum Target { }, } +impl Default for Target { + fn default() -> Self { + Self::VirtualTarget { index: 0 } + } +} + impl Target { pub fn wire(row: usize, column: usize) -> Self { Self::Wire(Wire { row, column }) @@ -49,7 +55,7 @@ impl Target { } /// A `Target` which has already been constrained such that it can only be 0 or 1. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] #[allow(clippy::manual_non_exhaustive)] pub struct BoolTarget { pub target: Target, diff --git a/plonky2/src/lib.rs b/plonky2/src/lib.rs index 17a7316d..4b7ebbbc 100644 --- a/plonky2/src/lib.rs +++ b/plonky2/src/lib.rs @@ -1,6 +1,7 @@ #![allow(clippy::too_many_arguments)] #![allow(clippy::needless_range_loop)] #![allow(clippy::upper_case_acronyms)] +#![allow(incomplete_features)] #![feature(generic_const_exprs)] #![cfg_attr(not(feature = "std"), no_std)] diff --git a/plonky2/src/plonk/circuit_builder.rs b/plonky2/src/plonk/circuit_builder.rs index 15c01ab0..851e23a8 100644 --- a/plonky2/src/plonk/circuit_builder.rs +++ b/plonky2/src/plonk/circuit_builder.rs @@ -1,4 +1,3 @@ -use alloc::boxed::Box; use alloc::collections::BTreeMap; use alloc::vec; use alloc::vec::Vec; @@ -33,7 +32,7 @@ use crate::hash::merkle_proofs::MerkleProofTarget; use crate::hash::merkle_tree::MerkleCap; use crate::iop::ext_target::ExtensionTarget; use crate::iop::generator::{ - ConstantGenerator, CopyGenerator, RandomValueGenerator, SimpleGenerator, WitnessGenerator, + ConstantGenerator, CopyGenerator, RandomValueGenerator, SimpleGenerator, WitnessGeneratorRef, }; use crate::iop::target::{BoolTarget, Target}; use crate::iop::wire::Wire; @@ -77,7 +76,7 @@ pub struct CircuitBuilder, const D: usize> { context_log: ContextTree, /// Generators used to generate the witness. - generators: Vec>>, + generators: Vec>, constants_to_targets: HashMap, targets_to_constants: HashMap, @@ -367,12 +366,13 @@ impl, const D: usize> CircuitBuilder { self.connect(x, one); } - pub fn add_generators(&mut self, generators: Vec>>) { + pub fn add_generators(&mut self, generators: Vec>) { self.generators.extend(generators); } pub fn add_simple_generator>(&mut self, generator: G) { - self.generators.push(Box::new(generator.adapter())); + self.generators + .push(WitnessGeneratorRef::new(generator.adapter())); } /// Returns a routable target with a value of 0. @@ -865,7 +865,7 @@ impl, const D: usize> CircuitBuilder { // Index generator indices by their watched targets. let mut generator_indices_by_watches = BTreeMap::new(); for (i, generator) in self.generators.iter().enumerate() { - for watch in generator.watch_list() { + for watch in generator.0.watch_list() { let watch_index = forest.target_index(watch); let watch_rep_index = forest.parents[watch_index]; generator_indices_by_watches diff --git a/plonky2/src/plonk/circuit_data.rs b/plonky2/src/plonk/circuit_data.rs index 2346b9db..8ecf646e 100644 --- a/plonky2/src/plonk/circuit_data.rs +++ b/plonky2/src/plonk/circuit_data.rs @@ -1,10 +1,10 @@ -use alloc::boxed::Box; use alloc::collections::BTreeMap; use alloc::vec; use alloc::vec::Vec; use core::ops::{Range, RangeFrom}; use anyhow::Result; +use serde::Serialize; use crate::field::extension::Extendable; use crate::field::fft::FftRootTable; @@ -22,7 +22,7 @@ use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget, RichField}; use crate::hash::hashing::HashConfig; use crate::hash::merkle_tree::MerkleCap; use crate::iop::ext_target::ExtensionTarget; -use crate::iop::generator::WitnessGenerator; +use crate::iop::generator::WitnessGeneratorRef; use crate::iop::target::Target; use crate::iop::witness::PartialWitness; use crate::plonk::circuit_builder::CircuitBuilder; @@ -31,9 +31,12 @@ use crate::plonk::plonk_common::PlonkOracle; use crate::plonk::proof::{CompressedProofWithPublicInputs, ProofWithPublicInputs}; use crate::plonk::prover::prove; use crate::plonk::verifier::verify; +use crate::util::serialization::{ + Buffer, GateSerializer, IoResult, Read, WitnessGeneratorSerializer, Write, +}; use crate::util::timing::TimingTree; -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct CircuitConfig { pub num_wires: usize, pub num_routed_wires: usize, @@ -107,6 +110,7 @@ impl CircuitConfig { } /// Circuit data required by the prover or the verifier. +#[derive(Eq, PartialEq, Debug)] pub struct CircuitData, C: GenericConfig, const D: usize> { pub prover_only: ProverOnlyCircuitData, pub verifier_only: VerifierOnlyCircuitData, @@ -116,6 +120,25 @@ pub struct CircuitData, C: GenericConfig, impl, C: GenericConfig, const D: usize> CircuitData { + pub fn to_bytes( + &self, + gate_serializer: &dyn GateSerializer, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult> { + let mut buffer = Vec::new(); + buffer.write_circuit_data(self, gate_serializer, generator_serializer)?; + Ok(buffer) + } + + pub fn from_bytes( + bytes: &[u8], + gate_serializer: &dyn GateSerializer, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult { + let mut buffer = Buffer::new(bytes.to_vec()); + buffer.read_circuit_data(gate_serializer, generator_serializer) + } + pub fn prove(&self, inputs: PartialWitness) -> Result> where [(); C::HCO::WIDTH]:, @@ -214,6 +237,25 @@ pub struct ProverCircuitData< impl, C: GenericConfig, const D: usize> ProverCircuitData { + pub fn to_bytes( + &self, + gate_serializer: &dyn GateSerializer, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult> { + let mut buffer = Vec::new(); + buffer.write_prover_circuit_data(self, gate_serializer, generator_serializer)?; + Ok(buffer) + } + + pub fn from_bytes( + bytes: &[u8], + gate_serializer: &dyn GateSerializer, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult { + let mut buffer = Buffer::new(bytes.to_vec()); + buffer.read_prover_circuit_data(gate_serializer, generator_serializer) + } + pub fn prove(&self, inputs: PartialWitness) -> Result> where [(); C::HCO::WIDTH]:, @@ -242,6 +284,20 @@ pub struct VerifierCircuitData< impl, C: GenericConfig, const D: usize> VerifierCircuitData { + pub fn to_bytes(&self, gate_serializer: &dyn GateSerializer) -> IoResult> { + let mut buffer = Vec::new(); + buffer.write_verifier_circuit_data(self, gate_serializer)?; + Ok(buffer) + } + + pub fn from_bytes( + bytes: Vec, + gate_serializer: &dyn GateSerializer, + ) -> IoResult { + let mut buffer = Buffer::new(bytes); + buffer.read_verifier_circuit_data(gate_serializer) + } + pub fn verify(&self, proof_with_pis: ProofWithPublicInputs) -> Result<()> where [(); C::HCO::WIDTH]:, @@ -263,12 +319,13 @@ impl, C: GenericConfig, const D: usize> } /// Circuit data required by the prover, but not the verifier. +#[derive(Eq, PartialEq, Debug)] pub struct ProverOnlyCircuitData< F: RichField + Extendable, C: GenericConfig, const D: usize, > { - pub generators: Vec>>, + pub generators: Vec>, /// Generator indices (within the `Vec` above), indexed by the representative of each target /// they watch. pub generator_indices_by_watches: BTreeMap>, @@ -291,7 +348,7 @@ pub struct ProverOnlyCircuitData< } /// Circuit data required by the verifier, but not the prover. -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, Serialize)] pub struct VerifierOnlyCircuitData, const D: usize> { /// A commitment to each constant polynomial and each permutation polynomial. pub constants_sigmas_cap: MerkleCap, @@ -300,8 +357,21 @@ pub struct VerifierOnlyCircuitData, const D: usize> { pub circuit_digest: <>::Hasher as Hasher>::Hash, } +impl, const D: usize> VerifierOnlyCircuitData { + pub fn to_bytes(&self) -> IoResult> { + let mut buffer = Vec::new(); + buffer.write_verifier_only_circuit_data(self)?; + Ok(buffer) + } + + pub fn from_bytes(bytes: Vec) -> IoResult { + let mut buffer = Buffer::new(bytes); + buffer.read_verifier_only_circuit_data() + } +} + /// Circuit data required by both the prover and the verifier. -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, Serialize)] pub struct CommonCircuitData, const D: usize> { pub config: CircuitConfig, @@ -332,6 +402,20 @@ pub struct CommonCircuitData, const D: usize> { } impl, const D: usize> CommonCircuitData { + pub fn to_bytes(&self, gate_serializer: &dyn GateSerializer) -> IoResult> { + let mut buffer = Vec::new(); + buffer.write_common_circuit_data(self, gate_serializer)?; + Ok(buffer) + } + + pub fn from_bytes( + bytes: Vec, + gate_serializer: &dyn GateSerializer, + ) -> IoResult { + let mut buffer = Buffer::new(bytes); + buffer.read_common_circuit_data(gate_serializer) + } + pub const fn degree_bits(&self) -> usize { self.fri_params.degree_bits } @@ -503,7 +587,7 @@ impl, const D: usize> CommonCircuitData { /// is intentionally missing certain fields, such as `CircuitConfig`, because we support only a /// limited form of dynamic inner circuits. We can't practically make things like the wire count /// dynamic, at least not without setting a maximum wire count and paying for the worst case. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct VerifierCircuitTarget { /// A commitment to each constant polynomial and each permutation polynomial. pub constants_sigmas_cap: MerkleCapTarget, diff --git a/plonky2/src/plonk/config.rs b/plonky2/src/plonk/config.rs index 60f9a7b8..a5fe5bdc 100644 --- a/plonky2/src/plonk/config.rs +++ b/plonky2/src/plonk/config.rs @@ -117,7 +117,7 @@ impl HashConfig for PoseidonHashConfig { const WIDTH: usize = 12; } /// Configuration using Poseidon over the Goldilocks field. -#[derive(Debug, Copy, Clone, Eq, PartialEq)] +#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize)] pub struct PoseidonGoldilocksConfig; impl GenericConfig<2> for PoseidonGoldilocksConfig { type F = GoldilocksField; diff --git a/plonky2/src/plonk/get_challenges.rs b/plonky2/src/plonk/get_challenges.rs index d0682572..0e90b398 100644 --- a/plonky2/src/plonk/get_challenges.rs +++ b/plonky2/src/plonk/get_challenges.rs @@ -94,7 +94,7 @@ impl, C: GenericConfig, const D: usize> } /// Computes all Fiat-Shamir challenges used in the Plonk proof. - pub(crate) fn get_challenges( + pub fn get_challenges( &self, public_inputs_hash: <>::InnerHasher as Hasher>::Hash, circuit_digest: &<>::Hasher as Hasher>::Hash, diff --git a/plonky2/src/plonk/proof.rs b/plonky2/src/plonk/proof.rs index 6332252f..fe4a0511 100644 --- a/plonky2/src/plonk/proof.rs +++ b/plonky2/src/plonk/proof.rs @@ -41,7 +41,7 @@ pub struct Proof, C: GenericConfig, const pub opening_proof: FriProof, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct ProofTarget { pub wires_cap: MerkleCapTarget, pub plonk_zs_partial_products_cap: MerkleCapTarget, @@ -102,7 +102,7 @@ impl, C: GenericConfig, const D: usize> }) } - pub(crate) fn get_public_inputs_hash( + pub fn get_public_inputs_hash( &self, ) -> <>::InnerHasher as Hasher>::Hash where @@ -276,7 +276,8 @@ impl, C: GenericConfig, const D: usize> } } -pub(crate) struct ProofChallenges, const D: usize> { +#[derive(Serialize)] +pub struct ProofChallenges, const D: usize> { /// Random values used in Plonk's permutation argument. pub plonk_betas: Vec, @@ -305,13 +306,13 @@ pub(crate) struct FriInferredElements, const D: usi pub Vec, ); -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct ProofWithPublicInputsTarget { pub proof: ProofTarget, pub public_inputs: Vec, } -#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +#[derive(Clone, Debug, Default, Serialize, Deserialize, Eq, PartialEq)] /// The purported values of each polynomial at a single point. pub struct OpeningSet, const D: usize> { pub constants: Vec, @@ -377,7 +378,7 @@ impl, const D: usize> OpeningSet { } /// The purported values of each polynomial at a single point. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct OpeningSetTarget { pub constants: Vec>, pub plonk_sigmas: Vec>, diff --git a/plonky2/src/recursion/cyclic_recursion.rs b/plonky2/src/recursion/cyclic_recursion.rs index c973ba60..7b584e4d 100644 --- a/plonky2/src/recursion/cyclic_recursion.rs +++ b/plonky2/src/recursion/cyclic_recursion.rs @@ -13,6 +13,7 @@ use crate::plonk::circuit_data::{ }; use crate::plonk::config::{AlgebraicHasher, GenericConfig}; use crate::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget}; +use crate::util::serialization::{Buffer, IoResult, Read, Write}; impl, const D: usize> VerifierOnlyCircuitData { fn from_slice(slice: &[C::F], common_data: &CommonCircuitData) -> Result @@ -41,6 +42,23 @@ impl, const D: usize> VerifierOnlyCircuitData { } impl VerifierCircuitTarget { + pub fn to_bytes(&self) -> IoResult> { + let mut buffer = Vec::new(); + buffer.write_target_merkle_cap(&self.constants_sigmas_cap)?; + buffer.write_target_hash(&self.circuit_digest)?; + Ok(buffer) + } + + pub fn from_bytes(bytes: Vec) -> IoResult { + let mut buffer = Buffer::new(bytes); + let constants_sigmas_cap = buffer.read_target_merkle_cap()?; + let circuit_digest = buffer.read_target_hash()?; + Ok(Self { + constants_sigmas_cap, + circuit_digest, + }) + } + fn from_slice, const D: usize>( slice: &[Target], common_data: &CommonCircuitData, diff --git a/plonky2/src/recursion/dummy_circuit.rs b/plonky2/src/recursion/dummy_circuit.rs index b0536b9c..79bfff15 100644 --- a/plonky2/src/recursion/dummy_circuit.rs +++ b/plonky2/src/recursion/dummy_circuit.rs @@ -3,11 +3,15 @@ use alloc::vec::Vec; use hashbrown::HashMap; use plonky2_field::extension::Extendable; +use plonky2_field::polynomial::PolynomialCoeffs; use plonky2_util::ceil_div_usize; +use crate::fri::proof::{FriProof, FriProofTarget}; +use crate::gadgets::polynomial::PolynomialCoeffsExtTarget; use crate::gates::noop::NoopGate; -use crate::hash::hash_types::RichField; +use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget, RichField}; use crate::hash::hashing::HashConfig; +use crate::hash::merkle_tree::MerkleCap; use crate::iop::generator::{GeneratedValues, SimpleGenerator}; use crate::iop::target::Target; use crate::iop::witness::{PartialWitness, PartitionWitness, WitnessWrite}; @@ -15,8 +19,12 @@ use crate::plonk::circuit_builder::CircuitBuilder; use crate::plonk::circuit_data::{ CircuitData, CommonCircuitData, VerifierCircuitTarget, VerifierOnlyCircuitData, }; -use crate::plonk::config::{AlgebraicHasher, GenericConfig}; -use crate::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget}; +use crate::plonk::config::{AlgebraicHasher, GenericConfig, GenericHashOut, Hasher}; +use crate::plonk::proof::{ + OpeningSet, OpeningSetTarget, Proof, ProofTarget, ProofWithPublicInputs, + ProofWithPublicInputsTarget, +}; +use crate::util::serialization::{Buffer, IoResult, Read, Write}; /// Creates a dummy proof which is suitable for use as a base proof in a cyclic recursion tree. /// Such a base proof will not actually be verified, so most of its data is arbitrary. However, its @@ -146,7 +154,7 @@ impl, const D: usize> CircuitBuilder { } #[derive(Debug)] -pub(crate) struct DummyProofGenerator +pub struct DummyProofGenerator where F: RichField + Extendable, C: GenericConfig, @@ -157,12 +165,101 @@ where pub(crate) verifier_data: VerifierOnlyCircuitData, } +impl Default for DummyProofGenerator +where + F: RichField + Extendable, + C: GenericConfig, +{ + fn default() -> Self { + let proof_with_pis_target = ProofWithPublicInputsTarget { + proof: ProofTarget { + wires_cap: MerkleCapTarget(vec![]), + plonk_zs_partial_products_cap: MerkleCapTarget(vec![]), + quotient_polys_cap: MerkleCapTarget(vec![]), + openings: OpeningSetTarget::default(), + opening_proof: FriProofTarget { + commit_phase_merkle_caps: vec![], + query_round_proofs: vec![], + final_poly: PolynomialCoeffsExtTarget(vec![]), + pow_witness: Target::default(), + }, + }, + public_inputs: vec![], + }; + + let proof_with_pis = ProofWithPublicInputs { + proof: Proof { + wires_cap: MerkleCap(vec![]), + plonk_zs_partial_products_cap: MerkleCap(vec![]), + quotient_polys_cap: MerkleCap(vec![]), + openings: OpeningSet::default(), + opening_proof: FriProof { + commit_phase_merkle_caps: vec![], + query_round_proofs: vec![], + final_poly: PolynomialCoeffs { coeffs: vec![] }, + pow_witness: F::ZERO, + }, + }, + public_inputs: vec![], + }; + + let verifier_data_target = VerifierCircuitTarget { + constants_sigmas_cap: MerkleCapTarget(vec![]), + circuit_digest: HashOutTarget { + elements: [Target::default(); 4], + }, + }; + + let verifier_data = VerifierOnlyCircuitData { + constants_sigmas_cap: MerkleCap(vec![]), + circuit_digest: + <>::Hasher as Hasher>::Hash::from_bytes( + &vec![0; <>::Hasher as Hasher>::HASH_SIZE], + ), + }; + + Self { + proof_with_pis_target, + proof_with_pis, + verifier_data_target, + verifier_data, + } + } +} + +impl DummyProofGenerator +where + F: RichField + Extendable, + C: GenericConfig + 'static, + C::Hasher: AlgebraicHasher, +{ + pub fn deserialize_with_circuit_data( + src: &mut Buffer, + cd: &CommonCircuitData, + ) -> IoResult { + let proof_with_pis_target = src.read_target_proof_with_public_inputs()?; + let proof_with_pis = src.read_proof_with_public_inputs(cd)?; + let verifier_data_target = src.read_target_verifier_circuit()?; + let verifier_data = src.read_verifier_only_circuit_data()?; + Ok(Self { + proof_with_pis_target, + proof_with_pis, + verifier_data_target, + verifier_data, + }) + } +} + impl SimpleGenerator for DummyProofGenerator where F: RichField + Extendable, C: GenericConfig + 'static, C::Hasher: AlgebraicHasher, { + fn id(&self) -> String { + "DummyProofGenerator".to_string() + } + fn dependencies(&self) -> Vec { vec![] } @@ -171,4 +268,15 @@ where out_buffer.set_proof_with_pis_target(&self.proof_with_pis_target, &self.proof_with_pis); out_buffer.set_verifier_data_target(&self.verifier_data_target, &self.verifier_data); } + + fn serialize(&self, dst: &mut Vec) -> IoResult<()> { + dst.write_target_proof_with_public_inputs(&self.proof_with_pis_target)?; + dst.write_proof_with_public_inputs(&self.proof_with_pis)?; + dst.write_target_verifier_circuit(&self.verifier_data_target)?; + dst.write_verifier_only_circuit_data(&self.verifier_data) + } + + fn deserialize(_src: &mut Buffer) -> IoResult { + panic!() + } } diff --git a/plonky2/src/util/mod.rs b/plonky2/src/util/mod.rs index 19f3cb74..dfc32fd8 100644 --- a/plonky2/src/util/mod.rs +++ b/plonky2/src/util/mod.rs @@ -9,7 +9,6 @@ use crate::field::types::Field; pub(crate) mod context_tree; pub(crate) mod partial_products; - pub mod reducing; pub mod serialization; pub mod strided_view; diff --git a/plonky2/src/util/serialization.rs b/plonky2/src/util/serialization.rs deleted file mode 100644 index 5ef93835..00000000 --- a/plonky2/src/util/serialization.rs +++ /dev/null @@ -1,835 +0,0 @@ -use alloc::vec; -use alloc::vec::Vec; -use core::convert::Infallible; -use core::fmt::{Debug, Display, Formatter}; -use core::mem::size_of; - -use hashbrown::HashMap; - -use crate::field::extension::{Extendable, FieldExtension}; -use crate::field::polynomial::PolynomialCoeffs; -use crate::field::types::{Field64, PrimeField64}; -use crate::fri::proof::{ - CompressedFriProof, CompressedFriQueryRounds, FriInitialTreeProof, FriProof, FriQueryRound, - FriQueryStep, -}; -use crate::hash::hash_types::RichField; -use crate::hash::hashing::HashConfig; -use crate::hash::merkle_proofs::MerkleProof; -use crate::hash::merkle_tree::MerkleCap; -use crate::plonk::circuit_data::CommonCircuitData; -use crate::plonk::config::{GenericConfig, GenericHashOut, Hasher}; -use crate::plonk::plonk_common::salt_size; -use crate::plonk::proof::{ - CompressedProof, CompressedProofWithPublicInputs, OpeningSet, Proof, ProofWithPublicInputs, -}; - -/// A no_std compatible variant of `std::io::Error` -#[derive(Debug)] -pub struct IoError; - -impl Display for IoError { - fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { - Debug::fmt(self, f) - } -} - -/// A no_std compatible variant of `std::io::Result` -pub type IoResult = Result; - -/// A `Read` which is able to report how many bytes are remaining. -pub trait Remaining: Read { - /// Returns the number of bytes remaining in the buffer. - fn remaining(&self) -> usize; - - /// Returns whether zero bytes are remaining. - fn is_empty(&self) -> bool { - self.remaining() == 0 - } -} - -/// Similar to `std::io::Read`, but works with no_std. -pub trait Read { - /// Reads exactly the length of `bytes` from `self` and writes it to `bytes`. - fn read_exact(&mut self, bytes: &mut [u8]) -> IoResult<()>; - - /// Reads a `u8` value from `self`. - #[inline] - fn read_u8(&mut self) -> IoResult { - let mut buf = [0; size_of::()]; - self.read_exact(&mut buf)?; - Ok(buf[0]) - } - - /// Reads a `u32` value from `self`. - #[inline] - fn read_u32(&mut self) -> IoResult { - let mut buf = [0; size_of::()]; - self.read_exact(&mut buf)?; - Ok(u32::from_le_bytes(buf)) - } - - /// Reads a element from the field `F` with size less than `2^64` from `self.` - #[inline] - fn read_field(&mut self) -> IoResult - where - F: Field64, - { - let mut buf = [0; size_of::()]; - self.read_exact(&mut buf)?; - Ok(F::from_canonical_u64(u64::from_le_bytes(buf))) - } - - /// Reads a vector of elements from the field `F` from `self`. - #[inline] - fn read_field_vec(&mut self, length: usize) -> IoResult> - where - F: Field64, - { - (0..length) - .map(|_| self.read_field()) - .collect::, _>>() - } - - /// Reads an element from the field extension of `F` from `self.` - #[inline] - fn read_field_ext(&mut self) -> IoResult - where - F: Field64 + Extendable, - { - let mut arr = [F::ZERO; D]; - for a in arr.iter_mut() { - *a = self.read_field()?; - } - Ok(>::from_basefield_array( - arr, - )) - } - - /// Reads a vector of elements from the field extension of `F` from `self`. - #[inline] - fn read_field_ext_vec( - &mut self, - length: usize, - ) -> IoResult> - where - F: RichField + Extendable, - { - (0..length).map(|_| self.read_field_ext::()).collect() - } - - /// Reads a hash value from `self`. - #[inline] - fn read_hash(&mut self) -> IoResult - where - F: RichField, - HC: HashConfig, - H: Hasher, - { - let mut buf = vec![0; H::HASH_SIZE]; - self.read_exact(&mut buf)?; - Ok(H::Hash::from_bytes(&buf)) - } - - /// Reads a value of type [`MerkleCap`] from `self` with the given `cap_height`. - #[inline] - fn read_merkle_cap(&mut self, cap_height: usize) -> IoResult> - where - F: RichField, - HC: HashConfig, - H: Hasher, - { - let cap_length = 1 << cap_height; - Ok(MerkleCap( - (0..cap_length) - .map(|_| self.read_hash::()) - .collect::, _>>()?, - )) - } - - /// Reads a value of type [`OpeningSet`] from `self` with the given `common_data`. - #[inline] - fn read_opening_set( - &mut self, - common_data: &CommonCircuitData, - ) -> IoResult> - where - F: RichField + Extendable, - C: GenericConfig, - { - let config = &common_data.config; - let constants = self.read_field_ext_vec::(common_data.num_constants)?; - let plonk_sigmas = self.read_field_ext_vec::(config.num_routed_wires)?; - let wires = self.read_field_ext_vec::(config.num_wires)?; - let plonk_zs = self.read_field_ext_vec::(config.num_challenges)?; - let plonk_zs_next = self.read_field_ext_vec::(config.num_challenges)?; - let partial_products = self - .read_field_ext_vec::(common_data.num_partial_products * config.num_challenges)?; - let quotient_polys = self.read_field_ext_vec::( - common_data.quotient_degree_factor * config.num_challenges, - )?; - Ok(OpeningSet { - constants, - plonk_sigmas, - wires, - plonk_zs, - plonk_zs_next, - partial_products, - quotient_polys, - }) - } - - /// Reads a value of type [`MerkleProof`] from `self`. - #[inline] - fn read_merkle_proof(&mut self) -> IoResult> - where - F: RichField, - HC: HashConfig, - H: Hasher, - { - let length = self.read_u8()?; - Ok(MerkleProof { - siblings: (0..length) - .map(|_| self.read_hash::()) - .collect::>()?, - }) - } - - /// Reads a value of type [`FriInitialTreeProof`] from `self` with the given `common_data`. - #[inline] - fn read_fri_initial_proof( - &mut self, - common_data: &CommonCircuitData, - ) -> IoResult> - where - F: RichField + Extendable, - C: GenericConfig, - { - let config = &common_data.config; - let salt = salt_size(common_data.fri_params.hiding); - let mut evals_proofs = Vec::with_capacity(4); - - let constants_sigmas_v = - self.read_field_vec(common_data.num_constants + config.num_routed_wires)?; - let constants_sigmas_p = self.read_merkle_proof()?; - evals_proofs.push((constants_sigmas_v, constants_sigmas_p)); - - let wires_v = self.read_field_vec(config.num_wires + salt)?; - let wires_p = self.read_merkle_proof()?; - evals_proofs.push((wires_v, wires_p)); - - let zs_partial_v = self.read_field_vec( - config.num_challenges * (1 + common_data.num_partial_products) + salt, - )?; - let zs_partial_p = self.read_merkle_proof()?; - evals_proofs.push((zs_partial_v, zs_partial_p)); - - let quotient_v = - self.read_field_vec(config.num_challenges * common_data.quotient_degree_factor + salt)?; - let quotient_p = self.read_merkle_proof()?; - evals_proofs.push((quotient_v, quotient_p)); - - Ok(FriInitialTreeProof { evals_proofs }) - } - - /// Reads a value of type [`FriQueryStep`] from `self` with the given `arity` and `compressed` - /// flag. - #[inline] - fn read_fri_query_step( - &mut self, - arity: usize, - compressed: bool, - ) -> IoResult> - where - F: RichField + Extendable, - C: GenericConfig, - { - let evals = self.read_field_ext_vec::(arity - usize::from(compressed))?; - let merkle_proof = self.read_merkle_proof()?; - Ok(FriQueryStep { - evals, - merkle_proof, - }) - } - - /// Reads a vector of [`FriQueryRound`]s from `self` with `common_data`. - #[inline] - #[allow(clippy::type_complexity)] - fn read_fri_query_rounds( - &mut self, - common_data: &CommonCircuitData, - ) -> IoResult>> - where - F: RichField + Extendable, - C: GenericConfig, - { - let config = &common_data.config; - let mut fqrs = Vec::with_capacity(config.fri_config.num_query_rounds); - for _ in 0..config.fri_config.num_query_rounds { - let initial_trees_proof = self.read_fri_initial_proof::(common_data)?; - let steps = common_data - .fri_params - .reduction_arity_bits - .iter() - .map(|&ar| self.read_fri_query_step::(1 << ar, false)) - .collect::>()?; - fqrs.push(FriQueryRound { - initial_trees_proof, - steps, - }) - } - Ok(fqrs) - } - - /// Reads a value of type [`FriProof`] from `self` with `common_data`. - #[inline] - fn read_fri_proof( - &mut self, - common_data: &CommonCircuitData, - ) -> IoResult> - where - F: RichField + Extendable, - C: GenericConfig, - { - let config = &common_data.config; - let commit_phase_merkle_caps = (0..common_data.fri_params.reduction_arity_bits.len()) - .map(|_| self.read_merkle_cap(config.fri_config.cap_height)) - .collect::, _>>()?; - let query_round_proofs = self.read_fri_query_rounds::(common_data)?; - let final_poly = PolynomialCoeffs::new( - self.read_field_ext_vec::(common_data.fri_params.final_poly_len())?, - ); - let pow_witness = self.read_field()?; - Ok(FriProof { - commit_phase_merkle_caps, - query_round_proofs, - final_poly, - pow_witness, - }) - } - - /// Reads a value of type [`Proof`] from `self` with `common_data`. - #[inline] - fn read_proof( - &mut self, - common_data: &CommonCircuitData, - ) -> IoResult> - where - F: RichField + Extendable, - C: GenericConfig, - { - let config = &common_data.config; - let wires_cap = self.read_merkle_cap(config.fri_config.cap_height)?; - let plonk_zs_partial_products_cap = self.read_merkle_cap(config.fri_config.cap_height)?; - let quotient_polys_cap = self.read_merkle_cap(config.fri_config.cap_height)?; - let openings = self.read_opening_set::(common_data)?; - let opening_proof = self.read_fri_proof::(common_data)?; - Ok(Proof { - wires_cap, - plonk_zs_partial_products_cap, - quotient_polys_cap, - openings, - opening_proof, - }) - } - - /// Reads a value of type [`ProofWithPublicInputs`] from `self` with `common_data`. - #[inline] - fn read_proof_with_public_inputs( - &mut self, - common_data: &CommonCircuitData, - ) -> IoResult> - where - Self: Remaining, - F: RichField + Extendable, - C: GenericConfig, - { - let proof = self.read_proof(common_data)?; - let public_inputs = self.read_field_vec(self.remaining() / size_of::())?; - Ok(ProofWithPublicInputs { - proof, - public_inputs, - }) - } - - /// Reads a value of type [`CompressedFriQueryRounds`] from `self` with `common_data`. - #[inline] - fn read_compressed_fri_query_rounds( - &mut self, - common_data: &CommonCircuitData, - ) -> IoResult> - where - F: RichField + Extendable, - C: GenericConfig, - { - let config = &common_data.config; - let original_indices = (0..config.fri_config.num_query_rounds) - .map(|_| self.read_u32().map(|i| i as usize)) - .collect::, _>>()?; - let mut indices = original_indices.clone(); - indices.sort_unstable(); - indices.dedup(); - let mut pairs = Vec::new(); - for &i in &indices { - pairs.push((i, self.read_fri_initial_proof::(common_data)?)); - } - let initial_trees_proofs = HashMap::from_iter(pairs); - - let mut steps = Vec::with_capacity(common_data.fri_params.reduction_arity_bits.len()); - for &a in &common_data.fri_params.reduction_arity_bits { - indices.iter_mut().for_each(|x| { - *x >>= a; - }); - indices.dedup(); - let query_steps = (0..indices.len()) - .map(|_| self.read_fri_query_step::(1 << a, true)) - .collect::, _>>()?; - steps.push( - indices - .iter() - .copied() - .zip(query_steps) - .collect::>(), - ); - } - - Ok(CompressedFriQueryRounds { - indices: original_indices, - initial_trees_proofs, - steps, - }) - } - - /// Reads a value of type [`CompressedFriProof`] from `self` with `common_data`. - #[inline] - fn read_compressed_fri_proof( - &mut self, - common_data: &CommonCircuitData, - ) -> IoResult> - where - F: RichField + Extendable, - C: GenericConfig, - { - let config = &common_data.config; - let commit_phase_merkle_caps = (0..common_data.fri_params.reduction_arity_bits.len()) - .map(|_| self.read_merkle_cap(config.fri_config.cap_height)) - .collect::, _>>()?; - let query_round_proofs = self.read_compressed_fri_query_rounds::(common_data)?; - let final_poly = PolynomialCoeffs::new( - self.read_field_ext_vec::(common_data.fri_params.final_poly_len())?, - ); - let pow_witness = self.read_field()?; - Ok(CompressedFriProof { - commit_phase_merkle_caps, - query_round_proofs, - final_poly, - pow_witness, - }) - } - - /// Reads a value of type [`CompressedProof`] from `self` with `common_data`. - #[inline] - fn read_compressed_proof( - &mut self, - common_data: &CommonCircuitData, - ) -> IoResult> - where - F: RichField + Extendable, - C: GenericConfig, - { - let config = &common_data.config; - let wires_cap = self.read_merkle_cap(config.fri_config.cap_height)?; - let plonk_zs_partial_products_cap = self.read_merkle_cap(config.fri_config.cap_height)?; - let quotient_polys_cap = self.read_merkle_cap(config.fri_config.cap_height)?; - let openings = self.read_opening_set::(common_data)?; - let opening_proof = self.read_compressed_fri_proof::(common_data)?; - Ok(CompressedProof { - wires_cap, - plonk_zs_partial_products_cap, - quotient_polys_cap, - openings, - opening_proof, - }) - } - - /// Reads a value of type [`CompressedProofWithPublicInputs`] from `self` with `common_data`. - #[inline] - fn read_compressed_proof_with_public_inputs( - &mut self, - common_data: &CommonCircuitData, - ) -> IoResult> - where - Self: Remaining, - F: RichField + Extendable, - C: GenericConfig, - { - let proof = self.read_compressed_proof(common_data)?; - let public_inputs = self.read_field_vec(self.remaining() / size_of::())?; - Ok(CompressedProofWithPublicInputs { - proof, - public_inputs, - }) - } -} - -/// Writing -pub trait Write { - /// Error Type - type Error; - - /// Writes all `bytes` to `self`. - fn write_all(&mut self, bytes: &[u8]) -> IoResult<()>; - - /// Writes a byte `x` to `self`. - #[inline] - fn write_u8(&mut self, x: u8) -> IoResult<()> { - self.write_all(&[x]) - } - - /// Writes a word `x` to `self.` - #[inline] - fn write_u32(&mut self, x: u32) -> IoResult<()> { - self.write_all(&x.to_le_bytes()) - } - - /// Writes an element `x` from the field `F` to `self`. - #[inline] - fn write_field(&mut self, x: F) -> IoResult<()> - where - F: PrimeField64, - { - self.write_all(&x.to_canonical_u64().to_le_bytes()) - } - - /// Writes a vector `v` of elements from the field `F` to `self`. - #[inline] - fn write_field_vec(&mut self, v: &[F]) -> IoResult<()> - where - F: PrimeField64, - { - for &a in v { - self.write_field(a)?; - } - Ok(()) - } - - /// Writes an element `x` from the field extension of `F` to `self`. - #[inline] - fn write_field_ext(&mut self, x: F::Extension) -> IoResult<()> - where - F: RichField + Extendable, - { - for &a in &x.to_basefield_array() { - self.write_field(a)?; - } - Ok(()) - } - - /// Writes a vector `v` of elements from the field extension of `F` to `self`. - #[inline] - fn write_field_ext_vec(&mut self, v: &[F::Extension]) -> IoResult<()> - where - F: RichField + Extendable, - { - for &a in v { - self.write_field_ext::(a)?; - } - Ok(()) - } - - /// Writes a hash `h` to `self`. - #[inline] - fn write_hash(&mut self, h: H::Hash) -> IoResult<()> - where - F: RichField, - HC: HashConfig, - H: Hasher, - { - self.write_all(&h.to_bytes()) - } - - /// Writes `cap`, a value of type [`MerkleCap`], to `self`. - #[inline] - fn write_merkle_cap(&mut self, cap: &MerkleCap) -> IoResult<()> - where - F: RichField, - HC: HashConfig, - H: Hasher, - { - for &a in &cap.0 { - self.write_hash::(a)?; - } - Ok(()) - } - - /// Writes a value `os` of type [`OpeningSet`] to `self.` - #[inline] - fn write_opening_set(&mut self, os: &OpeningSet) -> IoResult<()> - where - F: RichField + Extendable, - { - self.write_field_ext_vec::(&os.constants)?; - self.write_field_ext_vec::(&os.plonk_sigmas)?; - self.write_field_ext_vec::(&os.wires)?; - self.write_field_ext_vec::(&os.plonk_zs)?; - self.write_field_ext_vec::(&os.plonk_zs_next)?; - self.write_field_ext_vec::(&os.partial_products)?; - self.write_field_ext_vec::(&os.quotient_polys) - } - - /// Writes a value `p` of type [`MerkleProof`] to `self.` - #[inline] - fn write_merkle_proof(&mut self, p: &MerkleProof) -> IoResult<()> - where - F: RichField, - HC: HashConfig, - H: Hasher, - { - let length = p.siblings.len(); - self.write_u8( - length - .try_into() - .expect("Merkle proof length must fit in u8."), - )?; - for &h in &p.siblings { - self.write_hash::(h)?; - } - Ok(()) - } - - /// Writes a value `fitp` of type [`FriInitialTreeProof`] to `self.` - #[inline] - fn write_fri_initial_proof( - &mut self, - fitp: &FriInitialTreeProof, - ) -> IoResult<()> - where - F: RichField + Extendable, - C: GenericConfig, - { - for (v, p) in &fitp.evals_proofs { - self.write_field_vec(v)?; - self.write_merkle_proof(p)?; - } - Ok(()) - } - - /// Writes a value `fqs` of type [`FriQueryStep`] to `self.` - #[inline] - fn write_fri_query_step( - &mut self, - fqs: &FriQueryStep, - ) -> IoResult<()> - where - F: RichField + Extendable, - C: GenericConfig, - { - self.write_field_ext_vec::(&fqs.evals)?; - self.write_merkle_proof(&fqs.merkle_proof) - } - - /// Writes a value `fqrs` of type [`FriQueryRound`] to `self.` - #[inline] - fn write_fri_query_rounds( - &mut self, - fqrs: &[FriQueryRound], - ) -> IoResult<()> - where - F: RichField + Extendable, - C: GenericConfig, - { - for fqr in fqrs { - self.write_fri_initial_proof::(&fqr.initial_trees_proof)?; - for fqs in &fqr.steps { - self.write_fri_query_step::(fqs)?; - } - } - Ok(()) - } - - /// Writes a value `fq` of type [`FriProof`] to `self.` - #[inline] - fn write_fri_proof( - &mut self, - fp: &FriProof, - ) -> IoResult<()> - where - F: RichField + Extendable, - C: GenericConfig, - { - for cap in &fp.commit_phase_merkle_caps { - self.write_merkle_cap(cap)?; - } - self.write_fri_query_rounds::(&fp.query_round_proofs)?; - self.write_field_ext_vec::(&fp.final_poly.coeffs)?; - self.write_field(fp.pow_witness) - } - - /// Writes a value `proof` of type [`Proof`] to `self.` - #[inline] - fn write_proof(&mut self, proof: &Proof) -> IoResult<()> - where - F: RichField + Extendable, - C: GenericConfig, - { - self.write_merkle_cap(&proof.wires_cap)?; - self.write_merkle_cap(&proof.plonk_zs_partial_products_cap)?; - self.write_merkle_cap(&proof.quotient_polys_cap)?; - self.write_opening_set(&proof.openings)?; - self.write_fri_proof::(&proof.opening_proof) - } - - /// Writes a value `proof_with_pis` of type [`ProofWithPublicInputs`] to `self.` - #[inline] - fn write_proof_with_public_inputs( - &mut self, - proof_with_pis: &ProofWithPublicInputs, - ) -> IoResult<()> - where - F: RichField + Extendable, - C: GenericConfig, - { - let ProofWithPublicInputs { - proof, - public_inputs, - } = proof_with_pis; - self.write_proof(proof)?; - self.write_field_vec(public_inputs) - } - - /// Writes a value `cfqrs` of type [`CompressedFriQueryRounds`] to `self.` - #[inline] - fn write_compressed_fri_query_rounds( - &mut self, - cfqrs: &CompressedFriQueryRounds, - ) -> IoResult<()> - where - F: RichField + Extendable, - C: GenericConfig, - { - for &i in &cfqrs.indices { - self.write_u32(i as u32)?; - } - let mut initial_trees_proofs = cfqrs.initial_trees_proofs.iter().collect::>(); - initial_trees_proofs.sort_by_key(|&x| x.0); - for (_, itp) in initial_trees_proofs { - self.write_fri_initial_proof::(itp)?; - } - for h in &cfqrs.steps { - let mut fri_query_steps = h.iter().collect::>(); - fri_query_steps.sort_by_key(|&x| x.0); - for (_, fqs) in fri_query_steps { - self.write_fri_query_step::(fqs)?; - } - } - Ok(()) - } - - /// Writes a value `fq` of type [`CompressedFriProof`] to `self.` - #[inline] - fn write_compressed_fri_proof( - &mut self, - fp: &CompressedFriProof, - ) -> IoResult<()> - where - F: RichField + Extendable, - C: GenericConfig, - { - for cap in &fp.commit_phase_merkle_caps { - self.write_merkle_cap(cap)?; - } - self.write_compressed_fri_query_rounds::(&fp.query_round_proofs)?; - self.write_field_ext_vec::(&fp.final_poly.coeffs)?; - self.write_field(fp.pow_witness) - } - - /// Writes a value `proof` of type [`CompressedProof`] to `self.` - #[inline] - fn write_compressed_proof( - &mut self, - proof: &CompressedProof, - ) -> IoResult<()> - where - F: RichField + Extendable, - C: GenericConfig, - { - self.write_merkle_cap(&proof.wires_cap)?; - self.write_merkle_cap(&proof.plonk_zs_partial_products_cap)?; - self.write_merkle_cap(&proof.quotient_polys_cap)?; - self.write_opening_set(&proof.openings)?; - self.write_compressed_fri_proof::(&proof.opening_proof) - } - - /// Writes a value `proof_with_pis` of type [`CompressedProofWithPublicInputs`] to `self.` - #[inline] - fn write_compressed_proof_with_public_inputs( - &mut self, - proof_with_pis: &CompressedProofWithPublicInputs, - ) -> IoResult<()> - where - F: RichField + Extendable, - C: GenericConfig, - { - let CompressedProofWithPublicInputs { - proof, - public_inputs, - } = proof_with_pis; - self.write_compressed_proof(proof)?; - self.write_field_vec(public_inputs) - } -} - -impl Write for Vec { - type Error = Infallible; - - #[inline] - fn write_all(&mut self, bytes: &[u8]) -> IoResult<()> { - self.extend_from_slice(bytes); - Ok(()) - } -} - -/// Buffer -#[cfg(feature = "std")] -#[derive(Debug)] -pub struct Buffer { - bytes: Vec, - pos: usize, -} - -#[cfg(feature = "std")] -impl Buffer { - /// Builds a new [`Buffer`] over `buffer`. - #[inline] - pub fn new(bytes: Vec) -> Self { - Self { bytes, pos: 0 } - } - - /// Returns the inner buffer. - #[inline] - pub fn bytes(self) -> Vec { - self.bytes - } -} - -#[cfg(feature = "std")] -impl Remaining for Buffer { - fn remaining(&self) -> usize { - self.bytes.len() - self.pos - } -} - -#[cfg(feature = "std")] -impl Read for Buffer { - #[inline] - fn read_exact(&mut self, bytes: &mut [u8]) -> IoResult<()> { - let n = bytes.len(); - if self.remaining() < n { - Err(IoError) - } else { - bytes.copy_from_slice(&self.bytes[self.pos..][..n]); - self.pos += n; - Ok(()) - } - } -} diff --git a/plonky2/src/util/serialization/gate_serialization.rs b/plonky2/src/util/serialization/gate_serialization.rs new file mode 100644 index 00000000..351fa76b --- /dev/null +++ b/plonky2/src/util/serialization/gate_serialization.rs @@ -0,0 +1,105 @@ +use plonky2_field::extension::Extendable; + +use crate::gates::gate::GateRef; +use crate::hash::hash_types::RichField; +use crate::util::serialization::{Buffer, IoResult}; + +pub trait GateSerializer, const D: usize> { + fn read_gate(&self, buf: &mut Buffer) -> IoResult>; + fn write_gate(&self, buf: &mut Vec, gate: &GateRef) -> IoResult<()>; +} + +#[macro_export] +macro_rules! read_gate_impl { + ($buf:expr, $tag:expr, $($gate_types:ty),+) => {{ + let tag = $tag; + let buf = $buf; + let mut i = 0..; + $(if tag == i.next().unwrap() { + let gate = <$gate_types as $crate::gates::gate::Gate>::deserialize(buf)?; + Ok($crate::gates::gate::GateRef::::new(gate)) + } else)* + { + Err($crate::util::serialization::IoError) + } + }} +} + +#[macro_export] +macro_rules! get_gate_tag_impl { + ($gate:expr, $($gate_types:ty),+) => {{ + let gate_any = $gate.0.as_any(); + let mut i = 0..; + $(if let (tag, true) = (i.next().unwrap(), gate_any.is::<$gate_types>()) { + Ok(tag) + } else)* + { + log::log!(log::Level::Error, "attempted to serialize gate with id `{}` which is unsupported by this gate serializer", $gate.0.id()); + Err($crate::util::serialization::IoError) + } + }}; +} + +#[macro_export] +/// Macro implementing the `GateSerializer` trait. +/// To serialize a list of gates used for a circuit, +/// this macro should be called with a struct on which to implement +/// this as first argument, followed by all the targeted gates. +macro_rules! impl_gate_serializer { + ($target:ty, $($gate_types:ty),+) => { + fn read_gate(&self, buf: &mut $crate::util::serialization::Buffer) -> $crate::util::serialization::IoResult<$crate::gates::gate::GateRef> { + let tag = $crate::util::serialization::Read::read_u32(buf)?; + read_gate_impl!(buf, tag, $($gate_types),+) + } + + fn write_gate(&self, buf: &mut Vec, gate: &$crate::gates::gate::GateRef) -> $crate::util::serialization::IoResult<()> { + let tag = get_gate_tag_impl!(gate, $($gate_types),+)?; + + $crate::util::serialization::Write::write_u32(buf, tag)?; + gate.0.serialize(buf)?; + Ok(()) + } + }; +} + +pub mod default { + use plonky2_field::extension::Extendable; + + use crate::gates::arithmetic_base::ArithmeticGate; + use crate::gates::arithmetic_extension::ArithmeticExtensionGate; + use crate::gates::base_sum::BaseSumGate; + use crate::gates::constant::ConstantGate; + use crate::gates::coset_interpolation::CosetInterpolationGate; + use crate::gates::exponentiation::ExponentiationGate; + use crate::gates::multiplication_extension::MulExtensionGate; + use crate::gates::noop::NoopGate; + use crate::gates::poseidon::PoseidonGate; + use crate::gates::poseidon_mds::PoseidonMdsGate; + use crate::gates::public_input::PublicInputGate; + use crate::gates::random_access::RandomAccessGate; + use crate::gates::reducing::ReducingGate; + use crate::gates::reducing_extension::ReducingExtensionGate; + use crate::hash::hash_types::RichField; + use crate::util::serialization::GateSerializer; + + pub struct DefaultGateSerializer; + impl, const D: usize> GateSerializer for DefaultGateSerializer { + impl_gate_serializer! { + DefaultGateSerializer, + ArithmeticGate, + ArithmeticExtensionGate, + BaseSumGate<2>, + ConstantGate, + CosetInterpolationGate, + ExponentiationGate, + MulExtensionGate, + NoopGate, + PoseidonMdsGate, + PoseidonGate, + PublicInputGate, + RandomAccessGate, + ReducingExtensionGate, + ReducingGate + } + } +} diff --git a/plonky2/src/util/serialization/generator_serialization.rs b/plonky2/src/util/serialization/generator_serialization.rs new file mode 100644 index 00000000..5fab57e1 --- /dev/null +++ b/plonky2/src/util/serialization/generator_serialization.rs @@ -0,0 +1,164 @@ +//! A module to help with WitnessGeneratorRef serialization + +use plonky2_field::extension::Extendable; + +use crate::hash::hash_types::RichField; +use crate::iop::generator::WitnessGeneratorRef; +use crate::plonk::circuit_data::CommonCircuitData; +use crate::util::serialization::{Buffer, IoResult}; + +pub trait WitnessGeneratorSerializer, const D: usize> { + fn read_generator( + &self, + buf: &mut Buffer, + common: &CommonCircuitData, + ) -> IoResult>; + fn write_generator( + &self, + buf: &mut Vec, + generator: &WitnessGeneratorRef, + ) -> IoResult<()>; +} + +#[macro_export] +macro_rules! read_generator_impl { + ($buf:expr, $tag:expr, $common:expr, $($generator_types:ty),+) => {{ + let tag = $tag; + let buf = $buf; + let mut i = 0..; + + if tag == 0 { + let generator: $crate::recursion::dummy_circuit::DummyProofGenerator = + $crate::recursion::dummy_circuit::DummyProofGenerator::deserialize_with_circuit_data(buf, $common)?; + return Ok($crate::iop::generator::WitnessGeneratorRef::::new( + $crate::iop::generator::SimpleGenerator::::adapter(generator), + )); + } + + $(if tag == i.next().unwrap() { + let generator = + <$generator_types as $crate::iop::generator::SimpleGenerator>::deserialize(buf)?; + Ok($crate::iop::generator::WitnessGeneratorRef::::new( + $crate::iop::generator::SimpleGenerator::::adapter(generator), + )) + } else)* + { + Err($crate::util::serialization::IoError) + } + }}; +} + +#[macro_export] +macro_rules! get_generator_tag_impl { + ($generator:expr, $($generator_types:ty),+) => {{ + let mut i = 0..; + $(if let (tag, true) = (i.next().unwrap(), $generator.0.id() == $crate::iop::generator::SimpleGenerator::::id(&<$generator_types>::default())) { + Ok(tag) + } else)* + { + log::log!(log::Level::Error, "attempted to serialize generator with id {} which is unsupported by this generator serializer", $generator.0.id()); + Err($crate::util::serialization::IoError) + } + }}; +} + +#[macro_export] +/// Macro implementing the `WitnessGeneratorSerializer` trait. +/// To serialize a list of generators used for a circuit, +/// this macro should be called with a struct on which to implement +/// this as first argument, followed by all the targeted generators. +/// +/// ***NOTE:*** If you need to include `DummyProofGenerator`, you **MUST** +/// place it at the *beginning* of the generators list, right after +/// the serializer struct. +macro_rules! impl_generator_serializer { + ($target:ty, $($generator_types:ty),+) => { + fn read_generator( + &self, + buf: &mut $crate::util::serialization::Buffer, + common: &$crate::plonk::circuit_data::CommonCircuitData, + ) -> $crate::util::serialization::IoResult<$crate::iop::generator::WitnessGeneratorRef> { + let tag = $crate::util::serialization::Read::read_u32(buf)?; + read_generator_impl!(buf, tag, common, $($generator_types),+) + } + + fn write_generator( + &self, + buf: &mut Vec, + generator: &$crate::iop::generator::WitnessGeneratorRef, + ) -> $crate::util::serialization::IoResult<()> { + let tag = get_generator_tag_impl!(generator, $($generator_types),+)?; + + $crate::util::serialization::Write::write_u32(buf, tag)?; + generator.0.serialize(buf)?; + Ok(()) + } + }; +} + +pub mod default { + use core::marker::PhantomData; + + use plonky2_field::extension::Extendable; + + use crate::gadgets::arithmetic::EqualityGenerator; + use crate::gadgets::arithmetic_extension::QuotientGeneratorExtension; + use crate::gadgets::range_check::LowHighGenerator; + use crate::gadgets::split_base::BaseSumGenerator; + use crate::gadgets::split_join::{SplitGenerator, WireSplitGenerator}; + use crate::gates::arithmetic_base::ArithmeticBaseGenerator; + use crate::gates::arithmetic_extension::ArithmeticExtensionGenerator; + use crate::gates::base_sum::BaseSplitGenerator; + use crate::gates::coset_interpolation::InterpolationGenerator; + use crate::gates::exponentiation::ExponentiationGenerator; + use crate::gates::multiplication_extension::MulExtensionGenerator; + use crate::gates::poseidon::PoseidonGenerator; + use crate::gates::poseidon_mds::PoseidonMdsGenerator; + use crate::gates::random_access::RandomAccessGenerator; + use crate::gates::reducing::ReducingGenerator; + use crate::gates::reducing_extension::ReducingGenerator as ReducingExtensionGenerator; + use crate::hash::hash_types::RichField; + use crate::iop::generator::{ + ConstantGenerator, CopyGenerator, NonzeroTestGenerator, RandomValueGenerator, + }; + use crate::plonk::config::{AlgebraicHasher, GenericConfig}; + use crate::recursion::dummy_circuit::DummyProofGenerator; + use crate::util::serialization::WitnessGeneratorSerializer; + + pub struct DefaultGeneratorSerializer, const D: usize> { + pub _phantom: PhantomData, + } + + impl WitnessGeneratorSerializer for DefaultGeneratorSerializer + where + F: RichField + Extendable, + C: GenericConfig + 'static, + C::Hasher: AlgebraicHasher, + { + impl_generator_serializer! { + DefaultGeneratorSerializer, + DummyProofGenerator, + ArithmeticBaseGenerator, + ArithmeticExtensionGenerator, + BaseSplitGenerator<2>, + BaseSumGenerator<2>, + ConstantGenerator, + CopyGenerator, + EqualityGenerator, + ExponentiationGenerator, + InterpolationGenerator, + LowHighGenerator, + MulExtensionGenerator, + NonzeroTestGenerator, + PoseidonGenerator, + PoseidonMdsGenerator, + QuotientGeneratorExtension, + RandomAccessGenerator, + RandomValueGenerator, + ReducingGenerator, + ReducingExtensionGenerator, + SplitGenerator, + WireSplitGenerator + } + } +} diff --git a/plonky2/src/util/serialization/mod.rs b/plonky2/src/util/serialization/mod.rs new file mode 100644 index 00000000..5a92afb5 --- /dev/null +++ b/plonky2/src/util/serialization/mod.rs @@ -0,0 +1,2080 @@ +#[macro_use] +pub mod generator_serialization; + +#[macro_use] +pub mod gate_serialization; + +use alloc::collections::BTreeMap; +use alloc::vec; +use alloc::vec::Vec; +use core::convert::Infallible; +use core::fmt::{Debug, Display, Formatter}; +use core::mem::size_of; +use core::ops::Range; + +pub use gate_serialization::default::DefaultGateSerializer; +pub use gate_serialization::GateSerializer; +pub use generator_serialization::default::DefaultGeneratorSerializer; +pub use generator_serialization::WitnessGeneratorSerializer; +use hashbrown::HashMap; + +use crate::field::extension::{Extendable, FieldExtension}; +use crate::field::polynomial::PolynomialCoeffs; +use crate::field::types::{Field64, PrimeField64}; +use crate::fri::oracle::PolynomialBatch; +use crate::fri::proof::{ + CompressedFriProof, CompressedFriQueryRounds, FriInitialTreeProof, FriInitialTreeProofTarget, + FriProof, FriProofTarget, FriQueryRound, FriQueryRoundTarget, FriQueryStep, FriQueryStepTarget, +}; +use crate::fri::reduction_strategies::FriReductionStrategy; +use crate::fri::{FriConfig, FriParams}; +use crate::gadgets::polynomial::PolynomialCoeffsExtTarget; +use crate::gates::gate::GateRef; +use crate::gates::selectors::SelectorsInfo; +use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget, RichField}; +use crate::hash::hashing::HashConfig; +use crate::hash::merkle_proofs::{MerkleProof, MerkleProofTarget}; +use crate::hash::merkle_tree::{MerkleCap, MerkleTree}; +use crate::iop::ext_target::ExtensionTarget; +use crate::iop::generator::WitnessGeneratorRef; +use crate::iop::target::{BoolTarget, Target}; +use crate::iop::wire::Wire; +use crate::plonk::circuit_data::{ + CircuitConfig, CircuitData, CommonCircuitData, ProverCircuitData, ProverOnlyCircuitData, + VerifierCircuitData, VerifierCircuitTarget, VerifierOnlyCircuitData, +}; +use crate::plonk::config::{GenericConfig, GenericHashOut, Hasher}; +use crate::plonk::plonk_common::salt_size; +use crate::plonk::proof::{ + CompressedProof, CompressedProofWithPublicInputs, OpeningSet, OpeningSetTarget, Proof, + ProofTarget, ProofWithPublicInputs, ProofWithPublicInputsTarget, +}; + +/// A no_std compatible variant of `std::io::Error` +#[derive(Debug)] +pub struct IoError; + +impl Display for IoError { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + Debug::fmt(self, f) + } +} + +/// A no_std compatible variant of `std::io::Result` +pub type IoResult = Result; + +/// A `Read` which is able to report how many bytes are remaining. +pub trait Remaining: Read { + /// Returns the number of bytes remaining in the buffer. + fn remaining(&self) -> usize; + + /// Returns whether zero bytes are remaining. + fn is_empty(&self) -> bool { + self.remaining() == 0 + } +} + +/// Similar to `std::io::Read`, but works with no_std. +pub trait Read { + /// Reads exactly the length of `bytes` from `self` and writes it to `bytes`. + fn read_exact(&mut self, bytes: &mut [u8]) -> IoResult<()>; + + /// Reads a `bool` value from `self`. + #[inline] + fn read_bool(&mut self) -> IoResult { + let i = self.read_u8()?; + match i { + 0 => Ok(false), + 1 => Ok(true), + _ => Err(IoError), + } + } + + /// Reads a `BoolTarget` value from `self`. + #[inline] + fn read_target_bool(&mut self) -> IoResult { + Ok(BoolTarget::new_unsafe(self.read_target()?)) + } + + /// Reads a vector of `BoolTarget` from `self`. + #[inline] + fn read_target_bool_vec(&mut self) -> IoResult> { + let length = self.read_usize()?; + (0..length) + .map(|_| self.read_target_bool()) + .collect::, _>>() + } + + /// Reads a `u8` value from `self`. + #[inline] + fn read_u8(&mut self) -> IoResult { + let mut buf = [0; size_of::()]; + self.read_exact(&mut buf)?; + Ok(buf[0]) + } + + /// Reads a `u32` value from `self`. + #[inline] + fn read_u32(&mut self) -> IoResult { + let mut buf = [0; size_of::()]; + self.read_exact(&mut buf)?; + Ok(u32::from_le_bytes(buf)) + } + + /// Reads a `usize` value from `self`. + #[inline] + fn read_usize(&mut self) -> IoResult { + let mut buf = [0; std::mem::size_of::()]; + self.read_exact(&mut buf)?; + Ok(u64::from_le_bytes(buf) as usize) + } + + /// Reads a vector of `usize` value from `self`. + #[inline] + fn read_usize_vec(&mut self) -> IoResult> { + let len = self.read_usize()?; + let mut res = Vec::with_capacity(len); + for _ in 0..len { + res.push(self.read_usize()?); + } + + Ok(res) + } + + /// Reads a element from the field `F` with size less than `2^64` from `self.` + #[inline] + fn read_field(&mut self) -> IoResult + where + F: Field64, + { + let mut buf = [0; size_of::()]; + self.read_exact(&mut buf)?; + Ok(F::from_canonical_u64(u64::from_le_bytes(buf))) + } + + /// Reads a vector of elements from the field `F` from `self`. + #[inline] + fn read_field_vec(&mut self, length: usize) -> IoResult> + where + F: Field64, + { + (0..length) + .map(|_| self.read_field()) + .collect::, _>>() + } + + /// Reads an element from the field extension of `F` from `self.` + #[inline] + fn read_field_ext(&mut self) -> IoResult + where + F: Field64 + Extendable, + { + let mut arr = [F::ZERO; D]; + for a in arr.iter_mut() { + *a = self.read_field()?; + } + Ok(>::from_basefield_array( + arr, + )) + } + + /// Reads a vector of elements from the field extension of `F` from `self`. + #[inline] + fn read_field_ext_vec( + &mut self, + length: usize, + ) -> IoResult> + where + F: RichField + Extendable, + { + (0..length).map(|_| self.read_field_ext::()).collect() + } + + /// Reads a Target from `self.` + #[inline] + fn read_target(&mut self) -> IoResult { + let is_wire = self.read_bool()?; + if is_wire { + let row = self.read_usize()?; + let column = self.read_usize()?; + Ok(Target::wire(row, column)) + } else { + let index = self.read_usize()?; + Ok(Target::VirtualTarget { index }) + } + } + + /// Reads an ExtensionTarget from `self`. + #[inline] + fn read_target_ext(&mut self) -> IoResult> { + let mut res = [Target::wire(0, 0); D]; + for r in res.iter_mut() { + *r = self.read_target()?; + } + + Ok(ExtensionTarget(res)) + } + + /// Reads a vector of Target from `self`. + #[inline] + fn read_target_vec(&mut self) -> IoResult> { + let length = self.read_usize()?; + (0..length) + .map(|_| self.read_target()) + .collect::, _>>() + } + + /// Reads a vector of ExtensionTarget from `self`. + #[inline] + fn read_target_ext_vec(&mut self) -> IoResult>> { + let length = self.read_usize()?; + (0..length) + .map(|_| self.read_target_ext::()) + .collect::, _>>() + } + + /// Reads a hash value from `self`. + #[inline] + fn read_hash(&mut self) -> IoResult + where + F: RichField, + HC: HashConfig, + H: Hasher, + { + let mut buf = vec![0; H::HASH_SIZE]; + self.read_exact(&mut buf)?; + Ok(H::Hash::from_bytes(&buf)) + } + + /// Reads a HashOutTarget value from `self`. + #[inline] + fn read_target_hash(&mut self) -> IoResult { + let mut elements = [Target::wire(0, 0); 4]; + for e in elements.iter_mut() { + *e = self.read_target()?; + } + + Ok(HashOutTarget { elements }) + } + + /// Reads a vector of Hash from `self`. + #[inline] + fn read_hash_vec(&mut self, length: usize) -> IoResult> + where + F: RichField, + HC: HashConfig, + H: Hasher, + { + (0..length) + .map(|_| self.read_hash::()) + .collect::, _>>() + } + + /// Reads a value of type [`MerkleCap`] from `self` with the given `cap_height`. + #[inline] + fn read_merkle_cap(&mut self, cap_height: usize) -> IoResult> + where + F: RichField, + HC: HashConfig, + H: Hasher, + { + let cap_length = 1 << cap_height; + Ok(MerkleCap( + (0..cap_length) + .map(|_| self.read_hash::()) + .collect::, _>>()?, + )) + } + + /// Reads a value of type [`MerkleCapTarget`] from `self`. + #[inline] + fn read_target_merkle_cap(&mut self) -> IoResult { + let length = self.read_usize()?; + Ok(MerkleCapTarget( + (0..length) + .map(|_| self.read_target_hash()) + .collect::, _>>()?, + )) + } + + /// Reads a value of type [`MerkleTree`] from `self`. + #[inline] + fn read_merkle_tree(&mut self) -> IoResult> + where + F: RichField, + HC: HashConfig, + H: Hasher, + { + let leaves_len = self.read_usize()?; + let mut leaves = Vec::with_capacity(leaves_len); + for _ in 0..leaves_len { + let leaf_len = self.read_usize()?; + leaves.push(self.read_field_vec(leaf_len)?); + } + + let digests_len = self.read_usize()?; + let digests = self.read_hash_vec::(digests_len)?; + let cap_height = self.read_usize()?; + let cap = self.read_merkle_cap::(cap_height)?; + Ok(MerkleTree { + leaves, + digests, + cap, + }) + } + + /// Reads a value of type [`OpeningSet`] from `self` with the given `common_data`. + #[inline] + fn read_opening_set( + &mut self, + common_data: &CommonCircuitData, + ) -> IoResult> + where + F: RichField + Extendable, + C: GenericConfig, + { + let config = &common_data.config; + let constants = self.read_field_ext_vec::(common_data.num_constants)?; + let plonk_sigmas = self.read_field_ext_vec::(config.num_routed_wires)?; + let wires = self.read_field_ext_vec::(config.num_wires)?; + let plonk_zs = self.read_field_ext_vec::(config.num_challenges)?; + let plonk_zs_next = self.read_field_ext_vec::(config.num_challenges)?; + let partial_products = self + .read_field_ext_vec::(common_data.num_partial_products * config.num_challenges)?; + let quotient_polys = self.read_field_ext_vec::( + common_data.quotient_degree_factor * config.num_challenges, + )?; + Ok(OpeningSet { + constants, + plonk_sigmas, + wires, + plonk_zs, + plonk_zs_next, + partial_products, + quotient_polys, + }) + } + + /// Reads a value of type [`OpeningSetTarget`] from `self`. + #[inline] + fn read_target_opening_set(&mut self) -> IoResult> { + let constants = self.read_target_ext_vec::()?; + let plonk_sigmas = self.read_target_ext_vec::()?; + let wires = self.read_target_ext_vec::()?; + let plonk_zs = self.read_target_ext_vec::()?; + let plonk_zs_next = self.read_target_ext_vec::()?; + let partial_products = self.read_target_ext_vec::()?; + let quotient_polys = self.read_target_ext_vec::()?; + + Ok(OpeningSetTarget { + constants, + plonk_sigmas, + wires, + plonk_zs, + plonk_zs_next, + partial_products, + quotient_polys, + }) + } + + /// Reads a value of type [`MerkleProof`] from `self`. + #[inline] + fn read_merkle_proof(&mut self) -> IoResult> + where + F: RichField, + HC: HashConfig, + H: Hasher, + { + let length = self.read_u8()?; + Ok(MerkleProof { + siblings: (0..length) + .map(|_| self.read_hash::()) + .collect::>()?, + }) + } + + /// Reads a value of type [`MerkleProofTarget`] from `self`. + #[inline] + fn read_target_merkle_proof(&mut self) -> IoResult { + let length = self.read_u8()?; + Ok(MerkleProofTarget { + siblings: (0..length) + .map(|_| self.read_target_hash()) + .collect::>()?, + }) + } + + /// Reads a value of type [`FriInitialTreeProof`] from `self` with the given `common_data`. + #[inline] + fn read_fri_initial_proof( + &mut self, + common_data: &CommonCircuitData, + ) -> IoResult> + where + F: RichField + Extendable, + C: GenericConfig, + { + let config = &common_data.config; + let salt = salt_size(common_data.fri_params.hiding); + let mut evals_proofs = Vec::with_capacity(4); + + let constants_sigmas_v = + self.read_field_vec(common_data.num_constants + config.num_routed_wires)?; + let constants_sigmas_p = self.read_merkle_proof()?; + evals_proofs.push((constants_sigmas_v, constants_sigmas_p)); + + let wires_v = self.read_field_vec(config.num_wires + salt)?; + let wires_p = self.read_merkle_proof()?; + evals_proofs.push((wires_v, wires_p)); + + let zs_partial_v = self.read_field_vec( + config.num_challenges * (1 + common_data.num_partial_products) + salt, + )?; + let zs_partial_p = self.read_merkle_proof()?; + evals_proofs.push((zs_partial_v, zs_partial_p)); + + let quotient_v = + self.read_field_vec(config.num_challenges * common_data.quotient_degree_factor + salt)?; + let quotient_p = self.read_merkle_proof()?; + evals_proofs.push((quotient_v, quotient_p)); + + Ok(FriInitialTreeProof { evals_proofs }) + } + + /// Reads a value of type [`FriInitialTreeProofTarget`] from `self`. + #[inline] + fn read_target_fri_initial_proof(&mut self) -> IoResult { + let len = self.read_usize()?; + let mut evals_proofs = Vec::with_capacity(len); + + for _ in 0..len { + evals_proofs.push((self.read_target_vec()?, self.read_target_merkle_proof()?)); + } + + Ok(FriInitialTreeProofTarget { evals_proofs }) + } + + /// Reads a value of type [`FriQueryStep`] from `self` with the given `arity` and `compressed` + /// flag. + #[inline] + fn read_fri_query_step( + &mut self, + arity: usize, + compressed: bool, + ) -> IoResult> + where + F: RichField + Extendable, + C: GenericConfig, + { + let evals = self.read_field_ext_vec::(arity - usize::from(compressed))?; + let merkle_proof = self.read_merkle_proof()?; + Ok(FriQueryStep { + evals, + merkle_proof, + }) + } + + /// Reads a value of type [`FriQueryStepTarget`] from `self`. + #[inline] + fn read_target_fri_query_step(&mut self) -> IoResult> { + let evals = self.read_target_ext_vec::()?; + let merkle_proof = self.read_target_merkle_proof()?; + Ok(FriQueryStepTarget { + evals, + merkle_proof, + }) + } + + /// Reads a vector of [`FriQueryRound`]s from `self` with `common_data`. + #[inline] + #[allow(clippy::type_complexity)] + fn read_fri_query_rounds( + &mut self, + common_data: &CommonCircuitData, + ) -> IoResult>> + where + F: RichField + Extendable, + C: GenericConfig, + { + let config = &common_data.config; + let mut fqrs = Vec::with_capacity(config.fri_config.num_query_rounds); + for _ in 0..config.fri_config.num_query_rounds { + let initial_trees_proof = self.read_fri_initial_proof::(common_data)?; + let steps = common_data + .fri_params + .reduction_arity_bits + .iter() + .map(|&ar| self.read_fri_query_step::(1 << ar, false)) + .collect::>()?; + fqrs.push(FriQueryRound { + initial_trees_proof, + steps, + }) + } + Ok(fqrs) + } + + /// Reads a vector of [`FriQueryRoundTarget`]s from `self`. + #[inline] + fn read_target_fri_query_rounds( + &mut self, + ) -> IoResult>> { + let num_query_rounds = self.read_usize()?; + let mut fqrs = Vec::with_capacity(num_query_rounds); + for _ in 0..num_query_rounds { + let initial_trees_proof = self.read_target_fri_initial_proof()?; + let num_steps = self.read_usize()?; + let steps = (0..num_steps) + .map(|_| self.read_target_fri_query_step::()) + .collect::, _>>()?; + fqrs.push(FriQueryRoundTarget { + initial_trees_proof, + steps, + }) + } + Ok(fqrs) + } + + /// Reads a value of type [`FriProof`] from `self` with `common_data`. + #[inline] + fn read_fri_proof( + &mut self, + common_data: &CommonCircuitData, + ) -> IoResult> + where + F: RichField + Extendable, + C: GenericConfig, + { + let config = &common_data.config; + let commit_phase_merkle_caps = (0..common_data.fri_params.reduction_arity_bits.len()) + .map(|_| self.read_merkle_cap(config.fri_config.cap_height)) + .collect::, _>>()?; + let query_round_proofs = self.read_fri_query_rounds::(common_data)?; + let final_poly = PolynomialCoeffs::new( + self.read_field_ext_vec::(common_data.fri_params.final_poly_len())?, + ); + let pow_witness = self.read_field()?; + Ok(FriProof { + commit_phase_merkle_caps, + query_round_proofs, + final_poly, + pow_witness, + }) + } + + /// Reads a value of type [`FriProofTarget`] from `self`. + #[inline] + fn read_target_fri_proof(&mut self) -> IoResult> { + let length = self.read_usize()?; + let commit_phase_merkle_caps = (0..length) + .map(|_| self.read_target_merkle_cap()) + .collect::, _>>()?; + let query_round_proofs = self.read_target_fri_query_rounds::()?; + let final_poly = PolynomialCoeffsExtTarget(self.read_target_ext_vec::()?); + let pow_witness = self.read_target()?; + + Ok(FriProofTarget { + commit_phase_merkle_caps, + query_round_proofs, + final_poly, + pow_witness, + }) + } + + fn read_fri_reduction_strategy(&mut self) -> IoResult { + let variant = self.read_u8()?; + match variant { + 0 => { + let arities = self.read_usize_vec()?; + Ok(FriReductionStrategy::Fixed(arities)) + } + 1 => { + let arity_bits = self.read_usize()?; + let final_poly_bits = self.read_usize()?; + + Ok(FriReductionStrategy::ConstantArityBits( + arity_bits, + final_poly_bits, + )) + } + 2 => { + let is_some = self.read_u8()?; + match is_some { + 0 => Ok(FriReductionStrategy::MinSize(None)), + 1 => { + let max = self.read_usize()?; + Ok(FriReductionStrategy::MinSize(Some(max))) + } + _ => Err(IoError), + } + } + _ => Err(IoError), + } + } + + fn read_fri_config(&mut self) -> IoResult { + let rate_bits = self.read_usize()?; + let cap_height = self.read_usize()?; + let num_query_rounds = self.read_usize()?; + let proof_of_work_bits = self.read_u32()?; + let reduction_strategy = self.read_fri_reduction_strategy()?; + + Ok(FriConfig { + rate_bits, + cap_height, + num_query_rounds, + proof_of_work_bits, + reduction_strategy, + }) + } + + fn read_circuit_config(&mut self) -> IoResult { + let num_wires = self.read_usize()?; + let num_routed_wires = self.read_usize()?; + let num_constants = self.read_usize()?; + let security_bits = self.read_usize()?; + let num_challenges = self.read_usize()?; + let max_quotient_degree_factor = self.read_usize()?; + let use_base_arithmetic_gate = self.read_bool()?; + let zero_knowledge = self.read_bool()?; + let fri_config = self.read_fri_config()?; + + Ok(CircuitConfig { + num_wires, + num_routed_wires, + num_constants, + security_bits, + num_challenges, + max_quotient_degree_factor, + use_base_arithmetic_gate, + zero_knowledge, + fri_config, + }) + } + + fn read_fri_params(&mut self) -> IoResult { + let config = self.read_fri_config()?; + let reduction_arity_bits = self.read_usize_vec()?; + let degree_bits = self.read_usize()?; + let hiding = self.read_bool()?; + + Ok(FriParams { + config, + reduction_arity_bits, + degree_bits, + hiding, + }) + } + + fn read_gate, const D: usize>( + &mut self, + gate_serializer: &dyn GateSerializer, + ) -> IoResult>; + + fn read_generator, const D: usize>( + &mut self, + generator_serializer: &dyn WitnessGeneratorSerializer, + common_data: &CommonCircuitData, + ) -> IoResult>; + + fn read_selectors_info(&mut self) -> IoResult { + let selector_indices = self.read_usize_vec()?; + let groups_len = self.read_usize()?; + let mut groups = Vec::with_capacity(groups_len); + for _ in 0..groups_len { + let start = self.read_usize()?; + let end = self.read_usize()?; + groups.push(Range { start, end }); + } + + Ok(SelectorsInfo { + selector_indices, + groups, + }) + } + + fn read_polynomial_batch< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( + &mut self, + ) -> IoResult> { + let poly_len = self.read_usize()?; + let mut polynomials = Vec::with_capacity(poly_len); + for _ in 0..poly_len { + let plen = self.read_usize()?; + polynomials.push(PolynomialCoeffs::new(self.read_field_vec(plen)?)); + } + + let merkle_tree = self.read_merkle_tree()?; + let degree_log = self.read_usize()?; + let rate_bits = self.read_usize()?; + let blinding = self.read_bool()?; + + Ok(PolynomialBatch { + polynomials, + merkle_tree, + degree_log, + rate_bits, + blinding, + }) + } + + fn read_common_circuit_data, const D: usize>( + &mut self, + gate_serializer: &dyn GateSerializer, + ) -> IoResult> { + let config = self.read_circuit_config()?; + let fri_params = self.read_fri_params()?; + + let gates_len = self.read_usize()?; + let mut gates = Vec::with_capacity(gates_len); + for _ in 0..gates_len { + let gate = self.read_gate::(gate_serializer)?; + gates.push(gate); + } + + let selectors_info = self.read_selectors_info()?; + let quotient_degree_factor = self.read_usize()?; + let num_gate_constraints = self.read_usize()?; + let num_constants = self.read_usize()?; + let num_public_inputs = self.read_usize()?; + + let k_is_len = self.read_usize()?; + let k_is = self.read_field_vec(k_is_len)?; + + let num_partial_products = self.read_usize()?; + + Ok(CommonCircuitData { + config, + fri_params, + gates, + selectors_info, + quotient_degree_factor, + num_gate_constraints, + num_constants, + num_public_inputs, + k_is, + num_partial_products, + }) + } + + fn read_circuit_data< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( + &mut self, + gate_serializer: &dyn GateSerializer, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult> { + let common = self.read_common_circuit_data(gate_serializer)?; + let prover_only = self.read_prover_only_circuit_data(generator_serializer, &common)?; + let verifier_only = self.read_verifier_only_circuit_data()?; + Ok(CircuitData { + prover_only, + verifier_only, + common, + }) + } + + fn read_prover_only_circuit_data< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( + &mut self, + generator_serializer: &dyn WitnessGeneratorSerializer, + cd: &CommonCircuitData, + ) -> IoResult> { + let gen_len = self.read_usize()?; + let mut generators = Vec::with_capacity(gen_len); + for _ in 0..gen_len { + generators.push(self.read_generator(generator_serializer, cd)?); + } + let map_len = self.read_usize()?; + let mut generator_indices_by_watches = BTreeMap::new(); + for _ in 0..map_len { + let k = self.read_usize()?; + generator_indices_by_watches.insert(k, self.read_usize_vec()?); + } + + let constants_sigmas_commitment = self.read_polynomial_batch()?; + let sigmas_len = self.read_usize()?; + let mut sigmas = Vec::with_capacity(sigmas_len); + for _ in 0..sigmas_len { + let sigma_len = self.read_usize()?; + sigmas.push(self.read_field_vec(sigma_len)?); + } + + let subgroup_len = self.read_usize()?; + let subgroup = self.read_field_vec(subgroup_len)?; + + let public_inputs = self.read_target_vec()?; + + let representative_map = self.read_usize_vec()?; + + let is_some = self.read_bool()?; + let fft_root_table = match is_some { + true => { + let table_len = self.read_usize()?; + let mut table = Vec::with_capacity(table_len); + for _ in 0..table_len { + let len = self.read_usize()?; + table.push(self.read_field_vec(len)?); + } + Some(table) + } + false => None, + }; + + let circuit_digest = + self.read_hash::>::HCO, >::Hasher>()?; + + Ok(ProverOnlyCircuitData { + generators, + generator_indices_by_watches, + constants_sigmas_commitment, + sigmas, + subgroup, + public_inputs, + representative_map, + fft_root_table, + circuit_digest, + }) + } + + fn read_prover_circuit_data< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( + &mut self, + gate_serializer: &dyn GateSerializer, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult> { + let common = self.read_common_circuit_data(gate_serializer)?; + let prover_only = self.read_prover_only_circuit_data(generator_serializer, &common)?; + Ok(ProverCircuitData { + prover_only, + common, + }) + } + + fn read_verifier_only_circuit_data< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( + &mut self, + ) -> IoResult> { + let height = self.read_usize()?; + let constants_sigmas_cap = self.read_merkle_cap(height)?; + let circuit_digest = + self.read_hash::>::HCO, >::Hasher>()?; + Ok(VerifierOnlyCircuitData { + constants_sigmas_cap, + circuit_digest, + }) + } + + fn read_verifier_circuit_data< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( + &mut self, + gate_serializer: &dyn GateSerializer, + ) -> IoResult> { + let verifier_only = self.read_verifier_only_circuit_data()?; + let common = self.read_common_circuit_data(gate_serializer)?; + Ok(VerifierCircuitData { + verifier_only, + common, + }) + } + + fn read_target_verifier_circuit(&mut self) -> IoResult { + let constants_sigmas_cap = self.read_target_merkle_cap()?; + let circuit_digest = self.read_target_hash()?; + Ok(VerifierCircuitTarget { + constants_sigmas_cap, + circuit_digest, + }) + } + + /// Reads a value of type [`Proof`] from `self` with `common_data`. + #[inline] + fn read_proof( + &mut self, + common_data: &CommonCircuitData, + ) -> IoResult> + where + F: RichField + Extendable, + C: GenericConfig, + { + let config = &common_data.config; + let wires_cap = self.read_merkle_cap(config.fri_config.cap_height)?; + let plonk_zs_partial_products_cap = self.read_merkle_cap(config.fri_config.cap_height)?; + let quotient_polys_cap = self.read_merkle_cap(config.fri_config.cap_height)?; + let openings = self.read_opening_set::(common_data)?; + let opening_proof = self.read_fri_proof::(common_data)?; + Ok(Proof { + wires_cap, + plonk_zs_partial_products_cap, + quotient_polys_cap, + openings, + opening_proof, + }) + } + + /// Reads a value of type [`ProofTarget`] from `self`. + #[inline] + fn read_target_proof(&mut self) -> IoResult> { + let wires_cap = self.read_target_merkle_cap()?; + let plonk_zs_partial_products_cap = self.read_target_merkle_cap()?; + let quotient_polys_cap = self.read_target_merkle_cap()?; + let openings = self.read_target_opening_set::()?; + let opening_proof = self.read_target_fri_proof::()?; + Ok(ProofTarget { + wires_cap, + plonk_zs_partial_products_cap, + quotient_polys_cap, + openings, + opening_proof, + }) + } + + /// Reads a value of type [`ProofWithPublicInputs`] from `self` with `common_data`. + #[inline] + fn read_proof_with_public_inputs( + &mut self, + common_data: &CommonCircuitData, + ) -> IoResult> + where + Self: Remaining, + F: RichField + Extendable, + C: GenericConfig, + { + let proof = self.read_proof(common_data)?; + let pi_len = self.read_usize()?; + let public_inputs = self.read_field_vec(pi_len)?; + Ok(ProofWithPublicInputs { + proof, + public_inputs, + }) + } + + /// Reads a value of type [`ProofWithPublicInputsTarget`] from `self`. + #[inline] + fn read_target_proof_with_public_inputs( + &mut self, + ) -> IoResult> { + let proof = self.read_target_proof()?; + let public_inputs = self.read_target_vec()?; + Ok(ProofWithPublicInputsTarget { + proof, + public_inputs, + }) + } + + /// Reads a value of type [`CompressedFriQueryRounds`] from `self` with `common_data`. + #[inline] + fn read_compressed_fri_query_rounds( + &mut self, + common_data: &CommonCircuitData, + ) -> IoResult> + where + F: RichField + Extendable, + C: GenericConfig, + { + let config = &common_data.config; + let original_indices = (0..config.fri_config.num_query_rounds) + .map(|_| self.read_u32().map(|i| i as usize)) + .collect::, _>>()?; + let mut indices = original_indices.clone(); + indices.sort_unstable(); + indices.dedup(); + let mut pairs = Vec::new(); + for &i in &indices { + pairs.push((i, self.read_fri_initial_proof::(common_data)?)); + } + let initial_trees_proofs = HashMap::from_iter(pairs); + + let mut steps = Vec::with_capacity(common_data.fri_params.reduction_arity_bits.len()); + for &a in &common_data.fri_params.reduction_arity_bits { + indices.iter_mut().for_each(|x| { + *x >>= a; + }); + indices.dedup(); + let query_steps = (0..indices.len()) + .map(|_| self.read_fri_query_step::(1 << a, true)) + .collect::, _>>()?; + steps.push( + indices + .iter() + .copied() + .zip(query_steps) + .collect::>(), + ); + } + + Ok(CompressedFriQueryRounds { + indices: original_indices, + initial_trees_proofs, + steps, + }) + } + + /// Reads a value of type [`CompressedFriProof`] from `self` with `common_data`. + #[inline] + fn read_compressed_fri_proof( + &mut self, + common_data: &CommonCircuitData, + ) -> IoResult> + where + F: RichField + Extendable, + C: GenericConfig, + { + let config = &common_data.config; + let commit_phase_merkle_caps = (0..common_data.fri_params.reduction_arity_bits.len()) + .map(|_| self.read_merkle_cap(config.fri_config.cap_height)) + .collect::, _>>()?; + let query_round_proofs = self.read_compressed_fri_query_rounds::(common_data)?; + let final_poly = PolynomialCoeffs::new( + self.read_field_ext_vec::(common_data.fri_params.final_poly_len())?, + ); + let pow_witness = self.read_field()?; + Ok(CompressedFriProof { + commit_phase_merkle_caps, + query_round_proofs, + final_poly, + pow_witness, + }) + } + + /// Reads a value of type [`CompressedProof`] from `self` with `common_data`. + #[inline] + fn read_compressed_proof( + &mut self, + common_data: &CommonCircuitData, + ) -> IoResult> + where + F: RichField + Extendable, + C: GenericConfig, + { + let config = &common_data.config; + let wires_cap = self.read_merkle_cap(config.fri_config.cap_height)?; + let plonk_zs_partial_products_cap = self.read_merkle_cap(config.fri_config.cap_height)?; + let quotient_polys_cap = self.read_merkle_cap(config.fri_config.cap_height)?; + let openings = self.read_opening_set::(common_data)?; + let opening_proof = self.read_compressed_fri_proof::(common_data)?; + Ok(CompressedProof { + wires_cap, + plonk_zs_partial_products_cap, + quotient_polys_cap, + openings, + opening_proof, + }) + } + + /// Reads a value of type [`CompressedProofWithPublicInputs`] from `self` with `common_data`. + #[inline] + fn read_compressed_proof_with_public_inputs( + &mut self, + common_data: &CommonCircuitData, + ) -> IoResult> + where + Self: Remaining, + F: RichField + Extendable, + C: GenericConfig, + { + let proof = self.read_compressed_proof(common_data)?; + let public_inputs = self.read_field_vec(self.remaining() / size_of::())?; + Ok(CompressedProofWithPublicInputs { + proof, + public_inputs, + }) + } +} + +/// Writing +pub trait Write { + /// Error Type + type Error; + + /// Writes all `bytes` to `self`. + fn write_all(&mut self, bytes: &[u8]) -> IoResult<()>; + + /// Writes a bool `x` to `self`. + #[inline] + fn write_bool(&mut self, x: bool) -> IoResult<()> { + self.write_u8(u8::from(x)) + } + + /// Writes a target bool `x` to `self`. + #[inline] + fn write_target_bool(&mut self, x: BoolTarget) -> IoResult<()> { + self.write_target(x.target) + } + + /// Writes a vector of BoolTarget `v` to `self.` + #[inline] + fn write_target_bool_vec(&mut self, v: &[BoolTarget]) -> IoResult<()> { + self.write_usize(v.len())?; + for &elem in v.iter() { + self.write_target_bool(elem)?; + } + + Ok(()) + } + + /// Writes a byte `x` to `self`. + #[inline] + fn write_u8(&mut self, x: u8) -> IoResult<()> { + self.write_all(&[x]) + } + + /// Writes a word `x` to `self.` + #[inline] + fn write_u32(&mut self, x: u32) -> IoResult<()> { + self.write_all(&x.to_le_bytes()) + } + + /// Writes a word `x` to `self.` + #[inline] + fn write_usize(&mut self, x: usize) -> IoResult<()> { + self.write_all(&(x as u64).to_le_bytes()) + } + + /// Writes a vector of words `v` to `self.` + #[inline] + fn write_usize_vec(&mut self, v: &[usize]) -> IoResult<()> { + self.write_usize(v.len())?; + for &elem in v.iter() { + self.write_usize(elem)?; + } + + Ok(()) + } + + /// Writes an element `x` from the field `F` to `self`. + #[inline] + fn write_field(&mut self, x: F) -> IoResult<()> + where + F: PrimeField64, + { + self.write_all(&x.to_canonical_u64().to_le_bytes()) + } + + /// Writes a vector `v` of elements from the field `F` to `self`. + #[inline] + fn write_field_vec(&mut self, v: &[F]) -> IoResult<()> + where + F: PrimeField64, + { + for &a in v { + self.write_field(a)?; + } + Ok(()) + } + + /// Writes an element `x` from the field extension of `F` to `self`. + #[inline] + fn write_field_ext(&mut self, x: F::Extension) -> IoResult<()> + where + F: RichField + Extendable, + { + for &a in &x.to_basefield_array() { + self.write_field(a)?; + } + Ok(()) + } + + /// Writes a vector `v` of elements from the field extension of `F` to `self`. + #[inline] + fn write_field_ext_vec(&mut self, v: &[F::Extension]) -> IoResult<()> + where + F: RichField + Extendable, + { + for &a in v { + self.write_field_ext::(a)?; + } + Ok(()) + } + + /// Writes a Target `x` to `self.` + #[inline] + fn write_target(&mut self, x: Target) -> IoResult<()> { + match x { + Target::Wire(Wire { row, column }) => { + self.write_bool(true)?; + self.write_usize(row)?; + self.write_usize(column)?; + } + Target::VirtualTarget { index } => { + self.write_bool(false)?; + self.write_usize(index)?; + } + }; + + Ok(()) + } + + /// Writes an ExtensionTarget `x` to `self.` + #[inline] + fn write_target_ext(&mut self, x: ExtensionTarget) -> IoResult<()> { + for &elem in x.0.iter() { + self.write_target(elem)?; + } + + Ok(()) + } + + /// Writes a vector of Target `v` to `self.` + #[inline] + fn write_target_vec(&mut self, v: &[Target]) -> IoResult<()> { + self.write_usize(v.len())?; + for &elem in v.iter() { + self.write_target(elem)?; + } + + Ok(()) + } + + /// Writes a vector of ExtensionTarget `v` to `self.` + #[inline] + fn write_target_ext_vec(&mut self, v: &[ExtensionTarget]) -> IoResult<()> { + self.write_usize(v.len())?; + for &elem in v.iter() { + self.write_target_ext(elem)?; + } + + Ok(()) + } + + /// Writes a hash `h` to `self`. + #[inline] + fn write_hash(&mut self, h: H::Hash) -> IoResult<()> + where + F: RichField, + HC: HashConfig, + H: Hasher, + { + self.write_all(&h.to_bytes()) + } + + /// Writes a HashOutTarget `h` to `self`. + #[inline] + fn write_target_hash(&mut self, h: &HashOutTarget) -> IoResult<()> { + for r in h.elements.iter() { + self.write_target(*r)?; + } + + Ok(()) + } + + /// Writes a vector of Hash `v` to `self.` + #[inline] + fn write_hash_vec(&mut self, v: &[H::Hash]) -> IoResult<()> + where + F: RichField, + HC: HashConfig, + H: Hasher, + { + self.write_usize(v.len())?; + for &elem in v.iter() { + self.write_hash::(elem)?; + } + + Ok(()) + } + + /// Writes `cap`, a value of type [`MerkleCap`], to `self`. + #[inline] + fn write_merkle_cap(&mut self, cap: &MerkleCap) -> IoResult<()> + where + F: RichField, + HC: HashConfig, + H: Hasher, + { + for &a in &cap.0 { + self.write_hash::(a)?; + } + Ok(()) + } + + /// Writes `cap`, a value of type [`MerkleCapTarget`], to `self`. + #[inline] + fn write_target_merkle_cap(&mut self, cap: &MerkleCapTarget) -> IoResult<()> { + self.write_usize(cap.0.len())?; + for a in &cap.0 { + self.write_target_hash(a)?; + } + Ok(()) + } + + /// Writes `tree`, a value of type [`MerkleTree`], to `self`. + #[inline] + fn write_merkle_tree(&mut self, tree: &MerkleTree) -> IoResult<()> + where + F: RichField, + HC: HashConfig, + H: Hasher, + { + self.write_usize(tree.leaves.len())?; + for i in 0..tree.leaves.len() { + self.write_usize(tree.leaves[i].len())?; + self.write_field_vec(&tree.leaves[i])?; + } + self.write_hash_vec::(&tree.digests)?; + self.write_usize(tree.cap.height())?; + self.write_merkle_cap(&tree.cap)?; + + Ok(()) + } + + /// Writes a value `os` of type [`OpeningSet`] to `self.` + #[inline] + fn write_opening_set(&mut self, os: &OpeningSet) -> IoResult<()> + where + F: RichField + Extendable, + { + self.write_field_ext_vec::(&os.constants)?; + self.write_field_ext_vec::(&os.plonk_sigmas)?; + self.write_field_ext_vec::(&os.wires)?; + self.write_field_ext_vec::(&os.plonk_zs)?; + self.write_field_ext_vec::(&os.plonk_zs_next)?; + self.write_field_ext_vec::(&os.partial_products)?; + self.write_field_ext_vec::(&os.quotient_polys) + } + + /// Writes a value `os` of type [`OpeningSet`] to `self.` + #[inline] + fn write_target_opening_set( + &mut self, + os: &OpeningSetTarget, + ) -> IoResult<()> { + self.write_target_ext_vec::(&os.constants)?; + self.write_target_ext_vec::(&os.plonk_sigmas)?; + self.write_target_ext_vec::(&os.wires)?; + self.write_target_ext_vec::(&os.plonk_zs)?; + self.write_target_ext_vec::(&os.plonk_zs_next)?; + self.write_target_ext_vec::(&os.partial_products)?; + self.write_target_ext_vec::(&os.quotient_polys) + } + + /// Writes a value `p` of type [`MerkleProof`] to `self.` + #[inline] + fn write_merkle_proof(&mut self, p: &MerkleProof) -> IoResult<()> + where + F: RichField, + HC: HashConfig, + H: Hasher, + { + let length = p.siblings.len(); + self.write_u8( + length + .try_into() + .expect("Merkle proof length must fit in u8."), + )?; + for &h in &p.siblings { + self.write_hash::(h)?; + } + Ok(()) + } + + /// Writes a value `pt` of type [`MerkleProofTarget`] to `self.` + #[inline] + fn write_target_merkle_proof(&mut self, pt: &MerkleProofTarget) -> IoResult<()> { + let length = pt.siblings.len(); + self.write_u8( + length + .try_into() + .expect("Merkle proof length must fit in u8."), + )?; + for h in &pt.siblings { + self.write_target_hash(h)?; + } + Ok(()) + } + + /// Writes a value `fitp` of type [`FriInitialTreeProof`] to `self.` + #[inline] + fn write_fri_initial_proof( + &mut self, + fitp: &FriInitialTreeProof, + ) -> IoResult<()> + where + F: RichField + Extendable, + C: GenericConfig, + { + for (v, p) in &fitp.evals_proofs { + self.write_field_vec(v)?; + self.write_merkle_proof(p)?; + } + Ok(()) + } + + /// Writes a value `fitpt` of type [`FriInitialTreeProofTarget`] to `self.` + #[inline] + fn write_target_fri_initial_proof( + &mut self, + fitpt: &FriInitialTreeProofTarget, + ) -> IoResult<()> { + self.write_usize(fitpt.evals_proofs.len())?; + for (v, p) in &fitpt.evals_proofs { + self.write_target_vec(v)?; + self.write_target_merkle_proof(p)?; + } + Ok(()) + } + + /// Writes a value `fqs` of type [`FriQueryStep`] to `self.` + #[inline] + fn write_fri_query_step( + &mut self, + fqs: &FriQueryStep, + ) -> IoResult<()> + where + F: RichField + Extendable, + C: GenericConfig, + { + self.write_field_ext_vec::(&fqs.evals)?; + self.write_merkle_proof(&fqs.merkle_proof) + } + + /// Writes a value `fqst` of type [`FriQueryStepTarget`] to `self.` + #[inline] + fn write_target_fri_query_step( + &mut self, + fqst: &FriQueryStepTarget, + ) -> IoResult<()> { + self.write_target_ext_vec(&fqst.evals)?; + self.write_target_merkle_proof(&fqst.merkle_proof) + } + + /// Writes a value `fqrs` of type [`FriQueryRound`] to `self.` + #[inline] + fn write_fri_query_rounds( + &mut self, + fqrs: &[FriQueryRound], + ) -> IoResult<()> + where + F: RichField + Extendable, + C: GenericConfig, + { + for fqr in fqrs { + self.write_fri_initial_proof::(&fqr.initial_trees_proof)?; + for fqs in &fqr.steps { + self.write_fri_query_step::(fqs)?; + } + } + Ok(()) + } + + /// Writes a value `fqrst` of type [`FriQueryRoundTarget`] to `self.` + #[inline] + fn write_target_fri_query_rounds( + &mut self, + fqrst: &[FriQueryRoundTarget], + ) -> IoResult<()> { + self.write_usize(fqrst.len())?; + for fqr in fqrst { + self.write_target_fri_initial_proof(&fqr.initial_trees_proof)?; + self.write_usize(fqr.steps.len())?; + for fqs in &fqr.steps { + self.write_target_fri_query_step::(fqs)?; + } + } + Ok(()) + } + + /// Writes a value `fp` of type [`FriProof`] to `self.` + #[inline] + fn write_fri_proof( + &mut self, + fp: &FriProof, + ) -> IoResult<()> + where + F: RichField + Extendable, + C: GenericConfig, + { + for cap in &fp.commit_phase_merkle_caps { + self.write_merkle_cap(cap)?; + } + self.write_fri_query_rounds::(&fp.query_round_proofs)?; + self.write_field_ext_vec::(&fp.final_poly.coeffs)?; + self.write_field(fp.pow_witness) + } + + /// Writes a value `fpt` of type [`FriProofTarget`] to `self.` + #[inline] + fn write_target_fri_proof(&mut self, fpt: &FriProofTarget) -> IoResult<()> { + self.write_usize(fpt.commit_phase_merkle_caps.len())?; + for cap in &fpt.commit_phase_merkle_caps { + self.write_target_merkle_cap(cap)?; + } + self.write_target_fri_query_rounds::(&fpt.query_round_proofs)?; + self.write_target_ext_vec::(&fpt.final_poly.0)?; + self.write_target(fpt.pow_witness) + } + + fn write_fri_reduction_strategy( + &mut self, + reduction_strategy: &FriReductionStrategy, + ) -> IoResult<()> { + match reduction_strategy { + FriReductionStrategy::Fixed(seq) => { + self.write_u8(0)?; + self.write_usize_vec(seq.as_slice())?; + + Ok(()) + } + FriReductionStrategy::ConstantArityBits(arity_bits, final_poly_bits) => { + self.write_u8(1)?; + self.write_usize(*arity_bits)?; + self.write_usize(*final_poly_bits)?; + + Ok(()) + } + FriReductionStrategy::MinSize(max) => { + self.write_u8(2)?; + if let Some(max) = max { + self.write_u8(1)?; + self.write_usize(*max)?; + } else { + self.write_u8(0)?; + } + + Ok(()) + } + } + } + + fn write_fri_config(&mut self, config: &FriConfig) -> IoResult<()> { + let FriConfig { + rate_bits, + cap_height, + num_query_rounds, + proof_of_work_bits, + reduction_strategy, + } = &config; + + self.write_usize(*rate_bits)?; + self.write_usize(*cap_height)?; + self.write_usize(*num_query_rounds)?; + self.write_u32(*proof_of_work_bits)?; + self.write_fri_reduction_strategy(reduction_strategy)?; + + Ok(()) + } + + fn write_fri_params(&mut self, fri_params: &FriParams) -> IoResult<()> { + let FriParams { + config, + reduction_arity_bits, + degree_bits, + hiding, + } = fri_params; + + self.write_fri_config(config)?; + self.write_usize_vec(reduction_arity_bits.as_slice())?; + self.write_usize(*degree_bits)?; + self.write_bool(*hiding)?; + + Ok(()) + } + + fn write_circuit_config(&mut self, config: &CircuitConfig) -> IoResult<()> { + let CircuitConfig { + num_wires, + num_routed_wires, + num_constants, + security_bits, + num_challenges, + max_quotient_degree_factor, + use_base_arithmetic_gate, + zero_knowledge, + fri_config, + } = config; + + self.write_usize(*num_wires)?; + self.write_usize(*num_routed_wires)?; + self.write_usize(*num_constants)?; + self.write_usize(*security_bits)?; + self.write_usize(*num_challenges)?; + self.write_usize(*max_quotient_degree_factor)?; + self.write_bool(*use_base_arithmetic_gate)?; + self.write_bool(*zero_knowledge)?; + self.write_fri_config(fri_config)?; + + Ok(()) + } + + fn write_gate, const D: usize>( + &mut self, + gate: &GateRef, + gate_serializer: &dyn GateSerializer, + ) -> IoResult<()>; + + fn write_generator, const D: usize>( + &mut self, + generator: &WitnessGeneratorRef, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult<()>; + + fn write_selectors_info(&mut self, selectors_info: &SelectorsInfo) -> IoResult<()> { + let SelectorsInfo { + selector_indices, + groups, + } = selectors_info; + + self.write_usize_vec(selector_indices.as_slice())?; + self.write_usize(groups.len())?; + for group in groups.iter() { + self.write_usize(group.start)?; + self.write_usize(group.end)?; + } + Ok(()) + } + + fn write_polynomial_batch< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( + &mut self, + poly_batch: &PolynomialBatch, + ) -> IoResult<()> { + self.write_usize(poly_batch.polynomials.len())?; + for i in 0..poly_batch.polynomials.len() { + self.write_usize(poly_batch.polynomials[i].coeffs.len())?; + self.write_field_vec(&poly_batch.polynomials[i].coeffs)?; + } + self.write_merkle_tree(&poly_batch.merkle_tree)?; + self.write_usize(poly_batch.degree_log)?; + self.write_usize(poly_batch.rate_bits)?; + self.write_bool(poly_batch.blinding)?; + + Ok(()) + } + + fn write_common_circuit_data, const D: usize>( + &mut self, + common_data: &CommonCircuitData, + gate_serializer: &dyn GateSerializer, + ) -> IoResult<()> { + let CommonCircuitData { + config, + fri_params, + gates, + selectors_info, + quotient_degree_factor, + num_gate_constraints, + num_constants, + num_public_inputs, + k_is, + num_partial_products, + } = common_data; + + self.write_circuit_config(config)?; + self.write_fri_params(fri_params)?; + + self.write_usize(gates.len())?; + for gate in gates.iter() { + self.write_gate::(gate, gate_serializer)?; + } + + self.write_selectors_info(selectors_info)?; + self.write_usize(*quotient_degree_factor)?; + self.write_usize(*num_gate_constraints)?; + self.write_usize(*num_constants)?; + self.write_usize(*num_public_inputs)?; + + self.write_usize(k_is.len())?; + self.write_field_vec(k_is.as_slice())?; + + self.write_usize(*num_partial_products)?; + + Ok(()) + } + + fn write_circuit_data< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( + &mut self, + circuit_data: &CircuitData, + gate_serializer: &dyn GateSerializer, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult<()> { + self.write_common_circuit_data(&circuit_data.common, gate_serializer)?; + self.write_prover_only_circuit_data(&circuit_data.prover_only, generator_serializer)?; + self.write_verifier_only_circuit_data(&circuit_data.verifier_only) + } + + fn write_prover_only_circuit_data< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( + &mut self, + prover_only_circuit_data: &ProverOnlyCircuitData, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult<()> { + let ProverOnlyCircuitData { + generators, + generator_indices_by_watches, + constants_sigmas_commitment, + sigmas, + subgroup, + public_inputs, + representative_map, + fft_root_table, + circuit_digest, + } = prover_only_circuit_data; + + self.write_usize(generators.len())?; + for generator in generators.iter() { + self.write_generator::(generator, generator_serializer)?; + } + + self.write_usize(generator_indices_by_watches.len())?; + for (k, v) in generator_indices_by_watches { + self.write_usize(*k)?; + self.write_usize_vec(v)?; + } + + self.write_polynomial_batch(constants_sigmas_commitment)?; + self.write_usize(sigmas.len())?; + for i in 0..sigmas.len() { + self.write_usize(sigmas[i].len())?; + self.write_field_vec(&sigmas[i])?; + } + self.write_usize(subgroup.len())?; + self.write_field_vec(subgroup)?; + self.write_target_vec(public_inputs)?; + self.write_usize_vec(representative_map)?; + + match fft_root_table { + Some(table) => { + self.write_bool(true)?; + self.write_usize(table.len())?; + for i in 0..table.len() { + self.write_usize(table[i].len())?; + self.write_field_vec(&table[i])?; + } + } + None => self.write_bool(false)?, + } + + self.write_hash::>::HCO, >::Hasher>( + *circuit_digest, + )?; + + Ok(()) + } + + fn write_prover_circuit_data< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( + &mut self, + prover_circuit_data: &ProverCircuitData, + gate_serializer: &dyn GateSerializer, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult<()> { + self.write_common_circuit_data(&prover_circuit_data.common, gate_serializer)?; + self.write_prover_only_circuit_data(&prover_circuit_data.prover_only, generator_serializer) + } + + fn write_verifier_only_circuit_data< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( + &mut self, + verifier_only_circuit_data: &VerifierOnlyCircuitData, + ) -> IoResult<()> { + let VerifierOnlyCircuitData { + constants_sigmas_cap, + circuit_digest, + } = verifier_only_circuit_data; + + self.write_usize(constants_sigmas_cap.height())?; + self.write_merkle_cap(constants_sigmas_cap)?; + self.write_hash::>::HCO, >::Hasher>( + *circuit_digest, + )?; + + Ok(()) + } + + fn write_verifier_circuit_data< + F: RichField + Extendable, + C: GenericConfig, + const D: usize, + >( + &mut self, + verifier_circuit_data: &VerifierCircuitData, + gate_serializer: &dyn GateSerializer, + ) -> IoResult<()> { + self.write_verifier_only_circuit_data(&verifier_circuit_data.verifier_only)?; + self.write_common_circuit_data(&verifier_circuit_data.common, gate_serializer) + } + + fn write_target_verifier_circuit( + &mut self, + verifier_circuit: &VerifierCircuitTarget, + ) -> IoResult<()> { + let VerifierCircuitTarget { + constants_sigmas_cap, + circuit_digest, + } = verifier_circuit; + + self.write_target_merkle_cap(constants_sigmas_cap)?; + self.write_target_hash(circuit_digest)?; + + Ok(()) + } + + /// Writes a value `proof` of type [`Proof`] to `self.` + #[inline] + fn write_proof(&mut self, proof: &Proof) -> IoResult<()> + where + F: RichField + Extendable, + C: GenericConfig, + { + self.write_merkle_cap(&proof.wires_cap)?; + self.write_merkle_cap(&proof.plonk_zs_partial_products_cap)?; + self.write_merkle_cap(&proof.quotient_polys_cap)?; + self.write_opening_set(&proof.openings)?; + self.write_fri_proof::(&proof.opening_proof) + } + + /// Writes a value `proof` of type [`Proof`] to `self.` + #[inline] + fn write_target_proof(&mut self, proof: &ProofTarget) -> IoResult<()> { + self.write_target_merkle_cap(&proof.wires_cap)?; + self.write_target_merkle_cap(&proof.plonk_zs_partial_products_cap)?; + self.write_target_merkle_cap(&proof.quotient_polys_cap)?; + self.write_target_opening_set(&proof.openings)?; + self.write_target_fri_proof::(&proof.opening_proof) + } + + /// Writes a value `proof_with_pis` of type [`ProofWithPublicInputs`] to `self.` + #[inline] + fn write_proof_with_public_inputs( + &mut self, + proof_with_pis: &ProofWithPublicInputs, + ) -> IoResult<()> + where + F: RichField + Extendable, + C: GenericConfig, + { + let ProofWithPublicInputs { + proof, + public_inputs, + } = proof_with_pis; + self.write_proof(proof)?; + self.write_usize(public_inputs.len())?; + self.write_field_vec(public_inputs) + } + + /// Writes a value `proof_with_pis` of type [`ProofWithPublicInputsTarget`] to `self.` + #[inline] + fn write_target_proof_with_public_inputs( + &mut self, + proof_with_pis: &ProofWithPublicInputsTarget, + ) -> IoResult<()> { + let ProofWithPublicInputsTarget { + proof, + public_inputs, + } = proof_with_pis; + self.write_target_proof(proof)?; + self.write_target_vec(public_inputs) + } + + /// Writes a value `cfqrs` of type [`CompressedFriQueryRounds`] to `self.` + #[inline] + fn write_compressed_fri_query_rounds( + &mut self, + cfqrs: &CompressedFriQueryRounds, + ) -> IoResult<()> + where + F: RichField + Extendable, + C: GenericConfig, + { + for &i in &cfqrs.indices { + self.write_u32(i as u32)?; + } + let mut initial_trees_proofs = cfqrs.initial_trees_proofs.iter().collect::>(); + initial_trees_proofs.sort_by_key(|&x| x.0); + for (_, itp) in initial_trees_proofs { + self.write_fri_initial_proof::(itp)?; + } + for h in &cfqrs.steps { + let mut fri_query_steps = h.iter().collect::>(); + fri_query_steps.sort_by_key(|&x| x.0); + for (_, fqs) in fri_query_steps { + self.write_fri_query_step::(fqs)?; + } + } + Ok(()) + } + + /// Writes a value `fq` of type [`CompressedFriProof`] to `self.` + #[inline] + fn write_compressed_fri_proof( + &mut self, + fp: &CompressedFriProof, + ) -> IoResult<()> + where + F: RichField + Extendable, + C: GenericConfig, + { + for cap in &fp.commit_phase_merkle_caps { + self.write_merkle_cap(cap)?; + } + self.write_compressed_fri_query_rounds::(&fp.query_round_proofs)?; + self.write_field_ext_vec::(&fp.final_poly.coeffs)?; + self.write_field(fp.pow_witness) + } + + /// Writes a value `proof` of type [`CompressedProof`] to `self.` + #[inline] + fn write_compressed_proof( + &mut self, + proof: &CompressedProof, + ) -> IoResult<()> + where + F: RichField + Extendable, + C: GenericConfig, + { + self.write_merkle_cap(&proof.wires_cap)?; + self.write_merkle_cap(&proof.plonk_zs_partial_products_cap)?; + self.write_merkle_cap(&proof.quotient_polys_cap)?; + self.write_opening_set(&proof.openings)?; + self.write_compressed_fri_proof::(&proof.opening_proof) + } + + /// Writes a value `proof_with_pis` of type [`CompressedProofWithPublicInputs`] to `self.` + #[inline] + fn write_compressed_proof_with_public_inputs( + &mut self, + proof_with_pis: &CompressedProofWithPublicInputs, + ) -> IoResult<()> + where + F: RichField + Extendable, + C: GenericConfig, + { + let CompressedProofWithPublicInputs { + proof, + public_inputs, + } = proof_with_pis; + self.write_compressed_proof(proof)?; + self.write_field_vec(public_inputs) + } +} + +impl Write for Vec { + type Error = Infallible; + + #[inline] + fn write_all(&mut self, bytes: &[u8]) -> IoResult<()> { + self.extend_from_slice(bytes); + Ok(()) + } + + fn write_gate, const D: usize>( + &mut self, + gate: &GateRef, + gate_serializer: &dyn GateSerializer, + ) -> IoResult<()> { + gate_serializer.write_gate(self, gate) + } + + fn write_generator, const D: usize>( + &mut self, + generator: &WitnessGeneratorRef, + generator_serializer: &dyn WitnessGeneratorSerializer, + ) -> IoResult<()> { + generator_serializer.write_generator(self, generator) + } +} + +/// Buffer +#[cfg(feature = "std")] +#[derive(Debug)] +pub struct Buffer { + bytes: Vec, + pos: usize, +} + +#[cfg(feature = "std")] +impl Buffer { + /// Builds a new [`Buffer`] over `buffer`. + #[inline] + pub fn new(bytes: Vec) -> Self { + Self { bytes, pos: 0 } + } + + /// Returns the inner position. + #[inline] + pub fn pos(&self) -> usize { + self.pos + } + + /// Returns the inner buffer. + #[inline] + pub fn bytes(&self) -> Vec { + self.bytes.clone() + } + + /// Returns the inner unread buffer. + #[inline] + pub fn unread_bytes(&self) -> Vec { + self.bytes[self.pos..].to_vec() + } +} + +#[cfg(feature = "std")] +impl Remaining for Buffer { + fn remaining(&self) -> usize { + self.bytes.len() - self.pos + } +} + +#[cfg(feature = "std")] +impl Read for Buffer { + #[inline] + fn read_exact(&mut self, bytes: &mut [u8]) -> IoResult<()> { + let n = bytes.len(); + if self.remaining() < n { + Err(IoError) + } else { + bytes.copy_from_slice(&self.bytes[self.pos..][..n]); + self.pos += n; + Ok(()) + } + } + + fn read_gate, const D: usize>( + &mut self, + gate_serializer: &dyn GateSerializer, + ) -> IoResult> { + gate_serializer.read_gate(self) + } + + fn read_generator, const D: usize>( + &mut self, + generator_serializer: &dyn WitnessGeneratorSerializer, + common_data: &CommonCircuitData, + ) -> IoResult> { + generator_serializer.read_generator(self, common_data) + } +}