Skip to content

Commit

Permalink
fix(core-database): revertBlock (#3948)
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastijankuzner authored Aug 13, 2020
1 parent f21af37 commit 3565ef5
Show file tree
Hide file tree
Showing 8 changed files with 38 additions and 14 deletions.
7 changes: 4 additions & 3 deletions __tests__/unit/core-blockchain/blockchain.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ describe("Blockchain", () => {
logService.debug = jest.fn();

stateStore.started = false;
stateStore.getMaxLastBlocks = jest.fn().mockReturnValue(200);
stateStore.clearWakeUpTimeout = jest.fn();
stateStore.wakeUpTimeout = undefined;
stateStore.lastDownloadedBlock = undefined;
Expand Down Expand Up @@ -379,7 +380,7 @@ describe("Blockchain", () => {
const spyDispatch = jest.spyOn(blockchain, "dispatch");
stateStore.started = true;
stateStore.getLastBlock = jest.fn().mockReturnValue({ data: blockData });

jest.spyOn(Crypto.Slots, "getSlotNumber").mockReturnValueOnce(1).mockReturnValueOnce(2);
jest.spyOn(Crypto.Slots, "getTimeInMsUntilNextSlot").mockReturnValueOnce(5000);

Expand Down Expand Up @@ -500,15 +501,15 @@ describe("Blockchain", () => {
expect(spyQueuePush).toHaveBeenCalledWith({ blocks: [blockData] });
});

it("should push a chunk to the queue when currentBlocksChunk.length > 100", async () => {
it("should push a chunk to the queue when currentBlocksChunk.length >= 100", async () => {
const blockchain = sandbox.app.resolve<Blockchain>(Blockchain);
blockchain.initialize({});
stateStore.lastDownloadedBlock = { height: 23111 };

const spyQueuePush = jest.spyOn(blockchain.queue, "push");

const blocksToEnqueue = [];
for (let i = 0; i <= 101; i++) {
for (let i = 0; i < 101; i++) {
// @ts-ignore
blocksToEnqueue.push(blockData);
}
Expand Down
8 changes: 4 additions & 4 deletions __tests__/unit/core-database/database-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -666,12 +666,12 @@ describe("DatabaseService.getBlocks", () => {
const block102 = { height: 102, transactions: [] };

stateStore.getLastBlocksByHeight.mockReturnValueOnce([block101, block102]);
blockRepository.findByHeightRangeWithTransactions.mockResolvedValueOnce([block100, block101, block102]);
blockRepository.findByHeightRangeWithTransactions.mockResolvedValueOnce([block100]);

const result = await databaseService.getBlocks(100, 3);

expect(stateStore.getLastBlocksByHeight).toBeCalledWith(100, 102, undefined);
expect(blockRepository.findByHeightRangeWithTransactions).toBeCalledWith(100, 102);
expect(blockRepository.findByHeightRangeWithTransactions).toBeCalledWith(100, 100);
expect(result).toEqual([block100, block101, block102]);
});

Expand All @@ -683,12 +683,12 @@ describe("DatabaseService.getBlocks", () => {
const block102 = { height: 102 };

stateStore.getLastBlocksByHeight.mockReturnValueOnce([block101, block102]);
blockRepository.findByHeightRange.mockResolvedValueOnce([block100, block101, block102]);
blockRepository.findByHeightRange.mockResolvedValueOnce([block100]);

const result = await databaseService.getBlocks(100, 3, true);

expect(stateStore.getLastBlocksByHeight).toBeCalledWith(100, 102, true);
expect(blockRepository.findByHeightRange).toBeCalledWith(100, 102);
expect(blockRepository.findByHeightRange).toBeCalledWith(100, 100);
expect(result).toEqual([block100, block101, block102]);
});
});
Expand Down
6 changes: 6 additions & 0 deletions __tests__/unit/core-state/stores/state.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ beforeEach(() => {
afterAll(() => jest.clearAllMocks());

describe("State Storage", () => {
describe("getMaxLastBlocks", () => {
it("should return max last blocks limit", () => {
expect(stateStorage.getMaxLastBlocks()).toBe(100);
});
});

describe("getLastHeight", () => {
it("should return the last block height", () => {
stateStorage.setLastBlock(blocks[0]);
Expand Down
3 changes: 2 additions & 1 deletion packages/core-blockchain/src/blockchain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,8 @@ export class Blockchain implements Contracts.Blockchain.Blockchain {
currentTransactionsCount += block.numberOfTransactions;

const nextMilestone = milestoneHeights[0] && milestoneHeights[0] === block.height;
if (currentTransactionsCount >= 150 || currentBlocksChunk.length > 100 || nextMilestone) {

if (currentTransactionsCount >= 150 || currentBlocksChunk.length >= Math.min(this.state.getMaxLastBlocks(), 100) || nextMilestone) {
this.queue.push({ blocks: currentBlocksChunk });
currentBlocksChunk = [];
currentTransactionsCount = 0;
Expand Down
11 changes: 9 additions & 2 deletions packages/core-database/src/database-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,16 +266,23 @@ export class DatabaseService {
public async getBlocks(offset: number, limit: number, headersOnly?: boolean): Promise<Interfaces.IBlockData[]> {
// The functions below return matches in the range [start, end], including both ends.
const start: number = offset;
const end: number = offset + limit - 1;
let end: number = offset + limit - 1;

let blocks: Interfaces.IBlockData[] = this.stateStore.getLastBlocksByHeight(start, end, headersOnly);

if (blocks.length !== limit) {
// ! assumes that earlier blocks may be missing
// ! but querying database is unnecessary when later blocks are missing too (aren't forged yet)
blocks = headersOnly

if (blocks.length) {
end = blocks[0].height - 1;
}

const blocksFromDB = headersOnly
? await this.blockRepository.findByHeightRange(start, end)
: await this.blockRepository.findByHeightRangeWithTransactions(start, end);

blocks = [...blocksFromDB, ...blocks];
}

return blocks;
Expand Down
5 changes: 5 additions & 0 deletions packages/core-kernel/src/contracts/state/state-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ export interface StateStore {
*/
clearWakeUpTimeout(): void;

/**
* Get block storage limit.
*/
getMaxLastBlocks(): number;

/**
* Get the last block height.
*/
Expand Down
10 changes: 6 additions & 4 deletions packages/core-state/src/stores/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export class StateStore implements Contracts.State.StateStore {
// can be configured with the option `state.maxLastBlocks`.
private lastBlocks: OrderedMap<number, Interfaces.IBlock> = OrderedMap<number, Interfaces.IBlock>();
// Stores the last n incoming transaction ids. The amount of transaction ids
// can be configred with the option `state.maxLastTransactionIds`.
// can be configured with the option `state.maxLastTransactionIds`.
private cachedTransactionIds: OrderedSet<string> = OrderedSet();

/**
Expand Down Expand Up @@ -63,6 +63,10 @@ export class StateStore implements Contracts.State.StateStore {
}
}

public getMaxLastBlocks(): number {
return this.configuration.getRequired<number>("storage.maxLastBlocks");
}

/**
* Get the last block height.
*/
Expand Down Expand Up @@ -119,9 +123,7 @@ export class StateStore implements Contracts.State.StateStore {
}

// Delete oldest block if size exceeds the maximum
const maxLastBlocks = this.configuration.getRequired<number>("storage.maxLastBlocks");

if (this.lastBlocks.size > maxLastBlocks) {
if (this.lastBlocks.size > this.getMaxLastBlocks()) {
this.lastBlocks = this.lastBlocks.delete(this.lastBlocks.first<Interfaces.IBlock>().data.height);
}

Expand Down
2 changes: 2 additions & 0 deletions packages/core-transactions/src/handlers/two/ipfs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ export class IpfsTransactionHandler extends TransactionHandler {
sender.forgetAttribute("ipfs");
}

this.walletRepository.getIndex(Contracts.State.WalletIndexes.Ipfs).forget(transaction.data.asset.ipfs);

this.walletRepository.index(sender);
}

Expand Down

0 comments on commit 3565ef5

Please sign in to comment.