Introduction

Nomic is a layer-1 blockchain which offers a decentralized, non-custodial Bitcoin bridge.

It is undergoing active development, but is actively holding mainnet Bitcoin in the bridge and will be upgraded to mainnet soon.

Contributing

We welcome contributions to this wiki - if you want to add content or fix an issue, please send a pull request via the Github repo.

Running a Node

This guide will walk you through starting or upgrading a full node on the Nomic testnet.

Running a node increases the health of the network by decentralizing ledger validation and data, even for non-validator nodes. Community members are encouraged to run a node, especially when regularly interacting with the network via transactions and queries.

Need help?

If you need any help getting your node running, join the Discord and ask for the Validator role.

Setup

These instructions will help you set up a new Nomic Stakenet node from scratch. If you are already running an older Nomic node, follow the upgrade instructions instead.

Requirements

  • >= 4GB RAM
  • >= 100GB of storage
  • Linux or macOS

1. Build Nomic

Start by building Nomic.

  1. Install rustup if you haven't already:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  1. Install required dependencies:

Ubuntu/Debian:

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

Fedora:

sudo dnf install clang openssl-devel && sudo dnf group install "C Development Tools and Libraries"
  1. Clone the repo and switch to the correct directory and branch:
git clone https://github.com/nomic-io/nomic.git
cd nomic
git checkout main
  1. Build and install. This adds a nomic command to your PATH:
cargo install --locked --path .
nomic --version

2. Run your node

Start your Nomic node:

nomic start

This will run the Nomic state machine and a Tendermint process. For new nodes, the state-sync process will run automatically to get the node up to speed with the current chain.

Upgrading

Nomic has its own unique upgrade system. Once you switch to the latest release, your node will signal its readiness, and the network will automatically switch to the new version once enough voting power has signalled.

To prepare your Nomic Stakenet node for a network upgrade, simply compile the new version then restart:

cd nomic
git checkout main
git pull
cargo install --path . --locked

# (make sure to kill your existing node first)
nomic start

Validating

Becoming a validator comes with extra responsibility compared to running a non-validating full node. Your node becomes an authority for producing blocks and a signatory for the Bitcoin held in the bridge.

1. Acquiring coins and staking for voting power

First, find your address by running nomic balance (for now this must be run on the same machine as your active full node).

Ask the community for some coins in the Discord and include your address.

Once you have received coins, you can declare your node as a validator and delegate to yourself with this command:

nomic declare \
  <validator_consensus_key> \
  <amount> \
  <commission_rate> \
  <max_commission_rate> \
  <max_commission_rate_change_per_day> \
  <min_self_delegation> \
  <moniker> \
  <website> \
  <identity> \
  <details>

IMPORTANT NOTE: Carefully double-check all the fields since you will not be able to modify the commission_max or commission_max_change after declaring. If you make a mistake, you will have to declare a new validator instead.

  • The validator_consensus_key field is the base64 pubkey value field found under "validator_info" in the output of http://localhost:26657/status.
  • The identity field is the 64-bit hex key suffix found on your Keybase profile, used to get your profile picture in wallets and block explorers.

For example:

nomic declare \
  ohFOw5u9LGq1ZRMTYZD1Y/WrFtg7xfyBaEB4lSgfeC8= \
  100000 \
  0.042 \
  0.1 \
  0.01 \
  100000 \
  "Foo's Validator" \
  "https://foovalidator.com" \
  37AA68F6AA20B7A8 \
  "Please delegate to me!"

2. Run your Bitcoin signer

The funds in the Bitcoin bridge are held in a large multisig controlled by the Nomic validators. If you are a validator with a significant amount of voting power, it is very important that you run a signer.

Bitcoin Relayer

Relayer nodes carry data between the Bitcoin blockchain and the Nomic blockchain. You can help support the health of the network by running a Bitcoin node alongside your Nomic node and running the relayer process.

1. Sync a Bitcoin node

Download Bitcoin Core: https://bitcoin.org/en/download

Run it with:

# mainnet
bitcoind -server -rpcuser=satoshi -rpcpassword=nakamoto

# testnet
bitcoind -server -testnet -rpcuser=satoshi -rpcpassword=nakamoto

NOTE: To save on disk space, you may want to configure your Bitcoin node to prune block storage. For instance, add -prune=5000 to only keep a maximum of 5000 MB of blocks. You may also want to use the -daemon option to keep the node running in the background.

2. Run the relayer process

# mainnet
nomic relayer --rpc-port=8332 --rpc-user=satoshi --rpc-pass=nakamoto

# testnet
nomic relayer --rpc-port=18332 --rpc-user=satoshi --rpc-pass=nakamoto

Leave this running - the relayer will constantly scan the Bitcoin and Nomic chains and broadcast relevant data.

The relayer will also create a server which listens on port 9000 for clients to announce their deposit addresses. To help make the network more reliable, if you run a relayer please open this port and let us know your node's address in Discord or a Github issue so we can have clients make use of your node. If you're going to make this service public, putting the server behind an HTTP reverse proxy is recommended for extra safety.

Bitcoin Signer

The funds in the Bitcoin bridge are held in a large multisig controlled by the Nomic validators. If you are a validator with a significant amount of voting power, it is very important that you run a signer.

You can run the signer with:

nomic signer

This will automatically generate a Bitcoin extended private key and store it at ~/.nomic-stakenet-3/signer/xpriv. It will also prompt you to submit your public key to the network so you can be added to the multisig. KEEP THIS KEY SAFE - similar to your validator private key, it is important to be mindful of this key so that it is never lost or stolen.

Leave this process running, it will automatically sign Bitcoin transactions that the network wants to create.

In the future, we hope for the community to come up with alternative types of signers which provide for extra security, by e.g. airgapping keys, using HSMs, or prompting the user for an encryption key.

Circuit Breaker

The signer process will automatically halt signing if, over the past 24 hours, the signatory set has changed too much, or if too much Bitcoin is being withdrawn from the bridge.

These parameters are tunable:

nomic signer

        --max-sigset-change-rate <MAX_SIGSET_CHANGE_RATE>
            Limits the maximum allowed signatory set change within 24 hours

            The Total Variation Distance between a day-old signatory set and the newly-proposed
            signatory set may not exceed this value

            [default: 0.04]

        --max-withdrawal-rate <MAX_WITHDRAWAL_RATE>
            Limits the fraction of the total reserve that may be withdrawn within the trailing
            24-hour period

            [default: 0.04]

Tweaking these parameters is a decision that requires careful thought. A future release will integrate these circuit breaker checks into the protocol itself.

IBC Relayer

Running an IBC relayer for Nomic works mostly the same as with other Cosmos chains, but with a few caveats:

  1. Currently, Nomic is only compatible with Hermes and does not support the ibc-go relayer.
  2. Hermes must be configured with a custom proof spec. Please see the example configuration below.

1. Configure Hermes

Here's an example Hermes configuration relaying between a local Nomic and Osmosis node:

# ~/.hermes/config.toml

[[chains]]
id = 'nomic-stakenet-3'
rpc_addr = 'http://127.0.0.1:26657'
event_source = { mode = 'pull' }
grpc_addr = 'http://127.0.0.1:9001'
rpc_timeout = '10s'
account_prefix = 'nomic'
key_name = 'testkey'
store_prefix = 'ibc'
max_gas = 40000000
gas_price = { price = 0.001, denom = 'stake' }
clock_drift = '20s'
proof_specs = '''
[
  {
    "inner_spec": {
      "child_order": [
        0,
        1,
        2
      ],
      "child_size": 32,
      "empty_child": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
      "min_prefix_length": 1,
      "max_prefix_length": 1,
      "hash": 6
    },
    "leaf_spec": {
      "hash": 6,
      "prehash_key": 0,
      "prehash_value": 0,
      "length": 4,
      "prefix": "AA"
    },
    "max_depth": 0,
    "min_depth": 0
  },
  {
    "inner_spec": {
      "child_order": [
        0
      ],
      "child_size": 32,
      "empty_child": "",
      "min_prefix_length": 0,
      "max_prefix_length": 0,
      "hash": 6
    },
    "leaf_spec": {
      "hash": 6,
      "prehash_key": 0,
      "prehash_value": 0,
      "length": 0,
      "prefix": ""
    },
    "max_depth": 0,
    "min_depth": 0
  }
]
'''

[[chains]]
id = 'osmosis-1'
rpc_addr = 'http://127.0.0.1:26757'
grpc_addr = 'http://127.0.0.1:9090'
websocket_addr = 'ws://127.0.0.1:26757/websocket'
rpc_timeout = '10s'
account_prefix = 'osmo'
key_name = 'osmosis'
address_type = { derivation = 'cosmos' }
store_prefix = 'ibc'
default_gas = 5000000
max_gas = 15000000
gas_price = { price = 0.0026, denom = 'uosmo' }
gas_multiplier = 1.1
max_msg_num = 20
max_tx_size = 209715
clock_drift = '20s'
max_block_time = '10s'
trusting_period = '10days'
trust_threshold = { numerator = '1', denominator = '3' }
[chains.packet_filter]
policy = 'allow'
list = [
  ['transfer', 'channel-5555'], # nomic-stakenet-3
]

The proof_specs and event_source fields for Nomic are the main differences to note for those otherwise familiar with IBC relaying with Hermes.

Please refer to the Hermes docs for more information.

2. Run gRPC server

Nomic features a gRPC server to support IBC relaying, which implements only the minimum set of gRPC methods required by Hermes. The server does not run by default, and must be run in a separate process with:

# default port 9001
nomic grpc

or:

nomic grpc <PORT>

3. Fund relayer with NBTC

Fees for IBC transactions are paid with NBTC (1 sat per tx). After you've configured your relayer, you'll need to fund its Nomic account (hermes keys list --chain nomic-stakenet-3 to see the address) with NBTC.

4. (Optional) Relay operator keys

To ensure that NBTC is recoverable by the remote chain's validator set in the event of an Emergency Disbursal, run:

nomic relay-op-keys <COUNTERPARTY-RPC> <CLIENT_ID>

This command may be re-run anytime to refresh the operator keys of the remote chain's validator set. If an Emergency Disbursal occurs on Nomic, a portion of the Bitcoin reserves equal to the NBTC held in channels backed by the specified client will become spendable by 2/3+ of the voting power of that network's top 30 validators.

Other notes

Below are a couple other notes to keep in mind, given Nomic's custom IBC implementation.

Channel ports

For channels supporting token transfers, the Nomic channel port must be transfer. ICS 20 is the only application-layer standard currently supported by Nomic:

hermes create channel --a-chain osmosis-1  --b-chain nomic-stakenet-3 --a-port transfer --b-port transfer --new-client-connection

Manual clearing

Typically, the main Hermes process (hermes start) will properly relay packets between Nomic and its counterparty. However, if it seems like an event has been missed by Hermes, packets can be manually cleared (bidirectionally) with:

hermes clear packets --chain nomic-stakenet-3 --port transfer --channel channel-1