Remove risks of panic

This commit is contained in:
Robin Salen 2023-09-12 19:23:16 -04:00
parent 9508b49090
commit 5a1b05acfb
No known key found for this signature in database
GPG Key ID: FB87BACFB3CB2007
13 changed files with 101 additions and 119 deletions

View File

@ -200,7 +200,7 @@ impl<'a> Interpreter<'a> {
self.generation_state.memory.contexts[0].segments[segment as usize]
.content
.iter()
.map(|x| x.as_u32() as u8)
.map(|x| x.low_u32() as u8)
.collect()
}
@ -1045,7 +1045,7 @@ impl<'a> Interpreter<'a> {
self.generation_state
.memory
.mload_general(context, segment, offset + i)
.as_u32() as u8
.low_u32() as u8
})
.collect();
let value = U256::from_big_endian(&bytes);

View File

@ -75,7 +75,7 @@ fn run_blake2_f(
Ok(hash
.iter()
.map(|&x| x.as_u64())
.map(|&x| x.low_u64())
.collect::<Vec<_>>()
.try_into()
.unwrap())

View File

@ -47,9 +47,8 @@ use crate::proof::{
use crate::prover::prove;
use crate::recursive_verifier::{
add_common_recursion_gates, add_virtual_public_values,
get_memory_extra_looking_products_circuit, recursive_stark_circuit, set_block_hashes_target,
set_block_metadata_target, set_extra_public_values_target, set_public_value_targets,
set_trie_roots_target, PlonkWrapperCircuit, PublicInputs, StarkWrapperCircuit,
get_memory_extra_looking_products_circuit, recursive_stark_circuit, set_public_value_targets,
PlonkWrapperCircuit, PublicInputs, StarkWrapperCircuit,
};
use crate::stark::Stark;
use crate::util::h256_limbs;
@ -905,7 +904,8 @@ where
&mut root_inputs,
&self.root.public_values,
&all_proof.public_values,
);
)
.map_err(|_| anyhow::Error::msg("Invalid conversion when setting public_values target."))?;
let root_proof = self.root.circuit.prove(root_inputs)?;
@ -939,32 +939,13 @@ where
&self.aggregation.circuit.verifier_only,
);
set_block_hashes_target(
set_public_value_targets(
&mut agg_inputs,
&self.aggregation.public_values.block_hashes,
&public_values.block_hashes,
);
set_block_metadata_target(
&mut agg_inputs,
&self.aggregation.public_values.block_metadata,
&public_values.block_metadata,
);
&self.aggregation.public_values,
&public_values,
)
.map_err(|_| anyhow::Error::msg("Invalid conversion when setting public values target."))?;
set_trie_roots_target(
&mut agg_inputs,
&self.aggregation.public_values.trie_roots_before,
&public_values.trie_roots_before,
);
set_trie_roots_target(
&mut agg_inputs,
&self.aggregation.public_values.trie_roots_after,
&public_values.trie_roots_after,
);
set_extra_public_values_target(
&mut agg_inputs,
&self.aggregation.public_values.extra_block_data,
&public_values.extra_block_data,
);
let aggregation_proof = self.aggregation.circuit.prove(agg_inputs)?;
Ok((aggregation_proof, public_values))
}
@ -1022,32 +1003,10 @@ where
block_inputs
.set_verifier_data_target(&self.block.cyclic_vk, &self.block.circuit.verifier_only);
set_block_hashes_target(
&mut block_inputs,
&self.block.public_values.block_hashes,
&public_values.block_hashes,
);
set_extra_public_values_target(
&mut block_inputs,
&self.block.public_values.extra_block_data,
&public_values.extra_block_data,
);
set_block_metadata_target(
&mut block_inputs,
&self.block.public_values.block_metadata,
&public_values.block_metadata,
);
set_trie_roots_target(
&mut block_inputs,
&self.block.public_values.trie_roots_before,
&public_values.trie_roots_before,
);
set_trie_roots_target(
&mut block_inputs,
&self.block.public_values.trie_roots_after,
&public_values.trie_roots_after,
);
set_public_value_targets(&mut block_inputs, &self.block.public_values, &public_values)
.map_err(|_| {
anyhow::Error::msg("Invalid conversion when setting public values target.")
})?;
let block_proof = self.block.circuit.prove(block_inputs)?;
Ok((block_proof, public_values))

View File

@ -116,7 +116,7 @@ impl<F: Field> GenerationState<F> {
let code = self.memory.contexts[ctx].segments[Segment::Returndata as usize].content
[..returndata_size]
.iter()
.map(|x| x.as_u32() as u8)
.map(|x| x.low_u32() as u8)
.collect::<Vec<_>>();
debug_assert_eq!(keccak(&code), codehash);

View File

@ -20,7 +20,7 @@ pub(crate) struct AccountTrieRecord {
pub(crate) fn read_state_trie_value(slice: &[U256]) -> AccountTrieRecord {
AccountTrieRecord {
nonce: slice[0].as_u64(),
nonce: slice[0].low_u64(),
balance: slice[1],
storage_ptr: slice[2].as_usize(),
code_hash: H256::from_uint(&slice[3]),

View File

@ -13,7 +13,8 @@ use crate::permutation::{
get_n_grand_product_challenge_sets_target,
};
use crate::proof::*;
use crate::util::{h256_limbs, u256_limbs};
use crate::util::{h256_limbs, u256_limbs, u256_lowest_limb, u256_lowest_word};
use crate::witness::errors::ProgramError;
fn observe_root<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>(
challenger: &mut Challenger<F, C::Hasher>,
@ -56,35 +57,24 @@ fn observe_block_metadata<
>(
challenger: &mut Challenger<F, C::Hasher>,
block_metadata: &BlockMetadata,
) {
) -> Result<(), ProgramError> {
challenger.observe_elements(
&u256_limbs::<F>(U256::from_big_endian(&block_metadata.block_beneficiary.0))[..5],
);
challenger.observe_element(F::from_canonical_u32(
block_metadata.block_timestamp.as_u32(),
));
challenger.observe_element(F::from_canonical_u32(block_metadata.block_number.as_u32()));
challenger.observe_element(F::from_canonical_u32(
block_metadata.block_difficulty.as_u32(),
));
challenger.observe_element(F::from_canonical_u32(
block_metadata.block_gaslimit.as_u32(),
));
challenger.observe_element(F::from_canonical_u32(
block_metadata.block_chain_id.as_u32(),
));
challenger.observe_element(F::from_canonical_u32(
block_metadata.block_base_fee.as_u64() as u32,
));
challenger.observe_element(F::from_canonical_u32(
(block_metadata.block_base_fee.as_u64() >> 32) as u32,
));
challenger.observe_element(F::from_canonical_u32(
block_metadata.block_gas_used.as_u32(),
));
challenger.observe_element(u256_lowest_limb(block_metadata.block_timestamp)?);
challenger.observe_element(u256_lowest_limb(block_metadata.block_number)?);
challenger.observe_element(u256_lowest_limb(block_metadata.block_difficulty)?);
challenger.observe_element(u256_lowest_limb(block_metadata.block_gaslimit)?);
challenger.observe_element(u256_lowest_limb(block_metadata.block_chain_id)?);
let basefee = u256_lowest_word(block_metadata.block_base_fee)?;
challenger.observe_element(basefee.0);
challenger.observe_element(basefee.1);
challenger.observe_element(u256_lowest_limb(block_metadata.block_gas_used)?);
for i in 0..8 {
challenger.observe_elements(&u256_limbs(block_metadata.block_bloom[i]));
}
Ok(())
}
fn observe_block_metadata_target<
@ -115,17 +105,19 @@ fn observe_extra_block_data<
>(
challenger: &mut Challenger<F, C::Hasher>,
extra_data: &ExtraBlockData,
) {
challenger.observe_element(F::from_canonical_u32(extra_data.txn_number_before.as_u32()));
challenger.observe_element(F::from_canonical_u32(extra_data.txn_number_after.as_u32()));
challenger.observe_element(F::from_canonical_u32(extra_data.gas_used_before.as_u32()));
challenger.observe_element(F::from_canonical_u32(extra_data.gas_used_after.as_u32()));
) -> Result<(), ProgramError> {
challenger.observe_element(u256_lowest_limb(extra_data.txn_number_before)?);
challenger.observe_element(u256_lowest_limb(extra_data.txn_number_after)?);
challenger.observe_element(u256_lowest_limb(extra_data.gas_used_before)?);
challenger.observe_element(u256_lowest_limb(extra_data.gas_used_after)?);
for i in 0..8 {
challenger.observe_elements(&u256_limbs(extra_data.block_bloom_before[i]));
}
for i in 0..8 {
challenger.observe_elements(&u256_limbs(extra_data.block_bloom_after[i]));
}
Ok(())
}
fn observe_extra_block_data_target<
@ -181,12 +173,12 @@ pub(crate) fn observe_public_values<
>(
challenger: &mut Challenger<F, C::Hasher>,
public_values: &PublicValues,
) {
) -> Result<(), ProgramError> {
observe_trie_roots::<F, C, D>(challenger, &public_values.trie_roots_before);
observe_trie_roots::<F, C, D>(challenger, &public_values.trie_roots_after);
observe_block_metadata::<F, C, D>(challenger, &public_values.block_metadata);
observe_block_metadata::<F, C, D>(challenger, &public_values.block_metadata)?;
observe_block_hashes::<F, C, D>(challenger, &public_values.block_hashes);
observe_extra_block_data::<F, C, D>(challenger, &public_values.extra_block_data);
observe_extra_block_data::<F, C, D>(challenger, &public_values.extra_block_data)
}
pub(crate) fn observe_public_values_target<
@ -212,14 +204,14 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize> A
&self,
all_stark: &AllStark<F, D>,
config: &StarkConfig,
) -> AllProofChallenges<F, D> {
) -> Result<AllProofChallenges<F, D>, ProgramError> {
let mut challenger = Challenger::<F, C::Hasher>::new();
for proof in &self.stark_proofs {
challenger.observe_cap(&proof.proof.trace_cap);
}
observe_public_values::<F, C, D>(&mut challenger, &self.public_values);
observe_public_values::<F, C, D>(&mut challenger, &self.public_values)?;
let ctl_challenges =
get_grand_product_challenge_set(&mut challenger, config.num_challenges);
@ -227,7 +219,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize> A
let num_permutation_zs = all_stark.nums_permutation_zs(config);
let num_permutation_batch_sizes = all_stark.permutation_batch_sizes();
AllProofChallenges {
Ok(AllProofChallenges {
stark_challenges: core::array::from_fn(|i| {
challenger.compact();
self.stark_proofs[i].proof.get_challenges(
@ -238,7 +230,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize> A
)
}),
ctl_challenges,
}
})
}
#[allow(unused)] // TODO: should be used soon

View File

@ -150,7 +150,8 @@ where
challenger.observe_cap(cap);
}
observe_public_values::<F, C, D>(&mut challenger, &public_values);
observe_public_values::<F, C, D>(&mut challenger, &public_values)
.map_err(|_| anyhow::Error::msg("Invalid conversion of public values."))?;
let ctl_challenges = get_grand_product_challenge_set(&mut challenger, config.num_challenges);
let ctl_data_per_table = timed!(

View File

@ -43,9 +43,10 @@ use crate::proof::{
TrieRootsTarget,
};
use crate::stark::Stark;
use crate::util::{h256_limbs, u256_limbs};
use crate::util::{h256_limbs, u256_limbs, u256_lowest_limb, u256_lowest_word};
use crate::vanishing_poly::eval_vanishing_poly_circuit;
use crate::vars::StarkEvaluationTargets;
use crate::witness::errors::ProgramError;
/// Table-wise recursive proofs of an `AllProof`.
pub struct RecursiveAllProof<
@ -905,7 +906,8 @@ pub(crate) fn set_public_value_targets<F, W, const D: usize>(
witness: &mut W,
public_values_target: &PublicValuesTarget,
public_values: &PublicValues,
) where
) -> Result<(), ProgramError>
where
F: RichField + Extendable<D>,
W: Witness<F>,
{
@ -923,7 +925,7 @@ pub(crate) fn set_public_value_targets<F, W, const D: usize>(
witness,
&public_values_target.block_metadata,
&public_values.block_metadata,
);
)?;
set_block_hashes_target(
witness,
&public_values_target.block_hashes,
@ -934,6 +936,8 @@ pub(crate) fn set_public_value_targets<F, W, const D: usize>(
&public_values_target.extra_block_data,
&public_values.extra_block_data,
);
Ok(())
}
pub(crate) fn set_trie_roots_target<F, W, const D: usize>(
@ -994,7 +998,8 @@ pub(crate) fn set_block_metadata_target<F, W, const D: usize>(
witness: &mut W,
block_metadata_target: &BlockMetadataTarget,
block_metadata: &BlockMetadata,
) where
) -> Result<(), ProgramError>
where
F: RichField + Extendable<D>,
W: Witness<F>,
{
@ -1005,42 +1010,39 @@ pub(crate) fn set_block_metadata_target<F, W, const D: usize>(
witness.set_target_arr(&block_metadata_target.block_beneficiary, &beneficiary_limbs);
witness.set_target(
block_metadata_target.block_timestamp,
F::from_canonical_u32(block_metadata.block_timestamp.as_u32()),
u256_lowest_limb(block_metadata.block_timestamp)?,
);
witness.set_target(
block_metadata_target.block_number,
F::from_canonical_u32(block_metadata.block_number.as_u32()),
u256_lowest_limb(block_metadata.block_number)?,
);
witness.set_target(
block_metadata_target.block_difficulty,
F::from_canonical_u32(block_metadata.block_difficulty.as_u32()),
u256_lowest_limb(block_metadata.block_difficulty)?,
);
witness.set_target(
block_metadata_target.block_gaslimit,
F::from_canonical_u32(block_metadata.block_gaslimit.as_u32()),
u256_lowest_limb(block_metadata.block_gaslimit)?,
);
witness.set_target(
block_metadata_target.block_chain_id,
F::from_canonical_u32(block_metadata.block_chain_id.as_u32()),
u256_lowest_limb(block_metadata.block_chain_id)?,
);
// Basefee fits in 2 limbs
witness.set_target(
block_metadata_target.block_base_fee[0],
F::from_canonical_u32(block_metadata.block_base_fee.as_u64() as u32),
);
witness.set_target(
block_metadata_target.block_base_fee[1],
F::from_canonical_u32((block_metadata.block_base_fee.as_u64() >> 32) as u32),
);
let basefee = u256_lowest_word(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);
witness.set_target(
block_metadata_target.block_gas_used,
F::from_canonical_u64(block_metadata.block_gas_used.as_u64()),
u256_lowest_limb(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]));
}
witness.set_target_arr(&block_metadata_target.block_bloom, &block_bloom_limbs);
Ok(())
}
pub(crate) fn set_block_hashes_target<F, W, const D: usize>(

View File

@ -11,6 +11,8 @@ use plonky2::hash::hash_types::RichField;
use plonky2::iop::ext_target::ExtensionTarget;
use plonky2::util::transpose;
use crate::witness::errors::ProgramError;
/// Construct an integer from its constituent bits (in little-endian order)
pub fn limb_from_bits_le<P: PackedField>(iter: impl IntoIterator<Item = P>) -> P {
// TODO: This is technically wrong, as 1 << i won't be canonical for all fields...
@ -45,6 +47,29 @@ pub fn trace_rows_to_poly_values<F: Field, const COLUMNS: usize>(
.collect()
}
/// Returns the lowest LE 32-bit limb of a `U256` as a field element,
/// and errors in case the integer is actually greater.
pub(crate) fn u256_lowest_limb<F: Field>(u256: U256) -> Result<F, ProgramError> {
if TryInto::<u32>::try_into(u256).is_err() {
return Err(ProgramError::IntegerTooLarge);
}
Ok(F::from_canonical_u32(u256.low_u32()))
}
/// Returns the lowest LE 64-bit word of a `U256` as two field elements
/// each storing a 32-bit limb, and errors in case the integer is actually greater.
pub(crate) fn u256_lowest_word<F: Field>(u256: U256) -> Result<(F, F), ProgramError> {
if TryInto::<u64>::try_into(u256).is_err() {
return Err(ProgramError::IntegerTooLarge);
}
Ok((
F::from_canonical_u32(u256.low_u64() as u32),
F::from_canonical_u32((u256.low_u64() >> 32) as u32),
))
}
#[allow(unused)] // TODO: Remove?
/// Returns the 32-bit little-endian limbs of a `U256`.
pub(crate) fn u256_limbs<F: Field>(u256: U256) -> [F; 8] {

View File

@ -50,7 +50,9 @@ where
let AllProofChallenges {
stark_challenges,
ctl_challenges,
} = all_proof.get_challenges(all_stark, config);
} = all_proof
.get_challenges(all_stark, config)
.map_err(|_| anyhow::Error::msg("Invalid sampling of proof challenges."))?;
let nums_permutation_zs = all_stark.nums_permutation_zs(config);

View File

@ -13,6 +13,7 @@ pub enum ProgramError {
MemoryError(MemoryError),
GasLimitError,
InterpreterError,
IntegerTooLarge,
}
#[allow(clippy::enum_variant_names)]

View File

@ -1,4 +1,4 @@
mod errors;
pub(crate) mod errors;
mod gas;
pub(crate) mod memory;
mod operation;

View File

@ -139,7 +139,7 @@ pub(crate) fn generate_keccak_general<F: Field>(
..base_address
};
let val = state.memory.get(address);
val.as_u32() as u8
val.low_u32() as u8
})
.collect_vec();
log::debug!("Hashing {:?}", input);
@ -377,7 +377,7 @@ pub(crate) fn generate_push<F: Field>(
Segment::Code,
initial_offset + i,
))
.as_u32() as u8
.low_u32() as u8
})
.collect_vec();
@ -710,7 +710,7 @@ pub(crate) fn generate_mload_32bytes<F: Field>(
..base_address
};
let val = state.memory.get(address);
val.as_u32() as u8
val.low_u32() as u8
})
.collect_vec();