Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Enrollment Infrastructure

WEBCAT Infra Chain — the repository for the Rust enrollment infrastructure.

See the basic architecture explained here.

Getting Started

You’ll need to install the following tools:

  • Rust
  • Go
  • protoc
  • just

Or you can use the in-repo nix flake to bootstrap tooling.

Once you have the dependencies installed, you can use the justfile targets locally. Build and run the chain by running both CometBFT and Felidae (the ABCI application), each in its own terminal window. Start CometBFT via:

just cometbft

And the ABCI application via:

just felidae

Finally, to reset the chain state by blowing away both CometBFT and Felidae’s state:

just reset

Note that the application’s genesis file, which contains the initial configuration of the starting state of the chain, is located in ~/.cometbft/config/genesis.json.

Tip: For more verbose logging, run commands with RUST_LOG=info (or RUST_LOG=debug for even more detail).

Testing

Run the standard unit test suite:

just test

Run the integration tests (spawns a 3-validator network per test):

just integration

Block time configuration

Integration tests derive all timing from a configurable block interval (FELIDAE_BLOCK_TIME_SECS, default 1). The default keeps CI fast (~2 min). To test with longer block times (e.g. matching production’s 60s):

just integration 60

Or equivalently:

FELIDAE_BLOCK_TIME_SECS=60 just integration

Setting Up Admin and Oracle

1. Generate Configuration Template

cargo run --bin felidae admin template > config.json

This generates a configuration template (see the Config proto) that you’ll edit to add your own keys as an admin and oracle.

2. Generate Your Admin and Oracle Keypairs

cargo run --bin felidae admin init

This creates your admin keypair. To view your admin public key:

cargo run --bin felidae admin identity

Similarly for oracle:

cargo run --bin felidae oracle init

To view your oracle public key:

cargo run --bin felidae oracle identity

3. Configure config.json

Add your public keys (from step 2) to the authorized lists for both admins and oracles in config.json. For oracles, you’ll need to provide both the identity (public key) and endpoint (domain or IP address) for each oracle.

For a single-validator testing setup, configure the following:

Example chain configuration:

{
  "version": 1,
  "admins": {
    "voting": {
      "total": 1,
      "quorum": 1,
      "timeout": "1day",
      "delay": "0s"
    },
    "authorized": ["YOUR_ADMIN_KEY_HERE"]
  },
  "oracles": {
    "enabled": true,
    "voting": {
      "total": 1,
      "quorum": 1,
      "timeout": "5m",
      "delay": "30s"
    },
    "max_enrolled_subdomains": 5,
    "observation_timeout": "5m",
    "authorized": [
      {
        "identity": "YOUR_ORACLE_KEY_HERE",
        "endpoint": "127.0.0.1"
      }
    ]
  },
  "onion": {
    "enabled": false
  }
}

Note: Each oracle in the authorized array must have:

  • identity: The hex-encoded public key of the oracle (required)
  • endpoint: The endpoint (domain name or IP address) for the oracle (optional, defaults to “127.0.0.1” if omitted)

The endpoint is used by frontends to know where to submit enrollment requests to the oracle set.

Important: You must increment the version number in the config file unless you add the config to the genesis file.

Note: You can now skip steps 3-4 by adding the initial chain config in the genesis file by adding an app_state key with the config, e.g.:

{
  "genesis_time": "2025-09-13T23:47:47.144389Z",
  "chain_id": "my-webcat-testchain",
  "initial_height": 0,
  "app_state": {
    "config": {
      "version": 0,
      "admins": {
        "authorized": [...],
        "voting": { ... }
      },
      "oracles": {
        "enabled": true,
        "authorized": [...],
        "voting": { ... },
        "max_enrolled_subdomains": 5,
        "observation_timeout": "5m"
      },
      "onion": {
        "enabled": false
      }
    }
  }
}

4. Submit Configuration to Chain

cargo run --bin felidae admin config config.json --chain <CHAIN_ID>

Replace <CHAIN_ID> with the chain ID from ~/.cometbft/config/genesis.json.

Once the chain accepts this transaction, you’ll be configured as both admin and oracle. Verify the current configuration:

curl http://localhost:8080/config

5. Post an Oracle Observation

You can now submit oracle observations. For example:

cargo run --bin felidae oracle observe --domain element.nym.re. --zone nym.re.

If you omit the –zone, the oracle will automatically infer the zone from the domain using the Mozilla Public Suffix List (PSL).

After the observation reaches quorum and the delay period expires, the observed hash will be visible in the snapshot:

curl http://localhost/snapshot

Run Oracle as HTTP Server

Instead of using the CLI, you can run the oracle as an HTTP server that accepts observation requests via API:

cargo run --bin felidae oracle server \
  --homedir /persistent/keys \
  --node http://localhost:26657 \
  --bind 127.0.0.1:8081

TK: A client side PoW was added that is not documented here.

The server exposes two endpoints:

  • POST /observe - Submit observation requests (JSON: {“domain”: “example.com.”, “zone”: “com.”})
  • GET /health - Health check endpoint

Example request:

curl -X POST http://localhost:8081/observe \
  -H "Content-Type: application/json" \
  -d '{"domain": "example.com.", "zone": "com."}'