txdb: serialization.

This commit is contained in:
Christopher Jeffrey 2016-10-19 14:44:08 -07:00
parent 2f72937686
commit 284932f4cf
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
6 changed files with 83 additions and 138 deletions

View File

@ -15,7 +15,7 @@ var block = bcoin.block.fromJSON(require('../test/data/block300025.json'));
var btx = block.txs[397];
var tx1 = parseTX('../test/data/tx3.hex');
var tx4 = parseExtended('../test/data/tx4.hex');
var tx4 = parseTX('../test/data/tx4.hex');
var wtx = fs.readFileSync(__dirname + '/../test/data/wtx.hex', 'utf8');
wtx = new Buffer(wtx.trim(), 'hex');
var tx;
@ -30,11 +30,6 @@ function parseTX(file) {
return tx;
}
function parseExtended(file) {
file = fs.readFileSync(__dirname + '/' + file, 'utf8').trim();
return bcoin.tx.fromExtended(file, true, 'hex');
}
var end = bench('parse');
for (var i = 0; i < 1000; i++)
tx = bcoin.tx.fromRaw(wtx);

View File

@ -2392,129 +2392,10 @@ TX.isWitness = function isWitness(data) {
* timestamp, pending-since time, and optionally a vector
* for the serialized coins.
* @param {Boolean?} saveCoins - Whether to serialize the coins.
* @param {String?} enc - One of `"hex"` or `null`.
* @returns {Buffer}
*/
TX.prototype.toExtended = function toExtended(saveCoins, writer) {
var height = this.height;
var index = this.index;
var p = BufferWriter(writer);
var i, input;
if (height === -1)
height = 0x7fffffff;
if (index === -1)
index = 0x7fffffff;
this.toRaw(p);
p.writeU32(height);
p.writeHash(this.block || constants.ZERO_HASH);
p.writeU32(index);
p.writeU32(this.ts);
p.writeU32(this.ps);
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(input.coin.toRaw());
}
}
if (!writer)
p = p.render();
return p;
};
/**
* Inject properties from "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`.
*/
TX.prototype.fromExtended = function fromExtended(data, saveCoins) {
var p = BufferReader(data);
var i, coinCount, coin;
this.fromRaw(p);
this.height = p.readU32();
this.block = p.readHash('hex');
this.index = p.readU32();
this.ts = p.readU32();
this.ps = p.readU32();
if (this.block === constants.NULL_HASH)
this.block = null;
if (this.height === 0x7fffffff)
this.height = -1;
if (this.index === 0x7fffffff)
this.index = -1;
if (saveCoins) {
coinCount = p.readVarint();
for (i = 0; i < coinCount; i++) {
coin = p.readVarBytes();
if (coin.length === 0)
continue;
coin = Coin.fromRaw(coin);
coin.hash = this.inputs[i].prevout.hash;
coin.index = this.inputs[i].prevout.index;
this.inputs[i].coin = coin;
}
}
return this;
};
/**
* 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;
}
if (typeof data === 'string')
data = new Buffer(data, enc);
return new TX().fromExtended(data, saveCoins);
};
/**
* 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 {Boolean?} saveCoins - Whether to serialize the coins.
* @returns {Buffer}
*/
TX.prototype.toExtended2 = function toExtended2(saveCoins, writer) {
var p = BufferWriter(writer);
var i, input, field, bit, oct;
@ -2569,7 +2450,7 @@ TX.prototype.toExtended2 = function toExtended2(saveCoins, writer) {
* attempt to parse the coins.
*/
TX.prototype.fromExtended2 = function fromExtended2(data, saveCoins) {
TX.prototype.fromExtended = function fromExtended(data, saveCoins) {
var p = BufferReader(data);
var i, input, coin, field, bit, oct, spent;
@ -2618,7 +2499,7 @@ TX.prototype.fromExtended2 = function fromExtended2(data, saveCoins) {
* @returns {TX}
*/
TX.fromExtended2 = function fromExtended2(data, saveCoins, enc) {
TX.fromExtended = function fromExtended(data, saveCoins, enc) {
if (typeof saveCoins === 'string') {
enc = saveCoins;
saveCoins = false;
@ -2627,7 +2508,7 @@ TX.fromExtended2 = function fromExtended2(data, saveCoins, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new TX().fromExtended2(data, saveCoins);
return new TX().fromExtended(data, saveCoins);
};
/**

View File

@ -4,6 +4,9 @@ var constants = require('../lib/protocol/constants');
var WalletDB = require('../lib/wallet/walletdb');
var TXDB = require('../lib/wallet/txdb');
var BufferWriter = require('../lib/utils/writer');
var BufferReader = require('../lib/utils/reader');
var TX = require('../lib/primitives/tx');
var Coin = require('../lib/primitives/coin');
var utils = require('../lib/utils/utils');
var co = bcoin.co;
var layout = WalletDB.layout;
@ -61,7 +64,7 @@ var updateTXDB = co(function* updateTXDB() {
key = keys[i];
if (key[0] === 0x74 && key[5] === 0x74) {
tx = yield db.get(key);
tx = bcoin.tx.fromExtended(tx);
tx = fromExtended(tx);
hash = tx.hash('hex');
txs[hash] = tx;
}
@ -91,6 +94,44 @@ var updateTXDB = co(function* updateTXDB() {
yield walletdb.close();
});
function fromExtended(data, saveCoins) {
var tx = new TX();
var p = BufferReader(data);
var i, coinCount, coin;
tx.fromRaw(p);
tx.height = p.readU32();
tx.block = p.readHash('hex');
tx.index = p.readU32();
tx.ts = p.readU32();
tx.ps = 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 (saveCoins) {
coinCount = p.readVarint();
for (i = 0; i < coinCount; i++) {
coin = p.readVarBytes();
if (coin.length === 0)
continue;
coin = Coin.fromRaw(coin);
coin.hash = tx.inputs[i].prevout.hash;
coin.index = tx.inputs[i].prevout.index;
tx.inputs[i].coin = coin;
}
}
return tx;
}
co.spawn(function* () {
yield db.open();
batch = db.batch();

View File

@ -1 +1,2 @@
01000000018759d7397a86d6c42dfe2c55612e523d171e51708fec9e289118deb5ba99400101000000dc00493046022100da3264579decba370d0b5d896c5f4664dfdf06119cc3ca5cef937389e61b5bf1022100a5584aa704578d35080129edb22d2bea7a24f16f0603cc22a9390cdc0a8f6e6301483045022018478cf5c7ef4cf0b0b6583937bba83b76bf87461825f44130dbb854111a62d8022100e431be966081676b2d785a3260e2a50e250d8a2f5d8364309fe1195dfa87a31d01475221030c341a91e5de82732d6bfb1c3676585b817096cd8bf076cf0ea88c339b9815072102f3f450d36aced52de6023ca5e9d7e256d5c5183f3316211d53bb151c3585222e52ae000000000104c70300000000001976a914a532649591196c7ff3ebd5783c29c9a08d54a3a288ac370c05004a0c0500749180fd60334bdcbb7cfadad26ca3746367047cdd218635b315380200000000010000000db72b550000000001290100000098d9040014ee03000000000017a914195bde4cd150acf910b5c83a024fd2d9f33306af8700
01000000018759d7397a86d6c42dfe2c55612e523d171e51708fec9e289118deb5ba99400101000000dc00493046022100da3264579decba370d0b5d896c5f4664dfdf06119cc3ca5cef937389e61b5bf1022100a5584aa704578d35080129edb22d2bea7a24f16f0603cc22a9390cdc0a8f6e6301483045022018478cf5c7ef4cf0b0b6583937bba83b76bf87461825f44130dbb854111a62d8022100e431be966081676b2d785a3260e2a50e250d8a2f5d8364309fe1195dfa87a31d01475221030c341a91e5de82732d6bfb1c3676585b817096cd8bf076cf0ea88c339b9815072102f3f450d36aced52de6023ca5e9d7e256d5c5183f3316211d53bb151c3585222e52ae000000000104c70300000000001976a914a532649591196c7ff3ebd5783c29c9a08d54a3a288ac370c0500
0100000001c6ada6066f14a0cd4dc39f086f1f7637b76bfc08da5dc25f8179b0ccfc5d09f7000000006a473044022067934a2152ab5fe96119d702fc48322b967aee669a14e9da8913481d4b7f133402207e444ee1987fcb25ebcb9d98add22e3948ac847a67b306dba106d8e6ba48781001210297812667d2a62d7bbcf17e2d2ade2ade548a9464e9e8e29b42a777f85c93a48effffffff02f4ad2600000000001976a91454987f4e1ea17ec34a489d82ae9d39f6928e61cd88ac14ee03000000000017a914195bde4cd150acf910b5c83a024fd2d9f33306af8700000000

View File

@ -14,7 +14,7 @@ var fs = require('fs');
var tx1 = parseTX('data/tx1.hex');
var tx2 = parseTX('data/tx2.hex');
var tx3 = parseTX('data/tx3.hex');
var tx4 = parseExtended('data/tx4.hex');
var tx4 = parseTX('data/tx4.hex');
var wtx = parseTX('data/wtx.hex');
var coolest = parseTX('data/coolest-tx-ever-sent.hex');
@ -28,11 +28,6 @@ function parseTX(file) {
return tx;
}
function parseExtended(file) {
file = fs.readFileSync(__dirname + '/' + file, 'utf8').trim();
return bcoin.tx.fromExtended(file, true, 'hex');
}
function clearCache(tx, nocache) {
var i, input, output;

View File

@ -193,6 +193,8 @@ describe('Wallet', function() {
t1.addInput(dummy());
t1.ts = utils.now();
t1.height = 1;
t1.block = constants.NULL_HASH;
t1.index = 0;
// balance: 51000
yield w.sign(t1);
@ -291,6 +293,8 @@ describe('Wallet', function() {
t2.ts = utils.now();
t2.height = 1;
t2.block = constants.NULL_HASH;
t2.index = 0;
yield walletdb.addTX(t2);
}));
@ -302,6 +306,8 @@ describe('Wallet', function() {
tx.addInput(doubleSpend.coin);
tx.ts = utils.now();
tx.height = 1;
tx.block = constants.NULL_HASH;
tx.index = 0;
txs = yield w.getHistory();
assert.equal(txs.length, 5);
@ -353,6 +359,8 @@ describe('Wallet', function() {
t1.addInput(dummy());
t1.ts = utils.now();
t1.height = 1;
t1.block = constants.NULL_HASH;
t1.index = 0;
// balance: 51000
yield w.sign(t1);
@ -449,18 +457,26 @@ describe('Wallet', function() {
t2.ts = utils.now();
t2.height = 1;
t2.block = constants.NULL_HASH;
t2.index = 0;
yield walletdb.addTX(t2);
t3.ts = utils.now();
t3.height = 1;
t3.block = constants.NULL_HASH;
t3.index = 0;
yield walletdb.addTX(t3);
t4.ts = utils.now();
t4.height = 1;
t4.block = constants.NULL_HASH;
t4.index = 0;
yield walletdb.addTX(t4);
f1.ts = utils.now();
f1.height = 1;
f1.block = constants.NULL_HASH;
f1.index = 0;
yield walletdb.addTX(f1);
balance = yield w.getBalance();
@ -717,9 +733,10 @@ describe('Wallet', function() {
utx = utx.toTX();
// Simulate a confirmation
utx.ps = 0;
utx.ts = 1;
utx.height = 1;
utx.block = constants.NULL_HASH;
utx.index = 0;
assert.equal(w1[depth], 1);
@ -760,9 +777,10 @@ describe('Wallet', function() {
assert.equal(w3.change.getAddress('base58'), change);
// Simulate a confirmation
send.ps = 0;
send.ts = 1;
send.height = 1;
send.block = constants.NULL_HASH;
send.index = 0;
yield walletdb.addTX(send);
yield walletdb.addTX(send);
@ -1201,7 +1219,10 @@ describe('Wallet', function() {
t1 = bcoin.mtx()
.addOutput(addr, 50000);
t1.addInput(dummy());
t1.ts = utils.now();
t1.block = constants.NULL_HASH;
t1.height = 1;
t1.index = 0;
yield alice.sign(t1);
t1 = t1.toTX();
@ -1244,11 +1265,15 @@ describe('Wallet', function() {
// Bob sees t2 on the chain.
t2.height = 3;
t2.ts = utils.now();
t2.block = constants.NULL_HASH;
t2.index = 0;
yield bob.add(t2);
// Bob sees t3 on the chain.
t3.height = 3;
t3.ts = utils.now();
t3.block = constants.NULL_HASH;
t3.index = 0;
yield bob.add(t3);
assert.equal((yield bob.getBalance()).unconfirmed, 30000);
@ -1274,7 +1299,10 @@ describe('Wallet', function() {
t1 = bcoin.mtx()
.addOutput(addr, 50000);
t1.addInput(dummy());
t1.ts = utils.now();
t1.block = constants.NULL_HASH;
t1.height = 1;
t1.index = 0;
yield alice.sign(t1);
t1 = t1.toTX();
@ -1328,11 +1356,15 @@ describe('Wallet', function() {
// Bob sees t2 on the chain.
t2.height = 3;
t2.ts = utils.now();
t2.block = constants.NULL_HASH;
t2.index = 0;
yield bob.add(t2);
// Bob sees t3 on the chain.
t3.height = 3;
t3.ts = utils.now();
t3.block = constants.NULL_HASH;
t3.index = 0;
yield bob.add(t3);
assert.equal((yield bob.getBalance()).unconfirmed, 30000);