1
0
mirror of https://github.com/oceanprotocol/ocean.js.git synced 2024-11-26 20:39:05 +01:00

refactor compute (#731)

WARNING! This is a breaking change!

* Refactor compute functions to use a new interface (ComputeAlgorithm) instead of passing 4-5 params to different functions.
* add new test to prevent running a computeJob is both asset/algo are having compute services and they are not served from the same provider

Co-authored-by: Matthias Kretschmann <m@kretschmann.io>
This commit is contained in:
Alex Coseru 2021-04-13 18:34:34 +03:00 committed by GitHub
parent 7f05b8fdb5
commit 39938ec9c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 331 additions and 167 deletions

View File

@ -9,9 +9,12 @@ import {
import Account from './Account' import Account from './Account'
import { SubscribablePromise } from '../utils' import { SubscribablePromise } from '../utils'
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract' import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
import { Output } from './interfaces/ComputeOutput' import {
import { ComputeJob } from './interfaces/ComputeJob' ComputeOutput,
import { ComputeInput } from './interfaces/ComputeInput' ComputeJob,
ComputeInput,
ComputeAlgorithm
} from './interfaces/Compute'
import { Provider } from '../provider/Provider' import { Provider } from '../provider/Provider'
import { SHA256 } from 'crypto-js' import { SHA256 } from 'crypto-js'
@ -109,13 +112,10 @@ export class Compute extends Instantiable {
txId: string, txId: string,
tokenAddress: string, tokenAddress: string,
consumerAccount: Account, consumerAccount: Account,
algorithmDid?: string, algorithm: ComputeAlgorithm,
algorithmMeta?: MetadataAlgorithm, output?: ComputeOutput,
output?: Output,
serviceIndex?: string, serviceIndex?: string,
serviceType?: string, serviceType?: string,
algorithmTransferTxId?: string,
algorithmDataToken?: string,
additionalInputs?: ComputeInput[] additionalInputs?: ComputeInput[]
): Promise<ComputeJob> { ): Promise<ComputeJob> {
output = this.checkOutput(consumerAccount, output) output = this.checkOutput(consumerAccount, output)
@ -128,15 +128,12 @@ export class Compute extends Instantiable {
const computeJobsList = await provider.computeStart( const computeJobsList = await provider.computeStart(
did, did,
consumerAccount, consumerAccount,
algorithmDid, algorithm,
algorithmMeta,
output, output,
txId, txId,
serviceIndex, serviceIndex,
serviceType, serviceType,
tokenAddress, tokenAddress,
algorithmTransferTxId,
algorithmDataToken,
additionalInputs additionalInputs
) )
if (computeJobsList) return computeJobsList[0] as ComputeJob if (computeJobsList) return computeJobsList[0] as ComputeJob
@ -376,7 +373,7 @@ export class Compute extends Instantiable {
* @param {Output} output Output section used for publishing the result. * @param {Output} output Output section used for publishing the result.
* @return {Promise<Output>} Returns output object * @return {Promise<Output>} Returns output object
*/ */
private checkOutput(consumerAccount: Account, output?: Output): Output { private checkOutput(consumerAccount: Account, output?: ComputeOutput): ComputeOutput {
const isDefault = !output || (!output.publishAlgorithmLog && !output.publishOutput) const isDefault = !output || (!output.publishAlgorithmLog && !output.publishOutput)
if (isDefault) { if (isDefault) {
@ -412,31 +409,48 @@ export class Compute extends Instantiable {
public async isOrderable( public async isOrderable(
datasetDid: string, datasetDid: string,
serviceIndex: number, serviceIndex: number,
algorithmDid?: string, algorithm: ComputeAlgorithm
algorithmMeta?: MetadataAlgorithm
): Promise<boolean> { ): Promise<boolean> {
const ddo: DDO = await this.ocean.assets.resolve(datasetDid) const ddo: DDO = await this.ocean.assets.resolve(datasetDid)
const service: Service = ddo.findServiceById(serviceIndex) const service: Service = ddo.findServiceById(serviceIndex)
if (!service) return false if (!service) return false
if (service.type === 'compute') { if (service.type === 'compute') {
if (algorithmMeta) { if (algorithm.meta) {
// check if raw algo is allowed // check if raw algo is allowed
if (service.attributes.main.privacy) if (service.attributes.main.privacy)
if (service.attributes.main.privacy.allowRawAlgorithm) return true if (service.attributes.main.privacy.allowRawAlgorithm) return true
this.logger.error('ERROR: This service does not allow raw algorithm') this.logger.error('ERROR: This service does not allow raw algorithm')
return false return false
} }
if (algorithmDid) { if (algorithm.did) {
// check if both have compute services and then if they are served by the same provider
if (algorithm.serviceIndex) {
const algoDDO: DDO = await this.ocean.assets.resolve(algorithm.did)
const algoService: Service = algoDDO.findServiceById(algorithm.serviceIndex)
if (algoService && algoService.type === 'compute') {
// since both dataset & algo services are compute, we need to check if they are served by the same provider
const algoProvider = await Provider.getInstance(this.instanceConfig)
await algoProvider.setBaseUrl(algoService.serviceEndpoint)
const datasetProvider = await Provider.getInstance(this.instanceConfig)
await datasetProvider.setBaseUrl(service.serviceEndpoint)
if (algoProvider.providerAddress !== datasetProvider.providerAddress) {
this.logger.error(
'ERROR: Both assets with compute service are not served by the same provider'
)
return false
}
}
}
// check if did is in trusted list // check if did is in trusted list
if (service.attributes.main.privacy) { if (service.attributes.main.privacy) {
if (service.attributes.main.privacy.allowAllPublishedAlgorithms) return true if (service.attributes.main.privacy.allowAllPublishedAlgorithms) return true
if (!service.attributes.main.privacy.publisherTrustedAlgorithms) return false if (!service.attributes.main.privacy.publisherTrustedAlgorithms) return false
let algo: publisherTrustedAlgorithm let algo: publisherTrustedAlgorithm
for (algo of service.attributes.main.privacy.publisherTrustedAlgorithms) { for (algo of service.attributes.main.privacy.publisherTrustedAlgorithms) {
if (algo.did === algorithmDid) { if (algo.did === algorithm.did) {
// compute checkusms and compare them // compute checkusms and compare them
const trustedAlgorithm = await this.createPublisherTrustedAlgorithmfromDID( const trustedAlgorithm = await this.createPublisherTrustedAlgorithmfromDID(
algorithmDid algorithm.did
) )
if ( if (
algo.containerSectionChecksum && algo.containerSectionChecksum &&
@ -465,10 +479,11 @@ export class Compute extends Instantiable {
} }
// algorithmDid was not found // algorithmDid was not found
this.logger.error( this.logger.error(
'ERROR: Algorithm ' + algorithmDid + ' is not allowed by ' + datasetDid 'ERROR: Algorithm ' + algorithm.did + ' is not allowed by ' + datasetDid
) )
return false return false
} }
console.error('Algo Index:' + algorithm.serviceIndex)
} }
} }
return true // not a compute asset return true // not a compute asset
@ -480,6 +495,7 @@ export class Compute extends Instantiable {
* @param {string} datasetDid The DID of the dataset asset (of type `dataset`) to run the algorithm on. * @param {string} datasetDid The DID of the dataset asset (of type `dataset`) to run the algorithm on.
* @param {string} serviceIndex The Service index * @param {string} serviceIndex The Service index
* @param {string} algorithmDid The DID of the algorithm asset (of type `algorithm`) to run on the asset. * @param {string} algorithmDid The DID of the algorithm asset (of type `algorithm`) to run on the asset.
* @param {string} algorithmServiceIndex The index of the service in the algorithm
* @param {MetaData} algorithmMeta Metadata about the algorithm being run if `algorithm` is being used. This is ignored when `algorithmDid` is specified. * @param {MetaData} algorithmMeta Metadata about the algorithm being run if `algorithm` is being used. This is ignored when `algorithmDid` is specified.
* @return {Promise<string>} Returns the transaction details * @return {Promise<string>} Returns the transaction details
* *
@ -491,19 +507,13 @@ export class Compute extends Instantiable {
consumerAccount: string, consumerAccount: string,
datasetDid: string, datasetDid: string,
serviceIndex: number, serviceIndex: number,
algorithmDid?: string, algorithm: ComputeAlgorithm,
algorithmMeta?: MetadataAlgorithm,
mpAddress?: string, mpAddress?: string,
computeAddress?: string computeAddress?: string
): SubscribablePromise<OrderProgressStep, string> { ): SubscribablePromise<OrderProgressStep, string> {
return new SubscribablePromise(async (observer) => { return new SubscribablePromise(async (observer) => {
// first check if we can order this // first check if we can order this
const allowed = await this.isOrderable( const allowed = await this.isOrderable(datasetDid, serviceIndex, algorithm)
datasetDid,
serviceIndex,
algorithmDid,
algorithmMeta
)
if (!allowed) return null if (!allowed) return null
const ddo: DDO = await this.ocean.assets.resolve(datasetDid) const ddo: DDO = await this.ocean.assets.resolve(datasetDid)
// const service: Service = ddo.findServiceByType('compute') // const service: Service = ddo.findServiceByType('compute')

View File

@ -0,0 +1,43 @@
import DID from '../DID'
import { Metadata } from '../../ddo/interfaces/Metadata'
import { MetadataAlgorithm } from '../../ddo/interfaces/MetadataAlgorithm'
export interface ComputeJob {
owner: string
did: string
jobId: string
dateCreated: string
dateFinished: string
status: number
statusText: string
algorithmLogUrl: string
resultsUrl: string[]
resultsDid?: DID
}
export interface ComputeOutput {
publishAlgorithmLog?: boolean
publishOutput?: boolean
providerAddress?: string
providerUri?: string
metadata?: Metadata
metadataUri?: string
nodeUri?: string
owner?: string
secretStoreUri?: string
whitelist?: string[]
}
export interface ComputeInput {
documentId: string
serviceId: number
transferTxId?: string
}
export interface ComputeAlgorithm {
did?: string
serviceIndex?: number
meta?: MetadataAlgorithm
transferTxId?: string
dataToken?: string
}

View File

@ -1,5 +0,0 @@
export interface ComputeInput {
documentId: string
transferTxId: string
serviceId: number
}

View File

@ -1,15 +0,0 @@
import DID from '../DID'
export interface ComputeJob {
owner: string
jobId: string
dateCreated: string
dateFinished: string
status: number
statusText: string
algorithmLogUrl: string
resultsUrl: string[]
resultsDid?: DID
inputDID?: string[]
algoDID?: string
}

View File

@ -1,14 +0,0 @@
import { Metadata } from '../../ddo/interfaces/Metadata'
export interface Output {
publishAlgorithmLog?: boolean
publishOutput?: boolean
providerAddress?: string
providerUri?: string
metadata?: Metadata
metadataUri?: string
nodeUri?: string
owner?: string
secretStoreUri?: string
whitelist?: string[]
}

View File

@ -2,9 +2,12 @@ import Account from '../ocean/Account'
import { noZeroX } from '../utils' import { noZeroX } from '../utils'
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract' import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
import { File } from '../ddo/interfaces/File' import { File } from '../ddo/interfaces/File'
import { ComputeJob } from '../ocean/interfaces/ComputeJob' import {
import { ComputeInput } from '../ocean/interfaces/ComputeInput' ComputeJob,
import { Output } from '../ocean/interfaces/ComputeOutput' ComputeInput,
ComputeOutput,
ComputeAlgorithm
} from '../ocean/interfaces/Compute'
import { MetadataAlgorithm } from '../ddo/interfaces/MetadataAlgorithm' import { MetadataAlgorithm } from '../ddo/interfaces/MetadataAlgorithm'
import { Versions } from '../ocean/Versions' import { Versions } from '../ocean/Versions'
import { DDO } from '../ddo/DDO' import { DDO } from '../ddo/DDO'
@ -261,15 +264,12 @@ export class Provider extends Instantiable {
public async computeStart( public async computeStart(
did: string, did: string,
consumerAccount: Account, consumerAccount: Account,
algorithmDid?: string, algorithm: ComputeAlgorithm,
algorithmMeta?: MetadataAlgorithm, output?: ComputeOutput,
output?: Output,
txId?: string, txId?: string,
serviceIndex?: string, serviceIndex?: string,
serviceType?: string, serviceType?: string,
tokenAddress?: string, tokenAddress?: string,
algorithmTransferTxId?: string,
algorithmDataToken?: string,
additionalInputs?: ComputeInput[] additionalInputs?: ComputeInput[]
): Promise<ComputeJob | ComputeJob[]> { ): Promise<ComputeJob | ComputeJob[]> {
const address = consumerAccount.getId() const address = consumerAccount.getId()
@ -285,12 +285,12 @@ export class Provider extends Instantiable {
// continue to construct Provider URL // continue to construct Provider URL
if (output) payload.output = output if (output) payload.output = output
if (algorithmDid) payload.algorithmDid = algorithmDid if (algorithm.did) payload.algorithmDid = algorithm.did
if (algorithmMeta) payload.algorithmMeta = algorithmMeta if (algorithm.meta) payload.algorithmMeta = algorithm.meta
payload.consumerAddress = address payload.consumerAddress = address
if (txId) payload.transferTxId = txId if (txId) payload.transferTxId = txId
if (algorithmTransferTxId) payload.algorithmTransferTxId = algorithmTransferTxId if (algorithm.transferTxId) payload.algorithmTransferTxId = algorithm.transferTxId
if (algorithmDataToken) payload.algorithmDataToken = algorithmDataToken if (algorithm.dataToken) payload.algorithmDataToken = algorithm.dataToken
if (serviceIndex) payload.serviceId = serviceIndex if (serviceIndex) payload.serviceId = serviceIndex

View File

@ -15,7 +15,7 @@ import datatokensTemplate from '@oceanprotocol/contracts/artifacts/DataTokenTemp
import { Account, DDO, Metadata } from '../../src/lib' import { Account, DDO, Metadata } from '../../src/lib'
import { Cluster, Container, Server } from '../../src/ocean/Compute' import { Cluster, Container, Server } from '../../src/ocean/Compute'
import { LoggerInstance } from '../../src/utils' import { LoggerInstance } from '../../src/utils'
import { ComputeInput } from '../../src/ocean/interfaces/ComputeInput' import { ComputeInput, ComputeAlgorithm } from '../../src/ocean/interfaces/Compute'
const web3 = new Web3('http://127.0.0.1:8545') const web3 = new Web3('http://127.0.0.1:8545')
const fetch = require('cross-fetch') const fetch = require('cross-fetch')
@ -68,6 +68,7 @@ describe('Compute flow', () => {
let algorithmAsset: DDO let algorithmAsset: DDO
let algorithmAssetwithCompute: DDO let algorithmAssetwithCompute: DDO
let algorithmAssetRemoteProvider: DDO let algorithmAssetRemoteProvider: DDO
let algorithmAssetRemoteProviderWithCompute: DDO
let contracts: TestContractHandler let contracts: TestContractHandler
let datatoken: DataTokens let datatoken: DataTokens
let tokenAddress: string let tokenAddress: string
@ -77,6 +78,7 @@ describe('Compute flow', () => {
let tokenAddressAlgorithm: string let tokenAddressAlgorithm: string
let tokenAddressAlgorithmwithCompute: string let tokenAddressAlgorithmwithCompute: string
let tokenAddressAlgorithmRemoteProvider: string let tokenAddressAlgorithmRemoteProvider: string
let tokenAddressAlgorithmRemoteProviderWithCompute: string
let tokenAddressAdditional1: string let tokenAddressAdditional1: string
let tokenAddressAdditional2: string let tokenAddressAdditional2: string
let price: string let price: string
@ -207,6 +209,17 @@ describe('Compute flow', () => {
tokenAddressAlgorithmRemoteProvider != null, tokenAddressAlgorithmRemoteProvider != null,
'Creation of tokenAddressAlgorithmRemoteProvider failed' 'Creation of tokenAddressAlgorithmRemoteProvider failed'
) )
tokenAddressAlgorithmRemoteProviderWithCompute = await datatoken.create(
blob,
alice.getId(),
'10000000000',
'RemoteAlgoDTwC',
'RALGDTwC'
)
assert(
tokenAddressAlgorithmRemoteProviderWithCompute != null,
'Creation of tokenAddressAlgorithmRemoteProviderWithCompute failed'
)
tokenAddressAdditional1 = await datatoken.create( tokenAddressAdditional1 = await datatoken.create(
blob, blob,
@ -643,6 +656,82 @@ describe('Compute flow', () => {
) )
}) })
it('should publish an algorithm with a compute service using the 2nd provider', async () => {
const remoteProviderUri = 'http://172.15.0.7:8030'
const algoAssetRemoteProviderWithCompute: Metadata = {
main: {
type: 'algorithm',
name: 'Remote Algorithm',
dateCreated: dateCreated,
author: 'DevOps',
license: 'CC-BY',
files: [
{
url:
'https://raw.githubusercontent.com/oceanprotocol/test-algorithm/master/javascript/algo.js',
contentType: 'text/js',
encoding: 'UTF-8'
}
],
algorithm: {
language: 'js',
format: 'docker-image',
version: '0.1',
container: {
entrypoint: 'node $ALGO',
image: 'node',
tag: '10'
}
}
}
}
const origComputePrivacy = {
allowRawAlgorithm: false,
allowNetworkAccess: false,
allowAllPublishedAlgorithms: false,
publisherTrustedAlgorithms: []
}
const service1 = ocean.compute.createComputeService(
alice,
'1',
dateCreated,
providerAttributes,
origComputePrivacy as ServiceComputePrivacy,
3600,
remoteProviderUri
)
algorithmAssetRemoteProviderWithCompute = await ocean.assets.create(
algoAssetRemoteProviderWithCompute,
alice,
[service1],
tokenAddressAlgorithmRemoteProviderWithCompute,
null,
null,
null,
remoteProviderUri // only barge has 2 providers
)
assert(
algorithmAssetRemoteProviderWithCompute.dataToken ===
tokenAddressAlgorithmRemoteProviderWithCompute,
'algorithmAssetRemoteProvider.dataToken !== tokenAddressAlgorithmRemoteProvider'
)
const storeTx = await ocean.onChainMetadata.publish(
algorithmAssetRemoteProviderWithCompute.id,
algorithmAssetRemoteProviderWithCompute,
alice.getId()
)
assert(storeTx)
await waitForAqua(ocean, algorithmAssetRemoteProviderWithCompute.id)
const checkDDO = await ocean.assets.resolve(
algorithmAssetRemoteProviderWithCompute.id
)
const checkService = checkDDO.findServiceByType('compute')
assert(
checkService.serviceEndpoint === remoteProviderUri,
'algorithmAssetRemoteProviderWithCompute serviceEndpoint is not the remote provider'
)
})
it('Alice mints 100 DTs and tranfers them to the compute marketplace', async () => { it('Alice mints 100 DTs and tranfers them to the compute marketplace', async () => {
await datatoken.mint(tokenAddress, alice.getId(), tokenAmount) await datatoken.mint(tokenAddress, alice.getId(), tokenAmount)
await datatoken.mint(tokenAddressNoRawAlgo, alice.getId(), tokenAmount) await datatoken.mint(tokenAddressNoRawAlgo, alice.getId(), tokenAmount)
@ -651,6 +740,11 @@ describe('Compute flow', () => {
await datatoken.mint(tokenAddressAlgorithm, alice.getId(), tokenAmount) await datatoken.mint(tokenAddressAlgorithm, alice.getId(), tokenAmount)
await datatoken.mint(tokenAddressAlgorithmwithCompute, alice.getId(), tokenAmount) await datatoken.mint(tokenAddressAlgorithmwithCompute, alice.getId(), tokenAmount)
await datatoken.mint(tokenAddressAlgorithmRemoteProvider, alice.getId(), tokenAmount) await datatoken.mint(tokenAddressAlgorithmRemoteProvider, alice.getId(), tokenAmount)
await datatoken.mint(
tokenAddressAlgorithmRemoteProviderWithCompute,
alice.getId(),
tokenAmount
)
await datatoken.mint(tokenAddressAdditional1, alice.getId(), tokenAmount) await datatoken.mint(tokenAddressAdditional1, alice.getId(), tokenAmount)
await datatoken.mint(tokenAddressAdditional2, alice.getId(), tokenAmount) await datatoken.mint(tokenAddressAdditional2, alice.getId(), tokenAmount)
}) })
@ -709,6 +803,20 @@ describe('Compute flow', () => {
) )
assert(balance.toString() === dTamount.toString()) assert(balance.toString() === dTamount.toString())
}) })
await datatoken
.transfer(
tokenAddressAlgorithmRemoteProviderWithCompute,
bob.getId(),
dTamount,
alice.getId()
)
.then(async () => {
const balance = await datatoken.balance(
tokenAddressAlgorithmRemoteProviderWithCompute,
bob.getId()
)
assert(balance.toString() === dTamount.toString())
})
await datatoken await datatoken
.transfer(tokenAddressAdditional1, bob.getId(), dTamount, alice.getId()) .transfer(tokenAddressAdditional1, bob.getId(), dTamount, alice.getId())
@ -732,19 +840,20 @@ describe('Compute flow', () => {
computeAddress = await ocean.compute.getComputeAddress(ddo.id, computeService.index) computeAddress = await ocean.compute.getComputeAddress(ddo.id, computeService.index)
// check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions // check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions
const algoDefinition: ComputeAlgorithm = {
meta: algorithmMeta
}
const allowed = await ocean.compute.isOrderable( const allowed = await ocean.compute.isOrderable(
ddo.id, ddo.id,
computeService.index, computeService.index,
undefined, algoDefinition
algorithmMeta
) )
assert(allowed === true) assert(allowed === true)
computeOrderId = await ocean.compute.orderAsset( computeOrderId = await ocean.compute.orderAsset(
bob.getId(), bob.getId(),
ddo.id, ddo.id,
computeService.index, computeService.index,
undefined, algoDefinition,
algorithmMeta,
null, // no marketplace fee null, // no marketplace fee
computeAddress // CtD is the consumer of the dataset computeAddress // CtD is the consumer of the dataset
) )
@ -754,8 +863,7 @@ describe('Compute flow', () => {
computeOrderId, computeOrderId,
tokenAddress, tokenAddress,
bob, bob,
undefined, algoDefinition,
algorithmMeta,
output, output,
`${computeService.index}`, `${computeService.index}`,
computeService.type computeService.type
@ -829,12 +937,14 @@ describe('Compute flow', () => {
datasetNoRawAlgo.id, datasetNoRawAlgo.id,
service1.index service1.index
) )
const algoDefinition: ComputeAlgorithm = {
meta: algorithmMeta
}
const order = await ocean.compute.orderAsset( const order = await ocean.compute.orderAsset(
bob.getId(), bob.getId(),
datasetNoRawAlgo.id, datasetNoRawAlgo.id,
service1.index, service1.index,
undefined, algoDefinition,
algorithmMeta,
null, // no marketplace fee null, // no marketplace fee
computeAddress // CtD is the consumer of the dataset computeAddress // CtD is the consumer of the dataset
) )
@ -849,12 +959,14 @@ describe('Compute flow', () => {
datasetWithTrustedAlgo.id, datasetWithTrustedAlgo.id,
service1.index service1.index
) )
const algoDefinition: ComputeAlgorithm = {
did: 'did:op:7777'
}
// check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions // check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions
const allowed = await ocean.compute.isOrderable( const allowed = await ocean.compute.isOrderable(
datasetWithTrustedAlgo.id, datasetWithTrustedAlgo.id,
service1.index, service1.index,
'did:op:77777', algoDefinition
undefined
) )
assert(allowed === false) assert(allowed === false)
@ -863,8 +975,7 @@ describe('Compute flow', () => {
bob.getId(), bob.getId(),
datasetWithTrustedAlgo.id, datasetWithTrustedAlgo.id,
service1.index, service1.index,
'did:op:77777', algoDefinition,
undefined,
null, // no marketplace fee null, // no marketplace fee
computeAddress // CtD is the consumer of the dataset computeAddress // CtD is the consumer of the dataset
) )
@ -872,30 +983,30 @@ describe('Compute flow', () => {
}) })
it('should not allow a compute job with a published algo because asset does not allow allowAllPublishedAlgorithms', async () => { it('should not allow a compute job with a published algo because asset does not allow allowAllPublishedAlgorithms', async () => {
const output = {}
const computeService = ddo.findServiceByType('compute') const computeService = ddo.findServiceByType('compute')
// get the compute address first // get the compute address first
computeAddress = await ocean.compute.getComputeAddress(ddo.id, computeService.index) computeAddress = await ocean.compute.getComputeAddress(ddo.id, computeService.index)
assert(ddo != null, 'ddo should not be null') assert(ddo != null, 'ddo should not be null')
const algoDefinition: ComputeAlgorithm = {
did: algorithmAsset.id
}
const allowed = await ocean.compute.isOrderable( const allowed = await ocean.compute.isOrderable(
ddo.id, ddo.id,
computeService.index, computeService.index,
algorithmAsset.id, algoDefinition
undefined
) )
assert(allowed === false) assert(allowed === false)
const order = await ocean.compute.orderAsset( const order = await ocean.compute.orderAsset(
bob.getId(), bob.getId(),
ddo.id, ddo.id,
computeService.index, computeService.index,
algorithmAsset.id, algoDefinition,
undefined,
null, // no marketplace fee null, // no marketplace fee
computeAddress // CtD is the consumer of the dataset computeAddress // CtD is the consumer of the dataset
) )
assert(order === null, 'Order should be null') assert(order === null, 'Order should be null')
}) })
it('Alice updates Compute Privacy', async () => { it('Alice updates Compute Privacy', async () => {
const newComputePrivacy = { const newComputePrivacy = {
allowRawAlgorithm: false, allowRawAlgorithm: false,
@ -911,6 +1022,11 @@ describe('Compute flow', () => {
did: 'did:op:12345', did: 'did:op:12345',
filesChecksum: '1234', filesChecksum: '1234',
containerSectionChecksum: '1234' containerSectionChecksum: '1234'
},
{
did: algorithmAssetRemoteProviderWithCompute.id,
filesChecksum: '1234',
containerSectionChecksum: '1234'
} }
] ]
} }
@ -952,34 +1068,68 @@ describe('Compute flow', () => {
'allowNetworkAccess does not match' 'allowNetworkAccess does not match'
) )
}) })
it('should start a compute job with a published algo that has a compute service', async () => { it('should not allow a compute job with dataset/algo compute services served by different providers', async () => {
const output = {}
const computeService = ddo.findServiceByType('compute') const computeService = ddo.findServiceByType('compute')
assert(
algorithmAssetRemoteProviderWithCompute != null,
'algorithmAsset should not be null'
)
const serviceAlgo = algorithmAssetRemoteProviderWithCompute.findServiceByType(
'compute'
)
assert(serviceAlgo != null, 'serviceAlgo should not be null')
// get the compute address first // get the compute address first
computeAddress = await ocean.compute.getComputeAddress(ddo.id, computeService.index) computeAddress = await ocean.compute.getComputeAddress(ddo.id, computeService.index)
assert(ddo != null, 'ddo should not be null') assert(ddo != null, 'ddo should not be null')
const algoDefinition: ComputeAlgorithm = {
did: algorithmAssetRemoteProviderWithCompute.id,
serviceIndex: serviceAlgo.index
}
const allowed = await ocean.compute.isOrderable(
ddo.id,
computeService.index,
algoDefinition
)
assert(allowed === false)
const order = await ocean.compute.orderAsset(
bob.getId(),
ddo.id,
computeService.index,
algoDefinition,
null, // no marketplace fee
computeAddress // CtD is the consumer of the dataset
)
assert(order === null, 'Order should be null')
})
it('should start a compute job with a published algo that has a compute service', async () => {
const output = {}
const computeService = ddo.findServiceByType('compute')
assert(algorithmAsset != null, 'algorithmAsset should not be null')
const serviceAlgo = algorithmAssetwithCompute.findServiceByType('compute')
// get the compute address first
computeAddress = await ocean.compute.getComputeAddress(ddo.id, computeService.index)
assert(ddo != null, 'ddo should not be null')
const algoDefinition: ComputeAlgorithm = {
did: algorithmAssetwithCompute.id,
serviceIndex: serviceAlgo.index
}
// check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions // check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions
const allowed = await ocean.compute.isOrderable( const allowed = await ocean.compute.isOrderable(
ddo.id, ddo.id,
computeService.index, computeService.index,
algorithmAssetwithCompute.id, algoDefinition
undefined
) )
assert(allowed === true) assert(allowed === true)
const order = await ocean.compute.orderAsset( const order = await ocean.compute.orderAsset(
bob.getId(), bob.getId(),
ddo.id, ddo.id,
computeService.index, computeService.index,
algorithmAssetwithCompute.id, algoDefinition,
undefined,
null, // no marketplace fee null, // no marketplace fee
computeAddress // CtD is the consumer of the dataset computeAddress // CtD is the consumer of the dataset
) )
assert(order != null, 'Order should not be null') assert(order != null, 'Order should not be null')
// order the algorithm // order the algorithm
assert(algorithmAsset != null, 'algorithmAsset should not be null')
const serviceAlgo = algorithmAssetwithCompute.findServiceByType('compute')
const orderalgo = await ocean.compute.orderAlgorithm( const orderalgo = await ocean.compute.orderAlgorithm(
algorithmAssetwithCompute.id, algorithmAssetwithCompute.id,
serviceAlgo.type, serviceAlgo.type,
@ -989,19 +1139,17 @@ describe('Compute flow', () => {
computeAddress // CtD is the consumer of the dataset computeAddress // CtD is the consumer of the dataset
) )
assert(orderalgo != null, 'Order should not be null') assert(orderalgo != null, 'Order should not be null')
algoDefinition.transferTxId = orderalgo
algoDefinition.dataToken = algorithmAssetwithCompute.dataToken
const response = await ocean.compute.start( const response = await ocean.compute.start(
ddo.id, ddo.id,
order, order,
tokenAddress, tokenAddress,
bob, bob,
algorithmAssetwithCompute.id, algoDefinition,
undefined,
output, output,
`${computeService.index}`, `${computeService.index}`,
computeService.type, computeService.type
orderalgo,
algorithmAssetwithCompute.dataToken
) )
assert(response, 'Compute error') assert(response, 'Compute error')
jobId = response.jobId jobId = response.jobId
@ -1012,31 +1160,32 @@ describe('Compute flow', () => {
it('should start a compute job with a published algo', async () => { it('should start a compute job with a published algo', async () => {
const output = {} const output = {}
const computeService = ddo.findServiceByType('compute') const computeService = ddo.findServiceByType('compute')
assert(algorithmAsset != null, 'algorithmAsset should not be null')
const serviceAlgo = algorithmAsset.findServiceByType('access')
// get the compute address first // get the compute address first
computeAddress = await ocean.compute.getComputeAddress(ddo.id, computeService.index) computeAddress = await ocean.compute.getComputeAddress(ddo.id, computeService.index)
assert(ddo != null, 'ddo should not be null') assert(ddo != null, 'ddo should not be null')
const algoDefinition: ComputeAlgorithm = {
did: algorithmAsset.id,
serviceIndex: serviceAlgo.index
}
// check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions // check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions
const allowed = await ocean.compute.isOrderable( const allowed = await ocean.compute.isOrderable(
ddo.id, ddo.id,
computeService.index, computeService.index,
algorithmAsset.id, algoDefinition
undefined
) )
assert(allowed === true) assert(allowed === true)
const order = await ocean.compute.orderAsset( const order = await ocean.compute.orderAsset(
bob.getId(), bob.getId(),
ddo.id, ddo.id,
computeService.index, computeService.index,
algorithmAsset.id, algoDefinition,
undefined,
null, // no marketplace fee null, // no marketplace fee
computeAddress // CtD is the consumer of the dataset computeAddress // CtD is the consumer of the dataset
) )
assert(order != null, 'Order should not be null') assert(order != null, 'Order should not be null')
// order the algorithm // order the algorithm
assert(algorithmAsset != null, 'algorithmAsset should not be null')
const serviceAlgo = algorithmAsset.findServiceByType('access')
const orderalgo = await ocean.compute.orderAlgorithm( const orderalgo = await ocean.compute.orderAlgorithm(
algorithmAsset.id, algorithmAsset.id,
serviceAlgo.type, serviceAlgo.type,
@ -1046,19 +1195,17 @@ describe('Compute flow', () => {
computeAddress // CtD is the consumer of the dataset computeAddress // CtD is the consumer of the dataset
) )
assert(orderalgo != null, 'Order should not be null') assert(orderalgo != null, 'Order should not be null')
algoDefinition.transferTxId = orderalgo
algoDefinition.dataToken = algorithmAsset.dataToken
const response = await ocean.compute.start( const response = await ocean.compute.start(
ddo.id, ddo.id,
order, order,
tokenAddress, tokenAddress,
bob, bob,
algorithmAsset.id, algoDefinition,
undefined,
output, output,
`${computeService.index}`, `${computeService.index}`,
computeService.type, computeService.type
orderalgo,
algorithmAsset.dataToken
) )
assert(response, 'Compute error') assert(response, 'Compute error')
jobId = response.jobId jobId = response.jobId
@ -1070,31 +1217,33 @@ describe('Compute flow', () => {
const output = {} const output = {}
assert(ddo != null, 'ddo should not be null') assert(ddo != null, 'ddo should not be null')
const computeService = ddo.findServiceByType('compute') const computeService = ddo.findServiceByType('compute')
assert(
algorithmAssetRemoteProvider != null,
'algorithmAssetRemoteProvider should not be null'
)
const serviceAlgo = algorithmAssetRemoteProvider.findServiceByType('access')
// get the compute address first // get the compute address first
computeAddress = await ocean.compute.getComputeAddress(ddo.id, computeService.index) computeAddress = await ocean.compute.getComputeAddress(ddo.id, computeService.index)
const algoDefinition: ComputeAlgorithm = {
did: algorithmAssetRemoteProvider.id,
serviceIndex: serviceAlgo.index
}
// check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions // check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions
const allowed = await ocean.compute.isOrderable( const allowed = await ocean.compute.isOrderable(
ddo.id, ddo.id,
computeService.index, computeService.index,
algorithmAssetRemoteProvider.id, algoDefinition
undefined
) )
assert(allowed === true) assert(allowed === true)
const order = await ocean.compute.orderAsset( const order = await ocean.compute.orderAsset(
bob.getId(), bob.getId(),
ddo.id, ddo.id,
computeService.index, computeService.index,
algorithmAssetRemoteProvider.id, algoDefinition,
undefined,
null, // no marketplace fee null, // no marketplace fee
computeAddress // CtD is the consumer of the dataset computeAddress // CtD is the consumer of the dataset
) )
assert(order != null, 'Order should not be null') assert(order != null, 'Order should not be null')
assert(
algorithmAssetRemoteProvider != null,
'algorithmAssetRemoteProvider should not be null'
)
const serviceAlgo = algorithmAssetRemoteProvider.findServiceByType('access')
const orderalgo = await ocean.compute.orderAlgorithm( const orderalgo = await ocean.compute.orderAlgorithm(
algorithmAssetRemoteProvider.id, algorithmAssetRemoteProvider.id,
serviceAlgo.type, serviceAlgo.type,
@ -1104,18 +1253,17 @@ describe('Compute flow', () => {
computeAddress // CtD is the consumer of the dataset computeAddress // CtD is the consumer of the dataset
) )
assert(orderalgo != null, 'Order should not be null') assert(orderalgo != null, 'Order should not be null')
algoDefinition.transferTxId = orderalgo
algoDefinition.dataToken = algorithmAssetRemoteProvider.dataToken
const response = await ocean.compute.start( const response = await ocean.compute.start(
ddo.id, ddo.id,
order, order,
tokenAddress, tokenAddress,
bob, bob,
algorithmAssetRemoteProvider.id, algoDefinition,
undefined,
output, output,
`${computeService.index}`, `${computeService.index}`,
computeService.type, computeService.type
orderalgo,
algorithmAssetRemoteProvider.dataToken
) )
assert(response, 'Compute error') assert(response, 'Compute error')
assert(response.status >= 1, 'Invalid response status') assert(response.status >= 1, 'Invalid response status')
@ -1126,29 +1274,31 @@ describe('Compute flow', () => {
const output = {} const output = {}
assert(ddo != null, 'ddo should not be null') assert(ddo != null, 'ddo should not be null')
const computeService = ddo.findServiceByType('compute') const computeService = ddo.findServiceByType('compute')
assert(algorithmAsset != null, 'algorithmAsset should not be null')
const serviceAlgo = algorithmAsset.findServiceByType('access')
// get the compute address first // get the compute address first
computeAddress = await ocean.compute.getComputeAddress(ddo.id, computeService.index) computeAddress = await ocean.compute.getComputeAddress(ddo.id, computeService.index)
const algoDefinition: ComputeAlgorithm = {
did: algorithmAsset.id,
serviceIndex: serviceAlgo.index
}
let allowed let allowed
allowed = await ocean.compute.isOrderable( allowed = await ocean.compute.isOrderable(
ddo.id, ddo.id,
computeService.index, computeService.index,
algorithmAsset.id, algoDefinition
undefined
) )
assert(allowed === true) assert(allowed === true)
const order = await ocean.compute.orderAsset( const order = await ocean.compute.orderAsset(
bob.getId(), bob.getId(),
ddo.id, ddo.id,
computeService.index, computeService.index,
algorithmAsset.id, algoDefinition,
undefined,
null, // no marketplace fee null, // no marketplace fee
computeAddress // CtD is the consumer of the dataset computeAddress // CtD is the consumer of the dataset
) )
assert(order != null, 'Order should not be null') assert(order != null, 'Order should not be null')
// order the algo // order the algo
assert(algorithmAsset != null, 'algorithmAsset should not be null')
const serviceAlgo = algorithmAsset.findServiceByType('access')
const orderalgo = await ocean.compute.orderAlgorithm( const orderalgo = await ocean.compute.orderAlgorithm(
algorithmAsset.id, algorithmAsset.id,
serviceAlgo.type, serviceAlgo.type,
@ -1164,16 +1314,14 @@ describe('Compute flow', () => {
allowed = await ocean.compute.isOrderable( allowed = await ocean.compute.isOrderable(
ddoAdditional1.id, ddoAdditional1.id,
inputOrder1Service.index, inputOrder1Service.index,
algorithmAsset.id, algoDefinition
undefined
) )
assert(allowed === true) assert(allowed === true)
const inputOrder1 = await ocean.compute.orderAsset( const inputOrder1 = await ocean.compute.orderAsset(
bob.getId(), bob.getId(),
ddoAdditional1.id, ddoAdditional1.id,
inputOrder1Service.index, inputOrder1Service.index,
algorithmAsset.id, algoDefinition,
undefined,
null, // no marketplace fee null, // no marketplace fee
computeAddress // CtD is the consumer of the dataset computeAddress // CtD is the consumer of the dataset
) )
@ -1184,16 +1332,14 @@ describe('Compute flow', () => {
allowed = await ocean.compute.isOrderable( allowed = await ocean.compute.isOrderable(
ddoAdditional2.id, ddoAdditional2.id,
inputOrder2Service.index, inputOrder2Service.index,
algorithmAsset.id, algoDefinition
undefined
) )
assert(allowed === true) assert(allowed === true)
const inputOrder2 = await ocean.compute.orderAsset( const inputOrder2 = await ocean.compute.orderAsset(
bob.getId(), bob.getId(),
ddoAdditional2.id, ddoAdditional2.id,
inputOrder2Service.index, inputOrder2Service.index,
algorithmAsset.id, algoDefinition,
undefined,
null, // no marketplace fee null, // no marketplace fee
computeAddress // CtD is the consumer of the dataset computeAddress // CtD is the consumer of the dataset
) )
@ -1210,19 +1356,17 @@ describe('Compute flow', () => {
serviceId: inputOrder2Service.index serviceId: inputOrder2Service.index
} }
] ]
algoDefinition.transferTxId = orderalgo
algoDefinition.dataToken = algorithmAsset.dataToken
const response = await ocean.compute.start( const response = await ocean.compute.start(
ddo.id, ddo.id,
order, order,
tokenAddress, tokenAddress,
bob, bob,
algorithmAsset.id, algoDefinition,
undefined,
output, output,
`${computeService.index}`, `${computeService.index}`,
computeService.type, computeService.type,
orderalgo,
algorithmAsset.dataToken,
additionalInputs additionalInputs
) )
assert(response.status >= 1, 'Invalid response.status') assert(response.status >= 1, 'Invalid response.status')
@ -1303,13 +1447,14 @@ describe('Compute flow', () => {
// get the compute address first // get the compute address first
computeAddress = await ocean.compute.getComputeAddress(ddo.id, computeService.index) computeAddress = await ocean.compute.getComputeAddress(ddo.id, computeService.index)
assert(ddo != null, 'ddo should not be null') assert(ddo != null, 'ddo should not be null')
const algoDefinition: ComputeAlgorithm = {
did: algorithmAsset.id
}
// check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions // check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions
const allowed = await ocean.compute.isOrderable( const allowed = await ocean.compute.isOrderable(
ddo.id, ddo.id,
computeService.index, computeService.index,
algorithmAsset.id, algoDefinition
undefined
) )
assert(allowed === false, 'This should fail, the algo container section was changed!') assert(allowed === false, 'This should fail, the algo container section was changed!')
}) })
@ -1338,13 +1483,14 @@ describe('Compute flow', () => {
// get the compute address first // get the compute address first
computeAddress = await ocean.compute.getComputeAddress(ddo.id, computeService.index) computeAddress = await ocean.compute.getComputeAddress(ddo.id, computeService.index)
assert(ddo != null, 'ddo should not be null') assert(ddo != null, 'ddo should not be null')
const algoDefinition: ComputeAlgorithm = {
did: algorithmAssetRemoteProvider.id
}
// check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions // check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions
const allowed = await ocean.compute.isOrderable( const allowed = await ocean.compute.isOrderable(
ddo.id, ddo.id,
computeService.index, computeService.index,
algorithmAssetRemoteProvider.id, algoDefinition
undefined
) )
assert(allowed === false, 'This should fail, the algo files section was changed!') assert(allowed === false, 'This should fail, the algo files section was changed!')
}) })
@ -1393,13 +1539,14 @@ describe('Compute flow', () => {
datasetWithBogusProvider.id, datasetWithBogusProvider.id,
computeService.index computeService.index
) )
const algoDefinition: ComputeAlgorithm = {
meta: algorithmMeta
}
// check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions // check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions
const allowed = await ocean.compute.isOrderable( const allowed = await ocean.compute.isOrderable(
datasetWithBogusProvider.id, datasetWithBogusProvider.id,
computeService.index, computeService.index,
undefined, algoDefinition
algorithmMeta
) )
assert(allowed === false) assert(allowed === false)
// we know that it is not Orderable, but we are trying to force it // we know that it is not Orderable, but we are trying to force it
@ -1407,8 +1554,7 @@ describe('Compute flow', () => {
bob.getId(), bob.getId(),
datasetWithBogusProvider.id, datasetWithBogusProvider.id,
computeService.index, computeService.index,
undefined, algoDefinition,
algorithmMeta,
null, // no marketplace fee null, // no marketplace fee
computeAddress // CtD is the consumer of the dataset computeAddress // CtD is the consumer of the dataset
) )
@ -1420,8 +1566,7 @@ describe('Compute flow', () => {
computeOrderId, computeOrderId,
tokenAddress, tokenAddress,
bob, bob,
undefined, algoDefinition,
algorithmMeta,
output, output,
`${computeService.index}`, `${computeService.index}`,
computeService.type computeService.type