Merge pull request #635 from mir-protocol/nondeterministic_ec_ops

Use non-determinism in EC ops
This commit is contained in:
wborgeaud 2022-07-29 13:05:12 +02:00 committed by GitHub
commit 2bae8f92f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 321 additions and 2712 deletions

View File

@ -14,14 +14,26 @@ use crate::memory::segments::Segment;
pub static KERNEL: Lazy<Kernel> = Lazy::new(combined_kernel);
const EC_CONSTANTS: [(&str, [u8; 32]); 3] = [
(
"BN_BASE",
hex!("30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"),
),
(
"SECP_BASE",
hex!("fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"),
),
(
"SECP_SCALAR",
hex!("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"),
),
];
pub fn evm_constants() -> HashMap<String, U256> {
let mut c = HashMap::new();
c.insert(
"BN_BASE".into(),
U256::from_big_endian(&hex!(
"30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"
)),
);
for (name, value) in EC_CONSTANTS {
c.insert(name.into(), U256::from_big_endian(&value));
}
for segment in Segment::all() {
c.insert(segment.var_name().into(), (segment as u32).into());
}
@ -79,5 +91,6 @@ mod tests {
// Make sure we can parse and assemble the entire kernel.
let kernel = combined_kernel();
debug!("Total kernel size: {} bytes", kernel.code.len());
dbg!("Total kernel size: {} bytes", kernel.code.len());
}
}

View File

@ -11,7 +11,7 @@
%macro mulmodn
// stack: x, y
PUSH 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47
%bn_base
// stack: N, x, y
SWAP2
// stack: y, x, N
@ -25,482 +25,15 @@
%mulmodn
%endmacro
// Computes the inverse modulo N using x^-1 = x^(N-2) mod N and square-and-multiply modular exponentiation.
// Non-deterministically provide the inverse modulo N.
%macro inverse
DUP1
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
%squaremodn
%squaremodn
DUP2
%mulmodn
%squaremodn
%squaremodn
DUP2
%mulmodn
SWAP1
// stack: x, x^-1
POP
// stack: x
PROVER_INPUT(ff::bn254_base::inverse)
// stack: x^-1, x
%stack (inv, x) -> (inv, x, @BN_BASE, inv)
// stack: x^-1, x, N, x^-1
MULMOD
// stack: x^-1 * x, x^-1
%assert_eq_const(1)
// stack: x^-1
%endmacro

View File

@ -2,6 +2,10 @@
global ec_mul_valid_point_secp:
JUMPDEST
// stack: x, y, s, retdest
%stack (x,y) -> (x,y,x,y)
%ec_isidentity
// stack: (x,y)==(0,0), x, y, s, retdest
%jumpi(ret_zero_ec_mul)
DUP3
// stack: s, x, y, s, retdest
%jumpi(step_case)

View File

@ -17,656 +17,15 @@
%mulmodn_secp_scalar
%endmacro
// Computes the inverse modulo N using x^-1 = x^(N-2) mod N and square-and-multiply modular exponentiation.
// Non-deterministically provide the inverse modulo N.
%macro inverse_secp_scalar
DUP1
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
%squaremodn_secp_scalar
DUP2
%mulmodn_secp_scalar
SWAP1
// stack: x, x^-1
POP
// stack: x
PROVER_INPUT(ff::secp256k1_scalar::inverse)
// stack: x^-1, x
%stack (inv, x) -> (inv, x, @SECP_SCALAR, inv)
// stack: x^-1, x, N, x^-1
MULMOD
// stack: x^-1 * x, x^-1
%assert_eq_const(1)
// stack: x^-1
%endmacro

View File

@ -10,7 +10,7 @@
// stack: x^3+7, x, parity
DUP1
// stack: x^3+7, x^3+7, parity
%sqrt_secp_base
%sqrt_secp_base_unsafe
// stack: y, x^3+7, x, parity
SWAP1
// stack: x^3+7, y, parity
@ -60,759 +60,14 @@
ADDMOD
%endmacro
// Returns a square root of x if one exists, otherwise an undefined value.
// Computed as x^(q+1)/4, with q the Secp base field order.
// To replace with more efficient method using non-determinism later.
%macro sqrt_secp_base
// Non-deterministically provide the square root modulo N.
// Note: The square root is not checked and the macro doesn't panic if `x` is not a square.
%macro sqrt_secp_base_unsafe
// stack: x
DUP1
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
%squaremodn_secp_base
%squaremodn_secp_base
%squaremodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
%squaremodn_secp_base
PROVER_INPUT(ff::secp256k1_base::sqrt)
// stack: x, x
SWAP1
// stack: x, x^-1
// stack: x, x
POP
// stack: x^-1
// stack: x
%endmacro

View File

@ -25,762 +25,15 @@
%mulmodn_secp_base
%endmacro
// Computes the inverse modulo N using x^-1 = x^(N-2) mod N and square-and-multiply modular exponentiation.
// Non-deterministically provide the inverse modulo N.
%macro inverse_secp_base
DUP1
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
%squaremodn_secp_base
%squaremodn_secp_base
%squaremodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
%squaremodn_secp_base
%squaremodn_secp_base
DUP2
%mulmodn_secp_base
SWAP1
// stack: x, x^-1
POP
// stack: x
PROVER_INPUT(ff::secp256k1_base::inverse)
// stack: x^-1, x
%stack (inv, x) -> (inv, x, @SECP_BASE, inv)
// stack: x^-1, x, N, x^-1
MULMOD
// stack: x^-1 * x, x^-1
%assert_eq_const(1)
// stack: x^-1
%endmacro

View File

@ -7,6 +7,7 @@ use log::debug;
use super::ast::PushTarget;
use crate::cpu::kernel::ast::{Literal, StackReplacement};
use crate::cpu::kernel::keccak_util::hash_kernel;
use crate::cpu::kernel::prover_input::ProverInputFn;
use crate::cpu::kernel::stack_manipulation::expand_stack_manipulation;
use crate::cpu::kernel::{
ast::{File, Item},
@ -27,15 +28,23 @@ pub struct Kernel {
pub(crate) code_hash: [u32; 8],
pub(crate) global_labels: HashMap<String, usize>,
/// Map from `PROVER_INPUT` offsets to their corresponding `ProverInputFn`.
pub(crate) prover_inputs: HashMap<usize, ProverInputFn>,
}
impl Kernel {
fn new(code: Vec<u8>, global_labels: HashMap<String, usize>) -> Self {
fn new(
code: Vec<u8>,
global_labels: HashMap<String, usize>,
prover_inputs: HashMap<usize, ProverInputFn>,
) -> Self {
let code_hash = hash_kernel(&code);
Self {
code,
code_hash,
global_labels,
prover_inputs,
}
}
}
@ -57,6 +66,7 @@ impl Macro {
pub(crate) fn assemble(files: Vec<File>, constants: HashMap<String, U256>) -> Kernel {
let macros = find_macros(&files);
let mut global_labels = HashMap::new();
let mut prover_inputs = HashMap::new();
let mut offset = 0;
let mut expanded_files = Vec::with_capacity(files.len());
let mut local_labels = Vec::with_capacity(files.len());
@ -65,7 +75,12 @@ pub(crate) fn assemble(files: Vec<File>, constants: HashMap<String, U256>) -> Ke
let expanded_file = expand_repeats(expanded_file);
let expanded_file = inline_constants(expanded_file, &constants);
let expanded_file = expand_stack_manipulation(expanded_file);
local_labels.push(find_labels(&expanded_file, &mut offset, &mut global_labels));
local_labels.push(find_labels(
&expanded_file,
&mut offset,
&mut global_labels,
&mut prover_inputs,
));
expanded_files.push(expanded_file);
}
let mut code = vec![];
@ -76,7 +91,7 @@ pub(crate) fn assemble(files: Vec<File>, constants: HashMap<String, U256>) -> Ke
debug!("Assembled file size: {} bytes", file_len);
}
assert_eq!(code.len(), offset, "Code length doesn't match offset.");
Kernel::new(code, global_labels)
Kernel::new(code, global_labels, prover_inputs)
}
fn find_macros(files: &[File]) -> HashMap<String, Macro> {
@ -217,6 +232,7 @@ fn find_labels(
body: &[Item],
offset: &mut usize,
global_labels: &mut HashMap<String, usize>,
prover_inputs: &mut HashMap<usize, ProverInputFn>,
) -> HashMap<String, usize> {
// Discover the offset of each label in this file.
let mut local_labels = HashMap::<String, usize>::new();
@ -237,6 +253,10 @@ fn find_labels(
assert!(old.is_none(), "Duplicate local label: {}", label);
}
Item::Push(target) => *offset += 1 + push_target_size(target) as usize,
Item::ProverInput(prover_input_fn) => {
prover_inputs.insert(*offset, prover_input_fn.clone());
*offset += 1;
}
Item::StandardOp(_) => *offset += 1,
Item::Bytes(bytes) => *offset += bytes.len(),
}
@ -283,6 +303,9 @@ fn assemble_file(
code.push(get_push_opcode(target_bytes.len() as u8));
code.extend(target_bytes);
}
Item::ProverInput(_) => {
code.push(get_opcode("PROVER_INPUT"));
}
Item::StandardOp(opcode) => {
code.push(get_opcode(&opcode));
}
@ -357,7 +380,7 @@ mod tests {
expected_global_labels.insert("function_1".to_string(), 0);
expected_global_labels.insert("function_2".to_string(), 3);
let expected_kernel = Kernel::new(expected_code, expected_global_labels);
let expected_kernel = Kernel::new(expected_code, expected_global_labels, HashMap::new());
let program = vec![file_1, file_2];
assert_eq!(assemble(program, HashMap::new()), expected_kernel);

View File

@ -1,6 +1,8 @@
use ethereum_types::U256;
use plonky2_util::ceil_div_usize;
use crate::cpu::kernel::prover_input::ProverInputFn;
#[derive(Debug)]
pub(crate) struct File {
pub(crate) body: Vec<Item>,
@ -25,6 +27,8 @@ pub(crate) enum Item {
LocalLabelDeclaration(String),
/// A `PUSH` operation.
Push(PushTarget),
/// A `ProverInput` operation.
ProverInput(ProverInputFn),
/// Any opcode besides a PUSH opcode.
StandardOp(String),
/// Literal hex data; should contain an even number of hex chars.

View File

@ -15,7 +15,7 @@ literal = { literal_hex | literal_decimal }
variable = ${ "$" ~ identifier }
constant = ${ "@" ~ identifier }
item = { macro_def | macro_call | repeat | stack | global_label | local_label | bytes_item | push_instruction | nullary_instruction }
item = { macro_def | macro_call | repeat | stack | global_label | local_label | bytes_item | push_instruction | prover_input_instruction | nullary_instruction }
macro_def = { ^"%macro" ~ identifier ~ paramlist? ~ item* ~ ^"%endmacro" }
macro_call = ${ "%" ~ !(^"macro" | ^"endmacro" | ^"rep" | ^"endrep" | ^"stack") ~ identifier ~ macro_arglist? }
repeat = { ^"%rep" ~ literal ~ item* ~ ^"%endrep" }
@ -29,6 +29,8 @@ local_label = { identifier ~ ":" }
bytes_item = { ^"BYTES " ~ literal ~ ("," ~ literal)* }
push_instruction = { ^"PUSH " ~ push_target }
push_target = { literal | identifier | variable | constant }
prover_input_instruction = { ^"PROVER_INPUT" ~ "(" ~ prover_input_fn ~ ")" }
prover_input_fn = { identifier ~ ("::" ~ identifier)*}
nullary_instruction = { identifier }
file = { SOI ~ item* ~ silent_eoi }

View File

@ -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::assembler::Kernel;
use crate::cpu::kernel::prover_input::ProverInputFn;
use crate::generation::memory::MemoryContextState;
use crate::memory::segments::Segment;
@ -32,44 +36,46 @@ impl InterpreterMemory {
}
// TODO: Remove `code` and `stack` fields as they are contained in `memory`.
pub(crate) struct Interpreter<'a> {
pub struct Interpreter<'a> {
code: &'a [u8],
jumpdests: Vec<usize>,
offset: usize,
pub(crate) stack: Vec<U256>,
context: usize,
memory: InterpreterMemory,
/// Non-deterministic prover inputs, stored backwards so that popping the last item gives the
/// next prover input.
prover_inputs_map: &'a HashMap<usize, ProverInputFn>,
prover_inputs: Vec<U256>,
running: bool,
}
pub(crate) fn run(
code: &[u8],
pub fn run_with_kernel(
kernel: &Kernel,
initial_offset: usize,
initial_stack: Vec<U256>,
) -> anyhow::Result<Interpreter> {
run_with_input(code, initial_offset, initial_stack, vec![])
run(
&kernel.code,
initial_offset,
initial_stack,
&kernel.prover_inputs,
)
}
pub(crate) fn run_with_input(
code: &[u8],
pub fn run<'a>(
code: &'a [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),
offset: initial_offset,
stack: initial_stack,
context: 0,
memory: InterpreterMemory::default(),
prover_inputs,
prover_inputs_map: prover_inputs,
prover_inputs: Vec::new(),
context: 0,
running: true,
};
@ -326,11 +332,13 @@ impl<'a> Interpreter<'a> {
}
fn run_prover_input(&mut self) -> anyhow::Result<()> {
let input = self
.prover_inputs
.pop()
.ok_or_else(|| anyhow!("Out of prover inputs"))?;
self.stack.push(input);
let prover_input_fn = self
.prover_inputs_map
.get(&(self.offset - 1))
.ok_or_else(|| anyhow!("Offset not in prover inputs."))?;
let output = prover_input_fn.run(&self.stack);
self.stack.push(output);
self.prover_inputs.push(output);
Ok(())
}
@ -458,6 +466,8 @@ fn find_jumpdests(code: &[u8]) -> Vec<usize> {
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use crate::cpu::kernel::interpreter::{run, Interpreter};
use crate::memory::segments::Segment;
@ -466,7 +476,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(())
}
@ -489,7 +502,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!(

View File

@ -4,6 +4,7 @@ mod ast;
pub(crate) mod keccak_util;
mod opcodes;
mod parser;
pub mod prover_input;
mod stack_manipulation;
mod txn_fields;

View File

@ -33,6 +33,15 @@ fn parse_item(item: Pair<Rule>) -> Item {
}
Rule::bytes_item => Item::Bytes(item.into_inner().map(parse_literal).collect()),
Rule::push_instruction => Item::Push(parse_push_target(item.into_inner().next().unwrap())),
Rule::prover_input_instruction => Item::ProverInput(
item.into_inner()
.next()
.unwrap()
.into_inner()
.map(|x| x.as_str().into())
.collect::<Vec<_>>()
.into(),
),
Rule::nullary_instruction => Item::StandardOp(item.as_str().into()),
_ => panic!("Unexpected {:?}", item.as_rule()),
}

View File

@ -0,0 +1,139 @@
use std::str::FromStr;
use ethereum_types::U256;
use crate::cpu::kernel::prover_input::Field::{
Bn254Base, Bn254Scalar, Secp256k1Base, Secp256k1Scalar,
};
use crate::cpu::kernel::prover_input::FieldOp::{Inverse, Sqrt};
/// 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)]
pub struct ProverInputFn(Vec<String>);
impl From<Vec<String>> for ProverInputFn {
fn from(v: Vec<String>) -> Self {
Self(v)
}
}
impl ProverInputFn {
/// Run the function on the stack.
pub fn run(&self, stack: &[U256]) -> U256 {
match self.0[0].as_str() {
"ff" => self.run_ff(stack),
"mpt" => todo!(),
_ => panic!("Unrecognized prover input function."),
}
}
// Finite field operations.
fn run_ff(&self, stack: &[U256]) -> U256 {
let field = Field::from_str(self.0[1].as_str()).unwrap();
let op = FieldOp::from_str(self.0[2].as_str()).unwrap();
let x = *stack.last().expect("Empty stack");
field.op(op, x)
}
// MPT operations.
#[allow(dead_code)]
fn run_mpt(&self, _stack: Vec<U256>) -> U256 {
todo!()
}
}
enum Field {
Bn254Base,
Bn254Scalar,
Secp256k1Base,
Secp256k1Scalar,
}
enum FieldOp {
Inverse,
Sqrt,
}
impl FromStr for Field {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"bn254_base" => Bn254Base,
"bn254_scalar" => Bn254Scalar,
"secp256k1_base" => Secp256k1Base,
"secp256k1_scalar" => Secp256k1Scalar,
_ => panic!("Unrecognized field."),
})
}
}
impl FromStr for FieldOp {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"inverse" => Inverse,
"sqrt" => Sqrt,
_ => panic!("Unrecognized field operation."),
})
}
}
impl Field {
fn order(&self) -> U256 {
match self {
Field::Bn254Base => {
U256::from_str("0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47")
.unwrap()
}
Field::Bn254Scalar => todo!(),
Field::Secp256k1Base => {
U256::from_str("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f")
.unwrap()
}
Field::Secp256k1Scalar => {
U256::from_str("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141")
.unwrap()
}
}
}
fn op(&self, op: FieldOp, x: U256) -> U256 {
match op {
FieldOp::Inverse => self.inverse(x),
FieldOp::Sqrt => self.sqrt(x),
}
}
fn inverse(&self, x: U256) -> U256 {
let n = self.order();
assert!(x < n);
modexp(x, n - 2, n)
}
fn sqrt(&self, x: U256) -> U256 {
let n = self.order();
assert!(x < n);
let (q, r) = (n + 1).div_mod(4.into());
assert!(
r.is_zero(),
"Only naive sqrt implementation for now. If needed implement Tonelli-Shanks."
);
modexp(x, q, n)
}
}
fn modexp(x: U256, e: U256, n: U256) -> U256 {
let mut current = x;
let mut product = U256::one();
for j in 0..256 {
if e.bit(j) {
product = U256::try_from(product.full_mul(current) % n).unwrap();
}
current = U256::try_from(current.full_mul(current) % n).unwrap();
}
product
}

View File

@ -4,7 +4,7 @@ mod bn {
use ethereum_types::U256;
use crate::cpu::kernel::aggregator::combined_kernel;
use crate::cpu::kernel::interpreter::run;
use crate::cpu::kernel::interpreter::run_with_kernel;
use crate::cpu::kernel::tests::u256ify;
#[test]
@ -43,76 +43,76 @@ 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_with_kernel(&kernel, ec_add, initial_stack)?.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_with_kernel(&kernel, ec_add, initial_stack)?.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_with_kernel(&kernel, ec_add, initial_stack)?.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_with_kernel(&kernel, ec_double, initial_stack)?.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_with_kernel(&kernel, ec_mul, initial_stack)?.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_with_kernel(&kernel, ec_add, initial_stack)?.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_with_kernel(&kernel, ec_add, initial_stack)?.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_with_kernel(&kernel, ec_add, initial_stack)?.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_with_kernel(&kernel, ec_add, initial_stack)?.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_with_kernel(&kernel, ec_add, initial_stack)?.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_with_kernel(&kernel, ec_add, initial_stack)?.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_with_kernel(&kernel, ec_add, initial_stack)?.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_with_kernel(&kernel, ec_mul, initial_stack)?.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_with_kernel(&kernel, ec_mul, initial_stack)?.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_with_kernel(&kernel, ec_mul, initial_stack)?.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_with_kernel(&kernel, ec_mul, initial_stack)?.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_with_kernel(&kernel, ec_mul, initial_stack)?.stack;
assert_eq!(stack, vec![U256::MAX, U256::MAX]);
// Multiple calls
@ -126,7 +126,7 @@ mod bn {
point0.1,
point0.0,
])?;
let stack = run(&kernel.code, ec_add, initial_stack)?.stack;
let stack = run_with_kernel(&kernel, ec_add, initial_stack)?.stack;
assert_eq!(stack, u256ify([point4.1, point4.0])?);
Ok(())
@ -138,7 +138,7 @@ mod secp {
use anyhow::Result;
use crate::cpu::kernel::aggregator::combined_kernel;
use crate::cpu::kernel::interpreter::run;
use crate::cpu::kernel::interpreter::{run, run_with_kernel};
use crate::cpu::kernel::tests::u256ify;
#[test]
@ -176,55 +176,55 @@ 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_with_kernel(&kernel, ec_add, initial_stack)?.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_with_kernel(&kernel, ec_add, initial_stack)?.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_with_kernel(&kernel, ec_double, initial_stack)?.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_with_kernel(&kernel, ec_mul, initial_stack)?.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_with_kernel(&kernel, ec_add, initial_stack)?.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_with_kernel(&kernel, ec_add, initial_stack)?.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_with_kernel(&kernel, ec_add, initial_stack)?.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_with_kernel(&kernel, ec_mul, initial_stack)?.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_with_kernel(&kernel, ec_mul, initial_stack)?.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_with_kernel(&kernel, ec_mul, initial_stack)?.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_with_kernel(&kernel, ec_mul, initial_stack)?.stack;
assert_eq!(stack, u256ify([identity.1, identity.0])?);
// Multiple calls
@ -238,7 +238,7 @@ mod secp {
point0.1,
point0.0,
])?;
let stack = run(&kernel.code, ec_add, initial_stack)?.stack;
let stack = run_with_kernel(&kernel, ec_add, initial_stack)?.stack;
assert_eq!(stack, u256ify([point4.1, point4.0])?);
Ok(())

View File

@ -5,7 +5,7 @@ use ethereum_types::U256;
use crate::cpu::kernel::aggregator::combined_kernel;
use crate::cpu::kernel::assembler::Kernel;
use crate::cpu::kernel::interpreter::run;
use crate::cpu::kernel::interpreter::run_with_kernel;
use crate::cpu::kernel::tests::u256ify;
fn test_valid_ecrecover(
@ -18,7 +18,7 @@ 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_with_kernel(kernel, ecrecover, initial_stack)?.stack;
assert_eq!(stack[0], U256::from_str(expected).unwrap());
Ok(())
@ -27,7 +27,7 @@ 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_with_kernel(kernel, ecrecover, initial_stack)?.stack;
assert_eq!(stack, vec![U256::MAX]);
Ok(())

View File

@ -5,7 +5,7 @@ use ethereum_types::U256;
use rand::{thread_rng, Rng};
use crate::cpu::kernel::aggregator::combined_kernel;
use crate::cpu::kernel::interpreter::run;
use crate::cpu::kernel::interpreter::{run, run_with_kernel};
#[test]
fn test_exp() -> Result<()> {
@ -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_with_kernel(&kernel, exp, initial_stack)?.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_with_kernel(&kernel, exp, initial_stack)?.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_with_kernel(&kernel, exp, initial_stack)?.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(())