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

View File

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

View File

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

View File

@ -105,7 +105,7 @@ Output.prototype.__defineGetter__('n', function() {
return this.data.n || this.m; return this.data.n || this.m;
}); });
Output.prototype.__defineGetter__('lock', function() { Output.prototype.__defineGetter__('lockTime', function() {
return bcoin.script.getLockTime(this.script); return bcoin.script.getLockTime(this.script);
}); });
@ -162,7 +162,7 @@ Output.prototype.__defineGetter__('scriptaddr', function() {
// height: Number, // height: Number,
// flags: Array, // flags: Array,
// text: String, // text: String,
// lock: Number, // lockTime: Number,
// value: bn, // value: bn,
// script: Array, // script: Array,
// seq: Number, // seq: Number,
@ -203,7 +203,7 @@ Output.prototype.inspect = function inspect() {
m: this.m, m: this.m,
n: this.n, n: this.n,
text: this.text, text: this.text,
lock: this.lock, lockTime: this.lockTime,
value: utils.btc(this.value), value: utils.btc(this.value),
script: bcoin.script.format(this.script)[0] 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 // 4. Test data elements in input scripts
for (i = 0; i < tx.inputs.length; i++) { for (i = 0; i < tx.inputs.length; i++) {
input = tx.inputs[i]; input = tx.inputs[i];
prev = input.out.hash; prev = input.prevout.hash;
if (typeof prev === 'string') if (typeof prev === 'string')
prev = utils.toArray(prev, 'hex'); prev = utils.toArray(prev, 'hex');
@ -1018,8 +1018,8 @@ Pool.prototype.isWatched = function(tx, bloom) {
return true; return true;
// Test the prev_out script // Test the prev_out script
if (input.out.tx) { if (input.prevout.tx) {
prev = input.out.tx.outputs[input.out.index]; prev = input.prevout.tx.outputs[input.prevout.index];
if (testScript(prev.script)) if (testScript(prev.script))
return true; return true;
} }

View File

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

View File

@ -373,12 +373,12 @@ Parser.prototype.parseTXIn = function parseTXIn(p) {
return { return {
size: off + scriptLen + 4, size: off + scriptLen + 4,
out: { prevout: {
hash: utils.toArray(p.slice(0, 32)), hash: utils.toArray(p.slice(0, 32)),
index: utils.readU32(p, 32) index: utils.readU32(p, 32)
}, },
script: bcoin.script.decode(utils.toArray(p.slice(off, off + scriptLen))), 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), version: utils.read32(p, 0),
inputs: txIn, inputs: txIn,
outputs: txOut, outputs: txOut,
lock: utils.readU32(p, off), lockTime: utils.readU32(p, off),
_off: off + 4, _off: off + 4,
_size: p.length _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 key, sig, type, subscript, hash;
var keys, i, j, m; var keys, i, j, m;
var succ; var succ;
var lock, threshold; var lockTime, threshold;
var evalScript; var evalScript;
stack.alt = stack.alt || []; stack.alt = stack.alt || [];
@ -934,28 +934,28 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) {
if (!tx || stack.length === 0) if (!tx || stack.length === 0)
return false; return false;
lock = stack[stack.length - 1]; lockTime = stack[stack.length - 1];
if (!Array.isArray(lock)) if (!Array.isArray(lockTime))
return false; return false;
if (lock.length > 6) if (lockTime.length > 6)
return false; return false;
lock = script.num(lock, true); lockTime = script.num(lockTime, true);
if (lock < 0) if (lockTime < 0)
return false; return false;
threshold = constants.locktimeThreshold; threshold = constants.locktimeThreshold;
if (!( if (!(
(tx.lock < threshold && lock < threshold) (tx.lockTime < threshold && lockTime < threshold)
|| (tx.lock >= threshold && lock >= threshold) || (tx.lockTime >= threshold && lockTime >= threshold)
)) { )) {
return false; return false;
} }
if (lock > tx.lock) if (lockTime > tx.lockTime)
return false; return false;
if (!tx.inputs[index] || tx.inputs[index].seq === 0xffffffff) 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) { 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'); assert(typeof type === 'string');
@ -1355,7 +1355,7 @@ script._getInputData = function _getInputData(s, type) {
if (type === 'scripthash') { if (type === 'scripthash') {
raw = s[s.length - 1]; raw = s[s.length - 1];
redeem = script.decode(raw); redeem = script.decode(raw);
lock = script.getLockTime(redeem); lockTime = script.getLockTime(redeem);
hash = bcoin.wallet.key2hash(raw); hash = bcoin.wallet.key2hash(raw);
address = bcoin.wallet.hash2addr(hash, 'scripthash'); address = bcoin.wallet.hash2addr(hash, 'scripthash');
output = script.getOutputData(script.getSubscript(redeem)); output = script.getOutputData(script.getSubscript(redeem));
@ -1368,7 +1368,7 @@ script._getInputData = function _getInputData(s, type) {
redeem: redeem, redeem: redeem,
scripthash: hash, scripthash: hash,
scriptaddress: address, scriptaddress: address,
lock: lock lockTime: lockTime
}); });
} }
@ -2063,8 +2063,8 @@ script.format = function format(input, output) {
scripts.push(output); scripts.push(output);
} else if (input) { } else if (input) {
scripts.push(input.script); scripts.push(input.script);
if (input.out.tx && input.out.tx.outputs[input.out.index]) { if (input.prevout.tx && input.prevout.tx.outputs[input.prevout.index]) {
prev = input.out.tx.outputs[input.out.index].script; prev = input.prevout.tx.outputs[input.prevout.index].script;
scripts.push(prev); scripts.push(prev);
if (script.isScripthash(prev)) { if (script.isScripthash(prev)) {
redeem = script.decode(input.script[input.script.length - 1]); 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 // Consume unspent money or add orphans
for (i = 0; i < tx.inputs.length; i++) { for (i = 0; i < tx.inputs.length; i++) {
input = tx.inputs[i]; input = tx.inputs[i];
key = input.out.hash + '/' + input.out.index; key = input.prevout.hash + '/' + input.prevout.index;
unspent = this._unspent[key]; unspent = this._unspent[key];
if (!input.out.tx && this._all[input.out.hash]) if (!input.prevout.tx && this._all[input.prevout.hash])
input.out.tx = this._all[input.out.hash]; input.prevout.tx = this._all[input.prevout.hash];
if (unspent) { if (unspent) {
// Add TX to inputs and spend money // Add TX to inputs and spend money
index = tx._inputIndex(unspent.tx.hash('hex'), unspent.index); index = tx._inputIndex(unspent.tx.hash('hex'), unspent.index);
assert(index !== -1); assert(index !== -1);
assert(tx.inputs[index] === input); assert(tx.inputs[index] === input);
assert(tx.inputs[index].out.hash === unspent.tx.hash('hex')); assert(tx.inputs[index].prevout.hash === unspent.tx.hash('hex'));
assert(tx.inputs[index].out.index === unspent.index); assert(tx.inputs[index].prevout.index === unspent.index);
input.out.tx = unspent.tx; input.prevout.tx = unspent.tx;
// Skip invalid transactions // Skip invalid transactions
if (!tx.verify(index)) if (!tx.verify(index))
@ -123,13 +123,13 @@ TXPool.prototype.add = function add(tx, noWrite) {
// signature checking code to ownInput for p2sh and p2pk, // signature checking code to ownInput for p2sh and p2pk,
// we could in theory use ownInput here (and down below) // we could in theory use ownInput here (and down below)
// instead. // instead.
if (input.out.tx) { if (input.prevout.tx) {
if (!this._wallet.ownOutput(input.out.tx, input.out.index)) if (!this._wallet.ownOutput(input.prevout.tx, input.prevout.index))
continue; continue;
} }
// Add orphan, if no parent transaction is yet known // 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]) if (this._orphans[key])
this._orphans[key].push(orphan); this._orphans[key].push(orphan);
else else
@ -149,9 +149,9 @@ TXPool.prototype.add = function add(tx, noWrite) {
function checkOrphan(orphan) { function checkOrphan(orphan) {
var index = orphan.tx._inputIndex(tx.hash('hex'), orphan.index); var index = orphan.tx._inputIndex(tx.hash('hex'), orphan.index);
assert(index !== -1); assert(index !== -1);
assert(orphan.tx.inputs[index].out.hash === tx.hash('hex')); assert(orphan.tx.inputs[index].prevout.hash === tx.hash('hex'));
assert(orphan.tx.inputs[index].out.index === i); assert(orphan.tx.inputs[index].prevout.index === i);
orphan.tx.inputs[index].out.tx = tx; orphan.tx.inputs[index].prevout.tx = tx;
// Verify that input script is correct, if not - add output to unspent // Verify that input script is correct, if not - add output to unspent
// and remove orphan from storage // 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 Object.keys(this._all).map(function(key) {
return this._all[key]; return this._all[key];
}, this).filter(function(tx) { }, this).filter(function(tx) {
@ -234,7 +234,7 @@ TXPool.prototype.all = function all() {
}, this); }, this);
}; };
TXPool.prototype.unspent = function unspent() { TXPool.prototype.getUnspent = function getUnspent() {
return Object.keys(this._unspent).map(function(key) { return Object.keys(this._unspent).map(function(key) {
return this._unspent[key]; return this._unspent[key];
}, this).filter(function(item) { }, this).filter(function(item) {
@ -246,7 +246,7 @@ TXPool.prototype.hasUnspent = function hasUnspent(hash, unspent) {
var has; var has;
if (utils.isBuffer(hash) && hash.length && typeof hash[0] !== 'number') { if (utils.isBuffer(hash) && hash.length && typeof hash[0] !== 'number') {
unspent = this.unspent(); unspent = this.getUnspent();
has = hash.map(function(hash) { has = hash.map(function(hash) {
var h = this.hasUnspent(hash, unspent); var h = this.hasUnspent(hash, unspent);
if (!h) if (!h)
@ -260,14 +260,14 @@ TXPool.prototype.hasUnspent = function hasUnspent(hash, unspent) {
if (utils.isBuffer(hash)) if (utils.isBuffer(hash))
hash = utils.toHex(hash); hash = utils.toHex(hash);
else if (hash.out) else if (hash.prevout)
hash = hash.out.hash; hash = hash.prevout.hash;
else if (hash.tx) else if (hash.tx)
hash = hash.tx.hash('hex'); hash = hash.tx.hash('hex');
else if (hash instanceof bcoin.tx) else if (hash instanceof bcoin.tx)
hash = hash.hash('hex'); hash = hash.hash('hex');
unspent = unspent || this.unspent(); unspent = unspent || this.getUnspent();
has = unspent.filter(function(item) { has = unspent.filter(function(item) {
return item.tx.hash('hex') === hash; return item.tx.hash('hex') === hash;
@ -279,7 +279,7 @@ TXPool.prototype.hasUnspent = function hasUnspent(hash, unspent) {
return has; return has;
}; };
TXPool.prototype.pending = function pending() { TXPool.prototype.getPending = function getPending() {
return Object.keys(this._all).map(function(key) { return Object.keys(this._all).map(function(key) {
return this._all[key]; return this._all[key];
}, this).filter(function(tx) { }, 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 acc = new bn(0);
var unspent = this.unspent(); var unspent = this.getUnspent();
if (unspent.length === 0) if (unspent.length === 0)
return acc; return acc;
@ -298,6 +298,12 @@ TXPool.prototype.balance = function balance() {
}, acc); }, 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() { TXPool.prototype.toJSON = function toJSON() {
return { return {
v: 1, v: 1,

View File

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

View File

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