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

refactor(core-blockchain): remove old fast rebuild code #2210

Merged
merged 17 commits into from Mar 8, 2019
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 4 additions & 4 deletions __tests__/integration/core-blockchain/blockchain.test.ts
@@ -1,12 +1,12 @@
/* tslint:disable:max-line-length */
import "../../utils";
import { blocks101to155 } from "../../utils/fixtures/testnet/blocks101to155";
import { blocks2to100 } from "../../utils/fixtures/testnet/blocks2to100";
import { crypto, models, slots } from "@arkecosystem/crypto";
import { crypto, models } from "@arkecosystem/crypto";
import { asValue } from "awilix";
import delay from "delay";
import { Blockchain } from "../../../packages/core-blockchain/src/blockchain";
import { defaults } from "../../../packages/core-blockchain/src/defaults";
import "../../utils";
import { blocks101to155 } from "../../utils/fixtures/testnet/blocks101to155";
import { blocks2to100 } from "../../utils/fixtures/testnet/blocks2to100";
import { setUp, tearDown } from "./__support__/setup";

const { Block, Wallet } = models;
Expand Down
2 changes: 1 addition & 1 deletion __tests__/unit/core-api/__support__/setup.ts
@@ -1,8 +1,8 @@
import { app } from "@arkecosystem/core-container";
import { Database } from "@arkecosystem/core-interfaces";
import delay from "delay";
import { registerWithContainer, setUpContainer } from "../../../utils/helpers/container";
import { plugin } from "../../../../packages/core-api/src/plugin";
import { registerWithContainer, setUpContainer } from "../../../utils/helpers/container";

import { delegates } from "../../../utils/fixtures";
import { generateRound } from "./utils/generate-round";
Expand Down
169 changes: 6 additions & 163 deletions __tests__/unit/core-blockchain/blockchain.test.ts
@@ -1,12 +1,12 @@
/* tslint:disable:max-line-length */
import "../../utils";
import { blocks101to155 } from "../../utils/fixtures/testnet/blocks101to155";
import { blocks2to100 } from "../../utils/fixtures/testnet/blocks2to100";
import { crypto, models, slots } from "@arkecosystem/crypto";
import { asValue } from "awilix";
import delay from "delay";
import { Blockchain } from "../../../packages/core-blockchain/src/blockchain";
import { defaults } from "../../../packages/core-blockchain/src/defaults";
import "../../utils";
import { blocks101to155 } from "../../utils/fixtures/testnet/blocks101to155";
import { blocks2to100 } from "../../utils/fixtures/testnet/blocks2to100";
import { setUp, tearDown } from "./__support__/setup";

const { Block, Wallet } = models;
Expand Down Expand Up @@ -94,133 +94,23 @@ describe("Blockchain", () => {
});
});

describe("rebuild", () => {
it("should throw an exception", () => {
expect(() => blockchain.rebuild()).toThrow("Method [rebuild] not implemented!");
});
});

describe("enQueueBlocks", () => {
describe("enqueueBlocks", () => {
it("should just return if blocks provided are an empty array", async () => {
const processQueuePush = jest.spyOn(blockchain.processQueue, "push");
const processQueuePush = jest.spyOn(blockchain.queue, "push");

blockchain.enqueueBlocks([]);
expect(processQueuePush).not.toHaveBeenCalled();
});

it("should enqueue the blocks provided", async () => {
const processQueuePush = jest.spyOn(blockchain.processQueue, "push");
const processQueuePush = jest.spyOn(blockchain.queue, "push");

const blocksToEnqueue = [blocks101to155[54]];
blockchain.enqueueBlocks(blocksToEnqueue);
expect(processQueuePush).toHaveBeenCalledWith(blocksToEnqueue);
});
});

describe("rebuildBlock", () => {
it("should rebuild with a known block", async () => {
const mockCallback = jest.fn(() => true);
const lastBlock = blockchain.getLastBlock();

await blockchain.rebuildBlock(lastBlock, mockCallback);
await delay(200);

expect(mockCallback.mock.calls.length).toBe(1);
});

it("should rebuild with a new chained block", async () => {
const mockCallback = jest.fn(() => true);
const lastBlock = blockchain.getLastBlock();

await blockchain.removeBlocks(1); // remove 1 block so that we can add it then as a chained block

expect(blockchain.getLastBlock()).not.toEqual(lastBlock);

await blockchain.rebuildBlock(lastBlock, mockCallback);
await delay(200);

expect(mockCallback.mock.calls.length).toBe(1);
expect(blockchain.getLastBlock()).toEqual(lastBlock);
});

it("should disregard block with height == last height but different id", async () => {
const mockCallback = jest.fn(() => true);
const lastBlock = blockchain.getLastBlock();
const lastBlockCopy = new Block(lastBlock.data);
lastBlockCopy.data.id = "123456";

const loggerInfo = jest.spyOn(logger, "info");

await blockchain.rebuildBlock(lastBlockCopy, mockCallback);
await delay(200);

expect(mockCallback.mock.calls.length).toBe(1);
expect(loggerInfo).toHaveBeenCalledWith(
`Block ${lastBlockCopy.data.height.toLocaleString()} disregarded because on a fork`,
);
expect(blockchain.getLastBlock().data.id).toBe(lastBlock.data.id);
});

it("should disregard block with height > last height + 1", async () => {
const mockCallback = jest.fn(() => true);
const lastBlock = blockchain.getLastBlock();
const lastBlockCopy = new Block(lastBlock.data);
lastBlockCopy.data.height += 2;

await blockchain.rebuildBlock(lastBlockCopy, mockCallback);
await delay(200);

expect(mockCallback.mock.calls.length).toBe(1);
expect(blockchain.getLastBlock().data.id).toBe(lastBlock.data.id);
expect(blockchain.state.lastDownloadedBlock).toBe(lastBlock);
});

it("should disregard block not verified", async () => {
const mockCallback = jest.fn(() => true);
const lastBlock = blockchain.getLastBlock();
const lastBlockCopy = new Block(lastBlock.data);
lastBlockCopy.verification.verified = false;

const loggerWarn = jest.spyOn(logger, "warn");

await blockchain.rebuildBlock(lastBlockCopy, mockCallback);
await delay(200);

expect(mockCallback.mock.calls.length).toBe(1);
expect(loggerWarn).toHaveBeenCalledWith(
`Block ${lastBlockCopy.data.height.toLocaleString()} disregarded because verification failed`,
);
expect(blockchain.getLastBlock().data.id).toBe(lastBlock.data.id);
});

it("should commitQueuedQueries if block height % 20 000 == 0", async () => {
const mockCallback = jest.fn(() => true);
const lastBlock = blockchain.getLastBlock();
const lastBlockHeight = lastBlock.data.height;
const nextBlock = new Block(blocks2to100[lastBlock.data.height - 1]);
lastBlock.data.height = 19999;
nextBlock.data.height = 20000;

const commitQueuedQueries = jest
.spyOn(blockchain.database, "commitQueuedQueries")
// @ts-ignore
.mockReturnValueOnce(true);
// @ts-ignore
jest.spyOn(blockchain.database, "enqueueSaveBlock").mockReturnValueOnce(true);

await blockchain.rebuildBlock(nextBlock, mockCallback);
await delay(200);

expect(mockCallback.mock.calls.length).toBe(1);
expect(commitQueuedQueries).toHaveBeenCalled();
expect(blockchain.getLastBlock().data.id).toBe(nextBlock.data.id);

// reset to "stable" state
lastBlock.data.height = lastBlockHeight;
blockchain.state.setLastBlock(lastBlock);
});
});

describe("processBlock", () => {
it("should process a new chained block", async () => {
const mockCallback = jest.fn(() => true);
Expand Down Expand Up @@ -377,43 +267,6 @@ describe("Blockchain", () => {
});
});

describe("isRebuildSynced", () => {
describe("with a block param", () => {
it("should be ok", () => {
jest.spyOn(blockchain.p2p, "hasPeers").mockReturnValueOnce(true);
expect(
blockchain.isRebuildSynced({
data: {
timestamp: slots.getTime() - 3600 * 24 * 6,
height: blocks101to155[52].height,
},
} as models.IBlock),
).toBeTrue();
});
});

describe("without a block param", () => {
it("should use the last block", () => {
jest.spyOn(blockchain.p2p, "hasPeers").mockReturnValueOnce(true);
const getLastBlock = jest.spyOn(blockchain, "getLastBlock").mockReturnValueOnce({
// @ts-ignore
data: {
timestamp: slots.getTime(),
height: genesisBlock.height,
},
});
expect(blockchain.isRebuildSynced()).toBeTrue();
expect(getLastBlock).toHaveBeenCalled();
});
});

it("should return true when there is no peer", () => {
jest.spyOn(blockchain.p2p, "hasPeers").mockReturnValueOnce(false);

expect(blockchain.isRebuildSynced()).toBeTrue();
});
});

describe("getBlockPing", () => {
it("should return state.blockPing", () => {
const blockPing = {
Expand Down Expand Up @@ -471,16 +324,6 @@ describe("Blockchain", () => {
]);
});
});

describe("__registerQueue", () => {
it("should be ok", () => {
blockchain.__registerQueue();

expect(blockchain).toHaveProperty("queue");
expect(blockchain).toHaveProperty("processQueue");
expect(blockchain).toHaveProperty("rebuildQueue");
});
});
});

async function __start(networkStart) {
Expand Down
Expand Up @@ -15,14 +15,6 @@ describe("Blockchain machine > Fork", () => {
});
});

it("should transition to `revertBlocks` on `REBUILD`", () => {
expect(blockchainMachine).toTransition({
from: "fork.analysing",
on: "REBUILD",
to: "fork.revertBlocks",
});
});

it("should transition to `exit` on `NOFORK`", () => {
expect(blockchainMachine).toTransition({
from: "fork.analysing",
Expand Down