Skip to content

Commit

Permalink
fix(core-blockchain): block download (#4057)
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastijankuzner authored Sep 29, 2020
1 parent 448b941 commit da2e563
Show file tree
Hide file tree
Showing 13 changed files with 56 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ describe("BlockProcessor", () => {

const walletRepository = {
findByPublicKey: jest.fn(),
getNonce: jest.fn(),
};
const transactionHandlerRegistry = {
getActivatedHandlerForData: jest.fn(),
Expand Down Expand Up @@ -204,7 +205,7 @@ describe("BlockProcessor", () => {
],
};

databaseInteractions.walletRepository.getNonce = jest.fn().mockReturnValueOnce(Utils.BigNumber.ONE);
walletRepository.getNonce = jest.fn().mockReturnValueOnce(Utils.BigNumber.ONE);

const blockProcessor = sandbox.app.resolve<BlockProcessor>(BlockProcessor);

Expand All @@ -227,7 +228,7 @@ describe("BlockProcessor", () => {
],
};

databaseInteractions.walletRepository.getNonce = jest.fn().mockReturnValueOnce(Utils.BigNumber.ONE);
walletRepository.getNonce = jest.fn().mockReturnValueOnce(Utils.BigNumber.ONE);
databaseInteractions.getActiveDelegates = jest.fn().mockReturnValueOnce([]);
blockchain.getLastBlock = jest.fn().mockReturnValueOnce(baseBlock);
const generatorWallet = {
Expand Down Expand Up @@ -361,7 +362,7 @@ describe("BlockProcessor", () => {
databaseInteractions.getActiveDelegates = jest.fn().mockReturnValueOnce([]);
blockchain.getLastBlock = jest.fn().mockReturnValueOnce(baseBlock);
transactionRepository.getForgedTransactionsIds = jest.fn().mockReturnValueOnce([transactionData.id]);
databaseInteractions.walletRepository.getNonce = jest.fn().mockReturnValueOnce(Utils.BigNumber.ONE);
walletRepository.getNonce = jest.fn().mockReturnValueOnce(Utils.BigNumber.ONE);
const generatorWallet = {
getAttribute: jest.fn().mockReturnValue("generatorusername"),
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Container } from "@arkecosystem/core-kernel";
import { Interfaces } from "@arkecosystem/crypto";

import { BlockProcessorResult } from "../../../../../packages/core-blockchain/src/processor";
import { AcceptBlockHandler } from "../../../../../packages/core-blockchain/src/processor/handlers/accept-block-handler";
import { BlockProcessorResult } from "@packages/core-blockchain/src/processor";
import { AcceptBlockHandler } from "@packages/core-blockchain/src/processor/handlers/accept-block-handler";

describe("AcceptBlockHandler", () => {
const container = new Container.Container();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Container } from "@arkecosystem/core-kernel";
import { AlreadyForgedHandler } from "../../../../../packages/core-blockchain/src/processor/handlers/already-forged-handler";
import { BlockProcessorResult } from "../../../../../packages/core-blockchain/src/processor";
import { AlreadyForgedHandler } from "@packages/core-blockchain/src/processor/handlers/already-forged-handler";
import { BlockProcessorResult } from "@packages/core-blockchain/src/processor";
import { Interfaces } from "@arkecosystem/crypto";

describe("AlreadyForgedHandler", () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Container } from "@arkecosystem/core-kernel";
import { ExceptionHandler } from "../../../../../packages/core-blockchain/src/processor/handlers/exception-handler";
import { AcceptBlockHandler } from "../../../../../packages/core-blockchain/src/processor/handlers/accept-block-handler";
import { BlockProcessorResult } from "../../../../../packages/core-blockchain/src/processor";
import { ExceptionHandler } from "@packages/core-blockchain/src/processor/handlers/exception-handler";
import { AcceptBlockHandler } from "@packages/core-blockchain/src/processor/handlers/accept-block-handler";
import { BlockProcessorResult } from "@packages/core-blockchain/src/processor";
import { Interfaces } from "@arkecosystem/crypto";

describe("ExceptionHandler", () => {
Expand All @@ -10,7 +10,6 @@ describe("ExceptionHandler", () => {
const logger = { warning: jest.fn(), debug: jest.fn(), info: jest.fn() };
const blockchain = { resetLastDownloadedBlock: jest.fn() };
const database = { getBlock: jest.fn() };

const application = { resolve: jest.fn() };

beforeAll(() => {
Expand All @@ -28,7 +27,7 @@ describe("ExceptionHandler", () => {
describe("execute", () => {
const block = { data: { id: "123", height: 4445 } };

it("should return Rejected and resetLastDownloadedBlock when block already forged", async () => {
it("should return Rejected and resetLastDownloadedBlock if block is already forged", async () => {
const exceptionHandler = container.resolve<ExceptionHandler>(ExceptionHandler);

database.getBlock = jest.fn().mockResolvedValueOnce(block);
Expand All @@ -39,7 +38,7 @@ describe("ExceptionHandler", () => {
expect(blockchain.resetLastDownloadedBlock).toBeCalledTimes(1);
});

it("should call AcceptHandler when block not already forged", async () => {
it("should call AcceptHandler if block is not forged yet", async () => {
const exceptionHandler = container.resolve<ExceptionHandler>(ExceptionHandler);

const mockAcceptHandler = {
Expand Down
22 changes: 21 additions & 1 deletion packages/core-blockchain/src/blockchain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ export class Blockchain implements Contracts.Blockchain.Blockchain {

if (lastProcessResult === BlockProcessorResult.Accepted) {
acceptedBlocks.push(blockInstance);
this.stateStore.lastDownloadedBlock = blockInstance.data;
this.stateStore.setLastBlock(blockInstance);
} else {
if (lastProcessResult === BlockProcessorResult.Rollback) {
forkBlock = blockInstance;
Expand Down Expand Up @@ -475,6 +475,26 @@ export class Blockchain implements Contracts.Blockchain.Blockchain {
}
} else if (forkBlock) {
this.forkBlock(forkBlock);
} else if (lastProcessedBlock) {
// Not all blocks are accepted. Clear queue and start again

this.logger.warning(`Could not process block at height ${lastProcessedBlock.data.height}.`);

if (this.stateStore.getLastBlock().data.height === lastProcessedBlock.data.height) {
await this.databaseInteraction.revertBlock(lastProcessedBlock);

const lastBlock: Interfaces.IBlock = await this.database.getLastBlock();
const lastHeight: number = lastBlock.data.height;
const deleteRoundsAfter: number = Utils.roundCalculator.calculateRound(lastHeight).round;

this.stateStore.setLastBlock(lastBlock);

await this.database.deleteRound(deleteRoundsAfter + 1);
await this.databaseInteraction.loadBlocksFromCurrentRound();
}

this.clearQueue();
this.resetLastDownloadedBlock();
}

return acceptedBlocks;
Expand Down
8 changes: 5 additions & 3 deletions packages/core-blockchain/src/processor/block-processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ export class BlockProcessor {
@Container.inject(Container.Identifiers.DatabaseTransactionRepository)
private readonly transactionRepository!: Repositories.TransactionRepository;

@Container.inject(Container.Identifiers.WalletRepository)
@Container.tagged("state", "blockchain")
private readonly walletRepository!: Contracts.State.WalletRepository;

public async process(block: Interfaces.IBlock): Promise<BlockProcessorResult> {
if (Utils.isException({ ...block.data, transactions: block.transactions.map((tx) => tx.data) })) {
return this.app.resolve<ExceptionHandler>(ExceptionHandler).execute(block);
Expand Down Expand Up @@ -167,9 +171,7 @@ export class BlockProcessor {
const sender: string = data.senderPublicKey;

if (nonceBySender[sender] === undefined) {
nonceBySender[sender] = this.app
.get<any>(Container.Identifiers.DatabaseInteraction)
.walletRepository.getNonce(sender);
nonceBySender[sender] = this.walletRepository.getNonce(sender);
}

AppUtils.assert.defined<string>(data.nonce);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { Interfaces } from "@arkecosystem/crypto";
import { BlockProcessorResult } from "../block-processor";
import { BlockHandler } from "../contracts";

// todo: remove the abstract and instead require a contract to be implemented
@Container.injectable()
export class AcceptBlockHandler implements BlockHandler {
@Container.inject(Container.Identifiers.Application)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { BlockProcessorResult } from "../block-processor";
import { BlockHandler } from "../contracts";
import { AcceptBlockHandler } from "./accept-block-handler";

// todo: remove the abstract and instead require a contract to be implemented
@Container.injectable()
export class ExceptionHandler implements BlockHandler {
@Container.inject(Container.Identifiers.Application)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { Interfaces } from "@arkecosystem/crypto";
import { BlockProcessorResult } from "../block-processor";
import { BlockHandler } from "../contracts";

// todo: remove the abstract and instead require a contract to be implemented
@Container.injectable()
export class InvalidGeneratorHandler implements BlockHandler {
@Container.inject(Container.Identifiers.Application)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ class BlockNotReadyCounter {
}
}

// todo: remove the abstract and instead require a contract to be implemented
@Container.injectable()
export class UnchainedHandler implements BlockHandler {
public static notReadyCounter = new BlockNotReadyCounter();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { Interfaces } from "@arkecosystem/crypto";
import { BlockProcessorResult } from "../block-processor";
import { BlockHandler } from "../contracts";

// todo: remove the abstract and instead require a contract to be implemented
@Container.injectable()
export class VerificationFailedHandler implements BlockHandler {
@Container.inject(Container.Identifiers.Application)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export class DownloadBlocks implements Action {

try {
this.blockchain.enqueueBlocks(blocks);
this.stateStore.lastDownloadedBlock = blocks[blocks.length - 1];
this.blockchain.dispatch("DOWNLOADED");
} catch (error) {
this.logger.warning(`Failed to enqueue downloaded block.`);
Expand Down
18 changes: 16 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11236,7 +11236,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=

minimatch@^3.0.2, minimatch@^3.0.4:
minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
Expand Down Expand Up @@ -13032,7 +13032,7 @@ process-nextick-args@~2.0.0:
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==

progress@^2.0.3:
progress@^2.0.0, progress@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
Expand Down Expand Up @@ -13465,6 +13465,13 @@ readdirp@^3.4.0:
dependencies:
picomatch "^2.2.1"

rechoir@^0.6.2:
version "0.6.2"
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=
dependencies:
resolve "^1.1.6"

redent@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
Expand Down Expand Up @@ -14767,6 +14774,13 @@ supports-color@^5.0.0, supports-color@^5.3.0, supports-color@^5.5.0:
dependencies:
has-flag "^3.0.0"

supports-color@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3"
integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==
dependencies:
has-flag "^3.0.0"

supports-color@^7.0.0, supports-color@^7.1.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1"
Expand Down

0 comments on commit da2e563

Please sign in to comment.