diff --git a/copay.js b/copay.js index 258fe8d3c..7ed2f3804 100644 --- a/copay.js +++ b/copay.js @@ -4,4 +4,5 @@ module.exports.PublicKeyRing = require('./js/models/PublicKeyRing'); module.exports.Wallet = require('./js/models/Wallet'); module.exports.TxProposals = require('./js/models/TxProposals'); module.exports.CopayPeer = require('./js/models/CopayPeer'); +module.exports.PrivateKey = require('./js/models/PrivateKey'); module.exports.FakeStorage = require('./test/FakeStorage'); diff --git a/js/models/PrivateKey.js b/js/models/PrivateKey.js new file mode 100644 index 000000000..8e60ebf05 --- /dev/null +++ b/js/models/PrivateKey.js @@ -0,0 +1,35 @@ +'use strict'; + + +var imports = require('soop').imports(); +var bitcore = require('bitcore'); +var BIP32 = bitcore.BIP32; +var WalletKey = bitcore.WalletKey; +var networks = bitcore.networks; +var PublicKeyRing = require('./PublicKeyRing'); + +function PrivateKey(opts) { + this.id = opts.id; + this.network = opts.networkName === 'testnet' ? + networks.testnet : networks.livenet; + this.BIP32 = opts.BIP32 || new BIP32(this.network.name); +}; + + +PrivateKey.prototype.getBIP32 = function(index,isChange) { + if (typeof index === 'undefined') { + return this.BIP32; + } + return this.BIP32.derive( isChange ? + PublicKeyRing.ChangeBranch(index):PublicKeyRing.PublicBranch(index) ); +}; + +PrivateKey.prototype.get = function(index,isChange) { + var derivedBIP32 = this.getBIP32(index,isChange); + var wk = new WalletKey({network: this.network}); + var p = derivedBIP32.eckey.private.toString('hex'); + wk.fromObj({priv: p}); + return wk; +}; + +module.exports = require('soop')(PrivateKey); diff --git a/js/models/TxProposals.js b/js/models/TxProposals.js index d823a4d5e..ab414ce85 100644 --- a/js/models/TxProposals.js +++ b/js/models/TxProposals.js @@ -12,17 +12,13 @@ var buffertools = bitcore.buffertools; var Storage = imports.Storage || require('./Storage'); var storage = Storage.default(); -/* - * This follow Electrum convetion, as described in - * https://bitcointalk.org/index.php?topic=274182.0 - * - * We should probably adopt the next standard once it's ready, as discussed in: - * http://sourceforge.net/p/bitcoin/mailman/message/32148600/ - * - */ +function TxProposal(opts) { + this.tx = opts.tx; + this.seenBy = {}; + this.signedBy = {}; +}; +module.exports = require('soop')(TxProposal); -var PUBLIC_BRANCH = 'm/0/'; -var CHANGE_BRANCH = 'm/1/'; function TxProposals(opts) { opts = opts || {}; @@ -36,9 +32,9 @@ function TxProposals(opts) { this.dirty = 1; } - TxProposals.prototype.list = function() { var ret = []; + var ret = []; this.txs.forEach(function(tx) { }); @@ -66,9 +62,16 @@ TxProposals.prototype.create = function(toAddress, amountSat, utxos, onePrivKey) } var tx = b.build(); - var txHex = tx.serialize(); - this.txs.push(txHex); - return txHex; + this.txs.push( + new TxProposal({ + signedBy: { + }, + seenBy: { + }, + tx: tx + }) + ); + return tx; }; TxProposals.prototype.sign = function(index) { diff --git a/test/test.PrivateKey.js b/test/test.PrivateKey.js new file mode 100644 index 000000000..30c7ddd91 --- /dev/null +++ b/test/test.PrivateKey.js @@ -0,0 +1,50 @@ +'use strict'; + +var chai = chai || require('chai'); +var should = chai.should(); +var bitcore = bitcore || require('bitcore'); +var Transaction = bitcore.Transaction; +var buffertools = bitcore.buffertools; +var WalletKey = bitcore.WalletKey; +var Key = bitcore.Key; +var BIP32 = bitcore.BIP32; +var bignum = bitcore.bignum; +var networks = bitcore.networks; +var Address = bitcore.Address; +var BitcorePrivateKey = bitcore.PrivateKey; +var copay = copay || require('../copay'); +var PrivateKey = copay.PrivateKey || require('../js/models/PrivateKey'); + +var config = { + networkName:'livenet', +}; + +describe('PrivateKey model', function() { + + it('should create an instance', function () { + var w = new PrivateKey(config); + should.exist(w); + should.exist(w.BIP32); + should.exist(w.BIP32.derive); + }); + + it('should derive priv keys', function () { + var w = new PrivateKey(config); + for(var j=0; j<2; j++) { + for(var i=0; i<3; i++) { + var wk = w.get(i,j); + should.exist(wk); + var o=wk.storeObj(); + should.exist(o); + should.exist(o.priv); + should.exist(o.pub); + should.exist(o.addr); + var a = new Address(o.addr); + a.isValid().should.equal(true); + (function() { + var p = new PrivateKey(o.priv) + }).should.not.throw(); + } + } + }); +}); diff --git a/test/test.txproposal.js b/test/test.txproposal.js index adcafbc0a..164ffbb2c 100644 --- a/test/test.txproposal.js +++ b/test/test.txproposal.js @@ -12,6 +12,7 @@ var bignum = bitcore.bignum; var networks = bitcore.networks; var copay = copay || require('../copay'); var fakeStorage = copay.FakeStorage; +var PrivateKey = copay.PrivateKey || require('../js/models/PrivateKey'); var TxProposals = copay.TxProposals || require('../js/models/TxProposal'); var PublicKeyRing = (typeof process.versions === 'undefined') ? copay.PublicKeyRing : require('soop').load('../js/models/PublicKeyRing', {Storage: fakeStorage}); @@ -74,25 +75,21 @@ describe('TxProposals model', function() { unspentTest[0].address = w.publicKeyRing.getAddress(1, true); unspentTest[0].scriptPubKey = w.publicKeyRing.getRedeemScript(1, true).getBuffer(); - var txHex = w.create( + var tx = w.create( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', bignum('123456789'), unspentTest ); - should.exist(txHex); - - var t2=new Transaction(); - t2.parse(txHex); - t2.isComplete().should.equal(false); + should.exist(tx); + tx.isComplete().should.equal(false); }); it('#create. Singing with derivate keys', function () { - var oneBIP32 = new BIP32(config.networkName); - + var priv = new PrivateKey(config); var w = new TxProposals({ networkName: config.networkName, - publicKeyRing: createW([oneBIP32]), + publicKeyRing: createW([priv.getBIP32()]), }); should.exist(w); w.network.name.should.equal('livenet'); @@ -103,22 +100,15 @@ describe('TxProposals model', function() { unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange); unspentTest[0].scriptPubKey = w.publicKeyRing.getRedeemScript(index, isChange).getBuffer(); - var derivedBip32 = oneBIP32.derive( isChange ? PublicKeyRing.ChangeBranch(index):PublicKeyRing.PublicBranch(index) ); - var wk = new WalletKey({network: networks.livenet}); - var p = derivedBip32.eckey.private.toString('hex'); - wk.fromObj({priv: p}); - - var txHex = w.create( + var tx = w.create( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', bignum('123456789'), unspentTest, - wk + priv.get(index,isChange) ); - should.exist(txHex); - var t2=new Transaction(); - t2.parse(txHex); - t2.isComplete().should.equal(false); - t2.countInputMissingSignatures(0).should.equal(2); + should.exist(tx); + tx.isComplete().should.equal(false); + tx.countInputMissingSignatures(0).should.equal(2); } }