sui_move_natives_v1/crypto/
ed25519.rs1use crate::NativesCostTable;
4use fastcrypto::{
5 ed25519::{Ed25519PublicKey, Ed25519Signature},
6 traits::{ToFromBytes, VerifyingKey},
7};
8use move_binary_format::errors::PartialVMResult;
9use move_core_types::gas_algebra::InternalGas;
10use move_vm_runtime::{native_charge_gas_early_exit, native_functions::NativeContext};
11use move_vm_types::{
12 loaded_data::runtime_types::Type,
13 natives::function::NativeResult,
14 pop_arg,
15 values::{Value, VectorRef},
16};
17use smallvec::smallvec;
18use std::collections::VecDeque;
19
20const ED25519_BLOCK_SIZE: usize = 128;
21
22#[derive(Clone)]
23pub struct Ed25519VerifyCostParams {
24 pub ed25519_ed25519_verify_cost_base: InternalGas,
26 pub ed25519_ed25519_verify_msg_cost_per_byte: InternalGas,
28 pub ed25519_ed25519_verify_msg_cost_per_block: InternalGas,
30}
31pub fn ed25519_verify(
41 context: &mut NativeContext,
42 ty_args: Vec<Type>,
43 mut args: VecDeque<Value>,
44) -> PartialVMResult<NativeResult> {
45 debug_assert!(ty_args.is_empty());
46 debug_assert!(args.len() == 3);
47
48 let ed25519_verify_cost_params = &context
50 .extensions()
51 .get::<NativesCostTable>()
52 .ed25519_verify_cost_params
53 .clone();
54 native_charge_gas_early_exit!(
56 context,
57 ed25519_verify_cost_params.ed25519_ed25519_verify_cost_base
58 );
59
60 let msg = pop_arg!(args, VectorRef);
61 let msg_ref = msg.as_bytes_ref();
62 let public_key_bytes = pop_arg!(args, VectorRef);
63 let public_key_bytes_ref = public_key_bytes.as_bytes_ref();
64 let signature_bytes = pop_arg!(args, VectorRef);
65 let signature_bytes_ref = signature_bytes.as_bytes_ref();
66
67 native_charge_gas_early_exit!(
69 context,
70 ed25519_verify_cost_params.ed25519_ed25519_verify_msg_cost_per_byte
71 * (msg_ref.len() as u64).into()
72 + ed25519_verify_cost_params.ed25519_ed25519_verify_msg_cost_per_block
73 * (msg_ref.len().div_ceil(ED25519_BLOCK_SIZE) as u64).into()
74 );
75 let cost = context.gas_used();
76
77 let Ok(signature) = <Ed25519Signature as ToFromBytes>::from_bytes(&signature_bytes_ref) else {
78 return Ok(NativeResult::ok(cost, smallvec![Value::bool(false)]));
79 };
80
81 let Ok(public_key) = <Ed25519PublicKey as ToFromBytes>::from_bytes(&public_key_bytes_ref)
82 else {
83 return Ok(NativeResult::ok(cost, smallvec![Value::bool(false)]));
84 };
85
86 Ok(NativeResult::ok(
87 cost,
88 smallvec![Value::bool(public_key.verify(&msg_ref, &signature).is_ok())],
89 ))
90}