Skip to content

Commit b2a936c

Browse files
committed
Add benchmarks-based signature verification gas costs
1 parent e9c3603 commit b2a936c

File tree

1 file changed

+21
-9
lines changed

1 file changed

+21
-9
lines changed

packages/vm/src/imports.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Import implementations
22
3+
use std::cmp::max;
34
use std::convert::TryInto;
45

56
use cosmwasm_crypto::{
@@ -27,10 +28,17 @@ use crate::sections::encode_sections;
2728
use crate::serde::to_vec;
2829
use crate::GasInfo;
2930

30-
const GAS_COST_SECP256K1_VERIFY_SIGNATURE: u64 = 100;
31-
const GAS_COST_SECP256K1_RECOVER_PUBKEY_SIGNATURE: u64 = 100;
32-
const GAS_COST_VERIFY_ED25519_SIGNATURE: u64 = 100;
33-
const GAS_COST_BATCH_VERIFY_ED25519_SIGNATURE: u64 = GAS_COST_VERIFY_ED25519_SIGNATURE / 3;
31+
// 1000 Cosmos SDK * 100 CosmWasm factor (~154 us in crypto benchmarks)
32+
const GAS_COST_SECP256K1_VERIFY: u64 = 100000;
33+
34+
// Gas costs relative to secp256k1_verify cost
35+
const GAS_COST_SECP256K1_RECOVER_PUBKEY: u64 = 105195; // 100_000 * 162 us / 154 us
36+
const GAS_COST_ED25519_VERIFY: u64 = 40909; // 100_000 * 63 us / 154 us
37+
38+
// Gas costs relative to ed25519_verify cost
39+
// From https://docs.rs/ed25519-zebra/2.2.0/ed25519_zebra/batch/index.html
40+
const GAS_COST_ED25519_BATCH_VERIFY: u64 = GAS_COST_ED25519_VERIFY / 2;
41+
const GAS_COST_ED25519_BATCH_VERIFY_ONE_PUBKEY: u64 = GAS_COST_ED25519_VERIFY / 4;
3442

3543
/// A kibi (kilo binary)
3644
const KI: usize = 1024;
@@ -296,7 +304,7 @@ fn do_secp256k1_verify<A: BackendApi, S: Storage, Q: Querier>(
296304
let pubkey = read_region(&env.memory(), pubkey_ptr, ECDSA_PUBKEY_MAX_LEN)?;
297305

298306
let result = secp256k1_verify(&hash, &signature, &pubkey);
299-
let gas_info = GasInfo::with_cost(GAS_COST_SECP256K1_VERIFY_SIGNATURE);
307+
let gas_info = GasInfo::with_cost(GAS_COST_SECP256K1_VERIFY);
300308
process_gas_info::<A, S, Q>(env, gas_info)?;
301309
Ok(result.map_or_else(
302310
|err| match err {
@@ -327,7 +335,7 @@ fn do_secp256k1_recover_pubkey<A: BackendApi, S: Storage, Q: Querier>(
327335
};
328336

329337
let result = secp256k1_recover_pubkey(&hash, &signature, recover_param);
330-
let gas_info = GasInfo::with_cost(GAS_COST_SECP256K1_RECOVER_PUBKEY_SIGNATURE);
338+
let gas_info = GasInfo::with_cost(GAS_COST_SECP256K1_RECOVER_PUBKEY);
331339
process_gas_info::<A, S, Q>(env, gas_info)?;
332340
match result {
333341
Ok(pubkey) => {
@@ -358,7 +366,7 @@ fn do_ed25519_verify<A: BackendApi, S: Storage, Q: Querier>(
358366
let pubkey = read_region(&env.memory(), pubkey_ptr, EDDSA_PUBKEY_LEN)?;
359367

360368
let result = ed25519_verify(&message, &signature, &pubkey);
361-
let gas_info = GasInfo::with_cost(GAS_COST_VERIFY_ED25519_SIGNATURE);
369+
let gas_info = GasInfo::with_cost(GAS_COST_ED25519_VERIFY);
362370
process_gas_info::<A, S, Q>(env, gas_info)?;
363371
Ok(result.map_or_else(
364372
|err| match err {
@@ -402,8 +410,12 @@ fn do_ed25519_batch_verify<A: BackendApi, S: Storage, Q: Querier>(
402410
let public_keys = decode_sections(&public_keys);
403411

404412
let result = ed25519_batch_verify(&messages, &signatures, &public_keys);
405-
let gas_info =
406-
GasInfo::with_cost(GAS_COST_BATCH_VERIFY_ED25519_SIGNATURE * signatures.len() as u64);
413+
let gas_cost = if public_keys.len() == 1 {
414+
GAS_COST_ED25519_BATCH_VERIFY_ONE_PUBKEY
415+
} else {
416+
GAS_COST_ED25519_BATCH_VERIFY
417+
} * signatures.len() as u64;
418+
let gas_info = GasInfo::with_cost(max(gas_cost, GAS_COST_ED25519_VERIFY));
407419
process_gas_info::<A, S, Q>(env, gas_info)?;
408420
Ok(result.map_or_else(|err| err.code(), |valid| (!valid).into()))
409421
}

0 commit comments

Comments
 (0)