diff --git a/docs/api/version3.md b/docs/api/version3.md index 937b8ecda0..8a6a6abf4f 100644 --- a/docs/api/version3.md +++ b/docs/api/version3.md @@ -337,6 +337,12 @@ _Supports pagination._ "fee": "5166000", "minFee": "165000", "size": 166, + "block": { + "id": "ebb1ba587a1e8385a2aac1317edcb872c05b2b07df6560fabd0f0d23d7d6a0df", + "height": 122721, + "timestamp": 1678989430, + "isFinal": true + }, "sender": { "address": "lskyvvam5rxyvbvofxbdfcupxetzmqxu22phm4yuo", "publicKey": "475697e34ae02b394721020d38677a072dbd5c03d61c1c8fdd6563eb66160fa3", @@ -348,21 +354,18 @@ _Supports pagination._ "recipientAddress": "lskezo8pcrbsoceuuu64rpc8w2qkont2ec3n772yu", "data": "" }, - "block": { - "id": "ebb1ba587a1e8385a2aac1317edcb872c05b2b07df6560fabd0f0d23d7d6a0df", - "height": 122721, - "timestamp": 1678989430, - "isFinal": true - }, + "signatures": [ + "48425002226745847e155cf5480478c2336a43bb178439e9058cc2b50e26335cf7c8360b6c6a49793d7ae8d087bc746cab9618655e6a0adba4694cce2015b50f" + ], + "executionStatus": "successful", + "index": 0, "meta": { "recipient": { "address": "lskezo8pcrbsoceuuu64rpc8w2qkont2ec3n772yu", "publicKey": null, "name": null } - }, - "executionStatus": "successful", - "index": 0 + } }, ], "meta": { diff --git a/framework/src/queue.js b/framework/src/queue.js index 2920511ed4..b8d241f05b 100644 --- a/framework/src/queue.js +++ b/framework/src/queue.js @@ -68,7 +68,7 @@ const queueInstance = ( }); queue.on('failed', (job, err) => { - logger.warn(`${job.name} job failed with error: ${err.message}.`); + logger.warn(`${job.name} job failed with error: ${err.message}`); logger.debug(`${job.name} job failed with error:\n${err.stack}`); }); diff --git a/services/blockchain-app-registry/app.js b/services/blockchain-app-registry/app.js index 972d9b0ba4..3db304a5e8 100644 --- a/services/blockchain-app-registry/app.js +++ b/services/blockchain-app-registry/app.js @@ -47,7 +47,7 @@ app.addEvents(path.join(__dirname, 'events')); // Run the application const reportErrorAndExitProcess = err => { - logger.fatal(`Failed to start service ${packageJson.name} due to: ${err.message}.`); + logger.fatal(`Failed to start service ${packageJson.name} due to: ${err.message}`); logger.fatal(err.stack); process.exit(1); }; diff --git a/services/blockchain-app-registry/jobs/deleteNonMetadata.js b/services/blockchain-app-registry/jobs/deleteNonMetadata.js index bdf60c9644..93de454deb 100644 --- a/services/blockchain-app-registry/jobs/deleteNonMetadata.js +++ b/services/blockchain-app-registry/jobs/deleteNonMetadata.js @@ -66,7 +66,7 @@ module.exports = [ await removeEmptyDirectoriesAndNonMetaFiles(config.dataDir); logger.info('Data directory has been successfully cleaned.'); } catch (err) { - logger.warn(`Cleaning data directory failed due to: ${err.message}.`); + logger.warn(`Cleaning data directory failed due to: ${err.message}`); } }, }, diff --git a/services/blockchain-app-registry/jobs/metadata.js b/services/blockchain-app-registry/jobs/metadata.js index dfc962fb9d..19da8ab6af 100644 --- a/services/blockchain-app-registry/jobs/metadata.js +++ b/services/blockchain-app-registry/jobs/metadata.js @@ -31,7 +31,7 @@ module.exports = [ await syncWithRemoteRepo(); logger.info('Database has been successfully synchronized.'); } catch (err) { - logger.warn(`Refreshing blockchain application metadata failed due to: ${err.message}.`); + logger.warn(`Refreshing blockchain application metadata failed due to: ${err.message}`); } }, }, diff --git a/services/blockchain-connector/app.js b/services/blockchain-connector/app.js index 332201f41d..f1255dc727 100644 --- a/services/blockchain-connector/app.js +++ b/services/blockchain-connector/app.js @@ -65,7 +65,7 @@ nodeStatus.waitForNode().then(async () => { await init(); }) .catch(err => { - logger.fatal(`Failed to start service ${packageJson.name} due to: ${err.message}.`); + logger.fatal(`Failed to start service ${packageJson.name} due to: ${err.message}`); logger.fatal(err.stack); process.exit(1); }); diff --git a/services/blockchain-connector/events/controller/blockchain.js b/services/blockchain-connector/events/controller/blockchain.js index 2c684a8f2a..447f27ff65 100644 --- a/services/blockchain-connector/events/controller/blockchain.js +++ b/services/blockchain-connector/events/controller/blockchain.js @@ -80,7 +80,7 @@ const chainNewBlockController = async cb => { assets = block.assets; } catch (err) { logger.warn( - `Could not fetch block ${blockHeader.id} within chainNewBlockListener due to: ${err.message}.`, + `Could not fetch block ${blockHeader.id} within chainNewBlockListener due to: ${err.message}`, ); logger.debug(err.stack); } diff --git a/services/blockchain-connector/jobs/cacheCleanup.js b/services/blockchain-connector/jobs/cacheCleanup.js index 115694d921..40dfe16507 100644 --- a/services/blockchain-connector/jobs/cacheCleanup.js +++ b/services/blockchain-connector/jobs/cacheCleanup.js @@ -33,7 +33,7 @@ module.exports = [ logger.info('Cache has been successfully cleaned.'); } } catch (err) { - logger.warn(`Cleaning cache failed due to: ${err.message}.`); + logger.warn(`Cleaning cache failed due to: ${err.message}`); } }, }, diff --git a/services/blockchain-connector/shared/sdk/cache.js b/services/blockchain-connector/shared/sdk/cache.js index a9945af79b..121de97e24 100644 --- a/services/blockchain-connector/shared/sdk/cache.js +++ b/services/blockchain-connector/shared/sdk/cache.js @@ -75,7 +75,7 @@ const cacheBlocksFromWaitlist = async () => { await blocksCache.upsert({ id: block.header.id, timestamp: block.header.timestamp, block }); } catch (err) { logger.warn( - `Caching block ${block.header.id} (height: ${block.header.height}) failed. Will re-attempt. Error:\n${err.message}.`, + `Caching block ${block.header.id} (height: ${block.header.height}) failed. Will re-attempt.\nError: ${err.message}`, ); logger.debug(err.stack); blockCacheWaitlist.splice(0, 0, block); diff --git a/services/blockchain-connector/shared/sdk/client.js b/services/blockchain-connector/shared/sdk/client.js index 8e69c8ebe7..2b935747c1 100644 --- a/services/blockchain-connector/shared/sdk/client.js +++ b/services/blockchain-connector/shared/sdk/client.js @@ -89,11 +89,17 @@ const checkIsClientAlive = async () => const instantiateClient = async (isForceReInstantiate = false) => { try { if (!isInstantiating || isForceReInstantiate) { + isInstantiating = true; + if (!(await checkIsClientAlive()) || isForceReInstantiate) { - isInstantiating = true; instantiationBeginTime = Date.now(); - if (clientCache) await clientCache.disconnect(); + if (clientCache) { + clientCache.disconnect().catch(err => { + // Ensure failed disconnection doesn't impact the re-instantiation + logger.warn(`Client disconnection failed due to: ${err.message}`); + }); + } clientCache = config.isUseLiskIPCClient ? await createIPCClient(config.liskAppDataPath) @@ -105,15 +111,15 @@ const instantiateClient = async (isForceReInstantiate = false) => { // Inform listeners about the newly instantiated ApiClient Signals.get('newApiClient').dispatch(); - - isInstantiating = false; } + + isInstantiating = false; return clientCache; } if (Date.now() - instantiationBeginTime > MAX_INSTANTIATION_WAIT_TIME) { // Waited too long, reset the flag to re-attempt client instantiation - logger.warn( + logger.debug( `MAX_INSTANTIATION_WAIT_TIME of ${MAX_INSTANTIATION_WAIT_TIME}ms has expired. Resetting isInstantiating to false.`, ); isInstantiating = false; diff --git a/services/blockchain-connector/shared/sdk/events.js b/services/blockchain-connector/shared/sdk/events.js index e2ceef1069..d010463845 100644 --- a/services/blockchain-connector/shared/sdk/events.js +++ b/services/blockchain-connector/shared/sdk/events.js @@ -43,7 +43,7 @@ const events = [ let eventsCounter; const logError = (method, err) => { - logger.warn(`Invocation for ${method} failed with error: ${err.message}.`); + logger.warn(`Invocation for ${method} failed with error: ${err.message}`); logger.debug(err.stack); }; diff --git a/services/blockchain-connector/shared/sdk/formatter.js b/services/blockchain-connector/shared/sdk/formatter.js index 48eb6801ed..655bd07157 100644 --- a/services/blockchain-connector/shared/sdk/formatter.js +++ b/services/blockchain-connector/shared/sdk/formatter.js @@ -61,10 +61,6 @@ const formatTransaction = (transaction, additionalFee = 0) => { const schemaCompliantTransaction = parseInputBySchema(transaction, txSchema); // Calculate transaction min fee - const transactionParams = codec.decodeJSON( - txParamsSchema, - Buffer.from(transaction.params, 'hex'), - ); const schemaCompliantTransactionParams = codec.decode( txParamsSchema, Buffer.from(transaction.params, 'hex'), @@ -90,7 +86,7 @@ const formatTransaction = (transaction, additionalFee = 0) => { const formattedTransaction = { ...transaction, - params: transactionParams, + params: codec.decodeJSON(txParamsSchema, Buffer.from(transaction.params, 'hex')), size: transactionSize, minFee: transactionMinFee, }; diff --git a/services/blockchain-connector/shared/sdk/pos.js b/services/blockchain-connector/shared/sdk/pos.js index 752a29e54e..37474237b5 100644 --- a/services/blockchain-connector/shared/sdk/pos.js +++ b/services/blockchain-connector/shared/sdk/pos.js @@ -49,9 +49,13 @@ const getAllPosValidators = async isForceReload => { try { if (!allPosValidators || isForceReload) { const response = await invokeEndpoint('pos_getAllValidators'); - if (Array.isArray(response)) { + if (response && Array.isArray(response.validators)) { allPosValidators = response; - logger.info(`Reloaded pos validators list. Validators count: ${allPosValidators.length}.`); + logger.info( + `Reloaded PoS validators list with ${allPosValidators.validators.length} entries.`, + ); + } else { + return response; } } return allPosValidators; diff --git a/services/blockchain-coordinator/app.js b/services/blockchain-coordinator/app.js index c153e7a6a6..bbbc71bf5f 100644 --- a/services/blockchain-coordinator/app.js +++ b/services/blockchain-coordinator/app.js @@ -64,7 +64,7 @@ app await init(); }) .catch(err => { - logger.fatal(`Failed to start service ${packageJson.name} due to: ${err.message}.`); + logger.fatal(`Failed to start service ${packageJson.name} due to: ${err.message}`); logger.fatal(err.stack); process.exit(1); }); diff --git a/services/blockchain-coordinator/config.js b/services/blockchain-coordinator/config.js index bff4599f8d..81d30338e1 100644 --- a/services/blockchain-coordinator/config.js +++ b/services/blockchain-coordinator/config.js @@ -72,6 +72,8 @@ config.queue = { }; config.job = { + progressRefreshInterval: 30 * 1000, // millisecs + // Interval takes priority over schedule and must be greater than 0 to be valid indexMissingBlocks: { interval: Number(process.env.JOB_INTERVAL_INDEX_MISSING_BLOCKS) || 0, diff --git a/services/blockchain-coordinator/jobs/missingBlocks.js b/services/blockchain-coordinator/jobs/missingBlocks.js index 8ffb787e92..3b5e1e4701 100644 --- a/services/blockchain-coordinator/jobs/missingBlocks.js +++ b/services/blockchain-coordinator/jobs/missingBlocks.js @@ -29,7 +29,7 @@ module.exports = [ logger.debug('Attempting to schedule indexing for the missing blocks.'); await scheduleMissingBlocksIndexing(); } catch (err) { - logger.warn(`Failed to schedule missing blocks indexing due to: ${err.message}.`); + logger.warn(`Failed to schedule missing blocks indexing due to: ${err.message}`); logger.trace(err.stack); } }, diff --git a/services/blockchain-coordinator/shared/scheduler.js b/services/blockchain-coordinator/shared/scheduler.js index 5ceb647f35..fa1ba165d6 100644 --- a/services/blockchain-coordinator/shared/scheduler.js +++ b/services/blockchain-coordinator/shared/scheduler.js @@ -48,7 +48,7 @@ const accountMessageQueue = new MessageQueue( ); let intervalID; -const REFRESH_INTERVAL = 30000; +const REFRESH_INTERVAL = config.job.progressRefreshInterval; const getInProgressJobCount = async queue => { const jobCount = await queue.getJobCounts(); @@ -231,18 +231,18 @@ const scheduleMissingBlocksIndexing = async () => { return; } - const genesisHeight = await getGenesisHeight(); - const currentHeight = await getCurrentHeight(); - // Skip job scheduling when the jobCount is greater than the threshold const jobCount = await getLiveIndexingJobCount(); if (jobCount > config.job.indexMissingBlocks.skipThreshold) { logger.info( - `Skipping missing blocks job run. ${jobCount} indexing jobs already in the queue. Current threshold set at: ${config.job.indexMissingBlocks.skipThreshold}.`, + `Skipping missing blocks job run. ${jobCount} indexing jobs already in the queue. Current threshold: ${config.job.indexMissingBlocks.skipThreshold}.`, ); return; } + const genesisHeight = await getGenesisHeight(); + const currentHeight = await getCurrentHeight(); + // Missing blocks are being checked during regular interval // By default they are checked from the blockchain's beginning const lastVerifiedHeight = (await getIndexVerifiedHeight()) || genesisHeight; @@ -267,17 +267,14 @@ const scheduleMissingBlocksIndexing = async () => { if (Array.isArray(result)) { missingBlocksByHeight.push(...result); - - if (result.length === 0) { - const lastIndexVerifiedHeight = (await getIndexVerifiedHeight()) || genesisHeight; - if (batchEndHeight <= lastIndexVerifiedHeight + MAX_QUERY_RANGE) { - if (NUM_BATCHES > 1 && i < NUM_BATCHES - 1) { - logger.info( - `No missing blocks found in range ${batchStartHeight} - ${batchEndHeight}. Setting index verified height to ${batchEndHeight}.`, - ); - } - } - } + } else { + logger.warn( + `getMissingBlocks returned '${typeof result}' type instead of an Array.\nresult: ${JSON.stringify( + result, + null, + '\t', + )}`, + ); } } @@ -286,24 +283,25 @@ const scheduleMissingBlocksIndexing = async () => { if (indexStatus) { const { chainLength, numBlocksIndexed, lastBlockHeight } = indexStatus.data; const numStillMissingJobs = chainLength - numBlocksIndexed - missingBlocksByHeight.length; - if (numStillMissingJobs > 0 && numStillMissingJobs <= 10) { + + if (numStillMissingJobs > 0 && numStillMissingJobs <= 100) { missingBlocksByHeight.push( ...range(lastBlockHeight - numStillMissingJobs + 1, lastBlockHeight + 1), ); } } - if (missingBlocksByHeight.length === 0) { - logger.info( - `No missing blocks found in range ${blockIndexLowerRange} - ${blockIndexHigherRange}. Setting index verified height to ${blockIndexHigherRange}.`, - ); - } else { + if (missingBlocksByHeight.length) { // Schedule indexing for the missing blocks await scheduleBlocksIndexing(missingBlocksByHeight); logger.info('Successfully scheduled missing blocks indexing.'); + } else { + logger.info( + `No missing blocks found in range ${blockIndexLowerRange} - ${blockIndexHigherRange}.`, + ); } } catch (err) { - logger.warn(`Scheduling to index missing blocks failed due to: ${err.message}.`); + logger.warn(`Scheduling to index missing blocks failed due to: ${err.message}`); logger.trace(err.stack); } }; @@ -315,7 +313,7 @@ const init = async () => { await initIndexingScheduler(); await initEventsScheduler(); } catch (err) { - logger.error(`Unable to initialize coordinator due to: ${err.message}.`); + logger.error(`Unable to initialize coordinator due to: ${err.message}`); logger.trace(err.stack); throw err; } diff --git a/services/blockchain-coordinator/shared/sources/indexer.js b/services/blockchain-coordinator/shared/sources/indexer.js index 834f8c8736..3e311d228e 100644 --- a/services/blockchain-coordinator/shared/sources/indexer.js +++ b/services/blockchain-coordinator/shared/sources/indexer.js @@ -27,7 +27,8 @@ const isGenesisBlockIndexed = async () => { const getIndexStatus = async () => requestIndexer('index.status').catch(() => null); -const getMissingBlocks = async (from, to) => requestIndexer('getMissingBlocks', { from, to }); +const getMissingBlocks = async (from, to) => + requestIndexer('getMissingBlocks', { from, to }).catch(err => err); const getIndexVerifiedHeight = async () => requestIndexer('getIndexVerifiedHeight').catch(() => null); diff --git a/services/blockchain-indexer/app.js b/services/blockchain-indexer/app.js index 688390eeb7..7b3186a563 100644 --- a/services/blockchain-indexer/app.js +++ b/services/blockchain-indexer/app.js @@ -67,7 +67,7 @@ const defaultBrokerConfig = { // Add routes, events & jobs const reportErrorAndExitProcess = err => { - logger.fatal(`Failed to start service ${packageJson.name} due to: ${err.message}.`); + logger.fatal(`Failed to start service ${packageJson.name} due to: ${err.message}`); logger.fatal(err.stack); process.exit(1); }; diff --git a/services/blockchain-indexer/jobs/dataService/knownAccounts.js b/services/blockchain-indexer/jobs/dataService/knownAccounts.js index 875f32bfcb..41d241a1f3 100644 --- a/services/blockchain-indexer/jobs/dataService/knownAccounts.js +++ b/services/blockchain-indexer/jobs/dataService/knownAccounts.js @@ -31,7 +31,7 @@ module.exports = [ await reloadAccountKnowledge(); logger.info('Successfully initialized accounts knowledge.'); } catch (err) { - logger.warn(`Initializing accounts knowledge failed due to: ${err.message}.`); + logger.warn(`Initializing accounts knowledge failed due to: ${err.message}`); } }, controller: async () => { @@ -40,7 +40,7 @@ module.exports = [ await reloadAccountKnowledge(); logger.info('Successfully reloaded accounts knowledge.'); } catch (err) { - logger.warn(`Reloading accounts knowledge failed due to: ${err.message}.`); + logger.warn(`Reloading accounts knowledge failed due to: ${err.message}`); } }, }, diff --git a/services/blockchain-indexer/jobs/dataService/validators.js b/services/blockchain-indexer/jobs/dataService/validators.js index 148fa37e74..c79f862da0 100644 --- a/services/blockchain-indexer/jobs/dataService/validators.js +++ b/services/blockchain-indexer/jobs/dataService/validators.js @@ -60,7 +60,7 @@ module.exports = [ try { await validateValidatorCache(); } catch (err) { - logger.warn(`Validating validators cache failed due to: ${err.message}.`); + logger.warn(`Validating validators cache failed due to: ${err.message}`); logger.debug(err.stack); } } diff --git a/services/blockchain-indexer/jobs/indexer/deleteFinalizedCCUMetadata.js b/services/blockchain-indexer/jobs/indexer/deleteFinalizedCCUMetadata.js index 7fc8e08aee..12ed84f214 100644 --- a/services/blockchain-indexer/jobs/indexer/deleteFinalizedCCUMetadata.js +++ b/services/blockchain-indexer/jobs/indexer/deleteFinalizedCCUMetadata.js @@ -32,7 +32,7 @@ module.exports = [ await deleteFinalizedCCUMetadata(finalizedHeight); logger.info('Successfully deleted CCUs metadata until the finalized block height.'); } catch (err) { - logger.warn(`'Deleting CCUs metadata failed due to: ${err.message}.`); + logger.warn(`'Deleting CCUs metadata failed due to: ${err.message}`); } }, }, diff --git a/services/blockchain-indexer/jobs/indexer/updateAccounts.js b/services/blockchain-indexer/jobs/indexer/updateAccounts.js index 0e6ab9e7fc..3037bbe190 100644 --- a/services/blockchain-indexer/jobs/indexer/updateAccounts.js +++ b/services/blockchain-indexer/jobs/indexer/updateAccounts.js @@ -31,7 +31,7 @@ module.exports = [ await triggerAccountUpdates(); logger.info('Triggered account updates successfully.'); } catch (err) { - logger.warn(`Triggering account updates failed due to: ${err.message}.`); + logger.warn(`Triggering account updates failed due to: ${err.message}`); logger.trace(err.stack); } }, @@ -47,7 +47,7 @@ module.exports = [ await triggerAccountsBalanceUpdate(); logger.info('Triggered account balance updates successfully.'); } catch (err) { - logger.warn(`Triggering account balance updates failed due to: ${err.message}.`); + logger.warn(`Triggering account balance updates failed due to: ${err.message}`); logger.trace(err.stack); } }, diff --git a/services/blockchain-indexer/shared/dataService/business/pos/constants.js b/services/blockchain-indexer/shared/dataService/business/pos/constants.js index 4d063a6143..3c7d6c6a21 100644 --- a/services/blockchain-indexer/shared/dataService/business/pos/constants.js +++ b/services/blockchain-indexer/shared/dataService/business/pos/constants.js @@ -25,7 +25,7 @@ const getPosConstants = async () => { if (typeof posModuleConstants === 'undefined') posModuleConstants = await requestConnector('getPosConstants'); } catch (err) { - const errMessage = `Unable to fetch the PoS constants from connector due to: ${err.message}.`; + const errMessage = `Unable to fetch the PoS constants from connector due to: ${err.message}`; logger.warn(errMessage); logger.trace(err.stack); throw new Error(errMessage); diff --git a/services/blockchain-indexer/shared/dataService/knownAccounts.js b/services/blockchain-indexer/shared/dataService/knownAccounts.js index ab28a4f0c1..e004c1ec4d 100644 --- a/services/blockchain-indexer/shared/dataService/knownAccounts.js +++ b/services/blockchain-indexer/shared/dataService/knownAccounts.js @@ -68,7 +68,7 @@ const reloadAccountKnowledge = async () => { logger.warn(`Static information unavailable for the current chainID: ${chainID}.`); } } catch (err) { - logger.error(`Could not reload known accounts: ${err.message}.`); + logger.error(`Could not reload known accounts: ${err.message}`); logger.debug(err.stack); } }; diff --git a/services/blockchain-indexer/shared/dataService/pos/validators.js b/services/blockchain-indexer/shared/dataService/pos/validators.js index 720dae3f97..e7058949c8 100644 --- a/services/blockchain-indexer/shared/dataService/pos/validators.js +++ b/services/blockchain-indexer/shared/dataService/pos/validators.js @@ -149,7 +149,7 @@ const loadAllPosValidators = async () => { logger.info(`Updated validator list with ${validatorList.length} validators.`); } } catch (err) { - logger.warn(`Failed to load all validators due to: ${err.message}.`); + logger.warn(`Failed to load all validators due to: ${err.message}`); } }; diff --git a/services/blockchain-indexer/shared/dataService/transactions.js b/services/blockchain-indexer/shared/dataService/transactions.js index b556edcbf3..ffb1bebffc 100644 --- a/services/blockchain-indexer/shared/dataService/transactions.js +++ b/services/blockchain-indexer/shared/dataService/transactions.js @@ -117,7 +117,7 @@ const postTransactions = async params => { }; return { - data: { error: `Transaction payload was rejected by the network node: ${err.message}.` }, + data: { error: `Transaction payload was rejected by the network node: ${err.message}` }, status: 'BAD_REQUEST', }; } @@ -139,7 +139,7 @@ const dryRunTransactions = async params => { }; return { - data: { error: `Failed to dry run transaction: ${err.message}.` }, + data: { error: `Failed to dry run transaction: ${err.message}` }, status: 'BAD_REQUEST', }; } diff --git a/services/blockchain-indexer/shared/indexer/accountBalanceIndex.js b/services/blockchain-indexer/shared/indexer/accountBalanceIndex.js index 52ce7ad70c..81bb7b1a06 100644 --- a/services/blockchain-indexer/shared/indexer/accountBalanceIndex.js +++ b/services/blockchain-indexer/shared/indexer/accountBalanceIndex.js @@ -80,18 +80,23 @@ const triggerAccountsBalanceUpdate = async () => { config.set.accountBalanceUpdate.batchSize, ); + const numAddressesScheduled = addresses.length; try { // eslint-disable-next-line no-restricted-syntax - for (const address of addresses) { + while (addresses.length) { + const address = addresses.shift(); await updateAccountBalances(address); } + logger.info(`Successfully updated account balances for ${numAddressesScheduled} account(s).`); } catch (err) { - // Reschedule accounts balance update on error + // Reschedule accounts balance update on error for remaining addresses await scheduleAddressesBalanceUpdate(addresses); - } - if (addresses.length) { - logger.info(`Updated account balance for ${addresses.length} account(s).`); + const numPending = addresses.length; + const numSuccess = numAddressesScheduled - numPending; + logger.info( + `Successfully updated account balances for ${numSuccess} account(s). Rescheduling updates for ${numPending} account(s).`, + ); } }; diff --git a/services/blockchain-indexer/shared/indexer/blockchainIndex.js b/services/blockchain-indexer/shared/indexer/blockchainIndex.js index 90426d405f..cf6f430f16 100644 --- a/services/blockchain-indexer/shared/indexer/blockchainIndex.js +++ b/services/blockchain-indexer/shared/indexer/blockchainIndex.js @@ -152,6 +152,9 @@ const indexBlock = async job => { // Always index the last indexed blockHeight + 1 (sequential indexing) if (typeof lastIndexedHeight !== 'undefined') { blockHeightToIndex = lastIndexedHeight + 1; + + // Skip job run if the height to be indexed does not exist + if ((await getCurrentHeight()) < blockHeightToIndex) return; } const [currentBlockInDB = {}] = await blocksTable.find( @@ -380,9 +383,7 @@ const indexBlock = async job => { ); } catch (error) { // Stop genesisAsset index progress logging on errors - if (blockToIndexFromNode.height === genesisHeight) { - clearInterval(getGenesisAssetIntervalTimeout()); - } + clearInterval(getGenesisAssetIntervalTimeout()); // Block may not have been initialized when error occurred const failedBlockInfo = { diff --git a/services/blockchain-indexer/shared/indexer/genesisBlock.js b/services/blockchain-indexer/shared/indexer/genesisBlock.js index 4a6c1e396e..8a15b5b9b6 100644 --- a/services/blockchain-indexer/shared/indexer/genesisBlock.js +++ b/services/blockchain-indexer/shared/indexer/genesisBlock.js @@ -93,9 +93,7 @@ const indexTokenModuleAssets = async dbTrx => { const isGeneratorKeyValid = generatorKey => generatorKey !== INVALID_ED25519_KEY; const indexPosValidatorsInfo = async (numValidators, dbTrx) => { - logger.debug( - 'Starting to index the PoS Validators information from the genesis PoS module assets.', - ); + logger.debug('Starting to index the validators information from the genesis PoS module assets.'); if (numValidators > 0) { const commissionsTable = await getCommissionsTable(); @@ -136,13 +134,11 @@ const indexPosValidatorsInfo = async (numValidators, dbTrx) => { await commissionsTable.upsert(commissionEntries, dbTrx); } - logger.debug( - 'Finished indexing the PoS Validators information from the genesis PoS module assets.', - ); + logger.debug('Finished indexing the validators information from the genesis PoS module assets.'); }; const indexPosStakesInfo = async (numStakers, dbTrx) => { - logger.debug('Starting to index the PoS stakes information from the genesis PoS module assets.'); + logger.debug('Starting to index the stakes information from the genesis PoS module assets.'); let totalStake = BigInt(0); let totalSelfStake = BigInt(0); @@ -185,7 +181,7 @@ const indexPosStakesInfo = async (numStakers, dbTrx) => { await updateTotalSelfStake(totalSelfStake, dbTrx); logger.info(`Updated total self-stakes information at genesis: ${totalSelfStake.toString()}.`); - logger.debug('Finished indexing the PoS stakes information from the genesis PoS module assets.'); + logger.debug('Finished indexing the stakes information from the genesis PoS module assets.'); }; const indexPosModuleAssets = async dbTrx => { @@ -219,7 +215,7 @@ const indexTokenBalances = async () => { // eslint-disable-next-line no-restricted-syntax for (const address of allAccountsAddresses) { await updateAccountBalances(address).catch(err => { - const errorMessage = `Updating account balance for ${address} failed. Retrying.\nError: ${err.message}.`; + const errorMessage = `Updating account balance for ${address} failed. Retrying.\nError: ${err.message}`; logger.warn(errorMessage); logger.debug(err.stack); diff --git a/services/blockchain-indexer/shared/init.js b/services/blockchain-indexer/shared/init.js index 683883a8fc..ad536ff7e4 100644 --- a/services/blockchain-indexer/shared/init.js +++ b/services/blockchain-indexer/shared/init.js @@ -47,7 +47,7 @@ const init = async () => { await snapshotUtils.initSnapshot(); logger.info('Successfully downloaded and applied the snapshot.'); } catch (err) { - logger.warn(`Unable to apply snapshot:\n${err.message}.`); + logger.warn(`Unable to apply snapshot:\n${err.message}`); } } diff --git a/services/blockchain-indexer/shared/messageProcessor.js b/services/blockchain-indexer/shared/messageProcessor.js index 3d1541cc73..410dd783cd 100644 --- a/services/blockchain-indexer/shared/messageProcessor.js +++ b/services/blockchain-indexer/shared/messageProcessor.js @@ -84,20 +84,20 @@ const newBlockProcessor = async block => { await performLastBlockUpdate(newBlock); Signals.get('newBlock').dispatch(response); logger.info( - `Finished scheduling new block (${block.header.id}) event for the block at height ${block.header.height}.`, + `Finished scheduling new block (${block.header.id}) event for block height ${block.header.height}.`, ); }; const deleteBlockProcessor = async header => { try { logger.debug( - `Scheduling the delete block (${header.id}) event for the block at height ${header.height}.`, + `Scheduling the delete block (${header.id}) event for block height ${header.height}.`, ); const response = await formatBlock({ header }, true); await scheduleBlockDeletion(header); Signals.get('deleteBlock').dispatch(response); logger.info( - `Finished scheduling the delete block (${header.id}) event for the block at height ${header.height}.`, + `Finished scheduling the delete block (${header.id}) event for block height ${header.height}.`, ); } catch (err) { logger.warn( diff --git a/services/blockchain-indexer/tests/unit/shared/dataservice/knownAccounts.test.js b/services/blockchain-indexer/tests/unit/shared/dataservice/knownAccounts.test.js index 4c71f1063c..86bb42a6b7 100644 --- a/services/blockchain-indexer/tests/unit/shared/dataservice/knownAccounts.test.js +++ b/services/blockchain-indexer/tests/unit/shared/dataservice/knownAccounts.test.js @@ -120,7 +120,7 @@ describe('reloadAccountKnowledge', () => { info: jest.fn(), warn: jest.fn(), error: async data => - expect(data).toEqual('Could not reload known accounts: Test error message.'), + expect(data).toEqual('Could not reload known accounts: Test error message'), }), }; }); diff --git a/services/blockchain-indexer/tests/unit/shared/dataservice/transactions.test.js b/services/blockchain-indexer/tests/unit/shared/dataservice/transactions.test.js index f3d5e1263b..417fc2ed12 100644 --- a/services/blockchain-indexer/tests/unit/shared/dataservice/transactions.test.js +++ b/services/blockchain-indexer/tests/unit/shared/dataservice/transactions.test.js @@ -84,7 +84,7 @@ describe('dryRunTransactions', () => { it('should return bad request error response on other error', async () => { const mockError = new Error('Some other error'); const expectedErrorResponse = { - data: { error: `Failed to dry run transaction: Error: ${mockError.message}.` }, + data: { error: `Failed to dry run transaction: Error: ${mockError.message}` }, status: 'BAD_REQUEST', }; diff --git a/services/export/app.js b/services/export/app.js index 80c01bfa91..4b046972c2 100644 --- a/services/export/app.js +++ b/services/export/app.js @@ -47,7 +47,7 @@ app logger.info(`Service started ${packageJson.name}.`); }) .catch(err => { - logger.fatal(`Failed to start service ${packageJson.name} due to: ${err.message}.`); + logger.fatal(`Failed to start service ${packageJson.name} due to: ${err.message}`); logger.fatal(err.stack); process.exit(1); }); diff --git a/services/fee-estimator/app.js b/services/fee-estimator/app.js index 1fe76f4dbd..41314cf107 100644 --- a/services/fee-estimator/app.js +++ b/services/fee-estimator/app.js @@ -49,7 +49,7 @@ app logger.info(`Service started ${packageJson.name}.`); }) .catch(err => { - logger.fatal(`Failed to start service ${packageJson.name} due to: ${err.message}.`); + logger.fatal(`Failed to start service ${packageJson.name} due to: ${err.message}`); logger.fatal(err.stack); process.exit(1); }); diff --git a/services/gateway/apis/http-version3/swagger/definitions/transactions.json b/services/gateway/apis/http-version3/swagger/definitions/transactions.json index 01820dcaf6..6866a41b2c 100644 --- a/services/gateway/apis/http-version3/swagger/definitions/transactions.json +++ b/services/gateway/apis/http-version3/swagger/definitions/transactions.json @@ -242,6 +242,16 @@ } } }, + "signatures": { + "type": "array", + "description": "An array representing signature(s) of the transaction sender.", + "items": { + "type": "string" + }, + "example": [ + "48425002226745847e155cf5480478c2336a43bb178439e9058cc2b50e26335cf7c8360b6c6a49793d7ae8d087bc746cab9618655e6a0adba4694cce2015b50f" + ] + }, "executionStatus": { "type": "string", "example": "successful", diff --git a/services/gateway/app.js b/services/gateway/app.js index 178acb6e9a..c16cf4e542 100644 --- a/services/gateway/app.js +++ b/services/gateway/app.js @@ -231,7 +231,7 @@ tempApp.run().then(async () => { logger.info(`Started Gateway API on ${host}:${port}.`); }) .catch(err => { - logger.fatal(`Failed to start service ${packageJson.name} due to: ${err.message}.`); + logger.fatal(`Failed to start service ${packageJson.name} due to: ${err.message}`); logger.fatal(err.stack); process.exit(1); }); diff --git a/services/gateway/sources/version3/mappings/transaction.js b/services/gateway/sources/version3/mappings/transaction.js index 7222d05768..7211cbbf01 100644 --- a/services/gateway/sources/version3/mappings/transaction.js +++ b/services/gateway/sources/version3/mappings/transaction.js @@ -20,18 +20,21 @@ module.exports = { fee: '=,string', minFee: '=,string', size: '=,number', - sender: { - address: 'sender.address,string', - publicKey: 'sender.publicKey,string', - name: 'sender.name,string', - }, - params: '=', block: { id: 'block.id,string', height: 'block.height,number', timestamp: 'block.timestamp,number', isFinal: 'block.isFinal,boolean', }, + sender: { + address: 'sender.address,string', + publicKey: 'sender.publicKey,string', + name: 'sender.name,string', + }, + params: '=', + signatures: '=', + executionStatus: '=,string', + index: '=,number', meta: { recipient: { address: 'meta.recipient.address,string', @@ -39,6 +42,4 @@ module.exports = { name: 'meta.recipient.name,string', }, }, - executionStatus: '=,string', - index: '=,number', }; diff --git a/services/market/app.js b/services/market/app.js index dbe69f91c8..df9ffefdf3 100644 --- a/services/market/app.js +++ b/services/market/app.js @@ -46,7 +46,7 @@ app ); }) .catch(err => { - logger.fatal(`Failed to start service ${packageJson.name} due to: ${err.message}.`); + logger.fatal(`Failed to start service ${packageJson.name} due to: ${err.message}`); logger.fatal(err.stack); process.exit(1); }); diff --git a/services/template/app.js b/services/template/app.js index a634d95463..fe6313528d 100644 --- a/services/template/app.js +++ b/services/template/app.js @@ -45,7 +45,7 @@ app logger.info(`Service started ${packageJson.name}.`); }) .catch(err => { - logger.fatal(`Failed to start service ${packageJson.name} due to: ${err.message}.`); + logger.fatal(`Failed to start service ${packageJson.name} due to: ${err.message}`); logger.fatal(err.stack); process.exit(1); }); diff --git a/services/transaction-statistics/app.js b/services/transaction-statistics/app.js index aff61fe5c9..d70ba18c2f 100644 --- a/services/transaction-statistics/app.js +++ b/services/transaction-statistics/app.js @@ -45,7 +45,7 @@ app.addJobs(path.join(__dirname, 'jobs')); // Run the application const reportErrorAndExitProcess = err => { - logger.fatal(`Failed to start service ${packageJson.name} due to: ${err.message}.`); + logger.fatal(`Failed to start service ${packageJson.name} due to: ${err.message}`); logger.fatal(err.stack); process.exit(1); }; diff --git a/tests/schemas/api_v3/transaction.schema.js b/tests/schemas/api_v3/transaction.schema.js index 36d2187078..3489d7ab4c 100644 --- a/tests/schemas/api_v3/transaction.schema.js +++ b/tests/schemas/api_v3/transaction.schema.js @@ -46,12 +46,13 @@ const pendingTransactionSchema = { moduleCommand: Joi.string().pattern(regex.MODULE_COMMAND).required(), nonce: Joi.string().required(), fee: Joi.string().required(), + minFee: Joi.string().required(), size: Joi.number().integer().positive().required(), sender: Joi.object(sender).required(), params: Joi.object().required(), + signatures: Joi.array().items(Joi.string().required()).required(), executionStatus: Joi.string().valid('pending').required(), meta: Joi.object(transactionMetaSchema).optional(), - minFee: Joi.string().required(), }; const transactionSchema = {