simplified and cached address derivation

This commit is contained in:
Matias Alejo Garcia 2014-11-28 18:43:22 -03:00
commit a8f0401e8e
6 changed files with 297 additions and 381 deletions

View file

@ -887,7 +887,6 @@ Wallet.prototype._lockIncomming = function() {
Wallet.prototype._setBlockchainListeners = function() {
console.log('[Wallet.js.889] address'); //TODO
var self = this;
self.blockchain.removeAllListeners();
self.subscribeToAddresses();
@ -902,14 +901,12 @@ console.log('[Wallet.js.889] address'); //TODO
log.debug('Wallet:' + self.id + 'blockchain disconnect event');
self.emitAndKeepAlive('insightError');
});
self.blockchain.on('tx', function(tx) {
log.debug('Wallet:' + self.id + ' blockchain tx event');
var addresses = self.getAddressesInfo();
var addr = _.findWhere(addresses, {
addressStr: tx.address
});
if (addr) {
self.emitAndKeepAlive('tx', tx.address, addr.isChange);
var addresses = self.getAddresses();
if (_.indexOf(addresses,tx.address)>=0) {
self.emitAndKeepAlive('tx', tx.address, self.addressIsChange(tx.address));
}
});
@ -1055,6 +1052,7 @@ Wallet.prototype.toObj = function() {
settings: this.settings,
networkNonce: this.network.getHexNonce(), //yours
networkNonces: this.network.getHexNonces(), //copayers
publicKeyRing: this.publicKeyRing.toObj(),
txProposals: this.txProposals.toObj(),
privateKey: this.privateKey ? this.privateKey.toObj() : undefined,
addressBook: this.addressBook,
@ -1376,21 +1374,15 @@ Wallet.prototype._doGenerateAddress = function(isChange) {
return this.publicKeyRing.generateAddress(isChange, this.publicKey);
};
/**
* @callback addressCallback
* @param {string} addr - all the addresses of the wallet
*/
/**
* @desc Generate a new address
* @param {boolean} isChange - whether to generate a change address or a receive address
* @param {addressCallback} cb
* @return {string[]} a list of all the addresses generated so far for the wallet
*/
Wallet.prototype.generateAddress = function(isChange, cb) {
Wallet.prototype.generateAddress = function(isChange) {
var addr = this._doGenerateAddress(isChange);
this.sendIndexes();
this._newAddresses();
if (cb) return cb(addr);
return addr;
};
@ -1844,12 +1836,21 @@ Wallet.prototype.parsePaymentRequest = function(options, rawData) {
*/
Wallet.prototype._getPayProRefundOutputs = function(txp) {
var pkr = this.publicKeyRing;
var index = pkr.getHDParams(this.publicKey);
var amount = +txp.merchant.total.toString(10);
var output = new PayPro.Output();
var script = pkr.getScriptPubKeyHex(index.changeIndex, true, this.pubkey);
output.set('script', new Buffer(script, 'hex'));
var opts = JSON.parse(txp.builder.vanilla.opts);
if (!opts.remainderOut) {
log.warn('no remainder set. Not setting refund in PayPro');
return;
}
console.log('[Wallet.js.1842:builder:]',txp.builder.vanilla.opts); //TODO
var addrStr = opts.remainderOut.address;
var addr = new bitcore.Address(addrStr);
var script = bitcore.Script.createP2SH(addr.payload()).getBuffer();
log.debug('PayPro refund address set to:' + addrStr);
output.set('script', script);
output.set('amount', amount);
return [output];
};
@ -1867,7 +1868,6 @@ Wallet.prototype.createPayProPayment = function(txp) {
var tx = txp.builder.build();
var txBuf = tx.serialize();
var refund_outputs = this._getPayProRefundOutputs(txp);
// We send this to the serve after receiving a PaymentRequest
var pay = new PayPro();
@ -1878,9 +1878,11 @@ Wallet.prototype.createPayProPayment = function(txp) {
merchant_data = new Buffer(merchant_data, 'hex');
pay.set('merchant_data', merchant_data);
}
pay.set('transactions', [txBuf]);
pay.set('refund_to', refund_outputs);
var refund_outputs = this._getPayProRefundOutputs(txp);
if (refund_outputs)
pay.set('refund_to', refund_outputs);
// Unused for now
// options.memo = '';
@ -2002,28 +2004,32 @@ Wallet.prototype.getAddressesStr = function(opts) {
Wallet.prototype.subscribeToAddresses = function() {
if (!this.publicKeyRing.isComplete()) return;
console.log('[Wallet.js.2002:subscribeToAddresses:]'); //TODO
var addrInfo = this.publicKeyRing.getAddressesInfo();
this.blockchain.subscribe(_.pluck(addrInfo, 'addressStr'));
log.debug('Subscribed to ' + addrInfo.length + ' addresses');
var addresses = this.publicKeyRing.getAddresses();
this.blockchain.subscribe(addresses);
log.debug('Subscribed to ' + addresses.length + ' addresses');
};
/**
* @desc Alias for {@link PublicKeyRing#getAddressesInfo}
*/
Wallet.prototype.getAddressesInfo = function(opts) {
return this.publicKeyRing.getAddressesInfo(opts, this.publicKey);
};
/**
* @desc Returns true if a given address was generated by deriving our master public key
* @return {boolean}
*/
Wallet.prototype.addressIsOwn = function(addrStr) {
return !!this.publicKeyRing.addressToPath[addrStr];
return this.publicKeyRing.addressIsOwn(addrStr);
};
/**
* @desc Returns true if a given address is a change address (remainder)
* @param addrStr
* @return {boolean}
*/
Wallet.prototype.addressIsChange = function(addrStr) {
return this.publicKeyRing.addressIsChange(addrStr);
};
/**
* Estimate a tx fee in satoshis given its input count
* (only used when spending all wallet funds)
@ -2110,7 +2116,7 @@ Wallet.prototype.maxRejectCount = function() {
// TODO: Can we add cache to getUnspent?
Wallet.prototype.getUnspent = function(cb) {
var self = this;
this.blockchain.getUnspent(this.getAddressesStr(), function(err, unspentList) {
this.blockchain.getUnspent(this.getAddresses(), function(err, unspentList) {
if (err) {
return cb(err);
@ -2372,7 +2378,8 @@ Wallet.prototype.deriveAddresses = function(index, amount, isChange, copayerInde
var ret = new Array(amount);
for (var i = 0; i < amount; i++) {
ret[i] = this.publicKeyRing.getAddress(index + i, isChange, copayerIndex).toString();
// TODO
ret[i] = this.publicKeyRing._getAddress(index + i, isChange, copayerIndex).toString();
}
return ret;
};
@ -2534,7 +2541,7 @@ Wallet.prototype.getTransactionHistory = function(opts, cb) {
}
opts = opts || {};
var addresses = self.getAddressesInfo();
var addresses = self.getAddresses();
var proposals = self.txProposals.txps;
var satToUnit = 1 / self.settings.unitToSatoshi;
@ -2544,33 +2551,26 @@ Wallet.prototype.getTransactionHistory = function(opts, cb) {
function extractInsOuts(tx) {
// Inputs
var inputs = _.map(tx.vin, function(item) {
var addr = _.findWhere(addresses, {
addressStr: item.addr
});
return {
type: 'in',
address: addr ? addr.addressStr : item.addr,
isMine: !_.isUndefined(addr),
isChange: addr ? !!addr.isChange : false,
address: item.addr,
isMine: self.addressIsOwn(item.addr),
isChange: self.addressIsChange(item.addr),
amountSat: item.valueSat,
}
});
var outputs = _.map(tx.vout, function(item) {
var addr;
var itemAddr;
// If classic multisig, ignore
if (item.scriptPubKey && item.scriptPubKey.addresses.length == 1) {
itemAddr = item.scriptPubKey.addresses[0];
addr = _.findWhere(addresses, {
addressStr: itemAddr,
});
}
return {
type: 'out',
address: addr ? addr.addressStr : itemAddr,
isMine: !_.isUndefined(addr),
isChange: addr ? !!addr.isChange : false,
address: itemAddr,
isMine: self.addressIsOwn(itemAddr),
isChange: self.addressIsChange(itemAddr),
label: self.addressBook[itemAddr] ? self.addressBook[itemAddr].label : undefined,
amountSat: parseInt((item.value * bitcore.util.COIN).toFixed(0)),
}
@ -2608,6 +2608,8 @@ Wallet.prototype.getTransactionHistory = function(opts, cb) {
var fees = parseInt((tx.fees * bitcore.util.COIN).toFixed(0));
var amount;
if (amountIn == (amountOut + amountOutChange + (amountIn > 0 ? fees : 0))) {
tx.action = 'moved';
amount = amountOut;