Skip to content
This repository has been archived by the owner on Jun 11, 2024. It is now read-only.

Improve handling of deleted blocks #1896

Merged
merged 27 commits into from
Nov 10, 2023
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
1089ea3
Improve fork detection and block deletion
priojeetpriyom Oct 24, 2023
a96cc0c
Merge branch 'release/0.7.0' into 1191-improve-handling-of-deleted-bl…
priojeetpriyom Oct 24, 2023
bf2334a
:art: Format
priojeetpriyom Oct 24, 2023
d83e1a6
Optimize code
priojeetpriyom Oct 24, 2023
fe64e5c
:art: Refactor
priojeetpriyom Oct 24, 2023
d2f3b58
Improve retry logic and logging
priojeetpriyom Oct 24, 2023
41eced2
Merge branch 'release/0.7.0' into 1191-improve-handling-of-deleted-bl…
priojeetpriyom Oct 26, 2023
b72a5f1
Merge branch 'release/0.7.0' into 1191-improve-handling-of-deleted-bl…
priojeetpriyom Oct 27, 2023
7a3671e
Merge branch 'release/0.7.0' into 1191-improve-handling-of-deleted-bl…
priojeetpriyom Oct 30, 2023
44b0267
Fix blocks api return null total instead of 0
priojeetpriyom Oct 31, 2023
6224aa0
Merge branch 'release/0.7.0' into 1191-improve-handling-of-deleted-bl…
priojeetpriyom Oct 31, 2023
19a521d
Update regex check for name
priojeetpriyom Oct 31, 2023
3dc7388
Update regex for names
priojeetpriyom Oct 31, 2023
edddaef
Apply suggestions and fix bug
priojeetpriyom Nov 8, 2023
182de2c
Merge branch 'release/0.7.0' into 1191-improve-handling-of-deleted-bl…
priojeetpriyom Nov 8, 2023
1dba63d
:art: Format
priojeetpriyom Nov 8, 2023
fad332a
:hammer: Refactor code
sameersubudhi Nov 9, 2023
1736d0f
Fix delete indexed block job bugs
priojeetpriyom Nov 9, 2023
e1d53e9
:art: Lint
priojeetpriyom Nov 9, 2023
ee1d26a
Update block deletion logic
priojeetpriyom Nov 9, 2023
9c2bac6
:art: Format
priojeetpriyom Nov 9, 2023
c2d0fdf
:bug: Fix bugs and code refactor
sameersubudhi Nov 9, 2023
004b8c6
:bug: Fix apiClient alive check
sameersubudhi Nov 10, 2023
b7f7fc7
Merge branch 'release/0.7.0' into 1191-improve-handling-of-deleted-bl…
sameersubudhi Nov 10, 2023
cd63adc
Apply suggestions from code review
sameersubudhi Nov 10, 2023
19b8749
Add unit tests
nagdahimanshu Nov 10, 2023
ff7f435
:hammer: Update dependencies
sameersubudhi Nov 10, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions docs/api/version3.md
Original file line number Diff line number Diff line change
Expand Up @@ -899,7 +899,7 @@ Retrieves user-specific details from the Auth module.
| --------- | ---- | ---------- | ------- | ------- |
| address | String | `/^lsk[a-hjkm-z2-9]{38}$/` | *(empty)* | Required. |
<!-- | publicKey | String | `/^\b(?:[A-Fa-f0-9]){64}\b$/` | *(empty)* | | -->
<!-- | name | String | `/^[\w!@$&.]{3,20}$/` | *(empty)* | | -->
<!-- | name | String | `/^[a-z0-9!@$&_.]{1,20}$/` | *(empty)* | | -->

#### Response example

Expand Down Expand Up @@ -957,7 +957,7 @@ Retrieves user-specific details from the Validator module.
| --------- | ---- | ---------- | ------- | ------- |
| address | String | `/^lsk[a-hjkm-z2-9]{38}$/` | *(empty)* | Required. |
<!-- | publicKey | String | `/^\b(?:[A-Fa-f0-9]){64}\b$/` | *(empty)* | | -->
<!-- | name | String | `/^[\w!@$&.]{3,20}$/` | *(empty)* | | -->
<!-- | name | String | `/^[a-z0-9!@$&_.]{1,20}$/` | *(empty)* | | -->

#### Response example

Expand Down Expand Up @@ -1056,7 +1056,7 @@ Validates if an entry exists in the Token sub-store for the specified address.
| tokenID | String | `/^\b[a-fA-F0-9]{16}\b$/` | *(empty)* | Required. |
| address | String | `/^lsk[a-hjkm-z2-9]{38}$/` | *(empty)* | One of address, publicKey or name required. |
| publicKey | String | `/^\b(?:[A-Fa-f0-9]){64}\b$/` | *(empty)* | |
| name | String | `/^[\w!@$&.]{3,20}$/` | *(empty)* | |
| name | String | `/^[a-z0-9!@$&_.]{1,20}$/` | *(empty)* | |

#### Response example

Expand Down Expand Up @@ -1104,14 +1104,14 @@ Retrieves the balances from the Token sub-store for the specified address.
| limit | Number | `[1,100]` | 10 | |
| offset | Number | `[0,Inf)` | 0 | |
<!-- | publicKey | String | `/^\b(?:[A-Fa-f0-9]){64}\b$/` | *(empty)* | | -->
<!-- | name | String | `/^[\w!@$&.]{3,20}$/` | *(empty)* | | -->
<!-- | name | String | `/^[a-z0-9!@$&_.]{1,20}$/` | *(empty)* | | -->

#### Response example

200 OK

```jsonc
{
{
"data": {
"tokenID": "0000000000000000",
"availableBalance": "1000000000",
Expand Down Expand Up @@ -1445,7 +1445,7 @@ _Supports pagination._
| --------- | ---- | ---------- | ------- | ------- |
| address | String | `/^lsk[a-hjkm-z2-9]{38}$/` | *(empty)* | One of address, publicKey or name required. |
| publicKey | String | `/^\b(?:[A-Fa-f0-9]){64}\b$/` | *(empty)* | |
| name | String | `/^[\w!@$&.]{3,20}$/` | *(empty)* | |
| name | String | `/^[a-z0-9!@$&_.]{1,20}$/` | *(empty)* | |
| limit | Number | `[1,100]` | 10 | |
| offset | Number | `[0,Inf)` | 0 | |

Expand Down Expand Up @@ -1500,7 +1500,7 @@ _Supports pagination._
| --------- | ---- | ---------- | ------- | ------- |
| address | String | `/^lsk[a-hjkm-z2-9]{38}$/` | *(empty)* | One of address, publicKey or name required. |
| publicKey | String | `/^\b(?:[A-Fa-f0-9]){64}\b$/` | *(empty)* | |
| name | String | `/^[\w!@$&.]{3,20}$/` | *(empty)* | |
| name | String | `/^[a-z0-9!@$&_.]{1,20}$/` | *(empty)* | |
| limit | Number | `[1,100]` | 10 | |
| offset | Number | `[0,Inf)` | 0 | |

Expand Down Expand Up @@ -1619,7 +1619,7 @@ _Supports pagination._
| --------- | ---- | ---------- | ------- | ------- |
| address | String | `/^lsk[a-hjkm-z2-9]{38}$/` | *(empty)* | One of address, publicKey or name required. |
| publicKey | String | `/^\b(?:[A-Fa-f0-9]){64}\b$/` | *(empty)* | |
| name | String | `/^[\w!@$&.]{3,20}$/` | *(empty)* | |
| name | String | `/^[a-z0-9!@$&_.]{1,20}$/` | *(empty)* | |
| search | String | `/^[\w!@$&.]{1,64}$/` | *(empty)* | Case-insensitive search by name, address or publicKey. Supports both partial and full text search. |
| limit | Number | `[1,100]` | 10 | |
| offset | Number | `[0,Inf)` | 0 | |
Expand Down Expand Up @@ -1681,7 +1681,7 @@ Retrieves the list of stakes sent by the specified user by their address, public
| --------- | ---- | ---------- | ------- | ------- |
| address | String | `/^lsk[a-hjkm-z2-9]{38}$/` | *(empty)* | One of address, publicKey or name required. |
| publicKey | String | `/^\b(?:[A-Fa-f0-9]){64}\b$/` | *(empty)* | |
| name | String | `/^[\w!@$&.]{3,20}$/` | *(empty)* | |
| name | String | `/^[a-z0-9!@$&_.]{1,20}$/` | *(empty)* | |
| search | String | `/^[\w!@$&.]{1,64}$/` | *(empty)* | Case-insensitive search by name, address or publicKey. Supports both partial and full text search. |

#### Response example
Expand Down Expand Up @@ -1741,7 +1741,7 @@ _Supports pagination._
| --------- | ---- | ---------- | ------- | ------- |
| address | String | `/^lsk[a-hjkm-z2-9]{38}$/` | *(empty)* | One of address, publicKey or name required. |
| publicKey | String | `/^\b(?:[A-Fa-f0-9]){64}\b$/` | *(empty)* | |
| name | String | `/^[\w!@$&.]{3,20}$/` | *(empty)* | |
| name | String | `/^[a-z0-9!@$&_.]{1,20}$/` | *(empty)* | |
| isLocked | Boolean | `[true, false]` | *(empty)* | |
| limit | Number | `[1,100]` | 10 | |
| offset | Number | `[0,Inf)` | 0 | |
Expand Down Expand Up @@ -1809,7 +1809,7 @@ _Supports pagination._
| --------- | ---- | ---------- | ------- | ------- |
| address | String | `/^lsk[a-hjkm-z2-9]{38}$/` | *(empty)* | One of address, publicKey or name required. |
| publicKey | String | `/^\b(?:[A-Fa-f0-9]){64}\b$/` | *(empty)* | |
| name | String | `/^[\w!@$&.]{3,20}$/` | *(empty)* | |
| name | String | `/^[a-z0-9!@$&_.]{1,20}$/` | *(empty)* | |
| status | String | `/^\b(?:active\|standby\|banned\|punished\|ineligible\|,){0,9}\b$/` | *(empty)* | Can be expressed as a CSV. |
| search | String | `/^[\w!@$&.]{1,64}$/` | *(empty)* | Case-insensitive search by name, address or publicKey. Supports both partial and full text search. |
| limit | Number | `[1,100]` | 10 | |
Expand Down Expand Up @@ -5639,7 +5639,7 @@ _Supports pagination._
| Parameter | Type | Validation | Default | Comment |
| --------- | ---- | ---------- | ------- | ------- |
| chainID | String | `/^\b(?:[a-fA-F0-9]{8}\|,)+\b$/` | *(empty)* | Can be expressed as a CSV. |
| chainName | String | `/^[\w!@$&.]{3,20}$/` | *(empty)* | Supports case-insensitive chain name. |
| chainName | String | `/^[a-z0-9!@$&_.]{1,32}$/` | *(empty)* | Supports case-insensitive chain name. |
| status | String | `/^\b(?:registered\|activated\|terminated\|unregistered\|,){1,7}\b$/` | *(empty)* | Can be expressed as a CSV. |
| search | String | `/^[\w!@$&.]{1,20}$/` | *(empty)* | Case-insensitive search by chain name. Supports both partial and full text search. |
| limit | Number | `[1,100]` | 10 | |
Expand Down Expand Up @@ -5910,7 +5910,7 @@ _Supports pagination._

| Parameter | Type | Validation | Default | Comment |
| --------- | ---- | ---------- | ------- | ------- |
| chainName | String | `/^[\w!@$&.]{3,20}$/` | *(empty)* | Supports case-insensitive chain name. |
| chainName | String | `/^[a-z0-9!@$&_.]{1,32}$/` | *(empty)* | Supports case-insensitive chain name. |
| network | String | `/^\b(?:mainnet\|testnet\|betanet\|devnet\|,){0,7}\b$/` | *(empty)* | Can be expressed as a CSV. |
| search | String | `/^[\w!@$&.]{1,20}$/` | *(empty)* | Case-insensitive search by chain name. Supports both partial and full text search. |
| limit | Number | `[1,100]` | 10 | |
Expand Down Expand Up @@ -5967,8 +5967,8 @@ _Supports pagination._

| Parameter | Type | Validation | Default | Comment |
| --------- | ---- | ---------- | ------- | ------- |
| chainName | String | `/^[\w!@$&.]{3,20}$/` | *(empty)* | Supports case-insensitive chain name. |
| displayName | String | `/^[\w!@$&.]{3,20}$/` | *(empty)* | Supports case-insensitive display name. |
| chainName | String | `/^[a-z0-9!@$&_.]{1,32}$/` | *(empty)* | Supports case-insensitive chain name. |
| displayName | String | `/^[a-z0-9!@$&_.]{1,20}$/` | *(empty)* | Supports case-insensitive display name. |
| chainID | String | `/^\b(?:[a-fA-F0-9]{8}\|,)+\b$/` | *(empty)* | Can be expressed as a CSV. |
| isDefault | Boolean | `[true, false]` | *(empty)* | |
| network | String | `/^\b(?:mainnet\|testnet\|betanet\|devnet\|,){0,7}\b$/` | *(empty)* | Can be expressed as a CSV. |
Expand Down Expand Up @@ -6060,7 +6060,7 @@ _Supports pagination._

| Parameter | Type | Validation | Default | Comment |
| --------- | ---- | ---------- | ------- | ------- |
| chainName | String | `/^[\w!@$&.]{3,20}$/` | *(empty)* | Supports case-insensitive chain name. |
| chainName | String | `/^[a-z0-9!@$&_.]{1,32}$/` | *(empty)* | Supports case-insensitive chain name. |
| chainID | String | `/^\b[a-fA-F0-9]{8}\b$/` | *(empty)* | |
| tokenName | String | `/^[\w!@$&.,]{3,}$/` | *(empty)* | Supports case-insensitive token name. |
| tokenID | String | `/^\b([a-fA-F0-9]{16})(,[a-fA-F0-9]{16})*\b$/` | *(empty)* | Can be expressed as a CSV. |
Expand Down
6 changes: 4 additions & 2 deletions services/blockchain-connector/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,10 @@ config.job = {
},
};

// Every n number of blocks, verify if client connection is alive
config.connectionVerifyBlockInterval = process.env.CONN_VERIFY_BLOCK_INTERVAL || 10;
// Every n milliseconds, verify if client connection is alive
config.clientConnVerifyInterval = Number(
process.env.CLIENT_CONNECTION_VERIFY_INTERVAL || 30 * 1000,
); // in millisecs

config.apiClient = {
instantiation: {
Expand Down
16 changes: 7 additions & 9 deletions services/blockchain-connector/shared/sdk/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,13 @@ const getEventsByHeightFormatted = async height => {
};

// To ensure API Client is alive and receiving chain events
getNodeInfo().then(nodeInfo => {
setInterval(() => {
if (eventsCounter === 0) {
Signals.get('resetApiClient').dispatch();
} else if (eventsCounter > 0) {
eventsCounter = 0;
}
}, config.connectionVerifyBlockInterval * nodeInfo.genesis.blockTime * 1000);
});
setInterval(() => {
if (eventsCounter === 0) {
Signals.get('resetApiClient').dispatch();
} else if (eventsCounter > 0) {
eventsCounter = 0;
}
}, config.clientConnVerifyInterval);

module.exports = {
events,
Expand Down
9 changes: 6 additions & 3 deletions services/blockchain-indexer/shared/dataService/blocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const getBlocksTotal = async (params, blocksResponse) => {
let total;

if (params.generatorAddress) {
total = blocksResponse.meta.total || null;
total = 'total' in blocksResponse.meta ? blocksResponse.meta.total : null;
} else if (params.blockID || !Number.isNaN(Number(params.height))) {
total = blocksResponse.data.length;
} else if (
Expand All @@ -79,13 +79,16 @@ const getBlocksTotal = async (params, blocksResponse) => {
return total;
};

const formatBlock = async header => {
const formatBlock = async (header, isDeletedBlock = false) => {
const blocksResponse = {
data: [],
meta: {},
};

const response = await business.formatBlock({ header, assets: [], transactions: [] });
const response = await business.formatBlock(
{ header, assets: [], transactions: [] },
isDeletedBlock,
);
blocksResponse.data.push(response);

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const {

const logger = Logger();

const { getEventsByHeight } = require('./events');
const { getEventsByHeight, getEventsByBlockID } = require('./events');
const { getFinalizedHeight, MODULE, EVENT } = require('../../constants');
const blocksTableSchema = require('../../database/schema/blocks');

Expand All @@ -47,7 +47,7 @@ const latestBlockCache = CacheRedis('latestBlock', config.endpoints.cache);

let latestBlock;

const normalizeBlock = async originalBlock => {
const normalizeBlock = async (originalBlock, isDeletedBlock = false) => {
try {
const blocksTable = await getBlocksTable();

Expand Down Expand Up @@ -90,7 +90,9 @@ const normalizeBlock = async originalBlock => {
};
}

const events = await getEventsByHeight(block.height);
const events = isDeletedBlock
? await getEventsByBlockID(block.id)
: await getEventsByHeight(block.height);
const blockRewardEvent = events.find(
e =>
[MODULE.REWARD, MODULE.DYNAMIC_REWARD].includes(e.module) &&
Expand Down Expand Up @@ -189,7 +191,7 @@ const isQueryFromIndex = params => {
return !isDirectQuery && !isLatestBlockFetch;
};

const formatBlock = async block => normalizeBlock(block);
const formatBlock = async (block, isDeletedBlock = false) => normalizeBlock(block, isDeletedBlock);

const getBlocks = async params => {
const blocksTable = await getBlocksTable();
Expand Down Expand Up @@ -220,8 +222,9 @@ const getBlocks = async params => {

try {
if (params.ids) {
if (Array.isArray(params.ids) && !params.ids.length) return blocks;
blocks.data = await getBlocksByIDs(params.ids);
if (Array.isArray(params.ids) && params.ids.length) {
blocks.data = await getBlocksByIDs(params.ids);
}
} else if (params.id) {
blocks.data.push(await getBlockByID(params.id));
if ('offset' in params && params.limit)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const getTransactionIDsByBlockID = async blockID => {
const transactions = await transactionsTable.find(
{
whereIn: {
property: 'blockId',
property: 'blockID',
values: [blockID],
},
},
Expand Down
Loading
Loading