Attestra

Join a quorum

The quorum configuration block, the checks it enforces, and the three operational rules it cannot enforce for you.

Running a node alone is single-node mode: it answers with one key, and every consuming contract trusts that one key. Joining a quorum turns the node into one voice among several, polled by a collector that requires threshold of them to agree before it will assemble a bundle. This page covers the configuration block that does that, what it validates, and what it does not. For the design behind the round itself, see The oracle network.

The quorum block

quorum:
  peers:
    - http://127.0.0.1:8081
    - http://127.0.0.1:8082
  threshold: 2
  timeout: 5s
  • peers: a list of base URLs, one per oracle the collector polls.
  • threshold: how many peers must return the same digest before the round succeeds.
  • timeout: how long the collector waits for one fan-out round before treating a peer as absent. Defaults to 5 seconds if omitted.

The block itself is optional. Omitting quorum entirely runs the node in single-node mode: no peers are polled, and the node signs on its own.

Validation

A node refuses to start if the block fails any of these. Each is worth knowing individually, because each is a mistake an operator can make while copying a peer list around:

  • At least one peer. An empty list is rejected outright rather than silently behaving like single-node mode.
  • threshold between 1 and the number of peers. A threshold of 0 or one larger than the peer count can never be satisfied.
  • No duplicate peer. A repeated URL would be polled twice under two entries and could satisfy the threshold on its own, which defeats the point of counting distinct signers in the first place.
  • Every peer an http or https URL with a host. A malformed or schemeless entry is caught at startup, not the first time the collector tries to dial it.

Three rules the configuration cannot enforce

The validation above catches malformed input. It says nothing about whether the deployment it describes actually means what an operator intends. These three rules sit outside the config file and have to be arranged deliberately.

  1. The threshold must match the on-chain registry on every target chain. threshold in this block is what the collector requires before it will assemble a bundle; it is not what a chain requires before it will accept one. Each chain keeps its own threshold in its signer registry, and the on-chain value is the one that governs. A bundle this node considers sufficient is rejected on chain if the registry disagrees. Getting this wrong does not fail loudly at startup; it fails at the moment a push is submitted. See Deploy the contracts for where each chain's threshold is set.
  2. Every peer must be independently operated. A threshold of k is meant to mean k distinct operators, each running their own infrastructure and holding their own key. Nothing in peers or threshold can verify that. k-of-n counts distinct signing keys; it has no way to tell whether the people or organisations controlling those keys are actually different. If one party runs three of the five nodes in a 3-of-5 deployment, the configuration reads as a threshold of 3 and the deployment is, in practice, a threshold of 1: that one party can already reach quorum alone, and the other two nodes add nothing but the appearance of distributed trust.
  3. Each peer's signer address must be added to the signer registry on every chain. The collector will happily poll a peer, collect its signature, and count it toward the local threshold. Whether that signature counts for anything on chain is a separate question, answered by the registry, not by the collector. A peer whose address is missing from the registry has its signature collected and then rejected at verification time, which can silently reduce a nominal 3-of-5 to a working 2-of-4 or worse.

Timeouts are treated as absence, not delay

A peer that does not answer within timeout is treated the same way as a peer that returned an error: it becomes an outcome carrying a failure, and the round proceeds without it. The collector does not wait longer for a slow peer, and it does not retry. This is deliberate: surviving the slow or dead minority is the entire reason a threshold below the peer count exists. A quorum design that stalled on one unresponsive node would give up the availability it was built to provide.

On this page