Programmable Access Control on Bitcoin SV
The normative specification for the $403 Conditions Machine — on-chain finite state machines for permissions, restrictions, and programmable access control, enforced by sCrypt smart contracts and validated through Proof of Indexing.
Status: This specification is in DRAFT status. Implementations SHOULD NOT treat this as stable. The key words “MUST”, “MUST NOT”, “SHOULD”, “MAY” are to be interpreted as described in RFC 2119.
HTTP 403 means Forbidden — the server understood the request but refuses to authorize it. The $403 protocol extends this concept to the programmable web: conditions that determine access are no longer ad-hoc application logic but first-class on-chain objects — inspectable, composable, transferable, and enforced by the Bitcoin network itself.
$403 is the third protocol in the $40x stack:
Who you are. Root key, OAuth strands, attestations.
What you pay. Tokenized URL access, micropayments.
Whether you may. Programmable rules, gates, restrictions.
This document specifies the data structures, state machine semantics, on-chain encoding, guard expression language, Proof of Indexing mechanism, and integration points of the $403 protocol.
The $403 protocol defines a system where access conditions are:
A Condition is the atomic unit of the $403 protocol. Every condition MUST contain the following fields:
States array MUST contain 2–8 entries.
State names MUST be uppercase ASCII, max 32 chars.
Every state MUST be reachable from initial.
If irrevocable: true, the issuer key MUST NOT appear in any guard as a bypass authority.
Conditions MAY reference other conditions by ID (composition).
Every $403 condition is a deterministic finite state machine (FSM). The FSM is defined by:
A transition from state sᵢ to sⱼ fires if and only if:
sᵢG(context) evaluates to trueThe FSM is deterministic: given the same state and context, the same transitions fire. The guard language is intentionally NOT Turing-complete — all guard evaluations MUST terminate in bounded time.
Guards are boolean expressions written in a restricted predicate language. The language supports:
Restriction: No loops, no recursion, no unbounded computation. Guard evaluation MUST complete in O(n) time where n is the expression depth. Maximum expression depth: 16. Maximum referenced conditions in a single guard: 8.
A Transition object defines a single edge in the state machine graph:
subject — only the subject's $401 key can trigger.issuer — only the issuer can trigger.any — anyone with a valid guard proof can trigger (used for time-based auto-transitions).
Minimum number of blocks that MUST pass between consecutive triggers of the same transition. Prevents rapid state oscillation. MUST be 0 or greater. A value of 0 means no cooldown.
When irrevocable: true is set on the condition, reverse transitions (back to a previous state) MUST NOT list the issuer as authority. The issuer cannot undo the condition. Only the guard logic can advance state. This is critical for self-imposed restrictions (savings locks, vesting schedules).
Each $403 condition exists as a UTXO on BSV containing an sCrypt smart contract. State transitions spend the current UTXO and create a new one with the updated state, forming an immutable chain of state changes.
New condition → Deploy sCrypt contract as UTXO. Initial state set. Condition ID derived from txid.
Spend current UTXO → new UTXO with updated currentState. Auditable on-chain history.
Read latest UTXO for condition ID. Current state is currentState. No transaction needed for reads.
Conditions are only useful if they are correctly evaluated. Proof of Indexing (PoI) ensures that indexers who report condition states have actually done the computation.
Indexer processes a batch of N condition evaluations (recommended: N = 1000).
For each evaluation, record tuple: (condition_id, prev_state, new_state, guard_inputs_hash, block_height).
Construct a Merkle tree over all tuples. The root is the batch commitment.
Compute a PoW nonce meeting the current difficulty target: SHA256(merkle_root || nonce) < target.
Inscribe on-chain: { merkle_root, nonce, batch_size, indexer_pubkey, stake_txid }.
Challenge window: 144 blocks (~24h). Any party may request a Merkle proof for any condition_id in the batch.
If challenged, indexer MUST produce the Merkle proof. Failure to respond or incorrect proof: stake is slashed.
After challenge window: PoI is finalized. Indexer earns $403 tokens proportional to batch_size.
Unforgeable cost: PoW nonce requires real energy expenditure.
Verifiable: Merkle proofs are O(log n) to verify.
Challengeable: Any incorrect state can be proven wrong.
The $403 protocol defines seven standard permission classes. Each class has distinct guard patterns, authority models, and legal considerations:
The three protocols form a complete access control stack. Integration points are well-defined:
$401.resolve(pubkey) → Identity object with strands
$401.strand(type) → Specific attestation data
$401.strand_count() → Number of verified strands
$401.verify(attestation) → boolean
$402.balance(pubkey) → Token balance
$402.payment_state(resource) → Paid / Unpaid
$402.bind_condition(resource, condition_id) → Link
$402.process_payment(resource, identity) → Receipt
$403 messages are encoded as JSON over HTTPS or as on-chain OP_RETURN data. Two primary message types:
The $403 token governs the conditions network. It is earned through mining and indexing, and staked by condition evaluation nodes.
Mining: Hash-to-mint. Submit valid PoW to contract, receive $403.
Indexing: Earn $403 by submitting valid Proof of Indexing batches.
Staking: Stake $403 to run a condition evaluation node. Required for PoI submission.
Governance: $403 holders vote on protocol parameter changes (batch size, difficulty, stake minimum).
The $403 security model rests on three pillars:
Conditions are enforced by Bitcoin Script via sCrypt contracts. Miners validate every state transition. An invalid transition is an invalid transaction — it MUST NOT be mined. This provides the same security guarantees as Bitcoin's double-spend prevention.
Indexers MUST prove their work. The Merkle tree of state transitions is publicly challengeable. False claims result in full stake slashing. The economic incentive for honest indexing mirrors Bitcoin mining game theory.
Self-imposed restrictions are cryptographically irrevocable. No key, no social recovery, no admin override. The script will not execute until the programmed condition is met. This is what makes $403 useful as a commitment device.
The guard expression language is intentionally restricted: no loops, no recursion, maximum depth of 16. All evaluations terminate in bounded time. This prevents denial-of-service via complex guard expressions.
This specification intentionally leaves several areas for future work:
$403 Protocol Specification — Draft v0.1.0 — February 2026 — @b0ase
Not legal advice. Not financial advice. Subject to change.