Skip to content

Commit

Permalink
wallet: check account ownership of name before making transfer TX
Browse files Browse the repository at this point in the history
  • Loading branch information
pinheadmz committed Mar 20, 2020
1 parent 19219ca commit 2aff6e1
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 2 deletions.
13 changes: 11 additions & 2 deletions lib/wallet/wallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -2626,13 +2626,18 @@ class Wallet extends EventEmitter {
* @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 @@ -2655,6 +2660,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 @@ -2693,7 +2701,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
133 changes: 133 additions & 0 deletions test/wallet-accounts-auction-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -596,4 +596,137 @@ describe('Multiple accounts participating in same auction', function() {
});
});
});

describe('TRANSFER', function() {
// Alice will transfer to Bob
let toAddr;

before(async () => {
toAddr = await bob.receiveAddress();
});

describe('Library methods', function() {
it('reject from wrongly specified account', async () => {
await assert.rejects(async () => {
await wallet.sendTransfer(name, toAddr, {account: 'bob'});
}, {
name: 'Error',
message: `Account does not own: "${name}".`
});
});

it('send from correctly specified account', async () => {
const tx = await wallet.sendTransfer(name, toAddr, {account: 0});
assert(tx);

await wallet.abandon(tx.hash());

assert.strictEqual(node.mempool.map.size, 1);
await node.mempool.reset();
assert.strictEqual(node.mempool.map.size, 0);
});

it('send from correct account automatically', async () => {
const tx = await wallet.sendTransfer(name, toAddr);
assert(tx);

await wallet.abandon(tx.hash());

assert.strictEqual(node.mempool.map.size, 1);
await node.mempool.reset();
assert.strictEqual(node.mempool.map.size, 0);
});
});

describe('HTTP API', function () {
it('reject from wrongly specified account', async () => {
await assert.rejects(async () => {
await wclient.post(`wallet/${wallet.id}/transfer`, {
name: name,
address: toAddr.toString(network),
account: 'bob'
});
}, {
name: 'Error',
message: `Account does not own: "${name}".`
});
});

it('send from correctly specified account', async () => {
const tx = await wclient.post(`wallet/${wallet.id}/transfer`, {
name: name,
address: toAddr.toString(network),
account: 'default'
});
assert(tx);

await wallet.abandon(Buffer.from(tx.hash, 'hex'));

assert.strictEqual(node.mempool.map.size, 1);
await node.mempool.reset();
assert.strictEqual(node.mempool.map.size, 0);
});

it('send from correct account automatically', async () => {
const tx = await wclient.post(`wallet/${wallet.id}/transfer`, {
name: name,
address: toAddr.toString(network)
});
assert(tx);

await wallet.abandon(Buffer.from(tx.hash, 'hex'));

assert.strictEqual(node.mempool.map.size, 1);
await node.mempool.reset();
assert.strictEqual(node.mempool.map.size, 0);
});
});

describe('RPC API', function() {
it('reject from wrongly specified account', async () => {
await wclient.execute('selectwallet', [wallet.id]);

await assert.rejects(async () => {
await wclient.execute('sendtransfer', [
name,
toAddr.toString(network),
'bob'
]);
}, {
name: 'Error',
message: `Account does not own: "${name}".`
});
});

it('send from correctly specified account', async () => {
const tx = await wclient.execute('sendtransfer', [
name,
toAddr.toString(network),
'default'
]);
assert(tx);

await wallet.abandon(Buffer.from(tx.hash, 'hex'));

assert.strictEqual(node.mempool.map.size, 1);
await node.mempool.reset();
assert.strictEqual(node.mempool.map.size, 0);
});

it('send from correct account automatically', async () => {
const tx = await wclient.execute('sendtransfer', [
name,
toAddr.toString(network)
]);
assert(tx);

await wallet.abandon(Buffer.from(tx.hash, 'hex'));

// This time we will confirm the TRANSFER so we can CANCEL and FINALIZE
assert.strictEqual(node.mempool.map.size, 1);
await mineBlocks(1);
assert.strictEqual(node.mempool.map.size, 0);
});
});
});
});

0 comments on commit 2aff6e1

Please sign in to comment.