From 3cd4729d80be7007ae65c1b94ba337a54a794d55 Mon Sep 17 00:00:00 2001 From: zeroxbt <89495162+zeroxbt@users.noreply.github.com> Date: Sat, 3 Dec 2022 20:28:06 +0100 Subject: [PATCH 01/16] merge v6/develop into v6/development-network (#2225) * fixes, bump version (#2223) * update package-lock (#2224) --- ot-node.js | 32 +++++++++++++++------------ package-lock.json | 18 +++++++-------- package.json | 4 ++-- src/service/sharding-table-service.js | 2 +- 4 files changed, 30 insertions(+), 26 deletions(-) diff --git a/ot-node.js b/ot-node.js index 7b2818e61d..3773b2c4f3 100644 --- a/ot-node.js +++ b/ot-node.js @@ -28,6 +28,7 @@ class OTNode { async start() { await this.checkForUpdate(); await this.removeUpdateFile(); + await this.executeMigrations(); this.logger.info(' ██████╗ ████████╗███╗ ██╗ ██████╗ ██████╗ ███████╗'); this.logger.info('██╔═══██╗╚══██╔══╝████╗ ██║██╔═══██╗██╔══██╗██╔════╝'); @@ -42,11 +43,12 @@ class OTNode { this.logger.info(`Node is running in ${process.env.NODE_ENV} environment`); await this.initializeDependencyContainer(); - await this.executeMigrations(); this.initializeEventEmitter(); await this.initializeModules(); + await this.executeCleanOperationalDatabaseMigration(); + await this.listenOnHubContractChanges(); await this.createProfiles(); @@ -338,19 +340,6 @@ class OTNode { if (!(await blockchainIdentityMigration.migrationAlreadyExecuted())) { await blockchainIdentityMigration.migrate(); } - - const repositoryModuleManager = this.container.resolve('repositoryModuleManager'); - const cleanShardingTableMigration = new CleanOperationalDatabaseMigration( - 'CleanOperationalDatabaseMigration', - this.logger, - this.config, - repositoryModuleManager, - ); - if (!(await cleanShardingTableMigration.migrationAlreadyExecuted())) { - await cleanShardingTableMigration.migrate(); - this.logger.info('Operational database cleanup completed. Node will now restart!'); - this.stop(); - } } async checkForUpdate() { @@ -369,6 +358,21 @@ class OTNode { process.exit(code); } + async executeCleanOperationalDatabaseMigration() { + const repositoryModuleManager = this.container.resolve('repositoryModuleManager'); + const cleanOperationalDatabaseMigration = new CleanOperationalDatabaseMigration( + 'CleanOperationalDatabaseMigration', + this.logger, + this.config, + repositoryModuleManager, + ); + if (!(await cleanOperationalDatabaseMigration.migrationAlreadyExecuted())) { + await cleanOperationalDatabaseMigration.migrate(); + this.logger.info('Operational database cleanup completed. Node will now restart!'); + this.stop(); + } + } + async listenOnHubContractChanges() { const eventEmitter = this.container.resolve('eventEmitter'); const repositoryModuleManager = this.container.resolve('repositoryModuleManager'); diff --git a/package-lock.json b/package-lock.json index df06928589..b46b1b7495 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "origintrail_node", - "version": "6.0.0-beta.3.0.5", + "version": "6.0.0-beta.3.0.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "origintrail_node", - "version": "6.0.0-beta.3.0.5", + "version": "6.0.0-beta.3.0.6", "license": "ISC", "dependencies": { "@comunica/query-sparql": "^2.4.3", @@ -20,7 +20,7 @@ "bignumber.js": "^9.1.0", "cors": "^2.8.5", "deep-extend": "^0.6.0", - "dkg-evm-module": "^3.0.3", + "dkg-evm-module": "^3.0.4", "dotenv": "^16.0.1", "ethers": "^5.7.2", "express": "^4.18.1", @@ -7925,9 +7925,9 @@ } }, "node_modules/dkg-evm-module": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dkg-evm-module/-/dkg-evm-module-3.0.3.tgz", - "integrity": "sha512-XX8mB0U/icNhoqf6ubg9iINPcAhfHBOwXUpfPCCZxYtSAB90DoiLPMizKEdTRo1V3qxj/VCdlOxnGOTQ2dL7tA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dkg-evm-module/-/dkg-evm-module-3.0.4.tgz", + "integrity": "sha512-vHex5ll70L53q9pKQqZPqp8OoiNOHQcYOAZ77JTWg99Ir1so+zd0aRwaXc6NNCSpL/y1+4swQGANNrZO57XWdA==", "dependencies": { "@openzeppelin/contracts": "^4.7.3", "@polkadot/api": "^9.9.4", @@ -26641,9 +26641,9 @@ } }, "dkg-evm-module": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dkg-evm-module/-/dkg-evm-module-3.0.3.tgz", - "integrity": "sha512-XX8mB0U/icNhoqf6ubg9iINPcAhfHBOwXUpfPCCZxYtSAB90DoiLPMizKEdTRo1V3qxj/VCdlOxnGOTQ2dL7tA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dkg-evm-module/-/dkg-evm-module-3.0.4.tgz", + "integrity": "sha512-vHex5ll70L53q9pKQqZPqp8OoiNOHQcYOAZ77JTWg99Ir1so+zd0aRwaXc6NNCSpL/y1+4swQGANNrZO57XWdA==", "requires": { "@openzeppelin/contracts": "^4.7.3", "@polkadot/api": "^9.9.4", diff --git a/package.json b/package.json index 25fd4506ef..70de201473 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "origintrail_node", - "version": "6.0.0-beta.3.0.5", + "version": "6.0.0-beta.3.0.6", "description": "OTNode v6 Beta 2", "main": "index.js", "type": "module", @@ -73,7 +73,7 @@ "bignumber.js": "^9.1.0", "cors": "^2.8.5", "deep-extend": "^0.6.0", - "dkg-evm-module": "^3.0.3", + "dkg-evm-module": "^3.0.4", "dotenv": "^16.0.1", "ethers": "^5.7.2", "express": "^4.18.1", diff --git a/src/service/sharding-table-service.js b/src/service/sharding-table-service.js index 025ade7105..f277cf01ed 100644 --- a/src/service/sharding-table-service.js +++ b/src/service/sharding-table-service.js @@ -77,7 +77,7 @@ class ShardingTableService { ); shardingTable.push(...nodes.slice(sliceIndex).filter((node) => node.id !== '0x')); sliceIndex = 1; - startingIdentityId = nodes[nodes.length - 1].id; + startingIdentityId = nodes[nodes.length - 1].identityId; } this.logger.debug( From 8a916dbaa6d067b411dc995b56a0679937bae981 Mon Sep 17 00:00:00 2001 From: BRX <85747941+Valcyclovir@users.noreply.github.com> Date: Fri, 9 Dec 2022 01:32:11 -0500 Subject: [PATCH 02/16] add arch file dependency to installerv2 File dependency to install V6 node on Arch Linux --- installer/data/archlinux | 65 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 installer/data/archlinux diff --git a/installer/data/archlinux b/installer/data/archlinux new file mode 100644 index 0000000000..b162afcbc8 --- /dev/null +++ b/installer/data/archlinux @@ -0,0 +1,65 @@ +install_prereqs() { +perform_step install_aliases "Updating .bashrc file with OriginTrail node aliases" +perform_step pacman -Syu --noconfirm "Updating server" +perform_step pacman -S unzip wget jq --noconfirm "Installing unzip, wget, jq" +perform_step pacman -S jre-openjdk --noconfirm "Installing default-jre" +perform_step pacman -S npm nodejs-lts-gallium tcl --noconfirm "Installing npm, nodejs and tcl" +} + +install_sql() { + sql=mariadb + perform_step pacman -S mariadb --noconfirm "Downloading mariadb" + perform_step mariadb-install-db --user=mysql --basedir=/usr --datadir=/var/lib/mysql "Installing mariadb" + perform_step systemctl enable mariadb "Enabling mariadb" + perform_step systemctl start mariadb "Starting mariadb" + + #check old sql password + OUTPUT=$($sql -u root -e "status;" 2>&1) + if [[ $? -ne 0 ]]; then + while true; do + read -s -p "Enter your old sql password: " oldpassword + echo + echo -n "Password check: " + OUTPUT=$(MYSQL_PWD=$oldpassword $sql -u root -e "status;" 2>&1) + if [[ $? -ne 0 ]]; then + text_color $YELLOW "ERROR - The sql repository password provided does not match your sql password. Please try again." + else + text_color $GREEN "OK" + break + fi + done + fi + + #check operationaldb + if [[ -d "/var/lib/mysql/operationaldb/" ]]; then + read -p "Old operationaldb repository detected. Would you like to overwrite it ? (Default: No) [Y]es [N]o [E]xit " choice + case "$choice" in + [yY]* ) perform_step $(MYSQL_PWD=$oldpassword $sql -u root -e "DROP DATABASE IF EXISTS operationaldb;") "Overwritting slq repository";; + [eE]* ) text_color $RED"Installer stopped by user"; exit;; + * ) text_color $GREEN"Keeping previous sql repository"; NEW_DB=FALSE;; + esac + fi + + #check sql new password + read -p "Would you like to change your sql password or add one ? (Default: Yes) [Y]es [N]o [E]xit " choice + case "$choice" in + [nN]* ) text_color $GREEN"Keeping previous sql password"; password=$oldpassword;; + [eE]* ) text_color $RED"Installer stopped by user"; exit;; + * ) while true; do + read -s -p "Enter your new sql password: " password + echo + read -s -p "Please confirm your new sql password: " password2 + echo + [[ $password = $password2 ]] && break + text_color $YELLOW "Password entered do not match. Please try again." + done + perform_step $(MYSQL_PWD=$oldpassword $sql -u root -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '$password';") "Changing sql password";; + esac + + perform_step $(echo "REPOSITORY_PASSWORD=$password" > $OTNODE_DIR/.env) "Adding sql password to .env" + if [[ $NEW_DB != FALSE ]]; then + perform_step $(MYSQL_PWD=$password $sql -u root -e "CREATE DATABASE operationaldb /*\!40100 DEFAULT CHARACTER SET utf8 */;") "Creating new sql repository" + fi + perform_step $(echo -e "disable_log_bin\nwait_timeout = 31536000\ninteractive_timeout = 31536000" >> /etc/my.cnf.d/server.cnf) "Adding disable_log_bin, wait_timeout, interactive_timeout variables to $sql config" + perform_step systemctl restart $sql "Restarting $sql" +} From c1571980c61c66de65e1c37b2538d473547da7e0 Mon Sep 17 00:00:00 2001 From: zeroxbt Date: Thu, 15 Dec 2022 12:59:19 +0100 Subject: [PATCH 03/16] better handling of invalid messages --- .../network/implementation/libp2p-service.js | 62 +++++++++++-------- .../implementation/ot-triple-store.js | 2 +- src/service/data-service.js | 2 +- 3 files changed, 37 insertions(+), 29 deletions(-) diff --git a/src/modules/network/implementation/libp2p-service.js b/src/modules/network/implementation/libp2p-service.js index bf3e0ae187..a3291f739d 100644 --- a/src/modules/network/implementation/libp2p-service.js +++ b/src/modules/network/implementation/libp2p-service.js @@ -279,6 +279,12 @@ class Libp2pService { } async sendMessage(protocol, peerId, messageType, operationId, keyword, message) { + const nackMessage = { + header: { messageType: NETWORK_MESSAGE_TYPES.RESPONSES.NACK }, + data: { + errorMessage: '', + }, + }; const keywordUuid = uuidv5(keyword, uuidv5.URL); // const sessionStream = this.getSessionStream(operationId, remotePeerId.toB58String()); @@ -307,14 +313,11 @@ class Libp2pService { dialEnd = Date.now(); } catch (error) { dialEnd = Date.now(); - return { - header: { messageType: NETWORK_MESSAGE_TYPES.RESPONSES.NACK }, - data: { - errorMessage: `Unable to dial peer: ${remotePeerId.toB58String()}. protocol: ${protocol}, messageType: ${messageType} , operationId: ${operationId}, dial execution time: ${ - dialEnd - dialStart - } ms. Error: ${error.message}`, - }, - }; + nackMessage.data.errorMessage = `Unable to dial peer: ${remotePeerId.toB58String()}. protocol: ${protocol}, messageType: ${messageType} , operationId: ${operationId}, dial execution time: ${ + dialEnd - dialStart + } ms. Error: ${error.message}`; + + return nackMessage; } this.logger.trace( `Created stream for peer: ${remotePeerId.toB58String()}. protocol: ${protocol}, messageType: ${messageType} , operationId: ${operationId}, dial execution time: ${ @@ -344,14 +347,11 @@ class Libp2pService { sendMessageEnd = Date.now(); } catch (error) { sendMessageEnd = Date.now(); - return { - header: { messageType: NETWORK_MESSAGE_TYPES.RESPONSES.NACK }, - data: { - errorMessage: `Unable to send message to peer: ${remotePeerId.toB58String()}. protocol: ${protocol}, messageType: ${messageType}, operationId: ${operationId}, execution time: ${ - sendMessageEnd - sendMessageStart - } ms. Error: ${error.message}`, - }, - }; + nackMessage.data.errorMessage = `Unable to send message to peer: ${remotePeerId.toB58String()}. protocol: ${protocol}, messageType: ${messageType}, operationId: ${operationId}, execution time: ${ + sendMessageEnd - sendMessageStart + } ms. Error: ${error.message}`; + + return nackMessage; } // if (!this.sessions[remotePeerId.toB58String()]) { @@ -381,14 +381,11 @@ class Libp2pService { readResponseEnd = Date.now(); } catch (error) { readResponseEnd = Date.now(); - return { - header: { messageType: NETWORK_MESSAGE_TYPES.RESPONSES.NACK }, - data: { - errorMessage: `Unable to read response from peer ${remotePeerId.toB58String()}. protocol: ${protocol}, messageType: ${messageType} , operationId: ${operationId}, execution time: ${ - readResponseEnd - readResponseStart - } ms. Error: ${error.message}`, - }, - }; + nackMessage.data.errorMessage = `Unable to read response from peer ${remotePeerId.toB58String()}. protocol: ${protocol}, messageType: ${messageType} , operationId: ${operationId}, execution time: ${ + readResponseEnd - readResponseStart + } ms. Error: ${error.message}`; + + return nackMessage; } this.logger.trace( `Receiving response from ${remotePeerId.toB58String()}. protocol: ${protocol}, messageType: ${ @@ -398,7 +395,13 @@ class Libp2pService { } ms.`, ); - return response.valid ? response.message : null; + if (!response.valid) { + nackMessage.data.errorMessage = 'Invalid response'; + + return nackMessage; + } + + return response.message; } async sendMessageResponse( @@ -489,10 +492,14 @@ class Libp2pService { } async readMessageSink(source, isMessageValid, remotePeerId) { - const message = {}; - let stringifiedData = ''; + const message = { header: { operationId: '', keywordUuid: '' }, data: {} }; // we expect first buffer to be header const stringifiedHeader = (await source.next()).value; + + if (!stringifiedHeader?.length) { + return { message, valid: false, busy: false }; + } + message.header = JSON.parse(stringifiedHeader); // validate request / response @@ -508,6 +515,7 @@ class Libp2pService { return { message, valid: true, busy: true }; } + let stringifiedData = ''; // read data the data for await (const chunk of source) { stringifiedData += chunk; diff --git a/src/modules/triple-store/implementation/ot-triple-store.js b/src/modules/triple-store/implementation/ot-triple-store.js index 8e2217cd7a..99b227a568 100644 --- a/src/modules/triple-store/implementation/ot-triple-store.js +++ b/src/modules/triple-store/implementation/ot-triple-store.js @@ -139,7 +139,7 @@ class OtTripleStore { // no media type is passed because of comunica bug // https://github.com/comunica/comunica/issues/1034 const result = await this._executeQuery(query); - return JSON.parse(result); + return result ? JSON.parse(result) : []; } async ask(query) { diff --git a/src/service/data-service.js b/src/service/data-service.js index df798a85b8..3c15a15dbf 100644 --- a/src/service/data-service.js +++ b/src/service/data-service.js @@ -47,7 +47,7 @@ class DataService { * @param bindings * @returns {*[]} */ - parseBindings(bindings) { + parseBindings(bindings = []) { const result = []; for (const row of bindings) { From 3e0b0deb642ffc4811954783207164895cb2bab2 Mon Sep 17 00:00:00 2001 From: zeroxbt Date: Thu, 15 Dec 2022 13:19:18 +0100 Subject: [PATCH 04/16] add migration for values types in event table --- .../20221215130500-update-event-types.js | 23 +++++++++++++++++++ .../implementation/sequelize/models/event.js | 6 ++--- 2 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 src/modules/repository/implementation/sequelize/migrations/20221215130500-update-event-types.js diff --git a/src/modules/repository/implementation/sequelize/migrations/20221215130500-update-event-types.js b/src/modules/repository/implementation/sequelize/migrations/20221215130500-update-event-types.js new file mode 100644 index 0000000000..f78218f3e1 --- /dev/null +++ b/src/modules/repository/implementation/sequelize/migrations/20221215130500-update-event-types.js @@ -0,0 +1,23 @@ +export async function up({ context: { queryInterface, Sequelize } }) { + await queryInterface.changeColumn('event', 'value1', { + type: Sequelize.TEXT, + }); + await queryInterface.changeColumn('event', 'value2', { + type: Sequelize.TEXT, + }); + await queryInterface.changeColumn('event', 'value3', { + type: Sequelize.TEXT, + }); +} + +export async function down({ context: { queryInterface, Sequelize } }) { + await queryInterface.changeColumn('event', 'value1', { + type: Sequelize.STRING, + }); + await queryInterface.changeColumn('event', 'value2', { + type: Sequelize.STRING, + }); + await queryInterface.changeColumn('event', 'value3', { + type: Sequelize.STRING, + }); +} diff --git a/src/modules/repository/implementation/sequelize/models/event.js b/src/modules/repository/implementation/sequelize/models/event.js index 709f2f0208..360da526d8 100644 --- a/src/modules/repository/implementation/sequelize/models/event.js +++ b/src/modules/repository/implementation/sequelize/models/event.js @@ -10,9 +10,9 @@ export default (sequelize, DataTypes) => { operation_id: DataTypes.UUID, name: DataTypes.STRING, timestamp: DataTypes.STRING, - value1: DataTypes.STRING, - value2: DataTypes.STRING, - value3: DataTypes.STRING, + value1: DataTypes.TEXT, + value2: DataTypes.TEXT, + value3: DataTypes.TEXT, created_at: DataTypes.DATE, updated_at: DataTypes.DATE, }, From 467d70505b49fc3fd92160076cd6c5d6e60c7594 Mon Sep 17 00:00:00 2001 From: valcyclovir Date: Fri, 16 Dec 2022 14:09:04 -0500 Subject: [PATCH 05/16] small fuseki install bug fix --- installer/installer.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/installer/installer.sh b/installer/installer.sh index 963fd9d5aa..e0b984e650 100755 --- a/installer/installer.sh +++ b/installer/installer.sh @@ -102,7 +102,7 @@ install_fuseki() { perform_step wget https://dlcdn.apache.org/jena/binaries/$FUSEKI_VER.zip "Downloading Fuseki" perform_step unzip $FUSEKI_VER.zip "Unzipping Fuseki" - perform_step rm /root/$FUSEKI_VER.zip /root/ot-node/$FUSEKI_VER.zip "Removing Fuseki zip file" + perform_step rm /root/$FUSEKI_VER.zip "Removing Fuseki zip file" perform_step mkdir /root/ot-node/fuseki "Making /root/ot-node/fuseki directory" perform_step mkdir /root/ot-node/fuseki/tdb "Making /root/ot-node/fuseki/tdb directory" perform_step cp /root/$FUSEKI_VER/fuseki-server.jar /root/ot-node/fuseki/ "Copying Fuseki files to $OTNODE_DIR/fuseki/ 1/2" @@ -312,12 +312,12 @@ case "$choice" in esac if [[ $tripleStore = "ot-fuseki" ]]; then - if [[ -d "/root/fuseki" ]]; then + if [[ -d "$OTNODE_DIR/../fuseki" ]]; then read -p "Previously installed Fuseki triplestore detected. Would you like to overwrite it? (Default: Yes) [Y]es [N]o [E]xit " choice case "$choice" in [nN]* ) text_color $GREEN"Keeping previous Fuseki installation.";; [eE]* ) text_color $RED"Installer stopped by user"; exit;; - * ) text_color $GREEN"Reinstalling Fuseki."; perform_step rm -rf fuseki* "Removing previous Fuseki installation"; install_fuseki;; + * ) text_color $GREEN"Reinstalling Fuseki."; perform_step rm -rf $OTNODE_DIR/../fuseki "Removing previous Fuseki installation"; install_fuseki;; esac else install_fuseki From 1901d79c8f4ff3dc3dce1d35822e4a5314946679 Mon Sep 17 00:00:00 2001 From: Uladzislau Hubar Date: Mon, 19 Dec 2022 10:58:12 +0100 Subject: [PATCH 06/16] Added validation of input arguments for bid suggestion --- .../bid-suggestion-http-api-controller.js | 16 +++++++++++++++ src/controllers/http-api/http-api-router.js | 10 +++++++--- .../request-schema/bid-suggestion-schema.js | 16 +++++++++++++-- .../blockchain/blockchain-module-manager.js | 18 +++++++++++++++++ .../blockchain/implementation/web3-service.js | 20 +++++++++++++++++++ 5 files changed, 75 insertions(+), 5 deletions(-) diff --git a/src/controllers/http-api/bid-suggestion-http-api-controller.js b/src/controllers/http-api/bid-suggestion-http-api-controller.js index bffaf6be9c..6143d33240 100644 --- a/src/controllers/http-api/bid-suggestion-http-api-controller.js +++ b/src/controllers/http-api/bid-suggestion-http-api-controller.js @@ -3,10 +3,26 @@ import BaseController from './base-http-api-controller.js'; class BidSuggestionController extends BaseController { constructor(ctx) { super(ctx); + this.blockchainModuleManager = ctx.blockchainModuleManager; this.shardingTableService = ctx.shardingTableService; } async handleBidSuggestionRequest(req, res) { + if ( + !(await this.blockchainModuleManager.isAssetStorageContract( + req.query.contentAssetStorageAddress, + )) + ) + this.returnResponse(res, 400, { + code: 400, + message: `Invalid Content Asset Storage Contract Address`, + }); + if (!(await this.blockchainModuleManager.isHashFunction(req.query.hashFunctionId))) + this.returnResponse(res, 400, { + code: 400, + message: `Invalid Hash Function ID`, + }); + const { blockchain, epochsNumber, diff --git a/src/controllers/http-api/http-api-router.js b/src/controllers/http-api/http-api-router.js index 49d9127355..d82b0468fa 100644 --- a/src/controllers/http-api/http-api-router.js +++ b/src/controllers/http-api/http-api-router.js @@ -53,9 +53,13 @@ class HttpApiRouter { this.infoHttpApiController.handleInfoRequest(req, res); }); - this.httpClientModuleManager.get('/bid-suggestion', (req, res) => { - this.bidSuggestionHttpApiController.handleBidSuggestionRequest(req, res); - }); + this.httpClientModuleManager.get( + '/bid-suggestion', + (req, res) => { + this.bidSuggestionHttpApiController.handleBidSuggestionRequest(req, res); + }, + { requestSchema: this.jsonSchemaService.bidSuggestionSchema() }, + ); } async initializeBeforeMiddlewares() { diff --git a/src/controllers/http-api/request-schema/bid-suggestion-schema.js b/src/controllers/http-api/request-schema/bid-suggestion-schema.js index 256d234557..40e97fea1d 100644 --- a/src/controllers/http-api/request-schema/bid-suggestion-schema.js +++ b/src/controllers/http-api/request-schema/bid-suggestion-schema.js @@ -7,11 +7,23 @@ export default (blockchainImplementationNames) => ({ }, epochsNumber: { type: 'integer', - minimum: 0, + minimum: 1, }, assertionSize: { type: 'integer', - minimum: 0, + minimum: 1, + }, + contentAssetStorageAddress: { + type: 'string', + length: 42, + }, + firstAssertionId: { + type: 'string', + length: 66, + }, + hashFunctionId: { + type: 'integer', + minimum: 1, }, }, }); diff --git a/src/modules/blockchain/blockchain-module-manager.js b/src/modules/blockchain/blockchain-module-manager.js index 032cdf599a..945d055730 100644 --- a/src/modules/blockchain/blockchain-module-manager.js +++ b/src/modules/blockchain/blockchain-module-manager.js @@ -25,6 +25,16 @@ class BlockchainModuleManager extends BaseModuleManager { return this.callImplementationFunction(blockchain, 'getManagementKey'); } + async isHubContract(blockchain, contractAddress) { + return this.callImplementationFunction(blockchain, 'isHubContract', [contractAddress]); + } + + async isAssetStorageContract(blockchain, contractAddress) { + return this.callImplementationFunction(blockchain, 'isAssetStorageContract', [ + contractAddress, + ]); + } + async getIdentityId(blockchain) { return this.callImplementationFunction(blockchain, 'getIdentityId'); } @@ -225,6 +235,14 @@ class BlockchainModuleManager extends BaseModuleManager { return this.callImplementationFunction(blockchain, 'getProofWindowDurationPerc'); } + async isHashFunction(blockchain, hashFunctionId) { + return this.callImplementationFunction(blockchain, 'isHashFunction', [hashFunctionId]); + } + + async isScoreFunction(blockchain, scoreFunctionId) { + return this.callImplementationFunction(blockchain, 'isScoreFunction', [scoreFunctionId]); + } + async callScoreFunction(blockchain, scoreFunctionId, hashFunctionId, peerId, keyword, stake) { return this.callImplementationFunction(blockchain, 'callScoreFunction', [ scoreFunctionId, diff --git a/src/modules/blockchain/implementation/web3-service.js b/src/modules/blockchain/implementation/web3-service.js index d36c3b41fe..c6dfacd916 100644 --- a/src/modules/blockchain/implementation/web3-service.js +++ b/src/modules/blockchain/implementation/web3-service.js @@ -520,6 +520,14 @@ class Web3Service { return timestamp < timestampThirtyDaysInPast; } + async isHubContract(contractAddress) { + return this.callContractFunction(this.hubContract, 'isContract', [contractAddress]); + } + + async isAssetStorageContract(contractAddress) { + return this.callContractFunction(this.hubContract, 'isAssetStorage', [contractAddress]); + } + async getAssertionIdByIndex(assetContractAddress, tokenId, index) { return this.callContractFunction( this.assetStorageContracts[assetContractAddress.toLowerCase()], @@ -755,6 +763,18 @@ class Web3Service { ); } + async isHashFunction(hashFunctionId) { + return this.callContractFunction(this.HashingProxyContract, 'isHashFunction', [ + hashFunctionId, + ]); + } + + async isScoreFunction(scoreFunctionId) { + return this.callContractFunction(this.ScoringProxyContract, 'isScoreFunction', [ + scoreFunctionId, + ]); + } + async callScoreFunction(scoreFunctionId, hashFunctionId, peerId, keyword, stake) { return this.callContractFunction(this.ScoringProxyContract, 'callScoreFunction', [ scoreFunctionId, From a1add7b45a29d0236e80235997797e604e741b35 Mon Sep 17 00:00:00 2001 From: Uladzislau Hubar Date: Mon, 19 Dec 2022 13:02:55 +0100 Subject: [PATCH 07/16] Added missing required params in bid-suggestion schema, commented out overloaded functions --- .../bid-suggestion-http-api-controller.js | 37 +++++++++++-------- .../request-schema/bid-suggestion-schema.js | 15 ++++++-- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/controllers/http-api/bid-suggestion-http-api-controller.js b/src/controllers/http-api/bid-suggestion-http-api-controller.js index 6143d33240..7c65697b0e 100644 --- a/src/controllers/http-api/bid-suggestion-http-api-controller.js +++ b/src/controllers/http-api/bid-suggestion-http-api-controller.js @@ -8,20 +8,27 @@ class BidSuggestionController extends BaseController { } async handleBidSuggestionRequest(req, res) { - if ( - !(await this.blockchainModuleManager.isAssetStorageContract( - req.query.contentAssetStorageAddress, - )) - ) - this.returnResponse(res, 400, { - code: 400, - message: `Invalid Content Asset Storage Contract Address`, - }); - if (!(await this.blockchainModuleManager.isHashFunction(req.query.hashFunctionId))) - this.returnResponse(res, 400, { - code: 400, - message: `Invalid Hash Function ID`, - }); + // Uncomment when switch to ethers.js + // if ( + // !(await this.blockchainModuleManager.isAssetStorageContract( + // req.body.blockchain, + // req.body.contentAssetStorageAddress, + // )) + // ) + // this.returnResponse(res, 400, { + // code: 400, + // message: `Invalid Content Asset Storage Contract Address`, + // }); + // if ( + // !(await this.blockchainModuleManager.isHashFunction( + // req.body.blockchain, + // req.body.hashFunctionId, + // )) + // ) + // this.returnResponse(res, 400, { + // code: 400, + // message: `Invalid Hash Function ID`, + // }); const { blockchain, @@ -30,7 +37,7 @@ class BidSuggestionController extends BaseController { contentAssetStorageAddress, firstAssertionId, hashFunctionId, - } = req.query; + } = req.body; this.returnResponse(res, 200, { bidSuggestion: await this.shardingTableService.getBidSuggestion( diff --git a/src/controllers/http-api/request-schema/bid-suggestion-schema.js b/src/controllers/http-api/request-schema/bid-suggestion-schema.js index 40e97fea1d..0a2d5a94a6 100644 --- a/src/controllers/http-api/request-schema/bid-suggestion-schema.js +++ b/src/controllers/http-api/request-schema/bid-suggestion-schema.js @@ -1,6 +1,13 @@ export default (blockchainImplementationNames) => ({ type: 'object', - required: ['blockchain', 'epochsNumber', 'assertionSize'], + required: [ + 'blockchain', + 'epochsNumber', + 'assertionSize', + 'contentAssetStorageAddress', + 'firstAssertionId', + 'hashFunctionId', + ], properties: { blockchain: { enum: blockchainImplementationNames, @@ -15,11 +22,13 @@ export default (blockchainImplementationNames) => ({ }, contentAssetStorageAddress: { type: 'string', - length: 42, + minLength: 42, + maxLength: 42, }, firstAssertionId: { type: 'string', - length: 66, + minLength: 66, + maxLength: 66, }, hashFunctionId: { type: 'integer', From 8f25a22aec2a4dced7191e966dbbb10fb592a813 Mon Sep 17 00:00:00 2001 From: Uladzislau Hubar Date: Mon, 19 Dec 2022 14:19:24 +0100 Subject: [PATCH 08/16] Adapted request validation for queries, added pre-validation hook for numbers casting --- .../bid-suggestion-http-api-controller.js | 10 ++++---- .../request-schema/bid-suggestion-schema.js | 6 ++--- .../http-api/request-schema/publish-schema.js | 2 +- .../http-api/request-schema/search-schema.js | 4 +-- .../request-validation-middleware.js | 25 ++++++++++++++++--- 5 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/controllers/http-api/bid-suggestion-http-api-controller.js b/src/controllers/http-api/bid-suggestion-http-api-controller.js index 7c65697b0e..8b126372c3 100644 --- a/src/controllers/http-api/bid-suggestion-http-api-controller.js +++ b/src/controllers/http-api/bid-suggestion-http-api-controller.js @@ -11,8 +11,8 @@ class BidSuggestionController extends BaseController { // Uncomment when switch to ethers.js // if ( // !(await this.blockchainModuleManager.isAssetStorageContract( - // req.body.blockchain, - // req.body.contentAssetStorageAddress, + // req.query.blockchain, + // req.query.contentAssetStorageAddress, // )) // ) // this.returnResponse(res, 400, { @@ -21,8 +21,8 @@ class BidSuggestionController extends BaseController { // }); // if ( // !(await this.blockchainModuleManager.isHashFunction( - // req.body.blockchain, - // req.body.hashFunctionId, + // req.query.blockchain, + // req.query.hashFunctionId, // )) // ) // this.returnResponse(res, 400, { @@ -37,7 +37,7 @@ class BidSuggestionController extends BaseController { contentAssetStorageAddress, firstAssertionId, hashFunctionId, - } = req.body; + } = req.query; this.returnResponse(res, 200, { bidSuggestion: await this.shardingTableService.getBidSuggestion( diff --git a/src/controllers/http-api/request-schema/bid-suggestion-schema.js b/src/controllers/http-api/request-schema/bid-suggestion-schema.js index 0a2d5a94a6..bdbe527644 100644 --- a/src/controllers/http-api/request-schema/bid-suggestion-schema.js +++ b/src/controllers/http-api/request-schema/bid-suggestion-schema.js @@ -13,11 +13,11 @@ export default (blockchainImplementationNames) => ({ enum: blockchainImplementationNames, }, epochsNumber: { - type: 'integer', + type: 'number', minimum: 1, }, assertionSize: { - type: 'integer', + type: 'number', minimum: 1, }, contentAssetStorageAddress: { @@ -31,7 +31,7 @@ export default (blockchainImplementationNames) => ({ maxLength: 66, }, hashFunctionId: { - type: 'integer', + type: 'number', minimum: 1, }, }, diff --git a/src/controllers/http-api/request-schema/publish-schema.js b/src/controllers/http-api/request-schema/publish-schema.js index 8366876dad..f1ef4f378e 100644 --- a/src/controllers/http-api/request-schema/publish-schema.js +++ b/src/controllers/http-api/request-schema/publish-schema.js @@ -29,7 +29,7 @@ const assertionSchemaRequired = ['assertionId', 'assertion', 'blockchain', 'cont const assetSchemaProperties = (blockchainImplementationNames) => ({ ...assertionSchemaProperties(blockchainImplementationNames), tokenId: { - type: 'integer', + type: 'number', minimum: 0, }, }); diff --git a/src/controllers/http-api/request-schema/search-schema.js b/src/controllers/http-api/request-schema/search-schema.js index bbec2df266..366800b018 100644 --- a/src/controllers/http-api/request-schema/search-schema.js +++ b/src/controllers/http-api/request-schema/search-schema.js @@ -9,11 +9,11 @@ export default () => ({ uniqueItems: true, }, limit: { - type: 'integer', + type: 'number', minimum: 1, }, offset: { - type: 'integer', + type: 'number', minimum: 0, }, }, diff --git a/src/modules/http-client/implementation/middleware/request-validation-middleware.js b/src/modules/http-client/implementation/middleware/request-validation-middleware.js index 5363cb3df9..6a74af9c47 100644 --- a/src/modules/http-client/implementation/middleware/request-validation-middleware.js +++ b/src/modules/http-client/implementation/middleware/request-validation-middleware.js @@ -2,14 +2,33 @@ import { Validator } from 'jsonschema'; const v = new Validator(); +function preValidateProperty(object, key, schema, options, ctx) { + const value = object[key]; + if (typeof value === 'undefined') return; + + // Test if the schema declares a type, but the type keyword fails validation + if ( + schema.type && + v.attributes.type.call(v, value, schema, options, ctx.makeChild(schema, key)) + ) { + // If the type is "number" but the instance is not a number, cast it + if (schema.type === 'number' && typeof value !== 'number') { + // eslint-disable-next-line no-param-reassign + object[key] = parseFloat(value); + } + } +} + export default function requestValidationMiddleware(requestSchema) { return (req, res, next) => { - if (req.get('Content-Type') !== 'application/json') { + let result; + if (req.method === 'GET') + result = v.validate(req.query, requestSchema, { preValidateProperty }); + else if (req.get('Content-Type') !== 'application/json') { res.status(401).send('Invalid header format'); return; - } + } else result = v.validate(req.body, requestSchema); - const result = v.validate(req.body, requestSchema); if (result.errors.length > 0) { res.status(400).json({ status: 'FAILED', From 42b401983157d335d5d8cb65a9263f2805584306 Mon Sep 17 00:00:00 2001 From: Uladzislau Hubar Date: Tue, 20 Dec 2022 13:16:58 +0100 Subject: [PATCH 09/16] Added sharding table size validation for bid-suggestion --- .../http-api/bid-suggestion-http-api-controller.js | 7 +++++++ .../implementation/sequelize/sequelize-repository.js | 8 ++++++++ src/modules/repository/repository-module-manager.js | 6 ++++++ 3 files changed, 21 insertions(+) diff --git a/src/controllers/http-api/bid-suggestion-http-api-controller.js b/src/controllers/http-api/bid-suggestion-http-api-controller.js index 8b126372c3..2bf0967b56 100644 --- a/src/controllers/http-api/bid-suggestion-http-api-controller.js +++ b/src/controllers/http-api/bid-suggestion-http-api-controller.js @@ -3,11 +3,18 @@ import BaseController from './base-http-api-controller.js'; class BidSuggestionController extends BaseController { constructor(ctx) { super(ctx); + this.repositoryModuleManager = ctx.repositoryModuleManager; this.blockchainModuleManager = ctx.blockchainModuleManager; this.shardingTableService = ctx.shardingTableService; } async handleBidSuggestionRequest(req, res) { + if ((await this.repositoryModuleManager.getPeersCount(req.query.blockchain)) === 0) + this.returnResponse(res, 400, { + code: 400, + message: 'Empty Sharding Table', + }); + // Uncomment when switch to ethers.js // if ( // !(await this.blockchainModuleManager.isAssetStorageContract( diff --git a/src/modules/repository/implementation/sequelize/sequelize-repository.js b/src/modules/repository/implementation/sequelize/sequelize-repository.js index 661982e604..66e9ad4d5c 100644 --- a/src/modules/repository/implementation/sequelize/sequelize-repository.js +++ b/src/modules/repository/implementation/sequelize/sequelize-repository.js @@ -307,6 +307,14 @@ class SequelizeRepository { }); } + async getPeersCount(blockchain) { + return this.models.shard.count({ + where: { + blockchain_id: blockchain, + }, + }); + } + async getPeersToDial(limit, dialFrequencyMillis) { return this.models.shard.findAll({ attributes: ['peer_id'], diff --git a/src/modules/repository/repository-module-manager.js b/src/modules/repository/repository-module-manager.js index 999ed22860..8da194c332 100644 --- a/src/modules/repository/repository-module-manager.js +++ b/src/modules/repository/repository-module-manager.js @@ -183,6 +183,12 @@ class RepositoryModuleManager extends BaseModuleManager { } } + async getPeersCount(blockchain) { + if (this.initialized) { + return this.getImplementation().module.getPeersCount(blockchain); + } + } + async getPeersToDial(limit, dialFrequencyMillis) { if (this.initialized) { return this.getImplementation().module.getPeersToDial(limit, dialFrequencyMillis); From 769efb842a43cf0e805bd8f769c8bf07a4814175 Mon Sep 17 00:00:00 2001 From: Djordje Kovacevic Date: Wed, 21 Dec 2022 10:46:12 +0100 Subject: [PATCH 10/16] Updated unit test for get bid suggestion --- .../service/sharding-table-service.test.js | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 test/unit/service/sharding-table-service.test.js diff --git a/test/unit/service/sharding-table-service.test.js b/test/unit/service/sharding-table-service.test.js new file mode 100644 index 0000000000..45f919b0c3 --- /dev/null +++ b/test/unit/service/sharding-table-service.test.js @@ -0,0 +1,154 @@ +import { beforeEach, describe, it } from 'mocha'; +import { ethers } from 'ethers'; +import { expect } from 'chai'; +import ShardingTableService from '../../../src/service/sharding-table-service.js'; + +const testR2 = 20; +const testR0 = 3; + +const testPeers = [ + { + peer_id: 'QmcJY13uLyt2VQ6QiVNcYiWaxdfaHWHj3T7G472uaHPBf7', + blockchain_id: 'ganache', + ask: '0.2824612246520951', + stake: '50000.0', + last_seen: '1970-01-01 00:00:00', + last_dialed: '1970-01-01 00:00:00', + sha256: '0x6e08776479a010d563855dbc371a66f692d3edcbcf2b02c30f9879ebe02244e8', + }, + { + peer_id: 'Qmcxo88zf5zEvyBLYTrtfG8nGJQW6zHpf58b5MUcjoYVqL', + blockchain_id: 'ganache', + ask: '0.11680988694381877', + stake: '50000.0', + last_seen: '1970-01-01 00:00:00', + last_dialed: '1970-01-01 00:00:00', + sha256: '0x113d3da32b0e0b7031d188736792bbea0baf7911acb905511ac7dda2be9a6f55', + }, + { + peer_id: 'QmQeNwBzgeMQxquQEDXvBHqXBHNBEvKHtyHURg4QvnoLrD', + blockchain_id: 'ganache', + ask: '0.25255488168658036', + stake: '50000.0', + last_seen: '1970-01-01 00:00:00', + last_dialed: '1970-01-01 00:00:00', + sha256: '0xba14ac66ab5be40bf458bad9b4e9f10a9d06375b233e91a6ce3c2d4cbf9deea5', + }, + { + peer_id: 'QmU4ty8X8L4Xk6cbDCoyJUhgeBNLDo3HprTGEhNd9CtiT7', + blockchain_id: 'ganache', + ask: '0.25263875217271087', + stake: '50000.0', + last_seen: '1970-01-01 00:00:00', + last_dialed: '1970-01-01 00:00:00', + sha256: '0x5b3fdb88b3270a99cc89d28e0a4504d28789e5f8ca53080aa7608db48546d56b', + }, + { + peer_id: 'QmWmgmMCQQ1awraTeQqwsbWgqtR3ZMuX7NhbHyiftuAspb', + blockchain_id: 'ganache', + ask: '0.2429885059428509', + stake: '50000.0', + last_seen: '1970-01-01 00:00:00', + last_dialed: '1970-01-01 00:00:00', + sha256: '0x820a8e38cb792b89c8b69eb9c192faf3def6175c97c4c0f17708161bcb9c5028', + }, + { + peer_id: 'QmWyf3dtqJnhuCpzEDTNmNFYc5tjxTrXhGcUUmGHdg2gtj', + blockchain_id: 'ganache', + ask: '0.210617584797714', + stake: '50000.0', + last_seen: '1970-01-01 00:00:00', + last_dialed: '1970-01-01 00:00:00', + sha256: '0xf764186e9b675f3fd00af72026cf075d05ce8fc951ba089351d645b363acd3d3', + }, + { + peer_id: 'QmXgeHgBVbd7iyTp8PapUAyeKciqbsXTEvsakCjW7wZRqT', + blockchain_id: 'ganache', + ask: '0.2290449496761527', + stake: '50000.0', + last_seen: '1970-01-01 00:00:00', + last_dialed: '1970-01-01 00:00:00', + sha256: '0xaaeed7b766483aef7cf2d07325f336b3e703e2b7573e540ca8c6e2aab34265c3', + }, + { + peer_id: 'QmYys42KLmGEE9hEmJCVCe3SR3G9zf4epoAwDUK7pVUP6S', + blockchain_id: 'ganache', + ask: '0.1637075464317365', + stake: '50000.0', + last_seen: '1970-01-01 00:00:00', + last_dialed: '1970-01-01 00:00:00', + sha256: '0xc3bb7b5433ebe62ff9e98c6d439223d07d44e16e7d5e210e727823f87c0ef24b', + }, + { + peer_id: 'QmZi2nDhZJfa1Z5iXjvxQ1BigpR8TdTQ3gWQDGecn34e9x', + blockchain_id: 'ganache', + ask: '0.10242295311162795', + stake: '50000.0', + last_seen: '1970-01-01 00:00:00', + last_dialed: '1970-01-01 00:00:00', + sha256: '0x510ca60cdd7b33bf8d978576981ae7f9caaf5f133ddd40693d8ce007614c0a09', + }, + { + peer_id: 'QmZueq5jip24v5dbCSBGt8v16hPjUN1CXRb3zGaxH1jfHM', + blockchain_id: 'ganache', + ask: '0.23374911902136858', + stake: '50000.0', + last_seen: '1970-01-01 00:00:00', + last_dialed: '1970-01-01 00:00:00', + sha256: '0x7b4f717bd647104a72c7f1fce4600366982f36ebb1cef41540a5541c8e8ca1dd', + }, +]; + +const blockchainModuleManagerMock = { + getR2: () => testR2, + getR0: () => testR0, + convertToWei: (blockchainId, value) => + ethers.utils.parseUnits(value.toString(), 'ether').toString(), +}; + +const repositoryModuleManagerMock = { + getAllPeerRecords: () => testPeers, +}; + +const networkModuleManagerMock = {}; + +const validationModuleManagerMock = { + callHashFunction: (data) => { + const bytesLikeData = ethers.utils.toUtf8Bytes(data); + return ethers.utils.sha256(bytesLikeData); + }, + getHashFunctionName: () => 'sha256', +}; + +const eventEmitterMock = {}; +let shardingTableService; + +describe('Sharding table service test', async () => { + beforeEach(() => { + shardingTableService = new ShardingTableService({ + blockchainModuleManager: blockchainModuleManagerMock, + repositoryModuleManager: repositoryModuleManagerMock, + networkModuleManager: networkModuleManagerMock, + validationModuleManager: validationModuleManagerMock, + eventEmitter: eventEmitterMock, + }); + }); + + it('Get bid suggestion, returns bid suggestion successfully', async () => { + const epochsNumber = 5; + const assertionSize = 1024; + const contentAssetStorageAddress = '0xABd59A9aa71847F499d624c492d3903dA953d67a'; + const firstAssertionId = + '0xb44062de45333119471934bc0340c05ff09c0b463392384bc2030cd0a20c334b'; + const hashFunctionId = 1; + const bidSuggestions = await shardingTableService.getBidSuggestion( + 'ganache', + epochsNumber, + assertionSize, + contentAssetStorageAddress, + firstAssertionId, + hashFunctionId, + ); + expect(bidSuggestions).to.be.equal('3788323225298705400'); + }); +}); From 3f45430970c060421634bc9c0d7aef3f4cfe86f3 Mon Sep 17 00:00:00 2001 From: Djordje Kovacevic Date: Wed, 21 Dec 2022 11:11:47 +0100 Subject: [PATCH 11/16] Moved mock classes to separated files --- scripts/set-ask.js | 1 + scripts/set-stake.js | 1 + .../mock/blockchain-module-manager-mock.js | 17 +++ test/unit/mock/event-emitter-mock.js | 3 + test/unit/mock/network-module-manager-mock.js | 3 + .../mock/repository-module-manager-mock.js | 98 +++++++++++++ .../mock/validation-module-manager-mock.js | 14 ++ .../service/sharding-table-service.test.js | 134 ++---------------- 8 files changed, 147 insertions(+), 124 deletions(-) create mode 100644 test/unit/mock/blockchain-module-manager-mock.js create mode 100644 test/unit/mock/event-emitter-mock.js create mode 100644 test/unit/mock/network-module-manager-mock.js create mode 100644 test/unit/mock/repository-module-manager-mock.js create mode 100644 test/unit/mock/validation-module-manager-mock.js diff --git a/scripts/set-ask.js b/scripts/set-ask.js index 445c8c77b0..eae1209a68 100644 --- a/scripts/set-ask.js +++ b/scripts/set-ask.js @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ import { ethers } from 'ethers'; import { createRequire } from 'module'; import validateArguments from './utils.js'; diff --git a/scripts/set-stake.js b/scripts/set-stake.js index 8777b95db0..11a6a931ad 100644 --- a/scripts/set-stake.js +++ b/scripts/set-stake.js @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ import { ethers } from 'ethers'; import { createRequire } from 'module'; import validateArguments from './utils.js'; diff --git a/test/unit/mock/blockchain-module-manager-mock.js b/test/unit/mock/blockchain-module-manager-mock.js new file mode 100644 index 0000000000..60fb5060c3 --- /dev/null +++ b/test/unit/mock/blockchain-module-manager-mock.js @@ -0,0 +1,17 @@ +import { ethers } from 'ethers'; + +class BlockchainModuleManagerMock { + getR2() { + return 20; + } + + getR0() { + return 3; + } + + convertToWei(blockchainId, value) { + return ethers.utils.parseUnits(value.toString(), 'ether').toString(); + } +} + +export default BlockchainModuleManagerMock; diff --git a/test/unit/mock/event-emitter-mock.js b/test/unit/mock/event-emitter-mock.js new file mode 100644 index 0000000000..8a87286212 --- /dev/null +++ b/test/unit/mock/event-emitter-mock.js @@ -0,0 +1,3 @@ +class EventEmitterMock {} + +export default EventEmitterMock; diff --git a/test/unit/mock/network-module-manager-mock.js b/test/unit/mock/network-module-manager-mock.js new file mode 100644 index 0000000000..6c530fa249 --- /dev/null +++ b/test/unit/mock/network-module-manager-mock.js @@ -0,0 +1,3 @@ +class NetworkModuleManagerMock {} + +export default NetworkModuleManagerMock; diff --git a/test/unit/mock/repository-module-manager-mock.js b/test/unit/mock/repository-module-manager-mock.js new file mode 100644 index 0000000000..72db55b47e --- /dev/null +++ b/test/unit/mock/repository-module-manager-mock.js @@ -0,0 +1,98 @@ +class RepositoryModuleManagerMock { + getAllPeerRecords() { + return [ + { + peer_id: 'QmcJY13uLyt2VQ6QiVNcYiWaxdfaHWHj3T7G472uaHPBf7', + blockchain_id: 'ganache', + ask: '0.2824612246520951', + stake: '50000.0', + last_seen: '1970-01-01 00:00:00', + last_dialed: '1970-01-01 00:00:00', + sha256: '0x6e08776479a010d563855dbc371a66f692d3edcbcf2b02c30f9879ebe02244e8', + }, + { + peer_id: 'Qmcxo88zf5zEvyBLYTrtfG8nGJQW6zHpf58b5MUcjoYVqL', + blockchain_id: 'ganache', + ask: '0.11680988694381877', + stake: '50000.0', + last_seen: '1970-01-01 00:00:00', + last_dialed: '1970-01-01 00:00:00', + sha256: '0x113d3da32b0e0b7031d188736792bbea0baf7911acb905511ac7dda2be9a6f55', + }, + { + peer_id: 'QmQeNwBzgeMQxquQEDXvBHqXBHNBEvKHtyHURg4QvnoLrD', + blockchain_id: 'ganache', + ask: '0.25255488168658036', + stake: '50000.0', + last_seen: '1970-01-01 00:00:00', + last_dialed: '1970-01-01 00:00:00', + sha256: '0xba14ac66ab5be40bf458bad9b4e9f10a9d06375b233e91a6ce3c2d4cbf9deea5', + }, + { + peer_id: 'QmU4ty8X8L4Xk6cbDCoyJUhgeBNLDo3HprTGEhNd9CtiT7', + blockchain_id: 'ganache', + ask: '0.25263875217271087', + stake: '50000.0', + last_seen: '1970-01-01 00:00:00', + last_dialed: '1970-01-01 00:00:00', + sha256: '0x5b3fdb88b3270a99cc89d28e0a4504d28789e5f8ca53080aa7608db48546d56b', + }, + { + peer_id: 'QmWmgmMCQQ1awraTeQqwsbWgqtR3ZMuX7NhbHyiftuAspb', + blockchain_id: 'ganache', + ask: '0.2429885059428509', + stake: '50000.0', + last_seen: '1970-01-01 00:00:00', + last_dialed: '1970-01-01 00:00:00', + sha256: '0x820a8e38cb792b89c8b69eb9c192faf3def6175c97c4c0f17708161bcb9c5028', + }, + { + peer_id: 'QmWyf3dtqJnhuCpzEDTNmNFYc5tjxTrXhGcUUmGHdg2gtj', + blockchain_id: 'ganache', + ask: '0.210617584797714', + stake: '50000.0', + last_seen: '1970-01-01 00:00:00', + last_dialed: '1970-01-01 00:00:00', + sha256: '0xf764186e9b675f3fd00af72026cf075d05ce8fc951ba089351d645b363acd3d3', + }, + { + peer_id: 'QmXgeHgBVbd7iyTp8PapUAyeKciqbsXTEvsakCjW7wZRqT', + blockchain_id: 'ganache', + ask: '0.2290449496761527', + stake: '50000.0', + last_seen: '1970-01-01 00:00:00', + last_dialed: '1970-01-01 00:00:00', + sha256: '0xaaeed7b766483aef7cf2d07325f336b3e703e2b7573e540ca8c6e2aab34265c3', + }, + { + peer_id: 'QmYys42KLmGEE9hEmJCVCe3SR3G9zf4epoAwDUK7pVUP6S', + blockchain_id: 'ganache', + ask: '0.1637075464317365', + stake: '50000.0', + last_seen: '1970-01-01 00:00:00', + last_dialed: '1970-01-01 00:00:00', + sha256: '0xc3bb7b5433ebe62ff9e98c6d439223d07d44e16e7d5e210e727823f87c0ef24b', + }, + { + peer_id: 'QmZi2nDhZJfa1Z5iXjvxQ1BigpR8TdTQ3gWQDGecn34e9x', + blockchain_id: 'ganache', + ask: '0.10242295311162795', + stake: '50000.0', + last_seen: '1970-01-01 00:00:00', + last_dialed: '1970-01-01 00:00:00', + sha256: '0x510ca60cdd7b33bf8d978576981ae7f9caaf5f133ddd40693d8ce007614c0a09', + }, + { + peer_id: 'QmZueq5jip24v5dbCSBGt8v16hPjUN1CXRb3zGaxH1jfHM', + blockchain_id: 'ganache', + ask: '0.23374911902136858', + stake: '50000.0', + last_seen: '1970-01-01 00:00:00', + last_dialed: '1970-01-01 00:00:00', + sha256: '0x7b4f717bd647104a72c7f1fce4600366982f36ebb1cef41540a5541c8e8ca1dd', + }, + ]; + } +} + +export default RepositoryModuleManagerMock; diff --git a/test/unit/mock/validation-module-manager-mock.js b/test/unit/mock/validation-module-manager-mock.js new file mode 100644 index 0000000000..d2c4305fca --- /dev/null +++ b/test/unit/mock/validation-module-manager-mock.js @@ -0,0 +1,14 @@ +import { ethers } from 'ethers'; + +class ValidationModuleManagerMock { + callHashFunction(data) { + const bytesLikeData = ethers.utils.toUtf8Bytes(data); + return ethers.utils.sha256(bytesLikeData); + } + + getHashFunctionName() { + return 'sha256'; + } +} + +export default ValidationModuleManagerMock; diff --git a/test/unit/service/sharding-table-service.test.js b/test/unit/service/sharding-table-service.test.js index 45f919b0c3..378f3d675d 100644 --- a/test/unit/service/sharding-table-service.test.js +++ b/test/unit/service/sharding-table-service.test.js @@ -1,136 +1,22 @@ import { beforeEach, describe, it } from 'mocha'; -import { ethers } from 'ethers'; import { expect } from 'chai'; import ShardingTableService from '../../../src/service/sharding-table-service.js'; +import BlockchainModuleManagerMock from '../mock/blockchain-module-manager-mock.js'; +import RepositoryModuleManagerMock from '../mock/repository-module-manager-mock.js'; +import NetworkModuleManagerMock from '../mock/network-module-manager-mock.js'; +import ValidationModuleManagerMock from '../mock/validation-module-manager-mock.js'; +import EventEmitterMock from '../mock/event-emitter-mock.js'; -const testR2 = 20; -const testR0 = 3; - -const testPeers = [ - { - peer_id: 'QmcJY13uLyt2VQ6QiVNcYiWaxdfaHWHj3T7G472uaHPBf7', - blockchain_id: 'ganache', - ask: '0.2824612246520951', - stake: '50000.0', - last_seen: '1970-01-01 00:00:00', - last_dialed: '1970-01-01 00:00:00', - sha256: '0x6e08776479a010d563855dbc371a66f692d3edcbcf2b02c30f9879ebe02244e8', - }, - { - peer_id: 'Qmcxo88zf5zEvyBLYTrtfG8nGJQW6zHpf58b5MUcjoYVqL', - blockchain_id: 'ganache', - ask: '0.11680988694381877', - stake: '50000.0', - last_seen: '1970-01-01 00:00:00', - last_dialed: '1970-01-01 00:00:00', - sha256: '0x113d3da32b0e0b7031d188736792bbea0baf7911acb905511ac7dda2be9a6f55', - }, - { - peer_id: 'QmQeNwBzgeMQxquQEDXvBHqXBHNBEvKHtyHURg4QvnoLrD', - blockchain_id: 'ganache', - ask: '0.25255488168658036', - stake: '50000.0', - last_seen: '1970-01-01 00:00:00', - last_dialed: '1970-01-01 00:00:00', - sha256: '0xba14ac66ab5be40bf458bad9b4e9f10a9d06375b233e91a6ce3c2d4cbf9deea5', - }, - { - peer_id: 'QmU4ty8X8L4Xk6cbDCoyJUhgeBNLDo3HprTGEhNd9CtiT7', - blockchain_id: 'ganache', - ask: '0.25263875217271087', - stake: '50000.0', - last_seen: '1970-01-01 00:00:00', - last_dialed: '1970-01-01 00:00:00', - sha256: '0x5b3fdb88b3270a99cc89d28e0a4504d28789e5f8ca53080aa7608db48546d56b', - }, - { - peer_id: 'QmWmgmMCQQ1awraTeQqwsbWgqtR3ZMuX7NhbHyiftuAspb', - blockchain_id: 'ganache', - ask: '0.2429885059428509', - stake: '50000.0', - last_seen: '1970-01-01 00:00:00', - last_dialed: '1970-01-01 00:00:00', - sha256: '0x820a8e38cb792b89c8b69eb9c192faf3def6175c97c4c0f17708161bcb9c5028', - }, - { - peer_id: 'QmWyf3dtqJnhuCpzEDTNmNFYc5tjxTrXhGcUUmGHdg2gtj', - blockchain_id: 'ganache', - ask: '0.210617584797714', - stake: '50000.0', - last_seen: '1970-01-01 00:00:00', - last_dialed: '1970-01-01 00:00:00', - sha256: '0xf764186e9b675f3fd00af72026cf075d05ce8fc951ba089351d645b363acd3d3', - }, - { - peer_id: 'QmXgeHgBVbd7iyTp8PapUAyeKciqbsXTEvsakCjW7wZRqT', - blockchain_id: 'ganache', - ask: '0.2290449496761527', - stake: '50000.0', - last_seen: '1970-01-01 00:00:00', - last_dialed: '1970-01-01 00:00:00', - sha256: '0xaaeed7b766483aef7cf2d07325f336b3e703e2b7573e540ca8c6e2aab34265c3', - }, - { - peer_id: 'QmYys42KLmGEE9hEmJCVCe3SR3G9zf4epoAwDUK7pVUP6S', - blockchain_id: 'ganache', - ask: '0.1637075464317365', - stake: '50000.0', - last_seen: '1970-01-01 00:00:00', - last_dialed: '1970-01-01 00:00:00', - sha256: '0xc3bb7b5433ebe62ff9e98c6d439223d07d44e16e7d5e210e727823f87c0ef24b', - }, - { - peer_id: 'QmZi2nDhZJfa1Z5iXjvxQ1BigpR8TdTQ3gWQDGecn34e9x', - blockchain_id: 'ganache', - ask: '0.10242295311162795', - stake: '50000.0', - last_seen: '1970-01-01 00:00:00', - last_dialed: '1970-01-01 00:00:00', - sha256: '0x510ca60cdd7b33bf8d978576981ae7f9caaf5f133ddd40693d8ce007614c0a09', - }, - { - peer_id: 'QmZueq5jip24v5dbCSBGt8v16hPjUN1CXRb3zGaxH1jfHM', - blockchain_id: 'ganache', - ask: '0.23374911902136858', - stake: '50000.0', - last_seen: '1970-01-01 00:00:00', - last_dialed: '1970-01-01 00:00:00', - sha256: '0x7b4f717bd647104a72c7f1fce4600366982f36ebb1cef41540a5541c8e8ca1dd', - }, -]; - -const blockchainModuleManagerMock = { - getR2: () => testR2, - getR0: () => testR0, - convertToWei: (blockchainId, value) => - ethers.utils.parseUnits(value.toString(), 'ether').toString(), -}; - -const repositoryModuleManagerMock = { - getAllPeerRecords: () => testPeers, -}; - -const networkModuleManagerMock = {}; - -const validationModuleManagerMock = { - callHashFunction: (data) => { - const bytesLikeData = ethers.utils.toUtf8Bytes(data); - return ethers.utils.sha256(bytesLikeData); - }, - getHashFunctionName: () => 'sha256', -}; - -const eventEmitterMock = {}; let shardingTableService; describe('Sharding table service test', async () => { beforeEach(() => { shardingTableService = new ShardingTableService({ - blockchainModuleManager: blockchainModuleManagerMock, - repositoryModuleManager: repositoryModuleManagerMock, - networkModuleManager: networkModuleManagerMock, - validationModuleManager: validationModuleManagerMock, - eventEmitter: eventEmitterMock, + blockchainModuleManager: new BlockchainModuleManagerMock(), + repositoryModuleManager: new RepositoryModuleManagerMock(), + networkModuleManager: new NetworkModuleManagerMock(), + validationModuleManager: new ValidationModuleManagerMock(), + eventEmitter: new EventEmitterMock(), }); }); From fb3ab3cb831f5415684058ee33aa6c5d652d6992 Mon Sep 17 00:00:00 2001 From: zeroxbt <89495162+zeroxbt@users.noreply.github.com> Date: Wed, 21 Dec 2022 13:16:29 +0100 Subject: [PATCH 12/16] timeout network messages (#2306) * add network message timeouts * add new dependency to dependencies.md * fix error message --- dependencies.md | 6 ++ package-lock.json | 63 ++++++++++++------- package.json | 7 ++- .../common/protocol-message-command.js | 5 ++ .../sender/v1.0.0/v1-0-0-get-init-command.js | 6 +- .../v1.0.0/v1-0-0-get-request-command.js | 10 ++- .../v1.0.0/v1-0-0-publish-init-command.js | 6 +- .../v1.0.0/v1-0-0-publish-request-command.js | 6 +- src/constants/constants.js | 11 ++++ .../network/implementation/libp2p-service.js | 26 +++++++- src/modules/network/network-module-manager.js | 3 +- 11 files changed, 118 insertions(+), 31 deletions(-) diff --git a/dependencies.md b/dependencies.md index 04d5325bed..4e353104b1 100644 --- a/dependencies.md +++ b/dependencies.md @@ -349,6 +349,12 @@ - **version**: ^6.21.4 - **description**: used to communicate with sql repository +##### [timeout-abort-controller](https://www.npmjs.com/package/timeout-abort-controller) + +- **version**: ^3.0.0 +- **description**: timeout network messages + + ##### [multiformats](https://www.npmjs.com/package/multiformats) - **version**: ^9.8.1 diff --git a/package-lock.json b/package-lock.json index 5967335240..10cc985ae2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -64,6 +64,7 @@ "rolling-rate-limiter": "^0.2.13", "semver": "^7.3.7", "sequelize": "^6.21.4", + "timeout-abort-controller": "^3.0.0", "toobusy-js": "^0.5.1", "uint8arrays": "^3.1.0", "umzug": "^3.2.1", @@ -13778,6 +13779,20 @@ "private-ip": "^2.1.1" } }, + "node_modules/libp2p/node_modules/timeout-abort-controller": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/timeout-abort-controller/-/timeout-abort-controller-1.1.1.tgz", + "integrity": "sha512-BsF9i3NAJag6T0ZEjki9j654zoafI2X6ayuNd6Tp8+Ul6Tr5s4jo973qFeiWrRSweqvskC+AHDKUmIW4b7pdhQ==", + "dependencies": { + "abort-controller": "^3.0.0", + "retimer": "^2.0.0" + } + }, + "node_modules/libp2p/node_modules/timeout-abort-controller/node_modules/retimer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/retimer/-/retimer-2.0.0.tgz", + "integrity": "sha512-KLXY85WkEq2V2bKex/LOO1ViXVn2KGYe4PYysAdYdjmraYIUsVkXu8O4am+8+5UbaaGl1qho4aqAAPHNQ4GSbg==" + }, "node_modules/lilconfig": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", @@ -19100,19 +19115,13 @@ } }, "node_modules/timeout-abort-controller": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/timeout-abort-controller/-/timeout-abort-controller-1.1.1.tgz", - "integrity": "sha512-BsF9i3NAJag6T0ZEjki9j654zoafI2X6ayuNd6Tp8+Ul6Tr5s4jo973qFeiWrRSweqvskC+AHDKUmIW4b7pdhQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/timeout-abort-controller/-/timeout-abort-controller-3.0.0.tgz", + "integrity": "sha512-O3e+2B8BKrQxU2YRyEjC/2yFdb33slI22WRdUaDx6rvysfi9anloNZyR2q0l6LnePo5qH7gSM7uZtvvwZbc2yA==", "dependencies": { - "abort-controller": "^3.0.0", - "retimer": "^2.0.0" + "retimer": "^3.0.0" } }, - "node_modules/timeout-abort-controller/node_modules/retimer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/retimer/-/retimer-2.0.0.tgz", - "integrity": "sha512-KLXY85WkEq2V2bKex/LOO1ViXVn2KGYe4PYysAdYdjmraYIUsVkXu8O4am+8+5UbaaGl1qho4aqAAPHNQ4GSbg==" - }, "node_modules/tiny-emitter": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", @@ -31834,6 +31843,24 @@ "varint": "^6.0.0", "wherearewe": "^1.0.0", "xsalsa20": "^1.1.0" + }, + "dependencies": { + "timeout-abort-controller": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/timeout-abort-controller/-/timeout-abort-controller-1.1.1.tgz", + "integrity": "sha512-BsF9i3NAJag6T0ZEjki9j654zoafI2X6ayuNd6Tp8+Ul6Tr5s4jo973qFeiWrRSweqvskC+AHDKUmIW4b7pdhQ==", + "requires": { + "abort-controller": "^3.0.0", + "retimer": "^2.0.0" + }, + "dependencies": { + "retimer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/retimer/-/retimer-2.0.0.tgz", + "integrity": "sha512-KLXY85WkEq2V2bKex/LOO1ViXVn2KGYe4PYysAdYdjmraYIUsVkXu8O4am+8+5UbaaGl1qho4aqAAPHNQ4GSbg==" + } + } + } } }, "libp2p-bootstrap": { @@ -36199,19 +36226,11 @@ "integrity": "sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA==" }, "timeout-abort-controller": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/timeout-abort-controller/-/timeout-abort-controller-1.1.1.tgz", - "integrity": "sha512-BsF9i3NAJag6T0ZEjki9j654zoafI2X6ayuNd6Tp8+Ul6Tr5s4jo973qFeiWrRSweqvskC+AHDKUmIW4b7pdhQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/timeout-abort-controller/-/timeout-abort-controller-3.0.0.tgz", + "integrity": "sha512-O3e+2B8BKrQxU2YRyEjC/2yFdb33slI22WRdUaDx6rvysfi9anloNZyR2q0l6LnePo5qH7gSM7uZtvvwZbc2yA==", "requires": { - "abort-controller": "^3.0.0", - "retimer": "^2.0.0" - }, - "dependencies": { - "retimer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/retimer/-/retimer-2.0.0.tgz", - "integrity": "sha512-KLXY85WkEq2V2bKex/LOO1ViXVn2KGYe4PYysAdYdjmraYIUsVkXu8O4am+8+5UbaaGl1qho4aqAAPHNQ4GSbg==" - } + "retimer": "^3.0.0" } }, "tiny-emitter": { diff --git a/package.json b/package.json index 75a3c30462..9a3fe54761 100644 --- a/package.json +++ b/package.json @@ -65,16 +65,16 @@ "solhint": "^3.3.7" }, "dependencies": { - "assertion-tools": "^2.0.2", - "@polkadot/api": "^9.3.2", - "app-root-path": "^3.1.0", "@comunica/query-sparql": "^2.4.3", "@ethersproject/bytes": "^5.6.1", "@ethersproject/hash": "^5.6.1", "@ethersproject/wallet": "^5.6.2", + "@polkadot/api": "^9.3.2", "@polkadot/keyring": "^10.1.4", "@polkadot/util": "^10.1.4", "@polkadot/util-crypto": "^10.1.4", + "app-root-path": "^3.1.0", + "assertion-tools": "^2.0.2", "async": "^3.2.4", "async-mutex": "^0.3.2", "awilix": "^7.0.3", @@ -120,6 +120,7 @@ "rolling-rate-limiter": "^0.2.13", "semver": "^7.3.7", "sequelize": "^6.21.4", + "timeout-abort-controller": "^3.0.0", "toobusy-js": "^0.5.1", "uint8arrays": "^3.1.0", "umzug": "^3.2.1", diff --git a/src/commands/protocols/common/protocol-message-command.js b/src/commands/protocols/common/protocol-message-command.js index 04534ea3ec..5907dd0554 100644 --- a/src/commands/protocols/common/protocol-message-command.js +++ b/src/commands/protocols/common/protocol-message-command.js @@ -49,6 +49,7 @@ class ProtocolMessageCommand extends Command { operationId, keyword, message, + this.messageTimeout(), ); switch (response.header.messageType) { @@ -67,6 +68,10 @@ class ProtocolMessageCommand extends Command { } } + messageTimeout() { + throw Error('messageTimeout not implemented'); + } + async handleAck(command) { return this.continueSequence(command.data, command.sequence); } diff --git a/src/commands/protocols/get/sender/v1.0.0/v1-0-0-get-init-command.js b/src/commands/protocols/get/sender/v1.0.0/v1-0-0-get-init-command.js index ce27131468..f9e97c7ce3 100644 --- a/src/commands/protocols/get/sender/v1.0.0/v1-0-0-get-init-command.js +++ b/src/commands/protocols/get/sender/v1.0.0/v1-0-0-get-init-command.js @@ -1,5 +1,5 @@ import ProtocolInitCommand from '../../../common/protocol-init-command.js'; -import { ERROR_TYPE } from '../../../../../constants/constants.js'; +import { NETWORK_MESSAGE_TIMEOUT_MILLS, ERROR_TYPE } from '../../../../../constants/constants.js'; class GetInitCommand extends ProtocolInitCommand { constructor(ctx) { @@ -13,6 +13,10 @@ class GetInitCommand extends ProtocolInitCommand { return { assertionId: command.data.assertionId }; } + messageTimeout() { + return NETWORK_MESSAGE_TIMEOUT_MILLS.GET.INIT; + } + /** * Builds default getInitCommand * @param map diff --git a/src/commands/protocols/get/sender/v1.0.0/v1-0-0-get-request-command.js b/src/commands/protocols/get/sender/v1.0.0/v1-0-0-get-request-command.js index a6b51cf031..1935ec383f 100644 --- a/src/commands/protocols/get/sender/v1.0.0/v1-0-0-get-request-command.js +++ b/src/commands/protocols/get/sender/v1.0.0/v1-0-0-get-request-command.js @@ -1,5 +1,9 @@ import ProtocolRequestCommand from '../../../common/protocol-request-command.js'; -import { ERROR_TYPE, OPERATION_REQUEST_STATUS } from '../../../../../constants/constants.js'; +import { + NETWORK_MESSAGE_TIMEOUT_MILLS, + ERROR_TYPE, + OPERATION_REQUEST_STATUS, +} from '../../../../../constants/constants.js'; class GetRequestCommand extends ProtocolRequestCommand { constructor(ctx) { @@ -39,6 +43,10 @@ class GetRequestCommand extends ProtocolRequestCommand { return this.handleNack(command, responseData); } + messageTimeout() { + return NETWORK_MESSAGE_TIMEOUT_MILLS.GET.REQUEST; + } + /** * Builds default getRequest * @param map diff --git a/src/commands/protocols/publish/sender/v1.0.0/v1-0-0-publish-init-command.js b/src/commands/protocols/publish/sender/v1.0.0/v1-0-0-publish-init-command.js index c390d5be88..7cccc8a3e0 100644 --- a/src/commands/protocols/publish/sender/v1.0.0/v1-0-0-publish-init-command.js +++ b/src/commands/protocols/publish/sender/v1.0.0/v1-0-0-publish-init-command.js @@ -1,5 +1,5 @@ import ProtocolInitCommand from '../../../common/protocol-init-command.js'; -import { ERROR_TYPE } from '../../../../../constants/constants.js'; +import { NETWORK_MESSAGE_TIMEOUT_MILLS, ERROR_TYPE } from '../../../../../constants/constants.js'; class PublishInitCommand extends ProtocolInitCommand { constructor(ctx) { @@ -16,6 +16,10 @@ class PublishInitCommand extends ProtocolInitCommand { return { assertionId, blockchain, contract, tokenId, keyword, hashFunctionId }; } + messageTimeout() { + return NETWORK_MESSAGE_TIMEOUT_MILLS.PUBLISH.INIT; + } + /** * Builds default publishInitCommand * @param map diff --git a/src/commands/protocols/publish/sender/v1.0.0/v1-0-0-publish-request-command.js b/src/commands/protocols/publish/sender/v1.0.0/v1-0-0-publish-request-command.js index f5742be8ac..548ed1a0ce 100644 --- a/src/commands/protocols/publish/sender/v1.0.0/v1-0-0-publish-request-command.js +++ b/src/commands/protocols/publish/sender/v1.0.0/v1-0-0-publish-request-command.js @@ -1,5 +1,5 @@ import ProtocolRequestCommand from '../../../common/protocol-request-command.js'; -import { ERROR_TYPE } from '../../../../../constants/constants.js'; +import { NETWORK_MESSAGE_TIMEOUT_MILLS, ERROR_TYPE } from '../../../../../constants/constants.js'; class PublishRequestCommand extends ProtocolRequestCommand { constructor(ctx) { @@ -19,6 +19,10 @@ class PublishRequestCommand extends ProtocolRequestCommand { }; } + messageTimeout() { + return NETWORK_MESSAGE_TIMEOUT_MILLS.PUBLISH.REQUEST; + } + /** * Builds default publishRequestCommand * @param map diff --git a/src/constants/constants.js b/src/constants/constants.js index d60f932afe..77f6262cc9 100644 --- a/src/constants/constants.js +++ b/src/constants/constants.js @@ -135,6 +135,17 @@ export const NETWORK_MESSAGE_TYPES = { }, }; +export const NETWORK_MESSAGE_TIMEOUT_MILLS = { + PUBLISH: { + INIT: 5 * 1000, + REQUEST: 10 * 1000, + }, + GET: { + INIT: 5 * 1000, + REQUEST: 5 * 1000, + }, +}; + export const MAX_OPEN_SESSIONS = 10; export const ERROR_TYPE = { diff --git a/src/modules/network/implementation/libp2p-service.js b/src/modules/network/implementation/libp2p-service.js index a3291f739d..aa536fd19e 100644 --- a/src/modules/network/implementation/libp2p-service.js +++ b/src/modules/network/implementation/libp2p-service.js @@ -15,6 +15,7 @@ import toobusy from 'toobusy-js'; import { v5 as uuidv5 } from 'uuid'; import { mkdir, writeFile, readFile, stat } from 'fs/promises'; import ip from 'ip'; +import { TimeoutController } from 'timeout-abort-controller'; import { NETWORK_API_RATE_LIMIT, NETWORK_API_SPAM_DETECTION, @@ -278,7 +279,7 @@ class Libp2pService { }; } - async sendMessage(protocol, peerId, messageType, operationId, keyword, message) { + async sendMessage(protocol, peerId, messageType, operationId, keyword, message, timeout) { const nackMessage = { header: { messageType: NETWORK_MESSAGE_TYPES.RESPONSES.NACK }, data: { @@ -371,15 +372,37 @@ class Libp2pService { let readResponseStart; let readResponseEnd; let response; + const timeoutController = new TimeoutController(timeout); try { readResponseStart = Date.now(); + + timeoutController.signal.addEventListener( + 'abort', + async () => { + stream.abort(); + response = null; + }, + { once: true }, + ); + response = await this._readMessageFromStream( stream, this.isResponseValid.bind(this), remotePeerId.toB58String(), ); + + if (timeoutController.signal.aborted) { + throw Error('Message timed out!'); + } + + timeoutController.signal.removeEventListener('abort'); + timeoutController.clear(); + readResponseEnd = Date.now(); } catch (error) { + timeoutController.signal.removeEventListener('abort'); + timeoutController.clear(); + readResponseEnd = Date.now(); nackMessage.data.errorMessage = `Unable to read response from peer ${remotePeerId.toB58String()}. protocol: ${protocol}, messageType: ${messageType} , operationId: ${operationId}, execution time: ${ readResponseEnd - readResponseStart @@ -387,6 +410,7 @@ class Libp2pService { return nackMessage; } + this.logger.trace( `Receiving response from ${remotePeerId.toB58String()}. protocol: ${protocol}, messageType: ${ response.message?.header?.messageType diff --git a/src/modules/network/network-module-manager.js b/src/modules/network/network-module-manager.js index b8ac3faee9..6ba254d664 100644 --- a/src/modules/network/network-module-manager.js +++ b/src/modules/network/network-module-manager.js @@ -23,7 +23,7 @@ class NetworkModuleManager extends BaseModuleManager { } } - async sendMessage(protocol, remotePeerId, messageType, operationId, keyword, message) { + async sendMessage(protocol, remotePeerId, messageType, operationId, keyword, message, timeout) { if (this.initialized) { return this.getImplementation().module.sendMessage( protocol, @@ -32,6 +32,7 @@ class NetworkModuleManager extends BaseModuleManager { operationId, keyword, message, + timeout, ); } } From 97d931cef2045c385ebd2312c1541ad037ec4127 Mon Sep 17 00:00:00 2001 From: NZT48 Date: Wed, 21 Dec 2022 17:21:30 +0100 Subject: [PATCH 13/16] Limit hash function to be min and max 1 --- src/controllers/http-api/request-schema/bid-suggestion-schema.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/controllers/http-api/request-schema/bid-suggestion-schema.js b/src/controllers/http-api/request-schema/bid-suggestion-schema.js index bdbe527644..4bf997b84b 100644 --- a/src/controllers/http-api/request-schema/bid-suggestion-schema.js +++ b/src/controllers/http-api/request-schema/bid-suggestion-schema.js @@ -33,6 +33,7 @@ export default (blockchainImplementationNames) => ({ hashFunctionId: { type: 'number', minimum: 1, + maximum: 1, }, }, }); From f805d2fea681b5db8348c60ba161ae70c0b05f37 Mon Sep 17 00:00:00 2001 From: NZT48 Date: Thu, 22 Dec 2022 11:04:52 +0100 Subject: [PATCH 14/16] Increase timeout for libp2p messages --- src/constants/constants.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/constants/constants.js b/src/constants/constants.js index 77f6262cc9..3424dd4bb6 100644 --- a/src/constants/constants.js +++ b/src/constants/constants.js @@ -137,12 +137,12 @@ export const NETWORK_MESSAGE_TYPES = { export const NETWORK_MESSAGE_TIMEOUT_MILLS = { PUBLISH: { - INIT: 5 * 1000, - REQUEST: 10 * 1000, + INIT: 180 * 1000, + REQUEST: 180 * 1000, }, GET: { - INIT: 5 * 1000, - REQUEST: 5 * 1000, + INIT: 180 * 1000, + REQUEST: 180 * 1000, }, }; From f15f2fcfde76ada267bad9da1ca6fed50f176460 Mon Sep 17 00:00:00 2001 From: NZT48 Date: Thu, 22 Dec 2022 11:05:27 +0100 Subject: [PATCH 15/16] Bump version to 6.0.1 --- package-lock.json | 4 ++-- package.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 10cc985ae2..360154398e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "origintrail_node", - "version": "6.0.0", + "version": "6.0.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "origintrail_node", - "version": "6.0.0", + "version": "6.0.1", "license": "ISC", "dependencies": { "@comunica/query-sparql": "^2.4.3", diff --git a/package.json b/package.json index 9a3fe54761..d84ee20e8a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "origintrail_node", - "version": "6.0.0", - "description": "OTNode v6 Beta 2", + "version": "6.0.1", + "description": "OTNode V6", "main": "index.js", "type": "module", "scripts": { From 4ad35ead32062ae78fe407ce935630de56f0a8ba Mon Sep 17 00:00:00 2001 From: NZT48 Date: Thu, 22 Dec 2022 11:09:48 +0100 Subject: [PATCH 16/16] Set timeout to be 1 minute --- src/constants/constants.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/constants/constants.js b/src/constants/constants.js index 3424dd4bb6..5093ee1e5e 100644 --- a/src/constants/constants.js +++ b/src/constants/constants.js @@ -137,12 +137,12 @@ export const NETWORK_MESSAGE_TYPES = { export const NETWORK_MESSAGE_TIMEOUT_MILLS = { PUBLISH: { - INIT: 180 * 1000, - REQUEST: 180 * 1000, + INIT: 60 * 1000, + REQUEST: 60 * 1000, }, GET: { - INIT: 180 * 1000, - REQUEST: 180 * 1000, + INIT: 60 * 1000, + REQUEST: 60 * 1000, }, };