Skip to content

Latest commit

 

History

History
357 lines (258 loc) · 12 KB

File metadata and controls

357 lines (258 loc) · 12 KB

Usage

Clementine provides a single binary that can act as 3 different actor services:

  • Verifier (sometimes called a signer)
  • Operator
  • Aggregator

These services communicate via gRPC and use a PostgreSQL database. They can be configured to share the same database.

An entity can choose to run these services on a single host to be a part of the peg-in and peg-out process. All the services that are run by a single entity should ideally share the same database. Typical entities are:

  • Operator entity
    • Runs both an operator and a verifier service
  • Verifier entity
    • Runs a verifier service
  • Aggregator entity
    • Runs both an aggregator and a verifier service

Prerequisites

Before compiling Clementine:

  1. Install Rust: rustup.rs

  2. Install RiscZero (2.1.0): dev.risczero.com/api/zkvm/install

    curl -L https://risczero.com/install | bash
    rzup install cargo-risczero 2.1.0 # Or v2.1.0
    rzup install r0vm 2.1.0
    rzup install rust 1.88.0
  3. If on Mac, install XCode and its app from AppStore (if xcrun metal gives an error):

    xcode-select --install
  4. If on Ubuntu, install these packages:

    sudo apt install build-essential libssl-dev pkg-config

Before running Clementine:

  1. Install and configure a Bitcoin node (at least v30.0)

  2. Install and configure PostgreSQL. Using docker:

    docker run --name clementine-test-db \
    -e POSTGRES_USER=clementine \
    -e POSTGRES_PASSWORD=clementine \
    -e POSTGRES_DB=clementine \
    -p 5432:5432 \
    --restart always \
    -d postgres:15 \
    bash -c "exec docker-entrypoint.sh postgres -c 'max_connections=1000'"
  3. Install RISC Zero toolchain:

    cargo install cargo-risczero
  4. [Optional] TLS certificates required to start and connect to a Clementine server. For tests, these are automatically generated, if not present. Please check RPC Authentication and Security Considerations sections when generating certificates for a deployment.

    ./scripts/generate_certs.sh
  5. Set the RISC0_DEV_MODE environment variable if tests are going to be run or if the deployment requires it:

    export RISC0_DEV_MODE=1
  6. [Optional] Download pre-generated BitVM cache. If not downloaded, it will be generated automatically.

    wget https://static.testnet.citrea.xyz/common/bitvm_cache_v3.bin -O bitvm_cache.bin
    wget https://static.testnet.citrea.xyz/common/bitvm_cache_dev.bin -O bitvm_cache_dev.bin
    export BITVM_CACHE_PATH=/path/to/bitvm_cache.bin # If RISC0_DEV_MODE is not set
    export BITVM_CACHE_PATH=/path/to/bitvm_cache_dev.bin # If RISC0_DEV_MODE is set
  7. Set RUST_MIN_STACK environment variable to at least 33554432

    # On Unix-like systems:
    export RUST_MIN_STACK=33554432
  8. For automation mode only: Install additional dependencies required for automation features:

    • skopeo: Required for pulling and verifying Docker images
    • curl: Required for installing udocker
    • python3: Required by udocker
    • udocker: Required for running Docker containers without root privileges
    # On Debian/Ubuntu:
    sudo apt-get update
    sudo apt-get install -y python3 python-is-python3 tar skopeo curl
    
    # Download and install udocker (instructions by udocker: https://indigo-dc.github.io/udocker/installation_manual.html)
    wget https://github.com/indigo-dc/udocker/releases/download/1.3.17/udocker-1.3.17.tar.gz
    tar zxvf udocker-1.3.17.tar.gz
    export PATH=$(pwd)/udocker-1.3.17/udocker:$PATH
    
    # Install udocker (run the install command as the user that will run clementine; do not use sudo/root)
    udocker install
    # If you install as root, use: udocker --allow-root install

    When proving in automation mode, Clementine also requires an unlimited stack size limit. Configure the host so the hard limit allows an unlimited stack, then set the runtime limit before starting Clementine:

    ulimit -s unlimited

    To make the PATH change permanent, add it to your shell configuration file (e.g., ~/.bashrc or ~/.zshrc):

    echo 'export PATH="'$(pwd)'/udocker-1.3.17/udocker:${PATH}"' >> ~/.bashrc
    source ~/.bashrc

Configure Clementine

Clementine can be configured to enable automation at build-time via the automation feature. The automation feature enables the State Manager and Transaction Sender which automatically fulfills the duties of verifier/operator/aggregator entities. It also enables automatic sending and management of transactions to the Bitcoin network via Transaction Sender.

cargo build --release --features automation

Clementine supports two runtime primary configuration methods:

  1. Configuration Files: Specify main configuration and protocol parameters via TOML files
  2. Environment Variables: Configure the application entirely through environment variables

Configuration Files

Running the binary as a verifier, aggregator, or operator requires a configuration file. An example configuration file is located at core/src/test/data/bridge_config.toml and can be taken as reference. Please copy that configuration file to another location and modify fields to your local configuration.

Additionally, Clementine requires protocol parameters that are specified either by a file or from the environment. You can specify a separate protocol parameters file using the --protocol-params option. This file contains protocol-specific settings that affect transactions in the contract.

Environment Variables

It is also possible to use environment variables instead of configuration files. The .env.example file can be taken as a reference for this matter.

Configuration Source Selection

Clementine uses the following logic to determine the configuration source:

  1. Main Configuration:

    • If READ_CONFIG_FROM_ENV=1 or READ_CONFIG_FROM_ENV=on, configuration is read from environment variables
    • If READ_CONFIG_FROM_ENV=0 or READ_CONFIG_FROM_ENV=off or not set, configuration is read from the specified config file
  2. Protocol Parameters:

    • If READ_PARAMSET_FROM_ENV=1 or READ_PARAMSET_FROM_ENV=on, protocol parameters are read from environment variables
    • If READ_PARAMSET_FROM_ENV=0 or READ_PARAMSET_FROM_ENV=off or not set, protocol parameters are read from the specified protocol parameters file

You can mix these approaches - for example, reading main configuration from a file but protocol parameters from environment variables.

RPC Authentication

Clementine uses mutual TLS (mTLS) to secure gRPC communications between entities and to authenticate clients. Client certificates are verified and filtered by the verifier/operator to ensure that:

  1. Verifier/Operator methods can only be called by the aggregator (using aggregator's client certificate aggregator_cert_path)
  2. Internal methods can only be called by the entity's own client certificate (using the entity's client certificate client_cert_path)

The aggregator does not enforce client certificates but does use TLS for encryption.

Certificate Setup for Tests

Before running the servers, you need to generate certificates. A script is provided for this purpose:

# Run from the project root
./scripts/generate_certs.sh

This will create certificates in the following structure:

certs/
├── ca/
│   ├── ca.key     # CA private key
│   └── ca.pem     # CA certificate
├── server/
│   ├── ca.pem     # Copy of CA certificate (for convenience)
│   ├── server.key # Server private key
│   └── server.pem # Server certificate
├── client/
│   ├── ca.pem     # Copy of CA certificate (for convenience)
│   ├── client.key # Client private key
│   └── client.pem # Client certificate
└── aggregator/
    ├── ca.pem     # Copy of CA certificate (for convenience)
    ├── aggregator.key # Aggregator private key
    └── aggregator.pem # Aggregator certificate

Note

For production use, you should use certificates signed by a trusted CA rather than self-signed ones.

Starting a Server

Clementine is designed to be run multiple times for every actor that an entity requires. An actor's server can be started using its corresponding argument. Please follow instruction steps before trying to start a server.

Compiling Manually

# Build the binary (with optional automation)
cargo build --release [--features automation]

# Run binary with configuration file
./target/release/clementine-core verifier --config /path/to/config.toml
./target/release/clementine-core operator --config /path/to/config.toml
./target/release/clementine-core aggregator --config /path/to/config.toml

# Run with both configuration and protocol parameter files
./target/release/clementine-core verifier --config /path/to/config.toml --protocol-params /path/to/params.toml

# Run with environment variables
READ_CONFIG_FROM_ENV=1 READ_PARAMSET_FROM_ENV=1 ./target/release/clementine-core verifier

# Mixing configuration sources
READ_CONFIG_FROM_ENV=0 READ_PARAMSET_FROM_ENV=1 ./target/release/clementine-core verifier --config /path/to/config.toml

A server's log level can be specified with --verbose flag:

./target/release/clementine-core operator --config /path/to/config.toml --verbose 5 # Logs everything

Setting RUST_LIB_BACKTRACE to full will enable full backtraces for errors

RUST_LIB_BACKTRACE=full ./target/release/clementine-core operator --config /path/to/config.toml

For more information, use --help flag:

./target/release/clementine-core --help

Using Docker

A docker image is provided in Docker Hub. It can also be locally built with:

Standard build (without automation):

docker build -f scripts/docker/Dockerfile -t clementine:latest .

Automation mode build (with automation features enabled):

docker build -f scripts/docker/Dockerfile.automation -t clementine:latest .

Also, there are multiple Docker compose files located at scripts/docker/ which can be used to start Bitcoin, PostgreSQL, Citrea, and Clementine. Config files for these compose files can be found at scripts/docker/configs/. They are configured for a typical deployment and need modification before deployment. Please note that, apart from regtest, a newly created wallet won't have any funds and users are responsible for configuring their own address.

docker compose -f scripts/docker/docker-compose.verifier.testnet4.yml up
docker compose -f scripts/docker/docker-compose.full.regtest.yml up

Running Tests

To run all tests:

cargo test --all-features

Also, due to the test directory hierarchy, unit and integration tests can be run separately:

cargo test_unit
cargo test_integration

Helper Scripts

There are a handful of scripts in the scripts/ directory. Most of them are for testing but still can be used for setting up the environment. They can change quite frequently. So, please check for useful ones.

Each script should have a name and comment inside that explain its purpose.

Debugging Tokio Tasks (tokio-console)

To debug tokio tasks, you can uncomment the console-subscriber dependency in Cargo.toml and the console_subscriber::init(); line in src/utils.rs. Then, rebuild the project with cargo build_console which is an alias defined with the necessary flags.

cargo build_console

After running Clementine, you can access the console by running the following command:

tokio-console

Security Considerations

TLS Certificates

  • Keep private keys (*.key) secure and don't commit them to version control
  • In production, use properly signed certificates from a trusted CA
  • Rotate certificates regularly
  • Consider using distinct client certificates for different clients/services