coins and coinview.
This commit is contained in:
parent
6d5e277629
commit
cf9a62a75b
@ -95,6 +95,8 @@ bcoin.script = require('./bcoin/script');
|
|||||||
bcoin.input = require('./bcoin/input');
|
bcoin.input = require('./bcoin/input');
|
||||||
bcoin.output = require('./bcoin/output');
|
bcoin.output = require('./bcoin/output');
|
||||||
bcoin.coin = require('./bcoin/coin');
|
bcoin.coin = require('./bcoin/coin');
|
||||||
|
bcoin.coins = require('./bcoin/coins');
|
||||||
|
bcoin.coinview = require('./bcoin/coinview');
|
||||||
bcoin.tx = require('./bcoin/tx');
|
bcoin.tx = require('./bcoin/tx');
|
||||||
bcoin.mtx = require('./bcoin/mtx');
|
bcoin.mtx = require('./bcoin/mtx');
|
||||||
bcoin.ldb = require('./bcoin/ldb');
|
bcoin.ldb = require('./bcoin/ldb');
|
||||||
|
|||||||
@ -271,6 +271,21 @@ Block.reward = function reward(height) {
|
|||||||
return reward;
|
return reward;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Block.prototype.getPrevout = function getPrevout() {
|
||||||
|
var prevout = {};
|
||||||
|
|
||||||
|
this.txs.forEach(function(tx) {
|
||||||
|
if (tx.isCoinbase())
|
||||||
|
return;
|
||||||
|
|
||||||
|
tx.inputs.forEach(function(input) {
|
||||||
|
prevout[input.prevout.hash] = true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return Object.keys(prevout);
|
||||||
|
};
|
||||||
|
|
||||||
Block.prototype.inspect = function inspect() {
|
Block.prototype.inspect = function inspect() {
|
||||||
return {
|
return {
|
||||||
type: this.type,
|
type: this.type,
|
||||||
|
|||||||
197
lib/bcoin/coins.js
Normal file
197
lib/bcoin/coins.js
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
/**
|
||||||
|
* coins.js - coins object for bcoin
|
||||||
|
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
|
||||||
|
* https://github.com/indutny/bcoin
|
||||||
|
*/
|
||||||
|
|
||||||
|
var bcoin = require('../bcoin');
|
||||||
|
var utils = bcoin.utils;
|
||||||
|
var assert = utils.assert;
|
||||||
|
var constants = bcoin.protocol.constants;
|
||||||
|
var BufferReader = require('./reader');
|
||||||
|
var BufferWriter = require('./writer');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Coins
|
||||||
|
*/
|
||||||
|
|
||||||
|
function Coins(options, hash) {
|
||||||
|
if (!(this instanceof Coins))
|
||||||
|
return new Coins(options, hash);
|
||||||
|
|
||||||
|
if (Buffer.isBuffer(hash))
|
||||||
|
hash = utils.toHex(hash);
|
||||||
|
|
||||||
|
this.version = options.version;
|
||||||
|
this.height = options.height;
|
||||||
|
|
||||||
|
this.coinbase = options.isCoinbase
|
||||||
|
? options.isCoinbase()
|
||||||
|
: options.coinbase;
|
||||||
|
|
||||||
|
this.hash = hash;
|
||||||
|
|
||||||
|
this.outputs = options.outputs.map(function(coin, i) {
|
||||||
|
if (!coin)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (coin instanceof bcoin.coin)
|
||||||
|
return coin;
|
||||||
|
|
||||||
|
coin = utils.merge({}, coin);
|
||||||
|
coin.version = options.version;
|
||||||
|
coin.height = options.height;
|
||||||
|
coin.hash = hash;
|
||||||
|
coin.index = i;
|
||||||
|
coin.coinbase = this.coinbase;
|
||||||
|
|
||||||
|
return new bcoin.coin(coin);
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Coins.prototype.add = function add(tx, i) {
|
||||||
|
var coin;
|
||||||
|
|
||||||
|
if (i == null) {
|
||||||
|
coin = tx;
|
||||||
|
this.outputs[coin.index] = coin;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.outputs[i] = new bcoin.coin(tx, i);
|
||||||
|
};
|
||||||
|
|
||||||
|
Coins.prototype.has = function has(index) {
|
||||||
|
return this.outputs[index] != null;
|
||||||
|
};
|
||||||
|
|
||||||
|
Coins.prototype.get = function get(index) {
|
||||||
|
return this.outputs[index];
|
||||||
|
};
|
||||||
|
|
||||||
|
Coins.prototype.remove = function remove(index) {
|
||||||
|
if (index < this.outputs.length)
|
||||||
|
this.outputs[index] = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
Coins.prototype.spend = function spend(hash, index) {
|
||||||
|
var coin = this.get(hash, index);
|
||||||
|
this.remove(hash, index);
|
||||||
|
return coin;
|
||||||
|
};
|
||||||
|
|
||||||
|
Coins.prototype.fill = function fill(tx, spend) {
|
||||||
|
var res = true;
|
||||||
|
var i, input;
|
||||||
|
|
||||||
|
if (tx.txs)
|
||||||
|
tx = tx.txs;
|
||||||
|
|
||||||
|
if (Array.isArray(tx)) {
|
||||||
|
for (i = 0; i < tx.length; i++) {
|
||||||
|
if (!this.fill(tx[i]))
|
||||||
|
res = false;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < tx.inputs.length; i++) {
|
||||||
|
input = tx.inputs[i];
|
||||||
|
|
||||||
|
if (input.prevout.hash !== this.hash)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!input.output) {
|
||||||
|
if (spend)
|
||||||
|
input.output = this.spend(input.prevout.index);
|
||||||
|
else
|
||||||
|
input.output = this.get(input.prevout.index);
|
||||||
|
|
||||||
|
if (!input.output)
|
||||||
|
res = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
Coins.prototype.count = function count(index) {
|
||||||
|
return this.outputs.reduce(function(total, output) {
|
||||||
|
if (!output)
|
||||||
|
return total;
|
||||||
|
return total + 1;
|
||||||
|
}, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
Coins.prototype.forEach = function forEach(callback, context) {
|
||||||
|
this.outputs.forEach(function(output, i) {
|
||||||
|
callback.call(context || this, output, i);
|
||||||
|
}, this);
|
||||||
|
};
|
||||||
|
|
||||||
|
Coins.prototype.toRaw = function toRaw() {
|
||||||
|
return Coins.toRaw(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
Coins.fromTX = function fromTX(tx) {
|
||||||
|
return new Coins(tx, tx.hash('hex'));
|
||||||
|
};
|
||||||
|
|
||||||
|
Coins.toRaw = function toRaw(tx) {
|
||||||
|
var p = new BufferWriter();
|
||||||
|
var height = tx.height;
|
||||||
|
|
||||||
|
if (height === -1)
|
||||||
|
height = 0x7fffffff;
|
||||||
|
|
||||||
|
p.writeU32(tx.version);
|
||||||
|
p.writeU32(height);
|
||||||
|
p.writeU8(tx.coinbase ? 1 : 0);
|
||||||
|
p.writeUIntv(tx.outputs.length);
|
||||||
|
|
||||||
|
tx.outputs.forEach(function(output) {
|
||||||
|
if (!output) {
|
||||||
|
p.writeUIntv(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p.writeVarBytes(bcoin.protocol.framer.output(output));
|
||||||
|
});
|
||||||
|
|
||||||
|
return p.render();
|
||||||
|
};
|
||||||
|
|
||||||
|
Coins._fromRaw = function _fromRaw(buf) {
|
||||||
|
var tx = { outputs: [] };
|
||||||
|
var p = new BufferReader(buf);
|
||||||
|
var coinCount, i, coin;
|
||||||
|
|
||||||
|
tx.version = p.readU32();
|
||||||
|
tx.height = p.readU32();
|
||||||
|
tx.coinbase = p.readU8() === 1;
|
||||||
|
|
||||||
|
if (tx.height === 0x7fffffff)
|
||||||
|
tx.height = -1;
|
||||||
|
|
||||||
|
coinCount = p.readUIntv();
|
||||||
|
for (i = 0; i < coinCount; i++) {
|
||||||
|
coin = p.readVarBytes();
|
||||||
|
if (coin.length === 0) {
|
||||||
|
tx.outputs.push(null);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
coin = bcoin.protocol.parser.parseOutput(coin);
|
||||||
|
tx.outputs.push(coin);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx;
|
||||||
|
};
|
||||||
|
|
||||||
|
Coins.fromRaw = function fromRaw(buf, hash) {
|
||||||
|
return new Coins(Coins._fromRaw(buf), hash);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expose
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = Coins;
|
||||||
104
lib/bcoin/coinview.js
Normal file
104
lib/bcoin/coinview.js
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/**
|
||||||
|
* coinview.js - coinview object for bcoin
|
||||||
|
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
|
||||||
|
* https://github.com/indutny/bcoin
|
||||||
|
*/
|
||||||
|
|
||||||
|
var bcoin = require('../bcoin');
|
||||||
|
var utils = bcoin.utils;
|
||||||
|
var assert = utils.assert;
|
||||||
|
var constants = bcoin.protocol.constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CoinView
|
||||||
|
*/
|
||||||
|
|
||||||
|
function CoinView(coins) {
|
||||||
|
if (!(this instanceof CoinView))
|
||||||
|
return new CoinView(coins);
|
||||||
|
|
||||||
|
this.coins = coins || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
CoinView.prototype.add = function add(tx, i) {
|
||||||
|
var coin, hash;
|
||||||
|
|
||||||
|
if (i == null) {
|
||||||
|
coin = tx;
|
||||||
|
this.coins[coin.hash] = coin;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hash = tx.hash('hex');
|
||||||
|
|
||||||
|
if (!this.coins[hash]) {
|
||||||
|
this.coins[hash] = Object.create(bcoin.coins.prototype);
|
||||||
|
this.coins[hash].version = tx.version;
|
||||||
|
this.coins[hash].height = tx.height;
|
||||||
|
this.coins[hash].coinbase = tx.isCoinbase();
|
||||||
|
this.coins[hash].hash = hash;
|
||||||
|
this.coins[hash].outputs = new Array(tx.outputs.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.coins[hash].add(tx, i);
|
||||||
|
};
|
||||||
|
|
||||||
|
CoinView.prototype.get = function get(hash, index) {
|
||||||
|
if (!this.coins[hash])
|
||||||
|
return;
|
||||||
|
|
||||||
|
return this.coins[hash].get(index);
|
||||||
|
};
|
||||||
|
|
||||||
|
CoinView.prototype.count = function count(hash) {
|
||||||
|
if (!this.coins[hash])
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return this.coins[hash].count();
|
||||||
|
};
|
||||||
|
|
||||||
|
CoinView.prototype.has = function has(hash, index) {
|
||||||
|
if (!this.coins[hash])
|
||||||
|
return;
|
||||||
|
|
||||||
|
return this.coins[hash].has(index);
|
||||||
|
};
|
||||||
|
|
||||||
|
CoinView.prototype.remove = function remove(hash, index) {
|
||||||
|
if (!this.coins[hash])
|
||||||
|
return;
|
||||||
|
|
||||||
|
return this.coins[hash].remove(index);
|
||||||
|
};
|
||||||
|
|
||||||
|
CoinView.prototype.spend = function spend(hash, index) {
|
||||||
|
if (!this.coins[hash])
|
||||||
|
return;
|
||||||
|
|
||||||
|
return this.coins[hash].spend(index);
|
||||||
|
};
|
||||||
|
|
||||||
|
CoinView.prototype.fill = function fill(obj, spend) {
|
||||||
|
var keys = Object.keys(this.coins);
|
||||||
|
var res = true;
|
||||||
|
var i;
|
||||||
|
|
||||||
|
for (i = 0; i < keys.length; i++) {
|
||||||
|
if (!this.coins[keys[i]].fill(obj, spend))
|
||||||
|
res = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
CoinView.prototype.toArray = function toArray() {
|
||||||
|
return Object.keys(this.coins).map(function(hash) {
|
||||||
|
return this.coins[hash];
|
||||||
|
}, this);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expose
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = CoinView;
|
||||||
@ -1065,6 +1065,19 @@ TX.prototype.__defineGetter__('priority', function() {
|
|||||||
return this.getPriority();
|
return this.getPriority();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
TX.prototype.getPrevout = function getPrevout() {
|
||||||
|
var prevout = {};
|
||||||
|
|
||||||
|
if (this.isCoinbase())
|
||||||
|
return [];
|
||||||
|
|
||||||
|
this.inputs.forEach(function(input) {
|
||||||
|
prevout[input.prevout.hash] = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return Object.keys(prevout);
|
||||||
|
};
|
||||||
|
|
||||||
TX.prototype.inspect = function inspect() {
|
TX.prototype.inspect = function inspect() {
|
||||||
return {
|
return {
|
||||||
type: this.type,
|
type: this.type,
|
||||||
@ -1242,6 +1255,10 @@ TX.fromExtended = function fromExtended(buf, saveCoins) {
|
|||||||
return new TX(TX._fromExtended(buf, saveCoins));
|
return new TX(TX._fromExtended(buf, saveCoins));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TX.prototype.toCoins = function toCoins() {
|
||||||
|
return bcoin.coins.fromTX(this);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expose
|
* Expose
|
||||||
*/
|
*/
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user