Configure

Disclaimer: Canopy is alpha-stage software. While documentation and guides are provided to assist users, they come with no warranties, guarantees, or assurances of reliability. Users are solely responsible for any issues that may arise, including but not limited to the loss of funds. Please proceed with caution.

Configure

The Canopy software is designed with simplicity in mind and configuration is meant to be minimal while giving node runners power to adapt the software to the needs of the deployers or Nested Chains.

➩ This section details the configuration of Canopy nodes, and while Canopy is meant to be hassle free, the intended audience is Validator and RPC providers.

Data Directory

The data directory of a Canopy node contains the application level files that Canopy requires to function.

💡 The default location of a Canopy data directory is $USERHOME/.canopy or simply ~/.canopy.

$ ls ~/.canopy

> book.json config.json keystore.json polls.json validator_key.json
  canopy/ genesis.json heap1.out heap2.out logs proposals.json

Contents

  • book.json: the 'peer address book' of the Canopy node. This file contains addresses of 'potential peers' a node may connect to. This file is auto-populated by the P2P module of Canopy and is not meant to be manually edited, especially while the software is running.

  • config.json: the configuration file of the Canopy node. All configuration is handled in this single file. This file is loaded once upon startup, modifying this file during active operation is currently safe but changes are not reflected until the node is restarted.

  • keystore.json: the local store of encrypted private keys that may be utilized by the pre-packaged 1️⃣ web wallet, 2️⃣ command line interface, or 3️⃣ admin rpc. Importantly, this file is not critical for Validator operation, storing the validator key in this file does not change node behavior.

  • polls.json: this file is used to store non-critical 'on-chain' governance polling information parsed from blocks. If this file is modified or corrupted, it may lead to incorrect displays in the prepackaged web-wallet but otherwise does not affect consensus or any other critical component of node operation.

  • validator_key.json: the ⚠️ plain-text BDN (BLS) private key of the operator of the node. The security model of Canopy presumes there is no unauthorized access to the server. However, due to the non-custodial design of Canopy, the output private key (cold / off server) is what holds custody over staked tokens and rewards. Meaning, unauthorized access to the operator key allows unauthorized pausing, unauthorized unstaking, or P2P spoofing as a Validator, but does not copromise staked funds or rewards. As a result, little to no funds should be kept in the operator address.

  • canopy/: the nested directory where the badgerDB blockchain data is stored. Conveniently, Canopy includes data of transactions, blocks, state, and sparse merkle tree in a single database. Writes to the database are guarenteed to be atomic by badger so corruption events should be minimal if any. Live snapshotting this data while the software is running is not officially supported, but rsync (or similar) may be used to quickly copy data across servers if needed when the software is stopped. If provided a snapshot from a trusted party, this is likely the directory that should be replaced.

  • genesis.json: the json encoded version of the starting state of the blockchain. This file is interpreted and injected into the database by the software - allowing an 'agreed upon' starting point of the blockchain. Testnet, Mainnet, Canarynet and other Nested Chains will all have unique genesis files. If invalid block hash or similar error logs are seen when syncing height 1 - it's often due to an incorrect genesis.json file or incorrect chain_id configuration.

  • heap1.out / heap2.out: debug memory profiling files are generated automatically. Heap1 is created at startup and Heap2 is replaced every 10 seconds. These files will likely be removed in the future - but allow the development team to easily debug OOM situations. These files are overwritten at restart, so save them accordingly.

  • logs/: the sub-directory of gzipped logs. Logs are automatically directed to stdout, the web wallet, the admin rpc, and are saved in this directory. While the Canopy software auto-rotates and compresses logs, this directory should be periodically monitored for uncontrolled growth (especially during alpha and beta phases). Inclusion of the appopriate gzipped log file or log output is often a minimum requirement for debugging requests.

  • proposals.json: the local voting configuration of the Canopy node for governance proposals. This file is only applicable to active Validators, as it configures a Validator to allow a proposal transaction to be included in a block (or not). This file is not meant to be manually edited, especially while the software is running. This file may be safely edited using the prepackaged web wallet under the governance section.

Config.json

Configuration of a Canopy Validator is handled using a single config.json file.

➩ The config.json file is located in the data directory (default ~/.canopy) of the Canopy node and is loaded once upon startup.

This file is able to be edited during software operation, but requires a restart to apply any changes.

{
  "logLevel": "debug",
  "chainId": 1,
  "sleepUntil": 0,
  "rootChain": [
    {
      "chainId": 1,
      "url": "http://localhost:50002"
    },
    {
      "chainId": 2,
      "url": "http://localhost:40002"
    }
  ],
  "runVDF": true,
  "headless": false,
  "walletPort": "50000",
  "explorerPort": "50001",
  "rpcPort": "50002",
  "adminPort": "50003",
  "rpcURL": "http://localhost:50002",
  "adminRPCUrl": "http://localhost:50003",
  "rootChainPollMS": 333,
  "timeoutS": 3,
  "dataDirPath": "/root/.canopy",
  "dbName": "canopy",
  "inMemory": false,
  "networkID": 1,
  "listenAddress": "0.0.0.0:9001",
  "externalAddress": "tcp://canopy-rocks.io",
  "maxInbound": 21,
  "maxOutbound": 7,
  "trutedPeersIDs": null,
  "dialPeers": ["def02e9b054428f198e89179685a48b227f1c189966d4db002f24f8155c5119c
  bb9387146889b5dc4a260184f20d5ecd@tcp://canopy-does-rock.io:9001"],
  "bannedPeersIDs": null,
  "bannedIPs": null,
  "electionTimeoutMS": 200,
  "electionVoteTimeoutMS": 200,
  "proposeTimeoutMS": 1000,
  "proposeVoteTimeoutMS": 1000,
  "precommitTimeoutMS": 200,
  "precommitVoteTimeoutMS": 200,
  "commitTimeoutMS": 200,
  "roundInterruptTimeoutMS": 0,
  "maxTotalBytes": 10000000,
  "maxTransactionCount": 5000,
  "individualMaxTxSize": 4000,
  "dropPercentage": 35
}

logLevel:

Configures the level of specifity in logs

  • DEBUG: (color: BLUE | highest specificity), good for checkout out issues

  • INFO: (color: GREEN | medium specificity), good for most use-cases

  • WARN: (color: YELLOW | low specificity), only outputs potential problems

  • ERROR: (color: RED | minimum specificity), only outputs software issues

chainId:

The unique identifier of the chain (1=CNPY, 2=CNRY, etc) within a network

  • 1: CNPY

  • 2: CNRY

chain id is 1 tier below network id. Network ID is mainnet or testnet whereas chainId is the sovereign chains within the network (like CNPY or CNRY). This allows for future proof partitions of chain ids.

💡 An incorrect chainId may result in the inability to connect to peers, sync, or error output like unequal block-hash.

sleepUntil:

A Unix timestamp (in microseconds) that instructs the software to pause execution until the specified time. This allows validators to coordinate and begin operation simultaneously—useful for restarting networks or synchronizing genesis events.

rootChain

An array of chainId | url objects that specify the RPC endpoint of the root chain.

The root chain is a fundamental part of the Canopy architecture. It defines the validator set and provides critical information needed for a chain to operate as a validator.

For simplicity, you can think of the root chain as the "parent" chain responsible for:

  • Determining the active validator set

  • Providing configuration and coordination data

  • Serving as the chain where validators stake to participate in consensus for nested chains

A chain may designate itself as its root chain. This is known as chain independence.

Validators stake on the root chain to perform consensus operations for nested chains. They may also stake on nested chains to be "on-deck" for future independence, though this currently plays a more economic/preparatory role.

The Canopy software connects to the root chain over WebSockets using an upgraded JSON-RPC protocol, enabling fast and reliable access to validator-critical information.

Best Practices for a root chain RPC node:

  • Must be trusted

  • Should have low latency

Although the field accepts an array, only one root chain is active at a time. The array allows for:

  • Seamless root switching

  • Future graduation to independence

runVDF:

Boolean to enable or disable the proof-of-age verifiable delay function. As a Validator of a root chain, this should be true.

If the Nested Chain relies on some other fork-choice mechanism (like Checkpointing) then this may be disabled.

headless:

Disable the pre-packaged web wallet and block explorer of the Canopy software. This is useful for those who utilize the CLI only for operation - though it is encouraged for production deployments to use the front ends provided.

walletPort:

The rpcURL:port where the pre-packaged web wallet is hosted by the sofware.

View it in browser, behind a reverse proxy is recommended

Default: 50000

explorerPort:

The rpcURL:port where the pre-packaged block explorer is hosted by the sofware.

View it in browser, behind a reverse proxy is recommended

Default: 50001

rpcPort:

The rpcURL:port where the JSON RPC API is hosted by the software.

See the JSON RPC Specification for more details.

Default: 50002

adminPort

The rpcURL:port where the administrator JSON RPC API is hosted by the software

See the JSON RPC Specification for more details.

Default: 50003

rpcURL

The url where the RPC is hosted by the software. This URL is utilized by the prepackaged web wallet and block explorer to connect to the local node.

Default: http://localhost

adminRPCURL

The url where the admin RPC is hosted by the software. This URL is utilized by the prepackaged web wallet to connect to the local node.

Default: http://localhost

⚠️ HTTPS is required for production as passwords are sent plain-text

timeoutS

The RPC request timeout duration in seconds.

Default: 3

dataDirPath

The path of the data directory - default is $USERHOME/.canopy

NOTE: Datadirectory path is expiremental and requires the --data-dir=<PATH> flag as the software doesn't know where to look for the config.json file.

dbName

Modify the name of the database folder inside the data directory.

Changing between software runs will create a brand new database from scratch, resulting in a resync.

Default: canopy

inMemory

Debug only: run the blockchain database completely in memory and don't persist anything to disk

networkID

The unique identifier of the network (1=MAINNET, 2=TESTNET, etc). Each network has many chainIds within it.

  • 1: mainnet

  • 2:testnet

NOTE: chain id is 1 tier below network id. Network ID is mainnet or testnet whereas chainId is the sovereign chains within the network (like CNPY or CNRY). This allows for future proof partitions of chain ids.

💡 An incorrect networkId may result in the inability to connect to peers, sync, or error output like unequal block-hash.

listenAddress

The TCP listening address for the peer-to-peer module.

Importantly, the port must correspond with the chainId with the following formula:

:9000 + chainId

This enables multi-committee setups under a single netURL

Default for CNPY: 0.0.0.0:9001

externalAddress

The TCP URL where peers may discover this node. This URL is displayed within peer's address book and is exchanged with PEX events.

➪ This must be configured or no inbound peers will ever be able to be established.

Example: tcp://canopy-rocks.io (which firewall maps to the listenAddress)

maxInbound

The upper bound of inbound peers (peers that dialed this node)

  • The minimum appropriate ratio of inbound:outbound is 3:1. 4:1 or 5:1 is even healthier for the network.

Default: 21

maxOutbound

The upper bound of outbound peers (peers that this node dials)

  • The minimum appropriate ratio of inbound:outbound is 3:1. 4:1 or 5:1 is even healthier for the network.

Default: 7

trutedPeersIDs

A string array of hex-encoded public keys that will be allowed to surpass limits and will never be dropped due to a bad peer reputation.

Example: ["def02e9b054428f198e89179685a48b227f1c189966d4db002f24f8155c5119c bb9387146889b5dc4a260184f20d5ecd"]

dialPeers

A string array of peers to dial with exponential backoff upon startup.

Format is publicKey@externalAddress

Example: ["def02e9b054428f198e89179685a48b227f1c189966d4db002f24f8155c5119c bb9387146889b5dc4a260184f20d5ecd@tcp://canopy-rocks.io"]

bannedPeersIDs

A string array of hex-encoded public keys that will not be allowed to connect to this node.

Example: ["def02e9b054428f198e89179685a48b227f1c189966d4db002f24f8155c5119c bb9387146889b5dc4a260184f20d5ecd"]

bannedIPs

A string array of IPV4 addresses that will not be allowed to connect to this node.

Example: ["8.8.8.8"]

newHeightTimeoutMS

The amount of time in milliseconds wait taken after starting a new height. This allows processing like Committing the previous quorum certificate to storage.

⚠️ This value should not be modified once a genesis event takes place. It determines block timing

electionTimeoutMS

The amount of time in milliseconds wait taken after starting the election phase. This allows time for Validators to annouce themselves as leader candidates.

⚠️ This value should not be modified once a genesis event takes place. It determines block timing

electionVoteTimeoutMS

The amount of time in milliseconds wait taken after starting the election vote phase. This allows time for replicas to vote for who they believe is the leader.

⚠️ This value should not be modified once a genesis event takes place. It determines block timing

proposeTimeoutMS

The amount of time in milliseconds wait taken after starting the propose phase. This allows time for the leader to create and send a block proposal.

⚠️ This value should not be modified once a genesis event takes place. It determines block timing

proposeVoteTimeoutMS

The amount of time in milliseconds wait taken after starting the propose vote phase. This allows time for replicas to vote on the leaders' proposal.

⚠️ This value should not be modified once a genesis event takes place. It determines block timing

precommitTimeoutMS

The amount of time in milliseconds wait taken after starting the precommit phase. This allows time for the leader to send a proof of proposal approval to the replicas.

⚠️ This value should not be modified once a genesis event takes place. It determines block timing

precommitVoteTimeoutMS

The amount of time in milliseconds wait taken after starting the precommit vote phase. This allows time for the replicas time to vote on the proof of proposal approval.

⚠️ This value should not be modified once a genesis event takes place. It determines block timing

commitTimeoutMS

The amount of time in milliseconds wait taken after starting the commit phase. This allows time for the leader to communicate the 'commit' command to replicas.

⚠️ This value should not be modified once a genesis event takes place. It determines block timing

roundInterruptTimeoutMS (deprecated)

Round interrupt now relies onmsLeftInRound

⚠️ This value should not be modified once a genesis event takes place. It determines block timing

maxTotalBytes

The total amount of bytes allowed in the unconfirmed transaction memory pool (mempool)

5-10x block size recommended as a minimum

maxTransactionCount

The maximum count of individual transactions allowed in the unconfirmed transaction memory pool (mempool)

individualMaxTxSize

The maximum number of bytes allowed in an individual transaction in the unconfirmed transaction memory pool (mempool)

dropPercentage

The percentage of unconfirmed transaction memory pool (mempool) that is dropped when the mempool overflows. Lowest fee transactions dropped first

prometheusAddress

The address of prometheus metric collection

Default: 0.0.0.0:9090

Last updated