Last active
January 3, 2016 13:19
-
-
Save tlrobinson/8469121 to your computer and use it in GitHub Desktop.
Bitcoin blockchain parser. Note this is extremely slow and fails to parse certain blocks. Try https://github.com/znort987/blockparser for a fast blockchain parser.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fs = require "fs" | |
path = require "path" | |
binary = require "binary" | |
BLOCKS_DIR = "/Users/tlrobinson/Library/Application Support/Bitcoin/blocks" | |
MAGIC = new Buffer([0xf9, 0xbe, 0xb4, 0xd9]) | |
exports.varInt = varInt = (key) -> | |
@word8lu(key) | |
@tap (vars) -> | |
switch vars[key] | |
when 0xfd then @word16lu(key) | |
when 0xfe then @word32lu(key) | |
when 0xff then @word64lu(key) | |
# Works with Buffers | |
exports.chainSync = chainSync = -> | |
@scan("magicID", MAGIC) | |
@word32lu("blockLength") | |
block.call @ | |
# Works with Streams | |
exports.chainAsync = chainAsync = -> | |
@scan("magicID", MAGIC) | |
@word32lu("blockLength") | |
@buffer("block", "blockLength") | |
@tap (vars) -> | |
try | |
block.call(binary.parse(vars.block)) | |
.tap (vars) -> | |
console.log vars | |
catch err | |
console.log "BLOCK FAILED TO PARSE:", err, vars | |
exports.block = block = -> | |
@word32lu("version").tap (vars) -> | |
throw new Error("version="+vars.version) if vars.version isnt 1 | |
@buffer("previous", 32) | |
@buffer("merkle", 32) | |
@word32lu("timestamp") | |
@word32lu("difficulty") | |
@word32lu("nonce") | |
varInt.call(@, 'txCount') | |
txCount = 0 | |
@loop (end, vars) -> | |
return end() if txCount++ >= vars.txCount | |
@into "tx#{txCount}", -> | |
@word32lu("version").tap (vars) -> | |
throw new Error("txversion="+vars.version) if vars.version isnt 1 | |
inputCount = 0 | |
@word8lu('inputCount') | |
@loop (end, vars) -> | |
return end() if inputCount++ >= vars.inputCount | |
@into "input#{inputCount}", -> | |
@buffer("txHash", 32) | |
@word32lu("txIndex") | |
varInt.call(@, 'scriptLength') | |
@buffer('script', 'scriptLength') | |
@word32lu("sequenceNumber") | |
outputCount = 0 | |
@word8lu('outputCount') | |
@loop (end, vars) -> | |
return end() if outputCount++ >= vars.outputCount | |
@into "output#{outputCount}", -> | |
@word64lu("value") | |
varInt.call(@, 'scriptLength') | |
@buffer('script', 'scriptLength') | |
@word32lu("txLockTime") | |
input = fs.createReadStream path.join(BLOCKS_DIR, "blk00000.dat") | |
parser = binary().loop chainAsync | |
input.pipe parser |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
e.x. genesis block: