Skip to content

Commit 057674c

Browse files
[2.11.1] Implement blake libfunc (#1160)
* implement blake libfunc * doc * rename runtime function * remove blake type and fix runtime blake symbol * fmt * add blake libfuncs' firms to the comments * fmt * post merge fix * post merge fix * add tests * change test * fix secp256_get_point_from_x and secp256_new implementation * fix tests and reduce blake_utils exposure * remove dbg! from test
1 parent 5721eb7 commit 057674c

File tree

10 files changed

+671
-415
lines changed

10 files changed

+671
-415
lines changed

Cargo.lock

Lines changed: 316 additions & 409 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/libfuncs.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ use std::{
4545
};
4646

4747
mod array;
48+
mod blake;
4849
mod r#bool;
4950
mod bounded_int;
5051
mod r#box;
@@ -192,7 +193,9 @@ impl LibfuncBuilder for CoreConcreteLibfunc {
192193
Self::IntRange(selector) => self::int_range::build(
193194
context, registry, entry, location, helper, metadata, selector,
194195
),
195-
Self::Blake(_) => native_panic!("Implement blake libfunc"),
196+
Self::Blake(selector) => self::blake::build(
197+
context, registry, entry, location, helper, metadata, selector,
198+
),
196199
Self::Mem(selector) => self::mem::build(
197200
context, registry, entry, location, helper, metadata, selector,
198201
),

src/libfuncs/blake.rs

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
use cairo_lang_sierra::{
2+
extensions::{
3+
blake::BlakeConcreteLibfunc,
4+
core::{CoreLibfunc, CoreType},
5+
lib_func::SignatureOnlyConcreteLibfunc,
6+
},
7+
program_registry::ProgramRegistry,
8+
};
9+
use melior::{
10+
helpers::{ArithBlockExt, BuiltinBlockExt},
11+
ir::{Block, Location},
12+
Context,
13+
};
14+
15+
use crate::{
16+
error::{panic::ToNativeAssertError, Result},
17+
metadata::{runtime_bindings::RuntimeBindingsMeta, MetadataStorage},
18+
};
19+
20+
use super::LibfuncHelper;
21+
22+
pub fn build<'ctx, 'this>(
23+
context: &'ctx Context,
24+
registry: &ProgramRegistry<CoreType, CoreLibfunc>,
25+
entry: &'this Block<'ctx>,
26+
location: Location<'ctx>,
27+
helper: &LibfuncHelper<'ctx, 'this>,
28+
metadata: &mut MetadataStorage,
29+
selector: &BlakeConcreteLibfunc,
30+
) -> Result<()> {
31+
match selector {
32+
BlakeConcreteLibfunc::Blake2sCompress(info) => build_blake_operation(
33+
context, registry, entry, location, helper, metadata, info, false,
34+
),
35+
BlakeConcreteLibfunc::Blake2sFinalize(info) => build_blake_operation(
36+
context, registry, entry, location, helper, metadata, info, true,
37+
),
38+
}
39+
}
40+
41+
/// Performs a blake2s compression.
42+
///
43+
/// `bytes_count`: total amount of bytes hashed after hashing the message.
44+
/// `finalize`: wether the libfunc call is a finalize or not.
45+
/// ```cairo
46+
/// pub extern fn blake2s_compress(
47+
/// state: Blake2sState, byte_count: u32, msg: Blake2sInput,
48+
/// ) -> Blake2sState nopanic;
49+
/// ```
50+
///
51+
/// Similar to `blake2s_compress`, but it marks the end of the compression
52+
/// ```cairo
53+
/// pub extern fn blake2s_finalize(
54+
/// state: Blake2sState, byte_count: u32, msg: Blake2sInput,
55+
/// ) -> Blake2sState nopanic;
56+
/// ```
57+
#[allow(clippy::too_many_arguments)]
58+
fn build_blake_operation<'ctx, 'this>(
59+
context: &'ctx Context,
60+
_registry: &ProgramRegistry<CoreType, CoreLibfunc>,
61+
entry: &'this Block<'ctx>,
62+
location: Location<'ctx>,
63+
helper: &LibfuncHelper<'ctx, 'this>,
64+
metadata: &mut MetadataStorage,
65+
_info: &SignatureOnlyConcreteLibfunc,
66+
finalize: bool,
67+
) -> Result<()> {
68+
let state_ptr = entry.arg(0)?;
69+
let bytes_count = entry.arg(1)?;
70+
let message = entry.arg(2)?;
71+
let k_finalize = entry.const_int(context, location, finalize as u8, 1)?;
72+
73+
let runtime_bindings = metadata
74+
.get_mut::<RuntimeBindingsMeta>()
75+
.to_native_assert_error("runtime library should be available")?;
76+
77+
runtime_bindings.libfunc_blake_compress(
78+
context,
79+
helper,
80+
entry,
81+
state_ptr,
82+
message,
83+
bytes_count,
84+
k_finalize,
85+
location,
86+
)?;
87+
88+
helper.br(entry, 0, &[state_ptr], location)?;
89+
90+
Ok(())
91+
}
92+
93+
#[cfg(test)]
94+
mod tests {
95+
use crate::{jit_struct, load_cairo, utils::testing::run_program, Value};
96+
97+
// This test is taken from the Blake2s-256 implementeation RFC-7693, Appendix B.
98+
// https://www.rfc-editor.org/rfc/rfc7693#appendix-B.
99+
#[test]
100+
fn test_blake_3_bytes_compress() {
101+
let program = load_cairo!(
102+
use core::blake::{blake2s_compress, blake2s_finalize};
103+
104+
fn run_test() -> [u32; 8] nopanic {
105+
let initial_state: Box<[u32; 8]> = BoxTrait::new([
106+
0x6B08E647, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19,
107+
]);
108+
// This number represents the bytes for "abc" string.
109+
let abc_bytes = 0x00636261;
110+
let msg: Box<[u32; 16]> = BoxTrait::new([abc_bytes, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
111+
112+
blake2s_finalize(initial_state, 3, msg).unbox()
113+
}
114+
);
115+
116+
let result = run_program(&program, "run_test", &[]).return_value;
117+
118+
assert_eq!(
119+
result,
120+
jit_struct!(
121+
Value::Uint32(0x8C5E8C50),
122+
Value::Uint32(0xE2147C32),
123+
Value::Uint32(0xA32BA7E1),
124+
Value::Uint32(0x2F45EB4E),
125+
Value::Uint32(0x208B4537),
126+
Value::Uint32(0x293AD69E),
127+
Value::Uint32(0x4C9B994D),
128+
Value::Uint32(0x82596786),
129+
)
130+
);
131+
}
132+
}

src/metadata/runtime_bindings.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ enum RuntimeBinding {
4545
DictDrop,
4646
DictDup,
4747
GetCostsBuiltin,
48+
BlakeCompress,
4849
DebugPrint,
4950
U252ExtendedEuclideanAlgorithm,
5051
U384ExtendedEuclideanAlgorithm,
@@ -73,6 +74,7 @@ impl RuntimeBinding {
7374
RuntimeBinding::DictDrop => "cairo_native__dict_drop",
7475
RuntimeBinding::DictDup => "cairo_native__dict_dup",
7576
RuntimeBinding::GetCostsBuiltin => "cairo_native__get_costs_builtin",
77+
RuntimeBinding::BlakeCompress => "cairo_native__libfunc__blake_compress",
7678
RuntimeBinding::U252ExtendedEuclideanAlgorithm => {
7779
"cairo_native__u252_extended_euclidean_algorithm"
7880
}
@@ -128,6 +130,9 @@ impl RuntimeBinding {
128130
RuntimeBinding::GetCostsBuiltin => {
129131
crate::runtime::cairo_native__get_costs_builtin as *const ()
130132
}
133+
RuntimeBinding::BlakeCompress => {
134+
crate::runtime::cairo_native__libfunc__blake_compress as *const ()
135+
}
131136
RuntimeBinding::U252ExtendedEuclideanAlgorithm
132137
| RuntimeBinding::U384ExtendedEuclideanAlgorithm => return None,
133138
RuntimeBinding::CircuitArithOperation => return None,
@@ -425,6 +430,37 @@ impl RuntimeBindingsMeta {
425430
))
426431
}
427432

433+
#[allow(clippy::too_many_arguments)]
434+
pub fn libfunc_blake_compress<'c, 'a>(
435+
&mut self,
436+
context: &'c Context,
437+
module: &Module,
438+
block: &'a Block<'c>,
439+
state: Value<'c, 'a>,
440+
message: Value<'c, 'a>,
441+
count_bytes: Value<'c, 'a>,
442+
finalize: Value<'c, 'a>,
443+
location: Location<'c>,
444+
) -> Result<OperationRef<'c, 'a>>
445+
where
446+
'c: 'a,
447+
{
448+
let function = self.build_function(
449+
context,
450+
module,
451+
block,
452+
location,
453+
RuntimeBinding::BlakeCompress,
454+
)?;
455+
456+
Ok(block.append_operation(
457+
OperationBuilder::new("llvm.call", location)
458+
.add_operands(&[function])
459+
.add_operands(&[state, message, count_bytes, finalize])
460+
.build()?,
461+
))
462+
}
463+
428464
/// Register if necessary, then invoke the `ec_point_from_x_nz()` function.
429465
pub fn libfunc_ec_point_from_x_nz<'c, 'a>(
430466
&mut self,
@@ -846,6 +882,7 @@ pub fn setup_runtime(find_symbol_ptr: impl Fn(&str) -> Option<*mut c_void>) {
846882
RuntimeBinding::DictDrop,
847883
RuntimeBinding::DictDup,
848884
RuntimeBinding::GetCostsBuiltin,
885+
RuntimeBinding::BlakeCompress,
849886
RuntimeBinding::DebugPrint,
850887
#[cfg(feature = "with-cheatcode")]
851888
RuntimeBinding::VtableCheatcode,

src/runtime.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![allow(non_snake_case)]
22

3-
use crate::utils::BuiltinCosts;
3+
use crate::utils::{blake_utils, BuiltinCosts};
44
use cairo_lang_sierra_gas::core_libfunc_cost::{
55
DICT_SQUASH_REPEATED_ACCESS_COST, DICT_SQUASH_UNIQUE_KEY_COST,
66
};
@@ -144,6 +144,24 @@ pub unsafe extern "C" fn cairo_native__libfunc__hades_permutation(
144144
*op2 = state[2].to_bytes_le();
145145
}
146146

147+
pub unsafe extern "C" fn cairo_native__libfunc__blake_compress(
148+
state: &mut [u32; 8],
149+
message: &[u32; 16],
150+
count_bytes: u32,
151+
finalize: bool,
152+
) {
153+
let new_state = blake_utils::blake2s_compress(
154+
state,
155+
message,
156+
count_bytes,
157+
0,
158+
if finalize { 0xFFFFFFFF } else { 0 },
159+
0,
160+
);
161+
162+
*state = new_state;
163+
}
164+
147165
/// Felt252 type used in cairo native runtime
148166
#[derive(Debug)]
149167
pub struct FeltDict {

src/types.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -669,7 +669,7 @@ impl TypeBuilder for CoreTypeConcrete {
669669
let type_info = registry.get_type(&info.ty)?;
670670
type_info.is_zst(registry)?
671671
}
672-
CoreTypeConcrete::Blake(_info) => native_panic!("Implement is_zst for Blake type"),
672+
CoreTypeConcrete::Blake(_) => native_panic!("Implement is_zst for Blake type"),
673673
CoreTypeConcrete::QM31(_info) => native_panic!("Implement is_zst for QM31 type"),
674674
})
675675
}
@@ -796,9 +796,6 @@ impl TypeBuilder for CoreTypeConcrete {
796796
// arguments.
797797
Ok(match self {
798798
CoreTypeConcrete::IntRange(_) => false,
799-
CoreTypeConcrete::Blake(_info) => {
800-
native_panic!("Implement is_memory_allocated for Blake type")
801-
}
802799
CoreTypeConcrete::Array(_) => false,
803800
CoreTypeConcrete::Bitwise(_) => false,
804801
CoreTypeConcrete::Box(_) => false,
@@ -861,6 +858,9 @@ impl TypeBuilder for CoreTypeConcrete {
861858
CoreTypeConcrete::Coupon(_) => false,
862859
CoreTypeConcrete::Circuit(_) => false,
863860
CoreTypeConcrete::GasReserve(_) => false,
861+
CoreTypeConcrete::Blake(_) => {
862+
native_panic!("Implement is_memory_allocated for Blake type")
863+
}
864864
CoreTypeConcrete::QM31(_) => native_panic!("Implement is_memory_allocated for QM31"),
865865
})
866866
}

src/utils.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use std::{
3131
};
3232
use thiserror::Error;
3333

34+
pub(crate) mod blake_utils;
3435
pub mod mem_tracing;
3536
mod program_registry_ext;
3637
mod range_ext;

0 commit comments

Comments
 (0)