![logo](https://private-user-images.githubusercontent.com/3767044/282759418-6afd527d-1ff3-4a1f-886a-071060121c91.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQzNTI4MTEsIm5iZiI6MTcyNDM1MjUxMSwicGF0aCI6Ii8zNzY3MDQ0LzI4Mjc1OTQxOC02YWZkNTI3ZC0xZmYzLTRhMWYtODg2YS0wNzEwNjAxMjFjOTEucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MDgyMiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA4MjJUMTg0ODMxWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZDc0OWE3YWJkMTQ5ODk2NzRmYjQxNjY3OTg2YzNlODg0ZWFkODI3ZjdlY2UxZjljZDY3YTczNzc2YTkyZTUyNCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.7nS4KCAG8tGIdmeVSyNZA223-cFw7uK4LzIk4BUoTGk)
Sirius, renowned as the most luminous star in the night sky, deceives the naked eye by appearing as a solitary point of light when, in fact, it is a binary star system. Inspired by this duality, our project bears the name Sirius, capturing the essence of folded instances that give the illusion of being a singular entity.
Sirius is an open-source Plonkish Folding Framework for Incrementally Verifiable Computation [IVC].
Within the context of an IVC scheme, the prover's role is to demonstrate that, upon consecutively applying a step function F
exactly n
times to an initial value F
takes two inputs
The Sirius
folding framework is designed with a three-tiered architecture.
- Arithmetization Layer: This layer serves as the interface of the constraint system. User-defined circuits and witness data are converted into an intermediate representation format defined by the folding scheme. Our current implementation follows the special-sound interactive protocol (SPS) from Protostar.
- Folding Scheme Layer: At the heart of the framework is the folding scheme IVC circuit that accumulates the computations of multiple steps. At each step, the prover first calculates the instance-witness pairs from the previous step and folds them into the accumulator, then computes the cross terms and error vector for the folded instance-witness pairs. An IVC circuit then takes the outputs from the prover and performs the following steps: apply the step function
F
, fold the previous step's instance into the accumulator instance, and verify the inputs of the IVC circuit. - SNARK Layer: The SNARK layer leverages Polynomial Interactive Oracle Proofs (PIOP) and Polynomial Commitment Schemes (PCS) to generate zkSNARKs for succinct and zero-knowledge verification. Polynomial relation checks of the IVC decider are converted to the multivariate sum-check protocol. The evaluation phase of the sum-check protocol depends on the polynomial commitment scheme (PCS) we choose, e.g. Hyrax. It is worth noting that when the polynomials are sparse, we can use the Spark compiler from Spartan to handle them efficiently.
- 2023Q4 - halo2 frontend support
- 2023Q4 - folding scheme for plonkish custom gates
- 2023Q4 - folding scheme for lookup arguments
- 2024Q1 - IVC circuit
- 2024Q1 - IVC Benchmarks
- 2024Q2 - high-degree gates optimization from Protogalaxy
- 2024Q3 - IVC with cyclefold
- 2024Q3 - Snarkify Cloud integration and GPU acceleration
- 2024Q4 - Agg circuit
- 2024Q4 - IOP + PCS SNARK support (Spartan / Hyperplonk)
- 2025Q1 - on-chain verifier support
The estimated timeline is subject to change.
Use rustup
cargo add --git https://github.com/snarkify/sirius.git --tag v0.1.0 sirius
/// To allow your circuit to be folded, impl this trait
/// `ARITY` - size of input & output
pub trait StepCircuit<const ARITY: usize, F: PrimeField> {
type Config: Clone;
fn configure(cs: &mut ConstraintSystem<F>) -> Self::Config;
/// This method represents step function `F: z_i -> z_{i+1}`
///
/// Unlike `halo2::Circuit`, it takes array of assigned cells
/// and returns array of assigned cells
fn synthesize_step(
&self,
config: Self::Config,
layouter: &mut impl Layouter<F>,
z_in: &[AssignedCell<F, F>; ARITY],
) -> Result<[AssignedCell<F, F>; ARITY], SynthesisError>;
}
For runnable examples, please check examples folder.
An example of using the API of IVC:
fn main() {
let primary = poseidon_step_circuit::TestPoseidonCircuit::default();
let secondary = step_circuit::trivial::Circuit::<ARITY2, _>::default();
// Specifications for random oracle used as part of the IVC algorithm
let primary_spec = RandomOracleConstant::<C1Scalar>::new(10, 10);
let secondary_spec = RandomOracleConstant::<C2Scalar>::new(10, 10);
let primary_commitment_key = get_or_create_commitment_key::<C1Affine>(COMMITMENT_KEY_SIZE, "bn256");
let secondary_commitment_key = get_or_create_commitment_key::<C2Affine>(COMMITMENT_KEY_SIZE, "grumpkin");
let pp = PublicParams::<
'_,
ARITY1,
ARITY2,
MAIN_GATE_SIZE,
C1Affine,
C2Affine,
TestPoseidonCircuit<_>,
step_circuit::trivial::Circuit<ARITY, _>,
RandomOracle,
RandomOracle,
>::new(
CircuitPublicParamsInput::new(
PRIMARY_CIRCUIT_TABLE_SIZE as u32,
&primary_commitment_key,
primary_spec,
&primary,
),
CircuitPublicParamsInput::new(
SECONDARY_CIRCUIT_TABLE_SIZE as u32,
&secondary_commitment_key,
secondary_spec,
&secondary,
),
LIMB_WIDTH,
LIMBS_COUNT,
)
.expect("failed to create public params");
let primary_input = array::from_fn(|i| C1Scalar::from_u128(i as u128));
let secondary_input = array::from_fn(|i| C2Scalar::from_u128(i as u128));
let fold_step_count = NonZeroUsize::new(10).unwrap();
IVC::fold(
&pp,
primary,
primary_input,
secondary,
secondary_input,
fold_step_count,
)
.expect("failed to run IVC");
}
This code will run fold_step_count
of folding steps, and also check the proof after execution.
For runnable examples, please check examples folder.
# 're' is short for 'run example'
# Alias to run IVC with parameterization via cli arguments
cargo re-cli --help
# Alias for run the IVC for trivial `StepCircuit` (just returns its input unchanged)
cargo re-trivial
# Alias for run the IVC for the poseidon-circuit
cargo re-poseidon
Span lifetime tracking implemented, which allows you to understand in detail how long a particular step takes to complete.
# 're' is short for 'run example'
# By default, it will output all spans with a lifetime greater than 1s
cargo re-poseidon | python3 .scripts/build_profiling.py
# It is possible to specify the bottom border of the output span
cargo re-poseidon | python3 .scripts/build_profiling.py --min-runtime 0.1s
# You can also store logs and process them at a later date
cargo re-poseidon > log; cat log | python3 .scripts/build_profiling.py
The dhat utility and the dhat-rs experimental crate are used
# Run dhat with default IVC (poseidon+trivial)
cargo cli-dhat
# Check available params of run
cargo cli-dhat --help
For benches, please check benches folder.
cargo bench
You can also get a more detailed report. Please check for info criterion.rs
cargo criterion
We'd love for you to be a part of our community!
If you're as enthusiastic about Sirius
as we are, we invite you to join our developer community at Telegram. It's a great place to stay updated, get involved, and contribute to the project. Whether you're looking to contribute code, provide feedback, or simply stay in the loop, our Telegram group is the place to be.
👉 Join our developer community
Thank you for your interest in contributing to Sirius
! ✨