diff --git a/evm/src/cpu/columns/mod.rs b/evm/src/cpu/columns/mod.rs index 94b07dd2..825ce9ca 100644 --- a/evm/src/cpu/columns/mod.rs +++ b/evm/src/cpu/columns/mod.rs @@ -75,8 +75,8 @@ pub(crate) struct CpuColumnsView { /// If CPU cycle: We're in kernel (privileged) mode. pub is_kernel_mode: T, - /// If CPU cycle: Gas counter, split in two 32-bit limbs in little-endian order. - pub gas: [T; 2], + /// If CPU cycle: Gas counter. + pub gas: T, /// If CPU cycle: flags for EVM instructions (a few cannot be shared; see the comments in /// `OpsColumnsView`). diff --git a/evm/src/cpu/gas.rs b/evm/src/cpu/gas.rs index db4e9941..33ef9364 100644 --- a/evm/src/cpu/gas.rs +++ b/evm/src/cpu/gas.rs @@ -66,15 +66,11 @@ fn eval_packed_accumulate( }) .sum(); - // TODO: This may cause soundness issue if the recomputed gas (as u64) overflows the field size. - // This is fine as we are only using two-limbs for testing purposes (to support all cases from - // the Ethereum test suite). - // This should be changed back to a single 32-bit limb before going into production! - let gas_diff = nv.gas[1] * P::Scalar::from_canonical_u64(1 << 32) + nv.gas[0] - - (lv.gas[1] * P::Scalar::from_canonical_u64(1 << 32) + lv.gas[0]); - let constr = gas_diff - gas_used; + let constr = nv.gas - (lv.gas + gas_used); yield_constr.constraint_transition(filter * constr); + let gas_diff = nv.gas - lv.gas; + for (maybe_cost, op_flag) in izip!(SIMPLE_OPCODES.into_iter(), lv.op.into_iter()) { if let Some(cost) = maybe_cost { let cost = P::Scalar::from_canonical_u32(cost); @@ -129,8 +125,7 @@ fn eval_packed_init( // `nv` is the first row that executes an instruction. let filter = (is_cpu_cycle - P::ONES) * is_cpu_cycle_next; // Set initial gas to zero. - yield_constr.constraint_transition(filter * nv.gas[0]); - yield_constr.constraint_transition(filter * nv.gas[1]); + yield_constr.constraint_transition(filter * nv.gas); } /// Evaluate the gas constraints for the opcodes that cost a constant gas. @@ -174,22 +169,16 @@ fn eval_ext_circuit_accumulate, const D: usize>( }, ); - // TODO: This may cause soundness issue if the recomputed gas (as u64) overflows the field size. - // This is fine as we are only using two-limbs for testing purposes (to support all cases from - // the Ethereum test suite). - // This should be changed back to a single 32-bit limb before going into production! - let nv_gas = - builder.mul_const_add_extension(F::from_canonical_u64(1 << 32), nv.gas[1], nv.gas[0]); - let lv_gas = - builder.mul_const_add_extension(F::from_canonical_u64(1 << 32), lv.gas[1], lv.gas[0]); - let nv_lv_diff = builder.sub_extension(nv_gas, lv_gas); - - let constr = builder.sub_extension(nv_lv_diff, gas_used); + let constr = { + let t = builder.add_extension(lv.gas, gas_used); + builder.sub_extension(nv.gas, t) + }; let filtered_constr = builder.mul_extension(filter, constr); yield_constr.constraint_transition(builder, filtered_constr); for (maybe_cost, op_flag) in izip!(SIMPLE_OPCODES.into_iter(), lv.op.into_iter()) { if let Some(cost) = maybe_cost { + let nv_lv_diff = builder.sub_extension(nv.gas, lv.gas); let constr = builder.arithmetic_extension( F::ONE, -F::from_canonical_u32(cost), @@ -210,6 +199,7 @@ fn eval_ext_circuit_accumulate, const D: usize>( let jump_gas_cost = builder.add_const_extension(jump_gas_cost, F::from_canonical_u32(G_MID.unwrap())); + let nv_lv_diff = builder.sub_extension(nv.gas, lv.gas); let gas_diff = builder.sub_extension(nv_lv_diff, jump_gas_cost); let constr = builder.mul_extension(filter, gas_diff); yield_constr.constraint_transition(builder, constr); @@ -229,6 +219,7 @@ fn eval_ext_circuit_accumulate, const D: usize>( let binary_op_cost = builder.add_const_extension(binary_op_cost, F::from_canonical_u32(G_LOW.unwrap())); + let nv_lv_diff = builder.sub_extension(nv.gas, lv.gas); let gas_diff = builder.sub_extension(nv_lv_diff, binary_op_cost); let constr = builder.mul_extension(filter, gas_diff); yield_constr.constraint_transition(builder, constr); @@ -243,6 +234,7 @@ fn eval_ext_circuit_accumulate, const D: usize>( let ternary_op_cost = builder.add_const_extension(ternary_op_cost, F::from_canonical_u32(G_MID.unwrap())); + let nv_lv_diff = builder.sub_extension(nv.gas, lv.gas); let gas_diff = builder.sub_extension(nv_lv_diff, ternary_op_cost); let constr = builder.mul_extension(filter, gas_diff); yield_constr.constraint_transition(builder, constr); @@ -292,9 +284,7 @@ fn eval_ext_circuit_init, const D: usize>( let is_cpu_cycle_next = builder.add_many_extension(COL_MAP.op.iter().map(|&col_i| nv[col_i])); let filter = builder.mul_sub_extension(is_cpu_cycle, is_cpu_cycle_next, is_cpu_cycle_next); // Set initial gas to zero. - let constr = builder.mul_extension(filter, nv.gas[0]); - yield_constr.constraint_transition(builder, constr); - let constr = builder.mul_extension(filter, nv.gas[1]); + let constr = builder.mul_extension(filter, nv.gas); yield_constr.constraint_transition(builder, constr); } diff --git a/evm/src/cpu/jumps.rs b/evm/src/cpu/jumps.rs index 2eb865e5..f2285c0a 100644 --- a/evm/src/cpu/jumps.rs +++ b/evm/src/cpu/jumps.rs @@ -23,8 +23,9 @@ pub(crate) fn eval_packed_exit_kernel( // but we trust the kernel to set them to zero). yield_constr.constraint_transition(filter * (input[0] - nv.program_counter)); yield_constr.constraint_transition(filter * (input[1] - nv.is_kernel_mode)); - yield_constr.constraint_transition(filter * (input[6] - nv.gas[0])); - yield_constr.constraint_transition(filter * (input[7] - nv.gas[1])); + yield_constr.constraint_transition(filter * (input[6] - nv.gas)); + // High limb of gas must be 0 for convenient detection of overflow. + yield_constr.constraint(filter * input[7]); } /// Circuit version of `eval_packed_exit_kernel`. @@ -51,14 +52,14 @@ pub(crate) fn eval_ext_circuit_exit_kernel, const D yield_constr.constraint_transition(builder, kernel_constr); { - let diff = builder.sub_extension(input[6], nv.gas[0]); + let diff = builder.sub_extension(input[6], nv.gas); let constr = builder.mul_extension(filter, diff); yield_constr.constraint_transition(builder, constr); } { - let diff = builder.sub_extension(input[7], nv.gas[1]); - let constr = builder.mul_extension(filter, diff); - yield_constr.constraint_transition(builder, constr); + // High limb of gas must be 0 for convenient detection of overflow. + let constr = builder.mul_extension(filter, input[7]); + yield_constr.constraint(builder, constr); } } diff --git a/evm/src/cpu/syscalls_exceptions.rs b/evm/src/cpu/syscalls_exceptions.rs index 4fc71258..45302b9e 100644 --- a/evm/src/cpu/syscalls_exceptions.rs +++ b/evm/src/cpu/syscalls_exceptions.rs @@ -101,8 +101,7 @@ pub(crate) fn eval_packed( // Maintain current context yield_constr.constraint_transition(total_filter * (nv.context - lv.context)); // Reset gas counter to zero. - yield_constr.constraint_transition(total_filter * nv.gas[0]); - yield_constr.constraint_transition(total_filter * nv.gas[1]); + yield_constr.constraint_transition(total_filter * nv.gas); let output = nv.mem_channels[0].value; // New top of the stack: current PC + 1 (limb 0), kernel flag (limb 1), gas counter (limbs 6 and 7). @@ -110,9 +109,8 @@ pub(crate) fn eval_packed( yield_constr.constraint(filter_exception * (output[0] - lv.program_counter)); // Check the kernel mode, for syscalls only yield_constr.constraint(filter_syscall * (output[1] - lv.is_kernel_mode)); - // TODO: Range check `output[6] and output[7]`. - yield_constr.constraint(total_filter * (output[6] - lv.gas[0])); - yield_constr.constraint(total_filter * (output[7] - lv.gas[1])); + yield_constr.constraint(total_filter * (output[6] - lv.gas)); + yield_constr.constraint(total_filter * output[7]); // High limb of gas is zero. // Zero the rest of that register // output[1] is 0 for exceptions, but not for syscalls @@ -270,9 +268,7 @@ pub(crate) fn eval_ext_circuit, const D: usize>( } // Reset gas counter to zero. { - let constr = builder.mul_extension(total_filter, nv.gas[0]); - yield_constr.constraint_transition(builder, constr); - let constr = builder.mul_extension(total_filter, nv.gas[1]); + let constr = builder.mul_extension(total_filter, nv.gas); yield_constr.constraint_transition(builder, constr); } @@ -297,15 +293,14 @@ pub(crate) fn eval_ext_circuit, const D: usize>( let constr = builder.mul_extension(filter_syscall, diff); yield_constr.constraint(builder, constr); } - // TODO: Range check `output[6]` and `output[7]. { - let diff = builder.sub_extension(output[6], lv.gas[0]); + let diff = builder.sub_extension(output[6], lv.gas); let constr = builder.mul_extension(total_filter, diff); yield_constr.constraint(builder, constr); } { - let diff = builder.sub_extension(output[7], lv.gas[1]); - let constr = builder.mul_extension(total_filter, diff); + // High limb of gas is zero. + let constr = builder.mul_extension(total_filter, output[7]); yield_constr.constraint(builder, constr); } diff --git a/evm/src/fixed_recursive_verifier.rs b/evm/src/fixed_recursive_verifier.rs index 4cb15639..9f3ec06c 100644 --- a/evm/src/fixed_recursive_verifier.rs +++ b/evm/src/fixed_recursive_verifier.rs @@ -663,18 +663,15 @@ where builder.connect(pvs.txn_number_before, lhs.txn_number_before); builder.connect(pvs.txn_number_after, rhs.txn_number_after); - // Connect lhs `txn_number_after` with rhs `txn_number_before`. + // Connect lhs `txn_number_after`with rhs `txn_number_before`. builder.connect(lhs.txn_number_after, rhs.txn_number_before); // Connect the gas used in public values to the lhs and rhs values correctly. - builder.connect(pvs.gas_used_before[0], lhs.gas_used_before[0]); - builder.connect(pvs.gas_used_before[1], lhs.gas_used_before[1]); - builder.connect(pvs.gas_used_after[0], rhs.gas_used_after[0]); - builder.connect(pvs.gas_used_after[1], rhs.gas_used_after[1]); + builder.connect(pvs.gas_used_before, lhs.gas_used_before); + builder.connect(pvs.gas_used_after, rhs.gas_used_after); - // Connect lhs `gas_used_after` with rhs `gas_used_before`. - builder.connect(lhs.gas_used_after[0], rhs.gas_used_before[0]); - builder.connect(lhs.gas_used_after[1], rhs.gas_used_before[1]); + // Connect lhs `gas_used_after`with rhs `gas_used_before`. + builder.connect(lhs.gas_used_after, rhs.gas_used_before); // Connect the `block_bloom` in public values to the lhs and rhs values correctly. for (&limb0, &limb1) in pvs.block_bloom_after.iter().zip(&rhs.block_bloom_after) { @@ -683,7 +680,7 @@ where for (&limb0, &limb1) in pvs.block_bloom_before.iter().zip(&lhs.block_bloom_before) { builder.connect(limb0, limb1); } - // Connect lhs `block_bloom_after` with rhs `block_bloom_before`. + // Connect lhs `block_bloom_after`with rhs `block_bloom_before`. for (&limb0, &limb1) in lhs.block_bloom_after.iter().zip(&rhs.block_bloom_before) { builder.connect(limb0, limb1); } @@ -855,12 +852,8 @@ where F: RichField + Extendable, { builder.connect( - x.block_metadata.block_gas_used[0], - x.extra_block_data.gas_used_after[0], - ); - builder.connect( - x.block_metadata.block_gas_used[1], - x.extra_block_data.gas_used_after[1], + x.block_metadata.block_gas_used, + x.extra_block_data.gas_used_after, ); for (&limb0, &limb1) in x @@ -880,8 +873,7 @@ where // The initial number of transactions is 0. builder.assert_zero(x.extra_block_data.txn_number_before); // The initial gas used is 0. - builder.assert_zero(x.extra_block_data.gas_used_before[0]); - builder.assert_zero(x.extra_block_data.gas_used_before[1]); + builder.assert_zero(x.extra_block_data.gas_used_before); // The initial bloom filter is all zeroes. for t in x.extra_block_data.block_bloom_before { diff --git a/evm/src/generation/mod.rs b/evm/src/generation/mod.rs index ac477931..9b3a8e98 100644 --- a/evm/src/generation/mod.rs +++ b/evm/src/generation/mod.rs @@ -307,10 +307,7 @@ fn simulate_cpu, const D: usize>( row.context = F::from_canonical_usize(state.registers.context); row.program_counter = F::from_canonical_usize(pc); row.is_kernel_mode = F::ONE; - row.gas = [ - F::from_canonical_u32(state.registers.gas_used as u32), - F::from_canonical_u32((state.registers.gas_used >> 32) as u32), - ]; + row.gas = F::from_canonical_u64(state.registers.gas_used); row.stack_len = F::from_canonical_usize(state.registers.stack_len); loop { diff --git a/evm/src/get_challenges.rs b/evm/src/get_challenges.rs index e9e5de93..fc1d8403 100644 --- a/evm/src/get_challenges.rs +++ b/evm/src/get_challenges.rs @@ -61,16 +61,12 @@ fn observe_block_metadata< challenger.observe_element(u256_to_u32(block_metadata.block_number)?); challenger.observe_element(u256_to_u32(block_metadata.block_difficulty)?); challenger.observe_elements(&h256_limbs::(block_metadata.block_random)); - let gaslimit = u256_to_u64(block_metadata.block_gaslimit)?; - challenger.observe_element(gaslimit.0); - challenger.observe_element(gaslimit.1); + challenger.observe_element(u256_to_u32(block_metadata.block_gaslimit)?); challenger.observe_element(u256_to_u32(block_metadata.block_chain_id)?); let basefee = u256_to_u64(block_metadata.block_base_fee)?; challenger.observe_element(basefee.0); challenger.observe_element(basefee.1); - let gas_used = u256_to_u64(block_metadata.block_gas_used)?; - challenger.observe_element(gas_used.0); - challenger.observe_element(gas_used.1); + challenger.observe_element(u256_to_u32(block_metadata.block_gas_used)?); for i in 0..8 { challenger.observe_elements(&u256_limbs(block_metadata.block_bloom[i])); } @@ -93,10 +89,10 @@ fn observe_block_metadata_target< challenger.observe_element(block_metadata.block_number); challenger.observe_element(block_metadata.block_difficulty); challenger.observe_elements(&block_metadata.block_random); - challenger.observe_elements(&block_metadata.block_gaslimit); + challenger.observe_element(block_metadata.block_gaslimit); challenger.observe_element(block_metadata.block_chain_id); challenger.observe_elements(&block_metadata.block_base_fee); - challenger.observe_elements(&block_metadata.block_gas_used); + challenger.observe_element(block_metadata.block_gas_used); challenger.observe_elements(&block_metadata.block_bloom); } @@ -111,12 +107,8 @@ fn observe_extra_block_data< challenger.observe_elements(&h256_limbs(extra_data.genesis_state_trie_root)); challenger.observe_element(u256_to_u32(extra_data.txn_number_before)?); challenger.observe_element(u256_to_u32(extra_data.txn_number_after)?); - let gas_used_before = u256_to_u64(extra_data.gas_used_before)?; - challenger.observe_element(gas_used_before.0); - challenger.observe_element(gas_used_before.1); - let gas_used_after = u256_to_u64(extra_data.gas_used_after)?; - challenger.observe_element(gas_used_after.0); - challenger.observe_element(gas_used_after.1); + challenger.observe_element(u256_to_u32(extra_data.gas_used_before)?); + challenger.observe_element(u256_to_u32(extra_data.gas_used_after)?); for i in 0..8 { challenger.observe_elements(&u256_limbs(extra_data.block_bloom_before[i])); } @@ -140,8 +132,8 @@ fn observe_extra_block_data_target< challenger.observe_elements(&extra_data.genesis_state_trie_root); challenger.observe_element(extra_data.txn_number_before); challenger.observe_element(extra_data.txn_number_after); - challenger.observe_elements(&extra_data.gas_used_before); - challenger.observe_elements(&extra_data.gas_used_after); + challenger.observe_element(extra_data.gas_used_before); + challenger.observe_element(extra_data.gas_used_after); challenger.observe_elements(&extra_data.block_bloom_before); challenger.observe_elements(&extra_data.block_bloom_after); } diff --git a/evm/src/proof.rs b/evm/src/proof.rs index 1cdaa66e..60f2ce4d 100644 --- a/evm/src/proof.rs +++ b/evm/src/proof.rs @@ -97,31 +97,26 @@ pub struct BlockHashes { pub cur_hash: H256, } -// TODO: Before going into production, `block_gas_used` and `block_gaslimit` here -// as well as `gas_used_before` / `gas_used_after` in `ExtraBlockData` should be -// updated to fit in a single 32-bit limb, as supporting 64-bit values for those -// fields is only necessary for testing purposes. /// Metadata contained in a block header. Those are identical between /// all state transition proofs within the same block. #[derive(Debug, Clone, Default, Deserialize, Serialize)] pub struct BlockMetadata { /// The address of this block's producer. pub block_beneficiary: Address, - /// The timestamp of this block. It must fit in a `u32`. + /// The timestamp of this block. pub block_timestamp: U256, - /// The index of this block. It must fit in a `u32`. + /// The index of this block. pub block_number: U256, /// The difficulty (before PoS transition) of this block. pub block_difficulty: U256, - /// The `mix_hash` value of this block. pub block_random: H256, - /// The gas limit of this block. It must fit in a `u64`. + /// The gas limit of this block. It must fit in a `u32`. pub block_gaslimit: U256, - /// The chain id of this block. It must fit in a `u32`. + /// The chain id of this block. pub block_chain_id: U256, - /// The base fee of this block. It must fit in a `u64`. + /// The base fee of this block. pub block_base_fee: U256, - /// The total gas used in this block. It must fit in a `u64`. + /// The total gas used in this block. It must fit in a `u32`. pub block_gas_used: U256, /// The block bloom of this block, represented as the consecutive /// 32-byte chunks of a block's final bloom filter string. @@ -210,10 +205,10 @@ impl PublicValuesTarget { buffer.write_target(block_number)?; buffer.write_target(block_difficulty)?; buffer.write_target_array(&block_random)?; - buffer.write_target_array(&block_gaslimit)?; + buffer.write_target(block_gaslimit)?; buffer.write_target(block_chain_id)?; buffer.write_target_array(&block_base_fee)?; - buffer.write_target_array(&block_gas_used)?; + buffer.write_target(block_gas_used)?; buffer.write_target_array(&block_bloom)?; let BlockHashesTarget { @@ -235,8 +230,8 @@ impl PublicValuesTarget { buffer.write_target_array(&genesis_state_root)?; buffer.write_target(txn_number_before)?; buffer.write_target(txn_number_after)?; - buffer.write_target_array(&gas_used_before)?; - buffer.write_target_array(&gas_used_after)?; + buffer.write_target(gas_used_before)?; + buffer.write_target(gas_used_after)?; buffer.write_target_array(&block_bloom_before)?; buffer.write_target_array(&block_bloom_after)?; @@ -263,10 +258,10 @@ impl PublicValuesTarget { block_number: buffer.read_target()?, block_difficulty: buffer.read_target()?, block_random: buffer.read_target_array()?, - block_gaslimit: buffer.read_target_array()?, + block_gaslimit: buffer.read_target()?, block_chain_id: buffer.read_target()?, block_base_fee: buffer.read_target_array()?, - block_gas_used: buffer.read_target_array()?, + block_gas_used: buffer.read_target()?, block_bloom: buffer.read_target_array()?, }; @@ -279,8 +274,8 @@ impl PublicValuesTarget { genesis_state_trie_root: buffer.read_target_array()?, txn_number_before: buffer.read_target()?, txn_number_after: buffer.read_target()?, - gas_used_before: buffer.read_target_array()?, - gas_used_after: buffer.read_target_array()?, + gas_used_before: buffer.read_target()?, + gas_used_after: buffer.read_target()?, block_bloom_before: buffer.read_target_array()?, block_bloom_after: buffer.read_target_array()?, }; @@ -461,20 +456,20 @@ pub(crate) struct BlockMetadataTarget { /// `Target`s for the `mix_hash` value of this block. pub(crate) block_random: [Target; 8], /// `Target`s for the gas limit of this block. - pub(crate) block_gaslimit: [Target; 2], + pub(crate) block_gaslimit: Target, /// `Target` for the chain id of this block. pub(crate) block_chain_id: Target, /// `Target`s for the base fee of this block. pub(crate) block_base_fee: [Target; 2], /// `Target`s for the gas used of this block. - pub(crate) block_gas_used: [Target; 2], + pub(crate) block_gas_used: Target, /// `Target`s for the block bloom of this block. pub(crate) block_bloom: [Target; 64], } impl BlockMetadataTarget { /// Number of `Target`s required for the block metadata. - pub const SIZE: usize = 87; + pub const SIZE: usize = 85; /// Extracts block metadata `Target`s from the provided public input `Target`s. /// The provided `pis` should start with the block metadata. @@ -484,11 +479,11 @@ impl BlockMetadataTarget { let block_number = pis[6]; let block_difficulty = pis[7]; let block_random = pis[8..16].try_into().unwrap(); - let block_gaslimit = pis[16..18].try_into().unwrap(); - let block_chain_id = pis[18]; - let block_base_fee = pis[19..21].try_into().unwrap(); - let block_gas_used = pis[21..23].try_into().unwrap(); - let block_bloom = pis[23..87].try_into().unwrap(); + let block_gaslimit = pis[16]; + let block_chain_id = pis[17]; + let block_base_fee = pis[18..20].try_into().unwrap(); + let block_gas_used = pis[20]; + let block_bloom = pis[21..85].try_into().unwrap(); Self { block_beneficiary, @@ -526,16 +521,12 @@ impl BlockMetadataTarget { block_random: core::array::from_fn(|i| { builder.select(condition, bm0.block_random[i], bm1.block_random[i]) }), - block_gaslimit: core::array::from_fn(|i| { - builder.select(condition, bm0.block_gaslimit[i], bm1.block_gaslimit[i]) - }), + block_gaslimit: builder.select(condition, bm0.block_gaslimit, bm1.block_gaslimit), block_chain_id: builder.select(condition, bm0.block_chain_id, bm1.block_chain_id), block_base_fee: core::array::from_fn(|i| { builder.select(condition, bm0.block_base_fee[i], bm1.block_base_fee[i]) }), - block_gas_used: core::array::from_fn(|i| { - builder.select(condition, bm0.block_gas_used[i], bm1.block_gas_used[i]) - }), + block_gas_used: builder.select(condition, bm0.block_gas_used, bm1.block_gas_used), block_bloom: core::array::from_fn(|i| { builder.select(condition, bm0.block_bloom[i], bm1.block_bloom[i]) }), @@ -557,16 +548,12 @@ impl BlockMetadataTarget { for i in 0..8 { builder.connect(bm0.block_random[i], bm1.block_random[i]); } - for i in 0..2 { - builder.connect(bm0.block_gaslimit[i], bm1.block_gaslimit[i]) - } + builder.connect(bm0.block_gaslimit, bm1.block_gaslimit); builder.connect(bm0.block_chain_id, bm1.block_chain_id); for i in 0..2 { builder.connect(bm0.block_base_fee[i], bm1.block_base_fee[i]) } - for i in 0..2 { - builder.connect(bm0.block_gas_used[i], bm1.block_gas_used[i]) - } + builder.connect(bm0.block_gas_used, bm1.block_gas_used); for i in 0..64 { builder.connect(bm0.block_bloom[i], bm1.block_bloom[i]) } @@ -650,10 +637,10 @@ pub(crate) struct ExtraBlockDataTarget { pub txn_number_after: Target, /// `Target` for the accumulated gas used prior execution of the local state transition, starting /// at 0 for the initial transaction of a block. - pub gas_used_before: [Target; 2], + pub gas_used_before: Target, /// `Target` for the accumulated gas used after execution of the local state transition. It should /// match the `block_gas_used` value after execution of the last transaction in a block. - pub gas_used_after: [Target; 2], + pub gas_used_after: Target, /// `Target`s for the accumulated bloom filter of this block prior execution of the local state transition, /// starting with all zeros for the initial transaction of a block. pub block_bloom_before: [Target; 64], @@ -664,7 +651,7 @@ pub(crate) struct ExtraBlockDataTarget { impl ExtraBlockDataTarget { /// Number of `Target`s required for the extra block data. - const SIZE: usize = 142; + const SIZE: usize = 140; /// Extracts the extra block data `Target`s from the public input `Target`s. /// The provided `pis` should start with the extra vblock data. @@ -672,10 +659,10 @@ impl ExtraBlockDataTarget { let genesis_state_trie_root = pis[0..8].try_into().unwrap(); let txn_number_before = pis[8]; let txn_number_after = pis[9]; - let gas_used_before = pis[10..12].try_into().unwrap(); - let gas_used_after = pis[12..14].try_into().unwrap(); - let block_bloom_before = pis[14..78].try_into().unwrap(); - let block_bloom_after = pis[78..142].try_into().unwrap(); + let gas_used_before = pis[10]; + let gas_used_after = pis[11]; + let block_bloom_before = pis[12..76].try_into().unwrap(); + let block_bloom_after = pis[76..140].try_into().unwrap(); Self { genesis_state_trie_root, @@ -710,12 +697,8 @@ impl ExtraBlockDataTarget { ed1.txn_number_before, ), txn_number_after: builder.select(condition, ed0.txn_number_after, ed1.txn_number_after), - gas_used_before: core::array::from_fn(|i| { - builder.select(condition, ed0.gas_used_before[i], ed1.gas_used_before[i]) - }), - gas_used_after: core::array::from_fn(|i| { - builder.select(condition, ed0.gas_used_after[i], ed1.gas_used_after[i]) - }), + gas_used_before: builder.select(condition, ed0.gas_used_before, ed1.gas_used_before), + gas_used_after: builder.select(condition, ed0.gas_used_after, ed1.gas_used_after), block_bloom_before: core::array::from_fn(|i| { builder.select( condition, @@ -747,12 +730,8 @@ impl ExtraBlockDataTarget { } builder.connect(ed0.txn_number_before, ed1.txn_number_before); builder.connect(ed0.txn_number_after, ed1.txn_number_after); - for i in 0..2 { - builder.connect(ed0.gas_used_before[i], ed1.gas_used_before[i]); - } - for i in 0..2 { - builder.connect(ed1.gas_used_after[i], ed1.gas_used_after[i]); - } + builder.connect(ed0.gas_used_before, ed1.gas_used_before); + builder.connect(ed1.gas_used_after, ed1.gas_used_after); for i in 0..64 { builder.connect(ed0.block_bloom_before[i], ed1.block_bloom_before[i]); } diff --git a/evm/src/recursive_verifier.rs b/evm/src/recursive_verifier.rs index 792724a2..c9c2d1a4 100644 --- a/evm/src/recursive_verifier.rs +++ b/evm/src/recursive_verifier.rs @@ -443,10 +443,26 @@ pub(crate) fn get_memory_extra_looking_products_circuit< GlobalMetadata::BlockDifficulty as usize, public_values.block_metadata.block_difficulty, ), + ( + GlobalMetadata::BlockGasLimit as usize, + public_values.block_metadata.block_gaslimit, + ), ( GlobalMetadata::BlockChainId as usize, public_values.block_metadata.block_chain_id, ), + ( + GlobalMetadata::BlockGasUsed as usize, + public_values.block_metadata.block_gas_used, + ), + ( + GlobalMetadata::BlockGasUsedBefore as usize, + public_values.extra_block_data.gas_used_before, + ), + ( + GlobalMetadata::BlockGasUsedAfter as usize, + public_values.extra_block_data.gas_used_after, + ), ( GlobalMetadata::TxnNumberBefore as usize, public_values.extra_block_data.txn_number_before, @@ -457,10 +473,7 @@ pub(crate) fn get_memory_extra_looking_products_circuit< ), ]; - // This contains the `block_beneficiary`, `block_random`, `block_base_fee`, - // `block_gaslimit`, `block_gas_used` as well as `cur_hash`, `gas_used_before` - // and `gas_used_after`. - let block_fields_arrays: [(usize, &[Target]); 8] = [ + let beneficiary_random_base_fee_cur_hash_fields: [(usize, &[Target]); 4] = [ ( GlobalMetadata::BlockBeneficiary as usize, &public_values.block_metadata.block_beneficiary, @@ -473,26 +486,10 @@ pub(crate) fn get_memory_extra_looking_products_circuit< GlobalMetadata::BlockBaseFee as usize, &public_values.block_metadata.block_base_fee, ), - ( - GlobalMetadata::BlockGasLimit as usize, - &public_values.block_metadata.block_gaslimit, - ), - ( - GlobalMetadata::BlockGasUsed as usize, - &public_values.block_metadata.block_gas_used, - ), ( GlobalMetadata::BlockCurrentHash as usize, &public_values.block_hashes.cur_hash, ), - ( - GlobalMetadata::BlockGasUsedBefore as usize, - &public_values.extra_block_data.gas_used_before, - ), - ( - GlobalMetadata::BlockGasUsedAfter as usize, - &public_values.extra_block_data.gas_used_after, - ), ]; let metadata_segment = builder.constant(F::from_canonical_u32(Segment::GlobalMetadata as u32)); @@ -508,7 +505,7 @@ pub(crate) fn get_memory_extra_looking_products_circuit< ); }); - block_fields_arrays.map(|(field, targets)| { + beneficiary_random_base_fee_cur_hash_fields.map(|(field, targets)| { product = add_data_write( builder, challenge, @@ -704,10 +701,10 @@ pub(crate) fn add_virtual_block_metadata, const D: let block_number = builder.add_virtual_public_input(); let block_difficulty = builder.add_virtual_public_input(); let block_random = builder.add_virtual_public_input_arr(); - let block_gaslimit = builder.add_virtual_public_input_arr(); + let block_gaslimit = builder.add_virtual_public_input(); let block_chain_id = builder.add_virtual_public_input(); let block_base_fee = builder.add_virtual_public_input_arr(); - let block_gas_used = builder.add_virtual_public_input_arr(); + let block_gas_used = builder.add_virtual_public_input(); let block_bloom = builder.add_virtual_public_input_arr(); BlockMetadataTarget { block_beneficiary, @@ -739,8 +736,8 @@ pub(crate) fn add_virtual_extra_block_data, const D let genesis_state_trie_root = builder.add_virtual_public_input_arr(); let txn_number_before = builder.add_virtual_public_input(); let txn_number_after = builder.add_virtual_public_input(); - let gas_used_before = builder.add_virtual_public_input_arr(); - let gas_used_after = builder.add_virtual_public_input_arr(); + let gas_used_before = builder.add_virtual_public_input(); + let gas_used_after = builder.add_virtual_public_input(); let block_bloom_before: [Target; 64] = builder.add_virtual_public_input_arr(); let block_bloom_after: [Target; 64] = builder.add_virtual_public_input_arr(); ExtraBlockDataTarget { @@ -953,10 +950,10 @@ where &block_metadata_target.block_random, &h256_limbs(block_metadata.block_random), ); - // Gaslimit fits in 2 limbs - let gaslimit = u256_to_u64(block_metadata.block_gaslimit)?; - witness.set_target(block_metadata_target.block_gaslimit[0], gaslimit.0); - witness.set_target(block_metadata_target.block_gaslimit[1], gaslimit.1); + witness.set_target( + block_metadata_target.block_gaslimit, + u256_to_u32(block_metadata.block_gaslimit)?, + ); witness.set_target( block_metadata_target.block_chain_id, u256_to_u32(block_metadata.block_chain_id)?, @@ -965,10 +962,10 @@ where let basefee = u256_to_u64(block_metadata.block_base_fee)?; witness.set_target(block_metadata_target.block_base_fee[0], basefee.0); witness.set_target(block_metadata_target.block_base_fee[1], basefee.1); - // Gas used fits in 2 limbs - let gas_used = u256_to_u64(block_metadata.block_gas_used)?; - witness.set_target(block_metadata_target.block_gas_used[0], gas_used.0); - witness.set_target(block_metadata_target.block_gas_used[1], gas_used.1); + witness.set_target( + block_metadata_target.block_gas_used, + u256_to_u32(block_metadata.block_gas_used)?, + ); let mut block_bloom_limbs = [F::ZERO; 64]; for (i, limbs) in block_bloom_limbs.chunks_exact_mut(8).enumerate() { limbs.copy_from_slice(&u256_limbs(block_metadata.block_bloom[i])); @@ -1018,13 +1015,8 @@ where ed_target.txn_number_after, u256_to_u32(ed.txn_number_after)?, ); - // Gas used before/after fit in 2 limbs - let gas_used_before = u256_to_u64(ed.gas_used_before)?; - witness.set_target(ed_target.gas_used_before[0], gas_used_before.0); - witness.set_target(ed_target.gas_used_before[1], gas_used_before.1); - let gas_used_after = u256_to_u64(ed.gas_used_after)?; - witness.set_target(ed_target.gas_used_after[0], gas_used_after.0); - witness.set_target(ed_target.gas_used_after[1], gas_used_after.1); + witness.set_target(ed_target.gas_used_before, u256_to_u32(ed.gas_used_before)?); + witness.set_target(ed_target.gas_used_after, u256_to_u32(ed.gas_used_after)?); let block_bloom_before = ed.block_bloom_before; let mut block_bloom_limbs = [F::ZERO; 64]; diff --git a/evm/src/witness/operation.rs b/evm/src/witness/operation.rs index a7228f42..fddafa81 100644 --- a/evm/src/witness/operation.rs +++ b/evm/src/witness/operation.rs @@ -681,7 +681,7 @@ pub(crate) fn generate_syscall( state: &mut GenerationState, mut row: CpuColumnsView, ) -> Result<(), ProgramError> { - if TryInto::::try_into(state.registers.gas_used).is_err() { + if TryInto::::try_into(state.registers.gas_used).is_err() { return Err(ProgramError::GasLimitError); } @@ -786,7 +786,7 @@ pub(crate) fn generate_exit_kernel( assert!(is_kernel_mode_val == 0 || is_kernel_mode_val == 1); let is_kernel_mode = is_kernel_mode_val != 0; let gas_used_val = kexit_info.0[3]; - if TryInto::::try_into(gas_used_val).is_err() { + if TryInto::::try_into(gas_used_val).is_err() { return Err(ProgramError::GasLimitError); } @@ -944,7 +944,7 @@ pub(crate) fn generate_exception( state: &mut GenerationState, mut row: CpuColumnsView, ) -> Result<(), ProgramError> { - if TryInto::::try_into(state.registers.gas_used).is_err() { + if TryInto::::try_into(state.registers.gas_used).is_err() { return Err(ProgramError::GasLimitError); } diff --git a/evm/src/witness/transition.rs b/evm/src/witness/transition.rs index ca4e3275..cd381b1f 100644 --- a/evm/src/witness/transition.rs +++ b/evm/src/witness/transition.rs @@ -303,10 +303,7 @@ fn base_row(state: &mut GenerationState) -> (CpuColumnsView, u8) row.context = F::from_canonical_usize(state.registers.context); row.program_counter = F::from_canonical_usize(state.registers.program_counter); row.is_kernel_mode = F::from_bool(state.registers.is_kernel); - row.gas = [ - F::from_canonical_u32(state.registers.gas_used as u32), - F::from_canonical_u32((state.registers.gas_used >> 32) as u32), - ]; + row.gas = F::from_canonical_u64(state.registers.gas_used); row.stack_len = F::from_canonical_usize(state.registers.stack_len); fill_channel_with_value(&mut row, 0, state.registers.stack_top);