Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wallet: accept account argument for all covenant makers and verify account ownership during coin selection #233

Merged
merged 6 commits into from
Mar 26, 2020
14 changes: 14 additions & 0 deletions lib/wallet/txdb.js
Original file line number Diff line number Diff line change
Expand Up @@ -2250,6 +2250,20 @@ class TXDB {
});
}

/**
* Test whether an account owns a coin.
* @param {Number} acct
* @param {Hash} hash
* @param {Index} number
* @returns {Promise} - Returns Boolean.
*/

hasCoinByAccount(acct, hash, index) {
assert(typeof acct === 'number');

return this.bucket.has(layout.C.encode(acct, hash, index));
}

/**
* Get hashes of all transactions in the database.
* @param {Number} acct
Expand Down
116 changes: 98 additions & 18 deletions lib/wallet/wallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -1747,12 +1747,18 @@ class Wallet extends EventEmitter {
/**
* Make a reveal MTX.
* @param {String} name
* @param {(Number|String)?} acct
* @returns {MTX}
*/

async makeReveal(name) {
async makeReveal(name, acct) {
assert(typeof name === 'string');

if (acct != null) {
assert((acct >>> 0) === acct || typeof acct === 'string');
acct = await this.getAccountIndex(acct);
}

if (!rules.verifyName(name))
throw new Error('Invalid name.');

Expand Down Expand Up @@ -1789,6 +1795,9 @@ class Wallet extends EventEmitter {
if (!coin)
continue;

if (acct != null && !await this.txdb.hasCoinByAccount(acct, hash, index))
continue;

// Is local?
if (coin.height < ns.height)
continue;
Expand Down Expand Up @@ -1828,7 +1837,8 @@ class Wallet extends EventEmitter {
*/

async _createReveal(name, options) {
const mtx = await this.makeReveal(name);
const acct = options ? options.account : null;
const mtx = await this.makeReveal(name, acct);
await this.fill(mtx, options);
return this.finalize(mtx, options);
}
Expand Down Expand Up @@ -2000,15 +2010,21 @@ class Wallet extends EventEmitter {
/**
* Make a redeem MTX.
* @param {String} name
* @param {(Number|String)?} acct
* @returns {MTX}
*/

async makeRedeem(name) {
async makeRedeem(name, acct) {
assert(typeof name === 'string');

if (!rules.verifyName(name))
throw new Error('Invalid name.');

if (acct != null) {
assert((acct >>> 0) === acct || typeof acct === 'string');
acct = await this.getAccountIndex(acct);
}

const rawName = Buffer.from(name, 'ascii');
const nameHash = rules.hashName(rawName);
const ns = await this.getNameState(nameHash);
Expand Down Expand Up @@ -2036,6 +2052,7 @@ class Wallet extends EventEmitter {
if (!own)
continue;

// Winner can not redeem
if (prevout.equals(ns.owner))
continue;

Expand All @@ -2044,6 +2061,9 @@ class Wallet extends EventEmitter {
if (!coin)
continue;

if (acct != null && !await this.txdb.hasCoinByAccount(acct, hash, index))
continue;

// Is local?
if (coin.height < ns.height)
continue;
Expand Down Expand Up @@ -2075,7 +2095,8 @@ class Wallet extends EventEmitter {
*/

async _createRedeem(name, options) {
const mtx = await this.makeRedeem(name);
const acct = options ? options.account : null;
const mtx = await this.makeRedeem(name, acct);
await this.fill(mtx, options);
return this.finalize(mtx, options);
}
Expand Down Expand Up @@ -2325,16 +2346,22 @@ class Wallet extends EventEmitter {
* Make an update MTX.
* @param {String} name
* @param {Resource} resource
* @param {(Number|String)?} acct
* @returns {MTX}
*/

async makeUpdate(name, resource) {
async makeUpdate(name, resource, acct) {
pinheadmz marked this conversation as resolved.
Show resolved Hide resolved
assert(typeof name === 'string');
assert(resource instanceof Resource);

if (!rules.verifyName(name))
throw new Error('Invalid name.');

if (acct != null) {
assert((acct >>> 0) === acct || typeof acct === 'string');
acct = await this.getAccountIndex(acct);
}

const rawName = Buffer.from(name, 'ascii');
const nameHash = rules.hashName(rawName);
const ns = await this.getNameState(nameHash);
Expand All @@ -2350,6 +2377,9 @@ class Wallet extends EventEmitter {
if (!coin)
throw new Error(`Wallet does not own: "${name}".`);

if (acct != null && !await this.txdb.hasCoinByAccount(acct, hash, index))
throw new Error(`Account does not own: "${name}".`);

if (coin.covenant.isReveal() || coin.covenant.isClaim())
return this._makeRegister(name, resource);

Expand Down Expand Up @@ -2402,7 +2432,8 @@ class Wallet extends EventEmitter {
*/

async _createUpdate(name, resource, options) {
const mtx = await this.makeUpdate(name, resource);
const acct = options ? options.account : null;
const mtx = await this.makeUpdate(name, resource, acct);
await this.fill(mtx, options);
return this.finalize(mtx, options);
}
Expand Down Expand Up @@ -2460,16 +2491,21 @@ class Wallet extends EventEmitter {
* Make a renewal MTX.
* @private
* @param {String} name
* @param {Resource?} resource
* @param {(Number|String)?} acct
* @returns {MTX}
*/

async makeRenewal(name) {
async makeRenewal(name, acct) {
assert(typeof name === 'string');

if (!rules.verifyName(name))
throw new Error('Invalid name.');

if (acct != null) {
assert((acct >>> 0) === acct || typeof acct === 'string');
acct = await this.getAccountIndex(acct);
}

const rawName = Buffer.from(name, 'ascii');
const nameHash = rules.hashName(rawName);
const ns = await this.getNameState(nameHash);
Expand All @@ -2492,6 +2528,9 @@ class Wallet extends EventEmitter {
if (coin.height < ns.height)
throw new Error(`Wallet does not own: "${name}".`);

if (acct != null && !await this.txdb.hasCoinByAccount(acct, hash, index))
throw new Error(`Account does not own: "${name}".`);

const state = ns.state(height, network);

if (state !== states.CLOSED)
Expand Down Expand Up @@ -2531,7 +2570,8 @@ class Wallet extends EventEmitter {
*/

async _createRenewal(name, options) {
const mtx = await this.makeRenewal(name);
const acct = options ? options.account : null;
const mtx = await this.makeRenewal(name, acct);
await this.fill(mtx, options);
return this.finalize(mtx, options);
}
Expand Down Expand Up @@ -2586,16 +2626,22 @@ class Wallet extends EventEmitter {
* Make a transfer MTX.
* @param {String} name
* @param {Address} address
* @param {(Number|String)?} acct
* @returns {MTX}
*/

async makeTransfer(name, address) {
async makeTransfer(name, address, acct) {
assert(typeof name === 'string');
assert(address instanceof Address);

if (!rules.verifyName(name))
throw new Error('Invalid name.');

if (acct != null) {
assert((acct >>> 0) === acct || typeof acct === 'string');
acct = await this.getAccountIndex(acct);
}

const rawName = Buffer.from(name, 'ascii');
const nameHash = rules.hashName(rawName);
const ns = await this.getNameState(nameHash);
Expand All @@ -2618,6 +2664,9 @@ class Wallet extends EventEmitter {
if (coin.height < ns.height)
throw new Error(`Wallet does not own: "${name}".`);

if (acct != null && !await this.txdb.hasCoinByAccount(acct, hash, index))
throw new Error(`Account does not own: "${name}".`);

const state = ns.state(height, network);

if (state !== states.CLOSED)
Expand Down Expand Up @@ -2656,7 +2705,8 @@ class Wallet extends EventEmitter {
*/

async _createTransfer(name, address, options) {
const mtx = await this.makeTransfer(name, address);
const acct = options ? options.account : null;
const mtx = await this.makeTransfer(name, address, acct);
await this.fill(mtx, options);
return this.finalize(mtx, options);
}
Expand Down Expand Up @@ -2718,15 +2768,21 @@ class Wallet extends EventEmitter {
* Make a transfer-cancelling MTX.
* @private
* @param {String} name
* @param {(Number|String)?} acct
* @returns {MTX}
*/

async makeCancel(name) {
async makeCancel(name, acct) {
assert(typeof name === 'string');

if (!rules.verifyName(name))
throw new Error('Invalid name.');

if (acct != null) {
assert((acct >>> 0) === acct || typeof acct === 'string');
acct = await this.getAccountIndex(acct);
}

const rawName = Buffer.from(name, 'ascii');
const nameHash = rules.hashName(rawName);
const ns = await this.getNameState(nameHash);
Expand All @@ -2749,6 +2805,9 @@ class Wallet extends EventEmitter {
if (coin.height < ns.height)
throw new Error(`Wallet does not own: "${name}".`);

if (acct != null && !await this.txdb.hasCoinByAccount(acct, hash, index))
throw new Error(`Account does not own: "${name}".`);

const state = ns.state(height, network);

if (state !== states.CLOSED)
Expand Down Expand Up @@ -2781,7 +2840,8 @@ class Wallet extends EventEmitter {
*/

async _createCancel(name, options) {
const mtx = await this.makeCancel(name);
const acct = options ? options.account : null;
const mtx = await this.makeCancel(name, acct);
await this.fill(mtx, options);
return this.finalize(mtx, options);
}
Expand Down Expand Up @@ -2836,15 +2896,21 @@ class Wallet extends EventEmitter {
* Make a transfer-finalizing MTX.
* @private
* @param {String} name
* @param {(Number|String)?} acct
* @returns {MTX}
*/

async makeFinalize(name) {
async makeFinalize(name, acct) {
assert(typeof name === 'string');

if (!rules.verifyName(name))
throw new Error('Invalid name.');

if (acct != null) {
assert((acct >>> 0) === acct || typeof acct === 'string');
acct = await this.getAccountIndex(acct);
}

const rawName = Buffer.from(name, 'ascii');
const nameHash = rules.hashName(rawName);
const ns = await this.getNameState(nameHash);
Expand All @@ -2867,6 +2933,9 @@ class Wallet extends EventEmitter {
if (coin.height < ns.height)
throw new Error(`Wallet does not own: "${name}".`);

if (acct != null && !await this.txdb.hasCoinByAccount(acct, hash, index))
throw new Error(`Account does not own: "${name}".`);

const state = ns.state(height, network);

if (state !== states.CLOSED)
Expand Down Expand Up @@ -2915,7 +2984,8 @@ class Wallet extends EventEmitter {
*/

async _createFinalize(name, options) {
const mtx = await this.makeFinalize(name);
const acct = options ? options.account : null;
const mtx = await this.makeFinalize(name, acct);
await this.fill(mtx, options);
return this.finalize(mtx, options);
}
Expand Down Expand Up @@ -2969,15 +3039,21 @@ class Wallet extends EventEmitter {
/**
* Make a revoke MTX.
* @param {String} name
* @param {(Number|String)?} acct
* @returns {MTX}
*/

async makeRevoke(name) {
async makeRevoke(name, acct) {
assert(typeof name === 'string');

if (!rules.verifyName(name))
throw new Error('Invalid name.');

if (acct != null) {
assert((acct >>> 0) === acct || typeof acct === 'string');
acct = await this.getAccountIndex(acct);
}

const rawName = Buffer.from(name, 'ascii');
const nameHash = rules.hashName(rawName);
const ns = await this.getNameState(nameHash);
Expand All @@ -2993,6 +3069,9 @@ class Wallet extends EventEmitter {
if (!coin)
throw new Error(`Wallet does not own: "${name}".`);

if (acct != null && !await this.txdb.hasCoinByAccount(acct, hash, index))
throw new Error(`Account does not own: "${name}".`);

// Is local?
if (coin.height < ns.height)
throw new Error(`Wallet does not own: "${name}".`);
Expand Down Expand Up @@ -3036,7 +3115,8 @@ class Wallet extends EventEmitter {
*/

async _createRevoke(name, options) {
const mtx = await this.makeRevoke(name);
const acct = options ? options.account : null;
const mtx = await this.makeRevoke(name, acct);
await this.fill(mtx, options);
return this.finalize(mtx, options);
}
Expand Down Expand Up @@ -3067,7 +3147,7 @@ class Wallet extends EventEmitter {

async _sendRevoke(name, options) {
const passphrase = options ? options.passphrase : null;
const mtx = await this._createRevoke(name);
const mtx = await this._createRevoke(name, options);
return this.sendMTX(mtx, passphrase);
}

Expand Down
Loading