Aligned
[!CAUTION]
To be used in testnet only.
Basic repo demoing a Stark/Snark verifier AVS middleware with full EigenLayer integration.
The Project
Aligned works with EigenLayer to leverage ethereum consensus mechanism for ZK proof verification. Working outside the EVM, this allows for cheap verification of any proving system. This enables the usage of cutting edge algorithms, that may use new techniques to prove even faster. Even more, proving systems that reduces the proving overhead and adds verifier overhead, now become economically feasable to verify thanks to Aligned.
Full documentation and examples will be added soon
Dependencies
You will need go, rust, foundry, zap-pretty, abigen, eigenlayer-cli,
celestia,
jq and yq to run the examples below.
To install zap-pretty and abigen
make deps
To install foundry
make install_foundry
Then follow the command line instructions
Make sure to run foundryup
To install eigenlayer-cli
make install_eigenlayer_cli
How to use Devnet
Start anvil
Start anvil with every relevant contract deployed with:
make anvil_start
The above command starts a local anvil chain from a saved state with EigenLayer and Aligned contracts already deployed (but no operator registered).
Start aggregator
Make sure to set config file variables to correct value at config-files/config.yaml.
To start the aggregator with a default configuration, run:
make aggregator_start
To use some custom configuration, set the CONFIG_FILE parameter with the path to your configuration file:
make aggregator_start CONFIG_FILE=<path_to_your_config>
To run dummy operator to test aggregator SubmitTaskResponse endpoint, run:
make aggregator_send_dummy_responses
Make sure to have aggregator running on another terminal.
That command sends one dummy response to the aggregator with a task index of 0.
If you use task sender to send a task, you will see response changes from 1 to 0,
since the aggregator will have a task index of 0.
Start operator
First make sure to build SP1 with:
make build_sp1_macos # or make build_sp1_linux on linux
To do the full process (register with EigenLayer, deposit into strategy and register with Aligned), run:
make operator_full_registration CONFIG_FILE=<path_to_config_file>
Once the registration process is done, start the operator with
make operator_start CONFIG_FILE=<path_to_config_file>
If CONFIG_FILE is not provided, it will use the default config file at config-files/config.yaml.
To use the default configuration file, just run:
make build_sp1_macos # or make build_sp1_linux on linux
make operator_full_registration
make operator_start
Start batcher
First create a .env file inside the batcher directory.
An example of the .env file can be found at batcher/.env.example.
You can configure the batcher with config-files/config.yaml.
The values it uses are:
batcher.block_interval
batcher.batch_size_interval
ecda.private_key_store_path
ecda.private_key_store_password
eth_rpc_url
eth_ws_url
aligned_layer_deployment_config_file_path
To start the batcher, run:
make batcher_start
To send a dummy task to the batcher, run:
make batcher_send_dummy_task PROVING_SYSTEM=<sp1|plonk_bls12_381|plonk_bn254|groth16_bn254> # Default is sp1
Send task
Sending a Task Using to the Batcher using our Rust TaskSender CLI
To send a task to the Batcher, using the Batcher TaskSendet CLI, you can use one of the following commands, which will send one proof to the batcher:
make batcher_send_sp1_task
make batcher_send_groth16_task
Also, you can send infinite different tasks to the batcher:
make batcher_send_infinite_tasks
If you wish to be more specific about what you want to send to the batcher, you can run the CLI yourself, as following:
./batcher/test-client/target/debug/test-client \
--proving_system <desired_proving_system> \
--proof <proof_file>
This CLI also has other optional flags (such as a public_input file, a Verification Key file or a vm_program file), visualizable by running
./batcher/test-client/target/debug/test-client --help
Sending a Task directly to the Smart Contract using our GO TaskSender CLI
You can also send a task directly to the AlignedLayer smart contract, bypassing the batcher. This option is available but not recommended since the sender must send a whole batch himself, thus incurring in extra costs.
Anyhow, you can send some preset proofs, such as:
make send_plonk_bls12_381_proof
make send_plonk_bn254_proof
make send_groth16_bn254_proof
make send_sp1_proof
Also, you can send infinite different proofs, as following:
make send_infinite_groth16_bn254_proof
If you wish to be more specific about what you want to send to the batcher, you can run the CLI yourseld, ass following:
go run task_sender/cmd/main.go send-task \
--proving-system <desired_proving_system> \
--proof <proof_file> \
--public-input <public_input_file> \
--config config-files/config.yaml \
2>&1 | zap-pretty
Sending a Task Using the TaskSender CLI
To send a task to the ServiceManager using the TaskSender CLI with a specific proving system, you can use one of the following commands depending on the proving system you wish to use:
This will send a dummy task to the ServiceManager and an event will be emitted.
You should see logs from the operator with the received task's index.
Make sure to have the ServiceManager deployed and anvil running on another terminal or background.
Developing workflows in testnet
Upgrade contracts
When changing EigenLayer contracts, the anvil state needs to be updated with:
make anvil_deploy_eigen_contracts
You will also need to redeploy the MockStrategy & MockERC20 contracts:
make anvil_deploy_mock_strategy
When changing Aligned contracts, the anvil state needs to be updated with:
make anvil_deploy_aligned_contracts
Also make sure to re-generate the Go smart contract bindings:
make bindings
Operator registration step by step (WIP Guide)
When not using the default address, get eth with:
make operator_get_eth
Update the config in:
operator/config/devnet/config.yaml
operator/config/devnet/operator.yaml
To register with EigenLayer, run:
make operator_register_with_eigen_layer
To get mock tokens (DEVNET ONLY), run:
make operator_mint_mock_tokens
To deposit into strategy, and register with Aligned, run:
make operator_deposit_and_register
To just deposit into the strategy run:
export STRATEGY_ADDRESS=<strategy_address> && make operator_deposit_into_strategy
To deposit into mock strategy (DEVNET ONLY), run:
make operator_deposit_into_mock_strategy
To just register an operator with Aligned, run:
make operator_register_with_aligned_layer
Testnet/Mainnet Deployment
To deploy the contracts to Testnet/Mainnet, you will need to set environment variables
in a .env file in the same directory as the deployment script (contracts/scripts/).
The variables are as follows:
| Variable |
Description |
| RPC_URL |
The RPC URL of the network you want to deploy to. |
| PRIVATE_KEY |
The private key of the account you want to deploy the contracts with. |
| EXISTING_DEPLOYMENT_INFO_PATH |
The path to the file containing the deployment info about EigenLayer. |
| DEPLOY_CONFIG_PATH |
The path to the deployment config file. |
| OUTPUT_PATH |
The path to the file where the deployment info will be saved. |
Then run the following command:
make deploy_aligned_contracts
To get the existing deployment info about EigenLayer, you can download it
from EigenLayer repo.
You need to complete the DEPLOY_CONFIG_PATH file with the following information:
{
"chainInfo": {
"chainId": "<chain_id>"
},
"permissions" : {
"owner": "<owner_address>",
"aggregator": "<aggregator_address>",
"upgrader": "<upgrader_address>",
"churner": "<churner_address>",
"ejector": "<ejector_address>",
"deployer": "<deployer_address>",
"initalPausedStatus": 0
},
"minimumStakes": [],
"strategyWeights": [],
"operatorSetParams": [],
"uri": ""
}
You can find an example config file in contracts/script/deploy/config/holesky/aligned.holesky.config.json.
Notes on project creation / devnet deployment
Eigenlayer middleware was installed as a submodule with:
mkdir contracts
cd contacts
forge init . --no-commit
forge install Layr-Labs/eigenlayer-middleware@mainnet
Then to solve the issue https://github.com/Layr-Labs/eigenlayer-middleware/issues/229, we changed it to:
forge install yetanotherco/eigenlayer-middleware@yac-mainnet --no-commit
As soon as it gets fixed in mainnet we can revert it.
Base version of middleware used is 7229f2b
The script to initialize the devnet can be found on contracts/scripts/anvil
The addresses of the relevant contracts after running the anvil script is dumped on contracts/script/output/devnet.
The state is backuped on contracts/scripts/anvil/state
Eigenlayer contract deployment is almost the same as the EigenLayer contract deployment on mainnet. Changes are described on the file.
Strategies
The strategy contract is a contract where operators deposit restaked tokens.
For test purposes, we have a dummy strategy contract that takes a Mock ERC20 token.
Aggregator
Current aggregator implementation is WIP. The RPC method Aggregator.SubmitTaskResponse expects a SignedTaskResponse
as body and returns 0 if args.TaskIndex exists, and 1 otherwise.
Check common/types/signed_task_response.go for specification on SignedTaskResponse.
Operator
The following section is instructions on how to create an operator from scratch.
You can find more details on the EigenLayer documentation.
To create an operator, you will need to generate keys, generate a config, and register with EigenLayer.
To generate the operator keys, run:
make operator_generate_keys
This will output key paths & address, make sure to store them for following steps.
To generate a new operator config, run the command
make operator_generate_config
Then follow the instructions to populate the file
You will then need to populate two additional values, which are metadata_url and el_delegation_manager_address
To get the Delegation Manager Address of the last devnet deployment you can run:
make get_delegation_manager_address
For the metadata URL you can either use our example URL:
https://yetanotherco.github.io/operator_metadata/
Or Deploy your metadata to your own sever (can be GitHub Pages)
You can get devnet Ether for gas by running:
make operator_get_eth
Make sure to set OPERATOR_ADDRESS enviroment variable to your own address before running command.
This will send 1 eth to that address
Then you can register with EigenLayer by running:
make operator_register_with_eigen_layer
Config File
In config-files/config.yaml you can find the configuration file for the project.
There is a section for operator, aggregator, and keys. Also, there are common variables for the project.
There are also three other configuration files in the config-files directory for operators. They have their own keys and addresses.
Metrics
Aggregator Metrics
Aggregator metrics are exposed on the /metrics endpoint.
If you are using the default config, you can access the metrics on http://localhost:9091/metrics.
To run Prometheus and Grafana just run:
make run_metrics
Then you can access Grafana on http://localhost:3000 with the default credentials admin:admin.
If you want to install Prometheus and Grafana manually, you can follow the instructions below.
To install Prometheus, you can follow the instructions on the official website.
To install Grafana, you can follow the instructions on the official website.
FAQ
What is the objective of Aligned?
Aligned’s mission is to extend Ethereum’s zero-knowledge capabilities. We are certain the zero-knowledge proofs will have a key role in the future of blockchains and computation. We don’t know what that future will look like, but we are certain it will be in Ethereum. The question we want to share is: If we are certain zero-knowledge proofs are the future of Ethereum but we are not certain which of the many possible zero-knowledge futures will win. How can we build an infrastructure for Ethereum to be compatible with any future zero-knowledge proving system?
Why do we need a ZK verification layer?
Verifiable computation allows developers to build applications that help Ethereum scale or even create applications that were not possible before. We believe the future of Ethereum will be shaped by zero-knowledge and validity proofs, helping it increase its capabilities.
What are the use cases of Aligned?
Among the possible use cases of Aligned we have:
Soft finality for Rollups and Appchains, fast bridging, new settlement layers (use Aligned + EigenDA) for Rollups and Intent based systems, P2P protocols based on SNARKs such as payment systems and social networks, alternative L1s interoperable with Ethereum, Verifiable Machine Learning, cheap verification and interoperability for Identity Protocols, ZK Oracles, new credential protocols such as zkTLS based systems, ZK Coprocessor, encrypted Mempools using SNARKs to show the correctness of the encryption, protocols against misinformation and fake news, and on-chain gaming.
Why build on top of Ethereum?
Ethereum is the most decentralized and biggest source of liquidity in the crypto ecosystem. We believe it is the most ambitious and long-term project on the internet. Aligned is being built to help Ethereum achieve its highest potential, and we believe this is only possible through validity/zero-knowledge proofs.
Why not do this directly on top of Ethereum?
In order to do this we would have to aggregate all the proofs into a single proof. This is not a good solution considering that we would need some way to wrap proofs (for example, by means of recursion), which involves complex operations such as field emulation, bitwise, and/or elliptic curve operations.
Why not make Aligned a ZK L1?
An L1 would not have the security properties of Ethereum consensus, and bootstrapping a new decentralized network is not only expensive but might be an impossible task. Zero-knowledge proofs are a nascent technology, and change is a constant. The best solution for today may not be the best for tomorrow; modifying L1s is extremely costly, especially as time progresses.
Why not a ZK L2?
An L2 needs to use the EVM to settle in Ethereum. This means that the proofs need to be efficiently verified in the EVM, and their data made available there.
The EVM is not designed for ZK Verification, so most verifications are expensive.
To solve this, for pairing-based cryptography, Ethereum has added a precompile for verifications using the curve BN254.
But technology changes fast. BN254 security was demonstrated to be around 100 bits instead of the expected 128. Fast Starks need efficient hashing for fields. Which is the best field? Mersenne’s? Goldilocks? Binary fields? What about the sumcheck protocol? Is Jolt the endgame? Or is GKR going to be faster?
The amount of progress in the field is big, and nobody can predict the endgame.
Even more, it would be naive to think that only one optimized prover will exist in the future. In the world of ZK, as in many others, there are trade-offs and systems that solve different problems.
Maybe we want faster proving and don't care about proof size. Maybe we want the fastest proof verification and smallest size and can do more work on the prover. The system may be optimized to prove Keccak really fast. Or we can skip the traditional hashes altogether and just optimize for Poseidon, Rescue, or one hash not created yet.
Aligned solves all of this. No matter how or what you want to prove, it can be verified efficiently here while still inheriting the security of Ethereum as other L2s.
Why EigenLayer?
We believe Ethereum is the best settlement layer, and zero-knowledge will play a key role in helping it be THE settlement layer of the internet. We want to build a verification layer that helps Ethereum achieve this goal. This layer needs to have a decentralized group of validators that will just re-execute the verification of different proofs, but how can we build such a decentralized network that will help Ethereum? Creating a new L1 doesn’t benefit Ethereum because using it will add new trust assumptions to the Ethereum protocols relying on it. So, if we must have:
- A decentralized network of verifiers
- A similar economic security level that can be easily measured in Ethereum
- Part of the Ethereum ecosystem
- Flexible enough to support many current and future proving systems
Will you aggregate proofs?
Proof aggregation can also be supported by proving the verification of many of these different verifications. This will likely not be an urgent feature, but it will be needed in the future with more demand.
How does it compare to the Polygon aggregation layer?
Aligned is just a network of decentralized verifiers renting security from Ethereum. On the other hand, the Polygon aggregation layer, in essence, is a rollup verifying multiple proofs. That is not the case for Aligned, which just executes a rust binary from different verifiers directly in multiple Ethereum validators.