more writers and readers.
This commit is contained in:
parent
41eab6e27c
commit
1b3eb64998
@ -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() {
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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++;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -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')
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user