Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement kzg data availability hints #1887

Merged
merged 6 commits into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)

* fix: replace `div_rem` with `div_mod_floor` in `verify_zero` hints [#1881](https://github.com/lambdaclass/cairo-vm/pull/1881)

* feat: Implement `SECP related` hints [#1829](https://github.com/lambdaclass/cairo-vm/pull/1829)
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
109 changes: 109 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,109 @@
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)?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I can see in the hint, the var name should be "r" and not "res", right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part relates to this part of the hint:

segments.write_arg(ids.res.address_, split(r))"

I need to get the relocatable and write the following value:

    let res_arg: Vec<MaybeRelocatable> = bls_split(r)
        .into_iter()
        .map(|ref n| Felt252::from(n).into())
        .collect::<Vec<MaybeRelocatable>>();
        

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see, but where does this res variable come from? Where is it declared?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@FrancoGiachetta Any thoughts on merging this?


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(num: &BigInt) -> Vec<BigInt> {
use num_traits::Signed;
let mut num = num.clone();
let mut a = Vec::new();
for _ in 0..2 {
let residue = num.clone() % BLS_BASE.deref();
num /= BLS_BASE.deref();
a.push(residue);
}
a.push(num.clone());
assert!(num.abs() < BigInt::from_u128(1 << 127).unwrap());
a
}
FrancoGiachetta marked this conversation as resolved.
Show resolved Hide resolved

fn as_int(value: &BigInt, prime: &BigInt) -> BigInt {
let half_prime = prime.clone() / 2u32;
if value > &half_prime {
value - prime
} else {
value.clone()
}
}
FrancoGiachetta marked this conversation as resolved.
Show resolved Hide resolved

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
8 changes: 8 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,11 @@ 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());
}
Loading