#!/usr/bin/env python3 # # Build a static Bitflash block explorer (v0) from a node's blk0001.dat. # Emits into : # blocks.json summary of every main-chain block (newest first) # block/.json full detail per block (header + all txs) # index.html self-contained viewer (vanilla JS, same-origin fetch) # # Scope (v0, deliberately): block list, block detail, and coinbase. No mempool, # no per-address history. On this chain the coinbase payout key rotates every # block, so an address index would be nearly useless; block-level transparency is # what lets miners and users confirm the chain is honest. # # Usage: build-explorer.py import sys, os, json, hashlib, struct MAGIC = bytes([0xbf, 0x20, 0x5c, 0xfd]) ADDRESS_VERSION = 25 # Bitflash addresses start with "B" def sha256d(b): return hashlib.sha256(hashlib.sha256(b).digest()).digest() B58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" def b58check(payload): v = bytes([ADDRESS_VERSION]) + payload v += sha256d(v)[:4] n = int.from_bytes(v, 'big') s = "" while n > 0: n, r = divmod(n, 58); s = B58[r] + s for byte in v: if byte == 0: s = "1" + s else: break return s def hash160(b): return hashlib.new('ripemd160', hashlib.sha256(b).digest()).digest() class R: def __init__(s, b, o=0): s.b = b; s.o = o def u(s, n): v = s.b[s.o:s.o+n]; s.o += n; return v def i32(s): return struct.unpack(' OP_EQUALVERIFY OP_CHECKSIG if len(spk) == 25 and spk[0] == 0x76 and spk[1] == 0xa9 and spk[2] == 0x14 and spk[23] == 0x88 and spk[24] == 0xac: return {"type": "p2pkh", "address": b58check(spk[3:23])} # P2PK: OP_CHECKSIG (65- or 33-byte key) if len(spk) >= 35 and spk[-1] == 0xac: if spk[0] == 0x41 and len(spk) == 67: pk = spk[1:66]; return {"type": "p2pk", "pubkey": pk.hex(), "address": b58check(hash160(pk))} if spk[0] == 0x21 and len(spk) == 35: pk = spk[1:34]; return {"type": "p2pk", "pubkey": pk.hex(), "address": b58check(hash160(pk))} return {"type": "other", "hex": spk.hex()[:80]} def parse_tx(r): start = r.o r.i32() nin = r.cs(); vin = [] for _ in range(nin): ph = r.u(32); idx = r.u32(); r.script(); r.u32() coinbase = (ph == b'\x00' * 32 and idx == 0xffffffff) vin.append({"coinbase": coinbase, "prev": (None if coinbase else ph[::-1].hex()), "vout": (None if coinbase else idx)}) nout = r.cs(); vout = [] for _ in range(nout): val = r.i64(); spk = r.script(); vout.append(dict({"value": val}, **spk_info(spk))) r.u32() raw = r.b[start:r.o] return {"txid": sha256d(raw)[::-1].hex(), "vin": vin, "vout": vout, "size": len(raw)} def main(): if len(sys.argv) != 3: print("usage: build-explorer.py ", file=sys.stderr); sys.exit(2) blkpath, out = sys.argv[1], sys.argv[2] data = open(blkpath, 'rb').read() blocks = {}; o = 0; n = len(data) while o + 8 <= n: if data[o:o+4] != MAGIC: o += 1; continue o += 4; size = struct.unpack(' Bitflash Block Explorer

Bitflash Block Explorer

Read-only view of the main chain: blocks, their transactions, and the coinbase payout. There is no mempool and no per-address history here. On Bitflash the coinbase payout key rotates every block, so an address index would say almost nothing; what matters is that every block and every coinbase is here to check.

HeightTime (UTC)TxsSizeCoinbaseTo

""" if __name__ == "__main__": main()