sui_move_natives_latest/crypto/
bls12381.rs1use fastcrypto::{
4 bls12381::{min_pk, min_sig},
5 traits::{ToFromBytes, VerifyingKey},
6};
7use move_binary_format::errors::PartialVMResult;
8use move_core_types::gas_algebra::InternalGas;
9use move_vm_runtime::{native_charge_gas_early_exit, native_functions::NativeContext};
10use move_vm_types::{
11 loaded_data::runtime_types::Type,
12 natives::function::NativeResult,
13 pop_arg,
14 values::{Value, VectorRef},
15};
16use smallvec::smallvec;
17use std::collections::VecDeque;
18
19use crate::{NativesCostTable, get_extension};
20
21const BLS12381_BLOCK_SIZE: usize = 64;
22
23#[derive(Clone)]
24pub struct Bls12381Bls12381MinSigVerifyCostParams {
25 pub bls12381_bls12381_min_sig_verify_cost_base: InternalGas,
27 pub bls12381_bls12381_min_sig_verify_msg_cost_per_byte: InternalGas,
29 pub bls12381_bls12381_min_sig_verify_msg_cost_per_block: InternalGas,
31}
32pub fn bls12381_min_sig_verify(
42 context: &mut NativeContext,
43 ty_args: Vec<Type>,
44 mut args: VecDeque<Value>,
45) -> PartialVMResult<NativeResult> {
46 debug_assert!(ty_args.is_empty());
47 debug_assert!(args.len() == 3);
48
49 let bls12381_bls12381_min_sig_verify_cost_params = get_extension!(context, NativesCostTable)?
51 .bls12381_bls12381_min_sig_verify_cost_params
52 .clone();
53 native_charge_gas_early_exit!(
55 context,
56 bls12381_bls12381_min_sig_verify_cost_params.bls12381_bls12381_min_sig_verify_cost_base
57 );
58
59 let msg = pop_arg!(args, VectorRef);
60 let public_key_bytes = pop_arg!(args, VectorRef);
61 let signature_bytes = pop_arg!(args, VectorRef);
62
63 let msg_ref = msg.as_bytes_ref();
64 let public_key_bytes_ref = public_key_bytes.as_bytes_ref();
65 let signature_bytes_ref = signature_bytes.as_bytes_ref();
66
67 native_charge_gas_early_exit!(
69 context,
70 bls12381_bls12381_min_sig_verify_cost_params
71 .bls12381_bls12381_min_sig_verify_msg_cost_per_byte
72 * (msg_ref.len() as u64).into()
73 + bls12381_bls12381_min_sig_verify_cost_params
74 .bls12381_bls12381_min_sig_verify_msg_cost_per_block
75 * (msg_ref.len().div_ceil(BLS12381_BLOCK_SIZE) as u64).into()
76 );
77
78 let cost = context.gas_used();
79
80 let Ok(signature) =
81 <min_sig::BLS12381Signature as ToFromBytes>::from_bytes(&signature_bytes_ref)
82 else {
83 return Ok(NativeResult::ok(cost, smallvec![Value::bool(false)]));
84 };
85
86 let public_key =
87 match <min_sig::BLS12381PublicKey as ToFromBytes>::from_bytes(&public_key_bytes_ref) {
88 Ok(public_key) => match public_key.validate() {
89 Ok(_) => public_key,
90 Err(_) => return Ok(NativeResult::ok(cost, smallvec![Value::bool(false)])),
91 },
92 Err(_) => 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}
100
101#[derive(Clone)]
102pub struct Bls12381Bls12381MinPkVerifyCostParams {
103 pub bls12381_bls12381_min_pk_verify_cost_base: InternalGas,
105 pub bls12381_bls12381_min_pk_verify_msg_cost_per_byte: InternalGas,
107 pub bls12381_bls12381_min_pk_verify_msg_cost_per_block: InternalGas,
109}
110pub fn bls12381_min_pk_verify(
120 context: &mut NativeContext,
121 ty_args: Vec<Type>,
122 mut args: VecDeque<Value>,
123) -> PartialVMResult<NativeResult> {
124 debug_assert!(ty_args.is_empty());
125 debug_assert!(args.len() == 3);
126
127 let bls12381_bls12381_min_pk_verify_cost_params = get_extension!(context, NativesCostTable)?
129 .bls12381_bls12381_min_pk_verify_cost_params
130 .clone();
131
132 native_charge_gas_early_exit!(
134 context,
135 bls12381_bls12381_min_pk_verify_cost_params.bls12381_bls12381_min_pk_verify_cost_base
136 );
137
138 let msg = pop_arg!(args, VectorRef);
139 let public_key_bytes = pop_arg!(args, VectorRef);
140 let signature_bytes = pop_arg!(args, VectorRef);
141
142 let msg_ref = msg.as_bytes_ref();
143 let public_key_bytes_ref = public_key_bytes.as_bytes_ref();
144 let signature_bytes_ref = signature_bytes.as_bytes_ref();
145
146 native_charge_gas_early_exit!(
148 context,
149 bls12381_bls12381_min_pk_verify_cost_params
150 .bls12381_bls12381_min_pk_verify_msg_cost_per_byte
151 * (msg_ref.len() as u64).into()
152 + bls12381_bls12381_min_pk_verify_cost_params
153 .bls12381_bls12381_min_pk_verify_msg_cost_per_block
154 * (msg_ref.len().div_ceil(BLS12381_BLOCK_SIZE) as u64).into()
155 );
156
157 let cost = context.gas_used();
158
159 let signature =
160 match <min_pk::BLS12381Signature as ToFromBytes>::from_bytes(&signature_bytes_ref) {
161 Ok(signature) => signature,
162 Err(_) => return Ok(NativeResult::ok(cost, smallvec![Value::bool(false)])),
163 };
164
165 let public_key =
166 match <min_pk::BLS12381PublicKey as ToFromBytes>::from_bytes(&public_key_bytes_ref) {
167 Ok(public_key) => match public_key.validate() {
168 Ok(_) => public_key,
169 Err(_) => return Ok(NativeResult::ok(cost, smallvec![Value::bool(false)])),
170 },
171 Err(_) => return Ok(NativeResult::ok(cost, smallvec![Value::bool(false)])),
172 };
173
174 Ok(NativeResult::ok(
175 cost,
176 smallvec![Value::bool(public_key.verify(&msg_ref, &signature).is_ok())],
177 ))
178}