Rust protocol, wallet and channel libraries for sidestr sidechains, ported from Melvin Carvalho’s reference implementation.
Start · Architecture · Crates · Status · Oracle checks · Contributing
sidestr is a protocol for user-activated sidechains beside a Bitcoin-family parent. A chain is a JSON document. Its blocks carry a BIP-325 signed challenge instead of proof of work. Coins enter by a peg-in on the parent and leave by a burn the peg holders pay. Nostr relays carry the chain's transactions and its tip announcements.
Melvin Carvalho designed the protocol and the reference implementation this
repository ports (siding, with the bitcoin-desktop/schema kernel and
bitcoin-blake/blaketestnode it loads). This repository is a Rust port of
them. Where it adds something, it says so.
In a sidestr chain the output key of a taproot coin is a 32-byte x-only
secp256k1 key, and so is a Nostr identity. So an agent that holds a
did:nostr key holds a wallet. It can be paid by npub, spend with the key
its identity already has, and sign the event that carries each payment.
sidestr-agent is that wallet.
Experimental chain software. The documented estate example is
sidestr:dreamlabbeside Bitcoin testnet4. This README does not establish a production financial service. The unpublished Liquid adapter targets a different network; its presence is not evidence of a funded reserve or an active bridge.
For a library consumer, begin with sidestr-core for validation, sidestr-wallet for transaction construction or sidestr-agent for an agent-facing wallet.
cargo install sidestr-agent --version 0.6.0
sidestr-agent --help
# Offline: display the address of this public x-only key, with a chosen prefix.
# This is the public generator point, not a private key or a funded account.
sidestr-agent address --prefix drm \
79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798Balance, send and chain-resolution commands need the appropriate producer, mirror or relay configuration. A key's address is not evidence of a balance. The agent guide covers key files, peg-in planning, dry-run delivery and chain selection.
flowchart TB
HEAD["sidestr-header: Bitcoin-family headers"]
CORE["sidestr-core: deterministic chain validation"]
WALLET["sidestr-wallet: transaction construction"] --> CORE
ROUND["sidestr-round: co-signing state machine"] --> CORE
HITCH["sidestr-hitch: channel kernel"] --> CORE
EVM["sidestr-evm: optional execution rule"] --> CORE
NOSTR["sidestr-nostr: events and signing port"]
AGENT["sidestr-agent: wallet application"] --> WALLET
AGENT --> NOSTR
HEAD -.->|"Header family selected by the host"| HOST["Host: producer, relays, parent node, persistence"]
CORE -.-> HOST
ROUND -.-> HOST
HITCH -.-> HOST
NOSTR -.-> HOST
LIQUID["Unpublished Liquid adapter"] --> RESERVE["Unpublished reserve attestation"]
Dependency arrows point from a consumer to a library; dotted lines identify services a host must compose. sidestr-core does not depend on sidestr-header, Hitch or revm. Script compatibility and tested wire messages do not supply a running channel service or Lightning-network interoperability.
| crate | what | crates.io | docs |
|---|---|---|---|
sidestr-header |
both header families: stock 80-byte SHA-256d and Knots' 164-byte v2 BLAKE2b; compact targets, powLimit, BIP-325 block data; no_std |
docs.rs | |
sidestr-core |
the chain document, parents table, signed blocks, peg-in claims and peg-out burns, Knots' unified sighash, the parent view, block files, SPEC 12 assets, constant-product pools and prediction markets, a validating chain | docs.rs | |
sidestr-nostr |
the Nostr plane: NIP-01 events, a sealed signer port, tips (33333, with the peg script), transactions (23500/23501/23503), rule and genesis documents, the round envelopes, estate kinds 38420–38425 | docs.rs | |
sidestr-wallet |
coins, the reference coin selection, key-path spends, burns and EVM deposits signed by the parent's family, spends with records, issued assets (issue, transfer), the peg-in shape, delivery | docs.rs | |
sidestr-round |
the level-2 co-signing round and the peg-out PSBT round as pure state machines on the reference's wire, a vote journal, the cosign signer |
docs.rs | |
sidestr-hitch |
Hitch's Lightning-shaped channel kernel: 2-of-2 funding, revocable commitments, HTLCs and claims, peer finality/recovery, durable snapshots, invoices and one-hop routing | docs.rs | |
sidestr-agent |
an agent wallet where the did:nostr key is the wallet: balance, npub → address, spends, burns, EVM deposits and asset transfers as kind-23500 events, a peg-in plan, a faucet; the library builds for wasm32 | docs.rs | |
sidestr-evm |
the evm rule: Ethereum transactions carried in sidechain transactions, run through revm (Cancun) beside the UTXO set, deposits and withdrawals at 1 sat = 1 gwei, the state root in the coinbase; every root checked against the reference on ethereumjs |
not published | — |
webledgers-teller |
a teller for Web Ledgers on txbt4 (port of solidpayorg/teller, AGPL-3.0-or-later): the ledger and its genesis hash, deposit addresses by additive tweak, signed kind-3700 requests, payouts signed per input; pure | docs.rs |
Unpublished (publish = false), not live, for the owner's private USD unit
of account (ADR-2117):
sidestr-reserve: the reserve attestation thebridgerule will check, independent of the reserve's network. It states the origin, the credits keyed by replay id, the final origin tip, canonical bytes and a BIP-340 signing hook.sidestr-bridge-liquid: the Liquid origin adapter. A watch-only wallet on Blockstream's Liquid Wallet Kit, synced from the public Esplora server, read into asidestr-reserveattestation.
Neither depends on the published crates. Another reserve network would be a sibling adapter.
Dependencies remain acyclic. sidestr-hitch depends on sidestr-core;
the channel crate does not enter the consensus core. sidestr-core never
depends on sidestr-header, nor on the EVM: revm and alloy stay in
sidestr-evm.
Reviewed 21 October 2026 against f77856dd. Individual crate versions are in their manifests; there is no single workspace release version.
Reference commit
e8deb63
(SPEC 0.0.5).
The manifests mark eight crates publishable and three unpublished (publish = false): EVM, reserve and Liquid bridge. The October 2 release commit a7aadd68 updates the protocol/wallet/channel crates and Web Ledgers teller; publication history and configured registry badges are separate from live deployment. CI regenerates pinned reference-oracle fixtures. This README refresh did not rerun the full oracle suite.
Protocol evolution from SPEC 0.0.2 to 0.0.5
- the peg output is the taproot output the peg holders own, at any position (0.0.3);
- signatures follow the parent's family (0.0.3);
- the signer announces the peg script with every tip (the
pegtag), and an output paying it is the peg wherever it sits (0.0.4); - kind 23503 carries a signed parent transaction to a producer with a node (0.0.4);
- a record is exactly its push: bytes after it or missing refuse it (sidestr/spec#17; sidestr-rs always read it so).
- rule activation heights, assets, constant-product pools and binary prediction markets;
- producer eviction for a transaction that admission accepted but a block cannot carry;
- wallet-change and self-funding exclusions in peg scans, with one claim candidate per marker transaction;
- federated tip authors, one relay socket per URL, and
ETagcaching forblocks.json; - EVM snapshots restored at any retained height;
- the chain document as a kind-3500 event whose id is the chain's hash, the
tip's
etag naming it, and resolution by alias or hash with chains made before 0.0.5 resolving as before (0.0.5;sidestr-agent chain-eventandresolve).
- Level 1 (one signer): complete in the implemented reference scope. Both header families work end to end: genesis from the document, production, validation, the mempool policy, claims, burns, the block file, the wallet.
- Level 2 (a k-of-n federation): usable. Blocks are co-signed through the round, interoperating with the reference signer on the wire. Tested with three signers on one box, in both mixes of Rust and JS. Not yet done: a signer on another machine, changing the signer set, and a Byzantine fault-tolerant redesign of the round.
- The
evmrule: ported (sidestr-evm, not yet published). A follower validates an evm chain end to end, with the assets rule as consensus beside it, as the reference installs it on every chain naming a rule. Every state root of a scripted chain matches siding on ethereumjs byte for byte. The JSON-RPC endpoint (evmrpc.mjs) is ported assidestr_evm::rpc. - Assets, pools and markets: ported. Rule activation heights replay from the named height. Pools enforce the reference's integer constant-product boundary; markets cover open, split, merge, resolve, redeem and refund.
- Hitch channels: pure channel kernel ported, at Hitch's fifth adversarial-review round. The funding output, asymmetric commitments with two-party revocation keys, revocable delayed outputs, HTLC success/timeout/penalty paths, cooperative and unilateral close produce the reference's exact scripts and transaction ids. The Rust peer machine covers opening with proofs of possession, update/ack/revoke finality, rejects, set-aside states and their binding, collision handling, recovery, closes, the periodic tick, following a close on the chain and checked snapshots. Invoices and one-hop hub routing preserve Hitch's fee, timeout and protective-close rules. A host still supplies wallet funding, Nostr relay I/O, chain watches, storage and broadcasting.
- Out of scope: a trust-minimised peg-out and the draft dispute and multi-outcome market extensions. Assets are also available as a holders' view on chains that do not adopt the rule.
Reference conformance uses pinned upstream implementations as oracles. The following describes the test suite's scope, not a fresh run during this documentation review. Passing it establishes agreement on the covered fixtures and behaviours, not consensus safety under arbitrary faults.
Oracle coverage and how to run it
- Genesis: a throwaway chain's genesis is byte-identical to the one siding
seals. The sealed
sidestr:dreamlabgenesis replays to its documented hash. - Blocks: blocks made here are accepted by siding, and siding's are accepted here.
- Live chain replay: Melvin Carvalho's live
sidestr:txbt4-sidingchain (BLAKE2b parent) replays from genesis to its tip with every rule on. - Records: claims, burns and records read alike; the same blocks give the same records.
- Wallet: its spends and burns pass siding's
Siding.submit(). - Signatures: each engine verifies the other's key-path signatures under the family's rule. With the same auxiliary randomness they are byte-identical, on both families.
- Nostr events: events are byte-identical to siding's, including id and signature.
- Round: Rust and JS co-signers seal the same blocks and pay peg-outs proposed by either engine.
- EVM: a scripted
evmchain of 35 blocks, run by siding'sevm.mjson ethereumjs 10.1.3, is replayed bysidestr-evm: every accepted block's state root, withdrawals and receipts match byte for byte, and every refused block is refused (sidestr-evm/tests/oracle.rs). - Hitch: every Rust-built commitment, close, delayed sweep, penalty,
HTLC success/timeout/revocation claim and direct key-path claim, and every
transaction a Rust protocol run broadcasts, is checked by Hitch's
JavaScript module and the schema kernel interpreter, which also refuses an
owner's attempt on its own revocation leaf; Hitch recomputes the two-party
revocation key and verifies a Rust proof of possession
(
sidestr-hitch/tests/oracle.rs). Every message kind,rejectincluded, passes Hitch's exact JavaScript wire validator (sidestr-hitch/tests/wire_oracle.rs). Hitch's peer and adversarial suites run in Rust, 21 and 77 checks. - Audit regressions: independent audits' counter-examples are kept as
tests/audit_regressions*.rs. The 0.0.3 release was verified by GPT-6 Astra before publishing. It re-ran every gate and confirmed each change at its layer against the reference. It compared 103 stock and 104 BLAKE2b block snapshots, including claims, burns and the full UTXO set, and found them equal. It raised four findings, all fixed and pinned astests/audit_regressions_0_0_3.rs.
To run the oracle suites, check out the four reference repositories at the pinned commits and name them:
git clone https://github.com/sidestr/spec && git -C spec checkout e8deb63161c7459ed39c01d2ca9fda3d860b65b6
git clone https://github.com/bitcoin-desktop/schema && git -C schema checkout b8cbf6337c7450fe14ddc5bce00c7280059aab5d
git clone https://github.com/bitcoin-blake/blaketestnode && git -C blaketestnode checkout f1da4a6b64a6a9a6f791d2e5dea8a1c1be81ea09
git clone https://github.com/bitcoin-blake/hitch && git -C hitch checkout 62f8e390b8acbbf1e534ee48cf2d519e0b859586
SIDESTR_SIDING=$PWD/spec/siding SCHEMA=$PWD/schema BLAKETESTNODE=$PWD/blaketestnode HITCH=$PWD/hitch \
cargo test --workspace --all-featuresWithout these four variables the oracle halves say they are skipped, and
the Rust halves still run. You need Node.js 20 or later, and no npm install. CI runs both ways (.github/workflows/ci.yml).
The recorded sidestr:dreamlab instance uses Bitcoin testnet4 (tbtc4):
- address prefix
drm; - genesis
4db37517728bd509c0cb96ee5a2e3e2a77f9e965a092e9f67948b413d453dbc0, sealed 2026-09-22 (the document is vendored atsidestr-core/fixtures/dreamlab/chain.json); - mirror: https://dreamlab-ai.github.io/sidestr-dreamlab, holding
chain.json,blocks.datandblocks.json.
The repository’s deployment record assigns the instance to Agentbox with the upstream JavaScript siding producer. No live service probe was made for this README refresh. The Rust workspace is the validated library component;
deploying a Rust producer for this chain remains separate work.
On 2026-09-23 it ran its first full economic loop:
- a peg-in from testnet4;
- three trades between two agents, each a kind-23500 event signed with the agent's own Nostr key;
- a peg-out paid back on testnet4.
That loop found the two issues SPEC 0.0.3 fixes.
Earlier evidence also records an isolated BLAKE2b parent-node pair. That is staging history, not proof of an active sidestr deployment. See the local decision ledger for the implementation/activation split.
sidestr-rs supplies optional economic protocol libraries. Identity, runtime policy, storage and knowledge grounding belong to their respective products:
- VisionFlow: the ecosystem these components make up.
- VisionClaw: a knowledge graph engine with immersive 3D and XR and embodied agent swarms. It is the flagship.
- agentbox: a sovereign agent
container with
did:nostridentities. These crates were developed there. TheADR-,PRD-andDDD-numbers in the crate docs refer to its decision ledger. - solid-pod-rs: a Rust-native Solid pod server (LDP, WAC, NIP-98).
- nostr-rust-forum: a decentralised Nostr forum, all Rust.
- loom: the ontology node and model façade.
- knowledgeGraph: the public ontology frontend.
- dreamlab-ai-website: the dreamlab website.
Our local ADR ledger records the compatibility-oracle, crate-boundary and reserve-adapter decisions owned by this repository. Estate deployment and policy decisions remain in their owning repositories and are linked from the local records.
The sidestr crates are AGPL-3.0-only (LICENSE); webledgers-teller declares AGPL-3.0-or-later, following its own upstream. Inspect the individual crate manifest and notices when consuming it. The reference implementation these
crates port is AGPL-3.0, and they are derivative works of it: attributed
ports of its logic, tested against it. So they carry the same licence. They
are not dual-licensed, and a permissively licensed crate must not depend on
them. A network service built from them owes its users the source, as the
AGPL requires.
See CONTRIBUTING.md.