txdb: serialization.
This commit is contained in:
parent
2f72937686
commit
284932f4cf
@ -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);
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -1 +1,2 @@
|
||||
01000000018759d7397a86d6c42dfe2c55612e523d171e51708fec9e289118deb5ba99400101000000dc00493046022100da3264579decba370d0b5d896c5f4664dfdf06119cc3ca5cef937389e61b5bf1022100a5584aa704578d35080129edb22d2bea7a24f16f0603cc22a9390cdc0a8f6e6301483045022018478cf5c7ef4cf0b0b6583937bba83b76bf87461825f44130dbb854111a62d8022100e431be966081676b2d785a3260e2a50e250d8a2f5d8364309fe1195dfa87a31d01475221030c341a91e5de82732d6bfb1c3676585b817096cd8bf076cf0ea88c339b9815072102f3f450d36aced52de6023ca5e9d7e256d5c5183f3316211d53bb151c3585222e52ae000000000104c70300000000001976a914a532649591196c7ff3ebd5783c29c9a08d54a3a288ac370c05004a0c0500749180fd60334bdcbb7cfadad26ca3746367047cdd218635b315380200000000010000000db72b550000000001290100000098d9040014ee03000000000017a914195bde4cd150acf910b5c83a024fd2d9f33306af8700
|
||||
01000000018759d7397a86d6c42dfe2c55612e523d171e51708fec9e289118deb5ba99400101000000dc00493046022100da3264579decba370d0b5d896c5f4664dfdf06119cc3ca5cef937389e61b5bf1022100a5584aa704578d35080129edb22d2bea7a24f16f0603cc22a9390cdc0a8f6e6301483045022018478cf5c7ef4cf0b0b6583937bba83b76bf87461825f44130dbb854111a62d8022100e431be966081676b2d785a3260e2a50e250d8a2f5d8364309fe1195dfa87a31d01475221030c341a91e5de82732d6bfb1c3676585b817096cd8bf076cf0ea88c339b9815072102f3f450d36aced52de6023ca5e9d7e256d5c5183f3316211d53bb151c3585222e52ae000000000104c70300000000001976a914a532649591196c7ff3ebd5783c29c9a08d54a3a288ac370c0500
|
||||
0100000001c6ada6066f14a0cd4dc39f086f1f7637b76bfc08da5dc25f8179b0ccfc5d09f7000000006a473044022067934a2152ab5fe96119d702fc48322b967aee669a14e9da8913481d4b7f133402207e444ee1987fcb25ebcb9d98add22e3948ac847a67b306dba106d8e6ba48781001210297812667d2a62d7bbcf17e2d2ade2ade548a9464e9e8e29b42a777f85c93a48effffffff02f4ad2600000000001976a91454987f4e1ea17ec34a489d82ae9d39f6928e61cd88ac14ee03000000000017a914195bde4cd150acf910b5c83a024fd2d9f33306af8700000000
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user