diff --git a/config/config.json b/config/config.json index 2c5e22ba1..462f60200 100644 --- a/config/config.json +++ b/config/config.json @@ -487,7 +487,7 @@ "enabled": false, "package": "./blockchain/implementation/ot-parachain/ot-parachain-service.js", "config": { - "hubContractAddress": "0x94cb4Ce3C6ce3654b0dA47255a2325322DaD5552", + "hubContractAddress": "0xd7d073b560412c6A7F33dD670d323D01061E5DEb", "rpcEndpoints": [ "https://lofar-testnet.origin-trail.network", "https://lofar-testnet.origintrail.network" @@ -500,7 +500,7 @@ "package": "./blockchain/implementation/gnosis/gnosis-service.js", "config": { - "hubContractAddress": "0xC2d165484ee044aFCD0F693a84Ae57235FD986fA", + "hubContractAddress": "0x2c08AC4B630c009F709521e56Ac385A6af70650f", "gasPriceOracleLink": "https://blockscout.chiadochain.net/api/v1/gas-price-oracle", "rpcEndpoints": ["https://rpc.chiadochain.net"], "operatorFee": 0 @@ -511,7 +511,7 @@ "package": "./blockchain/implementation/base/base-service.js", "config": { - "hubContractAddress": "0x4A0aC589D7469868ff4EC889aa2c7eE43d30d823", + "hubContractAddress": "0xf21CE8f8b01548D97DCFb36869f1ccB0814a4e05", "rpcEndpoints": ["https://sepolia.base.org"], "operatorFee": 0 } @@ -579,9 +579,9 @@ "gnosis:10200": ["https://rpc.chiadochain.net"] }, "hubContractAddress": { - "base:84532": "0x4A0aC589D7469868ff4EC889aa2c7eE43d30d823", - "otp:20430": "0x94cb4Ce3C6ce3654b0dA47255a2325322DaD5552", - "gnosis:10200": "0xC2d165484ee044aFCD0F693a84Ae57235FD986fA" + "base:84532": "0xf21CE8f8b01548D97DCFb36869f1ccB0814a4e05", + "otp:20430": "0xd7d073b560412c6A7F33dD670d323D01061E5DEb", + "gnosis:10200": "0x2c08AC4B630c009F709521e56Ac385A6af70650f" } } } diff --git a/package-lock.json b/package-lock.json index f1642657b..6111184b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "origintrail_node", - "version": "8.0.0-sigma.17", + "version": "8.0.0-sigma.18", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "origintrail_node", - "version": "8.0.0-sigma.17", + "version": "8.0.0-sigma.18", "license": "ISC", "dependencies": { "@comunica/query-sparql": "^2.4.3", @@ -26,7 +26,7 @@ "axios": "^1.6.0", "cors": "^2.8.5", "deep-extend": "^0.6.0", - "dkg-evm-module": "^8.0.0-sigma.3", + "dkg-evm-module": "^8.0.0-sigma.5", "dotenv": "^16.0.1", "ethers": "^5.7.2", "express": "^4.18.1", @@ -9334,9 +9334,9 @@ } }, "node_modules/dkg-evm-module": { - "version": "8.0.0-sigma.3", - "resolved": "https://registry.npmjs.org/dkg-evm-module/-/dkg-evm-module-8.0.0-sigma.3.tgz", - "integrity": "sha512-32vhPrSwzSZt2cG3j5nf3y0Cu3QhMhanc7DeoXQ2e5VGKLVlA3yuNGw5e1zm0z3kQputYzNJaeznBFu13tDRwQ==", + "version": "8.0.0-sigma.5", + "resolved": "https://registry.npmjs.org/dkg-evm-module/-/dkg-evm-module-8.0.0-sigma.5.tgz", + "integrity": "sha512-oae/r41PDsBEkm/VX8j7HJh7Z27AEGrjfUM31gw8+3Vwttk+mz6xFABpGaF0zYegTJLrDOfkFzPZDSDRSNsNYg==", "dependencies": { "@openzeppelin/contracts": "^5.1.0", "@polkadot/api": "^15.0.2", @@ -31753,9 +31753,9 @@ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" }, "dkg-evm-module": { - "version": "8.0.0-sigma.3", - "resolved": "https://registry.npmjs.org/dkg-evm-module/-/dkg-evm-module-8.0.0-sigma.3.tgz", - "integrity": "sha512-32vhPrSwzSZt2cG3j5nf3y0Cu3QhMhanc7DeoXQ2e5VGKLVlA3yuNGw5e1zm0z3kQputYzNJaeznBFu13tDRwQ==", + "version": "8.0.0-sigma.5", + "resolved": "https://registry.npmjs.org/dkg-evm-module/-/dkg-evm-module-8.0.0-sigma.5.tgz", + "integrity": "sha512-oae/r41PDsBEkm/VX8j7HJh7Z27AEGrjfUM31gw8+3Vwttk+mz6xFABpGaF0zYegTJLrDOfkFzPZDSDRSNsNYg==", "requires": { "@openzeppelin/contracts": "^5.1.0", "@polkadot/api": "^15.0.2", diff --git a/package.json b/package.json index 8e3cd5e0a..6a5db1480 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "origintrail_node", - "version": "8.0.0-sigma.17", + "version": "8.0.0-sigma.18", "description": "OTNode V8", "main": "index.js", "type": "module", @@ -81,7 +81,7 @@ "axios": "^1.6.0", "cors": "^2.8.5", "deep-extend": "^0.6.0", - "dkg-evm-module": "^8.0.0-sigma.3", + "dkg-evm-module": "^8.0.0-sigma.5", "dotenv": "^16.0.1", "ethers": "^5.7.2", "express": "^4.18.1", diff --git a/src/commands/protocols/get/receiver/v1.0.0/v1-0-0-handle-get-request-command.js b/src/commands/protocols/get/receiver/v1.0.0/v1-0-0-handle-get-request-command.js index 09189febe..6d4efc513 100644 --- a/src/commands/protocols/get/receiver/v1.0.0/v1-0-0-handle-get-request-command.js +++ b/src/commands/protocols/get/receiver/v1.0.0/v1-0-0-handle-get-request-command.js @@ -110,18 +110,18 @@ class HandleGetRequestCommand extends HandleProtocolMessageCommand { let assertionPromise; - if (isOperationV0) { - if (!assertionId) { - assertionId = await this.tripleStoreService.getLatestAssertionId( - TRIPLE_STORE_REPOSITORIES.PUBLIC_CURRENT, - ual, - ); - - this.logger.info( - `Found assertion id: ${assertionId}, operation id ${operationId}, ual: ${ual}`, - ); - } + if (!assertionId) { + assertionId = await this.tripleStoreService.getLatestAssertionId( + TRIPLE_STORE_REPOSITORIES.PUBLIC_CURRENT, + ual, + ); + + this.logger.info( + `Found assertion id: ${assertionId}, operation id ${operationId}, ual: ${ual}`, + ); + } + if (assertionId) { // DO NOT RUN THIS IF !assertionId assertionPromise = this.tripleStoreService .getV6Assertion(TRIPLE_STORE_REPOSITORIES.PUBLIC_CURRENT, assertionId) @@ -145,10 +145,7 @@ class HandleGetRequestCommand extends HandleProtocolMessageCommand { blockchain, ); - return [ - ...(fallbackResult.public ?? []), - ...(fallbackResult.private ?? []), - ]; + return fallbackResult; } this.operationIdService.emitChangeEvent( @@ -161,11 +158,21 @@ class HandleGetRequestCommand extends HandleProtocolMessageCommand { }); } else { if (!knowledgeAssetId) { - knowledgeAssetId = await this.blockchainModuleManager.getKnowledgeAssetsRange( - blockchain, - contract, - knowledgeCollectionId, - ); + try { + knowledgeAssetId = await this.blockchainModuleManager.getKnowledgeAssetsRange( + blockchain, + contract, + knowledgeCollectionId, + ); + } catch (error) { + // Asset created on old content asset storage contract + // TODO: actually it could be other error so we should check that, or add try catch to getKARange function + knowledgeAssetId = { + startTokenId: 1, + endTokenId: 1, + burned: [], + }; + } } assertionPromise = this.tripleStoreService .getAssertion( @@ -208,7 +215,9 @@ class HandleGetRequestCommand extends HandleProtocolMessageCommand { const [assertion, metadata] = await Promise.all(promises); const responseData = { - assertion, + assertion: isOperationV0 + ? [...(assertion.public ?? []), ...(assertion.private ?? [])] + : assertion, ...(includeMetadata && metadata && { metadata }), }; diff --git a/src/commands/protocols/get/sender/get-find-shard-command.js b/src/commands/protocols/get/sender/get-find-shard-command.js index 409f50452..f3f0e5842 100644 --- a/src/commands/protocols/get/sender/get-find-shard-command.js +++ b/src/commands/protocols/get/sender/get-find-shard-command.js @@ -22,10 +22,7 @@ class GetFindShardCommand extends FindShardCommand { getOperationCommandSequence(nodePartOfShard, commandData) { const sequence = []; if (nodePartOfShard) { - // If operationV0 and no assertionId found go directly to networkGet - if (!commandData.isOperationV0 || commandData.assertionId) { - sequence.push('localGetCommand'); - } + sequence.push('localGetCommand'); } sequence.push('networkGetCommand'); diff --git a/src/commands/protocols/get/sender/get-validate-asset-command.js b/src/commands/protocols/get/sender/get-validate-asset-command.js index 67a75d61f..1b5423490 100644 --- a/src/commands/protocols/get/sender/get-validate-asset-command.js +++ b/src/commands/protocols/get/sender/get-validate-asset-command.js @@ -53,6 +53,7 @@ class GetValidateAssetCommand extends ValidateAssetCommand { blockchain, ); // TODO: Update to validate knowledge asset index + // TODO: Use isOldContract as variable and pass it through with command.data since it's used if ( !isOperationV0 && Object.values(OLD_CONTENT_STORAGE_MAP).every( diff --git a/src/commands/protocols/get/sender/local-get-command.js b/src/commands/protocols/get/sender/local-get-command.js index 39165d0e5..11001d308 100644 --- a/src/commands/protocols/get/sender/local-get-command.js +++ b/src/commands/protocols/get/sender/local-get-command.js @@ -34,6 +34,7 @@ class LocalGetCommand extends Command { knowledgeCollectionId, contentType, assertionId, + isOperationV0, } = command.data; let { knowledgeAssetId } = command.data; await this.operationIdService.updateOperationIdStatus( @@ -140,11 +141,20 @@ class LocalGetCommand extends Command { } else { // TODO: Do this in clean way if (!knowledgeAssetId) { - knowledgeAssetId = await this.blockchainModuleManager.getKnowledgeAssetsRange( - blockchain, - contract, - knowledgeCollectionId, - ); + try { + knowledgeAssetId = await this.blockchainModuleManager.getKnowledgeAssetsRange( + blockchain, + contract, + knowledgeCollectionId, + ); + } catch (error) { + // Asset created on old content asset storage contract + knowledgeAssetId = { + startTokenId: 1, + endTokenId: 1, + burned: [], + }; + } } assertionPromise = this.tripleStoreService .getAssertion( @@ -188,9 +198,12 @@ class LocalGetCommand extends Command { const [assertion, metadata] = await Promise.all(promises); const responseData = { - assertion, + assertion: isOperationV0 + ? [...(assertion?.public ?? []), ...(assertion?.private ?? [])] + : assertion, ...(includeMetadata && metadata && { metadata }), }; + if (assertion?.public?.length || assertion?.private?.length || assertion?.length) { await this.operationService.markOperationAsCompleted( operationId, 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 6cd5d3c24..cf2e0cd52 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 @@ -7,6 +7,7 @@ import { OPERATION_STATUS, OPERATION_ID_STATUS, PRIVATE_HASH_SUBJECT_PREFIX, + OLD_CONTENT_STORAGE_MAP, } from '../../../../../constants/constants.js'; class GetRequestCommand extends ProtocolRequestCommand { @@ -68,7 +69,13 @@ class GetRequestCommand extends ProtocolRequestCommand { } async handleAck(command, responseData) { - const { blockchain, contract, knowledgeCollectionId, knowledgeAssetId } = command.data; + const { blockchain, contract, knowledgeCollectionId, knowledgeAssetId, isOperationV0 } = + command.data; + + const isOldContract = Object.values(OLD_CONTENT_STORAGE_MAP).some((ca) => + ca.toLowerCase().includes(contract.toLowerCase()), + ); + if (responseData?.assertion?.public) { // Only whole collection can be validated not particular KA @@ -92,31 +99,47 @@ class GetRequestCommand extends ProtocolRequestCommand { publicKnowledgeAssetsTriplesGrouped.push( ...kcTools.groupNquadsBySubject(privateHashTriples, true), ); - try { - await this.validationService.validateDatasetOnBlockchain( - publicKnowledgeAssetsTriplesGrouped.map((t) => t.sort()).flat(), - blockchain, - contract, - knowledgeCollectionId, - ); - - // This is added as support when get starts supporting private for curated paranet - // TODO: This needs to be fixed when paranets are introduced - if (responseData.assertion?.private?.length) - await this.validationService.validatePrivateMerkleRoot( - responseData.assertion.public, - responseData.assertion.private, + + if (!isOldContract) { + try { + await this.validationService.validateDatasetOnBlockchain( + publicKnowledgeAssetsTriplesGrouped.map((t) => t.sort()).flat(), + blockchain, + contract, + knowledgeCollectionId, ); - } catch (e) { - return this.handleNack(command, { - errorMessage: e.message, - }); + + // This is added as support when get starts supporting private for curated paranet + // TODO: This needs to be fixed when paranets are introduced + if (responseData.assertion?.private?.length) + await this.validationService.validatePrivateMerkleRoot( + responseData.assertion.public, + responseData.assertion.private, + ); + } catch (e) { + return this.handleNack(command, { + errorMessage: e.message, + }); + } } } + + let updatedResponseData = responseData; + + if (isOperationV0) { + // TODO: Extract converting assertion into one array from the object into 1 function since its used for v0 + const assertion = [ + ...(responseData.assertion?.public ?? []), + ...(responseData.assertion?.private ?? []), + ]; + + updatedResponseData = { ...responseData, assertion }; + } + await this.operationService.processResponse( command, OPERATION_REQUEST_STATUS.COMPLETED, - responseData, + updatedResponseData, ); return ProtocolRequestCommand.empty(); diff --git a/src/controllers/http-api/v0/bid-suggestion-http-api-controller-v0.js b/src/controllers/http-api/v0/bid-suggestion-http-api-controller-v0.js index 252f7eeb6..e70c5d33b 100644 --- a/src/controllers/http-api/v0/bid-suggestion-http-api-controller-v0.js +++ b/src/controllers/http-api/v0/bid-suggestion-http-api-controller-v0.js @@ -10,7 +10,7 @@ class BidSuggestionController extends BaseController { async handleRequest(req, res) { try { - const { blockchain, epochsNumber, assertionSize } = req.body; + const { blockchain, epochsNumber, assertionSize } = req.query; const promises = [ this.blockchainModuleManager.getTimeUntilNextEpoch(blockchain), this.blockchainModuleManager.getEpochLength(blockchain), diff --git a/src/service/publish-service.js b/src/service/publish-service.js index 3c8dfe1f6..a8c2fc269 100644 --- a/src/service/publish-service.js +++ b/src/service/publish-service.js @@ -63,46 +63,57 @@ class PublishService extends OperationService { ); } - // Minimum replication reached, mark in the operational DB + // 1. Check minimum replication reached if (completedNumber === minAckResponses) { this.logger.debug( `Minimum replication ${minAckResponses} reached for operationId: ${operationId}, dataset root: ${datasetRoot}`, ); - await this.repositoryModuleManager.updateMinAcksReached(operationId, true); } - // All requests sent, minimum replication reached, mark as completed - if (leftoverNodes.length === 0 && completedNumber >= minAckResponses) { - await this.markOperationAsCompleted( - operationId, - blockchain, - null, - this.completedStatuses, - ); - this.logResponsesSummary(completedNumber, failedNumber); - } - - // All requests sent, minimum replication not reached, mark as failed - if (leftoverNodes.length === 0 && completedNumber < minAckResponses) { - this.markOperationAsFailed( - operationId, - blockchain, - 'Not replicated to enough nodes!', - this.errorType, - ); - this.logResponsesSummary(completedNumber, failedNumber); - } - - // Not all requests sent, still possible to reach minimum replication, - // schedule requests for leftover nodes - const potentialCompletedNumber = completedNumber + leftoverNodes.length; - if ( - leftoverNodes.length > 0 && - potentialCompletedNumber >= minAckResponses && - (totalResponses - 1) % batchSize === 0 - ) { - await this.scheduleOperationForLeftoverNodes(command.data, leftoverNodes); + // 2. Check if all responses have been received + if (totalResponses === numberOfFoundNodes) { + // 2.1 If minimum replication is reached, mark the operation as completed + if (completedNumber >= minAckResponses) { + await this.markOperationAsCompleted( + operationId, + blockchain, + null, + this.completedStatuses, + ); + this.logResponsesSummary(completedNumber, failedNumber); + } + // 2.2 Otherwise, mark as failed + else { + await this.markOperationAsFailed( + operationId, + blockchain, + 'Not replicated to enough nodes!', + this.errorType, + ); + this.logResponsesSummary(completedNumber, failedNumber); + } + } else { + // 3. Not all responses have arrived yet. + const potentialCompletedNumber = completedNumber + leftoverNodes.length; + const canStillReachMinReplication = potentialCompletedNumber >= minAckResponses; + const canScheduleBatch = (totalResponses - 1) % batchSize === 0; + + // 3.1 Check if minimum replication can still be achieve by scheduling leftover nodes + // (and it's at the end of a batch) + if (leftoverNodes.length > 0 && canStillReachMinReplication && canScheduleBatch) { + await this.scheduleOperationForLeftoverNodes(command.data, leftoverNodes); + } + // 3.2 If minimum replication cannot be reached and it's end of a batch, mark as failed + else if (!canStillReachMinReplication && canScheduleBatch) { + await this.markOperationAsFailed( + operationId, + blockchain, + 'Not replicated to enough nodes!', + this.errorType, + ); + this.logResponsesSummary(completedNumber, failedNumber); + } } }