Skip to content

13x-tech/ion-node

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

134 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ion-node

An independent Bitcoin P2P indexer for ION/Sidetree OP_RETURN anchors.

ion-node connects directly to the Bitcoin P2P network (no bitcoind, no Neutrino, no third-party API), syncs headers-first, downloads full blocks, and maintains a reorg-safe, resumable index of ION anchors ordered by anchor-time. It is the read/index foundation of a larger node; DID resolution and operation publishing are later milestones.

Status — Milestone 1 (anchor indexer)

Component Package State
Config / profiles / logging internal/config, internal/log
Chain interfaces + btcd adapters + merkle verify internal/chain
OP_RETURN anchor scanner internal/scan
Reorg-safe store (SQLite default, bbolt optional) internal/store
Validated most-work header chain internal/chain
Custom btcd P2P client internal/p2p
Indexer pipeline (sync / reorg / resume) internal/index
CLI (sync/start/status) cmd/ion-node

Future: M2 — read/resolution (fetch Sidetree files from IPFS via an external daemon behind sidetree-go's CAS interface, replay DID operations, expose resolution). M3 — write/anchor (build Sidetree files, publish to IPFS, construct + broadcast the anchoring Bitcoin transaction).

Building

ion-node depends on the private github.com/13x-tech/ion-sdk-go (and sidetree-go), and on a fork of go-jose for secp256k1. Both are handled, but you must set GOPRIVATE:

export GOPRIVATE=github.com/13x-tech/*
go build ./...
go test ./...

The go.mod carries the required replace github.com/go-jose/go-jose/v3 => github.com/13x-tech/go-jose/v3 directive. Requires Go 1.23+.

Quickstart

# Print the resolved configuration for a network profile.
ion-node --network regtest config

# Sync headers and index up to the stable frontier once, then exit.
ion-node --network mainnet --datadir ./data sync

# Run continuously (re-syncs on an interval) until Ctrl-C.
ion-node --network mainnet --datadir ./data start

# Print committed index status from the local store.
ion-node --network mainnet --datadir ./data status

Network profiles: mainnet (public ION: prefix ion:, genesis 667000), testnet (genesis 1764000), signet, regtest, simnet. Any field is overridable (--prefix, --genesis, --confirmations, --max-reorg, --peer, --anchor-peer, --store, …).

Storage engine

The anchor index sits behind a Store interface with two interchangeable backends, selected with --store:

  • sqlite (default) — pure-Go modernc.org/sqlite (no CGO), WAL mode. Chosen because later milestones query the index (by CID, txid, DID-suffix, confirmations, a resolution API), which SQL serves with free secondary indexes; reorg rollback is DELETE WHERE transaction_number >= ? with indexes unwinding automatically.
  • boltgo.etcd.io/bbolt B+tree, the original embedded ordered-KV backend.

Both implement identical semantics (whole-height replace, prevHash self-validation, gap-proof watermark, atomic rollback) and are parity-tested — including a differential fuzz test that runs random commit/rollback scripts against both and asserts they never diverge.

How it works

DNS seeds ─▶ btcd peer/connmgr ─▶ headers-first sync ─▶ HeaderChain (PoW + retarget + most-work)
                                                              │  stable frontier = tip − confirmationDepth
                                                              ▼
            full-block download ─▶ merkle verify ─▶ OP_RETURN scan ─▶ reorg-safe store (SQLite)
                                                              │  (txNumber = height·2³²+txIndex)
                                                              ▼
                                            M2: ion-sdk-go / sidetree-go resolution (future)
  • Headers-first, most-work fork choice. Each header is checked for raw proof-of-work, then difficulty/retarget/timewarp via btcd's CheckBlockHeaderContext (reused, not hand-rolled). The active chain is the one with the most cumulative work.
  • Commit only the stable zone (height ≤ tip − confirmationDepth, default depth 6). The committed index trails the tip, so it never races near-tip churn. Reorgs shallower than the depth are absorbed by the header loop; reorgs between the depth and maxReorgDepth (default 100) trigger an atomic rollback + reprocess; deeper reorgs fail-stop (see below).
  • Whole-height atomic commits keyed by transactionNumber. Reorg rollback is a single range delete; the watermark never advances over a gap, so restarts resume from the last contiguous height.

Trust posture (read this)

ion-node is an SPV-style indexer: it validates the most-work header chain (PoW + difficulty/retarget) and per-block merkle inclusion, but does not run full Bitcoin consensus (no UTXO set, no script/signature validation). It is anchored to a configurable minimum-chain-work floor + checkpoint + a reserved anchor peer / /16 peer-diversity floor.

This is sufficient to establish that the scanned OP_RETURN transactions really exist in the most-work chain. It does not protect against: invalid-but-well-formed blocks buried under real PoW (you trust miners for in-block validity), majority-hashpower rewrites below the finality depth (mitigated only by confirmationDepth), or eclipse attacks (mitigated by peer diversity + the min-work floor). Sidetree per-operation-fee / value-locking validity is not enforced. JWS signature verification of operations happens in ion-sdk-go's replay engine (M2), not here.

Deep reorgs

A reorg deeper than maxReorgDepth fails stop (the store is left untouched, no silent corruption) and requires an operator-triggered resync from a safe height.

License

Apache-2.0 © 13x LLC.

About

Independent Bitcoin P2P indexer for ION/Sidetree anchors

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors