Skip to content

Commit

Permalink
Merge branch 'main' into drand-voting
Browse files Browse the repository at this point in the history
  • Loading branch information
raugfer authored Dec 18, 2024
2 parents f0bb557 + ea2b7b6 commit 136a0f9
Show file tree
Hide file tree
Showing 168 changed files with 63,488 additions and 110,608 deletions.
78 changes: 78 additions & 0 deletions .github/scripts/declare_maintained_contracts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import asyncio
import os
from enum import Enum
from pathlib import Path

import dotenv
from starknet_py.net.account.account import Account
from starknet_py.net.full_node_client import FullNodeClient
from starknet_py.net.models import StarknetChainId
from starknet_py.net.signer.stark_curve_signer import KeyPair

from garaga.hints.io import to_int
from garaga.starknet.cli.smart_contract_project import SmartContractProject

dotenv.load_dotenv(".secrets")


class Network(Enum):
SEPOLIA = "sepolia"
MAINNET = "mainnet"

def to_starknet_chain_id(self):
if self == Network.SEPOLIA:
return StarknetChainId.SEPOLIA
elif self == Network.MAINNET:
return StarknetChainId.MAINNET
else:
raise ValueError(f"Unknown network: {self}")


class Fee(Enum):
ETH = "eth"
STRK = "strk"


def get_account(network: Network):
rpc_url = os.getenv(f"{network.value.upper()}_RPC_URL")
account_address = os.getenv(f"{network.value.upper()}_ACCOUNT_ADDRESS")
account_private_key = os.getenv(f"{network.value.upper()}_ACCOUNT_PRIVATE_KEY")

client = FullNodeClient(node_url=rpc_url)
account = Account(
address=account_address,
client=client,
key_pair=KeyPair.from_private_key(to_int(account_private_key)),
chain=network.to_starknet_chain_id(),
)
return account


async def declare_contract_from_path(path: Path, network: Network, fee: Fee):
contract = SmartContractProject(smart_contract_folder=path)
account = get_account(network)
await contract.declare_class_hash(account=account, fee=fee.value)


async def declare_contract_from_path_both_networks(path: Path, fee: Fee):
await declare_contract_from_path(path, Network.SEPOLIA, fee)
await declare_contract_from_path(path, Network.MAINNET, fee)


if __name__ == "__main__":
asyncio.run(
declare_contract_from_path_both_networks(
Path("src/contracts/universal_ecip"), Fee.STRK
)
)
asyncio.run(
declare_contract_from_path_both_networks(
Path("src/contracts/drand_quicknet"), Fee.STRK
)
)

asyncio.run(
declare_contract_from_path_both_networks(
Path("src/contracts/risc0_verifier_bn254"), Fee.STRK
)
)
70 changes: 70 additions & 0 deletions .github/scripts/verify_contracts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import ast
import asyncio
import sys
from enum import Enum
from pathlib import Path

from starknet_py.net.full_node_client import FullNodeClient

import garaga.hints.io as io
from garaga.starknet.cli.smart_contract_project import SmartContractProject


class Network(Enum):
SEPOLIA = "sepolia"
MAINNET = "mainnet"


def get_class_hash_from_generator():
try:
with open(
"hydra/garaga/starknet/groth16_contract_generator/generator.py", "r"
) as f:
tree = ast.parse(f.read())
for node in ast.walk(tree):
if isinstance(node, ast.Assign) and len(node.targets) == 1:
if getattr(node.targets[0], "id", None) == "ECIP_OPS_CLASS_HASH":
return hex(node.value.value)
raise ValueError("ECIP_OPS_CLASS_HASH not found in generator.py")
except Exception as e:
print(f"Error parsing generator.py: {str(e)}", file=sys.stderr)
sys.exit(1)


async def verify_network(network: Network, class_hash: str):
class_hash = io.to_hex_str(class_hash)
print(f"\nVerifying class hash {class_hash} on {network.value}...")
client = FullNodeClient(f"https://free-rpc.nethermind.io/{network.value}-juno")
try:
result = await client.get_class_by_hash(class_hash)
if not result:
print(f"Error: Contract not declared on {network.value}", file=sys.stderr)
sys.exit(1)
print(f"✓ Contract verified on {network.value}")
except Exception as e:
print(f"Error checking {network.value}: {str(e)}", file=sys.stderr)
sys.exit(1)


async def verify_ecip_contract():
class_hash = get_class_hash_from_generator()
print(f"Verifying ECIP contract using class hash: {class_hash}")

await verify_network(Network.SEPOLIA, class_hash)
await verify_network(Network.MAINNET, class_hash)

print("\n✓ Contract verified on both networks")


async def verify_contract_from_path(path: Path):
contract = SmartContractProject(smart_contract_folder=path)
class_hash = contract.get_sierra_class_hash()
print(f"Verifying contract {path} with class hash {io.to_hex_str(class_hash)}")
await verify_network(Network.SEPOLIA, class_hash)
await verify_network(Network.MAINNET, class_hash)


if __name__ == "__main__":
asyncio.run(verify_ecip_contract())
asyncio.run(verify_contract_from_path(Path("src/contracts/drand_quicknet")))
asyncio.run(verify_contract_from_path(Path("src/contracts/risc0_verifier_bn254")))
2 changes: 1 addition & 1 deletion .github/workflows/cairo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
- uses: actions/checkout@v3
- uses: software-mansion/setup-scarb@v1
with:
scarb-version: "2.8.2"
scarb-version: "2.9.1"
- run: scarb fmt --check
working-directory: src/
- run: cd src/ && scarb test
2 changes: 1 addition & 1 deletion .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
- name: Setup Scarb
uses: software-mansion/setup-scarb@v1
with:
scarb-version: "2.8.2"
scarb-version: "2.9.1"
- name: Install dependencies
run: make setup

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/hydra.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
- name: Set up Scarb
uses: software-mansion/setup-scarb@v1
with:
scarb-version: "2.8.2"
scarb-version: "2.9.1"
- name: Run make rewrite and check for unstaged changes
run: |
source venv/bin/activate
Expand Down
40 changes: 26 additions & 14 deletions .github/workflows/maturin.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
# This file is autogenerated by maturin v1.7.0
# To update, run
#
# maturin generate-ci github
#
name: CI

on:
push:
branches:
Expand Down Expand Up @@ -40,7 +34,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: 3.x
python-version: "3.10.x"
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
Expand Down Expand Up @@ -71,7 +65,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: 3.x
python-version: "3.10.x"
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
Expand All @@ -98,7 +92,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: 3.x
python-version: 3.10.x
architecture: ${{ matrix.platform.target }}
- name: Build wheels
uses: PyO3/maturin-action@v1
Expand All @@ -117,16 +111,15 @@ jobs:
strategy:
matrix:
platform:
- runner: macos-12
- runner: macos-14
target: x86_64
- runner: macos-14
target: aarch64
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
# Workaround to ensure python 3.10 is available on x86_64
python-version: ${{ matrix.platform.target == 'x86_64' && '3.10' || '3.x' }}
python-version: "3.10.x"
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
Expand Down Expand Up @@ -157,10 +150,29 @@ jobs:
release:
name: Release
runs-on: ubuntu-latest
# Note this will only run when a new tag is pushed
if: "startsWith(github.ref, 'refs/tags/')"
if: "startsWith(github.ref, 'refs/tags/')" # Only run on tag pushes
needs: [linux, musllinux, windows, macos, sdist]
steps:
- uses: actions/checkout@v4
- name: Set up Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
profile: minimal
components: rustfmt

- uses: software-mansion/setup-scarb@v1
with:
scarb-version: "2.9.1"
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10.x"
- name: Install dependencies
run: make setup
- name: Verify Contract Declaration
run: source venv/bin/activate && python .github/scripts/verify_contracts.py
- uses: actions/download-artifact@v4
- name: Publish to PyPI
uses: PyO3/maturin-action@v1
Expand Down
24 changes: 21 additions & 3 deletions .github/workflows/wasm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,29 @@ jobs:
release:
name: Release
runs-on: ubuntu-latest
# Note this will only run when a new tag is pushed
if: "startsWith(github.ref, 'refs/tags/')"
if: "startsWith(github.ref, 'refs/tags/')" # Only run on tag pushes
needs: [build, test, test-integration]
steps:
- uses: actions/checkout@v4
- name: Set up Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
profile: minimal
components: rustfmt

- uses: software-mansion/setup-scarb@v1
with:
scarb-version: "2.9.1"
- name: Set up Python 3.10.14
uses: actions/setup-python@v5
with:
python-version: 3.10.14
- name: Install dependencies
run: make setup
- name: Verify Contract Declaration
run: source venv/bin/activate && python .github/scripts/verify_contracts.py
- uses: actions/setup-node@v4
with:
node-version: 'lts/*'
Expand All @@ -90,7 +109,6 @@ jobs:
name: npm-package
- name: Publish to npm
run: |
npm login
npm publish --access=public *.tgz
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_API_TOKEN }}
11 changes: 4 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,7 @@ Garaga currently supports:
- Scalar & Multi-scalar multiplication for any Weirstrass curve, including BN254, BLS12_381, SECP256/R1, and ED25519. You can add the one you need by specifying the curve parameters.
- Pairing operations for BN254 and BLS12_381.
- Groth16 smart contract verifiers generators for BN254 and BLS12_381.

Following supported schemes will be
- BLS signatures contract generators.
- Plonk based SNARKs verifier, especially Noir.
- Noir smart contract verifiers generators for ultra keccak honk flavour.


## Architecture overview
Expand All @@ -62,9 +59,9 @@ Currently, only Groth16 on BN254 and BLS12_381 is supported with automatic suppo
6. Run the `garaga declare` command in your terminal to declare the smart contract on Starknet and obtain its class hash. Note that this is an expensive operation.
7. Run the `garaga deploy` command in your terminal using the class hash obtained in the previous step to get the contract address.

7. Run the `garaga verify-onchain` command in your terminal using the contract address, the verification key, the proof and the public inputs to verify the proof against the SNARK verifier contract.
8. Run the `garaga verify-onchain` command in your terminal using the contract address, the verification key, the proof and the public inputs to verify the proof against the SNARK verifier contract.

For more details, please refer to the [documentation](https://felt.gitbook.io/garaga/).
For more details, please refer to the [documentation](https://garaga.gitbook.io/garaga/).

## Developer setup

Expand All @@ -74,7 +71,7 @@ To get started with Garaga, you'll need to have some tools and dependencies inst

Ensure you have the following installed:
- [Python 3.10](https://www.python.org/downloads/) - /!\ Make sure `python3.10` is a valid command in your terminal. The core language used for development. Make sure you have the correct dependencies installed (in particular, GMP) for the `fastecdsa` python package. See [here](https://pypi.org/project/fastecdsa/#installing) for linux and [here](https://github.com/AntonKueltz/fastecdsa/issues/74) for macos.
- [Scarb 2.8.2](https://docs.swmansion.com/scarb/download.html) - The Cairo package manager. Comes with Cairo inside. Requires [Rust](https://www.rust-lang.org/tools/install).
- [Scarb 2.9.1](https://docs.swmansion.com/scarb/download.html) - The Cairo package manager. Comes with Cairo inside. Requires [Rust](https://www.rust-lang.org/tools/install).

##### Optionally :

Expand Down
Loading

0 comments on commit 136a0f9

Please sign in to comment.