11import { v4 as uuidV4 } from 'uuid' ;
22import { ethers } from 'ethers' ;
33import { utils } from 'iexec' ;
4+ import { ConsumableDatasetorder } from 'iexec/IExecOrderModule' ;
45import { mkdir , rm } from 'node:fs/promises' ;
56import { askForWallet } from '../cli-helpers/askForWallet.js' ;
67import {
@@ -27,14 +28,14 @@ import { warnBeforeTxFees } from '../cli-helpers/warnBeforeTxFees.js';
2728export async function run ( {
2829 iAppAddress,
2930 args,
30- protectedData,
31+ protectedData = [ ] ,
3132 inputFile : inputFiles = [ ] , // rename variable (it's an array)
3233 requesterSecret : requesterSecrets = [ ] , // rename variable (it's an array)
3334 chain,
3435} : {
3536 iAppAddress : string ;
3637 args ?: string ;
37- protectedData ?: string ;
38+ protectedData ?: string [ ] ;
3839 inputFile ?: string [ ] ;
3940 requesterSecret ?: { key : number ; value : string } [ ] ;
4041 chain ?: string ;
@@ -62,24 +63,26 @@ export async function run({
6263 if ( ( await readOnlyIexec . app . checkDeployedApp ( iAppAddress ) ) === false ) {
6364 throw Error ( 'No iApp found at the specified address.' ) ;
6465 }
65- if ( protectedData ) {
66- if (
67- ( await readOnlyIexec . dataset . checkDeployedDataset ( protectedData ) ) ===
68- false
69- ) {
70- throw Error ( 'No protectedData found at the specified address.' ) ;
71- }
72- const isSecretSet = await readOnlyIexec . dataset . checkDatasetSecretExists (
73- protectedData ,
74- {
75- teeFramework : 'scone' ,
76- }
66+ if ( protectedData . length > 0 ) {
67+ await Promise . all (
68+ protectedData . map ( async ( dataset ) => {
69+ if (
70+ ( await readOnlyIexec . dataset . checkDeployedDataset ( dataset ) ) ===
71+ false
72+ ) {
73+ throw Error ( `No protectedData found at ${ dataset } .` ) ;
74+ }
75+ const isSecretSet =
76+ await readOnlyIexec . dataset . checkDatasetSecretExists ( dataset , {
77+ teeFramework : 'scone' ,
78+ } ) ;
79+ if ( ! isSecretSet ) {
80+ throw Error (
81+ `The protectedData secret key for ${ dataset } is not registered in the Secret Management Service (SMS) of iExec protocol.`
82+ ) ;
83+ }
84+ } )
7785 ) ;
78- if ( ! isSecretSet ) {
79- throw Error (
80- `The protectedData secret key is not registered in the Secret Management Service (SMS) of iExec protocol.`
81- ) ;
82- }
8386 }
8487
8588 // Get wallet from privateKey
@@ -96,23 +99,6 @@ export async function run({
9699 } ) ;
97100 }
98101
99- // Workerpool Order
100- spinner . start ( 'Fetching workerpool order...' ) ;
101- const workerpoolOrderbook = await iexec . orderbook . fetchWorkerpoolOrderbook ( {
102- workerpool : useTdx ? WORKERPOOL_TDX : chainConfig . workerpool ,
103- app : iAppAddress ,
104- dataset : protectedData || ethers . ZeroAddress ,
105- minTag : SCONE_TAG ,
106- maxTag : SCONE_TAG ,
107- } ) ;
108- const workerpoolorder = workerpoolOrderbook . orders [ 0 ] ?. order ;
109- if ( ! workerpoolorder ) {
110- throw Error (
111- 'No WorkerpoolOrder found, Wait until some workerpoolOrder come back'
112- ) ;
113- }
114- spinner . succeed ( 'Workerpool order fetched' ) ;
115-
116102 // App Order
117103 spinner . start ( 'Creating app order...' ) ;
118104 const apporderTemplate = await iexec . order . createApporder ( {
@@ -124,26 +110,37 @@ export async function run({
124110 spinner . succeed ( 'AppOrder created' ) ;
125111
126112 // Dataset Order
127- let datasetorder ;
128- if ( protectedData ) {
113+ let bulkCid : string | undefined ;
114+ let volume = 1 ;
115+ let datasetorders : ConsumableDatasetorder [ ] = [ ] ;
116+ if ( protectedData . length > 0 ) {
129117 spinner . start ( 'Fetching protectedData access...' ) ;
130- const datasetOrderbook = await iexec . orderbook . fetchDatasetOrderbook (
131- protectedData ,
132- {
133- app : iAppAddress ,
134- workerpool : workerpoolorder . workerpool ,
135- requester : userAddress ,
136- minTag : SCONE_TAG ,
137- maxTag : SCONE_TAG ,
138- }
118+ datasetorders = await Promise . all (
119+ protectedData . map ( async ( dataset ) => {
120+ const datasetOrderbook = await iexec . orderbook . fetchDatasetOrderbook ( {
121+ dataset,
122+ app : iAppAddress ,
123+ requester : userAddress ,
124+ minTag : SCONE_TAG ,
125+ maxTag : SCONE_TAG ,
126+ bulkOnly : protectedData . length > 1 , // bulk if multiple datasets
127+ } ) ;
128+ const datasetorder = datasetOrderbook . orders [ 0 ] ?. order ;
129+ if ( ! datasetorder ) {
130+ throw Error (
131+ `No matching ProtectedData access found, It seems your iApp is not allowed to access the protectedData ${ dataset } , please grantAccess to it`
132+ ) ;
133+ }
134+ return datasetorder ;
135+ } )
139136 ) ;
140- datasetorder = datasetOrderbook . orders [ 0 ] ?. order ;
141- if ( ! datasetorder ) {
142- throw Error (
143- 'No matching ProtectedData access found, It seems your iApp is not allowed to access the protectedData, please grantAccess to it'
144- ) ;
145- }
146137 spinner . succeed ( 'ProtectedData access found' ) ;
138+ if ( protectedData . length > 1 ) {
139+ spinner . start ( 'Preparing bulk access...' ) ;
140+ const bulk = await iexec . order . prepareDatasetBulk ( datasetorders ) ;
141+ bulkCid = bulk . cid ;
142+ volume = bulk . volume ;
143+ }
147144 }
148145
149146 // Requester secrets
@@ -164,28 +161,52 @@ export async function run({
164161 spinner . succeed ( 'Requester secrets provisioned' ) ;
165162 }
166163
164+ // Workerpool Order
165+ spinner . start ( 'Fetching workerpool order...' ) ;
166+ const workerpoolOrderbook = await iexec . orderbook . fetchWorkerpoolOrderbook ( {
167+ workerpool : useTdx ? WORKERPOOL_TDX : chainConfig . workerpool ,
168+ app : iAppAddress ,
169+ minTag : SCONE_TAG ,
170+ maxTag : SCONE_TAG ,
171+ minVolume : volume , // TODO handle multiple matches if not enough volume
172+ } ) ;
173+ const workerpoolorder = workerpoolOrderbook . orders [ 0 ] ?. order ;
174+ if ( ! workerpoolorder ) {
175+ throw Error (
176+ 'No workerpool order found, Wait until some workerpool order come back'
177+ ) ;
178+ }
179+ spinner . succeed ( 'Workerpool order fetched' ) ;
180+
167181 spinner . start ( 'Creating request order...' ) ;
168182 const requestorderToSign = await iexec . order . createRequestorder ( {
169183 app : iAppAddress ,
170184 category : workerpoolorder . category ,
171- dataset : protectedData || ethers . ZeroAddress ,
185+ dataset :
186+ datasetorders . length === 1
187+ ? datasetorders [ 0 ] . dataset
188+ : ethers . ZeroAddress ,
172189 appmaxprice : apporder . appprice ,
173- datasetmaxprice : datasetorder ?. datasetprice || 0 ,
190+ datasetmaxprice :
191+ datasetorders . length === 1
192+ ? datasetorders [ 0 ] . datasetprice . toString ( )
193+ : 0 ,
174194 workerpoolmaxprice : workerpoolorder . workerpoolprice ,
175195 tag : SCONE_TAG ,
176- workerpool : workerpoolorder . workerpool ,
196+ volume ,
177197 params : {
178198 iexec_args : args ,
179199 iexec_input_files : inputFiles . length > 0 ? inputFiles : undefined ,
180200 iexec_secrets,
201+ bulk_cid : bulkCid ,
181202 } ,
182203 } ) ;
183204 const requestorder = await iexec . order . signRequestorder ( requestorderToSign ) ;
184205 spinner . succeed ( 'RequestOrder created' ) ;
185206
186207 const matchOrderParams = {
187208 apporder,
188- datasetorder : protectedData ? datasetorder : undefined ,
209+ datasetorder : datasetorders . length === 1 ? datasetorders [ 0 ] : undefined ,
189210 workerpoolorder,
190211 requestorder,
191212 } ;
0 commit comments