What Demos is
The Demos docs describe the Demos Network as an interconnectivity layer across chains and web contexts. The network has two parts, the node and the SDKs, and its nodes “can act either as validators or as synced read-only nodes” (architecture). Consensus is PoR-BFT, “Proof of Reputation (PoR) Byzantine Fault Tolerance” (consensus).
Parts the docs name
- Consensus
- PoR-BFT. Validators are shuffled into shards for each block; see below.
- State
- The Global Change Registry (GCR) holds account and subnet properties once blocks are synced (GCR).
- Identity
- Cross Context Identities (CCI): each address carries an
identitiesobject in the GCR (CCI). - Cross-chain
- The XM SDKs “help you create payloads to interact with other blockchains from DEMOS” (XM).
- Web2
- DAHR relays an HTTP request and anchors hashes of the response on chain; TLSNotary produces proofs from TLS sessions (Web2). See DAHR.
- Privacy
- L2PS, the Layer 2 Privacy Subnet, “a privacy-preserving transaction layer that enables encrypted transactions” (L2PS).
DNO is an independent observer built by XM33, not part of Demos. Its public reading comes from three public Demos endpoints read from outside, and from validators that answer as listed when fewer than two of those give their own height. It does not operate the protocol, admit validators, or decide anything on the network. DNO itself does not validate. XM33 runs a validator on the public testnet. In the public reading it counts like any other validator, and only if it publishes an address on chain.
Two mechanisms, two questions
DNO's cross-check compares public answers. Demos shard composition is a consensus step inside the network. They answer different questions, and DNO never sees the second one.
Outside: DNO's cross-check every 20 s
- 3 public seedstheir /info answers
- Own heightseach seed's own peerlist entry
- Median, ±25a height in the band is aligned
- Agreementstrong · moderate · weak · unknown
- Statuson /organism, with its reason
Inside: Demos shard composition every block
- validators tableACTIVE rows are eligible
- CVSA seedSHA-256 over recent block hashes
- Compositionthe seed shuffles the eligible set; validators failing health or sync checks are skipped (Phase 1)
- Shardruns consensus for the block, one round at a time
DNO's cross-check
DNO, from outside
- Question
- Did the public seeds answer, do the heights they report agree, and has DNO counted less than 30 minutes without a new height?
- Inputs
- The
/infoanswers of three public Kynesys seeds. A seed's height is its own peerlist entry; a seed that does not list itself has no height here. When fewer than two seeds give their own height, the/infoanswers of validators that answer as listed stand in. - Output
statuson/organism, always withstatus_reason.- Also dialed
- The cross-check RPCs (DAHR is attempted there) and fixnet peers for the reference table: never in status. The address each ACTIVE validator published on chain (counts only, on
/health): in status only when those validators stand in for a seed.
Demos shard composition
The network, for every block
- Question
- Which validators form the shard for this block?
- Inputs
- Validators that are
ACTIVEon chain, and the CVSA seed. - Output
- The shard that runs consensus for that block.
- What DNO sees of it
- Nothing.
So a stable reading means the public seeds answered (or validators stood in for one), the heights compared agree, and DNO has not counted 30 minutes without a new height. It does not mean a shard formed, that a given identity sat in one, or that the network is healthy in the sense the Demos docs use.
Validators
In the Demos docs, a validator is “an on-chain row in the validators table”. Its status moves through three states, driven by three transactions: validatorStake, validatorUnstake and validatorExit (validator lifecycle).
“Participating in consensus, eligible for shard selection.”ACTIVE, in the validator lifecycle page
| Move | Transaction | What the docs say |
|---|---|---|
| new → ACTIVE | validatorStake | Needs the minimum stake and a connection URL. |
| ACTIVE → ACTIVE | validatorStake | A top-up adds to the stake. |
| ACTIVE → UNSTAKING | validatorUnstake | Arms the lock: unstake_available_at = current block + 1,000. |
| UNSTAKING → EXITED | validatorExit | Only after the lock has elapsed. |
| UNSTAKING → ACTIVE | validatorStake | A top-up clears the unstake, so every stake unit sits under a fresh 1,000-block lock before exit. |
“Stake doesn't currently weight the random pick (Phase 2), but it gates eligibility (you must be
ACTIVE).”
The minimum stake, and reading the table
The minimum stake is a network parameter, minValidatorStake, not a fixed figure. The public Demos SDK reads the value in force with getNetworkParameters(), which it describes as the genesis defaults with every active network upgrade applied, and returns it as a whole-number string (Demos SDK). DNO assumes no figure.
The same SDK lists validator rows with getValidators(): the rows whose status is still active at a block. The lifecycle page describes UNSTAKING as still active until exit and EXITED as removed from the active set, so a count of exited validators does not come from that list.
Counts, as the public seeds list them. Once a minute DNO sends both calls to the three public seeds. It publishes how many rows are ACTIVE and minValidatorStake, each only when at least two seeds return the same answer; it publishes no address and keeps no stake. It then dials the address each ACTIVE validator published on chain and counts the answers: see how the counts are made. It publishes no identity. Given one full key, Find a node on the homepage says whether the agreed list shows that key ACTIVE or UNSTAKING, lists it with another status or does not list it, or that no agreed list is available; it says nothing about any other key.
The first read, with DNO's probe tool on 29 September 2026 at 09:05 UTC: two of the three public seeds returned the same 35 rows, all ACTIVE, and the same minValidatorStake, 1000000000000 as reported. The third seed did not answer.
The first dial, with the same tool at 11:31 UTC that day: 26 of the 35 rows were dialed at the address they published and 9 were not. 7 answered as their own key, all at the seeds' height; 18 answered with another key; 1 did not answer. A count of the published addresses at 11:41 UTC: the 9 publish none, and the 26 sit on 8 origins, one of them published by 19 keys. 2 of the 7 keys that answered as themselves are public seeds. 18 listed keys share one published origin with a key that answered. That is not 18 nodes down. Two runs from one place, not this cycle.
The identities in DNO's catalog are names listed on public peerlists, not validator rows: a larger catalog is not a larger validator set.
Inside a shard
“Per-shard consensus itself runs sequentially — one consensus round per shard at a time — not multiple rounds in parallel within the same shard.”
The parallel part is applying transactions. Within one block, independent transactions are split into groups and up to 8 groups are applied at once; the gain “lives in transaction-application within a block”, “not in concurrent consensus rounds”.
A height that moves, or does not. A designed pause and a fault look the same from outside, so DNO never says why a height stopped.
A node's own health
Every Demos node answers an unauthenticated GET /health on its RPC port. The status is the node's own word (health and readiness):
| Status | What the docs say | HTTP |
|---|---|---|
ok | “All subsystems healthy, main loop alive.” | 200 |
degraded | “At least one non-critical subsystem is failed, but the chain and main loop are alive.” | 200 |
dormant | “The node booted with an empty peer list and intentionally skipped signaling/MCP/TLSNotary/main loop.” Sent with an X-Demos-Dormant: true header. | 200 |
failing | “The mempool/DB is unreachable, the chain subsystem failed, or the main loop died (and the node is not dormant).” | 503 |
On readiness, the same page adds that “a probe wanting to gate traffic until consensus participation can additionally inspect dormant / the X-Demos-Dormant header or require boot.complete === true”.
None of these words. DNO reads each seed's /info, not its /health, and none of these statuses appears in DNO's reading. The peerlists DNO reads carry an online flag and one more status flag for each listed peer. DNO shows the online flag as peer-reported and leaves the other flag out, because the pages linked here do not say what it means.
DAHR
DAHR is the Data Agnostic HTTPS Relay (DAHR API reference). A client using the SDK calls createDahr(), then startProxy({ url, method }). A Demos node forwards the request to the target, returns the response, and hashes it.
- 1client → Demos node
startProxy({ url, method }) - 2Demos node → target URLforwards the requesthttp or https only
- 3target URL → Demos nodethe response
- 4Demos nodeSHA-256 of the body, SHA-256 of the headersheaders are canonicalized first: keys lower-cased, volatile and hop-by-hop headers dropped, sorted by key
- 5on chainone
web2Requesttransaction per callit stores the hashes, not the data; the pages linked here do not say which party signs and broadcasts it - 6SDK → clientthe response, its hashes and the
txHashreturned once the transaction is confirmed and broadcast;txHashis optional in the result type
“Each
startProxycall creates one on-chain web2Request transaction that stores only hashes of the response (body and headers), not the full data.”
What one call records
- SHA-256 hashes of the response's body and headers, in one on-chain
web2Requesttransaction. - Anyone holding the same response bytes can hash them and compare.
What it does not
- Store the response itself: only hashes go on chain.
- Say whether the content is correct, current or complete.
- Prove the TLS session. That is TLSNotary, a separate mechanism the docs list as slower (about 2–5 s against about 500 ms) and costlier (1+ DEM plus gas, against gas only).
Same letters, different object: the Key Server OAuth flow returns a DAHRAttestation, an Ed25519-signed record that the Key Server performed a verification (Key Server OAuth). DNO does not use it.
What DNO does with DAHR
- Each cycle DNO dials its cross-check RPCs. For each one that answers, it asks a Demos node, through the SDK, to relay a
GETof that RPC through DAHR. - It counts an attestation only when a transaction hash comes back, and keeps the URL, the transaction hash, the response hash, the HTTP status and the time.
- When on-chain publication is enabled, DNO attaches those records to its fleet alerts and daily summaries, never to the public reading. On-chain publication is disabled, so DNO posts none of them. The relays themselves still happen: per the Demos docs each relay call creates a
web2Requesttransaction, and DNO counts a relay when a transaction hash comes back, without checking that the transaction was included. /healthreports the state inattestation:available,last_count(how many of those relays returned a transaction hash this cycle) andlast_ok_at.
The three seeds whose answers enter status are not relayed through DAHR, and /organism carries no attestation. That is why the homepage says Observe. Explain. and mentions DAHR once, under the API: the sentence about the cross-check RPCs while attestation.available is true, and “DAHR attestation unavailable.” while it is false. The sentence also says that the reading itself is never posted.
Words that must not share a label
Demos uses its own words for a node's health, a validator's status and a validator skipped from a shard. DNO's words are different, and they describe what DNO saw from outside.
| Word | Whose word | Meaning | DNO sees it? |
|---|---|---|---|
ok degraded dormant failing | the node's own GET /health | ok: subsystems and main loop up. degraded: something non-critical failed, chain still up. dormant: booted with no peers and skipped work on purpose. failing: chain, mempool or main loop down. | No. DNO reads /info, not /health. |
ACTIVE UNSTAKING EXITED | the on-chain validators table | a validator row's status. ACTIVE is eligible for shard selection. | Counts of ACTIVE and UNSTAKING rows, as two public seeds list them. EXITED rows are not in that list, and no row is named. |
| out of sync | consensus, Phase 1 | that validator is skipped for shard composition on those blocks. It is not slashing. | No. |
stable | DNO | this cycle's reading of the public seeds, or of the validators standing in for a missing one: the heights compared agree (strong), DNO has not counted 30 minutes without a new height, and no warning or critical public incident is active. | Yes. It is not ok, and it is not ACTIVE. |
| at the seeds' height | DNO | a validator's own height, in its answer when DNO dialed the address it published, within ±25 blocks of the seeds' median. | Yes, for validators that answered. It is not Demos' sync check, and it is not out of sync. |
strong agreement | DNO | every own height sits within DNO's band, ±25 blocks of the median, and the spread is at most 20 blocks. | Yes, for the heights it compared: the seeds' own; one seed's and the closest stand-in's; or, with no seed, the counted stand-ins'. |
sufficient | DNO | at least two seeds reported their own height, or validators that answer as listed stood in for the missing one, and the observation is at most 300 s old. | Yes. It describes DNO's vantage, not the network. |
reachable unreachable | DNO, for endpoints it dials | an endpoint DNO dialed answered, or did not: the probed seeds on the homepage, the cross-check RPCs on /federate, the probed fixnet rows on /reference. | Yes, for those endpoints. Never for peer-listed identities, which DNO does not dial. |
| peer-reported | a seed's peerlist | what a public peerlist said about another identity. DNO did not dial it. | As reported, never confirmed. |
All 3 public seeds answered and their reported heights agree.One of the plain sentences DNO uses for a calm reading. It never says the Demos network is healthy.
What DNO cannot see
- Who is in a shard.
- EXITED validators: the list DNO reads holds only rows still active at the block.
- Votes, admission, and the health and sync checks consensus applies.
- A node's own
/healthstatus. - Whether a peer-listed identity is a validator, or whether it answers: DNO does not dial the catalog, and matches no catalog row against the validator list. Find a node checks only the one full key a reader gives it.
- Why a validator does not answer DNO. The address may refuse outside callers or be out of reach from here only; the row on chain does not change.
- What stands behind an address that several validators publish. Its answer names one key.
- Why height stopped. A designed pause and a fault look the same from here.
Sources
Demos documentation at docs.kynesys.xyz, read on 28 September 2026. If the docs change, this page may lag; the linked pages take precedence.
- Introductionwhat the Demos Network is
- Demos Network architecturenode and SDKs; validators or synced read-only nodes
- Consensus mechanismPoR-BFT
- Validator lifecyclestates, transactions, the unstake lock, stake gates eligibility
- Decentralization in PoR-BFTthe CVSA seed and per-block shards
- Enhanced securityPhase 1 exclusion of out-of-sync validators; slashing in Phase 2
- Unparalleled scalabilitysequential consensus per shard; parallel transaction application
- Health and readinessa node's own GET /health
- HTTP endpoints/info and /health
- Web2DAHR and TLSNotary compared
- DAHR API reference · typescreateDahr, startProxy, the hashes and txHash
- Web2 proxy (DAHR)how a node hashes and canonicalizes a response
- Key Server OAuthDAHRAttestation, a different object
- Demos SDK@kynesyslabs/demosdk 4.0.14 type definitions: getNetworkParameters, getValidators, the validator status codes
- Global Change Registry · Cross Context Identities · Cross-chain · L2PSthe other parts named above
How DNO forms its own reading: Methodology · Sources · Agent guide.
