Skip to content

Commit

Permalink
Merge branch 'main' into willem/full-prover-tests-behind-feature
Browse files Browse the repository at this point in the history
  • Loading branch information
willemolding authored Nov 27, 2023
2 parents 18a0c5d + 6902971 commit 4b76903
Show file tree
Hide file tree
Showing 39 changed files with 1,189 additions and 401 deletions.
13 changes: 13 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
DEPLOYER_PRIVATE_KEY="<private-key-here>"

LOCAL_RPC_URL="http://localhost:8545"
MAINNET_RPC_URL="https://mainnet.infura.io/ws/v3/<Your-API-Key>"
GOERLI_RPC_URL="https://goerli.infura.io/ws/v3/<Your-API-Key>"
SEPOLIA_RPC_URL="https://sepolia.infura.io/ws/v3/<Your-API-Key>"

# These two variables define the starting point for the Spectre light-client.
INITIAL_SYNC_PERIOD=10 # sync period for the initial committee
INITIAL_COMMITTEE_POSEIDON="0x9ab5d3df6912b5bfeeb8e33b5bddad7c3a4f448fd99804dae38c3641f55680fe" # hex encoded poseidon hash of the initial committee

# This is a fixed property of the chain that Spectre is acting as a light-client for
SLOTS_PER_PERIOD=8192 # 8192 = 256 epochs * 32 slots for mainnet ethereum.
23 changes: 8 additions & 15 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ incremental = true
[workspace.dependencies]
lightclient-circuits = { path = "lightclient-circuits" }
test-utils = { path = "test-utils" }
ethereum-consensus-types = { git = "ssh://[email protected]/sygmaprotocol/Zipline.git", rev = "27e8a01" }
ethereum-consensus-types = { git = "ssh://[email protected]/sygmaprotocol/Zipline.git", rev = "5ecf28d24690862814a7ebc5385c7e5c2eeb6e3d" }
eth-types = { path = "eth-types" }
contracts = { path = "contracts" }
preprocessor = { path = "preprocessor" }
ssz-rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "adf1a0b14cef90b9536f28ef89da1fab316465e1" }
zipline-test-utils = { package = "test-utils", git = "ssh://[email protected]/sygmaprotocol/Zipline.git", rev = "27e8a01" }
light-client-verifier = { git = "ssh://[email protected]/sygmaprotocol/Zipline.git", rev = "27e8a01" }
sync-committee-primitives = { git = "https://github.com/polytope-labs/sync-committee-rs", version = "0.1.0" }
zipline-test-utils = { package = "test-utils", git = "ssh://git@github.com/sygmaprotocol/Zipline.git", rev = "5ecf28d24690862814a7ebc5385c7e5c2eeb6e3d" }
zipline-cryptography = { package = "cryptography", git = "ssh://[email protected]/sygmaprotocol/Zipline.git", rev = "5ecf28d24690862814a7ebc5385c7e5c2eeb6e3d" }
light-client-verifier = { git = "ssh://[email protected]/sygmaprotocol/Zipline.git", rev = "5ecf28d24690862814a7ebc5385c7e5c2eeb6e3d" }
beacon-api-client = { git = "https://github.com/ralexstokes/ethereum-consensus.git", rev = "f3bff52e9c43866f231ec40c8ab0e34125a8957f" }

# halo2
halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2.git", tag = "v2023_02_02", features = [
Expand Down Expand Up @@ -60,10 +60,7 @@ snark-verifier-sdk = { git = "https://github.com/axiom-crypto/snark-verifier.git
] }
halo2_solidity_verifier = { git = "https://github.com/privacy-scaling-explorations/halo2-solidity-verifier", branch = "ac/initial-verifier-PR" }

# ethereum types
sync-committee-prover = { git = "https://github.com/polytope-labs/sync-committee-rs", version = "0.1.0", features = [
"testnet",
] }
ssz_rs = "0.9"

# crypto
group = "0.12"
Expand Down Expand Up @@ -94,9 +91,5 @@ poseidon = { git = "https://github.com/timoftime/halo2-lib", rev = "95bf9a5ce6b6
snark-verifier = { git = "https://github.com/timoftime/snark-verifier", branch = "timoftime/bump-revm" }
snark-verifier-sdk = { git = "https://github.com/timoftime/snark-verifier", branch = "timoftime/bump-revm" }

[patch."https://github.com/ralexstokes/ssz-rs"]
ssz-rs = { git = "https://github.com/polytope-labs/ssz-rs", branch = "main" }

[patch."https://github.com/polytope-labs/sync-committee-rs"]
sync-committee-prover = { git = "https://github.com/timoftime/sync-committee-rs", branch = "dev/accept-ssz" }
sync-committee-primitives = { git = "https://github.com/timoftime/sync-committee-rs", branch = "dev/accept-ssz" }
[patch.crates-io]
ssz_rs = { git = "https://github.com/ralexstokes/ssz-rs", rev = "5f1ec833718efa07bbbff427ab28a1eeaa706164" }
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,34 @@
# Spectre
Spectre is a ZK-based block header oracle protocol based on Altair fork light-client sync protocol.

## Deploying contracts

Just scripts are provided to deploy the contracts either to a local testnet, or public networks.

For either make a copy of the `.env.example` file called `.env`. Set the `INITIAL_SYNC_PERIOD`, `INITIAL_COMMITTEE_POSEIDON` and `SLOTS_PER_PERIOD` variables according to the network you want Spectre to act as a light-client for and the starting point.

### Deploying locally

1. Start a local anvil instance with:

```shell
anvil
```

2. Copy one of the private key strings printed into the `DEPLOYER_PRIVATE_KEY` in the `.env` file then run

```shell
just deploy-contracts-local
```

### Deploying to a public network

1. Obtain the required gas token and obtain the private key for the deployer account. Set the `DEPLOYER_PRIVATE_KEY` in the `.env` file.
2. Obtain a public RPC URL for the network and set the variable `<NETWORK>_RPC_URL` in the `.env` file (If using Infura this will require an API key)
3. Run

```shell
just deploy-contracts <NETWORK>
```

where `<NETWORK>` is one of `["GOERLI", "SEPOLIA", "MAINNET"]`.
2 changes: 1 addition & 1 deletion contract-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ lightclient-circuits = { workspace = true }
test-utils = { workspace = true }
halo2curves = { workspace = true }
eth-types = { workspace = true }
ssz-rs = { workspace = true }
ssz_rs = { workspace = true }
halo2-base = { workspace = true }
snark-verifier-sdk = { workspace = true }
contracts = { workspace = true }
8 changes: 5 additions & 3 deletions contract-tests/tests/rotation_input_encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ use ethers::contract::abigen;
use halo2curves::bn256::{self, Fr};
use itertools::Itertools;
use lightclient_circuits::committee_update_circuit::CommitteeUpdateCircuit;
use lightclient_circuits::poseidon::poseidon_committee_commitment_from_compressed;
use lightclient_circuits::witness::CommitteeRotationArgs;
use rstest::rstest;
use ssz_rs::prelude::*;
use ssz_rs::Merkleized;
use test_utils::{poseidon_committee_commitment_from_compressed, read_test_files_and_gen_witness};
use std::ops::Deref;
use test_utils::read_test_files_and_gen_witness;

abigen!(
RotateExternal,
Expand All @@ -33,7 +35,7 @@ async fn test_rotate_public_input_evm_equivalence(
.clone()
.hash_tree_root()
.unwrap()
.as_bytes()
.deref()
.try_into()
.unwrap();

Expand Down Expand Up @@ -91,7 +93,7 @@ where
let sync_committee_ssz = pk_vector
.hash_tree_root()
.unwrap()
.as_bytes()
.deref()
.try_into()
.unwrap();

Expand Down
10 changes: 5 additions & 5 deletions contract-tests/tests/step_input_encoding.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
use std::ops::Deref;
use std::path::PathBuf;

use contract_tests::make_client;
use eth_types::Minimal;
use ethers::contract::abigen;
use halo2curves::bn256;
use lightclient_circuits::poseidon::poseidon_committee_commitment_from_uncompressed;
use lightclient_circuits::sync_step_circuit::SyncStepCircuit;
use lightclient_circuits::witness::SyncStepArgs;
use rstest::rstest;
use ssz_rs::Merkleized;
use test_utils::{
poseidon_committee_commitment_from_uncompressed, read_test_files_and_gen_witness,
};
use test_utils::read_test_files_and_gen_witness;

abigen!(
SyncStepExternal,
Expand Down Expand Up @@ -57,7 +57,7 @@ impl<Spec: eth_types::Spec> From<SyncStepArgs<Spec>> for SyncStepInput {
.clone()
.hash_tree_root()
.unwrap()
.as_bytes()
.deref()
.try_into()
.unwrap();

Expand All @@ -66,7 +66,7 @@ impl<Spec: eth_types::Spec> From<SyncStepArgs<Spec>> for SyncStepInput {
SyncStepInput {
attested_slot: args.attested_header.slot,
finalized_slot: args.finalized_header.slot,
participation: participation,
participation,
finalized_header_root,
execution_payload_root,
}
Expand Down
4 changes: 0 additions & 4 deletions contracts/.env.example

This file was deleted.

4 changes: 1 addition & 3 deletions contracts/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ cache/
out/

# Ignores development broadcast logs
!/broadcast
/broadcast/*/31337/
/broadcast/**/dry-run/
broadcast/

# Docs
docs/
Expand Down
6 changes: 6 additions & 0 deletions contracts/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,9 @@ path = "rust-abi/lib.rs"

[dependencies]
ethers = "2.0.10"
lightclient-circuits.workspace = true
eth-types.workspace = true
ssz_rs.workspace = true
halo2curves = { workspace = true }
itertools = { workspace = true }
halo2-base = { workspace = true }
5 changes: 3 additions & 2 deletions contracts/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ fs_permissions = [{ access = "read", path = "./test/data/"}]
constantOptimizer = true
yul = false

# See more config options https://github.com/foundry-rs/foundry/tree/master/config

[rpc_endpoints]
mainnet = "${MAINNET_RPC_URL}"
goerli = "${GOERLI_RPC_URL}"
sepolia = "${SEPOLIA_RPC_URL}"
local = "${LOCAL_RPC_URL}"
117 changes: 103 additions & 14 deletions contracts/rust-abi/lib.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,109 @@
use ethers::contract::abigen;

abigen!(Spectre, "./out/Spectre.sol/Spectre.json");

abigen!(StepVerifier, "./out/sync_step.sol/Verifier.json");
#![feature(generic_const_exprs)]
use std::ops::Deref;

use ethers::contract::abigen;
use halo2_base::utils::ScalarField;
use halo2curves::bls12_381::{self};
use halo2curves::bn256::Fr;
use itertools::Itertools;
use lightclient_circuits::{
poseidon::fq_array_poseidon_native,
witness::{CommitteeRotationArgs, SyncStepArgs},
};
use ssz_rs::{Merkleized, Vector};
abigen!(
Spectre,
"./out/Spectre.sol/Spectre.json";
StepVerifier,
"./out/sync_step.sol/Verifier.json";
CommitteeUpdateVerifier,
"./out/committee_update_aggregated.sol/Verifier.json"
);

abigen!(
"./out/committee_update_aggregated.sol/Verifier.json";
StepMockVerifier,
"./out/SyncStepMockVerifier.sol/SyncStepMockVerifier.json"
);

abigen!(
"./out/SyncStepMockVerifier.sol/SyncStepMockVerifier.json";
CommitteeUpdateMockVerifier,
"./out/CommitteeUpdateMockVerifier.sol/CommitteeUpdateMockVerifier.json"
"./out/CommitteeUpdateMockVerifier.sol/CommitteeUpdateMockVerifier.json";
RotateExternal,
"./out/RotateExternal.sol/RotateExternal.json";
SyncStepExternal,
"./out/SyncStepExternal.sol/SyncStepExternal.json";
);

// SyncStepInput type produced by abigen macro matches the solidity struct type
impl<Spec: eth_types::Spec> From<SyncStepArgs<Spec>> for SyncStepInput {
fn from(args: SyncStepArgs<Spec>) -> Self {
let participation = args
.pariticipation_bits
.iter()
.map(|v| *v as u64)
.sum::<u64>();

let finalized_header_root: [u8; 32] = args
.finalized_header
.clone()
.hash_tree_root()
.unwrap()
.deref()
.try_into()
.unwrap();

let execution_payload_root: [u8; 32] = args.execution_payload_root.try_into().unwrap();

SyncStepInput {
attested_slot: args.attested_header.slot,
finalized_slot: args.finalized_header.slot,
participation,
finalized_header_root,
execution_payload_root,
}
}
}

// CommitteeRotationArgs type produced by abigen macro matches the solidity struct type
impl<Spec: eth_types::Spec> From<CommitteeRotationArgs<Spec, Fr>> for RotateInput
where
[(); Spec::SYNC_COMMITTEE_SIZE]:,
{
fn from(args: CommitteeRotationArgs<Spec, Fr>) -> Self {
let poseidon_commitment_le = poseidon_committee_commitment_from_compressed(
&args
.pubkeys_compressed
.iter()
.cloned()
.map(|mut b| {
b.reverse();
b
})
.collect_vec(),
);

let mut pk_vector: Vector<Vector<u8, 48>, { Spec::SYNC_COMMITTEE_SIZE }> = args
.pubkeys_compressed
.iter()
.cloned()
.map(|v| v.try_into().unwrap())
.collect_vec()
.try_into()
.unwrap();

let sync_committee_ssz = pk_vector
.hash_tree_root()
.unwrap()
.deref()
.try_into()
.unwrap();

RotateInput {
sync_committee_ssz,
sync_committee_poseidon: poseidon_commitment_le,
}
}
}

pub fn poseidon_committee_commitment_from_compressed(pubkeys_compressed: &[Vec<u8>]) -> [u8; 32] {
let pubkeys_x = pubkeys_compressed.iter().cloned().map(|mut bytes| {
bytes[47] &= 0b00011111;
bls12_381::Fq::from_bytes_le(&bytes)
});
let poseidon_commitment = fq_array_poseidon_native::<Fr>(pubkeys_x).unwrap();
poseidon_commitment.to_bytes_le().try_into().unwrap()
}
27 changes: 27 additions & 0 deletions contracts/script/DeploySpectre.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "forge-std/Script.sol";

import {Spectre} from "../src/Spectre.sol";
import {Verifier as SyncStepVerifier} from "../snark-verifiers/sync_step.sol";
import {Verifier as CommitteeUpdateVerifier} from "../snark-verifiers/committee_update_aggregated.sol";

contract DeploySpectre is Script {

function run() external {
uint256 deployerPrivateKey = vm.envUint("DEPLOYER_PRIVATE_KEY");
uint256 initialSyncPeriod = vm.envUint("INITIAL_SYNC_PERIOD");
bytes32 initialCommitteePoseidon = vm.envBytes32("INITIAL_COMMITTEE_POSEIDON");
uint256 slotsPerPeriod = vm.envUint("SLOTS_PER_PERIOD");

vm.startBroadcast(deployerPrivateKey);

SyncStepVerifier stepVerifier = new SyncStepVerifier();
CommitteeUpdateVerifier updateVerifier = new CommitteeUpdateVerifier();

Spectre spectre = new Spectre(address(stepVerifier), address(updateVerifier), initialSyncPeriod, initialCommitteePoseidon, slotsPerPeriod);

vm.stopBroadcast();
}
}
23 changes: 0 additions & 23 deletions contracts/script/SpectreDeployLocal.s.sol

This file was deleted.

6 changes: 0 additions & 6 deletions contracts/script/deploy_local.sh

This file was deleted.

2 changes: 1 addition & 1 deletion contracts/snark-verifiers/sync_step.sol

Large diffs are not rendered by default.

Loading

0 comments on commit 4b76903

Please sign in to comment.