mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-09 01:03:08 +00:00
Working
This commit is contained in:
parent
0c539795fa
commit
19e6725cfa
@ -1,7 +1,11 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use anyhow::{anyhow, bail};
|
||||
use ethereum_types::{BigEndianHash, U256, U512};
|
||||
use keccak_hash::keccak;
|
||||
|
||||
use crate::cpu::kernel::prover_input::ProverInputFn;
|
||||
|
||||
/// Halt interpreter execution whenever a jump to this offset is done.
|
||||
const HALT_OFFSET: usize = 0xdeadbeef;
|
||||
|
||||
@ -55,29 +59,16 @@ pub(crate) struct Interpreter<'a> {
|
||||
offset: usize,
|
||||
pub(crate) stack: Vec<U256>,
|
||||
pub(crate) memory: EvmMemory,
|
||||
/// Non-deterministic prover inputs, stored backwards so that popping the last item gives the
|
||||
/// next prover input.
|
||||
prover_inputs: Vec<U256>,
|
||||
prover_inputs: &'a HashMap<usize, ProverInputFn>,
|
||||
running: bool,
|
||||
}
|
||||
|
||||
pub(crate) fn run(
|
||||
code: &[u8],
|
||||
pub(crate) fn run<'a>(
|
||||
code: &'a [u8],
|
||||
initial_offset: usize,
|
||||
initial_stack: Vec<U256>,
|
||||
) -> anyhow::Result<Interpreter> {
|
||||
run_with_input(code, initial_offset, initial_stack, vec![])
|
||||
}
|
||||
|
||||
pub(crate) fn run_with_input(
|
||||
code: &[u8],
|
||||
initial_offset: usize,
|
||||
initial_stack: Vec<U256>,
|
||||
mut prover_inputs: Vec<U256>,
|
||||
) -> anyhow::Result<Interpreter> {
|
||||
// Prover inputs are stored backwards, so that popping the last item gives the next input.
|
||||
prover_inputs.reverse();
|
||||
|
||||
prover_inputs: &'a HashMap<usize, ProverInputFn>,
|
||||
) -> anyhow::Result<Interpreter<'a>> {
|
||||
let mut interpreter = Interpreter {
|
||||
code,
|
||||
jumpdests: find_jumpdests(code),
|
||||
@ -337,11 +328,12 @@ impl<'a> Interpreter<'a> {
|
||||
}
|
||||
|
||||
fn run_prover_input(&mut self) -> anyhow::Result<()> {
|
||||
let input = self
|
||||
let prover_input_fn = self
|
||||
.prover_inputs
|
||||
.pop()
|
||||
.ok_or_else(|| anyhow!("Out of prover inputs"))?;
|
||||
self.stack.push(input);
|
||||
.get(&(self.offset - 1))
|
||||
.ok_or_else(|| anyhow!("Offset not in prover inputs."))?;
|
||||
let output = prover_input_fn.run(self.stack.clone());
|
||||
self.stack.push(output);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -424,6 +416,8 @@ fn find_jumpdests(code: &[u8]) -> Vec<usize> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::HashMap;
|
||||
|
||||
use hex_literal::hex;
|
||||
|
||||
use crate::cpu::kernel::interpreter::{run, Interpreter};
|
||||
@ -433,7 +427,10 @@ mod tests {
|
||||
let code = vec![
|
||||
0x60, 0x1, 0x60, 0x2, 0x1, 0x63, 0xde, 0xad, 0xbe, 0xef, 0x56,
|
||||
]; // PUSH1, 1, PUSH1, 2, ADD, PUSH4 deadbeef, JUMP
|
||||
assert_eq!(run(&code, 0, vec![])?.stack, vec![0x3.into()]);
|
||||
assert_eq!(
|
||||
run(&code, 0, vec![], &HashMap::new())?.stack,
|
||||
vec![0x3.into()],
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -456,7 +453,8 @@ mod tests {
|
||||
0x60, 0xff, 0x60, 0x0, 0x52, 0x60, 0, 0x51, 0x60, 0x1, 0x51, 0x60, 0x42, 0x60, 0x27,
|
||||
0x53,
|
||||
];
|
||||
let run = run(&code, 0, vec![])?;
|
||||
let pis = HashMap::new();
|
||||
let run = run(&code, 0, vec![], &pis)?;
|
||||
let Interpreter { stack, memory, .. } = run;
|
||||
assert_eq!(stack, vec![0xff.into(), 0xff00.into()]);
|
||||
assert_eq!(&memory.memory, &hex!("00000000000000000000000000000000000000000000000000000000000000ff0000000000000042000000000000000000000000000000000000000000000000"));
|
||||
|
||||
@ -17,7 +17,7 @@ impl From<Vec<String>> for ProverInputFn {
|
||||
}
|
||||
|
||||
impl ProverInputFn {
|
||||
pub(crate) fn run(&self, mut stack: Vec<U256>) -> U256 {
|
||||
pub(crate) fn run(&self, stack: Vec<U256>) -> U256 {
|
||||
match self.0[0].as_str() {
|
||||
"ff" => self.run_ff(stack),
|
||||
"storage" => todo!(),
|
||||
|
||||
@ -43,76 +43,82 @@ mod bn {
|
||||
|
||||
// Standard addition #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0, point1.1, point1.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([point2.1, point2.0])?);
|
||||
// Standard addition #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", point1.1, point1.0, point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([point2.1, point2.0])?);
|
||||
|
||||
// Standard doubling #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0, point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([point3.1, point3.0])?);
|
||||
// Standard doubling #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_double, initial_stack)?.stack;
|
||||
let stack = run(
|
||||
&kernel.code,
|
||||
ec_double,
|
||||
initial_stack,
|
||||
&kernel.prover_inputs,
|
||||
)?
|
||||
.stack;
|
||||
assert_eq!(stack, u256ify([point3.1, point3.0])?);
|
||||
// Standard doubling #3
|
||||
let initial_stack = u256ify(["0xdeadbeef", "0x2", point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([point3.1, point3.0])?);
|
||||
|
||||
// Addition with identity #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", identity.1, identity.0, point1.1, point1.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([point1.1, point1.0])?);
|
||||
// Addition with identity #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", point1.1, point1.0, identity.1, identity.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([point1.1, point1.0])?);
|
||||
// Addition with identity #3
|
||||
let initial_stack =
|
||||
u256ify(["0xdeadbeef", identity.1, identity.0, identity.1, identity.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([identity.1, identity.0])?);
|
||||
|
||||
// Addition with invalid point(s) #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0, invalid.1, invalid.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, vec![U256::MAX, U256::MAX]);
|
||||
// Addition with invalid point(s) #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", invalid.1, invalid.0, point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, vec![U256::MAX, U256::MAX]);
|
||||
// Addition with invalid point(s) #3
|
||||
let initial_stack = u256ify(["0xdeadbeef", invalid.1, invalid.0, identity.1, identity.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, vec![U256::MAX, U256::MAX]);
|
||||
// Addition with invalid point(s) #4
|
||||
let initial_stack = u256ify(["0xdeadbeef", invalid.1, invalid.0, invalid.1, invalid.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, vec![U256::MAX, U256::MAX]);
|
||||
|
||||
// Scalar multiplication #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", s, point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([point4.1, point4.0])?);
|
||||
// Scalar multiplication #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", "0x0", point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([identity.1, identity.0])?);
|
||||
// Scalar multiplication #3
|
||||
let initial_stack = u256ify(["0xdeadbeef", "0x1", point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([point0.1, point0.0])?);
|
||||
// Scalar multiplication #4
|
||||
let initial_stack = u256ify(["0xdeadbeef", s, identity.1, identity.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([identity.1, identity.0])?);
|
||||
// Scalar multiplication #5
|
||||
let initial_stack = u256ify(["0xdeadbeef", s, invalid.1, invalid.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, vec![U256::MAX, U256::MAX]);
|
||||
|
||||
// Multiple calls
|
||||
@ -126,7 +132,7 @@ mod bn {
|
||||
point0.1,
|
||||
point0.0,
|
||||
])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([point4.1, point4.0])?);
|
||||
|
||||
Ok(())
|
||||
@ -176,55 +182,61 @@ mod secp {
|
||||
|
||||
// Standard addition #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0, point1.1, point1.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([point2.1, point2.0])?);
|
||||
// Standard addition #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", point1.1, point1.0, point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([point2.1, point2.0])?);
|
||||
|
||||
// Standard doubling #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0, point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([point3.1, point3.0])?);
|
||||
// Standard doubling #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_double, initial_stack)?.stack;
|
||||
let stack = run(
|
||||
&kernel.code,
|
||||
ec_double,
|
||||
initial_stack,
|
||||
&kernel.prover_inputs,
|
||||
)?
|
||||
.stack;
|
||||
assert_eq!(stack, u256ify([point3.1, point3.0])?);
|
||||
// Standard doubling #3
|
||||
let initial_stack = u256ify(["0xdeadbeef", "0x2", point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([point3.1, point3.0])?);
|
||||
|
||||
// Addition with identity #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", identity.1, identity.0, point1.1, point1.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([point1.1, point1.0])?);
|
||||
// Addition with identity #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", point1.1, point1.0, identity.1, identity.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([point1.1, point1.0])?);
|
||||
// Addition with identity #3
|
||||
let initial_stack =
|
||||
u256ify(["0xdeadbeef", identity.1, identity.0, identity.1, identity.0])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([identity.1, identity.0])?);
|
||||
|
||||
// Scalar multiplication #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", s, point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([point4.1, point4.0])?);
|
||||
// Scalar multiplication #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", "0x0", point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([identity.1, identity.0])?);
|
||||
// Scalar multiplication #3
|
||||
let initial_stack = u256ify(["0xdeadbeef", "0x1", point0.1, point0.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([point0.1, point0.0])?);
|
||||
// Scalar multiplication #4
|
||||
let initial_stack = u256ify(["0xdeadbeef", s, identity.1, identity.0])?;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_mul, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([identity.1, identity.0])?);
|
||||
|
||||
// Multiple calls
|
||||
@ -238,7 +250,7 @@ mod secp {
|
||||
point0.1,
|
||||
point0.0,
|
||||
])?;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack)?.stack;
|
||||
let stack = run(&kernel.code, ec_add, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack, u256ify([point4.1, point4.0])?);
|
||||
|
||||
Ok(())
|
||||
|
||||
@ -18,7 +18,13 @@ fn test_valid_ecrecover(
|
||||
) -> Result<()> {
|
||||
let ecrecover = kernel.global_labels["ecrecover"];
|
||||
let initial_stack = u256ify(["0xdeadbeef", s, r, v, hash])?;
|
||||
let stack = run(&kernel.code, ecrecover, initial_stack)?.stack;
|
||||
let stack = run(
|
||||
&kernel.code,
|
||||
ecrecover,
|
||||
initial_stack,
|
||||
&kernel.prover_inputs,
|
||||
)?
|
||||
.stack;
|
||||
assert_eq!(stack[0], U256::from_str(expected).unwrap());
|
||||
|
||||
Ok(())
|
||||
@ -27,7 +33,13 @@ fn test_valid_ecrecover(
|
||||
fn test_invalid_ecrecover(hash: &str, v: &str, r: &str, s: &str, kernel: &Kernel) -> Result<()> {
|
||||
let ecrecover = kernel.global_labels["ecrecover"];
|
||||
let initial_stack = u256ify(["0xdeadbeef", s, r, v, hash])?;
|
||||
let stack = run(&kernel.code, ecrecover, initial_stack)?.stack;
|
||||
let stack = run(
|
||||
&kernel.code,
|
||||
ecrecover,
|
||||
initial_stack,
|
||||
&kernel.prover_inputs,
|
||||
)?
|
||||
.stack;
|
||||
assert_eq!(stack, vec![U256::MAX]);
|
||||
|
||||
Ok(())
|
||||
|
||||
@ -18,26 +18,26 @@ fn test_exp() -> Result<()> {
|
||||
|
||||
// Random input
|
||||
let initial_stack = vec![U256::from_str("0xdeadbeef")?, b, a];
|
||||
let stack_with_kernel = run(&kernel.code, exp, initial_stack)?.stack;
|
||||
let stack_with_kernel = run(&kernel.code, exp, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
let initial_stack = vec![b, a];
|
||||
let code = [0xa, 0x63, 0xde, 0xad, 0xbe, 0xef, 0x56]; // EXP, PUSH4 deadbeef, JUMP
|
||||
let stack_with_opcode = run(&code, 0, initial_stack)?.stack;
|
||||
let stack_with_opcode = run(&code, 0, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack_with_kernel, stack_with_opcode);
|
||||
|
||||
// 0 base
|
||||
let initial_stack = vec![U256::from_str("0xdeadbeef")?, b, U256::zero()];
|
||||
let stack_with_kernel = run(&kernel.code, exp, initial_stack)?.stack;
|
||||
let stack_with_kernel = run(&kernel.code, exp, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
let initial_stack = vec![b, U256::zero()];
|
||||
let code = [0xa, 0x63, 0xde, 0xad, 0xbe, 0xef, 0x56]; // EXP, PUSH4 deadbeef, JUMP
|
||||
let stack_with_opcode = run(&code, 0, initial_stack)?.stack;
|
||||
let stack_with_opcode = run(&code, 0, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack_with_kernel, stack_with_opcode);
|
||||
|
||||
// 0 exponent
|
||||
let initial_stack = vec![U256::from_str("0xdeadbeef")?, U256::zero(), a];
|
||||
let stack_with_kernel = run(&kernel.code, exp, initial_stack)?.stack;
|
||||
let stack_with_kernel = run(&kernel.code, exp, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
let initial_stack = vec![U256::zero(), a];
|
||||
let code = [0xa, 0x63, 0xde, 0xad, 0xbe, 0xef, 0x56]; // EXP, PUSH4 deadbeef, JUMP
|
||||
let stack_with_opcode = run(&code, 0, initial_stack)?.stack;
|
||||
let stack_with_opcode = run(&code, 0, initial_stack, &kernel.prover_inputs)?.stack;
|
||||
assert_eq!(stack_with_kernel, stack_with_opcode);
|
||||
|
||||
Ok(())
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user