iota_move_natives_latest/crypto/
hash.rs1use std::{collections::VecDeque, ops::Mul};
6
7use fastcrypto::hash::{Blake2b256, HashFunction, Keccak256};
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;
18
19use crate::NativesCostTable;
20
21const BLAKE_2B256_BLOCK_SIZE: u16 = 128;
22const KECCAK_256_BLOCK_SIZE: u16 = 136;
23
24fn hash<H: HashFunction<DIGEST_SIZE>, const DIGEST_SIZE: usize>(
25 context: &mut NativeContext,
26 ty_args: Vec<Type>,
27 mut args: VecDeque<Value>,
28 msg_cost_per_byte: InternalGas,
30 msg_cost_per_block: InternalGas,
32 block_size: u16,
34) -> PartialVMResult<NativeResult> {
35 debug_assert!(ty_args.is_empty());
36 debug_assert!(args.len() == 1);
37
38 let msg = pop_arg!(args, VectorRef);
39 let msg_ref = msg.as_bytes_ref();
40
41 let block_size = block_size as usize;
42
43 native_charge_gas_early_exit!(
45 context,
46 msg_cost_per_byte.mul((msg_ref.len() as u64).into())
47 + msg_cost_per_block
49 .mul((msg_ref.len().div_ceil(block_size) as u64).into())
50 );
51
52 Ok(NativeResult::ok(
53 context.gas_used(),
54 smallvec![Value::vector_u8(
55 H::digest(msg.as_bytes_ref().as_slice()).digest
56 )],
57 ))
58}
59
60#[derive(Clone)]
61pub struct HashKeccak256CostParams {
62 pub hash_keccak256_cost_base: InternalGas,
64 pub hash_keccak256_data_cost_per_byte: InternalGas,
66 pub hash_keccak256_data_cost_per_block: InternalGas,
68}
69
70pub fn keccak256(
82 context: &mut NativeContext,
83 ty_args: Vec<Type>,
84 args: VecDeque<Value>,
85) -> PartialVMResult<NativeResult> {
86 let hash_keccak256_cost_params = &context
88 .extensions()
89 .get::<NativesCostTable>()
90 .hash_keccak256_cost_params
91 .clone();
92 native_charge_gas_early_exit!(context, hash_keccak256_cost_params.hash_keccak256_cost_base);
94
95 hash::<Keccak256, 32>(
96 context,
97 ty_args,
98 args,
99 hash_keccak256_cost_params.hash_keccak256_data_cost_per_byte,
100 hash_keccak256_cost_params.hash_keccak256_data_cost_per_block,
101 KECCAK_256_BLOCK_SIZE,
102 )
103}
104
105#[derive(Clone)]
106pub struct HashBlake2b256CostParams {
107 pub hash_blake2b256_cost_base: InternalGas,
109 pub hash_blake2b256_data_cost_per_byte: InternalGas,
111 pub hash_blake2b256_data_cost_per_block: InternalGas,
113}
114pub fn blake2b256(
126 context: &mut NativeContext,
127 ty_args: Vec<Type>,
128 args: VecDeque<Value>,
129) -> PartialVMResult<NativeResult> {
130 let hash_blake2b256_cost_params = &context
132 .extensions()
133 .get::<NativesCostTable>()
134 .hash_blake2b256_cost_params
135 .clone();
136 native_charge_gas_early_exit!(
138 context,
139 hash_blake2b256_cost_params.hash_blake2b256_cost_base
140 );
141
142 hash::<Blake2b256, 32>(
143 context,
144 ty_args,
145 args,
146 hash_blake2b256_cost_params.hash_blake2b256_data_cost_per_byte,
147 hash_blake2b256_cost_params.hash_blake2b256_data_cost_per_block,
148 BLAKE_2B256_BLOCK_SIZE,
149 )
150}