mempool: orphan serialization.

This commit is contained in:
Christopher Jeffrey 2016-12-04 03:13:44 -08:00
parent 30526aaea4
commit 38eca965a7
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
2 changed files with 65 additions and 69 deletions

View File

@ -9,6 +9,8 @@
var AsyncObject = require('../utils/async'); var AsyncObject = require('../utils/async');
var constants = require('../protocol/constants'); var constants = require('../protocol/constants');
var util = require('../utils/util'); var util = require('../utils/util');
var BufferReader = require('../utils/reader');
var BufferWriter = require('../utils/writer');
var co = require('../utils/co'); var co = require('../utils/co');
var assert = require('assert'); var assert = require('assert');
var crypto = require('../crypto/crypto'); var crypto = require('../crypto/crypto');
@ -22,6 +24,7 @@ var Coin = require('../primitives/coin');
var Locker = require('../utils/locker'); var Locker = require('../utils/locker');
var Outpoint = require('../primitives/outpoint'); var Outpoint = require('../primitives/outpoint');
var TX = require('../primitives/tx'); var TX = require('../primitives/tx');
var Coin = require('../primitives/coin');
var MempoolEntry = require('./mempoolentry'); var MempoolEntry = require('./mempoolentry');
/** /**
@ -1310,7 +1313,7 @@ Mempool.prototype.storeOrphan = function storeOrphan(tx) {
this.waiting[prev].push(hash); this.waiting[prev].push(hash);
} }
this.orphans[hash] = tx.toExtended(true); this.orphans[hash] = toOrphanRaw(tx);
this.totalOrphans++; this.totalOrphans++;
this.logger.debug('Added orphan %s to mempool.', tx.txid()); this.logger.debug('Added orphan %s to mempool.', tx.txid());
@ -1389,7 +1392,7 @@ Mempool.prototype.getOrphan = function getOrphan(hash) {
return; return;
try { try {
orphan = TX.fromExtended(data, true); orphan = fromOrphanRaw(data);
} catch (e) { } catch (e) {
delete this.orphans[hash]; delete this.orphans[hash];
this.logger.warning('%s %s', this.logger.warning('%s %s',
@ -1444,7 +1447,7 @@ Mempool.prototype.resolveOrphans = function resolveOrphans(tx) {
continue; continue;
} }
this.orphans[orphanHash] = orphan.toExtended(true); this.orphans[orphanHash] = toOrphanRaw(orphan);
} }
delete this.waiting[hash]; delete this.waiting[hash];
@ -1981,6 +1984,53 @@ AddressIndex.prototype.removeCoin = function removeCoin(coin) {
delete this.map[key]; delete this.map[key];
}; };
/*
* Helpers
*/
function toOrphanRaw(tx) {
var bw = new BufferWriter();
var i, input;
tx.toWriter(bw);
for (i = 0; i < tx.inputs.length; i++) {
input = tx.inputs[i];
if (!input.coin) {
bw.writeU8(0);
continue;
}
bw.writeU8(1);
input.coin.toWriter(bw);
}
return bw.render();
};
function fromOrphanRaw(data) {
var br = new BufferReader(data);
var i, tx, input, coin;
tx = TX.fromReader(br);
for (i = 0; i < tx.inputs.length; i++) {
input = tx.inputs[i];
if (br.readU8() === 0)
continue;
coin = Coin.fromReader(br);
coin.hash = input.prevout.hash;
coin.index = input.prevout.index;
input.coin = coin;
}
return tx;
}
/* /*
* Expose * Expose
*/ */

View File

@ -2435,17 +2435,20 @@ TX.isWitness = function isWitness(br) {
* This is the serialization format BCoin uses internally * This is the serialization format BCoin uses internally
* to store transactions in the database. The extended * to store transactions in the database. The extended
* serialization includes the height, block hash, index, * serialization includes the height, block hash, index,
* timestamp, pending-since time, and optionally a vector * timestamp, and pending-since time.
* for the serialized coins.
* @param {Boolean?} saveCoins - Whether to serialize the coins.
* @returns {Buffer} * @returns {Buffer}
*/ */
TX.prototype.toExtended = function toExtended(saveCoins) { TX.prototype.toExtended = function toExtended() {
var bw = new BufferWriter(); var bw = new BufferWriter();
var height = this.height; var height = this.height;
var index = this.index; var index = this.index;
var i, input, field, bit, oct;
if (height === -1)
height = 0x7fffffff;
if (index === -1)
index = 0x7fffffff;
this.toWriter(bw); this.toWriter(bw);
@ -2458,49 +2461,21 @@ TX.prototype.toExtended = function toExtended(saveCoins) {
bw.writeU8(0); bw.writeU8(0);
} }
if (height === -1)
height = 0x7fffffff;
if (index === -1)
index = 0x7fffffff;
bw.writeU32(height); bw.writeU32(height);
bw.writeU32(this.ts); bw.writeU32(this.ts);
bw.writeU32(index); bw.writeU32(index);
if (saveCoins) {
field = new Buffer(Math.ceil(this.inputs.length / 8));
field.fill(0);
bw.writeBytes(field);
for (i = 0; i < this.inputs.length; i++) {
input = this.inputs[i];
if (!input.coin) {
bit = i % 8;
oct = (i - bit) / 8;
field[oct] |= 1 << (7 - bit);
continue;
}
input.coin.toWriter(bw);
}
}
return bw.render(); return bw.render();
}; };
/** /**
* Inject properties from "extended" serialization format. * Inject properties from "extended" serialization format.
* @private
* @param {Buffer} data * @param {Buffer} data
* @param {Boolean?} saveCoins - If true, the function will
* attempt to parse the coins.
*/ */
TX.prototype.fromExtended = function fromExtended(data, saveCoins) { TX.prototype.fromExtended = function fromExtended(data) {
var br = new BufferReader(data); var br = new BufferReader(data);
var i, input, coin, field, bit, oct, spent;
this.fromReader(br); this.fromReader(br);
@ -2519,27 +2494,6 @@ TX.prototype.fromExtended = function fromExtended(data, saveCoins) {
if (this.index === 0x7fffffff) if (this.index === 0x7fffffff)
this.index = -1; this.index = -1;
if (saveCoins) {
field = br.readBytes(Math.ceil(this.inputs.length / 8), true);
for (i = 0; i < this.inputs.length; i++) {
input = this.inputs[i];
bit = i % 8;
oct = (i - bit) / 8;
spent = (field[oct] >>> (7 - bit)) & 1;
if (spent)
continue;
coin = Coin.fromReader(br);
coin.hash = input.prevout.hash;
coin.index = input.prevout.index;
input.coin = coin;
}
}
return this; return this;
}; };
@ -2547,22 +2501,14 @@ TX.prototype.fromExtended = function fromExtended(data, saveCoins) {
* Instantiate a transaction from a Buffer * Instantiate a transaction from a Buffer
* in "extended" serialization format. * in "extended" serialization format.
* @param {Buffer} data * @param {Buffer} data
* @param {Boolean?} saveCoins - If true, the function will
* attempt to parse the coins.
* @param {String?} enc - One of `"hex"` or `null`. * @param {String?} enc - One of `"hex"` or `null`.
* @returns {TX} * @returns {TX}
*/ */
TX.fromExtended = function fromExtended(data, saveCoins, enc) { TX.fromExtended = function fromExtended(data, enc) {
if (typeof saveCoins === 'string') {
enc = saveCoins;
saveCoins = false;
}
if (typeof data === 'string') if (typeof data === 'string')
data = new Buffer(data, enc); data = new Buffer(data, enc);
return new TX().fromExtended(data);
return new TX().fromExtended(data, saveCoins);
}; };
/** /**