🔒 Use iApps with Protected Data
Protected data is the cornerstone of privacy-preserving computation on iExec. This guide shows you how to use iApps with protected data, from granting access to processing and retrieving results.
Understanding Protected Data and iApps
Protected data is encrypted information that can only be processed by authorized iApps within Trusted Execution Environments (TEEs). The data remains confidential throughout the entire computation process.
The Workflow
- Protect Your Data: Encrypt sensitive information using the Data Protector
- Grant Access: Authorize specific iApps to process your data
- Execute iApp: Run the iApp with your protected data
- Retrieve Results: Get the computation results while data remains private
Step 1: Protect Your Data
Before using an iApp, you need to protect your sensitive data.
Basic Data Protection
ts
// Protect your data
const { address: protectedDataAddress } = await dataProtectorCore.protectData({
name: 'My Sensitive Data',
data: {
email: 'user@example.com',
apiKey: 'secret-api-key-12345',
preferences: {
theme: 'dark',
notifications: true,
},
},
});
Protecting Different Data Types
ts
// Protect contact list for email applications
const { address: contactListAddress } = await dataProtectorCore.protectData({
name: 'Email Contact List',
data: {
contacts: {
'0x123abc...': 'john@example.com',
'0x456def...': 'jane@example.com',
'0x789ghi...': 'bob@example.com',
},
},
});
// Protect trading data for oracle applications
const { address: tradingDataAddress } = await dataProtectorCore.protectData({
name: 'Trading History',
data: {
trades: {
'2024-01-01': { price: 50000, volume: 100 },
'2024-01-02': { price: 51000, volume: 150 },
'2024-01-03': { price: 49000, volume: 200 },
},
},
});
// Protect financial data for payment applications
const { address: paymentDataAddress } = await dataProtectorCore.protectData({
name: 'Payment Information',
data: {
bankAccount: '1234567890',
routingNumber: '987654321',
accountHolder: 'John Doe',
},
});
Step 2: Grant Access to iApps
iApps need explicit authorization to access your protected data.
Grant Access to a Specific iApp
ts
// Grant access to an iApp
const grantedAccess = await dataProtectorCore.grantAccess({
protectedData: '0x123abc...',
authorizedApp: '0x456def...', // The iApp address
authorizedUser: '0x789abc...', // Your wallet address
pricePerAccess: 5, // Price per access in nRLC
numberOfAccess: 10, // Number of allowed accesses
});
Check Granted Access
ts
// Check what access you've granted
const grantedAccessList = await dataProtectorCore.getGrantedAccess({
protectedData: '0x123abc...',
authorizedApp: '0x456def...',
authorizedUser: '0x789abc...',
});
Step 3: Execute iApp with Protected Data
Once access is granted, you can execute the iApp with your protected data.
Using DataProtector
ts
// Execute iApp with protected data
const result = await dataProtectorCore.processProtectedData({
protectedData: '0x123abc...',
app: '0x456def...', // The iApp address
});
Using SDK Library
ts
// Create & Sign a request order with protected data
const requestorderToSign = await iexec.order.createRequestorder({
app: '0x456def...', // The iApp address
category: 0,
appmaxprice: 10, // Maximum price in nRLC
dataset: protectedDataAddress, // Protected data address
datasetmaxprice: 5, // Maximum price for dataset access
workerpool: '0xa5de76...', // ENS address for iExec's debug workerpool
});
const requestOrder = await iexec.order.signRequestorder(requestorderToSign);
// Fetch app orders
const appOrders = await iexec.orderbook.fetchAppOrderbook(
'0x456def...' // Filter by specific app
);
if (appOrders.orders.length === 0) {
throw new Error('No app orders found for the specified app');
}
// Fetch protected data orders
const datasetOrders = await iexec.orderbook.fetchDatasetOrderbook(
protectedDataAddress // Filter by specific dataset
);
if (datasetOrders.orders.length === 0) {
throw new Error(
'No protectedData orders found for the specified protectedData'
);
}
// Fetch workerpool orders
const workerpoolOrders = await iexec.orderbook.fetchWorkerpoolOrderbook({
workerpool: '0xa5de76...', // Filter by specific workerpool
});
if (workerpoolOrders.orders.length === 0) {
throw new Error('No workerpool orders found for the specified workerpool');
}
// Execute the task
const taskId = await iexec.order.matchOrders({
requestorder: requestOrder,
apporder: appOrders.orders[0].order,
datasetorder: datasetOrders.orders[0].order,
workerpoolorder: workerpoolOrders.orders[0].order,
});
Using iExec CLI with Protected Data
bash
# Execute with protected data
iexec app run 0x456def... --dataset 0x123abc...
Step 4: Retrieve Results
After execution completes, retrieve the results from the task.
Using DataProtector
ts
// Retrieve the result
const taskResult = await dataProtectorCore.getResultFromCompletedTask({
taskId: taskId,
});
Using iExec CLI
bash
# Get the task ID from the execution result
TASK_ID="0x7ac398..."
# Retrieve the result
iexec task show $TASK_ID
# Retrieve a specific file from the result
iexec task show $TASK_ID --path "computed.json"
Real-World Examples
Example 1: Data Analysis System
ts
// 1. Protect sensitive dataset
const { address: datasetAddress } = await dataProtectorCore.protectData({
name: 'Customer Analytics Data',
data: {
customers: {
'0': { id: 1, purchases: 1500, category: 'premium' },
'1': { id: 2, purchases: 800, category: 'standard' },
'2': { id: 3, purchases: 2200, category: 'premium' },
},
},
});
// 2. Grant access to analytics iApp
await dataProtectorCore.grantAccess({
protectedData: datasetAddress,
authorizedApp: '0xanalytics...', // Analytics iApp address
authorizedUser: '0x789abc...',
pricePerAccess: 3,
numberOfAccess: 50,
});
// 3. Execute data analysis
const analysisResult = await dataProtectorCore.processProtectedData({
protectedData: datasetAddress,
app: '0xanalytics...',
args: '--analyze-customer-segments --output-format json',
appMaxPrice: 10,
});
Example 2: Oracle Price Update
ts
// 1. Protect trading data
const { address: tradingDataAddress } = await dataProtectorCore.protectData({
name: 'Trading Data',
data: {
trades: {
'2024-01-01': { price: 50000, volume: 100 },
'2024-01-02': { price: 51000, volume: 150 },
},
},
});
// 2. Grant access to oracle iApp
await dataProtectorCore.grantAccess({
protectedData: tradingDataAddress,
authorizedApp: '0xoracle...', // Oracle iApp address
authorizedUser: '0x789abc...',
pricePerAccess: 5,
numberOfAccess: 100,
});
// 3. Execute oracle update
const oracleResult = await dataProtectorCore.processProtectedData({
protectedData: tradingDataAddress,
app: '0xoracle...',
args: '--update-price-feed --asset ETH',
appMaxPrice: 10,
});
Example 3: Automated Payment Processing
ts
// 1. Protect payment data
const { address: paymentDataAddress } = await dataProtectorCore.protectData({
name: 'Payment Data',
data: {
bankAccount: '1234567890',
routingNumber: '987654321',
accountHolder: 'John Doe',
monthlyAmount: 1000,
},
});
// 2. Grant access to payment iApp
await dataProtectorCore.grantAccess({
protectedData: paymentDataAddress,
authorizedApp: '0xpayment...', // Payment iApp address
authorizedUser: '0x789abc...',
pricePerAccess: 2,
numberOfAccess: 12, // Monthly payments
});
// 3. Execute payment processing
const paymentResult = await dataProtectorCore.processProtectedData({
protectedData: paymentDataAddress,
app: '0xpayment...',
args: '--process-monthly-payment',
secrets: {
1: 'bank-api-key',
},
appMaxPrice: 8,
});
Best Practices
1. Always Grant Access Before Execution
ts
// Grant access first
await dataProtectorCore.grantAccess({
protectedData: protectedDataAddress,
authorizedApp: '0x456def...',
authorizedUser: '0x789abc...',
pricePerAccess: 5,
numberOfAccess: 10,
});
const result = await dataProtectorCore.processProtectedData({
protectedData: protectedDataAddress,
app: '0x456def...',
appMaxPrice: 10,
});
2. Monitor Access Usage
ts
// Check access usage regularly
const grantedAccess = await dataProtectorCore.getGrantedAccess({
protectedData: '0x123abc...',
authorizedApp: '0x456def...',
authorizedUser: '0x789abc...',
});
console.log('Remaining access:', grantedAccess.count);
3. Use Appropriate Price Limits
ts
// Set reasonable price limits
const result = await dataProtectorCore.processProtectedData({
protectedData: '0x123abc...',
app: '0x456def...',
appMaxPrice: 10, // Set appropriate limit
});
4. Handle Results Properly
ts
// Store task ID and retrieve results later
const result = await dataProtectorCore.processProtectedData({
protectedData: '0x123abc...',
app: '0x456def...',
appMaxPrice: 10,
});
// Store task ID for later retrieval
const taskId = result.taskId;
// Later, retrieve the result
const taskResult = await dataProtectorCore.getResultFromCompletedTask({
taskId: taskId,
});
Next Steps
Now that you understand how to use iApps with protected data:
- Learn about Different Ways to Execute iApps
- Explore How to Pay for Executions
- Check out our Add Inputs to Execution guide