UNPKG

@metamask/ocap-kernel

Version:
212 lines 9.89 kB
"use strict"; /* * Organization of keys in the key value store: * * Definitions * NN ::= some decimal integer * CAPDATA ::= capdata encoded structure value * JSON(${xx}) ::= JSON encoding of ${xx} * * ${koid} ::= ko${NN} // kernel object ID * ${kpid} ::= kp${NN} // kernel promise ID * ${kref} ::= ${koid} | ${kpid} // kernel reference * ${dir} ::= + | - // direction (for remote and vat references) * ${roid} ::= ro${dir}${NN} // remote object ID * ${rpid} ::= rp${dir}${NN} // remote promise ID * ${rref} ::= ${roid} | ${rpid} // remote reference * ${void} ::= o${dir}${NN} // vat object ID * ${vpid} ::= p${dir}${NN} // vat promise ID * ${vref} ::= ${void} | ${vpid} // vat reference * ${eref} ::= ${vref} | ${rref} // external reference * ${vatid} ::= v${NN} // vat ID * ${remid} ::= r${NN} // remote ID * ${endid} ::= ${vatid} | ${remid} // endpoint ID * ${queueName} ::= run | ${kpid} * * Queues * queue.${queueName}.head = NN // queue head index * queue.${queueName}.tail = NN // queue tail index * queue.${queueName}.${NN} = JSON(CAPDATA) // queue entry #NN * * Kernel objects * ${koid}.refCount = NN // reference count * ${koid}.owner = ${vatid} // owner (where the object is) * * Kernel promises * ${kpid}.refCount = NN // reference count * ${kpid}.state = unresolved | fulfilled | rejected // current state of settlement * ${kpid}.subscribers = JSON([${endid}]) // array of who is waiting for settlement * ${kpid}.decider = ${endid} // who decides on settlement * ${kpid}.value = JSON(CAPDATA) // value settled to, if settled * * C-lists * cle.${endid}.${eref} = ${kref} // ERef->KRef mapping * clk.${endid}.${kref} = ${eref} // KRef->ERef mapping * * Vat bookkeeping * e.nextObjectId.${endid} = NN // allocation counter for imported object ERefs * e.nextPromiseId.${endid} = NN // allocation counter for imported promise ERefs * vatConfig.${vatid} = JSON(CONFIG) // vat's configuration object * * Kernel bookkeeping * initialized = true // if set, indicates the store has been initialized * nextVatId = NN // allocation counter for vat IDs * nextRemoteId = NN // allocation counter for remote IDs * k.nextObjectId = NN // allocation counter for object KRefs * k.nextPromiseId = NN // allocation counter for promise KRefs */ Object.defineProperty(exports, "__esModule", { value: true }); exports.makeKernelStore = makeKernelStore; const base_ts_1 = require("./methods/base.cjs"); const clist_ts_1 = require("./methods/clist.cjs"); const crank_ts_1 = require("./methods/crank.cjs"); const gc_ts_1 = require("./methods/gc.cjs"); const id_ts_1 = require("./methods/id.cjs"); const object_ts_1 = require("./methods/object.cjs"); const pinned_ts_1 = require("./methods/pinned.cjs"); const promise_ts_1 = require("./methods/promise.cjs"); const queue_ts_1 = require("./methods/queue.cjs"); const reachable_ts_1 = require("./methods/reachable.cjs"); const refcount_ts_1 = require("./methods/refcount.cjs"); const revocation_ts_1 = require("./methods/revocation.cjs"); const subclusters_ts_1 = require("./methods/subclusters.cjs"); const translators_ts_1 = require("./methods/translators.cjs"); const vat_ts_1 = require("./methods/vat.cjs"); /** * Create a new KernelStore object wrapped around a raw kernel database. The * resulting object provides a variety of operations for accessing various * kernel-relevent persistent data structure abstractions on their own terms, * without burdening the kernel with the particular details of how they are * represented in storage. It is our hope that these operations may be later * reimplemented on top of a more sophisticated database layer that can realize * them more directly (and thus, one hopes, more efficiently) without requiring * the kernel itself to be any the wiser. * * @param kdb - The kernel database this store is based on. * @returns A KernelStore object that maps various persistent kernel data * structures onto `kdb`. */ // eslint-disable-next-line @typescript-eslint/explicit-function-return-type function makeKernelStore(kdb) { // Initialize core state /** KV store in which all the kernel's own state is kept. */ const kv = kdb.kernelKVStore; const { provideCachedStoredValue, provideStoredQueue } = (0, base_ts_1.getBaseMethods)(kv); const context = { kv, /** The kernel's run queue. */ runQueue: provideStoredQueue('run', true), /** Cache of the run queue's current length */ runQueueLengthCache: -1, /** Counter for allocating kernel object IDs */ nextObjectId: provideCachedStoredValue('nextObjectId', '1'), /** Counter for allocating kernel promise IDs */ nextPromiseId: provideCachedStoredValue('nextPromiseId', '1'), /** Counter for allocating VatIDs */ nextVatId: provideCachedStoredValue('nextVatId', '1'), /** Counter for allocating RemoteIDs */ nextRemoteId: provideCachedStoredValue('nextRemoteId', '1'), // As refcounts are decremented, we accumulate a set of krefs for which // action might need to be taken: // * promises which are now resolved and unreferenced can be deleted // * objects which are no longer reachable: export can be dropped // * objects which are no longer recognizable: export can be retired // This set is ephemeral: it lives in RAM, grows as deliveries and syscalls // cause decrefs, and will be harvested by processRefcounts(). This needs to be // called in the same transaction window as the syscalls/etc which prompted // the change, else removals might be lost (not performed during the next // replay). maybeFreeKrefs: new Set(), // Garbage collection gcActions: provideCachedStoredValue('gcActions', '[]'), reapQueue: provideCachedStoredValue('reapQueue', '[]'), terminatedVats: provideCachedStoredValue('vats.terminated', '[]'), inCrank: false, savepoints: [], // Subclusters subclusters: provideCachedStoredValue('subclusters', '[]'), nextSubclusterId: provideCachedStoredValue('nextSubclusterId', '1'), vatToSubclusterMap: provideCachedStoredValue('vatToSubclusterMap', '{}'), }; const id = (0, id_ts_1.getIdMethods)(context); const refCount = (0, refcount_ts_1.getRefCountMethods)(context); const object = (0, object_ts_1.getObjectMethods)(context); const promise = (0, promise_ts_1.getPromiseMethods)(context); const revocation = (0, revocation_ts_1.getRevocationMethods)(context); const gc = (0, gc_ts_1.getGCMethods)(context); const cList = (0, clist_ts_1.getCListMethods)(context); const queue = (0, queue_ts_1.getQueueMethods)(context); const vat = (0, vat_ts_1.getVatMethods)(context); const reachable = (0, reachable_ts_1.getReachableMethods)(context); const translators = (0, translators_ts_1.getTranslators)(context); const pinned = (0, pinned_ts_1.getPinMethods)(context); const crank = (0, crank_ts_1.getCrankMethods)(context, kdb); const subclusters = (0, subclusters_ts_1.getSubclusterMethods)(context); /** * Create a new VatStore for a vat. * * @param vatID - The vat for which this is being done. * * @returns a a VatStore object for the given vat. */ function makeVatStore(vatID) { return kdb.makeVatStore(vatID); } /** * Delete all persistent state associated with a vat. * * @param vatId - The vat whose state is to be deleted. */ function deleteVat(vatId) { vat.deleteVatConfig(vatId); kdb.deleteVatStore(vatId); subclusters.removeVatFromSubcluster(vatId); } /** * Reset the kernel's persistent state and reset all counters. */ function reset() { kdb.clear(); context.maybeFreeKrefs.clear(); context.runQueue = provideStoredQueue('run', true); context.gcActions = provideCachedStoredValue('gcActions', '[]'); context.reapQueue = provideCachedStoredValue('reapQueue', '[]'); context.terminatedVats = provideCachedStoredValue('vats.terminated', '[]'); context.nextObjectId = provideCachedStoredValue('nextObjectId', '1'); context.nextPromiseId = provideCachedStoredValue('nextPromiseId', '1'); context.nextVatId = provideCachedStoredValue('nextVatId', '1'); context.nextRemoteId = provideCachedStoredValue('nextRemoteId', '1'); context.subclusters = provideCachedStoredValue('subclusters', '[]'); context.nextSubclusterId = provideCachedStoredValue('nextSubclusterId', '1'); context.vatToSubclusterMap = provideCachedStoredValue('vatToSubclusterMap', '{}'); crank.releaseAllSavepoints(); } /** * Delete everything from the database. */ function clear() { kdb.clear(); } return harden({ ...id, ...queue, ...refCount, ...object, ...promise, ...revocation, ...gc, ...reachable, ...cList, ...vat, ...translators, ...pinned, ...crank, ...subclusters, makeVatStore, deleteVat, clear, reset, kv, }); } //# sourceMappingURL=index.cjs.map