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

chain-test: cover CSV by time #613

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
chain-test: cover CSV by time
  • Loading branch information
pinheadmz committed Oct 4, 2018
commit 865864af6d4aae1051aacc371f7e7edc409c2d3c
201 changes: 174 additions & 27 deletions test/chain-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,13 @@ async function mineBlock(job, flags) {
return await addBlock(block, flags);
}

async function mineCSV(fund) {
async function mineCSVbyHeight(fund) {
const job = await cpu.createJob();
const spend = new MTX();

spend.addOutput({
script: [
Opcode.fromInt(1),
Opcode.fromInt(2),
Opcode.fromSymbol('checksequenceverify')
],
value: 10000
Expand All @@ -102,6 +102,45 @@ async function mineCSV(fund) {
return await job.mineAsync();
}

async function mineCSVbyTime(fund) {
const job = await cpu.createJob();
const spend = new MTX();
const locktime = CSVencode(60 * 15); // fifteen minutes

spend.addOutput({
script: [
Opcode.fromInt(locktime),
Opcode.fromSymbol('checksequenceverify')
],
value: 10000
});

spend.addTX(fund, 0);
spend.setLocktime(chain.height);

wallet.sign(spend);

const [tx, view] = spend.commit();

job.addTX(tx, view);
job.refresh();

return await job.mineAsync();
}

// formats relative locktime in seconds with flags according to BIP112
function CSVencode(locktime) {
let locktimeUint32 = locktime >>> 0;
if(locktimeUint32 !== locktime)
throw new Error('Locktime must be a uint32.');

locktimeUint32 >>>= consensus.SEQUENCE_GRANULARITY; // 512-second units
locktimeUint32 &= consensus.SEQUENCE_MASK; // 0x0000ffff
locktimeUint32 |= consensus.SEQUENCE_TYPE_FLAG; // time, not height

return locktimeUint32;
}

chain.on('connect', (entry, block) => {
wallet.addBlock(entry, block.txs);
});
Expand Down Expand Up @@ -425,9 +464,9 @@ describe('Chain', function() {
assert.strictEqual(state, 3);
});

it('should test csv', async () => {
it('should test csv by height', async () => {
const tx = (await chain.getBlock(chain.height - 100)).txs[0];
const csvBlock = await mineCSV(tx);
const csvBlock = await mineCSVbyHeight(tx);

assert(await chain.add(csvBlock));

Expand All @@ -437,17 +476,19 @@ describe('Chain', function() {

spend.addOutput({
script: [
Opcode.fromInt(2),
Opcode.fromSymbol('checksequenceverify')
Opcode.fromBool(true)
],
value: 10000
});

spend.addTX(csv, 0);
spend.setSequence(0, 1, false);
spend.setSequence(0, 2, false);

const job = await cpu.createJob();
const block2 = await cpu.mineBlock();
assert(block2);
assert(await chain.add(block2));

const job = await cpu.createJob();
job.addTX(spend.toTX(), spend.view);
job.refresh();

Expand All @@ -456,16 +497,21 @@ describe('Chain', function() {
assert(await chain.add(block));
});

it('should fail csv with bad sequence', async () => {
const csv = (await chain.getBlock(chain.height - 100)).txs[0];
it('should fail csv by height with bad sequence', async () => {
const tx = (await chain.getBlock(chain.height - 100)).txs[0];
const csvBlock = await mineCSVbyHeight(tx);

assert(await chain.add(csvBlock));

const csv = csvBlock.txs[1];

const spend = new MTX();

spend.addOutput({
script: [
Opcode.fromInt(1),
Opcode.fromSymbol('checksequenceverify')
Opcode.fromBool(true)
],
value: 1 * 1e8
value: 10000
});

spend.addTX(csv, 0);
Expand All @@ -479,15 +525,9 @@ describe('Chain', function() {
'mandatory-script-verify-flag-failed');
});

it('should mine a block', async () => {
const block = await cpu.mineBlock();
assert(block);
assert(await chain.add(block));
});

it('should fail csv lock checks', async () => {
it('should fail csv by height lock checks', async () => {
const tx = (await chain.getBlock(chain.height - 100)).txs[0];
const csvBlock = await mineCSV(tx);
const csvBlock = await mineCSVbyHeight(tx);

assert(await chain.add(csvBlock));

Expand All @@ -497,10 +537,9 @@ describe('Chain', function() {

spend.addOutput({
script: [
Opcode.fromInt(2),
Opcode.fromSymbol('checksequenceverify')
Opcode.fromBool(true)
],
value: 1 * 1e8
value: 10000
});

spend.addTX(csv, 0);
Expand All @@ -513,8 +552,116 @@ describe('Chain', function() {
assert.strictEqual(await mineBlock(job), 'bad-txns-nonfinal');
});

it('should fail csv by time with lock checks', async () => {
const tx = (await chain.getBlock(chain.height - 100)).txs[0];
const csvBlock = await mineCSVbyTime(tx);

assert(await chain.add(csvBlock));

const csv = csvBlock.txs[1];

const spend = new MTX();

spend.addOutput({
script: [
Opcode.fromBool(true)
],
value: 10000
});

spend.addTX(csv, 0);
const seconds = 60 * 30; // thirty minutes
spend.setSequence(0, seconds, true);
spend.setLocktime(0);

const job2 = await cpu.createJob();
job2.addTX(spend.toTX(), spend.view);
job2.attempt.time = network.now() + 60 * 10; // ten minutes
job2.refresh();

assert.strictEqual(await mineBlock(job2), 'bad-txns-nonfinal');
});

it('should fail csv by time with bad sequence', async () => {
const tx = (await chain.getBlock(chain.height - 100)).txs[0];
const csvBlock = await mineCSVbyTime(tx);

assert(await chain.add(csvBlock));

const csv = csvBlock.txs[1];

const spend = new MTX();

spend.addOutput({
script: [
Opcode.fromBool(true)
],
value: 10000
});

spend.addTX(csv, 0);
const seconds = 60 * 1; // one minute
spend.setSequence(0, seconds, true);
spend.setLocktime(0);

const job2 = await cpu.createJob();
job2.addTX(spend.toTX(), spend.view);
job2.attempt.time = network.now() + 60 * 10; // ten minutes
job2.refresh();

assert.strictEqual(await mineBlock(job2),
'mandatory-script-verify-flag-failed');
});

it('should test csv by time', async () => {
consensus.MEDIAN_TIMESPAN = 1; // we need to mess with the clock here

const tx = (await chain.getBlock(chain.height - 100)).txs[0];
const csvBlock = await mineCSVbyTime(tx);

assert(await chain.add(csvBlock));

const csv = csvBlock.txs[1];

const spend = new MTX();

spend.addOutput({
script: [
Opcode.fromBool(true)
],
value: 10000
});

spend.addTX(csv, 0);
const seconds = 60 * 30; // thirty minutes
spend.setSequence(0, seconds, true);
spend.setLocktime(0);

// this block pushes the network mean time way ahead
const job1 = await cpu.createJob();
job1.attempt.time = network.now() + 60 * 45; // forty-five minutes
job1.refresh();
const block1 = await job1.mineAsync();
assert(await chain.add(block1));

const job2 = await cpu.createJob();
job2.addTX(spend.toTX(), spend.view);
job2.attempt.time = network.now() + 60 * 60 * 1.45; // almost two hours
job2.refresh();
const block2 = await job2.mineAsync();
assert(await chain.add(block2));

consensus.MEDIAN_TIMESPAN = 11; // reset
});

it('should mine a block', async () => {
const block = await cpu.mineBlock();
assert(block);
assert(await chain.add(block));
});

it('should have correct wallet balance', async () => {
assert.strictEqual(wallet.balance, 1412499980000);
assert.strictEqual(wallet.balance, 1414687440000);
});

it('should fail to connect bad bits', async () => {
Expand Down Expand Up @@ -627,7 +774,7 @@ describe('Chain', function() {
assert(await chain.add(block));
}

assert.strictEqual(chain.height, 2636);
assert.strictEqual(chain.height, 2643);
});

it('should mine a witness tx', async () => {
Expand Down Expand Up @@ -836,7 +983,7 @@ describe('Chain', function() {
assert(await chain.add(block, flags));
}

assert.strictEqual(chain.height, 2749);
assert.strictEqual(chain.height, 2756);
});

it('should fail to connect too many sigops', async () => {
Expand Down