Nodes, consensus and upgrades¶
How many nodes to run, how they agree, what the build number does, and how to upgrade or add a node without breaking the network.
How many nodes¶
A node checks its data against the other nodes. With few nodes there is little to check against.
- 1 to 3 nodes work, but treat that as the least you can run at all.
- 4 is a safe minimum.
- 5 or more is best.
Every node must use the same kind of storage (the embedded store or CouchDB) and the same build.
How consensus works¶
Every node runs each transaction and votes yes or no. The transaction is committed when the share of yes votes reaches consensus.reached in config.json, a percentage of all nodes (default 60). A transaction with $unanimous set needs every node.
With 5 nodes and reached at 60, three yes votes commit. With 4 nodes, three are needed, because two is 50%.
The same percentage decides repairs, but counted a little differently. When a node repairs a stream it asks the other nodes, so the bar is the percentage of all nodes, less one for the node asking, rounded up:
votes needed = ceil(reached / 100 × nodes − 1)
With 4 nodes at 60% that is ceil(2.4 − 1) = 2, so two other nodes agreeing is enough. The "less one" is what lets a network split exactly in half still decide. A full restore uses the same sum.
What SPI is¶
A stream is one record on the ledger, with a position that moves on each time it changes. When a node has fallen behind, its copy of a stream is at an older position than everyone else's, and its vote on the next transaction that touches that stream fails with "Stream Position Incorrect". SPI is the repair that follows: the node asks the other nodes which copy they hold, and when enough of them agree (the sum above) it adopts that copy and carries on. It happens on its own, while the node runs. A node that is far behind, or missing whole streams, needs a restore.
Builds¶
build in config.json is the protocol level the node runs at. A new release can run at the old level, so you can upgrade one node at a time; the new behaviour only switches on when every node's build is raised. Raising it on some nodes before every node is upgraded splits the network.
| Build | What it switches on |
|---|---|
40100 |
Authority expiry is enforced (an authority with an expire date stops signing after it). Contract source is stored once, as a reference to the deploying transaction, instead of a copy in the contract stream. |
40200 |
New contract versions compile to ES2025 (newer JavaScript) instead of ES2017. |
40300 |
Hybrid nodes: each node signs its vote and its commit, the hybrid section is asserted on-ledger, hybrids can register, and the /h/* API serves them. A contract update can lock older versions, and locks are recorded on the contract stream so a restore brings them back. |
A new node's generated config.json has 40200. A node joining an existing network must have its build set to that network's level before it starts. Running hybrids needs 40300.
Upgrading the network¶
Two steps, and the second only once the first is finished on every node.
- Upgrade every node, one at a time (below), leaving
buildas it is. - Set the new
buildin every node'sconfig.jsonand restart it. With"remote": trueyou can reload instead, from the node's own machine:
curl http://127.0.0.1:5260/a/admin-reload
You should see {"status":"success","build":40300}.
Upgrading one node¶
Do one node at a time and let it settle before the next, so the network keeps enough nodes to vote.
activeledger stop
This waits up to 30 seconds for the node to exit (--timeout <s> changes that). Install the new version, then:
activeledger
The start-up display walks through config, identity, database, network, consensus and ready. consensus is done when the node has found its neighbours. Check it from another shell:
activeledger status
You should see ready (pid 12345). It exits 2 with not running when the node is down. Transactions the node missed while it was off are repaired by SPI as streams are next touched.
Adding a node¶
Once the network is asserted, the list of nodes lives on the ledger and is changed with a transaction to the default/setup contract. More than half of the existing nodes must sign it with their own node keys (the .identity file), and the signatures are named by each node's host:port.
- On the new machine, install Activeledger and run
activeledger --publicto generate its identity and print the public key. - Submit an
addtransaction to any running node.suggester.identity.publicis the new node's public key, and$onames the network stream (the id in thenetworkkey of an existing node'sconfig.json, before the@).
{
"$tx": {
"$namespace": "default",
"$contract": "setup",
"$entry": "add",
"$i": {
"suggester": {
"type": "rsa",
"publicKey": "[a signing public key]",
"identity": { "type": "rsa", "public": "[new node public key]" },
"host": "10.0.0.14",
"port": "5260"
}
},
"$o": { "[network stream id]": {} }
},
"$selfsign": true,
"$sigs": {
"suggester": "[signature]",
"10.0.0.11:5260": "[signature]",
"10.0.0.12:5260": "[signature]",
"10.0.0.13:5260": "[signature]"
}
}
It is refused with Node already exists when that host:port is already in the list, and with Host node signature problem when there are not enough valid node signatures. On success every running node reloads its neighbourhood.
- Give the new node a
config.jsonwith the fullneighbourhood(itself included), the network'sconsensusandsecurity, the samebuildand the same kind of storage, andnetworkset to"<setup stream id>@<the setup stream's _rev>"(how to find the revision is in Restoring a node; without it the other nodes refuse the restore with 403). Then fetch the data before the node starts. The restore writes to the node's database, so start only that first, and run the restore in a second shell in the same folder:
activeledger --db-only
activerestore --full
It ends with exit 0 when the data is in. Stop the database with Ctrl+C.
- Start the new node. It reads the network's settings from its restored database from then on.
Removing a node is the same transaction with "$entry": "remove" and the leaving node's details in suggester.
Changing the network's settings¶
After assert, consensus, security and neighbourhood are no longer in the file. The hybrid rules are changed with activeledger hybrid ... (see Operating hybrids); nodes are added and removed as above. The settings that stay in the file (build, debug, restore, storage) are changed by editing it and restarting, or reloading with remote on.