wallet: move watchOnly flag to wallet for safety.
This commit is contained in:
parent
25946b8909
commit
2097450b42
@ -211,7 +211,7 @@ Account.fromOptions = function fromOptions(db, options) {
|
||||
* @const {Number}
|
||||
*/
|
||||
|
||||
Account.MAX_LOOKAHEAD = 5;
|
||||
Account.MAX_LOOKAHEAD = 10;
|
||||
|
||||
/**
|
||||
* Attempt to intialize the account (generating
|
||||
@ -794,7 +794,6 @@ Account.prototype.toRaw = function toRaw(writer) {
|
||||
p.writeU32(this.network.magic);
|
||||
p.writeVarString(this.name, 'ascii');
|
||||
p.writeU8(this.initialized ? 1 : 0);
|
||||
p.writeU8(this.watchOnly ? 1 : 0);
|
||||
p.writeU8(this.type);
|
||||
p.writeU8(this.m);
|
||||
p.writeU8(this.n);
|
||||
@ -831,7 +830,6 @@ Account.prototype.fromRaw = function fromRaw(data) {
|
||||
this.network = Network.fromMagic(p.readU32());
|
||||
this.name = p.readVarString('ascii');
|
||||
this.initialized = p.readU8() === 1;
|
||||
this.watchOnly = p.readU8() === 1;
|
||||
this.type = p.readU8();
|
||||
this.m = p.readU8();
|
||||
this.n = p.readU8();
|
||||
|
||||
@ -71,6 +71,7 @@ function Wallet(db, options) {
|
||||
this.id = null;
|
||||
this.master = null;
|
||||
this.initialized = false;
|
||||
this.watchOnly = false;
|
||||
this.accountDepth = 0;
|
||||
this.token = constants.ZERO_HASH;
|
||||
this.tokenDepth = 0;
|
||||
@ -111,6 +112,11 @@ Wallet.prototype.fromOptions = function fromOptions(options) {
|
||||
this.initialized = options.initialized;
|
||||
}
|
||||
|
||||
if (options.watchOnly != null) {
|
||||
assert(typeof options.watchOnly === 'boolean');
|
||||
this.watchOnly = options.watchOnly;
|
||||
}
|
||||
|
||||
if (options.accountDepth != null) {
|
||||
assert(utils.isNumber(options.accountDepth));
|
||||
this.accountDepth = options.accountDepth;
|
||||
@ -633,7 +639,6 @@ Wallet.prototype._createAccount = co(function* createAccount(options) {
|
||||
var passphrase = options.passphrase;
|
||||
var timeout = options.timeout;
|
||||
var name = options.name;
|
||||
var watchOnly = options.watchOnly === true;
|
||||
var key, master, account;
|
||||
|
||||
if (typeof options.account === 'string')
|
||||
@ -644,7 +649,7 @@ Wallet.prototype._createAccount = co(function* createAccount(options) {
|
||||
|
||||
master = yield this.unlock(passphrase, timeout);
|
||||
|
||||
if (watchOnly && options.accountKey) {
|
||||
if (this.watchOnly && options.accountKey) {
|
||||
key = options.accountKey;
|
||||
if (!HD.isHD(key))
|
||||
key = HD.from(key, this.network);
|
||||
@ -664,7 +669,7 @@ Wallet.prototype._createAccount = co(function* createAccount(options) {
|
||||
keys: options.keys,
|
||||
m: options.m,
|
||||
n: options.n,
|
||||
watchOnly: watchOnly
|
||||
watchOnly: this.watchOnly
|
||||
};
|
||||
|
||||
this.start();
|
||||
@ -742,6 +747,7 @@ Wallet.prototype.getAccount = co(function* getAccount(account) {
|
||||
|
||||
account.wid = this.wid;
|
||||
account.id = this.id;
|
||||
account.watchOnly = this.watchOnly;
|
||||
|
||||
return account;
|
||||
});
|
||||
@ -976,6 +982,14 @@ Wallet.prototype._importKey = co(function* importKey(account, ring, passphrase)
|
||||
if (account == null)
|
||||
account = 0;
|
||||
|
||||
if (!this.watchOnly) {
|
||||
if (!ring.privateKey)
|
||||
throw new Error('Cannot import pubkey into non watch-only wallet.');
|
||||
} else {
|
||||
if (ring.privateKey)
|
||||
throw new Error('Cannot import privkey into watch-only wallet.');
|
||||
}
|
||||
|
||||
exists = yield this.getPath(ring.getHash('hex'));
|
||||
|
||||
if (exists)
|
||||
@ -989,9 +1003,6 @@ Wallet.prototype._importKey = co(function* importKey(account, ring, passphrase)
|
||||
if (account.type !== Account.types.PUBKEYHASH)
|
||||
throw new Error('Cannot import into non-pkh account.');
|
||||
|
||||
if (!ring.privateKey && !account.watchOnly)
|
||||
throw new Error('Cannot import pubkey into non-watchonly account.');
|
||||
|
||||
yield this.unlock(passphrase);
|
||||
|
||||
ring = WalletKey.fromRing(account, ring);
|
||||
@ -1053,6 +1064,9 @@ Wallet.prototype._importAddress = co(function* importAddress(account, address) {
|
||||
if (account == null)
|
||||
account = 0;
|
||||
|
||||
if (!this.watchOnly)
|
||||
throw new Error('Cannot import address into non watch-only wallet.');
|
||||
|
||||
exists = yield this.getPath(address);
|
||||
|
||||
if (exists)
|
||||
@ -1066,9 +1080,6 @@ Wallet.prototype._importAddress = co(function* importAddress(account, address) {
|
||||
if (account.type !== Account.types.PUBKEYHASH)
|
||||
throw new Error('Cannot import into non-pkh account.');
|
||||
|
||||
if (!account.watchOnly)
|
||||
throw new Error('Cannot import address into non-watchonly account.');
|
||||
|
||||
path = Path.fromAddress(account, address);
|
||||
|
||||
this.start();
|
||||
@ -1132,6 +1143,9 @@ Wallet.prototype._fund = co(function* fund(tx, options) {
|
||||
if (!this.initialized)
|
||||
throw new Error('Wallet is not initialized.');
|
||||
|
||||
if (this.watchOnly)
|
||||
throw new Error('Cannot fund from watch-only wallet.');
|
||||
|
||||
if (options.account != null) {
|
||||
account = yield this.getAccount(options.account);
|
||||
if (!account)
|
||||
@ -1595,6 +1609,9 @@ Wallet.prototype.sign = co(function* sign(tx, options) {
|
||||
if (typeof options === 'string' || Buffer.isBuffer(options))
|
||||
options = { passphrase: options };
|
||||
|
||||
if (this.watchOnly)
|
||||
throw new Error('Cannot sign from a watch-only wallet.');
|
||||
|
||||
yield this.unlock(options.passphrase, options.timeout);
|
||||
|
||||
rings = yield this.deriveInputs(tx);
|
||||
@ -2073,6 +2090,7 @@ Wallet.prototype.toJSON = function toJSON() {
|
||||
wid: this.wid,
|
||||
id: this.id,
|
||||
initialized: this.initialized,
|
||||
watchOnly: this.watchOnly,
|
||||
accountDepth: this.accountDepth,
|
||||
token: this.token.toString('hex'),
|
||||
tokenDepth: this.tokenDepth,
|
||||
@ -2090,6 +2108,7 @@ Wallet.prototype.toJSON = function toJSON() {
|
||||
Wallet.prototype.fromJSON = function fromJSON(json) {
|
||||
assert(utils.isNumber(json.wid));
|
||||
assert(typeof json.initialized === 'boolean');
|
||||
assert(typeof json.watchOnly === 'boolean');
|
||||
assert(utils.isName(json.id), 'Bad wallet ID.');
|
||||
assert(utils.isNumber(json.accountDepth));
|
||||
assert(typeof json.token === 'string');
|
||||
@ -2100,6 +2119,7 @@ Wallet.prototype.fromJSON = function fromJSON(json) {
|
||||
this.wid = json.wid;
|
||||
this.id = json.id;
|
||||
this.initialized = json.initialized;
|
||||
this.watchOnly = json.watchOnly;
|
||||
this.accountDepth = json.accountDepth;
|
||||
this.token = new Buffer(json.token, 'hex');
|
||||
this.master = MasterKey.fromJSON(json.master);
|
||||
@ -2119,6 +2139,7 @@ Wallet.prototype.toRaw = function toRaw(writer) {
|
||||
p.writeU32(this.wid);
|
||||
p.writeVarString(this.id, 'ascii');
|
||||
p.writeU8(this.initialized ? 1 : 0);
|
||||
p.writeU8(this.watchOnly ? 1 : 0);
|
||||
p.writeU32(this.accountDepth);
|
||||
p.writeBytes(this.token);
|
||||
p.writeU32(this.tokenDepth);
|
||||
@ -2142,6 +2163,7 @@ Wallet.prototype.fromRaw = function fromRaw(data) {
|
||||
this.wid = p.readU32();
|
||||
this.id = p.readVarString('ascii');
|
||||
this.initialized = p.readU8() === 1;
|
||||
this.watchOnly = p.readU8() === 1;
|
||||
this.accountDepth = p.readU32();
|
||||
this.token = p.readBytes(32);
|
||||
this.tokenDepth = p.readU32();
|
||||
|
||||
@ -946,12 +946,10 @@ describe('Wallet', function() {
|
||||
it('should import pubkey', cob(function *() {
|
||||
var priv = bcoin.keyring.generate();
|
||||
var key = new bcoin.keyring(priv.publicKey);
|
||||
var w = yield walletdb.create();
|
||||
var w = yield walletdb.create({ watchOnly: true });
|
||||
var options, k, t1, t2, tx;
|
||||
|
||||
yield w.createAccount({ name: 'watchonly', watchOnly: true });
|
||||
|
||||
yield w.importKey('watchonly', key);
|
||||
yield w.importKey('default', key);
|
||||
|
||||
k = yield w.getPath(key.getHash('hex'));
|
||||
|
||||
@ -963,12 +961,10 @@ describe('Wallet', function() {
|
||||
|
||||
it('should import address', cob(function *() {
|
||||
var key = bcoin.keyring.generate();
|
||||
var w = yield walletdb.create();
|
||||
var w = yield walletdb.create({ watchOnly: true });
|
||||
var options, k, t1, t2, tx;
|
||||
|
||||
yield w.createAccount({ name: 'watchonly', watchOnly: true });
|
||||
|
||||
yield w.importAddress('watchonly', key.getAddress());
|
||||
yield w.importAddress('default', key.getAddress());
|
||||
|
||||
k = yield w.getPath(key.getHash('hex'));
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user