Skip to content

Commit

Permalink
wallet: update unconfirmed locked balance first during rescan
Browse files Browse the repository at this point in the history
  • Loading branch information
pinheadmz committed Mar 19, 2020
1 parent 98b33cc commit 6eb92ba
Show file tree
Hide file tree
Showing 2 changed files with 301 additions and 0 deletions.
6 changes: 6 additions & 0 deletions lib/wallet/txdb.js
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,12 @@ class TXDB {
if (!path)
continue;

// If the first time we see a TX is in a block
// (i.e. during a rescan) update the "unconfirmed" locked balance
// before updating the "confirmed" locked balance.
if (height !== -1)
await this.lockBalances(b, state, tx, i, path, -1);

await this.lockBalances(b, state, tx, i, path, height);

details.setOutput(i, path);
Expand Down
295 changes: 295 additions & 0 deletions test/wallet-test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-env mocha */
/* eslint prefer-arrow-callback: "off" */
/* eslint no-implicit-coercion: "off" */

'use strict';

Expand Down Expand Up @@ -1642,4 +1643,298 @@ describe('Wallet', function() {
}
});
});

describe('TXDB locked balance', function() {
const network = Network.get('regtest');
const workers = new WorkerPool({ enabled });
const wdb = new WalletDB({ network, workers });
const name = 'satoshi';
const value = 1e6;
const lockup = 2e6;
const fee = 10000;
let wallet;

before(async () => {
await wdb.open();
wallet = await wdb.create();
// rollout all names
wdb.height = 52 * 144 * 7;
});

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

it('should fund wallet', async () => {
const addr = await wallet.receiveAddress();

// Fund wallet
const mtx = new MTX();
mtx.addOutpoint(new Outpoint(Buffer.alloc(32), 0));
mtx.addOutput(addr, 10e6);
const tx = mtx.toTX();

// Dummy block
const block = {
height: wdb.height + 1,
hash: Buffer.alloc(32),
time: Date.now()
};

// Add confirmed funding TX to wallet
await wallet.txdb.add(tx, block);

// Check
const bal = await wallet.getBalance();
assert.strictEqual(bal.tx, 1);
assert.strictEqual(bal.coin, 1);
assert.strictEqual(bal.confirmed, 10e6);
assert.strictEqual(bal.unconfirmed, 10e6);
assert.strictEqual(bal.ulocked, 0);
assert.strictEqual(bal.clocked, 0);
});

it('should send and confirm OPEN', async () => {
const open = await wallet.sendOpen(name, false, {hardFee: fee});

// Check
let bal = await wallet.getBalance();
assert.strictEqual(bal.tx, 2);
assert.strictEqual(bal.coin, 2);
assert.strictEqual(bal.confirmed, 10e6);
assert.strictEqual(bal.unconfirmed, 10e6 - fee);
assert.strictEqual(bal.ulocked, 0);
assert.strictEqual(bal.clocked, 0);

// Confirm OPEN
const block = {
height: wdb.height + 1,
hash: Buffer.alloc(32),
time: Date.now()
};
await wallet.txdb.add(open, block);

// Check
bal = await wallet.getBalance();
assert.strictEqual(bal.tx, 2);
assert.strictEqual(bal.coin, 2);
assert.strictEqual(bal.confirmed, 10e6 - (1 * fee));
assert.strictEqual(bal.unconfirmed, 10e6 - (1 * fee));
assert.strictEqual(bal.ulocked, 0);
assert.strictEqual(bal.clocked, 0);
});

it('should send and confirm BID', async () => {
// Advance to bidding
wdb.height += network.names.treeInterval + 1;

const bid = await wallet.sendBid(name, value, lockup, {hardFee: fee});

// Check
let bal = await wallet.getBalance();
assert.strictEqual(bal.tx, 3);
assert.strictEqual(bal.coin, 3);
assert.strictEqual(bal.confirmed, 10e6 - (1 * fee));
assert.strictEqual(bal.unconfirmed, 10e6 - (2 * fee));
assert.strictEqual(bal.ulocked, lockup);
assert.strictEqual(bal.clocked, 0);

// Confirm BID
const block = {
height: wdb.height + 1,
hash: Buffer.alloc(32),
time: Date.now()
};
await wallet.txdb.add(bid, block);

// Check
bal = await wallet.getBalance();
assert.strictEqual(bal.tx, 3);
assert.strictEqual(bal.coin, 3);
assert.strictEqual(bal.confirmed, 10e6 - (2 * fee));
assert.strictEqual(bal.unconfirmed, 10e6 - (2 * fee));
assert.strictEqual(bal.ulocked, lockup);
assert.strictEqual(bal.clocked, lockup);
});

it('should send and confirm REVEAL', async () => {
// Advance to reveal
wdb.height += network.names.biddingPeriod;

const reveal = await wallet.sendReveal(name, {hardFee: fee});

// Check
let bal = await wallet.getBalance();
assert.strictEqual(bal.tx, 4);
assert.strictEqual(bal.coin, 4);
assert.strictEqual(bal.confirmed, 10e6 - (2 * fee));
assert.strictEqual(bal.unconfirmed, 10e6 - (3 * fee));
assert.strictEqual(bal.ulocked, value);
assert.strictEqual(bal.clocked, lockup);

// Confirm BID
const block = {
height: wdb.height + 1,
hash: Buffer.alloc(32),
time: Date.now()
};
await wallet.txdb.add(reveal, block);

// Check
bal = await wallet.getBalance();
assert.strictEqual(bal.tx, 4);
assert.strictEqual(bal.coin, 4);
assert.strictEqual(bal.confirmed, 10e6 - (3 * fee));
assert.strictEqual(bal.unconfirmed, 10e6 - (3 * fee));
assert.strictEqual(bal.ulocked, value);
assert.strictEqual(bal.clocked, value);
});
});

describe('TXDB locked balance after simulated rescan', function() {
const network = Network.get('regtest');
const workers = new WorkerPool({ enabled });
const wdb = new WalletDB({ network, workers });
const name = 'satoshi';
const value = 1e6;
const lockup = 2e6;
const fee = 10000;
let wallet;

before(async () => {
await wdb.open();
wallet = await wdb.create();
// rollout all names
wdb.height = 52 * 144 * 7;
});

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

it('should fund wallet', async () => {
const addr = await wallet.receiveAddress();

// Fund wallet
const mtx = new MTX();
mtx.addOutpoint(new Outpoint(Buffer.alloc(32), 0));
mtx.addOutput(addr, 10e6);
const tx = mtx.toTX();

// Dummy block
const block = {
height: wdb.height + 1,
hash: Buffer.alloc(32),
time: Date.now()
};

// Add confirmed funding TX to wallet
await wallet.txdb.add(tx, block);

// Check
const bal = await wallet.getBalance();
assert.strictEqual(bal.tx, 1);
assert.strictEqual(bal.coin, 1);
assert.strictEqual(bal.confirmed, 10e6);
assert.strictEqual(bal.unconfirmed, 10e6);
assert.strictEqual(bal.ulocked, 0);
assert.strictEqual(bal.clocked, 0);
});

it('should confirm new OPEN', async () => {
const open = await wallet.createOpen(name, false, {hardFee: fee});

// Check
let bal = await wallet.getBalance();
assert.strictEqual(bal.tx, 1);
assert.strictEqual(bal.coin, 1);
assert.strictEqual(bal.confirmed, 10e6);
assert.strictEqual(bal.unconfirmed, 10e6);
assert.strictEqual(bal.ulocked, 0);
assert.strictEqual(bal.clocked, 0);

// Confirm OPEN
const block = {
height: wdb.height + 1,
hash: Buffer.alloc(32),
time: Date.now()
};
await wallet.txdb.add(open.toTX(), block);

// Check
bal = await wallet.getBalance();
assert.strictEqual(bal.tx, 2);
assert.strictEqual(bal.coin, 2);
assert.strictEqual(bal.confirmed, 10e6 - (1 * fee));
assert.strictEqual(bal.unconfirmed, 10e6 - (1 * fee));
assert.strictEqual(bal.ulocked, 0);
assert.strictEqual(bal.clocked, 0);
});

it('should confirm new BID', async () => {
// Advance to bidding
wdb.height += network.names.treeInterval + 1;

const bid = await wallet.createBid(name, value, lockup, {hardFee: fee});

// Check
let bal = await wallet.getBalance();
assert.strictEqual(bal.tx, 2);
assert.strictEqual(bal.coin, 2);
assert.strictEqual(bal.confirmed, 10e6 - (1 * fee));
assert.strictEqual(bal.unconfirmed, 10e6 - (1 * fee));
assert.strictEqual(bal.ulocked, 0);
assert.strictEqual(bal.clocked, 0);

// Confirm BID
const block = {
height: wdb.height + 1,
hash: Buffer.alloc(32),
time: Date.now()
};
await wallet.txdb.add(bid.toTX(), block);

// Check
bal = await wallet.getBalance();
assert.strictEqual(bal.tx, 3);
assert.strictEqual(bal.coin, 3);
assert.strictEqual(bal.confirmed, 10e6 - (2 * fee));
assert.strictEqual(bal.unconfirmed, 10e6 - (2 * fee));
assert.strictEqual(bal.ulocked, lockup);
assert.strictEqual(bal.clocked, lockup);
});

it('should confirm new REVEAL', async () => {
// Advance to reveal
wdb.height += network.names.biddingPeriod;

const reveal = await wallet.createReveal(name, {hardFee: fee});

// Check
let bal = await wallet.getBalance();
assert.strictEqual(bal.tx, 3);
assert.strictEqual(bal.coin, 3);
assert.strictEqual(bal.confirmed, 10e6 - (2 * fee));
assert.strictEqual(bal.unconfirmed, 10e6 - (2 * fee));
assert.strictEqual(bal.ulocked, lockup);
assert.strictEqual(bal.clocked, lockup);

// Confirm BID
const block = {
height: wdb.height + 1,
hash: Buffer.alloc(32),
time: Date.now()
};
await wallet.txdb.add(reveal.toTX(), block);

// Check
bal = await wallet.getBalance();
assert.strictEqual(bal.tx, 4);
assert.strictEqual(bal.coin, 4);
assert.strictEqual(bal.confirmed, 10e6 - (3 * fee));
assert.strictEqual(bal.unconfirmed, 10e6 - (3 * fee));
assert.strictEqual(bal.ulocked, value);
assert.strictEqual(bal.clocked, value);
});
});
});

0 comments on commit 6eb92ba

Please sign in to comment.