|
1 | 1 | //! Import implementations |
2 | 2 |
|
| 3 | +use std::cmp::max; |
3 | 4 | use std::convert::TryInto; |
4 | 5 |
|
5 | 6 | use cosmwasm_crypto::{ |
@@ -27,10 +28,17 @@ use crate::sections::encode_sections; |
27 | 28 | use crate::serde::to_vec; |
28 | 29 | use crate::GasInfo; |
29 | 30 |
|
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_DIVISOR: u64 = 2; |
| 41 | +const GAS_COST_ED25519_BATCH_ONE_PUBKEY_DIVISOR: u64 = 4; |
34 | 42 |
|
35 | 43 | /// A kibi (kilo binary) |
36 | 44 | const KI: usize = 1024; |
@@ -296,7 +304,7 @@ fn do_secp256k1_verify<A: BackendApi, S: Storage, Q: Querier>( |
296 | 304 | let pubkey = read_region(&env.memory(), pubkey_ptr, ECDSA_PUBKEY_MAX_LEN)?; |
297 | 305 |
|
298 | 306 | 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); |
300 | 308 | process_gas_info::<A, S, Q>(env, gas_info)?; |
301 | 309 | Ok(result.map_or_else( |
302 | 310 | |err| match err { |
@@ -327,7 +335,7 @@ fn do_secp256k1_recover_pubkey<A: BackendApi, S: Storage, Q: Querier>( |
327 | 335 | }; |
328 | 336 |
|
329 | 337 | 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); |
331 | 339 | process_gas_info::<A, S, Q>(env, gas_info)?; |
332 | 340 | match result { |
333 | 341 | Ok(pubkey) => { |
@@ -358,7 +366,7 @@ fn do_ed25519_verify<A: BackendApi, S: Storage, Q: Querier>( |
358 | 366 | let pubkey = read_region(&env.memory(), pubkey_ptr, EDDSA_PUBKEY_LEN)?; |
359 | 367 |
|
360 | 368 | 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); |
362 | 370 | process_gas_info::<A, S, Q>(env, gas_info)?; |
363 | 371 | Ok(result.map_or_else( |
364 | 372 | |err| match err { |
@@ -402,8 +410,15 @@ fn do_ed25519_batch_verify<A: BackendApi, S: Storage, Q: Querier>( |
402 | 410 | let public_keys = decode_sections(&public_keys); |
403 | 411 |
|
404 | 412 | 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 divisor = if public_keys.len() == 1 { |
| 414 | + GAS_COST_ED25519_BATCH_ONE_PUBKEY_DIVISOR |
| 415 | + } else { |
| 416 | + GAS_COST_ED25519_BATCH_DIVISOR |
| 417 | + }; |
| 418 | + let gas_info = GasInfo::with_cost(max( |
| 419 | + GAS_COST_ED25519_VERIFY, |
| 420 | + GAS_COST_ED25519_VERIFY / divisor * signatures.len() as u64, |
| 421 | + )); |
407 | 422 | process_gas_info::<A, S, Q>(env, gas_info)?; |
408 | 423 | Ok(result.map_or_else(|err| err.code(), |valid| (!valid).into())) |
409 | 424 | } |
|
0 commit comments