tx: parse

This commit is contained in:
Fedor Indutny 2014-05-03 17:46:15 +04:00
parent cd3f04268a
commit 40ea4d1fb1
6 changed files with 153 additions and 13 deletions

View File

@ -5,6 +5,7 @@ bcoin.ecdsa = elliptic.ecdsa(elliptic.nist.secp256k1);
bcoin.utils = require('./bcoin/utils');
bcoin.bloom = require('./bcoin/bloom');
bcoin.protocol = require('./bcoin/protocol');
bcoin.script = require('./bcoin/script');
bcoin.tx = require('./bcoin/tx');
bcoin.block = require('./bcoin/block');
bcoin.chain = require('./bcoin/chain');

View File

@ -12,6 +12,11 @@ function Block(data) {
this.ts = data.ts;
this.bits = data.bits;
this.nonce = data.nonce;
this.totalTx = data.totalTx;
this.hashes = data.hashes.map(function(hash) {
return utils.toHex(hash);
});
this.flags = data.flags;
this._hash = null;
}

View File

@ -12,7 +12,7 @@ function Pool(options) {
EventEmitter.call(this);
this.options = options || {};
this.size = options.size || 2;
this.size = options.size || 3;
this.parallel = options.parallel || 2000;
this.load = {
timeout: options.loadTimeout || 10000,
@ -23,7 +23,7 @@ function Pool(options) {
hiReached: false
};
this.maxRetries = options.maxRetries || 300;
this.requestTimeout = options.requestTimeout || 30000;
this.requestTimeout = options.requestTimeout || 10000;
this.chain = new bcoin.chain();
this.bloom = new bcoin.bloom(8 * 10 * 1024,
10,

View File

@ -1,6 +1,7 @@
var assert = require('assert');
var util = require('util');
var EventEmitter = require('events').EventEmitter;
var bn = require('bn.js');
var bcoin = require('../../bcoin');
var utils = bcoin.utils;
@ -54,7 +55,8 @@ Parser.prototype.parse = function parse(chunk) {
return this.emit('error', new Error('Invalid checksum'));
this.packet.payload = this.parsePayload(this.packet.cmd,
this.packet.payload);
this.emit('packet', this.packet);
if (this.packet.payload)
this.emit('packet', this.packet);
this.waiting = 24;
this.packet = null;
@ -92,6 +94,8 @@ Parser.prototype.parsePayload = function parsePayload(cmd, p) {
return this.parseMerkleBlock(p);
else if (cmd === 'block')
return this.parseBlock(p);
else if (cmd === 'tx')
return this.parseTx(p);
else
return p;
};
@ -144,7 +148,7 @@ function readIntv(p, off) {
bytes = 9;
}
return { off: bytes, r: r };
return { off: off + bytes, r: r };
}
Parser.prototype.parseInvList = function parseInvList(p) {
@ -165,9 +169,29 @@ Parser.prototype.parseInvList = function parseInvList(p) {
};
Parser.prototype.parseMerkleBlock = function parseMerkleBlock(p) {
if (p.length < 84)
if (p.length < 86)
return this.emit('error', new Error('Invalid merkleblock size'));
var hashCount = readIntv(p, 84);
var off = hashCount.off;
hashCount = hashCount.r;
if (off + 32 * hashCount + 1 > p.length)
return this.emit('error', new Error('Invalid hash count'));
var hashes = new Array(hashCount);
for (var i = 0; i < hashCount; i++)
hashes[i] = p.slice(off + i * 32, off + (i + 1) * 32);
off = off + 32 * hashCount;
var flagCount = readIntv(p, off);
off = flagCount.off;
flagCount = flagCount.r;
if (off + flagCount > p.length)
return this.emit('error', new Error('Invalid flag count'));
var flags = p.slice(off, off + flagCount);
return {
version: readU32(p, 0),
prevBlock: p.slice(4, 36),
@ -175,10 +199,9 @@ Parser.prototype.parseMerkleBlock = function parseMerkleBlock(p) {
ts: readU32(p, 68),
bits: readU32(p, 72),
nonce: readU32(p, 76),
totalTx: readU32(p, 80)
// hashes:
// flags:
totalTx: readU32(p, 80),
hashes: hashes,
flags: flags
};
};
@ -194,8 +217,96 @@ Parser.prototype.parseBlock = function parseBlock(p) {
bits: readU32(p, 72),
nonce: readU32(p, 76),
totalTx: readU32(p, 80)
// hashes:
// flags:
};
};
Parser.prototype.parseTxIn = function parseTxIn(p) {
if (p.length < 41)
return this.emit('error', new Error('Invalid tx_in size'));
var scriptLen = readIntv(p, 36);
var off = scriptLen.off;
scriptLen = scriptLen.r;
if (off + scriptLen + 4 > p.length)
return this.emit('error', new Error('Invalid tx_in script length'));
return {
size: off + scriptLen + 4,
out: {
hash: p.slice(0, 32),
index: readU32(p, 32)
},
script: p.slice(off, off + scriptLen),
seq: readU32(p, off + scriptLen)
};
};
Parser.prototype.parseTxOut = function parseTxOut(p) {
if (p.length < 9)
return this.emit('error', new Error('Invalid tx_out size'));
var scriptLen = readIntv(p, 8);
var off = scriptLen.off;
scriptLen = scriptLen.r;
if (off + scriptLen > p.length)
return this.emit('error', new Error('Invalid tx_out script length'));
return {
size: off + scriptLen,
value: new bn(p.slice(0, 8).reverse()),
script: p.slice(off, off + scriptLen)
};
};
Parser.prototype.parseTx = function parseTx(p) {
if (p.length < 60)
return this.emit('error', new Error('Invalid tx size'));
var inCount = readIntv(p, 4);
var off = inCount.off;
inCount = inCount.r;
if (inCount <= 0)
return this.emit('error', new Error('Invalid tx_in count'));
if (off + 41 * inCount + 14 > p.length)
return this.emit('error', new Error('Invalid tx_in count'));
var txIn = new Array(inCount);
for (var i = 0; i < inCount; i++) {
var tx = this.parseTxIn(p.slice(off));
if (!tx)
return;
txIn[i] = tx;
off += tx.size;
if (off + 14 > p.length)
return this.emit('error', new Error('Invalid tx_in offset'));
}
var outCount = readIntv(p, off);
var off = outCount.off;
outCount = outCount.r;
if (outCount <= 0)
return this.emit('error', new Error('Invalid tx_out count'));
if (off + 9 * outCount + 4 > p.length)
return this.emit('error', new Error('Invalid tx_out count'));
var txOut = new Array(outCount);
for (var i = 0; i < outCount; i++) {
var tx = this.parseTxOut(p.slice(off));
if (!tx)
return;
txOut[i] = tx;
off += tx.size;
if (off + 4 > p.length)
return this.emit('error', new Error('Invalid tx_out offset'));
}
return {
_raw: p,
version: readU32(p, 0),
inputs: txIn,
outputs: txOut,
lock: readU32(p, off)
};
};

5
lib/bcoin/script.js Normal file
View File

@ -0,0 +1,5 @@
var script = exports;
script.parse = function parse(s) {
return s;
};

View File

@ -6,8 +6,26 @@ function TX(data) {
return new TX(data);
this.type = 'tx';
this.version = data.version;
this.inputs = data.inputs.map(function(input) {
return {
out: {
hash: utils.toHex(input.out.hash),
index: bcoin.script.parse(input.out.index)
},
script: input.script,
seq: input.seq
};
});
this.outputs = data.outputs.map(function(output) {
return {
value: output.value,
script: bcoin.script.parse(output.script)
};
});
this._hash = null;
this._raw = data || null;
this._raw = data._raw || null;
}
module.exports = TX;