Skip to content

Priyanshu-u07/chain-lens

Repository files navigation

⛓️ Chain Lens

A Bitcoin transaction & block analyzer I built for the Summer of Bitcoin 2026 challenge.

Chain Lens has two parts — a CLI tool that parses raw Bitcoin transactions/blocks into detailed JSON reports, and a web visualizer that explains all of it in plain English with a clean dark UI.

TypeScript Node.js Express Bitcoin


🎬 Demo

📹 Watch the walkthrough on YouTube (< 2 min)


📸 Screenshot

Chain Lens UI


✨ What it does

CLI Analyzer

  • Parses raw hex transactions byte-by-byte (both legacy and SegWit)
  • Computes txid, wtxid, fees, weight, vbytes — all from scratch
  • Classifies input/output scripts: P2PKH, P2SH, P2WPKH, P2WSH, P2TR, OP_RETURN, nested variants like P2SH-P2WPKH
  • Derives mainnet addresses (Base58Check, Bech32, Bech32m)
  • Full script disassembly to ASM
  • OP_RETURN payload decoding with protocol detection (Omni, OpenTimestamps)
  • RBF signaling & BIP68 relative timelock detection
  • SegWit discount / savings analysis
  • Warnings: high fee, dust outputs, unknown scripts, RBF

Block Parser

  • Reads Bitcoin Core raw blk*.dat / rev*.dat files directly
  • XOR key decryption support
  • Parses block headers, all transactions, and undo data for prevouts
  • Handles compressed script types in undo data (P2PKH, P2SH, P2PK, raw scripts)
  • Computes & verifies merkle root
  • Extracts BIP34 coinbase height
  • Generates per-block stats (total fees, weight, fee rate, script type summary)

Web Visualizer

  • Dark-themed, premium UI with particle animations
  • Paste a fixture JSON or try built-in samples (P2PKH, SegWit, Multi-Input)
  • Upload blk*.dat + rev*.dat + xor.dat for block analysis
  • Transaction flow diagram (inputs → outputs with fee visualization)
  • Expandable technical details per input/output
  • SegWit savings breakdown with visual comparison
  • Warning badges with explanations
  • Block overview with expandable transaction list
  • Health endpoint at GET /api/health

🏗️ Project Structure

chain-lens/
├── src/
│   ├── cli.ts              # CLI entry point
│   ├── server.ts           # Express server for web UI
│   ├── parser/
│   │   ├── transaction.ts  # Raw tx parsing (legacy + SegWit)
│   │   ├── block.ts        # Block + undo file parsing
│   │   ├── script.ts       # Script classification, disassembly, address derivation
│   │   ├── merkle.ts       # Merkle root computation
│   │   └── undo.ts         # Undo data parsing (compressed scripts)
│   ├── utils/
│   │   ├── buffer-reader.ts  # Low-level byte reader
│   │   ├── encoding.ts       # Hex/byte conversions
│   │   └── hash.ts           # Double SHA-256 hashing
│   └── types/              # TypeScript interfaces
├── public/
│   ├── index.html          # Web UI
│   ├── style.css           # Styling (dark theme, glassmorphism)
│   └── app.js              # Frontend logic & rendering
├── fixtures/               # Sample transaction & block fixtures
├── cli.sh                  # CLI runner script
├── web.sh                  # Web server runner script
└── setup.sh                # Dependency installer

🚀 Getting Started

Prerequisites

  • Node.js (v18+)
  • npm

Setup

# Install dependencies and build
bash setup.sh

Run the CLI

# Analyze a single transaction
bash cli.sh fixtures/transactions/tx_legacy_p2pkh.json

# Analyze a block
bash cli.sh --block <blk.dat> <rev.dat> <xor.dat>

Output goes to out/<txid>.json (transaction mode) or out/<block_hash>.json (block mode).

Run the Web UI

bash web.sh
# → http://127.0.0.1:3000

🔧 How it works (high level)

  1. Byte-level parsing — I read the raw hex byte by byte using a custom BufferReader. SegWit transactions have marker + flag bytes and a witness section; legacy ones don't. The parser handles both.

  2. Hashingtxid is the double-SHA256 of the serialized tx without the witness. wtxid includes it. For blocks, the block hash is double-SHA256 of the 80-byte header.

  3. Script classification — I match output scriptPubKeys against known templates (e.g., OP_DUP OP_HASH160 <20 bytes> OP_EQUALVERIFY OP_CHECKSIG → P2PKH). For inputs, I combine the scriptSig, witness, and prevout scriptPubKey to determine the spend type.

  4. Address derivation — P2PKH and P2SH use Base58Check encoding. P2WPKH/P2WSH use Bech32. P2TR uses Bech32m. All encoded from the hash inside the script.

  5. Block parsing — The undo file stores prevout data in a compressed format. Bitcoin Core uses special nSize values (0 = P2PKH, 1 = P2SH, 2-5 = compressed P2PK, ≥6 = raw script). I decompress these to reconstruct the full scriptPubKeys.

  6. Fee & weight — Fees = total input sats − total output sats. Weight uses the BIP141 formula: (non-witness bytes × 4) + witness bytes.


📋 Output Format

Transaction Mode

{
  "ok": true,
  "txid": "...",
  "fee_sats": 3456,
  "fee_rate_sat_vb": 24.51,
  "vin": [...],
  "vout": [...],
  "warnings": [{ "code": "RBF_SIGNALING" }],
  "segwit_savings": { "savings_pct": 36.82 }
}

Block Mode

{
  "ok": true,
  "mode": "block",
  "block_header": { "block_hash": "...", "merkle_root_valid": true },
  "tx_count": 150,
  "coinbase": { "bip34_height": 800000 },
  "transactions": [...],
  "block_stats": { "total_fees_sats": 6250000 }
}

Errors

{ "ok": false, "error": { "code": "INVALID_TX", "message": "..." } }

🛠️ Tech Stack

Layer Tech
Language TypeScript
Runtime Node.js
Server Express
Frontend Vanilla HTML/CSS/JS
Encoding bech32, bs58check
Styling Custom dark theme with CSS animations

No external Bitcoin libraries — all parsing logic is hand-written.


📝 What I learned

This project pushed me to actually understand Bitcoin at the byte level — how transactions are serialized, why SegWit introduced witness data, how script templates map to address types, and how Bitcoin Core stores block/undo data on disk. Writing the undo data decompressor for P2PK scripts was probably the trickiest part.


📄 License

This project was built as part of the Summer of Bitcoin 2026 developer challenge.

About

Bitcoin transaction & block analyzer

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors