account: hd watchonly support.
This commit is contained in:
parent
57bc9bf4b0
commit
7b3134d782
@ -69,6 +69,7 @@ function Account(db, options) {
|
||||
this.n = 1;
|
||||
this.keys = [];
|
||||
this.initialized = false;
|
||||
this.watchOnly = false;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
@ -171,6 +172,11 @@ Account.prototype.fromOptions = function fromOptions(options) {
|
||||
this.initialized = options.initialized;
|
||||
}
|
||||
|
||||
if (options.watchOnly != null) {
|
||||
assert(typeof options.watchOnly === 'boolean');
|
||||
this.watchOnly = options.watchOnly;
|
||||
}
|
||||
|
||||
if (this.n > 1)
|
||||
this.type = Account.types.MULTISIG;
|
||||
|
||||
@ -533,7 +539,7 @@ Account.prototype.deriveKey = function deriveKey(branch, index, master) {
|
||||
|
||||
assert(typeof branch === 'number');
|
||||
|
||||
if (master && master.key) {
|
||||
if (master && master.key && !this.watchOnly) {
|
||||
key = master.key.deriveAccount44(this.accountIndex);
|
||||
key = key.derive(branch).derive(index);
|
||||
} else {
|
||||
@ -668,6 +674,7 @@ Account.prototype.inspect = function inspect() {
|
||||
name: this.name,
|
||||
network: this.network,
|
||||
initialized: this.initialized,
|
||||
watchOnly: this.watchOnly,
|
||||
type: Account.typesByVal[this.type].toLowerCase(),
|
||||
m: this.m,
|
||||
n: this.n,
|
||||
@ -701,6 +708,7 @@ Account.prototype.toJSON = function toJSON() {
|
||||
wid: this.wid,
|
||||
name: this.name,
|
||||
initialized: this.initialized,
|
||||
watchOnly: this.watchOnly,
|
||||
type: Account.typesByVal[this.type].toLowerCase(),
|
||||
m: this.m,
|
||||
n: this.n,
|
||||
@ -739,6 +747,7 @@ Account.prototype.fromJSON = function fromJSON(json) {
|
||||
assert(utils.isName(json.id), 'Bad wallet ID.');
|
||||
assert(utils.isName(json.name), 'Bad account name.');
|
||||
assert(typeof json.initialized === 'boolean');
|
||||
assert(typeof json.watchOnly === 'boolean');
|
||||
assert(typeof json.type === 'string');
|
||||
assert(utils.isNumber(json.m));
|
||||
assert(utils.isNumber(json.n));
|
||||
@ -752,6 +761,7 @@ Account.prototype.fromJSON = function fromJSON(json) {
|
||||
this.wid = json.wid;
|
||||
this.name = json.name;
|
||||
this.initialized = json.initialized;
|
||||
this.watchOnly = json.watchOnly;
|
||||
this.type = Account.types[json.type.toUpperCase()];
|
||||
this.m = json.m;
|
||||
this.n = json.n;
|
||||
@ -784,6 +794,7 @@ 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);
|
||||
@ -820,6 +831,7 @@ 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();
|
||||
|
||||
@ -96,11 +96,10 @@ Wallet.prototype.fromOptions = function fromOptions(options) {
|
||||
if (!master)
|
||||
master = HD.fromMnemonic(null, this.network);
|
||||
|
||||
if (!HD.isHD(master) && !MasterKey.isMasterKey(master))
|
||||
if (!HD.isHD(master))
|
||||
master = HD.from(master, this.network);
|
||||
|
||||
if (HD.isHD(master))
|
||||
master = MasterKey.fromKey(master);
|
||||
master = MasterKey.fromKey(master);
|
||||
|
||||
assert(MasterKey.isMasterKey(master));
|
||||
|
||||
@ -633,6 +632,7 @@ 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')
|
||||
@ -643,7 +643,13 @@ Wallet.prototype._createAccount = co(function* createAccount(options) {
|
||||
|
||||
master = yield this.unlock(passphrase, timeout);
|
||||
|
||||
key = master.deriveAccount44(this.accountDepth);
|
||||
if (watchOnly && options.accountKey) {
|
||||
key = options.accountKey;
|
||||
if (!HD.isHD(key))
|
||||
key = HD.from(key, this.network);
|
||||
} else {
|
||||
key = master.deriveAccount44(this.accountDepth);
|
||||
}
|
||||
|
||||
options = {
|
||||
network: this.network,
|
||||
@ -656,7 +662,8 @@ Wallet.prototype._createAccount = co(function* createAccount(options) {
|
||||
type: options.type,
|
||||
keys: options.keys,
|
||||
m: options.m,
|
||||
n: options.n
|
||||
n: options.n,
|
||||
watchOnly: watchOnly
|
||||
};
|
||||
|
||||
this.start();
|
||||
@ -981,6 +988,9 @@ 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);
|
||||
@ -1055,6 +1065,9 @@ 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();
|
||||
|
||||
@ -900,7 +900,7 @@ describe('Wallet', function() {
|
||||
assert.equal(balance.total, 21840);
|
||||
}));
|
||||
|
||||
it('should import key', cob(function *() {
|
||||
it('should import privkey', cob(function *() {
|
||||
var key = bcoin.keyring.generate();
|
||||
var w = yield walletdb.create({ passphrase: 'test' });
|
||||
var options, k, t1, t2, tx;
|
||||
@ -943,16 +943,39 @@ describe('Wallet', function() {
|
||||
ekey = key;
|
||||
}));
|
||||
|
||||
it('should import pubkey', cob(function *() {
|
||||
var priv = bcoin.keyring.generate();
|
||||
var key = new bcoin.keyring(priv.publicKey);
|
||||
var w = yield walletdb.create();
|
||||
var options, k, t1, t2, tx;
|
||||
|
||||
yield w.createAccount({ name: 'watchonly', watchOnly: true });
|
||||
|
||||
yield w.importKey('watchonly', key);
|
||||
|
||||
k = yield w.getPath(key.getHash('hex'));
|
||||
|
||||
assert.equal(k.hash, key.getHash('hex'));
|
||||
|
||||
k = yield w.getKey(key.getHash('hex'));
|
||||
assert(k);
|
||||
}));
|
||||
|
||||
it('should import address', cob(function *() {
|
||||
var key = bcoin.keyring.generate();
|
||||
var w = yield walletdb.create();
|
||||
var options, k, t1, t2, tx;
|
||||
|
||||
yield w.importAddress('default', key.getAddress());
|
||||
yield w.createAccount({ name: 'watchonly', watchOnly: true });
|
||||
|
||||
yield w.importAddress('watchonly', key.getAddress());
|
||||
|
||||
k = yield w.getPath(key.getHash('hex'));
|
||||
|
||||
assert.equal(k.hash, key.getHash('hex'));
|
||||
|
||||
k = yield w.getKey(key.getHash('hex'));
|
||||
assert(!k);
|
||||
}));
|
||||
|
||||
it('should get details', cob(function *() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user