Skip to content

Commit 7a1fb22

Browse files
Adapt fuzz target to use oracle version of ecrecover
1 parent b295c04 commit 7a1fb22

File tree

7 files changed

+198
-80
lines changed

7 files changed

+198
-80
lines changed

tests/fuzzer/Cargo.lock

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 101 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,26 @@
11
#![no_main]
22
#![feature(allocator_api)]
33

4-
use arbitrary::{Arbitrary,Unstructured};
4+
use crate::common::{be_dec_inplace, be_inc_inplace};
5+
use arbitrary::{Arbitrary, Unstructured};
6+
use fuzz_precompiles_forward::precompiles::ecrecover as ecrecover_forward;
7+
use fuzz_precompiles_forward::precompiles::ecrecover_with_oracle;
58
use libfuzzer_sys::fuzz_target;
69
use revm_precompile::secp256k1::ec_recover_run;
7-
use fuzz_precompiles_forward::precompiles::ecrecover as ecrecover_forward;
8-
use fuzz_precompiles_proving::precompiles::ecrecover as ecrecover_proving;
9-
use secp256k1::{ecdsa::RecoverableSignature,Message,Secp256k1,SecretKey};
10-
use crate::common::{be_inc_inplace,be_dec_inplace};
10+
use secp256k1::{ecdsa::RecoverableSignature, Message, Secp256k1, SecretKey};
1111

1212
mod common;
1313

1414
const IN_LEN: usize = 128;
1515

1616
const N_SECP256K1: [u8; 32] = [
17-
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
18-
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
19-
0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,
20-
0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41,
17+
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
18+
0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41,
2119
];
2220

2321
const N_SECP256K1_HALF: [u8; 32] = [
24-
0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
25-
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
26-
0x5D,0x57,0x6E,0x73,0x57,0xA4,0x50,0x1D,
27-
0xDF,0xE9,0x2F,0x46,0x68,0x1B,0x20,0xA0,
22+
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
23+
0x5D, 0x57, 0x6E, 0x73, 0x57, 0xA4, 0x50, 0x1D, 0xDF, 0xE9, 0x2F, 0x46, 0x68, 0x1B, 0x20, 0xA0,
2824
];
2925

3026
#[derive(Arbitrary, Debug, Clone, Copy)]
@@ -36,25 +32,25 @@ enum Case {
3632

3733
#[derive(Arbitrary, Debug, Clone, Copy)]
3834
enum Mutation {
39-
Msg, // Bit flip mutate msg
40-
V, // Bit flip mutate v part of signature
41-
R, // Bit flip mutate r part of signature
42-
S, // Bit flip mutate s part of signature
43-
44-
V_0, // v = 0
45-
V_1, // v = 1
46-
V_29, // v = 29
47-
V_27, // force 27
48-
V_28, // force 28
49-
50-
ZeroR, // r = 0
51-
ZeroS, // s = 0
52-
R_EqN, // r = n
53-
S_EqN, // s = n
54-
R_GeN, // r = n+1
55-
S_GeN, // s = n+1
56-
HighS, // s = n-1
57-
LowS, // s = floor(n/2)
35+
Msg, // Bit flip mutate msg
36+
V, // Bit flip mutate v part of signature
37+
R, // Bit flip mutate r part of signature
38+
S, // Bit flip mutate s part of signature
39+
40+
V_0, // v = 0
41+
V_1, // v = 1
42+
V_29, // v = 29
43+
V_27, // force 27
44+
V_28, // force 28
45+
46+
ZeroR, // r = 0
47+
ZeroS, // s = 0
48+
R_EqN, // r = n
49+
S_EqN, // s = n
50+
R_GeN, // r = n+1
51+
S_GeN, // s = n+1
52+
HighS, // s = n-1
53+
LowS, // s = floor(n/2)
5854
}
5955

6056
#[derive(Arbitrary, Debug, Clone)]
@@ -70,9 +66,8 @@ struct Input {
7066
fn valid_tuple(seed: [u8; 32], msg32: [u8; 32]) -> ([u8; 32], [u8; 32], [u8; 32], [u8; 32]) {
7167
let secp = Secp256k1::signing_only();
7268

73-
let sk = SecretKey::from_slice(&seed).unwrap_or_else(|_| {
74-
SecretKey::from_slice(&[1u8; 32]).expect("non-zero sk")
75-
});
69+
let sk = SecretKey::from_slice(&seed)
70+
.unwrap_or_else(|_| SecretKey::from_slice(&[1u8; 32]).expect("non-zero sk"));
7671

7772
let msg = Message::from_slice(&msg32).expect("prehash");
7873
let recsig: RecoverableSignature = secp.sign_ecdsa_recoverable(&msg, &sk);
@@ -99,7 +94,9 @@ fn build_input(u: &mut Unstructured<'_>, i: &Input) -> Vec<u8> {
9994

10095
if let Some(t) = i.trunc {
10196
let t = t as usize;
102-
if t < v.len() { v.truncate(t); }
97+
if t < v.len() {
98+
v.truncate(t);
99+
}
103100
}
104101
v
105102
}
@@ -117,39 +114,81 @@ fn build_input(u: &mut Unstructured<'_>, i: &Input) -> Vec<u8> {
117114

118115
if let Some(t) = i.trunc {
119116
let t = t as usize;
120-
if t < out.len() { out.truncate(t); }
117+
if t < out.len() {
118+
out.truncate(t);
119+
}
121120
}
122121
out
123122
}
124123
}
125124
}
126125

127-
fn apply_mut(mutation: Mutation, msg: &mut [u8;32], v: &mut [u8;32], r: &mut [u8;32], s: &mut [u8;32], flip_idx: u8) {
128-
let flip = |b: &mut [u8;32], at: u8| {
126+
fn apply_mut(
127+
mutation: Mutation,
128+
msg: &mut [u8; 32],
129+
v: &mut [u8; 32],
130+
r: &mut [u8; 32],
131+
s: &mut [u8; 32],
132+
flip_idx: u8,
133+
) {
134+
let flip = |b: &mut [u8; 32], at: u8| {
129135
let i = (at as usize) & 31;
130136
b[i] ^= 1;
131137
};
132138
match mutation {
133139
Mutation::Msg => flip(msg, flip_idx),
134-
Mutation::V => flip(v, flip_idx),
135-
Mutation::R => flip(r, flip_idx),
136-
Mutation::S => flip(s, flip_idx),
137-
138-
Mutation::V_0 => { *v = [0u8;32]; }
139-
Mutation::V_1 => { *v = [0u8;32]; v[31] = 1; }
140-
Mutation::V_29 => { *v = [0u8;32]; v[31] = 29; }
141-
Mutation::V_27 => { *v = [0u8;32]; v[31] = 27; }
142-
Mutation::V_28 => { *v = [0u8;32]; v[31] = 28; }
143-
144-
Mutation::ZeroR => { *r = [0u8;32]; }
145-
Mutation::ZeroS => { *s = [0u8;32]; }
146-
Mutation::R_EqN => { *r = N_SECP256K1; }
147-
Mutation::S_EqN => { *s = N_SECP256K1; }
148-
Mutation::R_GeN => { *r = N_SECP256K1; be_inc_inplace(r); }
149-
Mutation::S_GeN => { *s = N_SECP256K1; be_inc_inplace(s); }
150-
151-
Mutation::HighS => { *s = N_SECP256K1; be_dec_inplace(s); }
152-
Mutation::LowS => { *s = N_SECP256K1_HALF; },
140+
Mutation::V => flip(v, flip_idx),
141+
Mutation::R => flip(r, flip_idx),
142+
Mutation::S => flip(s, flip_idx),
143+
144+
Mutation::V_0 => {
145+
*v = [0u8; 32];
146+
}
147+
Mutation::V_1 => {
148+
*v = [0u8; 32];
149+
v[31] = 1;
150+
}
151+
Mutation::V_29 => {
152+
*v = [0u8; 32];
153+
v[31] = 29;
154+
}
155+
Mutation::V_27 => {
156+
*v = [0u8; 32];
157+
v[31] = 27;
158+
}
159+
Mutation::V_28 => {
160+
*v = [0u8; 32];
161+
v[31] = 28;
162+
}
163+
164+
Mutation::ZeroR => {
165+
*r = [0u8; 32];
166+
}
167+
Mutation::ZeroS => {
168+
*s = [0u8; 32];
169+
}
170+
Mutation::R_EqN => {
171+
*r = N_SECP256K1;
172+
}
173+
Mutation::S_EqN => {
174+
*s = N_SECP256K1;
175+
}
176+
Mutation::R_GeN => {
177+
*r = N_SECP256K1;
178+
be_inc_inplace(r);
179+
}
180+
Mutation::S_GeN => {
181+
*s = N_SECP256K1;
182+
be_inc_inplace(s);
183+
}
184+
185+
Mutation::HighS => {
186+
*s = N_SECP256K1;
187+
be_dec_inplace(s);
188+
}
189+
Mutation::LowS => {
190+
*s = N_SECP256K1_HALF;
191+
}
153192
}
154193
}
155194

@@ -171,16 +210,16 @@ fn fuzz(data: &[u8]) {
171210
let r1 = ecrecover_forward(in_bytes.as_slice(), &mut out_forward);
172211
let fwd_ok = r1.is_ok();
173212

174-
let r2 = ecrecover_proving(in_bytes.as_slice(), &mut out_proving);
213+
let r2 = ecrecover_with_oracle(in_bytes.as_slice(), &mut out_proving);
175214
let prv_ok = r2.is_ok();
176215

177216
match (reth_ok, fwd_ok, prv_ok) {
178217
(true, true, true) => {
179218
let reth_bytes = r_reth.unwrap().bytes.to_vec();
180219
assert_eq!(out_forward, reth_bytes, "forward <> reth bytes mismatch");
181-
assert_eq!(out_proving, reth_bytes, "proving <> reth bytes mismatch");
220+
assert_eq!(out_proving, reth_bytes, "oracle <> reth bytes mismatch");
182221
}
183-
(false, false, false) => { }
222+
(false, false, false) => {}
184223
_ => {
185224
panic!(
186225
"status mismatch: reth_ok={reth_ok} fwd_ok={fwd_ok} prv_ok={prv_ok}, in_len={}",
@@ -193,4 +232,4 @@ fn fuzz(data: &[u8]) {
193232
fuzz_target!(|data: &[u8]| {
194233
// call fuzzing in a separate function, so we can see its coverage
195234
fuzz(data);
196-
});
235+
});
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
[package]
2+
name = "callable_oracles_forward"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[lib]
7+
path = "../../../../../callable_oracles/src/lib.rs"
8+
9+
[dependencies]
10+
zk_ee = { package = "zk_ee_forward", path = "../zk_ee_forward" }
11+
ruint = { version = "1.12.3", default-features = false, features = ["alloc"] }
12+
crypto = { package = "crypto_forward", path = "../crypto_forward", default-features = false }
13+
oracle_provider = { package = "oracle_provider_forward", path = "../oracle_provider_forward" }
14+
basic_system = { package = "basic_system_forward", path = "../basic_system_forward" }
15+
16+
risc_v_simulator = { git = "https://github.com/matter-labs/zksync-airbender", tag = "v0.4.3", optional = true }
17+
num-bigint = { version = "*", optional = true }
18+
num-traits = { version = "*", optional = true }
19+
20+
alloy-consensus = "1.0.41"
21+
c-kzg = "2.1.5"
22+
23+
[dev-dependencies]
24+
hex = "*"
25+
26+
[features]
27+
default = ["evaluate"]
28+
evaluate = ["risc_v_simulator", "num-bigint", "num-traits"]

tests/fuzzer/fuzz/wrappers/fuzz_precompiles_forward/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ edition = "2021"
66

77
[dependencies]
88
basic_system = { package = "basic_system_forward", path = "../basic_system_forward"}
9-
zk_ee = { package = "zk_ee_forward", path = "../zk_ee_forward" }
9+
zk_ee = { package = "zk_ee_forward", path = "../zk_ee_forward" }
10+
callable_oracles = { package = "callable_oracles_forward", path = "../callable_oracles_forward" }
11+
oracle_provider = { package = "oracle_provider_forward", path = "../oracle_provider_forward" }

tests/fuzzer/fuzz/wrappers/fuzz_precompiles_forward/src/precompiles.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,18 @@ pub fn ecrecover(src: &[u8], dst: &mut Vec<u8>) -> Result<(), SubsystemError<Sec
7272
EcRecoverImpl::execute(&src, dst, &mut resource, &mut DummyOracle, &mut NullLogger, allocator)
7373
}
7474

75+
/// ecrecover using native field operations oracle (for comparing oracle vs non-oracle paths)
76+
pub fn ecrecover_with_oracle(src: &[u8], dst: &mut Vec<u8>) -> Result<(), SubsystemError<Secp256k1ECRecoverErrors>> {
77+
use callable_oracles::field_hints::NativeFieldOpsQuery;
78+
use oracle_provider::{DummyMemorySource, ZkEENonDeterminismSource};
79+
80+
let allocator = std::alloc::Global;
81+
let mut resource = <BaseResources<DecreasingNative> as Resource>::FORMAL_INFINITE;
82+
let mut oracle = ZkEENonDeterminismSource::<DummyMemorySource>::default();
83+
oracle.add_external_processor(NativeFieldOpsQuery::<DummyMemorySource>::default());
84+
EcRecoverImpl::execute(&src, dst, &mut resource, &mut oracle, &mut NullLogger, allocator)
85+
}
86+
7587
pub fn pairing(src: &[u8], dst: &mut Vec<u8>) -> Result<(), SubsystemError<Bn254PairingCheckErrors>> {
7688
let allocator = std::alloc::Global;
7789
let mut resource = <BaseResources<DecreasingNative> as Resource>::FORMAL_INFINITE;

tests/fuzzer/fuzz/wrappers/fuzz_precompiles_proving/src/precompiles.rs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
use basic_system::system_functions::bn254_ecadd::Bn254AddImpl;
2-
use basic_system::system_functions::sha256::Sha256Impl;
3-
use basic_system::system_functions::keccak256::Keccak256Impl;
4-
use basic_system::system_functions::ripemd160::RipeMd160Impl;
52
use basic_system::system_functions::bn254_ecmul::Bn254MulImpl;
6-
use basic_system::system_functions::p256_verify::P256VerifyImpl;
7-
use basic_system::system_functions::ecrecover::EcRecoverImpl;
83
use basic_system::system_functions::bn254_pairing_check::Bn254PairingCheckImpl;
4+
use basic_system::system_functions::ecrecover::EcRecoverImpl;
5+
use basic_system::system_functions::keccak256::Keccak256Impl;
6+
use basic_system::system_functions::p256_verify::P256VerifyImpl;
97
use basic_system::system_functions::point_evaluation::PointEvaluationImpl;
8+
use basic_system::system_functions::ripemd160::RipeMd160Impl;
9+
use basic_system::system_functions::sha256::Sha256Impl;
1010
use zk_ee::reference_implementations::BaseResources;
11-
use zk_ee::system::{SystemFunction,SystemFunctionExt};
12-
use zk_ee::system::Resource;
1311
use zk_ee::reference_implementations::DecreasingNative;
12+
use zk_ee::system::base_system_functions::{
13+
Bn254AddErrors, Bn254MulErrors, Bn254PairingCheckErrors, Keccak256Errors, P256VerifyErrors,
14+
PointEvaluationErrors, RipeMd160Errors, Secp256k1ECRecoverErrors, Sha256Errors,
15+
};
1416
use zk_ee::system::errors::subsystem::SubsystemError;
15-
use zk_ee::system::base_system_functions::{Bn254AddErrors,Sha256Errors,RipeMd160Errors,Keccak256Errors,
16-
Bn254MulErrors,P256VerifyErrors,Secp256k1ECRecoverErrors,Bn254PairingCheckErrors,PointEvaluationErrors};
17+
use zk_ee::system::Resource;
18+
use zk_ee::system::{SystemFunction, SystemFunctionExt};
1719

1820
pub fn ecadd(src: &[u8], dst: &mut Vec<u8>) -> Result<(), SubsystemError<Bn254AddErrors>> {
1921
let allocator = std::alloc::Global;
@@ -51,13 +53,10 @@ pub fn p256_verify(src: &[u8], dst: &mut Vec<u8>) -> Result<(), SubsystemError<P
5153
P256VerifyImpl::execute(&src, dst, &mut resource, allocator)
5254
}
5355

54-
pub fn ecrecover(src: &[u8], dst: &mut Vec<u8>) -> Result<(), SubsystemError<Secp256k1ECRecoverErrors>> {
55-
let allocator = std::alloc::Global;
56-
let mut resource = <BaseResources<DecreasingNative> as Resource>::FORMAL_INFINITE;
57-
EcRecoverImpl::execute(&src, dst, &mut resource, allocator)
58-
}
59-
60-
pub fn pairing(src: &[u8], dst: &mut Vec<u8>) -> Result<(), SubsystemError<Bn254PairingCheckErrors>> {
56+
pub fn pairing(
57+
src: &[u8],
58+
dst: &mut Vec<u8>,
59+
) -> Result<(), SubsystemError<Bn254PairingCheckErrors>> {
6160
let allocator = std::alloc::Global;
6261
let mut resource = <BaseResources<DecreasingNative> as Resource>::FORMAL_INFINITE;
6362
Bn254PairingCheckImpl::execute(&src, dst, &mut resource, allocator)
@@ -67,4 +66,4 @@ pub fn kzg(src: &[u8], dst: &mut Vec<u8>) -> Result<(), SubsystemError<PointEval
6766
let allocator = std::alloc::Global;
6867
let mut resource = <BaseResources<DecreasingNative> as Resource>::FORMAL_INFINITE;
6968
PointEvaluationImpl::execute(&src, dst, &mut resource, allocator)
70-
}
69+
}

0 commit comments

Comments
 (0)