Skip to content

Commit

Permalink
wallet: check account ownership of bid TX when making reveal TX
Browse files Browse the repository at this point in the history
Adds new method acctOwnsTX(acct, hash) to txdb which returns true if
the txid (hash) is owned by the account (number). Adds this check to
wallet.makeReveal() to prevent BIDs from other wallet accounts being
included as inputs to a new REVEAL TX from a specific account.
  • Loading branch information
pinheadmz committed Aug 1, 2019
1 parent 0d5865f commit 90837d8
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 2 deletions.
13 changes: 13 additions & 0 deletions lib/wallet/txdb.js
Original file line number Diff line number Diff line change
Expand Up @@ -2240,6 +2240,19 @@ class TXDB {
});
}

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

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

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

/**
* Get hashes of all transactions in the database.
* @param {Number} acct
Expand Down
13 changes: 11 additions & 2 deletions lib/wallet/wallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -1742,9 +1742,14 @@ class Wallet extends EventEmitter {
* @returns {MTX}
*/

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

if (acct) {
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 @@ -1781,6 +1786,9 @@ class Wallet extends EventEmitter {
if (!coin)
continue;

if (acct && !await this.txdb.acctOwnsTX(acct, hash))
continue;

// Is local?
if (coin.height < ns.height)
continue;
Expand Down Expand Up @@ -1820,7 +1828,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
90 changes: 90 additions & 0 deletions test/double-reveal-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/* eslint-env mocha */
/* eslint prefer-arrow-callback: "off" */

'use strict';

const assert = require('bsert');
const Network = require('../lib/protocol/network');
const FullNode = require('../lib/node/fullnode');
const Address = require('../lib/primitives/address');
const rules = require('../lib/covenants/rules');

const network = Network.get('regtest');

const node = new FullNode({
memory: true,
network: 'regtest',
plugins: [require('../lib/wallet/plugin')]
});

const {wdb} = node.require('walletdb');
const name = rules.grindName(10, 20, network);

let wallet, alice, bob, aliceMiner, bobMiner;

async function mineBlocks(n, addr) {
addr = addr ? addr : new Address().toString('regtest');
for (let i = 0; i < n; i++) {
const block = await node.miner.mineBlock(null, addr);
await node.chain.add(block);
}
}

describe('One wallet, two accounts, one name', function() {
before(async () => {
await node.open();

wallet = await wdb.create();

alice = await wallet.createAccount({name: 'alice'});
bob = await wallet.createAccount({name: 'bob'});

aliceMiner = await alice.receiveAddress();
bobMiner = await bob.receiveAddress();
});

after(async () => {
await node.close();
});

it('should fund both accounts', async () => {
await mineBlocks(10, aliceMiner);
await mineBlocks(10, bobMiner);

// Wallet rescan is an effective way to ensure that
// wallet and chain are synced before proceeding.
await wdb.rescan(0);

const aliceBal = await wallet.getBalance('alice');
const bobBal = await wallet.getBalance('bob');
assert(aliceBal.confirmed === 2000 * 10 * 1e6);
assert(bobBal.confirmed === 2000 * 10 * 1e6);
});

it('should open an auction and proceed to REVEAL phase', async () => {
await wallet.sendOpen(name, false, {account: 'alice'});
await mineBlocks(network.names.treeInterval + 2);
let ns = await node.chain.db.getNameStateByName(name);
assert(ns.isBidding(node.chain.height, network));

await wdb.rescan(0);

await wallet.sendBid(name, 100000, 200000, {account: 'alice'});
await wallet.sendBid(name, 50000, 200000, {account: 'bob'});
await mineBlocks(network.names.biddingPeriod);
ns = await node.chain.db.getNameStateByName(name);
assert(ns.isReveal(node.chain.height, network));

await wdb.rescan(0);

const walletBids = await wallet.getBidsByName(name);
assert.strictEqual(walletBids.length, 2);

for (const bid of walletBids)
assert(bid.own);
});

it('should send REVEAL from one account', async () => {
await wallet.sendReveal(name, {account: 'alice'});
});
});

0 comments on commit 90837d8

Please sign in to comment.