add features potentially useful for blockchain explorers.
This commit is contained in:
parent
a7ea69f48a
commit
52b653083c
@ -31,10 +31,15 @@ function Block(data, subtype) {
|
|||||||
return utils.toHex(hash);
|
return utils.toHex(hash);
|
||||||
});
|
});
|
||||||
this.flags = data.flags || [];
|
this.flags = data.flags || [];
|
||||||
this._network = data._network || false;
|
|
||||||
this._raw = data._raw || null;
|
this._raw = data._raw || null;
|
||||||
this._size = data._size || 0;
|
this._size = data._size || 0;
|
||||||
|
|
||||||
|
this.network = data.network || false;
|
||||||
|
this.relayedBy = data.relayedBy || '0.0.0.0';
|
||||||
|
this._height = data._height != null ? data._height : -1;
|
||||||
|
this._nextBlock = data._nextBlock || null;
|
||||||
|
|
||||||
// List of matched TXs
|
// List of matched TXs
|
||||||
this.tx = [];
|
this.tx = [];
|
||||||
this.invalid = false;
|
this.invalid = false;
|
||||||
@ -42,7 +47,8 @@ function Block(data, subtype) {
|
|||||||
if (this.subtype === 'block') {
|
if (this.subtype === 'block') {
|
||||||
this.txs = data.txs || [];
|
this.txs = data.txs || [];
|
||||||
this.txs = this.txs.map(function(tx) {
|
this.txs = this.txs.map(function(tx) {
|
||||||
tx._network = self._network;
|
tx.network = self.network;
|
||||||
|
tx.relayedBy = self.relayedBy;
|
||||||
tx = bcoin.tx(tx);
|
tx = bcoin.tx(tx);
|
||||||
tx.block = self.hash('hex');
|
tx.block = self.hash('hex');
|
||||||
tx.ts = tx.ts || self.ts;
|
tx.ts = tx.ts || self.ts;
|
||||||
@ -69,7 +75,7 @@ Block.prototype.hash = function hash(enc) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Block.prototype.abbr = function abbr() {
|
Block.prototype.abbr = function abbr() {
|
||||||
if (this._network)
|
if (this.network)
|
||||||
return this._raw.slice();
|
return this._raw.slice();
|
||||||
|
|
||||||
var res = new Array(80);
|
var res = new Array(80);
|
||||||
@ -239,6 +245,49 @@ Block.prototype._checkBlock = function checkBlock() {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Block.prototype.__defineSetter__('height', function(height) {
|
||||||
|
return this._height = height;
|
||||||
|
});
|
||||||
|
|
||||||
|
Block.prototype.__defineGetter__('height', function() {
|
||||||
|
return this.getHeight(bcoin.chain.global);
|
||||||
|
});
|
||||||
|
|
||||||
|
Block.prototype.__defineGetter__('nextBlock', function() {
|
||||||
|
return this.getNextBlock(bcoin.chain.global);
|
||||||
|
});
|
||||||
|
|
||||||
|
Block.prototype.getHeight = function getHeight(chain) {
|
||||||
|
if (this._height >= 0)
|
||||||
|
return this._height;
|
||||||
|
|
||||||
|
chain = chain || bcoin.chain.global;
|
||||||
|
|
||||||
|
if (!chain)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return this._height = chain.getHeight(this.hash('hex'));
|
||||||
|
};
|
||||||
|
|
||||||
|
Block.prototype.getNextBlock = function getNextBlock(chain) {
|
||||||
|
var next;
|
||||||
|
|
||||||
|
if (this._nextBlock)
|
||||||
|
return this._nextBlock;
|
||||||
|
|
||||||
|
chain = chain || bcoin.chain.global;
|
||||||
|
|
||||||
|
if (!chain)
|
||||||
|
return utils.toHex(constants.protocol.zeroHash);
|
||||||
|
|
||||||
|
next = chain.getNextBlock(this.hash('hex'));
|
||||||
|
|
||||||
|
if (!next)
|
||||||
|
return utils.toHex(constants.zeroHash);
|
||||||
|
|
||||||
|
return this._nextBlock = next;
|
||||||
|
};
|
||||||
|
|
||||||
Block.prototype.toJSON = function toJSON() {
|
Block.prototype.toJSON = function toJSON() {
|
||||||
return {
|
return {
|
||||||
v: '1',
|
v: '1',
|
||||||
@ -247,6 +296,9 @@ Block.prototype.toJSON = function toJSON() {
|
|||||||
hash: this.hash('hex'),
|
hash: this.hash('hex'),
|
||||||
prevBlock: this.prevBlock,
|
prevBlock: this.prevBlock,
|
||||||
ts: this.ts,
|
ts: this.ts,
|
||||||
|
network: this.network,
|
||||||
|
relayedBy: this.relayedBy,
|
||||||
|
_height: this._height,
|
||||||
block: utils.toHex(bcoin.protocol.framer.block(this, this.subtype))
|
block: utils.toHex(bcoin.protocol.framer.block(this, this.subtype))
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -265,7 +317,9 @@ Block.fromJSON = function fromJSON(json) {
|
|||||||
? parser.parseMerkleBlock(raw)
|
? parser.parseMerkleBlock(raw)
|
||||||
: parser.parseBlock(raw);
|
: parser.parseBlock(raw);
|
||||||
|
|
||||||
data._network = json._network;
|
data.network = json.network;
|
||||||
|
data.relayedBy = json.relayedBy;
|
||||||
|
data._height = json._height;
|
||||||
|
|
||||||
block = new Block(data, json.subtype);
|
block = new Block(data, json.subtype);
|
||||||
|
|
||||||
|
|||||||
@ -30,17 +30,19 @@ function Chain(options) {
|
|||||||
this.storage = this.options.storage;
|
this.storage = this.options.storage;
|
||||||
this.strict = this.options.strict || false;
|
this.strict = this.options.strict || false;
|
||||||
this.cacheLimit = this.options.cacheLimit || 2000;
|
this.cacheLimit = this.options.cacheLimit || 2000;
|
||||||
|
|
||||||
this.block = {
|
this.block = {
|
||||||
list: [],
|
list: [],
|
||||||
|
|
||||||
// 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)
|
||||||
};
|
};
|
||||||
|
|
||||||
this.orphan = {
|
this.orphan = {
|
||||||
map: {},
|
map: {},
|
||||||
bmap: {},
|
bmap: {},
|
||||||
count: 0
|
count: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
this.index = {
|
this.index = {
|
||||||
bloom: null,
|
bloom: null,
|
||||||
hashes: [],
|
hashes: [],
|
||||||
@ -48,6 +50,7 @@ function Chain(options) {
|
|||||||
heights: [],
|
heights: [],
|
||||||
lastTs: 0
|
lastTs: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
this.request = new utils.RequestCache();
|
this.request = new utils.RequestCache();
|
||||||
|
|
||||||
// Start from the genesis block
|
// Start from the genesis block
|
||||||
@ -67,6 +70,8 @@ function Chain(options) {
|
|||||||
// Last TS after preload, needed for fill percent
|
// Last TS after preload, needed for fill percent
|
||||||
this.index.lastTs = this.index.ts[this.index.ts.length - 1];
|
this.index.lastTs = this.index.ts[this.index.ts.length - 1];
|
||||||
|
|
||||||
|
Chain.global = this;
|
||||||
|
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this._init();
|
this._init();
|
||||||
}
|
}
|
||||||
@ -591,6 +596,36 @@ Chain.prototype.getOrphanRoot = function getOrphanRoot(hash) {
|
|||||||
return root;
|
return root;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Chain.prototype.getHeight = function getHeight(hash) {
|
||||||
|
var chain, i, height;
|
||||||
|
|
||||||
|
if (Array.isArray(hash))
|
||||||
|
hash = utils.toHex(hash);
|
||||||
|
else if (hash.hash)
|
||||||
|
hash = hash.hash('hex');
|
||||||
|
|
||||||
|
i = this.index.hashes.indexOf(hash);
|
||||||
|
height = this.index.heights[i];
|
||||||
|
|
||||||
|
if (height === null)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return height;
|
||||||
|
};
|
||||||
|
|
||||||
|
Chain.prototype.getNextBlock = function getNextBlock(hash) {
|
||||||
|
var height, nextHeight, i;
|
||||||
|
|
||||||
|
height = this.getHeight(chain);
|
||||||
|
nextHeight = this.index.heights[i + 1];
|
||||||
|
i = this.index.heights.indexOf(nextHeight);
|
||||||
|
|
||||||
|
if (nextHeight !== height + 1)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return this.index.hashes[i] || null;
|
||||||
|
};
|
||||||
|
|
||||||
Chain.prototype.toJSON = function toJSON() {
|
Chain.prototype.toJSON = function toJSON() {
|
||||||
var keep = 1000;
|
var keep = 1000;
|
||||||
|
|
||||||
|
|||||||
@ -79,6 +79,10 @@ function Peer(pool, createSocket, options) {
|
|||||||
|
|
||||||
inherits(Peer, EventEmitter);
|
inherits(Peer, EventEmitter);
|
||||||
|
|
||||||
|
Peer.prototype.__defineGetter__('address', function() {
|
||||||
|
return this.socket && (this.socket.remoteAddress || '0.0.0.0');
|
||||||
|
});
|
||||||
|
|
||||||
Peer.prototype._init = function init() {
|
Peer.prototype._init = function init() {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
@ -108,10 +112,9 @@ Peer.prototype._init = function init() {
|
|||||||
|
|
||||||
if (this.pool.options.fullNode) {
|
if (this.pool.options.fullNode) {
|
||||||
this.once('version', function() {
|
this.once('version', function() {
|
||||||
var ip = self.socket && self.socket.remoteAddress || '0.0.0.0';
|
|
||||||
self.pool.emit('debug',
|
self.pool.emit('debug',
|
||||||
'Sent version (%s): height=%s',
|
'Sent version (%s): height=%s',
|
||||||
ip, this.pool.chain.getStartHeight());
|
self.address, this.pool.chain.getStartHeight());
|
||||||
// self.pool.emit('debug', 'version (%s): sending locator hashes', ip);
|
// self.pool.emit('debug', 'version (%s): sending locator hashes', ip);
|
||||||
// self.loadBlocks(self.chain.locatorHashes(), 0);
|
// self.loadBlocks(self.chain.locatorHashes(), 0);
|
||||||
});
|
});
|
||||||
@ -143,9 +146,7 @@ Peer.prototype.startSync = function startSync() {
|
|||||||
if (!this.pool.options.fullNode)
|
if (!this.pool.options.fullNode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var ip = this.socket && this.socket.remoteAddress || '0.0.0.0';
|
this.pool.emit('debug', 'version (%s): sending locator hashes', this.address);
|
||||||
|
|
||||||
this.pool.emit('debug', 'version (%s): sending locator hashes', ip);
|
|
||||||
|
|
||||||
this.loadBlocks(this.chain.locatorHashes(), 0);
|
this.loadBlocks(this.chain.locatorHashes(), 0);
|
||||||
};
|
};
|
||||||
@ -366,11 +367,13 @@ Peer.prototype._onPacket = function onPacket(packet) {
|
|||||||
return this._handleGetAddr();
|
return this._handleGetAddr();
|
||||||
|
|
||||||
if (cmd === 'merkleblock' || cmd === 'block') {
|
if (cmd === 'merkleblock' || cmd === 'block') {
|
||||||
payload._network = true;
|
payload.network = true;
|
||||||
|
payload.relayedBy = this.address;
|
||||||
payload = bcoin.block(payload, cmd);
|
payload = bcoin.block(payload, cmd);
|
||||||
this.lastBlock = payload;
|
this.lastBlock = payload;
|
||||||
} else if (cmd === 'tx') {
|
} else if (cmd === 'tx') {
|
||||||
payload._network = true;
|
payload.network = true;
|
||||||
|
payload.relayedBy = this.address;
|
||||||
payload = bcoin.tx(payload, this.lastBlock);
|
payload = bcoin.tx(payload, this.lastBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -499,7 +499,7 @@ Pool.prototype.bestPeer = function bestPeer() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (best)
|
if (best)
|
||||||
this.emit('debug', 'Best peer: %s', best.socket.remoteAddress);
|
this.emit('debug', 'Best peer: %s', best.address);
|
||||||
|
|
||||||
return best;
|
return best;
|
||||||
};
|
};
|
||||||
|
|||||||
203
lib/bcoin/tx.js
203
lib/bcoin/tx.js
@ -29,11 +29,15 @@ function TX(data, block) {
|
|||||||
this.lock = data.lock || 0;
|
this.lock = data.lock || 0;
|
||||||
this.ts = data.ts || 0;
|
this.ts = data.ts || 0;
|
||||||
this.block = null;
|
this.block = null;
|
||||||
|
|
||||||
this._hash = null;
|
this._hash = null;
|
||||||
|
|
||||||
this._raw = data._raw || null;
|
this._raw = data._raw || null;
|
||||||
this._network = data._network || false;
|
|
||||||
this._size = data._size || 0;
|
this._size = data._size || 0;
|
||||||
|
|
||||||
|
this.network = data.network || false;
|
||||||
|
this.relayedBy = data.relayedBy || '0.0.0.0';
|
||||||
|
this._height = data._height != null ? data._height : -1;
|
||||||
|
|
||||||
this._lock = this.lock;
|
this._lock = this.lock;
|
||||||
|
|
||||||
if (data.inputs) {
|
if (data.inputs) {
|
||||||
@ -71,7 +75,7 @@ TX.prototype.hash = function hash(enc) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
TX.prototype.render = function render() {
|
TX.prototype.render = function render() {
|
||||||
if (this._network)
|
if (this.network)
|
||||||
return this._raw.slice();
|
return this._raw.slice();
|
||||||
return bcoin.protocol.framer.tx(this);
|
return bcoin.protocol.framer.tx(this);
|
||||||
};
|
};
|
||||||
@ -887,30 +891,64 @@ TX.prototype.inputAddrs = function inputAddrs() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
TX.getInputData = function getInputData(input) {
|
TX.getInputData = function getInputData(input) {
|
||||||
if (!input || !input.script) return;
|
if (!input || !input.script)
|
||||||
|
return;
|
||||||
|
|
||||||
var script = input.script;
|
var s = input.script;
|
||||||
var sig, pub, hash, addr, redeem, data, output;
|
var sig, pub, hash, addr, redeem, data, output;
|
||||||
|
|
||||||
if (bcoin.script.isPubkeyhashInput(script)) {
|
if (!input.out) {
|
||||||
sig = utils.toHex(script[0]);
|
return {
|
||||||
pub = script[1];
|
addr: 'Unknown',
|
||||||
|
hash: 'Unknown',
|
||||||
|
value: new bn(0),
|
||||||
|
script: s,
|
||||||
|
seq: input.seq,
|
||||||
|
none: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (+input.out.hash === 0) {
|
||||||
|
return {
|
||||||
|
addr: 'Coinbase',
|
||||||
|
hash: 'Coinbase',
|
||||||
|
value: new bn(0),
|
||||||
|
script: s,
|
||||||
|
seq: input.seq,
|
||||||
|
none: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.out.tx) {
|
||||||
|
output = input.out.tx.outputs[input.out.index];
|
||||||
|
return TX.getOutputData(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bcoin.script.isPubkeyhashInput(s)) {
|
||||||
|
sig = utils.toHex(s[0]);
|
||||||
|
pub = s[1];
|
||||||
hash = utils.ripesha(pub);
|
hash = utils.ripesha(pub);
|
||||||
addr = bcoin.wallet.hash2addr(hash);
|
addr = bcoin.wallet.hash2addr(hash);
|
||||||
return {
|
return {
|
||||||
sig: sig,
|
sig: sig,
|
||||||
pub: pub,
|
pub: pub,
|
||||||
hash: hash,
|
hash: hash,
|
||||||
addr: addr
|
addr: addr,
|
||||||
|
value: new bn(0),
|
||||||
|
script: s,
|
||||||
|
seq: input.seq
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bcoin.script.isScripthashInput(script)) {
|
if (bcoin.script.isScripthashInput(s)) {
|
||||||
pub = script[script.length - 1];
|
pub = s[s.length - 1];
|
||||||
hash = utils.ripesha(pub);
|
hash = utils.ripesha(pub);
|
||||||
addr = bcoin.wallet.hash2addr(hash, 'scripthash');
|
addr = bcoin.wallet.hash2addr(hash, 'scripthash');
|
||||||
redeem = bcoin.script.decode(pub);
|
redeem = bcoin.script.decode(pub);
|
||||||
data = TX.getOutputData({ script: redeem });
|
data = TX.getOutputData({
|
||||||
|
script: redeem,
|
||||||
|
value: new bn(0)
|
||||||
|
});
|
||||||
data.pub = pub;
|
data.pub = pub;
|
||||||
data.hash = hash;
|
data.hash = hash;
|
||||||
data.addr = addr;
|
data.addr = addr;
|
||||||
@ -923,49 +961,61 @@ TX.getInputData = function getInputData(input) {
|
|||||||
n: data.multisig.n,
|
n: data.multisig.n,
|
||||||
keys: data.multisig.keys,
|
keys: data.multisig.keys,
|
||||||
hashes: data.multisig.hashes,
|
hashes: data.multisig.hashes,
|
||||||
addrs: data.multisig.addrs
|
addrs: data.multisig.addrs,
|
||||||
|
script: redeem
|
||||||
};
|
};
|
||||||
|
data.script = s;
|
||||||
|
data.seq = input.seq;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!input.out.tx)
|
return {
|
||||||
return;
|
addr: 'Unknown',
|
||||||
|
hash: 'Unknown',
|
||||||
output = input.out.tx.outputs[input.out.index];
|
value: new bn(0),
|
||||||
|
script: s,
|
||||||
return TX.getOutputData(output);
|
seq: input.seq,
|
||||||
|
none: true
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
TX.getOutputData = function getOutputData(output) {
|
TX.getOutputData = function getOutputData(output) {
|
||||||
if (!output || !output.script) return;
|
if (!output || !output.script) return;
|
||||||
|
|
||||||
var script = output.script;
|
var s = output.script;
|
||||||
|
var lock = bcoin.script.lockTime(s);
|
||||||
var pub, hash, addr, pubs, ret;
|
var pub, hash, addr, pubs, ret;
|
||||||
|
|
||||||
if (bcoin.script.isPubkey(script)) {
|
if (bcoin.script.isPubkey(s)) {
|
||||||
pub = script[0];
|
pub = s[0];
|
||||||
hash = utils.ripesha(pub);
|
hash = utils.ripesha(pub);
|
||||||
addr = bcoin.wallet.hash2addr(hash);
|
addr = bcoin.wallet.hash2addr(hash);
|
||||||
return {
|
return {
|
||||||
sig: null,
|
sig: null,
|
||||||
pub: pub,
|
pub: pub,
|
||||||
hash: hash,
|
hash: hash,
|
||||||
addr: addr
|
addr: addr,
|
||||||
|
value: output.value,
|
||||||
|
script: s,
|
||||||
|
lock: lock
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bcoin.script.isPubkeyhash(script)) {
|
if (bcoin.script.isPubkeyhash(s)) {
|
||||||
hash = script[2];
|
hash = s[2];
|
||||||
addr = bcoin.wallet.hash2addr(hash);
|
addr = bcoin.wallet.hash2addr(hash);
|
||||||
return {
|
return {
|
||||||
sig: null,
|
sig: null,
|
||||||
pub: null,
|
pub: null,
|
||||||
hash: hash,
|
hash: hash,
|
||||||
addr: addr
|
addr: addr,
|
||||||
|
value: output.value,
|
||||||
|
script: s,
|
||||||
|
lock: lock
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pubs = bcoin.script.isMultisig(script);
|
pubs = bcoin.script.isMultisig(s);
|
||||||
if (pubs) {
|
if (pubs) {
|
||||||
hash = utils.ripesha(pubs[0]);
|
hash = utils.ripesha(pubs[0]);
|
||||||
addr = bcoin.wallet.hash2addr(hash);
|
addr = bcoin.wallet.hash2addr(hash);
|
||||||
@ -976,21 +1026,24 @@ TX.getOutputData = function getOutputData(output) {
|
|||||||
addr: addr,
|
addr: addr,
|
||||||
keys: pubs,
|
keys: pubs,
|
||||||
multisig: {
|
multisig: {
|
||||||
m: new bn(script[0]).toNumber(),
|
m: new bn(s[0]).toNumber(),
|
||||||
n: new bn(script[script.length - 2]).toNumber(),
|
n: new bn(s[s.length - 2]).toNumber(),
|
||||||
keys: keys,
|
keys: pubs,
|
||||||
hashes: keys.map(function(key) {
|
hashes: pubs.map(function(key) {
|
||||||
return utils.ripesha(key);
|
return utils.ripesha(key);
|
||||||
}),
|
}),
|
||||||
addrs: keys.map(function(key) {
|
addrs: pubs.map(function(key) {
|
||||||
var hash = utils.ripesha(key);
|
var hash = utils.ripesha(key);
|
||||||
return bcoin.wallet.hash2addr(hash);
|
return bcoin.wallet.hash2addr(hash);
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
|
value: output.value,
|
||||||
|
script: s,
|
||||||
|
lock: lock
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bcoin.script.isScripthash(script)) {
|
if (bcoin.script.isScripthash(s)) {
|
||||||
hash = utils.toHex(s[1]);
|
hash = utils.toHex(s[1]);
|
||||||
addr = bcoin.wallet.hash2addr(hash, 'scripthash');
|
addr = bcoin.wallet.hash2addr(hash, 'scripthash');
|
||||||
return {
|
return {
|
||||||
@ -1003,17 +1056,35 @@ TX.getOutputData = function getOutputData(output) {
|
|||||||
pub: null,
|
pub: null,
|
||||||
hash: hash,
|
hash: hash,
|
||||||
addr: addr
|
addr: addr
|
||||||
}
|
},
|
||||||
|
value: output.value,
|
||||||
|
script: s,
|
||||||
|
lock: lock
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bcoin.script.isColored(script)) {
|
if (bcoin.script.isColored(s)) {
|
||||||
ret = bcoin.script.colored(script);
|
ret = bcoin.script.colored(s);
|
||||||
return {
|
return {
|
||||||
|
addr: 'OP_RETURN',
|
||||||
|
hash: 'OP_RETURN',
|
||||||
data: ret,
|
data: ret,
|
||||||
text: utils.array2ascii(ret)
|
text: utils.array2ascii(ret),
|
||||||
|
value: output.value,
|
||||||
|
script: s,
|
||||||
|
lock: lock,
|
||||||
|
none: true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
addr: '[Unknown]',
|
||||||
|
hash: '[Unknown]',
|
||||||
|
value: new bn(0),
|
||||||
|
script: s,
|
||||||
|
lock: lock,
|
||||||
|
none: true
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
TX.prototype.getFee = function getFee() {
|
TX.prototype.getFee = function getFee() {
|
||||||
@ -1050,6 +1121,49 @@ TX.prototype.funds = function funds(side) {
|
|||||||
return acc;
|
return acc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TX.prototype.__defineSetter__('height', function(height) {
|
||||||
|
return this._height = height;
|
||||||
|
});
|
||||||
|
|
||||||
|
TX.prototype.__defineGetter__('height', function() {
|
||||||
|
return this.getHeight(bcoin.chain.global);
|
||||||
|
});
|
||||||
|
|
||||||
|
TX.prototype.__defineGetter__('confirmations', function() {
|
||||||
|
return this.getConfirmations(bcoin.chain.global);
|
||||||
|
});
|
||||||
|
|
||||||
|
TX.prototype.getHeight = function getHeight(chain) {
|
||||||
|
if (this._height >= 0)
|
||||||
|
return this._height;
|
||||||
|
|
||||||
|
chain = chain || bcoin.chain.global;
|
||||||
|
|
||||||
|
if (!chain)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
this._height = this.block ? chain.getHeight(this.block) : -1;
|
||||||
|
|
||||||
|
return this._height;
|
||||||
|
};
|
||||||
|
|
||||||
|
TX.prototype.getConfirmations = function getConfirmations(chain) {
|
||||||
|
var top, height;
|
||||||
|
|
||||||
|
chain = chain || bcoin.chain.global;
|
||||||
|
|
||||||
|
if (!chain)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
top = chain.index.heights[chain.index.heights.length - 1];
|
||||||
|
height = this.getHeight(chain);
|
||||||
|
|
||||||
|
if (height === -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return top - height + 1;
|
||||||
|
};
|
||||||
|
|
||||||
TX.prototype.toJSON = function toJSON() {
|
TX.prototype.toJSON = function toJSON() {
|
||||||
// Compact representation
|
// Compact representation
|
||||||
return {
|
return {
|
||||||
@ -1058,16 +1172,25 @@ TX.prototype.toJSON = function toJSON() {
|
|||||||
ts: this.ts,
|
ts: this.ts,
|
||||||
ps: this.ps,
|
ps: this.ps,
|
||||||
block: this.block,
|
block: this.block,
|
||||||
|
network: this.network,
|
||||||
|
relayedBy: this.relayedBy,
|
||||||
tx: utils.toHex(this.render())
|
tx: utils.toHex(this.render())
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
TX.fromJSON = function fromJSON(json) {
|
TX.fromJSON = function fromJSON(json) {
|
||||||
|
var raw, data, tx;
|
||||||
|
|
||||||
assert.equal(json.v, 1);
|
assert.equal(json.v, 1);
|
||||||
assert.equal(json.type, 'tx');
|
assert.equal(json.type, 'tx');
|
||||||
|
|
||||||
var raw = utils.toArray(json.tx, 'hex');
|
raw = utils.toArray(json.tx, 'hex');
|
||||||
var tx = new TX(new bcoin.protocol.parser().parseTX(raw));
|
data = new bcoin.protocol.parser().parseTX(raw);
|
||||||
|
|
||||||
|
data.network = json.network;
|
||||||
|
data.relayedBy = json.relayedBy;
|
||||||
|
|
||||||
|
tx = new TX(data);
|
||||||
tx.ts = json.ts;
|
tx.ts = json.ts;
|
||||||
tx.block = json.block || null;
|
tx.block = json.block || null;
|
||||||
tx.ps = json.ps;
|
tx.ps = json.ps;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user