more writers and readers.

This commit is contained in:
Christopher Jeffrey 2016-03-15 14:44:37 -07:00
parent 41eab6e27c
commit 1b3eb64998
6 changed files with 138 additions and 82 deletions

View File

@ -7,6 +7,7 @@
var bcoin = require('../bcoin');
var utils = require('./utils');
var network = bcoin.protocol.network;
var BufferWriter = require('./writer');
/**
* AbstractBlock
@ -50,20 +51,21 @@ AbstractBlock.prototype.hash = function hash(enc) {
};
AbstractBlock.prototype.abbr = function abbr() {
var res;
var p;
if (this._raw)
return this._raw.slice(0, 80);
res = new Buffer(80);
utils.write32(res, this.version, 0);
utils.copy(new Buffer(this.prevBlock, 'hex'), res, 4);
utils.copy(new Buffer(this.merkleRoot, 'hex'), res, 36);
utils.writeU32(res, this.ts, 68);
utils.writeU32(res, this.bits, 72);
utils.writeU32(res, this.nonce, 76);
p = new BufferWriter();
return res;
p.write32(this.version);
p.writeHash(this.prevBlock);
p.writeHash(this.merkleRoot);
p.writeU32(this.ts);
p.writeU32(this.bits);
p.writeU32(this.nonce);
return p.render();
};
AbstractBlock.prototype.getSize = function getSize() {

View File

@ -341,60 +341,46 @@ Block.fromRaw = function fromRaw(data, enc, type) {
};
Block.prototype.toCompact = function toCompact() {
var block = this.abbr();
var p = new BufferWriter();
var height = this.height;
var off = 0;
var buf;
buf = new Buffer(
block.length + 4
+ utils.sizeIntv(this.txs.length)
+ this.txs.length * 32);
if (height === -1)
height = 0x7fffffff;
off += utils.copy(block, buf, off);
off += utils.writeU32(buf, height, off);
p.writeBytes(this.abbr());
p.writeU32(height);
p.writeIntv(this.txs.length);
off += utils.writeIntv(buf, this.txs.length, off);
this.txs.forEach(function(tx) {
off += utils.copy(tx.hash(), buf, off);
p.writeBytes(tx.hash());
});
return buf;
return p.render();
};
Block.fromCompact = function fromCompact(buf) {
var off = 0;
var p = new BufferReader(buf);
var hashes = [];
var version = p.read32();
var prevBlock = p.readHash('hex');
var merkleRoot = p.readHash('hex');
var ts = p.readU32();
var bits = p.readU32();
var nonce = p.readU32();
var height = p.readU32();
var txCount = p.readIntv();
var i;
var version = utils.read32(buf, 0);
var prevBlock = buf.slice(4, 36);
var merkleRoot = buf.slice(36, 68);
var ts = utils.readU32(buf, 68);
var bits = utils.readU32(buf, 72);
var nonce = utils.readU32(buf, 76);
var height = utils.readU32(buf, 80);
var txCount = utils.readIntv(buf, 84);
off = txCount.off;
txCount = txCount.r;
for (i = 0; i < txCount; i++) {
if (off + 32 > buf.length)
throw new Error('Bad TX count.');
hashes.push(utils.toHex(buf.slice(off, off + 32)));
off += 32;
}
for (i = 0; i < txCount; i++)
hashes.push(p.readHash('hex'));
if (height === 0x7fffffff)
height = -1;
return {
version: version,
prevBlock: utils.toHex(prevBlock),
merkleRoot: utils.toHex(merkleRoot),
prevBlock: prevBlock,
merkleRoot: merkleRoot,
ts: ts,
bits: bits,
nonce: nonce,

View File

@ -12,6 +12,7 @@ var constants = bcoin.protocol.constants;
var network = bcoin.protocol.network;
var utils = require('./utils');
var assert = utils.assert;
var BufferReader = require('./reader');
/**
* Chain
@ -254,6 +255,21 @@ Chain.prototype._preload = function _preload(callback) {
utils.debug('Loading %s', url);
function parseHeader(buf) {
var p = new BufferReader(buf);
var hash = utils.dsha256(buf.slice(0, 80));
return {
hash: utils.toHex(hash),
version: p.read32(),
prevBlock: p.readHash('hex'),
merkleRoot: p.readHash('hex'),
ts: p.readU32(),
bits: p.readU32(),
nonce: p.readU32()
};
}
this.db.getChainHeight(function(err, chainHeight) {
if (err)
return callback(err);
@ -305,15 +321,19 @@ Chain.prototype._preload = function _preload(callback) {
return;
blocks.forEach(function(data) {
var entry = bcoin.chainblock.fromRaw(self, data);
var block, start;
var block, entry, start;
entry.height = height;
data = parseHeader(data);
data.height = height;
block = bcoin.headers(entry);
// Make sure the genesis block is correct.
if (data.height === 0 && data.hash !== network.genesis.hash) {
stream.destroy();
return callback(new Error('Bad genesis block.'), 0);
}
// Do some paranoid checks.
if (lastEntry && entry.prevBlock !== lastEntry.hash) {
if (lastEntry && data.prevBlock !== lastEntry.hash) {
start = Math.max(0, height - 2);
stream.destroy();
return self.reset(start, function(err) {
@ -323,6 +343,9 @@ Chain.prototype._preload = function _preload(callback) {
});
}
// Create headers object for validation.
block = new bcoin.headers(data);
// Verify the block headers. We don't want to
// trust an external centralized source completely.
if (!block.verifyHeaders()) {
@ -335,31 +358,23 @@ Chain.prototype._preload = function _preload(callback) {
});
}
// Calculate chainwork.
delete entry.chainwork;
entry.chainwork = entry.getChainwork(lastEntry);
lastEntry = entry;
// Make sure the genesis block is correct.
if (height === 0 && entry.hash !== network.genesis.hash) {
stream.destroy();
return callback(new Error('Bad genesis block.'), 0);
}
// Create a chain entry.
entry = new bcoin.chainblock(self, data, lastEntry);
// Filthy hack to avoid writing
// redundant blocks to disk!
if (height <= chainHeight) {
if (entry.height <= chainHeight) {
self.db.addCache(entry);
// self.db.bloom(entry.hash, 'hex');
} else {
self.db.save(entry);
}
height++;
if ((height + 1) % 50000 === 0)
utils.debug('Received %d headers from electrum.org.', height + 1);
lastEntry = entry;
height++;
});
});

View File

@ -10,6 +10,8 @@ var constants = bcoin.protocol.constants;
var network = bcoin.protocol.network;
var utils = require('./utils');
var assert = utils.assert;
var BufferWriter = require('./writer');
var BufferReader = require('./reader');
/**
* ChainBlock
@ -241,31 +243,34 @@ ChainBlock.prototype.getMedianTimeAsync = function getMedianTimeAsync(callback)
};
ChainBlock.prototype.toRaw = function toRaw() {
var res = new Buffer(116);
var p = new BufferWriter();
utils.write32(res, this.version, 0);
utils.copy(new Buffer(this.prevBlock, 'hex'), res, 4);
utils.copy(new Buffer(this.merkleRoot, 'hex'), res, 36);
utils.writeU32(res, this.ts, 68);
utils.writeU32(res, this.bits, 72);
utils.writeU32(res, this.nonce, 76);
utils.writeU32(res, this.height, 80);
utils.copy(new Buffer(this.chainwork.toArray('le', 32)), res, 84);
p.write32(this.version);
p.writeHash(this.prevBlock);
p.writeHash(this.merkleRoot);
p.writeU32(this.ts);
p.writeU32(this.bits);
p.writeU32(this.nonce);
p.writeU32(this.height);
p.writeBytes(new Buffer(this.chainwork.toArray('le', 32)));
return res;
return p.render();
};
ChainBlock.fromRaw = function fromRaw(chain, p) {
ChainBlock.fromRaw = function fromRaw(chain, buf) {
var p = new BufferReader(buf);
var hash = utils.dsha256(buf.slice(0, 80));
return new ChainBlock(chain, {
hash: utils.toHex(utils.dsha256(p.slice(0, 80))),
version: utils.read32(p, 0),
prevBlock: utils.toHex(p.slice(4, 36)),
merkleRoot: utils.toHex(p.slice(36, 68)),
ts: utils.readU32(p, 68),
bits: utils.readU32(p, 72),
nonce: utils.readU32(p, 76),
height: utils.readU32(p, 80),
chainwork: new bn(p.slice(84, 116), 'le')
hash: utils.toHex(hash),
version: p.read32(),
prevBlock: p.readHash('hex'),
merkleRoot: p.readHash('hex'),
ts: p.readU32(),
bits: p.readU32(),
nonce: p.readU32(),
height: p.readU32(),
chainwork: new bn(p.readBytes(32), 'le')
});
};

View File

@ -172,7 +172,9 @@ BufferReader.prototype.readString = function readString(enc, size) {
return ret;
};
BufferReader.prototype.readHash = function readHash() {
BufferReader.prototype.readHash = function readHash(enc) {
if (enc)
return this.readBytes(32).toString(enc);
return this.readBytes(32);
};

View File

@ -1182,6 +1182,52 @@ utils.writeU64BE = function writeU64BE(dst, num, off) {
return 8;
};
utils.writeU256 = function writeU256(dst, num, off) {
var i;
if (!(num instanceof bn))
num = new bn(+num);
off = off >>> 0;
// We shouldn't think of
// this as negative.
if (num.isNeg())
num = num.neg();
num = num.toArray('le', 32);
assert.equal(num.length, 32);
for (i = 0; i < num.length; i++)
dst[off++] = num[i] & 0xff;
return 32;
};
utils.writeU256BE = function writeU256BE(dst, num, off) {
var i;
if (!(num instanceof bn))
num = new bn(+num);
off = off >>> 0;
// We shouldn't think of
// this as negative.
if (num.isNeg())
num = num.neg();
num = num.toArray('be', 32);
assert.equal(num.length, 32);
for (i = 0; i < num.length; i++)
dst[off++] = num[i] & 0xff;
return 32;
};
utils.write8 = function write8(dst, num, off) {
num = +num;
off = off >>> 0;