mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-07 00:03:10 +00:00
merge
This commit is contained in:
commit
cd5c92b574
@ -1,18 +1,20 @@
|
||||
[package]
|
||||
name = "plonky2_ecdsa"
|
||||
description = "ECDSA gadget for Plonky2"
|
||||
version = "0.1.0"
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
parallel = ["maybe_rayon/parallel", "plonky2/parallel"]
|
||||
parallel = ["plonky2_maybe_rayon/parallel", "plonky2/parallel"]
|
||||
|
||||
[dependencies]
|
||||
anyhow = { version = "1.0.40", default-features = false }
|
||||
itertools = { version = "0.10.0", default-features = false }
|
||||
maybe_rayon = { path = "../maybe_rayon", default-features = false }
|
||||
plonky2_maybe_rayon = { version = "0.1.0", default-features = false }
|
||||
num = { version = "0.4.0", default-features = false }
|
||||
plonky2 = { path = "../plonky2", default-features = false }
|
||||
plonky2_u32 = { path = "../u32", default-features = false }
|
||||
plonky2 = { version = "0.1.1", default-features = false }
|
||||
plonky2_u32 = { version = "0.1.0", default-features = false }
|
||||
serde = { version = "1.0", default-features = false, features = ["derive"] }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use itertools::Itertools;
|
||||
use maybe_rayon::*;
|
||||
use plonky2::field::types::{Field, PrimeField};
|
||||
use plonky2_maybe_rayon::*;
|
||||
|
||||
use crate::curve::curve_summation::affine_multisummation_best;
|
||||
use crate::curve::curve_types::{AffinePoint, Curve, ProjectivePoint};
|
||||
|
||||
@ -2,6 +2,11 @@
|
||||
name = "plonky2_evm"
|
||||
description = "Implementation of STARKs for the Ethereum Virtual Machine"
|
||||
version = "0.1.0"
|
||||
authors = ["Daniel Lubarov <daniel@lubarov.com>", "William Borgeaud <williamborgeaud@gmail.com>"]
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/mir-protocol/plonky2"
|
||||
keywords = ["EVM", "STARK", "Ethereum"]
|
||||
categories = ["cryptography"]
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
@ -15,13 +20,13 @@ hex-literal = "0.3.4"
|
||||
itertools = "0.10.3"
|
||||
keccak-hash = "0.10.0"
|
||||
log = "0.4.14"
|
||||
maybe_rayon = { path = "../maybe_rayon" }
|
||||
plonky2_maybe_rayon = "0.1.0"
|
||||
num = "0.4.0"
|
||||
once_cell = "1.13.0"
|
||||
pest = "2.1.3"
|
||||
pest_derive = "2.1.0"
|
||||
plonky2 = { path = "../plonky2", default-features = false, features = ["timing"] }
|
||||
plonky2_util = { path = "../util" }
|
||||
plonky2 = { version = "0.1.1", default-features = false, features = ["timing"] }
|
||||
plonky2_util = { version = "0.1.0" }
|
||||
rand = "0.8.5"
|
||||
rand_chacha = "0.3.1"
|
||||
rlp = "0.5.1"
|
||||
@ -42,7 +47,7 @@ sha2 = "0.10.6"
|
||||
[features]
|
||||
default = ["parallel"]
|
||||
asmtools = ["hex"]
|
||||
parallel = ["plonky2/parallel", "maybe_rayon/parallel"]
|
||||
parallel = ["plonky2/parallel", "plonky2_maybe_rayon/parallel"]
|
||||
|
||||
[[bin]]
|
||||
name = "assemble"
|
||||
|
||||
@ -8,7 +8,6 @@ use plonky2::iop::ext_target::ExtensionTarget;
|
||||
use crate::arithmetic::columns::*;
|
||||
use crate::arithmetic::utils::read_value_u64_limbs;
|
||||
use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer};
|
||||
use crate::range_check_error;
|
||||
|
||||
pub(crate) fn u256_add_cc(input0: [u64; N_LIMBS], input1: [u64; N_LIMBS]) -> ([u64; N_LIMBS], u64) {
|
||||
// Input and output have 16-bit limbs
|
||||
@ -104,7 +103,7 @@ where
|
||||
cy
|
||||
}
|
||||
|
||||
pub fn generate<F: RichField>(lv: &mut [F; NUM_ARITH_COLUMNS]) {
|
||||
pub fn generate<F: RichField>(lv: &mut [F]) {
|
||||
let input0 = read_value_u64_limbs(lv, ADD_INPUT_0);
|
||||
let input1 = read_value_u64_limbs(lv, ADD_INPUT_1);
|
||||
|
||||
@ -117,10 +116,6 @@ pub fn eval_packed_generic<P: PackedField>(
|
||||
lv: &[P; NUM_ARITH_COLUMNS],
|
||||
yield_constr: &mut ConstraintConsumer<P>,
|
||||
) {
|
||||
range_check_error!(ADD_INPUT_0, 16);
|
||||
range_check_error!(ADD_INPUT_1, 16);
|
||||
range_check_error!(ADD_OUTPUT, 16);
|
||||
|
||||
let is_add = lv[IS_ADD];
|
||||
let input0_limbs = &lv[ADD_INPUT_0];
|
||||
let input1_limbs = &lv[ADD_INPUT_1];
|
||||
|
||||
@ -1,13 +1,17 @@
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Add;
|
||||
|
||||
use itertools::Itertools;
|
||||
use plonky2::field::extension::{Extendable, FieldExtension};
|
||||
use plonky2::field::packed::PackedField;
|
||||
use plonky2::field::polynomial::PolynomialValues;
|
||||
use plonky2::hash::hash_types::RichField;
|
||||
use plonky2::util::transpose;
|
||||
|
||||
use crate::arithmetic::operations::Operation;
|
||||
use crate::arithmetic::{add, columns, compare, modular, mul, sub};
|
||||
use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer};
|
||||
use crate::lookup::{eval_lookups, eval_lookups_circuit, permuted_cols};
|
||||
use crate::permutation::PermutationPair;
|
||||
use crate::stark::Stark;
|
||||
use crate::vars::{StarkEvaluationTargets, StarkEvaluationVars};
|
||||
|
||||
@ -16,53 +20,60 @@ pub struct ArithmeticStark<F, const D: usize> {
|
||||
pub f: PhantomData<F>,
|
||||
}
|
||||
|
||||
impl<F: RichField, const D: usize> ArithmeticStark<F, D> {
|
||||
pub fn generate(
|
||||
&self,
|
||||
local_values: &mut [F; columns::NUM_ARITH_COLUMNS],
|
||||
next_values: &mut [F; columns::NUM_ARITH_COLUMNS],
|
||||
) {
|
||||
// Check that at most one operation column is "one" and that the
|
||||
// rest are "zero".
|
||||
assert_eq!(
|
||||
columns::ALL_OPERATIONS
|
||||
.iter()
|
||||
.map(|&c| {
|
||||
if local_values[c] == F::ONE {
|
||||
Ok(1u64)
|
||||
} else if local_values[c] == F::ZERO {
|
||||
Ok(0u64)
|
||||
} else {
|
||||
Err("column was not 0 nor 1")
|
||||
}
|
||||
})
|
||||
.fold_ok(0u64, Add::add),
|
||||
Ok(1)
|
||||
);
|
||||
const RANGE_MAX: usize = 1usize << 16; // Range check strict upper bound
|
||||
|
||||
if local_values[columns::IS_ADD].is_one() {
|
||||
add::generate(local_values);
|
||||
} else if local_values[columns::IS_SUB].is_one() {
|
||||
sub::generate(local_values);
|
||||
} else if local_values[columns::IS_MUL].is_one() {
|
||||
mul::generate(local_values);
|
||||
} else if local_values[columns::IS_LT].is_one() {
|
||||
compare::generate(local_values, columns::IS_LT);
|
||||
} else if local_values[columns::IS_GT].is_one() {
|
||||
compare::generate(local_values, columns::IS_GT);
|
||||
} else if local_values[columns::IS_ADDMOD].is_one() {
|
||||
modular::generate(local_values, next_values, columns::IS_ADDMOD);
|
||||
} else if local_values[columns::IS_SUBMOD].is_one() {
|
||||
modular::generate(local_values, next_values, columns::IS_SUBMOD);
|
||||
} else if local_values[columns::IS_MULMOD].is_one() {
|
||||
modular::generate(local_values, next_values, columns::IS_MULMOD);
|
||||
} else if local_values[columns::IS_MOD].is_one() {
|
||||
modular::generate(local_values, next_values, columns::IS_MOD);
|
||||
} else if local_values[columns::IS_DIV].is_one() {
|
||||
modular::generate(local_values, next_values, columns::IS_DIV);
|
||||
} else {
|
||||
panic!("the requested operation should not be handled by the arithmetic table");
|
||||
impl<F: RichField, const D: usize> ArithmeticStark<F, D> {
|
||||
/// Expects input in *column*-major layout
|
||||
fn generate_range_checks(&self, cols: &mut Vec<Vec<F>>) {
|
||||
debug_assert!(cols.len() == columns::NUM_ARITH_COLUMNS);
|
||||
|
||||
let n_rows = cols[0].len();
|
||||
debug_assert!(cols.iter().all(|col| col.len() == n_rows));
|
||||
|
||||
for i in 0..RANGE_MAX {
|
||||
cols[columns::RANGE_COUNTER][i] = F::from_canonical_usize(i);
|
||||
}
|
||||
|
||||
// For each column c in cols, generate the range-check
|
||||
// permutations and put them in the corresponding range-check
|
||||
// columns rc_c and rc_c+1.
|
||||
for (c, rc_c) in columns::SHARED_COLS.zip(columns::RC_COLS.step_by(2)) {
|
||||
let (col_perm, table_perm) = permuted_cols(&cols[c], &cols[columns::RANGE_COUNTER]);
|
||||
cols[rc_c].copy_from_slice(&col_perm);
|
||||
cols[rc_c + 1].copy_from_slice(&table_perm);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate(&self, operations: Vec<&dyn Operation<F>>) -> Vec<PolynomialValues<F>> {
|
||||
// The number of rows reserved is the smallest value that's
|
||||
// guaranteed to avoid a reallocation: The only ops that use
|
||||
// two rows are the modular operations and DIV, so the only
|
||||
// way to reach capacity is when every op is modular or DIV
|
||||
// (which is obviously unlikely in normal
|
||||
// circumstances). (Also need at least RANGE_MAX rows to
|
||||
// accommodate range checks.)
|
||||
let max_rows = std::cmp::max(2 * operations.len(), RANGE_MAX);
|
||||
let mut trace_rows = Vec::with_capacity(max_rows);
|
||||
|
||||
for op in operations {
|
||||
let (row1, maybe_row2) = op.to_rows();
|
||||
trace_rows.push(row1);
|
||||
|
||||
if let Some(row2) = maybe_row2 {
|
||||
trace_rows.push(row2);
|
||||
}
|
||||
}
|
||||
|
||||
// Pad the trace with zero rows if it doesn't have enough rows
|
||||
// to accommodate the range check columns.
|
||||
for _ in trace_rows.len()..RANGE_MAX {
|
||||
trace_rows.push(vec![F::ZERO; columns::NUM_ARITH_COLUMNS]);
|
||||
}
|
||||
|
||||
let mut trace_cols = transpose(&trace_rows);
|
||||
self.generate_range_checks(&mut trace_cols);
|
||||
|
||||
trace_cols.into_iter().map(PolynomialValues::new).collect()
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,8 +88,14 @@ impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for ArithmeticSta
|
||||
FE: FieldExtension<D2, BaseField = F>,
|
||||
P: PackedField<Scalar = FE>,
|
||||
{
|
||||
// Range check all the columns
|
||||
for col in columns::RC_COLS.step_by(2) {
|
||||
eval_lookups(vars, yield_constr, col, col + 1);
|
||||
}
|
||||
|
||||
let lv = vars.local_values;
|
||||
let nv = vars.next_values;
|
||||
|
||||
add::eval_packed_generic(lv, yield_constr);
|
||||
sub::eval_packed_generic(lv, yield_constr);
|
||||
mul::eval_packed_generic(lv, yield_constr);
|
||||
@ -92,6 +109,11 @@ impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for ArithmeticSta
|
||||
vars: StarkEvaluationTargets<D, { Self::COLUMNS }>,
|
||||
yield_constr: &mut RecursiveConstraintConsumer<F, D>,
|
||||
) {
|
||||
// Range check all the columns
|
||||
for col in columns::RC_COLS.step_by(2) {
|
||||
eval_lookups_circuit(builder, vars, yield_constr, col, col + 1);
|
||||
}
|
||||
|
||||
let lv = vars.local_values;
|
||||
let nv = vars.next_values;
|
||||
add::eval_ext_circuit(builder, lv, yield_constr);
|
||||
@ -104,4 +126,198 @@ impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for ArithmeticSta
|
||||
fn constraint_degree(&self) -> usize {
|
||||
3
|
||||
}
|
||||
|
||||
fn permutation_pairs(&self) -> Vec<PermutationPair> {
|
||||
const START: usize = columns::START_SHARED_COLS;
|
||||
const END: usize = START + columns::NUM_SHARED_COLS;
|
||||
let mut pairs = Vec::with_capacity(2 * columns::NUM_SHARED_COLS);
|
||||
for (c, c_perm) in (START..END).zip_eq(columns::RC_COLS.step_by(2)) {
|
||||
pairs.push(PermutationPair::singletons(c, c_perm));
|
||||
pairs.push(PermutationPair::singletons(
|
||||
c_perm + 1,
|
||||
columns::RANGE_COUNTER,
|
||||
));
|
||||
}
|
||||
pairs
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use anyhow::Result;
|
||||
use ethereum_types::U256;
|
||||
use plonky2::field::types::{Field, PrimeField64};
|
||||
use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
||||
use rand::{Rng, SeedableRng};
|
||||
use rand_chacha::ChaCha8Rng;
|
||||
|
||||
use super::{columns, ArithmeticStark};
|
||||
use crate::arithmetic::operations::*;
|
||||
use crate::stark_testing::{test_stark_circuit_constraints, test_stark_low_degree};
|
||||
|
||||
#[test]
|
||||
fn degree() -> Result<()> {
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
type S = ArithmeticStark<F, D>;
|
||||
|
||||
let stark = S {
|
||||
f: Default::default(),
|
||||
};
|
||||
test_stark_low_degree(stark)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn circuit() -> Result<()> {
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
type S = ArithmeticStark<F, D>;
|
||||
|
||||
let stark = S {
|
||||
f: Default::default(),
|
||||
};
|
||||
test_stark_circuit_constraints::<F, C, S, D>(stark)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn basic_trace() {
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
type S = ArithmeticStark<F, D>;
|
||||
|
||||
let stark = S {
|
||||
f: Default::default(),
|
||||
};
|
||||
|
||||
// 123 + 456 == 579
|
||||
let add = SimpleBinaryOp::new(columns::IS_ADD, U256::from(123), U256::from(456));
|
||||
// (123 * 456) % 1007 == 703
|
||||
let mulmod = ModularBinaryOp::new(
|
||||
columns::IS_MULMOD,
|
||||
U256::from(123),
|
||||
U256::from(456),
|
||||
U256::from(1007),
|
||||
);
|
||||
// (123 - 456) % 1007 == 674
|
||||
let submod = ModularBinaryOp::new(
|
||||
columns::IS_SUBMOD,
|
||||
U256::from(123),
|
||||
U256::from(456),
|
||||
U256::from(1007),
|
||||
);
|
||||
// 123 * 456 == 56088
|
||||
let mul = SimpleBinaryOp::new(columns::IS_MUL, U256::from(123), U256::from(456));
|
||||
// 128 % 13 == 11
|
||||
let modop = ModOp {
|
||||
input: U256::from(128),
|
||||
modulus: U256::from(13),
|
||||
};
|
||||
// 128 / 13 == 9
|
||||
let div = DivOp {
|
||||
numerator: U256::from(128),
|
||||
denominator: U256::from(13),
|
||||
};
|
||||
let ops: Vec<&dyn Operation<F>> = vec![&add, &mulmod, &submod, &mul, &div, &modop];
|
||||
|
||||
let pols = stark.generate(ops);
|
||||
|
||||
// Trace should always have NUM_ARITH_COLUMNS columns and
|
||||
// min(RANGE_MAX, operations.len()) rows. In this case there
|
||||
// are only 6 rows, so we should have RANGE_MAX rows.
|
||||
assert!(
|
||||
pols.len() == columns::NUM_ARITH_COLUMNS
|
||||
&& pols.iter().all(|v| v.len() == super::RANGE_MAX)
|
||||
);
|
||||
|
||||
// Each operation has a single word answer that we can check
|
||||
let expected_output = [
|
||||
// Row (some ops take two rows), col, expected
|
||||
(0, columns::ADD_OUTPUT, 579),
|
||||
(1, columns::MODULAR_OUTPUT, 703),
|
||||
(3, columns::MODULAR_OUTPUT, 674),
|
||||
(5, columns::MUL_OUTPUT, 56088),
|
||||
(6, columns::MODULAR_OUTPUT, 11),
|
||||
(8, columns::DIV_OUTPUT, 9),
|
||||
];
|
||||
|
||||
for (row, col, expected) in expected_output {
|
||||
// First register should match expected value...
|
||||
let first = col.start;
|
||||
let out = pols[first].values[row].to_canonical_u64();
|
||||
assert_eq!(
|
||||
out, expected,
|
||||
"expected column {} on row {} to be {} but it was {}",
|
||||
first, row, expected, out,
|
||||
);
|
||||
// ...other registers should be zero
|
||||
let rest = col.start + 1..col.end;
|
||||
assert!(pols[rest].iter().all(|v| v.values[row] == F::ZERO));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn big_traces() {
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
type S = ArithmeticStark<F, D>;
|
||||
|
||||
let stark = S {
|
||||
f: Default::default(),
|
||||
};
|
||||
|
||||
let mut rng = ChaCha8Rng::seed_from_u64(0x6feb51b7ec230f25);
|
||||
|
||||
let ops = (0..super::RANGE_MAX)
|
||||
.map(|_| {
|
||||
SimpleBinaryOp::new(
|
||||
columns::IS_MUL,
|
||||
U256::from(rng.gen::<[u8; 32]>()),
|
||||
U256::from(rng.gen::<[u8; 32]>()),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// TODO: This is clearly not the right way to build this
|
||||
// vector; I can't work out how to do it using the map above
|
||||
// though, with or without Boxes.
|
||||
let ops = ops.iter().map(|o| o as &dyn Operation<F>).collect();
|
||||
let pols = stark.generate(ops);
|
||||
|
||||
// Trace should always have NUM_ARITH_COLUMNS columns and
|
||||
// min(RANGE_MAX, operations.len()) rows. In this case there
|
||||
// are RANGE_MAX operations with one row each, so RANGE_MAX.
|
||||
assert!(
|
||||
pols.len() == columns::NUM_ARITH_COLUMNS
|
||||
&& pols.iter().all(|v| v.len() == super::RANGE_MAX)
|
||||
);
|
||||
|
||||
let ops = (0..super::RANGE_MAX)
|
||||
.map(|_| {
|
||||
ModularBinaryOp::new(
|
||||
columns::IS_MULMOD,
|
||||
U256::from(rng.gen::<[u8; 32]>()),
|
||||
U256::from(rng.gen::<[u8; 32]>()),
|
||||
U256::from(rng.gen::<[u8; 32]>()),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// TODO: This is clearly not the right way to build this
|
||||
// vector; I can't work out how to do it using the map above
|
||||
// though, with or without Boxes.
|
||||
let ops = ops.iter().map(|o| o as &dyn Operation<F>).collect();
|
||||
let pols = stark.generate(ops);
|
||||
|
||||
// Trace should always have NUM_ARITH_COLUMNS columns and
|
||||
// min(RANGE_MAX, operations.len()) rows. In this case there
|
||||
// are RANGE_MAX operations with two rows each, so 2*RANGE_MAX.
|
||||
assert!(
|
||||
pols.len() == columns::NUM_ARITH_COLUMNS
|
||||
&& pols.iter().all(|v| v.len() == 2 * super::RANGE_MAX)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,41 +32,42 @@ pub const IS_SUBMOD: usize = IS_ADDMOD + 1;
|
||||
pub const IS_MULMOD: usize = IS_SUBMOD + 1;
|
||||
pub const IS_LT: usize = IS_MULMOD + 1;
|
||||
pub const IS_GT: usize = IS_LT + 1;
|
||||
pub const IS_SHL: usize = IS_GT + 1;
|
||||
pub const IS_SHR: usize = IS_SHL + 1;
|
||||
|
||||
const START_SHARED_COLS: usize = IS_SHR + 1;
|
||||
|
||||
pub(crate) const ALL_OPERATIONS: [usize; 12] = [
|
||||
IS_ADD, IS_MUL, IS_SUB, IS_DIV, IS_MOD, IS_ADDMOD, IS_SUBMOD, IS_MULMOD, IS_LT, IS_GT, IS_SHL,
|
||||
IS_SHR,
|
||||
];
|
||||
pub(crate) const START_SHARED_COLS: usize = IS_GT + 1;
|
||||
|
||||
/// Within the Arithmetic Unit, there are shared columns which can be
|
||||
/// used by any arithmetic circuit, depending on which one is active
|
||||
/// this cycle.
|
||||
///
|
||||
/// Modular arithmetic takes 9 * N_LIMBS columns which is split across
|
||||
/// two rows, the first with 5 * N_LIMBS columns and the second with
|
||||
/// 4 * N_LIMBS columns. (There are hence N_LIMBS "wasted columns" in
|
||||
/// Modular arithmetic takes 11 * N_LIMBS columns which is split across
|
||||
/// two rows, the first with 6 * N_LIMBS columns and the second with
|
||||
/// 5 * N_LIMBS columns. (There are hence N_LIMBS "wasted columns" in
|
||||
/// the second row.)
|
||||
const NUM_SHARED_COLS: usize = 5 * N_LIMBS;
|
||||
pub(crate) const NUM_SHARED_COLS: usize = 6 * N_LIMBS;
|
||||
pub(crate) const SHARED_COLS: Range<usize> = START_SHARED_COLS..START_SHARED_COLS + NUM_SHARED_COLS;
|
||||
|
||||
const GENERAL_INPUT_0: Range<usize> = START_SHARED_COLS..START_SHARED_COLS + N_LIMBS;
|
||||
const GENERAL_INPUT_1: Range<usize> = GENERAL_INPUT_0.end..GENERAL_INPUT_0.end + N_LIMBS;
|
||||
pub(crate) const GENERAL_INPUT_0: Range<usize> = START_SHARED_COLS..START_SHARED_COLS + N_LIMBS;
|
||||
pub(crate) const GENERAL_INPUT_1: Range<usize> = GENERAL_INPUT_0.end..GENERAL_INPUT_0.end + N_LIMBS;
|
||||
const GENERAL_INPUT_2: Range<usize> = GENERAL_INPUT_1.end..GENERAL_INPUT_1.end + N_LIMBS;
|
||||
const GENERAL_INPUT_3: Range<usize> = GENERAL_INPUT_2.end..GENERAL_INPUT_2.end + N_LIMBS;
|
||||
const AUX_INPUT_0_LO: Range<usize> = GENERAL_INPUT_3.end..GENERAL_INPUT_3.end + N_LIMBS;
|
||||
// NB: Only one of these two sets of columns will be used for a given operation
|
||||
const GENERAL_INPUT_4: Range<usize> = GENERAL_INPUT_3.end..GENERAL_INPUT_3.end + N_LIMBS;
|
||||
const GENERAL_INPUT_4_DBL: Range<usize> = GENERAL_INPUT_3.end..GENERAL_INPUT_3.end + 2 * N_LIMBS;
|
||||
|
||||
// The auxiliary input columns overlap the general input columns
|
||||
// because they correspond to the values in the second row for modular
|
||||
// operations.
|
||||
const AUX_INPUT_0_HI: Range<usize> = START_SHARED_COLS..START_SHARED_COLS + N_LIMBS;
|
||||
const AUX_INPUT_1: Range<usize> = AUX_INPUT_0_HI.end..AUX_INPUT_0_HI.end + 2 * N_LIMBS;
|
||||
const AUX_INPUT_0: Range<usize> = START_SHARED_COLS..START_SHARED_COLS + N_LIMBS;
|
||||
const AUX_INPUT_1: Range<usize> = AUX_INPUT_0.end..AUX_INPUT_0.end + 2 * N_LIMBS;
|
||||
// These auxiliary input columns are awkwardly split across two rows,
|
||||
// with the first half after the general input columns and the second
|
||||
// half after the auxiliary input columns.
|
||||
const AUX_INPUT_2: Range<usize> = AUX_INPUT_1.end..AUX_INPUT_1.end + N_LIMBS;
|
||||
const AUX_INPUT_2: Range<usize> = AUX_INPUT_1.end..AUX_INPUT_1.end + 2 * N_LIMBS - 1;
|
||||
|
||||
// Each element c of {MUL,MODULAR}_AUX_INPUT is -2^20 <= c <= 2^20;
|
||||
// this value is used as an offset so that everything is positive in
|
||||
// the range checks.
|
||||
pub(crate) const AUX_COEFF_ABS_MAX: i64 = 1 << 20;
|
||||
|
||||
// ADD takes 3 * N_LIMBS = 48 columns
|
||||
pub(crate) const ADD_INPUT_0: Range<usize> = GENERAL_INPUT_0;
|
||||
@ -78,11 +79,12 @@ pub(crate) const SUB_INPUT_0: Range<usize> = GENERAL_INPUT_0;
|
||||
pub(crate) const SUB_INPUT_1: Range<usize> = GENERAL_INPUT_1;
|
||||
pub(crate) const SUB_OUTPUT: Range<usize> = GENERAL_INPUT_2;
|
||||
|
||||
// MUL takes 4 * N_LIMBS = 64 columns
|
||||
// MUL takes 5 * N_LIMBS = 80 columns
|
||||
pub(crate) const MUL_INPUT_0: Range<usize> = GENERAL_INPUT_0;
|
||||
pub(crate) const MUL_INPUT_1: Range<usize> = GENERAL_INPUT_1;
|
||||
pub(crate) const MUL_OUTPUT: Range<usize> = GENERAL_INPUT_2;
|
||||
pub(crate) const MUL_AUX_INPUT: Range<usize> = GENERAL_INPUT_3;
|
||||
pub(crate) const MUL_AUX_INPUT_LO: Range<usize> = GENERAL_INPUT_3;
|
||||
pub(crate) const MUL_AUX_INPUT_HI: Range<usize> = GENERAL_INPUT_4;
|
||||
|
||||
// LT and GT take 4 * N_LIMBS = 64 columns
|
||||
pub(crate) const CMP_INPUT_0: Range<usize> = GENERAL_INPUT_0;
|
||||
@ -90,8 +92,8 @@ pub(crate) const CMP_INPUT_1: Range<usize> = GENERAL_INPUT_1;
|
||||
pub(crate) const CMP_OUTPUT: usize = GENERAL_INPUT_2.start;
|
||||
pub(crate) const CMP_AUX_INPUT: Range<usize> = GENERAL_INPUT_3;
|
||||
|
||||
// MULMOD takes 4 * N_LIMBS + 2 * 2*N_LIMBS + N_LIMBS = 144 columns
|
||||
// but split over two rows of 80 columns and 64 columns.
|
||||
// MULMOD takes 4 * N_LIMBS + 3 * 2*N_LIMBS + N_LIMBS = 176 columns
|
||||
// but split over two rows of 96 columns and 80 columns.
|
||||
//
|
||||
// ADDMOD, SUBMOD, MOD and DIV are currently implemented in terms of
|
||||
// the general modular code, so they also take 144 columns (also split
|
||||
@ -100,18 +102,28 @@ pub(crate) const MODULAR_INPUT_0: Range<usize> = GENERAL_INPUT_0;
|
||||
pub(crate) const MODULAR_INPUT_1: Range<usize> = GENERAL_INPUT_1;
|
||||
pub(crate) const MODULAR_MODULUS: Range<usize> = GENERAL_INPUT_2;
|
||||
pub(crate) const MODULAR_OUTPUT: Range<usize> = GENERAL_INPUT_3;
|
||||
pub(crate) const MODULAR_QUO_INPUT_LO: Range<usize> = AUX_INPUT_0_LO;
|
||||
pub(crate) const MODULAR_QUO_INPUT: Range<usize> = GENERAL_INPUT_4_DBL;
|
||||
pub(crate) const MODULAR_OUT_AUX_RED: Range<usize> = AUX_INPUT_0;
|
||||
// NB: Last value is not used in AUX, it is used in MOD_IS_ZERO
|
||||
pub(crate) const MODULAR_QUO_INPUT_HI: Range<usize> = AUX_INPUT_0_HI;
|
||||
pub(crate) const MODULAR_AUX_INPUT: Range<usize> = AUX_INPUT_1.start..AUX_INPUT_1.end - 1;
|
||||
pub(crate) const MODULAR_MOD_IS_ZERO: usize = AUX_INPUT_1.end - 1;
|
||||
pub(crate) const MODULAR_OUT_AUX_RED: Range<usize> = AUX_INPUT_2;
|
||||
pub(crate) const MODULAR_MOD_IS_ZERO: usize = AUX_INPUT_1.start;
|
||||
pub(crate) const MODULAR_AUX_INPUT_LO: Range<usize> = AUX_INPUT_1.start + 1..AUX_INPUT_1.end;
|
||||
pub(crate) const MODULAR_AUX_INPUT_HI: Range<usize> = AUX_INPUT_2;
|
||||
// Must be set to MOD_IS_ZERO for DIV operation i.e. MOD_IS_ZERO * lv[IS_DIV]
|
||||
pub(crate) const MODULAR_DIV_DENOM_IS_ZERO: usize = AUX_INPUT_2.end;
|
||||
|
||||
#[allow(unused)] // TODO: Will be used when hooking into the CPU
|
||||
pub(crate) const DIV_NUMERATOR: Range<usize> = MODULAR_INPUT_0;
|
||||
#[allow(unused)] // TODO: Will be used when hooking into the CPU
|
||||
pub(crate) const DIV_DENOMINATOR: Range<usize> = MODULAR_MODULUS;
|
||||
#[allow(unused)] // TODO: Will be used when hooking into the CPU
|
||||
pub(crate) const DIV_OUTPUT: Range<usize> = MODULAR_QUO_INPUT_LO;
|
||||
pub(crate) const DIV_OUTPUT: Range<usize> =
|
||||
MODULAR_QUO_INPUT.start..MODULAR_QUO_INPUT.start + N_LIMBS;
|
||||
|
||||
pub const NUM_ARITH_COLUMNS: usize = START_SHARED_COLS + NUM_SHARED_COLS;
|
||||
// Need one column for the table, then two columns for every value
|
||||
// that needs to be range checked in the trace, namely the permutation
|
||||
// of the column and the permutation of the range. The two
|
||||
// permutations associated to column i will be in columns RC_COLS[2i]
|
||||
// and RC_COLS[2i+1].
|
||||
pub(crate) const NUM_RANGE_CHECK_COLS: usize = 1 + 2 * NUM_SHARED_COLS;
|
||||
pub(crate) const RANGE_COUNTER: usize = START_SHARED_COLS + NUM_SHARED_COLS;
|
||||
pub(crate) const RC_COLS: Range<usize> = RANGE_COUNTER + 1..RANGE_COUNTER + 1 + 2 * NUM_SHARED_COLS;
|
||||
|
||||
pub const NUM_ARITH_COLUMNS: usize = START_SHARED_COLS + NUM_SHARED_COLS + NUM_RANGE_CHECK_COLS;
|
||||
|
||||
@ -24,13 +24,12 @@ use crate::arithmetic::columns::*;
|
||||
use crate::arithmetic::sub::u256_sub_br;
|
||||
use crate::arithmetic::utils::read_value_u64_limbs;
|
||||
use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer};
|
||||
use crate::range_check_error;
|
||||
|
||||
pub(crate) fn generate<F: RichField>(lv: &mut [F; NUM_ARITH_COLUMNS], op: usize) {
|
||||
pub(crate) fn generate<F: RichField>(lv: &mut [F], filter: usize) {
|
||||
let input0 = read_value_u64_limbs(lv, CMP_INPUT_0);
|
||||
let input1 = read_value_u64_limbs(lv, CMP_INPUT_1);
|
||||
|
||||
let (diff, br) = match op {
|
||||
let (diff, br) = match filter {
|
||||
// input0 - input1 == diff + br*2^256
|
||||
IS_LT => u256_sub_br(input0, input1),
|
||||
// input1 - input0 == diff + br*2^256
|
||||
@ -84,10 +83,6 @@ pub fn eval_packed_generic<P: PackedField>(
|
||||
lv: &[P; NUM_ARITH_COLUMNS],
|
||||
yield_constr: &mut ConstraintConsumer<P>,
|
||||
) {
|
||||
range_check_error!(CMP_INPUT_0, 16);
|
||||
range_check_error!(CMP_INPUT_1, 16);
|
||||
range_check_error!(CMP_AUX_INPUT, 16);
|
||||
|
||||
let is_lt = lv[IS_LT];
|
||||
let is_gt = lv[IS_GT];
|
||||
|
||||
@ -147,7 +142,11 @@ pub(crate) fn eval_ext_circuit_lt<F: RichField + Extendable<D>, const D: usize>(
|
||||
);
|
||||
let good_output = builder.sub_extension(cy, output);
|
||||
let filter = builder.mul_extension(is_op, good_output);
|
||||
yield_constr.constraint_transition(builder, filter);
|
||||
if is_two_row_op {
|
||||
yield_constr.constraint_transition(builder, filter);
|
||||
} else {
|
||||
yield_constr.constraint(builder, filter);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eval_ext_circuit<F: RichField + Extendable<D>, const D: usize>(
|
||||
|
||||
@ -13,6 +13,8 @@ mod utils;
|
||||
pub mod arithmetic_stark;
|
||||
pub(crate) mod columns;
|
||||
|
||||
pub mod operations;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub(crate) enum BinaryOperator {
|
||||
Add,
|
||||
|
||||
@ -122,7 +122,6 @@ use crate::arithmetic::columns::*;
|
||||
use crate::arithmetic::compare::{eval_ext_circuit_lt, eval_packed_generic_lt};
|
||||
use crate::arithmetic::utils::*;
|
||||
use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer};
|
||||
use crate::range_check_error;
|
||||
|
||||
/// Convert the base-2^16 representation of a number into a BigInt.
|
||||
///
|
||||
@ -191,8 +190,8 @@ fn bigint_to_columns<const N: usize>(num: &BigInt) -> [i64; N] {
|
||||
/// NB: `operation` can set the higher order elements in its result to
|
||||
/// zero if they are not used.
|
||||
fn generate_modular_op<F: RichField>(
|
||||
lv: &mut [F; NUM_ARITH_COLUMNS],
|
||||
nv: &mut [F; NUM_ARITH_COLUMNS],
|
||||
lv: &mut [F],
|
||||
nv: &mut [F],
|
||||
filter: usize,
|
||||
operation: fn([i64; N_LIMBS], [i64; N_LIMBS]) -> [i64; 2 * N_LIMBS - 1],
|
||||
) {
|
||||
@ -263,37 +262,35 @@ fn generate_modular_op<F: RichField>(
|
||||
// Higher order terms of the product must be zero for valid quot and modulus:
|
||||
debug_assert!(&prod[2 * N_LIMBS..].iter().all(|&x| x == 0i64));
|
||||
|
||||
lv[MODULAR_OUTPUT].copy_from_slice(&output_limbs.map(F::from_canonical_i64));
|
||||
lv[MODULAR_QUO_INPUT].copy_from_slice("_limbs.map(F::from_noncanonical_i64));
|
||||
// constr_poly must be zero when evaluated at x = β :=
|
||||
// 2^LIMB_BITS, hence it's divisible by (x - β). `aux_limbs` is
|
||||
// the result of removing that root.
|
||||
let aux_limbs = pol_remove_root_2exp::<LIMB_BITS, _, { 2 * N_LIMBS }>(constr_poly);
|
||||
let mut aux_limbs = pol_remove_root_2exp::<LIMB_BITS, _, { 2 * N_LIMBS }>(constr_poly);
|
||||
|
||||
lv[MODULAR_OUTPUT].copy_from_slice(&output_limbs.map(|c| F::from_canonical_i64(c)));
|
||||
|
||||
// Copy lo and hi halves of quot_limbs into their respective registers
|
||||
for (i, &lo) in MODULAR_QUO_INPUT_LO.zip("_limbs[..N_LIMBS]) {
|
||||
lv[i] = F::from_noncanonical_i64(lo);
|
||||
}
|
||||
for (i, &hi) in MODULAR_QUO_INPUT_HI.zip("_limbs[N_LIMBS..]) {
|
||||
nv[i] = F::from_noncanonical_i64(hi);
|
||||
for c in aux_limbs.iter_mut() {
|
||||
// we store the unsigned offset value c + 2^20.
|
||||
*c += AUX_COEFF_ABS_MAX;
|
||||
}
|
||||
debug_assert!(aux_limbs.iter().all(|&c| c.abs() <= 2 * AUX_COEFF_ABS_MAX));
|
||||
|
||||
for (i, &c) in MODULAR_AUX_INPUT.zip(&aux_limbs[..2 * N_LIMBS - 1]) {
|
||||
nv[i] = F::from_noncanonical_i64(c);
|
||||
for (i, &c) in MODULAR_AUX_INPUT_LO.zip(&aux_limbs[..2 * N_LIMBS - 1]) {
|
||||
nv[i] = F::from_canonical_u16(c as u16);
|
||||
}
|
||||
for (i, &c) in MODULAR_AUX_INPUT_HI.zip(&aux_limbs[..2 * N_LIMBS - 1]) {
|
||||
nv[i] = F::from_canonical_u16((c >> 16) as u16);
|
||||
}
|
||||
|
||||
nv[MODULAR_MOD_IS_ZERO] = mod_is_zero;
|
||||
nv[MODULAR_OUT_AUX_RED].copy_from_slice(&out_aux_red.map(|c| F::from_canonical_i64(c)));
|
||||
nv[MODULAR_OUT_AUX_RED].copy_from_slice(&out_aux_red.map(F::from_canonical_i64));
|
||||
nv[MODULAR_DIV_DENOM_IS_ZERO] = mod_is_zero * lv[IS_DIV];
|
||||
}
|
||||
|
||||
/// Generate the output and auxiliary values for modular operations.
|
||||
///
|
||||
/// `filter` must be one of `columns::IS_{ADDMOD,MULMOD,MOD}`.
|
||||
pub(crate) fn generate<F: RichField>(
|
||||
lv: &mut [F; NUM_ARITH_COLUMNS],
|
||||
nv: &mut [F; NUM_ARITH_COLUMNS],
|
||||
filter: usize,
|
||||
) {
|
||||
pub(crate) fn generate<F: RichField>(lv: &mut [F], nv: &mut [F], filter: usize) {
|
||||
debug_assert!(lv.len() == NUM_ARITH_COLUMNS && nv.len() == NUM_ARITH_COLUMNS);
|
||||
match filter {
|
||||
columns::IS_ADDMOD => generate_modular_op(lv, nv, filter, pol_add),
|
||||
columns::IS_SUBMOD => generate_modular_op(lv, nv, filter, pol_sub),
|
||||
@ -319,14 +316,6 @@ fn modular_constr_poly<P: PackedField>(
|
||||
yield_constr: &mut ConstraintConsumer<P>,
|
||||
filter: P,
|
||||
) -> [P; 2 * N_LIMBS] {
|
||||
range_check_error!(MODULAR_INPUT_0, 16);
|
||||
range_check_error!(MODULAR_INPUT_1, 16);
|
||||
range_check_error!(MODULAR_MODULUS, 16);
|
||||
range_check_error!(MODULAR_QUO_INPUT_LO, 16);
|
||||
range_check_error!(MODULAR_QUO_INPUT_HI, 16);
|
||||
range_check_error!(MODULAR_AUX_INPUT, 20, signed);
|
||||
range_check_error!(MODULAR_OUTPUT, 16);
|
||||
|
||||
let mut modulus = read_value::<N_LIMBS, _>(lv, MODULAR_MODULUS);
|
||||
let mod_is_zero = nv[MODULAR_MOD_IS_ZERO];
|
||||
|
||||
@ -344,10 +333,14 @@ fn modular_constr_poly<P: PackedField>(
|
||||
|
||||
let mut output = read_value::<N_LIMBS, _>(lv, MODULAR_OUTPUT);
|
||||
|
||||
// Is 1 iff the operation is DIV and the denominator is zero.
|
||||
let div_denom_is_zero = nv[MODULAR_DIV_DENOM_IS_ZERO];
|
||||
yield_constr.constraint_transition(filter * (mod_is_zero * lv[IS_DIV] - div_denom_is_zero));
|
||||
|
||||
// Needed to compensate for adding mod_is_zero to modulus above,
|
||||
// since the call eval_packed_generic_lt() below subtracts modulus
|
||||
// verify in the case of a DIV.
|
||||
output[0] += mod_is_zero * lv[IS_DIV];
|
||||
// to verify in the case of a DIV.
|
||||
output[0] += div_denom_is_zero;
|
||||
|
||||
// Verify that the output is reduced, i.e. output < modulus.
|
||||
let out_aux_red = &nv[MODULAR_OUT_AUX_RED];
|
||||
@ -371,13 +364,12 @@ fn modular_constr_poly<P: PackedField>(
|
||||
true,
|
||||
);
|
||||
// restore output[0]
|
||||
output[0] -= mod_is_zero * lv[IS_DIV];
|
||||
output[0] -= div_denom_is_zero;
|
||||
|
||||
// prod = q(x) * m(x)
|
||||
let quot = {
|
||||
let mut quot = [P::default(); 2 * N_LIMBS];
|
||||
quot[..N_LIMBS].copy_from_slice(&lv[MODULAR_QUO_INPUT_LO]);
|
||||
quot[N_LIMBS..].copy_from_slice(&nv[MODULAR_QUO_INPUT_HI]);
|
||||
quot.copy_from_slice(&lv[MODULAR_QUO_INPUT]);
|
||||
quot
|
||||
};
|
||||
|
||||
@ -391,13 +383,21 @@ fn modular_constr_poly<P: PackedField>(
|
||||
let mut constr_poly: [_; 2 * N_LIMBS] = prod[0..2 * N_LIMBS].try_into().unwrap();
|
||||
pol_add_assign(&mut constr_poly, &output);
|
||||
|
||||
let base = P::Scalar::from_canonical_u64(1 << LIMB_BITS);
|
||||
let offset = P::Scalar::from_canonical_u64(AUX_COEFF_ABS_MAX as u64);
|
||||
|
||||
// constr_poly = c(x) + q(x) * m(x) + (x - β) * s(x)
|
||||
let mut aux = [P::ZEROS; 2 * N_LIMBS];
|
||||
for (i, j) in MODULAR_AUX_INPUT.enumerate() {
|
||||
aux[i] = nv[j];
|
||||
for (c, i) in aux.iter_mut().zip(MODULAR_AUX_INPUT_LO) {
|
||||
// MODULAR_AUX_INPUT elements were offset by 2^20 in
|
||||
// generation, so we undo that here.
|
||||
*c = nv[i] - offset;
|
||||
}
|
||||
// add high 16-bits of aux input
|
||||
for (c, j) in aux.iter_mut().zip(MODULAR_AUX_INPUT_HI) {
|
||||
*c += base * nv[j];
|
||||
}
|
||||
|
||||
let base = P::Scalar::from_canonical_u64(1 << LIMB_BITS);
|
||||
pol_add_assign(&mut constr_poly, &pol_adjoin_root(aux, base));
|
||||
|
||||
constr_poly
|
||||
@ -412,9 +412,9 @@ pub(crate) fn eval_packed_generic<P: PackedField>(
|
||||
// NB: The CTL code guarantees that filter is 0 or 1, i.e. that
|
||||
// only one of the operations below is "live".
|
||||
let filter = lv[columns::IS_ADDMOD]
|
||||
+ lv[columns::IS_SUBMOD]
|
||||
+ lv[columns::IS_MULMOD]
|
||||
+ lv[columns::IS_MOD]
|
||||
+ lv[columns::IS_SUBMOD]
|
||||
+ lv[columns::IS_DIV];
|
||||
|
||||
// Ensure that this operation is not the last row of the table;
|
||||
@ -480,7 +480,12 @@ fn modular_constr_poly_ext_circuit<F: RichField + Extendable<D>, const D: usize>
|
||||
modulus[0] = builder.add_extension(modulus[0], mod_is_zero);
|
||||
|
||||
let mut output = read_value::<N_LIMBS, _>(lv, MODULAR_OUTPUT);
|
||||
output[0] = builder.mul_add_extension(mod_is_zero, lv[IS_DIV], output[0]);
|
||||
|
||||
let div_denom_is_zero = nv[MODULAR_DIV_DENOM_IS_ZERO];
|
||||
let t = builder.mul_sub_extension(mod_is_zero, lv[IS_DIV], div_denom_is_zero);
|
||||
let t = builder.mul_extension(filter, t);
|
||||
yield_constr.constraint_transition(builder, t);
|
||||
output[0] = builder.add_extension(output[0], div_denom_is_zero);
|
||||
|
||||
let out_aux_red = &nv[MODULAR_OUT_AUX_RED];
|
||||
let one = builder.one_extension();
|
||||
@ -497,13 +502,11 @@ fn modular_constr_poly_ext_circuit<F: RichField + Extendable<D>, const D: usize>
|
||||
is_less_than,
|
||||
true,
|
||||
);
|
||||
output[0] =
|
||||
builder.arithmetic_extension(F::NEG_ONE, F::ONE, mod_is_zero, lv[IS_DIV], output[0]);
|
||||
output[0] = builder.sub_extension(output[0], div_denom_is_zero);
|
||||
let quot = {
|
||||
let zero = builder.zero_extension();
|
||||
let mut quot = [zero; 2 * N_LIMBS];
|
||||
quot[..N_LIMBS].copy_from_slice(&lv[MODULAR_QUO_INPUT_LO]);
|
||||
quot[N_LIMBS..].copy_from_slice(&nv[MODULAR_QUO_INPUT_HI]);
|
||||
quot.copy_from_slice(&lv[MODULAR_QUO_INPUT]);
|
||||
quot
|
||||
};
|
||||
|
||||
@ -516,13 +519,19 @@ fn modular_constr_poly_ext_circuit<F: RichField + Extendable<D>, const D: usize>
|
||||
let mut constr_poly: [_; 2 * N_LIMBS] = prod[0..2 * N_LIMBS].try_into().unwrap();
|
||||
pol_add_assign_ext_circuit(builder, &mut constr_poly, &output);
|
||||
|
||||
let offset =
|
||||
builder.constant_extension(F::Extension::from_canonical_u64(AUX_COEFF_ABS_MAX as u64));
|
||||
let zero = builder.zero_extension();
|
||||
let mut aux = [zero; 2 * N_LIMBS];
|
||||
for (i, j) in MODULAR_AUX_INPUT.enumerate() {
|
||||
aux[i] = nv[j];
|
||||
for (c, i) in aux.iter_mut().zip(MODULAR_AUX_INPUT_LO) {
|
||||
*c = builder.sub_extension(nv[i], offset);
|
||||
}
|
||||
let base = F::from_canonical_u64(1u64 << LIMB_BITS);
|
||||
for (c, j) in aux.iter_mut().zip(MODULAR_AUX_INPUT_HI) {
|
||||
*c = builder.mul_const_add_extension(base, nv[j], *c);
|
||||
}
|
||||
|
||||
let base = builder.constant_extension(F::Extension::from_canonical_u64(1u64 << LIMB_BITS));
|
||||
let base = builder.constant_extension(base.into());
|
||||
let t = pol_adjoin_root_ext_circuit(builder, aux, base);
|
||||
pol_add_assign_ext_circuit(builder, &mut constr_poly, &t);
|
||||
|
||||
|
||||
@ -64,9 +64,8 @@ use plonky2::iop::ext_target::ExtensionTarget;
|
||||
use crate::arithmetic::columns::*;
|
||||
use crate::arithmetic::utils::*;
|
||||
use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer};
|
||||
use crate::range_check_error;
|
||||
|
||||
pub fn generate<F: RichField>(lv: &mut [F; NUM_ARITH_COLUMNS]) {
|
||||
pub fn generate<F: RichField>(lv: &mut [F]) {
|
||||
let input0 = read_value_i64_limbs(lv, MUL_INPUT_0);
|
||||
let input1 = read_value_i64_limbs(lv, MUL_INPUT_1);
|
||||
|
||||
@ -96,23 +95,40 @@ pub fn generate<F: RichField>(lv: &mut [F; NUM_ARITH_COLUMNS]) {
|
||||
let mut aux_limbs = pol_remove_root_2exp::<LIMB_BITS, _, N_LIMBS>(unreduced_prod);
|
||||
aux_limbs[N_LIMBS - 1] = -cy;
|
||||
|
||||
lv[MUL_AUX_INPUT].copy_from_slice(&aux_limbs.map(|c| F::from_noncanonical_i64(c)));
|
||||
for c in aux_limbs.iter_mut() {
|
||||
// we store the unsigned offset value c + 2^20
|
||||
*c += AUX_COEFF_ABS_MAX;
|
||||
}
|
||||
|
||||
debug_assert!(aux_limbs.iter().all(|&c| c.abs() <= 2 * AUX_COEFF_ABS_MAX));
|
||||
|
||||
lv[MUL_AUX_INPUT_LO].copy_from_slice(&aux_limbs.map(|c| F::from_canonical_u16(c as u16)));
|
||||
lv[MUL_AUX_INPUT_HI]
|
||||
.copy_from_slice(&aux_limbs.map(|c| F::from_canonical_u16((c >> 16) as u16)));
|
||||
}
|
||||
|
||||
pub fn eval_packed_generic<P: PackedField>(
|
||||
lv: &[P; NUM_ARITH_COLUMNS],
|
||||
yield_constr: &mut ConstraintConsumer<P>,
|
||||
) {
|
||||
range_check_error!(MUL_INPUT_0, 16);
|
||||
range_check_error!(MUL_INPUT_1, 16);
|
||||
range_check_error!(MUL_OUTPUT, 16);
|
||||
range_check_error!(MUL_AUX_INPUT, 20);
|
||||
let base = P::Scalar::from_canonical_u64(1 << LIMB_BITS);
|
||||
|
||||
let is_mul = lv[IS_MUL];
|
||||
let input0_limbs = read_value::<N_LIMBS, _>(lv, MUL_INPUT_0);
|
||||
let input1_limbs = read_value::<N_LIMBS, _>(lv, MUL_INPUT_1);
|
||||
let output_limbs = read_value::<N_LIMBS, _>(lv, MUL_OUTPUT);
|
||||
let aux_limbs = read_value::<N_LIMBS, _>(lv, MUL_AUX_INPUT);
|
||||
|
||||
let aux_limbs = {
|
||||
// MUL_AUX_INPUT was offset by 2^20 in generation, so we undo
|
||||
// that here
|
||||
let offset = P::Scalar::from_canonical_u64(AUX_COEFF_ABS_MAX as u64);
|
||||
let mut aux_limbs = read_value::<N_LIMBS, _>(lv, MUL_AUX_INPUT_LO);
|
||||
let aux_limbs_hi = &lv[MUL_AUX_INPUT_HI];
|
||||
for (lo, &hi) in aux_limbs.iter_mut().zip(aux_limbs_hi) {
|
||||
*lo += hi * base - offset;
|
||||
}
|
||||
aux_limbs
|
||||
};
|
||||
|
||||
// Constraint poly holds the coefficients of the polynomial that
|
||||
// must be identically zero for this multiplication to be
|
||||
@ -133,7 +149,6 @@ pub fn eval_packed_generic<P: PackedField>(
|
||||
pol_sub_assign(&mut constr_poly, &output_limbs);
|
||||
|
||||
// This subtracts (x - β) * s(x) from constr_poly.
|
||||
let base = P::Scalar::from_canonical_u64(1 << LIMB_BITS);
|
||||
pol_sub_assign(&mut constr_poly, &pol_adjoin_root(aux_limbs, base));
|
||||
|
||||
// At this point constr_poly holds the coefficients of the
|
||||
@ -154,7 +169,20 @@ pub fn eval_ext_circuit<F: RichField + Extendable<D>, const D: usize>(
|
||||
let input0_limbs = read_value::<N_LIMBS, _>(lv, MUL_INPUT_0);
|
||||
let input1_limbs = read_value::<N_LIMBS, _>(lv, MUL_INPUT_1);
|
||||
let output_limbs = read_value::<N_LIMBS, _>(lv, MUL_OUTPUT);
|
||||
let aux_limbs = read_value::<N_LIMBS, _>(lv, MUL_AUX_INPUT);
|
||||
|
||||
let aux_limbs = {
|
||||
let base = builder.constant_extension(F::Extension::from_canonical_u64(1 << LIMB_BITS));
|
||||
let offset =
|
||||
builder.constant_extension(F::Extension::from_canonical_u64(AUX_COEFF_ABS_MAX as u64));
|
||||
let mut aux_limbs = read_value::<N_LIMBS, _>(lv, MUL_AUX_INPUT_LO);
|
||||
let aux_limbs_hi = &lv[MUL_AUX_INPUT_HI];
|
||||
for (lo, &hi) in aux_limbs.iter_mut().zip(aux_limbs_hi) {
|
||||
//*lo = lo + hi * base - offset;
|
||||
let t = builder.mul_sub_extension(hi, base, offset);
|
||||
*lo = builder.add_extension(*lo, t);
|
||||
}
|
||||
aux_limbs
|
||||
};
|
||||
|
||||
let mut constr_poly = pol_mul_lo_ext_circuit(builder, input0_limbs, input1_limbs);
|
||||
pol_sub_assign_ext_circuit(builder, &mut constr_poly, &output_limbs);
|
||||
|
||||
170
evm/src/arithmetic/operations.rs
Normal file
170
evm/src/arithmetic/operations.rs
Normal file
@ -0,0 +1,170 @@
|
||||
use ethereum_types::U256;
|
||||
use plonky2::hash::hash_types::RichField;
|
||||
use static_assertions::const_assert;
|
||||
|
||||
use crate::arithmetic::columns::*;
|
||||
use crate::arithmetic::{add, compare, modular, mul, sub};
|
||||
|
||||
#[inline]
|
||||
fn u64_to_array<F: RichField>(out: &mut [F], x: u64) {
|
||||
const_assert!(LIMB_BITS == 16);
|
||||
debug_assert!(out.len() == 4);
|
||||
|
||||
out[0] = F::from_canonical_u16(x as u16);
|
||||
out[1] = F::from_canonical_u16((x >> 16) as u16);
|
||||
out[2] = F::from_canonical_u16((x >> 32) as u16);
|
||||
out[3] = F::from_canonical_u16((x >> 48) as u16);
|
||||
}
|
||||
|
||||
fn u256_to_array<F: RichField>(out: &mut [F], x: U256) {
|
||||
const_assert!(N_LIMBS == 16);
|
||||
debug_assert!(out.len() == N_LIMBS);
|
||||
|
||||
u64_to_array(&mut out[0..4], x.0[0]);
|
||||
u64_to_array(&mut out[4..8], x.0[1]);
|
||||
u64_to_array(&mut out[8..12], x.0[2]);
|
||||
u64_to_array(&mut out[12..16], x.0[3]);
|
||||
}
|
||||
|
||||
pub trait Operation<F: RichField> {
|
||||
/// Convert operation into one or two rows of the trace.
|
||||
///
|
||||
/// Morally these types should be [F; NUM_ARITH_COLUMNS], but we
|
||||
/// use vectors because that's what utils::transpose expects.
|
||||
fn to_rows(&self) -> (Vec<F>, Option<Vec<F>>);
|
||||
}
|
||||
|
||||
pub struct SimpleBinaryOp {
|
||||
/// The operation is identified using the associated filter from
|
||||
/// `columns::IS_ADD` etc., stored in `op_filter`.
|
||||
op_filter: usize,
|
||||
input0: U256,
|
||||
input1: U256,
|
||||
}
|
||||
|
||||
impl SimpleBinaryOp {
|
||||
pub fn new(op_filter: usize, input0: U256, input1: U256) -> Self {
|
||||
assert!(
|
||||
op_filter == IS_ADD
|
||||
|| op_filter == IS_SUB
|
||||
|| op_filter == IS_MUL
|
||||
|| op_filter == IS_LT
|
||||
|| op_filter == IS_GT
|
||||
);
|
||||
Self {
|
||||
op_filter,
|
||||
input0,
|
||||
input1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: RichField> Operation<F> for SimpleBinaryOp {
|
||||
fn to_rows(&self) -> (Vec<F>, Option<Vec<F>>) {
|
||||
let mut row = vec![F::ZERO; NUM_ARITH_COLUMNS];
|
||||
row[self.op_filter] = F::ONE;
|
||||
|
||||
// Each of these operations uses the same columns for input; the
|
||||
// asserts ensure no-one changes this.
|
||||
// TODO: This is ugly; should just remove the other
|
||||
// *_INPUT_[01] variables and remove this.
|
||||
debug_assert!([ADD_INPUT_0, SUB_INPUT_0, MUL_INPUT_0, CMP_INPUT_0,]
|
||||
.iter()
|
||||
.all(|x| *x == GENERAL_INPUT_0));
|
||||
debug_assert!([ADD_INPUT_1, SUB_INPUT_1, MUL_INPUT_1, CMP_INPUT_1,]
|
||||
.iter()
|
||||
.all(|x| *x == GENERAL_INPUT_1));
|
||||
|
||||
u256_to_array(&mut row[GENERAL_INPUT_0], self.input0);
|
||||
u256_to_array(&mut row[GENERAL_INPUT_1], self.input1);
|
||||
|
||||
// This is ugly, but it avoids the huge amount of boilerplate
|
||||
// required to dispatch directly to each add/sub/etc. operation.
|
||||
match self.op_filter {
|
||||
IS_ADD => add::generate(&mut row),
|
||||
IS_SUB => sub::generate(&mut row),
|
||||
IS_MUL => mul::generate(&mut row),
|
||||
IS_LT | IS_GT => compare::generate(&mut row, self.op_filter),
|
||||
_ => panic!("unrecognised operation"),
|
||||
}
|
||||
|
||||
(row, None)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ModularBinaryOp {
|
||||
op_filter: usize,
|
||||
input0: U256,
|
||||
input1: U256,
|
||||
modulus: U256,
|
||||
}
|
||||
|
||||
impl ModularBinaryOp {
|
||||
pub fn new(op_filter: usize, input0: U256, input1: U256, modulus: U256) -> Self {
|
||||
assert!(op_filter == IS_ADDMOD || op_filter == IS_SUBMOD || op_filter == IS_MULMOD);
|
||||
Self {
|
||||
op_filter,
|
||||
input0,
|
||||
input1,
|
||||
modulus,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn modular_to_rows_helper<F: RichField>(
|
||||
op_filter: usize,
|
||||
input0: U256,
|
||||
input1: U256,
|
||||
modulus: U256,
|
||||
) -> (Vec<F>, Option<Vec<F>>) {
|
||||
let mut row1 = vec![F::ZERO; NUM_ARITH_COLUMNS];
|
||||
let mut row2 = vec![F::ZERO; NUM_ARITH_COLUMNS];
|
||||
|
||||
row1[op_filter] = F::ONE;
|
||||
|
||||
u256_to_array(&mut row1[MODULAR_INPUT_0], input0);
|
||||
u256_to_array(&mut row1[MODULAR_INPUT_1], input1);
|
||||
u256_to_array(&mut row1[MODULAR_MODULUS], modulus);
|
||||
|
||||
modular::generate(&mut row1, &mut row2, op_filter);
|
||||
|
||||
(row1, Some(row2))
|
||||
}
|
||||
|
||||
impl<F: RichField> Operation<F> for ModularBinaryOp {
|
||||
fn to_rows(&self) -> (Vec<F>, Option<Vec<F>>) {
|
||||
modular_to_rows_helper(self.op_filter, self.input0, self.input1, self.modulus)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ModOp {
|
||||
pub input: U256,
|
||||
pub modulus: U256,
|
||||
}
|
||||
|
||||
impl<F: RichField> Operation<F> for ModOp {
|
||||
fn to_rows(&self) -> (Vec<F>, Option<Vec<F>>) {
|
||||
modular_to_rows_helper(IS_MOD, self.input, U256::zero(), self.modulus)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DivOp {
|
||||
pub numerator: U256,
|
||||
pub denominator: U256,
|
||||
}
|
||||
|
||||
impl<F: RichField> Operation<F> for DivOp {
|
||||
fn to_rows(&self) -> (Vec<F>, Option<Vec<F>>) {
|
||||
let mut row1 = vec![F::ZERO; NUM_ARITH_COLUMNS];
|
||||
let mut row2 = vec![F::ZERO; NUM_ARITH_COLUMNS];
|
||||
|
||||
row1[IS_DIV] = F::ONE;
|
||||
|
||||
u256_to_array(&mut row1[DIV_NUMERATOR], self.numerator);
|
||||
u256_to_array(&mut row1[DIV_DENOMINATOR], self.denominator);
|
||||
|
||||
modular::generate(&mut row1, &mut row2, IS_DIV);
|
||||
|
||||
(row1, Some(row2))
|
||||
}
|
||||
}
|
||||
@ -8,7 +8,6 @@ use crate::arithmetic::add::{eval_ext_circuit_are_equal, eval_packed_generic_are
|
||||
use crate::arithmetic::columns::*;
|
||||
use crate::arithmetic::utils::read_value_u64_limbs;
|
||||
use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer};
|
||||
use crate::range_check_error;
|
||||
|
||||
pub(crate) fn u256_sub_br(input0: [u64; N_LIMBS], input1: [u64; N_LIMBS]) -> ([u64; N_LIMBS], u64) {
|
||||
const LIMB_BOUNDARY: u64 = 1 << LIMB_BITS;
|
||||
@ -28,7 +27,7 @@ pub(crate) fn u256_sub_br(input0: [u64; N_LIMBS], input1: [u64; N_LIMBS]) -> ([u
|
||||
(output, br)
|
||||
}
|
||||
|
||||
pub fn generate<F: RichField>(lv: &mut [F; NUM_ARITH_COLUMNS]) {
|
||||
pub fn generate<F: RichField>(lv: &mut [F]) {
|
||||
let input0 = read_value_u64_limbs(lv, SUB_INPUT_0);
|
||||
let input1 = read_value_u64_limbs(lv, SUB_INPUT_1);
|
||||
|
||||
@ -41,10 +40,6 @@ pub fn eval_packed_generic<P: PackedField>(
|
||||
lv: &[P; NUM_ARITH_COLUMNS],
|
||||
yield_constr: &mut ConstraintConsumer<P>,
|
||||
) {
|
||||
range_check_error!(SUB_INPUT_0, 16);
|
||||
range_check_error!(SUB_INPUT_1, 16);
|
||||
range_check_error!(SUB_OUTPUT, 16);
|
||||
|
||||
let is_sub = lv[IS_SUB];
|
||||
let input0_limbs = &lv[SUB_INPUT_0];
|
||||
let input1_limbs = &lv[SUB_INPUT_1];
|
||||
|
||||
@ -5,58 +5,7 @@ use plonky2::hash::hash_types::RichField;
|
||||
use plonky2::iop::ext_target::ExtensionTarget;
|
||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||
|
||||
use crate::arithmetic::columns::{NUM_ARITH_COLUMNS, N_LIMBS};
|
||||
|
||||
/// Emit an error message regarding unchecked range assumptions.
|
||||
/// Assumes the values in `cols` are `[cols[0], cols[0] + 1, ...,
|
||||
/// cols[0] + cols.len() - 1]`.
|
||||
///
|
||||
/// TODO: Hamish to delete this when he has implemented and integrated
|
||||
/// range checks.
|
||||
pub(crate) fn _range_check_error<const RC_BITS: u32>(
|
||||
_file: &str,
|
||||
_line: u32,
|
||||
_cols: Range<usize>,
|
||||
_signedness: &str,
|
||||
) {
|
||||
// error!(
|
||||
// "{}:{}: arithmetic unit skipped {}-bit {} range-checks on columns {}--{}: not yet implemented",
|
||||
// line,
|
||||
// file,
|
||||
// RC_BITS,
|
||||
// signedness,
|
||||
// cols.start,
|
||||
// cols.end - 1,
|
||||
// );
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! range_check_error {
|
||||
($cols:ident, $rc_bits:expr) => {
|
||||
$crate::arithmetic::utils::_range_check_error::<$rc_bits>(
|
||||
file!(),
|
||||
line!(),
|
||||
$cols,
|
||||
"unsigned",
|
||||
);
|
||||
};
|
||||
($cols:ident, $rc_bits:expr, signed) => {
|
||||
$crate::arithmetic::utils::_range_check_error::<$rc_bits>(
|
||||
file!(),
|
||||
line!(),
|
||||
$cols,
|
||||
"signed",
|
||||
);
|
||||
};
|
||||
([$cols:ident], $rc_bits:expr) => {
|
||||
$crate::arithmetic::utils::_range_check_error::<$rc_bits>(
|
||||
file!(),
|
||||
line!(),
|
||||
&[$cols],
|
||||
"unsigned",
|
||||
);
|
||||
};
|
||||
}
|
||||
use crate::arithmetic::columns::N_LIMBS;
|
||||
|
||||
/// Return an array of `N` zeros of type T.
|
||||
pub(crate) fn pol_zero<T, const N: usize>() -> [T; N]
|
||||
@ -139,11 +88,11 @@ pub(crate) fn pol_sub_ext_circuit<F: RichField + Extendable<D>, const D: usize>(
|
||||
b: [ExtensionTarget<D>; N_LIMBS],
|
||||
) -> [ExtensionTarget<D>; 2 * N_LIMBS - 1] {
|
||||
let zero = builder.zero_extension();
|
||||
let mut sum = [zero; 2 * N_LIMBS - 1];
|
||||
let mut diff = [zero; 2 * N_LIMBS - 1];
|
||||
for i in 0..N_LIMBS {
|
||||
sum[i] = builder.sub_extension(a[i], b[i]);
|
||||
diff[i] = builder.sub_extension(a[i], b[i]);
|
||||
}
|
||||
sum
|
||||
diff
|
||||
}
|
||||
|
||||
/// a(x) -= b(x), but must have deg(a) >= deg(b).
|
||||
@ -186,19 +135,13 @@ where
|
||||
res
|
||||
}
|
||||
|
||||
pub(crate) fn pol_mul_wide_ext_circuit<
|
||||
F: RichField + Extendable<D>,
|
||||
const D: usize,
|
||||
const M: usize,
|
||||
const N: usize,
|
||||
const P: usize,
|
||||
>(
|
||||
pub(crate) fn pol_mul_wide_ext_circuit<F: RichField + Extendable<D>, const D: usize>(
|
||||
builder: &mut CircuitBuilder<F, D>,
|
||||
a: [ExtensionTarget<D>; M],
|
||||
b: [ExtensionTarget<D>; N],
|
||||
) -> [ExtensionTarget<D>; P] {
|
||||
a: [ExtensionTarget<D>; N_LIMBS],
|
||||
b: [ExtensionTarget<D>; N_LIMBS],
|
||||
) -> [ExtensionTarget<D>; 2 * N_LIMBS - 1] {
|
||||
let zero = builder.zero_extension();
|
||||
let mut res = [zero; P];
|
||||
let mut res = [zero; 2 * N_LIMBS - 1];
|
||||
for (i, &ai) in a.iter().enumerate() {
|
||||
for (j, &bj) in b.iter().enumerate() {
|
||||
res[i + j] = builder.mul_add_extension(ai, bj, res[i + j]);
|
||||
@ -322,8 +265,8 @@ pub(crate) fn pol_adjoin_root_ext_circuit<
|
||||
) -> [ExtensionTarget<D>; N] {
|
||||
let zero = builder.zero_extension();
|
||||
let mut res = [zero; N];
|
||||
// res[deg] = NEG_ONE * root * a[0] + ZERO * zero
|
||||
res[0] = builder.arithmetic_extension(F::NEG_ONE, F::ZERO, root, a[0], zero);
|
||||
// res[0] = NEG_ONE * root * a[0] + ZERO * zero
|
||||
res[0] = builder.mul_extension_with_const(F::NEG_ONE, root, a[0]);
|
||||
for deg in 1..N {
|
||||
// res[deg] = NEG_ONE * root * a[deg] + ONE * a[deg - 1]
|
||||
res[deg] = builder.arithmetic_extension(F::NEG_ONE, F::ONE, root, a[deg], a[deg - 1]);
|
||||
@ -368,10 +311,7 @@ where
|
||||
|
||||
/// Read the range `value_idxs` of values from `lv` into an array of
|
||||
/// length `N`. Panics if the length of the range is not `N`.
|
||||
pub(crate) fn read_value<const N: usize, T: Copy>(
|
||||
lv: &[T; NUM_ARITH_COLUMNS],
|
||||
value_idxs: Range<usize>,
|
||||
) -> [T; N] {
|
||||
pub(crate) fn read_value<const N: usize, T: Copy>(lv: &[T], value_idxs: Range<usize>) -> [T; N] {
|
||||
lv[value_idxs].try_into().unwrap()
|
||||
}
|
||||
|
||||
@ -379,7 +319,7 @@ pub(crate) fn read_value<const N: usize, T: Copy>(
|
||||
/// length `N`, interpreting the values as `u64`s. Panics if the
|
||||
/// length of the range is not `N`.
|
||||
pub(crate) fn read_value_u64_limbs<const N: usize, F: RichField>(
|
||||
lv: &[F; NUM_ARITH_COLUMNS],
|
||||
lv: &[F],
|
||||
value_idxs: Range<usize>,
|
||||
) -> [u64; N] {
|
||||
let limbs: [_; N] = lv[value_idxs].try_into().unwrap();
|
||||
@ -390,7 +330,7 @@ pub(crate) fn read_value_u64_limbs<const N: usize, F: RichField>(
|
||||
/// length `N`, interpreting the values as `i64`s. Panics if the
|
||||
/// length of the range is not `N`.
|
||||
pub(crate) fn read_value_i64_limbs<const N: usize, F: RichField>(
|
||||
lv: &[F; NUM_ARITH_COLUMNS],
|
||||
lv: &[F],
|
||||
value_idxs: Range<usize>,
|
||||
) -> [i64; N] {
|
||||
let limbs: [_; N] = lv[value_idxs].try_into().unwrap();
|
||||
|
||||
@ -36,12 +36,13 @@ pub(crate) fn combined_kernel() -> Kernel {
|
||||
include_str!("asm/curve/bn254/field_arithmetic/frobenius.asm"),
|
||||
include_str!("asm/curve/bn254/field_arithmetic/util.asm"),
|
||||
include_str!("asm/curve/common.asm"),
|
||||
include_str!("asm/curve/secp256k1/curve_mul.asm"),
|
||||
include_str!("asm/curve/secp256k1/curve_add.asm"),
|
||||
include_str!("asm/curve/secp256k1/ecrecover.asm"),
|
||||
include_str!("asm/curve/secp256k1/inverse_scalar.asm"),
|
||||
include_str!("asm/curve/secp256k1/lift_x.asm"),
|
||||
include_str!("asm/curve/secp256k1/moddiv.asm"),
|
||||
include_str!("asm/curve/secp256k1/glv.asm"),
|
||||
include_str!("asm/curve/secp256k1/precomputation.asm"),
|
||||
include_str!("asm/exp.asm"),
|
||||
include_str!("asm/halt.asm"),
|
||||
include_str!("asm/hash/blake2b/addresses.asm"),
|
||||
|
||||
@ -15,7 +15,7 @@ global ec_add_valid_points_secp:
|
||||
%jumpi(ec_add_first_zero)
|
||||
// stack: x0, y0, x1, y1, retdest
|
||||
|
||||
// Check if the first point is the identity.
|
||||
// Check if the second point is the identity.
|
||||
DUP4
|
||||
// stack: y1, x0, y0, x1, y1, retdest
|
||||
DUP4
|
||||
@ -33,9 +33,9 @@ global ec_add_valid_points_secp:
|
||||
EQ
|
||||
// stack: x0 == x1, x0, y0, x1, y1, retdest
|
||||
%jumpi(ec_add_equal_first_coord)
|
||||
// Standard affine addition formula.
|
||||
global ec_add_valid_points_no_edge_case_secp:
|
||||
// stack: x0, y0, x1, y1, retdest
|
||||
|
||||
// Otherwise, we can use the standard formula.
|
||||
// Compute lambda = (y0 - y1)/(x0 - x1)
|
||||
DUP4
|
||||
// stack: y1, x0, y0, x1, y1, retdest
|
||||
@ -174,66 +174,49 @@ ec_add_equal_first_coord:
|
||||
// Assumption: x0 == x1 and y0 == y1
|
||||
// Standard doubling formula.
|
||||
ec_add_equal_points:
|
||||
// stack: x0, y0, x1, y1, retdest
|
||||
|
||||
// Compute lambda = 3/2 * x0^2 / y0
|
||||
%secp_base
|
||||
// stack: N, x0, y0, x1, y1, retdest
|
||||
%secp_base
|
||||
// stack: N, N, x0, y0, x1, y1, retdest
|
||||
DUP3
|
||||
// stack: x0, N, N, x0, y0, x1, y1, retdest
|
||||
DUP1
|
||||
// stack: x0, x0, N, N, x0, y0, x1, y1, retdest
|
||||
%stack (x0, y0, x1, y1, retdest) -> (x0, x0, @SECP_BASE, @SECP_BASE, x0, y0, x1, y1, retdest)
|
||||
MULMOD
|
||||
// stack: x0^2, N, x0, y0, x1, y1, retdest with
|
||||
PUSH 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffff7ffffe19 // 3/2 in the base field
|
||||
// stack: 3/2, x0^2, N, x0, y0, x1, y1, retdest
|
||||
MULMOD
|
||||
// stack: 3/2 * x0^2, x0, y0, x1, y1, retdest
|
||||
DUP3
|
||||
// stack: y0, 3/2 * x0^2, x0, y0, x1, y1, retdest
|
||||
%moddiv_secp_base
|
||||
// stack: lambda, x0, y0, x1, y1, retdest
|
||||
%jump(ec_add_valid_points_with_lambda)
|
||||
|
||||
// Secp256k1 elliptic curve doubling.
|
||||
// Assumption: (x0,y0) is a valid point.
|
||||
// Assumption: (x,y) is a valid point.
|
||||
// Standard doubling formula.
|
||||
global ec_double_secp:
|
||||
// stack: x0, y0, retdest
|
||||
DUP2
|
||||
// stack: y0, x0, y0, retdest
|
||||
DUP2
|
||||
// stack: x0, y0, x0, y0, retdest
|
||||
%jump(ec_add_equal_points)
|
||||
// stack: x, y, retdest
|
||||
DUP2 DUP2 %ec_isidentity
|
||||
// stack: (x,y)==(0,0), x, y, retdest
|
||||
%jumpi(retself)
|
||||
|
||||
// Compute lambda = 3/2 * x0^2 / y0
|
||||
%stack (x, y, retdest) -> (x, x, @SECP_BASE, @SECP_BASE, x, y, retdest)
|
||||
MULMOD
|
||||
PUSH 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffff7ffffe19 // 3/2 in the base field
|
||||
MULMOD
|
||||
DUP3
|
||||
%moddiv_secp_base
|
||||
%stack (lambda, x, y, retdest) -> (lambda, x, y, x, y, retdest)
|
||||
%jump(ec_add_valid_points_with_lambda)
|
||||
|
||||
retself:
|
||||
%stack (x, y, retdest) -> (retdest, x, y)
|
||||
JUMP
|
||||
|
||||
// Push the order of the Secp256k1 scalar field.
|
||||
%macro secp_base
|
||||
PUSH 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
|
||||
PUSH @SECP_BASE
|
||||
%endmacro
|
||||
|
||||
// Modular subtraction. Subtraction x-y underflows iff x<x-y, so can be computed as N*(x<x-y) + x-y.
|
||||
// Modular subtraction.
|
||||
// TODO: Use SUBMOD when it's ready
|
||||
%macro submod_secp_base
|
||||
// stack: x, y
|
||||
SWAP1
|
||||
// stack: y, x
|
||||
DUP2
|
||||
// stack: x, y, x
|
||||
SUB
|
||||
// stack: x - y, x
|
||||
DUP1
|
||||
// stack: x - y, x - y, x
|
||||
SWAP2
|
||||
// stack: x, x - y, x - y
|
||||
LT
|
||||
// stack: x < x - y, x - y
|
||||
%secp_base
|
||||
// stack: N, x < x - y, x - y
|
||||
MUL
|
||||
// stack: N * (x < x - y), x - y
|
||||
ADD
|
||||
// (x-y) % N
|
||||
%stack (x, y) -> (@SECP_BASE, y, x, @SECP_BASE)
|
||||
SUB ADDMOD
|
||||
%endmacro
|
||||
|
||||
// Check if (x,y) is a valid curve point.
|
||||
|
||||
@ -1,71 +0,0 @@
|
||||
// Same algorithm as in `exp.asm`
|
||||
global ec_mul_valid_point_secp:
|
||||
// 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)
|
||||
// stack: x, y, s, retdest
|
||||
%jump(ret_zero_ec_mul)
|
||||
|
||||
step_case:
|
||||
// stack: x, y, s, retdest
|
||||
PUSH recursion_return
|
||||
// stack: recursion_return, x, y, s, retdest
|
||||
PUSH 2
|
||||
// stack: 2, recursion_return, x, y, s, retdest
|
||||
DUP5
|
||||
// stack: s, 2, recursion_return, x, y, s, retdest
|
||||
DIV
|
||||
// stack: s / 2, recursion_return, x, y, s, retdest
|
||||
PUSH step_case_contd
|
||||
// stack: step_case_contd, s / 2, recursion_return, x, y, s, retdest
|
||||
DUP5
|
||||
// stack: y, step_case_contd, s / 2, recursion_return, x, y, s, retdest
|
||||
DUP5
|
||||
// stack: x, y, step_case_contd, s / 2, recursion_return, x, y, s, retdest
|
||||
%jump(ec_double_secp)
|
||||
|
||||
// Assumption: 2(x,y) = (x',y')
|
||||
step_case_contd:
|
||||
// stack: x', y', s / 2, recursion_return, x, y, s, retdest
|
||||
%jump(ec_mul_valid_point_secp)
|
||||
|
||||
recursion_return:
|
||||
// stack: x', y', x, y, s, retdest
|
||||
SWAP4
|
||||
// stack: s, y', x, y, x', retdest
|
||||
PUSH 1
|
||||
// stack: 1, s, y', x, y, x', retdest
|
||||
AND
|
||||
// stack: s & 1, y', x, y, x', retdest
|
||||
SWAP1
|
||||
// stack: y', s & 1, x, y, x', retdest
|
||||
SWAP2
|
||||
// stack: x, s & 1, y', y, x', retdest
|
||||
SWAP3
|
||||
// stack: y, s & 1, y', x, x', retdest
|
||||
SWAP4
|
||||
// stack: x', s & 1, y', x, y, retdest
|
||||
SWAP1
|
||||
// stack: s & 1, x', y', x, y, retdest
|
||||
%jumpi(odd_scalar)
|
||||
// stack: x', y', x, y, retdest
|
||||
SWAP3
|
||||
// stack: y, y', x, x', retdest
|
||||
POP
|
||||
// stack: y', x, x', retdest
|
||||
SWAP1
|
||||
// stack: x, y', x', retdest
|
||||
POP
|
||||
// stack: y', x', retdest
|
||||
SWAP2
|
||||
// stack: retdest, x', y'
|
||||
JUMP
|
||||
|
||||
odd_scalar:
|
||||
// stack: x', y', x, y, retdest
|
||||
%jump(ec_add_valid_points_secp)
|
||||
@ -6,19 +6,7 @@ global ecrecover:
|
||||
%ecrecover_input_check
|
||||
// stack: isValid(v,r,s), hash, v, r, s, retdest
|
||||
|
||||
// Lift r to an elliptic curve point if possible.
|
||||
SWAP2
|
||||
// stack: v, hash, isValid(v,r,s), r, s, retdest
|
||||
DUP4
|
||||
// stack: r, v, hash, isValid(v,r,s), r, s, retdest
|
||||
|
||||
// Compute v-27 which gives the parity of the y-coordinate of the lifted point.
|
||||
SWAP1
|
||||
// stack: v, r, hash, isValid(v,r,s), r, s, retdest
|
||||
PUSH 27
|
||||
// stack: 27, v, r, hash, isValid(v,r,s), r, s, retdest
|
||||
SWAP1
|
||||
// stack: v, 27, r, hash, isValid(v,r,s), r, s, retdest
|
||||
%stack (valid, hash, v, r, s, retdest) -> (v, 27, r, hash, valid, r, s, retdest)
|
||||
SUB
|
||||
// stack: v - 27, r, hash, isValid(v,r,s), r, s, retdest
|
||||
SWAP1
|
||||
@ -62,70 +50,58 @@ ecrecover_valid_input:
|
||||
%mulmodn_secp_scalar
|
||||
// stack: u1, y, hash, x, r^(-1), retdest
|
||||
|
||||
|
||||
// Compute (X,Y) = u1 * (x,y)
|
||||
PUSH ecrecover_with_first_point
|
||||
// stack: ecrecover_with_first_point, u1, y, hash, x, r^(-1), retdest
|
||||
SWAP1
|
||||
// stack: u1, ecrecover_with_first_point, y, hash, x, r^(-1), retdest
|
||||
SWAP2
|
||||
// stack: y, ecrecover_with_first_point, u1, hash, x, r^(-1), retdest
|
||||
SWAP1
|
||||
// stack: ecrecover_with_first_point, y, u1, hash, x, r^(-1), retdest
|
||||
SWAP3
|
||||
// stack: hash, y, u1, ecrecover_with_first_point, x, r^(-1), retdest
|
||||
SWAP4
|
||||
// stack: x, y, u1, ecrecover_with_first_point, hash, r^(-1), retdest
|
||||
%jump(ec_mul_valid_point_secp)
|
||||
|
||||
// ecrecover precompile.
|
||||
// Assumption: (X,Y) = u1 * P. Result is (X,Y) + u2*GENERATOR
|
||||
ecrecover_with_first_point:
|
||||
// stack: X, Y, hash, r^(-1), retdest
|
||||
%secp_scalar
|
||||
// stack: p, X, Y, hash, r^(-1), retdest
|
||||
SWAP1
|
||||
// stack: X, p, Y, hash, r^(-1), retdest
|
||||
SWAP4
|
||||
// stack: r^(-1), p, Y, hash, X, retdest
|
||||
SWAP2
|
||||
// stack: Y, p, r^(-1), hash, X, retdest
|
||||
SWAP3
|
||||
// stack: hash, p, r^(-1), Y, X, retdest
|
||||
|
||||
// Compute u2 = -hash * r^(-1)
|
||||
MOD
|
||||
// stack: hash%p, r^(-1), Y, X, retdest
|
||||
%secp_scalar
|
||||
// stack: p, hash%p, r^(-1), Y, X, retdest
|
||||
SUB
|
||||
// stack: -hash, r^(-1), Y, X, retdest
|
||||
%mulmodn_secp_scalar
|
||||
// stack: u2, Y, X, retdest
|
||||
%stack (u1, y, hash, x, rinv, retdest) -> (hash, @SECP_SCALAR, @SECP_SCALAR, rinv, @SECP_SCALAR, u1, x, y, pubkey_to_addr, retdest)
|
||||
MOD SWAP1 SUB MULMOD
|
||||
// stack: u2, u1, x, y, pubkey_to_addr, retdest
|
||||
%jump(ecdsa_msm_with_glv)
|
||||
|
||||
// Compute u2 * GENERATOR and chain the call to `ec_mul` with a call to `ec_add` to compute PUBKEY = (X,Y) + u2 * GENERATOR,
|
||||
// and a call to `pubkey_to_addr` to get the final result `KECCAK256(PUBKEY)[-20:]`.
|
||||
PUSH pubkey_to_addr
|
||||
// stack: pubkey_to_addr, u2, Y, X, retdest
|
||||
SWAP3
|
||||
// stack: X, u2, Y, pubkey_to_addr, retdest
|
||||
PUSH ec_add_valid_points_secp
|
||||
// stack: ec_add_valid_points_secp, X, u2, Y, pubkey_to_addr, retdest
|
||||
SWAP1
|
||||
// stack: X, ec_add_valid_points_secp, u2, Y, pubkey_to_addr, retdest
|
||||
PUSH 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 // x-coordinate of generator
|
||||
// stack: Gx, X, ec_add_valid_points_secp, u2, Y, pubkey_to_addr, retdest
|
||||
SWAP1
|
||||
// stack: X, Gx, ec_add_valid_points_secp, u2, Y, pubkey_to_addr, retdest
|
||||
PUSH 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 // y-coordinate of generator
|
||||
// stack: Gy, X, Gx, ec_add_valid_points_secp, u2, Y, pubkey_to_addr, retdest
|
||||
SWAP1
|
||||
// stack: X, Gy, Gx, ec_add_valid_points_secp, u2, Y, pubkey_to_addr, retdest
|
||||
SWAP4
|
||||
// stack: u2, Gy, Gx, ec_add_valid_points_secp, X, Y, pubkey_to_addr, retdest
|
||||
SWAP2
|
||||
// stack: Gx, Gy, u2, ec_add_valid_points_secp, X, Y, pubkey_to_addr, retdest
|
||||
%jump(ec_mul_valid_point_secp)
|
||||
// Computes `a * G + b * Q` using GLV+precomputation, where `G` is the Secp256k1 generator and `Q` is a point on the curve.
|
||||
// Pseudo-code:
|
||||
// precompute_table(G) -- precomputation table for the combinations of `G, phi(G), Q, phi(Q)`.
|
||||
// let a0, a1 = glv_decompose(a)
|
||||
// let b0, b1 = glv_decompose(b)
|
||||
// return msm_with_precomputation([a0, a1, b0, b1], [G, phi(G), Q, phi(Q)]) -- phi is the Secp endomorphism.
|
||||
ecdsa_msm_with_glv:
|
||||
%stack (a, b, Qx, Qy, retdest) -> (a, ecdsa_after_glv_a, b, Qx, Qy, retdest)
|
||||
%jump(glv_decompose)
|
||||
ecdsa_after_glv_a:
|
||||
%stack (a1neg, a0, a1, b, Qx, Qy, retdest) -> (b, ecdsa_after_glv_b, a1neg, a0, a1, Qx, Qy, retdest)
|
||||
%jump(glv_decompose)
|
||||
ecdsa_after_glv_b:
|
||||
%stack (b1neg, b0, b1, a1neg, a0, a1, Qx, Qy, retdest) -> (a1neg, b1neg, Qx, Qy, ecdsa_after_precompute, a0, a1, b0, b1, retdest)
|
||||
%jump(precompute_table)
|
||||
ecdsa_after_precompute:
|
||||
// stack: a0, a1, b0, b1, retdest
|
||||
PUSH 0 PUSH 0 PUSH 129 // 129 is the bit length of the GLV exponents
|
||||
// stack: i, accx, accy, a0, a1, b0, b1, retdest
|
||||
ecdsa_after_precompute_loop:
|
||||
%stack (i, accx, accy, a0, a1, b0, b1, retdest) -> (i, b1, i, accx, accy, a0, a1, b0, b1, retdest)
|
||||
SHR %and_const(1)
|
||||
%stack (bit_b1, i, accx, accy, a0, a1, b0, b1, retdest) -> (i, b0, bit_b1, i, accx, accy, a0, a1, b0, b1, retdest)
|
||||
SHR %and_const(1)
|
||||
%stack (bit_b0, bit_b1, i, accx, accy, a0, a1, b0, b1, retdest) -> (i, a1, bit_b0, bit_b1, i, accx, accy, a0, a1, b0, b1, retdest)
|
||||
SHR %and_const(1)
|
||||
%stack (bit_a1, bit_b0, bit_b1, i, accx, accy, a0, a1, b0, b1, retdest) -> (i, a0, bit_a1, bit_b0, bit_b1, i, accx, accy, a0, a1, b0, b1, retdest)
|
||||
SHR %and_const(1)
|
||||
%mul_const(2) ADD %mul_const(2) ADD %mul_const(2) ADD
|
||||
%stack (index, i, accx, accy, a0, a1, b0, b1, retdest) -> (index, index, i, accx, accy, a0, a1, b0, b1, retdest)
|
||||
%mul_const(2) %add_const(1)
|
||||
%mload_kernel(@SEGMENT_KERNEL_ECDSA_TABLE)
|
||||
SWAP1 %mul_const(2)
|
||||
%mload_kernel(@SEGMENT_KERNEL_ECDSA_TABLE)
|
||||
%stack (Px, Py, i, accx, accy, a0, a1, b0, b1, retdest) -> (Px, Py, accx, accy, ecdsa_after_precompute_loop_contd, i, a0, a1, b0, b1, retdest)
|
||||
%jump(ec_add_valid_points_secp)
|
||||
ecdsa_after_precompute_loop_contd:
|
||||
%stack (accx, accy, i, a0, a1, b0, b1, retdest) -> (i, accx, accy, ecdsa_after_precompute_loop_contd2, i, a0, a1, b0, b1, retdest)
|
||||
ISZERO %jumpi(ecdsa_after_precompute_loop_end)
|
||||
%jump(ec_double_secp)
|
||||
ecdsa_after_precompute_loop_contd2:
|
||||
%stack (accx, accy, i, a0, a1, b0, b1, retdest) -> (i, accx, accy, a0, a1, b0, b1, retdest)
|
||||
%decrement %jump(ecdsa_after_precompute_loop)
|
||||
ecdsa_after_precompute_loop_end:
|
||||
%stack (accx, accy, ecdsa_after_precompute_loop_contd2, i, a0, a1, b0, b1, retdest) -> (retdest, accx, accy)
|
||||
JUMP
|
||||
|
||||
// Take a public key (PKx, PKy) and return the associated address KECCAK256(PKx || PKy)[-20:].
|
||||
pubkey_to_addr:
|
||||
@ -207,13 +183,13 @@ pubkey_to_addr:
|
||||
%endmacro
|
||||
|
||||
%macro secp_scalar
|
||||
PUSH 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
|
||||
PUSH @SECP_SCALAR
|
||||
%endmacro
|
||||
|
||||
// Return u256::MAX which is used to indicate the input was invalid.
|
||||
%macro ecrecover_invalid_input
|
||||
// stack: retdest
|
||||
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
PUSH @U256_MAX
|
||||
// stack: u256::MAX, retdest
|
||||
SWAP1
|
||||
// stack: retdest, u256::MAX
|
||||
|
||||
104
evm/src/cpu/kernel/asm/curve/secp256k1/glv.asm
Normal file
104
evm/src/cpu/kernel/asm/curve/secp256k1/glv.asm
Normal file
@ -0,0 +1,104 @@
|
||||
// Inspired by https://github.com/AztecProtocol/weierstrudel/blob/master/huff_modules/endomorphism.huff
|
||||
// See also Sage code in evm/src/cpu/kernel/tests/ecc/glv_test_data
|
||||
// Given scalar `k ∈ Secp256k1::ScalarField`, return `u, k1, k2` with `k1,k2 < 2^129` and such that
|
||||
// `k = k1 - s*k2` if `u==0` otherwise `k = k1 + s*k2`, where `s` is the scalar value representing the endomorphism.
|
||||
// In the comments below, N means @SECP_SCALAR
|
||||
//
|
||||
// Z3 proof that the resulting `k1, k2` satisfy `k1>0`, `k1 < 2^129` and `|k2| < 2^129`.
|
||||
// ```python
|
||||
// from z3 import Solver, Int, Or, unsat
|
||||
// q = 115792089237316195423570985008687907852837564279074904382605163141518161494337
|
||||
// glv_s = 37718080363155996902926221483475020450927657555482586988616620542887997980018
|
||||
// g1 = 303414439467246543595250775667605759172
|
||||
// g2 = 64502973549206556628585045361533709077
|
||||
// b2 = 64502973549206556628585045361533709077
|
||||
// b1 = -303414439467246543595250775667605759171
|
||||
// k = Int("k")
|
||||
// c1 = Int("c1")
|
||||
// c2 = Int("c2")
|
||||
// s = Solver()
|
||||
//
|
||||
// c2p = -c2
|
||||
// s.add(k < q)
|
||||
// s.add(0 < k)
|
||||
// s.add(c1 * (2**256) <= g2 * k)
|
||||
// s.add((c1 + 1) * (2**256) > g2 * k)
|
||||
// s.add(c2p * (2**256) <= g1 * k)
|
||||
// s.add((c2p + 1) * (2**256) > g1 * k)
|
||||
//
|
||||
// q1 = c1 * b1
|
||||
// q2 = c2 * b2
|
||||
//
|
||||
// k2 = q2 - q1
|
||||
// k2L = (glv_s * k2) % q
|
||||
// k1 = k - k2L
|
||||
//
|
||||
// s.add(Or((k2 >= 2**129), (-k2 >= 2**129), (k1 >= 2**129), (k1 < 0)))
|
||||
// assert s.check() == unsat
|
||||
// ```
|
||||
global glv_decompose:
|
||||
// stack: k, retdest
|
||||
PUSH @SECP_SCALAR DUP1 DUP1
|
||||
// Compute c2 which is the top 256 bits of k*g1. Use asm from https://medium.com/wicketh/mathemagic-full-multiply-27650fec525d.
|
||||
PUSH @U256_MAX
|
||||
// stack: -1, N, N, N, k, retdest
|
||||
PUSH @SECP_GLV_MINUS_G1 DUP6
|
||||
// stack: k, g1, -1, N, N, N, k, retdest
|
||||
MULMOD
|
||||
// stack: (k * g1 % -1), N, N, N, k, retdest
|
||||
PUSH @SECP_GLV_MINUS_G1 DUP6
|
||||
// stack: k, g1, (k * g1 % -1), N, N, N, k, retdest
|
||||
MUL
|
||||
// stack: bottom = (k * g1), (k * g1 % -1), N, N, N, k, retdest
|
||||
DUP1 DUP3
|
||||
// stack: (k * g1 % -1), bottom, bottom, (k * g1 % -1), N, N, N, k, retdest
|
||||
LT SWAP2 SUB SUB
|
||||
// stack: c2, N, N, N, k, retdest
|
||||
PUSH @SECP_GLV_B2 MULMOD
|
||||
// stack: q2=c2*b2, N, N, k, retdest
|
||||
|
||||
// Use the same trick to compute c1 = top 256 bits of g2*k.
|
||||
PUSH @SECP_SCALAR PUSH @U256_MAX
|
||||
PUSH @SECP_GLV_G2 DUP7 MULMOD
|
||||
PUSH @SECP_GLV_G2 DUP7 MUL
|
||||
DUP1 DUP3 LT
|
||||
SWAP2 SUB SUB
|
||||
// stack: c1, N, q2, N, N, k, retdest
|
||||
PUSH @SECP_GLV_B1 MULMOD
|
||||
// stack: q1, q2, N, N, k, retdest
|
||||
|
||||
// We compute k2 = q1 + q2 - N, but we check for underflow and return N-q1-q2 instead if there is one,
|
||||
// along with a flag `underflow` set to 1 if there is an underflow, 0 otherwise.
|
||||
ADD %sub_check_underflow
|
||||
// stack: k2, underflow, N, k, retdest
|
||||
SWAP3 PUSH @SECP_SCALAR DUP5 PUSH @SECP_GLV_S
|
||||
// stack: s, k2, N, k, underflow, N, k2, retdest
|
||||
MULMOD
|
||||
// stack: s*k2, k, underflow, N, k2, retdest
|
||||
// Need to return `k + s*k2` if no underflow occur, otherwise return `k - s*k2` which is done in the `underflowed` fn.
|
||||
SWAP2 DUP1 %jumpi(underflowed)
|
||||
%stack (underflow, k, x, N, k2) -> (k, x, N, k2, underflow)
|
||||
ADDMOD
|
||||
%stack (k1, k2, underflow, retdest) -> (retdest, underflow, k1, k2)
|
||||
JUMP
|
||||
|
||||
underflowed:
|
||||
// stack: underflow, k, s*k2, N, k2
|
||||
// Compute (k-s*k2)%N. TODO: Use SUBMOD here when ready
|
||||
%stack (u, k, x, N, k2) -> (N, x, k, N, k2, u)
|
||||
SUB ADDMOD
|
||||
%stack (k1, k2, underflow, retdest) -> (retdest, underflow, k1, k2)
|
||||
JUMP
|
||||
|
||||
%macro sub_check_underflow
|
||||
// stack: x, y
|
||||
DUP2 DUP2 LT
|
||||
// stack: x<y, x, y
|
||||
DUP1 ISZERO DUP2 DUP4 DUP6 SUB MUL
|
||||
// stack: (y-x)*(x<y), x>=y, x<y, x, y
|
||||
%stack (a, b, c, x, y) -> (x, y, b, a, c)
|
||||
SUB MUL ADD
|
||||
%stack (res, bool) -> (res, @SECP_SCALAR, bool)
|
||||
MOD
|
||||
%endmacro
|
||||
|
||||
74
evm/src/cpu/kernel/asm/curve/secp256k1/precomputation.asm
Normal file
74
evm/src/cpu/kernel/asm/curve/secp256k1/precomputation.asm
Normal file
@ -0,0 +1,74 @@
|
||||
// Initial stack: Gneg, Qneg, Qx, Qy, retdest
|
||||
// Compute a*G ± b*phi(G) + c*Q ± d*phi(Q) for a,b,c,d in {0,1}^4 and store its x-coordinate at location `2*(8a+4b+2c+d)` and its y-coordinate at location `2*(8a+4b+2c+d)+1` in the SEGMENT_KERNEL_ECDSA_TABLE segment.
|
||||
global precompute_table:
|
||||
// First store G, ± phi(G), G ± phi(G)
|
||||
// Use Gneg for the ±, e.g., ±phi(G) is computed as `Gneg * (-phi(G)) + (1-Gneg)*phi(G)` (note only the y-coordinate needs to be filtered).
|
||||
// stack: Gneg, Qneg, Qx, Qy, retdest
|
||||
PUSH 32670510020758816978083085130507043184471273380659243275938904335757337482424 PUSH 17 PUSH 55066263022277343669578718895168534326250603453777594175500187360389116729240 PUSH 16
|
||||
%mstore_kernel(@SEGMENT_KERNEL_ECDSA_TABLE) %mstore_kernel(@SEGMENT_KERNEL_ECDSA_TABLE)
|
||||
|
||||
DUP1 DUP1 %mul_const(32670510020758816978083085130507043184471273380659243275938904335757337482424) SWAP1 PUSH 1 SUB %mul_const(83121579216557378445487899878180864668798711284981320763518679672151497189239) ADD
|
||||
PUSH 9 PUSH 85340279321737800624759429340272274763154997815782306132637707972559913914315 PUSH 8
|
||||
%mstore_kernel(@SEGMENT_KERNEL_ECDSA_TABLE) %mstore_kernel(@SEGMENT_KERNEL_ECDSA_TABLE)
|
||||
|
||||
DUP1 DUP1 %mul_const(83121579216557378445487899878180864668798711284981320763518679672151497189239) SWAP1 PUSH 1 SUB %mul_const(100652675408719987021357910538015346127426077519185866739835120963490438734674) ADD
|
||||
PUSH 25
|
||||
%mstore_kernel(@SEGMENT_KERNEL_ECDSA_TABLE)
|
||||
|
||||
DUP1 %mul_const(91177636130617246552803821781935006617134368061721227770777272682868638699771) SWAP1 PUSH 1 SUB %mul_const(66837770201594535779099350687042404727408598709762866365333192677982385899440) ADD
|
||||
PUSH 24
|
||||
%mstore_kernel(@SEGMENT_KERNEL_ECDSA_TABLE)
|
||||
|
||||
// Then store Q, ±phi(Q), Q ± phi(Q)
|
||||
%stack (Qneg, Qx, Qy, retdest) -> (4, Qx, 5, Qy, Qx, @SECP_BASE, Qneg, Qx, Qy, retdest)
|
||||
%mstore_kernel(@SEGMENT_KERNEL_ECDSA_TABLE) %mstore_kernel(@SEGMENT_KERNEL_ECDSA_TABLE)
|
||||
// stack: Qx, @SECP_BASE, Qx, Qy, retdest
|
||||
PUSH @SECP_GLV_BETA MULMOD
|
||||
%stack (betaQx, Qneg, Qx, Qy, retdest) -> (Qneg, Qy, Qneg, betaQx, Qx, Qy, retdest)
|
||||
MUL SWAP1 PUSH 1 SUB
|
||||
// stack: 1-Qneg, Qneg*Qy, betaQx, Qx, Qy, retdest
|
||||
DUP5 PUSH @SECP_BASE SUB MUL ADD
|
||||
%stack (selectQy, betaQx, Qx, Qy, retdest) -> (2, betaQx, 3, selectQy, betaQx, selectQy, Qx, Qy, precompute_table_contd, retdest)
|
||||
%mstore_kernel(@SEGMENT_KERNEL_ECDSA_TABLE) %mstore_kernel(@SEGMENT_KERNEL_ECDSA_TABLE)
|
||||
%jump(ec_add_valid_points_no_edge_case_secp)
|
||||
precompute_table_contd:
|
||||
%stack (x, y, retdest) -> (6, x, 7, y, retdest)
|
||||
%mstore_kernel(@SEGMENT_KERNEL_ECDSA_TABLE) %mstore_kernel(@SEGMENT_KERNEL_ECDSA_TABLE)
|
||||
PUSH 2
|
||||
// Use a loop to store a*G ± b*phi(G) + c*Q ± d*phi(Q) for a,b,c,d in {0,1}^4.
|
||||
precompute_table_loop:
|
||||
// stack: i, retdest
|
||||
DUP1 %increment %mload_kernel(@SEGMENT_KERNEL_ECDSA_TABLE)
|
||||
%stack (y, i, retdest) -> (i, y, i, retdest)
|
||||
%mload_kernel(@SEGMENT_KERNEL_ECDSA_TABLE)
|
||||
PUSH precompute_table_loop_contd
|
||||
DUP3 DUP3
|
||||
PUSH 9 %mload_kernel(@SEGMENT_KERNEL_ECDSA_TABLE)
|
||||
PUSH 8 %mload_kernel(@SEGMENT_KERNEL_ECDSA_TABLE)
|
||||
// stack: Gx, Gy, x, y, precompute_table_loop_contd, x, y, i, retdest
|
||||
%jump(ec_add_valid_points_secp)
|
||||
precompute_table_loop_contd:
|
||||
%stack (Rx, Ry, x, y, i, retdest) -> (i, 8, Rx, i, 9, Ry, x, y, i, retdest)
|
||||
ADD %mstore_kernel(@SEGMENT_KERNEL_ECDSA_TABLE) ADD %mstore_kernel(@SEGMENT_KERNEL_ECDSA_TABLE)
|
||||
DUP2 DUP2
|
||||
PUSH 17 %mload_kernel(@SEGMENT_KERNEL_ECDSA_TABLE)
|
||||
PUSH 16 %mload_kernel(@SEGMENT_KERNEL_ECDSA_TABLE)
|
||||
%stack (Gx, Gy, x, y, x, y, i, retdest) -> (Gx, Gy, x, y, precompute_table_loop_contd2, x, y, i, retdest)
|
||||
%jump(ec_add_valid_points_secp)
|
||||
precompute_table_loop_contd2:
|
||||
%stack (Rx, Ry, x, y, i, retdest) -> (i, 16, Rx, i, 17, Ry, x, y, i, retdest)
|
||||
ADD %mstore_kernel(@SEGMENT_KERNEL_ECDSA_TABLE) ADD %mstore_kernel(@SEGMENT_KERNEL_ECDSA_TABLE)
|
||||
PUSH 25 %mload_kernel(@SEGMENT_KERNEL_ECDSA_TABLE)
|
||||
PUSH 24 %mload_kernel(@SEGMENT_KERNEL_ECDSA_TABLE)
|
||||
%stack (Gx, Gy, x, y, i, retdest) -> (Gx, Gy, x, y, precompute_table_loop_contd3, i, retdest)
|
||||
%jump(ec_add_valid_points_secp)
|
||||
precompute_table_loop_contd3:
|
||||
%stack (Rx, Ry, i, retdest) -> (i, 24, Rx, i, 25, Ry, i, retdest)
|
||||
ADD %mstore_kernel(@SEGMENT_KERNEL_ECDSA_TABLE) ADD %mstore_kernel(@SEGMENT_KERNEL_ECDSA_TABLE)
|
||||
%add_const(2)
|
||||
DUP1 %eq_const(8) %jumpi(precompute_table_end)
|
||||
%jump(precompute_table_loop)
|
||||
|
||||
precompute_table_end:
|
||||
// stack: i, retdest
|
||||
POP JUMP
|
||||
@ -133,7 +133,7 @@
|
||||
PUSH $c
|
||||
// stack: c, input, ...
|
||||
GT // Check it backwards: (input < c) == (c > input)
|
||||
// stack: input <= c, ...
|
||||
// stack: input < c, ...
|
||||
%endmacro
|
||||
|
||||
%macro le_const(c)
|
||||
|
||||
@ -41,8 +41,8 @@ impl Kernel {
|
||||
prover_inputs: HashMap<usize, ProverInputFn>,
|
||||
) -> Self {
|
||||
let code_hash_bytes = keccak(&code).0;
|
||||
let code_hash = std::array::from_fn(|i| {
|
||||
u32::from_le_bytes(std::array::from_fn(|j| code_hash_bytes[i * 4 + j]))
|
||||
let code_hash = core::array::from_fn(|i| {
|
||||
u32::from_le_bytes(core::array::from_fn(|j| code_hash_bytes[i * 4 + j]))
|
||||
});
|
||||
let ordered_labels = global_labels
|
||||
.keys()
|
||||
|
||||
@ -63,7 +63,11 @@ const HASH_CONSTANTS: [(&str, [u8; 32]); 2] = [
|
||||
),
|
||||
];
|
||||
|
||||
const EC_CONSTANTS: [(&str, [u8; 32]); 3] = [
|
||||
const EC_CONSTANTS: [(&str, [u8; 32]); 10] = [
|
||||
(
|
||||
"U256_MAX",
|
||||
hex!("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
||||
),
|
||||
(
|
||||
"BN_BASE",
|
||||
hex!("30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"),
|
||||
@ -76,6 +80,30 @@ const EC_CONSTANTS: [(&str, [u8; 32]); 3] = [
|
||||
"SECP_SCALAR",
|
||||
hex!("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"),
|
||||
),
|
||||
(
|
||||
"SECP_GLV_BETA",
|
||||
hex!("7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee"),
|
||||
),
|
||||
(
|
||||
"SECP_GLV_S",
|
||||
hex!("5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72"),
|
||||
),
|
||||
(
|
||||
"SECP_GLV_MINUS_G1",
|
||||
hex!("00000000000000000000000000000000e4437ed6010e88286f547fa90abfe4c4"),
|
||||
),
|
||||
(
|
||||
"SECP_GLV_G2",
|
||||
hex!("000000000000000000000000000000003086d221a7d46bcde86c90e49284eb15"),
|
||||
),
|
||||
(
|
||||
"SECP_GLV_B1",
|
||||
hex!("fffffffffffffffffffffffffffffffdd66b5e10ae3a1813507ddee3c5765c7e"),
|
||||
),
|
||||
(
|
||||
"SECP_GLV_B2",
|
||||
hex!("000000000000000000000000000000003086d221a7d46bcde86c90e49284eb15"),
|
||||
),
|
||||
];
|
||||
|
||||
const GAS_CONSTANTS: [(&str, u16); 36] = [
|
||||
|
||||
@ -25,7 +25,7 @@ type F = GoldilocksField;
|
||||
const DEFAULT_HALT_OFFSET: usize = 0xdeadbeef;
|
||||
|
||||
impl MemoryState {
|
||||
fn mload_general(&self, context: usize, segment: Segment, offset: usize) -> U256 {
|
||||
pub(crate) fn mload_general(&self, context: usize, segment: Segment, offset: usize) -> U256 {
|
||||
self.get(MemoryAddress::new(context, segment, offset))
|
||||
}
|
||||
|
||||
@ -108,14 +108,12 @@ impl<'a> Interpreter<'a> {
|
||||
self.run_opcode()?;
|
||||
}
|
||||
println!("Opcode count:");
|
||||
let mut tot = 0;
|
||||
for i in 0..0x100 {
|
||||
if self.opcode_count[i] > 0 {
|
||||
tot += self.opcode_count[i];
|
||||
println!("{}: {}", get_mnemonic(i as u8), self.opcode_count[i])
|
||||
}
|
||||
}
|
||||
println!("TOTAL: {}", tot);
|
||||
println!("Total: {}", self.opcode_count.into_iter().sum::<usize>());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@ -4,13 +4,13 @@ use crate::keccak_sponge::columns::{KECCAK_WIDTH_BYTES, KECCAK_WIDTH_U32S};
|
||||
|
||||
/// Like tiny-keccak's `keccakf`, but deals with `u32` limbs instead of `u64` limbs.
|
||||
pub(crate) fn keccakf_u32s(state_u32s: &mut [u32; KECCAK_WIDTH_U32S]) {
|
||||
let mut state_u64s: [u64; 25] = std::array::from_fn(|i| {
|
||||
let mut state_u64s: [u64; 25] = core::array::from_fn(|i| {
|
||||
let lo = state_u32s[i * 2] as u64;
|
||||
let hi = state_u32s[i * 2 + 1] as u64;
|
||||
lo | (hi << 32)
|
||||
});
|
||||
keccakf(&mut state_u64s);
|
||||
*state_u32s = std::array::from_fn(|i| {
|
||||
*state_u32s = core::array::from_fn(|i| {
|
||||
let u64_limb = state_u64s[i / 2];
|
||||
let is_hi = i % 2;
|
||||
(u64_limb >> (is_hi * 32)) as u32
|
||||
@ -20,9 +20,9 @@ pub(crate) fn keccakf_u32s(state_u32s: &mut [u32; KECCAK_WIDTH_U32S]) {
|
||||
/// Like tiny-keccak's `keccakf`, but deals with bytes instead of `u64` limbs.
|
||||
pub(crate) fn keccakf_u8s(state_u8s: &mut [u8; KECCAK_WIDTH_BYTES]) {
|
||||
let mut state_u64s: [u64; 25] =
|
||||
std::array::from_fn(|i| u64::from_le_bytes(state_u8s[i * 8..][..8].try_into().unwrap()));
|
||||
core::array::from_fn(|i| u64::from_le_bytes(state_u8s[i * 8..][..8].try_into().unwrap()));
|
||||
keccakf(&mut state_u64s);
|
||||
*state_u8s = std::array::from_fn(|i| {
|
||||
*state_u8s = core::array::from_fn(|i| {
|
||||
let u64_limb = state_u64s[i / 8];
|
||||
u64_limb.to_le_bytes()[i % 8]
|
||||
});
|
||||
|
||||
@ -134,10 +134,12 @@ mod bn {
|
||||
|
||||
#[cfg(test)]
|
||||
mod secp {
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::cpu::kernel::aggregator::combined_kernel;
|
||||
use crate::cpu::kernel::interpreter::{run, run_interpreter};
|
||||
use anyhow::Result;
|
||||
use ethereum_types::U256;
|
||||
|
||||
use crate::cpu::kernel::aggregator::{combined_kernel, KERNEL};
|
||||
use crate::cpu::kernel::interpreter::{run, run_interpreter, Interpreter};
|
||||
use crate::cpu::kernel::tests::u256ify;
|
||||
|
||||
#[test]
|
||||
@ -146,7 +148,6 @@ mod secp {
|
||||
let kernel = combined_kernel();
|
||||
let ec_add = kernel.global_labels["ec_add_valid_points_secp"];
|
||||
let ec_double = kernel.global_labels["ec_double_secp"];
|
||||
let ec_mul = kernel.global_labels["ec_mul_valid_point_secp"];
|
||||
let identity = ("0x0", "0x0");
|
||||
let point0 = (
|
||||
"0xc82ccceebd739e646631b7270ed8c33e96c4940b19db91eaf67da6ec92d109b",
|
||||
@ -166,12 +167,6 @@ mod secp {
|
||||
"0x7872498939b02197c2b6f0a0f5767f36551e43f910de472fbbff0538b21f5f45",
|
||||
"0x294e15025d935438023a0e4056892abd6405fade13cf2b3131d8755be7cebad",
|
||||
);
|
||||
let s = "0xa72ad7d8ce24135b5138f853d7a9896381c40523b5d1cf03072151f2af10e35e";
|
||||
// point4 = s * point0
|
||||
let point4 = (
|
||||
"0xd8bec38864f0fe56d429540e6de624afb8ddc7fba1f738337913922a30b96c14",
|
||||
"0x5b086b2720ac39d173777bc36a49629c80c3a3e55e1c50527e60016d9be71318",
|
||||
);
|
||||
|
||||
// Standard addition #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0, point1.1, point1.0])?;
|
||||
@ -192,10 +187,6 @@ mod secp {
|
||||
let initial_stack = u256ify(["0xdeadbeef", point0.1, point0.0])?;
|
||||
let stack = run_interpreter(ec_double, initial_stack)?.stack().to_vec();
|
||||
assert_eq!(stack, u256ify([point3.1, point3.0])?);
|
||||
// Standard doubling #3
|
||||
let initial_stack = u256ify(["0xdeadbeef", "0x2", point0.1, point0.0])?;
|
||||
let stack = run_interpreter(ec_mul, initial_stack)?.stack().to_vec();
|
||||
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])?;
|
||||
@ -211,36 +202,29 @@ mod secp {
|
||||
let stack = run_interpreter(ec_add, initial_stack)?.stack().to_vec();
|
||||
assert_eq!(stack, u256ify([identity.1, identity.0])?);
|
||||
|
||||
// Scalar multiplication #1
|
||||
let initial_stack = u256ify(["0xdeadbeef", s, point0.1, point0.0])?;
|
||||
let stack = run_interpreter(ec_mul, initial_stack)?.stack().to_vec();
|
||||
assert_eq!(stack, u256ify([point4.1, point4.0])?);
|
||||
// Scalar multiplication #2
|
||||
let initial_stack = u256ify(["0xdeadbeef", "0x0", point0.1, point0.0])?;
|
||||
let stack = run_interpreter(ec_mul, initial_stack)?.stack().to_vec();
|
||||
assert_eq!(stack, u256ify([identity.1, identity.0])?);
|
||||
// Scalar multiplication #3
|
||||
let initial_stack = u256ify(["0xdeadbeef", "0x1", point0.1, point0.0])?;
|
||||
let stack = run_interpreter(ec_mul, initial_stack)?.stack().to_vec();
|
||||
assert_eq!(stack, u256ify([point0.1, point0.0])?);
|
||||
// Scalar multiplication #4
|
||||
let initial_stack = u256ify(["0xdeadbeef", s, identity.1, identity.0])?;
|
||||
let stack = run_interpreter(ec_mul, initial_stack)?.stack().to_vec();
|
||||
assert_eq!(stack, u256ify([identity.1, identity.0])?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Multiple calls
|
||||
let ec_mul_hex = format!("0x{ec_mul:x}");
|
||||
let initial_stack = u256ify([
|
||||
"0xdeadbeef",
|
||||
s,
|
||||
&ec_mul_hex,
|
||||
identity.1,
|
||||
identity.0,
|
||||
point0.1,
|
||||
point0.0,
|
||||
])?;
|
||||
let stack = run_interpreter(ec_add, initial_stack)?.stack().to_vec();
|
||||
assert_eq!(stack, u256ify([point4.1, point4.0])?);
|
||||
#[test]
|
||||
fn test_glv_verify_data() -> Result<()> {
|
||||
let glv = KERNEL.global_labels["glv_decompose"];
|
||||
|
||||
let f = include_str!("glv_test_data");
|
||||
for line in f.lines().filter(|s| !s.starts_with("//")) {
|
||||
let mut line = line
|
||||
.split_whitespace()
|
||||
.map(|s| U256::from_str_radix(s, 10).unwrap())
|
||||
.collect::<Vec<_>>();
|
||||
let k = line.remove(0);
|
||||
line.reverse();
|
||||
|
||||
let mut initial_stack = u256ify(["0xdeadbeef"])?;
|
||||
initial_stack.push(k);
|
||||
let mut int = Interpreter::new(&KERNEL.code, glv, initial_stack, &KERNEL.prover_inputs);
|
||||
int.run()?;
|
||||
|
||||
assert_eq!(line, int.stack());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -25,6 +25,24 @@ fn test_invalid_ecrecover(hash: &str, v: &str, r: &str, s: &str) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ecrecover_real_block() -> Result<()> {
|
||||
let f = include_str!("ecrecover_test_data");
|
||||
let convert_v = |v| match v {
|
||||
// TODO: do this properly.
|
||||
"0" => "0x1b",
|
||||
"1" => "0x1c",
|
||||
"37" => "0x1b",
|
||||
"38" => "0x1c",
|
||||
_ => panic!("Invalid v."),
|
||||
};
|
||||
for line in f.lines().filter(|s| !s.starts_with("//")) {
|
||||
let line = line.split_whitespace().collect::<Vec<_>>();
|
||||
test_valid_ecrecover(line[4], convert_v(line[0]), line[1], line[2], line[3])?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ecrecover() -> Result<()> {
|
||||
test_valid_ecrecover(
|
||||
184
evm/src/cpu/kernel/tests/ecc/ecrecover_test_data
Normal file
184
evm/src/cpu/kernel/tests/ecc/ecrecover_test_data
Normal file
@ -0,0 +1,184 @@
|
||||
// // `ethers.rs` code to get ECDSA data for every transaction in block 16141392.
|
||||
// #[tokio::main]
|
||||
// async fn main() -> Result<()> {
|
||||
// let provider =
|
||||
// Provider::<Http>::try_from("https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27")
|
||||
// .expect("could not instantiate HTTP Provider");
|
||||
// let mut ans = String::new();
|
||||
// let block = provider.get_block(16141392).await?.unwrap();
|
||||
// for tx in block.transactions {
|
||||
// let tx = provider.get_transaction(tx).await?.unwrap();
|
||||
// let typed_tx: TypedTransaction = (&tx).into();
|
||||
// ans.push_str(&format!(
|
||||
// "{} 0x{:x} 0x{:x} {:?} {:?}\n",
|
||||
// tx.v,
|
||||
// tx.r,
|
||||
// tx.s,
|
||||
// tx.from,
|
||||
// typed_tx.sighash()
|
||||
// ));
|
||||
// }
|
||||
// let mut f = File::create("ecrecover_test_data").expect("Unable to create");
|
||||
// f.write_all(ans.as_bytes()).expect("Unable to write");
|
||||
// Ok(())
|
||||
// }
|
||||
37 0x71e206f9a89076270d57e93486946ce5803dbcb76279780aa41bf258763fad23 0x5f7e34e4a781f7572f8192b845de80fe24d77f13552dfefb67e03c94388934c 0x7a7f78a2af5aef01a889e8713083ab77dcc9fc9b 0xf457bef979aae3c1cbbb294a8f015a8e149a60ec0146383a4bec6fb097098d24
|
||||
1 0x57d71702dde291f2d7c6ea8b9d8172523b72e93db5a7426c5b898bb74d555a3b 0x47303ce56b157b8c237bc0206a610975ef690bd71912315a35fd01ea428b7520 0x1113efd5c8896ccf251ea360bb9d91f113707f80 0x65a5c566f3dea5f436bb33e8803be619c1c6d3857b0199335630e643a1e3774c
|
||||
38 0x6cb3fd5d878b8b234906bc447c9b6abac34fec019d82d1e1419874bff40f08e1 0x4de3f2f5babfa400a014739e705f64219824ed75ab16058835452366e00b7498 0xea320901e51d9268a7f5789d305b1330657fc52b 0x3c922df979a5c1922d2baedca63215577d603b13b72862b57fbf240ca501bb20
|
||||
0 0xa34136f1b02ba36d0644d6aa695bca911c9a7ce5e19272f97b82056b03f481cc 0x26eb167cf65e0ce1f8f0c3809863e3c8542f706b8ef07ad849793fe208bcc7e6 0x4e80744fa23cec76e1621ce0dfaceb4b1d532e12 0xf4e022d9b83d279611395823e4b436d1b795054e59d0ddc663c42c41075026c4
|
||||
37 0xf4fa7bd652968977947eb8a9bbb216735ded98405e95555cafdf48615c1d4866 0x77545ac93bf7065641161ec455c23a8fe2b0e6f1f9d8ab8efefa39e6ae3ae0 0x9acbb72cf67103a30333a32cd203459c6a9c3311 0x2727dd81db2f9141fe2828b150dff11b073a825b88e514b1d33f3bec117e3c5a
|
||||
38 0xca14396f151b4c21129bb15c70db48c97969809f681d7521841d2dea13bd7be 0x3438d0e665fdaea72759ad3db4bab68674314cb50d902fb58a57ff8f61c89703 0x595063172c85b1e8ac2fe74fcb6b7dc26844cc2d 0x26c3de6bd2e155436e031928d2cec402853cf6797a4718cbcc89b48ed05d623c
|
||||
0 0xad3fd1fb3cf701e53cd5687926ca64b2fa978a062efdb1f6d78d15c7610ef5e5 0x33c82cf8f9cc1072307ac99ff833c76775e0a4c5cb0a177eb4b1b415cb96239c 0x8a89e016750479dc1d7ad32ecffcecd76e118697 0x548757e275d1152805810855b75dfbe12a421023aecab6da0cfa257156695d53
|
||||
1 0x95846057f4d5f4e8940f9f16b17d864b60f89a85257f5256988ce75748d24450 0x6a3accdf56960dcc8541971a12484022ab54d1359601dac5b93072e5c55e1f10 0x6da4980ab9a35ff025774203e721a4f63f78f953 0x8814c7e0039cb36f6050a9c5c72095f492bd50f156f3246c516be072f4a7b1b7
|
||||
1 0xa437b58f9d8dcb09593565cd607ebcc9ac72df40380d35332d1cc8e3e242e61e 0x6391ca50a4be1ccb9f7e46d4beae2196984f88ef0d3e9bd47a85cb2ad3d2aac5 0x19ff156cbeaabd04ffa2df84eb6eca93f266ba0a 0xe3ea3b265ff5bbf8746b3bd81c934ddcbfda502ca3047bc2fb41d6218c43c8f6
|
||||
0 0x912e235df87ed93dcfabb8646e4fbe7a5b5aac00a27b0c0795492df682311f01 0x4a08239f03720362976203222bd9a60536746a0717e951d20656149833ee8aee 0xdd0eddc7d2ac6fcc3a8bb54b4d329b71f96ec8ba 0x8e65adea948f96cdf3dbf74b65b0611455c6c8d8295715744af921a3d2b73fb5
|
||||
38 0x1c1f7fd0febe597836a8650dce0e8c72e1b506dfaac11aabb909821a77fe657a 0x23fc3c8b0e73eb6077a9e861cad7e38ea26920ccff72aa46616b241ae16eefa8 0x120051a72966950b8ce12eb5496b5d1eeec1541b 0xa2f59b3fb815c9d3d5ad410e793ec97962032e965f81ecb07bc8606821faaf7e
|
||||
38 0x88de71d84e271c4213391d1f78e47d2c7efb017b8b21fdebc97b8e2fc0d121f4 0x17a58f16c998f04e22577b88484ac1f7493a0473d2eb4dcdf5ccd659593712cb 0xe93381fb4c4f14bda253907b18fad305d799241a 0x2614f325a54ba5bcff2bb9221bda406e7ac17515a94abfc85e8764340f28f3c3
|
||||
38 0xda16a02577ac6d17701ad03320d1a1786320b7941680ae242d9faf5b117d5c2a 0xa475e4d3f36b7afa9af0e558f5ffb68377ff001d7f842b118416840cb7ed231 0x1062a747393198f70f71ec65a582423dba7e5ab3 0xe5bccf131464da99d721c610b1bda164418b645dfba3c98f01c5048e8dfb7934
|
||||
37 0xcefe9615f951106d5b52ff9f5e07c42319c998b70c3d291eb2218dd0c497ae18 0x52fca3109c234eac060b8daa57f673fb6b8b2c1278fd6a167f12deaee1071819 0xc55eddadeeb47fcde0b3b6f25bd47d745ba7e7fa 0x22cf2c4159f1fea8c78f1175b8c7f3743b31894525f5c272f027f8b20b56eba7
|
||||
37 0x8ec6fb0236f0a39bca70802551fab9d7258346399f6deb0bfab834af93beda56 0x6f273debd0a0e8e98ac63d6078d23fa93a7b5786a7456bb5cb3fecc19b1cebc7 0x75e89d5979e4f6fba9f97c104c2f0afb3f1dcb88 0xfafe13916c038b9b01e476ef5675341a75bd39f198500732b116221d92620781
|
||||
38 0xb244a0d2c66cf36f35455ecd8731f2960c64db35603ad2a76ffa34d22bdb821f 0x1a7038fceb3cbaa08fae08d5857192e44dae37666cf841b11c6e2bf84e655078 0x75e89d5979e4f6fba9f97c104c2f0afb3f1dcb88 0x17c8c48fb411df67de52aee98dc4a586f3725704199761f5bd23158437cb5872
|
||||
38 0x59ed90e66529f9b21ff820ab501e5ee0f18dde32c1debd66b5dc6e3342032b62 0x3f4b7b15b0af3339d791c8e73a7976d16bbd91316025d256d9161ff1ba894c69 0x75e89d5979e4f6fba9f97c104c2f0afb3f1dcb88 0x4a34d102022fa077a95899e102ef294cbd5941145fce1e29e2af39c6c831ce77
|
||||
38 0xd2bd67f5a2ff75cc124ebf944f7c26d87172d580cd92493d50002af32781c02 0x6536865fc12e5121a546458a45b480ca4a14b71d1cb899cf53c936044ad756f 0x75e89d5979e4f6fba9f97c104c2f0afb3f1dcb88 0x8d635892680e858fa7c2564751262f0ef074134ac6a46149b1ff02f16c0276f5
|
||||
37 0x274407742377dea657519cee052763f9f0247fb2fc8d6a587d3290b4056abd2e 0x1ab13a59094aaac36a7292c7cd6814d11119bd34363f313c993e46f4a4fe157c 0x97b9d2102a9a65a26e1ee82d59e42d1b73b68689 0x9d22cf1bda837de201fce2be661c2bcf5e6c3829fd75f58232a7200fe89abad1
|
||||
0 0x9613c1e52f935a04483aab79c0ef76f8d427f79feaa2543ba4c94a91cbff7f6 0x3d75a82cae83a3647c248f44752185b662055ef9f3f21abf2fe5260f6885002d 0x86e122e39d467eb13d82765881cdd944c94ba922 0xfe0f34ef96a36515135bff2c1fb7964a552c0bdfb88a1ad773414f2a05c77132
|
||||
37 0x37f09f9d9d034a9ea8892c3a7b4826de643778f59e217ded5199d5cd32b3237a 0x311f3b9d4f7d771015eaaa0a1c2cd5759ed798902ecc03632a18de47c078149a 0x9cbf099ff424979439dfba03f00b5961784c06ce 0x9d08d5163de3f8437d991d7fff25178eeb821ae6e272cbf42a86f4f1a22023b1
|
||||
37 0x28210d2f4b817744db46b71c7c993fd3318ad30a96975678f185cf5e8067b9dd 0x646aba390d36afcce34eeb928b92c8d0e12cfc5ad598569045de59d4b2de3526 0x41d9294128b6c8815dd92199700953220b1bd375 0xd4711cb46f4155bb887a2d978f2c4d877cf9bef8122ca0d30395d5815bc5a886
|
||||
0 0x4455fa740404acaec4e670be00843afe7cc6cfa379108ef02eb8368210791943 0x83f2557e17faf4951e9cb767b278f57487776927928cc53f5f1e4f028982cb1 0x0b5c4a7fcda49e0a8661419bb55b86161a86db2a 0xe676662e29b77af78c77311801b74666dc37ca016da761c164a3ddfe971502bf
|
||||
0 0xdfb1180544b6b942c23ddadbe4561c821dea1727735fb4442c2c0ad02185111 0x6524e1961d5357471ab6d7e4ff52fc434c88a962ac0a8f203dbf67cb4e971727 0xdcdf0feeede933ceafc6131b663f1ee210ac61ae 0x6f9cf3180ba5ffa60436b7539de12d8b11e0343810b0d3f85d6457745219b86c
|
||||
0 0xe3f04a7f4b367c274a018bf88c3e3929ace1ae203e6cbceb4809f4b6453b665 0x57da3d1b4b3e6adc031deeb9baf408b241d178e12577c105f97d15eb71945151 0xdc5432c573a1d4874d305a5cd7e62aed2b0bc522 0xd79be8888d4ac1d12398740b93f7cf5adbffa332356677973663b2580d45c7e2
|
||||
1 0xa29cc033a00f3efda65699bba97235eeede560f1adb51d307a168a2db841d8a8 0x6f761fa28ed8c0aa16773f7a11ab14c34dec9d31a085887a798dabcd00fb1905 0x19f494583c7c933be7b0ee58104ddafac1e8adfa 0x21f2778f84b87d28bd417f57a952fc3b86b86641717008fda61ebfc956dd7166
|
||||
0 0xa18dde11da20682e5d3904fce5591b2d499bea1980e113a6b851a786f9551415 0x7f29dab88a65cb3cef6b8fdd633e61f565ba385459998637b4e54de7a69c017b 0x4a3646402d1aed59cd97972474beb7d1c68b303d 0x889719b175613719e30dbdf7c59b0766ae3a642c0700fb43e6959b369796e218
|
||||
0 0x563776eb92b4ddecc85ceb07b5968ed78b47956554735cfc212db00e03fdaa04 0x28bac43c2efd049b4e9ab7c46d5961e216da1baab59c4e2930bf19ba146c5e21 0x8216874887415e2650d12d53ff53516f04a74fd7 0x4aa2be7cb95d651d91b8feb3d32c04f4abb1c8c36eb0b2c88a72b1a1630cdda3
|
||||
1 0x24dd078a4a604496c592fd0568c50e340c2df5d3343392b62f6669128c43777d 0x54a4e08b684ed36cdf20f132164ec18599b07763da289787ef4ecd21635e7bdf 0x64917e321c516a2dbdad48bef7e923873eb7854f 0x2335ef16b1d02b9e206f952b7d98bde5f453afd6e95391a6083fc4d6fc829e2b
|
||||
1 0x96942017e0365f7e059d8822e8bdb10f772e186e5f6dec136baac903f037863e 0xd94dc604b36c0b77740a4bbf70a051d239185611ee36f2a6224c8604b638016 0x0e7518b332f469a6a2f59e690f225cef5157cca9 0x62b0621f47ddb24e8581b2165cde8f4f883222c991fcb1ba2610d01948a5882e
|
||||
1 0x5e5f424b80fb1351a178d36348840d9bd5cf363c78550d829322f21b58a2adfb 0x41a2fb3e6fe3c5a4449106ba5fd2d0d5e9efc10e26e8c17e7133fecf6faf138d 0xa7fb5ca286fc3fd67525629048a4de3ba24cba2e 0x4a3adb07cc5bd5b0cd6dbdafb1d643e41e353c9ef1cf83ac1fda32815b09d461
|
||||
0 0x17216ef4d8539f74333914926d1fdec20b06ce4594d846af59bbb0995ad80bdc 0x5806f2eeef10c734ac9e577f3a7c73b338ef2553238b5543a1c2dcc35c3481b8 0x7f72687d4981e85d2d2746c17a0219d8054a2148 0x9a3fbe852ed1abfe59e63eca1d8e2453a1060fadc622360d4f6bc40cbb8e326d
|
||||
1 0xf765aa91e69fb3436969124c747b888e705d49e8150a63a545343ade5a425ac6 0x19235da122cf688b31101015a9f4c67ddd557f7139206641182187c308f608ed 0xb6e145b74eb1a016231483272fb622ffb68d3d7c 0x2537f24f5d73879d63799050aa0eaf5fce44bd670068aa2b1b997913859106b4
|
||||
1 0xa2c13c62165475ed08b64524b7c9a8c1e6f7d4fd041c579eca29306c0ccae15b 0x3fab181d182a0f0d9768d75bbb8461f2a9a6b3416212e8b91209680e29c5a31 0x24c09a812b6419ae0e929b95d562f635097d4590 0xf9113ed129138f590b498a572380efaa06b59e436689772534842d7837e092e8
|
||||
1 0x3dd17bdd0a94e61f79b21917b937bb45cac40ee88cb37a09c987ddd346ee551b 0x32017f92d89ed4ac0f4a235c5f6f41982faa4341076ac2dbfb29a7a8efd15e1b 0x41f0bbe07573e14944304c0a544c5dbe6f468cf9 0x7df3db64dad8bf775cd8e6e585a61065cc739ec914cde160b3aee6d0bcfeba72
|
||||
0 0x7ab5cbca681be515dce228b1fb30dd588e1fa9eaeee60a9c869a9e4d6a44da8e 0x6567506dacb0bdf3be1aa5ebd55bb97b159258d728d7f2e54034555648c434a8 0xf031dd3ef38f677b55e8c4a191c3b9e343c07758 0x76a21141c922911e735c493c8bac70d04c6c83af1793046cc74d417deb23c8ef
|
||||
0 0x541aad8b51542ac5f71abb002099c2107dc0a87da05751675deb23f683fd26a8 0x51b3820e49ba8cb365fcffb97269a30b826b509eaebc05b03c37be93ffba06ed 0x9079caa7968d77ca87967ced769bb4fef312a834 0xd570c731edcc02bf4f06f3631de76b4e2427fb64f315e9ea94080125d4478818
|
||||
1 0x896ac1bcf80a4a2c503f92bb030f0db43aa545e8f44693955b4f577bc6df260a 0x65c170a802c5b98a4567dbbeff8ec95d55434eaad260c12f37582334cbe013de 0x792eafab3593fd79f01c8dd5282965dec1bba51f 0x2c9a7a5e841d0a432a3d09a657c0a465604467f4ed0a8bf1d34583d2f49245b8
|
||||
0 0x9cd74d9898571e0af4e013337231472e033d7b95f70523a10f7122eb4a63497 0x4494e798d8905e9662b48b99c89835a2166b070be8581ede50bec94cfaac332e 0xaa9a1ec22aef4fd5119eafda899a72ffa0cae258 0x5c378afcde7290d00b044893da06469e9c2181a1558598a85830c3bae8de121f
|
||||
0 0xca04356a33bf7351027ecc535e3e08537abdd333f2907a98e7d16a2e4408997 0x6871c6fdd8152913909322eab21e55baa51ec4bddf161b0e7d71251da17e3b9e 0x4976a4a02f38326660d17bf34b431dc6e2eb2327 0xe814b149e4d1a7404f17678f8a845795364f99fb830b9db51a84421ae4891f17
|
||||
1 0xd390febaf6781e5ddaddc823f1791c133b6818588e4d071248e7c3418977c2b5 0xbd2a753d9c86388a052044df07193bdafce4d5dd36e4a4e3973ebbdf0a7bb91 0x4976a4a02f38326660d17bf34b431dc6e2eb2327 0xc20c2be74014e4d9032c422635038ec1ee0925b2e2da0b7922f5f3c0d2d3ce25
|
||||
1 0x54c0524f19276d1404c067e69f7288ee5eee955ad12226daec56d74b7894405a 0x4335aa0002e02ddabea351271f791f0a55f69119a88a5dd64048bd7c241c57ce 0x28c6c06298d514db089934071355e5743bf21d60 0x59c08d63ebe74a3ac3c3d2dd65e813ece338b4df7878d5842732a24b3bc886fb
|
||||
0 0x3f5bd3f07b802df407ac00f150b6b091f45a877c4dbb65c9d4ffacda8cadd858 0x4b02042d475f722e862608ebd4625dde1fe5b6c18a09025d61694e6e1a986ea6 0x28c6c06298d514db089934071355e5743bf21d60 0x2d81d7671ecfd4830d97fb7f2fad04440062a3cff4f10bfe7fb2f458fdc758fb
|
||||
0 0x4a704b00ae04e370b365d5d1f7d54f5b4554428bac0db7f24cb2d8e52b66a045 0x705197257bc2464a40381a5a6e062cce897e621013ea10c9647bafe1156ac2a2 0x28c6c06298d514db089934071355e5743bf21d60 0x368efdc35f07630059054c541f0cc8c259d57c2de9dd57fb3b72083f2fd1ca0b
|
||||
0 0xee6ee3b45d0bfb27c6c424bfe3e268b5c88c0c0a09863005e907f22cc9935aa6 0x5c5ff76d39ffc6483116642b4b9d4ce851fd9a30f3a6c7ab963c1e2e151d82f8 0x9696f59e4d72e237be84ffd425dcad154bf96976 0x9252f22653436777ec2df3e6f5d532d11cf7c4e1084bd4e86c0821cc2ebc719e
|
||||
1 0x81da46ac5a2c6a97e4c58a5e1081b6d68f97971bbd27a22cc3499c31fb557ded 0x140b455d2d09f1af1fea8777b828662b3b348265a5f9b336b4edc149434967dc 0x9696f59e4d72e237be84ffd425dcad154bf96976 0x2d03a34ba34a3ca1a8c8ba3cee10f0ca128c36f211b7e50b8728651fc8544d39
|
||||
0 0x60064f428d0d60a5bd28057f4b86e82c0d5592b3bdae2feea0d79881e5f72fb5 0x774b1055a8f27c9307bbe7eaaf9029bbb7e920acd9c0038b0646eb0538ef38fa 0x56eddb7aa87536c09ccc2793473599fd21a8b17f 0x0432c2c29c6bfa4242054e26254776f91678f21c99e672eddeccd3b9b2f92729
|
||||
1 0xc33b4f64a2183316ad21136cb72cf4f2260a864561cde658fd8a6ab5764a2f8b 0x59f25f6bcd7643bb349495b8816db070cad1776d6d6e18b0b119fbf9d8e4d001 0x56eddb7aa87536c09ccc2793473599fd21a8b17f 0x086ce311a8a9090542543571cab974bdfbc6c44abda76c8828b02672335da789
|
||||
0 0xa758e894173ce8be91f4d5544a7ba339744bfa95b535162a03acb61f5a9ea09a 0x39edb3cda1abb60a2ebd59636d9375ae08776745cb1a962eda45048fc1bd234e 0x56eddb7aa87536c09ccc2793473599fd21a8b17f 0xcf40ff9251650690129f50bc19a5a395ecb7d9b1bff94d16b14d759394f428e7
|
||||
1 0x50e249764da0ce92ad0e832b544d7526729eacfc43f3011fa6f555cbb6d394ce 0x52d85c3e2d5fc6505078b3200676e8efa8ef1626720938ec52ec3cac9f44ad33 0x21a31ee1afc51d94c2efccaa2092ad1028285549 0x584f942852d1ce266b8159c971f552e5b1692809b0fb98489e3605811b7f5de2
|
||||
0 0x673b134b030bc26cd02e4cea1ddd63effbdf0a178c9cacc932c2440042e1e18b 0x2aa60ee96d3dc050a0558fde204f482a85cb246ca431416b9ce9d18290a213af 0x21a31ee1afc51d94c2efccaa2092ad1028285549 0x978cbde7348b61241687919e376b531e1e9ab62eccd5c90c6fe2a8a0226e3689
|
||||
0 0xd626eabfbd7555bbbfde2f763b342a3145e85407efe2d2616f5138f816b73d11 0x217cb61fdf4d4a342cccfe81da91ed5fee89bd7e0d66218564c5cee47cbb6050 0xdfd5293d8e347dfe59e90efd55b2956a1343963d 0xe364db52cea6b264fd6f311bd700f91aa300194d4972f8f33cbd1dadcd5093af
|
||||
0 0xe311926be6a3abbf18ea2d8b71559b60679acba9026b6a2870e1bbac1467f91e 0x21c747f249093f5772501f380b56b42e96a8ddf77bb592f377b9bfea06d9e0e2 0xdfd5293d8e347dfe59e90efd55b2956a1343963d 0xb56f149f71adaaf2674917db32c1cd864214518c58cf5574703733f924e873a1
|
||||
1 0xd4b5e0226fe10e85df2ce70a16a1ca5422bcbf83a685e6da2be48bc388c932dd 0x256ca3b5e0f3c0b422f441bed3ae5f851347990adfb2d11cf79879f54bad2cf8 0xdfd5293d8e347dfe59e90efd55b2956a1343963d 0x1d5ffce90110bd94c5d7810642e8283e721e33aa987d570b1593b04ae17b8377
|
||||
0 0xd50421f2321a69714cd7a52ff57c4c3482ca01a94eee507afe06828c4e47898 0x27e919a35fdc99ceb109873286aaeeb3e90aee201211a14496192cb80e8906f9 0xe6ab9e371e39d1daf921f24cd83ae3c837d2cce5 0x785488a8196174e5efb61add20c39c19887fa1cbf6c2c4e6f2ff9db79b966c52
|
||||
1 0x71e9f2b77a94f63614bac8249564393fcf3b3531ccf23a232b3be77ccaf1f18a 0x445c4e2eba9856f71c6c7b6f5eb81e1b451c39086458ac88f931667a1705de5c 0x5804869f1e8a5b99f2eab8c6b1943bd0dd5b26f3 0x340b702ff1d5feb24988a865d19143b47854f8526c04bf427be42e7bafb37fc9
|
||||
0 0x742855759e28bd15e07562aa6f35ff93538daf448ada687416fed7844e793658 0x73fec36e58ada180a2bb4a8847142e8ed88047d485d926a226bb8fc2feb1c804 0x1d05754e9cd39e987a34343cc862a82370942e93 0x2b0b92eab8fff875b52a21071b2ce8dc23d56652ffad308a0ff14719e4dd81b9
|
||||
1 0xe05dc5b2eadf7292c2c3c14f97e08daef9dd1aa499ad11a235d77ef4d03956a3 0x119e1653354da4b22fb38cdb11fe3ad1d18d8d174812448a6f8dd412f7ebf812 0xe41ee97cfb75f1646d143aee40fcb4991450aad0 0x2dff8c6bbec665b3bcc66782635d9192025aa733a09e7c2dbe10008e15317c08
|
||||
1 0xb1d0d41adea5daf645b5e0600f2e451aae67b2eaa191d2208db210f6a6fc61a9 0x1dd9aee6dd6cfea5c8dea1b93f0cb55c97f036c0b91fd0b167a479c72a8e84d1 0x5e746b94aa1fbf9af9559c6e04a93ef0a7abd0de 0x95366c33a8a3012c6273656ed6954e28f790943c0fdb2fcdd58290b00e853af5
|
||||
1 0x76d1a4d73ed92b786f848998c7dc8643aed6d80700faedfdf1c7c54fb8af0775 0x59f7addf6dc96f924714bb1727513d2d546ed11913087be3240f7a91b87d1d4a 0x170b4cadf7deaa017b1f595de5ec7591f7a686ea 0xb69182c459c9e8d84abaec3af791abeec972544eb880845b361e43daf36aa66b
|
||||
0 0xb32e62641c4428e8d24e65ade6b2046b2deb890b887a89334ed8118f6f4f38d6 0x3b088d3fd2d2842f1a16da028cbff9d1f5014ee35f914e665538ac4c4936b548 0x285b3bc1f46d2bf1142966a5e1c4834b86b82aba 0xbc9b62e2e020145c9fe7933a0de0d6112fadab5f8a6bf701f5c360709668f743
|
||||
1 0x1dac69e7c23884811a95371d7b91e65ed6a364cbb5eee706bb560858759b1206 0x7a1b11dcc4f7219f8a8ed4d72357b66d9794fe4beab2902f5049e4e9ab64037b 0x5ae41ec3d27c0d14809be1786f35aaad447643af 0x9b21f4d49fd6e579933afb48b6535fd55ba2060a123bbd0263657622cbfe696f
|
||||
0 0x51a7b36b6d1b7fc9d2cf6eacc16aa98bfd9d36a40d06f390cc2887dd3b064c19 0xbe87f07c87c4ae834004a8dfd4ed9e3e08b7a639aebe4f3235f745a05071f74 0xc6d7425c44ed9ce936578f8c150b6e589f9b0b92 0x793900f4ac8f983513c4fdc6f8603fb8dec6a21965cd8c7f64771c167327976c
|
||||
1 0x5965e82f900e7f98922584a7aaab65615c69494054f9a0dcbbc50502c463d13f 0x23217a916260a082687453297be97454bc64e5d1617d9ff9973db5485f7fb235 0xeb2629a2734e272bcc07bda959863f316f4bd4cf 0x0386907e53874176bcc54754145fd0e8602730f9ac1ab6e680a4acd6ad584b65
|
||||
0 0x73b358681787d5541d791f3e97f851ccb6cf55b91e2c5640b52b4f3ebcf95666 0x1375414789a136c47ee9df880858d5f729b8da5b6776db925687ab58dad50880 0x95a9bd206ae52c4ba8eecfc93d18eacdd41c88cc 0x438abe80d5baf46affeca09ee17b6f85ffa3a8c438520c8a805ca95173d09fc1
|
||||
1 0xc42bea9052ad930f8041eaa138d9062a57ea4cfc53c109d429fa9fc10d01790c 0x758222e7ef5f17699e36737b1a1bd8d2870185cc80d42a7caf0b189238eebf34 0x95a9bd206ae52c4ba8eecfc93d18eacdd41c88cc 0xf8dcd114a2a0961f9614764ad17a1cc1b0d22106dd3275fa8d62a20a3cf6e0cd
|
||||
0 0x1b42517479fa75ee42fe8b1f26dea68fde5f0d8777d32ccf94357c94e4a2b90d 0x4f82ffafaadbba64bc338890ad1f24c278dfe6cc445efa4e7a55b6625f905056 0x95a9bd206ae52c4ba8eecfc93d18eacdd41c88cc 0x164372f5e578564fbe521627f408f8ebddc6310ef689dbbfdf4d7d3c7e65bd4b
|
||||
1 0xf4894537eabe5b3c19638fffa3416049469a3a216c8e5a97668c035cfc9e07d1 0x28b06efbe60e625e1be9cd81448a9b240b93a76657c1a18844d368c617ba882 0x2f043b4bb857a7f4b6831219184dac3105aca34d 0xdb1e4681868be2072d639150c9cff48b4e7883fa6c2c6665768389e5fa4f469d
|
||||
0 0x480de57d4582c3a33c16f1049e8261a0b27df1d9e34a77e41c9d45fef01e2142 0x4fb836362b300da267c0273193445df1ed68fe28327d87acc2a22e583e64749e 0x7830c87c02e56aff27fa8ab1241711331fa86f43 0xe967340f3203ff60407a16976795d14c3fce0447a68f4b98ba98d4176057afcd
|
||||
0 0xf80a9f48dfbcf60ffc4fba1c3a820bee256006608db5267fe8ea3d38949ecbfa 0x58ea47140e36a6754e2674bf5f13f444ebb9efcc076aafc9b925d531e14b456c 0x7830c87c02e56aff27fa8ab1241711331fa86f43 0xae9506abfb4b1aa41effa3510687329b80e824241e7e60e18c7bb3a2768f151e
|
||||
0 0x816e21a58cca55cb134caf496c8c7bcc247d63a74ceef9bcfc505cd4382fd20f 0x18e9867681a483785254bc2bc23c0a6ec5fe7ab98fffd7bab2ba2f69edc59ceb 0x7c195d981abfdc3ddecd2ca0fed0958430488e34 0x1c416922452e82a5c2910d7b481923a0d3fea94856707acdbbe88842401b7473
|
||||
1 0x99f8c14bf31ec945e4bdb7af86b1d584c3263e0304aaaca78a804d5db56fcbb5 0x2e2958ece32f5999aedcf12d20a16d52dafc4296744985fd171958d95d948bb7 0x7c195d981abfdc3ddecd2ca0fed0958430488e34 0x3cd70e64bba999d4c64ecfdca7257b59d3aa8c6f034bf6adfe8ee5088c17cdd0
|
||||
1 0x221b8aa1c94cef0192f7fe4499d18e2404d463e98d4840006c606b36cc5ab5db 0x3e26c8ee8ed31948c4fd1dde9721279647ad4e17238deb46fc668feb47582d6e 0x9396d062fef353765721fa3f700fe858703a4a48 0x03b4189ff4b99e8378f60d10e10ad47bdee0e9b56828162291c60ec3ff6b74bf
|
||||
1 0x28c8e1fff48f440d92b877725d28e5d31ddbefc59412caa2559d07fb74dbd4dc 0x32833c2b615db914646a55b3d16802901476fb2f1c78a73bb4d98dfc8521db63 0x760418292d007fd98e392ee3750876c27a6460fb 0xa3562fdde603f1da197b6824b951d8f4bb70b839129333b18b6f71897a67bf30
|
||||
0 0xc906182e3c40e1f5d259dbb4cea62d2ef3fec32efed97cd307a68e38bfc1761f 0x39e57fc10bbec73cc8521dd1d2db3b86d2e9b0f03cc73fc2ee0b5b6a3df28180 0x747197638a7af760e221636405c747aab7952cc6 0x7e689bb1704555c3dc0416989cfc372199b5dcf14819a66809c1a8e2dea8cec8
|
||||
1 0xed0248a764b72ccfb9549c1d17c855d8c810e25c829bc78f81bb22ff96f899d1 0x487912ba2a9979735b05ccdf0a777fba98923139e1a1b5cccc1068640b202a6 0x5b8972964bf9076eef6610e453a014516529a52b 0x778fb142afd5ef84a7ddb1f3d71b68d20e33b2e3243d7f4f47199897ab02c495
|
||||
1 0xf2b668b356cbdfc191da4079d9823b27dae5c1f3597a70d8bbf8db5256540539 0x2f5c858f4f81da7ed09f134fb95016e487cd2f4aa2a2da1f3076f46888981505 0xe6c6ba7ea35c1f200e72056f1467b188eb441ea5 0x5a34e826e965d0c9e7afa46f61ca73e97efb3f02d294a45e263be4029a2d3d65
|
||||
1 0xaa08c519409dfdbca88be959445ee38d7577c3de9674a6db64a8beec7449264c 0x4c85250f383d7ac2af72dc1f0d6ed5de9ada483eb896c49d32c2d56a8f0c84b1 0xff214c36ac0673bc49268ff1913b11e93534c86c 0xfee2ac113b09f4b1e9b33be3ebb4b227f2d2a0b6fde20b794aa834abb8348833
|
||||
1 0x98ffea8800969c9916a6214e763ade3d6d0cc30984d42330c8c131f9464fbd16 0x7a15dcfbddbf3c64817dbcd7d4e2c61d73d2ee4792f5e89103e9b27f4c36e7bb 0x0637d40e523c2dd75a9bee55967b7b18e2cc6ac8 0x520396bd99ef0e44ca80ec8ccd1c86a32d47f1c4fda146b0666475d5372af9a4
|
||||
1 0x611d611e426f6b2d4992dd556472bedab585481fd74f90081c40c5f18e16611a 0x2f32e37f67a5edd8e8a0da6675c13859d9944ea17f35e3e5815a997f06cce35b 0x68e0389f5678f1f15346a136d3e3096a84040c9c 0x4eee7476b26f9a3b565ad5f63edf4ed9f02c0463227c46a831a915584e4c2b6e
|
||||
0 0x893a0acacaa60ff5364228c38f5a555773c0aa819538a6c64e9684162b567263 0x4e43e2381e6829acc6e3f017899f2c0f9b82e0e6672dacc38e4399889796df46 0x18e7c0e8a28822b390b7e076eb712c0850409c41 0x39e094c665cecbb18a113d1ccfc64976f4cd9887ec5463d8403bafcc77b55fce
|
||||
1 0xeaa0f379c110a5ab9ccc71a5660230ba3be968a67de2d810efce78920da14066 0x699aa12379d9f2292bb619bfe2e713041bd49bfb02b85d67e05df54b76d66a2f 0xf795bc11cb62785c31f3e638aca0091b02b051fb 0xd632206bd8dffccc98d5a4b9ebbb612d63c2dbf05eff858324b931aca4c201bc
|
||||
0 0x3405d2887bf37cf4270a98517595c78c3100e158cdf262ef59a3c4c1017ede93 0x66ac9b238933dd3072333f178e5b292ed7e18e68646d064038849b91d7cb62c 0xd0702fd5da78f3ce9267753d77d0da9f17043c24 0x664d7d927bdefc8bd1151c907124bb817c257246747f703f3de8a7365caea912
|
||||
0 0x27915f3c65833e9e80794d5342d39ca391ee459f654c49d8e84fff9c831dc50 0x4f3472eba8a1a164b982b17a37906a3e89e4e97dac88d93e51b63aecb88ee7ba 0x8edaa40f4b511ced61d2006e591d2b165807c3f7 0x9bc40c99ca374fc638d17e7c82d3b0f2d04b8ae9fac6865437b5b0708bb8567b
|
||||
1 0xea0b758241ff151595d091982295c276316f47f17f871a2590a2628b2016c40b 0x23c56e6a0226e175d6751e36f2e2d59f3846c5fe17ddbc1d4a4b2f89676e1b43 0x4425abad97059fd35ae14c9e4d8ca8ccdfa16cd3 0x18f6e255eb1c86612447f6821769389df7f348829489a10f940b0c06fb30be2e
|
||||
0 0x3695c2a9ca1a52204a47a3576963990541cc402e1515b21c9835260e4f6954a7 0x797890b5905545293eb8428ec6e46cbcdc9da057c4e7791229f9188772c8d057 0x50525410d59beadf26d271f9d693d1f4191e5a04 0xc0e8063a935706d67cb5d9c9cb99daca1413d00c6248df3f04238fa4d4cf08eb
|
||||
0 0xba1400e2353ebfa00d5b24c1b41a16751d979e7442dfa163a25d6c4e9c6d51d8 0x6c38c1250a3394029822fa3cdb43e24fdb0bb4324d5bed1291170a348fd24955 0x4d29b7f953ba471fb650fc5842127b05e35949b5 0x17198f8a656bcc2511d33b20db5c6ad0c22c8a9d67ae7c5622096f779dd4abbb
|
||||
0 0xacc2bedb2fb80896b078301ad3b4cc677200fdcb5bf08674742c2a89c7e9dfde 0x630b75ca131a42236fd0fc94e1c1e69a8fdbc7cd93fe924aba6642791e4947c8 0xf959ff8366171a9e19d142340896cd94e1aa87ea 0xacd9925b4a9f9ee88ec57fc159881c18ea86e357b90c0240ab1d6bd5fe86e850
|
||||
0 0xb6179293816a9bd1889393b88c34d466d43ffc96771ecf0fe4ab7233446236fd 0x65b1acf754fa586c454495a479023b2d901b202044813a652ba664c5245acb2f 0xb8c26e86f38e22356d2d16c875d38289b6905021 0x0b97a1ed7e0d454011bcd52be2c016519ece9db2df56800acc626ce39cea9233
|
||||
1 0xcf67b4dd5b9d926004d1abf2fa23ed3f0e914423c231a4ae2dd08e19a3e9e4d5 0x24ee89ce5d32a50a4f890b44839b738feaaa59ac2508f6438b8aeeeb8be61363 0xc6554650ec0e3e48ea68b3bee277c552ae0debd7 0xcf807523ad7785086404c6a753d9aa332c761a36b89644f4caf9c465d348cdc7
|
||||
1 0x374aaca7f94e7e4d62b984b492a06df25968944ca9c250f10169a3628d05b0f9 0x15177b91e2404caf1bc42858b20e38e33bd99371f61814d01b686d6466d015be 0x6d0bce74c9375731d41d59ead889d5637bed4af0 0x97fb69fa87acc3c0b0950c22ff5d2adaa87f4d1d46026018938f266809c69a04
|
||||
0 0xeb8ff1cd76391a8ae07237568c08dac28d4e3bdc29575ad191bb8d335bbe2ed4 0x312ed03ddf43c67bacb693434da730d42b8929faf6c06a4204688f158f45dbea 0x68e3c86ba31081d59373df5f32dd0086939a36ed 0xcbd0757cbe0d6762392fbffcd0291d0c653f0470e3a28f30381c6d42ae594220
|
||||
0 0x2eab5ed09657a381c33b279b1670be03708b1e77ac91370087b426ee9aade920 0x5fc053a70338a0c868f11b2351b26d9be087172a77979fe0533c2053bd1df74c 0x8268d3d9bcd233db97641001e0a5f1c6785c3a1a 0xd4ab95a7d77b2859aaf8b8674608460c8e53732d2beba89d7fe76466292c4980
|
||||
1 0xabfe7fd3bfcef4f049c6a11e0717b22fba93a9bdf375132a3f2d4ecf82c999b4 0x52658fa3ca3d2a527ebf071c78051671545f0d987084b46460fabe57d9367404 0x3eafb74f0fb78383e4e4bcffff6ee4a9fc3f8c73 0x892d21e91838d7d29f4841129cf9a86539e9b2fece80cbde027070be1ded88ae
|
||||
0 0x2b4a7137d0b31a7ead72ed979ae69d1b4841334900194bc381dd5f71b6a2c337 0x4c393d7e881888cc50f195dba68cbc78f2ff55b3ae0a91e195b77f582cac3d2e 0x48a591f904d0266d32d3ae188504e2a7910b703e 0x97ccfaa3728c749711a1eb28fb888860cf38e67711dea979cf8b91cc1d999f35
|
||||
0 0xbd6f6a6af08d750e28f99357f0dfe768de9e8ed1772f9ed1e312980e1a830167 0x17e56aa8e9630383c197d6282404b659c10e2889ee50bf301e12629420484bba 0xd413fb3e1d268eb37eeb38de04734343ecf6c512 0x626eb6781f01e2a71fefb336122ff174e6f079b721bc47dfb6489a1eac87f35c
|
||||
0 0x7e42fb76826c7f00952ef47f200d5f5519fbc4c78e7f8b958f585306379a1a34 0x738cd052fc0152c03dac09f5b117ec6a1c21d92a2d2e636ac12a05536ecc44a9 0x261318280a2593780fc0b49463d2065bc4b9acea 0x2b6a207376c1f17c13d8e4da40ed4b2e60e1e8734125275ba89866a5abefdede
|
||||
1 0xad10c20fbaf33d13bb5fe184a340fb29f3d32a83c375adedc4d5178929472f4d 0x7f1c763ce7e89e090da9ec44153759833dfcbd2990e0beda598f0e041dbbba45 0x0109480dfabae54463568ce807b6818ee156f84a 0x457a1e31e350640cb9d4a8709d91a874fefbe6ed69984c87d72dad406f510ed1
|
||||
0 0x2aeae7d1d3bc76fd6f02f1234e5a4cd5a78f3f9ed2ca6f6664e0c6bd821f55c 0x19250127f033b2cf9783099f65801b3edce8bf6d26b32fbb5e44abba2d37e9e1 0x455ce87ee8207a3f8771cc3df3d80807e098ae9b 0x22f009e48382685fa1ed6ec3287b17fa144bee9c04c13c504101c9eb2cd1a1d7
|
||||
0 0x86d9311b4a2c1bce624d2a88e626614514fe3ba58dd656899f4fe5e6a170b37b 0x6dd4305274e769c830758afe3a56ee4745e4528501d635c48dfb3f80b3398214 0x6b1baa2a2343f50f422e9e7038826e703c584dc3 0xfd6b690eb2fd74672721123d5ae7cafc6cf053626e39f530571c74d0a5d7d666
|
||||
0 0x4f4e9705b7c7fdc08af4869b151154ea8f011ec61297ac1c419a2229985c7501 0x33fe5b95279c277bb2cb42dd9524453a8bf4c3600ccfceee3ba01557022e8514 0x5c7cf7b750b74b91212e97c4edb502b13ef7c603 0x8adebd9c90f7c9f54c9e28b17010732f84ecf9cad9c97d042c229572015cddd2
|
||||
0 0x3a105f1f5e1dcae92a1d5462222aaeabe96d71f02746692d946b2e092cb40292 0x724bea7cf27436bec762f4928cac3c738d0addc9e68a0ea1edb45a2fc7e99bb3 0xff90f956c9a7d52ac21c37fe7a34801849887f19 0x425245f8953a77bd17f6a99e85de70472a58fd712c2cd062661febfe4eef0f6b
|
||||
0 0xeb3165ba04a9df88da13aa967733573a9cdb76836b29e5565f4fdd1c10a555da 0x3387d1afba42b8659a13f020271deb5712b6c3146acf6f06e5fdfacaeafac00b 0xabfed9eaae37dbc55c03dbe890b64e59b965141d 0xc08a357bb6684da5fd835fec9b978f4b0d447492012ddfc5b02177f79362b432
|
||||
1 0x7ee780ccabdde306b172ff8e62ec05bcbc741e4fa8d5057bfc172d18b4121ece 0x3401ab66a0b0531b209239bf6ea6438aa5c0c7621d443c87f4ae50fc867c672b 0xbe7ab77ae4126496e193c97aaf83ab9cda87fc26 0xe557ee4e9aaf6a265f8572722719032b27a3dbf20519e7fd932db9310cf0ff4d
|
||||
0 0x282e2f0d2acbcbb5397705187713d73f3f320afc6e7e12992551ba2b844ba4ba 0x262117d4a997afd5f1e2bb8d2438e091e1f6e9f9e792e424e58bf98a3e438bf7 0x4a58bb7ec2b8064c4a03abc7c52d9d8a6b0116ab 0x4ee60a3d8de3688398227eab55b80b4ad52ee0429be1aaaec1075f07af01f26b
|
||||
0 0x35e88824f5d5e0019afb1dc818b338ef707fd32487126d089743a94e526a72dc 0x1f9a7cbe5ad46a1ba8d14ca47893b890ada28f4f69530b538d7535c9ca450fe1 0xa34df27ba953cdde360364eaa1b011e98a449174 0x3fe021424adf83aa8e582435a962724eaf11e264d463dffbbb1d5a7e96041da1
|
||||
1 0xe5437ebfd6f54a4580506a80e9baf1399546e270c1965daa1b317a3ae119c532 0xf486022026b018521fadf86ddbb73da9556fbce3e41ab6ac4982d23aba34732 0x59d9099ab334d4a3f19a6e125c427912c68fc32b 0xbed8dc0ed9fabdbd5168148daf1218f025a14ace2ffc3e8d8cc24a9a0f6e2643
|
||||
1 0x11378e51ed9404c97fa5c1a6d241a55c8cfb09202abd30380abeb8f7fd7c8f07 0x72867b97b9ce0562f5c6b0ee3a844e042fab36a56e36c35e040ff29122355b1f 0x4559ca770e7f95fce15bc54c8d09abdd3b5c660c 0x2224f14bcbc55c2a2de9a1c5a4daecb269745286056d28e61c10e5a745cc94f0
|
||||
0 0xacb3fa89cdea2bceef0f27eb974a4be19b33bce137d9e5b5efcc98ef67661726 0x515491ffd2a473f6d3323a318818f2c9df9cd553032922bfe9227daa2e303768 0xa838b09ae1b2223298d1dc43dce715d06aacd47f 0x7a345cb9dae9806b45d6b3067bae813643a5d455f5c20f2e475d6898e3f804fc
|
||||
0 0x35fab5e947d0fffab73351208b12ad003cb62172763113dd181016ab8297cbd8 0x3c6a548de3e59210c32f3d896fb149f18a7d6ca27a3d101a087e9ece3536d0a6 0x971e954dfc651a4b1743b7132fde87f6dcbe502e 0xa1c0b30b92991df606a0f37303ed0ecfbd3c23239cca4146e0aab00d907476c3
|
||||
0 0xbeb835e9af305824af71fef83f68da275750bda01bc9247f3f1ae946a35b0ed9 0x4f075ca8be453f38b035958699dac32d8370de3adb284a5d743253a6c8f1116a 0xf6926d15fc0ee0113ac4840e7d881d92cf193a7d 0xc5b5a0064d6b4e78407e1087a55d81456d914dd106d8bfb4d5d5791e30181a04
|
||||
1 0x257ca4a4fb774fa12d04ce2cbe4f7c2560a5d93bbd6b0dfae377907bb91d0b5a 0x541f5c5d044a15390ee23b9f4ae66810b38c3e7678f09ea8736709b4a05328b3 0x17be3026e13c693e72ba8cceb3adb589ed36f14e 0x612648064356c01dcc3dbcc6f8e8be1d80b1206ba4341003f2d122b0d673479a
|
||||
0 0x3bd7e74261648e61873edca54585ffc1b7dfc0ed11217bc032e3f5159bfb4817 0x79dd87b940b8552f48849cfa433223943faafe7aba5af8f778c645cace8fe409 0x5425324987996df91143b257c4e54a129fd6e85b 0xc533049e9303ccc8dd3b7e38c45db85ad01dfecc3784a1e1b59b54bd8c3c701a
|
||||
1 0x98c4a283642a6840580b138e65fdba451c87f9bd925329e83744263fd7be5048 0x69410c8d7f022f129f862f029083194c720a955b18970b5cd1a8a83ce172dff6 0x158d9cefd58c505021c54528feeb14ef73c9abff 0x15669ae7e934f1144b36117c84b02db899cffa206710ba72614820121fac67a9
|
||||
0 0xfae698f64c9b17dc1ea1c28055c28789fd5857c8dce25e46502e68694aae6c85 0x635303afde839cd5a566b6493a0d068f4796e57c238c35db7bfc64a9d950ebe4 0xfe52a5d0a116efce195baba279758964172e83ed 0x2526f94f656aea49757e6d11eca88a0f102752eebf43da5988b619959f9fde8e
|
||||
1 0x4982c820b96c2a6fb89724db1df3a0acfae4fd7bd5cfca1d88e40d77f6c5ae9e 0x4e4481b9cd42bb55fd00bebe0b6b90ad468cc02c29ed0ca1a84fe8738e2067fd 0x8d1f185fbf60bcacaf783d8f6436e117d1493658 0x3a14ca8d74432637ec0e4e5f24d0c61e54a82746fd12f146ebd9c7507ec08fef
|
||||
1 0xbf64b639128b416fbd70c247b7a8e33183f7cf186a1dcef142ae0c288d8a1e5a 0x64f71c1dd604e64c6881e8fb3783cab7b9c8f80db9307337b26429cc19096060 0xeb280aacafb6dc0b0f811f3e2c1291ddfaaff76e 0x93ffd8a9781f73bbf3d9849bf05b40571456d01e47fdc015a70ec6d0a53d8b7f
|
||||
1 0x7a0879264b7b0aaba53f632acd1c3dde1f03eab3b4adaf2086afbd4f1a26fdb9 0x4d2d10cfe5fd159c64bfdb72b9c39d576fe71ec7d1020741066d853138c896df 0xdec977d8d5f2c79018fc185ba5341f8cba15f0d6 0x97f1fe90d4298fd74c44458f70938a990ad00befce1fed9c9fde7334f8f2e59c
|
||||
0 0x3dd1e43bb8c1f5c634ab3b4c0c09da6fac71fc65ceebdcf825779ba9fa96dad7 0xe09348612309ac2f310bc0cd0d84f8fdbf67b3cedb93608792259257fe1af98 0xfeed5cf7d996ab0cacb4b0baf2450f6c51b1efde 0x5564e87cdfbd1d4d91051523f79d029604462b3c0a326c99ae2cf1920d3969be
|
||||
1 0xdf54d1d5e32037affe7401bebe5d24aec562c37b13bba5feaab5b77826c27c38 0x528086fb0042ec2e80aec346fa0b6f08a879c962208e6dd227303ae3c9abaafc 0x927940b4fe41d9fe519f9580a29a351e57203dc7 0xfec469c2a340cc83511598aceb236cb647bd3a47440ee7e8bd8d002ce3b3f6b8
|
||||
1 0x5077e7de2d1fd106ade42889ed4bfe3495da0768ce7db5ef58d0211a9458a646 0xaa9b688acd7b6ab5b4b1c089045ce03e22490cd2254278a38f61618bbae820d 0xfe512fa3651ff2289172b14fded9d6975ad9d96e 0xadd8c860fbb1dcb130d9398500809d625601123c8bdf0f9f37cdc04f5478eb77
|
||||
1 0xcc606a4b8339906e3aba6ca08c0eb4c0864ba8fe458cf34fc84a95293cba96e 0x22449b2384a73d51d3559f7d93034096727dfb8eb76623e8b10b1850f11414ea 0x120609da75cf68f9aacf4d7e8b627eb9186ba27b 0xbdc844e89608de09ec2b1bce2c8d370e17a394ed6a5148b38b6511fc62c630a2
|
||||
1 0xecf21e5f54d766a37377ddef3c805bad94e1de49486ee0a8267e36dffbd824ac 0xb61dd021b9fc6b7d39ccb56c66e48d1670b264169f9e68dd245ab1c50a62af4 0x6c0fc6ccd718f8d58c3033c13a5afa3adb10456f 0x3eb16ea21e33eb3fe986727dab3ad306cb27feaa6fb42aefbb00e66694154795
|
||||
0 0xc9f7eb02af669bb4b793edbaf3b0e7c8f131d459f94e71d7cf715991e67aa165 0x54b2deb2c57eeaed6c93a8313775cd55ba346ff11d89e91fa12c26f1cc45970e 0x8ec10af9662dc17432717d72ce8b62f4ac24f218 0x7303a277360590a8a25a495153748fcd4db789f9bcf4d73bc303b4ea02b1fee4
|
||||
1 0x226c7a8bebaaecd3304d01ca9df5a9b485fa31fbc44e5c9168d8eeff7cdbcdfc 0x6c170b6fcf4b8d2fdf17569d332f0a8cc52aceb4a7389458ed1606a7948d5e48 0x550d8a88ce3e8154d28233ad9a27945058b8bfe0 0xb04b8fc72c305357f84fb647136b5d85f0e2101d43e3e5bd0eea98519f5d1b9e
|
||||
0 0x8ab2815963748344b4aeaaac472c048145b4f5e1cc86093638300cae9bda1a23 0x83da77b10ffe076980296ed4276b1b81cd58a15f7c573cf83586e6139deb93e 0x945a21e3277e6aabda145da4cbabbf6d592fbce4 0x889dd7f6de4e9c49153c728d0b9d293bf27d69d2ba4463beee85ce75e4732edd
|
||||
1 0xea57e0ee8bc336c781a5ab966976188c16ef0fa5a8f36f858d11add5343c8ee 0x459d6f341d6231c1197f4af6c413c469d97d61425c0a17454ef6bb18db2ff703 0x599357d348a8fa302ced7d6b99d532d95457b543 0xed26da3f378bc480599b79a5fb45f054290abfd91cb463e193988aa78a133a86
|
||||
1 0xf0b422543404ad03d959f34c890d5de1e08e25ca7b7ab02159aebc6a0e83486f 0x4dfa3945f699962e264b18fae4da81bde6ba40091b952199f9f365b0bff00e3f 0x0b0669b9a9f43a2967a428f838191e8c5b84d3bc 0xb673f86a1928f94c69834fb94b522e18a9424022c0ca00d487a5a6af26a56d13
|
||||
0 0x84cba050dfb80413562659c50431c99eb10a345d87e555d092aa0a9bc911a37f 0x3bc0e3ca54d03b706d7ca51bd20590b4c020e1335865e8c945a8558cee5fc7e2 0xb223a6a0b9a4877429f984243c904325aaed59d7 0x40bfd52c11577ec77d87258121035b41aefeaa1da5e7752421d5cb51b640bddf
|
||||
0 0x1cd25acc3cc1aa3a47007f5442118baef3d61f6f30ba4672ad01f3fe2c389081 0x3149344942e7dd5525f676f9032e2d7a3bc3e154c3ca0469ed77df3639385307 0x1b56eb67f280add7cfe89727aca1134274443a39 0x6f534d1d9bf2218cf30617dd1e0293de6f84ef58390e73579f98bf7d5f947d44
|
||||
0 0xc308adac5cd7459f5aba700720966697f3b4ea36a4d9414e11d6e72e24571a6 0x74915e161c7b94d5844c22f3c6a34b3ad49a945180794ce94eb3d3410f45093a 0xab639feb2463513a9ee703cfa33f916bbe7408b7 0x2fffc85af8c55e07853ecc59522361f58eaa7063a10fd0f89205b62ac5cc7df5
|
||||
1 0xb55aeea98ea3bbef39431d8cc8a21309e288db69b9cb87685f82f9a3badf84e 0x740b80528ceb16bb4fa20ea0327fe93eb6a37580bfbd149981a7d00728ff1b36 0x7b28cc1860b9fb47cf7f3f000564bf6deacc953b 0xb51689bd8af058131fee38840f92da123b41d9dbc4b7ff43186a0c9368a4af2b
|
||||
1 0x95d2923d538780533d6db5fb1112fdb426f1d4f16399d2a732d4e140eff611a 0x37987b15715cfd43f44e4395b6f449bce0de642330a9785fb48b4f00c7f4ca7e 0xaa917265aa6903d94a63c1cbc38312e19c11a053 0x78205715444565c45daab6b0c0787ca35b5219e3e0ce0bd4445ca421ce407997
|
||||
0 0x1ed4e98c251bbcceaf2a0e967cc854cfe4d92fe978909891054042779c5461b0 0x556626dcb3e0081e9e7152af9a0da2aaab65fe584c718b2bb1fc8c78c52ec167 0xd59f6c5882f2279097e401938d4c6796c07c7b9e 0x23a88397f97ef6f4000c7a666e7a803c8733ed4d19a2156f0f3c6093321e5fe8
|
||||
1 0x6450a2b80accb717e3a9c219caa01c86177ebb8d4bb84b9529c1335eb74fceb4 0x31966d6ca31437a33710998adb1c1e0c3c0d5cbf7c1524ece60f3c404df70b5f 0xac10ca20fe0977ea9f448e73f6b670d9ffd42ebc 0x674136946178355f8ec71797957e066bd246cba36a6d8f7dd5a0ea56eaa509ce
|
||||
0 0xc10537417a178682e6e351a2eb7f1b971d37f7d9376ee2697c08b0e723079e67 0x4edc34693d7dff3adf57b018e87d929903e1eaea0f2500f52afed8b1e25efea2 0x32b53c2434f03884164f6cdc2dd7508b31f558d0 0xeccfc571b6b9a9a61f78e03bc5292971e96e542c1da09ab9d1a8af0cc4643413
|
||||
0 0xa0b659da4e9bebb27acb959197979e51cb56b63cf4324ef981d5bd01f815c0fb 0xb05f93b0cb57b04aff64501bc3ab1f84a7b25a1b4956b86729bf88964ed934 0xe33f06b81ddb8042a93648b4c13f9cbce8a04c42 0x76e03dd437fef2b02edf4a786afd1a24b06cbe73e7d21f85faeffdd26a4be022
|
||||
1 0x97341ea7db9c1541fdb2193bf0180e7515bf91215f4368ea17cd6e88358266be 0x3a4c5d0715f86221d1aeb7a0bec2a4fc5c0087a0e65c232149f8fdee7ab7bb93 0xcec616376b1da143d9f51738d4ca5ac96a5cecd8 0x12f61e7256fe5514b5139e8b6c24d5d2553555fd0a8fabf660da4305f9cefd76
|
||||
1 0xe0024310417f142d87d3b3443330c0b025aa927b307804f5db6a359cdbbfd478 0x3046a8a2c6ef41026d8dabb1d3804fe8b36338029df6de0b6fee303fb272b211 0x653f99f5cb0723e919b6dd7ca0bf9253b963b06d 0x4d2f79577e6e2cff93ebf1f0607039bebf0a24a88cc4a406dcdfb0f8c0216ef7
|
||||
1 0xfca536181c563f910b2593a75a68759a1cbe9e17add9e5350e5a9043bf2f6177 0x72967ecbebb5062aaae304aecefd33e585769c95785463f7494e0c685b22576b 0x7f9fa6f0fdf344c7176776febddc15d4740f5540 0x5cef49c7e6514cafec83cba5f7293e56fa077a92fa1164c60878e36579e70fe9
|
||||
0 0xd1169af593cf12684f1f1dc5ec0099210cf6eba379622ab27d54db6afeb0cbb2 0x7ea3c6458ce7d2f454d79f7a951872d4baf1236050c142f42448cca41c4dd65 0x50de7b9f1e46f80becbf9ccc1de9730c0fbb17ba 0x6b23f37c6bd54ed9304788fd2617d2775a21dfbd19bfb06177c9068194ab9608
|
||||
1 0x228682fd3644c4f2a2464fd9179b1489602485b84cac0cc434bb13be6f52e750 0x4443018948d31e38c24074103e882cf6628facdfbfc0f1bbbd3b73a7abd1b8c4 0x7a9adb31ec1623e463138dd4ce88df7e791c6f03 0x8a33ea11489e13b66d6fabbb2abfdc6f13273fbb9d95a4d936cc073f3b370473
|
||||
0 0x68b4d46ba8c97044fccabbcedc53bbf362f85dac7d5b6f20087909bf428cd977 0x1e6a77282107ca56253584a6577d937107c13c914fe96b00a49e66ac06a8a878 0xc17e64a2b177468f6d4c9b556b63d110499112f0 0x4782e3d06c981933650a9aeb4034d47557099cd5bb82cff7563837517982171d
|
||||
0 0xadeae9e3caefa9e5220a88447eeb24837f2e8d7d3b9f4b80f105cf8e055ad663 0x3728bf1007a5f106d50004df752b5bc611046734225bffa10d4553530c360b70 0x74dec05e5b894b0efec69cdf6316971802a2f9a1 0x27d57b0a0c8f8a6c784d860f42f7eee5bd459d7ef0e76676bfb41279bc59b4be
|
||||
0 0xe25df026f631d49fec33a23fba5c81e63b14b7255dfda8abd1faf24603460935 0x63e42f2844b2ed1a81738ccaa006b4c74465d360d529cd94df16774d8e38931b 0xe128efc01e4244ff423cfd6cd41e1cc56bd6866f 0x84013bea6d8f9df22d66fe7959145c0629e7367c1b951ce7ac198c2496a69c84
|
||||
0 0xa1784d0efa4a3075f07968e3c0969e064b986336a9c80a95cfbe4e314b13ddec 0x456bcd8e76c21c691658ed4c28158173c1f69b35178c2ed8c2a602b76cdfbede 0x983873529f95132bd1812a3b52c98fb271d2f679 0xac1c41d319b7e8f7aecd0d6130e8c94b9f748333bbfa03036aa69ba4376dfad5
|
||||
0 0x6526f92963f2338eb771ad90fb772d11904d4d4befa98b8c272c6a0abfab081e 0x5aec457455ba8d5aeadf17a688ca73754680ea1f6265c34ddf6718c85ff1e1b0 0x19e34d09c2664d4f0829b1431ea73dac1b2bea93 0xc61a5fc29b169a36e990142a63b49823dd06fabbbbf54a4f52dd25ff443ed640
|
||||
0 0xa026fb5c2ea92a4bced092ece32b06ad2664eca004ba355bfc9686b442131862 0x4dd3e552d74fb306c7e1a8f1c6c4f041d8bbe50fff482389e7959ebd90d67259 0xe697fa7a3f3165caae7458a7e7437fcf80a327b2 0xbc1705ec12a7475ace7e60c33bfa6a64fff88c538675d302ce603dd572f2f14d
|
||||
1 0xf2a1cf25ff00c08820ff9030f63ad96aa1e6d2f89ba9a270953610a7f5e9ac27 0x14c87ef1845068dc7d81686b4bf201676d48fe2359a05785c40bb674873673ab 0x6faea455ea5309259cdfb076caaf779488ddf8de 0xc7f21e2ddb3c14b1b29e355050dab2eddb82e1e8306ed184e277193a53256043
|
||||
0 0x9f97613b227a9f5c66d7c4c44897aef59bf482c72434dac864b48089906f4372 0xb35e44f4d594816de88c2e9c48662134b69892690ae7c844dfa35c73e6bb7a4 0xd6f440196f5060e81a943fa5110508c8430b31f2 0x8d6ad1adfadd98aaf2365632ff00dd9bd479b687f3ff43d16de4e0ce67c90bf2
|
||||
1 0xb34b1d4a28568a653ac8c1695dbb0f8da387fec9700985879beb2a0871eac428 0x7aa14d38f04dfd090c3d688f4847d0f55c2a8785719c63ca12702c3b2c755ed8 0xa6a688f107851131f0e1dce493ebbebfaf99203e 0x874c23e08d44be9a421c4c1131448c5877015d9ba1b76dbd94dabd6809ae0bdb
|
||||
0 0xc513f6281e4c95bca3e17a3ff8eaef844b09b17f7d7fd24a2637e81136aecd1d 0x75810f150e589d54765f58a44263fc7b26cc791bb88e771777aead7823327431 0xf61a659713d29221646b451d2c675f657e33c88c 0x1cf1502b1f131cf5eb85243f25aac443dbb2c8727c9e4d718ca614012da4f14d
|
||||
1 0xacb42d7d82bf160d188dda513982a48c9eb055c84a700bbe425b96ad5e1244e7 0x47cdb51f4a5b8fba9f4cdbd5b4ebcf42438fcd9f2ac996cefca27745140802c6 0x710bda329b2a6224e4b44833de30f38e7f81d564 0xdd0aa6a391179f21e01e5670e46b6664d1e23869a25b68e94bfc203148c8363c
|
||||
0 0x10077281c6b1283c4f8f7b3058aff92c72e5694d9cc53f1767d8977a50c4408c 0x3a02b1f7a35f12e0233f307489037fa3dbcb0aac33f23291a659068a0c15295d 0x22a98f59ded87c4143cf26323b0bd779580ead02 0xbd137a0fc25ca845d0863454dfbf05a78d8f364d821d569f27fc85dd7aaf6ff1
|
||||
1 0x58c87c54c33e54e868d9f6eaab464787256e5d46db9f7fa550ff6daa3f0d25e0 0x7b716d06c4163062b503e32650faaca47ee01f3ec269d62cbd9c9d6cd37f0968 0x9b2c4b8c833278b71789999a3d808b1bc0995fcb 0xfdc089847347bca14dd6a782cc102755a398f711f213d9b50548f1e33a66793f
|
||||
0 0x6c3f7f4cc50cb15e4d5b1454088e860fcf3484bea53979597056238bee8d2eca 0x354f75da6626ded0a649d6749a6e6f570a353504e4cf86878397771993397cc3 0x55fe002aeff02f77364de339a1292923a15844b8 0x9d1e9fda1dbec9bb273fdc32b4b3f93a478861d0e4a4f44f059efaccc4ca3aa2
|
||||
1 0xcbe9c14778b0b3204ba7a286bda1efd94eb79f00141fe807168954aaf2bc8887 0x7ddc9f6c4d6be095ad846a2d1e12196fbd31f144bbbdb672c7471e8a0c64ce3a 0x299c7265388216f6baf12c04bfaae0391c2b1be5 0x6a247771ba60f3e5b1ff3a95ca6ce256a75a7c8b4c2cc74fa02541458730bf39
|
||||
1 0xae6d5ee5e33792e97504b10f2a11e5e0945fe6e540ba0cb530ab49a3b0a6aed7 0xcf7f67a2f5a6a8297b80ad4214879ed6b8b6b0d5003afa6676bc62010aa152e 0x6dfc34609a05bc22319fa4cce1d1e2929548c0d7 0x33460c004ebe3b3c87b07a5228f1a6b163eb970181ad59ff11f8d03b729298e0
|
||||
1 0x77853702c849e381674e839ff6779d66ded67a7cfc325cec9dd8b93d577f1d5 0x7809c39b7692e2fa010a78ba9d521155cb6151b316daf15098684dcd3973cc72 0x4069d8a3de3a72eca86ca5e0a4b94619085e7362 0xb5e51e980067f75f75981e80b4b2d60da80dedf8fbcbadce9ae871ea02ea3c89
|
||||
1 0x7f8c8449f22a576d8868bf3e8bbe14dad8de838b4e45ff320fe4fc794051fe59 0x1ba41d48005b10b79602ee801ede56845ea5b700aef13dc2dfe93812672ef053 0x6887246668a3b87f54deb3b94ba47a6f63f32985 0xaad2bb9310cf9aea16caa84141dfcd3de424b7cbeba41d20a319b3c35342c2b1
|
||||
1048
evm/src/cpu/kernel/tests/ecc/glv_test_data
Normal file
1048
evm/src/cpu/kernel/tests/ecc/glv_test_data
Normal file
File diff suppressed because it is too large
Load Diff
2
evm/src/cpu/kernel/tests/ecc/mod.rs
Normal file
2
evm/src/cpu/kernel/tests/ecc/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
mod curve_ops;
|
||||
mod ecrecover;
|
||||
@ -2,8 +2,7 @@ mod account_code;
|
||||
mod balance;
|
||||
mod bn254;
|
||||
mod core;
|
||||
mod curve_ops;
|
||||
mod ecrecover;
|
||||
mod ecc;
|
||||
mod exp;
|
||||
mod hash;
|
||||
mod mpt;
|
||||
|
||||
@ -24,7 +24,7 @@ fn mpt_hash_empty() -> Result<()> {
|
||||
|
||||
#[test]
|
||||
fn mpt_hash_empty_branch() -> Result<()> {
|
||||
let children = std::array::from_fn(|_| PartialTrie::Empty.into());
|
||||
let children = core::array::from_fn(|_| PartialTrie::Empty.into());
|
||||
let state_trie = PartialTrie::Branch {
|
||||
children,
|
||||
value: vec![],
|
||||
@ -85,7 +85,7 @@ fn mpt_hash_branch_to_leaf() -> Result<()> {
|
||||
value: test_account_2_rlp(),
|
||||
}
|
||||
.into();
|
||||
let mut children = std::array::from_fn(|_| PartialTrie::Empty.into());
|
||||
let mut children = core::array::from_fn(|_| PartialTrie::Empty.into());
|
||||
children[3] = leaf;
|
||||
let state_trie = PartialTrie::Branch {
|
||||
children,
|
||||
|
||||
@ -66,7 +66,7 @@ fn mpt_insert_leaf_leaf_key_extends_insert_key() -> Result<()> {
|
||||
|
||||
#[test]
|
||||
fn mpt_insert_branch_replacing_empty_child() -> Result<()> {
|
||||
let children = std::array::from_fn(|_| PartialTrie::Empty.into());
|
||||
let children = core::array::from_fn(|_| PartialTrie::Empty.into());
|
||||
let state_trie = PartialTrie::Branch {
|
||||
children,
|
||||
value: vec![],
|
||||
@ -81,7 +81,7 @@ fn mpt_insert_branch_replacing_empty_child() -> Result<()> {
|
||||
#[ignore]
|
||||
fn mpt_insert_extension_nonoverlapping_keys() -> Result<()> {
|
||||
// Existing keys are 0xABC, 0xABCDEF; inserted key is 0x12345.
|
||||
let mut children = std::array::from_fn(|_| PartialTrie::Empty.into());
|
||||
let mut children = core::array::from_fn(|_| PartialTrie::Empty.into());
|
||||
children[0xD] = PartialTrie::Leaf {
|
||||
nibbles: 0xEF_u64.into(),
|
||||
value: test_account_1_rlp(),
|
||||
@ -104,7 +104,7 @@ fn mpt_insert_extension_nonoverlapping_keys() -> Result<()> {
|
||||
#[ignore]
|
||||
fn mpt_insert_extension_insert_key_extends_node_key() -> Result<()> {
|
||||
// Existing keys are 0xA, 0xABCD; inserted key is 0xABCDEF.
|
||||
let mut children = std::array::from_fn(|_| PartialTrie::Empty.into());
|
||||
let mut children = core::array::from_fn(|_| PartialTrie::Empty.into());
|
||||
children[0xB] = PartialTrie::Leaf {
|
||||
nibbles: 0xCD_u64.into(),
|
||||
value: test_account_1_rlp(),
|
||||
@ -129,7 +129,7 @@ fn mpt_insert_branch_to_leaf_same_key() -> Result<()> {
|
||||
}
|
||||
.into();
|
||||
|
||||
let mut children = std::array::from_fn(|_| PartialTrie::Empty.into());
|
||||
let mut children = core::array::from_fn(|_| PartialTrie::Empty.into());
|
||||
children[0] = leaf;
|
||||
let state_trie = PartialTrie::Branch {
|
||||
children,
|
||||
|
||||
@ -134,7 +134,7 @@ fn load_all_mpts_hash() -> Result<()> {
|
||||
|
||||
#[test]
|
||||
fn load_all_mpts_empty_branch() -> Result<()> {
|
||||
let children = std::array::from_fn(|_| PartialTrie::Empty.into());
|
||||
let children = core::array::from_fn(|_| PartialTrie::Empty.into());
|
||||
let state_trie = PartialTrie::Branch {
|
||||
children,
|
||||
value: vec![],
|
||||
|
||||
@ -178,15 +178,15 @@ where
|
||||
stark_config: &StarkConfig,
|
||||
) -> RootCircuitData<F, C, D> {
|
||||
let inner_common_data: [_; NUM_TABLES] =
|
||||
std::array::from_fn(|i| &by_table[i].final_circuits()[0].common);
|
||||
core::array::from_fn(|i| &by_table[i].final_circuits()[0].common);
|
||||
|
||||
let mut builder = CircuitBuilder::new(CircuitConfig::standard_recursion_config());
|
||||
let recursive_proofs =
|
||||
std::array::from_fn(|i| builder.add_virtual_proof_with_pis::<C>(inner_common_data[i]));
|
||||
let pis: [_; NUM_TABLES] = std::array::from_fn(|i| {
|
||||
core::array::from_fn(|i| builder.add_virtual_proof_with_pis::<C>(inner_common_data[i]));
|
||||
let pis: [_; NUM_TABLES] = core::array::from_fn(|i| {
|
||||
PublicInputs::from_vec(&recursive_proofs[i].public_inputs, stark_config)
|
||||
});
|
||||
let index_verifier_data = std::array::from_fn(|_i| builder.add_virtual_target());
|
||||
let index_verifier_data = core::array::from_fn(|_i| builder.add_virtual_target());
|
||||
|
||||
let mut challenger = RecursiveChallenger::<F, C::Hasher, D>::new(&mut builder);
|
||||
for pi in &pis {
|
||||
|
||||
@ -35,7 +35,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize> A
|
||||
let num_permutation_batch_sizes = all_stark.permutation_batch_sizes();
|
||||
|
||||
AllProofChallenges {
|
||||
stark_challenges: std::array::from_fn(|i| {
|
||||
stark_challenges: core::array::from_fn(|i| {
|
||||
challenger.compact();
|
||||
self.stark_proofs[i].proof.get_challenges(
|
||||
&mut challenger,
|
||||
|
||||
@ -116,13 +116,9 @@ pub fn permuted_cols<F: PrimeField64>(inputs: &[F], table: &[F]) -> (Vec<F>, Vec
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_range_loop)] // indexing is just more natural here
|
||||
for jj in j..n {
|
||||
unused_table_vals.push(sorted_table[jj]);
|
||||
}
|
||||
for ii in i..n {
|
||||
unused_table_inds.push(ii);
|
||||
}
|
||||
unused_table_vals.extend_from_slice(&sorted_table[j..n]);
|
||||
unused_table_inds.extend(i..n);
|
||||
|
||||
for (ind, val) in unused_table_inds.into_iter().zip_eq(unused_table_vals) {
|
||||
permuted_table[ind] = val;
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use itertools::Itertools;
|
||||
use maybe_rayon::*;
|
||||
use plonky2::field::extension::{Extendable, FieldExtension};
|
||||
use plonky2::field::packed::PackedField;
|
||||
use plonky2::field::polynomial::PolynomialValues;
|
||||
@ -10,6 +9,7 @@ use plonky2::hash::hash_types::RichField;
|
||||
use plonky2::timed;
|
||||
use plonky2::util::timing::TimingTree;
|
||||
use plonky2::util::transpose;
|
||||
use plonky2_maybe_rayon::*;
|
||||
|
||||
use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer};
|
||||
use crate::cross_table_lookup::Column;
|
||||
|
||||
@ -39,10 +39,11 @@ pub(crate) enum Segment {
|
||||
/// instructions; initialised by `kernel/asm/shift.asm::init_shift_table()`.
|
||||
ShiftTable = 16,
|
||||
JumpdestBits = 17,
|
||||
EcdsaTable = 18,
|
||||
}
|
||||
|
||||
impl Segment {
|
||||
pub(crate) const COUNT: usize = 18;
|
||||
pub(crate) const COUNT: usize = 19;
|
||||
|
||||
pub(crate) fn all() -> [Self; Self::COUNT] {
|
||||
[
|
||||
@ -64,6 +65,7 @@ impl Segment {
|
||||
Self::TrieEncodedChildLen,
|
||||
Self::ShiftTable,
|
||||
Self::JumpdestBits,
|
||||
Self::EcdsaTable,
|
||||
]
|
||||
}
|
||||
|
||||
@ -88,6 +90,7 @@ impl Segment {
|
||||
Segment::TrieEncodedChildLen => "SEGMENT_TRIE_ENCODED_CHILD_LEN",
|
||||
Segment::ShiftTable => "SEGMENT_SHIFT_TABLE",
|
||||
Segment::JumpdestBits => "SEGMENT_JUMPDEST_BITS",
|
||||
Segment::EcdsaTable => "SEGMENT_KERNEL_ECDSA_TABLE",
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,6 +115,7 @@ impl Segment {
|
||||
Segment::TrieEncodedChildLen => 6,
|
||||
Segment::ShiftTable => 256,
|
||||
Segment::JumpdestBits => 1,
|
||||
Segment::EcdsaTable => 256,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use itertools::Itertools;
|
||||
use maybe_rayon::*;
|
||||
use plonky2::field::batch_util::batch_multiply_inplace;
|
||||
use plonky2::field::extension::{Extendable, FieldExtension};
|
||||
use plonky2::field::packed::PackedField;
|
||||
@ -17,6 +16,7 @@ use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||
use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, Hasher};
|
||||
use plonky2::plonk::plonk_common::{reduce_with_powers, reduce_with_powers_ext_circuit};
|
||||
use plonky2::util::reducing::{ReducingFactor, ReducingFactorTarget};
|
||||
use plonky2_maybe_rayon::*;
|
||||
|
||||
use crate::config::StarkConfig;
|
||||
use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer};
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
use ethereum_types::{Address, H256, U256};
|
||||
use itertools::Itertools;
|
||||
use maybe_rayon::*;
|
||||
use plonky2::field::extension::{Extendable, FieldExtension};
|
||||
use plonky2::fri::oracle::PolynomialBatch;
|
||||
use plonky2::fri::proof::{FriChallenges, FriChallengesTarget, FriProof, FriProofTarget};
|
||||
@ -13,6 +12,7 @@ use plonky2::hash::merkle_tree::MerkleCap;
|
||||
use plonky2::iop::ext_target::ExtensionTarget;
|
||||
use plonky2::iop::target::Target;
|
||||
use plonky2::plonk::config::GenericConfig;
|
||||
use plonky2_maybe_rayon::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::all_stark::NUM_TABLES;
|
||||
@ -29,7 +29,7 @@ pub struct AllProof<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, co
|
||||
|
||||
impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize> AllProof<F, C, D> {
|
||||
pub fn degree_bits(&self, config: &StarkConfig) -> [usize; NUM_TABLES] {
|
||||
std::array::from_fn(|i| self.stark_proofs[i].proof.recover_degree_bits(config))
|
||||
core::array::from_fn(|i| self.stark_proofs[i].proof.recover_degree_bits(config))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,6 @@ use std::any::type_name;
|
||||
|
||||
use anyhow::{ensure, Result};
|
||||
use itertools::Itertools;
|
||||
use maybe_rayon::*;
|
||||
use once_cell::sync::Lazy;
|
||||
use plonky2::field::extension::Extendable;
|
||||
use plonky2::field::packable::Packable;
|
||||
@ -17,6 +16,7 @@ use plonky2::plonk::config::{GenericConfig, Hasher};
|
||||
use plonky2::timed;
|
||||
use plonky2::util::timing::TimingTree;
|
||||
use plonky2::util::transpose;
|
||||
use plonky2_maybe_rayon::*;
|
||||
use plonky2_util::{log2_ceil, log2_strict};
|
||||
|
||||
use crate::all_stark::{AllStark, Table, NUM_TABLES};
|
||||
|
||||
@ -107,7 +107,7 @@ impl<F: RichField + Extendable<D>, C: GenericConfig<D, F = F>, const D: usize>
|
||||
where
|
||||
[(); C::Hasher::HASH_SIZE]:,
|
||||
{
|
||||
let pis: [_; NUM_TABLES] = std::array::from_fn(|i| {
|
||||
let pis: [_; NUM_TABLES] = core::array::from_fn(|i| {
|
||||
PublicInputs::from_vec(&self.recursive_proofs[i].public_inputs, inner_config)
|
||||
});
|
||||
|
||||
@ -279,7 +279,7 @@ where
|
||||
num_permutation_zs,
|
||||
);
|
||||
|
||||
let init_challenger_state_target = std::array::from_fn(|_| builder.add_virtual_public_input());
|
||||
let init_challenger_state_target = core::array::from_fn(|_| builder.add_virtual_public_input());
|
||||
let mut challenger =
|
||||
RecursiveChallenger::<F, C::Hasher, D>::from_state(init_challenger_state_target);
|
||||
let challenges = proof_target.get_challenges::<F, C>(
|
||||
|
||||
@ -254,6 +254,7 @@ fn try_perform_instruction<F: Field>(state: &mut GenerationState<F>) -> Result<(
|
||||
|
||||
fn log_kernel_instruction<F: Field>(state: &mut GenerationState<F>, op: Operation) {
|
||||
let pc = state.registers.program_counter;
|
||||
// TODO: This is affecting performance...
|
||||
let is_interesting_offset = KERNEL
|
||||
.offset_label(pc)
|
||||
.filter(|label| !label.starts_with("halt_pc"))
|
||||
|
||||
@ -149,7 +149,7 @@ pub(crate) fn stack_pop_with_log_and_fill<const N: usize, F: Field>(
|
||||
return Err(ProgramError::StackUnderflow);
|
||||
}
|
||||
|
||||
let result = std::array::from_fn(|i| {
|
||||
let result = core::array::from_fn(|i| {
|
||||
let address = MemoryAddress::new(
|
||||
state.registers.context,
|
||||
Segment::Stack,
|
||||
|
||||
@ -56,7 +56,7 @@ fn test_basic_smart_contract() -> anyhow::Result<()> {
|
||||
};
|
||||
|
||||
let state_trie_before = {
|
||||
let mut children = std::array::from_fn(|_| PartialTrie::Empty.into());
|
||||
let mut children = core::array::from_fn(|_| PartialTrie::Empty.into());
|
||||
children[sender_nibbles.get_nibble(0) as usize] = PartialTrie::Leaf {
|
||||
nibbles: sender_nibbles.truncate_n_nibbles_front(1),
|
||||
value: rlp::encode(&sender_account_before).to_vec(),
|
||||
@ -110,7 +110,7 @@ fn test_basic_smart_contract() -> anyhow::Result<()> {
|
||||
..to_account_before
|
||||
};
|
||||
|
||||
let mut children = std::array::from_fn(|_| PartialTrie::Empty.into());
|
||||
let mut children = core::array::from_fn(|_| PartialTrie::Empty.into());
|
||||
children[sender_nibbles.get_nibble(0) as usize] = PartialTrie::Leaf {
|
||||
nibbles: sender_nibbles.truncate_n_nibbles_front(1),
|
||||
value: rlp::encode(&sender_account_after).to_vec(),
|
||||
|
||||
@ -83,7 +83,7 @@ fn test_simple_transfer() -> anyhow::Result<()> {
|
||||
..AccountRlp::default()
|
||||
};
|
||||
|
||||
let mut children = std::array::from_fn(|_| PartialTrie::Empty.into());
|
||||
let mut children = core::array::from_fn(|_| PartialTrie::Empty.into());
|
||||
children[sender_nibbles.get_nibble(0) as usize] = PartialTrie::Leaf {
|
||||
nibbles: sender_nibbles.truncate_n_nibbles_front(1),
|
||||
value: rlp::encode(&sender_account_after).to_vec(),
|
||||
|
||||
@ -2,13 +2,15 @@
|
||||
name = "plonky2_field"
|
||||
description = "Finite field arithmetic"
|
||||
version = "0.1.0"
|
||||
license = "MIT OR Apache-2.0"
|
||||
authors = ["Daniel Lubarov <daniel@lubarov.com>", "William Borgeaud <williamborgeaud@gmail.com>", "Jacqueline Nabaglo <j@nab.gl>", "Hamish Ivey-Law <hamish@ivey-law.name>"]
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow = { version = "1.0.40", default-features = false }
|
||||
itertools = { version = "0.10.0", default-features = false, features = ["use_alloc"] }
|
||||
num = { version = "0.4", default-features = false, features = ["alloc", "rand"] }
|
||||
plonky2_util = { path = "../util", default-features = false }
|
||||
plonky2_util = { version = "0.1.0", default-features = false }
|
||||
rand = { version = "0.8.5", default-features = false, features = ["getrandom"] }
|
||||
serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] }
|
||||
static_assertions = { version = "1.1.0", default-features = false }
|
||||
|
||||
@ -6,8 +6,8 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow = { version = "1.0.40", default-features = false }
|
||||
plonky2 = { path = "../plonky2", default-features = false }
|
||||
plonky2 = { version = "0.1.1", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
plonky2 = { path = "../plonky2" }
|
||||
plonky2 = { version = "0.1.1" }
|
||||
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
[package]
|
||||
name = "maybe_rayon"
|
||||
name = "plonky2_maybe_rayon"
|
||||
description = "Feature-gated wrapper around rayon"
|
||||
license = "MIT OR Apache-2.0"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
[package]
|
||||
name = "plonky2"
|
||||
description = "Recursive SNARKs based on PLONK and FRI"
|
||||
version = "0.1.0"
|
||||
authors = ["Polygon Zero <daniel@mirprotocol.org>"]
|
||||
version = "0.1.1"
|
||||
license = "MIT OR Apache-2.0"
|
||||
authors = ["Daniel Lubarov <daniel@lubarov.com>", "William Borgeaud <williamborgeaud@gmail.com>", "Nicholas Ward <npward@berkeley.edu>"]
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/mir-protocol/plonky2"
|
||||
keywords = ["cryptography", "SNARK", "PLONK", "FRI"]
|
||||
categories = ["cryptography"]
|
||||
edition = "2021"
|
||||
default-run = "generate_constants"
|
||||
|
||||
[features]
|
||||
default = ["gate_testing", "parallel", "rand_chacha", "std", "timing"]
|
||||
gate_testing = []
|
||||
parallel = ["hashbrown/rayon", "maybe_rayon/parallel"]
|
||||
parallel = ["hashbrown/rayon", "plonky2_maybe_rayon/parallel"]
|
||||
std = ["anyhow/std", "rand/std"]
|
||||
timing = ["std"]
|
||||
|
||||
@ -24,10 +24,10 @@ hashbrown = { version = "0.12.3", default-features = false, features = ["ahash",
|
||||
itertools = { version = "0.10.0", default-features = false }
|
||||
keccak-hash = { version = "0.8.0", default-features = false }
|
||||
log = { version = "0.4.14", default-features = false }
|
||||
maybe_rayon = { path = "../maybe_rayon", default-features = false }
|
||||
plonky2_maybe_rayon = { version = "0.1.0", default-features = false }
|
||||
num = { version = "0.4", default-features = false, features = ["rand"] }
|
||||
plonky2_field = { path = "../field", default-features = false }
|
||||
plonky2_util = { path = "../util", default-features = false }
|
||||
plonky2_field = { version = "0.1.0", default-features = false }
|
||||
plonky2_util = { version = "0.1.0", default-features = false }
|
||||
rand = { version = "0.8.4", default-features = false }
|
||||
rand_chacha = { version = "0.3.1", optional = true, default-features = false }
|
||||
serde = { version = "1.0", default-features = false, features = ["derive"] }
|
||||
@ -38,7 +38,6 @@ unroll = { version = "0.1.5", default-features = false }
|
||||
criterion = { version = "0.4.0", default-features = false }
|
||||
env_logger = { version = "0.9.0", default-features = false }
|
||||
num_cpus = { version = "1.14.0", default-features = false }
|
||||
plonky2 = { path = "." }
|
||||
rand = { version = "0.8.4", default-features = false, features = ["getrandom"] }
|
||||
rand_chacha = { version = "0.3.1", default-features = false }
|
||||
serde_cbor = { version = "0.11.2" }
|
||||
|
||||
@ -9,7 +9,6 @@ use core::str::FromStr;
|
||||
|
||||
use anyhow::{anyhow, Context as _, Result};
|
||||
use log::{info, Level, LevelFilter};
|
||||
use maybe_rayon::rayon;
|
||||
use plonky2::gates::noop::NoopGate;
|
||||
use plonky2::hash::hash_types::RichField;
|
||||
use plonky2::iop::witness::{PartialWitness, WitnessWrite};
|
||||
@ -20,6 +19,7 @@ use plonky2::plonk::proof::{CompressedProofWithPublicInputs, ProofWithPublicInpu
|
||||
use plonky2::plonk::prover::prove;
|
||||
use plonky2::util::timing::TimingTree;
|
||||
use plonky2_field::extension::Extendable;
|
||||
use plonky2_maybe_rayon::rayon;
|
||||
use rand::rngs::OsRng;
|
||||
use rand::{RngCore, SeedableRng};
|
||||
use rand_chacha::ChaCha8Rng;
|
||||
|
||||
@ -2,8 +2,8 @@ use alloc::format;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use itertools::Itertools;
|
||||
use maybe_rayon::*;
|
||||
use plonky2_field::types::Field;
|
||||
use plonky2_maybe_rayon::*;
|
||||
|
||||
use crate::field::extension::Extendable;
|
||||
use crate::field::fft::FftRootTable;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use maybe_rayon::*;
|
||||
use plonky2_maybe_rayon::*;
|
||||
|
||||
use crate::field::extension::{flatten, unflatten, Extendable};
|
||||
use crate::field::polynomial::{PolynomialCoeffs, PolynomialValues};
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
use alloc::vec;
|
||||
|
||||
use plonky2_field::extension::Extendable;
|
||||
|
||||
use crate::gates::coset_interpolation::CosetInterpolationGate;
|
||||
|
||||
@ -57,7 +57,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
access_index: Target,
|
||||
v: Vec<HashOutTarget>,
|
||||
) -> HashOutTarget {
|
||||
let selected = std::array::from_fn(|i| {
|
||||
let selected = core::array::from_fn(|i| {
|
||||
self.random_access(
|
||||
access_index,
|
||||
v.iter().map(|hash| hash.elements[i]).collect(),
|
||||
|
||||
@ -2,7 +2,7 @@ use alloc::vec::Vec;
|
||||
use core::mem::MaybeUninit;
|
||||
use core::slice;
|
||||
|
||||
use maybe_rayon::*;
|
||||
use plonky2_maybe_rayon::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::hash::hash_types::RichField;
|
||||
@ -84,7 +84,7 @@ fn fill_subtree<F: RichField, H: Hasher<F>>(
|
||||
// Split `leaves` between both children.
|
||||
let (left_leaves, right_leaves) = leaves.split_at(leaves.len() / 2);
|
||||
|
||||
let (left_digest, right_digest) = maybe_rayon::join(
|
||||
let (left_digest, right_digest) = plonky2_maybe_rayon::join(
|
||||
|| fill_subtree::<F, H>(left_digests_buf, left_leaves),
|
||||
|| fill_subtree::<F, H>(right_digests_buf, right_leaves),
|
||||
);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use maybe_rayon::*;
|
||||
use plonky2_maybe_rayon::*;
|
||||
|
||||
use crate::field::polynomial::PolynomialValues;
|
||||
use crate::field::types::Field;
|
||||
|
||||
@ -2,7 +2,7 @@ use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use anyhow::ensure;
|
||||
use maybe_rayon::*;
|
||||
use plonky2_maybe_rayon::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::field::extension::Extendable;
|
||||
|
||||
@ -3,7 +3,7 @@ use alloc::{format, vec};
|
||||
use core::mem::swap;
|
||||
|
||||
use anyhow::{ensure, Result};
|
||||
use maybe_rayon::*;
|
||||
use plonky2_maybe_rayon::*;
|
||||
|
||||
use crate::field::extension::Extendable;
|
||||
use crate::field::polynomial::{PolynomialCoeffs, PolynomialValues};
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use plonky2_field::extension::Extendable;
|
||||
|
||||
@ -804,12 +804,14 @@ impl Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Remaining for Buffer {
|
||||
fn remaining(&self) -> usize {
|
||||
self.bytes.len() - self.pos
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Read for Buffer {
|
||||
#[inline]
|
||||
fn read_exact(&mut self, bytes: &mut [u8]) -> IoResult<()> {
|
||||
|
||||
@ -2,11 +2,17 @@
|
||||
name = "starky"
|
||||
description = "Implementation of STARKs"
|
||||
version = "0.1.0"
|
||||
license = "MIT OR Apache-2.0"
|
||||
authors = ["Daniel Lubarov <daniel@lubarov.com>", "William Borgeaud <williamborgeaud@gmail.com>"]
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/mir-protocol/plonky2"
|
||||
keywords = ["cryptography", "STARK", "FRI"]
|
||||
categories = ["cryptography"]
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
default = ["parallel", "std", "timing"]
|
||||
parallel = ["plonky2/parallel", "maybe_rayon/parallel"]
|
||||
parallel = ["plonky2/parallel", "plonky2_maybe_rayon/parallel"]
|
||||
std = ["anyhow/std", "plonky2/std"]
|
||||
timing = ["plonky2/timing"]
|
||||
|
||||
@ -14,8 +20,8 @@ timing = ["plonky2/timing"]
|
||||
anyhow = { version = "1.0.40", default-features = false }
|
||||
itertools = { version = "0.10.0", default-features = false }
|
||||
log = { version = "0.4.14", default-features = false }
|
||||
maybe_rayon = { path = "../maybe_rayon", default-features = false }
|
||||
plonky2 = { path = "../plonky2", default-features = false }
|
||||
plonky2_maybe_rayon = { version = "0.1.0", default-features = false }
|
||||
plonky2 = { version = "0.1.1", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = { version = "0.9.0", default-features = false }
|
||||
|
||||
@ -4,7 +4,6 @@ use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use itertools::Itertools;
|
||||
use maybe_rayon::*;
|
||||
use plonky2::field::batch_util::batch_multiply_inplace;
|
||||
use plonky2::field::extension::{Extendable, FieldExtension};
|
||||
use plonky2::field::packed::PackedField;
|
||||
@ -17,6 +16,7 @@ use plonky2::iop::target::Target;
|
||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||
use plonky2::plonk::config::{AlgebraicHasher, GenericConfig, Hasher};
|
||||
use plonky2::util::reducing::{ReducingFactor, ReducingFactorTarget};
|
||||
use plonky2_maybe_rayon::*;
|
||||
|
||||
use crate::config::StarkConfig;
|
||||
use crate::constraint_consumer::{ConstraintConsumer, RecursiveConstraintConsumer};
|
||||
|
||||
@ -2,7 +2,6 @@ use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use itertools::Itertools;
|
||||
use maybe_rayon::*;
|
||||
use plonky2::field::extension::{Extendable, FieldExtension};
|
||||
use plonky2::fri::oracle::PolynomialBatch;
|
||||
use plonky2::fri::proof::{
|
||||
@ -16,6 +15,7 @@ use plonky2::hash::merkle_tree::MerkleCap;
|
||||
use plonky2::iop::ext_target::ExtensionTarget;
|
||||
use plonky2::iop::target::Target;
|
||||
use plonky2::plonk::config::GenericConfig;
|
||||
use plonky2_maybe_rayon::*;
|
||||
|
||||
use crate::config::StarkConfig;
|
||||
use crate::permutation::PermutationChallengeSet;
|
||||
|
||||
@ -3,7 +3,6 @@ use core::iter::once;
|
||||
|
||||
use anyhow::{ensure, Result};
|
||||
use itertools::Itertools;
|
||||
use maybe_rayon::*;
|
||||
use plonky2::field::extension::Extendable;
|
||||
use plonky2::field::packable::Packable;
|
||||
use plonky2::field::packed::PackedField;
|
||||
@ -17,6 +16,7 @@ use plonky2::plonk::config::{GenericConfig, Hasher};
|
||||
use plonky2::timed;
|
||||
use plonky2::util::timing::TimingTree;
|
||||
use plonky2::util::{log2_ceil, log2_strict, transpose};
|
||||
use plonky2_maybe_rayon::*;
|
||||
|
||||
use crate::config::StarkConfig;
|
||||
use crate::constraint_consumer::ConstraintConsumer;
|
||||
|
||||
@ -8,11 +8,11 @@ edition = "2021"
|
||||
anyhow = "1.0.40"
|
||||
itertools = "0.10.0"
|
||||
log = "0.4.14"
|
||||
plonky2 = { path = "../plonky2" }
|
||||
plonky2_util = { path = "../util" }
|
||||
plonky2 = { version = "0.1.1" }
|
||||
plonky2_util = { version = "0.1.0" }
|
||||
rand = "0.8.4"
|
||||
rand_chacha = "0.3.1"
|
||||
starky = { path = "../starky" }
|
||||
starky = { version = "0.1.0" }
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.4.0"
|
||||
|
||||
@ -1,14 +1,17 @@
|
||||
[package]
|
||||
name = "plonky2_u32"
|
||||
description = "u32 gadget for Plonky2"
|
||||
version = "0.1.0"
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/mir-protocol/plonky2"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow = { version = "1.0.40", default-features = false }
|
||||
itertools = { version = "0.10.0", default-features = false }
|
||||
num = { version = "0.4", default-features = false }
|
||||
plonky2 = { path = "../plonky2", default-features = false }
|
||||
plonky2 = { version = "0.1.1", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
plonky2 = { path = "../plonky2", default-features = false, features = ["gate_testing"] }
|
||||
plonky2 = { version = "0.1.1", default-features = false, features = ["gate_testing"] }
|
||||
rand = { version = "0.8.4", default-features = false, features = ["getrandom"] }
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
name = "plonky2_util"
|
||||
description = "Utilities used by Plonky2"
|
||||
version = "0.1.0"
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
@ -9,7 +9,7 @@ anyhow = "1.0.40"
|
||||
array_tool = "1.0.3"
|
||||
bimap = "0.6.1"
|
||||
itertools = "0.10.0"
|
||||
"plonky2" = { path = "../plonky2" }
|
||||
"plonky2_field" = { path = "../field" }
|
||||
"plonky2_util" = { path = "../util" }
|
||||
"plonky2" = { version = "0.1.0" }
|
||||
"plonky2_field" = { version = "0.1.0" }
|
||||
"plonky2_util" = { version = "0.1.0" }
|
||||
rand = "0.8.4"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user