mirror of
https://github.com/oceanprotocol/ocean.js.git
synced 2024-07-01 06:11:45 +02: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:
parent
7f05b8fdb5
commit
39938ec9c0
|
@ -9,9 +9,12 @@ import {
|
|||
import Account from './Account'
|
||||
import { SubscribablePromise } from '../utils'
|
||||
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
|
||||
import { Output } from './interfaces/ComputeOutput'
|
||||
import { ComputeJob } from './interfaces/ComputeJob'
|
||||
import { ComputeInput } from './interfaces/ComputeInput'
|
||||
import {
|
||||
ComputeOutput,
|
||||
ComputeJob,
|
||||
ComputeInput,
|
||||
ComputeAlgorithm
|
||||
} from './interfaces/Compute'
|
||||
import { Provider } from '../provider/Provider'
|
||||
import { SHA256 } from 'crypto-js'
|
||||
|
||||
|
@ -109,13 +112,10 @@ export class Compute extends Instantiable {
|
|||
txId: string,
|
||||
tokenAddress: string,
|
||||
consumerAccount: Account,
|
||||
algorithmDid?: string,
|
||||
algorithmMeta?: MetadataAlgorithm,
|
||||
output?: Output,
|
||||
algorithm: ComputeAlgorithm,
|
||||
output?: ComputeOutput,
|
||||
serviceIndex?: string,
|
||||
serviceType?: string,
|
||||
algorithmTransferTxId?: string,
|
||||
algorithmDataToken?: string,
|
||||
additionalInputs?: ComputeInput[]
|
||||
): Promise<ComputeJob> {
|
||||
output = this.checkOutput(consumerAccount, output)
|
||||
|
@ -128,15 +128,12 @@ export class Compute extends Instantiable {
|
|||
const computeJobsList = await provider.computeStart(
|
||||
did,
|
||||
consumerAccount,
|
||||
algorithmDid,
|
||||
algorithmMeta,
|
||||
algorithm,
|
||||
output,
|
||||
txId,
|
||||
serviceIndex,
|
||||
serviceType,
|
||||
tokenAddress,
|
||||
algorithmTransferTxId,
|
||||
algorithmDataToken,
|
||||
additionalInputs
|
||||
)
|
||||
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.
|
||||
* @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)
|
||||
|
||||
if (isDefault) {
|
||||
|
@ -412,31 +409,48 @@ export class Compute extends Instantiable {
|
|||
public async isOrderable(
|
||||
datasetDid: string,
|
||||
serviceIndex: number,
|
||||
algorithmDid?: string,
|
||||
algorithmMeta?: MetadataAlgorithm
|
||||
algorithm: ComputeAlgorithm
|
||||
): Promise<boolean> {
|
||||
const ddo: DDO = await this.ocean.assets.resolve(datasetDid)
|
||||
const service: Service = ddo.findServiceById(serviceIndex)
|
||||
if (!service) return false
|
||||
if (service.type === 'compute') {
|
||||
if (algorithmMeta) {
|
||||
if (algorithm.meta) {
|
||||
// check if raw algo is allowed
|
||||
if (service.attributes.main.privacy)
|
||||
if (service.attributes.main.privacy.allowRawAlgorithm) return true
|
||||
this.logger.error('ERROR: This service does not allow raw algorithm')
|
||||
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
|
||||
if (service.attributes.main.privacy) {
|
||||
if (service.attributes.main.privacy.allowAllPublishedAlgorithms) return true
|
||||
if (!service.attributes.main.privacy.publisherTrustedAlgorithms) return false
|
||||
let algo: publisherTrustedAlgorithm
|
||||
for (algo of service.attributes.main.privacy.publisherTrustedAlgorithms) {
|
||||
if (algo.did === algorithmDid) {
|
||||
if (algo.did === algorithm.did) {
|
||||
// compute checkusms and compare them
|
||||
const trustedAlgorithm = await this.createPublisherTrustedAlgorithmfromDID(
|
||||
algorithmDid
|
||||
algorithm.did
|
||||
)
|
||||
if (
|
||||
algo.containerSectionChecksum &&
|
||||
|
@ -465,10 +479,11 @@ export class Compute extends Instantiable {
|
|||
}
|
||||
// algorithmDid was not found
|
||||
this.logger.error(
|
||||
'ERROR: Algorithm ' + algorithmDid + ' is not allowed by ' + datasetDid
|
||||
'ERROR: Algorithm ' + algorithm.did + ' is not allowed by ' + datasetDid
|
||||
)
|
||||
return false
|
||||
}
|
||||
console.error('Algo Index:' + algorithm.serviceIndex)
|
||||
}
|
||||
}
|
||||
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} serviceIndex The Service index
|
||||
* @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.
|
||||
* @return {Promise<string>} Returns the transaction details
|
||||
*
|
||||
|
@ -491,19 +507,13 @@ export class Compute extends Instantiable {
|
|||
consumerAccount: string,
|
||||
datasetDid: string,
|
||||
serviceIndex: number,
|
||||
algorithmDid?: string,
|
||||
algorithmMeta?: MetadataAlgorithm,
|
||||
algorithm: ComputeAlgorithm,
|
||||
mpAddress?: string,
|
||||
computeAddress?: string
|
||||
): SubscribablePromise<OrderProgressStep, string> {
|
||||
return new SubscribablePromise(async (observer) => {
|
||||
// first check if we can order this
|
||||
const allowed = await this.isOrderable(
|
||||
datasetDid,
|
||||
serviceIndex,
|
||||
algorithmDid,
|
||||
algorithmMeta
|
||||
)
|
||||
const allowed = await this.isOrderable(datasetDid, serviceIndex, algorithm)
|
||||
if (!allowed) return null
|
||||
const ddo: DDO = await this.ocean.assets.resolve(datasetDid)
|
||||
// const service: Service = ddo.findServiceByType('compute')
|
||||
|
|
43
src/ocean/interfaces/Compute.ts
Normal file
43
src/ocean/interfaces/Compute.ts
Normal 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
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
export interface ComputeInput {
|
||||
documentId: string
|
||||
transferTxId: string
|
||||
serviceId: number
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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[]
|
||||
}
|
|
@ -2,9 +2,12 @@ import Account from '../ocean/Account'
|
|||
import { noZeroX } from '../utils'
|
||||
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
|
||||
import { File } from '../ddo/interfaces/File'
|
||||
import { ComputeJob } from '../ocean/interfaces/ComputeJob'
|
||||
import { ComputeInput } from '../ocean/interfaces/ComputeInput'
|
||||
import { Output } from '../ocean/interfaces/ComputeOutput'
|
||||
import {
|
||||
ComputeJob,
|
||||
ComputeInput,
|
||||
ComputeOutput,
|
||||
ComputeAlgorithm
|
||||
} from '../ocean/interfaces/Compute'
|
||||
import { MetadataAlgorithm } from '../ddo/interfaces/MetadataAlgorithm'
|
||||
import { Versions } from '../ocean/Versions'
|
||||
import { DDO } from '../ddo/DDO'
|
||||
|
@ -261,15 +264,12 @@ export class Provider extends Instantiable {
|
|||
public async computeStart(
|
||||
did: string,
|
||||
consumerAccount: Account,
|
||||
algorithmDid?: string,
|
||||
algorithmMeta?: MetadataAlgorithm,
|
||||
output?: Output,
|
||||
algorithm: ComputeAlgorithm,
|
||||
output?: ComputeOutput,
|
||||
txId?: string,
|
||||
serviceIndex?: string,
|
||||
serviceType?: string,
|
||||
tokenAddress?: string,
|
||||
algorithmTransferTxId?: string,
|
||||
algorithmDataToken?: string,
|
||||
additionalInputs?: ComputeInput[]
|
||||
): Promise<ComputeJob | ComputeJob[]> {
|
||||
const address = consumerAccount.getId()
|
||||
|
@ -285,12 +285,12 @@ export class Provider extends Instantiable {
|
|||
|
||||
// continue to construct Provider URL
|
||||
if (output) payload.output = output
|
||||
if (algorithmDid) payload.algorithmDid = algorithmDid
|
||||
if (algorithmMeta) payload.algorithmMeta = algorithmMeta
|
||||
if (algorithm.did) payload.algorithmDid = algorithm.did
|
||||
if (algorithm.meta) payload.algorithmMeta = algorithm.meta
|
||||
payload.consumerAddress = address
|
||||
if (txId) payload.transferTxId = txId
|
||||
if (algorithmTransferTxId) payload.algorithmTransferTxId = algorithmTransferTxId
|
||||
if (algorithmDataToken) payload.algorithmDataToken = algorithmDataToken
|
||||
if (algorithm.transferTxId) payload.algorithmTransferTxId = algorithm.transferTxId
|
||||
if (algorithm.dataToken) payload.algorithmDataToken = algorithm.dataToken
|
||||
|
||||
if (serviceIndex) payload.serviceId = serviceIndex
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ import datatokensTemplate from '@oceanprotocol/contracts/artifacts/DataTokenTemp
|
|||
import { Account, DDO, Metadata } from '../../src/lib'
|
||||
import { Cluster, Container, Server } from '../../src/ocean/Compute'
|
||||
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 fetch = require('cross-fetch')
|
||||
|
||||
|
@ -68,6 +68,7 @@ describe('Compute flow', () => {
|
|||
let algorithmAsset: DDO
|
||||
let algorithmAssetwithCompute: DDO
|
||||
let algorithmAssetRemoteProvider: DDO
|
||||
let algorithmAssetRemoteProviderWithCompute: DDO
|
||||
let contracts: TestContractHandler
|
||||
let datatoken: DataTokens
|
||||
let tokenAddress: string
|
||||
|
@ -77,6 +78,7 @@ describe('Compute flow', () => {
|
|||
let tokenAddressAlgorithm: string
|
||||
let tokenAddressAlgorithmwithCompute: string
|
||||
let tokenAddressAlgorithmRemoteProvider: string
|
||||
let tokenAddressAlgorithmRemoteProviderWithCompute: string
|
||||
let tokenAddressAdditional1: string
|
||||
let tokenAddressAdditional2: string
|
||||
let price: string
|
||||
|
@ -207,6 +209,17 @@ describe('Compute flow', () => {
|
|||
tokenAddressAlgorithmRemoteProvider != null,
|
||||
'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(
|
||||
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 () => {
|
||||
await datatoken.mint(tokenAddress, 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(tokenAddressAlgorithmwithCompute, 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(tokenAddressAdditional2, alice.getId(), tokenAmount)
|
||||
})
|
||||
|
@ -709,6 +803,20 @@ describe('Compute flow', () => {
|
|||
)
|
||||
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
|
||||
.transfer(tokenAddressAdditional1, bob.getId(), dTamount, alice.getId())
|
||||
|
@ -732,19 +840,20 @@ describe('Compute flow', () => {
|
|||
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
|
||||
const algoDefinition: ComputeAlgorithm = {
|
||||
meta: algorithmMeta
|
||||
}
|
||||
const allowed = await ocean.compute.isOrderable(
|
||||
ddo.id,
|
||||
computeService.index,
|
||||
undefined,
|
||||
algorithmMeta
|
||||
algoDefinition
|
||||
)
|
||||
assert(allowed === true)
|
||||
computeOrderId = await ocean.compute.orderAsset(
|
||||
bob.getId(),
|
||||
ddo.id,
|
||||
computeService.index,
|
||||
undefined,
|
||||
algorithmMeta,
|
||||
algoDefinition,
|
||||
null, // no marketplace fee
|
||||
computeAddress // CtD is the consumer of the dataset
|
||||
)
|
||||
|
@ -754,8 +863,7 @@ describe('Compute flow', () => {
|
|||
computeOrderId,
|
||||
tokenAddress,
|
||||
bob,
|
||||
undefined,
|
||||
algorithmMeta,
|
||||
algoDefinition,
|
||||
output,
|
||||
`${computeService.index}`,
|
||||
computeService.type
|
||||
|
@ -829,12 +937,14 @@ describe('Compute flow', () => {
|
|||
datasetNoRawAlgo.id,
|
||||
service1.index
|
||||
)
|
||||
const algoDefinition: ComputeAlgorithm = {
|
||||
meta: algorithmMeta
|
||||
}
|
||||
const order = await ocean.compute.orderAsset(
|
||||
bob.getId(),
|
||||
datasetNoRawAlgo.id,
|
||||
service1.index,
|
||||
undefined,
|
||||
algorithmMeta,
|
||||
algoDefinition,
|
||||
null, // no marketplace fee
|
||||
computeAddress // CtD is the consumer of the dataset
|
||||
)
|
||||
|
@ -849,12 +959,14 @@ describe('Compute flow', () => {
|
|||
datasetWithTrustedAlgo.id,
|
||||
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
|
||||
const allowed = await ocean.compute.isOrderable(
|
||||
datasetWithTrustedAlgo.id,
|
||||
service1.index,
|
||||
'did:op:77777',
|
||||
undefined
|
||||
algoDefinition
|
||||
)
|
||||
assert(allowed === false)
|
||||
|
||||
|
@ -863,8 +975,7 @@ describe('Compute flow', () => {
|
|||
bob.getId(),
|
||||
datasetWithTrustedAlgo.id,
|
||||
service1.index,
|
||||
'did:op:77777',
|
||||
undefined,
|
||||
algoDefinition,
|
||||
null, // no marketplace fee
|
||||
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 () => {
|
||||
const output = {}
|
||||
const computeService = ddo.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: algorithmAsset.id
|
||||
}
|
||||
const allowed = await ocean.compute.isOrderable(
|
||||
ddo.id,
|
||||
computeService.index,
|
||||
algorithmAsset.id,
|
||||
undefined
|
||||
algoDefinition
|
||||
)
|
||||
assert(allowed === false)
|
||||
const order = await ocean.compute.orderAsset(
|
||||
bob.getId(),
|
||||
ddo.id,
|
||||
computeService.index,
|
||||
algorithmAsset.id,
|
||||
undefined,
|
||||
algoDefinition,
|
||||
null, // no marketplace fee
|
||||
computeAddress // CtD is the consumer of the dataset
|
||||
)
|
||||
assert(order === null, 'Order should be null')
|
||||
})
|
||||
|
||||
it('Alice updates Compute Privacy', async () => {
|
||||
const newComputePrivacy = {
|
||||
allowRawAlgorithm: false,
|
||||
|
@ -911,6 +1022,11 @@ describe('Compute flow', () => {
|
|||
did: 'did:op:12345',
|
||||
filesChecksum: '1234',
|
||||
containerSectionChecksum: '1234'
|
||||
},
|
||||
{
|
||||
did: algorithmAssetRemoteProviderWithCompute.id,
|
||||
filesChecksum: '1234',
|
||||
containerSectionChecksum: '1234'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -952,34 +1068,68 @@ describe('Compute flow', () => {
|
|||
'allowNetworkAccess does not match'
|
||||
)
|
||||
})
|
||||
it('should start a compute job with a published algo that has a compute service', async () => {
|
||||
const output = {}
|
||||
it('should not allow a compute job with dataset/algo compute services served by different providers', async () => {
|
||||
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
|
||||
computeAddress = await ocean.compute.getComputeAddress(ddo.id, computeService.index)
|
||||
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
|
||||
const allowed = await ocean.compute.isOrderable(
|
||||
ddo.id,
|
||||
computeService.index,
|
||||
algorithmAssetwithCompute.id,
|
||||
undefined
|
||||
algoDefinition
|
||||
)
|
||||
assert(allowed === true)
|
||||
const order = await ocean.compute.orderAsset(
|
||||
bob.getId(),
|
||||
ddo.id,
|
||||
computeService.index,
|
||||
algorithmAssetwithCompute.id,
|
||||
undefined,
|
||||
algoDefinition,
|
||||
null, // no marketplace fee
|
||||
computeAddress // CtD is the consumer of the dataset
|
||||
)
|
||||
assert(order != null, 'Order should not be null')
|
||||
// order the algorithm
|
||||
assert(algorithmAsset != null, 'algorithmAsset should not be null')
|
||||
const serviceAlgo = algorithmAssetwithCompute.findServiceByType('compute')
|
||||
const orderalgo = await ocean.compute.orderAlgorithm(
|
||||
algorithmAssetwithCompute.id,
|
||||
serviceAlgo.type,
|
||||
|
@ -989,19 +1139,17 @@ describe('Compute flow', () => {
|
|||
computeAddress // CtD is the consumer of the dataset
|
||||
)
|
||||
assert(orderalgo != null, 'Order should not be null')
|
||||
|
||||
algoDefinition.transferTxId = orderalgo
|
||||
algoDefinition.dataToken = algorithmAssetwithCompute.dataToken
|
||||
const response = await ocean.compute.start(
|
||||
ddo.id,
|
||||
order,
|
||||
tokenAddress,
|
||||
bob,
|
||||
algorithmAssetwithCompute.id,
|
||||
undefined,
|
||||
algoDefinition,
|
||||
output,
|
||||
`${computeService.index}`,
|
||||
computeService.type,
|
||||
orderalgo,
|
||||
algorithmAssetwithCompute.dataToken
|
||||
computeService.type
|
||||
)
|
||||
assert(response, 'Compute error')
|
||||
jobId = response.jobId
|
||||
|
@ -1012,31 +1160,32 @@ describe('Compute flow', () => {
|
|||
it('should start a compute job with a published algo', async () => {
|
||||
const output = {}
|
||||
const computeService = ddo.findServiceByType('compute')
|
||||
assert(algorithmAsset != null, 'algorithmAsset should not be null')
|
||||
const serviceAlgo = algorithmAsset.findServiceByType('access')
|
||||
// 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: algorithmAsset.id,
|
||||
serviceIndex: serviceAlgo.index
|
||||
}
|
||||
// check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions
|
||||
const allowed = await ocean.compute.isOrderable(
|
||||
ddo.id,
|
||||
computeService.index,
|
||||
algorithmAsset.id,
|
||||
undefined
|
||||
algoDefinition
|
||||
)
|
||||
assert(allowed === true)
|
||||
const order = await ocean.compute.orderAsset(
|
||||
bob.getId(),
|
||||
ddo.id,
|
||||
computeService.index,
|
||||
algorithmAsset.id,
|
||||
undefined,
|
||||
algoDefinition,
|
||||
null, // no marketplace fee
|
||||
computeAddress // CtD is the consumer of the dataset
|
||||
)
|
||||
assert(order != null, 'Order should not be null')
|
||||
// order the algorithm
|
||||
assert(algorithmAsset != null, 'algorithmAsset should not be null')
|
||||
const serviceAlgo = algorithmAsset.findServiceByType('access')
|
||||
const orderalgo = await ocean.compute.orderAlgorithm(
|
||||
algorithmAsset.id,
|
||||
serviceAlgo.type,
|
||||
|
@ -1046,19 +1195,17 @@ describe('Compute flow', () => {
|
|||
computeAddress // CtD is the consumer of the dataset
|
||||
)
|
||||
assert(orderalgo != null, 'Order should not be null')
|
||||
|
||||
algoDefinition.transferTxId = orderalgo
|
||||
algoDefinition.dataToken = algorithmAsset.dataToken
|
||||
const response = await ocean.compute.start(
|
||||
ddo.id,
|
||||
order,
|
||||
tokenAddress,
|
||||
bob,
|
||||
algorithmAsset.id,
|
||||
undefined,
|
||||
algoDefinition,
|
||||
output,
|
||||
`${computeService.index}`,
|
||||
computeService.type,
|
||||
orderalgo,
|
||||
algorithmAsset.dataToken
|
||||
computeService.type
|
||||
)
|
||||
assert(response, 'Compute error')
|
||||
jobId = response.jobId
|
||||
|
@ -1070,31 +1217,33 @@ describe('Compute flow', () => {
|
|||
const output = {}
|
||||
assert(ddo != null, 'ddo should not be null')
|
||||
const computeService = ddo.findServiceByType('compute')
|
||||
assert(
|
||||
algorithmAssetRemoteProvider != null,
|
||||
'algorithmAssetRemoteProvider should not be null'
|
||||
)
|
||||
const serviceAlgo = algorithmAssetRemoteProvider.findServiceByType('access')
|
||||
// get the compute address first
|
||||
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
|
||||
const allowed = await ocean.compute.isOrderable(
|
||||
ddo.id,
|
||||
computeService.index,
|
||||
algorithmAssetRemoteProvider.id,
|
||||
undefined
|
||||
algoDefinition
|
||||
)
|
||||
assert(allowed === true)
|
||||
const order = await ocean.compute.orderAsset(
|
||||
bob.getId(),
|
||||
ddo.id,
|
||||
computeService.index,
|
||||
algorithmAssetRemoteProvider.id,
|
||||
undefined,
|
||||
algoDefinition,
|
||||
null, // no marketplace fee
|
||||
computeAddress // CtD is the consumer of the dataset
|
||||
)
|
||||
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(
|
||||
algorithmAssetRemoteProvider.id,
|
||||
serviceAlgo.type,
|
||||
|
@ -1104,18 +1253,17 @@ describe('Compute flow', () => {
|
|||
computeAddress // CtD is the consumer of the dataset
|
||||
)
|
||||
assert(orderalgo != null, 'Order should not be null')
|
||||
algoDefinition.transferTxId = orderalgo
|
||||
algoDefinition.dataToken = algorithmAssetRemoteProvider.dataToken
|
||||
const response = await ocean.compute.start(
|
||||
ddo.id,
|
||||
order,
|
||||
tokenAddress,
|
||||
bob,
|
||||
algorithmAssetRemoteProvider.id,
|
||||
undefined,
|
||||
algoDefinition,
|
||||
output,
|
||||
`${computeService.index}`,
|
||||
computeService.type,
|
||||
orderalgo,
|
||||
algorithmAssetRemoteProvider.dataToken
|
||||
computeService.type
|
||||
)
|
||||
assert(response, 'Compute error')
|
||||
assert(response.status >= 1, 'Invalid response status')
|
||||
|
@ -1126,29 +1274,31 @@ describe('Compute flow', () => {
|
|||
const output = {}
|
||||
assert(ddo != null, 'ddo should not be null')
|
||||
const computeService = ddo.findServiceByType('compute')
|
||||
assert(algorithmAsset != null, 'algorithmAsset should not be null')
|
||||
const serviceAlgo = algorithmAsset.findServiceByType('access')
|
||||
// get the compute address first
|
||||
computeAddress = await ocean.compute.getComputeAddress(ddo.id, computeService.index)
|
||||
const algoDefinition: ComputeAlgorithm = {
|
||||
did: algorithmAsset.id,
|
||||
serviceIndex: serviceAlgo.index
|
||||
}
|
||||
let allowed
|
||||
allowed = await ocean.compute.isOrderable(
|
||||
ddo.id,
|
||||
computeService.index,
|
||||
algorithmAsset.id,
|
||||
undefined
|
||||
algoDefinition
|
||||
)
|
||||
assert(allowed === true)
|
||||
const order = await ocean.compute.orderAsset(
|
||||
bob.getId(),
|
||||
ddo.id,
|
||||
computeService.index,
|
||||
algorithmAsset.id,
|
||||
undefined,
|
||||
algoDefinition,
|
||||
null, // no marketplace fee
|
||||
computeAddress // CtD is the consumer of the dataset
|
||||
)
|
||||
assert(order != null, 'Order should not be null')
|
||||
// order the algo
|
||||
assert(algorithmAsset != null, 'algorithmAsset should not be null')
|
||||
const serviceAlgo = algorithmAsset.findServiceByType('access')
|
||||
const orderalgo = await ocean.compute.orderAlgorithm(
|
||||
algorithmAsset.id,
|
||||
serviceAlgo.type,
|
||||
|
@ -1164,16 +1314,14 @@ describe('Compute flow', () => {
|
|||
allowed = await ocean.compute.isOrderable(
|
||||
ddoAdditional1.id,
|
||||
inputOrder1Service.index,
|
||||
algorithmAsset.id,
|
||||
undefined
|
||||
algoDefinition
|
||||
)
|
||||
assert(allowed === true)
|
||||
const inputOrder1 = await ocean.compute.orderAsset(
|
||||
bob.getId(),
|
||||
ddoAdditional1.id,
|
||||
inputOrder1Service.index,
|
||||
algorithmAsset.id,
|
||||
undefined,
|
||||
algoDefinition,
|
||||
null, // no marketplace fee
|
||||
computeAddress // CtD is the consumer of the dataset
|
||||
)
|
||||
|
@ -1184,16 +1332,14 @@ describe('Compute flow', () => {
|
|||
allowed = await ocean.compute.isOrderable(
|
||||
ddoAdditional2.id,
|
||||
inputOrder2Service.index,
|
||||
algorithmAsset.id,
|
||||
undefined
|
||||
algoDefinition
|
||||
)
|
||||
assert(allowed === true)
|
||||
const inputOrder2 = await ocean.compute.orderAsset(
|
||||
bob.getId(),
|
||||
ddoAdditional2.id,
|
||||
inputOrder2Service.index,
|
||||
algorithmAsset.id,
|
||||
undefined,
|
||||
algoDefinition,
|
||||
null, // no marketplace fee
|
||||
computeAddress // CtD is the consumer of the dataset
|
||||
)
|
||||
|
@ -1210,19 +1356,17 @@ describe('Compute flow', () => {
|
|||
serviceId: inputOrder2Service.index
|
||||
}
|
||||
]
|
||||
|
||||
algoDefinition.transferTxId = orderalgo
|
||||
algoDefinition.dataToken = algorithmAsset.dataToken
|
||||
const response = await ocean.compute.start(
|
||||
ddo.id,
|
||||
order,
|
||||
tokenAddress,
|
||||
bob,
|
||||
algorithmAsset.id,
|
||||
undefined,
|
||||
algoDefinition,
|
||||
output,
|
||||
`${computeService.index}`,
|
||||
computeService.type,
|
||||
orderalgo,
|
||||
algorithmAsset.dataToken,
|
||||
additionalInputs
|
||||
)
|
||||
assert(response.status >= 1, 'Invalid response.status')
|
||||
|
@ -1303,13 +1447,14 @@ describe('Compute flow', () => {
|
|||
// 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: algorithmAsset.id
|
||||
}
|
||||
// check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions
|
||||
const allowed = await ocean.compute.isOrderable(
|
||||
ddo.id,
|
||||
computeService.index,
|
||||
algorithmAsset.id,
|
||||
undefined
|
||||
algoDefinition
|
||||
)
|
||||
assert(allowed === false, 'This should fail, the algo container section was changed!')
|
||||
})
|
||||
|
@ -1338,13 +1483,14 @@ describe('Compute flow', () => {
|
|||
// 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: algorithmAssetRemoteProvider.id
|
||||
}
|
||||
// check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions
|
||||
const allowed = await ocean.compute.isOrderable(
|
||||
ddo.id,
|
||||
computeService.index,
|
||||
algorithmAssetRemoteProvider.id,
|
||||
undefined
|
||||
algoDefinition
|
||||
)
|
||||
assert(allowed === false, 'This should fail, the algo files section was changed!')
|
||||
})
|
||||
|
@ -1393,13 +1539,14 @@ describe('Compute flow', () => {
|
|||
datasetWithBogusProvider.id,
|
||||
computeService.index
|
||||
)
|
||||
|
||||
const algoDefinition: ComputeAlgorithm = {
|
||||
meta: algorithmMeta
|
||||
}
|
||||
// check if asset is orderable. otherwise, you might pay for it, but it has some algo restrictions
|
||||
const allowed = await ocean.compute.isOrderable(
|
||||
datasetWithBogusProvider.id,
|
||||
computeService.index,
|
||||
undefined,
|
||||
algorithmMeta
|
||||
algoDefinition
|
||||
)
|
||||
assert(allowed === false)
|
||||
// we know that it is not Orderable, but we are trying to force it
|
||||
|
@ -1407,8 +1554,7 @@ describe('Compute flow', () => {
|
|||
bob.getId(),
|
||||
datasetWithBogusProvider.id,
|
||||
computeService.index,
|
||||
undefined,
|
||||
algorithmMeta,
|
||||
algoDefinition,
|
||||
null, // no marketplace fee
|
||||
computeAddress // CtD is the consumer of the dataset
|
||||
)
|
||||
|
@ -1420,8 +1566,7 @@ describe('Compute flow', () => {
|
|||
computeOrderId,
|
||||
tokenAddress,
|
||||
bob,
|
||||
undefined,
|
||||
algorithmMeta,
|
||||
algoDefinition,
|
||||
output,
|
||||
`${computeService.index}`,
|
||||
computeService.type
|
||||
|
|
Loading…
Reference in New Issue
Block a user