plonky2/evm/src/generation/prover_input.rs

395 lines
13 KiB
Rust
Raw Normal View History

2023-01-21 13:19:07 +07:00
use std::mem::transmute;
2022-07-23 11:47:10 +02:00
use std::str::FromStr;
use anyhow::{bail, Error};
2023-03-21 21:10:01 -07:00
use ethereum_types::{BigEndianHash, H256, U256, U512};
2023-03-07 15:15:20 -08:00
use itertools::Itertools;
2023-07-16 15:01:32 -04:00
use num_bigint::BigUint;
use plonky2::field::types::Field;
2023-04-15 10:45:56 -04:00
use serde::{Deserialize, Serialize};
2022-07-23 11:47:10 +02:00
2023-03-21 21:10:01 -07:00
use crate::extension_tower::{FieldExt, Fp12, BLS381, BN254};
use crate::generation::prover_input::EvmField::{
2023-03-21 21:10:01 -07:00
Bls381Base, Bls381Scalar, Bn254Base, Bn254Scalar, Secp256k1Base, Secp256k1Scalar,
2022-07-23 11:47:10 +02:00
};
use crate::generation::prover_input::FieldOp::{Inverse, Sqrt};
use crate::generation::state::GenerationState;
2023-03-15 22:16:59 -07:00
use crate::memory::segments::Segment;
use crate::memory::segments::Segment::BnPairing;
use crate::util::{biguint_to_mem_vec, mem_vec_to_biguint, u256_to_usize};
use crate::witness::errors::ProgramError;
use crate::witness::errors::ProverInputError::*;
use crate::witness::util::{current_context_peek, stack_peek};
2022-07-23 11:47:10 +02:00
2022-07-23 12:52:45 +02:00
/// Prover input function represented as a scoped function name.
/// Example: `PROVER_INPUT(ff::bn254_base::inverse)` is represented as `ProverInputFn([ff, bn254_base, inverse])`.
2023-04-15 10:45:56 -04:00
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)]
2022-07-23 12:36:03 +02:00
pub struct ProverInputFn(Vec<String>);
2022-07-23 11:16:45 +02:00
impl From<Vec<String>> for ProverInputFn {
fn from(v: Vec<String>) -> Self {
Self(v)
}
}
2022-07-23 11:47:10 +02:00
impl<F: Field> GenerationState<F> {
pub(crate) fn prover_input(&mut self, input_fn: &ProverInputFn) -> Result<U256, ProgramError> {
match input_fn.0[0].as_str() {
2022-09-29 23:09:32 -07:00
"end_of_txns" => self.run_end_of_txns(),
2022-12-01 11:15:51 -08:00
"ff" => self.run_ff(input_fn),
2023-03-21 21:10:01 -07:00
"sf" => self.run_sf(input_fn),
2022-12-20 00:22:59 -08:00
"ffe" => self.run_ffe(input_fn),
2022-09-22 20:09:48 -07:00
"mpt" => self.run_mpt(),
2022-09-29 23:09:32 -07:00
"rlp" => self.run_rlp(),
2023-08-21 23:32:53 +01:00
"current_hash" => self.run_current_hash(),
2022-12-01 11:15:51 -08:00
"account_code" => self.run_account_code(input_fn),
"bignum_modmul" => self.run_bignum_modmul(),
"withdrawal" => self.run_withdrawal(),
_ => Err(ProgramError::ProverInputError(InvalidFunction)),
2022-07-23 11:47:10 +02:00
}
}
fn run_end_of_txns(&mut self) -> Result<U256, ProgramError> {
2022-09-29 23:09:32 -07:00
let end = self.next_txn_index == self.inputs.signed_txns.len();
if end {
Ok(U256::one())
2022-09-29 23:09:32 -07:00
} else {
self.next_txn_index += 1;
Ok(U256::zero())
2022-09-29 23:09:32 -07:00
}
}
/// Finite field operations.
fn run_ff(&self, input_fn: &ProverInputFn) -> Result<U256, ProgramError> {
let field = EvmField::from_str(input_fn.0[1].as_str())
.map_err(|_| ProgramError::ProverInputError(InvalidFunction))?;
let op = FieldOp::from_str(input_fn.0[2].as_str())
.map_err(|_| ProgramError::ProverInputError(InvalidFunction))?;
let x = stack_peek(self, 0)?;
2022-07-23 11:47:10 +02:00
field.op(op, x)
}
2022-07-23 12:52:45 +02:00
2023-03-21 21:10:01 -07:00
/// Special finite field operations.
fn run_sf(&self, input_fn: &ProverInputFn) -> Result<U256, ProgramError> {
let field = EvmField::from_str(input_fn.0[1].as_str())
.map_err(|_| ProgramError::ProverInputError(InvalidFunction))?;
2023-03-21 21:16:19 -07:00
let inputs: [U256; 4] = match field {
Bls381Base => (0..4)
.map(|i| stack_peek(self, i))
.collect::<Result<Vec<U256>, _>>()?
.try_into()
.unwrap(),
2023-03-21 21:10:01 -07:00
_ => todo!(),
};
let res = match input_fn.0[2].as_str() {
2023-03-21 21:16:19 -07:00
"add_lo" => field.add_lo(inputs),
"add_hi" => field.add_hi(inputs),
"mul_lo" => field.mul_lo(inputs),
"mul_hi" => field.mul_hi(inputs),
"sub_lo" => field.sub_lo(inputs),
"sub_hi" => field.sub_hi(inputs),
_ => return Err(ProgramError::ProverInputError(InvalidFunction)),
};
Ok(res)
2023-03-21 21:10:01 -07:00
}
2022-12-20 00:22:59 -08:00
/// Finite field extension operations.
fn run_ffe(&self, input_fn: &ProverInputFn) -> Result<U256, ProgramError> {
let field = EvmField::from_str(input_fn.0[1].as_str())
.map_err(|_| ProgramError::ProverInputError(InvalidFunction))?;
2023-01-21 13:52:26 +07:00
let n = input_fn.0[2]
.as_str()
.split('_')
.nth(1)
.unwrap()
.parse::<usize>()
.unwrap();
let ptr = stack_peek(self, 11 - n).map(u256_to_usize)??;
2023-01-21 16:38:43 +07:00
let f: [U256; 12] = match field {
Bn254Base => std::array::from_fn(|i| current_context_peek(self, BnPairing, ptr + i)),
2023-01-21 16:38:43 +07:00
_ => todo!(),
};
Ok(field.field_extension_inverse(n, f))
2022-12-20 00:22:59 -08:00
}
/// MPT data.
fn run_mpt(&mut self) -> Result<U256, ProgramError> {
2022-09-22 20:09:48 -07:00
self.mpt_prover_inputs
.pop()
.ok_or(ProgramError::ProverInputError(OutOfMptData))
2022-07-23 12:52:45 +02:00
}
2022-09-29 23:09:32 -07:00
/// RLP data.
fn run_rlp(&mut self) -> Result<U256, ProgramError> {
2022-09-29 23:09:32 -07:00
self.rlp_prover_inputs
.pop()
.ok_or(ProgramError::ProverInputError(OutOfRlpData))
2022-09-29 23:09:32 -07:00
}
2022-10-21 18:00:41 +02:00
fn run_current_hash(&mut self) -> Result<U256, ProgramError> {
Ok(U256::from_big_endian(&self.inputs.block_hashes.cur_hash.0))
2023-08-21 23:32:53 +01:00
}
2022-10-27 14:57:17 +02:00
/// Account code.
fn run_account_code(&mut self, input_fn: &ProverInputFn) -> Result<U256, ProgramError> {
2022-10-21 18:00:41 +02:00
match input_fn.0[1].as_str() {
"length" => {
2022-10-27 14:57:17 +02:00
// Return length of code.
// stack: codehash, ...
let codehash = stack_peek(self, 0)?;
Ok(self
.inputs
2023-02-24 23:10:26 -08:00
.contract_code
.get(&H256::from_uint(&codehash))
.ok_or(ProgramError::ProverInputError(CodeHashNotFound))?
2022-10-21 18:00:41 +02:00
.len()
.into())
2022-10-21 18:00:41 +02:00
}
"get" => {
2022-10-27 14:57:17 +02:00
// Return `code[i]`.
// stack: i, code_length, codehash, ...
let i = stack_peek(self, 0).map(u256_to_usize)??;
let codehash = stack_peek(self, 2)?;
Ok(self
.inputs
2023-02-24 23:10:26 -08:00
.contract_code
.get(&H256::from_uint(&codehash))
.ok_or(ProgramError::ProverInputError(CodeHashNotFound))?[i]
.into())
2022-10-21 18:00:41 +02:00
}
_ => Err(ProgramError::ProverInputError(InvalidInput)),
2022-10-21 18:00:41 +02:00
}
}
2023-03-07 15:15:20 -08:00
// Bignum modular multiplication.
// On the first call, calculates the remainder and quotient of the given inputs.
// These are stored, as limbs, in self.bignum_modmul_result_limbs.
// Subsequent calls return one limb at a time, in order (first remainder and then quotient).
fn run_bignum_modmul(&mut self) -> Result<U256, ProgramError> {
if self.bignum_modmul_result_limbs.is_empty() {
let len = stack_peek(self, 1).map(u256_to_usize)??;
let a_start_loc = stack_peek(self, 2).map(u256_to_usize)??;
let b_start_loc = stack_peek(self, 3).map(u256_to_usize)??;
let m_start_loc = stack_peek(self, 4).map(u256_to_usize)??;
2023-03-07 15:15:20 -08:00
let (remainder, quotient) =
self.bignum_modmul(len, a_start_loc, b_start_loc, m_start_loc);
2023-03-21 16:13:59 -07:00
self.bignum_modmul_result_limbs = remainder
2023-03-07 15:15:20 -08:00
.iter()
.cloned()
.pad_using(len, |_| 0.into())
2023-03-28 11:15:01 -07:00
.chain(quotient.iter().cloned().pad_using(2 * len, |_| 0.into()))
2023-03-07 15:15:20 -08:00
.collect();
self.bignum_modmul_result_limbs.reverse();
2023-03-07 15:15:20 -08:00
}
self.bignum_modmul_result_limbs
.pop()
.ok_or(ProgramError::ProverInputError(InvalidInput))
2023-03-07 15:15:20 -08:00
}
fn bignum_modmul(
2023-03-07 15:15:20 -08:00
&mut self,
len: usize,
a_start_loc: usize,
b_start_loc: usize,
m_start_loc: usize,
) -> (Vec<U256>, Vec<U256>) {
let n = self.memory.contexts.len();
let a = &self.memory.contexts[n - 1].segments[Segment::KernelGeneral as usize].content
2023-03-07 15:15:20 -08:00
[a_start_loc..a_start_loc + len];
let b = &self.memory.contexts[n - 1].segments[Segment::KernelGeneral as usize].content
2023-03-07 15:15:20 -08:00
[b_start_loc..b_start_loc + len];
let m = &self.memory.contexts[n - 1].segments[Segment::KernelGeneral as usize].content
2023-03-07 15:15:20 -08:00
[m_start_loc..m_start_loc + len];
let a_biguint = mem_vec_to_biguint(a);
let b_biguint = mem_vec_to_biguint(b);
let m_biguint = mem_vec_to_biguint(m);
let prod = a_biguint * b_biguint;
2023-07-16 15:01:32 -04:00
let quo = if m_biguint == BigUint::default() {
BigUint::default()
} else {
&prod / &m_biguint
};
2023-04-04 13:33:20 -07:00
let rem = prod - m_biguint * &quo;
2023-03-28 11:15:01 -07:00
(biguint_to_mem_vec(rem), biguint_to_mem_vec(quo))
2023-03-07 15:15:20 -08:00
}
/// Withdrawal data.
fn run_withdrawal(&mut self) -> Result<U256, ProgramError> {
self.withdrawal_prover_inputs
.pop()
.ok_or(ProgramError::ProverInputError(OutOfWithdrawalData))
}
2022-07-23 11:47:10 +02:00
}
enum EvmField {
2023-03-21 21:10:01 -07:00
Bls381Base,
Bls381Scalar,
2022-07-23 11:47:10 +02:00
Bn254Base,
Bn254Scalar,
Secp256k1Base,
Secp256k1Scalar,
}
enum FieldOp {
Inverse,
Sqrt,
}
impl FromStr for EvmField {
type Err = Error;
2022-07-23 11:47:10 +02:00
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
2023-03-21 21:10:01 -07:00
"bls381_base" => Bls381Base,
"bls381_scalar" => Bls381Scalar,
2022-07-23 11:47:10 +02:00
"bn254_base" => Bn254Base,
"bn254_scalar" => Bn254Scalar,
"secp256k1_base" => Secp256k1Base,
"secp256k1_scalar" => Secp256k1Scalar,
_ => bail!("Unrecognized field."),
2022-07-23 11:47:10 +02:00
})
}
}
impl FromStr for FieldOp {
type Err = Error;
2022-07-23 11:47:10 +02:00
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"inverse" => Inverse,
"sqrt" => Sqrt,
_ => bail!("Unrecognized field operation."),
2022-07-23 11:47:10 +02:00
})
}
}
impl EvmField {
2022-07-23 11:47:10 +02:00
fn order(&self) -> U256 {
match self {
2023-03-21 21:10:01 -07:00
EvmField::Bls381Base => todo!(),
EvmField::Bls381Scalar => todo!(),
EvmField::Bn254Base => {
2022-07-23 11:47:10 +02:00
U256::from_str("0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47")
.unwrap()
}
EvmField::Bn254Scalar => todo!(),
EvmField::Secp256k1Base => {
2022-07-27 16:49:26 +02:00
U256::from_str("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f")
.unwrap()
}
EvmField::Secp256k1Scalar => {
2022-07-27 16:49:26 +02:00
U256::from_str("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141")
.unwrap()
}
2022-07-23 11:47:10 +02:00
}
}
fn op(&self, op: FieldOp, x: U256) -> Result<U256, ProgramError> {
2022-07-23 11:47:10 +02:00
match op {
FieldOp::Inverse => self.inverse(x),
2022-07-27 17:06:16 +02:00
FieldOp::Sqrt => self.sqrt(x),
2022-07-23 11:47:10 +02:00
}
}
fn inverse(&self, x: U256) -> Result<U256, ProgramError> {
2022-07-23 11:47:10 +02:00
let n = self.order();
if x >= n {
return Err(ProgramError::ProverInputError(InvalidInput));
};
2022-07-23 11:47:10 +02:00
modexp(x, n - 2, n)
}
2022-07-27 17:06:16 +02:00
fn sqrt(&self, x: U256) -> Result<U256, ProgramError> {
2022-07-27 17:06:16 +02:00
let n = self.order();
if x >= n {
return Err(ProgramError::ProverInputError(InvalidInput));
};
2022-07-27 17:06:16 +02:00
let (q, r) = (n + 1).div_mod(4.into());
if !r.is_zero() {
return Err(ProgramError::ProverInputError(InvalidInput));
};
// Only naive sqrt implementation for now. If needed implement Tonelli-Shanks
2022-07-27 17:06:16 +02:00
modexp(x, q, n)
}
2022-12-20 00:22:59 -08:00
2023-03-21 21:10:01 -07:00
fn add_lo(&self, inputs: [U256; 4]) -> U256 {
let [y1, x0, x1, y0] = inputs;
let x = U512::from(x0) + (U512::from(x1) << 256);
let y = U512::from(y0) + (U512::from(y1) << 256);
let z = BLS381 { val: x } + BLS381 { val: y };
z.lo()
}
fn add_hi(&self, inputs: [U256; 4]) -> U256 {
let [x0, x1, y0, y1] = inputs;
let x = U512::from(x0) + (U512::from(x1) << 256);
let y = U512::from(y0) + (U512::from(y1) << 256);
let z = BLS381 { val: x } + BLS381 { val: y };
z.hi()
}
fn mul_lo(&self, inputs: [U256; 4]) -> U256 {
let [y1, x0, x1, y0] = inputs;
let x = U512::from(x0) + (U512::from(x1) << 256);
let y = U512::from(y0) + (U512::from(y1) << 256);
let z = BLS381 { val: x } * BLS381 { val: y };
z.lo()
}
fn mul_hi(&self, inputs: [U256; 4]) -> U256 {
let [x0, x1, y0, y1] = inputs;
let x = U512::from(x0) + (U512::from(x1) << 256);
let y = U512::from(y0) + (U512::from(y1) << 256);
let z = BLS381 { val: x } * BLS381 { val: y };
z.hi()
}
fn sub_lo(&self, inputs: [U256; 4]) -> U256 {
let [y1, x0, x1, y0] = inputs;
let x = U512::from(x0) + (U512::from(x1) << 256);
let y = U512::from(y0) + (U512::from(y1) << 256);
let z = BLS381 { val: x } - BLS381 { val: y };
z.lo()
}
fn sub_hi(&self, inputs: [U256; 4]) -> U256 {
let [x0, x1, y0, y1] = inputs;
let x = U512::from(x0) + (U512::from(x1) << 256);
let y = U512::from(y0) + (U512::from(y1) << 256);
let z = BLS381 { val: x } - BLS381 { val: y };
z.hi()
}
2023-01-21 16:38:43 +07:00
fn field_extension_inverse(&self, n: usize, f: [U256; 12]) -> U256 {
2023-03-21 19:19:02 -07:00
let f: Fp12<BN254> = unsafe { transmute(f) };
2023-01-23 14:59:08 +07:00
let f_inv: [U256; 12] = unsafe { transmute(f.inv()) };
2023-01-21 13:19:07 +07:00
f_inv[n]
2023-01-18 14:41:09 +07:00
}
2022-07-23 11:47:10 +02:00
}
fn modexp(x: U256, e: U256, n: U256) -> Result<U256, ProgramError> {
2022-07-23 11:47:10 +02:00
let mut current = x;
let mut product = U256::one();
for j in 0..256 {
2022-07-28 10:35:53 +02:00
if e.bit(j) {
product = U256::try_from(product.full_mul(current) % n)
.map_err(|_| ProgramError::ProverInputError(InvalidInput))?;
2022-07-23 11:47:10 +02:00
}
current = U256::try_from(current.full_mul(current) % n)
.map_err(|_| ProgramError::ProverInputError(InvalidInput))?;
2022-07-23 11:47:10 +02:00
}
Ok(product)
2022-07-23 11:47:10 +02:00
}