From 5b7bfe0ed40fbe2687f6ec699fadbb39d677c946 Mon Sep 17 00:00:00 2001 From: dthorpe Date: Mon, 7 Apr 2014 22:53:45 -0700 Subject: [PATCH 01/22] Fix Unresolved external symbol "FromConstructorTemplate..." linking on Windows, per #108 --- src/eckey.cc | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/eckey.cc b/src/eckey.cc index 973d98988..e5616c6a9 100644 --- a/src/eckey.cc +++ b/src/eckey.cc @@ -160,20 +160,26 @@ Key::New() Handle Key::New(const Arguments& args) { - if (!args.IsConstructCall()) { - return FromConstructorTemplate(s_ct, args); - } - HandleScope scope; - Key* key = new Key(); - if (key->lastError != NULL) { - return VException(key->lastError); + // this was invoked as Key() not new Key() + if (!args.IsConstructCall()) { +// return FromConstructorTemplate(s_ct, args); + + const int argc = 1; + Local argv[argc] = { args[0] }; + return scope.Close(s_ct->GetFunction()->NewInstance(argc, argv)); } + else{ + Key* key = new Key(); + if (key->lastError != NULL) { + return VException(key->lastError); + } - key->Wrap(args.Holder()); + key->Wrap(args.Holder()); - return scope.Close(args.This()); + return scope.Close(args.This()); + } } Handle From 72a44154d426659fd1742deffdfb08d279194e9a Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 9 Apr 2014 12:38:25 -0300 Subject: [PATCH 02/22] fix testling config --- package.json | 3 ++- test/index-testling.html | 52 ++++++++++++++++++++++++++++++++++++++++ test/test.PeerManager.js | 2 +- 3 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 test/index-testling.html diff --git a/package.json b/package.json index 9d4eaf0e5..7613cd2c4 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,8 @@ "istanbul": "~0.2.6" }, "testling": { - "files": "test/test*.js", + "harness": "mocha-tdd", + "html": "test/index-testling.html", "browsers": [ "ie/6..latest", "chrome/22..latest", diff --git a/test/index-testling.html b/test/index-testling.html new file mode 100644 index 000000000..e6a9447f0 --- /dev/null +++ b/test/index-testling.html @@ -0,0 +1,52 @@ + + + + Mocha + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/test.PeerManager.js b/test/test.PeerManager.js index 5f3aa7f30..ab6565d4c 100644 --- a/test/test.PeerManager.js +++ b/test/test.PeerManager.js @@ -5,7 +5,7 @@ var bitcore = bitcore || require('../bitcore'); var should = chai.should(); -var PeerManagerModule = bitcore.PeerManager || require('./PeerManager'); +var PeerManagerModule = bitcore.PeerManager; var PeerManager; From ae14c4aaa0095abf9c6f8fc6c61d67c68b7bc29d Mon Sep 17 00:00:00 2001 From: "Ryan X. Charles" Date: Wed, 9 Apr 2014 13:11:24 -0300 Subject: [PATCH 03/22] new convenient interface for creating addresses To create an address from a public key or script, you used to have to do the hashing yourself, and find the version yourself. For example: var hash = bitcore.util.sha256ripe160(pubkey); var version = bitcore.networks['livenet'].addressVersion; var addr = new Address(version, hash); But with this interface, things are much simpler: var addr = Address.fromPubKey(pubkey); The new convenience methods are: Address.fromPubKey (for regular pubkeyhash addresses) Address.fromPubKeys (for p2sh multisig addresses) Address.fromScript (for any p2sh address) --- Address.js | 50 ++++++++++++++++++++++++++++++++++++++++++-- test/test.Address.js | 39 ++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 2 deletions(-) diff --git a/Address.js b/Address.js index b9a4ed15d..d530bf004 100644 --- a/Address.js +++ b/Address.js @@ -1,7 +1,9 @@ 'use strict'; var imports = require('soop').imports(); -var parent = imports.parent || require('./util/VersionedData'); -var networks= imports.networks || require('./networks'); +var coinUtil = imports.coinUtil || require('./util/util'); +var parent = imports.parent || require('./util/VersionedData'); +var networks = imports.networks || require('./networks'); +var Script = imports.Script || require('./Script'); function Address() { Address.super(this, arguments); @@ -10,6 +12,50 @@ function Address() { Address.parent = parent; parent.applyEncodingsTo(Address); +//create a pubKeyHash address +Address.fromPubKey = function(pubKey, network) { + if (!network) + network = 'livenet'; + + if (pubKey.length != 33 && pubKey.length != 65) + throw new Error('Invalid public key'); + + var version = networks[network].addressVersion; + var hash = coinUtil.sha256ripe160(pubKey); + + return new Address(version, hash); +}; + +//create a p2sh m-of-n multisig address +Address.fromPubKeys = function(mReq, pubKeys, network) { + if (!network) + network = 'livenet'; + + for (var i in pubKeys) { + var pubKey = pubKeys[i]; + if (pubKey.length != 33 && pubKey.length != 65) + throw new Error('Invalid public key'); + } + + var version = networks[network].P2SHVersion; + var script = Script.createMultisig(mReq, pubKeys); + var buf = script.getBuffer(); + var hash = coinUtil.sha256ripe160(buf) + + return new Address(version, hash); +}; + +//create a p2sh address from redeemScript +Address.fromScript = function(script, network) { + if (!network) + network = 'livenet'; + + var version = networks[network].P2SHVersion; + var buf = script.getBuffer(); + var hash = coinUtil.sha256ripe160(buf); + + return new Address(version, hash); +}; Address.prototype.validate = function() { this.doAsBinary(function() { diff --git a/test/test.Address.js b/test/test.Address.js index 19825534a..9793902ab 100644 --- a/test/test.Address.js +++ b/test/test.Address.js @@ -82,5 +82,44 @@ describe('Address', function() { // script testnet new Address('2NBSBcf2KfjPEEqVusmrWdmUeNHRiUTS3Li').isScript().should.equal(true); }); + + describe('#fromPubKey', function() { + it('should make this pubkeyhash address from uncompressed this public key', function() { + var pubkey = new Buffer('04fa05ce8b25010cb6e17a30e0b66668bf083c40687547748ec330ee77adf53a42abd3d26148cbacfcf79c907ddefeb2c37f8bebc0a695ba79d634449d871de218', 'hex'); + var hash = bitcore.util.sha256ripe160(pubkey); + var addr = new Address(0, hash); + addr.toString().should.equal(Address.fromPubKey(pubkey).toString()); + }); + }); + + describe('#fromPubKeys', function() { + it('should make this p2sh multisig address from these pubkeys', function() { + var pubkey1 = new Buffer('03e0973263b4e0d5f5f56d25d430e777ab3838ff644db972c0bf32c31da5686c27', 'hex'); + var pubkey2 = new Buffer('0371f94c57cc013507101e30794161f4e6b9efd58a9ea68838daf429b7feac8cb2', 'hex'); + var pubkey3 = new Buffer('032c0d2e394541e2efdc7ac3500e16e7e69df541f38670402e95aa477202fa06bb', 'hex'); + var sortedPubKeys = [pubkey3, pubkey2, pubkey1]; + var mReq = 2; + var script = bitcore.Script.createMultisig(mReq, sortedPubKeys, {noSorting: true}); + var hash = bitcore.util.sha256ripe160(script.getBuffer()); + var version = bitcore.networks['livenet'].P2SHVersion; + var addr = new Address(version, hash); + var addr2 = Address.fromPubKeys(mReq, sortedPubKeys); + addr.toString().should.equal(addr2.toString()); + }); + }); + + describe('#fromScript', function() { + it('should make this p2sh multisig address from these pubkeys', function() { + var pubkey1 = new Buffer('03e0973263b4e0d5f5f56d25d430e777ab3838ff644db972c0bf32c31da5686c27', 'hex'); + var pubkey2 = new Buffer('0371f94c57cc013507101e30794161f4e6b9efd58a9ea68838daf429b7feac8cb2', 'hex'); + var pubkey3 = new Buffer('032c0d2e394541e2efdc7ac3500e16e7e69df541f38670402e95aa477202fa06bb', 'hex'); + var pubKeys = [pubkey1, pubkey2, pubkey3]; + var mReq = 2; + var script = bitcore.Script.createMultisig(mReq, pubKeys); + var addr = Address.fromScript(script); + var addr2 = Address.fromPubKeys(mReq, pubKeys); + addr.toString().should.equal(addr2.toString()); + }); + }); }); From a7c8cf49b39fab414da0732f1da7e012e87538b8 Mon Sep 17 00:00:00 2001 From: "Ryan X. Charles" Date: Wed, 9 Apr 2014 14:07:56 -0300 Subject: [PATCH 04/22] update fromPubKeys to use fromScript This means fewer code-duplication. Also added another test for fromScript to make sure it is thoroughly tested. Also pass through opts to createMultisig so that you can choose to lot let it be sorted if you want. --- Address.js | 9 +++------ test/test.Address.js | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/Address.js b/Address.js index d530bf004..c3bf0eed6 100644 --- a/Address.js +++ b/Address.js @@ -27,7 +27,7 @@ Address.fromPubKey = function(pubKey, network) { }; //create a p2sh m-of-n multisig address -Address.fromPubKeys = function(mReq, pubKeys, network) { +Address.fromPubKeys = function(mReq, pubKeys, network, opts) { if (!network) network = 'livenet'; @@ -37,12 +37,9 @@ Address.fromPubKeys = function(mReq, pubKeys, network) { throw new Error('Invalid public key'); } - var version = networks[network].P2SHVersion; - var script = Script.createMultisig(mReq, pubKeys); - var buf = script.getBuffer(); - var hash = coinUtil.sha256ripe160(buf) + var script = Script.createMultisig(mReq, pubKeys, opts); - return new Address(version, hash); + return Address.fromScript(script, network); }; //create a p2sh address from redeemScript diff --git a/test/test.Address.js b/test/test.Address.js index 9793902ab..bffc08a2e 100644 --- a/test/test.Address.js +++ b/test/test.Address.js @@ -120,6 +120,22 @@ describe('Address', function() { var addr2 = Address.fromPubKeys(mReq, pubKeys); addr.toString().should.equal(addr2.toString()); }); + + it('it should make this hand-crafted address', function() { + var pubkey1 = new Buffer('03e0973263b4e0d5f5f56d25d430e777ab3838ff644db972c0bf32c31da5686c27', 'hex'); + var pubkey2 = new Buffer('0371f94c57cc013507101e30794161f4e6b9efd58a9ea68838daf429b7feac8cb2', 'hex'); + var pubkey3 = new Buffer('032c0d2e394541e2efdc7ac3500e16e7e69df541f38670402e95aa477202fa06bb', 'hex'); + var pubKeys = [pubkey1, pubkey2, pubkey3]; + var mReq = 2; + var script = bitcore.Script.createMultisig(mReq, pubKeys); + var addr = Address.fromScript(script); + + var hash = bitcore.util.sha256ripe160(script.getBuffer()); + var version = bitcore.networks['livenet'].P2SHVersion; + var addr2 = new Address(version, hash); + + addr.toString().should.equal(addr2.toString()); + }); }); }); From a8f5f9fcb8ccd967413c0e339fcdf6316afdfae9 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 9 Apr 2014 14:13:48 -0300 Subject: [PATCH 05/22] remove unused params in example --- examples/CreateAndSignTx-PayToScriptHash.js | 4 ++-- test/test.TransactionBuilder.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/CreateAndSignTx-PayToScriptHash.js b/examples/CreateAndSignTx-PayToScriptHash.js index 8b035ee07..f80593caf 100644 --- a/examples/CreateAndSignTx-PayToScriptHash.js +++ b/examples/CreateAndSignTx-PayToScriptHash.js @@ -41,10 +41,10 @@ var run = function() { }); // multisig p2sh - var opts = {nreq:3, pubkeys:pubkeys, amount:0.05}; + var opts = {nreq:3, pubkeys:pubkeys}; // p2scriphash p2sh - //var opts = [{address: an_address, amount:0.05}]; + //var opts = [{address: an_address}]; var info = Builder.infoForP2sh(opts, 'testnet'); var p2shScript = info.scriptBufHex; diff --git a/test/test.TransactionBuilder.js b/test/test.TransactionBuilder.js index dc32198ce..e8804d0a4 100644 --- a/test/test.TransactionBuilder.js +++ b/test/test.TransactionBuilder.js @@ -563,7 +563,7 @@ describe('TransactionBuilder', function() { }; var data = getInfoForP2sh(); // multisig p2sh - var p2shOpts = {nreq:3, pubkeys:data.pubkeys, amount:0.05}; + var p2shOpts = {nreq:3, pubkeys:data.pubkeys}; var info = TransactionBuilder.infoForP2sh(p2shOpts, network); var outs = outs || [{ @@ -644,7 +644,7 @@ describe('TransactionBuilder', function() { remainderOut: {address: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd'}, }; // p2hash/ p2sh - var p2shOpts = {address:'mgwqzy6pF5BSc72vxHBFSnnhNEBcV4TJzV', amount:0.05}; + var p2shOpts = {address:'mgwqzy6pF5BSc72vxHBFSnnhNEBcV4TJzV'}; var info = TransactionBuilder.infoForP2sh(p2shOpts, network); //addr: 2NAwCQ1jPYPrSsyBQvfP6AJ6d6SSxnHsZ4e From 124a2ed8af8215a976223023183c14b3eceb1a42 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 10 Apr 2014 12:10:34 -0300 Subject: [PATCH 06/22] dummy commit to test testling integration --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7613cd2c4..f019316c3 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "istanbul": "~0.2.6" }, "testling": { - "harness": "mocha-tdd", + "harness": "mocha-bdd", "html": "test/index-testling.html", "browsers": [ "ie/6..latest", From c5cd242d15f01c251d19f4e0287bad794c9c7aa0 Mon Sep 17 00:00:00 2001 From: "Ryan X. Charles" Date: Thu, 10 Apr 2014 12:30:14 -0300 Subject: [PATCH 07/22] add test for .isValid() function --- test/test.PrivateKey.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/test.PrivateKey.js b/test/test.PrivateKey.js index 6374bdcd3..1b72dc59b 100644 --- a/test/test.PrivateKey.js +++ b/test/test.PrivateKey.js @@ -48,5 +48,12 @@ describe('PrivateKey', function() { var a = new PrivateKey('5JZsbYcnYN8Dz2YeSLZr6aswrVevedMUSFWxpie6SPpYRb2E4Gi'); a.network().name.should.equal('livenet'); }); + + describe('#isValid', function() { + it('should detect this private key as valid', function() { + var privKey = new PrivateKey('5JQkUX6RNQC91xv4Www6Cgbxb6Eri6WBJjtPGqwfXVKBzT37cAf'); + privKey.isValid().should.equal(true); + }); + }); }); From 521a260afc735b9a5c79ac6f2277809074a87ded Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 10 Apr 2014 15:39:54 -0300 Subject: [PATCH 08/22] remove deprecated chai uses --- test/test.Transaction.js | 2 +- test/test.TransactionBuilder.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test.Transaction.js b/test/test.Transaction.js index 70d93ddc5..29364c2c6 100644 --- a/test/test.Transaction.js +++ b/test/test.Transaction.js @@ -1,7 +1,7 @@ 'use strict'; var chai = chai || require('chai'); -chai.Assertion.includeStack = true; +chai.config.includeStack = true; var bitcore = bitcore || require('../bitcore'); var should = chai.should(); diff --git a/test/test.TransactionBuilder.js b/test/test.TransactionBuilder.js index e8804d0a4..4d844b348 100644 --- a/test/test.TransactionBuilder.js +++ b/test/test.TransactionBuilder.js @@ -1,7 +1,7 @@ 'use strict'; var chai = chai || require('chai'); -chai.Assertion.includeStack = true; +chai.config.includeStack = true; var bitcore = bitcore || require('../bitcore'); var should = chai.should(); From 9e02860fd9bdb2e438fe569b0beaa552fffc6a89 Mon Sep 17 00:00:00 2001 From: "Ryan X. Charles" Date: Thu, 10 Apr 2014 16:36:50 -0300 Subject: [PATCH 09/22] use "=" for dependencies to ensure exactly equal version ...so that things don't break when projects change. --- package.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index f019316c3..2db90c93d 100644 --- a/package.json +++ b/package.json @@ -56,15 +56,15 @@ "binary": "=0.3.0", "step": "=0.0.4", "buffers": "=0.1.1", - "buffertools": "~2.0.1", - "browserify": "~3.32.1", - "browser-pack": "~2.0.1", - "commander": "~2.1.0", + "buffertools": "=2.1.2", + "browserify": "=3.40.0", + "browser-pack": "=2.0.1", + "commander": "=2.1.0", "browserify-bignum": "git://github.com/maraoz/browserify-bignum.git", "browserify-buffertools": "git://github.com/maraoz/browserify-buffertools.git", - "brfs": "~1.0.0", - "chai": "~1.9.0", - "uglifyify": "~1.2.3" + "brfs": "=1.0.0", + "chai": "=1.9.1", + "uglifyify": "=1.2.3" }, "devDependencies": { "grunt-contrib-watch": "~0.5.3", From 6a5aa76b76fd5f799d4d7f88ea6e4c32a6366e88 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 10 Apr 2014 18:19:13 -0300 Subject: [PATCH 10/22] Buffers.monkey now at 100% coverage --- test/test.misc.js | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/test/test.misc.js b/test/test.misc.js index b3ecda63b..2354efdd9 100644 --- a/test/test.misc.js +++ b/test/test.misc.js @@ -3,6 +3,7 @@ var chai = chai || require('chai'); var bitcore = bitcore || require('../bitcore'); var buffertools = require('buffertools'); +buffertools.extend(); var should = chai.should(); @@ -15,6 +16,7 @@ var base58Check = base58.base58Check; var Address = bitcore.Address; var networks = bitcore.networks; var WalletKey = bitcore.WalletKey; +var Buffers = require('buffers'); describe('Miscelaneous stuff', function() { it('should initialze the config object', function() { @@ -26,7 +28,7 @@ describe('Miscelaneous stuff', function() { it('should initialze the network object', function() { should.exist(networks); var nets = [networks.livenet, networks.testnet]; - for (var i=0; i<2; i++) { + for (var i = 0; i < 2; i++) { var net = nets[i]; should.exist(net.addressVersion); should.exist(net.privKeyVersion); @@ -42,8 +44,36 @@ describe('Miscelaneous stuff', function() { should.exist(bitcore.Deserialize); should.exist(bitcore.Deserialize.intFromCompact); }); + it('should initialze the Buffer class', function() { + should.exist(bitcore.Buffer); + }); + describe('Buffers monkey patch', function() { + var bufs; + beforeEach(function() { + bufs = new Buffers(); + bufs.push(new Buffer([1, 2, 3])); + bufs.push(new Buffer([4, 5, 6, 7])); + bufs.push(new Buffer([8, 9, 10])); + }); + it('should monkey patch the Buffers class', function() { + require('../Buffers.monkey').patch(Buffers); + should.exist(bufs.skip); + }); + it('should work for 0', function() { + bufs.skip(0); + bufs.toBuffer().toHex().should.equal('0102030405060708090a'); + }); + it('should work for length', function() { + bufs.skip(bufs.length); + bufs.toBuffer().toHex().should.equal(''); + }); + it('should work for middle values', function() { + bufs.skip(5); + bufs.toBuffer().toHex().should.equal('060708090a'); + }); + }); // bignum it('should initialze the bignum object', function() { should.exist(bitcore.bignum); @@ -165,8 +195,10 @@ describe('Miscelaneous stuff', function() { priv: b58 }); }; - createLivenet.should.throw(); - createTestnet.should.throw(); + createLivenet.should. + throw (); + createTestnet.should. + throw (); }); }); From b58d5c508414720e7cec7ae9fb697318a9430e4f Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 10 Apr 2014 18:24:20 -0300 Subject: [PATCH 11/22] fix formatting --- test/test.misc.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/test.misc.js b/test/test.misc.js index 2354efdd9..fd212396d 100644 --- a/test/test.misc.js +++ b/test/test.misc.js @@ -195,10 +195,8 @@ describe('Miscelaneous stuff', function() { priv: b58 }); }; - createLivenet.should. - throw (); - createTestnet.should. - throw (); + createLivenet.should.throw(); + createTestnet.should.throw(); }); }); From 3cbcbd54cb7a4da9f1be3a263c8c328830ba04d8 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 10 Apr 2014 18:52:13 -0300 Subject: [PATCH 12/22] fix Buffers.skip in the browser --- Buffers.monkey.js | 3 +-- bitcore.js | 1 + browser/build.js | 3 +++ test/test.misc.js | 19 ++++++++++++------- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Buffers.monkey.js b/Buffers.monkey.js index ef7c73d26..5cf677085 100644 --- a/Buffers.monkey.js +++ b/Buffers.monkey.js @@ -9,8 +9,7 @@ exports.patch = function(Buffers) { } var pos = this.pos(i); this.buffers = this.buffers.slice(pos.buf); - this.buffers[0].length -= pos.offset; - this.buffers[0].offset += pos.offset; + this.buffers[0] = new Buffer(this.buffers[0].slice(pos.offset)); this.length -= i; }; }; diff --git a/bitcore.js b/bitcore.js index 93e1a8dd4..66eb47cfb 100644 --- a/bitcore.js +++ b/bitcore.js @@ -14,6 +14,7 @@ requireWhenAccessed('bignum', 'bignum'); requireWhenAccessed('base58', 'base58-native'); requireWhenAccessed('bufferput', 'bufferput'); requireWhenAccessed('buffertools', 'buffertools'); +requireWhenAccessed('Buffers.monkey', './Buffers.monkey'); requireWhenAccessed('config', './config'); requireWhenAccessed('const', './const'); requireWhenAccessed('Deserialize', './Deserialize'); diff --git a/browser/build.js b/browser/build.js index 941d52078..41280cf10 100644 --- a/browser/build.js +++ b/browser/build.js @@ -101,6 +101,9 @@ var createBitcore = function(opts) { b.require(opts.dir + 'base58-native', { expose: 'base58-native' }); + b.require(opts.dir + 'buffers', { + expose: 'buffers' + }); b.require('./' + opts.dir + 'bitcore', { expose: 'bitcore' }); diff --git a/test/test.misc.js b/test/test.misc.js index fd212396d..f3da0b852 100644 --- a/test/test.misc.js +++ b/test/test.misc.js @@ -17,6 +17,8 @@ var Address = bitcore.Address; var networks = bitcore.networks; var WalletKey = bitcore.WalletKey; var Buffers = require('buffers'); +var m = bitcore['Buffers.monkey'] || require('../Buffers.monkey'); +m.patch(Buffers); describe('Miscelaneous stuff', function() { it('should initialze the config object', function() { @@ -53,25 +55,28 @@ describe('Miscelaneous stuff', function() { var bufs; beforeEach(function() { bufs = new Buffers(); - bufs.push(new Buffer([1, 2, 3])); - bufs.push(new Buffer([4, 5, 6, 7])); - bufs.push(new Buffer([8, 9, 10])); + bufs.push(new Buffer('aaaaaa', 'hex')); + bufs.push(new Buffer('bbbb', 'hex')); + bufs.push(new Buffer('cc', 'hex')); }); it('should monkey patch the Buffers class', function() { - require('../Buffers.monkey').patch(Buffers); should.exist(bufs.skip); }); it('should work for 0', function() { bufs.skip(0); - bufs.toBuffer().toHex().should.equal('0102030405060708090a'); + bufs.toBuffer().toHex().should.equal('aaaaaabbbbcc'); }); it('should work for length', function() { bufs.skip(bufs.length); bufs.toBuffer().toHex().should.equal(''); }); it('should work for middle values', function() { - bufs.skip(5); - bufs.toBuffer().toHex().should.equal('060708090a'); + bufs.skip(4); + bufs.toBuffer().toHex().should.equal('bbcc'); + bufs.skip(1); + bufs.toBuffer().toHex().should.equal('cc'); + bufs.skip(1); + bufs.toBuffer().toHex().should.equal(''); }); }); // bignum From d507e7f3d508800badb822a5dbe5a13766970063 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Thu, 10 Apr 2014 19:43:28 -0300 Subject: [PATCH 13/22] add signatureAdded counter --- TransactionBuilder.js | 10 ++++++---- test/test.TransactionBuilder.js | 7 +++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/TransactionBuilder.js b/TransactionBuilder.js index 7ef7ac828..bd91648fa 100644 --- a/TransactionBuilder.js +++ b/TransactionBuilder.js @@ -110,6 +110,7 @@ function TransactionBuilder(opts) { this.tx = {}; this.inputsSigned= 0; + this.signaturesAdded= 0; return this; } @@ -482,7 +483,7 @@ TransactionBuilder.prototype._signPubKey = function(walletKeyMap, input, txSigHa var scriptSig = new Script(); scriptSig.chunks.push(sig); scriptSig.updateBuffer(); - return {isFullySigned: true, signaturesAdded: true, script: scriptSig.getBuffer()}; + return {isFullySigned: true, signaturesAdded: 1, script: scriptSig.getBuffer()}; }; TransactionBuilder.prototype._signPubKeyHash = function(walletKeyMap, input, txSigHash) { @@ -501,7 +502,7 @@ TransactionBuilder.prototype._signPubKeyHash = function(walletKeyMap, input, txS scriptSig.chunks.push(sig); scriptSig.chunks.push(wk.privKey.public); scriptSig.updateBuffer(); - return {isFullySigned: true, signaturesAdded: true, script: scriptSig.getBuffer()}; + return {isFullySigned: true, signaturesAdded: 1, script: scriptSig.getBuffer()}; }; // FOR TESTING @@ -577,7 +578,7 @@ TransactionBuilder.prototype._signMultiSig = function(walletKeyMap, input, txSig originalScriptBuf = this.tx.ins[input.i].s; var scriptSig = new Script (originalScriptBuf); - var signaturesAdded = false; + var signaturesAdded = 0; for(var j=0; j Date: Thu, 10 Apr 2014 23:30:04 -0300 Subject: [PATCH 14/22] add normalized hash for Txs --- Transaction.js | 18 +++++++++++++++++- test/test.Transaction.js | 16 ++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/Transaction.js b/Transaction.js index fe065634b..ea5ef3b5b 100644 --- a/Transaction.js +++ b/Transaction.js @@ -197,6 +197,22 @@ Transaction.prototype.getHash = function getHash() { return this.hash; }; + +Transaction.prototype.calcNormalizedHash = function () { + this.normalizedHash = this.hashForSignature(new Script(),0, SIGHASH_ALL); + return this.normalizedHash; +}; + + +Transaction.prototype.getNormalizedHash = function () { + if (!this.normalizedHash || !this.normalizedHash.length) { + this.normalizedHash = this.calcNormalizedHash(); + } + return this.normalizedHash; +}; + + + // convert encoded list of inputs to easy-to-use JS list-of-lists Transaction.prototype.inputs = function inputs() { var res = []; @@ -568,7 +584,7 @@ Transaction.prototype.calcSize = function() { return totalSize; }; -Transaction.prototype.getSize = function getHash() { +Transaction.prototype.getSize = function () { if (!this.size) { this.size = this.calcSize(); } diff --git a/test/test.Transaction.js b/test/test.Transaction.js index 29364c2c6..df68753f1 100644 --- a/test/test.Transaction.js +++ b/test/test.Transaction.js @@ -121,4 +121,20 @@ describe('Transaction', function() { coreTest(testdata.dataTxValid, true); coreTest(testdata.dataTxInvalid, false); + it('#normalized hash', function() { + // string output generated from: bitcoind createrawtransaction '[{"txid": "2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc1","vout":1},{"txid":"2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc2","vout":0} ]' '{"mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE":0.08}' + // + var Parser = bitcore.BinaryParser; + var tx = new Transaction(); + tx.parse(new Buffer('0100000002c1cf12ab89729d19d3cdec8ae531b5038d56c741006a105d532b3a7afa65c12a0100000000ffffffffc2cf12ab89729d19d3cdec8ae531b5038d56c741006a105d532b3a7afa65c12a0000000000ffffffff0100127a00000000001976a914774e603bafb717bd3f070e68bbcccfd907c77d1388ac00000000','hex')); + + tx.getNormalizedHash().toString('hex').should.equal('1f7d2666e2d0d663e098abb76db6ba392da972d21c14b6ea6f4336171d29966b'); + + var tx2 = new Transaction(); + tx2.parse(new Buffer('0100000001c1cf12ab89729d19d3cdec8ae531b5038d56c741006a105d532b3a7afa65c12a010000004b00473044022059085ff1b8ad03033e60969b1c770aa29ba5d74c28a9992c514b100d860792f1022057a307f77f91f4563651eefc0a959aa916d275c58525320309b6aeeff43d0d8a010000ffffffff0215cd5b07000000001976a91434f8e0c5be216025a52addf18a987543cad23f7a88acdbd53e340000000017a9147a769913c0721b1e0aa6bf8a93f4ef810c60587a8700000000','hex')); + + tx2.getNormalizedHash().toString('hex').should.equal('e298bbf3734898581b8e342f2064236abf0acca6ac7e9a3009a16ef7b64d4983'); + }); + + }); From 2d9afbd635e958db3253413414c4371f7cc94b9c Mon Sep 17 00:00:00 2001 From: olalonde Date: Fri, 11 Apr 2014 15:53:40 +0800 Subject: [PATCH 15/22] Transaction.js: removed confusing this.class assignment in file scope --- Transaction.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Transaction.js b/Transaction.js index fe065634b..f17eaeb87 100644 --- a/Transaction.js +++ b/Transaction.js @@ -125,7 +125,6 @@ function Transaction(data) { }) : []; if (data.buffer) this._buffer = data.buffer; }; -this.class = Transaction; Transaction.In = TransactionIn; Transaction.Out = TransactionOut; From 66428e00bcd3fe00a71c6b601af7186b5e225452 Mon Sep 17 00:00:00 2001 From: olalonde Date: Fri, 11 Apr 2014 16:15:54 +0800 Subject: [PATCH 16/22] Script: removed dead code this.class = Script --- Script.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Script.js b/Script.js index a4ffbd2cd..c9755388f 100644 --- a/Script.js +++ b/Script.js @@ -36,7 +36,6 @@ function Script(buffer) { this.chunks = []; this.parse(); } -this.class = Script; Script.TX_UNKNOWN = TX_UNKNOWN; Script.TX_PUBKEY = TX_PUBKEY; From 9aa210bccb65933e35c3911a67002a71d10414f9 Mon Sep 17 00:00:00 2001 From: olalonde Date: Fri, 11 Apr 2014 18:08:07 +0800 Subject: [PATCH 17/22] TxIn: add sequence to standardized object --- Transaction.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Transaction.js b/Transaction.js index fe065634b..f3a8dd097 100644 --- a/Transaction.js +++ b/Transaction.js @@ -432,7 +432,8 @@ Transaction.prototype.getStandardizedObject = function getStandardizedObject() { prev_out: { hash: buffertools.reverse(new Buffer(txin.getOutpointHash())).toString('hex'), n: txin.getOutpointIndex() - } + }, + sequence: (txin.q === 0xffffffff) ? null : txin.q }; if (txin.isCoinBase()) { txinObj.coinbase = txin.s.toString('hex'); From 7a88c3116471bb3a539105c8aa83b806ab49eba4 Mon Sep 17 00:00:00 2001 From: xubo zhang Date: Fri, 11 Apr 2014 18:23:06 +0800 Subject: [PATCH 18/22] change remainderAddress to remainderOut MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit should use remainderOut in TransactionBuilder’s opts; --- README.md | 2 +- examples/CreateAndSignTx-PayToPubkeyHash.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1cd568f9b..3c71e035d 100644 --- a/README.md +++ b/README.md @@ -176,7 +176,7 @@ peerman.on('connect', function() { var conn = peerman.getActiveConnection(); if (conn) { var outs = [{address:toAddress, amount:amt}]; - var opts = {remainderAddress: changeAddressString}; + var opts = {remainderOut: {address: changeAddressString}}; var Builder = bitcore.TransactionBuilder; var tx = new Builder(opts) diff --git a/examples/CreateAndSignTx-PayToPubkeyHash.js b/examples/CreateAndSignTx-PayToPubkeyHash.js index 1c2273e6c..4d703ce39 100644 --- a/examples/CreateAndSignTx-PayToPubkeyHash.js +++ b/examples/CreateAndSignTx-PayToPubkeyHash.js @@ -25,7 +25,7 @@ var run = function() { var outs = [{address:toAddress, amount:amt}]; var keys = [priv]; - var opts = {remainderAddress: changeAddressString}; + var opts = {remainderOut: {address: changeAddressString}}; var Builder = bitcore.TransactionBuilder; var tx = new Builder(opts) From 91a857f424ac2ac2a6e1065530da1ce3ba889152 Mon Sep 17 00:00:00 2001 From: olalonde Date: Fri, 11 Apr 2014 23:50:32 +0800 Subject: [PATCH 19/22] TxIn: don't set sequence to null if 0xffffffff --- Transaction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Transaction.js b/Transaction.js index f3a8dd097..20d86e809 100644 --- a/Transaction.js +++ b/Transaction.js @@ -433,7 +433,7 @@ Transaction.prototype.getStandardizedObject = function getStandardizedObject() { hash: buffertools.reverse(new Buffer(txin.getOutpointHash())).toString('hex'), n: txin.getOutpointIndex() }, - sequence: (txin.q === 0xffffffff) ? null : txin.q + sequence: txin.q }; if (txin.isCoinBase()) { txinObj.coinbase = txin.s.toString('hex'); From 174a3ca17c41a7c5895c97295eb68ee4cba5a23a Mon Sep 17 00:00:00 2001 From: olalonde Date: Sat, 12 Apr 2014 00:33:06 +0800 Subject: [PATCH 20/22] Transaction: set TransactionIn.MAX_SEQUENCE constant --- Transaction.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Transaction.js b/Transaction.js index 20d86e809..a97a8b737 100644 --- a/Transaction.js +++ b/Transaction.js @@ -40,6 +40,8 @@ function TransactionIn(data) { this.q = data.q ? data.q : data.sequence; } +TransactionIn.MAX_SEQUENCE = 0xffffffff; + TransactionIn.prototype.getScript = function getScript() { return new Script(this.s); }; From e61aa8528f402a909da91178e5e017a722f8ecc2 Mon Sep 17 00:00:00 2001 From: "Ryan X. Charles" Date: Fri, 11 Apr 2014 14:23:19 -0300 Subject: [PATCH 21/22] add some tests to make sure changes to Key C++ code work as expected --- test/test.Key.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/test.Key.js b/test/test.Key.js index aa412560e..9eb988239 100644 --- a/test/test.Key.js +++ b/test/test.Key.js @@ -16,6 +16,21 @@ describe('Key', function() { var k = new Key(); should.exist(k); }); + it('should not fail when called as Key() without "new"', function() { + var key = Key(); + should.exist(key); + }); + it('should not fail when called as Key() without "new" with some args', function() { + var key = Key(1, 2, 3, 4, 5); + should.exist(key); + }); + it('should have correct properties when called with Key() without "new"', function() { + var key = Key(); + key.compressed.should.equal(true); + should.not.exist(key.public); + should.not.exist(key.private); + should.exist(key); + }); it('should be able to generateSync instance', function() { var k = Key.generateSync(); should.exist(k); From 387185e626f8333005705601796bcc466b13dc2d Mon Sep 17 00:00:00 2001 From: "Ryan X. Charles" Date: Fri, 11 Apr 2014 14:23:41 -0300 Subject: [PATCH 22/22] remove commented-out code --- src/eckey.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/eckey.cc b/src/eckey.cc index e5616c6a9..41993682e 100644 --- a/src/eckey.cc +++ b/src/eckey.cc @@ -164,8 +164,6 @@ Key::New(const Arguments& args) // this was invoked as Key() not new Key() if (!args.IsConstructCall()) { -// return FromConstructorTemplate(s_ct, args); - const int argc = 1; Local argv[argc] = { args[0] }; return scope.Close(s_ct->GetFunction()->NewInstance(argc, argv));