Skip to content
LogoLogo

Compute to Data

Compute to Data runs an algorithm against a dataset without the algorithm's owner ever seeing the data. You order both, the node runs the job in an isolated environment, and you get back the results.

What is different in v2

C2D v2 changed the model substantially:

  • Resources are requested explicitly — [{ id: 'cpu', amount: 2 }] — instead of the old fixed CPU/GPU descriptors. Environments advertise what they have and what it costs per chain.
  • Payment runs through an escrow contract. The node quotes an amount, nautilus locks it.
  • All datasets travel in one array. v1 had dataset plus additionalDatasets on the wire.
  • Free compute exists, with no order, no escrow and no payment token.
  • Output is { remoteStorage, encryption }. The publishAlgorithmLog and publishOutput flags are gone.
Loading diagram...

Pick an environment first

v1 silently used the node's first environment. Worth choosing deliberately: resources, duration limits, accepted tokens and free-tier availability all differ.

const  = await .() 
 
for (const  of ) {
  .(., ., ., .)
}

fees is keyed by chain id, so a token that is not listed for your chain cannot pay for a job there.

A free job

The cheapest way to get started, where the environment offers it.

const  = await .()
const  = .(() => .) 
 
const  = await .({ 
  : { : 'did:ope:1234abcd...' }, 
  : { : 'did:ope:5678wxyz...' }, 
  : ?. 
}) 
 
const  = .[0].

No datatoken is bought and no escrow is touched. An environment without a free section throws, naming it — free jobs are opt-in for the node operator, and its access list may restrict who can use them.

A paid job

const  = await .()
const  = [0]
 
const  = await .({ 
  : { : 'did:ope:1234abcd...' }, 
  : { : 'did:ope:5678wxyz...' }, 
  : ., 
  : [ 
    { : 'cpu', : 2 }, 
    { : 'ram', : 2 } 
  ], 
  : 3600
}) 
 
const  = .[0].
.('orders', .)

What nautilus does, in order:

  1. Resolves every input and picks its compute service.
  2. Satisfies all credential policies. A failure here aborts with nothing spent — which is exactly why it comes before the orders.
  3. Asks the node to quote the job: provider fees, reusable orders, and the escrow amount.
  4. Funds and authorises escrow for the quoted amount.
  5. Orders each input, reusing an existing order where the node says one is valid.
  6. Starts the job.

resources defaults to each resource's declared minimum, paymentToken to the first token the environment accepts on your chain, and maxJobDuration is capped to the environment's limit with a warning.

Several datasets

const  = await .({
  : { : 'did:ope:1234abcd...' },
  : [ 
    { : 'did:ope:926098d069b017dcf...' }, 
    { : 'did:ope:475698d069b017dcf...' } 
  ], 
  : { : 'did:ope:5678wxyz...' }
})

nautilus assembles the single array the node expects. Every dataset is ordered.

Following the job

const  = await .({  }) 
 
.(?., ?.)

Status 70 (JobFinished) means the algorithm has run; 71 (JobSettle) means it has run and the node is only waiting on the payment-claim cron. Results are readable at either. While the job runs, you can read the container's logs — useful for debugging an algorithm you cannot otherwise observe:

const  = await .({  }) 

Getting the results

const  = await .({  }) 
 
if () {
  const  = await ()
}

undefined means the job has not finished, the node does not know it, or it produced no output result — the log line says which. A job also produces algorithmLog, configrationLog and publishLog entries, reachable by resultIndex.

For a large result, stream it instead of buffering a download:

const  = await .({  }) 
 
for await (const  of ) { 
  ..() 
} 

Stopping a job

await .({  }) 

Publishing for compute

On the dataset side, a COMPUTE service decides which algorithms may run. Pinning specific algorithms is the safe default — nautilus resolves their container and file checksums at publish time, so a publisher cannot swap the container afterwards:

const  = new <., .>({
  : .
})
  .('https://ocean-node.dev.pontus-x.eu')
  .({ : 'url', : 'https://data.example/x.csv', : 'GET' })
  .({ : 'free' })
  .(false) // no unpublished code
  .(false) // no exfiltration
  .([{ : 'did:ope:926098d069b017dcf...' }]) 
  .()

allowAlgorithmNetworkAccess(false) is what makes the isolation meaningful: without network access, an algorithm cannot send your data anywhere.

See Publishing for the algorithm side.

Try it

The examples cover the whole job lifecycle:

npm start -- compute:envs                            # what a node offers, and at what price
npm start -- compute:free  <datasetDid> <algoDid>    # no order, no escrow
npm start -- compute:paid  <datasetDid> <algoDid>    # funds the escrow from the node's quote
npm start -- compute:full  <datasetDid> <algoDid>    # start → wait → logs → result