bip152: implement segwit compact blocks.
This commit is contained in:
parent
cf5349cdaa
commit
62ef5ea7f4
@ -1317,7 +1317,7 @@ Chain.prototype.finish = function finish(block, entry) {
|
||||
time = elapsed[0] * 1000 + elapsed[1] / 1e6;
|
||||
|
||||
this.logger.info(
|
||||
'Block %s (%d) added to chain (size=%d, txs=%d time=%d).',
|
||||
'Block %s (%d) added to chain (size=%d txs=%d time=%d).',
|
||||
entry.rhash,
|
||||
entry.height,
|
||||
block.getSize(),
|
||||
|
||||
@ -183,13 +183,20 @@ CompactBlock.prototype.toRequest = function toRequest() {
|
||||
return TXRequest.fromCompact(this);
|
||||
};
|
||||
|
||||
CompactBlock.prototype.fillMempool = function fillMempool(mempool) {
|
||||
CompactBlock.prototype.fillMempool = function fillMempool(witness, mempool) {
|
||||
var have = {};
|
||||
var hashes = mempool.getSnapshot();
|
||||
var i, id, index, hash, tx;
|
||||
|
||||
for (i = 0; i < hashes.length; i++) {
|
||||
hash = hashes[i];
|
||||
tx = mempool.getTX(hash);
|
||||
assert(tx);
|
||||
hash = tx.hash();
|
||||
|
||||
if (witness)
|
||||
hash = tx.witnessHash();
|
||||
|
||||
id = this.sid(hash);
|
||||
index = this.idMap[id];
|
||||
|
||||
@ -203,11 +210,6 @@ CompactBlock.prototype.fillMempool = function fillMempool(mempool) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tx = mempool.getTX(hash);
|
||||
|
||||
if (!tx)
|
||||
continue;
|
||||
|
||||
this.available[index] = tx;
|
||||
have[index] = true;
|
||||
this.count++;
|
||||
@ -334,8 +336,8 @@ CompactBlock.prototype.toBlock = function toBlock() {
|
||||
return block;
|
||||
};
|
||||
|
||||
CompactBlock.prototype.fromBlock = function fromBlock(block, nonce) {
|
||||
var i, tx, id;
|
||||
CompactBlock.prototype.fromBlock = function fromBlock(block, witness, nonce) {
|
||||
var i, tx, hash, id;
|
||||
|
||||
this.version = block.version;
|
||||
this.prevBlock = block.prevBlock;
|
||||
@ -354,7 +356,10 @@ CompactBlock.prototype.fromBlock = function fromBlock(block, nonce) {
|
||||
|
||||
for (i = 1; i < block.txs.length; i++) {
|
||||
tx = block.txs[i];
|
||||
id = this.sid(tx.hash());
|
||||
hash = tx.hash();
|
||||
if (witness)
|
||||
hash = tx.witnessHash();
|
||||
id = this.sid(hash);
|
||||
this.ids.push(id);
|
||||
}
|
||||
|
||||
@ -363,8 +368,8 @@ CompactBlock.prototype.fromBlock = function fromBlock(block, nonce) {
|
||||
return this;
|
||||
};
|
||||
|
||||
CompactBlock.fromBlock = function fromBlock(block, nonce) {
|
||||
return new CompactBlock().fromBlock(block, nonce);
|
||||
CompactBlock.fromBlock = function fromBlock(block, witness, nonce) {
|
||||
return new CompactBlock().fromBlock(block, witness, nonce);
|
||||
};
|
||||
|
||||
CompactBlock.prototype.wait = function wait(time) {
|
||||
|
||||
@ -106,6 +106,7 @@ function Peer(pool, addr, socket) {
|
||||
this.syncSent = false;
|
||||
this.connectTimeout = null;
|
||||
this.compactMode = null;
|
||||
this.compactWitness = false;
|
||||
this.compactBlocks = {};
|
||||
this.sentAddr = false;
|
||||
this.bip151 = null;
|
||||
@ -523,7 +524,7 @@ Peer.prototype.announce = co(function* announce(items) {
|
||||
if (item instanceof Block) {
|
||||
if (!this.invFilter.added(item.hash()))
|
||||
continue;
|
||||
yield this._sendCompactBlock(item, false);
|
||||
yield this._sendCompactBlock(item, this.compactWitness);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -1543,12 +1544,12 @@ Peer.prototype._getItem = co(function* _getItem(item) {
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
Peer.prototype._sendBlock = co(function* _sendBlock(item) {
|
||||
Peer.prototype._sendBlock = co(function* _sendBlock(item, witness) {
|
||||
var block = this._getBroadcasted(item);
|
||||
|
||||
// Check for a broadcasted item first.
|
||||
if (block) {
|
||||
yield this.send(new packets.BlockPacket(block, item.hasWitness()));
|
||||
yield this.send(new packets.BlockPacket(block, witness));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1560,7 +1561,7 @@ Peer.prototype._sendBlock = co(function* _sendBlock(item) {
|
||||
|
||||
// If we have the same serialization, we
|
||||
// can write the raw binary to the socket.
|
||||
if (item.hasWitness() === !!this.options.witness) {
|
||||
if (witness === !!this.options.witness) {
|
||||
block = yield this.chain.db.getRawBlock(item.hash);
|
||||
|
||||
if (!block)
|
||||
@ -1573,7 +1574,7 @@ Peer.prototype._sendBlock = co(function* _sendBlock(item) {
|
||||
if (!block)
|
||||
return false;
|
||||
|
||||
yield this.send(new packets.BlockPacket(block, item.hasWitness()));
|
||||
yield this.send(new packets.BlockPacket(block, witness));
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1581,7 +1582,8 @@ Peer.prototype._sendBlock = co(function* _sendBlock(item) {
|
||||
|
||||
/**
|
||||
* Send a compact block.
|
||||
* @param {InvItem} item
|
||||
* @param {Block} block
|
||||
* @param {Boolean} witness
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
@ -1590,7 +1592,7 @@ Peer.prototype._sendCompactBlock = function _sendCompactBlock(block, witness) {
|
||||
// if we get a siphash collision.
|
||||
for (;;) {
|
||||
try {
|
||||
block = BIP152.CompactBlock.fromBlock(block);
|
||||
block = BIP152.CompactBlock.fromBlock(block, witness);
|
||||
} catch (e) {
|
||||
continue;
|
||||
}
|
||||
@ -1643,7 +1645,7 @@ Peer.prototype._handleGetData = co(function* _handleGetData(packet) {
|
||||
switch (item.type) {
|
||||
case constants.inv.BLOCK:
|
||||
case constants.inv.WITNESS_BLOCK:
|
||||
result = yield this._sendBlock(item);
|
||||
result = yield this._sendBlock(item, item.hasWitness());
|
||||
if (!result) {
|
||||
notFound.push(item);
|
||||
continue;
|
||||
@ -1676,7 +1678,7 @@ Peer.prototype._handleGetData = co(function* _handleGetData(packet) {
|
||||
case constants.inv.CMPCT_BLOCK:
|
||||
// Fallback to full block.
|
||||
if (block.height < this.chain.tip.height - 10) {
|
||||
result = yield this._sendBlock(item);
|
||||
result = yield this._sendBlock(item, this.compactWitness);
|
||||
if (!result) {
|
||||
notFound.push(item);
|
||||
continue;
|
||||
@ -1691,7 +1693,7 @@ Peer.prototype._handleGetData = co(function* _handleGetData(packet) {
|
||||
continue;
|
||||
}
|
||||
|
||||
yield this._sendCompactBlock(block, false);
|
||||
yield this._sendCompactBlock(block, this.compactWitness);
|
||||
|
||||
break;
|
||||
default:
|
||||
@ -2099,7 +2101,7 @@ Peer.prototype._handleUnknown = function _handleUnknown(packet) {
|
||||
*/
|
||||
|
||||
Peer.prototype._handleSendCmpct = function _handleSendCmpct(packet) {
|
||||
if (packet.version !== 1) {
|
||||
if (packet.version > 2) {
|
||||
// Ignore
|
||||
this.logger.info('Peer request compact blocks version %d (%s).',
|
||||
packet.version, this.hostname);
|
||||
@ -2115,6 +2117,7 @@ Peer.prototype._handleSendCmpct = function _handleSendCmpct(packet) {
|
||||
this.logger.info('Peer initialized compact blocks (%s).', this.hostname);
|
||||
|
||||
this.compactMode = packet;
|
||||
this.compactWitness = packet.version === 2;
|
||||
this.fire('sendcmpct', packet);
|
||||
};
|
||||
|
||||
@ -2148,7 +2151,7 @@ Peer.prototype._handleCmpctBlock = co(function* _handleCmpctBlock(packet) {
|
||||
|
||||
this.compactBlocks[hash] = block;
|
||||
|
||||
result = block.fillMempool(this.mempool);
|
||||
result = block.fillMempool(this.options.witness, this.mempool);
|
||||
|
||||
if (result) {
|
||||
delete this.compactBlocks[hash];
|
||||
@ -2216,7 +2219,7 @@ Peer.prototype._handleGetBlockTxn = co(function* _handleGetBlockTxn(packet) {
|
||||
|
||||
res = BIP152.TXResponse.fromBlock(block, req);
|
||||
|
||||
yield this.send(new packets.BlockTxnPacket(res, false));
|
||||
yield this.send(new packets.BlockTxnPacket(res, this.compactWitness));
|
||||
|
||||
this.fire('blocktxn', req);
|
||||
});
|
||||
|
||||
@ -215,7 +215,7 @@ describe('Block', function() {
|
||||
it('should handle compact block', function(cb) {
|
||||
var cblock = bip152.CompactBlock.fromRaw(cmpct[0], 'hex');
|
||||
var block = bcoin.block.fromRaw(cmpct[1], 'hex');
|
||||
var cblock2 = bip152.CompactBlock.fromBlock(block, cblock.keyNonce);
|
||||
var cblock2 = bip152.CompactBlock.fromBlock(block, false, cblock.keyNonce);
|
||||
var map = {};
|
||||
|
||||
assert.equal(cblock.toRaw().toString('hex'), cmpct[0]);
|
||||
@ -237,7 +237,7 @@ describe('Block', function() {
|
||||
|
||||
assert.equal(cblock.sid(block.txs[1].hash()), 125673511480291);
|
||||
|
||||
var result = cblock.fillMempool(fakeMempool);
|
||||
var result = cblock.fillMempool(false, fakeMempool);
|
||||
assert(result);
|
||||
for (var i = 0; i < cblock.available.length; i++)
|
||||
assert(cblock.available[i]);
|
||||
@ -248,7 +248,7 @@ describe('Block', function() {
|
||||
it('should handle half-full compact block', function(cb) {
|
||||
var cblock = bip152.CompactBlock.fromRaw(cmpct[0], 'hex');
|
||||
var block = bcoin.block.fromRaw(cmpct[1], 'hex');
|
||||
var cblock2 = bip152.CompactBlock.fromBlock(block, cblock.keyNonce);
|
||||
var cblock2 = bip152.CompactBlock.fromBlock(block, false, cblock.keyNonce);
|
||||
var map = {};
|
||||
|
||||
assert.equal(cblock.toRaw().toString('hex'), cmpct[0]);
|
||||
@ -273,7 +273,7 @@ describe('Block', function() {
|
||||
|
||||
assert.equal(cblock.sid(block.txs[1].hash()), 125673511480291);
|
||||
|
||||
var result = cblock.fillMempool(fakeMempool);
|
||||
var result = cblock.fillMempool(false, fakeMempool);
|
||||
assert(!result);
|
||||
|
||||
var req = cblock.toRequest();
|
||||
@ -301,7 +301,7 @@ describe('Block', function() {
|
||||
it('should handle compact block', function(cb) {
|
||||
var cblock = bip152.CompactBlock.fromRaw(cmpct2, 'hex');
|
||||
var block = bcoin.block.fromRaw(cmpct2block);
|
||||
var cblock2 = bip152.CompactBlock.fromBlock(block, cblock.keyNonce);
|
||||
var cblock2 = bip152.CompactBlock.fromBlock(block, false, cblock.keyNonce);
|
||||
var map = {};
|
||||
|
||||
assert.equal(cblock.toRaw().toString('hex'), cmpct2);
|
||||
@ -323,7 +323,7 @@ describe('Block', function() {
|
||||
|
||||
//assert.equal(cblock.sid(block.txs[1].hash()), 125673511480291);
|
||||
|
||||
var result = cblock.fillMempool(fakeMempool);
|
||||
var result = cblock.fillMempool(false, fakeMempool);
|
||||
assert(result);
|
||||
for (var i = 0; i < cblock.available.length; i++)
|
||||
assert(cblock.available[i]);
|
||||
@ -334,7 +334,7 @@ describe('Block', function() {
|
||||
it('should handle half-full compact block', function(cb) {
|
||||
var cblock = bip152.CompactBlock.fromRaw(cmpct2, 'hex');
|
||||
var block = bcoin.block.fromRaw(cmpct2block);
|
||||
var cblock2 = bip152.CompactBlock.fromBlock(block, cblock.keyNonce);
|
||||
var cblock2 = bip152.CompactBlock.fromBlock(block, false, cblock.keyNonce);
|
||||
var map = {};
|
||||
|
||||
assert.equal(cblock.toRaw().toString('hex'), cmpct2);
|
||||
@ -359,7 +359,7 @@ describe('Block', function() {
|
||||
|
||||
//assert.equal(cblock.sid(block.txs[1].hash()), 125673511480291);
|
||||
|
||||
var result = cblock.fillMempool(fakeMempool);
|
||||
var result = cblock.fillMempool(false, fakeMempool);
|
||||
assert(!result);
|
||||
|
||||
var req = cblock.toRequest();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user