move extended tx serialization.

This commit is contained in:
Christopher Jeffrey 2016-05-05 05:23:18 -07:00
parent fe18352a4c
commit f5b4bb2bf6
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
4 changed files with 125 additions and 90 deletions

View File

@ -911,6 +911,63 @@ Framer.renderTX = function renderTX(tx, useWitness, writer) {
return p; return p;
}; };
/**
* Serialize a transaction to BCoin "extended format".
* 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 {NakedTX|TX} tx
* @param {Boolean?} saveCoins - Whether to serialize the coins.
* @param {String?} enc - One of `"hex"` or `null`.
* @returns {Buffer}
*/
Framer.extendedTX = function extendedTX(tx, saveCoins, writer) {
var height = tx.height;
var index = tx.index;
var changeIndex = tx.changeIndex != null ? tx.changeIndex : -1;
var p = new BufferWriter(writer);
var i, input, tmp;
if (height === -1)
height = 0x7fffffff;
if (index === -1)
index = 0x7fffffff;
if (changeIndex === -1)
changeIndex = 0x7fffffff;
Framer.renderTX(tx, true, p);
p.writeU32(height);
p.writeHash(tx.block || constants.ZERO_HASH);
p.writeU32(index);
p.writeU32(tx.ts);
p.writeU32(tx.ps);
// p.writeU32(changeIndex);
if (saveCoins) {
p.writeVarint(tx.inputs.length);
for (i = 0; i < tx.inputs.length; i++) {
input = tx.inputs[i];
if (!input.coin) {
p.writeVarint(0);
continue;
}
p.writeVarBytes(Framer.coin(input.coin, false));
}
}
if (!writer)
p = p.render();
return p;
};
Framer._block = function _block(block, useWitness, writer) { Framer._block = function _block(block, useWitness, writer) {
var p = new BufferWriter(writer); var p = new BufferWriter(writer);
var witnessSize = 0; var witnessSize = 0;

View File

@ -692,6 +692,57 @@ Parser.parseBlockHeaders = function parseBlockHeaders(p) {
}; };
}; };
/**
* Parse a transaction in "extended" serialization format.
* @param {Buffer} p
* @param {Boolean?} saveCoins - If true, the function will
* attempt to parse the coins.
* @param {String?} enc - One of `"hex"` or `null`.
* @returns {NakedTX} - A "naked" transaction object.
*/
Parser.parseExtendedTX = function parseExtendedTX(p, saveCoins) {
var tx, coinCount, coin, i, tmp;
p = new BufferReader(p);
tx = Parser.parseTX(p);
tx.height = p.readU32();
tx.block = p.readHash('hex');
tx.index = p.readU32();
tx.ts = p.readU32();
tx.ps = p.readU32();
// tx.changeIndex = p.readU32();
if (tx.block === constants.NULL_HASH)
tx.block = null;
if (tx.height === 0x7fffffff)
tx.height = -1;
if (tx.index === 0x7fffffff)
tx.index = -1;
if (tx.changeIndex === 0x7fffffff)
tx.changeIndex = -1;
if (saveCoins) {
coinCount = p.readVarint();
for (i = 0; i < coinCount; i++) {
coin = p.readVarBytes();
if (coin.length === 0)
continue;
coin = Parser.parseCoin(coin, false);
coin.hash = tx.inputs[i].prevout.hash;
coin.index = tx.inputs[i].prevout.index;
tx.inputs[i].coin = coin;
}
}
return tx;
};
/** /**
* Parse block packet. * Parse block packet.
* @param {Buffer|BufferReader} p * @param {Buffer|BufferReader} p

View File

@ -1761,11 +1761,7 @@ TX.fromRaw = function fromRaw(data, enc) {
*/ */
TX.prototype.toExtended = function toExtended(saveCoins, enc) { TX.prototype.toExtended = function toExtended(saveCoins, enc) {
var height = this.height; var data;
var index = this.index;
var changeIndex = this.changeIndex != null ? this.changeIndex : -1;
var p = new BufferWriter();
var i, input, tmp;
if (typeof saveCoins === 'string') { if (typeof saveCoins === 'string') {
tmp = saveCoins; tmp = saveCoins;
@ -1773,57 +1769,24 @@ TX.prototype.toExtended = function toExtended(saveCoins, enc) {
enc = tmp; enc = tmp;
} }
if (height === -1) data = bcoin.protocol.framer.extendedTX(this, saveCoins);
height = 0x7fffffff;
if (index === -1)
index = 0x7fffffff;
if (changeIndex === -1)
changeIndex = 0x7fffffff;
bcoin.protocol.framer.renderTX(this, true, p);
p.writeU32(height);
p.writeHash(this.block || constants.ZERO_HASH);
p.writeU32(index);
p.writeU32(this.ts);
p.writeU32(this.ps);
// p.writeU32(changeIndex);
if (saveCoins) {
p.writeVarint(this.inputs.length);
for (i = 0; i < this.inputs.length; i++) {
input = this.inputs[i];
if (!input.coin) {
p.writeVarint(0);
continue;
}
p.writeVarBytes(bcoin.protocol.framer.coin(input.coin, false));
}
}
p = p.render();
if (enc === 'hex') if (enc === 'hex')
p = p.toString('hex'); data = data.toString('hex');
return p; return data;
}; };
/** /**
* Parse a transaction in "extended" serialization format. * Parse a transaction in "extended" serialization format.
* @param {Buffer} buf * @param {Buffer} data
* @param {Boolean?} saveCoins - If true, the function will * @param {Boolean?} saveCoins - If true, the function will
* attempt to parse the coins. * attempt to parse the coins.
* @param {String?} enc - One of `"hex"` or `null`. * @param {String?} enc - One of `"hex"` or `null`.
* @returns {NakedTX} - A "naked" transaction object. * @returns {NakedTX} - A "naked" transaction object.
*/ */
TX.parseExtended = function parseExtended(buf, saveCoins, enc) { TX.parseExtended = function parseExtended(data, saveCoins, enc) {
var p, tx, coinCount, coin, i, tmp;
if (typeof saveCoins === 'string') { if (typeof saveCoins === 'string') {
tmp = saveCoins; tmp = saveCoins;
saveCoins = enc; saveCoins = enc;
@ -1831,59 +1794,23 @@ TX.parseExtended = function parseExtended(buf, saveCoins, enc) {
} }
if (enc === 'hex') if (enc === 'hex')
buf = new Buffer(buf, 'hex'); data = new Buffer(data, 'hex');
p = new BufferReader(buf); return bcoin.protocol.parser.parseExtendedTX(data, saveCoins);
tx = bcoin.protocol.parser.parseTX(p);
tx.height = p.readU32();
tx.block = p.readHash('hex');
tx.index = p.readU32();
tx.ts = p.readU32();
tx.ps = p.readU32();
// tx.changeIndex = p.readU32();
if (tx.block === constants.NULL_HASH)
tx.block = null;
if (tx.height === 0x7fffffff)
tx.height = -1;
if (tx.index === 0x7fffffff)
tx.index = -1;
if (tx.changeIndex === 0x7fffffff)
tx.changeIndex = -1;
if (saveCoins) {
coinCount = p.readVarint();
for (i = 0; i < coinCount; i++) {
coin = p.readVarBytes();
if (coin.length === 0)
continue;
coin = bcoin.protocol.parser.parseCoin(coin, false);
coin.hash = tx.inputs[i].prevout.hash;
coin.index = tx.inputs[i].prevout.index;
tx.inputs[i].coin = coin;
}
}
return tx;
}; };
/** /**
* Instantiate a transaction from a Buffer * Instantiate a transaction from a Buffer
* in "extended" serialization format. * in "extended" serialization format.
* @param {Buffer} buf * @param {Buffer} data
* @param {Boolean?} saveCoins - If true, the function will * @param {Boolean?} saveCoins - If true, the function will
* attempt to parse the coins. * 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(buf, saveCoins, enc) { TX.fromExtended = function fromExtended(data, saveCoins, enc) {
return new TX(TX.parseExtended(buf, saveCoins, enc)); return new TX(TX.parseExtended(data, saveCoins, enc));
}; };
/** /**

View File

@ -672,13 +672,13 @@ Framer.item = function _item(item, p) {
} else { } else {
if (item instanceof bcoin.block) { if (item instanceof bcoin.block) {
p.writeU8(40); p.writeU8(40);
p.writeVarBytes(item.render()); bcoin.protocol.framer.witnessBlock(item, p);
} else if (item instanceof bcoin.tx) { } else if (item instanceof bcoin.tx) {
p.writeU8(41); p.writeU8(41);
p.writeVarBytes(item.toExtended(true)); bcoin.protocol.framer.extendedTX(item, true, p);
} else if (item instanceof bcoin.coin) { } else if (item instanceof bcoin.coin) {
p.writeU8(42); p.writeU8(42);
p.writeVarBytes(item.toExtended()); bcoin.protocol.framer.coin(item, true, p);
} else if (bn.isBN(item)) { } else if (bn.isBN(item)) {
p.writeU8(43); p.writeU8(43);
p.writeVarBytes(item.toBuffer()); p.writeVarBytes(item.toBuffer());
@ -830,11 +830,11 @@ Parser.parseItem = function parseItem(p) {
items[p.readVarString('utf8')] = Parser.parseItem(p); items[p.readVarString('utf8')] = Parser.parseItem(p);
return items; return items;
case 40: case 40:
return bcoin.block.fromRaw(p.readVarBytes()); return bcoin.block.fromRaw(p);
case 41: case 41:
return bcoin.tx.fromExtended(p.readVarBytes(), true); return bcoin.tx.fromExtended(p, true);
case 42: case 42:
return bcoin.coin.fromExtended(p.readVarBytes()); return bcoin.coin.fromExtended(p);
case 43: case 43:
return new bn(p.readVarBytes()); return new bn(p.readVarBytes());
default: default: