Skip to content

Commit 71a6906

Browse files
authored
Merge pull request #231 from Dstack-TEE/addr-as-appid
KmsAuth: Use the contract address as app-id
2 parents f3e0537 + bb84ddd commit 71a6906

13 files changed

Lines changed: 95 additions & 295 deletions

File tree

docs/deployment.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ After the dstack-vmm is ready, you can deploy an app on it following the steps b
295295
The on-chain registration process includes two steps:
296296

297297
1. Deploy an App's control contract AppAuth. Developers can develop their own or choose the reference contract from the Dstack repository. Custom contracts need to implement the IAppAuth interface.
298-
2. Call KmsAuth.registerApp(appAuthAddress) to register and obtain the App Id
298+
2. Call KmsAuth.registerApp(appAuthAddress) to register the contract.
299299

300300
The Dstack repository provides scripts to complete these two steps:
301301

@@ -352,7 +352,6 @@ Call the hardhat command to add it to the whitelist (using AppAuth as an example
352352

353353
```bash
354354
export PRIVATE_KEY=<your eth private key here>
355-
export KMS_CONTRACT_ADDRESS=0xFE6C45aE66344CAEF5E5D7e2cbD476286D651875
356355
npx hardhat app:add-hash --network phala --app-id 0xA35b434eE853fdf9c2Bf48Fa1583Ac1332d50255 0x44d9cb98aaa6ab11f5729fc7d6fd58117585e0e3fbec621612dcee6b2dfbcde5
357356
```
358357

kms/auth-eth/contracts/AppAuth.sol

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@ contract AppAuth is
1616
IAppAuth,
1717
IAppAuthBasicManagement
1818
{
19-
// App ID this contract is managing
20-
address public appId;
21-
2219
// Mapping of allowed compose hashes for this app
2320
mapping(bytes32 => bool) public allowedComposeHashes;
2421

@@ -43,31 +40,28 @@ contract AppAuth is
4340
// Initialize the contract
4441
function initialize(
4542
address initialOwner,
46-
address _appId,
4743
bool _disableUpgrades,
4844
bool _allowAnyDevice,
4945
bytes32 initialDeviceId,
5046
bytes32 initialComposeHash
5147
) public initializer {
5248
require(initialOwner != address(0), "invalid owner address");
53-
require(_appId != address(0), "invalid app ID");
54-
55-
appId = _appId;
49+
5650
_upgradesDisabled = _disableUpgrades;
5751
allowAnyDevice = _allowAnyDevice;
58-
52+
5953
// Add initial device if provided
6054
if (initialDeviceId != bytes32(0)) {
6155
allowedDeviceIds[initialDeviceId] = true;
6256
emit DeviceAdded(initialDeviceId);
6357
}
64-
58+
6559
// Add initial compose hash if provided
6660
if (initialComposeHash != bytes32(0)) {
6761
allowedComposeHashes[initialComposeHash] = true;
6862
emit ComposeHashAdded(initialComposeHash);
6963
}
70-
64+
7165
__Ownable_init(initialOwner);
7266
__UUPSUpgradeable_init();
7367
__ERC165_init();
@@ -131,11 +125,6 @@ contract AppAuth is
131125
function isAppAllowed(
132126
IAppAuth.AppBootInfo calldata bootInfo
133127
) external view override returns (bool isAllowed, string memory reason) {
134-
// Check if this controller is responsible for the app
135-
if (bootInfo.appId != appId) {
136-
return (false, "Wrong app controller");
137-
}
138-
139128
// Check if compose hash is allowed
140129
if (!allowedComposeHashes[bootInfo.composeHash]) {
141130
return (false, "Compose hash not allowed");

kms/auth-eth/contracts/KmsAuth.sol

Lines changed: 30 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,8 @@ contract KmsAuth is
3030
/// @custom:oz-renamed-from tproxyAppId
3131
string public gatewayAppId;
3232

33-
// Struct to store App configuration
34-
struct AppConfig {
35-
bool isRegistered;
36-
address controller;
37-
}
38-
3933
// Mapping of registered apps
40-
mapping(address => AppConfig) public apps;
34+
mapping(address => bool) public registeredApps;
4135

4236
// Mapping of allowed aggregated MR measurements for running KMS
4337
mapping(bytes32 => bool) public kmsAllowedAggregatedMrs;
@@ -48,9 +42,6 @@ contract KmsAuth is
4842
// Mapping of allowed image measurements
4943
mapping(bytes32 => bool) public allowedOsImages;
5044

51-
// Sequence number for app IDs - per user
52-
mapping(address => uint256) public nextAppSequence;
53-
5445
// AppAuth implementation contract address for factory deployment
5546
address public appAuthImplementation;
5647

@@ -65,7 +56,7 @@ contract KmsAuth is
6556
event OsImageHashRemoved(bytes32 osImageHash);
6657
event GatewayAppIdSet(string gatewayAppId);
6758
event AppAuthImplementationSet(address implementation);
68-
event AppDeployedViaFactory(address indexed appId, address indexed proxyAddress, address indexed deployer);
59+
event AppDeployedViaFactory(address indexed appId, address indexed deployer);
6960

7061
/// @custom:oz-upgrades-unsafe-allow constructor
7162
constructor() {
@@ -77,7 +68,7 @@ contract KmsAuth is
7768
__Ownable_init(initialOwner);
7869
__UUPSUpgradeable_init();
7970
__ERC165_init();
80-
71+
8172
// Set AppAuth implementation if provided
8273
if (_appAuthImplementation != address(0)) {
8374
appAuthImplementation = _appAuthImplementation;
@@ -130,32 +121,11 @@ contract KmsAuth is
130121
emit GatewayAppIdSet(appId);
131122
}
132123

133-
// View next app id
134-
function nextAppId() public view returns (address appId) {
135-
bytes32 fullHash = keccak256(
136-
abi.encodePacked(
137-
address(this),
138-
msg.sender,
139-
nextAppSequence[msg.sender]
140-
)
141-
);
142-
return address(uint160(uint256(fullHash)));
143-
}
144-
145-
// Internal function to register an app with the given app ID and controller
146-
function _registerAppInternal(address appId, address controller) private {
147-
require(!apps[appId].isRegistered, "App already registered");
148-
apps[appId].isRegistered = true;
149-
apps[appId].controller = controller;
150-
nextAppSequence[msg.sender]++;
151-
emit AppRegistered(appId);
152-
}
153-
154124
// Function to register an app
155-
function registerApp(address controller) external {
156-
require(controller != address(0), "Invalid controller address");
157-
address appId = nextAppId();
158-
_registerAppInternal(appId, controller);
125+
function registerApp(address appId) public {
126+
require(appId != address(0), "Invalid app ID");
127+
registeredApps[appId] = true;
128+
emit AppRegistered(appId);
159129
}
160130

161131
// Function to set AppAuth implementation contract address
@@ -172,30 +142,25 @@ contract KmsAuth is
172142
bool allowAnyDevice,
173143
bytes32 initialDeviceId,
174144
bytes32 initialComposeHash
175-
) external returns (address appId, address proxyAddress) {
145+
) external returns (address appId) {
176146
require(appAuthImplementation != address(0), "AppAuth implementation not set");
177147
require(initialOwner != address(0), "Invalid owner address");
178-
179-
// Calculate app ID
180-
appId = nextAppId();
181-
148+
182149
// Prepare initialization data
183150
bytes memory initData = abi.encodeWithSelector(
184-
bytes4(keccak256("initialize(address,address,bool,bool,bytes32,bytes32)")),
151+
bytes4(keccak256("initialize(address,bool,bool,bytes32,bytes32)")),
185152
initialOwner,
186-
appId,
187153
disableUpgrades,
188154
allowAnyDevice,
189155
initialDeviceId,
190156
initialComposeHash
191157
);
192-
158+
193159
// Deploy proxy contract
194-
proxyAddress = address(new ERC1967Proxy(appAuthImplementation, initData));
195-
160+
appId = address(new ERC1967Proxy(appAuthImplementation, initData));
196161
// Register to KMS
197-
_registerAppInternal(appId, proxyAddress);
198-
emit AppDeployedViaFactory(appId, proxyAddress, msg.sender);
162+
registerApp(appId);
163+
emit AppDeployedViaFactory(appId, msg.sender);
199164
}
200165

201166
// Function to register an aggregated MR measurement
@@ -269,23 +234,31 @@ contract KmsAuth is
269234
AppBootInfo calldata bootInfo
270235
) external view override returns (bool isAllowed, string memory reason) {
271236
// Check if app is registered
272-
if (!apps[bootInfo.appId].isRegistered) {
237+
if (!registeredApps[bootInfo.appId]) {
273238
return (false, "App not registered");
274239
}
275-
276-
// Check aggregated MR and image measurements
240+
// Check if the OS image is allowed
277241
if (!allowedOsImages[bootInfo.osImageHash]) {
278242
return (false, "OS image is not allowed");
279243
}
280244

281-
// Ask the app controller if the app is allowed to boot
282-
address controller = apps[bootInfo.appId].controller;
283-
if (controller == address(0)) {
284-
return (false, "App controller not set");
245+
// Check if the contract exists at the appId address
246+
if (!isContract(bootInfo.appId)) {
247+
return (false, "App not deployed or invalid address");
285248
}
286-
return IAppAuth(controller).isAppAllowed(bootInfo);
249+
250+
// Call the app's isAppAllowed function
251+
return IAppAuth(bootInfo.appId).isAppAllowed(bootInfo);
287252
}
288253

289254
// Add storage gap for upgradeable contracts
290255
uint256[50] private __gap;
291256
}
257+
258+
function isContract(address addr) view returns (bool){
259+
uint32 size;
260+
assembly {
261+
size := extcodesize(addr)
262+
}
263+
return (size > 0);
264+
}

kms/auth-eth/foundry-cast-cheatsheet.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,6 @@ cast call $KMS_CONTRACT_ADDRESS "isAppAllowed((address,bytes32,address,bytes32,b
259259
### Query Operations
260260

261261
```bash
262-
# Get app ID
263-
cast call $APP_AUTH_ADDRESS "appId()" --rpc-url $RPC_URL
264-
# To decode: cast abi-decode "appId()(address)" RETURN_DATA
265-
266262
# Get owner
267263
cast call $APP_AUTH_ADDRESS "owner()" --rpc-url $RPC_URL
268264
# To decode: cast abi-decode "owner()(address)" RETURN_DATA

kms/auth-eth/hardhat.config.ts

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,7 @@ async function getKmsAuth(ethers: any) {
7676
}
7777

7878
async function getAppAuth(ethers: any, appId: string) {
79-
const kmsAuth = await getKmsAuth(ethers);
80-
const controller = (await kmsAuth.apps(appId)).controller;
81-
if (controller === ethers.ZeroAddress) {
82-
throw new Error("AppAuth contract not found");
83-
}
84-
console.log("AppAuth address:", controller);
85-
return await ethers.getContractAt("AppAuth", controller);
79+
return await ethers.getContractAt("AppAuth", appId);
8680
}
8781

8882
// KMS Contract Tasks
@@ -240,14 +234,6 @@ task("kms:get-app-implementation", "Get current AppAuth implementation address")
240234
console.log("AppAuth implementation:", impl);
241235
});
242236

243-
task("app:show-controller", "Show the controller of an AppAuth contract")
244-
.addPositionalParam("appId", "App ID")
245-
.setAction(async ({ appId }, { ethers }) => {
246-
const kmsAuth = await getKmsAuth(ethers);
247-
const controller = await kmsAuth.apps(appId).then((app: any) => app.controller);
248-
console.log("AppAuth controller:", controller);
249-
});
250-
251237
task("app:deploy", "Deploy AppAuth with a UUPS proxy")
252238
.addFlag("allowAnyDevice", "Allow any device to boot this app")
253239
.addOptionalParam("device", "Initial device ID", "", types.string)
@@ -260,8 +246,6 @@ task("app:deploy", "Deploy AppAuth with a UUPS proxy")
260246
console.log("Account balance:", await accountBalance(ethers, deployerAddress));
261247

262248
const kmsContract = await getKmsAuth(ethers);
263-
const appId = await kmsContract.nextAppId();
264-
console.log("App ID:", appId);
265249

266250
// Parse device and hash (convert to bytes32, use 0x0 if empty)
267251
const deviceId = taskArgs.device ? taskArgs.device.trim() : "0x0000000000000000000000000000000000000000000000000000000000000000";
@@ -278,7 +262,6 @@ task("app:deploy", "Deploy AppAuth with a UUPS proxy")
278262
// Use standard deployment - all cases use the same 6-parameter initializer
279263
const appAuth = await deployContract(hre, "AppAuth", [
280264
deployerAddress,
281-
appId,
282265
false,
283266
taskArgs.allowAnyDevice,
284267
deviceId,
@@ -395,8 +378,7 @@ task("kms:create-app", "Create AppAuth via KMS factory method (single transactio
395378

396379
if (factoryEvent && registeredEvent) {
397380
console.log("✅ App deployed and registered successfully!");
398-
console.log("App ID:", factoryEvent.appId);
399-
console.log("Proxy Address:", factoryEvent.proxyAddress);
381+
console.log("Proxy Address (App Id):", factoryEvent.appId);
400382
console.log("Owner:", factoryEvent.deployer);
401383
console.log("Transaction hash:", tx.hash);
402384

kms/auth-eth/src/server.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,9 @@ export async function build(): Promise<FastifyInstance> {
9999
try {
100100
return await server.ethereum.checkBoot(request.body, true);
101101
} catch (error) {
102-
console.error(error);
102+
if (!(error instanceof Error && "Test backend error" == error.message)) {
103+
console.error(error);
104+
}
103105
reply.code(200).send({
104106
isAllowed: false,
105107
gatewayAppId: '',

0 commit comments

Comments
 (0)