842 lines
22 KiB
JavaScript
842 lines
22 KiB
JavaScript
'use strict';
|
|
|
|
const assert = require('bsert');
|
|
const Chain = require('../lib/blockchain/chain');
|
|
const BlockStore = require('../lib/blockstore/level');
|
|
const WorkerPool = require('../lib/workers/workerpool');
|
|
const Miner = require('../lib/mining/miner');
|
|
const MemWallet = require('./util/memwallet');
|
|
const Network = require('../lib/protocol/network');
|
|
const rules = require('../lib/covenants/rules');
|
|
const {ownership} = require('../lib/covenants/ownership');
|
|
const {CachedStubResolver, STUB_SERVERS} = require('./util/stub');
|
|
|
|
const network = Network.get('regtest');
|
|
const GNAME_SIZE = 10;
|
|
const NAME1 = rules.grindName(GNAME_SIZE, 20, network);
|
|
const NAME2 = rules.grindName(GNAME_SIZE, 20, network);
|
|
|
|
const workers = new WorkerPool({
|
|
// Must be disabled for `ownership.ignore`.
|
|
enabled: false,
|
|
size: 2
|
|
});
|
|
|
|
function createNode() {
|
|
const blocks = new BlockStore({
|
|
memory: true,
|
|
network
|
|
});
|
|
|
|
const chain = new Chain({
|
|
memory: true,
|
|
blocks,
|
|
network,
|
|
workers
|
|
});
|
|
|
|
const miner = new Miner({
|
|
chain,
|
|
workers
|
|
});
|
|
|
|
return {
|
|
chain,
|
|
blocks,
|
|
miner,
|
|
cpu: miner.cpu,
|
|
wallet: () => {
|
|
const wallet = new MemWallet({ network });
|
|
|
|
chain.on('connect', (entry, block) => {
|
|
wallet.addBlock(entry, block.txs);
|
|
});
|
|
|
|
chain.on('disconnect', (entry, block) => {
|
|
wallet.removeBlock(entry, block.txs);
|
|
});
|
|
|
|
wallet.getNameStatus = async (nameHash) => {
|
|
assert(Buffer.isBuffer(nameHash));
|
|
const height = chain.height + 1;
|
|
return chain.db.getNameStatus(nameHash, height);
|
|
};
|
|
|
|
return wallet;
|
|
}
|
|
};
|
|
}
|
|
|
|
describe('Auction', function() {
|
|
this.timeout(15000);
|
|
|
|
const originalResolver = ownership.Resolver;
|
|
const originalServers = ownership.servers;
|
|
|
|
before(() => {
|
|
ownership.Resolver = CachedStubResolver;
|
|
ownership.servers = STUB_SERVERS;
|
|
});
|
|
|
|
after(() => {
|
|
ownership.Resolver = originalResolver;
|
|
ownership.servers = originalServers;
|
|
});
|
|
|
|
describe('Vickrey Auction', function() {
|
|
const node = createNode();
|
|
const orig = createNode();
|
|
const comp = createNode();
|
|
|
|
const {chain, miner, cpu, blocks} = node;
|
|
|
|
const winner = node.wallet();
|
|
const runnerup = node.wallet();
|
|
|
|
let snapshot = null;
|
|
|
|
let transferBlock, transferLockupEnd, blocksUntilValidFinalize;
|
|
|
|
it('should open chain and miner', async () => {
|
|
await blocks.open();
|
|
await chain.open();
|
|
await miner.open();
|
|
});
|
|
|
|
it('should add addrs to miner', async () => {
|
|
miner.addresses.length = 0;
|
|
miner.addAddress(winner.getReceive());
|
|
miner.addAddress(runnerup.getReceive());
|
|
});
|
|
|
|
it('should mine 20 blocks', async () => {
|
|
for (let i = 0; i < 20; i++) {
|
|
const block = await cpu.mineBlock();
|
|
assert(block);
|
|
assert(await chain.add(block));
|
|
}
|
|
});
|
|
|
|
it('should open auction', async () => {
|
|
const mtx = await winner.createOpen(NAME1);
|
|
|
|
const job = await cpu.createJob();
|
|
job.addTX(mtx.toTX(), mtx.view);
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
assert(await chain.add(block));
|
|
});
|
|
|
|
it('should mine blocks', async () => {
|
|
for (let i = 0; i < network.names.treeInterval; i++) {
|
|
const block = await cpu.mineBlock();
|
|
assert(block);
|
|
assert(await chain.add(block));
|
|
}
|
|
});
|
|
|
|
it('should open a bid', async () => {
|
|
const mtx1 = await winner.createBid(NAME1, 1000, 2000);
|
|
const mtx2 = await runnerup.createBid(NAME1, 500, 2000);
|
|
|
|
const job = await cpu.createJob();
|
|
job.addTX(mtx1.toTX(), mtx1.view);
|
|
job.addTX(mtx2.toTX(), mtx2.view);
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
assert(await chain.add(block));
|
|
});
|
|
|
|
it('should mine through the bidding period', async () => {
|
|
for (let i = 0; i < network.names.biddingPeriod; i++) {
|
|
const block = await cpu.mineBlock();
|
|
assert(block);
|
|
assert(await chain.add(block));
|
|
}
|
|
});
|
|
|
|
it('should reveal a bid', async () => {
|
|
const mtx1 = await winner.createReveal(NAME1);
|
|
const mtx2 = await runnerup.createReveal(NAME1);
|
|
|
|
const job = await cpu.createJob();
|
|
job.addTX(mtx1.toTX(), mtx1.view);
|
|
job.addTX(mtx2.toTX(), mtx2.view);
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
assert(await chain.add(block));
|
|
});
|
|
|
|
it('should mine through the reveal period', async () => {
|
|
for (let i = 0; i < network.names.revealPeriod; i++) {
|
|
const block = await cpu.mineBlock();
|
|
assert(block);
|
|
assert(await chain.add(block));
|
|
}
|
|
});
|
|
|
|
it('should register a name', async () => {
|
|
const mtx = await winner.createRegister(NAME1, Buffer.from([1,2,3]));
|
|
|
|
assert(mtx.outputs.length > 0);
|
|
|
|
// Should pay the second highest bid.
|
|
assert.strictEqual(mtx.outputs[0].value, 500);
|
|
|
|
const job = await cpu.createJob();
|
|
job.addTX(mtx.toTX(), mtx.view);
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
assert(await chain.add(block));
|
|
});
|
|
|
|
it('should mine a tree interval', async () => {
|
|
for (let i = 0; i < network.names.treeInterval; i++) {
|
|
const block = await cpu.mineBlock();
|
|
assert(block);
|
|
assert(await chain.add(block));
|
|
}
|
|
});
|
|
|
|
it('should register again and update tree', async () => {
|
|
const mtx = await winner.createUpdate(NAME1, Buffer.from([1,2,4]));
|
|
|
|
const job = await cpu.createJob();
|
|
job.addTX(mtx.toTX(), mtx.view);
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
assert(await chain.add(block));
|
|
});
|
|
|
|
it('should redeem', async () => {
|
|
const mtx = await runnerup.createRedeem(NAME1);
|
|
|
|
const job = await cpu.createJob();
|
|
job.addTX(mtx.toTX(), mtx.view);
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
assert(await chain.add(block));
|
|
});
|
|
|
|
it('should renew', async () => {
|
|
const mtx = await winner.createRenewal(NAME1);
|
|
|
|
const job = await cpu.createJob();
|
|
job.addTX(mtx.toTX(), mtx.view);
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
assert(await chain.add(block));
|
|
});
|
|
|
|
it('should fail renew', async () => {
|
|
const mtx = await winner.createRenewal(NAME1);
|
|
|
|
const job = await cpu.createJob();
|
|
job.addTX(mtx.toTX(), mtx.view);
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
let err = null;
|
|
|
|
try {
|
|
await chain.add(block);
|
|
} catch (e) {
|
|
err = e;
|
|
}
|
|
|
|
assert(err);
|
|
assert.strictEqual(err.reason, 'bad-renewal-premature');
|
|
});
|
|
|
|
it('should mine a tree interval', async () => {
|
|
for (let i = 0; i < network.names.treeInterval; i++) {
|
|
const block = await cpu.mineBlock();
|
|
assert(block);
|
|
assert(await chain.add(block));
|
|
}
|
|
|
|
snapshot = {
|
|
treeRoot: chain.tip.treeRoot,
|
|
ns: await chain.db.getNameStateByName(NAME1)
|
|
};
|
|
});
|
|
|
|
it('should open other nodes', async () => {
|
|
await orig.blocks.open();
|
|
await orig.chain.open();
|
|
await orig.miner.open();
|
|
await comp.blocks.open();
|
|
await comp.chain.open();
|
|
await comp.miner.open();
|
|
});
|
|
|
|
it('should clone the chain', async () => {
|
|
for (let i = 1; i <= chain.height; i++) {
|
|
const block = await chain.getBlock(i);
|
|
assert(block);
|
|
assert(await orig.chain.add(block));
|
|
}
|
|
});
|
|
|
|
it('should mine a competing chain', async () => {
|
|
while (comp.chain.tip.chainwork.lte(chain.tip.chainwork)) {
|
|
const block = await comp.cpu.mineBlock();
|
|
assert(block);
|
|
assert(await comp.chain.add(block));
|
|
}
|
|
});
|
|
|
|
it('should reorg the auction', async () => {
|
|
let reorgd = false;
|
|
|
|
chain.once('reorganize', () => reorgd = true);
|
|
|
|
// chain.on('disconnect', async () => {
|
|
// const ns = await chain.db.getNameStateByName(NAME1);
|
|
// if (ns)
|
|
// console.log(ns.format(chain.height, network));
|
|
// });
|
|
|
|
for (let i = 1; i <= comp.chain.height; i++) {
|
|
assert(!reorgd);
|
|
const block = await comp.chain.getBlock(i);
|
|
assert(block);
|
|
assert(await chain.add(block));
|
|
}
|
|
|
|
assert(reorgd);
|
|
|
|
const ns = await chain.db.getNameStateByName(NAME1);
|
|
assert(!ns);
|
|
});
|
|
|
|
it('should reorg back to the correct state', async () => {
|
|
let reorgd = false;
|
|
|
|
chain.once('reorganize', () => reorgd = true);
|
|
|
|
// chain.on('connect', async () => {
|
|
// const ns = await chain.db.getNameStateByName(NAME1);
|
|
// if (ns)
|
|
// console.log(ns.format(chain.height, network));
|
|
// });
|
|
|
|
while (!reorgd) {
|
|
const block = await orig.cpu.mineBlock();
|
|
assert(block);
|
|
assert(await orig.chain.add(block));
|
|
assert(await chain.add(block));
|
|
}
|
|
});
|
|
|
|
it('should close other nodes', async () => {
|
|
await orig.miner.close();
|
|
await orig.chain.close();
|
|
await orig.blocks.close();
|
|
await comp.miner.close();
|
|
await comp.chain.close();
|
|
await comp.blocks.close();
|
|
});
|
|
|
|
it('should mine 10 blocks', async () => {
|
|
for (let i = 0; i < 10; i++) {
|
|
const block = await cpu.mineBlock();
|
|
assert(block);
|
|
assert(await chain.add(block));
|
|
}
|
|
});
|
|
|
|
it('should have the same DB state', async () => {
|
|
const ns = await chain.db.getNameStateByName(NAME1);
|
|
assert(ns);
|
|
|
|
assert.deepStrictEqual(ns, snapshot.ns);
|
|
assert.bufferEqual(chain.tip.treeRoot, snapshot.treeRoot);
|
|
});
|
|
|
|
it('should mine 2 blocks', async () => {
|
|
for (let i = 0; i < 2; i++) {
|
|
const block = await cpu.mineBlock();
|
|
assert(block);
|
|
assert(await chain.add(block));
|
|
}
|
|
});
|
|
|
|
it('should open auction', async () => {
|
|
const mtx = await winner.createOpen(NAME2);
|
|
|
|
const job = await cpu.createJob();
|
|
job.addTX(mtx.toTX(), mtx.view);
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
assert(await chain.add(block));
|
|
});
|
|
|
|
it('should have the same DB root', async () => {
|
|
assert((chain.height % network.names.treeInterval) !== 0);
|
|
const root = chain.db.txn.rootHash();
|
|
await chain.close();
|
|
await chain.open();
|
|
assert.bufferEqual(root, chain.db.txn.rootHash());
|
|
});
|
|
|
|
it('should not have transfer stats in JSON yet', async () => {
|
|
const ns = await chain.db.getNameStateByName(NAME1);
|
|
const {stats} = ns.getJSON(chain.height, network);
|
|
assert.ok(stats.renewalPeriodStart);
|
|
assert.ok(stats.renewalPeriodEnd);
|
|
assert.ok(stats.blocksUntilExpire);
|
|
assert.ok(stats.daysUntilExpire);
|
|
assert.ok(!stats.transferLockupStart);
|
|
assert.ok(!stats.transferLockupEnd);
|
|
assert.ok(!stats.blocksUntilValidFinalize);
|
|
assert.ok(!stats.hoursUntilValidFinalize);
|
|
});
|
|
|
|
it('should transfer a name', async () => {
|
|
const mtx = await winner.createTransfer(NAME1, runnerup.getReceive());
|
|
|
|
const job = await cpu.createJob();
|
|
job.addTX(mtx.toTX(), mtx.view);
|
|
job.refresh();
|
|
const block = await job.mineAsync();
|
|
const entry = await chain.add(block);
|
|
assert(entry);
|
|
transferBlock = entry.height;
|
|
});
|
|
|
|
it('should be in a transfer state', async () => {
|
|
const ns = await chain.db.getNameStateByName(NAME1);
|
|
assert.strictEqual(ns.transfer, transferBlock);
|
|
assert(ns.transfer !== 0);
|
|
});
|
|
|
|
it('should have transfer stats', async () => {
|
|
const ns = await chain.db.getNameStateByName(NAME1);
|
|
const {stats} = ns.getJSON(chain.height, network);
|
|
assert.ok(stats.renewalPeriodStart);
|
|
assert.ok(stats.renewalPeriodEnd);
|
|
assert.ok(stats.blocksUntilExpire);
|
|
assert.ok(stats.daysUntilExpire);
|
|
assert.ok(stats.transferLockupStart);
|
|
assert.ok(stats.transferLockupEnd);
|
|
assert.ok(stats.blocksUntilValidFinalize);
|
|
assert.ok(stats.hoursUntilValidFinalize);
|
|
|
|
// The height of the first block that can contain a valid FINALIZE
|
|
transferLockupEnd = stats.transferLockupEnd;
|
|
// The number of blocks (inclusive) until that height will be reached
|
|
blocksUntilValidFinalize = stats.blocksUntilValidFinalize;
|
|
});
|
|
|
|
it('should finalize at expected height', async () => {
|
|
const mtx = await winner.createFinalize(NAME1);
|
|
|
|
// Attempt to confirm the FINALIZE in a block.
|
|
// If it fails, mine an empty block instead.
|
|
// Repeat until the chain height completes the
|
|
// transfer lockup period and the FINALIZE is valid.
|
|
let count = 0;
|
|
let entry;
|
|
for (;;) {
|
|
try {
|
|
const job = await cpu.createJob();
|
|
job.addTX(mtx.toTX(), mtx.view);
|
|
job.refresh();
|
|
const block = await job.mineAsync();
|
|
entry = await chain.add(block);
|
|
|
|
// exit loop when FINALIZE is finally confirmed without error
|
|
assert.strictEqual(block.txs.length, 2);
|
|
count++;
|
|
break;
|
|
} catch(e) {
|
|
assert.strictEqual(e.reason, 'bad-finalize-maturity');
|
|
|
|
// Ok, fine - mine a block without the FINALIZE
|
|
const job = await cpu.createJob();
|
|
job.refresh();
|
|
const block = await job.mineAsync();
|
|
entry = await chain.add(block);
|
|
|
|
// just a coinbase
|
|
assert.strictEqual(block.txs.length, 1);
|
|
|
|
count++;
|
|
}
|
|
}
|
|
|
|
assert.strictEqual(count, blocksUntilValidFinalize);
|
|
assert.strictEqual(entry.height, transferLockupEnd);
|
|
});
|
|
|
|
it('should cleanup', async () => {
|
|
await miner.close();
|
|
await chain.close();
|
|
await blocks.close();
|
|
});
|
|
});
|
|
|
|
describe('Claim', function() {
|
|
this.timeout(10000);
|
|
|
|
const node = createNode();
|
|
const {chain, miner, cpu, blocks} = node;
|
|
|
|
const wallet = node.wallet();
|
|
const recip = node.wallet();
|
|
|
|
it('should open chain and miner', async () => {
|
|
await blocks.open();
|
|
await chain.open();
|
|
await miner.open();
|
|
});
|
|
|
|
it('should add addrs to miner', async () => {
|
|
miner.addresses.length = 0;
|
|
miner.addAddress(wallet.getReceive());
|
|
});
|
|
|
|
it('should mine a tree interval', async () => {
|
|
for (let i = 0; i < network.names.treeInterval; i++) {
|
|
const block = await cpu.mineBlock();
|
|
assert(block);
|
|
assert(await chain.add(block));
|
|
}
|
|
});
|
|
|
|
it('should reject a fraudulent claim', async () => {
|
|
const claim = await wallet.fakeClaim('cloudflare');
|
|
|
|
const job = await cpu.createJob();
|
|
job.pushClaim(claim, network);
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
let err = null;
|
|
|
|
try {
|
|
await chain.add(block);
|
|
} catch (e) {
|
|
err = e;
|
|
}
|
|
|
|
assert(err);
|
|
assert.strictEqual(err.reason, 'mandatory-script-verify-flag-failed');
|
|
});
|
|
|
|
it('should open a claim for cloudflare.com', async () => {
|
|
const claim = await wallet.fakeClaim('cloudflare');
|
|
|
|
const job = await cpu.createJob();
|
|
job.pushClaim(claim, network);
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
try {
|
|
ownership.ignore = true;
|
|
assert(await chain.add(block));
|
|
} finally {
|
|
ownership.ignore = false;
|
|
}
|
|
});
|
|
|
|
it('should open a TLD claim for .fr', async () => {
|
|
const claim = await wallet.fakeClaim('fr');
|
|
|
|
const job = await cpu.createJob();
|
|
job.pushClaim(claim, network);
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
try {
|
|
ownership.ignore = true;
|
|
assert(await chain.add(block));
|
|
} finally {
|
|
ownership.ignore = false;
|
|
}
|
|
});
|
|
|
|
it('should mine to deflation height', async () => {
|
|
assert(chain.height < network.deflationHeight - 2);
|
|
|
|
while (chain.height < network.deflationHeight - 2) {
|
|
const block = await cpu.mineBlock();
|
|
assert(block);
|
|
assert(await chain.add(block));
|
|
}
|
|
});
|
|
|
|
it('should open a TLD claim for .nl', async () => {
|
|
const claim = await wallet.fakeClaim('nl');
|
|
|
|
assert(chain.height === network.deflationHeight - 2);
|
|
|
|
const job = await cpu.createJob();
|
|
const last = job.attempt.fees;
|
|
|
|
job.pushClaim(claim, network);
|
|
|
|
assert(job.attempt.fees === last + job.attempt.claims[0].fee);
|
|
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
try {
|
|
ownership.ignore = true;
|
|
assert(await chain.add(block));
|
|
} finally {
|
|
ownership.ignore = false;
|
|
}
|
|
});
|
|
|
|
it('should fail to replace TLD claim for .nl', async () => {
|
|
const claim = await wallet.fakeClaim('nl', {
|
|
rate: 2000,
|
|
commitHeight: 2
|
|
});
|
|
|
|
assert(chain.height === network.deflationHeight - 1);
|
|
|
|
const job = await cpu.createJob();
|
|
job.pushClaim(claim, network);
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
let err = null;
|
|
|
|
ownership.ignore = true;
|
|
|
|
try {
|
|
await chain.add(block);
|
|
} catch (e) {
|
|
err = e;
|
|
}
|
|
|
|
ownership.ignore = false;
|
|
|
|
assert(err);
|
|
assert.strictEqual(err.reason, 'bad-claim-value');
|
|
});
|
|
|
|
it('should reject a fee-redeeming coinbase for .nl', async () => {
|
|
const claim = await wallet.fakeClaim('nl', {
|
|
commitHeight: 2
|
|
});
|
|
|
|
assert(chain.height === network.deflationHeight - 1);
|
|
|
|
const job = await cpu.createJob();
|
|
const last = job.attempt.fees;
|
|
|
|
job.pushClaim(claim, network);
|
|
|
|
assert(job.attempt.fees === last);
|
|
|
|
job.attempt.fees += job.attempt.claims[0].fee;
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
let err = null;
|
|
|
|
ownership.ignore = true;
|
|
|
|
try {
|
|
await chain.add(block);
|
|
} catch (e) {
|
|
err = e;
|
|
}
|
|
|
|
ownership.ignore = false;
|
|
|
|
assert(err);
|
|
assert.strictEqual(err.reason, 'bad-cb-amount');
|
|
});
|
|
|
|
it('should replace TLD claim for .nl', async () => {
|
|
const claim = await wallet.fakeClaim('nl', {
|
|
commitHeight: 2
|
|
});
|
|
|
|
assert(chain.height === network.deflationHeight - 1);
|
|
|
|
const job = await cpu.createJob();
|
|
job.pushClaim(claim, network);
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
try {
|
|
ownership.ignore = true;
|
|
assert(await chain.add(block));
|
|
} finally {
|
|
ownership.ignore = false;
|
|
}
|
|
});
|
|
|
|
it('should open a TLD claim for .af', async () => {
|
|
const claim = await wallet.fakeClaim('af');
|
|
|
|
assert(chain.height === network.deflationHeight);
|
|
|
|
const job = await cpu.createJob();
|
|
job.pushClaim(claim, network);
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
try {
|
|
ownership.ignore = true;
|
|
assert(await chain.add(block));
|
|
} finally {
|
|
ownership.ignore = false;
|
|
}
|
|
});
|
|
|
|
/*
|
|
it('should open an i18n-ized TLD claim', async () => {
|
|
const claim = await wallet.fakeClaim('xn--ogbpf8fl');
|
|
|
|
const job = await cpu.createJob();
|
|
job.pushClaim(claim, network);
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
assert(block.txs.length > 0);
|
|
assert(block.txs[0].outputs.length === 2);
|
|
assert(block.txs[0].outputs[1].value === 0);
|
|
|
|
try {
|
|
ownership.ignore = true;
|
|
assert(await chain.add(block));
|
|
} finally {
|
|
ownership.ignore = false;
|
|
}
|
|
});
|
|
*/
|
|
|
|
it('should mine a tree interval', async () => {
|
|
for (let i = 0; i < network.names.treeInterval; i++) {
|
|
const block = await cpu.mineBlock();
|
|
assert(block);
|
|
assert(await chain.add(block));
|
|
}
|
|
});
|
|
|
|
it('should register a claimed name', async () => {
|
|
const mtx = await wallet.createRegister('cloudflare', Buffer.from([1,2]));
|
|
|
|
const job = await cpu.createJob();
|
|
job.addTX(mtx.toTX(), mtx.view);
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
assert(await chain.add(block));
|
|
});
|
|
|
|
it('should mine 140 blocks', async () => {
|
|
for (let i = 0; i < 140; i++) {
|
|
const block = await cpu.mineBlock();
|
|
assert(block);
|
|
assert(await chain.add(block));
|
|
}
|
|
});
|
|
|
|
it('should register a claimed name', async () => {
|
|
const mtx = await wallet.createRegister('af', Buffer.from([1,2,3]));
|
|
|
|
const job = await cpu.createJob();
|
|
job.addTX(mtx.toTX(), mtx.view);
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
assert(await chain.add(block));
|
|
});
|
|
|
|
it('should transfer strong name', async () => {
|
|
const addr = recip.createReceive().getAddress();
|
|
const mtx = await wallet.createTransfer('af', addr);
|
|
|
|
const job = await cpu.createJob();
|
|
job.addTX(mtx.toTX(), mtx.view);
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
assert(await chain.add(block));
|
|
});
|
|
|
|
it('should not be able to finalize early', async () => {
|
|
const mtx = await wallet.createFinalize('af');
|
|
|
|
const job = await cpu.createJob();
|
|
job.addTX(mtx.toTX(), mtx.view);
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
let err = null;
|
|
|
|
try {
|
|
await chain.add(block);
|
|
} catch (e) {
|
|
err = e;
|
|
}
|
|
|
|
assert(err);
|
|
assert.strictEqual(err.reason, 'bad-finalize-maturity');
|
|
});
|
|
|
|
it('should mine through the transfer lockup period', async () => {
|
|
for (let i = 0; i < network.names.transferLockup; i++) {
|
|
const block = await cpu.mineBlock();
|
|
assert(block);
|
|
assert(await chain.add(block));
|
|
}
|
|
});
|
|
|
|
it('should finalize name', async () => {
|
|
const mtx = await wallet.createFinalize('af');
|
|
|
|
const job = await cpu.createJob();
|
|
job.addTX(mtx.toTX(), mtx.view);
|
|
job.refresh();
|
|
|
|
const block = await job.mineAsync();
|
|
|
|
assert(await chain.add(block));
|
|
});
|
|
|
|
it('should cleanup', async () => {
|
|
await miner.close();
|
|
await chain.close();
|
|
await blocks.close();
|
|
});
|
|
});
|
|
});
|