From 6ca0a19264dbbc2f08ba3e5596a986118084f16e Mon Sep 17 00:00:00 2001 From: kumavis Date: Sat, 10 Feb 2024 10:27:03 -1000 Subject: [PATCH 01/14] fix(daemon): rename petStore lookup to identifyLocal --- packages/daemon/src/daemon.js | 2 +- packages/daemon/src/mail.js | 4 ++-- packages/daemon/src/pet-store.js | 12 +++++++----- packages/daemon/src/types.d.ts | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/packages/daemon/src/daemon.js b/packages/daemon/src/daemon.js index 9d3e8b28b5..a5347575ca 100644 --- a/packages/daemon/src/daemon.js +++ b/packages/daemon/src/daemon.js @@ -671,7 +671,7 @@ const makeEndoBootstrap = ( * inspector for the value of the given pet name. */ const lookup = async petName => { - const formulaIdentifier = petStore.lookup(petName); + const formulaIdentifier = petStore.identifyLocal(petName); if (formulaIdentifier === undefined) { throw new Error(`Unknown pet name ${petName}`); } diff --git a/packages/daemon/src/mail.js b/packages/daemon/src/mail.js index 3290280b5d..46cb4200da 100644 --- a/packages/daemon/src/mail.js +++ b/packages/daemon/src/mail.js @@ -40,7 +40,7 @@ export const makeMailboxMaker = ({ if (Object.hasOwn(specialNames, petName)) { return specialNames[petName]; } - return petStore.lookup(petName); + return petStore.identifyLocal(petName); }; /** @@ -263,7 +263,7 @@ export const makeMailboxMaker = ({ ) => { if (responseName !== undefined) { /** @type {string | undefined} */ - let formulaIdentifier = senderPetStore.lookup(responseName); + let formulaIdentifier = senderPetStore.identifyLocal(responseName); if (formulaIdentifier === undefined) { formulaIdentifier = await requestFormulaIdentifier( what, diff --git a/packages/daemon/src/pet-store.js b/packages/daemon/src/pet-store.js index 30bbaec6e9..a085dedce4 100644 --- a/packages/daemon/src/pet-store.js +++ b/packages/daemon/src/pet-store.js @@ -67,11 +67,13 @@ export const makePetStoreMaker = (filePowers, locator) => { return petNames.has(petName); }; - /** @param {string} petName */ - const lookup = petName => { + /** + * @param {string} petName + * @returns {string | undefined} + */ + const identifyLocal = petName => { assertValidName(petName); - const formulaIdentifier = petNames.get(petName); - return formulaIdentifier; + return petNames.get(petName); }; /** @@ -259,7 +261,7 @@ export const makePetStoreMaker = (filePowers, locator) => { /** @type {import('./types.js').PetStore} */ const petStore = { has, - lookup, + identifyLocal, reverseLookup, list, follow, diff --git a/packages/daemon/src/types.d.ts b/packages/daemon/src/types.d.ts index 0a3e4a6654..65c489f13c 100644 --- a/packages/daemon/src/types.d.ts +++ b/packages/daemon/src/types.d.ts @@ -178,6 +178,7 @@ export interface Controller { export interface PetStore { has(petName: string): boolean; + identifyLocal(petName: string): string | undefined; list(): Array; follow(): Promise>>; listEntries(): Array<[string, FormulaIdentifierRecord]>; @@ -191,7 +192,6 @@ export interface PetStore { write(petName: string, formulaIdentifier: string): Promise; remove(petName: string); rename(fromPetName: string, toPetName: string); - lookup(petName: string): string | undefined; reverseLookup(formulaIdentifier: string): Array; } From eb9b3aa5ba44ede4541644d323625579d1df2372 Mon Sep 17 00:00:00 2001 From: kumavis Date: Sat, 10 Feb 2024 10:36:26 -1000 Subject: [PATCH 02/14] fix(daemon): rename mail lookupFormulaIdentifierForName to identifyLocal --- packages/daemon/src/host.js | 22 +++++++++------------- packages/daemon/src/mail.js | 21 ++++++++++----------- 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/packages/daemon/src/host.js b/packages/daemon/src/host.js index cc81133491..0975dd2127 100644 --- a/packages/daemon/src/host.js +++ b/packages/daemon/src/host.js @@ -41,7 +41,7 @@ export const makeHostMaker = ({ const { lookup, reverseLookup, - lookupFormulaIdentifierForName, + identifyLocal, listMessages, provideLookupFormula, followMessages, @@ -75,7 +75,7 @@ export const makeHostMaker = ({ /** @type {string | undefined} */ let formulaIdentifier; if (petName !== undefined) { - formulaIdentifier = lookupFormulaIdentifierForName(petName); + formulaIdentifier = identifyLocal(petName); } if (formulaIdentifier === undefined) { /** @type {import('./types.js').GuestFormula} */ @@ -129,7 +129,7 @@ export const makeHostMaker = ({ if (typeof workerName !== 'string') { throw new Error('worker name must be string'); } - let workerFormulaIdentifier = lookupFormulaIdentifierForName(workerName); + let workerFormulaIdentifier = identifyLocal(workerName); if (workerFormulaIdentifier === undefined) { const workerId512 = await randomHex512(); workerFormulaIdentifier = `worker-id512:${workerId512}`; @@ -156,7 +156,7 @@ export const makeHostMaker = ({ return `worker-id512:${workerId512}`; } assertPetName(workerName); - let workerFormulaIdentifier = lookupFormulaIdentifierForName(workerName); + let workerFormulaIdentifier = identifyLocal(workerName); if (workerFormulaIdentifier === undefined) { const workerId512 = await randomHex512(); workerFormulaIdentifier = `worker-id512:${workerId512}`; @@ -170,7 +170,7 @@ export const makeHostMaker = ({ * @param {string | 'NONE' | 'SELF' | 'ENDO'} partyName */ const providePowersFormulaIdentifier = async partyName => { - let guestFormulaIdentifier = lookupFormulaIdentifierForName(partyName); + let guestFormulaIdentifier = identifyLocal(partyName); if (guestFormulaIdentifier === undefined) { const guest = await provideGuest(partyName); guestFormulaIdentifier = formulaIdentifierForRef.get(guest); @@ -216,9 +216,7 @@ export const makeHostMaker = ({ const petNamePath = petNamePathFrom(petNameOrPath); if (petNamePath.length === 1) { - const formulaIdentifier = lookupFormulaIdentifierForName( - petNamePath[0], - ); + const formulaIdentifier = identifyLocal(petNamePath[0]); if (formulaIdentifier === undefined) { throw new Error(`Unknown pet name ${q(petNamePath[0])}`); } @@ -308,8 +306,7 @@ export const makeHostMaker = ({ workerName, ); - const bundleFormulaIdentifier = - lookupFormulaIdentifierForName(bundleName); + const bundleFormulaIdentifier = identifyLocal(bundleName); if (bundleFormulaIdentifier === undefined) { throw new TypeError(`Unknown pet name for bundle: ${bundleName}`); } @@ -364,7 +361,7 @@ export const makeHostMaker = ({ /** @type {string | undefined} */ let formulaIdentifier; if (petName !== undefined) { - formulaIdentifier = lookupFormulaIdentifierForName(petName); + formulaIdentifier = identifyLocal(petName); } if (formulaIdentifier === undefined) { const id512 = await randomHex512(); @@ -393,8 +390,7 @@ export const makeHostMaker = ({ * @param {string | 'NONE' | 'SELF' | 'ENDO'} powersName */ const provideWebPage = async (webPageName, bundleName, powersName) => { - const bundleFormulaIdentifier = - lookupFormulaIdentifierForName(bundleName); + const bundleFormulaIdentifier = identifyLocal(bundleName); if (bundleFormulaIdentifier === undefined) { throw new Error(`Unknown pet name: ${q(bundleName)}`); } diff --git a/packages/daemon/src/mail.js b/packages/daemon/src/mail.js index 46cb4200da..9fa128a3cf 100644 --- a/packages/daemon/src/mail.js +++ b/packages/daemon/src/mail.js @@ -35,8 +35,9 @@ export const makeMailboxMaker = ({ /** * @param {string} petName + * @returns {string | undefined} */ - const lookupFormulaIdentifierForName = petName => { + const identifyLocal = petName => { if (Object.hasOwn(specialNames, petName)) { return specialNames[petName]; } @@ -49,7 +50,7 @@ export const makeMailboxMaker = ({ */ const lookup = async (...petNamePath) => { const [headName, ...tailNames] = petNamePath; - const formulaIdentifier = lookupFormulaIdentifierForName(headName); + const formulaIdentifier = identifyLocal(headName); if (formulaIdentifier === undefined) { throw new TypeError(`Unknown pet name: ${q(headName)}`); } @@ -61,7 +62,7 @@ export const makeMailboxMaker = ({ }; const terminate = async petName => { - const formulaIdentifier = lookupFormulaIdentifierForName(petName); + const formulaIdentifier = identifyLocal(petName); if (formulaIdentifier === undefined) { throw new TypeError(`Unknown pet name: ${q(petName)}`); } @@ -113,7 +114,7 @@ export const makeMailboxMaker = ({ // naming hub's formula identifier and the pet name path. // A "naming hub" is an objected with a variadic lookup method. At present, // the only such objects are guests and hosts. - const hubFormulaIdentifier = lookupFormulaIdentifierForName('SELF'); + const hubFormulaIdentifier = identifyLocal('SELF'); const digester = makeSha512(); digester.updateText(`${hubFormulaIdentifier},${petNamePath.join(',')}`); const lookupFormulaNumber = digester.digestHex(); @@ -302,7 +303,7 @@ export const makeMailboxMaker = ({ if (resolveRequest === undefined) { throw new Error(`No pending request for number ${messageNumber}`); } - const formulaIdentifier = lookupFormulaIdentifierForName(resolutionName); + const formulaIdentifier = identifyLocal(resolutionName); if (formulaIdentifier === undefined) { throw new TypeError( `No formula exists for the pet name ${q(resolutionName)}`, @@ -357,8 +358,7 @@ export const makeMailboxMaker = ({ * @param {Array} petNames */ const send = async (recipientName, strings, edgeNames, petNames) => { - const recipientFormulaIdentifier = - lookupFormulaIdentifierForName(recipientName); + const recipientFormulaIdentifier = identifyLocal(recipientName); if (recipientFormulaIdentifier === undefined) { throw new Error(`Unknown pet name for party: ${recipientName}`); } @@ -390,7 +390,7 @@ export const makeMailboxMaker = ({ } const formulaIdentifiers = petNames.map(petName => { - const formulaIdentifier = lookupFormulaIdentifierForName(petName); + const formulaIdentifier = identifyLocal(petName); if (formulaIdentifier === undefined) { throw new Error(`Unknown pet name ${q(petName)}`); } @@ -469,8 +469,7 @@ export const makeMailboxMaker = ({ * @param {string} responseName */ const request = async (recipientName, what, responseName) => { - const recipientFormulaIdentifier = - lookupFormulaIdentifierForName(recipientName); + const recipientFormulaIdentifier = identifyLocal(recipientName); if (recipientFormulaIdentifier === undefined) { throw new Error(`Unknown pet name for party: ${recipientName}`); } @@ -553,7 +552,7 @@ export const makeMailboxMaker = ({ lookup, reverseLookup, reverseLookupFormulaIdentifier, - lookupFormulaIdentifierForName, + identifyLocal, provideLookupFormula, followMessages, listMessages, From f19e5e6a530dbc8dde285c6d1b75022bb6992c7e Mon Sep 17 00:00:00 2001 From: kumavis Date: Sat, 10 Feb 2024 11:21:37 -1000 Subject: [PATCH 03/14] feat(daemon): daemon exposes identifyFrom method --- packages/daemon/src/daemon.js | 11 +++++++++++ packages/daemon/src/types.d.ts | 5 +++++ 2 files changed, 16 insertions(+) diff --git a/packages/daemon/src/daemon.js b/packages/daemon/src/daemon.js index a5347575ca..79e8c1a917 100644 --- a/packages/daemon/src/daemon.js +++ b/packages/daemon/src/daemon.js @@ -107,6 +107,15 @@ const makeEndoBootstrap = ( return `readable-blob-sha512:${sha512Hex}`; }; + /** @type {import('./types.js').IdentifyFromFn} */ + const identifyFrom = async (originFormulaIdentifier, namePath) => { + // eslint-disable-next-line no-use-before-define + const origin = await provideValueForFormulaIdentifier( + originFormulaIdentifier, + ); + return E(origin).identify(namePath); + }; + /** * @param {string} workerId512 */ @@ -783,6 +792,8 @@ const makeEndoBootstrap = ( host: () => provideValueForFormulaIdentifier('host'), + identifyFrom, + leastAuthority: () => leastAuthority, webPageJs: () => provideValueForFormulaIdentifier('web-page-js'), diff --git a/packages/daemon/src/types.d.ts b/packages/daemon/src/types.d.ts index 65c489f13c..2032eb5d0e 100644 --- a/packages/daemon/src/types.d.ts +++ b/packages/daemon/src/types.d.ts @@ -304,6 +304,11 @@ export type FilePowers = { export type AssertValidNameFn = (name: string) => void; +export type IdentifyFromFn = ( + originIdentifier: string, + namePath: string | string[], +) => Promise; + export type PetStorePowers = { makeIdentifiedPetStore: ( id: string, From 5b3dc782c5e53ed1750989759ba0fb25a0a75efb Mon Sep 17 00:00:00 2001 From: kumavis Date: Sat, 10 Feb 2024 11:32:54 -1000 Subject: [PATCH 04/14] feat(daemon): petStore exposes an identify function --- packages/daemon/src/daemon.js | 2 ++ packages/daemon/src/pet-store.js | 40 ++++++++++++++++++++++++++++---- packages/daemon/src/types.d.ts | 16 +++++++++---- 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/packages/daemon/src/daemon.js b/packages/daemon/src/daemon.js index 79e8c1a917..aa864a6721 100644 --- a/packages/daemon/src/daemon.js +++ b/packages/daemon/src/daemon.js @@ -422,6 +422,7 @@ const makeEndoBootstrap = ( const external = petStorePowers.makeOwnPetStore( 'pet-store', assertPetName, + identifyFrom, ); return { external, internal: undefined }; } else if (formulaIdentifier === 'pet-inspector') { @@ -478,6 +479,7 @@ const makeEndoBootstrap = ( const external = petStorePowers.makeIdentifiedPetStore( formulaNumber, assertPetName, + identifyFrom, ); return { external, internal: undefined }; } else if (formulaType === 'host-id512') { diff --git a/packages/daemon/src/pet-store.js b/packages/daemon/src/pet-store.js index a085dedce4..70c51607a7 100644 --- a/packages/daemon/src/pet-store.js +++ b/packages/daemon/src/pet-store.js @@ -19,9 +19,14 @@ export const makePetStoreMaker = (filePowers, locator) => { /** * @param {string} petNameDirectoryPath * @param {(name: string) => void} assertValidName + * @param {import('./types.js').IdentifyFromFn} identifyFrom * @returns {Promise>} */ - const makePetStoreAtPath = async (petNameDirectoryPath, assertValidName) => { + const makePetStoreAtPath = async ( + petNameDirectoryPath, + assertValidName, + identifyFrom, + ) => { /** @type {Map} */ const petNames = new Map(); /** @type {Map>} */ @@ -76,6 +81,20 @@ export const makePetStoreMaker = (filePowers, locator) => { return petNames.get(petName); }; + /** @type {import('./types.js').IdentifyFn} */ + const identify = async maybeNamePath => { + const namePath = Array.isArray(maybeNamePath) + ? maybeNamePath + : [maybeNamePath]; + const [headName, ...namePathRest] = namePath; + const formulaIdentifier = identifyLocal(headName); + if (formulaIdentifier === undefined) { + return undefined; + } else { + return identifyFrom(formulaIdentifier, namePathRest); + } + }; + /** * @param {string} petName * @param {string} formulaIdentifier @@ -262,6 +281,7 @@ export const makePetStoreMaker = (filePowers, locator) => { const petStore = { has, identifyLocal, + identify, reverseLookup, list, follow, @@ -278,8 +298,9 @@ export const makePetStoreMaker = (filePowers, locator) => { /** * @param {string} id * @param {(name: string) => void} assertValidName + * @param {import('./types.js').IdentifyFromFn} identifyFrom */ - const makeIdentifiedPetStore = (id, assertValidName) => { + const makeIdentifiedPetStore = (id, assertValidName, identifyFrom) => { if (!validIdPattern.test(id)) { throw new Error(`Invalid identifier for pet store ${q(id)}`); } @@ -291,16 +312,25 @@ export const makePetStoreMaker = (filePowers, locator) => { prefix, suffix, ); - return makePetStoreAtPath(petNameDirectoryPath, assertValidName); + return makePetStoreAtPath( + petNameDirectoryPath, + assertValidName, + identifyFrom, + ); }; /** * @param {string} name * @param {(name: string) => void} assertValidName + * @param {import('./types.js').IdentifyFromFn} identifyFrom */ - const makeOwnPetStore = (name, assertValidName) => { + const makeOwnPetStore = (name, assertValidName, identifyFrom) => { const petNameDirectoryPath = filePowers.joinPath(locator.statePath, name); - return makePetStoreAtPath(petNameDirectoryPath, assertValidName); + return makePetStoreAtPath( + petNameDirectoryPath, + assertValidName, + identifyFrom, + ); }; return { diff --git a/packages/daemon/src/types.d.ts b/packages/daemon/src/types.d.ts index 2032eb5d0e..ebcf756b59 100644 --- a/packages/daemon/src/types.d.ts +++ b/packages/daemon/src/types.d.ts @@ -176,9 +176,18 @@ export interface Controller { terminator: Terminator; } +export type IdentifyFromFn = ( + originIdentifier: string, + namePath: string | string[], +) => Promise; +export type IdentifyFn = ( + namePath: string | string[], +) => Promise; + export interface PetStore { has(petName: string): boolean; identifyLocal(petName: string): string | undefined; + identify: IdentifyFn; list(): Array; follow(): Promise>>; listEntries(): Array<[string, FormulaIdentifierRecord]>; @@ -304,19 +313,16 @@ export type FilePowers = { export type AssertValidNameFn = (name: string) => void; -export type IdentifyFromFn = ( - originIdentifier: string, - namePath: string | string[], -) => Promise; - export type PetStorePowers = { makeIdentifiedPetStore: ( id: string, assertValidName: AssertValidNameFn, + identifyFrom: IdentifyFromFn, ) => Promise>; makeOwnPetStore: ( name: string, assertValidName: AssertValidNameFn, + identifyFrom: IdentifyFromFn, ) => Promise>; }; From 80cf0198286301df71de3e8589c8677e97cf8823 Mon Sep 17 00:00:00 2001 From: kumavis Date: Sat, 10 Feb 2024 11:45:20 -1000 Subject: [PATCH 05/14] feat(daemon): mail exposes an identify function --- packages/daemon/src/daemon.js | 1 + packages/daemon/src/mail.js | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/daemon/src/daemon.js b/packages/daemon/src/daemon.js index aa864a6721..b205c3c997 100644 --- a/packages/daemon/src/daemon.js +++ b/packages/daemon/src/daemon.js @@ -638,6 +638,7 @@ const makeEndoBootstrap = ( }); const makeMailbox = makeMailboxMaker({ + identifyFrom, formulaIdentifierForRef, provideValueForFormulaIdentifier, provideControllerForFormulaIdentifier, diff --git a/packages/daemon/src/mail.js b/packages/daemon/src/mail.js index 9fa128a3cf..77bd9ff3eb 100644 --- a/packages/daemon/src/mail.js +++ b/packages/daemon/src/mail.js @@ -9,6 +9,7 @@ import { assertPetName } from './pet-name.js'; const { quote: q } = assert; export const makeMailboxMaker = ({ + identifyFrom, provideValueForFormulaIdentifier, provideControllerForFormulaIdentifier, formulaIdentifierForRef, @@ -44,6 +45,20 @@ export const makeMailboxMaker = ({ return petStore.identifyLocal(petName); }; + /** @type {import('./types.js').IdentifyFn} */ + const identify = async maybeNamePath => { + const namePath = Array.isArray(maybeNamePath) + ? maybeNamePath + : [maybeNamePath]; + const [headName, ...namePathRest] = namePath; + const formulaIdentifier = identifyLocal(headName); + if (formulaIdentifier === undefined) { + return undefined; + } else { + return identifyFrom(formulaIdentifier, namePathRest); + } + }; + /** * @param {...string} petNamePath - A sequence of pet names. * @returns {Promise} The value resolved by the pet name path. @@ -549,10 +564,11 @@ export const makeMailboxMaker = ({ }; return harden({ + identifyLocal, + identify, lookup, reverseLookup, reverseLookupFormulaIdentifier, - identifyLocal, provideLookupFormula, followMessages, listMessages, From 3cdb9c5996a015baa2ff8e08a3fd0442d7192119 Mon Sep 17 00:00:00 2001 From: kumavis Date: Sat, 10 Feb 2024 11:49:56 -1000 Subject: [PATCH 06/14] feat(daemon): host exposes an identify function --- packages/daemon/src/host.js | 4 +++- packages/daemon/src/types.d.ts | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/daemon/src/host.js b/packages/daemon/src/host.js index 0975dd2127..bd899b36f6 100644 --- a/packages/daemon/src/host.js +++ b/packages/daemon/src/host.js @@ -39,9 +39,10 @@ export const makeHostMaker = ({ ); const { + identifyLocal, + identify, lookup, reverseLookup, - identifyLocal, listMessages, provideLookupFormula, followMessages, @@ -438,6 +439,7 @@ export const makeHostMaker = ({ /** @type {import('./types.js').EndoHost} */ const host = Far('EndoHost', { has, + identify, lookup, reverseLookup, listMessages, diff --git a/packages/daemon/src/types.d.ts b/packages/daemon/src/types.d.ts index ebcf756b59..53d8eda0f5 100644 --- a/packages/daemon/src/types.d.ts +++ b/packages/daemon/src/types.d.ts @@ -235,6 +235,7 @@ export interface EndoGuest { } export interface EndoHost { + identify: IdentifyFn; listMessages(): Promise>; followMessages(): ERef>; lookup(...petNamePath: string[]): Promise; From 06d96c84262f462a6f9c3510cd7b16fdafb3083a Mon Sep 17 00:00:00 2001 From: kumavis Date: Sat, 10 Feb 2024 12:05:57 -1000 Subject: [PATCH 07/14] feat(daemon): guest exposes an identify function --- packages/daemon/src/guest.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/daemon/src/guest.js b/packages/daemon/src/guest.js index 3ec17b4804..df7e3707bd 100644 --- a/packages/daemon/src/guest.js +++ b/packages/daemon/src/guest.js @@ -45,6 +45,7 @@ export const makeGuestMaker = ({ } const { + identify, lookup, reverseLookup, followMessages, @@ -80,6 +81,7 @@ export const makeGuestMaker = ({ /** @type {import('@endo/eventual-send').ERef} */ const guest = Far('EndoGuest', { has, + identify, lookup, reverseLookup, request, From 7f0acf8f2f7ab4f173a5f869ef215421f2a71976 Mon Sep 17 00:00:00 2001 From: kumavis Date: Sat, 10 Feb 2024 15:08:18 -1000 Subject: [PATCH 08/14] feat(daemon): petStoreInspector exposes an identify function --- packages/daemon/src/daemon.js | 92 +++++++++++++++++++++++++++++++---- 1 file changed, 82 insertions(+), 10 deletions(-) diff --git a/packages/daemon/src/daemon.js b/packages/daemon/src/daemon.js index b205c3c997..b463929def 100644 --- a/packages/daemon/src/daemon.js +++ b/packages/daemon/src/daemon.js @@ -663,6 +663,24 @@ const makeEndoBootstrap = ( makeMailbox, }); + const allowedInspectorFormulaTypes = [ + 'eval-id512', + 'lookup-id512', + 'make-unconfined-id512', + 'make-bundle-id512', + 'guest-id512', + 'web-bundle', + ]; + + const allowedInspectorFormulaIdentificationsByType = { + eval: ['endowments', 'worker'], + lookup: ['hub'], + guest: ['host'], + 'make-bundle': ['bundle', 'powers', 'worker'], + 'make-unconfined': ['powers', 'worker'], + 'web-bundle': ['bundle', 'powers'], + }; + /** * Creates an inspector for the current party's pet store, used to create * inspectors for values therein. Notably, can provide references to otherwise @@ -677,6 +695,68 @@ const makeEndoBootstrap = ( petStoreFormulaIdentifier, ); + const identifyOnFormula = (formula, propertyName, namePath) => { + if ( + allowedInspectorFormulaIdentificationsByType[formula.type] === undefined + ) { + // Cannot provide a reference under the requested formula type. + return { formulaIdentifier: undefined, remainderPath: namePath }; + } + const allowedInspectorFormulaIdentifications = + allowedInspectorFormulaIdentificationsByType[formula.type]; + if (!allowedInspectorFormulaIdentifications.includes(propertyName)) { + // Cannot provide a reference for the requested property. + return { formulaIdentifier: undefined, remainderPath: namePath }; + } + if (formula.type === 'eval' && propertyName === 'endowments') { + // We consume an additional part of the path for the endowment name. + const [endowmentName, ...namePathRest] = namePath; + assertPetName(endowmentName); + const endowmentIndex = formula.names.indexOf(endowmentName); + if (endowmentIndex === -1) { + // Cannot provide a reference to the missing endowment. + return { formulaIdentifier: undefined, remainderPath: namePath }; + } + const formulaIdentifier = formula.values[endowmentIndex]; + return { formulaIdentifier, remainderPath: namePathRest }; + } + const formulaIdentifier = formula[propertyName]; + return { formulaIdentifier, remainderPath: namePath }; + }; + + /** @type {import('./types.js').IdentifyFn} */ + const identify = async maybeNamePath => { + const namePath = Array.isArray(maybeNamePath) + ? maybeNamePath + : [maybeNamePath]; + const [petName, propertyName, ...namePathRest] = namePath; + assertPetName(petName); + assertPetName(propertyName); + const entryFormulaIdentifier = petStore.identifyLocal(petName); + if (entryFormulaIdentifier === undefined) { + return undefined; + } + const { type: formulaType, number: formulaNumber } = + parseFormulaIdentifier(entryFormulaIdentifier); + // Identify is only supported on these types of formulas. + if (!allowedInspectorFormulaTypes.includes(formulaType)) { + return undefined; + } + const formula = await persistencePowers.readFormula( + formulaType, + formulaNumber, + ); + const { formulaIdentifier, remainderPath } = identifyOnFormula( + formula, + propertyName, + namePathRest, + ); + if (formulaIdentifier === undefined) { + return undefined; + } + return identifyFrom(formulaIdentifier, remainderPath); + }; + /** * @param {string} petName - The pet name to inspect. * @returns {Promise} An @@ -689,16 +769,7 @@ const makeEndoBootstrap = ( } const { type: formulaType, number: formulaNumber } = parseFormulaIdentifier(formulaIdentifier); - if ( - ![ - 'eval-id512', - 'lookup-id512', - 'make-unconfined-id512', - 'make-bundle-id512', - 'guest-id512', - 'web-bundle', - ].includes(formulaType) - ) { + if (!allowedInspectorFormulaTypes.includes(formulaType)) { return makeInspector(formulaType, formulaNumber, harden({})); } const formula = await persistencePowers.readFormula( @@ -777,6 +848,7 @@ const makeEndoBootstrap = ( const list = () => petStore.list(); const info = Far('Endo inspector facet', { + identify, lookup, list, }); From dd6f2f8d11fcaf1a844439e94445b4fd9f1d5b9b Mon Sep 17 00:00:00 2001 From: kumavis Date: Sat, 10 Feb 2024 15:38:09 -1000 Subject: [PATCH 09/14] fix(daemon): identifyFrom should return originIdentifier when path empty + fix types --- packages/daemon/src/daemon.js | 4 ++++ packages/daemon/src/types.d.ts | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/daemon/src/daemon.js b/packages/daemon/src/daemon.js index b463929def..52b8ccd86e 100644 --- a/packages/daemon/src/daemon.js +++ b/packages/daemon/src/daemon.js @@ -109,6 +109,10 @@ const makeEndoBootstrap = ( /** @type {import('./types.js').IdentifyFromFn} */ const identifyFrom = async (originFormulaIdentifier, namePath) => { + await null; + if (namePath.length === 0) { + return originFormulaIdentifier; + } // eslint-disable-next-line no-use-before-define const origin = await provideValueForFormulaIdentifier( originFormulaIdentifier, diff --git a/packages/daemon/src/types.d.ts b/packages/daemon/src/types.d.ts index 53d8eda0f5..205fab1e96 100644 --- a/packages/daemon/src/types.d.ts +++ b/packages/daemon/src/types.d.ts @@ -178,7 +178,7 @@ export interface Controller { export type IdentifyFromFn = ( originIdentifier: string, - namePath: string | string[], + namePath: string[], ) => Promise; export type IdentifyFn = ( namePath: string | string[], From 34b2cfaf700012ddd4a835af29c33ee81a900b3c Mon Sep 17 00:00:00 2001 From: kumavis Date: Sat, 10 Feb 2024 15:39:08 -1000 Subject: [PATCH 10/14] feat(cli): add identify command --- packages/cli/src/commands/identify.js | 14 ++++++++++++++ packages/cli/src/endo.js | 9 +++++++++ 2 files changed, 23 insertions(+) create mode 100644 packages/cli/src/commands/identify.js diff --git a/packages/cli/src/commands/identify.js b/packages/cli/src/commands/identify.js new file mode 100644 index 0000000000..6a2b42d05b --- /dev/null +++ b/packages/cli/src/commands/identify.js @@ -0,0 +1,14 @@ +/* global process */ +import os from 'os'; +import { E } from '@endo/far'; +import { withEndoBootstrap } from '../context.js'; + +export const identify = async ({ cancel, cancelled, sockPath, namePath }) => + withEndoBootstrap({ os, process }, async ({ bootstrap }) => { + const defaultHostFormulaIdentifier = 'host'; + const formulaId = await E(bootstrap).identifyFrom( + defaultHostFormulaIdentifier, + namePath, + ); + console.log(formulaId); + }); diff --git a/packages/cli/src/endo.js b/packages/cli/src/endo.js index c624f328ee..d147e5851c 100644 --- a/packages/cli/src/endo.js +++ b/packages/cli/src/endo.js @@ -340,6 +340,15 @@ export const main = async rawArgs => { return rename({ fromName, toName, partyNames }); }); + program + .command('identify ') + .description('prints the formulaId for the named path') + .action(async namePathString => { + const namePath = namePathString.split('.'); + const { identify } = await import('./commands/identify.js'); + return identify({ namePath }); + }); + program .command('show ') .description('prints the named value') From d0c160fabfa1e441c1d0ae7dba06ec279c7aed71 Mon Sep 17 00:00:00 2001 From: kumavis Date: Sat, 10 Feb 2024 15:55:42 -1000 Subject: [PATCH 11/14] wip: implement lookup on top of identify --- packages/daemon/src/mail.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/packages/daemon/src/mail.js b/packages/daemon/src/mail.js index 77bd9ff3eb..5965c5d837 100644 --- a/packages/daemon/src/mail.js +++ b/packages/daemon/src/mail.js @@ -1,6 +1,5 @@ // @ts-check -import { E } from '@endo/far'; import { makePromiseKit } from '@endo/promise-kit'; import { makeChangeTopic } from './pubsub.js'; import { makeIteratorRef } from './reader-ref.js'; @@ -64,16 +63,8 @@ export const makeMailboxMaker = ({ * @returns {Promise} The value resolved by the pet name path. */ const lookup = async (...petNamePath) => { - const [headName, ...tailNames] = petNamePath; - const formulaIdentifier = identifyLocal(headName); - if (formulaIdentifier === undefined) { - throw new TypeError(`Unknown pet name: ${q(headName)}`); - } - // Behold, recursion: - return tailNames.reduce( - (currentValue, petName) => E(currentValue).lookup(petName), - provideValueForFormulaIdentifier(formulaIdentifier), - ); + const formulaIdentifier = await identify(petNamePath); + return provideValueForFormulaIdentifier(formulaIdentifier); }; const terminate = async petName => { From f30080863681c99f2ab96124b6e9165e67fa422e Mon Sep 17 00:00:00 2001 From: kumavis Date: Sat, 10 Feb 2024 18:42:05 -1000 Subject: [PATCH 12/14] feat(daemon): daemon exposes lookupFrom method --- packages/daemon/src/daemon.js | 14 ++++++++++++++ packages/daemon/src/types.d.ts | 6 ++++++ 2 files changed, 20 insertions(+) diff --git a/packages/daemon/src/daemon.js b/packages/daemon/src/daemon.js index 52b8ccd86e..36b41f367a 100644 --- a/packages/daemon/src/daemon.js +++ b/packages/daemon/src/daemon.js @@ -120,6 +120,19 @@ const makeEndoBootstrap = ( return E(origin).identify(namePath); }; + /** @type {import('./types.js').LookupFromFn} */ + const lookupFrom = async (originFormulaIdentifier, namePath) => { + const formulaIdentifier = await identifyFrom( + originFormulaIdentifier, + namePath, + ); + if (formulaIdentifier === undefined) { + throw new Error(`Failed to lookup ${namePath.join('.')}`); + } + // eslint-disable-next-line no-use-before-define + return provideValueForFormulaIdentifier(formulaIdentifier); + }; + /** * @param {string} workerId512 */ @@ -872,6 +885,7 @@ const makeEndoBootstrap = ( host: () => provideValueForFormulaIdentifier('host'), identifyFrom, + lookupFrom, leastAuthority: () => leastAuthority, diff --git a/packages/daemon/src/types.d.ts b/packages/daemon/src/types.d.ts index 205fab1e96..7a0c893158 100644 --- a/packages/daemon/src/types.d.ts +++ b/packages/daemon/src/types.d.ts @@ -180,6 +180,12 @@ export type IdentifyFromFn = ( originIdentifier: string, namePath: string[], ) => Promise; + +export type LookupFromFn = ( + originIdentifier: string, + namePath: string[], +) => Promise; + export type IdentifyFn = ( namePath: string | string[], ) => Promise; From 9f5a079accc4b6b76806df0ad35d4cf0e02bf375 Mon Sep 17 00:00:00 2001 From: kumavis Date: Sat, 10 Feb 2024 18:48:52 -1000 Subject: [PATCH 13/14] feat(cli): show command uses daemon lookupFrom --- packages/cli/src/commands/show.js | 12 ++++++++---- packages/cli/src/endo.js | 14 ++++---------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/packages/cli/src/commands/show.js b/packages/cli/src/commands/show.js index 554da43b16..86d04bb95b 100644 --- a/packages/cli/src/commands/show.js +++ b/packages/cli/src/commands/show.js @@ -1,10 +1,14 @@ /* global process */ import os from 'os'; import { E } from '@endo/far'; -import { withEndoParty } from '../context.js'; +import { withEndoBootstrap } from '../context.js'; -export const show = async ({ cancel, cancelled, sockPath, name, partyNames }) => - withEndoParty(partyNames, { os, process }, async ({ party }) => { - const pet = await E(party).lookup(name); +export const show = async ({ cancel, cancelled, sockPath, namePath }) => + withEndoBootstrap({ os, process }, async ({ bootstrap }) => { + const defaultHostFormulaIdentifier = 'host'; + const pet = await E(bootstrap).lookupFrom( + defaultHostFormulaIdentifier, + namePath, + ); console.log(pet); }); diff --git a/packages/cli/src/endo.js b/packages/cli/src/endo.js index d147e5851c..466b638e31 100644 --- a/packages/cli/src/endo.js +++ b/packages/cli/src/endo.js @@ -350,18 +350,12 @@ export const main = async rawArgs => { }); program - .command('show ') + .command('show ') .description('prints the named value') - .option( - '-a,--as ', - 'Pose as named party (as named by current party)', - collect, - [], - ) - .action(async (name, cmd) => { - const { as: partyNames } = cmd.opts(); + .action(async (namePathString, cmd) => { + const namePath = namePathString.split('.'); const { show } = await import('./commands/show.js'); - return show({ name, partyNames }); + return show({ namePath }); }); program From 482a6572559a4b114cd6c6bbe586565cbd5c76e5 Mon Sep 17 00:00:00 2001 From: kumavis Date: Sat, 10 Feb 2024 19:00:18 -1000 Subject: [PATCH 14/14] feat(daemon): attempt to shortcut identify for host + host-id512 --- packages/daemon/src/daemon.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/packages/daemon/src/daemon.js b/packages/daemon/src/daemon.js index 36b41f367a..b940b32d20 100644 --- a/packages/daemon/src/daemon.js +++ b/packages/daemon/src/daemon.js @@ -113,6 +113,25 @@ const makeEndoBootstrap = ( if (namePath.length === 0) { return originFormulaIdentifier; } + // Attempt to shortcut the identify by reading directly from the petStore. + const { type: formulaType, number: formulaNumber } = parseFormulaIdentifier( + originFormulaIdentifier, + ); + if (formulaType === 'host' || formulaType === 'host-id512') { + let storeFormulaIdentifier = `pet-store`; + if (formulaType === 'host-id512') { + storeFormulaIdentifier = `pet-store-id512:${formulaNumber}`; + } + // eslint-disable-next-line no-use-before-define + const petStore = await provideValueForFormulaIdentifier( + storeFormulaIdentifier, + ); + const result = await E(petStore).identify(namePath); + // Use result if present, otherwise fallback to identifying from the host. + if (result !== undefined) { + return result; + } + } // eslint-disable-next-line no-use-before-define const origin = await provideValueForFormulaIdentifier( originFormulaIdentifier,