Skip to content

Commit f86f463

Browse files
Feature/update processprotecteddata (#426)
2 parents 93d9993 + 2c5e125 commit f86f463

File tree

6 files changed

+258
-117
lines changed

6 files changed

+258
-117
lines changed

packages/sdk/src/config/config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ export const SCONE_TAG = ['tee', 'scone'];
2323

2424
export const DEFAULT_MAX_PRICE = 0;
2525

26+
export const MAX_DESIRED_DATA_ORDER_PRICE = 0;
27+
28+
export const MAX_DESIRED_APP_ORDER_PRICE = 0;
29+
30+
export const MAX_DESIRED_WORKERPOOL_ORDER_PRICE = 0;
31+
2632
export const KEY_PURPOSE_SELECTOR = 'keyHasPurpose(bytes32,uint256)';
2733

2834
export const GROUP_MEMBER_PURPOSE = 4;

packages/sdk/src/lib/dataProtectorCore/processProtectedData.ts

Lines changed: 116 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { ethers } from 'ethers';
22
import {
3-
DEFAULT_MAX_PRICE,
3+
MAX_DESIRED_APP_ORDER_PRICE,
4+
MAX_DESIRED_DATA_ORDER_PRICE,
5+
MAX_DESIRED_WORKERPOOL_ORDER_PRICE,
46
SCONE_TAG,
57
WORKERPOOL_ADDRESS,
68
} from '../../config/config.js';
@@ -11,7 +13,7 @@ import {
1113
} from '../../utils/errors.js';
1214
import {
1315
checkUserVoucher,
14-
findWorkerpoolOrders,
16+
filterWorkerpoolOrders,
1517
} from '../../utils/processProtectedData.models.js';
1618
import { pushRequesterSecret } from '../../utils/pushRequesterSecret.js';
1719
import {
@@ -45,7 +47,9 @@ export const processProtectedData = async ({
4547
protectedData,
4648
app,
4749
userWhitelist,
48-
maxPrice = DEFAULT_MAX_PRICE,
50+
dataMaxPrice = MAX_DESIRED_DATA_ORDER_PRICE,
51+
appMaxPrice = MAX_DESIRED_APP_ORDER_PRICE,
52+
workerpoolMaxPrice = MAX_DESIRED_WORKERPOOL_ORDER_PRICE,
4953
path,
5054
args,
5155
inputFiles,
@@ -67,9 +71,15 @@ export const processProtectedData = async ({
6771
const vUserWhitelist = addressSchema()
6872
.label('userWhitelist')
6973
.validateSync(userWhitelist);
70-
const vMaxPrice = positiveNumberSchema()
71-
.label('maxPrice')
72-
.validateSync(maxPrice);
74+
const vDataMaxPrice = positiveNumberSchema()
75+
.label('dataMaxPrice')
76+
.validateSync(dataMaxPrice);
77+
const vAppMaxPrice = positiveNumberSchema()
78+
.label('appMaxPrice')
79+
.validateSync(appMaxPrice);
80+
const vWorkerpoolMaxPrice = positiveNumberSchema()
81+
.label('workerpoolMaxPrice')
82+
.validateSync(workerpoolMaxPrice);
7383
const vPath = stringSchema().label('path').validateSync(path);
7484
const vInputFiles = urlArraySchema()
7585
.label('inputFiles')
@@ -136,76 +146,111 @@ export const processProtectedData = async ({
136146
}
137147

138148
vOnStatusUpdate({
139-
title: 'FETCH_PROTECTED_DATA_ORDERBOOK',
149+
title: 'FETCH_ORDERS',
140150
isDone: false,
141151
});
142-
const datasetOrderbook = await iexec.orderbook.fetchDatasetOrderbook(
143-
vProtectedData,
144-
{
145-
app: vApp,
146-
workerpool: vWorkerpool,
147-
requester,
148-
}
149-
);
150-
const datasetorder = datasetOrderbook.orders[0]?.order; //The first order is the cheapest one
151-
if (!datasetorder) {
152-
throw new Error(`No dataset orders found`);
153-
}
154-
vOnStatusUpdate({
155-
title: 'FETCH_PROTECTED_DATA_ORDERBOOK',
156-
isDone: true,
157-
});
152+
const [
153+
datasetorderForApp,
154+
datasetorderForWhitelist,
155+
apporder,
156+
workerpoolorder,
157+
] = await Promise.all([
158+
// Fetch dataset order
159+
iexec.orderbook
160+
.fetchDatasetOrderbook(vProtectedData, {
161+
app: vApp,
162+
requester: requester,
163+
})
164+
.then((datasetOrderbook) => {
165+
const desiredPriceDataOrderbook = datasetOrderbook.orders.filter(
166+
(order) => order.order.datasetprice <= vDataMaxPrice
167+
);
168+
return desiredPriceDataOrderbook[0]?.order; // may be undefined
169+
}),
170+
// Fetch dataset order for whitelist
171+
iexec.orderbook
172+
.fetchDatasetOrderbook(vProtectedData, {
173+
app: vUserWhitelist,
174+
requester: requester,
175+
})
176+
.then((datasetOrderbook) => {
177+
const desiredPriceDataOrderbook = datasetOrderbook.orders.filter(
178+
(order) => order.order.datasetprice <= vDataMaxPrice
179+
);
180+
return desiredPriceDataOrderbook[0]?.order; // may be undefined
181+
}),
182+
// Fetch app order
183+
iexec.orderbook
184+
.fetchAppOrderbook(vApp, {
185+
minTag: ['tee', 'scone'],
186+
maxTag: ['tee', 'scone'],
187+
workerpool: vWorkerpool,
188+
})
189+
.then((appOrderbook) => {
190+
const desiredPriceAppOrderbook = appOrderbook.orders.filter(
191+
(order) => order.order.appprice <= vAppMaxPrice
192+
);
193+
const desiredPriceAppOrder = desiredPriceAppOrderbook[0]?.order;
194+
if (!desiredPriceAppOrder) {
195+
throw new Error('No App order found for the desired price');
196+
}
197+
return desiredPriceAppOrder;
198+
}),
199+
// Fetch workerpool order for App or AppWhitelist
200+
Promise.all([
201+
// for app
202+
iexec.orderbook.fetchWorkerpoolOrderbook({
203+
workerpool: vWorkerpool,
204+
app: vApp,
205+
dataset: vProtectedData,
206+
requester: requester, // public orders + user specific orders
207+
isRequesterStrict: useVoucher, // If voucher, we only want user specific orders
208+
minTag: ['tee', 'scone'],
209+
maxTag: ['tee', 'scone'],
210+
category: 0,
211+
}),
212+
// for app whitelist
213+
iexec.orderbook.fetchWorkerpoolOrderbook({
214+
workerpool: vWorkerpool === ethers.ZeroAddress ? 'any' : vWorkerpool,
215+
app: vUserWhitelist,
216+
dataset: vProtectedData,
217+
requester: requester, // public orders + user specific orders
218+
isRequesterStrict: useVoucher, // If voucher, we only want user specific orders
219+
minTag: ['tee', 'scone'],
220+
maxTag: ['tee', 'scone'],
221+
category: 0,
222+
}),
223+
]).then(
224+
([workerpoolOrderbookForApp, workerpoolOrderbookForAppWhitelist]) => {
225+
const desiredPriceWorkerpoolOrder = filterWorkerpoolOrders({
226+
workerpoolOrders: [
227+
...workerpoolOrderbookForApp.orders,
228+
...workerpoolOrderbookForAppWhitelist.orders,
229+
],
230+
workerpoolMaxPrice: vWorkerpoolMaxPrice,
231+
useVoucher: vUseVoucher,
232+
userVoucher,
233+
});
234+
if (!desiredPriceWorkerpoolOrder) {
235+
throw new Error('No Workerpool order found for the desired price');
236+
}
237+
return desiredPriceWorkerpoolOrder;
238+
}
239+
),
240+
]);
158241

159-
vOnStatusUpdate({
160-
title: 'FETCH_APP_ORDERBOOK',
161-
isDone: false,
162-
});
163-
const appOrderbook = await iexec.orderbook.fetchAppOrderbook(vApp, {
164-
dataset: protectedData,
165-
requester,
166-
minTag: SCONE_TAG,
167-
maxTag: SCONE_TAG,
168-
workerpool: vWorkerpool,
169-
});
170-
const apporder = appOrderbook.orders[0]?.order; //The first order is the cheapest one
171-
if (!apporder) {
172-
throw new Error(`No app orders found`);
242+
if (!workerpoolorder) {
243+
throw new Error('No Workerpool order found for the desired price');
173244
}
174-
vOnStatusUpdate({
175-
title: 'FETCH_APP_ORDERBOOK',
176-
isDone: true,
177-
});
178245

179-
vOnStatusUpdate({
180-
title: 'FETCH_WORKERPOOL_ORDERBOOK',
181-
isDone: false,
182-
});
183-
const workerpoolOrderbook = await iexec.orderbook.fetchWorkerpoolOrderbook({
184-
workerpool: vWorkerpool === ethers.ZeroAddress ? 'any' : vWorkerpool, // if address zero was chosen use any workerpool
185-
app: vApp,
186-
dataset: vProtectedData,
187-
requester: requester,
188-
isRequesterStrict:
189-
vVoucherOwner && vVoucherOwner.toLowerCase() !== requester.toLowerCase()
190-
? false
191-
: useVoucher,
192-
minTag: SCONE_TAG,
193-
maxTag: SCONE_TAG,
194-
category: 0,
195-
});
196-
const workerpoolOrder = findWorkerpoolOrders({
197-
workerpoolOrders: [...workerpoolOrderbook.orders],
198-
useVoucher: vUseVoucher,
199-
userVoucher,
200-
});
201-
if (!workerpoolOrder) {
202-
throw new Error('No Workerpool order found.');
246+
const datasetorder = datasetorderForApp || datasetorderForWhitelist;
247+
if (!datasetorder) {
248+
throw new Error('No Dataset order found for the desired price');
203249
}
204250
vOnStatusUpdate({
205-
title: 'FETCH_WORKERPOOL_ORDERBOOK',
251+
title: 'FETCH_ORDERS',
206252
isDone: true,
207253
});
208-
209254
vOnStatusUpdate({
210255
title: 'PUSH_REQUESTER_SECRET',
211256
isDone: false,
@@ -222,13 +267,13 @@ export const processProtectedData = async ({
222267
});
223268
const requestorderToSign = await iexec.order.createRequestorder({
224269
app: vApp,
225-
category: workerpoolOrder.category,
270+
category: workerpoolorder.category,
226271
dataset: vProtectedData,
227272
appmaxprice: apporder.appprice,
228273
datasetmaxprice: datasetorder.datasetprice,
229-
workerpoolmaxprice: workerpoolOrder.workerpoolprice,
274+
workerpoolmaxprice: workerpoolorder.workerpoolprice,
230275
tag: SCONE_TAG,
231-
workerpool: workerpoolOrder.workerpool,
276+
workerpool: workerpoolorder.workerpool,
232277
params: {
233278
iexec_input_files: vInputFiles,
234279
iexec_secrets: secretsId,
@@ -239,7 +284,7 @@ export const processProtectedData = async ({
239284

240285
const orders = {
241286
requestorder,
242-
workerpoolorder: workerpoolOrder,
287+
workerpoolorder: workerpoolorder,
243288
apporder: apporder,
244289
datasetorder: datasetorder,
245290
};
@@ -248,20 +293,6 @@ export const processProtectedData = async ({
248293
...(vVoucherOwner ? { voucherAddress: userVoucher?.address } : {}),
249294
};
250295

251-
const estimatedMatchOrderPrice = await iexec.order.estimateMatchOrders(
252-
orders,
253-
matchOptions
254-
);
255-
if (
256-
estimatedMatchOrderPrice.total
257-
.sub(estimatedMatchOrderPrice.sponsored)
258-
.ltn(vMaxPrice)
259-
) {
260-
throw new Error(
261-
`No orders found within the specified price limit ${vMaxPrice} nRLC.`
262-
);
263-
}
264-
265296
const { dealid, txHash } = await iexec.order.matchOrders(
266297
orders,
267298
matchOptions

packages/sdk/src/lib/types/coreTypes.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ export type TransferResponse = {
276276

277277
// ---------------------ProcessProtectedData Types------------------------------------
278278
export type ProcessProtectedDataStatuses =
279+
| 'FETCH_ORDERS'
279280
| 'FETCH_PROTECTED_DATA_ORDERBOOK'
280281
| 'FETCH_APP_ORDERBOOK'
281282
| 'FETCH_WORKERPOOL_ORDERBOOK'
@@ -302,11 +303,22 @@ export type ProcessProtectedDataParams = {
302303
userWhitelist?: Address;
303304

304305
/**
305-
* The maximum price per task for processing the protected data.
306-
* It is the sum of the application price, dataset price and workerpool price per task.
306+
* The maximum price of dataset per task for processing the protected data.
307307
@default = 0
308308
*/
309-
maxPrice?: number;
309+
dataMaxPrice?: number;
310+
311+
/**
312+
* The maximum price of application per task for processing the protected data.
313+
@default = 0
314+
*/
315+
appMaxPrice?: number;
316+
317+
/**
318+
* The maximum price of workerpool per task for processing the protected data.
319+
@default = 0
320+
*/
321+
workerpoolMaxPrice?: number;
310322

311323
/**
312324
* The file name of the desired file in the returned ZIP file.

packages/sdk/src/utils/processProtectedData.models.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@ export function checkUserVoucher({
2424
}
2525
}
2626

27-
export function findWorkerpoolOrders({
27+
export function filterWorkerpoolOrders({
2828
workerpoolOrders,
29+
workerpoolMaxPrice,
2930
useVoucher,
3031
userVoucher,
3132
}: {
3233
workerpoolOrders: PublishedWorkerpoolorder[];
34+
workerpoolMaxPrice: number;
3335
useVoucher: boolean;
3436
userVoucher?: VoucherInfo;
3537
}) {
@@ -38,6 +40,8 @@ export function findWorkerpoolOrders({
3840
}
3941

4042
let eligibleWorkerpoolOrders = workerpoolOrders;
43+
let maxVoucherSponsoredAmount = 0; // may be safer to use bigint
44+
4145
if (useVoucher) {
4246
if (!userVoucher) {
4347
throw new Error(
@@ -53,11 +57,20 @@ export function findWorkerpoolOrders({
5357
'Found some workerpool orders but none can be sponsored by your voucher.'
5458
);
5559
}
60+
maxVoucherSponsoredAmount = bnToNumber(userVoucher.balance);
5661
}
5762

5863
const [cheapestOrder] = eligibleWorkerpoolOrders.sort(
5964
(order1, order2) =>
6065
order1.order.workerpoolprice - order2.order.workerpoolprice
6166
);
67+
68+
if (
69+
!cheapestOrder ||
70+
cheapestOrder.order.workerpoolprice >
71+
workerpoolMaxPrice + maxVoucherSponsoredAmount
72+
) {
73+
return null;
74+
}
6275
return cheapestOrder.order;
6376
}

packages/sdk/tests/test-utils.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,32 @@ export const mockWorkerpoolOrderbook = {
211211
count: 1,
212212
};
213213

214+
export const mockAppOrderbook = {
215+
orders: [
216+
{
217+
order: {
218+
app: '0xc8c5E295D2BedA01D1fB8DD4d85A1Cb769185a34',
219+
appprice: 0,
220+
volume: 10000000,
221+
tag: '0x0000000000000000000000000000000000000000000000000000000000000003',
222+
datasetrestrict: '0x0000000000000000000000000000000000000000',
223+
workerpoolrestrict: '0x0000000000000000000000000000000000000000',
224+
requesterrestrict: '0x0000000000000000000000000000000000000000',
225+
salt: '0x82107d3b5694d3ab4cd4e5f2057e1bdeb7da359518ccfb15638405c619fa12b0',
226+
sign: '0x0112d6f1b53777a001054daf62f542a5f94679f88885515a2126a6794505d6993e425c3a432b4c2cdbf004f6f0c8c9908493135dedb829f6c958e67daa068dd61c',
227+
},
228+
orderHash:
229+
'0x64208bc3580bbee092c4a4efb26629cf885a2f1e99b6b4d9bd809ea85b58332f',
230+
chainId: 134,
231+
publicationTimestamp: '2025-02-05T14:35:51.271Z',
232+
signer: '0x9cfFa14604A6836E9d6fBAcCc624cfE0bE3Be5B4',
233+
status: 'open',
234+
remaining: 9999961,
235+
},
236+
],
237+
count: 1,
238+
};
239+
214240
export function observableMockComplete() {
215241
const mockObservable: any = {
216242
subscribe: jest.fn(({ complete }) => {

0 commit comments

Comments
 (0)