@abtnode/core 1.8.68-beta-500af7e5 → 1.8.68

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,6 @@ const { EventEmitter } = require('events');
2
2
  const fs = require('fs-extra');
3
3
  const { fileURLToPath } = require('url');
4
4
  const path = require('path');
5
- const pick = require('lodash/pick');
6
5
  const cloneDeep = require('lodash/cloneDeep');
7
6
  const { toBase58 } = require('@ocap/util');
8
7
 
@@ -162,11 +161,7 @@ class BundleDownloader extends EventEmitter {
162
161
  }
163
162
  ctrlStore[rootDid].set(did, cancelCtrl);
164
163
 
165
- const headers = pick(context.headers ? cloneDeep(context.headers) : {}, [
166
- 'x-server-did',
167
- 'x-server-public-key',
168
- 'x-server-signature',
169
- ]);
164
+ const headers = context.headers ? cloneDeep(context.headers) : {};
170
165
  const exist = (context.downloadTokenList || []).find((x) => x.did === did);
171
166
  if (exist) {
172
167
  headers['x-download-token'] = exist.token;
@@ -4,7 +4,6 @@ const fs = require('fs-extra');
4
4
  const path = require('path');
5
5
  const flat = require('flat');
6
6
  const get = require('lodash/get');
7
- const merge = require('lodash/merge');
8
7
  const pick = require('lodash/pick');
9
8
  const cloneDeep = require('lodash/cloneDeep');
10
9
  const semver = require('semver');
@@ -16,18 +15,20 @@ const { isNFTExpired, getNftExpirationDate } = require('@abtnode/util/lib/nft');
16
15
  const didDocument = require('@abtnode/util/lib/did-document');
17
16
  const { sign } = require('@arcblock/jwt');
18
17
  const { isValid: isValidDid } = require('@arcblock/did');
18
+ const { verifyPresentation } = require('@arcblock/vc');
19
19
  const { toSvg: createDidLogo } =
20
20
  process.env.NODE_ENV !== 'test' ? require('@arcblock/did-motif') : require('@arcblock/did-motif/dist/did-motif.cjs');
21
21
  const getBlockletInfo = require('@blocklet/meta/lib/info');
22
22
  const sleep = require('@abtnode/util/lib/sleep');
23
23
 
24
24
  const logger = require('@abtnode/logger')('@abtnode/core:blocklet:manager');
25
+ const { getVcFromPresentation } = require('@abtnode/util/lib/vc');
25
26
  const {
27
+ VC_TYPE_BLOCKLET_PURCHASE,
26
28
  WHO_CAN_ACCESS,
27
29
  SERVER_ROLES,
28
30
  WHO_CAN_ACCESS_PREFIX_ROLES,
29
31
  BLOCKLET_INSTALL_TYPE,
30
- NODE_MODES,
31
32
  } = require('@abtnode/constant');
32
33
 
33
34
  const getBlockletEngine = require('@blocklet/meta/lib/engine');
@@ -48,7 +49,7 @@ const getComponentProcessId = require('@blocklet/meta/lib/get-component-process-
48
49
  const toBlockletDid = require('@blocklet/meta/lib/did');
49
50
  const { validateMeta } = require('@blocklet/meta/lib/validate');
50
51
  const { update: updateMetaFile } = require('@blocklet/meta/lib/file');
51
- const { titleSchema, updateMountPointSchema, environmentNameSchema } = require('@blocklet/meta/lib/schema');
52
+ const { titleSchema, mountPointSchema, environmentNameSchema } = require('@blocklet/meta/lib/schema');
52
53
  const hasReservedKey = require('@blocklet/meta/lib/has-reserved-key');
53
54
  const Lock = require('@abtnode/util/lib/lock');
54
55
 
@@ -110,10 +111,6 @@ const {
110
111
  validateAppConfig,
111
112
  checkDuplicateAppSk,
112
113
  checkDuplicateMountPoint,
113
- validateStore,
114
- validateInServerless,
115
- isRotatingAppSk,
116
- isRotatingAppDid,
117
114
  } = require('../../util/blocklet');
118
115
  const StoreUtil = require('../../util/store');
119
116
  const states = require('../../states');
@@ -196,14 +193,13 @@ class BlockletManager extends BaseBlockletManager {
196
193
  /**
197
194
  * @param {*} dataDirs generate by ../../util:getDataDirs
198
195
  */
199
- constructor({ dataDirs, startQueue, installQueue, backupQueue, daemon = false, teamManager }) {
196
+ constructor({ dataDirs, startQueue, installQueue, daemon = false, teamManager }) {
200
197
  super();
201
198
 
202
199
  this.dataDirs = dataDirs;
203
200
  this.installDir = dataDirs.blocklets;
204
201
  this.startQueue = startQueue;
205
202
  this.installQueue = installQueue;
206
- this.backupQueue = backupQueue;
207
203
  this.teamManager = teamManager;
208
204
 
209
205
  // cached installed blocklets for performance
@@ -246,8 +242,6 @@ class BlockletManager extends BaseBlockletManager {
246
242
  * did: string;
247
243
  * title: string;
248
244
  * description: string;
249
- * storeUrl: string;
250
- * appSk: string;
251
245
  * sync: boolean = false; // download synchronously, not use queue
252
246
  * delay: number; // push download task to queue after a delay
253
247
  * downloadTokenList: Array<{did: string, token: string}>;
@@ -270,7 +264,6 @@ class BlockletManager extends BaseBlockletManager {
270
264
 
271
265
  const info = await states.node.read();
272
266
 
273
- // Note: if you added new header here, please change core/state/lib/blocklet/downloader/bundle-downloader.js to use that header
274
267
  context.headers = Object.assign(context?.headers || {}, {
275
268
  'x-server-did': info.did,
276
269
  'x-server-public-key': info.pk,
@@ -285,31 +278,28 @@ class BlockletManager extends BaseBlockletManager {
285
278
  context.startImmediately = !!params.startImmediately;
286
279
  }
287
280
 
288
- const { appSk } = params;
289
-
290
281
  if (type === BLOCKLET_INSTALL_TYPE.URL) {
291
282
  const { url, controller, sync, delay } = params;
292
- return this._installFromUrl({ url, controller, sync, delay, appSk }, context);
283
+ return this._installFromUrl({ url, controller, sync, delay }, context);
293
284
  }
294
285
 
295
286
  if (type === BLOCKLET_INSTALL_TYPE.UPLOAD) {
296
287
  const { file, did, diffVersion, deleteSet } = params;
297
- return this._installFromUpload({ file, did, diffVersion, deleteSet, appSk }, context);
288
+ return this._installFromUpload({ file, did, diffVersion, deleteSet, context });
298
289
  }
299
290
 
300
291
  if (type === BLOCKLET_INSTALL_TYPE.STORE) {
301
292
  const { did, controller, sync, delay, storeUrl } = params;
302
- return this._installFromStore({ did, controller, sync, delay, storeUrl, appSk }, context);
293
+ return this._installFromStore({ did, controller, sync, delay, storeUrl }, context);
303
294
  }
304
295
 
305
296
  if (type === BLOCKLET_INSTALL_TYPE.CREATE) {
306
- const { title, description } = params;
307
- return this._installFromCreate({ title, description, appSk }, context);
297
+ return this._installFromCreate({ title: params.title, description: params.description }, context);
308
298
  }
309
299
 
310
300
  if (type === BLOCKLET_INSTALL_TYPE.RESTORE) {
311
- const { url } = params;
312
- return this._installFromBackup({ url, appSk }, context);
301
+ const { url, blockletSecretKey } = params;
302
+ return this._installFromBackup({ url, blockletSecretKey }, context);
313
303
  }
314
304
 
315
305
  // should not be here
@@ -353,16 +343,10 @@ class BlockletManager extends BaseBlockletManager {
353
343
  },
354
344
  context = {}
355
345
  ) {
356
- const mountPoint = await updateMountPointSchema.validateAsync(tmpMountPoint);
346
+ const mountPoint = await mountPointSchema.validateAsync(tmpMountPoint);
357
347
  logger.debug('start install component', { rootDid, mountPoint, url });
358
348
 
359
349
  if (file) {
360
- // TODO: 如何触发这种场景?
361
- const info = await states.node.read();
362
- if (info.mode === NODE_MODES.SERVERLESS) {
363
- throw new Error("Can't install component in serverless-mode server via upload");
364
- }
365
-
366
350
  return this._installComponentFromUpload({
367
351
  rootDid,
368
352
  mountPoint,
@@ -376,11 +360,6 @@ class BlockletManager extends BaseBlockletManager {
376
360
  }
377
361
 
378
362
  if (url) {
379
- const info = await states.node.read();
380
- if (info.mode === NODE_MODES.SERVERLESS) {
381
- validateStore(info, url);
382
- }
383
-
384
363
  return this._installComponentFromUrl({
385
364
  rootDid,
386
365
  mountPoint,
@@ -452,6 +431,25 @@ class BlockletManager extends BaseBlockletManager {
452
431
  return { isInstalled: !!blocklet, isRunning, blockletDid, isExternal };
453
432
  }
454
433
 
434
+ async installBlockletFromVc({ vcPresentation, challenge }, context) {
435
+ logger.info('Install from vc');
436
+ const vc = getVcFromPresentation(vcPresentation);
437
+
438
+ // FIXME: 这里的 trustedIssuers 相当于相信任何 VC,需要想更安全的方法
439
+ verifyPresentation({ presentation: vcPresentation, trustedIssuers: [get(vc, 'issuer.id')], challenge });
440
+
441
+ if (!vc.type.includes(VC_TYPE_BLOCKLET_PURCHASE)) {
442
+ throw new Error(`Expect ${VC_TYPE_BLOCKLET_PURCHASE} VC type`);
443
+ }
444
+
445
+ const blockletUrl = get(vc, 'credentialSubject.purchased.blocklet.url');
446
+ const urlObject = new URL(blockletUrl);
447
+ const did = get(vc, 'credentialSubject.purchased.blocklet.id');
448
+ const registry = urlObject.origin;
449
+
450
+ return this._installFromStore({ did, registry }, context);
451
+ }
452
+
455
453
  async start({ did, throwOnError, checkHealthImmediately = false, e2eMode = false }, context) {
456
454
  logger.info('start blocklet', { did });
457
455
  // should check blocklet integrity
@@ -610,67 +608,32 @@ class BlockletManager extends BaseBlockletManager {
610
608
  }
611
609
 
612
610
  /**
613
- * FIXME: @wangshijun create audit log for this
614
- * @param {import('@abtnode/client').RequestBackupToSpacesInput} input
611
+ *
612
+ *
613
+ * @param {import('@abtnode/client').BackupToSpacesParams} input
615
614
  * @memberof BlockletManager
616
615
  */
617
- // eslint-disable-next-line no-unused-vars
618
- async backupToSpaces({ did }, context) {
619
- // add to queue
620
- // const ticket = this.backupQueue.push({
621
- // entity: 'blocklet',
622
- // action: 'backup-to-space',
623
- // did,
624
- // context,
625
- // });
626
-
627
- // ticket.on('failed', async (err) => {
628
- // logger.error('backup failed', { entity: 'blocklet', did, error: err });
629
- // this.emit('blocklet.backup.failed', { did, err });
630
- // this._createNotification(did, {
631
- // title: 'Blocklet Backup Failed',
632
- // description: `Blocklet backup failed with error: ${err.message || 'queue exception'}`,
633
- // entityType: 'blocklet',
634
- // entityId: did,
635
- // severity: 'error',
636
- // });
637
- // });
638
-
639
- const userDid = context.user.did;
640
- const { referrer } = context;
641
-
642
- // FIXME: @yejianchao did should be renamed to appDid
643
- const spacesBackup = new SpacesBackup({ did, event: this, userDid, referrer });
644
- this.emit(BlockletEvents.backupProgress, { did, message: 'Start backup...', progress: 10 });
616
+ async backupToSpaces(input) {
617
+ const spacesBackup = new SpacesBackup(input);
645
618
  await spacesBackup.backup();
646
- this.emit(BlockletEvents.backupProgress, { did, completed: true, progress: 100 });
647
619
  }
648
620
 
649
621
  /**
650
- * FIXME: @linchen support cancel
651
- * FIXME: @wangshijun create audit log for this
622
+ *
623
+ *
652
624
  * @param {import('@abtnode/client').RequestRestoreFromSpacesInput} input
653
625
  * @memberof BlockletManager
654
626
  */
655
- // eslint-disable-next-line no-unused-vars
656
- async restoreFromSpaces(input, context) {
657
- // FIXME: @yejianchao did should be renamed to appDid
658
- this.emit(BlockletEvents.restoreProgress, { did: input.appDid, message: 'Start restore...' });
659
-
660
- const userDid = context.user.did;
661
- const { referrer } = context;
627
+ async restoreFromSpaces(input) {
628
+ const spacesRestore = new SpacesRestore(input);
629
+ await spacesRestore.restore();
662
630
 
663
- const spacesRestore = new SpacesRestore({ ...input, event: this, userDid, referrer });
664
- const params = await spacesRestore.restore();
665
-
666
- this.emit(BlockletEvents.restoreProgress, { did: input.appDid, message: 'Installing blocklet...' });
631
+ // FIXME: 需要改成队列执行,本次失败,下次还需要重试,页面刷新后也能知道最新的状态
667
632
  await this._installFromBackup({
668
633
  url: `file://${spacesRestore.blockletRestoreDir}`,
634
+ blockletSecretKey: spacesRestore.blockletWallet.secretKey,
669
635
  moveDir: true,
670
- ...merge(...params),
671
636
  });
672
-
673
- this.emit(BlockletEvents.restoreProgress, { did: input.appDid, completed: true });
674
637
  }
675
638
 
676
639
  async restart({ did }, context) {
@@ -1040,9 +1003,8 @@ class BlockletManager extends BaseBlockletManager {
1040
1003
  return blocklets;
1041
1004
  }
1042
1005
 
1043
- // CAUTION: this method currently only support config by blocklet.meta.did
1044
1006
  // eslint-disable-next-line no-unused-vars
1045
- async config({ did, configs: newConfigs, skipHook, skipDidDocument }, context) {
1007
+ async config({ did, configs: newConfigs, skipHook }, context) {
1046
1008
  if (!Array.isArray(newConfigs)) {
1047
1009
  throw new Error('configs list is not an array');
1048
1010
  }
@@ -1072,7 +1034,7 @@ class BlockletManager extends BaseBlockletManager {
1072
1034
  throw new Error(`Cannot set ${x.key} to child blocklet`);
1073
1035
  }
1074
1036
 
1075
- await validateAppConfig(x, states);
1037
+ await validateAppConfig(x, rootDid, states);
1076
1038
  } else if (!BLOCKLET_CONFIGURABLE_KEY[x.key] && !isPreferenceKey(x)) {
1077
1039
  if (!(blocklet.meta.environments || []).some((y) => y.name === x.key)) {
1078
1040
  // forbid unknown format key
@@ -1095,26 +1057,14 @@ class BlockletManager extends BaseBlockletManager {
1095
1057
  });
1096
1058
  }
1097
1059
 
1098
- const willAppSkChange = isRotatingAppSk(newConfigs, blocklet.configs, blocklet.externalSk);
1099
- const willAppDidChange = isRotatingAppDid(newConfigs, blocklet.configs, blocklet.externalSk);
1100
-
1101
1060
  // update db
1102
1061
  await states.blockletExtras.setConfigs(dids, newConfigs);
1103
1062
 
1104
- if (willAppSkChange) {
1105
- const info = await states.node.read();
1106
- const { wallet } = getBlockletInfo(blocklet, info.sk);
1107
- const migratedFrom = blocklet.migratedFrom || [];
1108
- await states.blocklet.updateBlocklet(rootDid, {
1109
- migratedFrom: [
1110
- ...migratedFrom,
1111
- { appSk: wallet.secretKey, appDid: wallet.address, at: new Date().toISOString() },
1112
- ],
1113
- });
1114
- }
1063
+ const isSkOrWalletTypeChanged = newConfigs.find((item) =>
1064
+ [BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_SK, BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_WALLET_TYPE].includes(item.key)
1065
+ );
1115
1066
 
1116
- // FIXME: @zhenqiang best way to handle the did document: allow all appDids to resolve
1117
- if (willAppDidChange && !skipDidDocument) {
1067
+ if (isSkOrWalletTypeChanged) {
1118
1068
  await this._updateDidDocument(blocklet);
1119
1069
  }
1120
1070
 
@@ -1248,7 +1198,7 @@ class BlockletManager extends BaseBlockletManager {
1248
1198
  }
1249
1199
 
1250
1200
  async updateComponentMountPoint({ did, rootDid: inputRootDid, mountPoint: tmpMountPoint }, context) {
1251
- const mountPoint = await updateMountPointSchema.validateAsync(tmpMountPoint);
1201
+ const mountPoint = await mountPointSchema.validateAsync(tmpMountPoint);
1252
1202
 
1253
1203
  const blocklet = await states.blocklet.getBlocklet(inputRootDid);
1254
1204
 
@@ -1729,13 +1679,13 @@ class BlockletManager extends BaseBlockletManager {
1729
1679
  * /blocklet.json
1730
1680
  * /blocklet_extras.json
1731
1681
  * @see Blocklet 端到端备份方案的设计与实现(一期) https://team.arcblock.io/comment/discussions/e62084d5-fafa-489e-91d5-defcd6e93223
1732
- * @param {{ url: string, appSk: string, moveDir: boolean}} [{ url }={}]
1682
+ * @param {{ url: string, blockletSecretKey: string, moveDir: boolean}} [{ url }={}]
1733
1683
  * @param {Record<string, string>} [context={}]
1734
1684
  * @return {Promise<any>}
1735
1685
  * @memberof BlockletManager
1736
1686
  */
1737
- async _installFromBackup({ url, appSk, moveDir } = {}, context = {}) {
1738
- return installFromBackup({ url, appSk, moveDir, context, manager: this, states });
1687
+ async _installFromBackup({ url, blockletSecretKey, moveDir } = {}, context = {}) {
1688
+ return installFromBackup({ url, blockletSecretKey, moveDir, context, manager: this, states });
1739
1689
  }
1740
1690
 
1741
1691
  async ensureBlocklet(did, opts = {}) {
@@ -2117,14 +2067,6 @@ class BlockletManager extends BaseBlockletManager {
2117
2067
  // put BLOCKLET_APP_ID at root level for indexing
2118
2068
  blocklet.appDid = appSystemEnvironments.BLOCKLET_APP_ID;
2119
2069
 
2120
- if (!blocklet.migratedFrom) {
2121
- blocklet.migratedFrom = [];
2122
- }
2123
- // This can only be set once, can be used for indexing, will not change ever
2124
- if (!blocklet.appPid) {
2125
- blocklet.appPid = appSystemEnvironments.BLOCKLET_APP_PID;
2126
- }
2127
-
2128
2070
  // update state to db
2129
2071
  return states.blocklet.updateBlocklet(did, blocklet);
2130
2072
  }
@@ -2142,18 +2084,17 @@ class BlockletManager extends BaseBlockletManager {
2142
2084
  *
2143
2085
  * @param {{
2144
2086
  * did: string;
2087
+ * registry: string;
2145
2088
  * sync: boolean;
2146
2089
  * delay: number;
2147
2090
  * controller: Controller;
2148
- * appSk: string;
2149
- * storeUrl: string;
2150
2091
  * }} params
2151
2092
  * @param {*} context
2152
2093
  * @return {*}
2153
2094
  * @memberof BlockletManager
2154
2095
  */
2155
2096
  async _installFromStore(params, context) {
2156
- const { did, storeUrl, sync, delay, controller, appSk } = params;
2097
+ const { did, storeUrl, sync, delay, controller } = params;
2157
2098
 
2158
2099
  logger.debug('start install blocklet', { did });
2159
2100
  if (!isValidDid(did)) {
@@ -2197,7 +2138,6 @@ class BlockletManager extends BaseBlockletManager {
2197
2138
  sync,
2198
2139
  delay,
2199
2140
  controller,
2200
- appSk,
2201
2141
  context,
2202
2142
  });
2203
2143
  }
@@ -2214,14 +2154,13 @@ class BlockletManager extends BaseBlockletManager {
2214
2154
  * sync: boolean;
2215
2155
  * delay: number;
2216
2156
  * controller: Controller;
2217
- * appSk: string;
2218
2157
  * }} params
2219
2158
  * @param {{}} context
2220
2159
  * @return {*}
2221
2160
  * @memberof BlockletManager
2222
2161
  */
2223
2162
  async _installFromUrl(params, context) {
2224
- const { url, sync, delay, controller, appSk } = params;
2163
+ const { url, sync, delay, controller } = params;
2225
2164
 
2226
2165
  logger.debug('start install blocklet', { url });
2227
2166
 
@@ -2235,18 +2174,13 @@ class BlockletManager extends BaseBlockletManager {
2235
2174
 
2236
2175
  // install from store if url is a store url
2237
2176
  const { inStore, registryUrl, blockletDid: bundleDid } = await StoreUtil.parseSourceUrl(url, controller);
2238
-
2239
- const nodeInfo = await states.node.read();
2240
-
2241
- await validateStore(nodeInfo, registryUrl);
2242
-
2243
2177
  if (inStore) {
2244
2178
  const exist = await states.blocklet.getBlocklet(blockletDid);
2245
2179
  if (exist) {
2246
2180
  return this.upgrade({ did: blockletDid, storeUrl: registryUrl, sync, delay }, context);
2247
2181
  }
2248
2182
 
2249
- return this._installFromStore({ did: bundleDid, storeUrl: registryUrl, controller, sync, delay, appSk }, context);
2183
+ return this._installFromStore({ did: bundleDid, storeUrl: registryUrl, controller, sync, delay }, context);
2250
2184
  }
2251
2185
 
2252
2186
  const meta = ensureMeta(bundleMeta, { name: blockletName, did: blockletDid });
@@ -2272,7 +2206,6 @@ class BlockletManager extends BaseBlockletManager {
2272
2206
  sync,
2273
2207
  delay,
2274
2208
  controller,
2275
- appSk,
2276
2209
  context,
2277
2210
  });
2278
2211
  }
@@ -2377,7 +2310,7 @@ class BlockletManager extends BaseBlockletManager {
2377
2310
  );
2378
2311
  }
2379
2312
 
2380
- async _installFromCreate({ title, description, appSk }, context = {}) {
2313
+ async _installFromCreate({ title, description }, context = {}) {
2381
2314
  logger.debug('create blocklet', { title, description });
2382
2315
 
2383
2316
  await joi.string().label('title').max(20).required().validateAsync(title);
@@ -2405,9 +2338,11 @@ class BlockletManager extends BaseBlockletManager {
2405
2338
  };
2406
2339
  const meta = validateMeta(rawMeta);
2407
2340
 
2408
- await states.blocklet.addBlocklet({ meta, source: BlockletSource.custom, externalSk: !!appSk });
2341
+ await states.blocklet.addBlocklet({
2342
+ meta,
2343
+ source: BlockletSource.custom,
2344
+ });
2409
2345
  await this._setConfigsFromMeta(did);
2410
- await this._setAppSk(did, appSk);
2411
2346
 
2412
2347
  // check duplicate appSk
2413
2348
  await checkDuplicateAppSk({ did, states });
@@ -2447,7 +2382,7 @@ class BlockletManager extends BaseBlockletManager {
2447
2382
  return { cwd, tarFile };
2448
2383
  }
2449
2384
 
2450
- async _installFromUpload({ file, did, diffVersion, deleteSet, appSk }, context) {
2385
+ async _installFromUpload({ file, did, diffVersion, deleteSet, context }) {
2451
2386
  logger.info('install blocklet', { from: 'upload file' });
2452
2387
  const { tarFile } = await this._downloadFromUpload(file);
2453
2388
 
@@ -2539,14 +2474,12 @@ class BlockletManager extends BaseBlockletManager {
2539
2474
  source: BlockletSource.upload,
2540
2475
  deployedFrom: `Upload by ${context.user.fullName}`,
2541
2476
  children,
2542
- externalSk: !!appSk,
2543
2477
  });
2544
2478
 
2545
2479
  const action = 'install';
2546
2480
  const oldState = { extraState: oldExtraState };
2547
2481
  try {
2548
2482
  await this._setConfigsFromMeta(meta.did);
2549
- await this._setAppSk(appSk);
2550
2483
  await validateBlocklet(blocklet);
2551
2484
 
2552
2485
  // check duplicate appSk
@@ -2843,7 +2776,6 @@ class BlockletManager extends BaseBlockletManager {
2843
2776
  * meta: {}; // blocklet meta
2844
2777
  * source: number; // example: BlockletSource.registry,
2845
2778
  * deployedFrom: string;
2846
- * appSk: string;
2847
2779
  * context: {}
2848
2780
  * sync: boolean = false;
2849
2781
  * delay: number;
@@ -2853,15 +2785,10 @@ class BlockletManager extends BaseBlockletManager {
2853
2785
  * @memberof BlockletManager
2854
2786
  */
2855
2787
  async _install(params) {
2856
- const { meta, source, deployedFrom, context, sync, delay, controller, appSk } = params;
2788
+ const { meta, source, deployedFrom, context, sync, delay, controller } = params;
2857
2789
 
2858
2790
  validateBlockletMeta(meta, { ensureDist: true });
2859
2791
 
2860
- const info = await states.node.read();
2861
- if (info.mode === NODE_MODES.SERVERLESS) {
2862
- validateInServerless({ blockletMeta: meta });
2863
- }
2864
-
2865
2792
  const { name, did, version } = meta;
2866
2793
 
2867
2794
  const oldExtraState = await states.blockletExtras.findOne({ did: meta.did });
@@ -2874,7 +2801,6 @@ class BlockletManager extends BaseBlockletManager {
2874
2801
  source,
2875
2802
  deployedFrom,
2876
2803
  children,
2877
- externalSk: !!appSk,
2878
2804
  });
2879
2805
 
2880
2806
  await validateBlocklet(blocklet);
@@ -2882,7 +2808,6 @@ class BlockletManager extends BaseBlockletManager {
2882
2808
  await states.blockletExtras.addMeta({ did, meta: { did, name }, controller });
2883
2809
 
2884
2810
  await this._setConfigsFromMeta(did);
2885
- await this._setAppSk(did, appSk);
2886
2811
 
2887
2812
  // check duplicate appSk
2888
2813
  await checkDuplicateAppSk({ did, states });
@@ -3480,31 +3405,12 @@ class BlockletManager extends BaseBlockletManager {
3480
3405
  }
3481
3406
  }
3482
3407
 
3483
- async _setAppSk(did, appSk, context) {
3484
- if (process.env.NODE_ENV === 'production' && !appSk) {
3485
- throw new Error(`appSk for blocklet ${did} is required`);
3486
- }
3487
-
3488
- if (appSk) {
3489
- await this.config(
3490
- {
3491
- did,
3492
- configs: [{ key: 'BLOCKLET_APP_SK', value: appSk, secure: true }],
3493
- skipHook: true,
3494
- skipDidDocument: true,
3495
- },
3496
- context
3497
- );
3498
- }
3499
- }
3500
-
3501
3408
  async _findNextCustomBlockletName(leftTimes = 10) {
3502
3409
  if (leftTimes <= 0) {
3503
3410
  throw new Error('Generate custom blocklet did too many times');
3504
3411
  }
3505
3412
  const number = await states.node.increaseCustomBlockletNumber();
3506
3413
  const name = `custom-${number}`;
3507
- // MEMO: 空壳 APP可以保留原有的 did 生成逻辑
3508
3414
  const did = toBlockletDid(name);
3509
3415
  const blocklet = await states.blocklet.getBlocklet(did);
3510
3416
  if (blocklet) {
@@ -19,7 +19,7 @@ const { validateBlocklet, checkDuplicateAppSk, getAppDirs } = require('../../../
19
19
  * }} param0
20
20
  * @returns
21
21
  */
22
- module.exports = async ({ url, appSk, moveDir, context = {}, states, manager } = {}) => {
22
+ module.exports = async ({ url, blockletSecretKey, moveDir, context = {}, states, manager } = {}) => {
23
23
  // TODO: support more url schema feature (http, did-spaces)
24
24
  if (!url.startsWith('file://')) {
25
25
  throw new Error('url must starts with file://');
@@ -71,17 +71,17 @@ module.exports = async ({ url, appSk, moveDir, context = {}, states, manager } =
71
71
  throw new Error('blocklet is already exist');
72
72
  }
73
73
 
74
- if (appSk) {
74
+ if (blockletSecretKey) {
75
75
  extra.configs = extra.configs || [];
76
76
  const skConfig = extra.configs.find((x) => x.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_SK);
77
77
  if (skConfig) {
78
- skConfig.value = appSk;
78
+ skConfig.value = blockletSecretKey;
79
79
  skConfig.secure = true;
80
80
  skConfig.shared = false;
81
81
  } else {
82
82
  extra.configs.push({
83
83
  key: BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_SK,
84
- value: appSk,
84
+ value: blockletSecretKey,
85
85
  secure: true,
86
86
  shared: false,
87
87
  });
@@ -1,9 +1,8 @@
1
1
  const { removeSync, outputJsonSync, readFileSync } = require('fs-extra');
2
2
  const { isEmpty, cloneDeep } = require('lodash');
3
3
  const { join } = require('path');
4
- const { Hasher } = require('@ocap/mcrypto');
5
- const { toBuffer } = require('@ocap/util');
6
4
  const security = require('@abtnode/util/lib/security');
5
+ const { BLOCKLET_CONFIGURABLE_KEY } = require('@blocklet/constant');
7
6
  const states = require('../../../states');
8
7
  const { BaseBackup } = require('./base');
9
8
 
@@ -33,7 +32,7 @@ class BlockletExtrasBackup extends BaseBackup {
33
32
  throw new Error('blockletExtra cannot be empty');
34
33
  }
35
34
 
36
- return this.cleanData(blockletExtra);
35
+ return this.cleanDate(blockletExtra);
37
36
  }
38
37
 
39
38
  /**
@@ -43,7 +42,7 @@ class BlockletExtrasBackup extends BaseBackup {
43
42
  * @return {Promise<void>}
44
43
  * @memberof BlockletExtrasBackup
45
44
  */
46
- async cleanData(blockletExtraInput) {
45
+ async cleanDate(blockletExtraInput) {
47
46
  const blockletExtra = cloneDeep(blockletExtraInput);
48
47
 
49
48
  const queue = [blockletExtra];
@@ -58,7 +57,7 @@ class BlockletExtrasBackup extends BaseBackup {
58
57
  }
59
58
 
60
59
  // 加解密
61
- this.encryptBlockletConfigs(currentBlockletExtra.configs);
60
+ this.useBlockletEncryptConfigs(currentBlockletExtra.configs);
62
61
 
63
62
  if (currentBlockletExtra?.children) {
64
63
  queue.push(...currentBlockletExtra.children);
@@ -75,28 +74,33 @@ class BlockletExtrasBackup extends BaseBackup {
75
74
  * @return {void}
76
75
  * @memberof BlockletExtrasBackup
77
76
  */
78
- encryptBlockletConfigs(configs) {
77
+ useBlockletEncryptConfigs(configs) {
79
78
  if (isEmpty(configs)) {
80
79
  return;
81
80
  }
82
81
 
83
- const { secretKey, address } = this.blockletWallet;
84
-
85
82
  // 准备加解密所需的参数
86
83
  // @see: https://github.com/ArcBlock/blocklet-server/blob/f561ba7290285f2e23dccb6d5323eb4d43c3cc3e/core/state/lib/index.js#L59
87
- const dk = readFileSync(join(this.serverDataDir, '.sock'));
88
- const ek = toBuffer(Hasher.SHA3.hash256(Buffer.concat([secretKey, address].map(toBuffer))));
84
+ const dek = readFileSync(join(this.serverDataDir, '.sock'));
89
85
 
90
86
  for (const config of configs) {
91
- if (config.secure) {
87
+ // 置空 blocklet 的密钥,但是保留其他属性,这很重要
88
+ if (config.key === BLOCKLET_CONFIGURABLE_KEY.BLOCKLET_APP_SK) {
89
+ config.value = '';
90
+ } else if (config.secure) {
92
91
  // secure 为 true 的配置才需要被加密保存上次到 did spaces
92
+
93
93
  const encryptByServer = config.value;
94
94
  // 先从 blocklet server 解密
95
95
  // @see https://github.com/ArcBlock/blocklet-server/blob/f40338168a66893f325464cea79ae54c43f623b1/core/state/lib/blocklet/extras.js#L139
96
- const decrypted = security.decrypt(encryptByServer, this.blocklet.meta.did, dk);
97
- // 再用 blocklet 信息加密,然后才可以上传到 spaces
98
- const encrypted = security.encrypt(decrypted, address, ek);
99
- config.value = encrypted;
96
+ const decryptByServer = security.decrypt(encryptByServer, this.blocklet.meta.did, dek);
97
+ // 再用 blocklet secret 加密,然后才可以上传到 spaces
98
+ const encryptByBlocklet = security.encrypt(
99
+ decryptByServer,
100
+ this.blockletWallet.address,
101
+ Buffer.from(this.blockletWallet.secretKey)
102
+ );
103
+ config.value = encryptByBlocklet;
100
104
  }
101
105
  }
102
106
  }