2026 Update
The 2026 Review assessed the Assign Onward design documents and outlined what a fresh implementation could look like. Four days later, development began. This update reports what was actually built: eight Rust crates, a React PWA, 742 tests, and a protocol that has progressed from serialization primitives to competing recorders with atomic cross-chain escrow.
What Was Built
Phase 0: Specifications (Weeks 1–4)
The 2018 design documents were spread across 30+ HTML files with numerous ambiguities—unspecified negative VBC encoding, undocumented type code schema, unresolved separability bit positions, unspecified signature byte format, undetermined deterministic rounding rules. All were resolved in writing before any code was written. Four specification documents and a conformance test vector file now serve as the single source of truth:
Architecture. Actor model with precise trust boundaries. System topology (HTTP, WebSocket, MQTT, SSE). Data flow diagrams for the full lifecycle of a share assignment. Security model: where private keys live, what each component can and cannot do if compromised.
Wire Format. Byte-level binary specification. VBC encoding with 30+ worked examples including negative numbers. DataItem structure. GMP integer and rational fraction encoding. Timestamp encoding (signed i64, Unix seconds × 189,000,000, ~5.29ns resolution). Complete block layout with a worked minimal example.
Cryptographic Choices. Ed25519 (RFC 8032) for signatures, SHA2-256 for chain integrity, BLAKE3 for content addressing. Wallet encryption via Argon2id + XChaCha20-Poly1305. One signature type, two hash types, extensible via type codes.
Economic Rules. Deterministic fee arithmetic (ceil(data_bytes × FEE_RATE_num × SHARES_OUT / FEE_RATE_den)), arbitrary-precision integer, division last. Expiration modes (hard cutoff and age tax). Late recording semantics. Five worked fee examples.
Conformance Vectors. A JSON file with hand-computed test vectors: VBC (30+), GMP integers (15+), rationals (10+), timestamps, signatures with timestamp concatenation, minimal genesis block, assignment, block with correct hash, fee calculations, expiration calculations. These are the ground truth all implementations build against.
Foundation Layer (Weeks 5–10)
Three Rust crates established the protocol foundation.
ao-types implements VBC signed/unsigned codec, DataItem binary and JSON serialization, a 56-code type registry, BigInt/Rational encoding via num-bigint/num-rational, the AO timestamp type, recording fee arithmetic with ceil rounding, and separable item identification. 42 tests including property-based fuzzing across the full i64/u64 range.
ao-crypto wraps Ed25519 via ring 0.17,*Originally specified as ed25519-dalek, switched early in Phase 1 after discovering a test vector incompatibility. The lesson is documented in the repository.
provides SHA2-256 and BLAKE3, implements separable-item hash substitution, and signs/verifies DataItems per the wire format specification. 13 tests.
ao-cli provides command-line tools: ao keygen (Ed25519 keypair generation), ao genesis (complete genesis block creation), ao inspect (binary DataItem to JSON/hex), and later expanded to nine commands covering balance queries, assignment building, refutation, history, and export.
All Phase 0 conformance vectors pass. Genesis block binary round-trips produce identical bytes. Fee arithmetic matches the specification examples exactly.
Single-Chain Recorder—TⒶ¹ (Weeks 11–20)
ao-chain implements the chain engine: genesis loading with issuer signature verification, SQLite UTXO store (sequence ID to pubkey, amount, block, timestamp, status), block construction with hash chaining, assignment validation (participant signatures, timestamp ordering, UTXO availability, expiration, single-use key enforcement, deadline with late-recording rules, balance equation), expiration sweep, and refutation tracking.
ao-recorder is the HTTP server: Axum 0.8 with multi-chain hosting. Create chains from genesis JSON at runtime. Per-chain endpoints for info, UTXO lookup, block retrieval, assignment submission, refutation, SSE real-time events, and WebSocket. TOML configuration supports single-chain and multi-chain startup. 14 integration tests cover the full API surface including double-spend rejection, key reuse rejection, and real-time notifications.
Deployment artifacts: multi-stage Dockerfile, hardened systemd service file, GitHub Actions CI with x86_64 build/test/clippy and aarch64 cross-compilation.
Vendor and Consumer Apps (Weeks 21–28)
A React Progressive Web App provides vendor and consumer interfaces, built in progressive layers:
Protocol simulation harness. A Rust binary exercising genesis, assignments, SSE, and error cases against a live recorder, producing reference JSON fixtures for TypeScript conformance testing.
TypeScript core data layer. VBC codec, DataItem JSON serialization, BigInt/Rational encoding (native JS BigInt), timestamp conversion, recording fee calculation. All conformance vectors pass.
Browser crypto. Ed25519 keygen/sign/verify via the Web Crypto API,*Supported natively in Chrome 113+, Edge, Firefox 129+, Safari 17+. No fallback library needed—coverage is effectively universal for modern browsers.
SHA-256, BLAKE3 (WASM), separable-item hash substitution, wallet encryption (Argon2id in Web Worker), IndexedDB key storage.
Consumer view (AOE). Wallet with persistent Ed25519 seed, UTXO balance scanner, transfer with change (two-receiver assignment, 3-round iterative fee convergence), real-time SSE block events, chain discovery via QR scanner, transaction history with CSV export, offline assignment queue with auto-submit on reconnection.
Vendor view (AOS). Incoming assignment monitor via SSE, share float display, price card, vendor profile editor with GPS location, printable QR signage (SVG preview, PDF print, PNG download), sales reporting with daily/weekly/monthly aggregation, payment notification chime (three sound styles, quiet hours, quick-mute).
Investor view (AOI). Multi-chain portfolio dashboard, exchange status with current rates, trade history with filters.
PWA infrastructure. Vite + React 19 + TypeScript. Service worker with stale-while-revalidate caching. Offline-first with IndexedDB queues. 70KB gzipped production build. Installs from the browser on iOS and Android without app store review.
Market Making and Exchange (Weeks 29–38)
ao-exchange is a standalone daemon with a config-driven trading rules engine (configurable spreads, float-sensitive pricing, position limits). The agent loop monitors chains via SSE, matches incoming shares against rules, and executes two-leg trades automatically. The trade request API generates fresh deposit and receive keys with configurable TTL. Deposit detection upgraded from polling to SSE with automatic polling fallback. Trade history persisted in SQLite with time-range queries, pair volume aggregation, and P&L tracking.
MQTT block publishing via rumqttc: optional integration in ao-recorder. Blocks published to topic-prefixed channels after construction. Recorder runs normally without MQTT configured. Exchange agent registration with TTL expiration, spread/min/max metadata, and contact URL for trade requests.
EXCHANGE_LISTING on-chain structure: separable container children (chain symbol, amount, note) attached to every agent-initiated assignment, making exchange rates transparent and auditable.
Validation and Trust (Weeks 39–44)
ao-validator is a standalone daemon that periodically polls recorder chains, verifies blocks against a rolled-up hash, tracks chain status (ok / unreachable / alert), and maintains state in SQLite. It provides an HTTP API for querying validation status, fires webhooks on alteration/unreachable/recovered events, and publishes external anchors.
The design principle is built-in, not required. A chain with zero validators, zero anchors, and zero credentials is a valid, functional chain. Trust features reduce risk when available, degrade gracefully when absent, and never gate basic operation.
External anchoring. File-based append-only anchor backend with a pluggable trait for future Bitcoin OP_RETURN, transparency log, or IPFS backends. Replicated anchors write to a primary path plus N replica paths (best-effort). Anchoring is operator-invoked—frequency is a deployment decision. Auto-anchoring triggers after configurable block intervals.
Vendor credentials. CREDENTIAL_REF and CREDENTIAL_URL as separable items in vendor profiles. Structure: URL + SHA2-256 content hash. Client-side verification fetches the URL and compares the hash. No JSON-LD parsing, no DID resolution, no issuer signature verification—hash-match only, which is sufficient for the face-to-face trust model the system targets.
PWA trust indicators. Validator endorsement display: green (verified, at most one block behind), amber (lagging), red (alert/unreachable). Credential hash-match: green check, red warning, grey dash. Indicators appear automatically when data is present, hidden when absent.
Atomic Multi-Chain Exchange—TⒶ² (Weeks 45–54)
The CAA (Conditional Assignment Agreement) protocol enables atomic value transfer across independent blockchains. This was identified in the 2026 Review as the most technically demanding component of the system.
Ten new type codes (69–78) define the CAA wire format: CAA envelope, per-chain components, chain references, escrow deadlines, chain ordering, recording proofs, coordinator bonds.
Escrow state machine in ao-chain: proposed → signed → recording → binding → finalized / expired. Escrowed shares cannot be spent in regular assignments. Expired escrows auto-release. The ouroboros recording protocol submits to chains in order, collects recording proofs from each, then submits binding proofs back to earlier chains. Idempotent submission handles retries.
Coordinator in ao-exchange: execute_caa() orchestrates the full ouroboros sequence—builds signed CAA with per-component and overall signatures, iterative fee convergence, sequential submission, proof collection, binding.
PWA escrow UI. Propose Swap form with fee-aware balance computation, pending escrow list with countdown timer, status polling. The Review noted that “a practical first deployment could defer multi-chain atomicity by having exchange agents hold inventory and absorb the settlement risk themselves.” Both approaches are now implemented: Charlie-style inventory holding (ao-exchange auto-trade) and full atomic CAA escrow.
Beyond the Protocol: Deployment Readiness
Phases 0–6 produced working protocol software. The next 35 work items (N1–N35) closed the gap between “protocol works” and “a real person can use this.”
Operations
Server setup. ao-recorder init generates a starter config with fresh keypair. ao-recorder doctor runs a diagnostic checklist: config parseable, seed valid, directory writable, port available, SQLite functional. ao-recorder bench benchmarks block insertion and Ed25519 throughput.
Monitoring. /health JSON endpoint with per-chain metrics (block height, UTXO count, DB size, last block age) and system metrics (RAM, CPU, disk). Self-contained /dashboard HTML page with 10-second auto-refresh, color-coded status dots, RAM and disk gauges. Optional Prometheus /metrics endpoint behind a feature flag, with counters, gauges, and histograms for block submissions, blob uploads, SSE/WebSocket connections, validation runs. Example Grafana dashboard provided.
Alerting. Background task checks disk space, stale chains, and memory baseline every 60 seconds. Webhook integration fires HTTP POST for disk warnings, critical disk, and stale chain events.
Sysop guide. Comprehensive operations document covering installation (Pi, Debian, Windows, source), first-time setup, monitoring, common problems and solutions, disk management, TLS configuration (Caddy and nginx examples), benchmarking, full configuration reference, and operational checklists.
Security Hardening
A structured security audit identified ten items in the HTTP/deployment harness. All resolved:*The core protocol (signatures, shares, fees, timestamps, serialization) was clean. Every security finding was in the surrounding infrastructure: authentication, rate limiting, connection management, error sanitization, BigInt precision in exchange arithmetic.
API key authentication with Authorization: Bearer header. Per-IP token-bucket rate limiting with configurable read/write limits. Connection semaphore for SSE and WebSocket (excess connections get 503). BigInt exchange arithmetic replacing f64 (exact precision, no rounding errors). PREV_HASH chain validation in the validator. Lock error handling (no more .expect() on mutex locks). Validator URL validation rejecting non-HTTPS for non-local hosts. Block size guard (1 MB) before deserialization. Error sanitization (generic messages to clients, details in server logs only).
Wallet and Multi-Device Sync
The single-use key model means a wallet is not one key but a continuously growing set of keys. Multi-device sync was built in five sub-phases:
UTXO validation on connect—queries the recorder for each held key's status on startup and on new block events. Stale keys marked spent. Unknown-device spend alerts displayed.
IndexedDB wallet with keys, peers, config object stores. Device identity (persistent 16-byte random ID). Seed encryption via Argon2id + XChaCha20-Poly1305. Passphrase prompt for setup and session unlock. Migration from single-seed localStorage wallet on first load.
QR key transfer with multi-frame animated QR for large payloads (>1800 bytes). File-based fallback for desktop-to-desktop. Idempotent key import.
Paired-device push relay. X25519 key agreement, HKDF-SHA256, AES-GCM encrypted relay messages. ao-relay crate: Axum WebSocket forwarder with per-wallet broadcast channels and 72-hour message retention. KEY_ACQUIRED/KEY_SPENT/HEARTBEAT sync messages with sequence replay protection.
Encrypted backup. PBKDF2-SHA256 + AES-256-GCM file-based backup/restore. Backup age tracking with staleness warnings.
Binary Attachments
Photo and document attachments on assignments, using DATA_BLOB (type 33) as a separable item with MIME metadata (NUL-delimited: image/jpeg\0<bytes>). Content-addressed blob storage on the recorder with atomic writes, MIME allowlist, per-chain storage quotas (configurable, default 100 MB), and cross-chain isolation. Upload endpoint with security headers (nosniff, no-script CSP, attachment disposition for non-images). Client-side image compression (WebP/JPEG, max 2048px) before upload.
Recording fees computed on pre-substitution size (full blob payloads, not just the 33-byte hash that replaces them on-chain). Machine-readable BLOB_POLICY in genesis blocks (8 new type codes: policy, rule, MIME pattern, retention period, capacity limit, throttle, max size, priority). Automated blob pruning evaluates retention rules, deletes expired files, keeps metadata for 410 Gone responses. Paginated blob manifest endpoint. HEAD endpoint for blob metadata.
Cooperative Metadata
Structured metadata conventions for agricultural cooperatives, using existing AO separable types. Four record types (delivery, sale, cost allocation, advance) encoded in NOTE (type 32) key:value format. Provenance tracing via lot identifiers across deliveries and sales. Dedicated CooperativeView in the PWA with tabbed Entry/Ledger/Provenance interface, per-crop delivery aggregation, and sales summary with revenue tracking.
Recorder Federation and Competing Recorders—TⒶ³
The protocol advanced from TⒶ¹ (single recorder per chain) through TⒶ² (atomic multi-chain escrow) to TⒶ³ (competing recorders with chain migration). This is the most architecturally significant progression: it means no single recorder operator can hold a chain hostage.
Federation infrastructure. Quick-restart resilience with WAL checkpoint on shutdown and integrity verification on startup. Hot standby mode with batch sync and live SSE replication. Signed recorder identity (RECORDER_IDENTITY, type 134). Authenticated sync endpoint (/chain/{id}/sync) with NDJSON streaming and identity header verification. Chain redirect (HTTP 307) for migrated chains. Trusted sync peer configuration.
Owner key rotation. 16 new type codes (128–143) for key rotation, revocation, recorder changes, chain migration, reward rates. Valid key set tracking per block height. Rate-limited rotation with pre-live exemption. Revocation with override, hold, and auto-revocation sweep.
Recorder switching. RECORDER_CHANGE_PENDING → CAA drain → auto-constructed RECORDER_CHANGE. New CAA blocked during transition while regular transactions continue. Dual-signed recorder URL change blocks.
Share rewards. Extended balance equation: givers = receivers + fee burned + reward to recorder. REWARD_RATE_CHANGE via dual-signed blocks (owner + recorder consent). Per-block fee transparency via RECORDING_FEE_ACTUAL, validated against the genesis ceiling.
Chain migration. CHAIN_MIGRATION freeze block, UTXO carry-forward into new genesis, surrogate proof validation (>50% share ownership). Chain reference linking old and new chains.
PWA integration. Owner key management UI with active/held/inactive key grouping and cooldown display. Recorder switch flow with 4-phase visual indicator. Chain migration banner for frozen chains. Reward rate display with dual-signed change flow.
13 of 16 acceptance test scenarios from the TⒶ³ specification pass. Three are deferred pending owner key override implementation and multi-recorder infrastructure.
By the Numbers
| Rust crates | 8 (ao-types, ao-crypto, ao-chain, ao-recorder, ao-exchange, ao-validator, ao-cli, ao-relay) |
| Rust tests | 326 |
| PWA tests | 416 |
| Total tests | 742 |
| Type codes | 56 standard + 16 TⒶ³ = 72 |
| Clippy warnings | 0 |
| Specifications | Architecture, Wire Format, Crypto Choices, Economic Rules, Validation & Trust, Atomic Exchange, Wallet Sync, Blob Retention, Cooperative Metadata, Competing Recorders |
| PWA production build | 70 KB gzipped |
What the Review Got Right
The 2026 Review made several predictions. Most held up:
Rust was the right choice. Memory safety for cryptographic code, cross-compilation to ARM, the ring and sha2 crates, num-bigint/num-rational replacing GMP—all as predicted. The one deviation: no_std was dropped as a hard requirement. No current consumer needs it, the Meshtastic goal is served by the compact wire format (a mesh relay forwards opaque bytes, it doesn't parse DataItems), and the alloc feature-flag machinery added maintenance cost for no benefit. Core serialization signatures are kept alloc-compatible for future extraction if needed.
Axum + SQLite + MQTT + React PWA was the right stack. Axum's tower middleware composability proved especially valuable for adding authentication, rate limiting, and connection management as layers. SQLite's single-file databases simplified multi-chain hosting—each chain gets its own file, trivially backed up or migrated.
PWAs work. Cross-platform, no app store, offline-capable, 70 KB gzipped. Web Crypto API provides native Ed25519 in all target browsers. The one gap the Review didn't anticipate: the single-use key model creates a wallet sync problem that required significant engineering (IndexedDB state model, QR transfer, WebSocket relay, encrypted backup).
CAA was the hardest part. The Review called it “the most technically demanding component” and suggested deferring it by having exchange agents absorb settlement risk. Both approaches were implemented: the simple path (ao-exchange auto-trade with inventory holding) and the full protocol (CAA ouroboros escrow with recording proofs). Having both means deployments can start simple and upgrade to atomic swaps when the volume justifies the complexity.
What Changed
ed25519-dalek was replaced by ring 0.17 early in Phase 1 after a test vector incompatibility. The lesson: trust the specification vectors, not the library's defaults.
SHA3-512 was dropped entirely. The original 2018 design specified SHA3 as an option. SHA2-256 handles chain integrity and separable item replacement; BLAKE3 handles content addressing and performance-sensitive hashing. Two hash types are sufficient.
TⒶ³ competing recorders went from “not covered” to implemented. The Review did not discuss recorder competition. The specification and implementation were driven by the deployment stories: if a chain's recorder becomes unreliable or extractive, the chain owner needs an exit path. Owner key rotation, recorder switching, and chain migration provide that exit.
Cooperative metadata emerged from the deployment stories. The Farming Cooperatives story created requirements not anticipated in the original protocol design: structured record types, lot-level provenance tracing, crop aggregation. These were implemented using existing separable types (NOTE, DESCRIPTION, DATA_BLOB) with conventions rather than new protocol features—the type system was flexible enough to accommodate agricultural accounting without modification.
What Remains
Hardware Testing
Several acceptance criteria require physical hardware that has not yet been exercised: 72-hour Pi stress test without memory growth, two-device assignment latency under 3 seconds, iOS and Android PWA install testing, Lighthouse PWA audit, Pi MQTT throughput at 100 messages per second, chaos testing with random process kills and network partitions. The software is ready for these tests; the hardware is not yet provisioned.
The Same Hard Problems
The Review identified three non-technical challenges. None have been solved by code, because they cannot be:
Cold start. The system delivers value only when vendors, consumers, and exchange agents are using it simultaneously in the same area. The software now exists to support a pilot; finding the first community willing to try it is a business problem, not a software deliverable.
Regulatory exposure. Exchange agents likely qualify as money transmitters. Commodity-backed tokens sit closer to gift cards than securities, but the line remains blurry. The architecture targets the most favorable regulatory category, but any real deployment needs jurisdiction-specific legal counsel.
Competition from established systems. Square, Venmo, M-Pesa already solve “pay the vendor without cash” in most markets. Assign Onward's advantage remains in contexts where those systems are unavailable, unreliable, or too expensive: small island economies, informal markets, agricultural cooperatives, communities that want to keep economic value circulating locally.
The Review concluded that “the hard problems are not in the code.” That assessment was correct. The code is now written. The hard problems—finding Eddie, Bob, Charlie, and Gene on the same island at the same time—remain exactly where they were.
Assign Onward
9 March 2026
MIT License
Copyright (c) 2018 Assign Onward
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.