wallet: store timestamp of transactions
This commit is contained in:
parent
292da0625e
commit
048bca0b8a
@ -20,9 +20,6 @@ function Chain(options) {
|
|||||||
this.block = {
|
this.block = {
|
||||||
list: [],
|
list: [],
|
||||||
|
|
||||||
// Bloom filter for all merkle trees
|
|
||||||
merkleBloom: new bcoin.bloom(8 * 1024 * 1024, 16, 0xdeadbeed),
|
|
||||||
|
|
||||||
// Bloom filter for all known blocks
|
// Bloom filter for all known blocks
|
||||||
bloom: new bcoin.bloom(8 * 1024 * 1024, 16, 0xdeadbeef)
|
bloom: new bcoin.bloom(8 * 1024 * 1024, 16, 0xdeadbeef)
|
||||||
};
|
};
|
||||||
@ -215,7 +212,6 @@ Chain.prototype._compress = function compress() {
|
|||||||
// Bloom filter rebuilt is needed
|
// Bloom filter rebuilt is needed
|
||||||
this.block.list = this.block.list.slice(-1000);
|
this.block.list = this.block.list.slice(-1000);
|
||||||
this.block.bloom.reset();
|
this.block.bloom.reset();
|
||||||
this.block.merkleBloom.reset();
|
|
||||||
|
|
||||||
for (var i = 0; i < this.block.list.length; i++)
|
for (var i = 0; i < this.block.list.length; i++)
|
||||||
this._bloomBlock(this.block.list[i]);
|
this._bloomBlock(this.block.list[i]);
|
||||||
@ -223,8 +219,6 @@ Chain.prototype._compress = function compress() {
|
|||||||
|
|
||||||
Chain.prototype._bloomBlock = function _bloomBlock(block) {
|
Chain.prototype._bloomBlock = function _bloomBlock(block) {
|
||||||
this.block.bloom.add(block.hash(), 'hex');
|
this.block.bloom.add(block.hash(), 'hex');
|
||||||
for (var i = 0; i < block.hashes.length; i++)
|
|
||||||
this.block.merkleBloom.add(block.hashes[i], 'hex');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Chain.prototype.has = function has(hash, noProbe, cb) {
|
Chain.prototype.has = function has(hash, noProbe, cb) {
|
||||||
@ -258,20 +252,6 @@ Chain.prototype.has = function has(hash, noProbe, cb) {
|
|||||||
return cb(!!this.orphan.map[hash]);
|
return cb(!!this.orphan.map[hash]);
|
||||||
};
|
};
|
||||||
|
|
||||||
Chain.prototype.hasMerkle = function hasMerkle(hash) {
|
|
||||||
if (!this.block.merkleBloom.test(hash, 'hex'))
|
|
||||||
return false;
|
|
||||||
if (!this.strict)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
hash = utils.toHex(hash);
|
|
||||||
for (var i = 0; i < this.block.list.length; i++)
|
|
||||||
if (this.block.list[i].hasMerkle(hash))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
Chain.prototype.get = function get(hash, cb) {
|
Chain.prototype.get = function get(hash, cb) {
|
||||||
// Cached block found
|
// Cached block found
|
||||||
if (this.block.bloom.test(hash, 'hex')) {
|
if (this.block.bloom.test(hash, 'hex')) {
|
||||||
|
|||||||
@ -250,15 +250,16 @@ Peer.prototype._onPacket = function onPacket(packet) {
|
|||||||
else if (cmd === 'pong')
|
else if (cmd === 'pong')
|
||||||
return this._handlePong(payload);
|
return this._handlePong(payload);
|
||||||
|
|
||||||
if (cmd === 'merkleblock' || cmd === 'block')
|
if (cmd === 'merkleblock' || cmd === 'block') {
|
||||||
payload = bcoin.block(payload);
|
payload = bcoin.block(payload);
|
||||||
else if (cmd === 'tx')
|
this.lastBlock = payload;
|
||||||
payload = bcoin.tx(payload);
|
} else if (cmd === 'tx') {
|
||||||
if (this._res(cmd, payload)) {
|
payload = bcoin.tx(payload, this.lastBlock);
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
this.emit(cmd, payload);
|
|
||||||
}
|
}
|
||||||
|
if (this._res(cmd, payload))
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
this.emit(cmd, payload);
|
||||||
};
|
};
|
||||||
|
|
||||||
Peer.prototype._handleVersion = function handleVersion(payload) {
|
Peer.prototype._handleVersion = function handleVersion(payload) {
|
||||||
|
|||||||
@ -12,10 +12,11 @@ function TXPool(wallet) {
|
|||||||
|
|
||||||
this._wallet = wallet;
|
this._wallet = wallet;
|
||||||
this._storage = wallet.storage;
|
this._storage = wallet.storage;
|
||||||
this._prefix = 'bt/' + wallet.getAddress() + '/tx/';
|
this._prefix = wallet.prefix + 'tx/';
|
||||||
this._all = {};
|
this._all = {};
|
||||||
this._unspent = {};
|
this._unspent = {};
|
||||||
this._orphans = {};
|
this._orphans = {};
|
||||||
|
this._lastTs = 0;
|
||||||
|
|
||||||
// Load TXs from storage
|
// Load TXs from storage
|
||||||
this._init();
|
this._init();
|
||||||
@ -39,6 +40,9 @@ TXPool.prototype._init = function init() {
|
|||||||
s.on('error', function(err) {
|
s.on('error', function(err) {
|
||||||
self.emit('error', err);
|
self.emit('error', err);
|
||||||
});
|
});
|
||||||
|
s.on('end', function() {
|
||||||
|
self.emit('load', self._lastTs);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
TXPool.prototype.add = function add(tx, noWrite) {
|
TXPool.prototype.add = function add(tx, noWrite) {
|
||||||
@ -76,6 +80,8 @@ TXPool.prototype.add = function add(tx, noWrite) {
|
|||||||
if (!own)
|
if (!own)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
var updated = false;
|
||||||
|
|
||||||
// Add unspent outputs or fullfill orphans
|
// Add unspent outputs or fullfill orphans
|
||||||
for (var i = 0; i < tx.outputs.length; i++) {
|
for (var i = 0; i < tx.outputs.length; i++) {
|
||||||
var out = tx.outputs[i];
|
var out = tx.outputs[i];
|
||||||
@ -84,7 +90,7 @@ TXPool.prototype.add = function add(tx, noWrite) {
|
|||||||
var orphan = this._orphans[key];
|
var orphan = this._orphans[key];
|
||||||
if (!orphan) {
|
if (!orphan) {
|
||||||
this._unspent[key] = { tx: tx, index: i };
|
this._unspent[key] = { tx: tx, index: i };
|
||||||
this.emit('update');
|
updated = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
delete this._orphans[key];
|
delete this._orphans[key];
|
||||||
@ -93,6 +99,10 @@ TXPool.prototype.add = function add(tx, noWrite) {
|
|||||||
orphan.tx.input(tx, orphan.index);
|
orphan.tx.input(tx, orphan.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._lastTs = Math.max(tx.ts, this._lastTs);
|
||||||
|
if (updated)
|
||||||
|
this.emit('update', this._lastTs);
|
||||||
|
|
||||||
if (!noWrite && this._storage) {
|
if (!noWrite && this._storage) {
|
||||||
var self = this;
|
var self = this;
|
||||||
this._storage.put(this._prefix + hash, tx.toJSON(), function(err) {
|
this._storage.put(this._prefix + hash, tx.toJSON(), function(err) {
|
||||||
|
|||||||
@ -4,9 +4,9 @@ var bn = require('bn.js');
|
|||||||
var bcoin = require('../bcoin');
|
var bcoin = require('../bcoin');
|
||||||
var utils = bcoin.utils;
|
var utils = bcoin.utils;
|
||||||
|
|
||||||
function TX(data) {
|
function TX(data, block) {
|
||||||
if (!(this instanceof TX))
|
if (!(this instanceof TX))
|
||||||
return new TX(data);
|
return new TX(data, block);
|
||||||
this.type = 'tx';
|
this.type = 'tx';
|
||||||
|
|
||||||
if (!data)
|
if (!data)
|
||||||
@ -16,6 +16,7 @@ function TX(data) {
|
|||||||
this.inputs = [];
|
this.inputs = [];
|
||||||
this.outputs = [];
|
this.outputs = [];
|
||||||
this.lock = data.lock || 0;
|
this.lock = data.lock || 0;
|
||||||
|
this.ts = data.ts || 0;
|
||||||
|
|
||||||
this._hash = null;
|
this._hash = null;
|
||||||
this._raw = data._raw || null;
|
this._raw = data._raw || null;
|
||||||
@ -30,6 +31,9 @@ function TX(data) {
|
|||||||
this.out(out, null);
|
this.out(out, null);
|
||||||
}, this);
|
}, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!data.ts && block && block.hasMerkle(this.hash('hex')))
|
||||||
|
this.ts = block.ts;
|
||||||
}
|
}
|
||||||
module.exports = TX;
|
module.exports = TX;
|
||||||
|
|
||||||
@ -174,10 +178,19 @@ TX.prototype.verify = function verify() {
|
|||||||
|
|
||||||
TX.prototype.toJSON = function toJSON() {
|
TX.prototype.toJSON = function toJSON() {
|
||||||
// Compact representation
|
// Compact representation
|
||||||
return utils.toBase58(this.render());
|
var ts = new Array(4);
|
||||||
|
bcoin.utils.writeU32(ts, this.ts, 0);
|
||||||
|
return utils.toBase58(this.render().concat(ts));
|
||||||
};
|
};
|
||||||
|
|
||||||
TX.fromJSON = function fromJSON(json) {
|
TX.fromJSON = function fromJSON(json) {
|
||||||
// Compact representation
|
// Compact representation
|
||||||
return new TX(new bcoin.protocol.parser().parseTX(utils.fromBase58(json)));
|
var data = utils.fromBase58(json);
|
||||||
|
var tx = data.slice(0, -4);
|
||||||
|
var ts = bcoin.utils.readU32(data, data.length - 4);
|
||||||
|
|
||||||
|
tx = new TX(new bcoin.protocol.parser().parseTX(tx));
|
||||||
|
tx.ts = ts;
|
||||||
|
|
||||||
|
return tx;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -37,6 +37,7 @@ function Wallet(options, passphrase) {
|
|||||||
this.key = bcoin.ecdsa.genKeyPair();
|
this.key = bcoin.ecdsa.genKeyPair();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.prefix = 'bt/' + this.getAddress() + '/';
|
||||||
this.tx = new bcoin.txPool(this);
|
this.tx = new bcoin.txPool(this);
|
||||||
this._init();
|
this._init();
|
||||||
}
|
}
|
||||||
@ -47,13 +48,17 @@ Wallet.prototype._init = function init() {
|
|||||||
// Notify owners about new accepted transactions
|
// Notify owners about new accepted transactions
|
||||||
var self = this;
|
var self = this;
|
||||||
var prevBalance = null;
|
var prevBalance = null;
|
||||||
this.tx.on('update', function(tx) {
|
this.tx.on('update', function() {
|
||||||
var b = this.balance();
|
var b = this.balance();
|
||||||
if (prevBalance && prevBalance.cmp(b) !== 0)
|
if (prevBalance && prevBalance.cmp(b) !== 0)
|
||||||
self.emit('balance', b);
|
self.emit('balance', b);
|
||||||
prevBalance = b;
|
prevBalance = b;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.tx.once('load', function(ts) {
|
||||||
|
self.emit('load', ts);
|
||||||
|
});
|
||||||
|
|
||||||
this.tx.on('error', function(err) {
|
this.tx.on('error', function(err) {
|
||||||
self.emit('error', err);
|
self.emit('error', err);
|
||||||
});
|
});
|
||||||
@ -186,7 +191,7 @@ Wallet.prototype.sign = function sign(tx, type) {
|
|||||||
return inputs.length;
|
return inputs.length;
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.addTX = function addTX(tx) {
|
Wallet.prototype.addTX = function addTX(tx, block) {
|
||||||
return this.tx.add(tx);
|
return this.tx.add(tx);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user