tx: refactor network handling in json serialization.

This commit is contained in:
Christopher Jeffrey 2016-11-17 04:05:32 -08:00
parent 97703e4c7d
commit 39aee21030
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
11 changed files with 119 additions and 86 deletions

View File

@ -211,10 +211,8 @@ Chain.prototype._open = co(function* open() {
this.logger.info('Chain Height: %d', tip.height);
if (tip.height > this.bestHeight) {
if (tip.height > this.bestHeight)
this.bestHeight = tip.height;
this.network.updateHeight(tip.height);
}
this.logger.memory();
@ -853,7 +851,6 @@ Chain.prototype.disconnect = co(function* disconnect(entry) {
this.height = prev.height;
this.bestHeight = prev.height;
this.network.updateHeight(prev.height);
this.emit('tip', prev);
this.emit('disconnect', entry, block);
@ -900,7 +897,6 @@ Chain.prototype.reconnect = co(function* reconnect(entry) {
this.state = result.state;
this.bestHeight = entry.height;
this.network.updateHeight(entry.height);
this.emit('tip', entry);
this.emit('reconnect', entry, block);
@ -1250,10 +1246,8 @@ Chain.prototype._add = co(function* add(block) {
if (prev)
height = prev.height + 1;
if (height > this.bestHeight) {
if (height > this.bestHeight)
this.bestHeight = height;
this.network.updateHeight(height);
}
// If previous block wasn't ever seen,
// add it current to orphans and break.
@ -1267,10 +1261,8 @@ Chain.prototype._add = co(function* add(block) {
// We do this even for orphans (peers will send
// us their highest block during the initial
// getblocks sync, making it an orphan).
if (block.getCoinbaseHeight() > this.bestHeight) {
if (block.getCoinbaseHeight() > this.bestHeight)
this.bestHeight = block.getCoinbaseHeight();
this.network.updateHeight(this.bestHeight);
}
this.emit('orphan', block, block.getCoinbaseHeight());

View File

@ -180,7 +180,7 @@ HTTPClient.prototype.onDisconnect = function onDisconnect() {
*/
HTTPClient.prototype._request = co(function* _request(method, endpoint, json) {
var query, network, height, res;
var query, network, res;
if (this.token) {
if (!json)
@ -210,11 +210,6 @@ HTTPClient.prototype._request = co(function* _request(method, endpoint, json) {
if (network && network !== this.network.type)
throw new Error('Wrong network.');
height = +res.headers['x-bcoin-height'];
if (utils.isNumber(height))
this.network.updateHeight(height);
if (res.statusCode === 404)
return;

View File

@ -605,8 +605,8 @@ HTTPServer.prototype._init = function _init() {
coins = yield this.node.getCoinsByAddress(req.options.address);
send(200, coins.map(function(coin) {
return coin.toJSON();
}));
return coin.toJSON(this.network);
}, this));
}));
// UTXO by id
@ -621,7 +621,7 @@ HTTPServer.prototype._init = function _init() {
if (!coin)
return send(404);
send(200, coin.toJSON());
send(200, coin.toJSON(this.network));
}));
// Bulk read UTXOs
@ -633,8 +633,8 @@ HTTPServer.prototype._init = function _init() {
coins = yield this.node.getCoinsByAddress(req.options.address);
send(200, coins.map(function(coin) {
return coin.toJSON();
}));
return coin.toJSON(this.network);
}, this));
}));
// TX by hash
@ -650,7 +650,7 @@ HTTPServer.prototype._init = function _init() {
yield this.node.fillHistory(tx);
send(200, tx.toJSON());
send(200, tx.toJSON(this.network));
}));
// TX by address
@ -667,8 +667,8 @@ HTTPServer.prototype._init = function _init() {
}
send(200, txs.map(function(tx) {
return tx.toJSON();
}));
return tx.toJSON(this.network);
}, this));
}));
// Bulk read TXs
@ -685,8 +685,8 @@ HTTPServer.prototype._init = function _init() {
}
send(200, txs.map(function(tx) {
return tx.toJSON();
}));
return tx.toJSON(this.network);
}, this));
}));
// Block by hash/height
@ -701,7 +701,7 @@ HTTPServer.prototype._init = function _init() {
if (!block)
return send(404);
send(200, block.toJSON());
send(200, block.toJSON(this.network));
}));
// Mempool snapshot
@ -719,8 +719,8 @@ HTTPServer.prototype._init = function _init() {
}
send(200, txs.map(function(tx) {
return tx.toJSON();
}));
return tx.toJSON(this.network);
}, this));
}));
// Broadcast TX
@ -910,7 +910,7 @@ HTTPServer.prototype._init = function _init() {
var passphrase = options.passphrase;
var tx = yield req.wallet.createTX(options);
yield req.wallet.sign(tx, passphrase);
send(200, tx.toJSON());
send(200, tx.toJSON(this.network));
}));
// Sign TX
@ -920,7 +920,7 @@ HTTPServer.prototype._init = function _init() {
var tx = req.options.tx;
enforce(tx, 'TX is required.');
yield req.wallet.sign(tx, passphrase);
send(200, tx.toJSON());
send(200, tx.toJSON(this.network));
}));
// Fill TX
@ -928,7 +928,7 @@ HTTPServer.prototype._init = function _init() {
var tx = req.options.tx;
enforce(tx, 'TX is required.');
yield req.wallet.fillHistory(tx);
send(200, tx.toJSON());
send(200, tx.toJSON(this.network));
}));
// Zap Wallet TXs
@ -1068,8 +1068,8 @@ HTTPServer.prototype._init = function _init() {
sortCoins(coins);
send(200, coins.map(function(coin) {
return coin.toJSON();
}));
return coin.toJSON(this.network);
}, this));
}));
// Locked coins
@ -1120,7 +1120,7 @@ HTTPServer.prototype._init = function _init() {
if (!coin)
return send(404);
send(200, coin.toJSON());
send(200, coin.toJSON(this.network));
}));
// Wallet TXs
@ -1547,6 +1547,7 @@ function ClientSocket(server, socket) {
this.filter = null;
this.api = false;
this.network = this.server.network;
this.node = this.server.node;
this.chain = this.server.chain;
this.mempool = this.server.mempool;
@ -1658,7 +1659,7 @@ ClientSocket.prototype.watchChain = function watchChain() {
this.bind(pool, 'tx', function(tx) {
if (self.testFilter(tx))
self.emit('mempool tx', tx.toJSON());
self.emit('mempool tx', tx.toJSON(self.network));
});
};
@ -1679,7 +1680,7 @@ ClientSocket.prototype.testBlock = function testBlock(block) {
for (i = 0; i < block.txs.length; i++) {
tx = block.txs[i];
if (this.testFilter(tx))
txs.push(tx.toJSON());
txs.push(tx.toJSON(this.network));
}
if (txs.length === 0)
@ -1757,7 +1758,7 @@ ClientSocket.prototype.scanner = function scanner(entry, txs) {
var i;
for (i = 0; i < txs.length; i++)
json[i] = txs[i].toJSON();
json[i] = txs[i].toJSON(this.network);
this.emit('block tx', entry.toJSON(), json);

View File

@ -592,7 +592,6 @@ Block.prototype.getPrevout = function getPrevout() {
Block.prototype.inspect = function inspect() {
return {
type: 'block',
hash: this.rhash,
height: this.height,
size: this.getSize(),
@ -619,9 +618,9 @@ Block.prototype.inspect = function inspect() {
* @returns {Object}
*/
Block.prototype.toJSON = function toJSON() {
Block.prototype.toJSON = function toJSON(network) {
network = Network.get(network);
return {
type: 'block',
hash: this.rhash,
height: this.height,
version: this.version,
@ -632,7 +631,7 @@ Block.prototype.toJSON = function toJSON() {
nonce: this.nonce,
totalTX: this.totalTX,
txs: this.txs.map(function(tx) {
return tx.toJSON();
return tx.toJSON(network);
})
};
};

View File

@ -103,8 +103,7 @@ Coin.fromOptions = function fromOptions(options) {
*/
Coin.prototype.getConfirmations = function getConfirmations(height) {
if (height == null)
height = Network.primary.height;
assert(typeof height === 'number', 'Must pass a height.');
if (this.height === -1)
return 0;
@ -151,7 +150,7 @@ Coin.prototype.inspect = function inspect() {
coinbase: this.coinbase,
hash: this.hash ? utils.revHex(this.hash) : null,
index: this.index,
age: this.getAge(),
// age: this.getAge(),
address: this.getAddress()
};
};
@ -164,11 +163,13 @@ Coin.prototype.inspect = function inspect() {
* @returns {Object}
*/
Coin.prototype.toJSON = function toJSON() {
Coin.prototype.toJSON = function toJSON(network) {
var address = this.getAddress();
network = Network.get(network);
if (address)
address = address.toBase58();
address = address.toBase58(network);
return {
version: this.version,

View File

@ -266,15 +266,17 @@ Input.prototype.inspect = function inspect() {
* @returns {Object}
*/
Input.prototype.toJSON = function toJSON() {
Input.prototype.toJSON = function toJSON(network) {
var address = this.getAddress();
network = Network.get(network);
if (address)
address = address.toBase58();
address = address.toBase58(network);
return {
prevout: this.prevout.toJSON(),
coin: this.coin ? this.coin.toJSON() : null,
coin: this.coin ? this.coin.toJSON(network) : null,
script: this.script.toJSON(),
witness: this.witness.toJSON(),
sequence: this.sequence,

View File

@ -1312,11 +1312,7 @@ MTX.prototype.sortMembers = function sortMembers() {
*/
MTX.prototype.avoidFeeSniping = function avoidFeeSniping(height) {
if (height == null)
height = Network.primary.height;
if (height === -1)
height = 0;
assert(typeof height === 'number', 'Must pass in height.');
if ((Math.random() * 10 | 0) === 0)
height = Math.max(0, height - (Math.random() * 100 | 0));

View File

@ -131,11 +131,13 @@ Output.prototype.inspect = function inspect() {
* @returns {Object}
*/
Output.prototype.toJSON = function toJSON() {
Output.prototype.toJSON = function toJSON(network) {
var address = this.getAddress();
network = Network.get(network);
if (address)
address = address.toBase58();
address = address.toBase58(network);
return {
value: utils.btc(this.value),

View File

@ -1767,15 +1767,11 @@ TX.prototype.getPriority = function getPriority(height, size) {
var sum = 0;
var i, input, age;
assert(typeof height === 'number', 'Must pass in height.');
if (this.isCoinbase())
return sum;
if (height == null) {
height = this.height;
if (height === -1)
height = Network.primary.height;
}
if (size == null)
size = this.maxSize();
@ -1901,8 +1897,7 @@ TX.prototype.getRate = function getRate(size) {
*/
TX.prototype.getConfirmations = function getConfirmations(height) {
if (height == null)
height = Network.primary.height;
assert(typeof height === 'number', 'Must pass in height.');
if (this.height === -1)
return 0;
@ -2093,8 +2088,13 @@ TX.getRate = function getRate(size, fee) {
*/
TX.prototype.inspect = function inspect() {
var rate = this.getRate();
// Rate can exceed 53 bits in testing.
if (!utils.isSafeInteger(rate))
rate = 0;
return {
type: 'tx',
hash: this.rhash,
witnessHash: this.rwhash,
size: this.getSize(),
@ -2103,9 +2103,7 @@ TX.prototype.inspect = function inspect() {
value: utils.btc(this.getOutputValue()),
fee: utils.btc(this.getFee()),
minFee: utils.btc(this.getMinFee()),
rate: this.getRate(), // Rate can sometimes exceed 53 bits in testing
confirmations: this.getConfirmations(),
priority: this.getPriority(),
rate: utils.btc(rate),
date: utils.date(this.ts || this.ps),
block: this.block ? utils.revHex(this.block) : null,
ts: this.ts,
@ -2127,25 +2125,33 @@ TX.prototype.inspect = function inspect() {
* @returns {Object}
*/
TX.prototype.toJSON = function toJSON() {
TX.prototype.toJSON = function toJSON(network) {
var rate = this.getRate();
// Rate can exceed 53 bits in testing.
if (!utils.isSafeInteger(rate))
rate = 0;
network = Network.get(network);
return {
type: 'tx',
hash: utils.revHex(this.hash('hex')),
witnessHash: utils.revHex(this.witnessHash('hex')),
height: this.height,
block: this.block ? utils.revHex(this.block) : null,
ts: this.ts,
ps: this.ps,
date: utils.date(this.ts || this.ps),
index: this.index,
fee: utils.btc(this.getFee()),
confirmations: this.getConfirmations(),
rate: utils.btc(rate),
version: this.version,
flag: this.flag,
inputs: this.inputs.map(function(input) {
return input.toJSON();
return input.toJSON(network);
}),
outputs: this.outputs.map(function(output) {
return output.toJSON();
return output.toJSON(network);
}),
locktime: this.locktime
};

View File

@ -24,7 +24,6 @@ function Network(options) {
assert(!Network[options.type], 'Cannot create two networks.');
this.type = options.type;
this.height = -1;
this.seeds = options.seeds;
this.magic = options.magic;
this.port = options.port;
@ -77,15 +76,6 @@ Network.segnet3 = null;
Network.segnet4 = null;
Network.simnet = null;
/**
* Update the height of the network.
* @param {Number} height
*/
Network.prototype.updateHeight = function updateHeight(height) {
this.height = height;
};
/**
* Determine how many blocks to request
* based on current height of the chain.
@ -169,6 +159,31 @@ Network.get = function get(type) {
assert(false, 'Unknown network.');
};
/**
* Get a network with a string or a Network object.
* @param {NetworkType|Network} type - Network type.
* @returns {Network}
*/
Network.ensure = function ensure(type) {
if (!type) {
assert(Network.primary, 'No default network.');
return Network.primary;
}
if (type instanceof Network)
return type;
if (typeof type === 'string') {
if (networks[type])
return Network.create(type);
}
assert(Network.primary, 'No default network.');
return Network.primary;
};
/**
* Get a network by its magic number.
* @returns {Network}

View File

@ -3180,6 +3180,8 @@ function Details(txdb, tx) {
this.chainHeight = txdb.walletdb.state.height;
this.hash = tx.hash('hex');
this.size = tx.getSize();
this.vsize = tx.getVirtualSize();
this.tx = tx;
this.block = tx.block;
@ -3303,6 +3305,17 @@ Details.prototype.getFee = function getFee() {
return inputValue - outputValue;
};
/**
* Calculate fee rate. Only works if wallet
* owns all inputs. Returns 0 otherwise.
* @param {Amount} fee
* @returns {Rate}
*/
Details.prototype.getRate = function getRate(fee) {
return TX.getRate(this.vsize, fee);
};
/**
* Convert details to a more json-friendly object.
* @returns {Object}
@ -3310,6 +3323,13 @@ Details.prototype.getFee = function getFee() {
Details.prototype.toJSON = function toJSON() {
var self = this;
var fee = this.getFee();
var rate = this.getRate(fee);
// Rate can exceed 53 bits in testing.
if (!utils.isSafeInteger(rate))
rate = 0;
return {
wid: this.wid,
id: this.id,
@ -3318,8 +3338,12 @@ Details.prototype.toJSON = function toJSON() {
block: this.block ? utils.revHex(this.block) : null,
ts: this.ts,
ps: this.ps,
date: utils.date(this.ts || this.ps),
index: this.index,
fee: utils.btc(this.getFee()),
size: this.size,
virtualSize: this.vsize,
fee: utils.btc(fee),
rate: utils.btc(rate),
confirmations: this.getConfirmations(),
inputs: this.inputs.map(function(input) {
return input.toJSON(self.network);