iota_move_natives_latest/crypto/
bls12381.rs1use std::collections::VecDeque;
6
7use fastcrypto::{
8 bls12381::{min_pk, min_sig},
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 BLS12381_BLOCK_SIZE: usize = 64;
25
26#[derive(Clone)]
27pub struct Bls12381Bls12381MinSigVerifyCostParams {
28 pub bls12381_bls12381_min_sig_verify_cost_base: InternalGas,
30 pub bls12381_bls12381_min_sig_verify_msg_cost_per_byte: InternalGas,
32 pub bls12381_bls12381_min_sig_verify_msg_cost_per_block: InternalGas,
34}
35pub fn bls12381_min_sig_verify(
53 context: &mut NativeContext,
54 ty_args: Vec<Type>,
55 mut args: VecDeque<Value>,
56) -> PartialVMResult<NativeResult> {
57 debug_assert!(ty_args.is_empty());
58 debug_assert!(args.len() == 3);
59
60 let bls12381_bls12381_min_sig_verify_cost_params = &context
62 .extensions()
63 .get::<NativesCostTable>()
64 .bls12381_bls12381_min_sig_verify_cost_params
65 .clone();
66 native_charge_gas_early_exit!(
68 context,
69 bls12381_bls12381_min_sig_verify_cost_params.bls12381_bls12381_min_sig_verify_cost_base
70 );
71
72 let msg = pop_arg!(args, VectorRef);
73 let public_key_bytes = pop_arg!(args, VectorRef);
74 let signature_bytes = pop_arg!(args, VectorRef);
75
76 let msg_ref = msg.as_bytes_ref();
77 let public_key_bytes_ref = public_key_bytes.as_bytes_ref();
78 let signature_bytes_ref = signature_bytes.as_bytes_ref();
79
80 native_charge_gas_early_exit!(
82 context,
83 bls12381_bls12381_min_sig_verify_cost_params
84 .bls12381_bls12381_min_sig_verify_msg_cost_per_byte
85 * (msg_ref.len() as u64).into()
86 + bls12381_bls12381_min_sig_verify_cost_params
87 .bls12381_bls12381_min_sig_verify_msg_cost_per_block
88 * (msg_ref.len().div_ceil(BLS12381_BLOCK_SIZE) as u64).into()
89 );
90
91 let cost = context.gas_used();
92
93 let Ok(signature) =
94 <min_sig::BLS12381Signature as ToFromBytes>::from_bytes(&signature_bytes_ref)
95 else {
96 return Ok(NativeResult::ok(cost, smallvec![Value::bool(false)]));
97 };
98
99 let public_key =
100 match <min_sig::BLS12381PublicKey as ToFromBytes>::from_bytes(&public_key_bytes_ref) {
101 Ok(public_key) => match public_key.validate() {
102 Ok(_) => public_key,
103 Err(_) => return Ok(NativeResult::ok(cost, smallvec![Value::bool(false)])),
104 },
105 Err(_) => return Ok(NativeResult::ok(cost, smallvec![Value::bool(false)])),
106 };
107
108 Ok(NativeResult::ok(
109 cost,
110 smallvec![Value::bool(public_key.verify(&msg_ref, &signature).is_ok())],
111 ))
112}
113
114#[derive(Clone)]
115pub struct Bls12381Bls12381MinPkVerifyCostParams {
116 pub bls12381_bls12381_min_pk_verify_cost_base: InternalGas,
118 pub bls12381_bls12381_min_pk_verify_msg_cost_per_byte: InternalGas,
120 pub bls12381_bls12381_min_pk_verify_msg_cost_per_block: InternalGas,
122}
123pub fn bls12381_min_pk_verify(
141 context: &mut NativeContext,
142 ty_args: Vec<Type>,
143 mut args: VecDeque<Value>,
144) -> PartialVMResult<NativeResult> {
145 debug_assert!(ty_args.is_empty());
146 debug_assert!(args.len() == 3);
147
148 let bls12381_bls12381_min_pk_verify_cost_params = &context
150 .extensions()
151 .get::<NativesCostTable>()
152 .bls12381_bls12381_min_pk_verify_cost_params
153 .clone();
154
155 native_charge_gas_early_exit!(
157 context,
158 bls12381_bls12381_min_pk_verify_cost_params.bls12381_bls12381_min_pk_verify_cost_base
159 );
160
161 let msg = pop_arg!(args, VectorRef);
162 let public_key_bytes = pop_arg!(args, VectorRef);
163 let signature_bytes = pop_arg!(args, VectorRef);
164
165 let msg_ref = msg.as_bytes_ref();
166 let public_key_bytes_ref = public_key_bytes.as_bytes_ref();
167 let signature_bytes_ref = signature_bytes.as_bytes_ref();
168
169 native_charge_gas_early_exit!(
171 context,
172 bls12381_bls12381_min_pk_verify_cost_params
173 .bls12381_bls12381_min_pk_verify_msg_cost_per_byte
174 * (msg_ref.len() as u64).into()
175 + bls12381_bls12381_min_pk_verify_cost_params
176 .bls12381_bls12381_min_pk_verify_msg_cost_per_block
177 * (msg_ref.len().div_ceil(BLS12381_BLOCK_SIZE) as u64).into()
178 );
179
180 let cost = context.gas_used();
181
182 let signature =
183 match <min_pk::BLS12381Signature as ToFromBytes>::from_bytes(&signature_bytes_ref) {
184 Ok(signature) => signature,
185 Err(_) => return Ok(NativeResult::ok(cost, smallvec![Value::bool(false)])),
186 };
187
188 let public_key =
189 match <min_pk::BLS12381PublicKey as ToFromBytes>::from_bytes(&public_key_bytes_ref) {
190 Ok(public_key) => match public_key.validate() {
191 Ok(_) => public_key,
192 Err(_) => return Ok(NativeResult::ok(cost, smallvec![Value::bool(false)])),
193 },
194 Err(_) => return Ok(NativeResult::ok(cost, smallvec![Value::bool(false)])),
195 };
196
197 Ok(NativeResult::ok(
198 cost,
199 smallvec![Value::bool(public_key.verify(&msg_ref, &signature).is_ok())],
200 ))
201}