mtx/tests: more refactoring.

This commit is contained in:
Christopher Jeffrey 2017-01-08 21:45:56 -08:00
parent 95c205b309
commit ee4e918024
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
5 changed files with 90 additions and 78 deletions

View File

@ -71,12 +71,12 @@ MTX.prototype.fromOptions = function fromOptions(options) {
var i;
if (options.version != null) {
assert(util.isNumber(options.version));
assert(util.isUInt32(options.version));
this.version = options.version;
}
if (options.flag != null) {
assert(util.isNumber(options.flag));
assert(util.isUInt8(options.flag));
this.flag = options.flag;
}
@ -93,7 +93,7 @@ MTX.prototype.fromOptions = function fromOptions(options) {
}
if (options.locktime != null) {
assert(util.isNumber(options.locktime));
assert(util.isUInt32(options.locktime));
this.locktime = options.locktime;
}
@ -126,34 +126,45 @@ MTX.prototype.clone = function clone() {
/**
* Add an input to the transaction.
* @example
* tx.addInput({ prevout: { hash: ... }, script: ... });
* tx.addInput(new Input());
* @param {Input|Object} options
* @returns {Input}
*
* @example
* mtx.addInput({ prevout: { hash: ... }, script: ... });
* mtx.addInput(new Input());
*/
MTX.prototype.addInput = function addInput(options) {
var input = Input.fromOptions(options);
this.inputs.push(input);
return this;
return input;
};
/**
* Add an outpoint as an input.
* @param {Outpoint|Object} outpoint
* @returns {Input}
*
* @example
* mtx.addOutpoint({ hash: ..., index: 0 });
* mtx.addOutpoint(new Outpoint(hash, index));
*/
MTX.prototype.addOutpoint = function addOutpoint(outpoint) {
var prevout = Outpoint.fromOptions(outpoint);
var input = Input.fromOutpoint(prevout);
this.inputs.push(input);
return this;
return input;
};
/**
* Add a coin as an input. Note that this will
* add the coin to the internal coin viewpoint.
* @param {Coin} coin
* @returns {Input}
*
* @example
* mtx.addCoin(Coin.fromTX(tx, 0, -1));
*/
MTX.prototype.addCoin = function addCoin(coin) {
@ -166,7 +177,7 @@ MTX.prototype.addCoin = function addCoin(coin) {
this.inputs.push(input);
this.view.addCoin(coin);
return this;
return input;
};
/**
@ -176,6 +187,10 @@ MTX.prototype.addCoin = function addCoin(coin) {
* @param {TX} tx
* @param {Number} index
* @param {Number?} height
* @returns {Input}
*
* @example
* mtx.addTX(tx, 0);
*/
MTX.prototype.addTX = function addTX(tx, index, height) {
@ -192,16 +207,20 @@ MTX.prototype.addTX = function addTX(tx, index, height) {
this.inputs.push(input);
this.view.addCoin(coin);
return this;
return input;
};
/**
* Add an output.
* @example
* tx.addOutput({ address: ..., value: 100000 });
* tx.addOutput(address, Amount.value('0.1'));
* @param {Address|Script|Output|Object} options
* @param {Amount?} value - Only needs to be present for non-output options.
* @returns {Output}
*
* @example
* mtx.addOutput(new Output());
* mtx.addOutput({ address: ..., value: 100000 });
* mtx.addOutput(address, 100000);
* mtx.addOutput(script, 100000);
*/
MTX.prototype.addOutput = function addOutput(options, value) {
@ -224,7 +243,7 @@ MTX.prototype.addOutput = function addOutput(options, value) {
this.outputs.push(output);
return this;
return output;
};
/**
@ -269,7 +288,6 @@ MTX.prototype.getInputValue = function getInputValue() {
/**
* Get all input addresses.
* @private
* @returns {Address[]} addresses
*/
@ -325,6 +343,16 @@ MTX.prototype.getSigopsCost = function getSigopsCost(flags) {
return TX.prototype.getSigopsCost.call(this, this.view, flags);
};
/**
* Calculate the virtual size of the transaction
* (weighted against bytes per sigop cost).
* @returns {Number} vsize
*/
MTX.prototype.getSigopsSize = function getSigopsSize() {
return TX.prototype.getSigopsSize.call(this, this.getSigopsCost());
};
/**
* Perform contextual checks to verify input, output,
* and fee values, as well as coinbase spend maturity
@ -525,6 +553,7 @@ MTX.prototype.scriptVector = function scriptVector(prev, vector, ring) {
* Sign a transaction input on the worker pool
* (if workers are enabled).
* @param {Number} index
* @param {Coin|Output} coin
* @param {KeyRing} ring
* @param {SighashType?} type
* @returns {Promise}
@ -799,6 +828,7 @@ MTX.prototype.isSigned = function isSigned() {
/**
* Test whether an input is fully-signed.
* @param {Number} index
* @param {Coin|Output} coin
* @returns {Boolean}
*/
@ -890,10 +920,10 @@ MTX.prototype.isVectorSigned = function isVectorSigned(prev, vector) {
};
/**
* Built input scripts (or witnesses) and sign the inputs.
* Build input scripts (or witnesses).
* @param {KeyRing} ring - Address used to sign. The address
* must be able to redeem the coin.
* @returns {Boolean} Whether the input was able to be signed.
* @returns {Number} Number of inputs templated.
*/
MTX.prototype.template = function template(ring) {
@ -931,7 +961,7 @@ MTX.prototype.template = function template(ring) {
* @param {KeyRing} ring - Address used to sign. The address
* must be able to redeem the coin.
* @param {SighashType} type
* @returns {Boolean} Whether the input was able to be signed.
* @returns {Number} Number of inputs signed.
*/
MTX.prototype.sign = function sign(ring, type) {
@ -976,7 +1006,6 @@ MTX.prototype.sign = function sign(ring, type) {
* @param {KeyRing} ring
* @param {SighashType?} type
* @returns {Promise}
* @returns {Boolean} Whether the inputs are valid.
*/
MTX.prototype.signAsync = function signAsync(ring, type) {
@ -1113,20 +1142,8 @@ MTX.prototype.estimateSize = co(function* estimateSize(estimate) {
* Select necessary coins based on total output value.
* @param {Coin[]} coins
* @param {Object?} options
* @param {String?} options.selection - Coin selection priority. Can
* be `age`, `random`, or `all`. (default=age).
* @param {Boolean} options.confirmed - Select only confirmed coins.
* @param {Boolean} options.round - Whether to round to the nearest
* kilobyte for fee calculation.
* See {@link TX#getMinFee} vs. {@link TX#getRoundFee}.
* @param {Amount?} options.hardFee - Use a hard fee rather
* than calculating one.
* @param {Rate?} options.rate - Rate used for fee calculation.
* @param {Number|Boolean} options.subtractFee - Whether to subtract the
* fee from * existing outputs rather than adding more inputs.
* @returns {CoinSelection}
* @throws on not enough funds available.
* @throws on unable to subtract fee.
*/
MTX.prototype.selectCoins = function selectCoins(coins, options) {
@ -1357,7 +1374,10 @@ MTX.prototype.getJSON = function getJSON(network) {
};
/**
* @see TX.fromJSON
* Instantiate a transaction from a
* jsonified transaction object.
* @param {Object} json - The jsonified transaction object.
* @returns {MTX}
*/
MTX.fromJSON = function fromJSON(json) {
@ -1365,7 +1385,9 @@ MTX.fromJSON = function fromJSON(json) {
};
/**
* @see TX.fromReader
* Instantiate a transaction from a buffer reader.
* @param {BufferReader} br
* @returns {MTX}
*/
MTX.fromReader = function fromReader(br) {
@ -1373,7 +1395,10 @@ MTX.fromReader = function fromReader(br) {
};
/**
* @see TX.fromRaw
* Instantiate a transaction from a serialized Buffer.
* @param {Buffer} data
* @param {String?} enc - Encoding, can be `'hex'` or null.
* @returns {MTX}
*/
MTX.fromRaw = function fromRaw(data, enc) {
@ -1391,17 +1416,6 @@ MTX.prototype.toTX = function toTX() {
return new TX(this);
};
/**
* Inject properties from transaction.
* @private
* @param {TX} tx
* @returns {MTX}
*/
MTX.prototype.fromTX = function fromTX(tx, view) {
return this.fromRaw(tx.toRaw());
};
/**
* Instantiate MTX from TX.
* @param {TX} tx
@ -1409,7 +1423,7 @@ MTX.prototype.fromTX = function fromTX(tx, view) {
*/
MTX.fromTX = function fromTX(tx) {
return new MTX().fromTX(tx);
return new MTX(tx);
};
/**
@ -1830,8 +1844,8 @@ function sortRandom(a, b) {
}
function sortInputs(a, b) {
var ahash = util.revHex(a.prevout.hash);
var bhash = util.revHex(b.prevout.hash);
var ahash = a.prevout.rhash();
var bhash = b.prevout.rhash();
var cmp = util.strcmp(ahash, bhash);
if (cmp !== 0)

View File

@ -64,6 +64,15 @@ Outpoint.prototype.isNull = function isNull() {
return this.index === 0xffffffff && this.hash === encoding.NULL_HASH;
};
/**
* Get little-endian hash.
* @returns {Hash}
*/
Outpoint.prototype.rhash = function rhash() {
return util.revHex(this.hash);
};
/**
* Serialize outpoint to a key
* suitable for a hash table.
@ -254,7 +263,7 @@ Outpoint.toKey = function toKey(hash, index) {
*/
Outpoint.prototype.inspect = function inspect() {
return '<Outpoint: ' + util.revHex(this.hash) + '/' + this.index + '>';
return '<Outpoint: ' + this.rhash() + '/' + this.index + '>';
};
/*

View File

@ -907,7 +907,7 @@ TX.prototype.getOutputValue = function getOutputValue() {
* Get all input addresses.
* @private
* @param {CoinView} view
* @returns {Array}
* @returns {Object}
*/
TX.prototype._getInputAddresses = function getInputAddresses(view) {
@ -940,7 +940,7 @@ TX.prototype._getInputAddresses = function getInputAddresses(view) {
/**
* Get all output addresses.
* @private
* @returns {Array}
* @returns {Object}
*/
TX.prototype._getOutputAddresses = function getOutputAddresses() {
@ -970,7 +970,7 @@ TX.prototype._getOutputAddresses = function getOutputAddresses() {
* Get all addresses.
* @private
* @param {CoinView} view
* @returns {Array}
* @returns {Object}
*/
TX.prototype._getAddresses = function getAddresses(view) {

View File

@ -160,10 +160,7 @@ Witness.prototype.toASM = function toASM(decode) {
};
/**
* Clone the witness object. Note that the raw
* encoded witness data will be lost. This is
* because the function assumes you are going
* to be altering the stack items by hand.
* Clone the witness object.
* @returns {Witness} A clone of the current witness object.
*/

View File

@ -497,7 +497,7 @@ describe('Wallet', function() {
var view, t1, t2, t3, balance, err;
// Coinbase
t1 = new MTX()
t1 = new MTX();
t1.addInput(dummy(encoding.NULL_HASH));
t1.addOutput(w1.getAddress(), 5460);
t1.addOutput(w1.getAddress(), 5460);
@ -508,7 +508,8 @@ describe('Wallet', function() {
yield walletdb.addTX(t1);
// Create new transaction
t2 = new MTX().addOutput(w2.getAddress(), 5460);
t2 = new MTX();
t2.addOutput(w2.getAddress(), 5460);
yield w1.fund(t2, { rate: 10000 });
yield w1.sign(t2);
@ -553,7 +554,7 @@ describe('Wallet', function() {
var w1 = yield walletdb.create();
var w2 = yield walletdb.create();
var to = yield walletdb.create();
var t1, t2, tx, cost, total, coins1, coins2, left;
var t1, t2, tx, cost, total, coins1, coins2;
// Coinbase
t1 = new MTX();
@ -586,20 +587,11 @@ describe('Wallet', function() {
coins1 = yield w1.getCoins();
coins2 = yield w2.getCoins();
// Add dummy output (for `left`) to calculate maximum TX size
tx.addOutput(w1.getAddress(), 0);
// Add our unspent inputs to sign
tx.addCoin(coins1[0]);
tx.addCoin(coins1[1]);
tx.addCoin(coins2[0]);
left = tx.getInputValue() - total;
if (left === 0)
tx.outputs.pop();
else
tx.outputs[tx.outputs.length - 1].value = left;
// Sign transaction
total = yield w1.sign(tx);
assert.equal(total, 2);
@ -670,19 +662,19 @@ describe('Wallet', function() {
assert.equal(w2.account[rec].getAddress('base58'), b58);
assert.equal(w3.account[rec].getAddress('base58'), b58);
paddr = w1.getNested('base58');
assert.equal(w1.getNested('base58'), paddr);
assert.equal(w2.getNested('base58'), paddr);
assert.equal(w3.getNested('base58'), paddr);
paddr = w1.getNested();
if (witness) {
assert(paddr);
assert.equal(w1.getNested('base58'), paddr.toBase58());
assert.equal(w2.getNested('base58'), paddr.toBase58());
assert.equal(w3.getNested('base58'), paddr.toBase58());
}
// Add a shared unspent transaction to our wallets
utx = new MTX();
if (bullshitNesting)
utx.addOutput({ address: paddr, value: 5460 * 10 });
else
utx.addOutput({ address: addr, value: 5460 * 10 });
utx.addInput(dummy());
utx.addOutput(bullshitNesting ? paddr : addr, 5460 * 10);
utx = utx.toTX();
// Simulate a confirmation
@ -704,7 +696,7 @@ describe('Wallet', function() {
// Create a tx requiring 2 signatures
send = new MTX();
send.addOutput({ address: receive.getAddress(), value: 5460 });
send.addOutput(receive.getAddress(), 5460);
assert(!send.verify(flags));
yield w1.fund(send, { rate: 10000, round: true });