mirror of https://github.com/BTCPrivate/copay.git
BIP32 PrivateKey wrapper
This commit is contained in:
parent
1caea99917
commit
972ffb34b6
1
copay.js
1
copay.js
|
@ -3,4 +3,5 @@ module.exports.Storage = require('./js/models/Storage');
|
|||
module.exports.PublicKeyRing = require('./js/models/PublicKeyRing');
|
||||
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');
|
||||
|
|
|
@ -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);
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue