Skip to content

About

sidestr-rs — Rust port of Melvin Carvalho's sidestr sidechains, AGPL-3.0-only: the economic engine for did:nostr agents. A did:nostr key is a sidechain wallet.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

sidestr-rs

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:dreamlab beside 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.

Quick start

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 \
  79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798

Balance, 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.

How the pieces fit

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"]
Loading

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.

Crates

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 crates.io docs.rs

Unpublished (publish = false), not live, for the owner's private USD unit of account (ADR-2117):

  • sidestr-reserve: the reserve attestation the bridge rule 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 a sidestr-reserve attestation.

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.

Working status

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 peg tag), 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 ETag caching for blocks.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 e tag naming it, and resolution by alias or hash with chains made before 0.0.5 resolving as before (0.0.5; sidestr-agent chain-event and resolve).
  • 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 evm rule: 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 as sidestr_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.

What is proven against the reference

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:dreamlab genesis 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-siding chain (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 evm chain of 35 blocks, run by siding's evm.mjs on ethereumjs 10.1.3, is replayed by sidestr-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, reject included, 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 as tests/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-features

Without 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).

Estate chain and activation

The recorded sidestr:dreamlab instance uses Bitcoin testnet4 (tbtc4):

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.

Where it sits in VisionFlow

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:nostr identities. These crates were developed there. The ADR-, PRD- and DDD- 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.

Architecture decisions

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.

Licence

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.

Contributing

See CONTRIBUTING.md.

About

sidestr-rs — Rust port of Melvin Carvalho's sidestr sidechains, AGPL-3.0-only: the economic engine for did:nostr agents. A did:nostr key is a sidechain wallet.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages