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