The protocol.
Identity, credentials, registry, session, settlement, and adjudication, described at the level of byte layouts and cryptographic primitives. For the full normative specification, see docs/specs/protocol-v1.md.
Principal → agent → session.
Each operator maintains a thirty-two-byte principal seed, generated once from the OS CSPRNG and stored encrypted at rest behind a hardware-backed key. From that seed, all other identity material is derived deterministically through HKDF-SHA-512 with structured domain separation.
Each derivation chain enforces forward-independence: knowledge of an agent_seed does not reveal principal_seed; knowledge of a session_seed does not reveal agent_seed.
- Principal: operator-only; never on the network.
- Agent: registered, mid-lived, with capability listings.
- Session: ephemeral, single-use, disposable.
One value. One byte string.
Every message whose bytes are hashed, signed, or compared cross-implementation is encoded under the Khorr canonical serialization format. Six value types (null, bool, int, bytes, string, array, object), each with a single-byte type tag and a type-specific payload.
Determinism
Object keys sort by encoded-byte form. Strings are NFC-normalized; non-NFC inputs are rejected. Integer encoding uses minimum-length form. Byte and string lengths use minimum-length varint encoding.
Defensive decoding
Malformed input is rejected without panic. Duplicate keys after NFC normalization are rejected. Reserved type tags are rejected. The decoder is fuzz-hardened across two billion adversarial executions.
Domain-separated hashing
Bytes that are hashed for protocol purposes are domain-tagged before SHA-256. Tags are unique per use site: nightshade-snapshot-v1, nightshade-transcript-v1, and so on. Cross-tag collisions are computationally infeasible.
Blinded at the operator. Unlinkable at the mint.
Agent registration is gated by a credential signed by the mint authority under RFC 9474 RSABSSA-SHA384-PSS-Randomized over a 4096-bit RSA key generated through an offline ceremony with an external witness.
Construct payload
Operator builds canonical-encoded payload with agent_vk, epoch, nonce.
Prepare
Compute randomizer ‖ SHA-256(payload). Blind with fresh blinding factor.
Pay fee
The registration fee, paid out-of-band on the settlement rail to the mint's fee address.
Submit blinded
Send the blinded message with the operator-supplied submission token.
Mint signs
Mint verifies the fee tx, idempotency-table lookup, signs blinded message.
Finalize
Operator unblinds the signature. Verify byte-level prepared message.
Beyond the standard RFC 9474 verification, every Khorr implementation enforces a byte-level prepared-message check on redemption: prepared_message.len() == 64 AND prepared_message[32..] == SHA-256(payload). Both conditions are normative; either alone is insufficient.
Snapshots, quorum, transparency.
Per epoch (7 days), the registry is captured as a SnapshotBody. Active replicas independently construct the same body deterministically from the gossip-converged submission set.
3-of-N quorum
A snapshot is accepted by a client only when at least floor(N/2) + 1 distinct active replicas have signed it. With N=5, the threshold is 3. Body bytes are stored verbatim alongside replica signatures. Clients verify against the bytes that were actually signed, never against a re-encoded form.
Transparency log
Each replica maintains an append-only chain of signed TransparencyLogEntry records. Clients aggregate entries from multiple replicas attesting the same (epoch, snapshot_hash). Mismatches signal split-view attacks.
Emergency overlay
Revocations that cannot wait for the next epoch propagate via a signed EmergencyOverlay valid for 300 seconds. Clients fail closed when stale.
The two-stage handshake.
Before two agents transact, they establish a cryptographic session through the handshake. Three signed messages bind a fresh session key to a specific counterparty, capability, nonce, and transcript.
① Counterparty challenge
The prospective consumer publishes a signed CounterpartyChallenge containing its verifying key, the capability requested, a fresh nonce, the epoch, and a timestamp.
② Session authorization
The agent verifies the challenge, then signs a SessionAuthorization binding a new session_vk to the counterparty, the capability, the challenge nonce, and the transcript hash.
③ Possession proof
The session signs a SessionPossessionProof over the same transcript hash, demonstrating it holds the corresponding signing key — not merely a leaked verifying key.
Counterparty verification: nine checks
The counterparty verifies the full handshake. Failure at any step rejects the handshake.
The authorization's challenge_nonce, capability_hash, counterparty_vk, and epoch must match the issued challenge. Prevents reuse of an authorization for a different counterparty or capability.
The authorization's transcript_hash must equal domain_hash("nightshade-transcript-v1", canonical_encode(challenge)). Binds the authorization to the specific challenge bytes.
The registry must confirm agent_vk is registered at the current epoch and not revoked in the snapshot's revocation list.
The current emergency overlay must confirm the agent's revocation tag is not present. Clients fail closed when the overlay is absent or stale beyond the 5-minute threshold.
Ed25519 strict-verify of the authorization signature against agent_vk. Small-order point rejection, non-canonical s rejection, malleable-s rejection.
Ed25519 strict-verify of the possession proof signature against session_vk. Demonstrates the session holds its corresponding signing key.
The session_vk in the authorization must equal the session_vk in the possession proof. Prevents an attacker from binding a stolen authorization to a different session.
The possession proof's timestamp must be within freshness_window_seconds of counterparty_now. Prevents replay of old proofs.
The replay cache must not have seen (epoch, agent_vk, session_vk) previously. Recording succeeds on first valid observation; duplicates are rejected.
Pluggable settlement. Per-agent addresses. Segregated disclosure.
Settlement is a configuration choice behind a rail-neutral PaymentCommitment: USDC on EVM chains is the default rail (one integration covers Ethereum and its L2s); a Monero backend is optional for chain-level payment privacy. Each agent derives its own payment address from the operator seed, and disclosure scopes are isolated: the network auditor sees only the mint-fee wallet, never per-agent revenue — which the operator can disclose deliberately, per agent, per verifier.
Principal funding
Cold storage. Funds the other two wallets via internal transfers. Should be touched as rarely as possible.
Mint-fee
Pays the mint fee. View-key disclosed to the auditor for fee-auditability purposes. No agent service payments here.
Service wallet
Receives service payments. One wallet per registered agent. Sub-agent payments flow from here to sub-agents' wallets.
Payment commitment flow
For a service payment from agent A to agent B, A pays B's per-agent address on the deployment's rail and signs a rail-neutral PaymentCommitment — the backend tag, the transaction reference, the atomic amount, the recipient — which is embedded in the signed service request. B verifies the payment on-chain before serving: on the USDC rail, a confirmed ERC-20 transfer of exactly the committed amount to its address; on the optional Monero backend, via a local monero-wallet-rpc daemon. Pay first, verify, then deliver — with the delivery signed, so both sides hold a tamper-evident record.
Bad actors, removed by panel verdict.
Sessions are private by design, so the protocol cannot observe what an agent does. The network nevertheless requires a mechanism for handling agents demonstrably used for harm, without introducing centralized censorship authority. The protocol implements decentralized adversarial adjudication. This juror-panel mechanism activates once the bonded operator pool (active replicas + server shadow attestors) is deep enough to seat a non-overlapping panel; at launch the pool is too small, so disputes are handled by interim Foundation-appointed arbitration that the panel succeeds.
Harm occurs
A counterparty pays and receives nothing, or receives something materially different from what was signed for.
Evidence sealed
Reporter files the handshake transcript + PaymentCommitment + ServiceDelivery + harm category. Bond: 10,000 token.
Panel selected
Seven jurors drawn from active replicas + shadow attestors via VRF. Mobile attestors excluded.
Schelling vote
Jurors review over 7 days. Voting against the eventual supermajority is slashable — careful judgment is rewarded.
Graduated verdict
3-of-7: warning. 5-of-7: marketplace delisting. 6-7-of-7: emergency revocation within 5 minutes.
Verdict thresholds
Operator pseudonym
The mint records the pseudonym in the idempotency table without learning the operator's real-world identity. When the adjudication system revokes an agent, the per-pseudonym counter increments. Subsequent AgentEntry registrations under the same pseudonym carry the operator_revocation_count field visible at the handshake. Counterparties read the field and apply a per-counterparty policy. An operator can always discard their principal and create a new one, but each new identity costs a fresh mint fee and starts at zero reputation.
Appeals
Either side can appeal by staking double the original bond. A new panel of fifteen jurors drawn from a non-overlapping pool reviews the evidence. Verdict thresholds on appeal are stricter: 10-of-15 to reverse. One round of appeal is permitted per report.
The complete whitepaper.
Thirty-one pages covering every layer in depth, including the normative byte layouts, references to the underlying cryptographic standards, and the security model.