Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions fastcrypto-zkp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ harness = false
[[bench]]
name = "zklogin"
harness = false
required-features = ["test-utils"]

[[bench]]
name = "poseidon"
Expand All @@ -37,6 +38,7 @@ schemars = "0.8.10"
serde = { version = "1.0.152", features = ["derive"] }
serde_json = "1.0.93"
once_cell = "1.16"
tracing = "0.1"
im = "15"
reqwest = { version = "0.12", default-features = false, features = ["blocking", "json", "rustls-tls"] }
neptune = { version = "13.0.0", default-features = false }
Expand All @@ -63,3 +65,4 @@ proptest = "1.1.0"

[features]
e2e = []
test-utils = []
222 changes: 206 additions & 16 deletions fastcrypto-zkp/benches/zklogin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@ mod zklogin_benches {

use ark_std::rand::rngs::StdRng;
use ark_std::rand::SeedableRng;
use criterion::Criterion;
use criterion::{BatchSize, Criterion};
use fastcrypto::ed25519::Ed25519KeyPair;
use fastcrypto::error::FastCryptoError;
use fastcrypto::rsa::{Base64UrlUnpadded, Encoding};
use fastcrypto::traits::KeyPair;
use fastcrypto_zkp::bn254::utils::gen_address_seed;
use fastcrypto_zkp::bn254::zk_login::clear_cache_for_testing;
use fastcrypto_zkp::bn254::zk_login::ZkLoginInputs;
use fastcrypto_zkp::bn254::zk_login::JWK;
use fastcrypto_zkp::bn254::zk_login::{JwkId, OIDCProvider};
use fastcrypto_zkp::bn254::zk_login_api::ZkLoginEnv;
use fastcrypto_zkp::bn254::zk_login_api::{ZkLoginEnv, CIRCUIT_CONFIG_V1, CIRCUIT_CONFIG_V2};
use im::hashmap::HashMap as ImHashMap;

/// Benchmark the `fastcrypto_zkp::bn254::zk_login_api::verify_zk_login` function and it's main
Expand All @@ -32,7 +33,6 @@ mod zklogin_benches {
// Test values taken from `test_verify_zk_login_google`. See the test for more details on
// the values.
let user_salt = "206703048842351542647799591018316385612";
let max_epoch = 10;
let address_seed = gen_address_seed(
user_salt,
"sub",
Expand All @@ -58,6 +58,7 @@ mod zklogin_benches {
),
content.clone(),
);
let max_epoch = 10;
let modulus = Base64UrlUnpadded::decode_vec(&content.n)
.map_err(|_| {
FastCryptoError::GeneralError("Invalid Base64 encoded jwk modulus".to_string())
Expand All @@ -70,19 +71,47 @@ mod zklogin_benches {
b.iter(|| input_clone.get_proof().as_arkworks().unwrap())
});

// Benchmark the `calculate_all_inputs_hash` function called by `verify_zk_login`.
// Benchmark `calculate_all_inputs_hash` with a WARM modulus-hash cache (all
// iterations hit).
let eph_pubkey_clone = eph_pubkey.clone();
let input_clone = input.clone();
let modulus_clone = modulus.clone();
c.bench_function("verify_zk_login/calculate_all_inputs_hash", move |b| {
c.bench_function("verify_zk_login/calculate_all_inputs_hash/warm", move |b| {
b.iter(|| {
input_clone
.calculate_all_inputs_hash(&eph_pubkey_clone, &modulus_clone, max_epoch)
.calculate_all_inputs_hash(
&eph_pubkey_clone,
&modulus_clone,
max_epoch,
&CIRCUIT_CONFIG_V1,
)
.unwrap()
});
});

// Benchmark `calculate_all_inputs_hash` with a COLD cache (cleared before
// each iteration, so each timed call recomputes the modulus hash).
let eph_pubkey_clone = eph_pubkey.clone();
let input_clone = input.clone();
let modulus_clone = modulus.clone();
c.bench_function("verify_zk_login/calculate_all_inputs_hash/cold", move |b| {
b.iter_batched(
clear_cache_for_testing,
|_| {
input_clone
.calculate_all_inputs_hash(
&eph_pubkey_clone,
&modulus_clone,
max_epoch,
&CIRCUIT_CONFIG_V1,
)
.unwrap()
},
BatchSize::PerIteration,
)
});
let input_hashes = input
.calculate_all_inputs_hash(&eph_pubkey, &modulus, max_epoch)
.calculate_all_inputs_hash(&eph_pubkey, &modulus, max_epoch, &CIRCUIT_CONFIG_V1)
.unwrap();

// Benchmark the `verify_zk_login_proof_with_fixed_vk` function called by `verify_zk_login`.
Expand All @@ -92,32 +121,193 @@ mod zklogin_benches {
move |b| {
b.iter(|| {
fastcrypto_zkp::bn254::zk_login_api::verify_zk_login_proof_with_fixed_vk(
&ZkLoginEnv::Prod,
&ZkLoginEnv::Test,
&proof,
&[input_hashes],
false,
)
})
},
);

// Benchmark the entire `verify_zk_login` function (warm: modulus hash cache hit).
let input_warm = input.clone();
let eph_warm = eph_pubkey.clone();
let map_warm = map.clone();
c.bench_function("verify_zk_login/warm", move |b| {
b.iter(|| {
fastcrypto_zkp::bn254::zk_login_api::verify_zk_login(
&input_warm,
max_epoch,
&eph_warm,
&map_warm,
&ZkLoginEnv::Test,
)
})
});

// Benchmark `verify_zk_login` on a cold cache (first call after a JWK refresh).
c.bench_function("verify_zk_login/cold", move |b| {
b.iter_batched(
clear_cache_for_testing,
|_| {
fastcrypto_zkp::bn254::zk_login_api::verify_zk_login(
&input,
max_epoch,
&eph_pubkey,
&map,
&ZkLoginEnv::Test,
)
},
BatchSize::PerIteration,
)
});
}

/// Benchmark V2 proof verification for 8192-bit RSA keys
fn verify_zk_login_v2(c: &mut Criterion) {
// Test values captured from test_zklogin_v2
let max_epoch = 10;
let address_seed =
"1930628255822123795956154519923524356793387287437090556144422698180443693114";

let input = ZkLoginInputs::from_json(
r#"{"proofPoints":{"a":["4913491815640002925508764814861178584881454035317776104347888483537912573177","17464247119089096977765585378460061328465709176842125201639874369409917083365","1"],"b":[["13623903508208593385147109129252793918112295419570003309520868038720322470557","21609423682403605552756457705069928412495291852654002331866073641632927420027"],["21392198638402084688930318789933313022805249822640479452861513428525783839707","1188996632803951473949030842369314644349566079256879538309939741515182911983"],["1","0"]],"c":["8847019028968200963788057481027139711885570926967685201543612972187276716667","14579483098715294861159755601821797996287919909580326110060065627124968449243","1"]},"issBase64Details":{"value":"wiaXNzIjoiaHR0cHM6Ly9qd3QtdGVzdGVyLm15c3RlbmxhYnMuY29tIiw","indexMod4":2},"headerBase64":"eyJraWQiOiJzdWkta2V5LWlkLTgxOTIiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9","addressSeed":"1930628255822123795956154519923524356793387287437090556144422698180443693114"}"#,
address_seed,
).unwrap();

let kp = Ed25519KeyPair::generate(&mut StdRng::from_seed([0; 32]));
let mut eph_pubkey = vec![0x00];
eph_pubkey.extend(kp.public().as_ref());

let mut map = ImHashMap::new();
let content = JWK {
kty: "RSA".to_string(),
e: "AQAB".to_string(),
n: "lViYJOuLB6EZenCimgyWrwOH_QBEkCZxSIEfcQgP5MrZkRlohbrTAN1YpXGRaqugp9A4mRzCmi9ddXscpRBSsLefdPJJLG8lQZ2qrw6X2-6HD5kDFd6-K7JZS-_GOEfr5xGEDm8_MS_SorbmneKspL0n4MPYWH8qke4OBFCwL6WzGBU9rqDuvhYmafmkvVvOtHIqekBxNrCud7Spv43BHdiBM0V-jUquuNM3oK97i_GVLjGfwrGRpR3tK4nva_ryiHh9Ajs68If7-ZhIoLJ05lRsHJJpqsloiEqlCZwhge9zEMnNkoaIzdQr-xLy0GPnr5W0gikjlSGYiInfx9ITADwK3W33xdOB7npM7lqJY73Njbuw8hBQicU8t0M0gvvWfmh1KDeA5IqffZgue-ka9Jj1nrYmZtd0JimQpPDUiGbLv69gQJZcLVQWf9z6mVC4gNm8VU2OafssnolrvNndC3wIm8AgqzVzn_DIOcMQdhIe8jTF3hu1_6R4Id3KoA5Hb3uI2H86-8RjhSG2wKb3zi44yKSmxEDhzl7i450PQX64JK4ftv5jb9vSw5unpikmVvGlGsuvrqWFuWKBcrcXLgyar8pGvRO8fR9ifDHSj-D2fBiLnhK0-iqsJeU8XnfJhUvKxSjXejwsoQeLqlgq9-PgCDP3dE61fkqGpJ1UZjZ44Q9Vh4YLCPAO6oX8btXSkwreuP5m0UtWgFsc-ynWbt6NYS7JlsMtJNWybM4_auqRdil_cPMwFsUgjocztGLeG304YH-GehmyBJyGKuDIiXL9RfLoZ35jKawrWJb4UqckKWV5kOKeXsXdKtMw96ABFumcnhrzxAsqwshS5a2lT8P7Cdd9g3T1JXI7JM1AnJU9_gPXmJoc3yEFNf-JxEf00URoy2xUusyyxYdTswLJp3NQP4VjrAGwnsp7gHKC-V-mJ21FpQCHsV0JQ-1x-E3du9hkpsjTtGkffetEsV8k9enbkudox7WIlsnPcA8y7aY4lnaBqLLSzaj2GOf4KTN4cRpcPzOmSvgcVVYYQXDjRw45X86P1WJG8UDl6Wkl044tAdQRuIxW8QVzBFWWxeXcoagOBKn1_DV0RKUX9Ud4LLauy81rUNfoAcnolz9nippTBEZA_4OOBvXhdngCYaoZyjAkmYdPhKIkghGhKoVVKiEJ1Ua6nUr3zB9WFlTO9lODeV9h0tgKGtKGu3UBeaRCQSMv9gZK-eGIpcqjsqK_rEf4htdDZUBzfOJ0VtCiFYUUBPiuJNuIf9xQGVDE7qZufK1irvGug8jvWSWzB4pGLP75PnPH7B9axnXrxssaIR90Y3Vr9ih_ptzcfNrwD_wiGHUTy698FHu2fXp51HbSEQ".to_string(),
alg: "RS256".to_string(),
};

map.insert(
JwkId::new(
OIDCProvider::TestIssuerKey8192.get_config().iss,
"sui-key-id-8192".to_string(),
),
content.clone(),
);
let modulus = Base64UrlUnpadded::decode_vec(&content.n)
.map_err(|_| {
FastCryptoError::GeneralError("Invalid Base64 encoded jwk modulus".to_string())
})
.unwrap();

// Benchmark the `as_arkworks` function called by `verify_zk_login`.
let input_clone = input.clone();
c.bench_function("verify_zk_login_v2/as_arkworks", move |b| {
b.iter(|| input_clone.get_proof().as_arkworks().unwrap())
});

// Benchmark `calculate_all_inputs_hash` with a WARM modulus-hash cache.
let eph_pubkey_clone = eph_pubkey.clone();
let input_clone = input.clone();
let modulus_clone = modulus.clone();
c.bench_function(
"verify_zk_login_v2/calculate_all_inputs_hash/warm",
move |b| {
b.iter(|| {
input_clone
.calculate_all_inputs_hash(
&eph_pubkey_clone,
&modulus_clone,
max_epoch,
&CIRCUIT_CONFIG_V2,
)
.unwrap()
});
},
);

// Benchmark `calculate_all_inputs_hash` with a COLD cache (cleared each iteration).
let eph_pubkey_clone = eph_pubkey.clone();
let input_clone = input.clone();
let modulus_clone = modulus.clone();
c.bench_function(
"verify_zk_login_v2/calculate_all_inputs_hash/cold",
move |b| {
b.iter_batched(
clear_cache_for_testing,
|_| {
input_clone
.calculate_all_inputs_hash(
&eph_pubkey_clone,
&modulus_clone,
max_epoch,
&CIRCUIT_CONFIG_V2,
)
.unwrap()
},
BatchSize::PerIteration,
)
},
);
let input_hashes = input
.calculate_all_inputs_hash(&eph_pubkey, &modulus, max_epoch, &CIRCUIT_CONFIG_V2)
.unwrap();

// Benchmark the `verify_zk_login_proof_with_fixed_vk` function called by `verify_zk_login`.
let proof = input.get_proof().as_arkworks().unwrap();
c.bench_function(
"verify_zk_login_v2/verify_zk_login_proof_with_fixed_vk",
move |b| {
b.iter(|| {
fastcrypto_zkp::bn254::zk_login_api::verify_zk_login_proof_with_fixed_vk(
&ZkLoginEnv::Test,
&proof,
&[input_hashes],
true,
)
})
},
);

// Benchmark the entire `verify_zk_login` function.
c.bench_function("verify_zk_login", move |b| {
// Benchmark the entire `verify_zk_login` function (warm: modulus hash cache hit).
let input_warm = input.clone();
let eph_warm = eph_pubkey.clone();
let map_warm = map.clone();
c.bench_function("verify_zk_login_v2/warm", move |b| {
b.iter(|| {
fastcrypto_zkp::bn254::zk_login_api::verify_zk_login(
&input,
10,
&eph_pubkey,
&map,
&ZkLoginEnv::Prod,
&input_warm,
max_epoch,
&eph_warm,
&map_warm,
&ZkLoginEnv::Test,
)
})
});

// Benchmark `verify_zk_login` on a cold cache (first call after a JWK refresh).
c.bench_function("verify_zk_login_v2/cold", move |b| {
b.iter_batched(
clear_cache_for_testing,
|_| {
fastcrypto_zkp::bn254::zk_login_api::verify_zk_login(
&input,
max_epoch,
&eph_pubkey,
&map,
&ZkLoginEnv::Test,
)
},
BatchSize::PerIteration,
)
});
}

criterion_group! {
name = zklogin_benches;
config = Criterion::default();
targets = verify_zk_login,
targets = verify_zk_login, verify_zk_login_v2,
}
}

Expand Down
Loading
Loading