Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
31858fd
wip: getValidationSignature only for authentificated requests
paulo-ocean Feb 4, 2025
91cabf1
add nft update metadata role check
paulo-ocean Feb 5, 2025
0bd615f
fix test, was ok
paulo-ocean Feb 6, 2025
1c537e8
Merge branch 'main' into issue-816-validateddo-signature
paulo-ocean Feb 14, 2025
f80a946
fix logic + check also acess list + refactor + utils function
paulo-ocean Feb 18, 2025
2559251
add ci env var + fix var name on comments
paulo-ocean Feb 18, 2025
7c21109
change cli branch due to AUTHORIZED_PUBLISHERS
paulo-ocean Feb 18, 2025
bb6de36
add address used on the CLI consume flow, for AUTHORIZED_PUBLISHERS
paulo-ocean Feb 18, 2025
76023a4
change response, 200 but no signature
paulo-ocean Feb 18, 2025
78f653d
add some comments to check
paulo-ocean Feb 18, 2025
8a3bde5
add support for other parameters on validate ddo
paulo-ocean Feb 19, 2025
490c68c
add support for other parameters on validate ddo
paulo-ocean Feb 19, 2025
5887f27
Merge branch 'main' into issue-816-validateddo-signature
paulo-ocean Feb 21, 2025
beba63a
add changes to validate ddo publishers
paulo-ocean Feb 24, 2025
d7b66af
merge main & fix conflicts
paulo-ocean Mar 10, 2025
a288516
Merge branch 'main' into issue-816-validateddo-signature
paulo-ocean Mar 19, 2025
4e5694f
update decrypters list
paulo-ocean Mar 19, 2025
d9b36cb
try update tsx version
paulo-ocean Mar 19, 2025
1dd765b
fix pack lock
paulo-ocean Mar 19, 2025
edea714
fix lint
paulo-ocean Mar 19, 2025
faca4c0
update dep
paulo-ocean Mar 19, 2025
eae0dbc
fix ddo nft
paulo-ocean Mar 19, 2025
94c230e
fix lint
paulo-ocean Mar 19, 2025
2ef3ba4
merge main and fix conflicts
paulo-ocean Mar 20, 2025
5f6e11b
merge main & fix conflicts
paulo-ocean Mar 24, 2025
c5d8feb
do a try with open pr
paulo-ocean Mar 24, 2025
6d10b9b
fix lint
paulo-ocean Mar 24, 2025
2d7587e
put back main ref
paulo-ocean Mar 24, 2025
a09fab2
remove unneeded dep
paulo-ocean Mar 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,11 @@ jobs:
DB_URL: 'http://localhost:9200'
FEE_TOKENS: '{ "1": "0x967da4048cD07aB37855c090aAF366e4ce1b9F48", "137": "0x282d8efCe846A88B159800bd4130ad77443Fa1A1", "80001": "0xd8992Ed72C445c35Cb4A2be468568Ed1079357c8", "56": "0xDCe07662CA8EbC241316a15B611c89711414Dd1a" }'
FEE_AMOUNT: '{ "amount": 1, "unit": "MB" }'
AUTHORIZED_DECRYPTERS: '["0xe2DD09d719Da89e5a3D0F2549c7E24566e947260"]'
AUTHORIZED_DECRYPTERS: '["0xe2DD09d719Da89e5a3D0F2549c7E24566e947260","0x529043886F21D9bc1AE0feDb751e34265a246e47"]'
P2P_ENABLE_UPNP: 'false'
P2P_ENABLE_AUTONAT: 'false'
ALLOWED_ADMINS: '["0xe2DD09d719Da89e5a3D0F2549c7E24566e947260"]'
AUTHORIZED_PUBLISHERS: '["0xe2DD09d719Da89e5a3D0F2549c7E24566e947260","0x529043886F21D9bc1AE0feDb751e34265a246e47"]'
DB_TYPE: 'elasticsearch'
MAX_REQ_PER_MINUTE: 320
MAX_CONNECTIONS_PER_MINUTE: 320
Expand Down
7 changes: 7 additions & 0 deletions src/@types/DDO/Nft.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,10 @@ export interface Nft {
owner?: string
created?: string
}

export interface NftRoles {
manager: boolean
deployERC20: boolean
updateMetadata: boolean
store: boolean
}
3 changes: 3 additions & 0 deletions src/@types/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ export interface FindDDOCommand extends DDOCommand {
// https://github.com/oceanprotocol/ocean-node/issues/47
export interface ValidateDDOCommand extends Command {
ddo: DDO
publisherAddress?: string
signature?: string
nonce?: string
}

export interface StatusCommand extends Command {
Expand Down
142 changes: 137 additions & 5 deletions src/components/core/handler/ddoHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@
} from '../utils/findDdoHandler.js'
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
import { GENERIC_EMOJIS, LOG_LEVELS_STR } from '../../../utils/logging/Logger.js'
import { sleep, readStream } from '../../../utils/util.js'
import { sleep, readStream, isDefined } from '../../../utils/util.js'
import { DDO } from '../../../@types/DDO/DDO.js'
import { CORE_LOGGER } from '../../../utils/logging/common.js'
import { Blockchain } from '../../../utils/blockchain.js'
import { Blockchain, getBlockchainHandler } from '../../../utils/blockchain.js'
import { ethers, isAddress } from 'ethers'
import ERC721Template from '@oceanprotocol/contracts/artifacts/contracts/templates/ERC721Template.sol/ERC721Template.json' assert { type: 'json' }
import AccessListContract from '@oceanprotocol/contracts/artifacts/contracts/accesslists/AccessList.sol/AccessList.json' assert { type: 'json' }
// import lzma from 'lzma-native'
import lzmajs from 'lzma-purejs-requirejs'
import {
getNftPermissions,
getValidationSignature,
makeDid,
validateObject
Expand All @@ -43,6 +44,11 @@
getNetworkHeight,
wasNFTDeployedByOurFactory
} from '../../Indexer/utils.js'
import { checkNonce } from '../utils/nonceHandler.js'
import {
checkCredentialOnAccessList,
existsAccessListConfigurationForChain
} from '../../../utils/credentials.js'
import { deleteIndexedMetadataIfExists, validateDDOHash } from '../../../utils/asset.js'

const MAX_NUM_PROVIDERS = 5
Expand Down Expand Up @@ -282,7 +288,7 @@
try {
encryptedDocument = ethers.getBytes(task.encryptedDocument)
flags = Number(task.flags)
documentHash = task.documentHash

Check warning on line 291 in src/components/core/handler/ddoHandler.ts

View workflow job for this annotation

GitHub Actions / lint

Use object destructuring
} catch (error) {
CORE_LOGGER.logMessage(`Decrypt DDO: error ${error}`, true)
return {
Expand Down Expand Up @@ -852,10 +858,136 @@
status: { httpStatus: 400, error: `Validation error: ${validation[1]}` }
}
}
const signature = await getValidationSignature(JSON.stringify(task.ddo))

// command contains optional parameter publisherAddress
// command contains optional parameter nonce and nonce is valid for publisherAddress
// command contains optional parameter signature which is the signed message based on nonce by publisherAddress
// ddo.nftAddress exists and it's valid (done above on validateObject())
// publisherAddress has updateMetadata role on ddo.nftAddress contract
// publisherAddress has publishing rights on this node (see #815) (TODO needs other PR merged first)

if (task.publisherAddress && task.nonce && task.signature) {
const nonceDB = this.getOceanNode().getDatabase().nonce
const nonceValid = await checkNonce(
nonceDB,
task.publisherAddress,
Number(task.nonce),
task.signature,
task.ddo.id + task.nonce
)

if (!nonceValid.valid) {
// BAD NONCE OR SIGNATURE
return {
stream: null,
status: { httpStatus: 403, error: 'Invalid nonce' }
}
}

const chain = String(task.ddo.chainId)
// has publishing rights on this node?
const { authorizedPublishers, authorizedPublishersList, supportedNetworks } =
await getConfiguration()
const validChain = isDefined(supportedNetworks[chain])
// first check if chain is valid
if (validChain) {
const blockChain = getBlockchainHandler(supportedNetworks[chain])

// check also NFT permissions
const hasUpdateMetadataPermissions = await (
await getNftPermissions(
blockChain.getSigner(),
task.ddo.nftAddress,
ERC721Template.abi,
task.publisherAddress
)
).updateMetadata
console.log('hasUpdateMetadataPermissions:', hasUpdateMetadataPermissions)

if (!hasUpdateMetadataPermissions) {
// Has no update metadata permissions
return {
stream: null,
status: {
httpStatus: 400,
error: `Validation error: Publisher: ${task.publisherAddress} does not have "updateMetadata" permissions`
}
}
}

let hasPublisherRights = false

// 1 ) check if publisher address is part of AUTHORIZED_PUBLISHERS
const isAuthorizedPublisher =
authorizedPublishers.length > 0 &&
authorizedPublishers.filter(
(publisher) =>
publisher.toLowerCase() === task.publisherAddress.toLowerCase()
).length > 0

if (isAuthorizedPublisher) {
hasPublisherRights = true
} else {
// 2 ) check if there is an access list for this chain: AUTHORIZED_PUBLISHERS_LIST
const existsAccessList = existsAccessListConfigurationForChain(
authorizedPublishersList,
chain
)
if (existsAccessList) {
// check access list contracts
hasPublisherRights = await checkCredentialOnAccessList(
authorizedPublishersList,
chain,
task.publisherAddress,
await blockChain.getSigner()
)
}
}

if (!hasPublisherRights) {
return {
stream: null,
status: {
httpStatus: 400,
error: `Validation error: publisher address is invalid for this node`
}
}
}
} else {
// the chain is not supported, so we can't validate on this node
return {
stream: null,
status: {
httpStatus: 400,
error: `Validation error: DDO chain is invalid for this node`
}
}
}

// ALL GOOD - ADD SIGNATURE
const signature = await getValidationSignature(JSON.stringify(task.ddo))
return {
stream: Readable.from(JSON.stringify(signature)),
status: { httpStatus: 200 }
}
}
// Missing signature, nonce or publisher address
// DDO is a valid object, but we cannot verify the signatures
// const msg =
// 'Partial validation: DDO is valid, but none of "publisher address", "signature" or "nonce" are present. Cannot add validation signature'
// return {
// stream: Readable.from(JSON.stringify(msg)),
// status: {
// httpStatus: 200,
// error: msg
// }
// }
return {
stream: Readable.from(JSON.stringify(signature)),
status: { httpStatus: 200 }
stream: null,
status: {
httpStatus: 400,
error: `Validation error: Either publisher address is missing or there is an invalid signature/nonce`
}
}
} catch (error) {
CORE_LOGGER.logMessageWithEmoji(
Expand Down
Loading
Loading