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

Emit event new block and delete block with accounts - Closes #4825 #4830

Merged
25 changes: 23 additions & 2 deletions elements/lisk-chain/src/chain.ts
Expand Up @@ -100,6 +100,8 @@ interface ChainConstructor {

const DEFAULT_MIN_BLOCK_HEADER_CACHE = 303;
const DEFAULT_MAX_BLOCK_HEADER_CACHE = 505;
const EVENT_NEW_BLOCK = 'NEW_BLOCK';
const EVENT_DELETE_BLOCK = 'DELETE_BLOCK';

// tslint:disable-next-line no-magic-numbers
const TRANSACTION_TYPES_VOTE = [3, 11];
Expand Down Expand Up @@ -198,7 +200,7 @@ const undoConfirmedStep = async (

const debug = Debug('lisk:chain');

export class Chain extends EventEmitter {
export class Chain {
private _lastBlock: BlockInstance;
private readonly blocksVerify: BlocksVerify;
private readonly storage: Storage;
Expand All @@ -217,6 +219,7 @@ export class Chain extends EventEmitter {
readonly activeDelegates: number;
readonly blockSlotWindow: number;
};
private readonly events: EventEmitter;

public readonly blockReward: {
readonly [key: string]: (height: number) => number | bigint;
Expand Down Expand Up @@ -247,7 +250,7 @@ export class Chain extends EventEmitter {
minBlockHeaderCache = DEFAULT_MIN_BLOCK_HEADER_CACHE,
maxBlockHeaderCache = DEFAULT_MAX_BLOCK_HEADER_CACHE,
}: ChainConstructor) {
super();
this.events = new EventEmitter();

this.storage = storage;
this.dataAccess = new DataAccess({
Expand Down Expand Up @@ -481,6 +484,15 @@ export class Chain extends EventEmitter {
}
this.dataAccess.addBlockHeader(blockInstance);
this._lastBlock = blockInstance;

const accounts = stateStore.account
.getUpdated()
.map(anAccount => anAccount.toJSON());

this.events.emit(EVENT_NEW_BLOCK, {
block: this.serialize(blockInstance),
accounts,
});
});
}

Expand Down Expand Up @@ -531,6 +543,15 @@ export class Chain extends EventEmitter {
await stateStore.finalize(tx);
await this.dataAccess.removeBlockHeader(block.id);
this._lastBlock = secondLastBlock;

const accounts = stateStore.account
.getUpdated()
.map(anAccount => anAccount.toJSON());

this.events.emit(EVENT_DELETE_BLOCK, {
block: this.serialize(block),
accounts,
});
});
}

Expand Down
52 changes: 52 additions & 0 deletions elements/lisk-chain/test/unit/chain.spec.ts
Expand Up @@ -21,6 +21,7 @@ import { registeredTransactions } from '../utils/registered_transactions';
import * as randomUtils from '../utils/random';
import { Slots } from '../../src/slots';
import { BlockJSON } from '../../src/types';
import { Account } from '../../src/account';

jest.mock('events');

Expand Down Expand Up @@ -346,6 +347,11 @@ describe('chain', () => {
describe('save', () => {
let stateStoreStub: StateStore;

const fakeAccounts = [
Account.getDefaultAccount('1234L'),
Account.getDefaultAccount('5678L'),
];

beforeEach(async () => {
stubs.tx.batch.mockImplementation((promises: any) =>
Promise.all(promises),
Expand All @@ -355,6 +361,9 @@ describe('chain', () => {
);
stateStoreStub = {
finalize: jest.fn(),
account: {
getUpdated: jest.fn().mockReturnValue(fakeAccounts),
},
} as any;
});

Expand Down Expand Up @@ -471,14 +480,39 @@ describe('chain', () => {
blockCreateError,
);
});

it('should emit block and accounts', async () => {
// Arrange
jest.spyOn((chainInstance as any).events, 'emit');
const block = newBlock();

// Act
await chainInstance.save(block, stateStoreStub);

// Assert
expect((chainInstance as any).events.emit).toHaveBeenCalledWith(
'NEW_BLOCK',
{
accounts: fakeAccounts.map(anAccount => anAccount.toJSON()),
block: chainInstance.serialize(block),
},
);
});
});

describe('remove', () => {
let stateStoreStub: StateStore;
const fakeAccounts = [
Account.getDefaultAccount('1234L'),
Account.getDefaultAccount('5678L'),
];

beforeEach(async () => {
stateStoreStub = {
finalize: jest.fn(),
account: {
getUpdated: jest.fn().mockReturnValue(fakeAccounts),
},
} as any;
stubs.tx.batch.mockImplementation((promises: any) =>
Promise.all(promises),
Expand Down Expand Up @@ -586,6 +620,24 @@ describe('chain', () => {
);
});
});

it('should emit block and accounts', async () => {
// Arrange
jest.spyOn((chainInstance as any).events, 'emit');
const block = newBlock();

// Act
await chainInstance.save(block, stateStoreStub);

// Assert
expect((chainInstance as any).events.emit).toHaveBeenCalledWith(
'NEW_BLOCK',
{
accounts: fakeAccounts.map(anAccount => anAccount.toJSON()),
block: chainInstance.serialize(block),
},
);
});
});

describe('removeBlockFromTempTable()', () => {
Expand Down
2 changes: 0 additions & 2 deletions framework/src/application/node/node.js
Expand Up @@ -573,7 +573,5 @@ module.exports = class Node {

_unsubscribeToEvents() {
this.bft.removeAllListeners(EVENT_BFT_BLOCK_FINALIZED);
this.chain.removeAllListeners(EVENT_UNCONFIRMED_TRANSACTION);
this.chain.removeAllListeners(EVENT_MULTISIGNATURE_SIGNATURE);
}
};