Skip to content

Commit ddb50d7

Browse files
authored
Merge pull request #169 from anoma/xuyang/refine_feature_flags
refine feature flags
2 parents 4bf2110 + d37c76f commit ddb50d7

File tree

11 files changed

+145
-116
lines changed

11 files changed

+145
-116
lines changed

README.md

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -73,36 +73,24 @@ We have the following feature flags in arm lib:
7373
| Feature | Implies | Description |
7474
| ------------------------ | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
7575
| `compliance_circuit` | | A specific feature for compliance circuit |
76-
| `transaction (default)` | `compliance_circuit`, `client` | It provides full transaction processing capabilities and will be in the Anoma SDK and validator with a selected prover feature. Succinct prover is used by default. |
76+
| `transaction (default)` | `compliance_circuit`, `client` | It provides full transaction processing capabilities and supports Succinct(STARK) and Groth16 proof types. Groth16 proofs require x86_64 machines. |
7777
| `prove` | | Enables RISC0 proving capabilities (required for actual proof generation) |
7878
| `bonsai` | | Enables RISC0 bonsai sdk |
7979
| `client` | | Enables RISC0 client sdk |
8080
| `cuda` | | Enables CUDA GPU acceleration for the prover. Requires CUDA toolkit to be installed. |
81-
| `fast_prover` | | Fastest option producing linear-size proofs, and does not support compression via recursion |
82-
| `composite_prover` | | Fastest option producing linear-size proofs, and supports compression via recursion |
83-
| `groth16_prover` | | Generates groth16 proofs(requires x86_64 machines) |
8481
| `nif` | | Enables Erlang/Elixir NIF (Native Implemented Function) bindings |
8582
| `aggregation_circuit` | | A specific feature for (pcd-based) aggregation circuits |
86-
| `aggregation` | `aggregation_circuit`, `transaction` | Enables proof aggregation (with constant-sized proofs by default) |
87-
|`fast_aggregation` | `aggregation` | Faster aggregation with linear-sized proofs without compression
88-
|`groth16_aggregation` | `aggregation` | Generates groth16 aggregation proofs (requires x86_64 machines)
89-
83+
| `aggregation` | `aggregation_circuit`, `transaction` | Enables proof aggregation (only succinct proofs can be aggregated) |
9084

9185
### Usage Examples
9286

9387
```toml
94-
# Default configuration (succinct proofs + transaction support)
88+
# Default configuration
9589
arm = "0.12.0"
9690

97-
# Blockchain deployment with Groth16 proofs
98-
arm = { version = "0.12.0", default-features = false, features = ["groth16_prover", "transaction"] }
99-
10091
# Proof aggregation (a single succinct proof per transaction)
10192
arm = { version = "0.12.0", features = ["aggregation"] }
10293

103-
# Blockchain deployment with a Groth16 aggregation proof
104-
arm = { version = "0.12.0", features = ["groth16_aggregation"] }
105-
10694
# Logic-circuit-only usage
10795
arm = { version = "0.12.0", default-features = false }
10896

@@ -137,36 +125,38 @@ cargo install --force --git https://github.com/risc0/risc0 --tag v3.0.3 -Fexperi
137125
```
138126

139127
## Proof aggregation
140-
If a single transaction bundles too many resources, it is possible to aggregate all compliance and logic proofs into a single aggregation proof, attesting to the validity of them all. This reduces overall verification time and transaction size.
128+
If a single transaction bundles too many resources, it is possible to aggregate all compliance and logic proofs into a single aggregation proof, attesting to the validity of them all. This reduces overall verification time and transaction size.
141129

142130
### Before aggregation
143-
Generate the transaction in the normal way in your workflow. But note that succinct proofs will yield faster aggregation.
131+
Generate the transaction in the normal way in your workflow. But note that succinct proofs will yield faster aggregation.
144132

145-
**Warning:** Bonsai does not support in-circuit verification of Groth16 proofs. You would need to generate succinct compliance and logic proofs instead.
133+
**Warning:** It does not support in-circuit verification of Groth16 proofs. You would need to generate succinct compliance and logic proofs instead.
146134

147135

148136
### Prove aggregations
149-
You need to enable the `aggregation` feature to be able to prove or verify aggregations.
137+
You need to enable the `aggregation` feature to be able to prove or verify aggregations.
150138

151-
The type of the aggregation proof is selected via a feature. It defaults to succinct stark proofs. For on-chain verification, you probably want to aggregate with the `groth16_aggregation` feature enabled. See the features table above for more information.
139+
The aggregation proof type is specified by the ProofType argument. The inner proofs must be Succinct.
152140

153141
We currently support two different aggregation strategies. The _batch_ strategy aggregates all proofs in the transaction in a single run. It is the default aggregation.
154142

155143
```rust
156144
use arm::transaction;
157145

158-
let mut tx = generate_test_transaction(1); // Just a dummy tx, for illustration.
146+
// Just a dummy tx, for illustration. The inner proofs must be Succinct.
147+
let mut tx = generate_test_transaction(1, 1, ProofType::Succinct);
159148

160149
// Upon succesful aggregation, compliance and resource logic proofs are erased.
161-
assert!(tx.aggregate().is_ok());
150+
// The aggregated proof_type can be ProofType::Succinct or ProofType::Groth16
151+
assert!(tx.aggregate(proof_type).is_ok());
162152
```
163153

164154
The _sequential_ strategy aggregates sequentially, in an IVC style.
165155

166156
```rust
167157
use arm::aggregation::AggregationStrategy;
168158

169-
assert!(tx.aggregate_with_strategy(AggregationStrategy::Sequential).is_ok());
159+
assert!(tx.aggregate_with_strategy(AggregationStrategy::Sequential, proof_type).is_ok());
170160
```
171161

172162
**Warning:** Once again, aggregation erases all the individual proofs from `tx` and replaces them with the (single) aggregation proof in a dedicated field. This is why the transaction must be `mut`. This is true independently of the strategy used.

arm/Cargo.toml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,9 @@ slab = "0.4.11"
2828
default = ["transaction", "prove"]
2929
transaction = ["compliance_circuit", "dep:sha3"]
3030
compliance_circuit = []
31-
fast_prover = []
32-
composite_prover = []
33-
groth16_prover = []
3431
nif = ["dep:rustler"]
3532
prove = ["risc0-zkvm/prove"]
3633
bonsai = ["risc0-zkvm/bonsai"]
3734
cuda = ["risc0-zkvm/cuda"]
3835
aggregation = ["aggregation_circuit","transaction"]
3936
aggregation_circuit = []
40-
fast_aggregation = ["aggregation"]
41-
groth16_aggregation = ["aggregation"]

arm/src/aggregation/batch.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::aggregation::{
99
use crate::compliance::ComplianceInstanceWords;
1010
use crate::constants::COMPLIANCE_VK;
1111
use crate::error::ArmError;
12+
use crate::proving_system::ProofType;
1213
use crate::transaction::Transaction;
1314
use crate::utils::{bytes_to_words, words_to_bytes};
1415

@@ -19,7 +20,10 @@ pub struct BatchProof(pub InnerReceipt);
1920
pub struct BatchAggregation;
2021

2122
impl BatchAggregation {
22-
pub fn prove_transaction_aggregation(tx: &Transaction) -> Result<BatchProof, ArmError> {
23+
pub fn prove_transaction_aggregation(
24+
tx: &Transaction,
25+
proof_type: ProofType,
26+
) -> Result<BatchProof, ArmError> {
2327
// Collect instances, proofs, and keys.
2428
let BatchCU {
2529
instances: cu_instances,
@@ -74,17 +78,14 @@ impl BatchAggregation {
7478
.build()
7579
.map_err(|_| ArmError::BuildProverEnvFailed)?;
7680

77-
#[cfg(feature = "fast_aggregation")]
78-
let prover_opts = ProverOpts::fast();
79-
80-
#[cfg(all(not(feature = "fast_aggregation"), feature = "groth16_aggregation"))]
81-
let prover_opts = ProverOpts::groth16();
82-
83-
#[cfg(all(
84-
not(feature = "fast_aggregation"),
85-
not(feature = "groth16_aggregation")
86-
))]
87-
let prover_opts = ProverOpts::succinct();
81+
let prover_opts = match proof_type {
82+
ProofType::Succinct => {
83+
ProverOpts::succinct() // Succinct receipts, constant size.
84+
}
85+
ProofType::Groth16 => {
86+
ProverOpts::groth16() // Groth16 receipts, constant size, blockchain-friendly.
87+
}
88+
};
8889

8990
let prover = default_prover();
9091

arm/src/aggregation/pcd.rs

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::aggregation::{BatchCU, BatchLP};
22
use crate::constants::COMPLIANCE_VK;
33
use crate::error::ArmError;
44
use crate::proving_system;
5+
use crate::proving_system::ProofType;
56
use crate::utils::words_to_bytes;
67
use crate::{compliance::ComplianceInstance, logic_instance::LogicInstance};
78
use risc0_zkvm::{
@@ -58,6 +59,7 @@ pub trait PCDAggregation {
5859
step_instance: &StepInstance,
5960
step_proof: &StepProof,
6061
output_node: bool,
62+
proof_type: ProofType,
6163
) -> Result<PcdProof, ArmError> {
6264
// Sanity check
6365
if input_aggregations.len() != <Self as PCDAggregation>::INPUT_ARITY {
@@ -110,22 +112,13 @@ pub trait PCDAggregation {
110112

111113
// If not an output node, prove fast.
112114
let prover_opts = if output_node {
113-
#[cfg(feature = "fast_aggregation")]
114-
{
115-
ProverOpts::fast()
116-
}
117-
118-
#[cfg(all(not(feature = "fast_aggregation"), feature = "groth16_aggregation"))]
119-
{
120-
ProverOpts::groth16()
121-
}
122-
123-
#[cfg(all(
124-
not(feature = "fast_aggregation"),
125-
not(feature = "groth16_aggregation")
126-
))]
127-
{
128-
ProverOpts::succinct()
115+
match proof_type {
116+
ProofType::Succinct => {
117+
ProverOpts::succinct() // Succinct receipts, constant size.
118+
}
119+
ProofType::Groth16 => {
120+
ProverOpts::groth16() // Groth16 receipts, constant size, blockchain-friendly.
121+
}
129122
}
130123
} else {
131124
ProverOpts::fast()

arm/src/aggregation/sequential.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use risc0_zkvm::Digest;
33
use crate::{
44
aggregation::constants::{SEQUENTIAL_AGGREGATION_PK, SEQUENTIAL_AGGREGATION_VK},
55
error::ArmError,
6+
proving_system::ProofType,
67
transaction::Transaction,
78
};
89

@@ -29,6 +30,7 @@ impl SequentialAggregation {
2930
pub fn prove_transcript_aggregation(
3031
instances: &[StepInstance],
3132
proofs: &[StepProof],
33+
proof_type: ProofType,
3234
) -> Result<PcdProof, ArmError> {
3335
if instances.len() != proofs.len() {
3436
// Can't aggregate.
@@ -46,6 +48,7 @@ impl SequentialAggregation {
4648
instance,
4749
proof,
4850
pos == instances.len() - 1,
51+
proof_type,
4952
)?;
5053

5154
agg = <SequentialAggregation as PCDAggregation>::aggregate_step(&[agg], instance);
@@ -57,9 +60,12 @@ impl SequentialAggregation {
5760
}
5861

5962
/// Prove correctness of the transcript induced by a transaction.
60-
pub fn prove_transaction_aggregation(tx: &Transaction) -> Result<PcdProof, ArmError> {
63+
pub fn prove_transaction_aggregation(
64+
tx: &Transaction,
65+
proof_type: ProofType,
66+
) -> Result<PcdProof, ArmError> {
6167
if let (instances, Some(proofs)) = &SequentialAggregation::transaction_transcript(tx)? {
62-
SequentialAggregation::prove_transcript_aggregation(instances, proofs)
68+
SequentialAggregation::prove_transcript_aggregation(instances, proofs, proof_type)
6369
} else {
6470
Err(ArmError::ProveFailed(
6571
"Error deriving transcript for proving (individual instances and proofs)".into(),

arm/src/compliance_unit.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ use k256::ProjectivePoint;
88
use serde::{Deserialize, Serialize};
99

1010
#[cfg(feature = "prove")]
11-
use crate::{compliance::ComplianceWitness, constants::COMPLIANCE_PK, proving_system::prove};
11+
use crate::{
12+
compliance::ComplianceWitness,
13+
constants::COMPLIANCE_PK,
14+
proving_system::{prove, ProofType},
15+
};
1216

1317
#[derive(Clone, Debug, Deserialize, Serialize)]
1418
pub struct ComplianceUnit {
@@ -21,8 +25,8 @@ impl ComplianceUnit {
2125
// Proving key and verifying key are constants, so we don't need to pass
2226
// them as parameters. Instance is generated by proving.
2327
#[cfg(feature = "prove")]
24-
pub fn create(witness: &ComplianceWitness) -> Result<Self, ArmError> {
25-
let (proof, instance) = prove(COMPLIANCE_PK, witness)?;
28+
pub fn create(witness: &ComplianceWitness, proof_type: ProofType) -> Result<Self, ArmError> {
29+
let (proof, instance) = prove(COMPLIANCE_PK, witness, proof_type)?;
2630
Ok(ComplianceUnit {
2731
proof: Some(proof),
2832
instance,

arm/src/logic_proof.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use risc0_zkvm::{serde::to_vec, sha::Digest};
1616
use serde::{Deserialize, Serialize};
1717

1818
#[cfg(feature = "prove")]
19-
use crate::proving_system::prove;
19+
use crate::proving_system::{prove, ProofType};
2020

2121
pub trait LogicProver: Default + Clone + Serialize + for<'de> Deserialize<'de> {
2222
type Witness: Default + Clone + Serialize + for<'de> Deserialize<'de>;
@@ -32,8 +32,8 @@ pub trait LogicProver: Default + Clone + Serialize + for<'de> Deserialize<'de> {
3232
fn witness(&self) -> &Self::Witness;
3333

3434
#[cfg(feature = "prove")]
35-
fn prove(&self) -> Result<LogicVerifier, ArmError> {
36-
let (proof, instance) = prove(Self::proving_key(), self.witness())?;
35+
fn prove(&self, proof_type: ProofType) -> Result<LogicVerifier, ArmError> {
36+
let (proof, instance) = prove(Self::proving_key(), self.witness(), proof_type)?;
3737
Ok(LogicVerifier {
3838
proof: Some(proof),
3939
instance,
@@ -198,6 +198,6 @@ impl LogicProver for TrivialLogicWitness {
198198
#[test]
199199
fn test_padding_logic_prover() {
200200
let trivial_logic = PaddingResourceLogic::default();
201-
let proof = trivial_logic.prove().unwrap();
201+
let proof = trivial_logic.prove(ProofType::Succinct).unwrap();
202202
proof.verify().unwrap();
203203
}

arm/src/proving_system.rs

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,20 @@ use risc0_zkvm::{default_prover, ExecutorEnv, ProverOpts, VerifierContext};
77
#[cfg(feature = "prove")]
88
use serde::Serialize;
99

10+
#[derive(Debug, Clone, Copy)]
11+
pub enum ProofType {
12+
Succinct,
13+
Groth16,
14+
}
15+
1016
// It takes a proving key and a witness, and returns the proof and the instance
1117
#[cfg(feature = "prove")]
1218
pub fn prove<T: Serialize>(
1319
proving_key: &[u8],
1420
witness: &T,
21+
proof_type: ProofType,
1522
) -> Result<(Vec<u8>, Vec<u8>), ArmError> {
16-
let receipt = prove_inner(witness, proving_key)?;
23+
let receipt = prove_inner(witness, proving_key, proof_type)?;
1724

1825
let proof = bincode::serialize(&receipt.inner).map_err(|_| ArmError::SerializationError)?;
1926
let instance = receipt.journal.bytes;
@@ -57,33 +64,25 @@ pub fn encode_seal(proof: &[u8]) -> Result<Vec<u8>, ArmError> {
5764
}
5865

5966
#[cfg(feature = "prove")]
60-
fn prove_inner<T: Serialize>(witness: &T, proving_key: &[u8]) -> Result<Receipt, ArmError> {
67+
fn prove_inner<T: Serialize>(
68+
witness: &T,
69+
proving_key: &[u8],
70+
proof_type: ProofType,
71+
) -> Result<Receipt, ArmError> {
6172
let env = ExecutorEnv::builder()
6273
.write(witness)
6374
.map_err(|_| ArmError::WriteWitnessFailed)?
6475
.build()
6576
.map_err(|_| ArmError::BuildProverEnvFailed)?;
6677

67-
#[cfg(feature = "fast_prover")]
68-
let prover_opts = ProverOpts::fast(); // Fastest, linear size, no recursion.
69-
70-
#[cfg(all(not(feature = "fast_prover"), feature = "composite_prover"))]
71-
let prover_opts = ProverOpts::composite(); // Composite receipts, linear size, supports recursion.
72-
73-
#[cfg(all(
74-
not(feature = "fast_prover"),
75-
not(feature = "composite_prover"),
76-
feature = "groth16_prover"
77-
))]
78-
let prover_opts = ProverOpts::groth16(); // Groth16 receipts, constant size, blockchain-friendly.
79-
80-
// If no specific prover feature is enabled, default to succinct prover.
81-
#[cfg(all(
82-
not(feature = "fast_prover"),
83-
not(feature = "composite_prover"),
84-
not(feature = "groth16_prover")
85-
))]
86-
let prover_opts = ProverOpts::succinct(); // Succinct receipts, constant size.
78+
let prover_opts = match proof_type {
79+
ProofType::Succinct => {
80+
ProverOpts::succinct() // Succinct receipts, constant size.
81+
}
82+
ProofType::Groth16 => {
83+
ProverOpts::groth16() // Groth16 receipts, constant size, blockchain-friendly.
84+
}
85+
};
8786

8887
let prove_info = default_prover()
8988
.prove_with_ctx(env, &VerifierContext::default(), proving_key, &prover_opts)

0 commit comments

Comments
 (0)