Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
691599d
refactor(l2): use hardcoded vk in Aligned mode
avilagaston9 Jun 13, 2025
14047f4
Decode aligned vk
avilagaston9 Jun 17, 2025
0fd48b4
Add vk to options
avilagaston9 Jun 17, 2025
7dd00d7
Merge branch 'main' into l2/refactor/aligned_use_hardcoded_vk
avilagaston9 Jun 17, 2025
2b939eb
Fix clippy
avilagaston9 Jun 17, 2025
5197e64
Fix error in estimate_Gas
avilagaston9 Jun 17, 2025
ba02140
fix(l2): use aligned SDK latest release
avilagaston9 Jun 17, 2025
b19f1a3
Proper get the blob_versioned_hashes
avilagaston9 Jun 17, 2025
e80238e
Update nix build
avilagaston9 Jun 18, 2025
191f8c6
Update cargo lock
avilagaston9 Jun 18, 2025
993c02b
Fix service.nix
avilagaston9 Jun 18, 2025
f45537d
Merge branch 'main' into l2/fix/use_aligned_sdk_release
avilagaston9 Jun 18, 2025
80d4277
Add guide to setup a dev Aligned environment
avilagaston9 Jun 18, 2025
835b165
nit
avilagaston9 Jun 18, 2025
b4c38e9
Improve docs
avilagaston9 Jun 18, 2025
556640a
Improve aligned docs
avilagaston9 Jun 18, 2025
8463d3b
Merge branch 'main' into l2/fix/use_aligned_sdk_release
avilagaston9 Jun 18, 2025
1389f1d
Address copilot comments
avilagaston9 Jun 18, 2025
25bdabc
Merge branch 'l2/fix/use_aligned_sdk_release' into l2/refactor/aligne…
avilagaston9 Jun 18, 2025
d0307e2
Merge branch 'main' into l2/fix/use_aligned_sdk_release
avilagaston9 Jun 18, 2025
c990abd
Merge branch 'l2/fix/use_aligned_sdk_release' into l2/refactor/aligne…
avilagaston9 Jun 18, 2025
b0cde72
Not convert vk to hex
avilagaston9 Jun 18, 2025
5ca1d69
Use generic contract addresses
avilagaston9 Jun 18, 2025
a08befb
Update aligned docs
avilagaston9 Jun 18, 2025
da7dc46
Merge branch 'l2/fix/use_aligned_sdk_release' into l2/refactor/aligne…
avilagaston9 Jun 18, 2025
2d47e03
Read sp1_vk from contract
avilagaston9 Jun 19, 2025
ae774b5
Fix types
avilagaston9 Jun 19, 2025
c7ded61
Remove unnecessary code
avilagaston9 Jun 19, 2025
4bd1c83
Add missing end of block
avilagaston9 Jun 19, 2025
17d5d15
Restore estimate_gas error
avilagaston9 Jun 19, 2025
4586fa2
Merge branch 'main' into l2/fix/use_aligned_sdk_release
avilagaston9 Jun 23, 2025
0a282a5
Merge branch 'main' into l2/fix/use_aligned_sdk_release
avilagaston9 Jun 24, 2025
bb016fa
Merge branch 'l2/fix/use_aligned_sdk_release' into l2/refactor/aligne…
avilagaston9 Jun 24, 2025
39425e1
Remove dbg from builder
avilagaston9 Jun 24, 2025
397e0c7
Fix typo
avilagaston9 Jun 24, 2025
4a4f6e9
Update crates/networking/rpc/clients/eth/mod.rs
avilagaston9 Jun 24, 2025
ede427f
Merge branch 'main' into l2/refactor/aligned_use_hardcoded_vk
avilagaston9 Jun 24, 2025
028e1af
Fix merge
avilagaston9 Jun 24, 2025
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
15 changes: 5 additions & 10 deletions crates/l2/contracts/bin/deployer/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -493,20 +493,15 @@ async fn initialize_contracts(
.to_str()
.ok_or(DeployerError::FailedToGetStringFromPath)?,
);
let sp1_vk_string = read_to_string(&opts.sp1_vk_path).unwrap_or_else(|_| {

let sp1_vk = std::fs::read(&opts.sp1_vk_path)
.unwrap_or_else(|_| {
warn!(
path = opts.sp1_vk_path,
"Failed to read SP1 verification key file, will use 0x00..00, this is expected in dev mode"
);
"0x00".to_string()
});
let sp1_vk = hex::decode(sp1_vk_string.trim_start_matches("0x"))
.map_err(|err| {
DeployerError::DecodingError(format!(
"failed to parse sp1_vk ({sp1_vk_string}) from hex: {err}"
))
})?
.into();
vec![0u8; 32]
}).into();

let deployer_address = get_address_from_secret_key(&opts.private_key)?;

Expand Down
3 changes: 1 addition & 2 deletions crates/l2/contracts/src/l1/OnChainProposer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,6 @@ contract OnChainProposer is
function verifyBatchAligned(
uint256 batchNumber,
bytes calldata alignedPublicInputs,
bytes32 alignedProgramVKey,
bytes32[] calldata alignedMerkleProof
) external override onlySequencer whenNotPaused {
require(
Expand All @@ -377,7 +376,7 @@ contract OnChainProposer is
bytes memory callData = abi.encodeWithSignature(
"verifyProofInclusion(bytes32[],bytes32,bytes)",
alignedMerkleProof,
alignedProgramVKey,
SP1_VERIFICATION_KEY,
alignedPublicInputs
);
(bool callResult, bytes memory response) = ALIGNEDPROOFAGGREGATOR
Expand Down
2 changes: 0 additions & 2 deletions crates/l2/contracts/src/l1/interfaces/IOnChainProposer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,10 @@ interface IOnChainProposer {

/// @notice Method used to verify a batch of L2 blocks in Aligned.
/// @param alignedPublicInputs The public inputs bytes of the proof.
/// @param alignedProgramVKey The public verifying key.
/// @param alignedMerkleProof The Merkle proof (sibling hashes) needed to reconstruct the Merkle root.
function verifyBatchAligned(
uint256 batchNumber,
bytes calldata alignedPublicInputs,
bytes32 alignedProgramVKey,
bytes32[] calldata alignedMerkleProof
) external;

Expand Down
1 change: 0 additions & 1 deletion crates/l2/prover/src/backends/sp1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ pub fn to_batch_proof(
BatchProof::ProofBytes(ProofBytes {
proof: bincode::serialize(&proof.proof)?,
public_values: proof.proof.public_values.to_vec(),
vk: proof.vk.hash_bytes().into(),
})
} else {
BatchProof::ProofCalldata(to_calldata(proof))
Expand Down
17 changes: 13 additions & 4 deletions crates/l2/prover/zkvm/interface/build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
fn main() {
println!("cargo::rerun-if-changed=build.rs");
println!("cargo:rerun-if-env-changed=PROVER_CLIENT_ALIGNED");

#[cfg(feature = "risc0")]
build_risc0_program();
Expand Down Expand Up @@ -53,8 +54,16 @@ fn build_sp1_program() {
.expect("could not read SP1 elf file");
let prover = ProverClient::from_env();
let (_, vk) = prover.setup(&elf);
let vk = vk.vk.bytes32();
dbg!(&vk);
std::fs::write("./sp1/out/riscv32im-succinct-zkvm-vk", &vk)
.expect("could not write SP1 vk to file");

let aligned_mode = std::env::var("PROVER_CLIENT_ALIGNED").unwrap_or("false".to_string());

if aligned_mode == "true" {
let vk = vk.vk.hash_bytes();
std::fs::write("./sp1/out/riscv32im-succinct-zkvm-vk", &vk)
.expect("could not write SP1 vk to file");
} else {
let vk = vk.vk.bytes32_raw();
std::fs::write("./sp1/out/riscv32im-succinct-zkvm-vk", &vk)
.expect("could not write SP1 vk to file");
};
}
2 changes: 0 additions & 2 deletions crates/l2/sequencer/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,6 @@ pub enum ProofVerifierError {
InternalError(String),
#[error("ProofVerifier failed to parse beacon url")]
ParseBeaconUrl(String),
#[error("ProofVerifier decoding error: {0}")]
DecodingError(String),
#[error("Failed with a SaveStateError: {0}")]
SaveStateError(#[from] SaveStateError),
#[error("Failed to encode calldata: {0}")]
Expand Down
16 changes: 8 additions & 8 deletions crates/l2/sequencer/l1_proof_verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ use super::{
utils::{send_verify_tx, sleep_random},
};

const ALIGNED_VERIFY_FUNCTION_SIGNATURE: &str =
"verifyBatchAligned(uint256,bytes,bytes32,bytes32[])";
const ALIGNED_VERIFY_FUNCTION_SIGNATURE: &str = "verifyBatchAligned(uint256,bytes,bytes32[])";

pub async fn start_l1_proof_verifier(cfg: SequencerConfig) -> Result<(), SequencerError> {
let l1_proof_verifier = L1ProofVerifier::new(
Expand All @@ -46,6 +45,7 @@ struct L1ProofVerifier {
on_chain_proposer_address: Address,
proof_verify_interval_ms: u64,
network: Network,
sp1_vk: [u8; 32],
}

impl L1ProofVerifier {
Expand All @@ -57,6 +57,10 @@ impl L1ProofVerifier {
) -> Result<Self, ProofVerifierError> {
let eth_client = EthClient::new_with_multiple_urls(eth_cfg.rpc_url.clone())?;

let sp1_vk = eth_client
.get_sp1_vk(committer_cfg.on_chain_proposer_address)
.await?;

Ok(Self {
eth_client,
beacon_url: aligned_cfg.beacon_url.clone(),
Expand All @@ -65,6 +69,7 @@ impl L1ProofVerifier {
l1_private_key: proof_coordinator_cfg.l1_private_key,
on_chain_proposer_address: committer_cfg.on_chain_proposer_address,
proof_verify_interval_ms: aligned_cfg.aligned_verifier_interval_ms,
sp1_vk,
})
}

Expand Down Expand Up @@ -115,13 +120,9 @@ impl L1ProofVerifier {
) -> Result<Option<H256>, ProofVerifierError> {
let proof = read_proof(batch_number, StateFileType::BatchProof(ProverType::Aligned))?;
let public_inputs = proof.public_values();
// TODO: use a hardcoded vk
let vk = proof.vk();

let verification_data = AggregationModeVerificationData::SP1 {
vk: vk.clone().try_into().map_err(|e| {
ProofVerifierError::DecodingError(format!("Failed to decode vk: {e:?}"))
})?,
vk: self.sp1_vk,
public_inputs: public_inputs.clone(),
};

Expand Down Expand Up @@ -170,7 +171,6 @@ impl L1ProofVerifier {
let calldata_values = [
Value::Uint(U256::from(batch_number)),
Value::Bytes(public_inputs.into()),
Value::FixedBytes(vk.into()),
Value::Array(merkle_path),
];

Expand Down
9 changes: 0 additions & 9 deletions crates/l2/utils/prover/proving_systems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,6 @@ impl BatchProof {
BatchProof::ProofBytes(proof_bytes) => proof_bytes.public_values.clone(),
}
}

pub fn vk(&self) -> Vec<u8> {
match self {
BatchProof::ProofCalldata(_) => vec![],
BatchProof::ProofBytes(proof_bytes) => proof_bytes.vk.clone(),
}
}
}

/// Contains the Proof and the public values generated by the prover.
Expand All @@ -124,8 +117,6 @@ impl BatchProof {
pub struct ProofBytes {
pub proof: Vec<u8>,
pub public_values: Vec<u8>,
// TODO: use a hardcoded value for the vk
pub vk: Vec<u8>,
}

/// Contains the data ready to be sent to the on-chain verifiers.
Expand Down
29 changes: 29 additions & 0 deletions crates/networking/rpc/clients/eth/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1057,6 +1057,14 @@ impl EthClient {
.await
}

pub async fn get_sp1_vk(
&self,
on_chain_proposer_address: Address,
) -> Result<[u8; 32], EthClientError> {
self._call_bytes32_variable(b"SP1_VERIFICATION_KEY()", on_chain_proposer_address)
.await
}

pub async fn get_last_fetched_l1_block(
&self,
common_bridge_address: Address,
Expand Down Expand Up @@ -1167,6 +1175,27 @@ impl EthClient {
Ok(value)
}

async fn _call_bytes32_variable(
&self,
selector: &[u8],
contract_address: Address,
) -> Result<[u8; 32], EthClientError> {
let hex_string = self._generic_call(selector, contract_address).await?;

let hex = hex_string.strip_prefix("0x").ok_or(EthClientError::Custom(
"Couldn't strip '0x' prefix from hex string".to_owned(),
))?;

let bytes = hex::decode(hex)
.map_err(|e| EthClientError::Custom(format!("Failed to decode hex string: {}", e)))?;

let arr: [u8; 32] = bytes.try_into().map_err(|_| {
EthClientError::Custom("Failed to convert bytes to [u8; 32]".to_owned())
})?;

Ok(arr)
}

pub async fn wait_for_transaction_receipt(
&self,
tx_hash: H256,
Expand Down
41 changes: 36 additions & 5 deletions docs/l2/aligned_mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,21 @@ This document explains how to run an Ethrex L2 node in **Aligned mode** and high
> [!IMPORTANT]
> For this guide we assumed that there is an L1 running with all Aligned environment set.

### 1. Deploying L1 Contracts
### 1. Generate the SP1 ELF Program and Verification Key

Run:

```bash
cd ethrex/crates/l2
SP1_PROVER=cuda make build-prover PROVER=sp1 PROVER_CLIENT_ALIGNED=true
```

This will generate the SP1 ELF program and verification key under:
- `crates/l2/prover/zkvm/interface/sp1/out/riscv32im-succinct-zkvm-elf`
- `crates/l2/prover/zkvm/interface/sp1/out/riscv32im-succinct-zkvm-vk`


### 2. Deploying L1 Contracts

In a console with `ethrex/crates/l2` as the current directory, run the following command:

Expand All @@ -25,14 +39,15 @@ cargo run --release --bin ethrex_l2_l1_deployer --manifest-path contracts/Cargo.
--bridge-owner <ADDRESS> \
--on-chain-proposer-owner <ADDRESS> \
--private-keys-file-path <PRIVATE_KEYS_FILE_PATH> \
--sequencer-registry-owner <ADDRESS>
--sequencer-registry-owner <ADDRESS> \
--sp1-vk-path <SP1_VERIFICATION_KEY_PATH>
```

> [!NOTE]
> In this step we are initiallizing the `OnChainProposer` contract with the `ALIGNED_PROOF_AGGREGATOR_SERVICE_ADDRESS` and skipping the rest of verifiers.
> Save the addresses of the deployed proxy contracts, as you will need them to run the L2 node.

### 2. Deposit funds to the `AlignedBatchePaymentService` contract from the proof sender
### 3. Deposit funds to the `AlignedBatcherPaymentService` contract from the proof sender

```bash
aligned \
Expand All @@ -44,7 +59,7 @@ aligned \
> [!IMPORTANT]
> Using the [Aligned CLI](https://docs.alignedlayer.com/guides/9_aligned_cli)

### 3. Running a node
### 4. Running a node

In a console with `ethrex/crates/l2` as the current directory, run the following command:

Expand Down Expand Up @@ -90,6 +105,10 @@ SP1_PROVER=cuda make init-prover PROVER=sp1 PROVER_CLIENT_ALIGNED=true

## How to Run Using an Aligned Dev Environment

> [!IMPORTANT]
> This guide asumes you have already generated the SP1 ELF Program and Verification Key. See: [Generate the SP1 ELF Program and Verification Key](#1-generate-the-sp1-elf-program-and-verification-key)


### Set Up the Aligned Environment

1. Clone the Aligned repository and checkout the currently supported release:
Expand Down Expand Up @@ -207,12 +226,24 @@ SP1_PROVER=cuda make init-prover PROVER=sp1 PROVER_CLIENT_ALIGNED=true

### Aggregate proofs:

After some time, you will see that the `l1_proof_verifier` is waiting for Aligned to aggregate the proofs. You can aggregate them by running:
After some time, you will see that the `l1_proof_verifier` is waiting for Aligned to aggregate the proofs:
```
2025-06-18T22:03:53.470356Z INFO ethrex_l2::sequencer::l1_proof_verifier: Batch 1 has not yet been aggregated by Aligned. Waiting for 5 seconds
```

You can aggregate them by running:
```
cd aligned_layer
make start_proof_aggregator AGGREGATOR=sp1
```

If successful, the `l1_proof_verifier` will print the following logs:

```
INFO ethrex_l2::sequencer::l1_proof_verifier: Proof for batch 1 aggregated by Aligned with commitment 0xa9a0da5a70098b00f97d96cee43867c7aa8f5812ca5388da7378454580af2fb7 and Merkle root 0xa9a0da5a70098b00f97d96cee43867c7aa8f5812ca5388da7378454580af2fb7
INFO ethrex_l2::sequencer::l1_proof_verifier: Batch 1 verified in AlignedProofAggregatorService, with transaction hash 0x731d27d81b2e0f1bfc0f124fb2dd3f1a67110b7b69473cacb6a61dea95e63321
```

## Behavioral Differences in Aligned Mode

### Prover
Expand Down