wallet/keypair: fixes.

This commit is contained in:
Christopher Jeffrey 2016-02-02 13:43:43 -08:00
parent 156601e40a
commit f3fd85354e
3 changed files with 54 additions and 32 deletions

View File

@ -5,10 +5,7 @@
*/ */
var bcoin = require('../bcoin'); var bcoin = require('../bcoin');
var hash = require('hash.js');
var bn = require('bn.js'); var bn = require('bn.js');
var inherits = require('inherits');
var EventEmitter = require('events').EventEmitter;
var utils = bcoin.utils; var utils = bcoin.utils;
var assert = utils.assert; var assert = utils.assert;
var constants = bcoin.protocol.constants; var constants = bcoin.protocol.constants;
@ -32,36 +29,36 @@ function KeyPair(options) {
return options.key; return options.key;
this.options = options; this.options = options;
this.key = options.key || null; this._key = options.key || null;
this.hd = options.hd || null; this.hd = options.hd || null;
this.compressed = options.compressed !== false; this.compressed = options.compressed !== false;
if (options.priv instanceof bcoin.hd.priv) { if (options.priv instanceof bcoin.hd.priv) {
this.hd = options.priv; this.hd = options.priv;
this.key = options.priv.pair; this._key = options.priv.pair;
} else if (options.pub instanceof bcoin.hd.pub) { } else if (options.pub instanceof bcoin.hd.pub) {
this.hd = options.pub; this.hd = options.pub;
this.key = options.pub.pair; this._key = options.pub.pair;
} else if (options.hd) { } else if (options.hd) {
this.hd = typeof options.hd === 'object' this.hd = typeof options.hd === 'object'
? bcoin.hd.priv(options.hd) ? bcoin.hd.priv(options.hd)
: bcoin.hd.priv(); : bcoin.hd.priv();
this.key = this.hd.pair; this._key = this.hd.pair;
} else if (options.key) { } else if (options.key) {
if ((options.key instanceof bcoin.hd.priv) if ((options.key instanceof bcoin.hd.priv)
|| (options.key instanceof bcoin.hd.pub)) { || (options.key instanceof bcoin.hd.pub)) {
this.hd = options.key; this.hd = options.key;
this.key = options.key.pair; this._key = options.key.pair;
} else { } else {
this.key = options.key; this._key = options.key;
} }
} else if (options.priv || options.pub) { } else if (options.priv || options.pub) {
this.key = bcoin.ecdsa.keyPair({ this._key = bcoin.ecdsa.keyPair({
priv: options.priv, priv: options.priv,
pub: options.pub pub: options.pub
}); });
} else { } else {
this.key = bcoin.ecdsa.genKeyPair({ this._key = bcoin.ecdsa.genKeyPair({
pers: options.personalization, pers: options.personalization,
entropy: options.entropy entropy: options.entropy
|| (options.passphrase ? utils.sha256(options.passphrase) : null) || (options.passphrase ? utils.sha256(options.passphrase) : null)
@ -70,15 +67,15 @@ function KeyPair(options) {
} }
KeyPair.prototype.__defineGetter__('priv', function() { KeyPair.prototype.__defineGetter__('priv', function() {
return this.key.getPrivate(); return this._key.getPrivate();
}); });
KeyPair.prototype.__defineGetter__('pub', function() { KeyPair.prototype.__defineGetter__('pub', function() {
return this.key.getPublic(); return this._key.getPublic();
}); });
KeyPair.prototype.getPrivate = function getPrivate(enc) { KeyPair.prototype.getPrivate = function getPrivate(enc) {
var priv = this.key.getPrivate(); var priv = this._key.getPrivate();
if (!priv) if (!priv)
return; return;
@ -95,7 +92,7 @@ KeyPair.prototype.getPrivate = function getPrivate(enc) {
}; };
KeyPair.prototype.getPublic = function getPublic(enc) { KeyPair.prototype.getPublic = function getPublic(enc) {
var pub = this.key.getPublic(this.compressed, 'array'); var pub = this._key.getPublic(this.compressed, 'array');
if (enc === 'base58') if (enc === 'base58')
return utils.toBase58(pub); return utils.toBase58(pub);
@ -182,7 +179,7 @@ KeyPair.prototype.toJSON = function toJSON(encrypt) {
return json; return json;
} }
if (this.key.priv) { if (this._key.priv) {
json.priv = encrypt json.priv = encrypt
? encrypt(this.getPrivate('base58')) ? encrypt(this.getPrivate('base58'))
: this.getPrivate('base58'); : this.getPrivate('base58');

View File

@ -64,12 +64,17 @@ TXPool.prototype._init = function init() {
}); });
}; };
TXPool.prototype.add = function add(tx, noWrite) { TXPool.prototype.add = function add(tx, noWrite, strict) {
var hash = tx.hash('hex'); var hash = tx.hash('hex');
var updated; var updated;
var i, input, key, unspent, index, orphan; var i, input, key, unspent, index, orphan;
var out, key, orphans, some; var out, key, orphans, some;
if (strict) {
if (!this._wallet.ownInput(tx) && !this._wallet.ownOutput(tx))
return false;
}
// Ignore stale pending transactions // Ignore stale pending transactions
if (tx.ts === 0 && tx.ps + 2 * 24 * 3600 < utils.now()) { if (tx.ts === 0 && tx.ps + 2 * 24 * 3600 < utils.now()) {
this._removeTX(tx, noWrite); this._removeTX(tx, noWrite);
@ -80,9 +85,12 @@ TXPool.prototype.add = function add(tx, noWrite) {
if (this._all[hash]) { if (this._all[hash]) {
// Transaction was confirmed, update it in storage // Transaction was confirmed, update it in storage
if (tx.ts !== 0 && this._all[hash].ts === 0) { if (tx.ts !== 0 && this._all[hash].ts === 0) {
this._all[hash].ps = 0;
this._all[hash].ts = tx.ts; this._all[hash].ts = tx.ts;
this._all[hash].block = tx.block; this._all[hash].block = tx.block;
this._storeTX(hash, tx, noWrite); this._storeTX(hash, tx, noWrite);
this.emit('tx', tx);
this.emit('confirmed', tx);
} }
return false; return false;
} }

View File

@ -29,6 +29,8 @@ function Wallet(options) {
if (!options) if (!options)
options = {}; options = {};
options = utils.merge({}, options);
this.options = options; this.options = options;
this.addresses = []; this.addresses = [];
this.master = options.master || null; this.master = options.master || null;
@ -39,23 +41,24 @@ function Wallet(options) {
this.addressIndex = options.addressIndex || 0; this.addressIndex = options.addressIndex || 0;
this.changeIndex = options.changeIndex || 0; this.changeIndex = options.changeIndex || 0;
if (options.addresses && options.addresses.length > 0) { if (!options.addresses)
options.addresses.forEach(function(address) { options.addresses = [];
this.addAddress(address);
}, this); if (!options.addresses.length)
} else { options.addresses.push(utils.merge({}, options));
this.createNewAddress(options);
} options.addresses.forEach(function(address) {
this.addAddress(address);
}, this);
// Create a non-master account address if we don't have one. // Create a non-master account address if we don't have one.
// Might not be necessary now.
if (this.master) { if (this.master) {
for (i = 0; i < this.addresses.length; i++) { for (i = 0; i < this.addresses.length; i++) {
if (this.addresses[i].key.hd && !this.addresses[i].change) if (this.addresses[i].key.hd && !this.addresses[i].change)
break; break;
} }
if (i === this.addresses.length) if (i === this.addresses.length)
this.createNewAddress(options); this.createNewAddress(this._cleanOptions(options.addresses[0]));
} }
// Find the last change address if there is one. // Find the last change address if there is one.
@ -70,7 +73,6 @@ function Wallet(options) {
this.changeAddress = this.addresses[i]; this.changeAddress = this.addresses[i];
this.storage = options.storage; this.storage = options.storage;
this.label = options.label || '';
this.loaded = false; this.loaded = false;
this.lastTs = 0; this.lastTs = 0;
@ -83,6 +85,15 @@ function Wallet(options) {
inherits(Wallet, EventEmitter); inherits(Wallet, EventEmitter);
Wallet.prototype._cleanOptions = function _cleanOptions(options) {
return utils.merge(options, {
key: null,
priv: null,
pub: null,
hd: null
});
};
Wallet.prototype._init = function init() { Wallet.prototype._init = function init() {
var self = this; var self = this;
var prevBalance = null; var prevBalance = null;
@ -104,8 +115,10 @@ Wallet.prototype._init = function init() {
this.tx.on('tx', function(tx) { this.tx.on('tx', function(tx) {
// TX using this change address was // TX using this change address was
// confirmed. Allocate a new change address. // confirmed. Allocate a new change address.
if (self.changeAddress.ownOutput(tx)) if (tx.block) {
self.changeAddress = self.createChangeAddress(); if (self.changeAddress.ownOutput(tx))
self.changeAddress = self.createChangeAddress();
}
self.emit('tx', tx); self.emit('tx', tx);
}); });
@ -231,6 +244,9 @@ Wallet.prototype.addAddress = function addAddress(address) {
this._addressTable[address.getKeyAddress()] = index; this._addressTable[address.getKeyAddress()] = index;
if (address.label && this._labelTable[address.label] == null)
this._labelTable[address.label] = index;
this.emit('add address', address); this.emit('add address', address);
return address; return address;
@ -258,6 +274,9 @@ Wallet.prototype.removeAddress = function removeAddress(address) {
delete address._onUpdate; delete address._onUpdate;
delete address._wallet; delete address._wallet;
if (this._labelTable[address.label] === i)
delete this._labelTable[address.label];
this.emit('remove address', address); this.emit('remove address', address);
return address; return address;
@ -538,7 +557,6 @@ Wallet.prototype.toJSON = function toJSON(encrypt) {
v: 3, v: 3,
name: 'wallet', name: 'wallet',
network: network.type, network: network.type,
label: this.label,
accountIndex: this.accountIndex, accountIndex: this.accountIndex,
addressIndex: this.addressIndex, addressIndex: this.addressIndex,
changeIndex: this.changeIndex, changeIndex: this.changeIndex,
@ -569,7 +587,6 @@ Wallet.fromJSON = function fromJSON(json, decrypt) {
assert.equal(json.network, network.type); assert.equal(json.network, network.type);
w = new Wallet({ w = new Wallet({
label: json.label,
accountIndex: json.accountIndex, accountIndex: json.accountIndex,
addressIndex: json.addressIndex, addressIndex: json.addressIndex,
changeIndex: json.changeIndex, changeIndex: json.changeIndex,
@ -589,7 +606,7 @@ Wallet.fromJSON = function fromJSON(json, decrypt) {
for (i = 0; i < w.changeIndex; i++) { for (i = 0; i < w.changeIndex; i++) {
w.addAddress({ w.addAddress({
change: true, change: true,
key: w.master.key.hd.deriveChange(w.accountIndex, i) priv: w.master.key.hd.deriveChange(w.accountIndex, i)
}); });
} }
} }