api: rename methods, properties. add legacy support.

This commit is contained in:
Christopher Jeffrey 2016-02-01 11:39:38 -08:00
parent 0e57bb36ff
commit 6ad621cace
13 changed files with 362 additions and 274 deletions

140
README.md
View File

@ -99,7 +99,7 @@ pool.on('watched', function(tx, peer) {
// Look for balance changes
wallet.on('balance', function() {
utils.print('Wallet balance updated: %s', utils.btc(wallet.balance()));
utils.print('Wallet balance updated: %s', utils.btc(wallet.getBalance()));
});
// Start the getheaders sync
@ -135,7 +135,7 @@ fs.writeFileSync(process.env.HOME + '/my-new-wallet.json',
var tx = bcoin.tx();
// Add an output, send some money to our new wallet
tx.output({
tx.addOutput({
address: receiver.getAddress(),
// Every satoshi value in bcoin is
// a big number, so we can convert
@ -148,8 +148,8 @@ tx.output({
// Fill the transaction inputs with the
// necessary unspents (hopefully we have them!).
tx.fillUnspent(
wallet.unspent(), // Our unspents to choose from
tx.fill(
wallet.getUnspent(), // Our unspents to choose from
wallet.getAddress(), // Our change address (warning: address re-use)
null // We could put a hard fee here, but lets let bcoin figure it out
);
@ -252,7 +252,7 @@ utils.assert(buyer.getScriptAddress() === mediator.getScriptAddress());
utils.print('Created 2-of-3 wallet with address: %s', buyer.getScriptAddress());
// Create a fake coinbase for buyer to use as his funds
var coinbase = bcoin.tx().output(buyer.getKeyAddress(), utils.satoshi('50.0'));
var coinbase = bcoin.tx().addOutput(buyer.getKeyAddress(), utils.satoshi('50.0'));
buyer.addTX(coinbase);
// Now let's create a tx as the buyer.
@ -261,13 +261,14 @@ var btx = bcoin.tx();
// Send 25 BTC to the shared wallet
// to buy something from seller.
btx.output({
btx.addOutput({
address: buyer.getScriptAddress(),
value: utils.satoshi('25.0')
});
// Fill the unspents and sign
buyer.fillUnspent(btx);
if (!buyer.fill(btx))
throw new Error('Not enough funds');
buyer.sign(btx);
// Buyer sends his funds to the 2-of-3 wallet
@ -280,7 +281,7 @@ seller.addTX(btx);
var stx = bcoin.tx();
// Seller wants to send the BTC to himself
stx.output({
stx.addOutput({
address: seller.getKeyAddress(),
value: utils.satoshi('25.0')
// Subtract the fee
@ -291,13 +292,13 @@ stx.output({
// Give the mediator a little something,
// since he's such a cool guy.
stx.output({
stx.addOutput({
address: mediator.getKeyAddress(),
value: utils.satoshi('1.0')
});
// Add the buyer's utxo as the input
stx.input(btx, 0);
stx.addInput(btx, 0);
// Add _one_ signature to the tx
seller.sign(stx);
@ -329,7 +330,7 @@ and human-writable. For example, a standard pay-to-pubkey script would look
like:
``` js
tx.output({
tx.addOutput({
value: new bn(100000),
script: [
'dup',
@ -347,9 +348,9 @@ prefixes removed. Pushdata ops are represented with Arrays.
The above script could be redeemed with:
``` js
tx2.input({
out: { tx: tx, hash: tx.hash('hex'), index: 0 },
seq: 0xffffffff,
tx2.addInput({
prevout: { tx: tx, hash: tx.hash('hex'), index: 0 },
sequence: 0xffffffff,
script: [
signature, // Byte Array
publicKey // Byte Array
@ -408,14 +409,14 @@ var wallet = bcoin.wallet({
]
});
console.log(wallet.getScriptAddress());
var tx1 = bcoin.tx().output(wallet.getScriptAddress(), new bn(100000));
var tx1 = bcoin.tx().addOutput(wallet.getScriptAddress(), new bn(100000));
```
Which would be redeemed with:
``` js
tx2.input({
out: { tx: tx1, hash: tx1.hash('hex'), index: 0 },
tx2.addInput({
prevout: { tx: tx1, hash: tx1.hash('hex'), index: 0 },
script: [
2,
// Redeem script:
@ -437,7 +438,7 @@ var bn = bcoin.bn;
...
// Add an output with 100,000 satoshis as a value.
tx.output(wallet.getKeyAddress(), new bn(100000));
tx.addOutput(wallet.getKeyAddress(), new bn(100000));
```
To make this easier to deal with, bcoin has two helper functions: `utils.btc()`
@ -642,6 +643,7 @@ Subtype can be `block`, `merkleblock`, or `header`.
validation will fail.
- __isGenesis()__ - Returns true if block is the genesis block of the network.
before the reference node.
- __getSize()__ - Return block size in bytes.
- __getHeight()__ - Returns height in the blockchain. Returns `-1` if block is
not present in the chain.
node.
@ -933,7 +935,7 @@ Usage: `bcoin.input([options])`
- __out.hash__ - Previous output's txid as a hex string.
- __out.index__ - Previous output's index.
- __script__ - Array of opcodes.
- __seq__ - Input's nSequence, `0xffffffff` by default.
- __sequence__ - Input's nSequence, `0xffffffff` by default.
##### Properties:
@ -968,8 +970,8 @@ which parse the script and grab the previous output data and cache it as
- __scriptaddress__ - The p2sh address.
- __m__ - `m` value (required signatures).
- __n__ - `n` value (number of keys).
- __lock__ - The OP_CHECKLOCKTIMEVERIFY locktime if present (NOTE: This will only
grab the first value and not deal with OP_IF statements, etc).
- __lockTime__ - The OP_CHECKLOCKTIMEVERIFY locktime if present (NOTE: This
will only grab the first value and not deal with OP_IF statements, etc).
- __flags__ - Coinbase flags if present.
- __text__ - Coinbase flags converted to UTF-8, if present.
- __output__ - Previous Output object.
@ -1034,8 +1036,8 @@ script and cache it as `_data`.
- __scriptaddress__ - The p2sh address.
- __m__ - `m` value (required signatures).
- __n__ - `n` value (number of keys).
- __lock__ - The OP_CHECKLOCKTIMEVERIFY locktime if present (NOTE: This will only
grab the first value and not deal with OP_IF statements, etc).
- __lockTime__ - The OP_CHECKLOCKTIMEVERIFY locktime if present (NOTE: This
will only grab the first value and not deal with OP_IF statements, etc).
- __flags__ - `nulldata` data.
- __text__ - `nulldata` data converted to UTF-8.
@ -1406,10 +1408,10 @@ Usage: `bcoin.txPool(wallet)`
- Inherits all from EventEmitter.
- __add(tx)__ - Add TX to the pool.
- __all()__ - Return all TXes in the pool owned by wallet.
- __unspent()__ - Return all TXes with unspent outputs, owned by wallet.
- __pending()__ - Return all 0-confirmation transactions.
- __balance()__ - Return total balance of TX pool.
- __getAll()__ - Return all TXes in the pool owned by wallet.
- __getUnspent()__ - Return all TXes with unspent outputs, owned by wallet.
- __getPending()__ - Return all 0-confirmation transactions.
- __getBalance()__ - Return total balance of TX pool.
- __toJSON()__ - Return TX pool in serialized JSON format.
- __fromJSON()__ - Load TX pool from serialized JSON format.
@ -1427,9 +1429,9 @@ Usage: `bcoin.tx([options], [block])`
##### Options:
- __version__ - Transaction version (default: 1).
- __inputs__ - Array of input objects with `tx.input()` options.
- __outputs__ - Array of output objects with `tx.output()` options.
- __lock__ - nLockTime value.
- __inputs__ - Array of input objects with `tx.addInput()` options.
- __outputs__ - Array of output objects with `tx.addOutput()` options.
- __lockTime__ - nLockTime value.
- __ts__ - Timestamp (set by `block` if passed in arguments - spv-mode).
- __block__ - Block hash (Set by `block` if passed in arguments - spv-mode).
- __network__ - Should be `true` if TX came in from the network.
@ -1468,34 +1470,35 @@ Usage: `bcoin.tx([options], [block])`
- __render([force])__ - Serialize transaction. Returns raw byte array. Will
return raw data passed in from the network if available. Set `force=true` to
force serialization.
- __size()__ - Return serializzed transaction size in bytes.
- __input(options)__ - Add an input to the transaction. Options can be an Input
object (see above), in the form of an Input object (containing properties
`out.tx`, `out.hash`, `out.index`, `script`, and `seq`).
- `input()` can handle many different arguments in the forms of:
- `tx.input(tx, index)`
- `tx.input(txHash, index)`
- `tx.input(input)`
- `tx.input({ hash: hash, index: index })`
- `tx.input({ tx: tx, index: index })`
- __getSize()__ - Return serializzed transaction size in bytes.
- __addInput(options)__ - Add an input to the transaction. Options can be an
Input object (see above), in the form of an Input object (containing
properties `prevout.tx`, `prevout.hash`, `prevout.index`, `script`, and
`sequence`).
- `addInput()` can handle many different arguments in the forms of:
- `tx.addInput(tx, index)`
- `tx.addInput(txHash, index)`
- `tx.addInput(input)`
- `tx.addInput({ hash: hash, index: index })`
- `tx.addInput({ tx: tx, index: index })`
- __scriptInput(index/input, pub, redeem)__ - Initialize the input scripts
based on previous output script type. `n` signatures will be added.
Signatures will be null dummies (empty signature slots) until `signInput()`
is called. `pub` (the public key) and `redeem` (raw redeem script) should
always be passed in if there is a pubkeyhash or scripthash output being
redeemed. Will not overwrite existing input scripts.
- __signature(index/input, key, [type])__ - Create a signature for the desired
input using `key` as the private key and `type` as the sighash type. Sighash
type can be a number or a string (`all`, `single`, or `none`). Returns a DER
signature byte array.
- __createSignature(index/input, key, [type])__ - Create a signature for the
desired input using `key` as the private key and `type` as the sighash type.
Sighash type can be a number or a string (`all`, `single`, or `none`).
Returns a DER signature byte array.
- __signInput(index/input, key, [type])__ - Sign the desired input and place
the signature in an empty signature slot. Finalize the input script and
reduce signature slots to `m` once the minimum amount of signatures has been
reached.
- __scriptSig(index/input, key, pub, redeem, type)__ - Execute `scriptInput`
_and_ `signInput`.
- __output(options), output(output), output(address, value)__ - Add an output to the
transaction.
- __addOutput(options), addOutput(output), addOutput(address, value)__ - Add an
output to the transaction.
- `options` can be in the form of:
{
@ -1507,11 +1510,11 @@ Usage: `bcoin.tx([options], [block])`
n: [n value],
flags: [nulldata],
scripthash: [true or false],
lock: [locktime for checklocktimeverify]
lockTime: [locktime for checklocktimeverify]
}
- __scriptOutput(index/output, options)__ - Compile an output script for the
output based on the same options `output()` handles.
output based on the same options `addOutput()` handles.
- __signatureHash(index/input, s, type)__ - Return the to-be-signed hash of the
transaction for the desired input. Must pass in previous output subscript as
`s`, as well as the sighash type (number or string of `all`, `none`, or
@ -1525,9 +1528,9 @@ Usage: `bcoin.tx([options], [block])`
- __isCoinbase()__ - Returns true if TX is a coinbase.
- __maxSize()__ - Estimate the size of the transaction in bytes (works before
input scripts are compiled and signed). Useful for fee calculation.
- __getUnspent(unspent, changeAddress, [fee])__ - Determine which unspents to
- __getInputs(unspent, changeAddress, [fee])__ - Determine which unspents to
use from `unspent` (an array of possible unspents, usually returned by
`wallet.unspent()`). Calculates the fee and chooses unspents based on the
`wallet.getUnspent()`). Calculates the fee and chooses unspents based on the
total value required for the transaction. A hard `fee` can be passed in
(satoshis/big number) which will skip the fee calculation. Calculates the
necessary change. Returns an object in the form of:
@ -1542,22 +1545,22 @@ Usage: `bcoin.tx([options], [block])`
}
`inputs` will be `null` if not enough funds were available.
__NOTE:__ `getUnspent()` should only be called once all outputs have been added.
- __fillUnspent(unspent, [changeAddress], [fee])__ - Calls `getUnspent()` and
__NOTE:__ `getInputs()` should only be called once all outputs have been added.
- __fill(unspent, [changeAddress], [fee])__ - Calls `getInputs()` and
adds the created inputs to the transaction. Adds a change output if
necessary. Returns the same result value as `getUnspent()`. __NOTE:__ Should
necessary. Returns the same result value as `getInputs()`. __NOTE:__ Should
only be called once all outputs have been added.
- __getFee()__ - Returns the fee for transaction.
- __funds(side)__ - Returns the total funds for a side of the transaction
`'in'` or `'out'`.
- __setLockTime(lock)__ - Sets a locktime for the transaction. Will set the
- __getFunds(side)__ - Returns the total funds for a side of the transaction
`'input'` or `'output'`.
- __setLockTime(lockTime)__ - Sets a locktime for the transaction. Will set the
nSequences accordingly.
- __increaseFee(fee)__ - Increase fee to a hard fee. Opts transaction in for
replace-by-fee. __NOTE:__ Transaction must be rescripted and resigned before
broadcasting.
- __fill(wallet/txpool/object)__ - Fills all the transaction's inputs with the
appropriate previous outputs using the available transactions in a wallet,
txpool, or an object with txids as its keys and txs as its values.
- __fillPrevout(wallet/txpool/object)__ - Fills all the transaction's inputs
with the appropriate previous outputs using the available transactions in a
wallet, txpool, or an object with txids as its keys and txs as its values.
- __isFull()__ - Returns true if the TX has all previous output references.
- __isFinal(height, ts)__ - Mimics the bitcoind `IsFinalTx()` function. Checks
the locktime and input sequences. Returns true or false.
@ -1616,7 +1619,7 @@ Usage: `bcoin.wallet(options)`
##### Events:
- __balance(balance)__ - Emitted when balance is updated. `balance` is in
- __getBalance(balance)__ - Emitted when balance is updated. `balance` is in
satoshis (big number).
- __tx(tx)__ - Emitted when a TX is added to the wallet's TXPool.
- __load(ts)__ - Emitted when the TXPool is finished loading. `ts` is the
@ -1646,9 +1649,10 @@ Usage: `bcoin.wallet(options)`
this wallet. If `index` is not present, all outputs will be tested.
- __ownInput(tx, [index])__ - Check to see if input at `index` pertains to
this wallet. If `index` is not present, all inputs will be tested.
- __fillUnspent(tx, [changeAddress], [fee])__ - Fill tx with inputs necessary
for total output value. Uses `wallet.unspent()` as the unspent list.
- __fillTX(tx)__ - "Fill" a transactions' inputs with references to its
- __fill(tx, [changeAddress], [fee])__ - Fill tx with inputs necessary for
total output value. Uses `wallet.getUnspent()` as the unspent list. Returns true
if successfully filled necessary funds.
- __fillPrevout(tx)__ - "Fill" a transactions' inputs with references to its
previous outputs if available.
- __scriptInputs(tx)__ - Compile necessary scripts for inputs (with OP_0 where
the signatures should be). Will not overwrite existing input scripts.
@ -1657,13 +1661,11 @@ Usage: `bcoin.wallet(options)`
- __sign(tx)__ - Equivalent to calling both `scriptInputs(tx)` and
`signInputs(tx)` in one go.
- __addTX(tx)__ - Add a transaction to the wallet's TXPool.
- __all()__ - Returns all transactions from the TXPool.
- __unspent()__ - Returns all TXes with unspent outputs from the TXPool.
- __pending()__ - Returns all TXes in the TXPool that have yet to be included
- __getAll()__ - Returns all transactions from the TXPool.
- __getUnspent()__ - Returns all TXes with unspent outputs from the TXPool.
- __getPending()__ - Returns all TXes in the TXPool that have yet to be included
in a block.
- __balance()__ - Returns total balance of the TXPool.
- __fill(tx)__ - Attempt to `fillUnspent(tx)`. Return `null` if failed to reach
total output value. Return `tx` if successful.
- __getBalance()__ - Returns total balance of the TXPool.
- __toAddress()__ - Return blockchain-explorer-like data in the format of:
{

View File

@ -128,10 +128,13 @@ Block.prototype.render = function render() {
return bcoin.protocol.framer.block(this, this.subtype);
};
Block.prototype.size = function size() {
Block.prototype.getSize = function getSize() {
return this._size || this.render().length;
};
// Legacy
Block.prototype.size = Block.prototype.getSize;
Block.prototype.hasTX = function hasTX(hash) {
return this.tx.indexOf(hash) !== -1;
};
@ -255,7 +258,7 @@ Block.prototype._verify = function _verify() {
// Size can't be bigger than MAX_BLOCK_SIZE
if (this.txs.length > constants.block.maxSize
|| this.size() > constants.block.maxSize) {
|| this.getSize() > constants.block.maxSize) {
utils.debug('Block is too large: %s', this.rhash);
return false;
}
@ -456,10 +459,10 @@ Block.prototype.verifyContext = function verifyContext() {
// We need the previous output in order
// to verify the script.
if (!input.out.tx)
if (!input.prevout.tx)
continue;
assert(input.out.tx);
assert(input.prevout.tx);
// Verify the script
if (!tx.verify(j, true, flags)) {
@ -468,7 +471,7 @@ Block.prototype.verifyContext = function verifyContext() {
}
// Ensure tx is not double spending an output
// if (this.chain.isSpent(input.out.hash, input.out.index)) {
// if (this.chain.isSpent(input.prevout.hash, input.prevout.index)) {
// utils.debug('Block is using spent inputs: %s', this.rhash);
// return false;
// }

View File

@ -519,7 +519,7 @@ Chain.prototype.hashRange = function hashRange(start, end) {
return hashes;
};
Chain.prototype.locatorHashes = function locatorHashes(start) {
Chain.prototype.getLocator = function getLocator(start) {
var hashes = [];
var top = this.height();
var step = 1;

View File

@ -14,25 +14,50 @@ var constants = bcoin.protocol.constants;
*/
function Input(options) {
var prevout;
if (!(this instanceof Input))
return new Input(options);
this.out = {
tx: options.out.tx || null,
hash: options.out.hash,
index: options.out.index
prevout = options.prevout || options.out;
this.prevout = {
tx: prevout.tx || null,
hash: prevout.hash,
index: prevout.index
};
if (typeof this.out.hash !== 'string')
this.out.hash = utils.toHex(this.out.hash);
if (utils.isBuffer(this.prevout.hash))
this.prevout.hash = utils.toHex(this.prevout.hash);
this.script = options.script ? options.script.slice() : [];
this.seq = options.seq === undefined ? 0xffffffff : options.seq;
this.sequence = options.sequence == null ? 0xffffffff : options.sequence;
// Legacy
if (options.seq != null)
this.sequence = options.seq;
if (options.script && options.script._raw)
utils.hidden(this.script, '_raw', options.script._raw);
}
// Legacy
Input.prototype.__defineSetter__('seq', function(sequence) {
return this.sequence = sequence;
});
Input.prototype.__defineGetter__('seq', function() {
return this.sequence;
});
Input.prototype.__defineSetter__('out', function(prevout) {
return this.prevout = prevout;
});
Input.prototype.__defineGetter__('out', function() {
return this.prevout;
});
Input.prototype.__defineGetter__('data', function() {
var data;
@ -41,7 +66,7 @@ Input.prototype.__defineGetter__('data', function() {
data = Input.getData(this);
if (this.script.length && this.out.tx)
if (this.script.length && this.prevout.tx)
utils.hidden(this, '_data', data);
return data;
@ -107,10 +132,10 @@ Input.prototype.__defineGetter__('n', function() {
return this.data.n || this.m;
});
Input.prototype.__defineGetter__('lock', function() {
Input.prototype.__defineGetter__('lockTime', function() {
if (!this.output)
return 0;
return this.output.lock;
return this.output.lockTime;
});
Input.prototype.__defineGetter__('flags', function() {
@ -122,9 +147,9 @@ Input.prototype.__defineGetter__('text', function() {
});
Input.prototype.__defineGetter__('output', function() {
if (!this.out.tx)
if (!this.prevout.tx)
return;
return this.out.tx.outputs[this.out.index];
return this.prevout.tx.outputs[this.prevout.index];
});
Input.prototype.__defineGetter__('value', function() {
@ -134,7 +159,7 @@ Input.prototype.__defineGetter__('value', function() {
});
Input.prototype.__defineGetter__('tx', function() {
return this.out.tx;
return this.prevout.tx;
});
Input.prototype.__defineGetter__('addr', function() {
@ -182,7 +207,7 @@ Input.prototype.__defineGetter__('scriptaddr', function() {
// height: Number,
// flags: Array,
// text: String,
// lock: Number,
// lockTime: Number,
// value: bn,
// script: Array,
// seq: Number,
@ -204,12 +229,12 @@ Input.getData = function getData(input) {
seq: input.seq
};
if (input.out) {
def.prev = input.out.hash;
def.index = input.out.index;
if (input.prevout) {
def.prev = input.prevout.hash;
def.index = input.prevout.index;
}
if (input.out && +input.out.hash === 0) {
if (input.prevout && +input.prevout.hash === 0) {
data = bcoin.script.getCoinbaseData(input.script);
return utils.merge(def, data, {
type: 'coinbase',
@ -217,8 +242,8 @@ Input.getData = function getData(input) {
});
}
if (input.out && input.out.tx) {
output = input.out.tx.outputs[input.out.index];
if (input.prevout && input.prevout.tx) {
output = input.prevout.tx.outputs[input.prevout.index];
if (output) {
data = bcoin.script.getInputData(input.script, output.script);
data.value = output.value;
@ -229,6 +254,10 @@ Input.getData = function getData(input) {
return utils.merge(def, bcoin.script.getInputData(input.script));
};
Input.prototype.isFinal = function isFinal() {
return this.sequence === 0xffffffff;
};
Input.prototype.getID = function getID() {
var data = bcoin.script.encode(this.script);
var hash = utils.toHex(utils.ripesha(data));
@ -240,9 +269,9 @@ Input.prototype.inspect = function inspect() {
? this.output.inspect()
: { type: 'unknown', value: '0.0' };
output.hash = this.out.hash;
output.rhash = utils.revHex(this.out.hash);
output.index = this.out.index;
output.hash = this.prevout.hash;
output.rhash = utils.revHex(this.prevout.hash);
output.index = this.prevout.index;
return {
type: this.type,
@ -254,7 +283,7 @@ Input.prototype.inspect = function inspect() {
scriptaddress: this.scriptaddress,
signatures: this.signatures.map(utils.toHex),
text: this.text,
lock: this.lock,
lockTime: this.lockTime,
value: utils.btc(output.value),
script: bcoin.script.format(this.script)[0],
redeem: this.redeem ? bcoin.script.format(this.redeem)[0] : null,

View File

@ -142,7 +142,7 @@ Miner.prototype.addTX = function addTX(tx) {
var full, ts;
full = this.index.inputs.every(function(input) {
return !!input.out.tx;
return !!input.prevout.tx;
});
// Cannot calculate fee if we don't have the prev_out.
@ -200,7 +200,7 @@ Miner.prototype.createBlock = function createBlock(tx) {
coinbase = bcoin.tx();
coinbase.input({
out: {
prevout: {
hash: utils.toHex(constants.zeroHash),
index: 0xffffffff
},
@ -226,7 +226,7 @@ Miner.prototype.createBlock = function createBlock(tx) {
if (script.size(coinbase.inputs[0].script) > 100)
throw new Error('Coinbase script is too large');
coinbase.output({
coinbase.addOutput({
address: this.address,
value: new bn(0)
});

View File

@ -105,7 +105,7 @@ Output.prototype.__defineGetter__('n', function() {
return this.data.n || this.m;
});
Output.prototype.__defineGetter__('lock', function() {
Output.prototype.__defineGetter__('lockTime', function() {
return bcoin.script.getLockTime(this.script);
});
@ -162,7 +162,7 @@ Output.prototype.__defineGetter__('scriptaddr', function() {
// height: Number,
// flags: Array,
// text: String,
// lock: Number,
// lockTime: Number,
// value: bn,
// script: Array,
// seq: Number,
@ -203,7 +203,7 @@ Output.prototype.inspect = function inspect() {
m: this.m,
n: this.n,
text: this.text,
lock: this.lock,
lockTime: this.lockTime,
value: utils.btc(this.value),
script: bcoin.script.format(this.script)[0]
};

View File

@ -1008,7 +1008,7 @@ Pool.prototype.isWatched = function(tx, bloom) {
// 4. Test data elements in input scripts
for (i = 0; i < tx.inputs.length; i++) {
input = tx.inputs[i];
prev = input.out.hash;
prev = input.prevout.hash;
if (typeof prev === 'string')
prev = utils.toArray(prev, 'hex');
@ -1018,8 +1018,8 @@ Pool.prototype.isWatched = function(tx, bloom) {
return true;
// Test the prev_out script
if (input.out.tx) {
prev = input.out.tx.outputs[input.out.index];
if (input.prevout.tx) {
prev = input.prevout.tx.outputs[input.prevout.index];
if (testScript(prev.script))
return true;
}

View File

@ -280,14 +280,14 @@ Framer.tx = function tx(tx) {
for (i = 0; i < tx.inputs.length; i++) {
input = tx.inputs[i];
off += utils.copy(utils.toArray(input.out.hash, 'hex'), p, off, true);
off += utils.writeU32(p, input.out.index, off);
off += utils.copy(utils.toArray(input.prevout.hash, 'hex'), p, off, true);
off += utils.writeU32(p, input.prevout.index, off);
s = bcoin.script.encode(input.script);
off += utils.writeIntv(p, s.length, off);
off += utils.copy(s, p, off, true);
off += utils.writeU32(p, input.seq, off);
off += utils.writeU32(p, input.sequence, off);
}
off += utils.writeIntv(p, tx.outputs.length, off);
@ -301,7 +301,7 @@ Framer.tx = function tx(tx) {
off += utils.writeIntv(p, s.length, off);
off += utils.copy(s, p, off, true);
}
off += utils.writeU32(p, tx.lock, off);
off += utils.writeU32(p, tx.lockTime, off);
return p;
};

View File

@ -373,12 +373,12 @@ Parser.prototype.parseTXIn = function parseTXIn(p) {
return {
size: off + scriptLen + 4,
out: {
prevout: {
hash: utils.toArray(p.slice(0, 32)),
index: utils.readU32(p, 32)
},
script: bcoin.script.decode(utils.toArray(p.slice(off, off + scriptLen))),
seq: utils.readU32(p, off + scriptLen)
sequence: utils.readU32(p, off + scriptLen)
};
};
@ -461,7 +461,7 @@ Parser.prototype.parseTX = function parseTX(p) {
version: utils.read32(p, 0),
inputs: txIn,
outputs: txOut,
lock: utils.readU32(p, off),
lockTime: utils.readU32(p, off),
_off: off + 4,
_size: p.length
};

View File

@ -386,7 +386,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
var key, sig, type, subscript, hash;
var keys, i, j, m;
var succ;
var lock, threshold;
var lockTime, threshold;
var evalScript;
stack.alt = stack.alt || [];
@ -934,28 +934,28 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
if (!tx || stack.length === 0)
return false;
lock = stack[stack.length - 1];
lockTime = stack[stack.length - 1];
if (!Array.isArray(lock))
if (!Array.isArray(lockTime))
return false;
if (lock.length > 6)
if (lockTime.length > 6)
return false;
lock = script.num(lock, true);
lockTime = script.num(lockTime, true);
if (lock < 0)
if (lockTime < 0)
return false;
threshold = constants.locktimeThreshold;
if (!(
(tx.lock < threshold && lock < threshold)
|| (tx.lock >= threshold && lock >= threshold)
(tx.lockTime < threshold && lockTime < threshold)
|| (tx.lockTime >= threshold && lockTime >= threshold)
)) {
return false;
}
if (lock > tx.lock)
if (lockTime > tx.lockTime)
return false;
if (!tx.inputs[index] || tx.inputs[index].seq === 0xffffffff)
@ -1312,7 +1312,7 @@ script.getInputData = function getData(s, prev) {
};
script._getInputData = function _getInputData(s, type) {
var sig, key, hash, raw, redeem, lock, hash, address, input, output;
var sig, key, hash, raw, redeem, lockTime, hash, address, input, output;
assert(typeof type === 'string');
@ -1355,7 +1355,7 @@ script._getInputData = function _getInputData(s, type) {
if (type === 'scripthash') {
raw = s[s.length - 1];
redeem = script.decode(raw);
lock = script.getLockTime(redeem);
lockTime = script.getLockTime(redeem);
hash = bcoin.wallet.key2hash(raw);
address = bcoin.wallet.hash2addr(hash, 'scripthash');
output = script.getOutputData(script.getSubscript(redeem));
@ -1368,7 +1368,7 @@ script._getInputData = function _getInputData(s, type) {
redeem: redeem,
scripthash: hash,
scriptaddress: address,
lock: lock
lockTime: lockTime
});
}
@ -2063,8 +2063,8 @@ script.format = function format(input, output) {
scripts.push(output);
} else if (input) {
scripts.push(input.script);
if (input.out.tx && input.out.tx.outputs[input.out.index]) {
prev = input.out.tx.outputs[input.out.index].script;
if (input.prevout.tx && input.prevout.tx.outputs[input.prevout.index]) {
prev = input.prevout.tx.outputs[input.prevout.index].script;
scripts.push(prev);
if (script.isScripthash(prev)) {
redeem = script.decode(input.script[input.script.length - 1]);

View File

@ -93,20 +93,20 @@ TXPool.prototype.add = function add(tx, noWrite) {
// Consume unspent money or add orphans
for (i = 0; i < tx.inputs.length; i++) {
input = tx.inputs[i];
key = input.out.hash + '/' + input.out.index;
key = input.prevout.hash + '/' + input.prevout.index;
unspent = this._unspent[key];
if (!input.out.tx && this._all[input.out.hash])
input.out.tx = this._all[input.out.hash];
if (!input.prevout.tx && this._all[input.prevout.hash])
input.prevout.tx = this._all[input.prevout.hash];
if (unspent) {
// Add TX to inputs and spend money
index = tx._inputIndex(unspent.tx.hash('hex'), unspent.index);
assert(index !== -1);
assert(tx.inputs[index] === input);
assert(tx.inputs[index].out.hash === unspent.tx.hash('hex'));
assert(tx.inputs[index].out.index === unspent.index);
input.out.tx = unspent.tx;
assert(tx.inputs[index].prevout.hash === unspent.tx.hash('hex'));
assert(tx.inputs[index].prevout.index === unspent.index);
input.prevout.tx = unspent.tx;
// Skip invalid transactions
if (!tx.verify(index))
@ -123,13 +123,13 @@ TXPool.prototype.add = function add(tx, noWrite) {
// signature checking code to ownInput for p2sh and p2pk,
// we could in theory use ownInput here (and down below)
// instead.
if (input.out.tx) {
if (!this._wallet.ownOutput(input.out.tx, input.out.index))
if (input.prevout.tx) {
if (!this._wallet.ownOutput(input.prevout.tx, input.prevout.index))
continue;
}
// Add orphan, if no parent transaction is yet known
orphan = { tx: tx, index: input.out.index };
orphan = { tx: tx, index: input.prevout.index };
if (this._orphans[key])
this._orphans[key].push(orphan);
else
@ -149,9 +149,9 @@ TXPool.prototype.add = function add(tx, noWrite) {
function checkOrphan(orphan) {
var index = orphan.tx._inputIndex(tx.hash('hex'), orphan.index);
assert(index !== -1);
assert(orphan.tx.inputs[index].out.hash === tx.hash('hex'));
assert(orphan.tx.inputs[index].out.index === i);
orphan.tx.inputs[index].out.tx = tx;
assert(orphan.tx.inputs[index].prevout.hash === tx.hash('hex'));
assert(orphan.tx.inputs[index].prevout.index === i);
orphan.tx.inputs[index].prevout.tx = tx;
// Verify that input script is correct, if not - add output to unspent
// and remove orphan from storage
@ -225,7 +225,7 @@ TXPool.prototype._removeTX = function _removeTX(tx, noWrite) {
});
};
TXPool.prototype.all = function all() {
TXPool.prototype.getAll = function getAll() {
return Object.keys(this._all).map(function(key) {
return this._all[key];
}, this).filter(function(tx) {
@ -234,7 +234,7 @@ TXPool.prototype.all = function all() {
}, this);
};
TXPool.prototype.unspent = function unspent() {
TXPool.prototype.getUnspent = function getUnspent() {
return Object.keys(this._unspent).map(function(key) {
return this._unspent[key];
}, this).filter(function(item) {
@ -246,7 +246,7 @@ TXPool.prototype.hasUnspent = function hasUnspent(hash, unspent) {
var has;
if (utils.isBuffer(hash) && hash.length && typeof hash[0] !== 'number') {
unspent = this.unspent();
unspent = this.getUnspent();
has = hash.map(function(hash) {
var h = this.hasUnspent(hash, unspent);
if (!h)
@ -260,14 +260,14 @@ TXPool.prototype.hasUnspent = function hasUnspent(hash, unspent) {
if (utils.isBuffer(hash))
hash = utils.toHex(hash);
else if (hash.out)
hash = hash.out.hash;
else if (hash.prevout)
hash = hash.prevout.hash;
else if (hash.tx)
hash = hash.tx.hash('hex');
else if (hash instanceof bcoin.tx)
hash = hash.hash('hex');
unspent = unspent || this.unspent();
unspent = unspent || this.getUnspent();
has = unspent.filter(function(item) {
return item.tx.hash('hex') === hash;
@ -279,7 +279,7 @@ TXPool.prototype.hasUnspent = function hasUnspent(hash, unspent) {
return has;
};
TXPool.prototype.pending = function pending() {
TXPool.prototype.getPending = function getPending() {
return Object.keys(this._all).map(function(key) {
return this._all[key];
}, this).filter(function(tx) {
@ -287,9 +287,9 @@ TXPool.prototype.pending = function pending() {
});
};
TXPool.prototype.balance = function balance() {
TXPool.prototype.getBalance = function getBalance() {
var acc = new bn(0);
var unspent = this.unspent();
var unspent = this.getUnspent();
if (unspent.length === 0)
return acc;
@ -298,6 +298,12 @@ TXPool.prototype.balance = function balance() {
}, acc);
};
// Legacy
TXPool.prototype.all = TXPool.prototype.getAll;
TXPool.prototype.unspent = TXPool.prototype.getUnspent;
TXPool.prototype.pending = TXPool.prototype.getPending;
TXPool.prototype.balance = TXPool.prototype.getBalance;
TXPool.prototype.toJSON = function toJSON() {
return {
v: 1,

View File

@ -26,11 +26,15 @@ function TX(data, block) {
this.version = data.version || 1;
this.inputs = [];
this.outputs = [];
this.lock = data.lock || 0;
this.lockTime = data.lockTime || 0;
this.ts = data.ts || 0;
this.block = data.block || null;
this._hash = null;
// Legacy
if (data.lock != null)
this.lockTime = data.lock;
this._raw = data._raw || null;
this._size = data._size || 0;
@ -42,14 +46,14 @@ function TX(data, block) {
if (data.inputs) {
assert(this.inputs.length === 0);
data.inputs.forEach(function(input) {
this.input(input);
this.addInput(input);
}, this);
}
if (data.outputs) {
assert(this.outputs.length === 0);
data.outputs.forEach(function(output) {
this.output(output);
this.addOutput(output);
}, this);
}
@ -65,15 +69,25 @@ function TX(data, block) {
this.subtractFee = data.subtractFee || null;
this.changeAddress = data.changeAddress || null;
this.changeIndex = data.changeIndex != null ? data.changeIndex : -1;
this.total = data.total || null;
// ps = Pending Since
this.ps = this.ts === 0 ? utils.now() : 0;
// Discourage fee snipping a la bitcoind
// if (data.lock == null)
// this._avoidFeeSnipping();
// if (data.lockTime == null && data.lock == null)
// this.avoidFeeSnipping();
}
// Legacy
TX.prototype.__defineSetter__('lock', function(lockTime) {
return this.lockTime = lockTime;
});
TX.prototype.__defineGetter__('lock', function() {
return this.lockTime;
});
TX.prototype.clone = function clone() {
return new TX(this);
};
@ -89,22 +103,26 @@ TX.prototype.render = function render(force) {
return bcoin.protocol.framer.tx(this);
};
TX.prototype.size = function size() {
TX.prototype.getSize = function getSize() {
return this._size || this.render().length;
};
TX.prototype.input = function input(i, index) {
this._input(i, index);
TX.prototype.size = TX.prototype.getSize;
TX.prototype.addInput = function addInput(i, index) {
this._addInput(i, index);
return this;
};
// tx._input(tx, index)
// tx._input(hash, index)
// tx._input(input)
// tx._input({ hash: hash, index: index })
// tx._input({ tx: tx, index: index })
TX.prototype._input = function _input(obj, index) {
var options, hash, input, ex, i;
TX.prototype.input = TX.prototype.addInput;
// tx._addInput(tx, index)
// tx._addInput(hash, index)
// tx._addInput(input)
// tx._addInput({ hash: hash, index: index })
// tx._addInput({ tx: tx, index: index })
TX.prototype._addInput = function _addInput(obj, index) {
var options, hash, input, ex, i, prevout;
if (obj instanceof TX)
options = { tx: obj, index: index };
@ -113,10 +131,12 @@ TX.prototype._input = function _input(obj, index) {
else
options = obj;
prevout = options.prevout || options.out;
if (options.tx)
hash = options.tx.hash('hex');
else if (options.out)
hash = options.out.hash;
else if (prevout)
hash = prevout.hash;
else
hash = options.hash;
@ -125,21 +145,21 @@ TX.prototype._input = function _input(obj, index) {
input = bcoin.input({
tx: this,
out: {
tx: options.out ? options.out.tx : options.tx,
prevout: {
tx: prevout ? prevout.tx : options.tx,
hash: hash,
index: options.out ? options.out.index : options.index
index: prevout ? prevout.index : options.index
},
script: options.script,
seq: options.seq
sequence: options.sequence || options.seq
});
// Try modifying existing input first
i = this._inputIndex(input.out.hash, input.out.index);
i = this._inputIndex(input.prevout.hash, input.prevout.index);
if (i !== -1) {
ex = this.inputs[i];
input.out.tx = input.out.tx || ex.out.tx;
input.seq = input.seq || ex.seq;
input.prevout.tx = input.prevout.tx || ex.prevout.tx;
input.sequence = input.sequence || ex.sequence;
input.script = input.script.length ? input.script : ex.script;
this.inputs[i] = input;
} else {
@ -150,6 +170,8 @@ TX.prototype._input = function _input(obj, index) {
return i;
};
TX.prototype._input = TX.prototype._addInput;
TX.prototype._inputIndex = function _inputIndex(hash, index) {
var i, ex;
@ -158,7 +180,7 @@ TX.prototype._inputIndex = function _inputIndex(hash, index) {
for (i = 0; i < this.inputs.length; i++) {
ex = this.inputs[i];
if (ex.out.hash === hash && ex.out.index === index)
if (ex.prevout.hash === hash && ex.prevout.index === index)
return i;
}
@ -176,14 +198,14 @@ TX.prototype.scriptInput = function scriptInput(index, pub, redeem) {
assert(input);
// We should have previous outputs by now.
assert(input.out.tx);
assert(input.prevout.tx);
// Already has a script template (at least)
if (input.script.length)
return;
// Get the previous output's subscript
s = input.out.tx.getSubscript(input.out.index);
s = input.prevout.tx.getSubscript(input.prevout.index);
// P2SH
if (bcoin.script.isScripthash(s)) {
@ -236,7 +258,7 @@ TX.prototype.scriptInput = function scriptInput(index, pub, redeem) {
}
};
TX.prototype.signature = function signature(index, key, type) {
TX.prototype.createSignature = function createSignature(index, key, type) {
var input, s, hash, signature;
if (typeof index !== 'number')
@ -253,10 +275,10 @@ TX.prototype.signature = function signature(index, key, type) {
assert(input);
// We should have previous outputs by now.
assert(input.out.tx);
assert(input.prevout.tx);
// Get the previous output's subscript
s = input.out.tx.getSubscript(input.out.index);
s = input.prevout.tx.getSubscript(input.prevout.index);
// We need to grab the redeem script when
// signing p2sh transactions.
@ -278,6 +300,9 @@ TX.prototype.signature = function signature(index, key, type) {
return signature;
};
// Legacy
TX.prototype.signature = TX.prototype.createSignature;
// Sign the now-built scriptSigs
TX.prototype.signInput = function signInput(index, key, type) {
var input, s, hash, signature;
@ -291,13 +316,13 @@ TX.prototype.signInput = function signInput(index, key, type) {
assert(input);
// We should have previous outputs by now.
assert(input.out.tx);
assert(input.prevout.tx);
// Create our signature.
signature = this.signature(index, key, type);
signature = this.createSignature(index, key, type);
// Get the previous output's subscript
s = input.out.tx.getSubscript(input.out.index);
s = input.prevout.tx.getSubscript(input.prevout.index);
// Script length, needed for multisig
len = input.script.length;
@ -484,7 +509,7 @@ TX.prototype.scriptSig = function scriptSig(index, key, pub, redeem, type) {
return input.script;
};
TX.prototype.output = function output(obj, value) {
TX.prototype.addOutput = function addOutput(obj, value) {
var options, output;
if (obj instanceof bcoin.wallet)
@ -512,7 +537,8 @@ TX.prototype.output = function output(obj, value) {
return this;
};
TX.prototype.out = TX.prototype.output;
TX.prototype.out = TX.prototype.addOutput;
TX.prototype.output = TX.prototype.addOutput;
TX.prototype.scriptOutput = function scriptOutput(index, options) {
var output, script, keys, m, n, hash, flags;
@ -618,9 +644,9 @@ TX.prototype.scriptOutput = function scriptOutput(index, options) {
// P2SH Transaction
// hash160 [hash] eq
if (options.scripthash) {
if (options.lock != null) {
if (options.lockTime != null) {
script = [
bcoin.script.array(options.lock),
bcoin.script.array(options.lockTime),
'checklocktimeverify',
'drop',
'codeseparator'
@ -648,7 +674,7 @@ TX.prototype.signatureHash = function signatureHash(index, s, type) {
if (!Array.isArray(s)) {
type = s;
s = this.inputs[index].out.tx.getSubscript(this.inputs[index].out.index);
s = this.inputs[index].prevout.tx.getSubscript(this.inputs[index].prevout.index);
if (bcoin.script.isScripthash(s)) {
s = this.inputs[index].script[this.inputs[index.script.length - 1]];
s = bcoin.script.getSubscript(bcoin.script.decode(s));
@ -687,7 +713,7 @@ TX.prototype.signatureHash = function signatureHash(index, s, type) {
// Allow input sequence updates for other inputs.
for (i = 0; i < copy.inputs.length; i++) {
if (i !== index)
copy.inputs[i].seq = 0;
copy.inputs[i].sequence = 0;
}
} else if ((type & 0x1f) === constants.hashType.single) {
// Bitcoind used to return 1 as an error code:
@ -709,7 +735,7 @@ TX.prototype.signatureHash = function signatureHash(index, s, type) {
// Allow input sequence updates for other inputs.
for (i = 0; i < copy.inputs.length; i++) {
if (i !== index)
copy.inputs[i].seq = 0;
copy.inputs[i].sequence = 0;
}
}
@ -761,15 +787,15 @@ TX.prototype.verify = function verify(index, force, flags) {
if (index != null && index !== i)
return true;
if (!input.out.tx)
if (!input.prevout.tx)
return false;
// Somethis is very wrong if this is
// not the case.
assert.equal(input.out.tx.hash('hex'), input.out.hash);
assert.equal(input.prevout.tx.hash('hex'), input.prevout.hash);
// Grab the previous output.
output = input.out.tx.outputs[input.out.index];
output = input.prevout.tx.outputs[input.prevout.index];
// Transaction is referencing an output
// that does not exist.
@ -777,7 +803,7 @@ TX.prototype.verify = function verify(index, force, flags) {
return false;
// Transaction cannot reference itself.
if (input.out.hash === this.hash('hex'))
if (input.prevout.hash === this.hash('hex'))
return false;
return bcoin.script.verify(input.script, output.script, this, i, flags);
@ -785,7 +811,7 @@ TX.prototype.verify = function verify(index, force, flags) {
};
TX.prototype.isCoinbase = function isCoinbase() {
return this.inputs.length === 1 && +this.inputs[0].out.hash === 0;
return this.inputs.length === 1 && +this.inputs[0].prevout.hash === 0;
};
TX.prototype.maxSize = function maxSize() {
@ -804,7 +830,7 @@ TX.prototype.maxSize = function maxSize() {
size = 0;
// Get the previous output's subscript
s = input.out.tx.getSubscript(input.out.index);
s = input.prevout.tx.getSubscript(input.prevout.index);
// If we have access to the redeem script,
// we can use it to calculate size much easier.
@ -888,9 +914,9 @@ TX.prototype.maxSize = function maxSize() {
return total;
};
TX.prototype.getUnspent = function getUnspent(unspent, address, fee) {
TX.prototype.getInputs = function getInputs(unspent, address, fee) {
var tx = this.clone();
var cost = tx.funds('out');
var cost = tx.getFunds('output');
var totalkb = 1;
var total = cost.addn(constants.tx.fee);
var inputs = [];
@ -906,10 +932,10 @@ TX.prototype.getUnspent = function getUnspent(unspent, address, fee) {
// Add new inputs until TX will have enough
// funds to cover both minimum post cost
// and fee.
var index = tx._input(unspent);
var index = tx._addInput(unspent);
inputs.push(tx.inputs[index]);
lastAdded++;
return tx.funds('in').cmp(total) < 0;
return tx.getFunds('input').cmp(total) < 0;
}
// Transfer `total` funds maximum.
@ -918,7 +944,7 @@ TX.prototype.getUnspent = function getUnspent(unspent, address, fee) {
if (!fee) {
// Add dummy output (for `change`) to
// calculate maximum TX size.
tx.output({
tx.addOutput({
address: address,
value: new bn(0)
});
@ -931,7 +957,7 @@ TX.prototype.getUnspent = function getUnspent(unspent, address, fee) {
// break;
// }
// }
// total = tx.funds('out');
// total = tx.getFunds('output');
// }
// Change fee value if it is more than 1024
@ -945,17 +971,17 @@ TX.prototype.getUnspent = function getUnspent(unspent, address, fee) {
totalkb += newkb;
// Failed to get enough funds, add more inputs.
if (tx.funds('in').cmp(total) < 0)
if (tx.getFunds('input').cmp(total) < 0)
unspent.slice(lastAdded).every(addInput);
} while (tx.funds('in').cmp(total) < 0 && lastAdded < unspent.length);
} while (tx.getFunds('input').cmp(total) < 0 && lastAdded < unspent.length);
}
if (tx.funds('in').cmp(total) < 0) {
if (tx.getFunds('input').cmp(total) < 0) {
// Still failing to get enough funds.
inputs = null;
} else {
// How much money is left after filling outputs.
change = tx.funds('in').sub(total);
change = tx.getFunds('input').sub(total);
}
// Return necessary inputs and change.
@ -969,7 +995,7 @@ TX.prototype.getUnspent = function getUnspent(unspent, address, fee) {
};
};
TX.prototype.fillUnspent = function fillUnspent(unspent, address, fee) {
TX.prototype.fill = function fill(unspent, address, fee) {
var result;
if (unspent)
@ -983,13 +1009,15 @@ TX.prototype.fillUnspent = function fillUnspent(unspent, address, fee) {
assert(this.changeAddress);
result = this.getUnspent(this.unspent, this.changeAddress, this.hardFee);
result = this.getInputs(this.unspent, this.changeAddress, this.hardFee);
this.total = result.total;
if (!result.inputs)
return result;
result.inputs.forEach(function(input) {
this.input(input);
this.addInput(input);
}, this);
if (result.change.cmpn(constants.tx.dust) < 0) {
@ -1000,7 +1028,7 @@ TX.prototype.fillUnspent = function fillUnspent(unspent, address, fee) {
);
this.changeIndex = -1;
} else {
this.output({
this.addOutput({
address: this.changeAddress,
value: result.change
});
@ -1011,6 +1039,10 @@ TX.prototype.fillUnspent = function fillUnspent(unspent, address, fee) {
return result;
};
// Legacy
TX.prototype.fillUnspent = TX.prototype.fill;
TX.prototype.fillInputs = TX.prototype.fill;
TX.prototype._recalculateFee = function recalculateFee() {
var output = this.outputs[this.changeIndex];
var size, real, fee;
@ -1019,7 +1051,7 @@ TX.prototype._recalculateFee = function recalculateFee() {
return;
if (!output) {
this.output({
this.addOutput({
address: this.changeAddress,
value: new bn(0)
});
@ -1060,26 +1092,26 @@ TX.prototype._recalculateFee = function recalculateFee() {
};
TX.prototype.getFee = function getFee() {
if (this.funds('in').cmp(this.funds('out')) < 0)
if (this.getFunds('input').cmp(this.getFunds('output')) < 0)
return new bn(0);
return this.funds('in').sub(this.funds('out'));
return this.getFunds('input').sub(this.getFunds('output'));
};
TX.prototype.funds = function funds(side) {
TX.prototype.getFunds = function getFunds(side) {
var acc = new bn(0);
var inputs;
if (side === 'in') {
if (side === 'in' || side === 'input') {
inputs = this.inputs.filter(function(input) {
return input.out.tx;
return input.prevout.tx;
});
if (inputs.length === 0)
return acc;
inputs.reduce(function(acc, input) {
return acc.iadd(input.out.tx.outputs[input.out.index].value);
return acc.iadd(input.prevout.tx.outputs[input.prevout.index].value);
}, acc);
return acc;
@ -1096,25 +1128,28 @@ TX.prototype.funds = function funds(side) {
return acc;
};
TX.prototype._avoidFeeSnipping = function _avoidFeeSnipping() {
// Legacy
TX.prototype.funds = TX.prototype.getFunds;
TX.prototype.avoidFeeSnipping = function avoidFeeSnipping() {
if (!this.chain)
return;
this.lock = this.chain.height();
this.lockTime = this.chain.height();
if ((Math.random() * 10 | 0) === 0)
this.lock = Math.max(0, this.lock - (Math.random() * 100 | 0));
this.lockTime = Math.max(0, this.lockTime - (Math.random() * 100 | 0));
};
TX.prototype.setLockTime = function setLockTime(lock) {
TX.prototype.setLockTime = function setLockTime(lockTime) {
var i, input;
this.lock = lock;
this.lockTime = lockTime;
for (i = 0; i < this.inputs.length; i++) {
input = this.inputs[i];
if (input.seq === 0xffffffff)
input.seq = 0;
if (input.sequence === 0xffffffff)
input.sequence = 0;
}
};
@ -1122,11 +1157,11 @@ TX.prototype.increaseFee = function increaseFee(fee) {
var i, input;
this.hardFee = fee || this.getFee().add(new bn(10000));
this.fillUnspent();
this.fill();
for (i = 0; i < this.inputs.length; i++) {
input = this.inputs[i];
input.seq = 0xffffffff - 1;
input.sequence = 0xffffffff - 1;
}
};
@ -1134,11 +1169,11 @@ TX.prototype.isFull = function isFull() {
if (this.inputs.length === 0)
return false;
return this.inputs.every(function(input) {
return !!input.out.tx;
return !!input.prevout.tx;
});
};
TX.prototype.fill = function fill(txs) {
TX.prototype.fillPrevout = function fillPrevout(txs) {
var inputs;
if (txs instanceof bcoin.txPool)
@ -1154,9 +1189,9 @@ TX.prototype.fill = function fill(txs) {
}
inputs = this.inputs.filter(function(input) {
if (!input.out.tx && txs[input.out.hash])
input.out.tx = txs[input.out.hash];
return !!input.out.tx;
if (!input.prevout.tx && txs[input.prevout.hash])
input.prevout.tx = txs[input.prevout.hash];
return !!input.prevout.tx;
}, this);
return inputs.length === this.inputs.length;
@ -1206,14 +1241,14 @@ TX.prototype.isFinal = function isFinal(height, ts) {
if (!this.chain)
return true;
if (this.lock === 0)
if (this.lockTime === 0)
return true;
if (this.lock < (this.lock < threshold ? height : ts))
if (this.lockTime < (this.lockTime < threshold ? height : ts))
return true;
for (i = 0; i < this.inputs.length; i++) {
if (this.inputs[i].seq !== 0xffffffff)
if (this.inputs[i].sequence !== 0xffffffff)
return false;
}
@ -1290,10 +1325,10 @@ TX.prototype.isStandardInputs = function isStandardInputs(flags) {
for (i = 0; i < this.inputs.length; i++) {
input = this.inputs[i];
if (!input.out.tx)
if (!input.prevout.tx)
return false;
prev = input.out.tx.outputs[input.out.index];
prev = input.prevout.tx.outputs[input.prevout.index];
if (!prev)
return false;
@ -1347,11 +1382,11 @@ TX.prototype.getPriority = function getPriority() {
for (i = 0; i < this.inputs.length; i++) {
input = this.inputs[i];
if (!input.out.tx)
if (!input.prevout.tx)
return constants.tx.freeThreshold.clone();
output = input.out.tx.outputs[input.out.index];
age = input.out.tx.getConfirmations();
output = input.prevout.tx.outputs[input.prevout.index];
age = input.prevout.tx.getConfirmations();
if (age === -1)
age = 0;
@ -1399,7 +1434,7 @@ TX.prototype.getConfirmations = function getConfirmations() {
};
TX.prototype.getValue = function getValue() {
return this.funds('out');
return this.getFunds('output');
};
TX.prototype.__defineGetter__('chain', function() {

View File

@ -148,7 +148,7 @@ Wallet.prototype._init = function init() {
// Notify owners about new accepted transactions
this.tx.on('update', function(lastTs, tx) {
var b = this.balance();
var b = this.getBalance();
if (prevBalance && prevBalance.cmp(b) !== 0)
self.emit('balance', b);
self.emit('update', tx);
@ -453,8 +453,8 @@ Wallet.prototype.ownInput = function ownInput(tx, index) {
var inputs = tx.inputs.filter(function(input, i) {
var s;
if (!input.out.tx && this.tx._all[input.out.hash])
input.out.tx = this.tx._all[input.out.hash];
if (!input.prevout.tx && this.tx._all[input.prevout.hash])
input.prevout.tx = this.tx._all[input.prevout.hash];
if (index != null && index !== i)
return false;
@ -473,10 +473,10 @@ Wallet.prototype.ownInput = function ownInput(tx, index) {
return true;
}
if (!input.out.tx)
if (!input.prevout.tx)
return false;
s = input.out.tx.getSubscript(input.out.index);
s = input.prevout.tx.getSubscript(input.prevout.index);
if (bcoin.script.isPubkey(s, key))
return true;
@ -501,27 +501,41 @@ Wallet.prototype.ownInput = function ownInput(tx, index) {
return inputs;
};
Wallet.prototype.fillUnspent = function fillUnspent(tx, address, fee) {
Wallet.prototype.fill = function fill(tx, address, fee) {
var result;
if (!address)
address = this.changeAddress || this.getAddress();
return tx.fillUnspent(this.unspent(), address, fee);
result = tx.fill(this.getUnspent(), address, fee);
if (!result.inputs)
return false;
return true;
};
Wallet.prototype.fillTX = function fillTX(tx) {
return tx.fill(this);
// Legacy
Wallet.prototype.fillUnspent = Wallet.prototype.fill;
Wallet.prototype.fillInputs = Wallet.prototype.fill;
Wallet.prototype.fillPrevout = function fillPrevout(tx) {
return tx.fillPrevout(this);
};
// Legacy
Wallet.prototype.fillTX = Wallet.prototype.fillPrevout;
Wallet.prototype.scriptInputs = function scriptInputs(tx) {
var pub = this.getPublicKey();
var redeem = this.getScript();
var inputs = tx.inputs;
inputs = inputs.filter(function(input, i) {
if (!input.out.tx && this.tx._all[input.out.hash])
input.out.tx = this.tx._all[input.out.hash];
if (!input.prevout.tx && this.tx._all[input.prevout.hash])
input.prevout.tx = this.tx._all[input.prevout.hash];
if (!input.out.tx || !this.ownOutput(input.out.tx))
if (!input.prevout.tx || !this.ownOutput(input.prevout.tx))
return false;
tx.scriptInput(i, pub, redeem);
@ -537,10 +551,10 @@ Wallet.prototype.signInputs = function signInputs(tx, type) {
var inputs = tx.inputs;
inputs = inputs.filter(function(input, i) {
if (!input.out.tx && this.tx._all[input.out.hash])
input.out.tx = this.tx._all[input.out.hash];
if (!input.prevout.tx && this.tx._all[input.prevout.hash])
input.prevout.tx = this.tx._all[input.prevout.hash];
if (!input.out.tx || !this.ownOutput(input.out.tx))
if (!input.prevout.tx || !this.ownOutput(input.prevout.tx))
return false;
tx.signInput(i, key, type);
@ -559,11 +573,11 @@ Wallet.prototype.sign = function sign(tx, type) {
// Add signature script to each input
inputs = inputs.filter(function(input, i) {
if (!input.out.tx && this.tx._all[input.out.hash])
input.out.tx = this.tx._all[input.out.hash];
if (!input.prevout.tx && this.tx._all[input.prevout.hash])
input.prevout.tx = this.tx._all[input.prevout.hash];
// Filter inputs that this wallet own
if (!input.out.tx || !this.ownOutput(input.out.tx))
if (!input.prevout.tx || !this.ownOutput(input.prevout.tx))
return false;
tx.scriptSig(i, key, pub, redeem, type);
@ -578,28 +592,27 @@ Wallet.prototype.addTX = function addTX(tx, block) {
return this.tx.add(tx);
};
Wallet.prototype.all = function all() {
return this.tx.all();
Wallet.prototype.getAll = function getAll() {
return this.tx.getAll();
};
Wallet.prototype.unspent = function unspent() {
return this.tx.unspent();
Wallet.prototype.getUnspent = function getUnspent() {
return this.tx.getUnspent();
};
Wallet.prototype.pending = function pending() {
return this.tx.pending();
Wallet.prototype.getPending = function getPending() {
return this.tx.getPending();
};
Wallet.prototype.balance = function balance() {
return this.tx.balance();
Wallet.prototype.getBalance = function getBalance() {
return this.tx.getBalance();
};
Wallet.prototype.fill = function fill(tx, changeAddress, fee) {
var result = this.fillUnspent(tx, changeAddress, fee);
if (!result.inputs)
return false;
return true;
};
// Legacy
Wallet.prototype.all = Wallet.prototype.getAll;
Wallet.prototype.unspent = Wallet.prototype.getUnspent;
Wallet.prototype.pending = Wallet.prototype.getPending;
Wallet.prototype.balance = Wallet.prototype.getBalance;
Wallet.prototype.toAddress = function toAddress() {
var self = this;
@ -627,7 +640,7 @@ Wallet.prototype.toAddress = function toAddress() {
hash: utils.toHex(this.getHash()),
received: received,
sent: sent,
balance: this.balance(),
balance: this.getBalance(),
txs: txs
};
};
@ -641,7 +654,7 @@ Wallet.prototype.toJSON = function toJSON(encrypt) {
label: this.label,
address: this.getKeyAddress(),
scriptaddress: this.getScriptAddress(),
balance: utils.toBTC(this.balance()),
balance: utils.toBTC(this.getBalance()),
pub: this.getPublicKey('hex'),
priv: encrypt
? encrypt(this.getPrivateKey('base58'))