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 constants = require('../protocol/constants');
var util = require('../utils/util');
var BufferReader = require('../utils/reader');
var BufferWriter = require('../utils/writer');
var co = require('../utils/co');
var assert = require('assert');
var crypto = require('../crypto/crypto');
@ -22,6 +24,7 @@ var Coin = require('../primitives/coin');
var Locker = require('../utils/locker');
var Outpoint = require('../primitives/outpoint');
var TX = require('../primitives/tx');
var Coin = require('../primitives/coin');
var MempoolEntry = require('./mempoolentry');
/**
@ -1310,7 +1313,7 @@ Mempool.prototype.storeOrphan = function storeOrphan(tx) {
this.waiting[prev].push(hash);
}
this.orphans[hash] = tx.toExtended(true);
this.orphans[hash] = toOrphanRaw(tx);
this.totalOrphans++;
this.logger.debug('Added orphan %s to mempool.', tx.txid());
@ -1389,7 +1392,7 @@ Mempool.prototype.getOrphan = function getOrphan(hash) {
return;
try {
orphan = TX.fromExtended(data, true);
orphan = fromOrphanRaw(data);
} catch (e) {
delete this.orphans[hash];
this.logger.warning('%s %s',
@ -1444,7 +1447,7 @@ Mempool.prototype.resolveOrphans = function resolveOrphans(tx) {
continue;
}
this.orphans[orphanHash] = orphan.toExtended(true);
this.orphans[orphanHash] = toOrphanRaw(orphan);
}
delete this.waiting[hash];
@ -1981,6 +1984,53 @@ AddressIndex.prototype.removeCoin = function removeCoin(coin) {
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
*/

View File

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