mempool: orphan serialization.
This commit is contained in:
parent
30526aaea4
commit
38eca965a7
@ -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
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -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);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user