diff --git a/ScriptInterpreter.js b/ScriptInterpreter.js index dce95817c..52958204a 100644 --- a/ScriptInterpreter.js +++ b/ScriptInterpreter.js @@ -1,12 +1,12 @@ -var imports = require('soop').imports(); -var config = imports.config || require('./config'); -var log = imports.log || require('./util/log'); -var util = imports.util || require('./util/util'); -var Opcode = imports.Opcode || require('./Opcode'); +var imports = require('soop').imports(); +var config = imports.config || require('./config'); +var log = imports.log || require('./util/log'); +var util = imports.util || require('./util/util'); +var Opcode = imports.Opcode || require('./Opcode'); var buffertools = imports.buffertools || require('buffertools'); -var bignum = imports.bignum || require('bignum'); -var Util = imports.Util || require('./util/util'); -var Script = require('./Script'); +var bignum = imports.bignum || require('bignum'); +var Util = imports.Util || require('./util/util'); +var Script = require('./Script'); var SIGHASH_ALL = 1; var SIGHASH_NONE = 2; @@ -21,7 +21,8 @@ for (var i in Opcode.map) { var intToBufferSM = Util.intToBufferSM var bufferSMToInt = Util.bufferSMToInt; -function ScriptInterpreter() { +function ScriptInterpreter(opts) { + this.opts = opts || {}; this.stack = []; this.disableUnsafeOpcodes = true; }; @@ -98,8 +99,7 @@ ScriptInterpreter.prototype.eval = function eval(script, tx, inIndex, hashType, if (exec && Buffer.isBuffer(opcode)) { this.stack.push(opcode); - } - else if (exec || (OP_IF <= opcode && opcode <= OP_ENDIF)) + } else if (exec || (OP_IF <= opcode && opcode <= OP_ENDIF)) switch (opcode) { case OP_0: this.stack.push(new Buffer([])); @@ -411,10 +411,13 @@ ScriptInterpreter.prototype.eval = function eval(script, tx, inIndex, hashType, this.stackPop(); this.stackPop(); this.stack.push(new Buffer([value ? 1 : 0])); + console.log(script.toHumanReadable()); if (opcode === OP_EQUALVERIFY) { if (value) { this.stackPop(); } else { + console.log(v1); + console.log(v2); throw new Error("OP_EQUALVERIFY negative"); } } @@ -621,7 +624,7 @@ ScriptInterpreter.prototype.eval = function eval(script, tx, inIndex, hashType, scriptCode.findAndDelete(sig); // - isCanonicalSignature(new Buffer(sig)); + this.isCanonicalSignature(new Buffer(sig)); // Verify signature checkSig(sig, pubkey, scriptCode, tx, inIndex, hashType, function(e, result) { @@ -695,8 +698,9 @@ ScriptInterpreter.prototype.eval = function eval(script, tx, inIndex, hashType, var scriptCode = Script.fromChunks(scriptChunks); // Drop the signatures, since a signature can't sign itself + var that = this; sigs.forEach(function(sig) { - isCanonicalSignature(new Buffer(sig)); + that.isCanonicalSignature(new Buffer(sig)); scriptCode.findAndDelete(sig); }); @@ -811,7 +815,7 @@ ScriptInterpreter.prototype.stackTop = function stackTop(offset) { }; ScriptInterpreter.prototype.stackBack = function stackBack() { - return this.stack[this.stack.length -1]; + return this.stack[this.stack.length - 1]; }; /** @@ -882,6 +886,7 @@ ScriptInterpreter.prototype.getResult = function getResult() { return castBool(this.stack[this.stack.length - 1]); }; +// Use ScriptInterpreter.verifyFull instead ScriptInterpreter.verify = function verify(scriptSig, scriptPubKey, txTo, n, hashType, callback) { if ("function" !== typeof callback) { @@ -912,8 +917,8 @@ ScriptInterpreter.verify = return si; }; -function verifyStep4(scriptSig, scriptPubKey, txTo, nIn, - hashType, opts, callback, si, siCopy) { +ScriptInterpreter.prototype.verifyStep4 = function(scriptSig, scriptPubKey, + txTo, nIn, hashType, callback, siCopy) { if (siCopy.stack.length == 0) { callback(null, false); return; @@ -922,19 +927,19 @@ function verifyStep4(scriptSig, scriptPubKey, txTo, nIn, callback(null, castBool(siCopy.stackBack())); } -function verifyStep3(scriptSig, scriptPubKey, txTo, nIn, - hashType, opts, callback, si, siCopy) { - if (si.stack.length == 0) { +ScriptInterpreter.prototype.verifyStep3 = function(scriptSig, + scriptPubKey, txTo, nIn, hashType, callback, siCopy) { + if (this.stack.length == 0) { callback(null, false); return; } - if (castBool(si.stackBack()) == false) { + if (castBool(this.stackBack()) == false) { callback(null, false); return; } // if not P2SH, we're done - if (!opts.verifyP2SH || !scriptPubKey.isP2SH()) { + if (!this.opts.verifyP2SH || !scriptPubKey.isP2SH()) { callback(null, true); return; } @@ -949,46 +954,48 @@ function verifyStep3(scriptSig, scriptPubKey, txTo, nIn, var subscript = new Script(siCopy.stackPop()); - ok = true; + var that = this; siCopy.eval(subscript, txTo, nIn, hashType, function(err) { - if (err) - callback(err); - else - verifyStep4(scriptSig, scriptPubKey, txTo, nIn, - hashType, opts, callback, si, siCopy); + if (err) callback(err); + else that.verifyStep4(scriptSig, scriptPubKey, txTo, nIn, + hashType, callback, siCopy); }); -} +}; -function verifyStep2(scriptSig, scriptPubKey, txTo, nIn, - hashType, opts, callback, si, siCopy) { - if (opts.verifyP2SH) { - si.stack.forEach(function(item) { +ScriptInterpreter.prototype.verifyStep2 = function(scriptSig, scriptPubKey, + txTo, nIn, hashType, callback, siCopy) { + if (this.opts.verifyP2SH) { + this.stack.forEach(function(item) { siCopy.stack.push(item); }); } - si.eval(scriptPubKey, txTo, nIn, hashType, function(err) { - if (err) - callback(err); - else - verifyStep3(scriptSig, scriptPubKey, txTo, nIn, - hashType, opts, callback, si, siCopy); + var that = this; + this.eval(scriptPubKey, txTo, nIn, hashType, function(err) { + if (err) callback(err); + else that.verifyStep3(scriptSig, scriptPubKey, txTo, nIn, + hashType, callback, siCopy); }); -} +}; ScriptInterpreter.verifyFull = function verifyFull(scriptSig, scriptPubKey, txTo, nIn, hashType, opts, callback) { - var si = new ScriptInterpreter(); - var siCopy = new ScriptInterpreter(); + var si = new ScriptInterpreter(opts); + si.verifyFull(scriptSig, scriptPubKey, + txTo, nIn, hashType, callback); +}; + +ScriptInterpreter.prototype.verifyFull = function(scriptSig, scriptPubKey, + txTo, nIn, hashType, callback) { + var siCopy = new ScriptInterpreter(this.opts); + var that = this; + this.eval(scriptSig, txTo, nIn, hashType, function(err) { + if (err) callback(err); + else that.verifyStep2(scriptSig, scriptPubKey, txTo, nIn, + hashType, callback, siCopy); + }); - si.eval(scriptSig, txTo, nIn, hashType, function(err) { - if (err) - callback(err); - else - verifyStep2(scriptSig, scriptPubKey, txTo, nIn, - hashType, opts, callback, si, siCopy); - }); }; var checkSig = ScriptInterpreter.checkSig = @@ -1019,68 +1026,70 @@ var checkSig = ScriptInterpreter.checkSig = } }; -var isCanonicalSignature = ScriptInterpreter.isCanonicalSignature = function(sig, opts) { - // See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623 - // A canonical signature exists of: <30> <02> <02> - // Where R and S are not negative (their first byte has its highest bit not set), and not - // excessively padded (do not start with a 0 byte, unless an otherwise negative number follows, - // in which case a single 0 byte is necessary and even required). - - if (!Buffer.isBuffer(sig)) - throw new Error("arg should be a Buffer"); +ScriptInterpreter.prototype.isCanonicalSignature = function(sig) { + // See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623 + // A canonical signature exists of: <30> <02> <02> + // Where R and S are not negative (their first byte has its highest bit not set), and not + // excessively padded (do not start with a 0 byte, unless an otherwise negative number follows, + // in which case a single 0 byte is necessary and even required). - opts = opts || {}; + if (!Buffer.isBuffer(sig)) + throw new Error("arg should be a Buffer"); - var l = sig.length; - if (l < 9) throw new Error("Non-canonical signature: too short"); - if (l > 73) throw new Error("Non-canonical signature: too long"); + // TODO: change to opts.verifyStrictEnc to make the default + // behavior not verify, as in bitcoin core + if (this.opts.dontVerifyStrictEnc) return true; - var nHashType = sig[l-1] & (~(SIGHASH_ANYONECANPAY)); - if (nHashType < SIGHASH_ALL || nHashType > SIGHASH_SINGLE) - throw new Error("Non-canonical signature: unknown hashtype byte"); + var l = sig.length; + if (l < 9) throw new Error("Non-canonical signature: too short"); + if (l > 73) throw new Error("Non-canonical signature: too long"); - if (sig[0] !== 0x30) - throw new Error("Non-canonical signature: wrong type"); - if (sig[1] !== l-3) - throw new Error("Non-canonical signature: wrong length marker"); + var nHashType = sig[l - 1] & (~(SIGHASH_ANYONECANPAY)); + if (nHashType < SIGHASH_ALL || nHashType > SIGHASH_SINGLE) + throw new Error("Non-canonical signature: unknown hashtype byte"); - var nLenR = sig[3]; - if (5 + nLenR >= l) - throw new Error("Non-canonical signature: S length misplaced"); + if (sig[0] !== 0x30) + throw new Error("Non-canonical signature: wrong type"); + if (sig[1] !== l - 3) + throw new Error("Non-canonical signature: wrong length marker"); - var nLenS = sig[5+nLenR]; - if ( (nLenR+nLenS+7) !== l) - throw new Error("Non-canonical signature: R+S length mismatch"); - - var rPos = 4; - var R = new Buffer(nLenR); - sig.copy(R, 0, rPos, rPos+ nLenR); - if (sig[rPos-2] !== 0x02) - throw new Error("Non-canonical signature: R value type mismatch"); - if (nLenR == 0) - throw new Error("Non-canonical signature: R length is zero"); - if (R[0] & 0x80) - throw new Error("Non-canonical signature: R value negative"); - if (nLenR > 1 && (R[0] == 0x00) && !(R[1] & 0x80)) - throw new Error("Non-canonical signature: R value excessively padded"); + var nLenR = sig[3]; + if (5 + nLenR >= l) + throw new Error("Non-canonical signature: S length misplaced"); - var sPos = 6 + nLenR; - var S = new Buffer(nLenS); - sig.copy(S, 0, sPos, sPos+ nLenS); - if (sig[sPos-2] != 0x02) - throw new Error("Non-canonical signature: S value type mismatch"); - if (nLenS == 0) - throw new Error("Non-canonical signature: S length is zero"); - if (S[0] & 0x80) - throw new Error("Non-canonical signature: S value negative"); - if (nLenS > 1 && (S[0] == 0x00) && !(S[1] & 0x80)) - throw new Error("Non-canonical signature: S value excessively padded"); + var nLenS = sig[5 + nLenR]; + if ((nLenR + nLenS + 7) !== l) + throw new Error("Non-canonical signature: R+S length mismatch"); - if (opts.verifyEvenS) { - if (S[nLenS-1] & 1) - throw new Error("Non-canonical signature: S value odd"); - } - return true; + var rPos = 4; + var R = new Buffer(nLenR); + sig.copy(R, 0, rPos, rPos + nLenR); + if (sig[rPos - 2] !== 0x02) + throw new Error("Non-canonical signature: R value type mismatch"); + if (nLenR == 0) + throw new Error("Non-canonical signature: R length is zero"); + if (R[0] & 0x80) + throw new Error("Non-canonical signature: R value negative"); + if (nLenR > 1 && (R[0] == 0x00) && !(R[1] & 0x80)) + throw new Error("Non-canonical signature: R value excessively padded"); + + var sPos = 6 + nLenR; + var S = new Buffer(nLenS); + sig.copy(S, 0, sPos, sPos + nLenS); + if (sig[sPos - 2] != 0x02) + throw new Error("Non-canonical signature: S value type mismatch"); + if (nLenS == 0) + throw new Error("Non-canonical signature: S length is zero"); + if (S[0] & 0x80) + throw new Error("Non-canonical signature: S value negative"); + if (nLenS > 1 && (S[0] == 0x00) && !(S[1] & 0x80)) + throw new Error("Non-canonical signature: S value excessively padded"); + + if (this.opts.verifyEvenS) { + if (S[nLenS - 1] & 1) + throw new Error("Non-canonical signature: S value odd"); + } + return true; }; module.exports = require('soop')(ScriptInterpreter); diff --git a/Transaction.js b/Transaction.js index 31d4dcf38..25df32322 100644 --- a/Transaction.js +++ b/Transaction.js @@ -259,10 +259,10 @@ Transaction.prototype.verify = function verify(txCache, blockChain, callback) { } return txout; - }; + } Step( - function verifyInputs() { + function verifyInputs(opts) { var group = this.group(); if (self.isCoinBase()) { @@ -278,7 +278,7 @@ Transaction.prototype.verify = function verify(txCache, blockChain, callback) { outpoints.push(txin.o); - self.verifyInput(n, txout.getScript(), group()); + self.verifyInput(n, txout.getScript(), opts, group()); }); }, @@ -351,11 +351,14 @@ Transaction.prototype.verify = function verify(txCache, blockChain, callback) { ); }; -Transaction.prototype.verifyInput = function verifyInput(n, scriptPubKey, callback) { - return ScriptInterpreter.verify(this.ins[n].getScript(), - scriptPubKey, - this, n, 0, - callback); +Transaction.prototype.verifyInput = function verifyInput(n, scriptPubKey, opts, callback) { + var valid = ScriptInterpreter.verifyFull( + this.ins[n].getScript(), + scriptPubKey, + this, n, 0, + opts, + callback); + return valid; }; /** diff --git a/test/test.ScriptInterpreter.js b/test/test.ScriptInterpreter.js index e4f579b31..12353775b 100644 --- a/test/test.ScriptInterpreter.js +++ b/test/test.ScriptInterpreter.js @@ -81,9 +81,10 @@ describe('ScriptInterpreter', function() { isHex = 1; } catch (e) {} - if (isHex) - ScriptInterpreter.isCanonicalSignature.bind(sig).should. - throw (); + // ignore non-hex strings + if (isHex) { + ScriptInterpreter.isCanonicalSignature.bind(sig).should.throw(); + } }); }); diff --git a/test/test.Transaction.js b/test/test.Transaction.js index 8b4d005bd..9ab40229c 100644 --- a/test/test.Transaction.js +++ b/test/test.Transaction.js @@ -6,8 +6,7 @@ var bitcore = bitcore || require('../bitcore'); var should = chai.should(); -var TransactionModule = bitcore.Transaction; -var Transaction; +var Transaction = bitcore.Transaction; var In; var Out; var Script = bitcore.Script; @@ -40,7 +39,7 @@ function parse_test_transaction(entry) { }); var raw = new Buffer(entry[1], 'hex'); - var tx = new TransactionModule(); + var tx = new Transaction(); tx.parse(raw); // Sanity check transaction has been parsed correctly @@ -53,10 +52,6 @@ function parse_test_transaction(entry) { describe('Transaction', function() { it('should initialze the main object', function() { - should.exist(TransactionModule); - }); - it('should be able to create class', function() { - Transaction = TransactionModule; should.exist(Transaction); In = Transaction.In; Out = Transaction.Out; @@ -72,7 +67,7 @@ describe('Transaction', function() { it('#selectUnspent should be able to select utxos', function() { - var u = Transaction.selectUnspent(testdata.dataUnspent,1.0, true); + var u = Transaction.selectUnspent(testdata.dataUnspent, 1.0, true); u.length.should.equal(3); should.exist(u[0].amount); @@ -80,37 +75,37 @@ describe('Transaction', function() { should.exist(u[0].scriptPubKey); should.exist(u[0].vout); - u = Transaction.selectUnspent(testdata.dataUnspent,0.5, true); + u = Transaction.selectUnspent(testdata.dataUnspent, 0.5, true); u.length.should.equal(3); - u = Transaction.selectUnspent(testdata.dataUnspent,0.1, true); + u = Transaction.selectUnspent(testdata.dataUnspent, 0.1, true); u.length.should.equal(2); - u = Transaction.selectUnspent(testdata.dataUnspent,0.05, true); + u = Transaction.selectUnspent(testdata.dataUnspent, 0.05, true); u.length.should.equal(2); - u = Transaction.selectUnspent(testdata.dataUnspent,0.015, true); + u = Transaction.selectUnspent(testdata.dataUnspent, 0.015, true); u.length.should.equal(2); - u = Transaction.selectUnspent(testdata.dataUnspent,0.01, true); + u = Transaction.selectUnspent(testdata.dataUnspent, 0.01, true); u.length.should.equal(1); }); it('#selectUnspent should return null if not enough utxos', function() { - var u = Transaction.selectUnspent(testdata.dataUnspent,1.12); + var u = Transaction.selectUnspent(testdata.dataUnspent, 1.12); should.not.exist(u); }); it('#selectUnspent should check confirmations', function() { - var u = Transaction.selectUnspent(testdata.dataUnspent,0.9); + var u = Transaction.selectUnspent(testdata.dataUnspent, 0.9); should.not.exist(u); - var u = Transaction.selectUnspent(testdata.dataUnspent,0.9,true); + u = Transaction.selectUnspent(testdata.dataUnspent, 0.9, true); u.length.should.equal(3); - var u = Transaction.selectUnspent(testdata.dataUnspent,0.11); + u = Transaction.selectUnspent(testdata.dataUnspent, 0.11); u.length.should.equal(2); - var u = Transaction.selectUnspent(testdata.dataUnspent,0.111); + u = Transaction.selectUnspent(testdata.dataUnspent, 0.111); should.not.exist(u); }); @@ -121,8 +116,11 @@ describe('Transaction', function() { }; it('#create should be able to create instance', function() { - var utxos =testdata.dataUnspent; - var outs = [{address:'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE', amount:0.08}]; + var utxos = testdata.dataUnspent; + var outs = [{ + address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE', + amount: 0.08 + }]; var ret = Transaction.create(utxos, outs, opts); should.exist(ret.tx); @@ -143,24 +141,35 @@ describe('Transaction', function() { }); it('#create should fail if not enough inputs ', function() { - var utxos =testdata.dataUnspent; - var outs = [{address:'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE', amount:80}]; + var utxos = testdata.dataUnspent; + var outs = [{ + address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE', + amount: 80 + }]; Transaction .create .bind(utxos, outs, opts) - .should.throw(); + .should. + throw (); - var outs2 = [{address:'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE', amount:0.5}]; - should.exist( Transaction.create(utxos, outs2, opts)); + var outs2 = [{ + address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE', + amount: 0.5 + }]; + should.exist(Transaction.create(utxos, outs2, opts)); // do not allow unconfirmed - Transaction.create.bind(utxos, outs2).should.throw(); + Transaction.create.bind(utxos, outs2).should. + throw (); }); it('#create should create same output as bitcoind createrawtransaction ', function() { - var utxos =testdata.dataUnspent; - var outs = [{address:'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE', amount:0.08}]; + var utxos = testdata.dataUnspent; + var outs = [{ + address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE', + amount: 0.08 + }]; var ret = Transaction.create(utxos, outs, opts); var tx = ret.tx; @@ -170,10 +179,15 @@ describe('Transaction', function() { }); it('#create should create same output as bitcoind createrawtransaction wo remainder', function() { - var utxos =testdata.dataUnspent; + var utxos = testdata.dataUnspent; // no remainder - var outs = [{address:'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE', amount:0.08}]; - var ret = Transaction.create(utxos, outs, {fee:0.03} ); + var outs = [{ + address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE', + amount: 0.08 + }]; + var ret = Transaction.create(utxos, outs, { + fee: 0.03 + }); var tx = ret.tx; // string output generated from: bitcoind createrawtransaction '[{"txid": "2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc1","vout":1},{"txid":"2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc2","vout":0} ]' '{"mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE":0.08}' @@ -182,15 +196,21 @@ describe('Transaction', function() { }); it('#createAndSign should sign a tx', function() { - var utxos =testdata.dataUnspentSign.unspent; - var outs = [{address:'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE', amount:0.08}]; + var utxos = testdata.dataUnspentSign.unspent; + var outs = [{ + address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE', + amount: 0.08 + }]; var ret = Transaction.createAndSign(utxos, outs, testdata.dataUnspentSign.keyStrings, opts); var tx = ret.tx; tx.isComplete().should.equal(true); tx.ins.length.should.equal(1); tx.outs.length.should.equal(2); - var outs2 = [{address:'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE', amount:16}]; + var outs2 = [{ + address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE', + amount: 16 + }]; var ret2 = Transaction.createAndSign(utxos, outs2, testdata.dataUnspentSign.keyStrings, opts); var tx2 = ret2.tx; tx2.isComplete().should.equal(true); @@ -200,8 +220,11 @@ describe('Transaction', function() { it('#createAndSign should sign an incomplete tx ', function() { var keys = ['cNpW8B7XPAzCdRR9RBWxZeveSNy3meXgHD8GuhcqUyDuy8ptCDzJ']; - var utxos =testdata.dataUnspentSign.unspent; - var outs = [{address:'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE', amount:0.08}]; + var utxos = testdata.dataUnspentSign.unspent; + var outs = [{ + address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE', + amount: 0.08 + }]; var ret = Transaction.createAndSign(utxos, outs, keys, opts); var tx = ret.tx; tx.ins.length.should.equal(1); @@ -209,8 +232,11 @@ describe('Transaction', function() { }); it('#isComplete should return TX signature status', function() { var keys = ['cNpW8B7XPAzCdRR9RBWxZeveSNy3meXgHD8GuhcqUyDuy8ptCDzJ']; - var utxos =testdata.dataUnspentSign.unspent; - var outs = [{address:'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE', amount:0.08}]; + var utxos = testdata.dataUnspentSign.unspent; + var outs = [{ + address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE', + amount: 0.08 + }]; var ret = Transaction.createAndSign(utxos, outs, keys, opts); var tx = ret.tx; tx.isComplete().should.equal(false); @@ -219,31 +245,37 @@ describe('Transaction', function() { }); it('#sign should sign a tx in multiple steps (case1)', function() { - var outs = [{address:'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE', amount:1.08}]; + var outs = [{ + address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE', + amount: 1.08 + }]; var ret = Transaction.create(testdata.dataUnspentSign.unspent, outs, opts); - var tx = ret.tx; + var tx = ret.tx; var selectedUtxos = ret.selectedUtxos; - var k1 = testdata.dataUnspentSign.keyStrings.slice(0,1); + var k1 = testdata.dataUnspentSign.keyStrings.slice(0, 1); tx.isComplete().should.equal(false); tx.sign(selectedUtxos, k1).should.equal(false); - var k23 = testdata.dataUnspentSign.keyStrings.slice(1,3); + var k23 = testdata.dataUnspentSign.keyStrings.slice(1, 3); tx.sign(selectedUtxos, k23).should.equal(true); tx.isComplete().should.equal(true); }); it('#sign should sign a tx in multiple steps (case2)', function() { - var outs = [{address:'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE', amount:16}]; + var outs = [{ + address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE', + amount: 16 + }]; var ret = Transaction.create(testdata.dataUnspentSign.unspent, outs, opts); - var tx = ret.tx; + var tx = ret.tx; var selectedUtxos = ret.selectedUtxos; - var k1 = testdata.dataUnspentSign.keyStrings.slice(0,1); - var k2 = testdata.dataUnspentSign.keyStrings.slice(1,2); - var k3 = testdata.dataUnspentSign.keyStrings.slice(2,3); + var k1 = testdata.dataUnspentSign.keyStrings.slice(0, 1); + var k2 = testdata.dataUnspentSign.keyStrings.slice(1, 2); + var k3 = testdata.dataUnspentSign.keyStrings.slice(2, 3); tx.sign(selectedUtxos, k1).should.equal(false); tx.sign(selectedUtxos, k2).should.equal(false); tx.sign(selectedUtxos, k3).should.equal(true); @@ -253,11 +285,14 @@ describe('Transaction', function() { it('#createAndSign: should generate dynamic fee and readjust (and not) the selected UTXOs', function() { //this cases exceeds the input by 1mbtc AFTEr calculating the dynamic fee, //so, it should trigger adding a new 10BTC utxo - var utxos =testdata.dataUnspentSign.unspent; + var utxos = testdata.dataUnspentSign.unspent; var outs = []; - var n =101; - for (var i=0; i