Skip to content

Commit

Permalink
feat: implement kzg data availability hints (lambdaclass#1887)
Browse files Browse the repository at this point in the history
* feat: kzg data availability hints

Context: port of the Starknet OS to Rust.

We need an implementation of the hints used by the Starknet OS in KZG commitments for data availability. This hint relies on private primitives in cairo-vm and must be implemented in this repository.

* add: PR to CHANGELOG

* fix: remove unnecessary clones

* lint: cargo fmt
  • Loading branch information
whichqua authored Jan 2, 2025
1 parent 404d763 commit 052e7ce
Show file tree
Hide file tree
Showing 10 changed files with 170 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ jobs:
strategy:
fail-fast: false
matrix:
special_features: ["", "extensive_hints", "mod_builtin", "cairo-0-secp-hints"]
special_features: ["", "extensive_hints", "mod_builtin", "cairo-0-secp-hints", "cairo-0-data-availability-hints"]
target: [ test#1, test#2, test#3, test#4, test-no_std#1, test-no_std#2, test-no_std#3, test-no_std#4, test-wasm ]
name: Run tests
runs-on: ubuntu-22.04
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#### Upcoming Changes

* feat: implement `kzg` data availability hints [#1887](https://github.com/lambdaclass/cairo-vm/pull/1887)

#### [2.0.0-rc3] - 2024-12-26

* chore: update cairo-lang dependencies to 2.10.0-rc.0 #[1901](https://github.com/lambdaclass/cairo-vm/pull/1901)
Expand Down
9 changes: 7 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ SECP_CAIRO0_HINTS_DIR=cairo_programs/cairo-0-secp-hints-feature
SECP_CAIRO0_HINTS_FILES:=$(wildcard $(SECP_CAIRO0_HINTS_DIR)/*.cairo)
COMPILED_SECP_CAIRO0_HINTS:=$(patsubst $(SECP_CAIRO0_HINTS_DIR)/%.cairo, $(SECP_CAIRO0_HINTS_DIR)/%.json, $(SECP_CAIRO0_HINTS_FILES))

KZG_DA_CAIRO0_HINTS_DIR=cairo_programs/cairo-0-kzg-da-hints
KZG_DA_CAIRO0_HINTS_FILES:=$(wildcard $(KZG_DA_CAIRO0_HINTS_DIR)/*.cairo)
COMPILED_KZG_DA_CAIRO0_HINTS:=$(patsubst $(KZG_DA_CAIRO0_HINTS_DIR)/%.cairo, $(KZG_DA_CAIRO0_HINTS_DIR)/%.json, $(KZG_DA_CAIRO0_HINTS_FILES))

PRINT_TEST_DIR=cairo_programs/print_feature
PRINT_TEST_FILES:=$(wildcard $(PRINT_TEST_DIR)/*.cairo)
COMPILED_PRINT_TESTS:=$(patsubst $(PRINT_TEST_DIR)/%.cairo, $(PRINT_TEST_DIR)/%.json, $(PRINT_TEST_FILES))
Expand Down Expand Up @@ -243,7 +247,7 @@ run:
check:
cargo check

cairo_test_programs: $(COMPILED_TESTS) $(COMPILED_BAD_TESTS) $(COMPILED_NORETROCOMPAT_TESTS) $(COMPILED_PRINT_TESTS) $(COMPILED_MOD_BUILTIN_TESTS) $(COMPILED_SECP_CAIRO0_HINTS)
cairo_test_programs: $(COMPILED_TESTS) $(COMPILED_BAD_TESTS) $(COMPILED_NORETROCOMPAT_TESTS) $(COMPILED_PRINT_TESTS) $(COMPILED_MOD_BUILTIN_TESTS) $(COMPILED_SECP_CAIRO0_HINTS) $(COMPILED_KZG_DA_CAIRO0_HINTS)
cairo_proof_programs: $(COMPILED_PROOF_TESTS) $(COMPILED_MOD_BUILTIN_PROOF_TESTS)
cairo_bench_programs: $(COMPILED_BENCHES)
cairo_1_test_contracts: $(CAIRO_1_COMPILED_CASM_CONTRACTS)
Expand All @@ -268,7 +272,7 @@ test-wasm: cairo_proof_programs cairo_test_programs
# NOTE: release mode is needed to avoid "too many locals" error
wasm-pack test --release --node vm --no-default-features
test-extensive_hints: cairo_proof_programs cairo_test_programs
$(TEST_COMMAND) --workspace --features "test_utils, cairo-1-hints, cairo-0-secp-hints, extensive_hints"
$(TEST_COMMAND) --workspace --features "test_utils, cairo-1-hints, cairo-0-secp-hints, cairo-0-data-availability-hints, extensive_hints"

check-fmt:
cargo fmt --all -- --check
Expand Down Expand Up @@ -349,6 +353,7 @@ clean:
rm -f $(BENCH_DIR)/*.json
rm -f $(BAD_TEST_DIR)/*.json
rm -f $(SECP_CAIRO0_HINTS_DIR)/*.json
rm -f $(KZG_DA_CAIRO0_HINTS_DIR)/*.json
rm -f $(PRINT_TEST_DIR)/*.json
rm -f $(CAIRO_1_CONTRACTS_TEST_DIR)/*.sierra
rm -f $(CAIRO_1_CONTRACTS_TEST_DIR)/*.casm
Expand Down
29 changes: 29 additions & 0 deletions cairo_programs/cairo-0-kzg-da-hints/reduced_mul.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
%builtins range_check

from starkware.starknet.core.os.data_availability.bls_field import reduced_mul, BigInt3

func main{range_check_ptr: felt}() {
let x = BigInt3(0, 0, 0);
let y = BigInt3(1, 1, 1);

let res = reduced_mul(x, y);

assert res = BigInt3(0, 0, 0);

let x = BigInt3(100, 99, 98);
let y = BigInt3(10, 9, 8);

let res = reduced_mul(x, y);

assert res = BigInt3(
49091481911800146991175221, 43711329369885800715738617, 405132241597509509195407
);

let x = BigInt3(47503316700827173496989353, 17218105161352860131668522, 527908748911931938599018);
let y = BigInt3(50964737623371959432443726, 60451660835701602854498663, 5043009036652075489876599);

let res = reduced_mul(x, y);
assert res = BigInt3(43476011663489831917914902, 15057238271740518603165849, 1923992965848504555868221);

return ();
}
1 change: 1 addition & 0 deletions vm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ cairo-1-hints = [
tracer = []
mod_builtin = []
cairo-0-secp-hints = []
cairo-0-data-availability-hints = []

# Note that these features are not retro-compatible with the cairo Python VM.
test_utils = ["std", "dep:arbitrary", "starknet-types-core/arbitrary", "starknet-types-core/std"] # This feature will reference every test-oriented feature
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,14 @@ impl HintProcessorLogic for BuiltinHintProcessor {
&hint_data.ap_tracking,
constants,
),
#[cfg(feature = "cairo-0-data-availability-hints")]
super::kzg_da::WRITE_DIVMOD_SEGMENT => super::kzg_da::write_div_mod_segment(
vm,
exec_scopes,
&hint_data.ids_data,
&hint_data.ap_tracking,
constants,
),

code => Err(HintError::UnknownHint(code.to_string().into_boxed_str())),
}
Expand Down
108 changes: 108 additions & 0 deletions vm/src/hint_processor/builtin_hint_processor/kzg_da/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
use core::str::FromStr;

use super::{
hint_utils::get_relocatable_from_var_name,
secp::{bigint_utils::BigInt3, secp_utils::SECP_P},
};
use crate::{
hint_processor::hint_processor_definition::HintReference,
serde::deserialize_program::ApTracking,
types::relocatable::MaybeRelocatable,
vm::{errors::hint_errors::HintError, vm_core::VirtualMachine},
Felt252,
};
use crate::{
stdlib::{collections::HashMap, ops::Deref, prelude::*},
types::exec_scope::ExecutionScopes,
};
use lazy_static::lazy_static;
use num_bigint::BigInt;
use num_integer::Integer;
use num_traits::FromPrimitive;
use num_traits::Zero;

lazy_static! {
static ref BLS_BASE: BigInt = BigInt::from_u64(2).unwrap().pow(86);
static ref BLS_PRIME: BigInt = BigInt::from_str(
"52435875175126190479447740508185965837690552500527637822603658699938581184513"
)
.unwrap();
}
pub const WRITE_DIVMOD_SEGMENT: &str = r#"from starkware.starknet.core.os.data_availability.bls_utils import BLS_PRIME, pack, split
a = pack(ids.a, PRIME)
b = pack(ids.b, PRIME)
q, r = divmod(a * b, BLS_PRIME)
# By the assumption: |a|, |b| < 2**104 * ((2**86) ** 2 + 2**86 + 1) < 2**276.001.
# Therefore |q| <= |ab| / BLS_PRIME < 2**299.
# Hence the absolute value of the high limb of split(q) < 2**127.
segments.write_arg(ids.q.address_, split(q))
segments.write_arg(ids.res.address_, split(r))"#;

pub fn write_div_mod_segment(
vm: &mut VirtualMachine,
_exec_scopes: &mut ExecutionScopes,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
_constants: &HashMap<String, Felt252>,
) -> Result<(), HintError> {
let a = bls_pack(
&BigInt3::from_var_name("a", vm, ids_data, ap_tracking)?,
&SECP_P,
);
let b = bls_pack(
&BigInt3::from_var_name("b", vm, ids_data, ap_tracking)?,
&SECP_P,
);
let (q, r) = (a * b).div_mod_floor(&BLS_PRIME);
let q_reloc = get_relocatable_from_var_name("q", vm, ids_data, ap_tracking)?;
let res_reloc = get_relocatable_from_var_name("res", vm, ids_data, ap_tracking)?;

let q_arg: Vec<MaybeRelocatable> = bls_split(q)
.into_iter()
.map(|ref n| Felt252::from(n).into())
.collect::<Vec<MaybeRelocatable>>();
let res_arg: Vec<MaybeRelocatable> = bls_split(r)
.into_iter()
.map(|ref n| Felt252::from(n).into())
.collect::<Vec<MaybeRelocatable>>();
vm.write_arg(q_reloc, &q_arg).map_err(HintError::Memory)?;
vm.write_arg(res_reloc, &res_arg)
.map_err(HintError::Memory)?;
Ok(())
}

fn bls_split(mut num: BigInt) -> Vec<BigInt> {
use num_traits::Signed;
let mut a = Vec::new();
for _ in 0..2 {
let residue = &num % BLS_BASE.deref();
num /= BLS_BASE.deref();
a.push(residue);
}
assert!(num.abs() < BigInt::from_u128(1 << 127).unwrap());
a.push(num);
a
}

fn as_int(value: BigInt, prime: &BigInt) -> BigInt {
let half_prime = prime / 2u32;
if value > half_prime {
value - prime
} else {
value
}
}

fn bls_pack(z: &BigInt3, prime: &BigInt) -> BigInt {
let limbs = &z.limbs;
limbs
.iter()
.enumerate()
.fold(BigInt::zero(), |acc, (i, limb)| {
let limb_as_int = as_int(limb.to_bigint(), prime);
acc + limb_as_int * &BLS_BASE.pow(i as u32)
})
}
4 changes: 4 additions & 0 deletions vm/src/hint_processor/builtin_hint_processor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,7 @@ pub mod uint384_extension;
pub mod uint_utils;
pub mod usort;
pub mod vrf;

#[cfg(feature = "cairo-0-data-availability-hints")]
#[cfg_attr(docsrs, doc(cfg(feature = "cairo-0-data-availability-hints")))]
pub mod kzg_da;
1 change: 1 addition & 0 deletions vm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
//! - implementations of [`arbitrary::Arbitrary`](https://docs.rs/arbitrary/latest/arbitrary/) for some structs.
//! - `cairo-1-hints`: Enable hints that were introduced in Cairo 1. Not enabled by default.
//! - `cairo-0-secp-hints`: Enable secp hints that were introduced in Cairo 0. Not enabled by default.
//! - `cairo-0-data-availability-hints`: Enable data availability hints that were introduced in Cairo 0. Not enabled by default.
#![cfg_attr(docsrs, feature(doc_cfg))]
#![deny(warnings)]
Expand Down
9 changes: 9 additions & 0 deletions vm/src/tests/cairo_run_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1308,3 +1308,12 @@ fn cairo_run_secp_cairo0_ec_mul_by_uint256() {
);
run_program_simple(program_data.as_slice());
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
#[cfg(feature = "cairo-0-data-availability-hints")]
fn cairo_run_data_availability_reduced_mul() {
let program_data =
include_bytes!("../../../cairo_programs/cairo-0-kzg-da-hints/reduced_mul.json");
run_program_simple(program_data.as_slice());
}

0 comments on commit 052e7ce

Please sign in to comment.