From 177e7bb602f4dc4a769c73925c9ed3db3ad8b067 Mon Sep 17 00:00:00 2001 From: Dmitry Tyshchenko Date: Tue, 25 Feb 2020 02:38:33 +0200 Subject: [PATCH 1/2] Collator test --- .../core-transaction-pool/collator.test.ts | 83 +++++++++++++++++++ .../core-transaction-pool/src/collator.ts | 19 +++-- 2 files changed, 93 insertions(+), 9 deletions(-) create mode 100644 __tests__/unit/core-transaction-pool/collator.test.ts diff --git a/__tests__/unit/core-transaction-pool/collator.test.ts b/__tests__/unit/core-transaction-pool/collator.test.ts new file mode 100644 index 0000000000..9e4dbf5d44 --- /dev/null +++ b/__tests__/unit/core-transaction-pool/collator.test.ts @@ -0,0 +1,83 @@ +import { Container } from "@arkecosystem/core-kernel"; +import { Managers } from "@arkecosystem/crypto"; + +import { Collator } from "../../../packages/core-transaction-pool/src/collator"; + +jest.mock("@arkecosystem/crypto"); + +describe("Collator", () => { + const container = new Container.Container(); + + describe("getBlockCandidateTransactions", () => { + const validator = { validate: jest.fn() }; + const configuration = { get: jest.fn() }; + const createTransactionValidator = jest.fn(() => validator); + const blockchain = { getLastBlock: jest.fn() }; + const pool = { cleanUp: jest.fn(), removeTransaction: jest.fn() }; + const poolQuery = { getAllFromHighestPriority: jest.fn() }; + const logger = { error: jest.fn() }; + + beforeAll(() => { + container.unbindAll(); + container.bind(Container.Identifiers.PluginConfiguration).toConstantValue(configuration); + container + .bind(Container.Identifiers.TransactionValidatorFactory) + .toConstantValue(createTransactionValidator); + container.bind(Container.Identifiers.BlockchainService).toConstantValue(blockchain); + container.bind(Container.Identifiers.TransactionPoolService).toConstantValue(pool); + container.bind(Container.Identifiers.TransactionPoolQuery).toConstantValue(poolQuery); + container.bind(Container.Identifiers.LogService).toConstantValue(logger); + }); + + beforeEach(() => { + validator.validate.mockClear(); + configuration.get.mockClear(); + createTransactionValidator.mockClear(); + blockchain.getLastBlock.mockClear(); + pool.cleanUp.mockClear(); + poolQuery.getAllFromHighestPriority.mockClear(); + logger.error.mockClear(); + }); + + it("should respect milestone transaction count limit", async () => { + const poolTransactions = new Array(10).fill({ data: "12345678" }); + const milestone = { block: { maxTransactions: 5 } }; + const lastBlock = { data: { height: 10 } }; + + (Managers.configManager.getMilestone as jest.Mock).mockReturnValueOnce(milestone); + blockchain.getLastBlock.mockReturnValueOnce(lastBlock); + poolQuery.getAllFromHighestPriority.mockReturnValueOnce(poolTransactions); + + const collator = container.resolve(Collator); + const candidateTransaction = await collator.getBlockCandidateTransactions(); + + expect(candidateTransaction.length).toBe(5); + expect(configuration.get).toBeCalled(); + expect(Managers.configManager.getMilestone).toBeCalled(); + expect(createTransactionValidator).toBeCalled(); + expect(pool.cleanUp).toBeCalled(); + expect(validator.validate).toBeCalledTimes(5); + }); + + it("should respect maxTransactionBytes configuration limit", async () => { + const poolTransactions = new Array(10).fill({ data: "12345678" }); + const milestone = { block: { maxTransactions: 100 } }; + const lastBlock = { data: { height: 10 } }; + + (Managers.configManager.getMilestone as jest.Mock).mockReturnValueOnce(milestone); + configuration.get.mockReturnValueOnce(25); + blockchain.getLastBlock.mockReturnValueOnce(lastBlock); + poolQuery.getAllFromHighestPriority.mockReturnValueOnce(poolTransactions); + + const collator = container.resolve(Collator); + const candidateTransaction = await collator.getBlockCandidateTransactions(); + + expect(candidateTransaction.length).toBe(2); + expect(configuration.get).toBeCalled(); + expect(Managers.configManager.getMilestone).toBeCalled(); + expect(createTransactionValidator).toBeCalled(); + expect(pool.cleanUp).toBeCalled(); + expect(validator.validate).toBeCalledTimes(2); + }); + }); +}); diff --git a/packages/core-transaction-pool/src/collator.ts b/packages/core-transaction-pool/src/collator.ts index a1d51c5f32..2d27a90598 100644 --- a/packages/core-transaction-pool/src/collator.ts +++ b/packages/core-transaction-pool/src/collator.ts @@ -26,26 +26,27 @@ export class Collator implements Contracts.TransactionPool.Collator { private readonly logger!: Contracts.Kernel.Logger; public async getBlockCandidateTransactions(): Promise { - let bytesLeft = this.configuration.get("maxTransactionBytes") ?? null; + let bytesLeft: number | undefined = this.configuration.get("maxTransactionBytes"); - const height = this.blockchain.getLastBlock().data.height; + const height: number = this.blockchain.getLastBlock().data.height; const milestone = Managers.configManager.getMilestone(height); const transactions: Interfaces.ITransaction[] = []; - const validator = this.createTransactionValidator(); + const validator: Contracts.State.TransactionValidator = this.createTransactionValidator(); for (const transaction of this.memory.allSortedByFee().slice()) { if (transactions.length === milestone.block.maxTransactions) { break; } + if (bytesLeft !== undefined) { + bytesLeft -= JSON.stringify(transaction.data).length; + if (bytesLeft < 0) { + break; + } + } + try { await validator.validate(transaction); - if (bytesLeft !== null) { - bytesLeft -= JSON.stringify(transaction.data).length; - if (bytesLeft < 0) { - break; - } - } transactions.push(transaction); } catch (error) { this.pool.removeTransactionById(transaction.id!); From 95a546a5718fbeb8e212fcf9e77ca9d5afd653bd Mon Sep 17 00:00:00 2001 From: Dmitry Tyshchenko Date: Tue, 25 Feb 2020 03:43:52 +0200 Subject: [PATCH 2/2] Port collator test to 3.0 --- .../unit/core-transaction-pool/collator.test.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/__tests__/unit/core-transaction-pool/collator.test.ts b/__tests__/unit/core-transaction-pool/collator.test.ts index 9e4dbf5d44..f32ca03c49 100644 --- a/__tests__/unit/core-transaction-pool/collator.test.ts +++ b/__tests__/unit/core-transaction-pool/collator.test.ts @@ -13,8 +13,8 @@ describe("Collator", () => { const configuration = { get: jest.fn() }; const createTransactionValidator = jest.fn(() => validator); const blockchain = { getLastBlock: jest.fn() }; - const pool = { cleanUp: jest.fn(), removeTransaction: jest.fn() }; - const poolQuery = { getAllFromHighestPriority: jest.fn() }; + const pool = { removeTransactionById: jest.fn() }; + const memory = { allSortedByFee: jest.fn() }; const logger = { error: jest.fn() }; beforeAll(() => { @@ -25,7 +25,7 @@ describe("Collator", () => { .toConstantValue(createTransactionValidator); container.bind(Container.Identifiers.BlockchainService).toConstantValue(blockchain); container.bind(Container.Identifiers.TransactionPoolService).toConstantValue(pool); - container.bind(Container.Identifiers.TransactionPoolQuery).toConstantValue(poolQuery); + container.bind(Container.Identifiers.TransactionPoolMemory).toConstantValue(memory); container.bind(Container.Identifiers.LogService).toConstantValue(logger); }); @@ -34,8 +34,7 @@ describe("Collator", () => { configuration.get.mockClear(); createTransactionValidator.mockClear(); blockchain.getLastBlock.mockClear(); - pool.cleanUp.mockClear(); - poolQuery.getAllFromHighestPriority.mockClear(); + memory.allSortedByFee.mockClear(); logger.error.mockClear(); }); @@ -46,7 +45,7 @@ describe("Collator", () => { (Managers.configManager.getMilestone as jest.Mock).mockReturnValueOnce(milestone); blockchain.getLastBlock.mockReturnValueOnce(lastBlock); - poolQuery.getAllFromHighestPriority.mockReturnValueOnce(poolTransactions); + memory.allSortedByFee.mockReturnValueOnce(poolTransactions); const collator = container.resolve(Collator); const candidateTransaction = await collator.getBlockCandidateTransactions(); @@ -55,7 +54,6 @@ describe("Collator", () => { expect(configuration.get).toBeCalled(); expect(Managers.configManager.getMilestone).toBeCalled(); expect(createTransactionValidator).toBeCalled(); - expect(pool.cleanUp).toBeCalled(); expect(validator.validate).toBeCalledTimes(5); }); @@ -67,7 +65,7 @@ describe("Collator", () => { (Managers.configManager.getMilestone as jest.Mock).mockReturnValueOnce(milestone); configuration.get.mockReturnValueOnce(25); blockchain.getLastBlock.mockReturnValueOnce(lastBlock); - poolQuery.getAllFromHighestPriority.mockReturnValueOnce(poolTransactions); + memory.allSortedByFee.mockReturnValueOnce(poolTransactions); const collator = container.resolve(Collator); const candidateTransaction = await collator.getBlockCandidateTransactions(); @@ -76,7 +74,6 @@ describe("Collator", () => { expect(configuration.get).toBeCalled(); expect(Managers.configManager.getMilestone).toBeCalled(); expect(createTransactionValidator).toBeCalled(); - expect(pool.cleanUp).toBeCalled(); expect(validator.validate).toBeCalledTimes(2); }); });