From 268e62f8d68063de6416042ac1a8b94df89f3399 Mon Sep 17 00:00:00 2001 From: Chip Morningstar Date: Tue, 7 Feb 2023 16:28:17 -0800 Subject: [PATCH 01/26] feat: implement swingStore data export/import in support of state sync Closes #6773 --- .../extract-transcript-from-kerneldb.js | 9 +- .../SwingSet/misc-tools/replay-transcript.js | 2 +- .../SwingSet/src/kernel/state/kernelKeeper.js | 29 +- .../SwingSet/src/kernel/state/vatKeeper.js | 64 +-- packages/SwingSet/src/kernel/vat-warehouse.js | 3 +- packages/SwingSet/src/types-ambient.js | 3 +- packages/SwingSet/src/types-external.js | 5 +- .../test/device-plugin/test-device.js | 6 + packages/SwingSet/test/test-state.js | 16 +- packages/SwingSet/test/test-xsnap-metering.js | 2 +- packages/SwingSet/test/test-xsnap-store.js | 10 +- .../SwingSet/test/upgrade/test-upgrade.js | 2 +- .../vat-admin/terminate/test-terminate.js | 10 +- .../test/vat-warehouse/test-preload.js | 2 +- .../vat-warehouse/test-reload-snapshot.js | 6 +- packages/swing-store/docs/data-export.md | 194 +++++++ .../swing-store/docs/images/data-export-1.jpg | Bin 0 -> 138962 bytes .../docs/images/data-export-2a.jpg | Bin 0 -> 93211 bytes .../docs/images/data-export-2b.jpg | Bin 0 -> 110090 bytes .../swing-store/docs/images/data-export-3.jpg | Bin 0 -> 141618 bytes .../swing-store/docs/images/data-export-4.jpg | Bin 0 -> 131220 bytes packages/swing-store/package.json | 1 + packages/swing-store/src/hasher.js | 25 +- packages/swing-store/src/snapStore.js | 292 +++++++++- packages/swing-store/src/streamStore.js | 162 ------ packages/swing-store/src/swingStore.js | 542 ++++++++++++++++-- packages/swing-store/src/transcriptStore.js | 523 +++++++++++++++++ packages/swing-store/test/test-deletion.js | 93 +++ .../swing-store/test/test-exportImport.js | 444 ++++++++++++++ packages/swing-store/test/test-snapstore.js | 57 +- packages/swing-store/test/test-state.js | 181 +++--- packages/swingset-runner/src/dumpstore.js | 8 +- 32 files changed, 2228 insertions(+), 463 deletions(-) create mode 100644 packages/swing-store/docs/data-export.md create mode 100644 packages/swing-store/docs/images/data-export-1.jpg create mode 100644 packages/swing-store/docs/images/data-export-2a.jpg create mode 100644 packages/swing-store/docs/images/data-export-2b.jpg create mode 100644 packages/swing-store/docs/images/data-export-3.jpg create mode 100644 packages/swing-store/docs/images/data-export-4.jpg delete mode 100644 packages/swing-store/src/streamStore.js create mode 100644 packages/swing-store/src/transcriptStore.js create mode 100644 packages/swing-store/test/test-deletion.js create mode 100644 packages/swing-store/test/test-exportImport.js diff --git a/packages/SwingSet/misc-tools/extract-transcript-from-kerneldb.js b/packages/SwingSet/misc-tools/extract-transcript-from-kerneldb.js index 4f10d99c6bd..ad1987f23a4 100644 --- a/packages/SwingSet/misc-tools/extract-transcript-from-kerneldb.js +++ b/packages/SwingSet/misc-tools/extract-transcript-from-kerneldb.js @@ -18,7 +18,7 @@ if (!dirPath) { if (!isSwingStore(dirPath)) { throw Error(`${dirPath} does not appear to be a swingstore (no ./data.mdb)`); } -const { kvStore, streamStore } = openSwingStore(dirPath).kernelStorage; +const { kvStore, transcriptStore } = openSwingStore(dirPath).kernelStorage; function get(key) { return kvStore.get(key); } @@ -98,7 +98,7 @@ if (!vatName) { fs.writeSync(fd, JSON.stringify(first)); fs.writeSync(fd, '\n'); - // The streamStore holds concatenated transcripts from all upgraded + // The transcriptStore holds concatenated transcripts from all upgraded // versions. For each old version, it holds every delivery from // `startVat` through `stopVat`. For the current version, it holds // every delivery from `startVat` up through the last delivery @@ -123,9 +123,8 @@ if (!vatName) { console.log(`${transcriptLength} transcript entries`); let deliveryNum = 0; - const transcriptStream = `transcript-${vatID}`; - const stream = streamStore.readStream(transcriptStream, startPos, endPos); - for (const entry of stream) { + const transcript = transcriptStore.readSpan(vatID, startPos, endPos); + for (const entry of transcript) { // entry is JSON.stringify({ d, syscalls }), syscall is { d, response } const t = { transcriptNum, ...JSON.parse(entry) }; // console.log(`t.${deliveryNum} : ${t}`); diff --git a/packages/SwingSet/misc-tools/replay-transcript.js b/packages/SwingSet/misc-tools/replay-transcript.js index 441a2ba72f4..2a6cedfa7d7 100644 --- a/packages/SwingSet/misc-tools/replay-transcript.js +++ b/packages/SwingSet/misc-tools/replay-transcript.js @@ -142,7 +142,7 @@ async function replay(transcriptFile) { return loadRaw(snapFile); }, } - : makeSnapStore(process.cwd(), makeSnapStoreIO()); + : makeSnapStore(process.cwd(), () => {}, makeSnapStoreIO()); const testLog = undefined; const meterControl = makeDummyMeterControl(); const gcTools = harden({ diff --git a/packages/SwingSet/src/kernel/state/kernelKeeper.js b/packages/SwingSet/src/kernel/state/kernelKeeper.js index 6de9927b716..4cdc9d84664 100644 --- a/packages/SwingSet/src/kernel/state/kernelKeeper.js +++ b/packages/SwingSet/src/kernel/state/kernelKeeper.js @@ -38,8 +38,7 @@ const enableKernelGC = true; * @typedef { import('../../types-external.js').KernelSlog } KernelSlog * @typedef { import('../../types-external.js').ManagerType } ManagerType * @typedef { import('../../types-external.js').SnapStore } SnapStore - * @typedef { import('../../types-external.js').StreamPosition } StreamPosition - * @typedef { import('../../types-external.js').StreamStore } StreamStore + * @typedef { import('../../types-external.js').TranscriptStore } TranscriptStore * @typedef { import('../../types-external.js').VatKeeper } VatKeeper * @typedef { import('../../types-external.js').VatManager } VatManager */ @@ -86,8 +85,6 @@ const enableKernelGC = true; // $vatSlot is one of: o+$NN/o-$NN/p+$NN/p-$NN/d+$NN/d-$NN // v$NN.c.$vatSlot = $kernelSlot = ko$NN/kp$NN/kd$NN // v$NN.nextDeliveryNum = $NN -// v$NN.t.startPosition = $NN // inclusive -// v$NN.t.endPosition = $NN // exclusive // v$NN.vs.$key = string // v$NN.meter = m$NN // XXX does this exist? // v$NN.reapInterval = $NN or 'never' @@ -174,7 +171,7 @@ const FIRST_METER_ID = 1n; * @param {KernelSlog|null} kernelSlog */ export default function makeKernelKeeper(kernelStorage, kernelSlog) { - const { kvStore, streamStore, snapStore } = kernelStorage; + const { kvStore, transcriptStore, snapStore } = kernelStorage; insistStorageAPI(kvStore); @@ -787,7 +784,7 @@ export default function makeKernelKeeper(kernelStorage, kernelSlog) { const promisePrefix = `${vatID}.c.p`; const kernelPromisesToReject = []; - vatKeeper.deleteSnapshots(); + vatKeeper.deleteSnapshotsAndTranscript(); // Note: ASCII order is "+,-./", and we rely upon this to split the // keyspace into the various o+NN/o-NN/etc spaces. If we were using a @@ -1297,11 +1294,11 @@ export default function makeKernelKeeper(kernelStorage, kernelSlog) { return found; } if (!kvStore.has(`${vatID}.o.nextID`)) { - initializeVatState(kvStore, streamStore, vatID); + initializeVatState(kvStore, transcriptStore, vatID); } const vk = makeVatKeeper( kvStore, - streamStore, + transcriptStore, kernelSlog, vatID, addKernelObject, @@ -1328,20 +1325,6 @@ export default function makeKernelKeeper(kernelStorage, kernelSlog) { } /** - * Cease writing to the vat's transcript. - * - * @param {string} vatID - */ - function closeVatTranscript(vatID) { - insistVatID(vatID); - const transcriptStream = `transcript-${vatID}`; - streamStore.closeStream(transcriptStream); - } - - /** - * NOTE: caller is responsible to closeVatTranscript() - * before evicting a VatKeeper. - * * @param {string} vatID */ function evictVatKeeper(vatID) { @@ -1448,7 +1431,6 @@ export default function makeKernelKeeper(kernelStorage, kernelSlog) { if (vk) { // TODO: find some way to expose the liveSlots internal tables, the // kernel doesn't see them - closeVatTranscript(vatID); const vatTable = { vatID, state: { transcript: Array.from(vk.getTranscript()) }, @@ -1615,7 +1597,6 @@ export default function makeKernelKeeper(kernelStorage, kernelSlog) { provideVatKeeper, vatIsAlive, evictVatKeeper, - closeVatTranscript, cleanupAfterTerminatedVat, addDynamicVatID, getDynamicVats, diff --git a/packages/SwingSet/src/kernel/state/vatKeeper.js b/packages/SwingSet/src/kernel/state/vatKeeper.js index 71a7f561552..e95000f88fe 100644 --- a/packages/SwingSet/src/kernel/state/vatKeeper.js +++ b/packages/SwingSet/src/kernel/state/vatKeeper.js @@ -18,8 +18,7 @@ import { enumeratePrefixedKeys } from './storageHelper.js'; * @typedef { import('../../types-external.js').ManagerOptions } ManagerOptions * @typedef { import('../../types-external.js').SnapStore } SnapStore * @typedef { import('../../types-external.js').SourceOfBundle } SourceOfBundle - * @typedef { import('../../types-external.js').StreamPosition } StreamPosition - * @typedef { import('../../types-external.js').StreamStore } StreamStore + * @typedef { import('../../types-external.js').TranscriptStore } TranscriptStore * @typedef { import('../../types-external.js').VatManager } VatManager * @typedef { import('../../types-internal.js').RecordedVatOptions } RecordedVatOptions * @typedef { import('../../types-external.js').TranscriptEntry } TranscriptEntry @@ -36,25 +35,24 @@ const FIRST_DEVICE_ID = 70n; * Establish a vat's state. * * @param {*} kvStore The key-value store in which the persistent state will be kept - * @param {*} streamStore Accompanying stream store + * @param {*} transcriptStore Accompanying transcript store * @param {string} vatID The vat ID string of the vat in question * TODO: consider making this part of makeVatKeeper */ -export function initializeVatState(kvStore, streamStore, vatID) { +export function initializeVatState(kvStore, transcriptStore, vatID) { kvStore.set(`${vatID}.o.nextID`, `${FIRST_OBJECT_ID}`); kvStore.set(`${vatID}.p.nextID`, `${FIRST_PROMISE_ID}`); kvStore.set(`${vatID}.d.nextID`, `${FIRST_DEVICE_ID}`); kvStore.set(`${vatID}.nextDeliveryNum`, `0`); kvStore.set(`${vatID}.incarnationNumber`, `1`); - kvStore.set(`${vatID}.t.startPosition`, `${streamStore.STREAM_START}`); - kvStore.set(`${vatID}.t.endPosition`, `${streamStore.STREAM_START}`); + transcriptStore.initTranscript(vatID); } /** * Produce a vat keeper for a vat. * * @param {KVStore} kvStore The keyValue store in which the persistent state will be kept - * @param {StreamStore} streamStore Accompanying stream store, for the transcripts + * @param {TranscriptStore} transcriptStore Accompanying transcript store, for the transcripts * @param {*} kernelSlog * @param {string} vatID The vat ID string of the vat in question * @param {*} addKernelObject Kernel function to add a new object to the kernel's @@ -76,7 +74,7 @@ export function initializeVatState(kvStore, streamStore, vatID) { */ export function makeVatKeeper( kvStore, - streamStore, + transcriptStore, kernelSlog, vatID, addKernelObject, @@ -94,7 +92,6 @@ export function makeVatKeeper( snapStore = undefined, ) { insistVatID(vatID); - const transcriptStream = `transcript-${vatID}`; function getRequired(key) { const value = kvStore.get(key); @@ -475,20 +472,12 @@ export function makeVatKeeper( /** * Generator function to return the vat's transcript, one entry at a time. * - * @param {StreamPosition} [startPos] Optional position to begin reading from + * @param {number} [startPos] Optional position to begin reading from * * @yields { TranscriptEntry } a stream of transcript entries */ function* getTranscript(startPos) { - if (startPos === undefined) { - startPos = Number(getRequired(`${vatID}.t.startPosition`)); - } - const endPos = Number(getRequired(`${vatID}.t.endPosition`)); - for (const entry of streamStore.readStream( - transcriptStream, - /** @type { StreamPosition } */ (startPos), - endPos, - )) { + for (const entry of transcriptStore.readSpan(vatID, startPos)) { yield /** @type { TranscriptEntry } */ (JSON.parse(entry)); } } @@ -499,21 +488,13 @@ export function makeVatKeeper( * @param {object} entry The transcript entry to append. */ function addToTranscript(entry) { - const oldPos = Number(getRequired(`${vatID}.t.endPosition`)); - const newPos = streamStore.writeStreamItem( - transcriptStream, - JSON.stringify(entry), - oldPos, - ); - kvStore.set(`${vatID}.t.endPosition`, `${newPos}`); + transcriptStore.addItem(vatID, JSON.stringify(entry)); } - /** @returns {StreamPosition} */ + /** @returns {number} */ function getTranscriptEndPosition() { - const endPosition = - kvStore.get(`${vatID}.t.endPosition`) || - assert.fail('missing endPosition'); - return Number(endPosition); + const { endPos } = transcriptStore.getCurrentSpanBounds(vatID); + return endPos; } function getSnapshotInfo() { @@ -540,6 +521,7 @@ export function makeVatKeeper( const endPosition = getTranscriptEndPosition(); const info = await manager.makeSnapshot(endPosition, snapStore); + transcriptStore.rolloverSpan(vatID); const { hash, uncompressedSize, @@ -560,19 +542,18 @@ export function makeVatKeeper( return true; } - function deleteSnapshots() { + function deleteSnapshotsAndTranscript() { if (snapStore) { snapStore.deleteVatSnapshots(vatID); } + transcriptStore.deleteVatTranscripts(vatID); } - function removeSnapshotAndTranscript() { + function dropSnapshotAndResetTranscript() { if (snapStore) { - snapStore.deleteVatSnapshots(vatID); + snapStore.stopUsingLastSnapshot(vatID); } - - const endPos = getRequired(`${vatID}.t.endPosition`); - kvStore.set(`${vatID}.t.startPosition`, endPos); + transcriptStore.rolloverSpan(vatID); } function vatStats() { @@ -584,9 +565,8 @@ export function makeVatKeeper( const objectCount = getCount(`${vatID}.o.nextID`, FIRST_OBJECT_ID); const promiseCount = getCount(`${vatID}.p.nextID`, FIRST_PROMISE_ID); const deviceCount = getCount(`${vatID}.d.nextID`, FIRST_DEVICE_ID); - const startCount = Number(getRequired(`${vatID}.t.startPosition`)); - const endCount = Number(getRequired(`${vatID}.t.endPosition`)); - const transcriptCount = endCount - startCount; + const { startPos, endPos } = transcriptStore.getCurrentSpanBounds(vatID); + const transcriptCount = endPos - startPos; // TODO: Fix the downstream JSON.stringify to allow the counts to be BigInts return harden({ @@ -645,8 +625,8 @@ export function makeVatKeeper( vatStats, dumpState, saveSnapshot, - deleteSnapshots, getSnapshotInfo, - removeSnapshotAndTranscript, + deleteSnapshotsAndTranscript, + dropSnapshotAndResetTranscript, }); } diff --git a/packages/SwingSet/src/kernel/vat-warehouse.js b/packages/SwingSet/src/kernel/vat-warehouse.js index bde42866978..a51d135d94e 100644 --- a/packages/SwingSet/src/kernel/vat-warehouse.js +++ b/packages/SwingSet/src/kernel/vat-warehouse.js @@ -241,7 +241,6 @@ export function makeVatWarehouse(kernelKeeper, vatLoader, policyOptions) { } ephemeral.vats.delete(vatID); xlate.delete(vatID); - kernelKeeper.closeVatTranscript(vatID); kernelKeeper.evictVatKeeper(vatID); // console.log('evict: shutting down', vatID); @@ -383,7 +382,7 @@ export function makeVatWarehouse(kernelKeeper, vatLoader, policyOptions) { async function resetWorker(vatID) { await evict(vatID); const vatKeeper = kernelKeeper.provideVatKeeper(vatID); - vatKeeper.removeSnapshotAndTranscript(); + vatKeeper.dropSnapshotAndResetTranscript(); } /** diff --git a/packages/SwingSet/src/types-ambient.js b/packages/SwingSet/src/types-ambient.js index dbaf86f92c2..18bd2299a27 100644 --- a/packages/SwingSet/src/types-ambient.js +++ b/packages/SwingSet/src/types-ambient.js @@ -135,8 +135,7 @@ */ /** * @typedef { import('@agoric/swing-store').KVStore } KVStore - * @typedef { import('@agoric/swing-store').StreamStore } StreamStore - * @typedef { import('@agoric/swing-store').StreamPosition } StreamPosition + * @typedef { import('@agoric/swing-store').TranscriptStore } TranscriptStore * @typedef { import('@agoric/swing-store').SwingStore } SwingStore * @typedef { import('@agoric/swing-store').SwingStoreKernelStorage } SwingStoreKernelStorage * @typedef { import('@agoric/swing-store').SwingStoreHostStorage } SwingStoreHostStorage diff --git a/packages/SwingSet/src/types-external.js b/packages/SwingSet/src/types-external.js index cebac5c0eea..6949b7f4475 100644 --- a/packages/SwingSet/src/types-external.js +++ b/packages/SwingSet/src/types-external.js @@ -205,7 +205,7 @@ export {}; * vatSyscallHandler: unknown) => Promise, * } } VatManagerFactory * @typedef { { deliver: (delivery: VatDeliveryObject) => Promise, - * replayTranscript: (startPos: StreamPosition | undefined) => Promise, + * replayTranscript: (startPos: number | undefined) => Promise, * makeSnapshot?: (endPos: number, ss: SnapStore) => Promise, * shutdown: () => Promise, * } } VatManager @@ -273,8 +273,7 @@ export {}; * @typedef { import('@agoric/swing-store').KVStore } KVStore * @typedef { import('@agoric/swing-store').SnapStore } SnapStore * @typedef { import('@agoric/swing-store').SnapshotResult } SnapshotResult - * @typedef { import('@agoric/swing-store').StreamStore } StreamStore - * @typedef { import('@agoric/swing-store').StreamPosition } StreamPosition + * @typedef { import('@agoric/swing-store').TranscriptStore } TranscriptStore * @typedef { import('@agoric/swing-store').SwingStore } SwingStore * @typedef { import('@agoric/swing-store').SwingStoreKernelStorage } SwingStoreKernelStorage * @typedef { import('@agoric/swing-store').SwingStoreHostStorage } SwingStoreHostStorage diff --git a/packages/SwingSet/test/device-plugin/test-device.js b/packages/SwingSet/test/device-plugin/test-device.js index 307587e3de6..7b38950c373 100644 --- a/packages/SwingSet/test/device-plugin/test-device.js +++ b/packages/SwingSet/test/device-plugin/test-device.js @@ -90,6 +90,12 @@ test.serial('plugin first time', async t => { ]); }); +// NOTE: the following test CANNOT be run standalone. It requires execution of +// the prior test to establish its necessary starting state. This is a bad +// practice and should be fixed. It's not bad enough to warrant fixing right +// now, but worth flagging with this comment as a help to anyone else who gets +// tripped up by it. + test.serial('plugin after restart', async t => { const { bridge, cycle, dump, plugin, queueThunkForKernel } = await setupVatController(t); diff --git a/packages/SwingSet/test/test-state.js b/packages/SwingSet/test/test-state.js index e5946c367e5..72932c659aa 100644 --- a/packages/SwingSet/test/test-state.js +++ b/packages/SwingSet/test/test-state.js @@ -145,13 +145,15 @@ function duplicateKeeper(serialize) { test('kernelStorage param guards', async t => { const { kvStore } = buildKeeperStorageInMemory(); - const exp = { message: /true must be a string/ }; - t.throws(() => kvStore.set('foo', true), exp); - t.throws(() => kvStore.set(true, 'foo'), exp); - t.throws(() => kvStore.has(true), exp); - t.throws(() => kvStore.getNextKey(true), exp); - t.throws(() => kvStore.get(true), exp); - t.throws(() => kvStore.delete(true), exp); + const expv = { message: /value must be a string/ }; + const expk = { message: /key must be a string/ }; + const exppk = { message: /previousKey must be a string/ }; + t.throws(() => kvStore.set('foo', true), expv); + t.throws(() => kvStore.set(true, 'foo'), expk); + t.throws(() => kvStore.has(true), expk); + t.throws(() => kvStore.getNextKey(true), exppk); + t.throws(() => kvStore.get(true), expk); + t.throws(() => kvStore.delete(true), expk); }); test('kernel state', async t => { diff --git a/packages/SwingSet/test/test-xsnap-metering.js b/packages/SwingSet/test/test-xsnap-metering.js index 36bbc38175c..5731ba0b0f6 100644 --- a/packages/SwingSet/test/test-xsnap-metering.js +++ b/packages/SwingSet/test/test-xsnap-metering.js @@ -45,7 +45,7 @@ function checkMetered(t, args, metered) { async function doTest(t, metered) { const db = sqlite3(':memory:'); - const store = makeSnapStore(db, makeSnapStoreIO()); + const store = makeSnapStore(db, () => {}, makeSnapStoreIO()); const { p: p1, startXSnap: start1 } = make(store); const worker1 = await start1('vat', 'name', handleCommand, metered, false); diff --git a/packages/SwingSet/test/test-xsnap-store.js b/packages/SwingSet/test/test-xsnap-store.js index 4083d2b0dda..6adfbd547a8 100644 --- a/packages/SwingSet/test/test-xsnap-store.js +++ b/packages/SwingSet/test/test-xsnap-store.js @@ -60,7 +60,7 @@ test(`create XS Machine, snapshot (${snapSize.raw} Kb), compress to smaller`, as t.teardown(() => vat.close()); const db = sqlite3(':memory:'); - const store = makeSnapStore(db, makeMockSnapStoreIO()); + const store = makeSnapStore(db, () => {}, makeMockSnapStoreIO()); const { compressedSize } = await store.saveSnapshot( 'vat0', @@ -81,7 +81,7 @@ test('SES bootstrap, save, compress', async t => { t.teardown(() => vat.close()); const db = sqlite3(':memory:'); - const store = makeSnapStore(db, makeMockSnapStoreIO()); + const store = makeSnapStore(db, () => {}, makeMockSnapStoreIO()); await vat.evaluate('globalThis.x = harden({a: 1})'); @@ -101,7 +101,7 @@ test('SES bootstrap, save, compress', async t => { test('create SES worker, save, restore, resume', async t => { const db = sqlite3(':memory:'); - const store = makeSnapStore(db, makeMockSnapStoreIO()); + const store = makeSnapStore(db, () => {}, makeMockSnapStoreIO()); const vat0 = await bootSESWorker('ses-boot2', async m => m); t.teardown(() => vat0.close()); @@ -127,7 +127,7 @@ test('create SES worker, save, restore, resume', async t => { */ test('XS + SES snapshots are long-term deterministic', async t => { const db = sqlite3(':memory:'); - const store = makeSnapStore(db, makeMockSnapStoreIO()); + const store = makeSnapStore(db, () => {}, makeMockSnapStoreIO()); const vat = await bootWorker('xs1', async m => m, '1 + 1'); t.teardown(() => vat.close()); @@ -173,7 +173,7 @@ Then commit the changes in .../snapshots/ path. async function makeTestSnapshot() { const db = sqlite3(':memory:'); - const store = makeSnapStore(db, makeMockSnapStoreIO()); + const store = makeSnapStore(db, () => {}, makeMockSnapStoreIO()); const vat = await bootWorker('xs1', async m => m, '1 + 1'); const bootScript = await getBootScript(); await vat.evaluate(bootScript); diff --git a/packages/SwingSet/test/upgrade/test-upgrade.js b/packages/SwingSet/test/upgrade/test-upgrade.js index ebe690359e4..096dd9ef002 100644 --- a/packages/SwingSet/test/upgrade/test-upgrade.js +++ b/packages/SwingSet/test/upgrade/test-upgrade.js @@ -487,7 +487,7 @@ test('failed upgrade - explode', async t => { }, }; - const kernelStorage = initSwingStore().kernelStorage; + const { kernelStorage } = initSwingStore(); await initializeSwingset(config, [], kernelStorage); const c = await makeSwingsetController(kernelStorage); c.pinVatRoot('bootstrap'); diff --git a/packages/SwingSet/test/vat-admin/terminate/test-terminate.js b/packages/SwingSet/test/vat-admin/terminate/test-terminate.js index 2a98d2f5669..1bc8c73572c 100644 --- a/packages/SwingSet/test/vat-admin/terminate/test-terminate.js +++ b/packages/SwingSet/test/vat-admin/terminate/test-terminate.js @@ -443,7 +443,7 @@ test.serial('dead vat state removed', async t => { const configPath = new URL('swingset-die-cleanly.json', import.meta.url) .pathname; const config = await loadSwingsetConfigFile(configPath); - const kernelStorage = initSwingStore().kernelStorage; + const { kernelStorage, debug } = initSwingStore(); const controller = await buildVatController(config, [], { kernelStorage, @@ -456,16 +456,22 @@ test.serial('dead vat state removed', async t => { controller.kpResolution(controller.bootstrapResult), kser('bootstrap done'), ); - const kvStore = kernelStorage.kvStore; + const { kvStore } = kernelStorage; t.is(kvStore.get('vat.dynamicIDs'), '["v6"]'); t.is(kvStore.get('ko26.owner'), 'v6'); t.is(Array.from(enumeratePrefixedKeys(kvStore, 'v6.')).length > 30, true); + const beforeDump = debug.dump(true); + t.truthy(beforeDump.transcripts.v6); + t.truthy(beforeDump.snapshots.v6); controller.queueToVatRoot('bootstrap', 'phase2', []); await controller.run(); t.is(kvStore.get('vat.dynamicIDs'), '[]'); t.is(kvStore.get('ko26.owner'), undefined); t.is(Array.from(enumeratePrefixedKeys(kvStore, 'v6.')).length, 0); + const afterDump = debug.dump(true); + t.falsy(afterDump.transcripts.v6); + t.falsy(afterDump.snapshots.v6); }); test.serial('terminate with presence', async t => { diff --git a/packages/SwingSet/test/vat-warehouse/test-preload.js b/packages/SwingSet/test/vat-warehouse/test-preload.js index 18a647e093d..65b4f1fcde7 100644 --- a/packages/SwingSet/test/vat-warehouse/test-preload.js +++ b/packages/SwingSet/test/vat-warehouse/test-preload.js @@ -35,7 +35,7 @@ test('only preload maxVatsOnline vats', async t => { const argv = []; const db = sqlite3(':memory:'); - const snapStore = makeSnapStore(db, makeSnapStoreIO()); + const snapStore = makeSnapStore(db, () => {}, makeSnapStoreIO()); const kernelStorage = { ...initSwingStore().kernelStorage, snapStore }; await initializeSwingset(config, argv, kernelStorage, initOpts); diff --git a/packages/SwingSet/test/vat-warehouse/test-reload-snapshot.js b/packages/SwingSet/test/vat-warehouse/test-reload-snapshot.js index e822b2593c4..2dae19bbca3 100644 --- a/packages/SwingSet/test/vat-warehouse/test-reload-snapshot.js +++ b/packages/SwingSet/test/vat-warehouse/test-reload-snapshot.js @@ -24,7 +24,7 @@ test('vat reload from snapshot', async t => { }; const db = sqlite3(':memory:'); - const snapStore = makeSnapStore(db, makeSnapStoreIO()); + const snapStore = makeSnapStore(db, () => {}, makeSnapStoreIO()); const kernelStorage = { ...initSwingStore().kernelStorage, snapStore }; const argv = []; @@ -38,8 +38,8 @@ test('vat reload from snapshot', async t => { const snapshotInfo = snapStore.getSnapshotInfo(vatID); const start = snapshotInfo ? snapshotInfo.endPos : 0; - const endPosition = kernelStorage.kvStore.get(`${vatID}.t.endPosition`); - const end = Number(endPosition); + const bounds = kernelStorage.transcriptStore.getCurrentSpanBounds(vatID); + const end = bounds.endPos; return [start, end]; } diff --git a/packages/swing-store/docs/data-export.md b/packages/swing-store/docs/data-export.md new file mode 100644 index 00000000000..c538448fa21 --- /dev/null +++ b/packages/swing-store/docs/data-export.md @@ -0,0 +1,194 @@ +# SwingStore Data Import/Export + +The "SwingStore" package provides the database-backed storage component that each SwingSet kernel uses to hold all necessary state. This includes message queues, c-list tables, XS heap snapshots, and vat delivery transcripts. The host application is responsible for creating a swingstore instance and passing it to the new kernel, and for committing the store's database at the appropriate point in the execution cycle. + +Some applications may want to record their state changes in a way that can be cloned, to create new instances of the application. For example, a blockchain may consist of many "validators", each of which holds a replica of (hopefully) identical SwingSet kernel state, and we need a way to launch new validators and bring them quickly and cheaply up-to-date with the existing ones. We want the old validators to publish their SwingSet state, and for a prospective new validator node to be able to download this state as a starting point, rather than needing to replay the entire transaction/transcript history of the chain from the beginning. Some portion of this data may follow an untrusted path, so the new node must be able to validate the data it receives against some trust root. Typically there is a "block root hash" which they use as a starting point (which they either accept on faith from their operator, or which they somehow test against chain voting rules), then they can validate additional data against this root hash. + +Blockchain platforms like cosmos-sdk have tools to implement "state-sync", so the library will handle data formatting and distribution. But at the application layer, we must provide the SwingStore state to this library in a suitable format. The cosmos-sdk state-sync tools require that 1: every block includes a commitment to the entire state of the application, and 2: every once in a while (perhaps once per day) the application will be asked for a set of "export artifacts". The combination of the current block's commitment and the export artifacts should be sufficient for a new participant to receive a state vector that can be safely validated against the current chain state. + +Each SwingStore instance provides methods to facilitate this state export, and then to build a new SwingStore from the exported dataset. There is one set of methods to perform one-time full exports of the state. To facilitate consensus machines, a second set of methods are provided to perform incremental export of just the validation data, allowing the (large) remaining data to be exported only on rare occasions. + +## Two Stages: Export Data and Export Artifacts + +The SwingStore export protocol defines two stages (effectively two datasets). The contents of both are private to the SwingStore (the host application should make no assumptions about their contents or semantics). The first stage is called the "export data", and contains a set of key-value pairs (both strings). The second is a called the "export artifacts", each of which has a name (a string), and contains a blob of bytes. In general, the artifact blobs are much larger than the first-stage export data values, and take more time to generate. Host applications will typically not access the second-stage export artifacts until after the swingstore `commit()` is complete. + +![image 1](./images/data-export-1.jpg) + +Each time a SwingStore API is used to modify the state somehow (e.g. adding/changing/deleting a `kvStore` entry, or pushing a new item on to a transcript), the contents of both datasets may change. New first-stage entries can be created, existing ones may be modified or deleted. And the set of second-stage artifacts may change. + +These export data/artifact changes can happen when calling into the kernel (e.g. invoking the external API of a device, causing the device code to change its own state or push messages onto the run-queue), or by normal kernel operations as it runs (any time `controller.run()` is executing). When the kernel is idle (after `controller.run()` has completed), the kernel will not make any changes to the SwingStore, and both datasets will be stable. + +Among other things, the SwingStore records a transcript of deliveries for each vat. The collection of all deliveries to a particular vat since its last heap snapshot was written is called the "current span". For each vat, the first-stage export data will record a single record that remembers the extent and the hash of the current span. This record then refers to a second-stage export artifact that contains the actual transcript contents. + +![image 2a](./images/data-export-2a.jpg) + +When a delivery is made, a new entry is appended to the end of the current span. This updates (replaces) the record in the first-stage export data: the new record has a longer extent (the `endPos` value is higher), and the span contents have a new hash. The second-stage export artifact is replaced as well: the name remains the same, but contents are now different. + +![image 2b](./images/data-export-2b.jpg) + +To clone a SwingStore, the host application must extract both stages from the source copy, and somehow deliver them to a new instance of the application, which can feed both datasets into a new SwingStore. When complete, the destination SwingStore will have the same contents as the original, or at least enough to continue execution from the moment of copy (it may be lacking optional/historical data, like non-current vat transcripts from before the most recent heap snapshot). + +The host application is responsible for delivering both datasets, but it is only responsible for maintaining the *integrity* of the first stage export data. This table contains enough information to validate the contents of the export artifacts. The new clone is entirely reliant upon the contents of the first stage: if someone can manage to corrupt its contents, the new clone may be undetectably and arbitrarily corrupted. But as long as the first stage was delivered correctly, any changes to the second stage export artifacts will be discovered by the new SwingStore, and the import process will abort with an error. This split reduces the cost of supporting occasional state-sync export operations, as described below. + +## Full Export + +The simplest (albeit more expensive) way to use SwingStore data export is by creating an "exporter" and asking it to perform a one-time full export operation. + +The exporter is created by calling `makeSwingStoreExporter(dirpath)`, passing it the same directory pathname that was used to make your SwingStore instance. This API allows the exporter to use a separate SQLite database connection, so the original can continue executing deliveries and moving the application forward, while the exporter continues in the background. The exporter creates a new read-only SQLite transaction, which allows it to read from the old DB state even though new changes are being made on top of that checkpoint. In addition, the exporter can run in a thread or child process, so the export process can run in parallel with ongoing application work. This gives you as much time as you want to perform the export, without halting operations (however note that the child process must survive long enough to finish the export). + +After calling `hostStorage.commit()`, the host application can extract the first-stage export data, and then the second-stage export artifacts: + +```js + import { buffer } from 'node:stream/consumers'; + + const dirPath = '.../swing-store'; + const swingStore = openSwingStore(dirPath); + ... + await controller.run(); + hostStorage.commit(); + // spawn a child process + + // child process does: + const exporter = makeSwingStoreExporter(dirPath); + // exporter now has a txn, parent process is free to proceed forward + const exportData = new Map(); + for (const [key, value] of exporter.getExportData()) { + exportData.set(key, value); + } + const exportArtifacts = new Map(); + for (const name of exporter.getArtifactNames()) { + const reader = exporter.getArtifact(name); + // reader is an async iterable of Uint8Array, e.g. a stream + const data = await buffer(reader); + exportArtifacts.set(name, data); + } + // export is 'exportData' and 'exportArtifacts' +``` + +![image 3](./images/data-export-3.jpg) + +When doing a complete export, the `getExportData()` iterator will only announce each first-stage key once. + +Note that the new DB transaction is created during the execution of `makeSwingStoreExporter()`. If the exporter is run in a child process, the parent must ensure that it does not invoke the next `hostStorage.commit()` before the child reports that `makeSwingStoreExporter()` has completed. The export will capture the state of the SwingStore as of some particular commit, and we don't want to have a race between the parent finishing the next block, and the child establishing a transactional anchor on the state from the previous block. + +## Incremental Export + +The full export can be useful for backing up a "solo" swingset kernel, where consensus among multiple nodes is not required. However the more common (and complicated) use case is in a consensus machine, where multiple replicas are trying to maintain the same state. SwingStore offers an "incremental export" mode that is designed to work with the cosmos-sdk state-sync protocol. + +In this protocol, every block must contain enough information (hashes) to validate the entire state-sync dataset, even though most blocks are not used for for state-sync (and only a very few replicas will volunteer to create state-sync data). All validators vote on the block hashes, and these blocks are widely reported by block explorers and follower/archive nodes, so it is fairly easy to answer the question "is this the correct root hash?" for an arbitrary block height. + +When someone wants to launch a new validator, they ask around for an available state-sync snapshot. This will typically come from an archiving node, which produces a new snapshot each day. The archive node will report back the block height of their latest state-sync snapshot. The new validator operator must acquire a valid block header for that height, doing their own due diligence on the correctness of that header (checking its hash against public sources, etc). Then they can instruct their application to proceed with the state-sync download, which fetches the contents of the state-sync snapshot and compares them against the approved block header root hash. + +So, to include SwingStore data in this state-sync snapshot, we need a way to get the first-stage export data (including its validation hashes) into every block, as cheaply as possible. We defer the more expensive second-stage export until a state-sync producing node decides it is time to make a snapshot. + +To support this, SwingStore has an "incremental export" mode. This is activated when the host application supplies an "export callback" option to the SwingStore instance constructor. Instead of retrieving the entire first-stage export data at the end of the block, the host application will be continuously notified about changes to this data as the kernel executes. The host application can then incorporate those entries into an existing hashed Merkle tree (e.g. the cosmos-sdk IAVL tree), whose root hash is included in the consensus block hash. Every time the callback is given `(key, value)`, the host should add a new (or modify some existing) IAVL entry, using an IAVL key within some range dedicated to the SwingStore first-stage export data. When the callback receives `(key, undefined)` or `(key, null)`, it should delete the entry. In this way, the IAVL tree maintains a "shadow copy" of the first-stage export data at all times, making the contents both covered by the consensus hash, and automatically included in the cosmos-sdk IAVL tree where it will become available to the new validator as it begins to reconstruct the SwingStore. + +All validator nodes use this export callback, even if they never perform the rest of the export process, to ensure that the consensus state includes the entire first-stage dataset. (Note that the first stage data is generally smaller than the full dataset, making this relatively inexpensive). + +Then, on the few occasions when the application needs to build a full state-sync snapshot, it can ask the SwingStore (after block commit) for the full set of artifacts that match the most recent commit. + +![image 4](./images/data-export-4.jpg) + +```js + const dirPath = '.../swing-store'; + const iavl = ...; + function exportCallback(key, value) { + const iavlKey = `ssed.${key}`; // 'ssed' is short for SwingStoreExportData + if (value) { + iavl.set(iavlKey, value); + } else { + iavl.delete(iavlKey); // value===undefined means delete + } + } + const swingStore = openSwingStore(dirPath, { exportCallback }); + ... + await controller.run(); + hostStorage.commit(); + + // now, if the validator is configured to publish state-sync snapshots, + // and if this block height is one of the publishing points, + // do the following: + + // spawn a child process + + // child process does: + const exporter = makeSwingStoreExporter(dirPath); + // note: no exporter.getExportData(), the first-stage data is already in IAVL + const artifacts = new Map(); + for (const name of exporter.getArtifactNames()) { + artifacts.set(name, exporter.getArtifact(name)); + } + // instruct cosmos-sdk to include 'artifacts' in the state-sync snapshot +``` + +## Import + +On other end of the export process is an importer. This is a new host application, which wants to start from the contents of the export, rather than initializing a brand new (empty) kernel state. + +When starting a brand new instance, host applications would normally call `openSwingStore(dirPath)` to create a new (empty) SwingStore, then call SwingSet's `initializeSwingset(config, .., kernelStorage)` to let the kernel initialize the DB with a config-dependent starting state: + +```js +// this is done only the first time an instance is created: + +import { openSwingStore } from '@agoric/swing-store'; +import { initializeSwingset } from '@agoric/swingset-vat'; +const dirPath = './swing-store'; +const { hostStorage, kernelStorage } = openSwingStore(dirPath); +await initializeSwingset(config, argv, kernelStorage); +``` + +Once the initial state is created, each time the application is launched, it will build a controller around the existing state: + +```js +import { openSwingStore } from '@agoric/swing-store'; +import { makeSwingsetController } from '@agoric/swingset-vat'; +const dirPath = './swing-store'; +const { hostStorage, kernelStorage } = openSwingStore(dirPath); +const controller = await makeSwingsetController(kernelStorage); +// ... now do things like controller.run(), etc +``` + +When cloning an existing kernel, the initialization step is replaced with `importSwingStore`. The host application should feed the importer with the export data and artifacts, by passing an object that has the same API as the SwingStore's exporter: + +```js +import { importSwingStore } from '@agoric/swing-store'; +const dirPath = './swing-store'; +const exporter = { + getExportData() { // return iterator of [key,value] pairs }, + getArtifactNames() { // return iterator of names }, + getArtifact(name) { // return blob of artifact data }, +}; +const { hostStorage } = importSwingStore(exporter, dirPath); +hostStorage.commit(); +// now the swingstore is fully populated +``` + +Once the new SwingStore is fully populated with the previously-exported data, the host application can use `makeSwingsetController()` to build a kernel that will start from the exported state. + +## Optional / Historical Data + +Some of the data maintained by SwingStore is not strictly necessary for kernel execution, at least under normal circumstances. For example, once a vat worker performs a heap snapshot, we no longer need the transcript entries from before the snapshot was taken, since vat replay will start from the snapshot point. We split each vat's transcript into "spans", delimited by heap snapshot events, and the "current span" is the most recent one (still growing), whereas the "historical spans" are all closed and immutable. Likewise, we only really need the most recent heap snapshot for each vat: older snapshots might be interesting for experiments that replay old transcripts with different versions of the XS engine, but no normal kernel will ever need them. + +Most validators would prefer to prune this data, to reduce their storage needs. But we can imagine some [extreme upgrade scenarios](https://github.com/Agoric/agoric-sdk/issues/1691) that would require access to these historical transcript spans. Our compromise is to record *validation data* for these historical spans in the export data, but omit the spans themselves from the export artifacts. Validators can delete the old spans at will, and if we ever need them in the future, we can add code that will fetch copies from an archive service, validate them against the export data hashes, and re-insert the relevant entries into the SwingStore. + +Likewise, each time a heap snapshot is recorded, we cease to need any previous snapshot. And again, as a hedge against even more drastic recovery scenarios, we strike a compromise between minimizing retained data and the ability to validate old snapshots, by retaining only their hashes. + +As a result, for each active vat, the first-stage Export Data contains a record for every old transcript span, plus one for the current span. It also contains a record for every old heap snapshot, plus one for the most recent heap snapshot, plus a `.current` record that points to the most recent snapshot. However the exported artifacts may or may not include blobs for the old transcript spans, or for the old heap snapshots. + +The `openSwingStore()` function has an option named `keepTranscripts` (which defaults to `true`), which causes the transcriptStore to retain the old transcript items. A second option named `keepSnapshots` (which defaults to `false`) causes the snapStore to retain the old heap snapshots. Opening the swingStore with a `false` option does not necessarily delete the old items immediately, but they'll probably get deleted the next time the kernel triggers a heap snapshot or transcript-span rollover. Validators who care about minimizing their disk usage will want to set both to `false`. In the future, we will arrange the SwingStore SQLite tables to provide easy `sqlite3` CLI commands that will delete the old data, so validators can also periodically use the CLI command to prune it. + +The `getArtifactNames()` API includes an option named `includeHistorical`. If `true`, all available historical artifacts will be included in the export (limited by what the `openSwingStore` options have deleted). If `false`, none will be included. Note that the "export data" is necessarily unaffected: if we *ever* want to validate this optional data, the hashes are mandatory. But the `getArtifactNames()` list will be smaller if you set `includeHistorical = false`. Also, re-exporting from a pruned copy will lack the old data, even if the re-export uses `includeHistorical = true`, because the second SwingStore cannot magically reconstruct the missing data. + +Note that when a vat is terminated, we delete all information about it, including transcript items and snapshots, both current and old. This will remove all the Export Data records, and well as the matching artifacts from `getArtifactNames`. + +## Implementation Details + +SwingStore contains components to accomodate all the various kinds of state that the SwingSet kernel needs to store. This currently consists of three portions: + +* `kvStore`, a general-purpose string/string key-value table +* `transcriptStore`: append-only vat deliveries, broken into "spans", delimited by heap snapshot events +* `snapshotStore`: binary blobs containing JS engine heap state, to limit transcript replay depth + +Currently, the SwingStore treats transcript spans and heap snapshots as export artifacts, with hashes recorded in the export data for validation (and to remember exactly which artifacts are necessary). The `kvStore` is copied one-to-one into the export data (i.e. we keep a full shadow copy in IAVL), because that is the fastest way to ensure the `kvStore` data is fully available and validated. + +If some day we implement an IAVL-like Merkle tree inside SwingStore, and use it to automatically generate a root hash for the `kvStore` at the end of each block, we will replace this (large) shadow copy with a single `kvStoreRootHash` entry, and add a new export artifact to contain the full contents of the kvStore. This reduce the size of the IAVL tree, as well as the rate of IAVL updates during block execution, at the cost of increased CPU and complexity within SwingStore. diff --git a/packages/swing-store/docs/images/data-export-1.jpg b/packages/swing-store/docs/images/data-export-1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e8aa4aced8d4c31d5ca29a5192d943cacb961bba GIT binary patch literal 138962 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

&7@$EZiJ#k_X=L?h($ifT^KP`y96tev zbBVtN9&?*R+xoLm-~5a}Yw|r${35MET6CXjh<|yq>`%u3^>F0vs&RVgC~`#55uX$a zx2^Efrt0}783n&|tw$3@MQZvS~1Q zmGHM#jMA6~gd2(_JMeY04 zWms`_IxEd1?o4h!%q&bTSJYla94)cN81a3)^g%~wj|>xS+8nUfffLlZ;nbK0e8A&O$=&Rg`*YhR@h6?*-NG4qBZ1zJ|7D^6NPL?f| zin)jNp+pPT4PS&^u?bE8;2MFRSq;VFrvFh*{SgP=e~SS&N0*RC2!aRRIR zFFp4PEEk{XDaA+*3Y+DQd9#xij2Lq!i*zkQHz`*q>jOc#HlY$EH;D|~qxZf|cM)@c zQSVFXP%S_HuG(4u1ZLsTfy|a8C?t=<;&Sp5M3KKa5Hz-owUUS^?Dq<)-R3b^4jZX&)Vk)7I8HtcVeFM@ubSrrY)d zA4DK4O(TuoN%H2-3WdSY=q5&QG7$=s(4kPzvLX`2DeTH_6JL4z>X%+;>36FPMm>Zw z1w6Htc;Qak%}uHwoU%m=PwsKUgTHW{EKnkiPjw(v3+l)Y?4gFr@ zjf7#EW{v}eA&<(tIk1wr|0jd+$b1K(KPEcTZ{mx8q z+>-ysT1?%kLvvB&nTP9%((Ij4VFI{&SlVEJ^{I7~gKkTVXI5BEO$FX=+o zpdM-X>|o6!98#yma5dejN|xqIq+7*OY@Rrup6D#Ejir?ogJrBt*}`6#6ubYJ8->X; z`@=^3Oc>T?aJwwyW}$e}^HlB02arjrOHUnInblU`7n9B!`buXmoVwn9)Mho)TiN?; z_SK+p2Z`pcwO2I~z6yI^F zT>)_tQLT(g(Q+_uv*6-VNr52L`KBhN_{xQ=ScYpt8>CC29m8zHQRBy#ibhG;^PBb$ z?O&7IaRsw!1n+S_k8G*cN^|Z-kya0lpm&eX+>BC;wS18xCXa&rlh_f_Xq_17n5X7W(U|LloV=D<-Zd_c1NS%;E8^MC$ z4U8R)O4|2ZvwyUm z9iGHRo8zwej0_|>TX`?43+>#hP%Gy2T3#ktw3{t4>W;d`S>hC#G?dyKei`3ATcD#r)1AhV7Vu`e^YPJSCG6 zCxnJds4-wnL4631gQp-!&ZF0HGUb3qbAIZ_41-%uX}%xdRDX*Vs9eT&(O$)Ww6nXE z=P5e!)}KUo!usnQYhSxW$+-9-Xe9K;=+@U(#fxE&Ta`d$22cyWR00tThOeiInMfH# zJon$(d|@iE-FO0b%wDxYNxQX3twbK3=icyMwxmq1O5;eK?EvJ0a&Tjs=>ix;O z0J!`e0|s%S;>J7w7e&jAm6pqIl|iL+s57?xbGkC4*&z?4kemEGtCt z5{P!6P_R=eG*l%=iW8~ZRIEEi_a{KV`H?YC3mhnI+90s%uM#-wx@vFgoc0lRdx^8( z{$Tms1k)sTIisq?f2$&K`l2hw?Zc`T`myr3?!>~IU7gG|^{IK~+Ul7i(ig)eLmQ=n z%QA=?(1)XX9S+~5SCt~G%x%2o%qd-uK>!@FcCmrODj4(ABDUN^pHvsS;_>I8muk6Z$c0Rz!zh6#d|S z_e$c;Q9=3nGne-rUHLC-Aco~h!j0TnXVT(jlUCh<^jL14g4nGR&9#``a=R>}p3X!# zb!@2M?M@GW!M0Mc?K8C;fm;#^^+H2g_eZP{iThL({~*QuTI+a9mI+Du(#(jBZ1s|? zr;R!_$)>^s1KLD&`jbL45MYfe(Rz9!u*BSq0wE;UZ#+uetN*jZWO!ny)9I*|uuIQF z+0dhhjt{ifj2veb?LZ}>?7zedBsh7xHPh1vDHJ3WALv%p4@bO*x@NfO3+L9}?NzYY zaXpICV3mDyUYFWUOI9=q+;mb{ExcX_mwB*R>|k2pa zle6T#m2Yw>U!Big)B)_V&fMz|xV-Gjo|E*Lnq3oU?)&5O);LGq*3$gNbhF(}H~0N< z$)oG7-wLit487*JPdwiLtfYEG`*05Gu9Om~b2}il-8E1k8?3Mf*^&cml(8O-7F64K zFq?s2>HNIt8X87}=?6!lt~k4)u5L58H6tY~%6-_-yXX)lX9x@_FMqW2C!pB2*zIjX z7Y^s0OzTjn<1`(mrq|bgps;x)kP4q+zr5a!6bG9JJ+EWuk#jxr{OWGT!ZKg(pd#dNG%!G2ReYF`z zaT9x(&J>{i8?mBTprtw>63riYyl`R$a!C!N6S6M{Yb7izR@Yp5p|VcPl82~`H~FL8PUY%` z72hgR4x%vA(fKkrDm|US6CkN^23XzbkNlmC4ne_dwTj0J=?czwOKzK7v*^FkUQkSd z)npk9{{&nhQDI<{;KeaeZ+}oBHM`>O0FZd(`l&d{rYEoE%dsh({PR(crh(%UCfqZ` z{qC7QB1MHvV^>(j5-`osvPZW|CX<`Hg6>`a0(J^Q7JQfccq7GmC=o!;4Oy*(7qtJV zrVAp`ida8yhIU%4vrAUq2Um&hN7r8Omz~v8>dt7$z-sy$QPg?K)n@NyTqg@}rR2I%o{pbT=HGdBo z1i|;r?*o)%@BhkA-EooBUUkdF9%EZ2jgvCYuiHS+w8Sd+u*(lvHg*gd(x!(>J$s5T zWFPDB@0==`ZBQ2#Vc_DQ4z!R((ny<{$NI^a3)Yj@#pWCwl03kOMfKQxU(?r(hOhGE z?{=46NpX|VTp;4)`nyU6$NK7DIAKl8ElKYP zASBjgN&$)>5M)@un(yISH;0XG1!u}PbJfZ?rOa;lXv`YmyH(5&SQ@CduUY9T_N3Ji z>vCIFk1`y35abwuzWjA zDX5)Kvj0`76_4a54qvFRjV>4?imx_|X1pe7Vs!9v1SoLfh4yY;xM-8jp$wln0}+q* zRmpK!QTl$K6trt%c7{ONFL!@ZfHaaX{fuva0+83OU6r@5Pk56d! z=Og#sCLri)BL7YZ++@&}aWbxN4myr6_4CoNmZd@%8~JJ@$CC1h#eRO#uby|;MZ^>G znhwOqt!2tzv-Bt%#V-*>eNW zLS~t@`Rx$9^w|zsxereqh?=o9CKM)*SX~1O?D`n)gxLl8x(rWryyYp~3!OBfwRm-u zh*lU$IIk$B*g((iTF(pGY-l)SvyW>uizsxr(D>j6Y7vjVs8GEm{Vf%YZB@vZH5RDa zt_XEbNh>%cCVnmT=@IGYK^HA9s`X3KEkz40(_3Gec~!tnbw_-h0&qx_xYDRgqyVH2 z2;5%hPkq`#<#8fycbIsiGhYmJd+ibVXKJKjy2gc#6B;3EB)2;9S#GHhb(7rhUDG%n z-7U)=T^(t2h*sl$EmYiB=FbpQ2*npz60bfqAkY`(SN%?C%@l+)?aS>uGY;Gwix2MX zpkr5tY^{>`V7F&2`3|-kR8z5a)BR*g?Gl>KBZTByOm%riop{nn;i*@xI(w41>NELrg+#fN0N+j=p-D)zj_Ti;>kKgU%ay<57qv&PP^1U0ps_Y)q z)oSuB)~2*HyS?Uny>eZ4Mx)4_ zY8zi$&~C%N%hEKrfmG-nj;*M_R8gkTd}G{K+OT~q%Iat%A9=Lf?CMpafI@D%(sV%6 zyx|jDG6`Q7zZ8fIVSGT zmXsn0EXTMq7NCz~>Y=8WY9668bUWJXMhZu&b*^i1rA~NOt5Ef?A8-|`v%AZRt{xE0 z6a0RP_zZA$qP95kdV_HJRq4~aB185V!MnLv6FMXH@LJJM?ZfgQd41fKwB*K-^)nf2 zaH*1-K0o_Q@g8N96)uaGKJBI2`chq`Z%mGr=uCJ@$gM%@EUDnNYaUxe%?1Wov29sd z`LnUbRh2b&M-E}Ihx@<6drSC}TPuzR2|GyMj$`-7pKAS+;75kXD^dG3u#xo;MWT6>cAmgST?#$_&4gJmcicCv7sM z_03QM9R0Z%q0)2h6p_QO=Llqc6}kfkA$RDOMarok^R*6@+|@B17M%!^%%~nPgzq`W zF&S?qau3O<^drWnzvK$Ajmn!fwq*T!_n?{>;!V$ryv~a~dDER1#6Oy{U7g@{EOlGu z80|w_T^~8%;KTWAXhhk%o()yuv%(IY_xM}E^S0KR#kG)9Pg9yfhL!k7Y7+8sq{NjP zXY>hpt|(E%M<;NpoTVE-miErBga@B2^gUtOfBOihJEJHmBoD^*6TkB&`r5R&5)%{qT|sI9DDEE2RPP1jAFm@^N!ta8JLJJ$V}9P z!s9pz(*E$|AYT4!9zJsYLX^X$mXZUS+<^qP_|=mMUoW}#vc(1Qm@nnXHs52&3cz|YSP=_k#>8%g!dvZxyx2vvmDs| z=6uAK74UE};z(vZh{QRw-$4z@>aRj#`;aFC`kjduL@^6}fRa<`iD zLA^~XNE#aN%Y3s!85H-jjMtE>15%`=suLkhlH|KZq^3bk-I9Xqlq-5E=!#2|N97Z8#g;_!WfvgO3;h>%;mwCnp)7skX5vHF<+CkeMc{tG%X&} z5x*cJ@px;-NA&Fl#Ka`jIWM9MrLe@LFP+qRm2BT}$0a)3zW?zv;OO_gF}%E}B^5h# zNDr)AV>QzlW+-<4U_trdQTu7zWE?|n{7ODkeJIOPB8XUX&6irpn9VDaoh!~@%p z&6RFFaDbEgot2Vwys??u!b?3Fm1lyhsbX#3{i_R-C`DK8L85@oh@yA^j|(bu-M(nU zVaT;}K3@@|t3LZGhRS64~N#{y{vNs}Ps;7jApRC)gp z)hFF`>q=!K1+mb6H6)pGkE8wdqrr2y*n8@5z@ zm&BQS%N2$xHWwXZ?)l{=h%|o{JHTT#l7PomI%PtgW(uiw_9Z3iYV@T8Y7_3T6({;R zRQS6hm$&q6op*av#j4WBTJoN`b^06}Mkv$}jR`)})lbOo``@5jE&LC^sFZij9&OZb zZ~|i;DhXzpda?70GRra_c{zUqskp{+*miww@cE@Na9!c_*OGbsCK5^6{W_Ago?C?)6p2+=k4v?F(KtHUcR?D zxOZ$nKH0F*sinpY0E>$s9IYfgoQYLQqEsi=;4Om}ARP`A0e^S))Qkx(9)3D~*>Bt2 zEBpie-UCYfs_S0iXXOnW^B2rkKAqvgj@*?)HX}$Vx~4IGiULZMkc_8$TKJ=83!9cMePnI&%Pqo(HcA>hBdQ&Uj6gpp4;xq*D z!fVVv)aJN4Wcl>;dV|Dcd@(DQio+@1DOhC5?u*C`u6m4Vct3`B(#@hs5(o&nB z$^NTR>Oxwv=%>}RJ8@>B&9-fQZE<5%u%}pYZJcB}fA;XA=G_m^saLWptp&~_#63rX zu@nI$`VQ7(QhEO~zuy_n=8XuSZq};Uq^j0(OpR0&&5Lf@QJiC(Vnv8N(eB-=r;ZXw zdXFRc(}Oo7E28QaF(`Kwu(} zJ!1mOC5sE&&GtpS2-1J*bFr8waaAoaD3PyIArJ3z+vpCe{)L{+D%s8u(jDAP z=UDwShaTF>car{VTQS+ON!q0$jp>?6yD*NT`>6iBwZ1v~u6INt|>_VZSVDiR z$t#&7>Ap>#C>Xjwl#8422#F>w?z5;pO5(7bS!{C z%7ujN&xKD8*`Hl-^2hxXoxMrqUOIu0*W2EOmJ?}6LtVc!Z3P7tdeLeUdzEQDDH7`*4_1Z7=!>P zC30~&!EIQ+15TDPPP#2$u5m4)Z{I#W0bmRmjyl8hE$P2Nc49YY(`URTEig_hre6PeZ1+AY`a zAMkj`b7=hC5y#Ivty{yoWo8oYgR@#TrU0)_~pm{&^;*IxXx?V>fIq@+o$Ww zcj%N1Cq=gu)w7WcOewzBsF{zXx*phEdw)3RK|JED1=n`M#(ls#B9h-(B3@43h+all zdx$n#OZ+5!mF0`($$supC*(;&9}Katn!c0Y_qQ=QR(Ey2y4x_KJ8T;~=2MCFk8J-4t@bR&1C@c0sCNRoNFGiHxF)OcrM#71;gQRtx*;(E@7g) z{4#(={7=b_$aj2If0u^;_GAOv2Pz#m5qe{)nUG32IV$NrX5S->OvpEOzYup2H&tHy zssLbM75U^}YxHkI;L+bE$8f3dZku?T*Ka*r7jZfEGzUGHXx2!`MS0A9X+%S&1QQ_Hc7x4ki$H|LKgeF_} zXDU(-1e)Go7{vMxApBG<9;^u6d_ppy7MD5WymM`}c+F*YzTqMxxhWh>g zsREYR`Z6{395++9(J2Bn z)1gi9f(=}Yc@wdot2YnyIY^iEfg=s6#=>E6`za91+WiwYhcpkF2`UO$ecS};8Ge;% z^O07X4yIH0H|W{bJMzz#%gX9MX_ocCDAJ^HNy;SuZH{ot$-z(>8rt0S+QO9$j83Nb zaB*z|x4BY}efsU54J|0IVfuP$eYNvx0 z4u5|5IqP+={SNoYGvNMG4aJ4rJ#2|y0foaP>t#wn{+;ebUbW!9fwWQ7 zJlHm?6Rvh~?TU9AY1EB^y!lGgOwWRAF-d?w)G1In3b763Jbt&=-#0CGxT~t%zh~q` zCx*W`_|0BIVgKGc1#b4kO#y?0IkyIFhE58dJRvNVWo~CHo=1Lq$psS?56(EdK6}h;3@koLL zQT-TQ{lxu$(Zz3S`4{+~T`~puc4<>K%?loWm4Si`&O{qS#S#1k4vxY{a$<=I=3 z(rKbZ9se1OOw@XsCUoH^;E%ZcnULJ zAYO2}g|ZmXX+CS=_;oyTPUJTXq5)RS7=u|*8Iw2YXA)hPCzg$5PyB}YoQ~jYd^1T9j4fMUZPZjxAUozgem0G2XQwIQWI2)8^v%v9MlEj?t5yd zTd?jtC{#SWU(ip$Z@K@UmBcba%fj`ew=c~~Zj@GiUv1eu`5WdkyYE}#i1j9pQ@k>U zoz%t*D&p5x=fM{J5Qaq*Rp3+wGUI04vxddMy*BIN6lc7WUz+KY)o45_C6U&Hq`7q) zr^mwNpqDz*xTptz?M;GN6N`%I&}FvVtC3RExX@E);?x)nJz6~8Cp=No(C3!f?(Rcz zuy*Y6(^ORVKi^CbrG7}wkr-&>5kBPv;5`5QUz+6q%Rs#Qv*L`Xrni)zfJlxT@ZI0% zddh7C>zkkL-rsDl?$6w0Q-LoS{2;W?9JZ~l2>KIg_{pwp)u7N z3yMlrs?wVQ2~9v$ia5Kuy~QIbIDp@Xl2^qK@PRDmQAs+0r>#X=3eBp_X?6afVh z5%E3wes`SldG7t*GtL>~jC=M!*~!k{YwuO&T6@mtd8UasujbB7q5AtP*Iy1l!6sBk ztEyvSPfOOi7}^i5%_q7z4|<%{T-h7|dMS}^KA`~&CPm}+M89vQf|8!%X92-=bsE2y z_aaa6*Khu6h@c`XH&jBLN)m_sOzXrNL?gY&k@033%A*%Lfx{Qf%Ob`{R>Z=6TngRj#3 zaV~RIvS5Cf4E$PKcf3;sm`B`_)*`oMIvObjR{c6+b)>gU-VoKFVeW`Hd{yCQlZu$- z;}AI!r+VLs6>+LwPA(r!FA@M{man>Vu~?1(lccCD+pE|!(+Tm0Z+S7OSZTjasZJQ**O=s1vmol6?Fpb{5Jx=hw z;5+$zzAm>L<WkR+mTo9THcOQ&m*#oVHcE(1Myw$gKB?={ zw0n2B6i(6k5X!jE2zCm%gz8w5O{{^x$ZIeA^#lozFe^2k^qr^t|v}m;D%lyum z40`(==T;d9G%*uzNLHohjHr0`EnN=2Q`z2QcgH~pU>o2h{{m@k0~k^cBznq}j{$+&YL3K) zWCPK{0jJ}i;qz_>2rnjBJa*KeSiw#DH^@e{Yl=c@(vQR?d{f?)bKggiAf!68Qw170 zm_icmykTB7uROB``)VnE^#IeDHg*CXm!_T@XXkCruB8ukVK?_Er*K2vAUHSGqQF|f zN&nawm56VGyX6?_^LRf<3H2LI=rnTJg@=q@-s5=EFSRQa4-Sa;zA<6l}>A?^-2q3d$K^L6JL&YZsL{HzN{o;KwG&9q))s5|LIHLH=B3( z==S4L-IQwkM!#*H8VJ^#ArRL(pxrx?Z>%9?5~C_L4PBM8BY`x`?27U)Y{a%|H>&@f zX$C%B(H(Dz-@E)bTUUUL-;U7VY`gm{zMGzbMko8OcQgnA-K&x|LcZVOu0aiMULRB_ z*VQNXw->!L+({iRlv1CE5Xzgkb(nbWt{;E($oR-7Qr!r;(-dt>B;}ktA)C=JuW}We zr0~Y~4UAEv0tB3{UD#x?s-m|{Wo|2Q7h=X6%E4Arg3koHl@0Nn7+6~U&MMmAd!!R) z==4YX@Q*%+ge|-6vF@tLCZ+Z5*0z#->iRuSBIq$humsyPD<4tv=+h;5YTxF{b3KZV z_1ka17E6mHn{CE_cXZgU?x${bmh?guN%ML^)~Cx`KhYPZPD_K{>&j*U%_GZ4EEV)6 z)@?;Q`5iN^~*7M#m@!rb}=sMh{b}vZ79uWy-Imb0elMWPPkmpoZt;coS6*a91IA#0wF-u!CpoKS&vnU%wlAj-?u6_8P8snB_Y#iK6y~pkc z=i2ZWK;Pl}K7~*bkukF%%7HNkNp3Auu)0KTl7Qfxa~Ylj*oa32MK!|58Fn725N}== zi2wvWa26z0l#6(e;+TeH6qp&Js0IkY1{xNAd&0U*4F?Dbeq%|iXbKAdc{H<4-rW^B zFc{x3W0zS3Zj;)}`&xUHp%j^gsR|}{RfvPLuZG;(8J~%`q)&)613Qy|W%4~W za($Y5!Pqme`Ag+572|zYtb-;4;M%kU+3XQ3*#PMEp%SR=Nu-)@v8lf!3mjtrmM{to zA%!`wIH`(nPnujBr-(Q_gHJHs=vIn|d7nDGU zM(_9WKG(~E_149Qc*Vq{VQixx%pvb5jTRKt!=39Z<9(%+VTm`@!d_;5S=Nt&-2H~W z))NwIvo;K$H!zyh;k+SkKDZwsc6W2C2(@@4%d|qDJYbgZez(l%)7_aw0j3zq`KG0f z#r0LH69r3_6ilcEs45ulwf)Ynu2849B=21&FYMlHjBg0)-`xBFPAt-Fu^(OjzE@@Q zJ=1Glc=Kkzrb}CnT||WXUw4RZWAYZvu+zm8pPA-(vE9tsO(W=#8r&?9jbQh;YnK8PUy|#Tvp8iO4dtKM3@&ZPSDh%(eb|jbBlR$vzcs@efjiMjS}3SnhG;8Q#e2!-It;AivRl zd|ATYl+r^37}Dj@=Z|OZN&P%yPS?C8&ve^$!z8tCS!Ov$$*GR`rL0P8BaE&ibw%gu z>v)m#!TdD-y!4SZYl^vY&qioBHmrJ6v$8ahe*93-}3ppQ~D#B&*dg8zjV+DU{`ubHBG7+C&3~MA^?3 z4?hPFrym^7bDB8yhB&%PJJWtmy$fMj8FcyP-#Tgax-qlF`6v*y3Nmmi4UI(%W?I1& z5!I3_hDJT*vxIy6AtfDuvmF-PCYQS__+vsOE?~uV+LZzzih@X^jR!Wq6;>n^Hyb z^Wb_Cbny;Mf+6pd2@M>2Qr3l`s3v(c$=Yo>i;~||j?CQt?~a0h{`^0xTL_ve_@=#k zsUjZZu8>}765Lb5i$@f7+sX9l&?X)*PZ}ao?{zQMnwS0Hx)etm@*BCBrNAZZQx>LB z9&YvaheoH?_$;pK$6+6G;{@*vJSNLy@p)%>UZYgx#js!0c*henqNMzW?JWEB!`W)d zGjXHkdZkvofW`kf{?9V^TuoV!vL}2n+sXNMLBI9W`V^TJNOr^cz zT{>?aJ|AS4bS+ZOoYIE}U}q(!r3ih}1w#fbe87*y$J@m&r8aeO-sP1z`waQ7SSyeG z`(%h1x$7%FCOT$t#EgZ)V^@$w+C!^nrMTeQFD8+eo~4H6&Qq3*L&b(8YoWDLb|vaL zy7_h`zvXLnjDMZVPc)2({5V{~pXgW_I(_l%y4-jP$(Y=DX_U0sDa~0FMB-|}wq}2Z%WtN4=0T+3J?*JO?Cq6uuh^*geBum+C0wlp|lCiC7+in#sCM3TUF`%^;acJv7(%<9LZ{=OJ&#I$pMH9>bSM@-bh_Cky;2^t+Y%I9($+$ zg47gBL+Mp~B2(lYL@^dOhGUnV#BczMm2uCjv5|1Zl%hN%IqF$Y##7Xhle2WHwP4|D z_44aY4ya*C>ZA-&X7Rxupkh{1 zB^t7EeQU~p$8S~r8$MaAMls zOSqRt2-ng&eXhDJP}4yuIqj$@4ALaBT190IaQbyojZVDQbi>M+j>~){Lvi)OGISm5 zlFxT;B?h#4Pr&LlifUE}5)8O-r-HV{g=b@K*Y-|Ee_cdC6DpR*ylfOpq!f85aW|v| z5kMzmh5+OV^||WRQTwn=6S5;$s#QjF9=-~d=i@k&nO&yeKm_M0CZE%$FK0!fs6(~m zLdFuXA6#n%K&i|+6SIWZra_DtMpm7)V}^$J7=rR+Ti!?9H?jG|B5lOU%t()&A}94` zW=ml`2BlVdG|{1@JUc?slmSKE-#tAzfr3lho3_=OXGJ2^1X8ahPV?rd+0ecWO8vm! zg2U}}nro-^<=(%X7B$&ya1TDiS6p+Y>aM*j_u_L!zdXnVBsc{D5|Gl4a&gf*@yxgh zDFj{I@1~>uMi5^CpUhu+75G{hp&Q~2&~j!%F(xiZpsJj_itU!bml4=|Z9o;Qoi|W` z<6}#{l@o)&K&IQ{Wj%7lme1~XiZqbt3_<}~G zVsN~u2<)s{)fC$0r3NP^Oi`7HN$oF-H7h@rzw%Ixvp_L4$Gx{slqz!%!5>e?uSQWk z2ggepR{)aZoi{&uE9^h}H5mp+wDYe8O4cXZG=w|3#ZjU*gr8(x>3$YEQd*6?s3kj; zW1l{cLsJ*7;yuKMXYE`J?T96b#ws8#f4AjUvg5hd@C=Mcqh%M_4yh$k6{|#a$q8yR ze#F41Zv_{K0~tS(qyj&G;s)$Tl^v)Zu=LWX;`ZC;-k4zu(>RAgOI5u z_8_7YF;zxyFk+hEJefWconGdihr9IHAzC`S@8+hpNZsWiTEy{1zY3lc^`9dvgN{cH z+WmaBcl|4KRiIL4$TGc{yOQJZk^gV);LQT4hk`Bb#>y}RFFUxfV@B+#o6y4`Jo=T@+(nNe&;cp?K91pNF@^IO5iBB17U_(T4LGP4>oEhFZU6a(3C1&1kb9 zGVQ1Cx2tb>TR|x8H5D}lgH%?m%Efg~<^O%cALstl?*B?0jnn3D zHWmP#-ztp1D}X2;A>0EEaC&Z%bl5Qou$en-OMS^%e5Wxe?6NxaSJSPDD`%VaJy;qA z7Cz6aD=t(%P$JsJl|f-pEjObLJU-)`)aTKm-PlePK&bhxCkiHE#WvX#CF;q06S$i7=~-8QpwK8_d{CtlIIPZ!kjw z6{#n_O}Y z$Dj6Be&Tz5%7H$47jvlRzn1q)hC)gp&!J^N93LkT8&f3f&%2Jytcbex15w$eT5+f^I zE9XKlD&J!Q&c3OUc6fhq&9uo!#M!Stjn;b-Mj8IvK%2ub@JcHoFHg1q zuwO;bzIY}D{v1(J#A{o_tvC;kAI@J=XxYoRWiPCt)nTkBnqb1_h~`6QV-;z-<1ku+ z@#~n@>}!h|u~zkZQh(WG;BTy18Hmt@Pn9(l_j_!iBNWu0T0gTdr@d(Cf&~J{%#X#_ z(EiGvvq^gnY##6&tCkvqRSDQ@MrU%D&eWyA+JZp=cv05iKb!~)e%9(?B1 z%~OIX6WiBx_{)B&<|VB3h@k~y9ABNcolUcuCkZ_+_rq^qKZI_T(CMSMH}HelSKEAkaxf}XpAp>L zm;Sjtd#c`ZqDdaNPMs$;*vCs1WRq->uihKyf&?|&t0(L}al_UMAr=m2-Rt^qH(&F+ z!9>9J`jD0UlXWX;F#Dg37f_<*<=lhRnHlu7&Dz~ak{)EP)Qs2O_}dW&t#xHO4wfOTzN!!B{1Ku@`O`vM9pZH*m+oan2 zXD1acitfa;1-d(FH3D8wIz?q60G;BxlJ(ri@n%}JN2+Zb^&Upb;$mGb~6JLw^C%38$ITVL+2^4)@BjRE#r`3ideuM83;(m6wfpJ)LMftB+uk;Hg5j6 zJ@j3G{nKk~Yy}_x>k=LIv)X9Sw-0`(oqhT5eKt(PAA&^3lj+{yimaZBFv2gq@cN&X z{D0=y|A4ak|B!o+wM(1AEvGVo`tH}d%{;W$=(2hyWxWH>xI!L#(L(~~warWXqcmeJ z=^0jW>Uh#*Vpg9}CLUhYl_=BpW`*8*@Ryu!yRYKdhg%$S-6;QMc}i%qH%;Uc%cx%u zP8BmSq7C8GGXVynfm}(tYa!H%;aOFBo$saK{?svp0?|Xz_kkZ3SJTLDMIuY70aJEg z&W%KUzx)2u^{fmy3}9SFX#B}E?KWLfh$5L-!e?k`bzhm|4?-xEN5Shw4){J07^ zvNhVjcwMF~Q5F(_ae*NU;p-o3)`gs(y_Oa)fHKj}S}*Km?JGrhMk-_&3(}SK9bYl= zl@W2iW$o&0I!F{S%jkI@Fx4XQq_E$nil_<*K^obR`j>D}lb-tjBJKI8){>20TJ=0H z4v$fUpDa{5;&J0aS=aqS+y>}H&#i}(S%TNr-5D;g@v3#%I^0vEP;-^0@Z)6Al;zhU z16qGO<}n*F&O7L39;A)_XGbgX383T+O+OOtK|DHc3g#)iLYHy zEIIPJI@5t>8}cpoOCPnRP|7AvE2fX8()aDgwFblsp@=j-ta+c^iN2k3w|8zpi}2_3 zU`AJ+X#!+H=!sp~lPvj<~gk7EKt&=n_ z!RGQBf1#REuL_t{$=_@RwT${HO|1Ngi?#@{mW1m;hA}rOedPvb8G-g^;~^3v*Vug5 z?;V{#Q2!Y3$D-`mlSc*@yhMvfr3YkBdux}P`q9ydhqxT$J$9|sRp#4})z%M7m)1mO z%o>Sgwgutfr|35`Lfl+pm6=;R(X@5=Jw8zy{9pP5U2G>4!{9%A0qAr3JM%_R zRZuJ>jlI1CQip4eOPc5GNVGRQ!_@k5a+^()u#x4JsK+GQa=Xj6JR2nTgPNH2x+oiF}*P{o@~d!o%R0j+xv}udLtmo)12a(BnKDwMQXQB1d60zDvg1Ck>q;% z=sfy*Ki%Vn@1)rfE)G5ai>^k(0_HW%yWO+G45}S>Lg?a3_)Ncb^XN7d+p#oQmeO37 zG#Z%iZt3mVZR;43y#cfkR~D&+1Y=XiP3rhMy2 zT=~rkf*`B}8Vj;At0M={XHb$4HhD^Z1Jz!}_ocF+VZYdpRQ)TTLFej!#x{>WP8BQE?-tkV%CVILi7RJCQye8r9o;%d*LT;Jf&tzW$A8q) zuHtV-wM=0Xikt!Ls@Ddtr@`lYV}{dYDdH+e+MBI{EN^62Wgv?NTK~8|f9*GJ?z)es zcvdoQk&3SF~mV{kYUVL zGUaAsM-a8$(AaGmO22PNnOLOklp}%YkpY1aFCSGo@=oVJ7aEYIkFdWJXj=!^ZVxw; zKk?GdtgZd=u|eW61LwK2b51hdkVS|ggmjYmOC-b=JG1oe?<=<0ES+P;NHO1>&0;nj znZ>u06}1A;Xja5hR&|d)V#N}b>MDW8S(j9w-5Z7BFIZPx1fJoag`D%3qlqy$3F~ z*O%+Uo!pCeT~YPz&4x76u-r2PYN^REfa*at%=;+q9v`_b)Qwf{kOlFrS_vIhiEF~zf3)KtHQj0P{=oWe&%KQy z7wNXfk9DS%&7dL^|MBb*c0_R^tuS*vM$*u4N+ZC|*V~RXB#6EzT4+o6Pdj$S?n8gM z@`v4?5>>h?PA<(C0+xpq4QA*h{e%?QY&mAWWPkdfi)_E$Z(2)mA_wNgCTn_Gt@MpK z=URB}E2VV$^1)C2TU!9fPAThc7x5188@si~h=LJ|aEh>xsS1o4$8zn=*c%H@wMz*vYFlJF?rGbY z^;i{G%w?E9EHOLu<5`J=>Ct-WBj9+FrzsfFKiv&$3G{6Uf4!^QuHvp5PcwqC36}VDU>}A%Ft}X zU)0F=6hOib?sbfO=y;1YCNL)&q;1xD+iWZih=WA4V#COS`EOA$-7IzqM)FgACQHJ9 zTIX2wKNP&hr$hQel({sxBiz_m3EDf}@ydXlAI-@g)Cvo5FyA}~DM2|^TXGSGot*SX ztG?&8?@iCHa!cG(6R-a)BY*AD7-}5%NnY7bT&?j^E=qcpOF(orpu^rcA?DjTu|Gzl z=)bFZq4;59iI|HUX^Cpy-YC~;TK@@hr8{^kli^e)lFkSl{W;Vis#`Xt=_IHT`CLf6yNgQZIQMFjgt z*D=PQS;JkXO;f&fU4C@i@E@A{DhCnFCx}<9f`s5>Pee<0`ReO*3}PW^`QAFG6Mmf2 zPNF8%`&iW?DMGH38(H85w>;w5On6pb{peh|q81&jA)pr%@5g}Qi|a3()BlGDf8{=x z=hI?CtJJb)#+20lw3gl?Tc$!ZzwIC~EN(2pC}px^yYO7)*6xhO*>e^bCz zQkm7uQPkBzq^GDgFBYhyCLvu5JSZHU;3sBO*lU$WbJ@eIKQ`#&VWs`Wx@f+az2ZtY z82%DvG58=C!x!XMDYg8~)Y4+jTYn6j;D3*%#F>x1_tN5Dqu!)_?6W_hIb?X^f_w&Y z?9$}=+8-%3G*|3nF`BJo4t_f5OPPHfzsA$QwlhDe=&S}?d1|Kv@_hB`i+D-*q@S29 zOSOXtjTz|Wu0(bfmZKWxR+6B$^>6F`=NvB36F%KF2_CBso9{<9eI7-H6yzgecV$(u zqCzHrVf2V#PrrlG>`;cwi!YM=FFva79^!q%EPxL~Zb{q|K+%X0?yO=gLXxobdhJ7) z0p=q{L(q2fhuX;7W6%G1x<75jYCzK1g<^DRg<4*$(wT|ahfVc+);=kgacVltgC=3= z!|P=GXhBeFxvb*er0C%SC9KeM;I$l;LiTd>0ixu75~)l9Y8_Fkwzj$5w^UbcM#~M7 z?qn=I*4(LgZSfxlh_(lCLLMIi-8^vFsd3}yY=2^eM7!kKqN6Xwc;veoq|Z7dQ61k< z!T8IZ$9HQ-8BDh^=SJFm;oQMmEW-W*rv2PTkax;tiPeg9j-71a;Y)gd82&1IPxpOQJb2=@>>+*kYPLYdF z$S4E*vT_fnrU>8{@?>4+E9sC89$Cq3*?zgR)mYW)(S!JDT`%!l?rz#f3#D%^KXF^v zctbg75aCduCSPiVAom&)s0AvU_cN}QIw`;C{f`7JE8T+KbQr|gZ<1m$yFyB z?q%FI_?+l(_`;lE*N1c%fra5RQ^I+xhZEhrU7SED3Nm;_tvqf`^Qd)N7{teU3%Fik zw|D56uwe-9rQ3JkmoNd{nwpqZ%e)KY2C;aT=g|L9B)l((zx3fo(8J)1sC%11eASxNvll)`+N8-*A0RSD7dULM(6v(6SYkE!AQDRBZjR5CUnn|4$!#LXm6@GCT7v6*2#i{$ zM#^=(L>feD?H7hg7D^H*Ybt=Vt=NB<>iVVyz;o5#hbkd(eyN^7M#;uk%xD^i zPb$~-EyCAWdLJf!xWYlq!|Qeb*)%0hd!pn#?9m^1PyZNDX!Xw*tM5v^*~ZcW9V$04 zC~~kfNFRi)AuUt6yp>m+bqY4GKG14ZG#uDt!kCnCIW@O9i4@4YYi2z0{@Ug@Sqwbx zu&=2y`rzF)Mr+DH7>Rz@Uh1@vmit_=9q-R2`pJ)^se#+X;nNLk_&4XcI=Ad07Yq!R z_sOl|dLTm=*tw!)Y7~hjjn(Qj>mO!!*@3@LO|7AJVq|Cvyc(yX_!;qC*v>;WO>($U zV$1sNTkk&>yMLNPkr06mp$FYedFa8DV>766zB*x3g%Y>dADlZdVAZbcB_TBSw9UN| zRiqQ)%e-o4qSXyc|972tx7@bn0i|ROy(^PYAJ}7-{y(R100H0x4%XY>SmH`waKT8r zk?~QL|G7KQKc|04YQQR7$iC4TJi#!of==RkTkS7wc+^*MjNTy zp=ZAvbX{tc9QUa~dA*v{z)kR-`ytukQ?LuX1uP1f@~%O(^H-`(3pG0-0UE|9OaF73 z3*((?1N#2h+Kp_XT9J`7Ky1pId<&jz6W73j!zq_(qyproAB|mR-k5+o6-Wh;#raR4 z&U};EV6qX%XSh`1zMoKNg-{mFQD!0i>-I^4y5;R2ByTcIN;;V9U!1%4W7Skxy$b0# z#ixAaXdVaI!L*e3+ zF(kN;IQ_h`xkqUbPIr3x)Pi=b;xC-YWNu{$+1vl=`23G%(*ZOeyYfNYxi=2|TuRYX zmal$)+0COi+}=5YwLYjAZSxDLRil6v*NV9<-ZiBuB}eut7RGQG9?(DRT^cd3d^)3A z!i!P^^`_te1ND(1Qh8G#f#jSl{!gZLE+6*%b>3fxp;qlHW_aAp7&(wE()<_ff*z z_59z<*AS4QcX!%;zA$>?ekMxRn!A3RH?!ZcQlZ7)xgB6mC5D6!iN-0_&sCNoo6_0A ztdxc*c1fauI0;9H*Ath0-4)aF@qDmiS5WD7V~-k2E<8(|t2o=N2&MEga<(?DQV)cO zI~YS~-+bT8{&J0~iV`LM5n*$m)qNDk(Kt=m8~aBzuvbx ze};L?CxAd9cgn2()qfCqDrfGXjmSpRmwse)-gMb(7wXe5yv+UMQ}4`=!l2^Uw~fI6 zO5}X-$8Ua5<{t>}XU+0@s_~yb^?&;?LNJFOUo#=2BEQ<;BQnvdFe{5L`3a>T{(eLn zbrdCDykAt-BR<$^^VtsEQFrC;%9j}WOE0|iBnZET1S(PlzN(3mT-$nkUEZ2najo(| z2VS!sf5pZo>3My`^KN3hHEDL4=ggvQlxf{>`t=3zC`NZpsvZjNW>w ze~(!bXvD6xXH{?H8xY^jzHSdk>{&|wj731H{6>2d7BiP}u;jbnU-St`xSgS6ikrDx zHr^oAu29U>6;4Y?iOIap=+heVhCciy4u|(B0?8*uWos|=^qStI_5g)>7c>K7~CWBJ%C?#}Dj*KgflNh<|(j^wf&Npld}9v~aF`XEyv5$M00Y zq~Wjlr=tP|!LJ6(NgH*}T*Q)y-U^d5&XiS}$4=6fI<+xUhpKU6;#e{`DzbKcFR9--ZNS`)!SQ{qhPClWEQoU z(Bu2|jbxpb^Zkm%+ezuGz1P;>gaIt=!%T^hJnLcRuVN^YcmcQ{u|XhK+xf#l%dowD zsN_Pq+#Pbht7QV#GHjYz-17Bh5$Lp3R%GOs0GD9xypzM7!=gipZ%2*nuloFUo9N)T z^7I+Zx>L&oQ&nF}$h4P}waNq#TW3bNn;K%t~THgpsNp77*(-ZScO>mtX$J z@)I#`sby`#j30JZ3H^=Rcwj<&Oz)s*<7Gimt>;c-?CeNDh`Ck>EP3#J&R8gwd?0Uc zHA}o@g;Wp0Y|mYz(>@bO^)4u}6YWS=CYU_-+=%iAny!~oT$!&aXU^F0_?S}_WfZ}T z74IoYh}=rtx|@eyI%YY2Z4}4jI*ZIX8~@kF{wzNOI9+M@$_knKQPZ>mp~kHL$xA4& z$3V8T0J96S*!;^jg@sb5b&CfhS-|n)u3E-n%@N>7lVxU=Z`9*<4fLZDhY_z?i!u1O z{o{m+eD;Y@G_m8nnXtID{mit=^t6sqX?CUE(`zhVjwi|_`Z5+`qg5{bx#+t0XlwOj zgCKY4lS~_f0`Lc!-MLQh8=>L^^-0L^dOQ^c>XN1t?f#6HaSmV(aay!UxMaGdandNUltfCYU}4158>M96_R2W`j`nA9 zn_aschlUfGD9coV(Y)9l9?#4m>E|XaNi5K`Wd`>g`NAd~MeQ?;8pguva858!(M)9c z_{yC_Hk_C|1QVHBwriQ{t#a_{rq4{sohP8s+?xd6wQRD+)EP&qllh+FXAUQid?-Ny z?Nbs5@T!qiiXgKfINrfR*I-2M%OdLg)Tae8&$jnN>@Ub#SuV8Jwn8O%Z@gJpA@Ivf z0%Q^a%QitsRhlhvdFyCVlz$$%F-ZQBJIQ)8Z{(wNCnl_-fUAT=v;6MJ2wScnYE$NK z0;8|cL5T_9>$(EWjr+#T6$%|0G?nySWF9wg&eZh&G9xDG#xK{{y1VmcZLbow+vf1= zGiPw&_K3O^6m7yLVjUb0xwU+ReH3u@f$6(T4GFHnOeGWK$9_N1dNEUi2b{7#Vx~lt zm4+$0kERL06Gvur&USVAmrad?(+;yFxq12n96rqa&JH-2RH(YXfyCwJj$e4y6%!K^ zuP1hR-+4oWyB58tUMe8Jpk?D$swIi`Q%#-U?ZiULDmFU))) zm;miEG3ZFL@a?pEA+pF5W%%4Vjaz`(E~ia;vdYFbSO0#Z;_XD`b$ceq@gLtN%C#8C zoV&sDgKag)8wEjEY0k8{SAE9|K)I`#=n=>zmR>-=;>4u5X{GHwgKk4hk4ZDZN)v(( zP)Nz}QP+TmTt`>;%_u@;P_T@zmC8riFGt!J-NyiXQ=!zvK2G0wwM`B0YasKYib#jP zxAAY)dtZ3;CqA!mGtUz*b;z79QqOIzK2MYG_scJ5SKE|q=(GuTD=@LXe01T}EZgxR z$F_{b!`C{E35eQH52vfjvVyt>NmO^OX~Q#?4@?8Nn@3QF3&P`=+G!OXzrhaid0Itt zk_cUW6!W7v%fHQ~*C!u#ZhN7t=~4`ZdUgR-TxyzP{lpoq0xlvi-QHz^K>n zBQ?sqUGQ&@bJ#thkTmXC?!_C6(Wy`OFISnS6uR+}T(yeLx7wUC zZExhLSPbCdU7|I_s1m0&%-}K?3PG$?!KtfltT7xwxzr-hWYbJrigJEneVT$>`kd^xmo%P~j*c^358+ z`IsrTQ#|9#vz3-g36qL726;!~C_frfM6d!VaXXQBd^gq&3&g#J=#T&`8Hoj;C4_OWIN)0|N_&@$o))viUUF80*$`zChv~tb2mM+79yq$t~%=pPh)r{UOWN<8ika(hvZuF{%?bP`O0PS;5Raq&q z$xv0j$Zs0Vz*u5TcYzWk#T_~5!R-wdMbruO6Sv@C1)egn ziVb5-9Iq@NVw_PT;Qf9%+xsM8kA~;U45+_UeEZbE9oTLutvPDxt}-cvd{0)R`6w}9 z%+sg@oOlUC;h}qI_wUFLwR;Mc)%4X)gr#zKEaeG3XU_WA2Pz4>#NPu3JW>{Q=8hKQ z4L&HZ^saLe*wPIK##?Dzq*Y5u+~Xd!yK*c7#=r3)v7$nV*5Cp?U$P+vTQ!uPhIIyjzx}%nq|8ZUV+moUL}0X4v7+eUHf%+ExQ;I zBl;{zc9Xcxo7D#C%|d4(H_3&mCErD@Y#PJF0|116pf&|^=*LE_@rjJimscA`5wu$t z;sCASMA-RPuZ}9!ua2MVF8Q1qqTjAz9j=xLhvFL^kC5YitTmM&AB})k$U*wNWidT( zn%C?)2!t2K$MQFi)pl6FQ9?QwdQb3=)Kd$S$u)|CzBm@F(%fsxs_W5v8BkOV#;zNL zEYz9yQ?_SgA9J;TbDuOpRp)E`QgJ7LilOBM z&&D3$=AMUnSqXW)RQSXx9W~MGxYkgy4w=M4!d}KfhQ0FT2$_~*eXUYjg^GwX5+FG+ zU^?ktkNTa$xLl&GkoFQ1)rb(6(&4@5KK22#eqNAn4(#awV?e583&DVl*;KqNv-8bg zr+;Ue7Ayi@DYs8P|DyBmiG~L#eRs%vfHLM;C7->BF02ot5INE**WtGwJB<@?Mq|Xk z*p3+tJiXl%zb|v|FmXuOy*c@NLF4x)?b}~kkVM3?72HSb<;kNtUqN=OUb1P zNDh*)q_5t(Ulzz8_P16praqNi`7#Vi~nAIrQ@PWrG_#$s5yIDg3Z}*PHmo$tx_7)=+`RWYqoTP1bb|oashJ!DkV^g_u6Zx^iGGwidEZ;N1ktf}FPGv1=2}Hug;iNFN5C@~P_KxNS!@%SB(_74w@A_EltZ6oj z^XWk)+wC@5EC{%n7;s;qAuTjea{2T_)eRd9SF2viU2Py~uRdAQ^vs zcnUHMw>m*4j?92}0Ygk6KaavEfk~=@hTy{iiZf(QbuA(VtS_H-D!^+d!A;zo0uL?> zrTq{k7^=xoU1h4-c0fffQ;P8spbNZVqD2@5ngZgg!&V{GkR9Q$$If?!&4^anDlDYye$t>O|1Mq_{Y_Ozg7a&mACi}FSGV%$6CH?Avz(G&Id5=SK%)KZ~&(Mw+ADO5j-~XMj1rd86 z6syF{iyTQ(jXk+-ZvrSsdIn}KGeF?_;$8%Ac2#<{!IQ&|1gIJ^SU$H=nk_;;7F`hq*J8FTJ0vr z#)XJ9P_xTWU3PmvUc>QB`h~mw-Rhw6i~o(i_l#(+&_i;6rT-~$Lq2|cKxDGEv_ zfdB~sBoq~C351Rah*;>I0HJph2vr~<5SoSFO8^N?s?wzkwl8~+ea^#s#_Jg0_l>d7 zugxE3$h}y}y62p0-E&@ZUQ$}Lq&a0^v>VvSE{WHy#Z3Z23-WH&1-m$Cq4x{!Umm{= zeP8hS$E#t+W7RAb!P$|dEm0vRml~KLA#;PVttlG@0l=C}?jl!?AXu_a4Cy|xUk z%-3Q04r<$)mL|cnj6zk(*MQ~OzA)HfZ*mcC$xA6u_05d$OKR8OAP=TFhlu8|g^Qpf zYq`uZME^edq)f$2g!ObEau)xtaCHN;E~~0DWhqz0FA4?^GEOG^c$@EltV!;2vz*Cn zn5nVP`3`&(%RM*^7w!^>3WT!Nm`uxkQdsK_j6wU``uz+h5N06e|XTlGeDZ z6nFVAUf^BeVx8Um8yj0mKxTx8P>-aAUEyc3I`M73Xv$pmc3H7ISUe5Mfl@awn$^ht z+i@SIi*0F#8W}yEU7nOMy&@@0JLk7`**vm4?5ur;+k02KZlOFjp`+U3?Dv_>%CELd zu&hU>AQ{u!*a({(*)It+7>sQJjPO7e02-4x3?v96mHKlSbl#LngZkO24%6FmXH8C8 zG$)VP3e7pszcxTmt3teJeG<=TwW53F`H>@7kQ!&X0-lGWh~Sn;QFo9E-*4ZM_SdPn zkAHm7b3JK!2}fDJ{nae4TOppX5{@o$` zOH)+QgNxR0*aJi_4<>5a zSePy3k8Q2ch7yuiWSg2O&u{vsx?_LZdGGISvO*!7bQ6J4)% zq4}j0@=&T-%6g9P*GX91$_J>H)n51ga^7}#!1q{j&okqJ#-|hwlYxtr6z0B0On`jV&;bHA5s&Kov@1sc?@-?QXqx!oS zI?=L|Lr3{zeC*DSayRgmQ{CD;)#mj~j#O~Aisg}YWBupG&Mh^hCC*ei(wwivKQq&@ zts~f;mhMC(UE<_{DCD*J7@1^ss+l2I zMBCe=P(ms{8Lj(>N=fXqCl>mM1rpar>;nRvf4J_-EdUO?H#XL$qgA4;C(FKOA{$l| zILSVPrba;~?rFLxS@`S<3x$*QmXMN8O|_PbNMvODL85q!Iv>P%+DWzc)0l@;9Cw+q z@NF56Q#Be4gc(STEAThd-|_XxrQt$W>~lhTev?_o&!2UhAC4^PAtrU(>&#`d{q%5u z{S?Wy>Qb=jZ4UbhS>#6-AC{U~xJ@p~fK3<<8VzHMw7OQfW^7V4DCr}~B^86wi|Xst z+gmy?_bYfslYy9^UerNi=+G^VYvQpP0#hXV1H5iSkkqpY9 z<3iWYepaX+e9FFGY>-3ewxbvK5L%u%;c|L()8gnr3(v?J2?-fdl&sLP?aN2L!I66= zaNlO$oQp5g3}ig4j~+%SET1wpYKBFFb|$<7iaqz^bAAr~{rv-IHvL&G(CXlLh`PH7 z7g|5plSImI^=eTV3e@sVk-(Hn3>nFSmuM#zy#H{IvWKgK-gBH&lNzqiak=+mO^MHp zlHaZSY#wY=6}hbQtuS451SKRaJ863HM8{M6Rbb4Lr*F$jyg0{w%89dydWa4b20jK8 z>1e+CeNHP}zi3E}M(#h;RsN6C%^Yzb{+2266~ihMc&kg-e1#E`bKMpC#3D!kE{Qhs zV%WtMYUvuQzRHQe%>^8;2xFIx3ir5-s#oGs-9;KWAp^CMV7Lv$Gs5bCp?oD|FdCV~ zer#*|4@;=Ed2!_1V_8d1Kc&$+BD&~ZaVKGDHi1-1&$|E$;RGhcxjF2*hJIUya z51#m>iHu1QT2OS5uc17euc|?n#MN1dp+k(#1U$IGLb75yJv{t-o8m()qVa+gKaV)V zMYTixnRN>08R*PMLjnFHZ-xA`>~4F1dH9YD-aI!!?QJVtl+t4HlG(nf>RZ%lftvJO zoY){SAWhyypu06E76twp_AeF{`GLO84DKFIm)>2{i9+DZI7Bnu(Vi)A|IbJZF07?9 zDPI9Hx0*58A0?`A`!(vy8MI}A^+fG+8euecMs8k0ULm&H0z`|QN%=yLjI5Dv|CUsJ zPvz0!KVJ5zw^$yYPIM!`SRQLA50_`bytRaCsvx-sB`wq;-i@G{UM0H9GLBJeb<5Jg z8JHoFv>@5%C)^*-rxm{TsFV5`z&7XIy?sGEl05BovGl!ge+Mw`i%srz0Tus$7Vqc^ z?G_oY*}eC7vzsJ2Y*hOK3+zcj`9Jf7P4cgsofqXRu#s7*Dn%zA0GC+a7Yr4OhD2+G za8fh&y(VmPO{=`Lsjp~#Rwo~Ab^Spjz^)fjB{oi?i|}?D-RmNP+1Rc~?;Uc&T1gP> zgXfmevMXgDNXZI$t4X`%$E$DeYx@#RSJ-IVOOS?|#Bq)aR!KsNX@`g;?6~ZtN&5RP zZC*EMerU(JQNMCep+BiSTVv&jMXBvrjmrrbP|sX3|pUKHC_|{sMlD~U!IIzRnMASTqMV=BhGKa7(4115U(?Dau@GIb@ zRTE2pJAoTVw&Z_V%)3I1CD73CQMaxM8m_g_d!2H-kmKfIqLZVpyXwwTmYxG=)|d`-kC^h2X=8{t z_isO{FE>m9w;o8obnPw3OONBZ&|EXiON(!+8_7r8n70&pf##Znd4AEgFPJ4tCMMpM z8vjdXMEF+skd1*;hTdxzlW`dL7hPB?gI_Ch7kECDHRad8cf5xWUbzz|?@PXK0s&fd zBTQ?>OQ5lHy^5TyN+@Bo98nu27yd1kEZC%3he-_=;S;JmO_;Ys9FDyfWapc>hB_-N z`<2bl&gPy9_=w9rs`y{DIOtr5oo2psm1TN1yIDFR_d=}l$Z%L9?8`>u3fKY{x_@8Z zLo3&z%SXhvp3#FTxdFfCc(E3dXwP-UdF&CyU6@?3?2v$CR!YrW9O{Wn;`3CNJGLG0 z?=|yswPe?K$U=#rW>aYwPqXCk^HKmoAW6Xn?I%}F%csbu$`SW{S`KIM-Y0GIA~H^a zU%s6r6|Q+R44(25D06dAZwHX-yRY}n1ywM4Y^(3ze?M^^SRwu`*bv@no9 zPqqwU0LTtDCv?VG(&`$f*10!aT!*Yq2*!Hg_*>ZX?safWPEl;T!8e;xL$Tvss)d8P zqPtTQv`EU%BrPU}NdS0636JXjj)3UeWeCYVQ{ZOOLVfFO#-LXlKya}1vw zE{tbApE3z^Rr%H(>RERJWL-~$W|+2l|734sPqs0#2mwm2V|2Qs-mj=~1GKbkH2ew* zU@s2L|DgXRjfGqShly4tcW4E6OHTS-c!MX#_P5S0)6_y&{a1&l4zC2;de);w} z46_?Q_D3J3wfDT+eG6vG(_%e~@6It-OrUy+KJ!vYUeMFf=@YbLF!rDhiiUf+cLl5h z719J8E&#AavM4To_aV| zH>{$N+`YX8=3I}XeJ{II7&vI>+VkUY=B~gB9-L*(n)-tUJCeBUq~&cz{Y4Xu z>&i&`IU|$YVy#Xez{SR2Y*4oO>=|CZae%WbB6jL0oNT(May^-?a@s{vQyqV-ZhI=_6&w_Xj`3{+c_iC>`it2>&hWxoK-bnnd99L-yIM+E2|9`@jRa2$D>Jibv{1%RmfnJy4bI=@nIcBf46&d;8f$6gy5ZD6|pI79Yf)^`=g@Z4llAm zrGzno!g>&v5wLcl;dVU5Hd#Ycw3pa7^g)OWQ2K>&I6s_ATN{-$n>!2Jl_XeKS{F8j zuRWJE{>gioJY019(Q1b-Eq~G6-#1`&T}JyIUR~gfHA~_W-CN~qLAk-+wr$hb=;V(N zohVg_iu#}5o1k}oGtniao4y8S|B6}2N8Gyi1pb<+h~-btUD5NEoBK5k()^kCAg&Wy zWv)9B{j*Pcw?8b^;K9_C*~J5c=BK&w1v&Ryhl1*cCwA`lEd50M^>Jo!i8Q}%v^0=g zP^@JJIsg4E(4=c9zj<2xxm5Cl<;X_~%gEg;$P*CZ-%N8cOKTrf?!M!dU1Uz(byS-i zJuEUL-uur1Wq$THV*>B|xNYr252L=Yg0z49co+MFf5cp~V@Chu^9^O+MA1S*z?<3M zOx?y0xiXTX0K#-Br?9Mdx{&bk^ zfDAmO>E{Wqir-9@_P?3tuTL_r{1wkt@zdisQ(SoWiSniKO~B!$PQ(3Q@w1C}_tAHM zGqHu>tr)|06C;v;Gfgnyb3bV<4%hcnWlW_H=bk)jlX{65lfYjIawZwE;5|gEzKR8S zKdAYS31dPJx{Euyymh^8P2!Dec!_ty>pLOP>(i;aATMZKjzB9daSB%i;C2PwXk3kR z#E6+Tr4pTftRA|jy0OrTbY-D8SR7YHHrR3o`@1_DIGWDs!fA!8r#ea%^ztpowGaqr zi6OuKv+&v$YN?lOB0$vNo|uZ1m8HcztBI{&8+V>2ISiDJBO}hm>jg%&Zwgl8Qk@!S z;TjeOVOeG=Dai{4SGuPx(en(%h4hhJfa!7VqpujPJh(M#9TWv=Mry>W>r1j31n6S- zuSXJ<;8J`*y+;1Zeyg4i*Q!O!>5NR5GyzfVZ1w7mb3eW$D=V##?r` zb*m8NL%h(E>-s!A#dRX4_5!Us&($IQ6K)5_EwUduXlI@+*?+0@n%I1rZw9vXHtshQ zp$YM3CE?o*XYMC;+kOPOLMI)t^0{-db~7GD;L--#F8_L!eTf3p!q${-dcQ$4cj>X7NWBX(YYCB1M^3RkK% z+k9WLuN`zv3A}HNf#(98K~C8FZnrx|911e<_3?)TAH&8jt*ggsHUv*6G3vzepD23 zsc>9oBLgxzyL9(-_7&au^GlH2Ukb!$x5D3oeBb>&|qWoUjzQ-tmC;f=RmY zPvPhP3%x^*AH}4e9m&`=D#~13`lc0>aNMI}ndHkwPjSvNFVuJ`Np?nVNtA-UfJI2& z_39BqnD+D+GC-^#u=Va^DYfw!(_Y0_4x7fvLfbB!>=0rQy8b9d1Ve%h!POAt!iaIR zM?!T#rq7Vv4mR2&AcW(SX^PPe zuAk?!^q^Xg$=pE~CAlR)lggIjHOV^-)>L)#i=mhZ#NLC5N0| zOOYC6PB0=Z*dkaY4Z6La9=tD-lAS&*UG8=oqO1#>{A9Rf%1?i~^LrMVpfw(K}8McsqWlJ`4T#&;bm#Atx zE?6Vzr6bvo=O9aEsIb9l(q!JVHI4g5n%0WP+*L-ntqQJaLLYn$*P-Yg63tBH<8Li@ zhgJKtt5bOOD$LADdnQHkP?5nw5$*z0>??SfNCQ|TPiP1hQ|Tru-CEWW7vt7ag;BmC z5_WMArKf4$Axy)P6|nMb0_?({?%lL&9#yy!R7H-_a;|bwFL&9OH@PxOM`wG@`Dkoe zst4<*zxM3&jHE}00J_M~ z269R?eVxC#+_EK>zm+R@-IHpNXp3<8ESCY4^T?W*o(7)RbR_ycR@S0mzI(~Cx%3lv znrU{oVabNGIoNpM(D3NQgwV8`eT%L#B5y_Z*!Jv?Coft%F6)jW*{Q-lbn7B8(hHKC z=+H9=lBt}S;%kyMsaX4vzW3DeGOaN2d}8?a7O#8sigOwx_v=c9dnXKh!5J6ZWcUp+ zs!?Z^F8aLRuzUg(8fzU{;6I+yKvWc2G{e-CQlU`YtxT9mC~i44Ay0NTZ$(+_C(1g~ z@*#tKy2Q!N$$Y5jRGlPL65DM00O&P<#)zPSPrp2qpBp(5z1n4(2j4PzN?zvt+s*M@ z`=FT6`7%6fk?b2GA_e|h87e6v-QM+9>&AERgvo;Q`$~nfR{3P(J+~--d1EM{#()6j zYe|O`i^BtcrliKu7Y$xUZ(rk`>)3zh^irWE`>w|aRSJLQf_$PrO7yiV_JQ0+oHKVp zd0{s-vJDsa@FVR!*o2e4H}_pNu4`ae+xomtAR$wpw@?9mJ2)|Qw4T9}wYgH3EgJbi zyR9~Sx;tfBrZ>1J16yR3B(Y`NcQcZ+fw^}+I=`Vl(=jX7`Pxey!C_@oHLPsN>5giu zoBTC<-<8|I3j^&@_OVyfocfy78YAB1;u3joeq6~972)D#vBt#=~zWlgnMh~*) z%hA{&>2bjGeECOR<3)VqpS5l%)|PL2d;UFsjm^5mP4M99cOLrQ_*Q()cgC@c&B9A* zg^E|e$^xIA_GOw&v!49w0>rs5+~pk|D>ld$z|>wS@{pR`lN6uW+Z1>W zzk7DVvTTO_OEm3X^ROQh1}522)L%pVUwh78c`T$071{4lT4%$hv#O~G=fg^QkrTef zqA#6|P`#soB7dlxbq*ei%@r~#OVy!_*k~5T7~KdZSDY5BSYempy~d3s@#I&+AEfE! zwMBjp%p2Bl#GK3%2GP2##F|e&^0)1F%G53Lzfm_By{2ZIr6VwF@yujtq zFTHeim*nIra$Sg36JchhHx4Eh4|2^?8BvxE?#$E|nUBmyhFx6f3(lq55i-VSc#ZVaT@-Z1 zyWBk!hz`P^64whn6D)KRa%E0GPM^5p-1=m^Bg{mj0w@75?Gyq|Luu;iDTv%hC~Ro> ztqb^*DOWabVyC92gg(mQdZ`)ZT8v9rRFC;ORE}h zwdqe+?=oQS!`ohBK6G^nsB$#`3cJfpx>S}Qn@F6M+i;x%foL&SL&*+1RJ)P!n=}+{ zPpIAB6skO2Id*j-G8J6PBBf8lgN4BYrhIa=Hpj52&3PW6!g$c5@e;WB;CL4F#UwDW zEl7gwqVOGv^)`2tl!Y<601GSY>~h~4S!*&X8ge8{a;jKDA`48R$v+S`e*l!CF+;W= zgpKS-+<0>Wvf$@rz0c?MAHfe3+X$vQu&r%&@pP z2b=i4NZ1DpE5)|5DZP1ZY4q{3!ZjkH*k0ehE;i_Dzm38A#uo=!g9oq_FYc(wGi@b7 zyAak%XZklA);D=`BS+I5$1Y7Kl2%K3nx2haE)9#_?6F$4gb*FO6!gjLPDGoe@bhat z;gJ62?t=nYV?uU&A`uOInOE`pdWmDfP_vV^9ocpJvv^TqPOF5*K_+2INoNX>l9KtW zZrbyV)W4n&C>Z*`KOZ#zW=io;R+sv8q1d~RdIOrGmaqoL_B06Lh~6v^MtfXb?dOZ? z8nhrD_WbqA&k7kFe$84kX%SZ*k2jX<)yUNGyu4oovs9-oRS~-zf5_v_JB;*!qWRoX zjlc^eknjqBWV(E)odx?kgQ8{7neIlPMmrjwkUc#j?3GliG-~;%p{AHy)VHLcCZF6Yr!c&Apb?f+u z#o!8(>JVB+)&kl$9H1J@4atICw7x-G42! zQff{!7X_SRy-LWiJZCK%>2ca`3C=;M`NlaUtjqv0semTc>W7Ei&akWSoV2p0iLZ|Z zgKI~*92wM+Lcj$e1Rev`>+b%R{9dd187wFT&n?Vt#IkOFAm1LQ3tZgk+_0hLVcw$L=6xa-}mEk1> zD=xIzyM-I>5RkS(KT7@L{Y1M6n%fSJqkwp!6<6}BZ5dpWNpg3YMV^@VU71^r;<|I? z#?ujG!U&vLnHH>+2GppDYXiN8vFjGEi@^xKK$9|JVAFMz${n^degRkOd5-Y ziF7^1B3E)Qa2l{#rw-GGckj32NGnkpL(b)*F?=0ia=0*%kB6MxCKuvASEB>ZBUUHrzV?J?P`AZ_OKt9Vt*{eyL+-#75qer1I@_8LU$R3Mv++i z9G=Mbn&cl17;~)SW?3!QPkH*p&6P0z{FI&!VI#DyVRSf`$&%7oNEu<=Pdl5 zbvB{AzMIL@7vOloq9{nxEg~}t$DfG>0MBF4a5L8)Flb8VoUGFGt+r||%@>n0znLn( zc#9~QILoz|WYS0qRWtQiH!*5}XH8H>OvxSZW1YsYZTr`1oXgYQ!lBBAp>DpY`do|% zs&u@1iJE!g51^}AP2d2Oh6mP*!GXPlSoIVk#^Nri}#`gx|4qaya zKE2AIpt?CVDBe{&wVGGRA~?lea$JqHXHLlLZ~U^6sO$UE{CSonS-qg|dAtbWo;$)u zsSwL7iuKBaaaT7Ci&NrrzT^R)21fY4lp(XvC#n}Tm=;v7K8>G<3<5_FrFw*7hJf<` zbK;Z`NO%(H8+xYq%4Q1smbZ;xypXX>J?*ZtdES61@ata5@TvQ42 zay)3Jja+>8QP8lYG35pznHpr9BuulF4C0tf9_-T08Rn5kA}lx{w8RS(uZt48_ z{Lp=@gGi3Wg&w6OHZ>UB=M z%cVg^rh%<-6N4*ec5~XqG zYACJ@LlQQk?Hgj3g#^pZleI65?QT=oqz&u`9JQP9YFQdl{HiXvh=Jy-3FgiAWg%@= zS8pzIphw)F4*{*P)-9BYh5|)nUkwJARSg>7DwaU;lEH|)HYuW!WRzk*-vZH_Yi`t? zcJ49LDx949`3_7ND*c!g8D7j;rR-&@+v$I+QJ;`c&#jwxCW>_vv)wk{f!uYUR2$0Ns_z^i6tYO8d|*H*yGVm`2P zHtN}r*FxsOHV_d!OVV*=_wUyy*&Nfv%oJ4gG8YvjGq~=YyRhdRx>;cSm^6gGb;Bfx zeaw_ySapA1%lGRI3S=V9uaBr22f7-md}}6 z<*DKG7TrxhDYTpOWDF|OC;xuViOCgr$nPph@%dy(L?!i zRwHVF?43R>TQCVY&->4q|07p;;{Hx;r^)AES=Oyh`%>GFS-}%{=YSP+F8SX~dtKYI zjLHhEzu;Cv`Iue(!|AO@DZgq2mpwYQnryQw#sfMC`M;Sg*vy%j#b_TA+@5!#c)6SA z2gdG>o>bO6xF;5HcFowOqWppT0Qa?F?&H-=>;|Q2PTbS)&F!I&tr{2dQ9p;XUHQVE z_;;k(y{{`8!3~;P-3`*O7ag)y&BG7sb%@(3B>^EC!8^zf6yrYlUagy3zD9U;cfRtF z&BnzuwP5wlTU+Hv`^`-=r4{ZalfDdtnF0osY`xCQ98dZoPdbfAD}Qh}TseB!ZdlHA zGGrj?75|)314v$@ubhhB?2b7Uj_tfRPaAU=%^1+C5ncK<^=8KLpi-xZ>E!15`0qB! z8d~?WvtR+-hdru{|E_qqVDG|?a-@RA%Yqw0h3AHTR$BOdU%5fQcSe!0I$kv?to}04 z$wr)tD>`Xh(zGIRI)E<9QVrC#qW6vi8Sx>iu|(2F>8N=SOEvopN2n5e*hvjvwEy$5 zi1eeK_L&)ZP{>zC0W0IDhV3sVmdJ;H3cUWWzX$t(F2o!geY*Rf6&zA=f3NPEM^&~4 zG(E9x*C!CS%o)-Nq>|l5FDf zg2tRV9s2EXEE?J4FeMDm52clzMzVRv9xEA7{uSk9Nx>`}*Bcd`g6HaHGEg2Q`do`M zh&fjzE{=x>oVi)tDBIs&!-cNUAxvO#or7wf&KYciBX~aY2GkNvpDv7c1zn9x#bQC0Ff**ob&W)G?hu-y)D6J zo+lcj(fJCUsKnvtPXo~6#iP6Wl!CIuZZ|J(uh8}*Ng`h~Z0vjyeCbQQreDa#Lt@jW zd0Z2%%W|n0cPCrT7+`}>0Zs1>J=3j0Z?J%)lr`qktkM^z!HsTp8yg;0{2>`w6Pfxcg@u)MnZ0M2lb{ff0a+PU3eihMu;9y1SR8M7 zAb^zT74NPz`7i-I3oVH-k_BGqZZlx|J3?(J`#!EgriYv@$|)MfS>yTb-q>>w05C(X}~r(ud@dGlFAM>;~_7mB+rVztJ$h?{--- z7pv?I&~Y=kIfZ|_&(hPQTkZiH4eqoaxZnj{yvM};;(wXP|M~l*pZ`z9gz>unwI4d> z$Hk5|K2M5YM%Mg#$aGBe?SG6q7FpZ)WO@2U(^oY2jeq200QV#G+{^;lxg~wVuiJ$` z1kZi?k6}z_x}YTVSa?+R8pQ5`<%lVyR0qR@p~CvGu6^oesk+7@lnxO)%{8|T5|3EH z6ujK!j$c>6?76KYiH#F;egC|3<{yzY&-K3tDL*%~Az@0%R9Jn@fsW@x#Lfin$y z%J=eqH&_1cm)E>OpBju%QkXT*MVy^qp;f&i!p8UO5G<*oic6|>>q^-3`Ez{7_GUO$ zp)^s!#48@IsbXgnd<&yKhP7tzw=>2JW8_bFTQ+Z$XTnlE%!we_#!{|cOmS%I{e$03%r?}yk>Qt#z|>viKq5Ni zboO{Ok$K3+0nA^_fb%i{<@|31Wc*dO68(JUrWhcPzm$*2{`UeL>N)uj9l7fg*P5WL z5Iqi~OSjJXQ4zUdkS|(erm&rIVV^uh$m_d(_Yo3 zU$17a+@N5Wu&lv>Wjrqq+?MteipTr-x2C_n{6~Df)brnflyCY+C;mk}k|~b$Vz_eO zo*;~sXCiIJIGr#^*Q3=?KVVwadv&6*GQhaB4q;)CiY-LAzYU(~J^q*TQw9QXUdu62 zr?)HUm@}KQATBbjCFgFd$OhwRi#{`?)cGajf>D8feFq=mviIGTQ_Jnmy|B46%+pj#vkcrSF6UGE%+z0tp2bYC~E zb?Q)&RZX5NKezu(Pm@7C-fHUUJ|jQg%z8u?c$np%++8cG+m6Cv9ov5P}*j&uE(}baVK%iEp(vw z+c}hY?X8iP(#a}T6X0O_G{lqbAiDxyAh+JhT;{@r`aTv ziP%9pzA_gaAF8_F8pV-eOb8-6X0s;oXZb)H>NhulznMah$|~jE9UqsooZ;onNeyg8 zoNkNv3lPKdjSC5L^lgn022saeNP)nyNMH=?DeZs#!c&`uVy!#cx?at#(UsN8}MPB+Q- zbqEr8;qKVv%$EVgiG#9jQd#Vj?HW^gV>B`|ow?Z+r?9gmWu#NW6v5)c1eoo`!N$M8 zYs)`n#pY65giiTpJnNq<82($rFyGq)r56m~gsEOfb9 z6dGMJ_i9!rs6Ps<11wn#@FY0M<15wlD7a^=A$%bh79tj#d@b*X$n<|9t#s1t0Qd4? zmR^WMyb7b_F}Bn4AkQwbngl$@I8~Blg^z99|Fd%*-9$&sKMUUf)*D!tc6HLT>p3nc z-f~z)4XK9n*U_&>(a%`ve|PHJw{Wg-SwZt`c&?0_95*3)nE>!k+LJ?1(?NTu zk+}R))-b<^Dkgte+}B!ksZ$n;1;oko()8_heK$QqdW$BRN--+iM)mK&yS$M3ku;>h z#S;_lW__&IVQ-ekghdR2V_qjWTCJZoSI-WVrG0O(iF)e7A4C-ROF+8e$d36h9*lQv zTTZ84?pc_tr8iK}vy)4;xF2=NusZb-V$UZpW?PNH0gvt8-`yY!(sHa!f*?kFFr zM2Labn4O0%vJdJhf+b%U5c$&#RzBKNYxYs4U9Y8j+iE7cqDXUtHUs*_KziNIVp2|H z7_+K2qzBLlO=Z={4EAfG`tfV^jMnWdCq`Y5IvxZ1QjcP_a0b^Pwgd-Jn0VXX`tiGR z$dNgsnqj=mw-_U#*%O}){=MzxKH*1odh=ZqH1j%tI`|i&ty1{#o>t7Fm?$lMR8FVS~8E!7YO;K|5he~rp&-EhoWcc~MtOpa&ZizoWEqnD#9cd2;)4lDdm=@(NC#q)>|rl>5r0mZom^mP7(bVrnB%H)=d}KM*T?Gj z)iYCcTAw-ui03^=k||BLylx&IoVnYdvt z3C*N!y)=C-x|L_R*c-VGPeCQkSEsO)><*CQ_1X665+b>GnOXK)`@R{7j@p?2{hLX` z-0QFeAu-(iTKQrPrU1H-9r}IeKZ_x`@Xcqsvi>wBGPAKHx$hRg=A1feB*6iB+0a%J z61oEd$)mNjKk=82#k)<0VK^6_PSKE>ENBr$6-2XO5{K`X1SzYZ+Bsjqv~L2W6Y~t# z>;HX7Ke8vBZ@aUW5w&)QPm}@p<>nbE9+C85gXDT_Gegs(y%HK{(}V$q$*3J_<PVSoko7}wt@~lO=W3FHZuG6wrJDJQX9>kmQ#3@mF)i`YMQSF2nfZ2TAWI>13Nt9Vsnl~ zGRysA;zB?A8Z66g*^?Zv<0W&w;4Ch4_dP%mNfgy2ZuV0@u}1C#H##p1O%zo;ky1!x zYd6Tv_mJL)UCB+e)88(F>tLgL*5+h|glPWf=Ql--Dn{;za*?Z{Gzx-*Ww4PmaQ5wy zJHO&+Rnz^~gnogCe=|MybZ^ve${*(o_&^NUy>(Cg>wiAwF){rsuwMFKVD}G!|8)@) zoAcBI?ViND*I4&Lj}QLKtH*S)!TSF)k??qM9DIjAu7fGRn8qU8XL<#TU zq$!1Tkn-6bAUqdtpplZ_9op&R@@Op&Xu~PXk0E=s=8>mb!;A_fAs?NnvAT-gkrC?v z!2T)1@hVMuKcrMqmQK@1ShY6p$JBcUh?*5CI>v9l?RWk+({&`1FsDQp{Mv3VCT^ig z@lDhAi6d8Xy*MqYM;7|cbYz6GLz<0`OV8@HAMYHPtn>eS$C~YpZmB%J<_t;0NWDtv zVQmuno_Z&1L_Of$_X~5822TpaEWJ5hgr;r$I?60$wh3KXYdlUp=EZvnWT55`BSD=P z$#VoY`C%0%CN2aM6TgJ}?A!32r9os2&uz5V=L|DJmK;D)0)rezNJv&zB}de9BClrQ z^2s#w^N-WIr1XP*Rd$b`ixvz3_!S|)#qBpwE$w0>AMLG{PxvT`JdTPkMSq~RUJEKJ z_t1H~Z=lW%?-9RtEN+{fGv}+k+?W@4-2SRhv{Sb+TCK7~iNn`Y@*J}`Du2IM>it~! z3UYV^Z9=fSIofeUAq0JM)_UucRa0cwykNp_CRwrW52KqY&jLYNi#7+zg)fW%x^sA$ z!(X!3VuOu-bZ5!3K4`Vw`l~Y_C4SL5m#G65olv*(t-Dc;+h7~?tXnyNJE>h=;+LI4 zN_glAfR++`qkIm;NLkri~es zu^Jo;bCJmR2!1lmWp2YL@+mmuLv&8nEpK2P&D*RTxyMXfFV-nM>6B01?eLv+%`rAC zCP4L8Jhge;Jn}oE=ZYXKm6KLPHSoE9icyX;ode0oHJ;y+Jx+QmN3{{{Nbb+kR=;q4 z%uA3ZJ50i0La6^CFj6zzDV0`??QO-8&y~t0z{QMEY;!70;=3@3)_w>`7N|#_eP$4P z@m4i(`t;VAy^PUjgMTXN@Hm@6nJn}fZbxf8wzB}#Fm0V1)#t+K7%TiWs)fGJS3Zj( zU4WXB@f>Mdj-EH=3O*|83$}tpNP`B?;>%{ZQEzvIXO%R02FRstMU2G!f4Z}R|8>Ga902C zk9kk)@`y!i$2_%Qh_^v}od!V4bzU-zyHOQOY&Q~j%XEtI^Wlwv;nLaTRdPn62PtJL zhCCSkI&jpjWq!UenXJBQUGXhWtO_2>L5lmvjONR^dHIY`4y>r)q8Z=Vef21W zz|L{eAEaB~b1hU{jIp~Lp}SLGmlYDspR9PzQO&c5;*mGOgbeTva|z4##MB{yjG=&3 zKuTd;+4^S6QX%sqX9mV(?`N6GGVN*Qf}tB(ZmD(KrZSQu28Q5XsW4kDdxJHb!yrPR z>~8gZ;99lE)F&s}=&}zcN>1boP3}x;-0Db#h;pTfhvvn08iM0`x5I#IYqKgRAzU6$ zc8{g5jH)A)e5F7P+|Mvat186(zi>a>Y6v{HNS~TKcbwbbb)!6w>*KgXeaj-ZZ2ffI5bVah|GPj*PA2$^(k7y9_^xpdF9?=BDaem+oyduQZ>5{AaD5yO|h zrl~3|gPD<;!utCxbHYHK-L+f6F}ef{rYcG+!@ycPWY}|P(j16oY46BS?H?qqKoD5D zxLvm)sNR#BxvHe~L2qub>Gn^jF>;#UZkFoK38SgH|tjE4iiE^H$; zJAAE+wd#yj0RRQOW(;6k1Q#ZZ?6+fdBnY(s@b*9+^4~;&_sx&=$x4z_c z+P0!E>3Z~+M-q`(v;1A;enQzv^Y;u3K3 z#jE95r3p97> zd9!8sh1f(g7^d_NqDFH%NNa#hS zH-RL8R0Tw&i!?>ilW(8BpSAWqd*A!rd(YX=eV%*r&&(Kej5&X!%sJ*5bx)*51q&54fh`_W#HY zp-?S5@PV*o*F>BbkckY4v7wrUz$9x|xzoP_z%Vr=%+pDMlQSd3Dd>EZ=P{xC4d?Ht zDVj9Y2MqcaRb=s#sCSNx<-}SRbl?cy(}G_ zj+3X*b+Q0%%^hozuRPQWDh8~k-n_e?$-^OZ4dK_7i=u*QMx|4|u57d5!v*8Djf~YG z9ctX_xaDc*ps)S{Bt)oXY8SgtiFCC{jaRr)WU}!Pot`Pt_}0%a{8!f8FYv_yprmE5ri0>A zWG4a7XdGtE&Wx&IIFe$&C@kWwQ87;npX_@TK%cIrE@?~^wT$UMk(Z?2$Hx)Piq`#$B$0e4BPv|E2uO5(6|QwMG-wF{ z!DrQ3U5|MtDQ}_eZlEC-kQ`kud)o(wgPEHwa3#Yfql^KwLG3#WcbUXkTyWR^SE=u=acFG+rhDRQvsr0 zyIXSNWB8D1_q)wzyv|D*^yOBS>B#Wu1f4`Z`(8a@&1j9Lcupr5;)#za{q=L!@t*!V z9zOYv^Lh9*A*igh5cXks(}3H>#3e**M_DktfWk6wN-wSeu!_gjBP?|TmGK{nKFMYo zPMwgj;@wlkx-=WUkfl{XEix@|DnKtgk_-g3!a579%Yjk&#oCN>bB-Q#2sAsU-trTk zMo>+fN$jZfWkV2OoAu{U@$OH0Q`UnMoyV^yx8{2M!BN6R)qdS@m}eAn2f}6<4C?PFbb!8C0rgR}k2RWs*`WfK1t_<|n(qXDH2b_Q^_)<6Ko5@aQJyTL|0fD~qUi z49>l#qJB5u{QIeqB9w4_u%IT`R{wt2MI^?;k2fU~CS`wX(E;xMptXi)3Cm;4b~Mbp zU$vO!Q0VanX(~`IP3)+dMEcCiw-jae((|3{g5>9)@0B-T&s*%mgX=wQn&Bi^k^A8l zHho^zSk3opW`oa13j=#P4|J(tLY{dUXgaH`ukUfJQ#U@>kZ<}X;3o`14sOHCl#z=& z)jj5k{P{Sa$UaOdWn|D-Z$+aJxgRmvU9Ly!ijaz)waK22l}{bIVG0jK2h!wrT0v(^ zTLkd7)Se#YLtr}_J;r8w$XKenUiz{EcQ>1?W0utqH^os2&$IA>2gzDcoz4VfVkwrv zMmZ#)%QZ`evUCXU^rGI_h|A#%&zz8xn8+cjz&V;jk{B2wS9na`qFKe72OD3GN~j$l zpkp!=4w!7zh3aH?lAAzO55qV%Zj5u4>6h|tI4V~Ey?)`lj4j7+=3a?TBcN~Gm>GOf zfHQRHIFHXzp(`jU3Vy-iEfZJQrWJU&xy|#rlex!J9ymH%zom*#u_Cn;k$X**UHk6i z3HCh7>T^j6x>YKp-Gh z>TRAy0ewo0Vp@DS)#?I}y=v$R;j{i`9 z-2k?dZ;)P>t0$=s6iI_|FU=6%t)7d?E0xp?-UZZC=LQnrQw-<&8Wac)<^@&iI^>uJ zuRs=*{wS&iEvK~X#6M4JT1YK~Ad{hZb&1kW?A=Ef%}azfglzG~1^|+Nyw9QhgHMBD zip4_=feX--EN6^TO#Et`8r1H%=wM@Re#)0qrp?Q4T;l5;;!(1W))f`R|RY@MO z*ohD+z-z>@BK^$0vkaou7Q_V6f5zPzXgq)Je)F$QRp~VS7dDn(sxA$SUPcq{Xr(W+ z0hZ5vCjx@TIt$y)-8@F9(%l9Eoe()zKf6J5r*=#(y#i6%tR35Ut!@F8##PTQ*bgMZ z;Z*f+vAugD8*(~;7#s+s&G{2goBRy#gl_u4kM(0dx@l*Sj zBIOT<>!p08v8Nmu(k{@&>!A?FV3tc1z#%y36zWveUm|n`Hz$1$rs}39WBA^@PWKA) z9pQuLu4mMifpk0@Bg}FUPQ*s`jG||$DOD?}1LnpCch->-0&;wZ6!+~?B z%qEy~P3!l~XJ_87ObnW4-yY++vqm45{dM%tP)uU_6Q9V|*tsxY7J#9(m1e?E;LB9g zxDxBbv&$vBJ-R-js#m@t9E8dR4chk{njXObX7`S3tz3O+%fx8iKld-uni3_uEzeez zURVA)dhr!y=$=~$1>G)yMX$5K&V9{wVa$JC;|o1KFCnEne`Ka-m}R`-83F!;es$nl zs8Z^)#eTeAPIBD^J|$Wj`rO$9f@e|Jf3q}A z#>NJ>DjFmfZ{Br1y>Sy-Dz^9X`C7uF3qj^!EYwY{`Ul*E?Fe^i#=iMIj)H1zVo?ME;UR@u8SOuQLMokr9Rx&7KS{o14AFjNscAQ+?V;q5Z&vM&*4+ zO#K3_>Jt8oRCGsX8q+0KSUo`q+VjOqvyU;W(wy2h<@2jnoUdG)JXLfIblAmt{@Zz6 zP{(OQ+h1)HhN~p8ua)sNgYF-4C|;pjmfF&qH9o)6datQ~1W~Vm+AghBd13jSI_Cr& z1NqsmdIb{9gjN6frJU7u>BKh)XSQ2$D$P~l!&lnN&vMWUD_rk}B&msdCB9yG>)bsi zdhNs)81>4IC@0^3!lxDz_xn?FWh+06*1p{TS4O6Xc{g=Gcm%R824wJsMRiUke4mhy z`Eg>b$6ea*OI6=)lmOx2vVGyNxQTHl9*84)!r##~Y(2)jv?TCJsh4Z}8zk*-I-! z4%0VOezQ=^Yu+C)Gy_yWL z_qB5gd?=nR`9Q7BnhvRlkS*nEmyrE=y zqM?t@gqNQ7m2E4hA0Mxr7#XB6<(mc@BBKi&`Z66vR~|_KCHjN!WuzA0U7`Pje_-j) zhCt2YCB669o(#pI7b_2@nmrY~bn<}9xS3Dc`zV2&Gm)Qr?OEmTSib+7;u|; zvBHEfp436O^QKKqyWk3tdv6ci2%iYd#g{s#joCU~WbT_*i8U%;)x=^vczw zpo0-POEhSjc1Z+j#c{Xl2NXpP#@d!o>rOLd; zgn~~NPM=%|+^Qf#DV$Ppbf`g?i(^n=AlBa?-}&%4qvYVq-KRa>rH-htW$!EDzY$|az&BAM*5?egjyI#RCl4{WM($)OB=&S-WHKEQFvpgCku9h&|&@n zYUYh4#V?ib_GE%rJl-X}ZApy=w0Q@{+9Jx$^HoXY23_@U6uH*hPH%U~2R>`)nHO8q zJMv{OjinU=d`_jD5}Lih?5|j|N8iZ>ztmJl@;0LpleprpdZ(mRRO8gnDNqtyc(KTDVXu(;dIV+J~#yk^V?UbSiG zX;MSyPWMU}*va2=4u;=LCBoBzBy8)irPN)InO6GHTqK7kGO3n(xa^Kc)9=dTa2e z@z&?y&H#b-P0-3EPf;dDnypUm+)Mq&+AiMC&JsdT`E1Q%clsJ6OsJu6$a2UQ=6~X{2F0enzkfi+>VNx>&dg2`%R!f$W0oK(0lmhaW zfnfqM4&9Bu5yYkO&!e9S{p?=To=;7k_DabPD4XC@b?Bg}@u?9C2@2O>SgyoNMO}|K zpgN^P^SrPxrxG1z`4lwj2Mt|671m1e9FJe%CT%sOWUa4^*8meMh<24KLwSxfsEX~x zEf`}HA7@=OJxc!S|7mQv`BL%D$_!9|-aM?-rKJ@(qcF0|q3OUWk$l+N+!1(LBGB;s zkQj3ax^wofwxau(dR1VK#JpI{UEIQVhowUn79Ve&`uAh{T~^D?CD+cd7ove%tHle| z-Ybt5G~V(1tCPwTKC!THTl~u~bZH=K*{$*$6NhptKk09Q=UisM9$Jq6Pe0>t8a%HO zzssp7uevWbCA_&%_20)YUH)1J5NQny>mUBc2b@B;L~)BdJtZije=zmW-SA;Lo;70f zC7NsV9~c3-q@a>tCU@6fVs?(%vz(b=R5Rff{mz$tWvuQA|L=4EFYD!eCPCO>qjGif zvj4;UG|wOPQRDd&bYp;eaGs#m9?R&7^s|yI z(6+zopXGm_`u|^TXpQ~6(r@NHQl>cOjXOsW&q7D;^2Y{nJ@u|o3Du06)8j%C;IULO zG0+2kwzKxJFss*hdB?lV6f{n*rm#Y|enzrk(ydiN%SlbnaMN{5m~fGW?%_b>>W6>( z&OQEjchatqe>W%oo>!hZKOTDf`H73*5z4B{p@=gL=sYp3fn&~o;7~5BOC9vR&2?i(-HGa)d~K_C z+T(^0%-P1G){Hv8tZKEVvQO83^+#N;-n<$vjP41%F$hue7(2$C1=MK9J@V92y>w@sLyFZ0g&wbpq9>91C2^2o~h%3xge59t{?{qSviVTcO7kcveh z8x{8*600GG4U5jd`YQ_QhbulLK+fXnNnWczv_6Jv0KBoRQgu2^$A)gItF z5L_~~T%f+SmM%1#tA2AT?9eWK5%gSkg*h7*z_vwe4q4?+LU@~)Knn`Mb6_>ZWB7}Cnmf{7mm z6qdC^-=DCDv0lkazgY_2HO}5XDu}WEb>nog6*Bxc%U)ni&Tp3YQ9j<2LXC}kz$UDs8*u?I}w%J3PE-*T6VpDaIXvYzpBLR_BJa~0Im7{@PyaD~Ac4#~nRiF<%? z`=9p}C(Wpf300RS6kV@z~S}+tU$6oQmcO(np3SMf~ zrU36yKVK;9485BT9lMo@f%RBP$bT;wa+c5JY^f2alX)XZ=WE|~HWZ!|Rdds_n>nzx zgR8XcBYahM7iR{y5!U?>m<(hZeL*D1okKrxw-R~i%FHE(~ zmt*#4qtFF!^3;*wKRC~XvVN>vr<=rx-b*F{Rb+SNz8ySR4Lakveyi1M!aX`(zHPg| zGLQ(o+_dYEQC1LyGa6sb+_D0Q5jraYa9BzBHa~xAIKiC3;u+(oX6Z} z;2f@+ZV~FKfbvM=Ik_0yi>sp#R!l>XeyDl=#KbGdmfuXiSsC2WXvC#&=5dXb=65L= zYxfUkBr=FQ=>t{22wAk(*(RQO1yDb;=fwi2R!fnF(Ifynb4$b zGJzKkrzM+ewTIYR-QSI)<-c64b|#d`{{@DyO}&1=td4Zb(Dc9IIbP2j^w zQO0*Sq!q09d-LUYe&}2F+!2zHwTn*cR_*mWtPZv4QhKE6 zRp3lv(ltbu$W+V=nHn-0R2xhK^?kKzC<;(B^1UOfCUZ+L5__|^2Rkg_g4(& zn?%b@{Gn}%Ax3po=Oq_sIn9hh?Q*w^2edw0ZZ_c^9Mgry5Bt)nqKWY8#h-qL4J%`k zz?)upB|%hjT?!yMyf=9|yq;U9<1wH`TBPUeThBNTjBP#y+N95THq z)txjGhaaydQ!2r%!Edos#Pj+JBht@>0_~lN?S2afa`4JN@kT`6-Rz}Cu=9|r0xI}O zESaRxkqhD@%e0Hi6MK`PnlD09D&Cg`TO6nuzR}@*5$*D~0KMz$(7-MW%jZx373y7o zADI59|4;ZX+xFC4a8{iBL-xkKGrw7g1D~}MTWR>bnvP>m|8~0=->--2F68eI9#Q_} zefIazMd4BPln?(5)4{)8>wh>#*Z7U8y=Z-F`3)0Nc9K*lI@f_kE?h1ta{-~tY#W`- z03zb{=dzcF>di_*VRF})WSaKlb~-5S6agOxhd0j{kzWN7l`6D8Cr>sIvZ%Cy{~td> zEcJ*fKYe|)X5;bQ_RQKuoh0_8`l>_AhlW0txc3SCcmPjgxu{RZb;HHJl~}8I@hpw-qM26Jt7C9WK*h*`R=Z>NH$sbs4805&1t@H zKfMuq-}z3B=y3Q)XTo_oZGHC+ML1%(GMqv3ewsAHTqYSW#H8f2$4_*avks2w^zZfm z5#`iqh{qBlK>l8qz8@vb<*ydyyHK8z&dN7Hs|bO;%$KUC`XP(*S>@x~?)K8WXH{|p zM^|lDqyu2Lw!CB-@h<(|1dF-vtJ846>Jz3aV*nr5+~(!nFO`#+6i3kgPK1M8cj zh@p(iE+?jU#eQV_bD!(Sx;86d52pE#KPGxS4fMz+O-ECfjLNx$V|d=3T)Fio)4zBI zDdcKbFfvjgUon8nv$AXn4n%|FN)k66ODm)^@Qlx6y1U=c3lmAVd2ovCx?+mG>E;5- zICOE&#fcJQmW!4XFYRCWI6H*hv*aTv@(6qgHSz_-bQkFth#G%(_>!`{8Zj>f7m-3;@B9!Z>IqdAOHK=+qMS|G^Ag3-oA zhIXYDi+Es~qw3L*x*U&=qQy0mBvopB$DWWxVd>0|dK<4eJ!^TaYyr=P?`&=%W2jvbE{#cwe zn0)}6b*x-HN|qLwgif+IP?^j#=e*JSVarY|yeY=zzjy}Dd^}Gp)_qMesLyrR)7=Bh zc(_J`q)R)C$QEnmsU>|dWB!!_{{p(9OZOgEt7fS|BH}S7RNT&bcCi+CmQbbQw<0!n zE4b#^RtVkcrq`Q>E$4(QbeWf9=G6Cb0^V@KN$A>!H(4`yzuZ_te?jzvV~JIvT|l!| z0ump6WOJ5qn%=_D?!9xXW}n7{^<8WEQ|*Ir4!l;kP;q)JxF>29O!qJ5Z4@Ei&w3U>B2e!!#pc1}r6CHa2FUM=P!eMD8i@ zJ58YjSLLqwoHjVNhQj+yX=x9aqr^0#-`56cl3giBdy>78{$hw2Fj!oRNZ+0{IK1p? zS0trADcQi!@-<`^mojzPJ$F~2_S7Tq>a4&TIchV-$VhaJueDBLO2%4`uY(KXmHHe)V{zxhWM>9uXM z9Q+w@acx%`>)vWo`Db`!F)`S%Pt$I+lxnbDI^c&Cqg%b)fJn3K7rCJiRo6R*(W4bTr*1KUB(X7XpeFz)Ci09+XazUb$tt&$hj^>hL>P5bXQvgI z_2L~nnr3esV3~-jUwBnU^|eZNw(qK>%Zo%+3px`{g^nNHUW`uny z(@2O#bY;(|u!fKcd_NfmnPt|~cg0qX;=u&N((&ioDU!SQBR=MHs65&P44Xc>em>|_ zVbGH5waci=GSe|rEpsJH!;!K8b{NR=lZDTCt6n`8K(WJr5qM_ZEkfx@62P8G;nH-k zS%ooCF+^ff-qYBBX{hA}ziS`HlT;hE@Lf_k}|Az2QxQo7zmxg)PNu9JV;%%FK1)Z|Cf$GpCD{-ZHA#T(rD< zuK0gEf5jboLjA;w|x1e4yIjGY0f4w##~6^B01xW=#S^OLe${)m^4ge z#%@5e`F64cECA9+s0FWyBK3Oxt+P0!r`=F><|fmfQx+aX=UEsT<2;einQ`<6a_rNw z6}pUk^fX%%w5%hypVyV#TTNmRV=9>X1(>7P-*@Ac z6I&J9>AD&>N|#2QxXmLDCv-M86^w%18^`jAKJ!)2l{^F#=F>J*5$q^PKoNKUNjP8O zC}XNm0z{HG06*pbGUx5jY8YzztQVU$0~=R6zSSZSgTIY^ENt^(IP-~emCBUapukuY z9OFk(J6jQZigv=JH$&rX7b7|tzez5>6;O%f5fxu4Vys6QiWK3p@xLiXIOya#yXsO|aX3nvdh(afRM z0aoa@s*`VmCy)141h6Xx@@YxNc+zkj8TlE4#ldS)x9xu(e&G**(vt_ud90L}>h9=| z7HEEu!n8_3?jpI%pOO^gGN4V2oqCVO8<4&Id}0$UPf$bNOr`}N|II=n^HD1mz$*&9 zt_I=T9&@-(Vhr+&Bz2_sTVi73wn*mx@NM)TM*KTp#s5$u=pWgR@op^b22GlL{qmc| zDFh_)?}FlL1;H|}SOhP<`Va5$PedN8em~ArlC*wEiU=~EDl?Wjm&H}6?11ee^GivC z*qN@n$tg@lq(pwsSVG^?<^%823O!!m^d;#=FjHEj4DwAM0|=MX@2FRdLd4N zoV(egU3Z*n%oB*o{FJBrsPU%puQxVZZ_|1>J}&9}V2x>4u@;JVMP2$O1ZKw zF86aK$Yaw0_2@-<^A2gd>(#O7B+!4F^AZ{SzdoZd3@f`4nk!lyN3rrQoUSYE)&Yk( zb&pLtO_;b&ppp~$-Yc2BO7JswW6|LeXO>j8CpBEE7MIE%rGwAVE}{c|Hl^l?EceRq*UVl7!#JOX z)fFdWmxpgQIV2}$NDf+De5t5P9zlyXhQ(E^@) zt|%=nEupOwHZ7QO2LBx9#!yAn{+@4yc=9~bHi@zmkRHLic)GD1yD7kM$WcmZ2{JTR zwG{#;Gv!YSS&bF<6CAA$6ddxUwO5dhcC}U{)MRRn1~OUOxJTUYLNXAl`s^sm?GG!TOZ3?_g|<$=XY^^dhNJL#`;8vEr}q#B+>XZ+{qL*d)I?F6~8|W_eY;*YueB%0n3=yJWT_ zjk8{bbvX>hHP1N>Uaedqgrzbb!iPTHd5{yQ+r!hW_T)Ks&3;PD$-SA==YaoCKJ~?# zG$M{Hg^WR(T{g5N9INRkAwQ$Nci})qkb2JX%!W}>ZF>;pa4pSF&HCS1}2CD&7$c;xdP`@e1 zOcef(>rRPAWF!dqU9N4uCfSV>G{IfMTdBez2_#eu8&~&qG<=eixg{YyJ6kiRZ+Uek zXPn73RUjLi{Qj2n@&jT*+xxj6&jB-SL(3_?QC)RDYbx(rrD7Lt8Vg39?(r&NUe_!Qvba;#$S^p>{hXY38;v6(t|P zE8q0P^&$w=1+uJD6Z-_gWjB!iN zWXaqJRL_s|eci#C)rsZ>o4$rM6vB$92!wtwJBNHyCpT@=;eta1R}#E;qQ$P&utj9U zWi9l&utCiZ&{2F^9zRpl?)Cs8!9b=77inv*ngb(vx^HkQ*ViXDIgpsL#q5$;G5ZRh z1UX&4l$Uno=J52zs-AKLc`)O8W4C@7(4cLVLGi{TVQdf$0tCj@5Pv6P|5i`En&>9k zL5OfOx)Qll)mEbqx8Ne1Ox)}d%YLduIP+|hgel1eI_Z>{v0N6jiFvZrq-fS-T3)9Y z#Up{k;|z6;$vx(-%YygukOc=yaeoM}9*G%uqGyqgk8GA*e_ z<+D{AUzCQ!iuzm^ApWW2l&f(OXInw~!pGcbD?U?~!9d=)Jdhh<%s23GoJ!cbmUS4Nr1B{jn{I)q^fnl>B0nF@b>&+Wuy0$sj9eq zll~&cYoVeiKyz&~I=Zh0^|W-NrN7N?E_?EMjNfD4l2X0YKS-*A8z~7=8w<@B1WW6bWJIeLZf$T!vtWn3FFz0nsK#CwESL5PBQ}RvUU&*{@&_Aa^z+ zgX&L45S@moB4f|f36{GyaMNL@P=hj0xSC(s4I7t^(CyYPjxUt;TAL4{vnOXU%(icg zk$9FmgNScgO2`FTCtQ7Mm6^&1Rp zuN!^#5y+V*Ge~yv1yo=YpBan57$48a!Nt()a@Z8@x~=}WTK6WCN<3Kq6E8`f6%sp`3SIzvrBHw!dAKxEook@=P*ROY20e z#k*SJ`Pqsuw_;75XdCh~aTb*5X70$|SjOjdy8nI@<9TFiQNt7pt}Y%N@EK!sJzTis zdlkK3sminN^T8j(;$N!i&ZcY`B7NKrHZ8?d_ajWZr7?ETiZYc9+a^ptNUJP`;w=13 zsex#++9-x1l)52croO70f;3mOR_iQ%*7|9X{+>u#1D%hgU5iWkVxZknJZon9tOUrXl1X1RJ(141AhVn@27CunX_eukKUqJw4-Jq{$*I9 zs!?Jp{MdEo8ivxGi#;#MhR*@*_xlZ<>7_xb0^D}?WGStnbG>fnw*_poMKU~Gv1g|! z<>-2BW7?m29I^ej;w3sL9W$U|T^#GC(+I5(FD9RnxKHd%ho=0^7M_+VF^n{thVVy_DWo6=6qzdC*P)wlCpOELrMW;NQ0dX3g-cp2@kbQa*y2AnF^ zK)McRWMJavzB`TTG{mc|aNH0!o%eC+t5sJ)ilRU7l~+|Fa=54{FK(5@KT|*#L}0-b zki}F~f#@ATAKaC7q=7$}l~N&N&=t^fR1VwZnHlpdA2V5=^=^_-c`DKqxF_R{qCA;3 zhyp2d;se$UT=v3qyN2eY6lGz&-q+Mb%AB`aw&Zsbm`f>|{pL+!JMj$#NHjEO5s<;h zB2?lSbUA6e7~inPindI&nN&DDYdlvEiY}+!H8n4xIi;pfTuxRhm-b`>q?rT0t#!Pv zGd(`pRKsziZVSjcTIN@{ZBHrDr|81x8?@dG#!@xQz^<@gU^GrmclWa2rS+re?LUyg zUOfc{4kQ!%8zjA)yBS9QE=79?JF;A36Y=(OpC5(LDQB*7kkz;F3=;}RyQ@ZngsPQB zQn{XvrP@akXE0d)=g4SNQHGTCEEo(HJ61U6s_M+P;jC5sVZbX-%d+bpnq=mLN=0_+ za7bq;77sI^zy;U@?9vmDDnOSbRcEz@&s%*`_TuFcTYgtfIV zvb#wQiAoafa3ym7$g8_07Z`Yja)D_=bfx(jygifv)z`pQO1z^E_j&fP z){Hd20UI8NFx7kTdpU8wUR7qr78h?EPWcu>M)_Zgj4f-2iW?LKttATh%Su7*Fb6pY z5k^8&)zP3^<#k6^iin~c*bp*K;!=KRYs{SPA2Xt$tbX8~|5uZ)1m=!bpFi zX}gvw%Z9baqWCk9qw|{pMVMWoo13>5@dIpT%jX(PPtS`D<+Q<>B;k}sPli+l4KTDk zqxLOMxn9scOTpW|V8(ol3#L;Q?x3Z4@7T_p_g*Cg6PKe98G}YS?U&Dh(CVEjDI`ec zenF6_vi7>swi-_nf7%gm<^vt)0S+vGlG6A#Q`8_QrqZXS%$8`{BIUPS1! z1ZI3FjbboZH=E~1mqewf$W*+0tRFe!wBb&(z|>=1qNK){aw8fG4vzDejp~9saNT?7 zv}PmzXjU(gnyjW7Et2hWJ%0tmUHY(tpEsjnia3Ci77@mI;j8g=EBWVDBM*VXK2eHd zwbsx3vdl81K9{G4DP3jMTN*dFgpmOT?pz3cnnBoe@7eUh7%^8CrfaPo@X_wKLe9`K zpYr$47L!4f2@2q8hdj;a@KT*o&rf5QG|PO5^B$N?jgc^1Rc6|ZV9L|B>$ z`^}x!9+Ac;3_CCNM}%*uG{%CuKpvpay3uJ&cdr8l1(ns9(&Tz>Y6jnN1>x*dAO4A@ z24<4~rD%_T&V>Ig)qjD6;)$3g%a?V8H-7l_po~XVi5NFkuarw1g1Y`IYi*C;B6pHNEM|D%stGxqA#<$PX zdB)kd7mDAmOSWG)&9@@@j^4eNdr+3^b{T*bcrfcdw`VfcgzW4Wl7wG+Lr098Q+AzZ1{UtA?v>t#wXDQw@4Tc95Yn9T= z_iv5Gktc;uaZ;sXQFaFL>D9&y$`m1-I~1aD(N3quB{OCU$jQP8_`f#y&f=pB_y569 z3kB5*;)*h7Fr}U_DHw0DLtyrq$kT%VNd=+nwm+S0-dJ@Vb6t#)BZ$A`A&(RlgbERN zH~`6EiBdISF<9cZ=ndjOQybnLcOOI!ZtG`jS^s9yh}k}^+_9IF21y<$Q&jIp57xO# zCo=h>yk;X)0S!0^u*VoM)IAuvYn;fL8qU-c4Vn1=K(n0xt405rUUmA(Ly0#&4Pa@) zIa~Xl7*0~#kMjI3K;4usgT%i{;N(o_Q2SelQTeMOC&I_=~ZxEg_Z?9~dIQnv1N1ljFlbq|3w)ZkgwNQLkln>u+ zH~B!~%;3!#uI7Tb7jB)u^0)4M{Qa(gphf<&D;4@A8n&eBCh|(phuiJmtcHG-yZ&s4 z7+8L#IO6$X*D569Cu(vwjBkNu;pnf&r{izEctf~Q`B9gC&O76WR|8_1LmrQ!-+k?G zARqI={@lwhg+4Nyj@_^gt5?>~9UF3HT%Cp!eO7pqlQ`(Bh%FkUzNxR#6yNUZxr?V(i? z{}(tCO5#uCQVMKiO$vuJ%Qh7{G?%O^m)8BOTee}OH^Ra$O=DD(uDyfj$ulBdn1SM zP!=&9Z~YyH!-C8oOwp3`Go7Ic*q4+35m`)nU`tp1Es;);cnaVra2|B-^zFa3&p+{& z99)lU_BHRFu$Swpt-&mhmxI}4CFh=?1ePt-3*LJ^%~#Xu9E|iEJ?{!~oIlxwzge2ctQ9#DTVsEE{$`n7tCU|s!FR(wSB~b&zQ33Y*7dv{a~APZEa=ZY zkxIz0^GGEkAVymL-H=|G2$}P}h6Qds6`>gkW+bQZoe+}) z*eS;i*A|~{!Bx@R&S~S-JIL~xnIuX_FQaK>O)Kp}PynsqhT5VOpFt;9Yx*6=G{DvN zg57uN1b081AvfbP@dCIxkl^Hu#eqSrS_@|D#L6|30e?!l8Bf8N)({q7&wt;||GCir zddY~B&IX6%F+*>kpJE#QoRzApC8laa^e=H|B~PwV?X!q-Y(x1LMMiGUH65e^FSi)0 z=?0;q;dD2kP{)emjLSz->)6kpY*jM0cU4_w)#n$Y%Ty>-F%Ma^RQ_oo@mL8zxW4#BxE;wM z2|_5DB(NE~9h8Xzc}sdC$5yf=7o#mnI#j`O3-=uGZrr0ja&P8zZ5cJy0=QF?Z4y`p z%tXQgKp`$IXzmN4jUUGqPfjIWF!9_Q@<|c9O0_PT;XbSku!oTiv>(sP_Wovpc?MPy zN9-Ih9>$4IP`jWA)fvj!vi`Q6HlBh{WaLVMZkk~`r;iXu-n7Thv$HF9w=?UdAF*yo zD!%dok+90!MUQd)(Zs|=gPFVDcbamZZroXQ)>D4^Vzn5myt&gSFOaMi3NctsDrnl1 zI}tzhPLqGAu1xvI*jcfjmktN;Ny?(xg;_h8#3!h;a6qb#A98#Ae0g`U&=(5^lM znq`2t^vA|eV^U)U(D~cas{Q`GUr|Z)C@yZI@#pwc_I)q**-B;v`NzM;#w>h|@H7!< zTt)AU$gz4}DlC)j3x8UFIgM+oKF8JByi(eDCtRyQ6eQg&=%`{}8Qj@t2Gwo7*8C)m z^)q+L=1tG>S%s2%|3&*cejI>Gk?n>6PkYS28R*YQ}V(xO?zQd#x#T$%zt&wb)$pxG>;3AKDxuKuQO z^n35hPpC9jieSIbNT@+mYO8k16Ov2ucw?=>P?zUS3RY-)&5WRUt7)blfV}cPnA)Y) z=AEaAcFBM1iU5P>V5=#TDbq4oh&c}e+Ew?#tO^c92$^IQV<#?yZC%D}U(EQtD5?ya ztXr_q;A{(1YAC#BqbU*l1(+Wfy^z_I&_%g~D!lvOuKGMYmGYT&W;+y(+a-T+c_9A7$GW^HedFz`IQ zM*&rI-=CWs@ki=#j6Wj_@A_^Nq>HX-3UjIfonzvwTSUaiyjs>&&rd!WmVCc=)`6OR zCBxr}XW~cxV&N$1W}8PrB3JTsmBLVuhHgFPds!?ou<-eMaPpU@gG;FuEjX(%rhg)e zFwN9U@~7N91q6npo#yVi5xFNz+D3-;AMC}j*G=On6dKplt5H&LgodbGf#?@@(WJ=A zL!jSP3)Cw0KDm*<+mZ|dU&vj;8eimLi^biMI^FODU8W#>z%|mq@<~;1sB-4JCdY@! z12xQJjdsVeB{Lw>zDl<7oJj$2w*&DRY=R>owhr`?ad$ok+Xd`<^)M`W;wx2rRmv@l zL>V=~HRL~}+rj1}YQKh%t4wg06sR<&4ca7JQo6zuoW8#L3rxK+>#)|Gmto%&g~E~) z^!sPbrRL=P!Akn#4k-fq(i+cjvtqE##I%LNT2Q;Ut@K-P`&ZC`?@RO4!7Xj+6zGqp zbK!B)I8Sc6uBK}A9m&XNc8*m|i5VHaD&(jiA*rAz6~@JYF3)m{iUD&3kJ7)o{HjsZ<;{t^aXB#FYd?@~8>O#yJA#kzvpp zZIAfS1c~6*I9{7-S4qnCl3o1b%wC^Wl##5^AqnQ{2B#gV<~Pn2@wZH)hwf*dPiz#xSu*JLyQR8DIa4VNBY*8jfU`c`kHs!<(-5P}G)f8SL z0a{z?{Bi8YEV72!J*^XqN8hzL;el!M4C8NHb1|*k*2UIFC{x30z5Y{u*m7*R1&&g|ecXh_HKHG@hsBMHj0Jv>P`}MriQ~ z_+PJl+sQsx2fH|+xebjThqFDom;~D)r!CQSSWJKa)var*F{6QW8+8if4YCT~| z=WM3`UsHI0Oa0Lqb&8~3#U~TKaVhs&vNYT#ODxmeliFmV?)y8+ol9-|`c3Hzt&mG* zNj|C#c~WXlLdZN_jjt7Uy!kg>mkHsuP#MOwzrF_VmO7hCv5aHc^-u5>mhi@V?4!bP z_J9=2#7ikF6((V>*lsUjvPK0|+lVRly|c46H+y5oz3KfQGFJ~d?fU>S=P@$9+rwg{ zb+2!Ly?3)d^@F;Y$u-M34G63w(QOu?srx3T_|_=~+&?f-TvB6_+xg*9-^`OP!Hq`? z#bD$5)*-emGqjuJaLgNcsuof4`1rG&B1FVvyh(VB?i1c_tQbBFxh&f7oO2nj{-sjQe!%dWT^_)QWmrjux;TfrJ+r5_Q_c{Y%tZ4@%7B}jqWB-*!ngu zdq9dfd~4a@rj0&%^|X=+Gqy!W#INM7!H#>gvs(!(vnP4ko%pUdQJcoKV)Z_Y?WU@5 ztqJ)KvDud<;Vs{wVZ3$P9)buV#Tl?qAJMXJa_Zrf%W8b?fujPC9W~dle^G#g)iJnb? zp)!Pf8 zob_1I5C65J$bT#6z_~8mdlGbRszRntc@bMebcO$j@3I=!yJ$qkt%OR=O3oT>`xXag+IlY6B* zMH>*%By@1^jA z-)Ai)={^i^XdWFN7)_#*Sd1BAuSwOaD~$WEJ6D-{av86`AoiQGeXW5=3iK3-LEJMT z1nKDlSd&#ae!&^#V*`=A&(2}xdiTj=T=7w`$1d~||5y03P-Sm4SIzr%V2zbyxNM8g z_AOwNHuW5VOf2q6AY*GZq?%TlGm_`(hxbL`bT&_O-km~j&2TkNz7A7CvY=E_xb4-X)0 zb+*K@G2aHD-15j@o5um_S~v8RqCxAv23~z-+2BZl7D;O0T!uXedmQd@tLYmcTAgw_2od zR~OV7_~HxdSd7teKb`7D+|!In@LHWY9v&Vl5Z^U+_qGNqjbW)@2|y2H$lfJGRkqf} zaXq}X*q+GRDH(xi=O_8<_$#i7?Fq=r@CtTu50#opzC7QCPoC*KvKGcF*wlbSium6z zm`uK(&+xvjRG)({n^84@(;Af#C?&h(ugTten~<`!P8}}^O!Ztmf$B#W zUoTeco;zp)bOrbHw*lo3%CR;Hpo(XJpGHj%Ptu+=3XJ9R6<^0k)h_o|Lwd!f!?}>@ zacu$|(ur$Fm+K7!8X-=R*Do1Midw*}up;%F$5~A~)1zrGpYS_9N%Q#dz73hRfX%r>jdg7nE`_yPFohN#547B2{-@G96LG6ffaO#t=y&L9}NyNx#4a!_xE^ zt}`d;5agHciH?aH-n658nZrgeOJQ;XAb5=9YFMwyp?i>7X4+&i9piZ!t1&3O1Jo*+ zY7!iHKrvl0RR`QkceG$)LJ)e1#pw{}oac+4DMzJ35@D!o}#_?keVtRGUrvx&&$vX?WEAT>w$w0jtST09@(+sw*^>M+`d_!TKF?*o< zRo12AcL9ah-Y@TII>pCdLEWxIry{yCDN>tD3I&P+?LL*qn2nxhy@|I%*Ax4ZT zVUZ0qyxB$kuDlS8E3s&2{i@J;rsq9oACctrbJ-=! zDA&zMbhLbPRGTHt5?ax6S?$k*sm+YVd*+*8P80tD95La7^L!uttWITD^V?o+Imlh)!M?ch)XaDFTcS{<`0G-nCu|9OAIqtjvjbzFdz#~h>C zcB^xUmcp-~g>5Y?<@CuU`CWJC_5ah^&CHXB6#1SehkGAY{;4C1Nj?DRnL%n)?L2PM zOBY#_^)pQyLWi69AB}enoCuI{WPVD)S4F|E<9}8e#tjWmf_@Zb=tRwm$#GI*z~^}O zapV^6^0|xc@82D<$s zRHR+^{wB{2gLuIgu0ZSk`WMMeZ>0`}xXDD2)K@A)bL@A;bga=qkh z=H6M&Gg}IuSs5Ef9*xQ`A4rNF9wl{`1srwWOG>zF1FEjnQDifAW4P(U7jCHCp(dad z`9fhDxpzsTn|%&U#=hVR`vR0#I1c)*e9v+5IrpqIO9W&>P3h{9u34~H zoo7_3?_7-vuN>c=gT+VOk(pAY+vp_DG^v~f8D)DH)*)BwC1hni!m>q)2Jwi=Q34JU zid%k-oO5jdxvX*i=h=(Jns};+#30){$EY{%d!lV8Or6WGCJ8G9)=xhN=F8^4VaKHEkRdcScj-8U@8h~z?GG3Ix%oTX+^~yS{RllWJBQ<=0#%X4Q}hZgSJM=7 z#T*Oy&=#t2a2+^*A(tg9AdQj2T;wlbF8H1pY`?BNg#pEp<42$XL^IRdk?b&xQ98se zUc*u_u1(t`jkDp-wW9UuDYfpxnjcH2h6kG)xeKFHr@KD|e@*2${!Yl(>VM7}z2r|Vhsc1z?B=IL8>xf6eOZ}kPsplz24`fN!}2tw46 z&acqR4?XbGkwQ{hE_8$?PB-A=``pZ`IF9pxY1_H*Y%mYOWwIf<~~Mb{no6RJMjoz3&U-gyA7fg zq+;(5wwN)WmGsx78l637(yWZ(C447kusimp8%&l@ZcFB@fE~(Wj@2e4aC|Ot7aWA1 zA2lcB$-tyfPFCH1KBks2pkjF(7$3#ce1r&^gVBWdl&F?n{-3pxUc0FA?*Sq)uI#fM z#0S1V+gta}S^cXAJm;6<6+u3ia33hUb7tte9^gHxE@bCO3aYXq@#&D~lf0(rQ(u_b zC`n_v`!AuRFj5fyRz&8gV}TTh4$@6+a|;8k70??yywv^a$pQVv)Y-P%^mEz4<<$oU z&zu^~EoFW-%y4ST%k4;0QMGKA=rN{Jhc?7#5a6rR>pxy&_=y;kEg8B@t=64vkcvgD zXjxj^*L8CJc~U~rGet8ywpXBzb@n7#XMlnK_c~zyx>P`gQ{{nSVroq9NOe%K{Q9*Z zDyqr^KT9jY>%Ib^?CkBI)Z!)W4h9!e?n>tz;veqfN~fwhn-0CIiA5*Ejp9`2`T=Ow zOS&mx&dl-qvE?cxqD$l1%78QX2BdmJNj_7=Q^eq~ynJrE_>-U0W@+_+lK;jRpjpla zVy|`PNwkRD8Txqyuz&LWa&=_{rFNQoL!l79{GnIVTVo|pM$6E*Ct-CS~w(a%^trTf^5>)SIyTt9}=AWS(Sxcp7C zoH%RIoqW-ox5~k4GZD@t6w8t`oVY3LY6%Njat9lort00My2%ltxc-0_St)&rHFN=` zC}J>0t#yx+c^Bb6kX;hqRoSdYe{YbJyWR>!MQfyt>?2dgqb?0gkJ!VZrtGvo1Tw8M1n*`j zPua%vh1V78+pEmL)boW@DxYI1lB!V$9B#;aHyoN|sulxXIHn~aM!{0XgGWqOU-~Sh z|E3AqE1Hw5XsH=)h>EJ^>JlmuO8c9J16|@=oN(Y+w{i0*DkO5L_0OCpwd750__$~g zt*^}sx*9?+VRA!(fD6t5db5FI@%MK0)QR8jk~s{oNYv~d)WgXiMeA{KWOssyk)vLI zfQpV_G3H~}w+8eJOJtI^T#~e$mIY(tR>IBc$0KV;S;`}LuY+y11oP68aD#FJq+C`X zCEGFsqZ7~@<=YbRg1RFrs+HtkQ~s1ksXPL^`C6AkNmNus0w~z2?;>eNkby&4dVE|9 z{s%Zq2c1lC23cB3v#jlWmCq`wZP>JoH*(&t+YXGlRPIZp)6>t<75FxSDaVZ>QtpDO z^2lu&CzkXMWZ(}32E5Lv)GmwMsz;`QEG;rPdWP8Oqk*V`(E!%#f4fFM8#S1VkNo7f-cIGM#?{ZIsM*9tTf#XE+}T=paQ~{ zz*+9vk@e_S93IwE?U)+Tj(Jpucrh(MkGpg3qY~|Dbe9yW1Q(S}D5m0i03a=q?JW^M z;5_v{Oily4HpfOK^G(?RJ736qow6n$Dm!-Q*Hl5-F9|wnAU8T0E%(Lf%Q_g_%SxaN z9!0Qo8~4PMvW%dCT}V&CFKV1+qU}LnYWHZTEuO?|&Em=|m_bep*De^vD_Jk}Sag7< zxSf^&Vbxn0{o*;0IVP2^_{xngMQy|Nj~gX=?e4bHt$GqqV{|HsYhfL9O+zay3}Tf* zGun8hn5!)N6FFcYI_OHB6)ET5a4ECk_Hacs%NbL#i6xfEnTax5+tY)<^cvR6Qu6Lv z8e$8vT*68Wzzfwh8E&^xCxM%4viI6ef2ik@_VJRe`!Y91XxH?ceq^R~70It~my7b% z=CTRyKi_|nCg{XR^f8m|P2EcLT6$_8>f5ZLryP8%*j-hyypC~VLRfg%`5Rya7gn5Q zoSqatui<#1l~w@hup)BjBzG)?cE{@X*k5nFUek~|{)2V&KTW!Ncyf%vm(CnN`~Dtx z(IEKDWX5zW_`#``)rAKF1gzKTCz|syumACw3#>jto5a?0uf7r_9e#z+gBJ0}#+cT4 zipo`0Jd?`rc#Hq6{km%N=@p|>#_g>;N8P`UwHFI}UG|IHP6Lg8?yCFoD(k2eYTRBR zB^)6{J~2g%-0s|Scbd4>WgB*9V`0Ff~T?q-cgcj5_q33RzIqXaI3U3w0mO8Z{~yKmr|u zW%(91)_sU89FdtqfCIY1Tlw;O#g<|wsJlnLX1J`CjM>?Vch;b&rn_?VO4#a6&S76V z?30GVTcUDgZ3ZmAio%lavYHhgICGBMMP05)nzy)iTSs;Nf_1k{;1SEF*wc1d53^ER zmI5j^DN=iaRzv8;ibZDXHkX0)Gz1VQ&KIPkO8!=K)BGNOFC02mW|cB4OA_FD7HiP> z!5Av`rDm|yS(lcn7ggJVY=;%dWzCblu5<3BFu;e`GNxUq9x_Pbx-;8(f4oelzskKn zbj>~Zkh4ixLp|-QSItJealBdW^MTVd(#rPD@zr{kqu8pYFSR~nVs0!p!s?fESSIWx zFb{3qNxI#%3&zKiD1a4uiYZQ9Fd0IAcvu=z^5X&2ZGw5shxz45tssufjmE7GstXnI z5tR`-`b}eDB<5U90PnycLn50_ppAtE4@B4`8{;SFmyj=gH0n`jwR zV^CerNt6;Fo>1ob;7B4yyG=@4y4Ph^M|&GARTb8;62pNrUbgvFvf_*6!oY6HL`g%(;p0yTFI$dB=#k z$=&TH;oA&u{NljU`1zL#tnf7t01|*p(@wX9<*CZD5qj!g5Dv}_@4zz*t6^bdP}zgt zm-So_L>hdBM{F4k`%quNPG6htUZ>k{l8y!A(_Gct*6NR2qadui2}n16Q>fn%XdNkA zP$+0Z(mgy{8=wGzSiZB><-EVP5_i^DA4|evUz|z@#uny&*}+Q> z(zbO>9)=6{93f$olF-X-4r1H|O)I8x*bxAaJZ zyT`ZlBKN3^aWPgW0Cm}G$r>rujYEgqB$i7{y`M9Hu+KIfizz088^>+Qntey{VA z83EO9l~z;&^68dCJsw74s^*Xeve$k5esoPgVb|V905wa%Syx{NW;}CHHMt;}^rr^*Z1^*E|)HvCD&PGy0T4{sJ$uB%xbr=wuXdyLxq~91?1g;A||+ zk79c@!jZ@zUNC@P&D%EE66`TzJ>Q-9%045Bt-pf(`pnDyK6b2Btd6ue(5c#U4_J`6 z>L%mC6k}ViQ)VafU6tJUmyRDdC3U|9VmNO!Arp2}AF+^I4b^cB>>q^K-osomC%51$E@%z9NhdxZ>OtMAs8FjF)?i0Q)X z4L&3at%4ak?!q4-#5Tdrx10-BgJ_&z@|O@w6@?t+u`Vq2w7GS6ku`)tbTTfTYWK-- zl>=`l8lw=N;7$>Xan~@um45NE(C~1fr(indA~GFy>cq-|4!J3%a&_?a_k;H>m?tOY z)6eMN9Nzj@WNF0GHm@V+**@f%YRlJlRcf5X8O!FEr%K?ltPy94#?gfl1=kCjZBwBA=-P`x zZdyHcn+vdsa&6*MO3P-QPy*H{ejTV|*V$#K|FEDww*Zl6P*?e^@=ax9LuJr#u|=u! zBD=Yu*by_hdfmj2QAkFb3-kk}q|Oc>KYB6JHEaBidm{2Fg#|s7b{Sy#CcXNa*ULq` zosq!saQm&xcB=9H6qsHHL()5G44qCyp_~VMMvwSkiMhv>8*9m)R>?y-X+CA_=?M-K zJTr#&W95J~gp+J)etPm=LhZK$z zFEY(76+TB)I?kILwPO+J&)(nt4I0w)A-df9YxF-iqZ*LW@5JEollIVL7j>-{4 zp%;Bi3VNJa{TRbHGKCWSqG<5?16rLUE=7^eL zmhi+4$UQt7Kc!{(0`9$77pIv|OGri{u=)jg%LiMF8lT~7fI+Q^ms&kuPBRkd$8y?* zGy3B^a;H)WO%*U457s`dC(1892Rdz~DVSPSb}A`b9G)yxya zVf1`CI=U+^T$&VjQCmtsOg-0Y;<}21piB^#mp!yaw^X}yHbqL-wAaU%n~~e3?R|fR z4+B#jPhw$M?nR9}&q{SjgWW3G1%>l#@j`hNWqACtoDf8oD5u+$#4@qnNMj;BpF&-) zpHfW)vGh`=(tAcL1ls-T8M?D~ZGn}G4P+i($9{YDQtRU3O**AY$7W-6kBRb*_)t(D zUSDWM8;Cv{8%%y1j^5Zy6iMmC_&B>yuMMTy_nB%$>n3>0=&iW;KwLW9QLtHEa^2Mck>o)J>EMhX-G$5Puej zOyd0$LgG=k=3>ll@6>URVs=YP2{9VhRnP&W2Q)PIKT5>6U)0NewBD~2fS_s|5`a|j zUAIYSsn3LjUbk%vm5L&6u~E_yHD(xYX6wzgAm&UZ0??EK4-PV+ZtrMC;gdr{-20O& z+$ldj>R!GL)eU*1`bM?L#C@Cs8({@A8TcxoglGjgz$S(AcpXV29-C3_bM@{;G3!r5 zFHMib`Z*t2w(OT6R})dCH)c^>y;nGzwg1N-w1WDn_=t=@LEulRT$^KK>C zWD`%q>5gCh|*&xO`HcFE!b;3r^We-`YOPF9_+EhxICcS9AmgDjfLg_1nKR=t$ z&`M1EAoGegJZDU`C)QcLEMMumTuC52^E_^)TP7Ut-^#HtF5cwK@#~XvIm@e~VFJI@ zBAKBB566)%29yK^0Aq=Xa=>9xzo|`d@}`Z}#9qYL($^O&tTXWd z{p-qX_<9$^;it_4!O>4mThY|oBp4*zRG$i>~Px;`34K)mx7R@y={mE`8ifz_l z#A*zgvK1Pj*(PR5V&j2Bb-{sXF{9qAacQ@+{130`)d62>i;n{s-N5&^ z4t%9q(y36_Tq*ze(f7a80OuUVL~#FI^?ajAp;{{5;8s-M`!;I;^+c2$YQ#yYm72Hq zOK_*T=+#%XUxEE$aN+A5iyX3EuN;c%ua0vz1t`oaFzYiI?SH^ZI*9<1%OCM(2l}1m z@u<+0zmmk>Gu$3Lxp+2zcLE{;_}U`}TCFL!gqR4U_@4s(y4GPy8P#l-G5(!=e6xj` z9sR{HzpdRuM-iqsK}Nh>tELTsH!Z;irNI}SlMazdM1I=~JP&9lH8koZdS1dtZ2G_V zQS#bBAFK+kw|+pq*fivC^x|}fp?nWalhb(<^yF5pfk&F{@dKC*lIWW@x!J zuqm%Ybv35#ob$}0X2H6(76twKygb1D@s?zvTsrX;jihjJffbTsUHrl-83?$s zE?SUM^3--7)r?{5x6$V7=!ptQ;U8iWCMw!j0tbA{#chhn(6{?3sU`J8J=`EN7>(Nw z(IV2CTY?K2T|s8enKW7h?mHRt3mI*Z$_r^;DDdAjrcTGqPbQ5lE5J$8S$=V=tKu;5 z^q4<3?S7rFuOUccE19oVq!T4Pj=O)LP-yLU2y0{`ZT0ZN-?hi#^+3`ZaHFXi?LA(s zATrOkWJHL|jD|Lwp){j1YO?5_O=>To+ALa|ZsP zc}6@k4O;HE2HRLM{9r1cp}PJ_rYTgr!uqDLA(en;={Z-0Xwl%ThlzThCmhC>V9JF> z?DL3o576ArV=ng{mePOR^KcWZS2S3=#waAHi!=0b>a-@7znwKJ&l$87J4h60U01rU z?;mB9VLvDSEX~}7vR_)=w0mEx6!r3bu{4`~mKaYbL=yQ;`t67ZDYNfvMeUmLv&&AyjTOox38T)*el9J{O zQy+?x%0F`0W$wjbQ>^NUE7 zyo(;)W8xvA<)+Jvv7pg{7RQ1#Dq8e&iH#Q_8^QD79FkPa(~C!=XVC9actxYuq-(z( zO7T~5YB30sQjdPVIN+$dv#l09K9{irDfTBF?j}zCBs~ZMc12@+@IBW3fQ`+ zYY(_2tf6X084&5NAthg=J+`+(D7EXAfR^$A{C653+h33W)#l${^v~ZuE$#NN{^a=g zZj(^`t?3FXFO_$M3^rNkM9&BQ>d(ku-Da5eOBk>Hk_npZERL@o`! zeyQMueROySom4y|gF0uI8l8p5|ul|V@>IuQTJ zsgeOJ4_qEm1QdOCD~W2ZD1KSv5&2h}&h0iV4poVq=+xJ`vD6;s)&-1I7^o(H^XZD} zn==Mhi^(Xv_n?Zx5)5c+0{*?p_7+V$@NnJfH-7If;rjt^ch%3wmsr~PJpb14jjO9} z(CS!7#K^6=lCx^R^p|LV5@`89`u*7|o=maZWxCKMC@;5_C7JduvWE!x45WWMvaXZI z)wOt73Ivv&at>e9`PC!831seXy{!a||9rwSvbGDwx@&5N)3Jj>fN9K-xY~Y*mC5SL;r->u94F4!PdKD@pDoq_xSJL#|G-ayh{W41Ih zzqR$3ba$)wPAhtQ+0}jM>^W3tOAl7njc#B}_(jtbn0ObP_WG3za%o)&`6pp&FAmO}9&p8eo*I2L>B<^--u@9Qj%A2( zM=yAvpO^V9 z>J?nR*Y%9_>_&YYWcr>{`mF?@g9)S1v1rk7(D)7;18}F4sPtd{!bRpf3;y?q4^!-{~^miOJA+?e2~A~my;5C0z3!#mzc!n%{5yZn#rzz ztLQqoN(*g$E3KAohQ)cTL}DgdT&i~#wrs6k=xXGrHR`NkJ3`&*J{ftwOvqp}qr`nJ zxnNs}Q&kddv4ghfi5HuH^1})>ppWV*A4tj0YE3?Sz}NOQ&m)7c zBk`>BmIwFrxjw%<8;4{&rhvVgEAPAPH_~j~Ih!^dS~%o)N)~v zDpmKVRq3M3=cezS;EO})Th9MVDd(&^|NkuXX=pT1LCZ_DD#xomUUVPC2!A3abrPl@|K@z| z`BH}TIPn+$iM#^ADGLoL>|V+wlO##WlLEeO9K)2vA#(JuQy?NnP1a;S2}FQ&EG7!uV(+I zx4vv^fPpUjcujNZ_P;d2{$F7t|6`W=7iW5n+U=4olOtJ!HfhlhH!FxK%DT99Kq!(jxbmcHo7>9tZ| zpk&I@3T`=o&BjV031kL+04cVXTS-Rj#YT8yC7tudkI?T1uIAgUz8X&oM(k$B?A4zS zMvG%wR)TRE?no`OjE;iBK{$`(SM@nboAOk*8pxiP$5S*ZDt;_(AkwIg(b(Cjc&y=@ zNEQT!Q4p-1Yhe$I1uG_jgV2xr4RmzcRh-lI`5(lFM<1ek;3ds9T-^@FLdgm6=^MR;x8<31k!k=W(5k~DZ`nSa(z@jEl!n%}bZX>7zXS3G(U}U}41xBFOLuUX z*BC{0-698Vq4ei#<;g{!(Jw4~++@NZ+eJFw2CQG!eQ}vAhRfGRCIV}X8Y?);L`lAmc5i^SvKDfE?>F*^6Z^vq!&e9_Co*9TI1`-R&jP1CW+$-b67`0?z8Q>p z#}4WY$@618-GnLoN6cc78L=f#Ptif=0E%YE<-!`iwaY7wHjx6Z*5M}g4#shmrMLjF zz45X}(9zXdHSJi^D2aZ5q_CW=3~T=S`|OSC8dmo=#=YYeewEW6Rv~FnvjfhHTEU+R zx-!H%k=1Y%eh0s6Bjy_|q+J9|OH3OzdwHc5l?-7Gedwems|TJ&_oGMh!R3piX^sV3 zNka-jd!>GZg511m2(YuWIwm&j&Ff|!_Z`La$L?FRn~|1Or2gkVf!R?ieB>>cOtYrB z7i(y$o}s=nup;bk??x`7Cj8Zng&62gl7p=8!t(B=e&fQ2qiCT*v;rfGa5iXoV(^(1 zxXz@UkjRn=-!GAQlm^U7!Fkt94u+Jx3yzOzn5{<;%t|)Y!CA1?%CfZOWM|w90ovM1 zuTEFTa-zToovHM~%cL$)Rkcp-9}{<`H>TgO&qnYA1Hz=cAw`yn4El_0ENH`TjPgyP z;&jSY$=!12ju}APjn#0<<|cgZ#&jW}=+>=Iv7Jh_<$}>{3MMVEd(sxggHRd4ql74W z@y=wJ>dYrIb!VG1Z*$9XOM>sz8)I+Dd~i>G;+~f_+OS$PM14Ln$36l?O+R;t7b<13qg=h=mm@PPbDC(~Hs#zE3bU0CuwtI1piPEe z&}GSVGgJf@Vi?LVr+{6h#T357*;$@c?V5a-mYek9SFIY;P@VMVO}_vaL`;!Yt)3Lj zz+iiUS!=n$AW2DOHaEYOb2H;u=t@sYg*ghos2Gn-mognIsJW&j&duNkDIU22)#ej_ z5Ny?NR5oh4hN0X!%iC7`Ydg~}w2C}hY8j%QW#kQm7jL$lDg-Ml*ap*cwMpNs@XWnf z!$TG`FramtvK3eTbjVRnl$9i>uph+6c|Nx8oA9nsz2C~k(9G_SHUz2m`wa|W#Wt_@ zKdGLXRwUQK68}V*KOFSrcbFhbW(COVKs45exb#{g^VsUl#^Q?K7a$NW_@vo&o}V@u zDvNis-j%!r7!F=Ctf)7Md75vw_HxhASTl(g;+3R!cmBsbU%|l91O^csHTJ1TY36gl z%=qE+&xf6C)f<+uLGv;R)7ZD#Xe;+IYj|xbm=G<_WcsN;YGpF9Y%sOjRy)yZ;2>S8 z$bONkF>?YWaVl`8>fOACiGCnQLVAsca|x-+nglIGK$UKyd-bPU`Nt&-Ba^Eud_@q! zVH@p{`r)uTgNOxhdwlylNrB`Fe+@LjO-edZwgD;NM^ND8>*Oq~-mbSzI2KqVZKuIK zjvh$OWS;2C4!BX3hrX#3ubL+U^+v~xuZg@hO55Yud}Y2B`^6G%1pw%mfrX?4O#C)W zd?cJbeZaF;P;lxpAp#ucA);!L9y<_=Z_3Ku-BQgZ*XvLB_yf|cBaO2&R3~$vCJf~^ zvq_bx>GlQXm1TR4x%avWfVHT6HI}Ys5qCRg3(9Oo15{Qk(bHY!FV|<9x_x}z!dg}i zp>s21dOwc>*R_0lPUMy{nBX4Q=t<{TP?gpg71Mq0e771?1;@y7w^#KX#>He9NJB2EuVQo#GdKS*Yu0&?uLy%0yG`X-o516vlpfY@x zyvbGt<@6toOIVcvFUL|A#naUl8vXyG!Wx4CX-l7dYyUff7Ns90E_u==)wfWM` z0!y^FwuTcWE~0Ck9!L!}no8>aA@nk4#PpJ&yofcfK-dD0VgftESbZGh6gRci(V>L6 zH<-SbUE-8^#ob9(Ta;b_sOXlh`@9s3$j(H5Jc%!G-)oP0vGjD}7bP;|yXuuwlOwc=8d?pPh=H2YJ(LH&*?8n3QEH#}7?QYlw zTHz8kV_32tOOJr)qpI#a`G7d?B_>hG%cCIP{39g;W23b(nt!z(P*!q$P+}Oe{&J%I zesDMqrx4gGl6lS3ZSW&0(>5HliXeP{^>8=gTcTi`Ft?=gWsM6f^c?wn!Al9&Ljdx6 zlBqu^xxO|-JjY%O1rw%oOgCl(-@G+Q6r!>xClxs6ONvPo8i~$DDU!G`rmE(90uyCc zT4i)L?EodfqgOz7F$Ks3PoUbxoIPJKp6{cjZjCpZN~_r4o0jSq?|7!k*9AoxIGq z?uc*%}_68!PcdEvOuED!dnv^2>{Xx+6+HtwfF0=&qSZ+l`~?ghvs z13;l@oX7-NdS~-MDP?mS!D63BhEEiMcQ?>{kNO#VQy^%9S=y6a=fb2I(3DO=zBVH( zBb#naJjQ&==fN|&ny0-dS|#;#op>P>C6KY)Iq&X-y#k7Hz(P6S3;IOtqU#LEq{gDq z8Hk|wuo>LjbdR(AAcgJBfpGJb7Zi_qou-HG$Ux}GCSh72>j|4pZN6N=m`}3noH4GO zH=`ya6FuoPj0;iL1tlg5I{T@f__k3r$y=f!-%ChI7EvSpAOiDM(U2zf&<4dHULD*E zh?9o95@NMp4*S$?ESiFuiySodL@+1~QaAbFiz{N&AR!*1-9 zk-YF{iYeMM+5L{b91!X(otn@aEU0qc~eot6@%g*Q*Jm1GbbuM3|m+U5n3fit435nqPAPPAesSL3&YWT z711Ca<1u4~QyLnLMyoSXWO}U1^&o7{oW;9Ut#|qm^D7CLVbYJaZS9U-kCO1p!HkHb{nag;6^^@Zr z6S}xi@3F0VPxU-d{(y7A2_4uPDx7AaP@Aqr0P(U>uh_nTziM3gtkrjC^lLy+z%?}- zRDU$XYHWn5oMTBHcBurp#^-`ZOhlKeaxE4*2Kn2R3s2`gOWstii0EB<9AjcPCG;eD zM{pVxXUXa{pf zKMdysVhM9$)$3KFCsx-th~PR{L$HF6IY(Jd3Y#RmKQxI^{r-4uB3u37g3Nlw&Z-p)J=UQMxq7bF@YU(^{Lt8YxZs5x&pta`iw_g102;80Qe||a- zKNjWWT5S3>z5rjl&Bd={qEeVcnroJ4Vt85_% z!T6YkZpybUj}7K$3eYyUxkvM2-9D_;7rJ1d6n<`f+9j~J<@+;DY86D|~Q|;(bLVG+?%9jy0;pLA%SfyGq z&7{O@pdI?rk!<)zZa;ZGO`5ym7laO99}W5o194Cjih`ag>vPJ;tTUTd?7*xg z3&g#aNBMhyaYy-k7`8jER;kr}dP`C5jUS0NX>P94kj+-s6NLi zSgZ7cJxj7MPEvW~WufsEVHCK?xE$J~SYgVq0J`m?IN*EBoNAQBFbWqJ61x|KEYxrW zUck=JG$-uwH4uC4tPTG!=H3IUsjo{L$BKxcfPeu3sZs=_Hvy#t5_)J7nn(>0kS^Uu zCmsQTeVqrR-*2p`$M9Wtkg`f* zyw;}ij9u_s2RQi|i<~r4wWmT%&Da8Hi6!455;+Z03xR&-vwd=aT!-O3i&N#oAli0j zFfD-Zpb$M#^YpA_Oi|0AAK6p!B@Q>R(OFbMR_2rJn|F^rr`n6#RLc*Q8)=n-gjU+Z7=yV^}uZq8(0gmbZ8G-V!jYrKd$o^1N)9-tT8Y(=NZgiEl(LUA{$WY5eVae#(ybTHkM zd|VDZ(JF9Xhz!31z0mo1A^s1m#}@54uAABQ=ZcB=z10s;!6yT>}9nViO3v3O1h?%Z=mo8$jG7Qsyz4-G$D7U0tcz#o2G2$ujw6t&!T* zMaM(g3=iA6-N{5p2bTz%gQSj8^@6#Bwql1JcY9fnuf~wU(0vDbhoqZP>ecs=gGMZ@ z!gNUnQJf(lX^~NRe*5dP|F&1onH|{T0>&%*(7NlH*YE1}j4pIkn!>U^8rwqf8EjGB zR_2FH(X!@MuO@O7D!3yRJJf^iglhCNYg%RD^fTWwf)9t zvs!RkrUn;U{x%FYRnR}=t5pbjx6X#zR}3vN#IjNLTrb>}+d6cExC!EoQ!Z>Xhc%In z=^#qt-gDvGCd!Q3b?7M39x9=)=AM+u2lOT+R)ohEO8yl3o_%Rg2u*6?h@%^IQ2zBr zq%cNRWG{6eJXzi{gPf2__p6``RP%rf1-E^#+8gJ=JSI^O)5P;HP@`@Zh~P6%TfCu;<(pECuI1K)epuN_Qu|+O>;NCjMg#s zyL&y?`9X|>zW9_r4TgDWJ}VHzS-t=5KU=VH6+Nx2`Mj3j@5t5DmM6}wWRY2#Hvl1KIQnN3j?&Uib=PMp}|;w zIc{&O`lAcdje@i2wm~s9Ed0qq7a}6=qTZYIv(|Y!cAr;L!v=ZoWb5Ct0%rkhkH-H7 zENDQ0M;?;@`I^YtyUA8c%;qfbC$-lE&LPQ<46Bb!*qWlC3m>OC9r>PV<7S!NjaRCL zt*IxjH7#dnhw*RJhfI+9n6Vj4U9-PtF4;tjlasDrPa#9;I#LB^yGfI}COb(@y?(`b zrX8L4Qj)!fWh+m6Q6WPi+{GlP#`#J7@{8!YUizfTnrf#}O=_iontZXhZFyEPAoZ*$ zoOR0X^UN26cabdLS_^dS%6=iqS^L`ZyTO_VbNbcZ$BZ?3a`ijGr>qWt3`RG#hg#we zW)(KB*FW}pU2;CTobqY3mCE#@S$^24Ai#2xUjF96U+dzi!!ja$FXTo_l(y$yW`$S} zlpQ=|vR9cleQ9r+8;k^lqM~9kmUs(U^jFfuB&MHH$HAUo{=K*B-_QSLDiB8Wmw5u| z(|=rh)vzLNVAoQktLZF*sO-a^NAU+CdqqS<_U3Y`s;T?e3h5sxz2&>#Tql5qjho_u-`=E zHiKcNb-m121s--Xg)MoM*FWwU{=xKF+*P#a=DDA@=?P2S%EUDHV9q6O#tDFAX6x|S z=tB+A33XS*x(?HsgPG+SddK_O2HNmwa%}st2O(qLZLv$Ep@Fc%+Aj5VP}hd!$!0I) z=BQWe<5u@$UA$wLSZrFo4YEXbHS+8D6AX3gG4Ms(-K#tW0%lZQ8oPWfVdwqsr;_J+ zk15UUx63nC5a#w*TSdJ2=Fr(eGt(Sx%jHie$gSz>r)a;fjl?@KL}t$jcl{>%=$^u0 zZrgk{!;o|;+V8b!apyjnZ)}VbRnh)P@d=;$x+710p=E70L~B19*Xp5hgm^EzK{}j) z-_UO0c%tKiG=*b)o$(<46@j1xzvp{r-u1ibz@ehloDzg=rkqD)M_s8cZLiwPr5v6{ ztcVN#{3x9ZP-&Ew#M#_G-MZB&__NM1r*yEablODM|z z;QHZ*3)=I4bW)>Y|8umomqy?>5l0=s6l;$6uuVy(JMb(VkX^t}>aPl{RFsf+_nh1p zaA4YrhcrNgN)XWpaL2LlhMK>LVlHu?nVm6pje6KkCyXC>rcTN()Z3mZnA7V_l3H^0 zTMTh~+6J*aDvxd2pw}qi6U`9DawtTwSy;)N0lR7>D%M}c#QS$*1dB$Z=JH>tC2WK~ zIteTae8jnTY@~11>DhTzm&(5UJrwVS&Ot`YF5X@~H+{edsLwnCrpr>9l<1PDNRM*5 z<&cYaP9ti4CUDZ!gzOQ*G03e5b^1=3TWajb&K*Z_3z)4aa@xZ^J&>h|+KkHS4j#s?VYll= zT^E*0A5kk-@6vA71Rwg7E{<=4>M92i;8{V(jYuvFo zBU)>S)xG^DoaZg;UyeHPml`uSxZnn!u_wjOyscB>IErNqF?W3Dr!M?{bGQZi;gkYO6jNpq1CYpCiL%Q%9}w!Ls^%_U zrfD@P<&FX6iq18K7>4im@ykn7et3jO_Y(pMe-h2$QTb(1kRp~b5W3BmenwR<-%hVN zpR=dft@jA4TFLWj8TE_83=dfkN;UPdu=P;LEJx1gYW-v@H_tHfemeKW*VK8UmM?QC z>v3!hvu#$Fkqy>Gt;r8eCu+coFB2({ej)kboSo|#fSnDRkg#k*wI+a`t*QW+gFk>3 zr=7%yf%a}HFK^NLB!0+L0xdhz3nV$g98KsK6;hPDjFs&YZfcmTJHMW1-x1_?>9$z>6$>?UotwRB=bHfC-J63MDxBFOjfux-!zxqhK#yPjIQ zmwBQhT0X=yy;wgn57EJ2#n5I59&DtuNMcnF6);G zAuVsPLt7XJR$Yuf=dQk$F#G{(-ms=iPD36V{L!%OOJmx-q?#oN?pL+O*BtZh+Cv48l zf`$VTmA`HXc8;d=<-oaUrNmErL8hR_5kpxgkA#&6N`w=V0_|8eu6&Q~suFuLj++vT zgd6DjOeUUtrC-kz7~@A>A8D3*y&yO%=|ET|9j&z6Is{2|j6(VrCmp3`9%|!wyI3iw z4gw(DP$XBDdk!qf`5}<z#SI;5cw-8l~?lv6U{19rGGEHZZVB;ou2Qdhoy94yv zLRJKasfoui+gYArIOYwdZY#%y+PH5-X`xk@R+QtN^QK#vadc@yFfKFjGp-gJb-Ec4 z1(rlBhxlpb*7}(ToZ8Jy75>VQW`i;0S(fgoLCzqp^a0Iwbu{c&bWf&LDTr|=CW9oC zCRBtb5vKxMZ?k)uA2{qjn+~eqF6bc-(93BFU|+T6Dv_w5($mqyJ33?rk*UDAzrjY0 zML@4tDR!y6?JS_Z51dC)r-s0H-N(jX=GO(dDySdy&oNo@Xgi2zbq6DEf8C!h+V_vO^)*hJs4RhBVkS=XlBAhW7) znu&Ahs)}gP?a|{P_ue}yrr3!odkQ9GfyB2bT(gpB6cwV5%qSR{R^LvOsHrSr*$N(**fKJW*&q;f3z?DV)nYvuI7B$U zWf-Y9FoX~TRKy1jd;>=?m8fb0H30}Sl&ytuL&R=+2i>tuB$umRi8Ph)bWp*nWea|P z`fe25Zdb8nKolv$NdR5bzkF$|*!STB2rsHQ$`K6j(R8wyr~IT9kr+58+OIH? zB$hg>#Tn~;(o(ohvjW5JOlsI9rZgz@sQtjnsTtnEvnv}YDhX?Ikqb=UUGh-vQ>;!| z+~Za8mGyX*nk|B}&NQ@TYZa)K#7l+Ji{Og6ErNG)I2}RcLbZc;r!x6NHN8HC6+jU} zHViR^k1Aqw^ewN~slK-xM$2be+_aAoSJ!>fm^jtm0pog>sUpJOinoKf$_3YKW)SiP z9jy%K3IcZmHOJ3IHJp+}F&oeXK()8P_rBzH54vZi5`!SFa!q9dA905C6G;zvies&v zyB1HG3hDhkroIZ>AeuV+I+d4K`m?x51fl({1^LPLNSG6ccL&Qs8Q@mz`M}4usOhG? zZchlBkAnGt58%QAvNbub+2akIlAD+owv7hs0Hgc+Oz7CNgLZMzwhMXZWF6M(-Q(ms z5)tA~vkpOb(4v8WhZ$_?5$4|UIU&!+p> zTxxqOAtw;m7R5}$yQI^ZG-Ho2#AE^z7z47>ld?7J%JUiV3{2!Qk*ME&?{C$K#$DqtyS1~|JzR5&{9Mj@b_ z=x;*bM7(RR7M_fkaFFMZXkSLt1*ruNt21-K!ZZV8QA5kD(-34_0=P_i2;#;%qB9Q$*XH!#ICz))hGG)?-O8K@$V$oghT6&IcYLlN%kPvW?hEJO)&xQtpL;V} zlhX1TS87z14b5=?b_a9_an=k|L70wb^ihZ3s#&Dj|(ZXtYu4-msIEOy|&Y+F|0C#qH08*ZO7M zo|X2kji`u~U-g!Z*P!s|=av%)J?@3l>tb$7kZF!PW%PN&TyhXQkZp;OG^za5s}bcc zLLv_jxg|8SMk{YzfNP%{{*|2ads_mHxq1%b*Wz4NDI5-9T-_6ty`GplY|u)595GNn zVrpe6E$k&ypp{hoQo&ZC&D8rnPps3w25phE-Yx~BvV9|HIsN4}Ttl{er_w^N(J-+X#g<<@P z7NQ3-$GQtlC4g9mdGfR0l&QP1cj-gbyk%$XVr8$=xSB*q0Kxc zoyMLD9YYM5)#Upte0PP4Ii->C{WIN8LECLB2#0}d7rfAEIC;1O!MsGX7Eq}?4KdQ7 z)Jn+nu4C!%YqI!$EWt zTJo(oaMdJ|L*z26ddZxIP64Tk1x$;HlCZ>TN9{x4Ec8~=5-jMGO#D$`IlvU@pq=Q{ zqRgF-o{r{SNF=$c&_QLx0*MSIu;UOlPVIr{rN7mH+dey|AYOd^lp!suXuE0cn^~ro zmu#rKln82fnx@T&N#EiRtR{DhJZQtpw~c4ixsSrbmWz3u7z2#U2c72hDY)Kia|tI! zP}x01!t)2wEI%n$W?i4`29{7yM%x=zMN-%dXB!kRwd_%@E=5!Hu5h$tgy)rCO?uL& zcn4t#xenRS#tGZx)ejaIg^Y(CWmyFXKy-;42aGB@Z5eG&Wtn7kEz0&s?+JUFRh4M1 z2YpZJ7bS29VFgrFyOt}Kcuu!YyWrf3y%W#Yn)qo)bxTUrF`_wkJJYazzD>POVLt7p z`3>qWDe8$6iJn#g7;TC~P`9W3_aE=O}C?H$FWLv04T(ue^HCmp8=D^G6gUhx7%<`N zXbFcWndF?B7ved!t<{p)15@R*rmRve%LHw;VZ8eVK;$axrKE|=jE_HCsnxODCuw); zPR0sGOCPIM&|%Q>H{>X%0wk?4Z2cAr%5wWt(kgEfHz%Dxk8+@FXj0A;{em~N8WiTl zZmOojDS5i1UjdwkOXjaJs8bp}q=Up&V+eRV+arfQDfus^a2)nG`FOCCy@|f0?nPQT z1bp;G3osW6JPxwrhzv(uCj>pS5&*dSxs$j})YscwURpU+tDdy}tV*ik#u0y9uwfXh z&i6!84npE+K2QRLKb1-Arl+oO?vbCo94wq*uV75_o+>-u(9L`lCwh&ie^CeF-JBWW zHa(4BHtF6UGA7NjCycKDkK}Rcg?}PqGTtz)9s5o6Ardd&`>&>0e?7r^uEL*A13U!f z`gPrUepz&(5jzAEw`1+j#k0zrNpN8EN*GjZ`1hWtSfN=i*}qv7qZz7sGEvh}uo(8N zf?_?ceC-q~>7fQr%dF+;C$siPsi7ONX=T7|QKi$iPd8s(MImY( zc+w(x#+5jYa`ZpDD+mP-oB$m}gOJFREc13xbJWcZ-ZfLJ6Yy}v($zZC{4BYF-$Ys! znkBOJk&Bm}zd_Q5Rmm5g)6(?28)pM%En3LqH7ehoL&m_t=eudWPk6>852|HCy^Soq z18^szEVVfWzJuWVZuq!;|M+VfhBXB$me+r@xeUTUEcjtbJA0b6eZ1VA$@fApy=JV( zCn}z{qi#0SgST{nq^%fL#t8HR z3G!WW=fhGF>6w?2Muk)43Cpo7W!4q3egiHGGw3^YRhyw(_u(ah>XmnjUMvLLhQ2=t z$4@%4v!Bj=!WfpH)%LmcbLt%1L19(o+yM17&#MZ8S9EhHc~=HOPevp_B#^U{AQf?At6{f`n)oqNODts zHpGmc7tU(R=X@|JxALrLyj1?}6x4T#-c5Fj`FQ!HZQtSixXVCh8CsWUtq+0c9U)5f z&(a}pT;JDb=kk52;nAwl$+ypakNr)ANz#p7Z183K&U)TH%Q-1xfAVx%(&}F6$1-nP z2K48ht}WhXtm%ZLGRYdnIcr(pajQ13omE)1j-7kL6_2q)Vc^8jmP6F7cp}ta8}Hwa zq``F@38t8ybiH&D!8Az30>~*vJ;yVS5(d3%LMfaOb=Jfh*Wn=^tM3= zlWO!6b@uFAWhSeHLh;CquI-T%?mI7p^nSXHu_G3(E7>eY)Jmj$&FBm&|$E zIqs$^{GC^+UJdXQWcyB9y@iOPCCsY4m#@;a(>+x;v(rQ+M}HYd=O#Ux_mQl9S=5?W zz)*|F^QIHe0Is4I$FAVTn9yc!*>(Q4WU_(xc-lZG8K>e-fO3=%5jCccK@Nyo=+K1Q zpba?jD4Jj}f@`K<_r;a)kqz!MC78j!tqT>bIBQ;aaLCYsL~=;5?v4mEU1c=Pft?%D zfwTM47Z_+R0)M%79A+G(n`;%a|2isp)}1PLgZD!{6yT7A5RAz#GKN_A5UUd1cTbZq zoJ~^dsaeCr`ZuPWH1_yrHY?X)RJq!BzzHG+bG&<^9bydJyehiV>G5;)PkXu#;X;oL zV!#fnalG>}Z#>$L8T&A zyH)Fkxy8Vm0`Prh?VK|GRdu=O8>uSA3~&^dkWsmiA3mro#7hQ^4LIw?-ID%zyFVQ9 z&ROv*B)e6f0xB4Ln? z&L^?SerWXy!@M?a5|m;t5?&sYe;D3Fwz-w3lMsq0y3VnAgfH;pi~eZ~Fw3{RxlU?M zZ>&$iTM(j50Vc2y=kKwA4YXDc`*Ok>t)5CSanKIND4xP0zg(!_#CeKv?s6HjOcZv* z)s9*D&;pp8G8y|H;;6J4=^m9$z|CMg^df-g_#@G^n19`c{&7aBVs==q#bk*9?b{si znZ^4L76gE&OlDr>A`#JDqkmDp*Oj#7Q1FZNH_`R<=sylVQR@E*;23qpCqoGNoUe{- zyi@p(QhfHhE1@$Jq$s&e#OCo?lUgQ6`^)S)V0`>$QV*7dSIq|MI$&MoU37U)^0s2c z_3f}2DQB_7Hzh$A$dAe?G~)EFd^#KLGq%JXW^cpGo`j&fBYzXEMb+Yo?~HlFPf6c= zek66}fiBODe2z@PmjmR96$Jdyl4-&Uz^KAnlS#>ZA;$P5lgILQ$*9=NqWN2nih4vR z{+$ds+8+6gJR;wQALJ8Zi=PCIxePgdW24rX*Y+f%p(nXPZKo$dZnn3AvgL zVfEv^lSLth3lGh`E_`92eturTmg^Euj6{g@_v22a4}Hq;!e{Cbl=F# z?gYUVcQpZgr~;Hsm(g@+L--%oZ4a3^$~#9~Iac-EE$f$^7+m8W6v0dH0k}#FD`j?x z`@zE*I$mzeN*lMyN;_IgjF%zQ)>bDY)tZMlpAGTlP*$aEcz7IDF4YvSmW>w4AH0E2 zU- zEDIf4Ok2q>$``2nqYaV&=geybR7;478kC^F#JK+OiBY%3Y9T+mpsqx2$0GqO4 zADzN$MMU)0|8dbwO$)i>r(xO+gyz{oXr3|`F8_kVBZk2(&z7?7S?R9_4| z7Z28~X^SDwUOMrheEdAha&*%x-!Qd^%O$C>#{ukT*5g14B70DFl!3!X=2Qm_G^p$` zef}s5R5~Jx`J=D>VNUnh^wZggx5t9A?b7`HevMDh089&)buQ|n(R&gN@1`ibe$%gR-^GzV9^*o)NFJ-5!WKf41WH{(zErnGoIe zfU*0Za}=iLOfC>1$Da^RN~?9}{LMdJ4}br=t>*?I5Rax{@h_W|Om?@}OU`2e1Pr*; z&jB^Hy0r~fO;E2%_o{oz=N67zOnXE#UtWcdOx5u8ABL(!1DIi}s+Y#*zk7@;&XXem`{dM)w=ryU8H7(LPoG;!VYTX1}j1YE{$? zl~$O~b1KKPy-$|Ay#0;N_6bW+SVzJ7Y`YkXYS_uL%0|)omz!U%=IU8$qTI4Y{Q0Ng3zx+56Deh3Q6T z3Hxp^v(?l;Tnuh#o^i76Keh4_$moZY0qq~ z5WjN%uwE)Rqu{-0Y1ZtPkp@B*Eo%qM-9AEz_hJO8vQonH67chxv6-prbe0>M&b^NB)!i^*o<0v3T_zgjRc>29?9d zY)m(cIlHR>INu(~4psJ)XxptZbBp^*sp~Z*8|_PmF&sf2J?SOQu;wOm!6AVW6$46- zo+dF}EHb!^<$II%vC&`Vu*4=6qRitj$EI}dOM_5lzlrEF)^;l*Ck1`&G!4e|{@(Wff-La=!WsBWi~Z}tjXaxM591$aSw`b% zx?{Jec=a`vYd2_mfK{FN@CCsS+mM*7>}p_HkuIfPOac4y(2>e#6}4oQk(t^8uO^1| zYM)L6Ue&7a>R7!j(@wC)=AFv60>L=doJ93>^)SwXbTPE4}=f@hCzG#!^aHoFWO zmk^?JR3eK;BN&D~9_PY0D}&p1!}mlC*t)@1OVZVuf$qe?7BpZ0%QL>mOI0YKH@{Co%18CbPZ6C zP-?9_!w5WB1D73DG0IhHb2rMAg7LrquH@KGqGvu*;a!66rWNW|euDyUKO?4P9$7HcV zoi)Zj{o*P$p!wkSpf89z|5vDP$K78h5fXWwKQEE**_!#^OOUT%J*srQ5VIUxex4UT zxU&V!qTLQbNjb|V1zm`Nj!m~$=l;EGtxg~RZ(X|2ZOE}$3!wIJ=#tpkh!VZs6JtL$ zIKa)I$UYK*DF+Wh)C;1vzm>TWJifKz{$|db3(liH0c?qZ#3<{MuUA+c(>rVFW4YNf zMitp&W~uC^^*$7G3G+V0W@~S}FH@WQIWGV!dqecUfZlakB->YKHM^?Xk0Raj#z@M( zc5dq8$}eC5>ax#-hlt7Z)8qr_X^EAp0e!h=4_b>O?#zjc|`fd)QkZ# z)!?B5W3qCq7?)-KZ1}7FG}A028tFCXskjuuAaaWv4sBVzA-uNoz8aD+2ud+8SPK*U zi*0XysANbY3)B*V;H~vHMR!E3iP+F8BnaSffY|TpYQn2`5n>e|%bdQa?|+;dY3-o> zK?*PwO&{S6-VhCfrFq4`3K)80(zXZ z%ilC1X`lKhhrFn|*Nf&8062=SweTc609O*CsJyc*jGkPnvM@4yWjvlovEXIj>8&$) zT@Ah(tx;Lxi|@|Pl``s}By12EMCEyc2Be{Bm!!}Zb?BAn&>!P7(}nXKHg4~7Dr*Ym zorj^=-7Ve)G4`u7b9XZV!W9)$!nmx}yBQA{l-PdwbjS*gRhCk=SF98l(d!vI=*ksc z>rhhXn6l`=mj_Ywrmh~9Jj1fre&_5{SblA>WVH0cD{sE0I*dR>Z^$@dwOqjtVU_|= z=R|Cw7mGo55WUHQR4iPno{%rs-$xp~>?uh;d@q$xI7gG}RsZ(B@>Hb$Qs}LN{ynQ? zOLbA;Jamh4utcs*8^#KXil12z*Gl0UWjIRW3r#`gM>=cIK{!z(!J&vm z&D~HZ6$mN=&7N`cla9@-Ws}!!`aSh~>duxjA#(1wRxL6q)gC4Af$^v~ z-=ZhukM{VkigR4bg^M}br|>^8pG5X#_pcv1aQ)2LUEb{UD;W~{QGZnRAnlnz?on$$ z>eJa(@Qn@hX?`esM|(s?O3`Cp&Ct#j)OCKTw^E%@$mt;W}6wW+=08 zA{iON*X?0Y9&yszI@m1j>AnECVO6MHP(FROsM12a&A2H_9%Zj&-I*J^ylGtiE6W zLLatI`tsvGhmf$Fq93XC{qX+X#gmjlG`pzbNx}BB)Rcn&6mDnQi`=JOJnlh*M&!*T z!bwZ7DxW<#HT`fius_rT_3GN=yPiMKsN z=icI?a7r^L{yUv!RtJ=V@gSG~hVv?Zy`l^#-3ovf1=H2%@YJu0U7?xh4E~xGs0w*VKP)JCs~Av>~89{FYbsm$7Gn`k1D5)+a!!!wOrxAB;5=Na1b?QE(afrDPNZt zT@VI~WP6+J11+-|r9`HIUGDJ9W1rT~luH=023{UBu_V1}kGWTqP(G>P9Im|41VRC@Hb~pO=*I$n#(*I%J@`ZZ&XnpT+YpV6iU%vMV~Fbc<%joOLq<^*u`!Ph zwbLn(ZuqiWslJ{1!$q&gUT0GafOwi%G-A6AhTTWj!LFS4(Sr+Iga{HRix_53;5G$T z5&P@5af9Qnjetjqx01?#Rq!RISe>T#4-nX{H6e*U75$SP+D1EF$#Vt66w8X)R~S|L z?pTv{z7N}xTssI?ZHbtUX123*bn_l*wk98++v0U;z|_vfoMIrq4VHpN6)*~ z95pINRWU$A(O4(VRHqvjgAe$#otAv`=??*boY(_Q;VHN{F2hG*TfV=>4{vKb?99#IBTUD{H4dd+O&+)-bIK z>I2sD4^p)smcP?;@=ox+*LXAIBf60;@!SCQa&D@7m~mDE+zTWB3XxWQ)vob(<#Ud(sI4xv5t%z|3%2@*pT4CcVHD zveu+_5nL^TCboaxVzt5uUe^Rs(M`lj zPY*Tqb^_)s-fXp_5feZ8 z-k8p5@J$=fmjR%RCRJ-1XLR%(Oq;JdrXQr9&CG!q<}to)JbS~lTrJx|IbOXl#b@^J z@u}xQ58&8PYk7%mOf^{nP`;bBo6=u*_ucHYW2ow(_XcSxxqfL~X=Wq&lI!jG>QKb`GKAvkvq;L-mHN82ojHJ zUi#&`h!$K38c~L05=YR4*aVyqQ}HjitXY_S?K?vUwn0q7tG@#WEY#H(ap`^No(6Y} zRg1_x`N7R6f{Na=RTB}EKtmRyrx#)#AeuiV2`^iY;(a^oVqARp(~O(rBTC`@IqKs& zCs^I;0xlPmu)f+=u{)i{_Q{ZQE6dspFo^U3Xdw@<{9cg#xS;xZ%{{RY2YP54`_|Lk zH~}>WA8`lCY?6dqpT{%z#p+?;!8x(uFo?$cJgs6kzqB$-4}NLBlx1niKz2VMVq$cf zMnmeCN~4vgpz-pn?Ho(`&b zN=38>O!$3#XF!n}Fx(8QIwv1Qy}lPRRqQrFdrh(cx$!=UE?UW*v@FCIACpN|nVrma z>nD^945r3@>Ux`+A~`>9mFYd`(o^9yYNiknllypSkWE3PdY!s8ybo(ER?8#AjgyvH9`#GicAjG?C zniWC`jfaol=CiDE-@y*RCsIjmQvfz9H!Ar-cXF=+KP2pSX9;!?V^cqXrL_qkstLAJ z*bR~p-DmBG?0obt52G}m_`j;$Gl(+OqRS|RB*}k>Bh{%yQEJHd$27OjLYv}4f8@#< zRu&tl>*jO{YVUIN&()t~DS%iZBkv()EG%=r3i1*T6C*uoYTN`=xFODuB(|?IhBCwe zNNDwN@^}NG zv9J>vovvjj;v?iJfE7ZicmtXmBs|v_E{ed~eML876%_(m zve1APh+b?mD~Jm`4Lna=j#jUJMGtI4P&bfrnJaVae~ML?#}3(qujRgc=2ULMBB-%u zXt+s1`zActyCULY7fq~wTpPQ)Z&=J*hA)InlQ;W7*X_r|D1jYg?QprD)WNWN=m>Yf= z36Snrau}CzZF5f=+4q5SgnC;NBnuc04haA!`RGhVEC65&^iketK-7hl8xRsiCbWJN zaVy05RS>}=HmFNan5viPi6STVI&SqHll(1d<-8Z+{bbf6ZO2Y)_!#xLXWg#!ieDR< zX5^8=Y6GiI(O*lgE458^#x~cq<>cx z(HN=}V2`6$FSL43P3JHFLOj1$t0&Ifu6rsb!OOoGEdwPW>mvpDoD=Mi?S!?L^@kM| zzlDJ;2$@Uy$BJU)-K8tX9@nr+h-`hKYZ%xW3BY|4j-i5!qS&gD$o}A~af1(S)y^+{ zl>qzIx1H%sxSgZJZkvieO**|&JffAXgtsPHh$6s#2izPZ0x{MUWM==&w3l+PD1v0^ zFgPBAw6wGLg7VyFMS4XKI#H5dx_CEmjqlbht1nu1nYxk)DOG_gA#eb!+^e3L`Ay`h z?(myv()-+ORjZR3`rTjx*o!GIB+Nr>UJd;wGSIqHbRtIp(pM^Y2+QsBb>66Q6DTTi zh$9)1O;`Sikj-Uag6r1%iXuBj3bw4zOV}L!T#^Z;pkD02*5?^|-7#mgdIsB&tl{X~ z`lGUm>py^FN|sQL)r1y-AL7P#Nm_BNru8w^u=B68M8q-~>xb{)8^c@@@C!6#WjnpZSgj4ln|(~FAV2=sRX7R)yFpxk7^^pCSk^M|(IuuG z1K%4ZV%2Ke2hU&d{$E`RhZ$3)o)}sF+Xumy2mf+pKJjp{mgrJ(`2W@YPySyj0=CEA z?`qYP4)Yi^u1XhEM;vW%BCTxA`OEfem((+> z(Vc6&t4*35{o~nfUfKlS0hdDc)Ax+MzgWrL|`Tbxa(5~%#_8XaZ2p86wVyBk3PNutNQi9SoYEck( zDKJ|BzU;k0CWp_BJ~i=>lp2na>>p3!f?sV+^rYAf7k7J7liWRmHljxuk@KogQcsZ+ zQ|6%|9PhQ*x$)iYUB-Dr4hHcfoASa2zdnqgbpOGE3AqPGPda}Xx{uB zEjXv3eDW@l&{`=|S?vqRA>kp<(910{tEC2c-4X8wZlVH!EG`=M-P1xRg*m4z;}mL1 z`x<$vOQ2uMb0c)G>kX>>-Via|ANXH@%)G;)(DiGL#5o#Y^d#LWD+Fl#uA8kxyr_Nn zN5OT}W=TL^2(yvvP|))YW0n)T*NcvybN%e4)ck48NeeN#EkhB!Ud{Uia<|+7#wS52 zRBQ+v>yJ{n_cu5rKTfLf#H{e>8$zklQFIY+*u_vdp} zFWp+&4~A$Br&53h8Z1A1-u*C;9AlIG`jPrFPPuVl4ProC9v zH&R&yss~r^-B2GwYe)Yk^k9SousF&fF?Z%zIkm6UaZ%vg*TIWtnBEAsGMFx1Se*LQbO(Zya6!b^YC3_bp z|LfMd_>qB4+09-)XP+FF2hgI~sh$ghffI1{TvR4t85Kp5knod*`3%t^`?4n--|l(7 zp35Ov=@Y2g2Lkvt~M{V?HfaKfAqX@I2#l zyt4+*sd*y^`xvd!8w;6)WpDBC6gEg{eeA=$IuK*EEw4$4omgAT(ot+fH?idk?buM8 zkZ*wY?u!f2thJgwf0l_hZISRH^LRP7)W^rfKf&(wi@QmbFXD-d*qE-YDEWnWU+y-$ zo+LIG469L?hV)XchOxyj-WN3?7+Eu8S`9NAGGvT(onu zKbrHK^}36ZfZ;+E50FCUG3c=-cd8GF>5P!r*-Rt4#Swd)gP2tUcMGAt5m;rIH!h6+ zf7E&Yy#_)SQy$PXerV5|Z1Ga1MPzXq2g^yeysqkCslLlG?lWCR0N^VcTgysz{U#F> zEJw`FTcr};157AmKcqBriw>`EG=#T~7=yvc3_-zzcKbR;eg0U{7aK}4n%7X5MV5D} ze2PnnZ6$Wz4*YOFGPfefyZj(Bc*<%L$rIN_|JWU!#wngUIw@i5En;>ks77n6ng@;5 zO^OsD#rRzBap`p?b$|KPjmzx6|mkud7Bkk?J>1~IAE zyX~R(QLXFvoS)*|EJpyh^E{dNEWXHRfWUGM!&h8WAR(!RaFR};> z@=lf#XCvWCHWOaGDPOK0K6LDfMz1QObhhK(RrB5@3tCn{OTc5U@}08hn!d zo2VP`o9Kl{Hf%*N<`W4&=30pVmq~F;K;piC-VNM&;ZLt$g2HLv>JTO2MRsQ-JLl_e z#9rz#JWnaDi)d|#e-pi47xT?CK}T^N_!~XmAAno(A4asexf6)DLQBH-OFnK9gY;go zHRvO%7X69WqcyBe3YYUMeiMm77<2Du>{PanH?{{W;hnkHi%zJ7!~X`ZK=5P8pG%?W zOmA-4>%{r4m;bIU)6B*X&KSb1LA;!!VT*I`H&OYgjbCnO1lxUbo?v$W6&c>3qTfWN z1}ndb8a2HXf3Qclc%}gqSbq~)-@;p-Jq~Xulk#Km*NrC;!snp~^RelJ_|gQ{pF)Z+ z2(|g0A}A+fCi47fqB?x0&S#jq=;-mY30F4+0kFZkU=}X+o5*M5o!Z)Hj}~EC!t!9h z2yR7Su1~>n6KHT7F=?l%4>lwvTZakON5aaYrz|$QJRVMRU?buVP>r_@Qk^^wd#5C* zO=g85^k>>v%9hLE25+LJEhKoiW^1f|JUnaI8^3nEaL=nLFXH@cB9BX&5K5O%V_INE zo2Q7KD80nt>Z@&Xc2Xt-@t^!n1Z8V5xaaC(e%Ro*Xhev(s5q~9(O}5&cU>~&>gI%j zf`GV_)!#%N5b1jNVglWo&Wq*l@o6KI+?gV#@@h1P|5*FqARTO*XJ9fNc-mR5+h4nb z(=54=Cu_`HaU2f4*G5@3WgB!H7lPKSgb7T1IAiO>)!?JYbx>aQVF5h0<3M|!cGgXH zQI_~Q=Ha-mS=_9z>>~Tl0)9Nddb0ZV*09P#+j^C#s109b1=raz;i3Qh7Y7q1_eo?r zaYXf}DF66Vh7O19as8Fd!yjVjFYWl$>Jq{VQ=FJ)^LXYW$DJM5Ta8`A-khHq`!D>< z#Sv1uqZ%buT$YE6V&~>RJpwY)EL{glw|ed7Nv5jA%gy+zsa?;{%mxVH81T5R!l?qL z*?j49Gp{n}|7q{L(-l2 zxT^z=@E9NuJV?$yN39n_NZpTvBp$P3zmepkCya1jFC&9?8i&e z^63O=mSuJ@Bd~zeDsb1x!J>a@B{c*NQcQ_*1W1W#L|5gT<~<%`F@v|dU{W$)jZR0W z)IAj$Dt8UtFiC+5PkL~}CxheE?KWb)cND5|$&`%&JY9CkYMa=*jgLbp>1Tu7f5foO z(jGT%;^-sNMO+2i$#Af!elESU=FH7t-d^$haLezxgRRVT81u>upboo`Ykes7q2QDI zTUWjn?bEp*WTnjsYH81m;kqRUJ{C_o7XD1oAs)(`&s#_G85|!5_@M#s8_JolCtv z76(hoX?$M`k*t)va-!8VQc@+IqYq57uu#bykn~#F;nU4~jfigtFkJ3)ULMJRpkD^{sd(Bd+$2X6{gy7CEaF4bSlJlop_N=q`)NH*HTjYlj=D0agtfeFPRfyvtV#Dpl^8 zWCA%-ge!Vg8~`+?LlCU=lNLzNk1cZT-17ZSb@#D4S0%G;^Y3~~(^B;AJWSFkIT`Ge z*@5JJD$@An|&m!E8C{*b@1GnK#BKaaqBRSnX1a{!!bd=_ztu`I z$J|TqCgGObs|u7Nwon96l3SrdAi7txSWGg(HZO@BYYMN z#?{_P4<~YWY$+*nO%}k|LWK~8Qh~=XEWG;zwpZGLiyodKl#;XRkA z7|0%s$Ihqg9h^z6ROMM>SF|eEVt6&P-9m&SaX42S$y#W9>Sf#)*gJD)JcJDWGyP5e zu+8K9EG2$(%0*ADxb5y16(MP7s-v*d0yZ~6M83d*76xDF-a&RGEO?@fDZKPGoeRs5NNjN(gY`#!+H6OUt>@$FBGkQRe! zaR=)!Mn8Z=AAhF_BC9TVqF)WWn8xAPwab;hV$VxB&#P`HzM$=8-G+Cok{>{4jh8rW z_0G5+HPGWcYa?C|-ihp8QTO?Aka;#A`2EI>2EiUF6|*?6&)S*h9fg{lr1`3KcEb}n z(JfQZ&IDhqQe{O5%k8<+Z97mWgo3w50ptan~4iixk zqZPJ(>#}5}p~7x3r+O9_=;k(!;BUvTFa5RDVbqH~OUyvbD9@ylG}1B+{p+A6Q_TcVGRgGOqYV3=wLS|FWyuxZkXT2zrax)xLuqJQ{BDMU<|mWN;`EO5sP$0)w}@ z8QyDjGpIiB>K%&R6u`F3aPmeei_FF%AcTZq8{RiKc(sf(Rid$K+UuH( zh3f4_`?ZdqsyV1OLJ$MXxFP@pl$b!X6NF@B83&9+Pzb0Q9GCts*C1X1J8r}@xXxpn zKSY^DeH$od4~@FJD2y=hf-i}F6H z`|wztM4PM*Qxrw?IAJK3+huFdX%a%37lmfjpCGD!=XOLr(}n3y5+t2J(dhBIxz5$O zw;EDmErfJoM9Oj)Qnk13D7(OjS|Jgk$~ z)Wd!tSelOXf3s>;AmqWlyswgG0Z<3DZ=))u&wB@l*iTW%D5mi=zNI8<4Ilz&+2-#<(2E(NmwYt-=7z z7z)wQKaNwob>~56dla(7lXIZ35-9zq%3Ce(P8ZzfsEi6=;Sw9ILLK6YiiD@L?1Pko z6hAw9g=nS0j(vV6fSA00Os<{NRPbngVpf+hHsF9YQ-gWZC29)HK&Q~=!RbQzq{@7p z?|2IKHDCPA*G!!m#p16*P1%W_E97jk12`4NTU#2V%d^#o_OuP=#L2estvHQMi4UWr z@p8n%ArVtbk1FP;se;TqV4kaNwK z8P;1+U{LY4OG7TBv=cYQS|Kmk+RG|W>YG6`5%E?Lfea>GMT9YCgDcN@eVC?$F6TAK znMJ);2oNCJ7ycmO9#40CAH{eB?Ua+gJ?#8SAS=Lgw5n)w?8g1)HbrwmNRY{p8KCR+ z{fu|E_Za;$Dz~%h)Mj|1eK;@>|ESi0mpm5MPxMj>PNa&-n`{pnSOx~=OKyE?*|m9D zrru}WA>UQCkZvWC0nV*y%5e+zrc>nn_QW`jOFdr?loz9ss^nX)spweD1bT!KRIi@{ z6mn{MLt~FI{SqWs@hD=OiP;0A(##Y>HC*fC+Fjl{J>uy0$hBS>6gZBaD>--vXCWM! z1!mJiOaUf09Ox7gTps;Z*Nd%39M5UdI-kovDtFh=pbYvRDx&L63e8RCHq(_`0c2L3 z*YZ(?Uxi{1suVMN+T(|>O*nU`Q0=oMD#!}UW@~VLH)%2W7xWfl^5g9qR z7Wu|^P0v4SOpZB5MV7QYP1f~T@>nj^KtjD;Q6E<;UVpVwlHJrwheh+mdfCY5cpyNE z(jX_H{?a1*cIVa1NE;^pv#KxziGg6%@r2%{)~XMk@B?_0=H@J8AVdeZjs0 zz`8Q4dptg2+bNtTTUmyf>JZ1Vq8M8qIW&pt)})C(Z@h>(919&lMjj5pQm$XgTgQZR z9Vwb7-a4sdSXzw{6E_^&j`iK$h%cM-HIzYUnq*>qbG|q{%Y3lVXlSY3qJAHnv;7HRVCWkS7q0qmb<8$A*B2Y|bXd7+fO)3(~j$RpG?;3VoNKRdj z_q_j{pH0WYzh4M}(XFBmTxHNFBeae}0Pk5Kd#-)}lDS5jrde*koQws?^R!i)gPMX8 znYHq9rAuRW)emdvxoDhfH7bCbihx103~T^JRxyFKX;S|cQzdni!R_Osn+KRqz1+!i zDGN(^u`>DWE=PX5cDs1{NR{#>p{&h(4OR*i?AZ_?Ifu8yaw5oL!Hp!g+mm5z$%%Aq zUt2Xu+Z$}(O-vI~UOveRtjh4;7aV?1N!xO_Q?!`tu~f~fFyO;r)SITwvd&DyqMmq_ z!NU2n9TF~mhwd{RM|jyL!gbZW@2H%jSyZ^G)2T=|YkdZ(CscJH^{^ihXsB_|;B*lt zQdY{@qS>9kccJed-I05c`DtQW1uQlXY$=KgM)L@L zRGZL8KTJ)ggO zMZ-muoYz68!FAFW%I5Ua=I+-MS}OBJTBZiQazT?kRXt1w=-Z)g%X(=Qk+XLKgOuGi zh=M(A4!S9_e)9T^2k=00-Y$ab%tP%yj}<7GR;92dva2Edchr{NewfP(^1Cv71(B{( zTu=ci8lyaCtl`H|z0n%r;;c-k^-1WJW;5_Uo-l_QIE6`lw^=1i2I)U(855_5CUSxE z)p^@uCQmZ7sx&j@bJY{fzedqD^+L7z7xEKX639yNA)?EX0%-FQ*WsVapp(5`pKD^o z1D4y6_eUvdqq7mkBiD>$ zTi>C5BkPDvM-CB*VV6k@bKqdsy#hptALx`61;4k5DYk@B9hfUdj%p$9FOpRS`D9cL z8CPcZ`%&g8q%h(Adw)q_H7FeaX|vYHblg5)DrRyg?M3vhGT)Jc}4k)sU$ynMH& zQ#Cs#`?DAoM}P*EY1I*GGh&Md@uHRp^F8E_S#7%Ym&C8Qq+;`MWP?2FHp+@?nVL+|VhT~ytG=lnvFCh6`87D`=pY^@B zyI934s6^WBaVM%YZUv0jm4&@n3L#85wK$+(41bGed1U>U;sma`W)5V(@$GM-MHo|(H&BZ!wH0ZO*_5$zK^7Rze)G2vQu=nuT|tD zPWJs8=3jEi8VPHFVrFFc8q{D7Cw>8Xw|QYn**=mAvK5Ury-U4V}a zi}Z_mlAOq$Q`Cv(-Wtk!`-ZMvkB^plbpAF{(j)ID&%--pCE1VUOWP?*JkDN=dLD-I zq^QzGV~1ZU>rNNqohhQcI#N{Kqp-uFEcsi*?5Cedz7*62^sn!@qf#66gN@GSnhJXT zBGyal5{x`*?l+vYa;UN|wg;>=Z*p%9BP4g;x@dkPY3KZzU{IpLqef%*9i6CN>OAy0 z-6!-ro}zawXB~y7zVb6SJw*#>A5T1@xl*IHzBpXkeV~W`NnP@_LBlU^b0`rAT;Da! z^K4Iw@kn3Ad>-mjIw2CYPTd)YHb8^jLM&5DjU^gyK}}DqUCEF4FRh4|3wJ5I@pR)^ zbbj%T(e5r6*0UHj;ljJ+uswPi$VU4P^r>e-pzs=M|q3|W}+<{m@kx06dZ zHexWhjaC-Fm~A45OM+f>^2tcfW7)a)1wit`r=y(p^!YTc8*F|Wl0OqT(SZtBeIJ}P zlIkhrw`SkpZO}BHuppm3kbKi}Q0nRqrx*1=5zMLJ1JcsMj3eNprwO!MMep{bwf`&J@q2lO1h1bfvKP0`Sxh2># zQ7Y-O?nGGVT6K~j=2=@7Hn0=NVVOErBQP3{S=~(Z@v}ciWssW@L=HRI#&mrf;%WMR z^OQS!6=&3=5!~>}Su0dibW&wD!Lhy{0QCg(=svwHy_eo$&WGQxb}pi*$2oATo-03F zebu4NeCUqi!Gn(P-uI0=TV|>yAY;$9n#KbGcp@!iEMC+vW#HBC9WZQuDx11dkma>} z#B6rM3Yyhwm&8T>tdh3BZ+`c)!aO4jyxz626kB)JTkL-v$TV47AC}1F@q%IF?$y>Z z)tu5bi7{$bYTt>t3i^@|!o`NNY|l23@ezgY_wrFHxfgY=%I=a=;puws1_!9zI+T`= zv%Ah|#uzx2hl|h5B8QKg(w2w5_HO4*$J3{o4ry?0cZD4@ubpL-60E3%?jyOI=Z8nL zC6e~^6I4<+5Mvf+GA!^pTNlfMmZXgk3Axk_ZjDZ()k>*||IPo!c%7=`Et2>_d=^9b z!t1n#EeT^zhSwW$uUEQf#>DW!gJx@+o-U1axmWi?n9DXgnAg)wEe%C$xe@pyp>VRL zLkyL|xR~Y71ou>oZ$5{?ai&&Hc!L6$n}|KQmR5_oIpRdxh^^v>r?n&-Op52B7E1)s9@1$8#k-xu+zpCTbqB4f?Sb;Hjz>re{4ztE5?~Hx0XriF@@mu$>BQUa?@7mF3&c&Gd{6SJF?- ztx4YBZ?^QD+kfTJ897Jm%^bU%n;$|griH7zA6Go~kEtn2h^C{PMq@K1Rp6E#k%f;_Y_2C$%q&9-+6KQ=1{Q?#PiE^1(QX9*I!lI2(`3-&`Tm3S zsFOW~f#^t^AMJXH+>6t~8d$U?wpo$sxPPV=Yms>s{ub|HhR+oJEn^U=vv$K07pe@} ziP8+~Y74F-L-N(V>AoeUgGWVl)8K!B39^Y2GN)J*Ssk&80mNpueMrE^GVCf-hoAs; z-Gi*xv#1q1rGWGa2;)QLmgiGp*1Q9#5sG;+n$Yr-=pjx^Cawvofii$HnUgYpO`oA2 zi$X>0M-a?f%~|N)-MH~u-6n)}RY|dAqKYP8+QhA0=Fm8rRbVYpBl_(&O+K&l{tLgM zC&EK~ZQ(^?TJ6qbOQDVTo;wUDcgL9fBMILG2;hyDPD*Y|83IsZ>TW zBjXqp@j)0tb?UKo-!oQ)R^4Buaz*KQ(OXg#6g~MkK&==eF)(1RZz1L14%Sd=YwMI| z7T{m&smLXVFvkw6_^HMzID80R0R3pQ6&PjeOB9Zli&F8Ht;tRzP^}V(^07HfS7@f7 z=P%Fu%$FF!e=B+UGj>H;NyfuLF?JVL3bwP1h?0p~y5qZbPjH6!Ue{~^)wbbh?YwN4KFbUXZh-b#VUrnni}sw4)bg?KHjQv&tmgA-tZe=68Eyd} zWVS$Ry^+U(HNC?Ess~6bqd7UjWRVJ6 z3SsXlNz!N$U#fViNj!~dq&u-YbR_wR27_4iWXl|`inzXm8fqAbHD{Yr%H*ME{2M1e)&Wb*&PH^L*kV5L|KLK*&zuRD5|NC%3==^QWExwy{{IUoN2BuRSkHM ziD10d!?d(jG&}3wbR{V>GYI2KnQ@8GI8re9L=HBqs%oKb5%R={XQJUL0ZFLY!G(m) zS5@85v?jDS-T6)x^sn%-<1jX-UkEM-z58XZyh3I7c4M&NlIJ&^fbsA2WypNxu_n49 zbXD@ER3(|@MVy*nr`S7Eb*DGfPf52n9~`!ZN)tm~we{w>RH&Ij9Rvp1pj2-zUD|O% z-t)2v?fz7l^geoHm0Y*qWq^dXJwO^Y7OS5p^aI$pH@p>SIviip5EdlAx5Ln&*U~A$ zSg_gs)U`)gZ=2ZE5kcSqa!KU=@uSRB_2K@aW%1l>|Jf72ts$F|UVjVmQZ@S0kl44< zdXow77{Xqdbeu~77_e=>6=6KtPqHkXrS4hB-6)uYr`{cMGD*9RRvM!*=8}^tf-SoY zjB-sjUZ)d7#Aq>_jRsrM=;vbVBop#AzkjEZFBXJ*GEjuA%u9OwCg!&a2~J&ig>|>L z&CXMvt#yqWwKiuSyWE-nO$^AChUbTGX$_D-lD@V(=JYL8GAI1EBGQLzBBQ2Fz~s@~ zJHPe%PU~+He=l-&{Hrdm{MPF$+rLS?@mrDqc8y#(+x67bbllMa``KYrG1w@;So&bX z+n5I#j7^1BTXDp=EH1%=GLUolvDxXxd;M8~BAUSxev;-@9 zWytvGH?3Xz@!N3l`d5#j8*{%&yz|?j^EmtUgV!QSH>E-)ce( z-D?(UWVr_q=U=F>rD3feSdA`+1MsjDHYzOL67-pjJ@pb;XZy^k0;qx0uu~~t=(z6Q zz#YS>u6l8#5mo_tUS=3~Dm6+M+Iw`PkP?qkakpIFxb$4=Bm8Y24&>w}@M8nxsr+z% za=mk|eDF-jcX~~B)Uyc?F|v;T!R^}bXtaGB<|r;X{{YraEd5VNc;>70-&z3mb*1rL zV*S3lo6Q>2Z57^IAF-T5X2l|Y3=)LXc23eN4b9drrr8M;)p1t)8S4$R6m9E{o^4jb zI;_o=)9%lICZHYHnVnQw!y{T-%GrFy$9|ZBIgNTu9+;Y#VT0C<-xU*CC|2&2zjWZ6 zuMOkLBae<2{uTF03?Eff-VFE5Ym5v+xR~{ z$p4uF|E2zl|BT>&fcIagT>3&4v{J@b+pOog&F@Jw!JdNp{fDSPu-sWiSx>!BUk6<6B%^ATilMTsjHi4bnRT)?A zXsn(1)Yc=}T#N04gZG&Gs=xfX&VN8_f0O0^{S5q9oA)mOBEicRr8n$~(=K+?caEYM z?JE)=SO{W6fpdGbMDC9eQEOBQ&`MF1GD8Qv(+Tk=zS@VusY))Ga=7ref#1 zn_Gxa>6Pplq4r@`7u7<~<}$UL_$DN)T+RZbfnZWciw4)gVPf>gnB8*$j9&FT)~pl| zIC#58-;Yg(GFf_~hHf}GVH!D9nQo%rRCHbXHvIKzRD^YHKM77#xqOub>~~kP35PO;1S^DOatr-FJ%$MGnSfs>2@b)AuE-CST8DGB|$E zl}TtN3g9jAE?*5w1l`3%pcUu71fRS&O&T^c5|(|;Hw(E&G2R9g>PPQz#w@WZWh>ic zRdx#WWvlsc%8dCRVW>zWwsjI1#L#mEhmPyU+@^skbRNkz$+nW|UM}Xvyh*yTDwtrI%U+v|}g`pjwQ!vfExBNRA@EIW1xB(5mLcapgi=I9A}zrfTvRZL*urz*kWN_p9*P{I2H{iGmnI8hj)x4twhKw6fa zr=^|z&VjmVoW*E3blSHl-q^6f_NI;=;e@^uJH<-D@ALyS9E zvopg5}xj_qRGAOL zzKDg8;RpV}F3FS3;1#QaF{m0o$P5CGe?vcMdS_yo{sC%$XEJd`WWZK{oC3r4{&M;y z{qLC&xRsIv(hAs68S}O)I?L<>RugnnSn))1aYFH>X7Lj*|6EA!uvG$*B=KqHFeTG7 zAV;)*(UbD(YP8{<5vB}dMzh?=*+u|7@7~n`|ACPEU|_0;IcVz1ZARfO z6pT3gJMq4CVY4PL4fQv4)8l*9_2!E+B9ZFO_hmAe`7W)Bmf;hKJ}<9x9N^NY8XFBI z#!pV4pH<%Dji-k^kDRHRu)Adv#B45?!A@Em1&+HcK$j)*bx{t{=!9fz@_SZ+w15<= z~JFswZubE}rBy zZ4N4Sx;p{cBr=*V-UKrjuwj!Qk}g6%4lQ=;@iUuzK12iw=?>fUk9#5pLtmq-PDG}+ zOa-ds*O@Cy=Tu|fu(DwK!qhWeNmEK<2So7s(43Ku$b7h<;cF=qUB-^Yo-SVn_WR?v zHCzf8$EBRKvQ`m5R?faJrgkq7y&^G`#LGk6rP-qtSVUy0$BMo-G*}Ct@2fyay}OLs zZF3tU2%4gU0c&=-m#S0x9~=h-ejD4=A6%1jw<3aIUTeX6Ac35Tkpa1zb{5v2asznx zQ)m}1N&swoJIJJ~QL~KiM7Xq6w!vk(f;O1fGh}rQs7e)Q>rCd6FrN}Uexc|tSL9m zgrf`seO91`juoV8fFVL}){!l_w}X|@HMJN{-ythAk9&-x{wcP-Y>-j8|MEyj6U%D=kPO`1tS;NkkqzxrkV4?g%Gza07BdSYZ_Ly+BUX)#_pZcpg=i@bhmwCHK;2cEmUE|s@Au3B7RrN2WTo z=QY&DyI;;evz!U87(e)x_rLDSJbnSDofLGquW6%Owb!uCXh~F?sxjEQOF(do_fO)8 z;N80wI;YouCh$^g5590i$Q?PiqLO_so_or8>zl%990SDR@%E(r%uU@twDU4>lwqZ1 zENr__aKD{GEyPj&*rq)5)I#aZR`$<{89-dvB7XUl6K)}q2~!;(Nd`oNoJ1B&w;X2kVesMI$U!S^nTKUS zDulFE+qmYelChmq>6%7<3|AqSpdDhppCdAl6&zYJNYbgvp)L@``@_H2kSI);{LH&QL=69p7WzY)k3V!SF+?*qrmOLmM|BLFoc)dEDAJt>7}}$?U z<>>v@EV?$Cd6#XvDWmjN2e1TkI01qS>Ao)qo|Q2XS@8I&bX%f(B=ga$gh}XZ*34K! zz70a~qfl3(bys*9ZcHc<8P6W?JOoXv86tCK@Ed7$At?-gbWLBJH?TTXq4zQMs_-P8 zD@}0?&rzP1F-UO{AS*?u9>1&r+{U$C-$!gvikm(0GVS{g)FakcODnaR+L!$_o*(FU zvjfB+OB%^i2rIQyCcbH{m6FXdLx<0OR{B{*Cau3HF=TZzGtK~+&}}%M#p&h35!~H# zRlh(HpcV;o!o!jX031F){quPFo7hlz9_o;g7@k@``9htIvB;W)$vmY@ZHS`W*O|^h zSBdce-TRvn5o@ikf+V+;X*N=e zU1KMvxJ1?K>wT>dv`rw7+v~HOFEx4Ji&^RyD1f}9iM$4}qdKd@-NK`Z=Ce_NU6pN) zU<|;%Z+EjVx-$nhp2PV{yxv|ce9oU+;X@cC$!lA6C6$Y?)b)SCg?tq zmsSgD)|0$5`b6qN&M3HycdNUFG=g=XDj`w#@+|ZYgv96*Tk>j_4wf|7ol(7rkgU(L zlob4m53RrY4Had1$CzyvfUrQtk>8?EN*zHgxiu3yFVQXXe%>vGlD%fu@OSBCO)S<2~oZ|0iA6pv~hLll@* z^4QfIL*H?6-$1NOM)8_aAW7Uk64i?39hHeY>TYR+@@kZGT&!el4%&H_leKeRc$=n2 zJm}vj%t2JnHn#6gtgu#96mdqQ_&&bkq4VI08j9Topen$s)RFCx3hmtBwd~B~=Yrqq zwc14bNsy**4If`4$qtMm8%tF7$9`rh8{G|VQ@pE|tq=~83Q&YNo5{H^PnHL?mWQ}m zx+mogLc~?uQuZCH5FiB<+f~7MqF6)7B8sX|?1$19Cj;IgMLB`AhL2oIO0}#lo7L(3 zbVNX^R-z&Gf#^5=C^R5GK0bHAw3xK!myvvP*upc189v<-BRTv)PYO6Tz0x-7w4J58 z-$J4G=b`?0E;sS6ZJo=q5p@HI)RIODfHiAI>A%yEzwr29l56)*a{u^M zAt4SoAWYoN9&*W(pbVbtQP1}`l!?-j0g$b5Bpe`A4nG-HGUa1rV2DEPRT&xCL%-G+zqiFtesPlF^^3!ChJ~l@ zk(ahBe(!nug-$cT-n~U$=(+vxoxU;pkb%baLeDRBhkwBc|H4OCJ=@`XOl?yuK-JM#K?L%ru|`rnA)8TJXR!}%KmBuotNImj z{kw40&c?G0f->)mcOMS|_KFDzERFv{-T%ptuDV@tytvGMF)TAKY86^}{*vI5?3Z7J zTnetLcU+x**MLuF#Q!^eiPhG?of9|R>cHU5Xh6ttapn1kw#n5npNWjCp98Z!s+c-R zi|{_eD#AF=5cAX`1$>&WU;b`nK^w=kpb%?KVg8o2Ee4i%p}RM$kBGD`+6Y&P?z@XZ7$AV+Bs zZ^6M<=CSSwZQCsEEIBKrVFD|ewhWqo2%0{MfZt-%fKQWBt))k-q(>xqmDG>}QaGI( zpTGhGt!RYLDl+xu^&%cb)&P3kO{q}vRFRBzwP2g>+l$^1z1V8*S05KB$(LvwZvc=t z9A{IN$+1NmQ(@Ps(fiei5h=~ewe1(c%Kk0k>~`5kWir#+mpr%FtXdA~hNViE9cJTs zm(u7u<=x9;Ca^Cf2YhI(R;n#jc9g~sWaQCt&zlV^>c&CKpXm?dzSt z&&a^(z{qe|F2(F<>&oZ^e+o3T-sLZzyY5VyL>PO_VDZ z6`%+twQ_k^R9CG9K+SNC5Ok+;txxdscZ$x(I)jf{pWwrAR_8Ez271?iV&~S<7_pK4 znLrAs6S=Z|AU-dT4ku3Nt`rWlGym~1J$Rd9KTZE`VAfmEiVDm185*?2ymw4_R_?Uj zXgnerM^PQW8lguh30GdF0HRvOCpyGCztE}6w5XplSokbgdzoTUw4(5U zlB<{$z{x+QF&Vg9obk+}wv3ZFi^UX8Nm?=&qOv^V-K+UC!H>&TKNIwSBgg{~WtvV4 zcdKkxWJ~M|M+n#xD%$ukf?b&drRTvCY%(ZrY2F5c;kBl5~N2k^wLG*9~c|2+f*@>V1MC+{y4pmXH zJdG)vw!FYG4U<(v_M85l@7$ zbG6a=4Uqd_2~I&~fCDo%aXfgOfm^RnAS%9S`qOk#voa(e!H+1F;Bnq$iEXq+RcE*; z3Q;?C)6`^}rqd^8rH_k@-#5J(@BX~gEMZZxmY17TXTD0CLQh7{=`iMQcMDV5ShNaD z+a8bu41pXu|d<$AL!9lLMlz_y6b`3iK_%47oA z(}&5Q%kE5e(cuweI)B-It7AB#>~wnMh&N+ix(oC#+i!cG^G1M)pT<;AEA4+Lf7yKN z|Cu1-ZH3(pbIF~V3-mXh^dC0aDPY#c@DgTbCJlv7BTM;yC-)v9B?s3C>S2We6I9D1zd-cL#N;+t)+;0XXq7D7nD8J@qGcOn_Oo@2$yHkqY`gFQ_CwF6*~@DQC9A#Vz&%B#~=&OGHOX0N@yEn`l@Fw;fIah9m4W$~Zy~McZGS3G%{b`I3 zZ=AoACLs?@5#Rqx;h6-XSIPNb$Qa~Pq;{se=rZtgfZqk$*R0>yv6w)?o!;ekr{^Qb zpkL;M3p7=x+`mQtTjBT-_wQl$e^}=KedDqwzHrn+C{1Gd@SL|>$Y9i{H_l;OJEJ** zFnbOCINGur>p#J+GaDTVuFfK*Bv$%igVUZ1(HyhdP;v+&AYgp>r>X6Cq@sTowdk+T zjQ{Be|IpO>pO*4>E8vfN+%u{Fo${PmnhgXg1L8O}UkaCH*&0`NXcc7uS=xf}3C6Gb zTtswY9H)ueGAA;(Dm5PwN2sQ2Jb+GGv2Z*0jRFu;8Vzr41O?Y5D-C6&CD%m9?{zNL zjUaa4Q9QW0J7ibR9@p*mX>jS%zn}bD2mc-i{{w8{;)x9ZkNu>LfQ8)`>p+(;YbQ*W z(;B0pUyDZfEk^URm91txYUhVm&RS%0^xzog#A!W;5(F+ds2(eY^>=#ucW1JHGyKoc Jz@?u@{}+m9n4kav literal 0 HcmV?d00001 diff --git a/packages/swing-store/docs/images/data-export-2a.jpg b/packages/swing-store/docs/images/data-export-2a.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b4dd268543d79950bed66f0cc2c2d2f52f6ca620 GIT binary patch literal 93211 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

)opi>1 zO`bLnRWHrF+$p~RuRO7^HfW}BR;xDfH!r7;U@wznO@Nb2d;xE@iu@g9bL&%W(=w$A zIIj++066y^NSjC)XzSR?_L8e}P{PB^BcXN+7)=^IDF5aB`+u+IuO)`rmBf>D=3m4| zM|Zh&q#sa;9rv`4$3HL7n3%-Xl=g9${AQ{h>HBxLZHB75{~_3(`LC}-Khr*CI?X7X zy=klelg9bsDksB}-&62F)qH=GhrRd@5&k=ecRHD~^f1sAsWHSJgM2^RXL=FK*5`=M z^*X1fySYY1<~LSTmuhW%ngH^LkEdZEp*S*8TCJ=nHH3Lrr)E03_u?g#s!7^OR)%n* zAECIxtWP(5Y?nn>Go{Cv`vEgEGrD+ZJDFK1I`(dARgS~^*uk7}D+(zaRl&Tx1L`3{ zEjqfOnpFtrC4QjPUc#fR-)=uuurzpF6uj8k0?>OwG3Ly{NX?CrqIbA*jQ2UtuUqX& zv8Gq_%!eM1U*qk`l0Jc%e=LVRu0yUrIn)W$bxNL?N(7191udDDX;T_;_>t_$*UCr( zg)Mx|=~LmbZ#K=}RM+`sI^=!)_a>WRo;*|J|XK}oVOS^{DUz%gex8*>pkgn zHN27fqSAGNKndo{Z_Y`LJZ}las~C2OSTYOr!;R%iL8#Mdq>WBafGzE0!h4v|WWrz} z;y?c$yga{6R+6u$*|E|7P&E26!1%m!Y_Li@7cLlFgab^SJW|@;DITlNQ;}s|g4pDx zdDJg&+PK`sr9k0vl~zUb7lX{cNl`-+jo^poc1<9 z!HIgj?8*V1qJ96QA!kSZz;^ZjEjV3$pZmOL@ULc-|%N za7|1Lnhf`3?9$4MW`5$hH6^J=T3xJVLQ-0I@Qi7I5}C$ySDy>jrF9`JV}z}`hE0Bd z7us2cJ`dT6AzevnJ)XqYhMT=`0Y0=njN=jE3qQkgZ(@)x&CSa6C9Us? zL2QPk>zajKf0zY&WQH%JO#7t)9zEFOt9YTFL=)KFFeL)O%$&?5n0iGvZJRhH6A}a_XCQ2q;%aY&dXqWaJ=FSE`8NbQQvDT z5Qp(ZG3n6;2(4$1^VklFWf;x$q$c=;H~3(S`1xgUUnVt%4}hcGs0#*ZUI;=Om3^1S z>3z@9W~CTQFyyO)e~_ZCN)t5ERQh_N+U2VHBdg}0VK-^m?^1usbMc)X4jrLa8?D=X z;A>tHI)PR-kGhu2bCgFmfJv#g)t(BiA$fJr0;3-l(FW7VZqE~LM(fIL*8%k?z|fz6bvm~kV# z+B2>FWuOABJt}^B(sc*r#F*E`V>~kfkcAk-7phHw%Eu<({~UFMZ?(Et`1|MuPi2wH~sLi)Qcf~z>M!-tHB z^kQ!CyQV_pvi*GzX&xmR%Bj0mt2vREO$>^bUPOtMLOwmye|U<>-Vcv%u=ZFrv8-Mv z33uI-UI?4-x;T5!9ojGEwH>9sJBY63D*UG3yM|KUTTdl<$0Fxsye;?C_WjuwU;BwE z_4Os5z$sr=mf^x4w1cw`2Ib6WihJDhJPjeax-Pjhl$oWHEcVunJH6fWE>Um(ZHeR9 zH|B`jk#`gECk>(VGTB1$RPdUI)4|~vdFkOjC-M5)V_S?|8dv%UwQeEGT3=`s^VPTk zQCvZx6$Lf|8E(e0w@cyxyX4Te_n+85s6)9ds+0og_{mz1FHupepl%j?OZ`jDL?YZD zBvDjKl6V99{LEA26oo$>u?e=mL*MN3i}mwpwAMG7J_^a6cJ_Sz!4t=JA?qnWlfDmu z(@~aT9*Slmh2P>ya4V}`Xqtu^;9Z|R;0+l_RaPp#~CjqBIoyWb6pmN^x2&XmuCkcio+4^|%{OlwM%tV^qqns~Xb zIW7d1H>}e$q|QMih53>7PK|!pl;0~Sna=g~kR#n7R$|+rSBD zcex2Bx1Ei#s%ELOgL1`2GbPO?7Gj<5q;uCqF6{()v~Xqw47EX6rN7DT$W<=v@H{qi z;qnZQYn#amE(u(1SY&8G7-p%D7D`bX_F|-a7vyG3UGk3ph{7iQtdL{$iLn~ign3MYp$_=kd*u^;s^%&L>AaROskD*B*G8cwipm)4UtTmy$=A}jn5W_ zZA?)pO&CyGS_;T74P<56S@ATTjp!4= zxrih%k6WlG9q8|{Jo6u^gQ@X>3xV*A?1mOs)bq_1#8??ttn2;EE6lmuR%}C(WUHGopVp z{z_|K#m!NeG5-2$Zbw0SRCU&`KWR8?r}GCsa;+$h?;V zktbfh8Z)zqdV)@KtpaoV{rrgkMd~K=Wwn(yruDk4o_*gv9oRI!WgvQw*&eMPSXixT z>D6AA$P-l;WmGqYSgOc!FG#}Ss{B$dJWDzKFZ9L6eJ!M#q_4mo%R~%jkl#(4xDjEa zp+#7kvF;bOmYRbRg0kI~&#y3TPV8@Ugfvwq&$bgNG>HaMof`Q*b_vhuAwk>MoTlQlZCi+|4F5{=66u_L$LP zIS*jtpq);H#zkg;kX9@?2%UJ8R)-0NGs>k2e1PUHrc& z{eL;yID=CzwdizWt1ap1`<>U9?WY=+1x^ir}YDY2Q=Cf0mM0*)fHs-US5 zm|A5|Tra4kbkAp=$|e;Bn0E)`T549cCFKyV5lvEfT{knG6xqxl-#i;NJ1RyPUgDFv z8Wz*{7i}P+LuGa;%)9nx)jFXJ;3PvwmBUh6P@`KQ7XrP9V}2RJ(MgCtxfPmW&VFNl zW#q9#=cj;ik@Qpkvcel`K9qj446?KzN(I0%g+8$1qb!{^CtdA5;BA&nU(s}OOpzk+sUajA=&^puNYQ(4e&| zrGD<=-aC$?@+SpXKl|3CwY^;_l1uAtcqN9oRbJQ9utZ?9;@f^NE$^u0!QHl3MF;0r z{bu*GL;S`aV{)BSNQ+J^PhX!zrRrzFUlm~p%wawvI6gSG_JZ^TJEVxV9r$Q@p{o;0h92+8N|!E93G>sm^UHUvX-qi?#<_5*C)Y4u-TMLtAOmV1n6k(a6uP1UM9DMP&a zsItMSXFvwmbAN3=$M0yoD{jQFZBa%4^>djz(erz`xOOaOFI~J|%nzB!X>}sp)_Y>Q z3Iz?xO4I-fq_;3kcD3PFoi6)bGU`4pYtD)dfQ<^P^ik58!Carl5dfdk0kQV?sd$fM zG!m*+2YqHaSgf~TtJq~87}a}{N^b`MEQl(i`a@oUON~>1RH!c!Sw2h|LQ4yE+WBBV z?tE-4UK`v=cJ6XiY2T7P7`03YX_%8vO>q|blO{ZS8hF&e!Uq4eqDBt4-#*@tXL{Et z3?h%Cii=2~m!a$t*W7I)uvnBe?TGNYaWdzIR4KL+-e2uiPTWTb=ygo(KU^5w`aFOc zgjq*BSV6)ia$!3un8jz}--~;C22*yOt~T}L^kY_{nvlTy$P6^VM^A+vZxHaFe@cD0 z(MAoh&s>({XZY~`&vyk=E+L~nyjMK?ccUOud=_rWYcdV#`CiXt1^P+F6{fhLxVScr z3^MB6tY!TB)^x792iLV!i{Yh|t0M}{(%h5T!4MVMd9->gVw~O*ZMA87ap2uA1i4HF zJo3J*r&%mbwbV+}qEP=C5wM5gN^%Q+t`cA@kOZaXWzp9vm2G^a>3GnsuL~&X=SpMK zrDJzfNpWn@d@Ket`jh6g2lm7Fd7ogQQ`p(v?jKCXm1s-2Y2O1CIwcU-qVg;Z?1XNT zv$b|Vfvj6AC2v~Ma;REbRIK_jLEp{L^f>d^ z#W>Kao!UO$)soB9o;hhyPrCdoVagP(%Bj&&VqZFnC4<4H*UqfevVmdn+eP^TqFC&3 z++m`+xZqpeAH+K8UTzM)MX!5af*%V@l1LC4Q`5|;wOOBWu}-awBDxv)s5MO5{@nU- zc<1X-DA{oG`3*%eZ}h37nLRE3j^iXNv~dX!Pu2?vQ-a_DRaGIfp4N~_+vj6yykF5y zs=_9F(4D?Rf$?QC&L&`=FQ7N+L3KXxdg`tHz&RCteV%C?d#hl!7#3)pI0(J@wb6z$ z>A4>CfIa;LvpR0%C8m0tM0E_X9^yuZ1obLq#A*!d0l0ddpGZho1ZBjqt&h7eF5F)d zDpG2ijeb9;TkWY-#~-l9p30S05>fwloRC=w^}Ke^%7v}7R3wPzTt(8qeC+*>`MTX4 zXs4ziYH{G*vUn4IM&CfHJzvOHFDpoR!KF9a{+8Z*KyT@@YWC2~h;Qe~QpEod^xVJa zRZMjKcQp9EB-JeFw|rWF3%!s9>3ctJ$ZvRewLkq2A^y)f?EXhQk-_aB(8j;DqeA(g zqlo9JRQrDlJNl0FelSt3Hv&F60Zrp z{4&*kr6ctPLc=ca7?aEPWkt=u&(b4a;U$(5MQlcMR(K^QJe*>t33OF9j1c(4&IU44 zw2{6G?gOPdI0E`IiMBCpGwZrT0l{{1qt%{FoQ3B5N@ zK1+>xDXHbN6wqh0tr6xLx0++ZMnvl;qn(>druQg4iO9;J0r`es4V@yqarooa70uIC z;bXvY!NEWu<_FnqU-|%AMH4?Z6WFcyFF*Fm8>k(FJZ@<*zM~k^9{IQ|%+I&*u^(F) z!%yRiyWFMq9{zpy)n2BCgN`)?`Q^Meb7lECo%R}cOwq#^H@0VQNM&qgr(OG&S+VZ2 z88s;{EVw3VF+4QR)o`Zuk=+0F6(_EcJyzs84#$lN63in2?AndMfCiigUR4Dz7J&zy z^q}Ye?OT#=x~OPX-4_NcH&C%O+GPDEBbc9n8k4KSS|Qyv(44?P{JR3gO+ zvU_q`4D#AASFoa=1)w#+R1QQ~9ec`%j#UUF9d#)z>8T$_%C;~WBy5VIGzw){7X6C# z)<9wwE&Z=;h|%r`#ie~>4lBn}CoO09+^> zE{tG9%4u;{QV8$Nen~Ou#IHTau-TLI%KP(2W;&9a{?qy}j99U1$AD03l(i)bwixIC z7md-W(|0bw+rM_v|6=!lilXJWCY*PS>vp)Exw>k5&F3){4#P8i|5p3_*3nvoc{_OIrPr%KBKux5 zr(RZo=wdrwbu|7x=o&_?F;_oB0iqf9xyvdl=v+dlvRy|dYh(7SJ=GPjD4jqA9}vFO zw#U5%Pfhh`h!DZ>X;)`?Gv5v^0Nf5h&iIr7xDwT8@P@D_gxUg{+M5bX*8taZsH)j+q-3;1mTFVKkN?z~!(~WaOaiGei z6q$xJ5q-P>aZG(O;i=M1UZ$ScJ9^qgw@G56b)rSVc-C40*$F`<6OD$lY8K;!;^KvY zQq+x~@B81r?ElXGqVhlF5_U59J<;&fzec`b`7bjFgS`HE(&6VN8GJAumf9(rhz_jAIP$ zuu+B~?#Au|Lc0hCDVJqI2upNaKVm-YqK%GkK)}tvw*UXx-GO+uku35OuYU??q!i1*f%2?c z1VNK^$`Q@ayHG$NDNeIf`Ht@@XTr$cN4+++({9=8Zu@(TJdoYic-e zDV87_nw9EGYTB9pyvh1qx`JBsHsove#2aD|)bWg(*nnQFW-?0(X_p3Mq zRW$ih&Srl_NZ~ad5RSi_m1Wbd`$zS)6KH(RLx)ANJ6ov|3e{~d$TEk@{6%jg7Pf6_W1CfS#X2^F*@ zB`Q>MzUI$r?~2X$1nqJaN_I4{C!r@A!77xG}ICes~ zC>`qsQW0Gm8`2=@L4sA4Rw<7sJGK5d-6ExRYn*>A z3+|bc-Tsp%81;BH<7!d2?q+H_w_rL}Jx3sYq&SWoJyfbLt;!2{8g=WrOkkkYBA$v= zP`ECj*mSReU(L-^bl5DR|gEdxk&`&Q`c&dOvwYb>b&Y!=lRLR)I z#jdV&42R73und;jc90$DG`pqanN z)^bx>_-wYb8LffLm^frqpxISJ!0<&p+SrF5$gg^?WO@0E_{%$5_Q%Dw=05~(c~NTg zUrA!$=q4(as$)CF;~u<7H<~EsPE^LKMln#+4r!61C$tW`&Q34z_zE2rMNIt>Q}<XWJLy~}exg3EMe?z@1gX9-^73%1jnCMN4v*T>*wtuU zk{d12*6_7)LaSp?k-cy?YXK-;C@#^(0Hm<`=v_VAFU?8SXJ0BpQx)XV2yd*HbT7U; z*>|#B>SlN5BCT#LZ7%abqe~~ZmtSPPm|S#{_F?haq5I-0Cbh2^>^f=XNGIwH!H9do zSsl^p*&64eO{Uf7Q`yTGL)_{dFSWE7zRXkUP>qV>^m}9oGgM#uyDB&o9!>9VQ7y_RJ6lg5WMTuFa9Q z-yrZy>A72W(=W?#VWcP?M|wj_sTy9YWb>L046<>aYFf}hfIhkyc3FVgRZ~;#!Pkwf zHbL?Vm+9%9TyYik+|q}m!eV$rG8TnQ!-3%N;VK1)u+$z;)Z5TX%RyDv`*~8vU!GhY z^pp%h3vb0#wG5S3qoL~6 zYXYg^XYs8#2N3A1CJ${S@co?fVpf`(`BT*=U5h~ zdbZD@%i+r;+n01Zsi|)$ifii8S3BGdW>dd=K9N7V`3YFcz^FkM2#l;M&eH4Y=?-0C ziQ55~Z>46sz)hVZy@SKQUF;ehk{#HnudVNJ(U+MQvIkjfX|_l%_JpHMXKsYhIlds1 z$0|~?R0YRAzWj7d6UXoJhj0C>JM60t!~3v+?ltrhiReG)is!h_4APq>y`}iPEa) z$c6n&E-kSK)oN!P^3Y6heR!?fR78Ry)@fQ)%SmaE$HdBhH?K!gx=a%PA zZ?D>~T)U%J_VlHN`2(@r^5PBK-4>OPO2ovA_#|VJzA?%gIm5%cbUo=U1!Bzy>^%?5 z`FIwiAa+;ojdzK;!>5`bWVLj9={34t)|O?UJhNP{iZqU@^btn?0-u9*s z@6;U^`v>_VDco8_CS%+MSeNQrG@|tIbb5>6c4)|1AG8%SB^^HDFd^Amq30M6S_Wm- z1HU8i?au|TrcVi!O%xL#=B=(NKxwHBw)R(jeBnV6UZy*J7tbtKeb69igs?_*HD%ej z;H>oNfFtART!wxOhxT21{qU(8q?2>30m(+S{Q9PfW~z?ti`jtEt3~h`pG%!0u=Gg# z7d_;-xcUCrRKqisv(K;YRJ61X$UWvI@19HWtZS;caxGS^go}2-tf0t5cAJ@n+8y~- zbzl!_&PiN`+f~*Fijf585DVR)P*TD*(J7w?ALojvI_;Y`;tagT^3BTBJ(pQVF%_AS zvwp}U0G`gjf6lxwRs(nj+`VGh(H8~p-^=us&u?={!}l19{Sa8x;rN|6#znUc-R zJ@4|?2JXD%J|QObeMRXN<7|lO`Ef1+cX&DzU(=vp3Er(PHv#NYk`pkd#kw>4b6h^K;$R^t&`rWivK(`rDaJuDZfcx}N* zZ;X)oj_a=grb545k_wWv#3L3>1;j6O=q2cCCIq1HLS%9>h^nbEkb7OI1_D2qiQS9f z#7A&;YX$yzpBY1+B(YW^gdsu(SX9ap9V;2Q891v~lI1!S(}+{^XF=F+x=`&X zTu5&%CL}M>Oy&XD>29^EIcEDiB6gp9w!1EU7q*$2%$b>4B_|VWt0U^Gd$uHpWT*Tx z`X|WspAQ9ZeOPWne9*r>t@$*PGGn^5if6&xLGq6agkJ9Sj5zvGdYWUn-`M?bMWeCk zW6=21iBKYe!2)$hKLBRli@%~9J&ogy-Z$Pmb8{ltx+CJXBADV?BsCn*>ET8Bo*4|u>5S>;D!45HPSW9;%FHXE z&g(abjK*T+M8#gQu^AxP3Xz>Ci3N(E*9U#iRtv&b(Rd%_=QhkKj&__Jv;7fTGE>K= zmoUKS9bBIJo!3$QdQ$Xim7E@RFeg3fTqHew#J1hvg>-9)bZq^3o2mN5WRqoy&#jpc ztk|=L>EL(Q;+Ytddt|pd8a84nDZNKr$nPBwqbrn{rzv~529aYQuHlMEjGSQm5dCcf zZta_2pan0)VvFDyddfr{KfhQV^xcQ#fJvPM=02p7_ z7@QRjr63r^kM`B{VQq@*P{X}Mg4+W{H~;r@4_IwH;;BWwZh9nRNFFVv;@-9Ok1OR~bUuJLRHW*dl+`<3 zSG>yOEbP$5&=_0~&GOh-+zX1JTPB-k({t2*I*ZHaJJxz-Y5d-^6AiNoHth5n(2X1& zj@0@2(c|^oYaj1R4@Cr>36_sy6A9UD-YvEC{91~D9Irp{XV6h-hNXl(sZRfz{MKHomRF1X7mzq{$Jd^cTm$|-0g`Cr7GQ^pg<@A zf>J^U1wtSRMM7u^pmY)l(p8Em(mNrc_a3T3sER1P*U-TNf^-D|v4ETR{&C-#-Mw?~ z?B2bzyO~UeNoK+%lixhgbI$pGPMznWXd}YntVz*>=FLJGk*c1cjn%~S51TgpO4@AR zTH&q$VNDyZWQ}4x9_sg|NE`VU6PNiFB4V;hq@fb-T_3=zJnP(YLjUD$CuC4F`)eTh z&&7rE$b=OcpE#i|3WkC}BIjldugUMxMQ-07X5O=Q1UH^tjN|Wc)#$~pgU7%Z!9fQR zvqmHH#9U@Sv4A|StF;z)K&6*E@bP??x3?;OSDAslHob3}%xa&O`Baw#kNobNI&vg% znv*!A#bB^%q}I_7dK7A-h5L1BzxiaH@Ys@8<{a6{-wK~|ZFI14_{0M(?8KR|$mJ{F$ zOw+outD@~`LH~w!udnoQVWV4}KfmcDONJ7zZ3cs$lx1PA%E*-AiV$PDfBPou=-9}M z(WmGv6ft%45$wLKWQxw?2?FhU%!e36D{HiK*p2SO&u(E*(ij`$}y{Q zs6nG)*%Nxji5BG|eP1AQvRq?#3nX~KUcGounPQj~nZ{DF3%^%cO?a41t4%N*Fl5a!|L8@ynYw9GtEJenQWwtmB`bVI z*6BwrIv|;R-6%}}kI2q{%{?q$u>Gc(T6n@p&R|zdu}$XBNEwttvK7dnKT-yRCVwG! ze=dmJNwh1bH}6QSjM%?yl2NRai9=R{6E+})7gQyg=IW=3A}A~Op{Rp-qY9G}Ci){7 ziCOHGtl_`C1z~x?=*3HZh(wtRRyDg*SVZnL&OwO2GP#HNJDzb~N~>aw8s4RyFTXjz zrC?J9z-5_b`fy3L7^nhbY%GWyb`ZwjAak4r%q@oAIvI4sHpRbIooHDfmqZ7oFvm+? zkBBBH&!uMa8!v8%>;X8^IL~}}`EBbC*N#44cliBSt3vd`R}o}_OI`J4U0~mV0!0jl zKtz$~-S)zAS43w9*q)mUtcJ{46qr$b+(i)F2tr9k)kX#%gyVc$N#$Fx|B-&Isl2d= zEStC8aJf~}n$jn^O_V5#fY_bVV9yZjSa=F`N$c#XbBg! zTeuO2GB{m$FibC~pVLG(A_?SO#9 zNV40oYQ0HtilMQFEzz~3|DGf30RzRsxb^myU+qOIYQODE@Jv7mUFO` zw&5Q+nrd2k^LBmYFB%T9;RoJ&wlmgld4H#_X0@A%O++_T7gN~fprxcDh~lPVN-b=H zx^bpvh1eaZS7OJ0-C|Fsh0(f?_W)uL92J)Gq$@euHKz!;)!XB!ig2&bGm2H8H`Nm* zsk>Sr6p4BTr}0qvoc8m74gWEm^ZA;8-pq1U{k_-*DWqx(vHQBR!S#a1fUcN`hYVxc zPY{b}2It9ydsn>>z<}9XI@#0)ZaQsZMGFrAMv)oT+}mtpbpnCi!ZN zidnV3zrmu?5V&x`cd#xGBjJ|W!AX8wI$_*{8EP(HFqIUR-@B#rNjLxgVBtoSdsaa3 zod2}_MEOCZ5wxFZ4OAR-T9H3d<>2t5$75+jQKpo?70R|Pa;x*{x>06Z0oj`iX;$`J zu1-wG0(Bx*>nUKKBOR@ECko%)uPRo1oI&n9uXga(P3e)3Xk=AWr_NkwHGRyz_Nde! z_{k-0<1P(zv5@Z}?9vtHH|C$HH<3@p*J2*x#NWe3IlkZKwP2{<1O4;Ew z=!+YLt|QDN>?ab3Bd*4DdfC@4NY{lD8W-r3aB$u*qVOlEZl~67h7os0<3BRqv9{@o z8;`*C(S|iS&XeG1GT$k!@1ksf8ez&y{)(5eqLRCh%GB=^+AL!cgp+NC z8A>#I3ry}Ih}oP+$XwSqygE8?F+5!_O5U@SE$fL*lZ|peX8{T~FItkxS!XmELB2%~ zAi}~xsyFnB`}JY{@1@VyzucQCLB#?W51EhQFToNlGlTrdJ9- z8+PKX8^Plm9nRPB3rt93b*Boe1(A7e+I>7y8%`&A)3e|~qaa?V%j~y18p61d{-15| z8>I^5X-pKZOebb*fnCUWt9z=T>59Ja=SG;zm>$OGVY;d!WOozdZ$(`}-#yZXs$xU?QGgy^R;~&G7rtH$wOBT0|!{s*!&z9xta|Vz{sk{%iW>um# zQ!9dnKbqmtwCr;}S%lnmCBuLpn4b$6xB6bK(KWuk(g*Fwtj1r_;k5(pFEn|A;)_l= zUZLe#jwf&5|H~-;qvEdWsrf@j$%g~$cVHx7w(@`nMn+wnT0HHkIru9Nq@JQzBmWcjNx)O%eBJGg6j9>8$tqySr63u26`! zmG@FN562}?kg+!~I{SDx48zgb4%i#h%5Bb^0DG8coh>`x(lA3|lQDn4F_QUtF#cm; z+m`;u=|{2v2j-%`}= zyVY82qnhu;O;@sEd8dT#Ah;+TxeG@SjH?iyo)*m`{zcRQpoPJ%Q zctsH6e1}6^zj+S5TsH0oe{LKz4ua1rh>GPD&P`#@hloF@TZlf0got}aU|!jO5roPU=o z=~~i`7z^ryQ+e{j+#DvY(06|90H@ceH+kq$87U9Y?iys;TH&{d_J^#P847zDKZ_da z_Hu*sr+fs%PciR;7groKftW|70uR=%FOjyuTl>iJG#_J}lmTq47?>1ar$9_}Kh(@IJP*q; z)ER&1^h42{Jg!%%JA9B8lbSJ9Q_W1#)>i4ua(pOS1W|_;8I6nYD9FnQ+xDpQbZkE^ z5FY7@Q8R7Hp~zk*?BcC;Zv=QK)P0L;z0`LIU&kb`YZrdxuCnig_)k#gmFrc1bjGaO zRcKdNeEvZ!D$%VO6kqrr2ylMc^*oM17sX< zHfRd)Sx<+;C1}u;Nu8NU!Drm{vgv;krZwFuk1fI_B@1`4R_O=x=uj<~eg2P8KL6%G zu_Cdtx$?eI7idP_Sy}LdX)cFpfsv{u<@$7hMaxiebC@ZDPhRkPb>V&0xvfGfFcS$C z2~B(!S2K;99kr$gU{Zu4}CTrCQ*kFcrW z3;*M-Uu6!c7`5a4pv_rGU{iE8iiY!@GdX@^&oKy@$+n)J9hJStzffOJWiskY^At{9 ztOz$k9e8F6Pcdm@2>Q$9n|}_rnrZ`u_X)=mQ+IkcL;4(pMi7Ig@k$qJq%L_ZO2;Qs##ao87vsj|S{ji(!FpC-eK8J!*B<;mHR8 zw*z?k72b9cnF6VTEw#!6~JwKX&Sj zs$z>%MhLhSIblsk(dYZSc#RgXd!^W)juNIgh~gij0WK^BcTn3lD@V6{e^%0HPIlcCRiGXv@y&jrch&|Rw znNvFVbHchE7eC3Lg$V~VPONN^CTtbQT!BObQgPa2Oq#%@F0bfcx;3lQ&pqu=ExZDn zTneLkHs35f4a$9*C)#+=4WmCp0c@8+Q~G^O#~M>6Y=Z*315%Z|3AJ2q3P*Nm$wB&| z{Wi?dXUGiIK?{|a2T~0AqvA#lt05YYGl$!Qw^TA-)ZrdiOWhv&yaIV#ZCG>8B4qTl%Y7y0rkF>w~yxyYIQ)ER*XyUE?Njp3Q<;>Ja6xOs~!fd=G)#_MVKp8Wp=w z_8HHvFu~V!8a!dkyt4UcC&xI^M>9p6RNH4F(IBU(ciwIp_PA0helKu^@ENzjjc?r` zZQ*CK4mAixjwIMVRiox$0#hw1Z=q6992Mo0x|-tnc@!jbW6s}j23sqf1y9dRnF`1l z3C@Ulu7PlK@1qJ63SyHl{C!&QgsvL_rpk+%1af_|RW5mUQ9Khx^16|Yeh2n}VIDHci z!BS|%&;-2#%n_=Y04iYj&i{PYoM^(6C4{-rYG}@yc%pAK_v$;Yt2V_aB=v!+`}MA~ z-PTeKulQOxc>I22xdiQ)=aDj$JC0g_JvmWgRNP;v@Y{Pg&LjUE;__&PiA}`O3stKB z7?|#?HEW7XTn-gI`Ar?&G`XwyCMo3k*2h)Jr!ix13&Xv&PA}GmkSM>Uw13BAg6z^v zNzWK$^8b5##Q&E>ZP?`jRp+{`#a@5^%$XIp(+eXTIsN3s>)cYFOYxA1jV4;uIp4ps z{f^P&OOX<9Dwcqc!2FQRIC3(dq3G}OeR=n!r==;avDDm96e04JcX?thdp@a7qvkxm zSs9*Xz}AbM2#ybbWDxUZ-bsBEC1|K|bX6?6OVJVW1O$=7bscb|=E}}}ys8y$nO?fs zC9T|8qhzJ0I60+?l@q|JW~_%-ixsDq1~b}--FbbD>3b(@(*EslmkA3GTlJ$4Q5)4T zY?saX1|cAReJ|tLXe(hyM?QxY4n*<2TXUR}vXa3gO;{~`qPLZ2|9QNr%ZTb+ zrv4E+hqYN^@a4!`zwfU(Z##eLP-iM1db4HLT)GPX9jtNswRF-FWt;RP7Qo{*Vk7?HHN=Bt-{Qc~WvzB}Ow*(7$U^_?6G zzkP~QIxz44+60cpj}-Pc?pzDV&?$y4>^|n6jqiyYnIFc_;_859W*`K8#6i=kyryq{Y@2LUbr5D0gcnd41ROCI)u5?*gjAw;!QhMW?v>=4oCcQrV&akXjmgtp<^;{f_NgW`nMgl@8)_V125Cv=%rs_xn6Vs*>56b*yYdLAEZ5fkDEQ=Etw)I+*&in7@dSbFYG zZRPLq)KfHnkC1)nhf=H(fg@tJ{D&0g8sT2LW40WePQLtWcJn|)ZpIXRVYidjp;O(Z z#IX8v_#A)x*&M0n;&y>1PLjq;^7f+*qqfb7fYg#+BckliThBrESE?)uL(o^{7C_fc z$jc?vITV}>aK&p?#f>>zLyRKmR~x%Dt6YhSPUoOvyvN-qlS$hFjtY7@H5r`#)B3{m z=FxC`KrX!&7z@VU_Lz(fAvRnfH*2^^RoI;~F{(fT@Fsm%> z+kZ{^`M+f`H%{4xo6uJrdDDq z)1(z2?k~k44d!{A0U-Z$NkVR=7oNxSL~H*a1LEb!!Ut3DUia))cB=-r>lRHqa%88O zz8smJ!~shrQGp%bM)Om4G003>!#9lD^x=w!sT8S&|Jut6*=xj(p+uCtcHe}v-dKR= z^{KSySEVB5Pb)3cO>kpnsnaPpCoJ(=oXr5P;+#4#>!7v<13Fhf{ae@jtu^UV^U0wl z=Y{xcRS>g86+J{xhotX2u5@n6wo?sG^R@S|{!V$$g>L5I6j(uFiKwZwSk{^HZZU1@ z{F4rXXk-0YgUO~#nf_nb*$_Ky!*BA;!#M?JCyzR3KYo&`oAf}Yb9IqYjyBu_U!$>? zCwNoYdj7GjeO|w0-uSeTddz+9Z23N(J69@)kWX_w8n6_EhcIVZ>ZIunRP^~0QL$>4 z=loG`Wj!irF=kKGWTI_Kq2-fhbS77#YhVjzQG({jIe`o3LGXG=f|7cWX=7Wv3c*~5!`)-S%FA8<)Y+x|fWX+B_IA>xp zF+&o5BPe1KE)hkOv0kiLEiF*qM1AM)v<{b^F5zL6gX1;D@bH__un+(f=ZlB;z!-x7 zwpTi36QE?SSAyJ^`V#)5gk=5_k$7_coD#up?t}5)75nq<#-&Cufn~=?@s7%#h=zhX zCE5>3VX&biy&cX-NVPTw4Ik?xyOsYs8dx3n!ycKHMR`nb{*+!nIHqG!D)hr&M5?V*mm=D}ce`kzk{z*{{#cfKr#lr*Y%m{I)J zuU3ZoR9ku=t6|<)+U$-(nfXC+e+)rL!Z@fNLewW(8{1rRmGnIAFkGyJJLLV4hq zR%H^+aPbs0ABBF(XgP0fWi-Inum@&>w&jXaaVy1YNttF#2`Z$n?B$vDQBw&rTEnnN zXf3W~r=gKVk*S!kL8dWEXXcpnvduUR6u`V@Qe7yN zZhpR!|L2C{5BW5Cy?GfOG*M_AX#GE3j1X{C>n| z52X*us}Q_QjLA~wf~03s05ahy+Bm3)Ajj_og}T($jl~_a(Ahyh!<6S&P2NbgeO?rY z8u%ISI_JP|8~@0jE~OU7O%1EOYml2;DJ`kheLUM}E`(x#{uF}_jL38oM}UpEyfLC_ z+Wk@@!gN?1zzeJw`mV!Twxd+Ex6_R=oFJUF5;O`^wwl<02^ul}ngtpxd3va%PdV zV!Nr00lBF;vZ{2ta-cy;zs-}`@$C2u&R;C<1uYA+29Hk%$tayEN$bLbW-e{*J;4k7vqCkl<@gga`)F4hMUh}*IqFPF9_$5VG`&G57 zMw<~L-ib5qLV4BB4MgKLIB(gCW(xNs?tcu|G_Uf#_5j>iS0-QKB)=cPk`YcZhjV&u zz$v`m^%?%K7~hCB<r)VqthzIm5C3T7MuXn+)l0|uk z*D#xmsy7xfLB0lCCWUW})dBZ3Snl&l)ZoDeomkpy(~B!;dIw@9%3!nm{i0C=*J}X+ zq1Q=_nw%Cmx<}`zpVSn?91suV*x$cF<}P8c+-{v|7N?R5I5)W)ZG)2ZC?eS?|HhEd zGsaN??RBhTziDRCCu#F~1Q6|Qh3vS)buM4(xN}dhA|A|=koo-#!`I1oVqZ@pUYuxO zO|EnMR2%+}L2Nl_Tw-QN4YQr!MsI+dlC0NFN}bqIq<155SOY^s9cuG&Qm7F;6GzZ7H_6na;}BT!vIu6sW;?*wzZ z-f}Wa{rcd}k`DD1s>Gy3;HgO6%BTnP7hQsc)y;{o5b9@%p<~wx&#W3$sG3&{7Ff zF4P4GCJ;po52T2528!<`G4teZ2ls1&?bx6c9=y$X2)J?bZkkaU9kMXfnDeBU7M2XD zZ>V&WpXtickE?!aDDfz`iM*{^_|YA1|B63>=oJktZtY}To)Rc2u|~N*m^bR*GaAVi z8k?Wa@&8wlf7~_|5@YSR?xNa+lM#k;l@Rf)< zq1|W(?mBAc%!>CP6TfRwFC#Ev*W&N89H4PA?`*LVF!-fgi>pXb?gY}gzSZ|@z#z9())MO zFvr5{BUX0+jcOq;27jZ^ghak8wL1)lwv>IKx(Po&`?(^2A{I>YQOvV?qU|zvPldv-{caqHU%d~8GFvW@xyDke>aJJ zgesk^L~o!2x-}Knxzeq1CXUoJt6*~RMB{WgM+qEd&^JNf$~eQ+72Aq%vj<_=Bb!(B zGt>em8!BlnR;Y&{1yG<1IAC(dp8RAK>&JlvHCSKp)MKY6xhtF80hrCf3RGqMJHNH- zQ|Bjgfcd0`x=jF1UvZ+EOdv)j+GOddkxV5CQ#g_&+fTXA^^T_)x&E$J-yFS9>={oBt7K;8Uf8x%E39;@Ri!VPszLuwP_TiNX|G!*& zN`Ki#bD!~u-?SR(R0noky{Z#GS&E5?I*6t*$5jMwMr(3?1H05w=^c@2E&KCwK!7W> zx=`*0pZsy9@#va@rSiq+x~gUF6QvbSwvG342!*2CCA|k2IGm6g?TD}vCwRE0wrx~& ze@S8ezQrYH6Y%Zx&KHTyfQ)jM51=!ppa z7lhsr#}B%axipmTWKG0d0?jlMnjh1qbadZ-LBJr z_R#T>sDAP2>N^g$;a&ap!n6aS;|Cu>5wO0624#^$UAKRn(luU7V~mvfbhYPVUX@LlP@|p5-lRu?~#ZjXxvZu0<)7;orqno;Q60A#H z*Tfvn7fS0gzA3^HOe{(8uiQB#Ayt0rI7lY+rT|^J`Xu{-SXw zd?~d-+$@m?QSED&$3Sw-(3pkJdtr@o)a>UA6bqMh=0yZl*#V;e?2x zXee^INFmuhW68tB&AHmwiTBVxmZRTz@=r|hieZ`AHP!*bL#YFyI?U*@R&@1W$&O!W z453M!ZO4VejRR#EK3f%3Ez(ZP@%2lMzXq;qBo`8)LB@$3G!O`5$N~pRf?4S`6F2Ew z7V)`(!4nBZ(iKcKJa+7Q;IeT<7R$a%vaC z?@VV5JnK63)5oR*2!n@`tM>FPKtmd51HZP@E7=%nU**XS^9dVR^thC$YaxBM3+zYp z<6+f!iT{a~+N^X~_~C(Y`!9lqgN#ueUCJNrEvVU^s@w#@|ZO=>%!W z`J3w6B%pFxOxtcMA0iv-2XrJ81rRAzXbFd4=H4A&Z|T)a8Lvg;&;#~sjmwwO)x1?_ zE6s2 z_gv#rBvqvQn~*3GuxUYtD@L$bese`7A|8}&kGY)o6cqz@FT%|J0#q3Mm?OLny{5OA zcmq~T#bnWY%P9Osrka<8`4VzaW#%_!(Z$B`s@%m~Rq(h?8yxM1Hj$b^j5?X1kGkI} zw0%dn)<^D_abO_1TZPJNix%m z*eIow>NCG~Xg3NbD*Exvv~Xf{Tdq5eu!(UmpL#bG)kmEeVOU#_PdwxPqt|{&e2Tw! zh6DAq=%&u$Y7$`4)Dc?@b{ZbJmt=E-)^re@rx14o4DawN*k6Svr8Xd3frBQuHVl*nvGZAd* z@cgGuzwhToE9!nrdZfVSBjp#70FES_u^drLIv$gm>V_Fc$ZPUPqZwe2&C>oTUAiUp z`?wKrmLdO&ztjv<gPuv(x00bRm)7CwrqxrrjGy*5fhIUZTmKG6Jf7bqgP=ppvH7*#9M1j?o0v^ZU zh;ORwjv$|)fdd5lm4@BNJe0AlYHZ3MA~Mdsu8`2FP)?#t2g)3KlQx&AJPa2QF^O}YFw z;As}RR6UhG*xKmdFNs2@AR0L+{Kh-_eSL!_lFu%EJnw0)$!vn>PObgZxb0meBzK+c zISMjTstbh+)z5)R>zIw+s6SWh!~Js=W*b=5+A>M4hR}J_wt+qBCVIZ#6=hbiCkjlA z1_TzXF`PjoQ#v{`7kppm0bZH6Y2mu6%73^~ln3d#adNWK_`BvZ$CFN>-(PEHnzpma z<~vg6sq}y~!c0UTo&aET;$!AsKgV;-ZWe8bUkwk{mitny{ETQK zSTYpmG$lQZR3K)dlBp$t?M>HPocg}zyoi^kY`5HySHO%?98$cQVw^VC#mat=ejEYZ zk2iI0;)Z)+)tI$7j;Wu-^UnZg>i#h}FIw&q*7ymCy4Zx7QWZorpe$3uNRHYM&x%qU zcCHp}DIiW*b9Fx7np);bhIds8wmh(KMB3-w58Y;x>B6A)uX(8g@@Zrsc^98@E6Vrg zxwKAJ^}^2@FLXOAy$$BL=eeJ*C2UU>JgioORht)!g5;<4#)ur3|I^adjo|r8y7->+ z^aSH_D3LGnLI2LX!*BcKJG!p-O|)BX(v#XV?E~l&o`PUlwdU`UO_xM5rg{m8U->LSoSz{7+_`yRCGq;B=cw)X z|N4q+3QuY5cct z=axUD5*nh+8xR9;aM9)CZmidFuh5$d;#heRg`Jxdh3hgvM~58-_Q1>EPsch2>D}y> zXvc|ih2rLP&xs!iDbObFv#WK|LK3q^Zz4Z&Y;TD&BpCa*1^Kv z>ds=+1Empo8hC=xIJvwWEapBk}YYbHXSX1 z5Zuny3ZF|`GdRYATGuA8$Ss9KtW{sFlhVYew%E=1&>4+CZzJtequJ`PqEzdV*9Zt- zaOo(U@ljV*!^)xj#a-z^`;CFfVHru{FyZI*3S;d4HOEwHrI{jeVP-o5@l8KkRj|bQ z2}pWDd!>^l;U7Z{hDK>(Rmf!`u9*1N8qSlF4Fe9xB}c9bTeKTIgUi)_wTRhdfChcd}v%{&6z?X zc(*ss7j4W71M~kez?B`08T|M3wh~iA04H3;1QrRUisQ}C1)|iq&L713fi@cZ^t#h^ ziQrG&>^y@erIkefnXy!`ghXl=vy9+Mh}%67ZIl7FpJB#f8inouh%M z8$nYZ-ytS;?v=U)C1t0?4PStJLxrDAxbh3YB^5l>+>5={#|`Fq!+ES;=Jjbi|4iM^ zuZGO323MM8JpZ&)Ezb=)_53jf1B{K%xKgL`=*vHbt~c0SH{#!~+Y45mqQqi4B+EEG zA@7x3EmdR>Jj@ae5Oq|@V|r=K=81S_eky=9FwL^!=qJ|JAyNx(HTq3{BL$0>olh;R zgIb?$^?6v*AlwdklsKnQ`+yM(vlte=B5Y`xq|pJrSSUK-aizmKXsw*R2#r zebrNcb?0fDQk^J&p&ItN-qCw7w&WmHdOhiwk>AkR>heO3iii0t;#9neQ@7j?@q5}W zX`BHdc93cbvj{DYMAy9@h%yL1=DEaUX@I8qI1ELC>inWP7XL%_1H-|KS!Y=%r;9cCeUNl^rtM98Gv-(geQ~w;UqH(F7waa}9CPSX zICD2@b7zA!QBe#Rch_! zX=hh}sekU33O!Uv(O{xC`%;th*bJh=jr*s5INR-fOwT+y^qnZ@{#M(|4}t*n?HZIH z8pvrI!mtQA5xQL%bom*}yK`YLWj|h&HF6+rYjy<)c(~~+@$o7Ye(gUWz~9o~S`QB_ z#(3TGee{6g+%K=5Il@Er<$Lp-coZpsQ@_<6Mx&lIjxTQp`!vIaaPp#jJ+N~prBfS_ zR36Dh(`Xfv^nz(}E|MaeOz&TsaK@}Vb*>0)am%NqalQP(vOj~REDLPtHx>1_iIu9B z4Ip8^N?8R831WdrxjmwOci&5|`)pnasUNp@kBb)By61L7Uw~x5^b71sS8yF<>|kDa zM(51bv+ove2Wqy-V(s43LMTd7@`!$h>_Oci{3p5rz`?g6D{#-pBn_L{I^3YsBjs#} zK=vneYRu|?%`r(9Wust3@g^A@oCZTfeX&tY_s(C;u(s|&;wzyY*-V`+WMs{@Q!k*V z-<3YIM5kC=d*L*0c7TNGqqOd5q|`y zD}wmeC0lcku{eWnPTE|*bfM)8mox8pZ`OP)qUpQd6_9_Z6T;MQ;Keq`dm#o#BLj3P zoKf`MrMAhAxNeco^y}qat5=B^Jojtku7+eT>Xcjab~%|j%Uk9)6%IQUPIau&O2kn{ z6~JaA;E}&C*gxvlrAy}T+xKn=csCim{eD`6$p0|)TPqtUFG87(8zyuse9lz(kE~*? z<4{^X6^66Tyl&qEe`Vgpu=!}j^OfiV8D|={Bj*;U9k+3uG(86>PW)5);q7w3CGb0D zO7dS!*XvYDw6c6m!+vwctc$s!O2v5YBr)sj4ICWPigqmjO(cKJPX&CxMdG=ZEsL({#sd0?d7&)8^QlSkp|-kX0`q+>R}4kL z_=4P@xL+$>0L!$fLppGCD+CemcfeaiH2%i`37bnDW%K=Hz2MY!sKJ^4-MmJ<-#g6S z9*6FWm9$o3B4`uv9x1wxLw(s#0v?S3+&%)X#g6qe(Mv+}pLq29^Ez!x@i;FRetvzV zIc%NTPf#e55e3xKGK}GPn45;N8Nd^CpY>&H&wG0QgB*Fl3-ax2+bg+l9o#8A?>Chf zv^=UkrMJt$8wS;#diH+@%xnH;byf9M#^cn*L66O7IAviVX--LnMfsb;(fjg4Eq-F1 zVoKRL5fKgFvB+O(aWQtzOpi3)+Yny2ZoBE07C=HJ_W1rW>~8}yfPKGtt4ogiCTl_m zp4H5bm@g^6V>mlNnUQP{T?ql@hk*C?p2(>KO!h-VzPkq3n1x*EIW@g|id|XWcYG{Y zw0iy@!>6&~%KkEB%p3z~`s+1$jxy(&i;K;;M>)7T(zQAQ2%;RXhfM%U%zBcD-?&5Nw5~pTfV7@Tel~#1Yvx@Ep#0J6g<P&bYZx7`V^-o z!R6c=l&`{)I{ROCS{oDFtV-B`Q6!knuiVUJfbTD%LTKgM9Zp%}OV!NPbk_xAZ*Mx6 zI+5Xwp72UpaJoq0N4b(5p)SKI#koJ-99x6JIsP%Y&PDz5{`O<_*=jv5{78m*MTT+N znFq_gWnLh*>6`<}g!*>bBgIy%*&6$jV6LX+Cds@L)^ZxYV9~g#xhHllyQ6? zO!u!u*kk6ka!W~B(eiM&UhOmbA$3MZwI}u!?LUi8(i@t!4BjK%&Wsz^drV7ReLTqZ zYd!}NV2d*V^|BkQ?njHhgn0lD>G`|hJ4b}U-t;*7Y~<_PZRycJ8p7+_=d@orKUggh z{6qm4y;mQgu%v6dR^z8cZK$y#&F)!`~uPXwFMIBM*`2? z^>d{1`)JV#B02Ia?{S`VDR+GTzF7`AbVh@xr4BerQF2V(==qg9aTUv2>tYl}kN?&S z|1By1>+t1s!js!#GaY!*ePRSZl0qlP$%_(WpRb>l`a&E0z`x8^;B9Xt zgc+036P`*)HjXy6lN0Wpb1Jj(%&;v-&5Ten6fsA`?~|qiPc>%EM=b00URdUZQPUg0 zsI^x3^6#i}s+7k%8Qq?zrKS{`QWrKgh{A9%Ny^Yq7Vzc%?W)y|cjY1Y={9e0ye~RU zlI#f$E1QM(Or+-FmQrX9K&ARl8&nOWHA0v2;nvqQxmmwk?5+^=?_XKPd2E9{935~i za!fr-Yf*`RdId`RRd-y=xE-N)H9xrGY8aNLm{^vdUv%YwWNzghbQbZi2v0zsMfur9f+fL@RZly0QXAu?faSp9jM zB#h43{uFI-#kem)_}ltT;*Ff;Kv<2TvTUGFA_xg2a@0)3Gge=UJGjm3h-No#f1AFt ze`GP@iQT)WqS<#^;gC2ucVFcl?_bmHkITdNxh4Dh*De7o(hPfwg}+A)wEdeE)5U^Bw2Z{86=R=A z*u%G(rsL+Jlx#v^r{=naf)W2y;g#{SGYjvBcgWrk!m$EXZm{)QlczjQPyz( z3I2Z5h}yEIo6MlLUnTOj!~e$Kdj~bytqs4}1r?=BReB8ygepZkNeCr0A%LPJkU;3Y zSdd;NBtYnpgkGeDCW_KKgeJuT2uM@96w8-q@ArIr|8e$w^Uj$$=RGq|{>UVgyM#s7 zy4Ss~>-zmfvUQ6FH7UCr7+J^dyq+X29c0TdAS|^t+n}D~=HHXk|2HR`|DALFA10>^ zgsiMBQx9pOxHDJpCz!t>DH3BpFS0roH!7|Ah>rJsJcyeMXK$u250c?E7uEz zYbN{HzLft%_j2nnD}7l%)jXM#FYWA(MqH~iXs$rPc6LlWEzW1Tsh1U&U?W5Wz7i96 z%(s6pCv-lZw>uL1-eY$Ac&pvYPLoD8NWOfn-@I8F=P`1;rPrlY&sTbz8|xBGqUn44-)W8KXdh(>%riFOQ)G;Yke zc##P{A5nlU7>{pl=l=~HGgL^uhq^)u8x_+sh!OtA#Buj`8{K1oR(N~=iw-@w@23V& zK(hFKQh!X+`+uI`LV8Kvm%eY~ZSkuiSbDa<7(Al>20Kq*n2H_yv6r!$zPY1Q52JH?_WH$U2?3@fuVhdrseW^{SS?z5Ya16x|OeDKV1 zg36b?yQO_dV6o$v+pBjxHYVVBB#r5`Cn%=|93Lk6!SicQR?b{&mF7U468P7kdj4M{ zZQ>7Y#E+r#{6V(TecXR<{g129-)-_=7vH~sCx7>y7k~GLzk9>~)N6yZ_0K$O>o?M+ zx_H<7wZazbDb_`A5$4tjDM`&WU}m(L4sH!;YuFPJcRj_`p_SvJvKFQs*nouMp$*^H zYz@9cZCH<~#=xNR5gcjQOg;R??1O*apPl+#IaN&QU8)PX)!R}Z&&~8KHMVb|K8~o zX89jAP%0=d?}>$1ZFIoef3%eVDZBx#h}hx8kHl2_aF>OpIGCU#mF1lOvlwfA~D#E`$sR->C+H?#k$ z3uY*~f{8!EzlOiHuyAZ}FJJd}q^$wX#o)IncI#&ba#4H=R{2vT6?LtzTz= z9o>`Z>A4Axr&8gQo}WGgBEHt%F>tr;e)5#UQ82J6z&t*}iD-4={eAkqeVklfp||8;Qwe;xPf|Nl=TxNI3{;w@j)>|sM}n=(eINH^J+!12X9=;VI?LhrCA>PW^q4LXEi-- zCKkX31Apko5xf(&9gj`s2HuipaZ?Us6Qp}k$=7ZvV6A;GNSA)$^d?5~qz}li@`JcB zLwGdg=K0O}2fILNJwtZ>lcmi3OL4rZNin#4v*PkD9X%PEH;2ifDbvDfm%alY1eR)X zekifT*Sc4$bfQFDdNpSuNJU9unlq;#(N;fB%P=?HE6kc*&)ye!!wg75j(F@05${o6 z87-4W9OO<5hKfKbSP)lI7jevtMjFqJ4}E!xoc^Czg8ug>oDKaqen<)aLjTx$3ViYJ z0@uPK&ilqV=|ZR~n@8=Jj$7#>4wt`-y|uceZm4w>hUBz)`o9nIj~6tl$*-l{6UjHX zyXykVo&-Am?xUg7uG44+|0d*(5Bq}KB9w6KCH$A@_>8 z|DlssCFwtu$wxN8K(e#eoHt`cg8aLjDl@K!wg|FpsOl%%$2ra!PS{c;5=Tor#@vL6 zhVGj)6CeT0oHbwLE|ugI&TADb>K2)P6>s_uK5HoMb4;itc1%j z{?LaIhsxyXUF3s%7&A&Ad0;+O#Wi#>5k46@vHAQq+!4b{*pY$eYYDiV68Vhiy_$gC&_|Vg z^S%m2;pr%@<5viSr1Lsvo(5=@RBD13lwNk$H4DU)rj$VM7;MAzG_B1fc#2io#A9-t z5bLi-h^iW0l^H_l;W_C8dq$~nBY;j6C7xz@-B6;1n2s+F*o4$AW-H1BXy|obWSuax z&m7XvK0DPgN6j!LcQDrhNV(^Pj{VGSz6QOZ*E#Pq{VI<$x#JFY_3ehryFT6CCk^ly zgTi~Vg{Uo5eEG;C)h}m!9QAj^XnbjuwM>@hK3~KuD{8CPiw+YO4&vP0 z0-P0(Z<^|C{sx5hPnzCdzB1)$Y74i>sL*~B`))+Xh|Hxl!!0uD7@@SbH!G+qH0(Ga z{gNReoP$H`m7!Ul$#&{st$NK`SsY zD+QJWJsU)3xXJJvk4Y4*8<3RSu=cmSqisxBYZVBeUwcibmj%6hj@E7jlqS5i5PeWb z?F)(d)+Ce4jiH)iP26g4+^;Tyi?m)G=!xp6eCQNGysAI4Ciusu11h3<~e{bSibiWyZw9#nm z2Lcnv8NPXotPHLA$_bq3VI9-1po63O~uuKL#eDYG-5@pU2QPIct<;w#Rlu75t8 z)z({AbW5i01TFl|f(-{WF(*El_l9m{P;ixh=(1KqLb>?~@CK%Go@>qDvm}y?l09a( zewQe89Igcx3Dy;uhfRaA!8*N41&dTH&Gn&lRtBf)?=KU;q1$1D6_B@47Sp#+q+ zl0*I)Oj8G8&5*O~!f4vHZ4 z)AHY6FXjU)=>X9coUe!Wi}3QMG{#lmdK3D%M+GJ!%+f@&_Y60#D9oo)`w`;P-zk~u996=8-;d|oZ1!iuRG#1rdy!&fdR-nc;8ar zGXKgAZf3WSN)fUd=J)zRSkyS#(2)iz{XK;d(=xFWq8jY0d)}4Txa@vwllw}As@8Gl zzQ%e%)alx}tRHvgevR=m?gj^o&rZ*dxj5F3*c?awleeT8@5|tl%Dp{CTkkwQ% z6xtc#za)8TOSao>r(>qi#)H_5SLWlg9jD?cGgxw?GpM|0JUstA#FXH{L*`puGA^7d zVXnM%{%tm-*w}$ku29G}ce%n5Utv2JUfwH&Bmy%tP>VM?e9l=9rXsdk&Q?dA-+-vd zbM|45EW|7{T(2ef0t`L%3t!VpFT{5{TW2JAE6{?JKG{wU%oq9b0wE{*Gpg*;Q zp+6EU9BsJb_vJ$?BOM>bb-Y?wMEpu%vpv_l`5atnOc`IanE7@8b#!~Q8a^dRDV+48 z)wHhGv_hu<3a{X+0m1~;cIBeP{Kk$*;w-_;ceGp z;8S<0rsC>VpWxU6Y8tr2%z!%EC&V=Z7J!Y^DdCiB7Otp>-(fH+4CZ&)zQH18D_AdN ze;DUct6QM!Ny$!KcT=L(Wq`Cm05VukPWG$dHepLphMJG^r1!i~YOYhD;S-O{mDqIW zdtB5;v|Qa23$QKi7X|xCu9+XzvalhYZpQC{S?XvdST-Jla&lu3$!GhQ58s5CPIr~^ z@#@zkL@`eIl$m9yphPag=3=CKFR?78C`5kPOdAD?_&Ystr0N**CLe{e>-B zCL08R=#V1$hmql>GC~DRe9N5apn|!{%mO`sdOuZcj?aU^k;!}9@#Pb3Qfvx zT@%QZ6$Pl%C-&hpV_grVZZotdPFr_vxOLLA>Fug{*eG1^uASRcQL&uu4M?t8gF;K{ zN<<1~g_Yd+%3uaq9j%&2(4x4XIf~@u=*d*24;*#`tKuvbvPdnzi{{2gg)>Y67lCPL zs9AvF^QfUJPsiHWa&eZ6RWnDhCP}~6pnQXzxjr;J?KEuh6|NNS=m^oI(KzFK4z~r_ zrs!{b%T9l+S-l<;-S`1sE%p8-p>U)GSFh55<{b({O(*_JK8tL)M#fZOX!Ca_VWAWg zyO6F&5rWe1Ay%E>R)DY0m}R?^*=z{GwkX>dKt5Xwj!|L85!J4SU46P)0bX;9vrqCC zkm-inpAGEjEpw(-8-WjeN9xC1pgz*iGDGr@{3;wO&(8RtedW|#c^#*?I(dwe%TizT z99jvOBUDp@ROsvHWSXk`_`~)V_AD*>d(IhCNpVl>TKNm@; z1%%V)KN><$;caZ}`~JAPDv8y5qgy?j?@IcP6TOl)x-Vs0$qad(Ja%`wpJck-^wGjS z*unVt58cUK+aI5ha?&8|4i|!yG3SXEBGc1U8v}<-OaWcN%TI8A3!d_2!QxxA`O`G` zM%71fI7~p#^#cSX!dwI7GGD+Z`Z_vR7`{jm6pkZ4r|(RAIg=CbkB;{bn&6i|3+umE zNZVjk^uq~z*BicqS1VQww^uI8%E$Qd$knb+Zg6^))ZRd|1goz1m+8pU*pr5PQwSla z0vIhRKqxv|G^GBcKfAyK;g}G+S~J;NctJNoey=VvrrSK*yds=QSR*ewTK{NrP;00A zf!W6fl?+Et%|`ENbGnsP&Rgwyf}9EM*AM0C6`5MK>0U;*_~`Rjfo2w zq4xNa@X1W%uxvW%xivevCXI6FtcPZI5}n4!5Pk}~?FHowDl{44N-<~_2{}xYIN01s zu?|^@LD`twtmkivTDY!xM-R_Er+moH9O##p_na}52> z8!o)N`sq^o1FYp$OH7S4UW<<8+ETkXP9>E`Q#4yZk+}{yh9ptQT&(pIt1==hI31Iuu8N&&VP5Q0xLGS6=IJ3IW9ne9Fo%Rd zW^NsUbdOmdi1s1C=a8Aq)ev0F?V{Ur>B9;^|C+CgteEFxo$iCj}#o5Xi zzgn9!15Q0)Djyg~;ew1(Z9{aROdK6LqA2X*-RPf3Ny5e3nPx+cmErutrSX60G?||M zdg^p8F<`w;o9v?URqm7$=h@Fw$fwSA2}YglJ)5Ww%CPWJmwQ&$V8& z&%EcJ2Q8dV9yW3^f5R?U<$XEDi2c=c1_@16&*rhx%KLa<0eKQ(pw{U#j zm)?_q3QZs1zGJ!QN-D)N>x35%V0CCpmkyh&+N!yYA6!izH@nWw+jmA^Q6PvkG21IK zlSFk{jL-|X!hxQ#(q2bejwPa0|5Wc2c;h$Qw~s8^13GkUenEw$OZ&K&dz%tzWI6Vs zqS^y(t1AI?)TeC5ELlq≦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∈lsy$~igEY8Hg+KdAps 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 literal 0 HcmV?d00001 diff --git a/packages/swing-store/docs/images/data-export-3.jpg b/packages/swing-store/docs/images/data-export-3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4321a3405705219df87563fc438f4414ef2f73c6 GIT binary patch literal 141618 zcmeFYcT`hbw>TO_QL1#MD-a-HKtdA`I8p+kN@zkThZYDBdXa7c=_MibCcOrvg{E+n z-bA_t5T$nn=^*@a?)SUjIpd9c#~bhc?tA0=>M!-+q+0|2Ao|Dyi??iPiuou>_n=m+WV z0E8hoD-WyxQ05xxdKHNT0QQOj02&hjfblZ`K#BNIMgMC1S6}=$&w7{ChJ*B+uB4wm zz!_i%xC?**TmUuz5fTOgJOGFRq%Nlc$^f#ff5M+vG7?-PzxF5GBqzU4PH~fxlHw)> z1ts+@YDy|vDhdi3dK%hWbaeD|l++B240MbnobFF1SN?2CcI_sqAsrP373uE(L%93{ zK!5WZ57}F?D?EU!^jFB}uUvKjI7!_{1|Ylgr)&RjAir_*+I0%DtAAEI&;bC~$w<{V zsVFHZu9IJ(0bIFCcI`TehMwUbBhwvL9x>ym$rQ{G>BmOCNh70UEVp@O^z^Oj+J_C0 z?mjOtxRe@kiHAyX@5Jg_K1pk@1!WJf%{8X5VG|DgF(4f^X0jQ7MI>kX4LF|)w+4KUbTh?V<` z>JLA7#3ih2c6otP$~GRJA1{djYBCZBdNO)|BH%#lZ!-Rs&?l^OPnoD$F{o!B2F!yj zB%ATP)5#`;-+4^2-Hr?P%`(_ib|lgkieUA=67sw^>k_cz&tt!1FtipPa`rVM?QC59 z^moZr>a@9wqdflL1Fefx-%G&z)ySOp`iezlCjV~oZ;SogVg5Z{{ykm%AI_HLu1=?~ zj9Sr73@y(gouxe6Wwq)rMA}qU9xnfk;yKdr^qdYFz(NB8$qfIozEER=E+8#rizBWZ zaPkILp0jg1pBudea}x!Cv2Xt>OAwjR2Jc*=)|?CndfAIkmz+7)Dj+K=rs`<<4{KfZ8XOy6Yl63U3}jvLG8lgNrVE@-{F9;9&P z%eNVJQMP{Pr+DVn*wYa67P{rZJJ$SGYfo?Soh^&+WJO1xnS=*+1^ujc4{;J({iQS! zK>T&ie14HNa`5&BHs~ko(WlPNUlr}GHVP+S8r$kq{lhAb>d%h3LUh*rzmWARoWz{1 zSkGTfSj~y$1a6vH5(nh}!Q_@=vDbU&D~mb*$^OAk>QJkXi0BrQE7wVWEBN9@&S0Qd>~leyeKwJtFo3b1T@v9iCNf`9%f z@t@2&|EcpB*#3Rh+#f$reKjZk;DR0fCv)0=>b%ZU`*m{Xo8K?F!j0emE0a7ppfcHU zI{NYG-v;@IkNkgX5V2J##w8=_=LaUasPzhsGJ}G)2U$tLz!?*M%}5yQMJVR>KCSMZ zJsZ6bZ=w0%d24%@*fVSUhJDR&eY1(h4w2sgTqx4Hl-2leW0N|%B0gAKJTR~ROsw+x ze~eUe_0~%OtNDvPl=ML<86xIyQz*dE?SFWtxw6<*qBuf+dI<=SxnPPn>CQM3VZyHj z{chod7SVegGy8bWn_}IyPV4C!Uy6ua3Xlzl!}^Mp&GkU-wjMIz*%)^CMIC(HhX0Y5T(V+Ls+ky zbUbjKY;(2u5BuT4>sJ??QSyUb?hZe$H zRuBw)EZ_nh@=)MM?Vtk?znL`W9x*!VBcBLk+4bqn^!M@~eosl5mS!O&w}oPBB!&0x zyb{1Q`x8gwId?QZjXF;Hcg+UL9r_SrC5zF^JoeRLfTwA5RFiIomjIsr@?KB{sGzTS zNHdU8M7Dv)l5;33Ql+3&F1ssn4};0h=}cE|pW@c>!EYIx;!hK^3YF>++ue^GoZs!r zW{ZecyZ%6la>qw^V|K>kzE;JqN%#l)mk$hziqVU)A9M_DOr7q08A%ll(B`eY<3_$l zNZIr;yM4{fTbq#OJ~fng-!b%6_UpMIjd`p<>_<~Su30T?cHtri@gn*y3$S7WBJ!kV ziTU*hDK}JHb6v}{Xs{N(tG~{x`Sw*;yENCHp~&=-p(M6I-{qh4y_&k;BdfGqq#`1- zb0(1&PN>)oF|pHw2kJCGt*1=shkgQ0q_i6#i6)NXQ89V`2KHkw_nL?CPUubn5BW?W z*K`hN#9`M|0H=1x6n|U1eXmy1@Zt~j9=OHGD73L}pp{JD>2X>hITDfm@$glQ^(2yz zjdHZDaIMcrO}EP0=N4&+$MH;ebT5WK-@m#4s@U7cNg8NY)#5yotCw#mA`s=-r9ZYn z!^$_%5n?itO0@hW%kfh@Lsd5i&0?IzwE_u@^Ii3|19FYYyI<&Xh0&n1bOA5OOwAFXb}mI;wWB=3>cW5Sk`(HGw@yCsve z4Irm7ABM@eV+LjP*Y~JPW@DrL{N6<=S z-$Stvs0HqK^_0GL<-pJL{+^1;)Tajz?(~9 zFz3YeykpteD<$S&n}P-Y+OBLzk^TmXf;OS6W*$nEiXxPLg%yKi=}d@+#3PC0Wn?xv z#&H$&P|Tq8hV|%r)cdr;>Z8XHKd!H`4fzbJvzr4` zcj6{uH~M3n5WZeRx{H?ACf=2#rk>*j0V(s&cIN#@2O=LDV!=Hn50RT;1!EBde6c#R z_||I$@zyg9;u^j)J>GjuMU*;PiS^dfY3I4rDny^q-^kaRHo?@Wwc`n-Qkd*YQ-+oN zOrD2wWquv_q;cBiUQq+@EC@USn-B5@a=1#Yc`})$rup@2Ct8?8sO{8~w71OtL?FaA z%DRj$7s7&F&sZ2MrcnN7{H&Y1AFQa?-=q3#-McLWvBe1K-|V}!`IYfg`Y>Z%$AFJd z^=BH@{IgrSO;Mc29E)-&?b&lqj8;iKJYi(+_t6CgcHkj&Lv6ts1%c~&!mv#Cdgf2L zE(o4izFQZ`KnUj@-Omf|j?55@0vhfKj78S!tn2N}yPF8xz_voTnLY&RXoHXNrR@7# z^pb~pzUw>dQw8&NMxvZzLaXGBW1sH*VH(uM6abaKH64gCh?~k%HKd@}Oh^i5(R-`o zgVMlhpzG2@K->9B4Vw~eg#%6*Z^0T>rlE@nOkexw1;gQc3l9hHrW$qh-cL7Hz5mWO zr+IH5T&9aNHC7L|CpDTv+wq+1q2fGpM&!^)=zpT{q3-xB{CL-K( z&Lo=KKs9tuy2_T0BUp3Y?^cgO1RgVvLveU2{-O9ZxADhtyzv?BT7+(9@)z{i*dDtD zaY?B{HU?W{KCcNYS9gv3t3D1^aeZ1d-|qf%amOvj6E$74cr~V(j zGf#q&s>n@7*M?bTyk*1fh)h1}JrP(0hHWgL2gaIm+C7G~(VD4Kv{|7u%&gvKGiYA2 zxW^>>YBkub5K^<6@2-sp7k-57M&>Oh&JaZJW+1xWu8I5AgPhZ(zFK2ihv($QYE7*& zCX>YJxihGqe`(6lNUd4w++Kb!F+R?pLJld=C`|mMkiw>B%=F6Z%xG507oK6UY-|27 z&ABXJ?aSA}zO={|qq71|jbyK0i1y2b4Y|g+N4kj`8qF?2(yX0b`%`skl1Y)%T<2v2 zXou9z)SX|40@w3)Ny7?@;Vv@qQSOOr*L0sWP*}_)$up}fyAZVB=(xJQ^8XEQ>|#1*>Ye* z3M}?WowGD&E9nl zd``5s28%I#GO41ReaOEWjxrxD#TE?~OY19@ZZ{G}h%@dru=LNb7NH~WLhY(kEPLDb z6)$2BS1znWHeBN34eDcoqkGroGj|=w%e)Wt(hcnMWI%#i3bT7kx;1_jb9Dl`rLJSm zCsJ?sCwV$jqVm+c+-%zkw-x+GpJE-Q>E^tuJj6|LRo?yRF?&LLkNa2Qlt?#c{S3~$ znUb`+4psZSS#!l+S8~Dbbe|mN0sz^Es^@@zsbjAoTJ{g5g7uJOU89b|mOr1T!}}5V zv`$II)fA>=~Uu?Zc&Re^eT?pAyWJ$KhP71#w7Q)h7C=5YcZOVa1ZB2LVN;nxOG; z?qD|55PrPN%*OV}q?AGzJgYO~cRMObZDN1MM!B-k9aYmUG(5~%J=|uD{G|PMv0%qx z_4VsR&Gp1S)o@kKPyF)AdGfNVs<)FZZM^_mmH z?jaLru;w?D9fbmJt+MmO-rxPy_jYZp+&>E>+Go=|4D4N1ia6s-bcARa6S@jnS?P0> z6<&q?aa_!vZYvHGe}GeJx3j{OW|Q z#hUp`P0x#$JQpuU9EN@YH*+o?wT;bj9==x`k-}f>yt)LaycWF#=uKV%NDK%z=Moof zz0cOS^JQ6LtH+*JHBReKs#wE-2*%hX`EClz^TNS8;gcuI*MJ&Ikq&x=F!`RILx^IZ zyw*GS`yA7SXQm&_HSSa9k7=0oDep;3H|x+41CA)b!8Xo8g_l1kkfw0(ul! zQs#*zq@i7O2{@9xIazZn3B4XYMlJ5x#=ML^$n1;%JrBn64@{gf`7A)>R&^SsY<7x;;Gm`J`Etp@ooQCi|KvfisWOPH14_5FT;H%(XYu+ukei z=3VwWVj8hHD#(R{3ik~ZQVdOM)tgnl!Cm1`!+$wYm0w_<`cQ{U-jPA5tc zeIg#E&F_w8O(ZW=lvdk!4DWrMV)wAQv{PmRuP9uww} zL@FCS7uD(D5{G3Rh6d~@6cT2A8HQ|<*NWjag+5d1XJ~n|f*raTo z*qYbwN6C~CWM(ZYvTonIqhrWG&0Z_1zG+=`0qN1lb>i!Kb{Mij#r_j8ytyJFLwkL} zQ{;tmc~|x>Vb4)$AcT@hI$3>VOQbG_cuU`=ip5THx4x zi-x#aQl5tG4-IKkZ>G-G@~ae!wBz=yeLba&H(Y-E%E*2Q4BrLyPZ+j=Jz|o zCEEO*uvePsgl!8)-XHqW{Lk*?3WDXU{#+3;(3I1toMr_f17>`0li#uz zyO7_81WV(=9I?6DvGJRZBi8bP7KWXr@}sm#T)e1b?OTr=O;YyX#&6tR znFKd8=rM?-Jp{97-b~28-o)1*9CYiO*kY+Rd7Gw|U;PBp=VD;%ovzQc>#(q=j2ICK z;x2nh*cKYkw|L<>T{{z|U!<;*TGgxjv0eDn`o<;?%!n zWQbkwiA3y6WvmvuejbYQPl14#7b=PUreV=;(^x*m_|%yrNRz5>PkG zS9COO`zGS}r(4`4?x|~6y#+e2@~D$hs=?UIOaIxHCRB*qF5|H~+t0>}!aP^xh=l22{2*nD81YiMK;>dmX-M_aBH)CFu;^*iK5 zBR~y|*U6JG=j2e8kk9u{i66$waCeB9F1~>>AexX_378JwFqara{_udoXCpF$sYwdt0BYpk`d9LH}k zTCBx2Z~gMR<4#OluAP+^m3e*i2Q!5+`AgU4pr^PZ5S`QTJliRTkUIN0QS`IU!>V;= z=Jw5C`-iucN~KOg%%&Q%5M)_ti4}$GFGJapwwp=lB|e7Jo$4H%c@x2|x-d(Kmr}oM zcV)(KwNeSPn!*X9)a%0*xHcpBexk_(4!)WDJgMz!j7y1{)GZqRDjHx>%kHD%J#ZBK z3+!e?0M%EqLqFZ99>1RMBGx7n(F+{(@xLQ+8#mJ7i3pi+z5jbJcF6$Prr;IM2gA;1 z`%N-ABBJ%S3k8Qt(?}3&_~y}&ak~7qP zJ3}e3jC-K)4Rxu`JG*k$&KFM`kTCs(6K!SMb`%t;-Kqv?KZ9Sx5L1Kznit_;S8cA~ir-JO)Wi=`qKK zh2+!5?1o!Mz7Y}GCwL^k&C$s=mN)TXsk~dbNThvYBbZBoi{ePR-z6YcT>cU;m@ALj38Ccv376i$ zcHusgc3slbIVX{q0DSY^=Fw5)I&F^MU9eX(TSTFp4w=^jLs220`= zPHn+;SdJc(J<*kXKO>ssd%AgwkBW+EJ;b1+7e!k*0xLbh%Ypc9gN3j`)Pa|P$PI~; zcUhy~3g=x-Vi$r_iQq|2m)EkUk}P%IYG>fL04^XY7wlgh?NLU?!etcq8`(G?W%|R zY_z({ty>Fx^))nYx|at*c`o5E2IA4Z95KCo0k@UDG}Ff17zGu6h&x{b(YyT056MWA zs_PmR`8xGZq(vlm3!m#@uv$y=h~}6f`QupD(LC}MxPPDfF|f(=lS9k*$}D%=vp6$p z6DiKv*=?!*!8B)-dmSq)~TpA4edQ{~ZG-YAf zcjWH5?drTPsuZ*JKf*Wut&H02Y*t1-YBQo_zC-veugT30^gUxT<%{b zmGUG8>8u%c&-u}Cy0$>40|f5N3t0_ThHy6@bh?>K3J6Qf`{Wvz$l?lnJ(on3`}vZ4 zc})k#Y*kcLCv$1vkzp*1MP0J-XWA?1j8UU;iv28*wP~S{SA-`|Z~nuMi0#q_Qxkno z2;3l%7nZWb%c_LT_Z&D4@akptSl?vl;rR}CZ(u^87ak@8%TKkAI4d>B@H@EO_iZu4 z`%xVJc8w){G5b;$n%nHupiocAhXvVdCTW}4jfR9~N}OAxG{sM}v~+nPa;99%TUVto zaLUiRVBknx?5kw(oEAc(_Rf1@{PYGd5U!{9EVm@qY{&;@cFX(O zS6xv{!PV!!XpK1+1J|0HX>o6~x17JH-Y=>6qkhk@^D2jzk8_905i@7qPHQg;>Y%$% z7YdjZ;qcq&?SEPq?B2vExfWWs)psIwZr@ZTeE9xpd{468(vZ6|HoC`lD(9-=hzhSB zu)nwu=|!OnP2}uo?jNZ5OqfWV71D?;j0wqEJP7y?9P*^ro(iXl?sFpP8b z^n71O*|nYn1RT>${Zj5ftxkXCu!wk>LKA163AJyU=~)a&OXNqs6c-nti^p{@Zw{Ck zoyIj9`zSXGRdYZjRWb7IzYn|%pQ8V930S@N?e0%4j#gg`N9CWR&BdHB9UL0PrQU@Z#Ar08EO}6GUq#=AH6ua_W=10|HeN`CM#jNRAa>~Q*!kYfs8QbWtR|>TwbT{oRu?y>5Q_H1JX$skN znk#u@C5AR(OM1Wg2xi{ym99#&F8@aw3d5r;Dx^WFtTJ*85@DdSE%uldnCx#$aDO&Q z+gf`aRb1iPk1wt*^S3|H4(EeUPdAMWA6(B^WqSE$1X9?~MM*ln59^w?@X>RJcK=ii-!pF8NnT=xh zaXO}*`9C9a=2eT{!#B6t^OjqRlZ-YR%e+eqUOE(v0h@p$k6F_MGG5zPv*u`DFmm?? zFE@dOA`Q0?FAJfW>iTvp9yKHMfk$J=^{`Xh2 ziP|)(TJ_+f#MU#ZFc%%Tx~Ejs1x%jhE&R`rBQ$X+p)y5D1_+4aZs&ELE+ zA_0!MCP^-TG@`JMZy7X`uBV|Zl_}&2k_5G0;DSJ(>XK-m?8%7$=SZ%BkfG+`OgKa0 z-FX8(MFT6syaHl-vJKKr(KH|!Z-}vJX`3lFYL9V)!T$yL-$%C zEw6xUC30}B+@bE3{o6fnzw_h=ewC2(;eBlzzFtpmEtL;$;L$IGapT%5ZagEa$~BXq z%1fU`PF3o!?;ka6F8zj$q^@!m>3^KAd)lpM*!S>L*c1Omv!3KmSuan%_iW}Cav}tz zimirHGSr+pzSNKUTILNkcxy$J_%6?cC>zJ^;zG)Zneo$3e=NlIG(8EK`)SJ1r!x9y8uO`u~$HJYTx%0l6 z@jIaf5~g8(28Dt>5pA&Ni-1^SnlQ&)Tx(~1$aD%L#&>I2qpTXN?Hs_(gVI=-EY|C9 ztkRVIydBcqUlXgk-5NBs6?2&HGvl*FT6R6AvA)y2J#B)ti`RnQy|R*1G3*=P`OTb@ zHiNQ+zo55EGZc|d^VJN7@SYCpcG4(^m)9LSj%j3SgtA_9L~0phH+1M(G3iE$5QPG} z&ldoWx1>CLgauo|2NnsTf$~@Pi6y}=IC~l2h#6U}mGF5<;JgH9BwasaVRON+62pGl zm1d!*Qsncssvbv^JHB}s)hY92RzH+@yZK4JxWwjn@ACq?AAq+2RiQK|=Fc0w^-d;` zvEqs3Kz;2blbEqW?nQoFjY$st_=cZp)swAe|Mf{`B#j6a5?84;C1_QU9&b(B0z@<@ zgpJ*JL~fMlNXSt%@jiDrG^jU>ziR?3d9dQ6!mm+2OFx3z#*?z)T<)JKsQt*EC66ik z>hr!|GfUxf(;73bU8zM4^wSiZJlQc22@PYV-`~4KyH9?7G-T7%%@@gP-H;z4oOpMtP4(v=;1fPg3F9Kf{7NuxtiN_SApXpol>WUy5 z8d6*YPJTn&mF=S$Mw{zpWjM_k^mX`{NtyXvBP`ydrKeA4DqzJ3+wgulJ-F+#LddR? zbCPr$y=`h$IYsoaBX}fy?Fby3IPaAM$!ihTEpa!HWVsn3UvP^CGbI*vcS`fv81?nX z`JX(|4%iiFF#gssk8eV^cAwlJPQJra&1Y;4rg-aZ?Ef^TT`&CPsQ-vC=YlR7ZS69b zCVgeGUa46#QHv_8m^}gugghK_ zu52nAQopi--&HOfukybpXn2jWny;r6G7YB-f@$M5cuc%S3hbAz+`VG3@@^JoV`dXD zmS-#Hk>NRlo~i{^7YxNuADKYm3-k}_U25TH3ZO41q=4KuZ?o5!cd_4hD%sVZDV482il?rd8#Il9Q9b)&7xmys*YM;2?PwV&Gt9BvI*RI^5dYNG8*10l3XI9k#fCB zyC7>GCpc19ZVkL2bGT7`lXMVD@-8jB^R|ZHrgUmbn5)Q1uUu!uibE*$nrxnu8H@oQ z+f>Sjz&42U<mgB@eMU6 zyLX0xW1IyhGE!rW0uZPRv~VI{)BBo*zJydQWcvH+)u&{|ja9-*pOtCNQw+JH()jbN z3|R-E0@`vO3q-*tbdzgCq6ce>)+xStZc@iQHo>E?%%GWONhrq|JcZ#Y?6WqiL8%+9 zZDCP-n=7Ofq39E~f*X|ah+&w8Y!&<|THQ{r7l-f`pm~ISwKgvFWu%gy3<`*~$+#LGbAR1C$yH9~7`J?Uq;jH} z$geb1HtXG)mX6Dx8R}6bt)4tQpNtpNm$9B%lqba#jttczI_1*PDtMtfV(YWxj_Vh# zI4AMVREsXn$E-j;wQBBfBMB3~{XH`a6kV(SOzN;nNZPL3RU4yUrclaYt_@r6)l}@k zl|)4MF5dHeUR^Z4F5#1b+L27#&PpdHwW;QNU;iputQeJe;e*+4f9IqV!YpvU#k&^0 ze|<=MS2Ut+TmdW-6Fd-zyZvk;^Fm1Xgs3)3yNj1OH^})}7hfd$`PTm?6A+7^ipRd( zVH?fqgk1vU)K9Jc;@o+9Wvvysd;7GwV_ED>Z10Krf~n_msp1NXTT8C1Ze5f*OOMt;~W|tyTL4)cqjl%zue|z;t(Q!(L<$4ZdYWHS$?_=Ls)X;pvB_OLH z=)vCJ+upJO8}3?e;D2Wkve7`z zdC>#i$N`%}o5eRRf9d@<`C`G({aqsiRWC|+|82K_c+$U^-4IXDxTha}oQ$fDLt-lbIFZOW9ed7}`6tCSQAvwh zu~zQ)Ri{qs9_aVK<-nszSv6q_qf`jnJkbL`2H#)o@sHfDYidHoJPk8PU+r-zzjvwe z@%CxsA4^gsxObMjEC%=pnIhxTJy0TDm^(Z* zs9vgu_xM&+d`b85?ksvOcvR<3{x^Rk!`$KI1(u~whVRzdcC4C`xeRxFyTx^RMGtO9 zTLVR1pqwey!%v&<6xceWWfQ%->%i&r=CvvAfA~wpJ1&-PQwP&U2Vd*c>UsBi?VMc2 z5bEAkscVx6GAh4=kMip0z2A`{#N5UMyC>l|ZL2yFkuz9mW~y(a z4YK@p3(8hH<39TaLHMqPggY>0zcWKm;OdxOiO(b_&Lj<*(|iI^$-!hp>?xk=jBisW z8cy%+yOCsgWeVt+rI5lv;ffO|j`8XfCP&jl5d@3(Nb9vO8CP*f{-#9q@-`G@!e7os zBkLJ$#?R6uni20K_d~x-gkmvIoJXgVu=0K>|4dnaUc=m;V#)vU7&^mb!DXl!BPH91 zR!r`RTj2Ztj+g*7^W%-Y%}2i(%2xX+yVC5;b_onMOAY53^J(ycd?;)~jB$t~`7EuK?}-<@jnqRRIvcaKP9_a4J$ zEFw{&XL2nr_SLc|kx;DY>ltnV@6aH)aCl&_3QN2L(lP3Op~=-ohC z=O?L0Uh*YuAZ@l(QSp#D<87L*1c*5XD-huQBsa^d*=rrGJ}@|*+wH57VLDMe1=8E< zAn4L+(w0ruuM+Jh-;=RfADR_T`I!=vAa)eAV0Rk>8{mU5cRcVVwbu?07 zV>9meO&GUs6WN1mD>%j<)Mpx3r=8=)TIOt|bu{OKXU*?jWEc>O^fWvxxm~YZg7C;f z4HW5(E7fm3^Tdd`rJ3Sf9-R$thu!b(zDbZDO529bV;^qU-Cb{cK=h5HuJ)Sa%5@%_ z4Vy6*Gf!Yc^x7@+u^tJRYa}iZiVnp^51XGSSaaU`4x0E?i}gS=7%l{BMPJ23>SgnR z9JY+;(mIKL9biG-M6VKK$GHJt%z&5a@#yyL*ynpXrZyZS?C)qw_Tt_q4-~NX;rf`~ zA5DA0()<+YWj@|MET4QzsEEN7HWJ>~v#~0tS*R|NTc`5duu4^~I1D;2&(mc^_YQ^J zyOZN+f5%WdM1$?^Uh^vNLmC<4PXDauZW~UYxYb%xk5{#M#GNp2HqH?^E7qUgqSi3~ z?mVhC^Q(#v?sW{V0H}8)Pxz9YKNBBW)Y<8KQHS?8%#AOXef)A<2*Z^FO)=I!&^5lf z1*8#yL7jt?STNlXh7C@}Z!dHRDlD7qA!`0HMLF0bg*ObJemLRPC?=r9qc9#xp%(T2P-oe$ z8S4bwY14hYN6XeRMF8{YXum~GUeQljNML;8FsRpJ{kT!JI=L$-U0U>+;-5A{p2hiweg!@poPG>sCC1c4{YYa(JD>r4@x8$ z()S%O)FZv`@0mv>)Hl|Ci^Y*rfeZFGMn6Zhb=AA$i*>3uqcl)BSxrYr4wYt7wrYAT z)GQN@3x?o=w9fPC*7CR->z01ks^(c^0sAp*FqHioS^B9JhmwxGKD8^r+&c59kgPQ!32{%T6 z`KjyW6By_c6z)WN**)Zxu(t3DRCb6a=>k$G4#)kqcXPoK#$*h@E%{ukw_fEG@OCR%ce9xrTZfE_{P2M45Z z_J|pdQa$c`vush=VjDCYG|+{Bj#gi+#?^OnM0Q{f&jVb{BF>dugPNTs@N0=RE}+9l zn1sq3%VL2lwQHLX&qGTVYlSq@;=;|A#o?P z>Mm|$05*r!AA~wcq|syOb9lwY-$}rfvQp{>^*Yl|M@kLXe0~KHz2!5oR0AzSnNt$` zcBLZD`QHk`!0Jt`lKu}`V6m^$#w`;%cQSv^+^>79dKirYbIi8UorrxTR^853%_Q-) zEf&UFs-3pAIOi$P`a;me=WCZi59_DxXm<-L{i;ui%%M`FD)p?nFC~C{trQRuGtH0@ z6{uA_cvj+@pGA-4XbhkAsc>?|BcEBlC_O^uhbDU=A?*?H(Nd?AsOV{zlzCeCZt~rR za*0iQq(1)3I1^}1`{Uz65xgJ-$h91#-b~3ZY_my9^N}>Y$otVH9FE~Jc3zzJ1Z__) zjLf{=vz7YZ)VmdllBk(tna*CfIHPAd;^%7-H{W%cm`rsWy>k)ZxcR%PV;fiTtb@LN z^PqEf&lG~C`~1y=i?Bqz=N}J-$eW@xCJsN@+ZuEG9ND7>TC~p?7P>pO5*c}z-98Q35RYr>rN_i0R; z9)!(m`!~gc;zbP8JS)BI9!^t1^geoHEu9e_;=G&3SnP6lr#cU1IF;3X-&F6&lA{`J zy7ISzhUo~*nn$L|N5pmmU*wSqFJEIFkV->_9t)e40uQ-Q={vLgYH{_@V4UZlmF1f@ z8NHBcu4gW0DcS0YoBotL@fjHyh|HM&g+;VDYkX1LP4bi`65o#Dd&BSh+pR~8rz0d0 z{@O5!H3m3gkzH2|Xp1h?PUqlN!UjfueGScu>uXPKP*^h8P#fFMbzYUy3b4R#35_+} z$)0IQa0Q~=kIbA01?C^^a-AC>3yw?q=u3F(5*(Y((#^$Unz*l_k6WEJjWzr`+UuQVw1xenlgu+*XAIOG^^^jM{E;cx ziL-kur4)*{twn}<%u@O+F=DTM+u1@Z*V%O^>=e$5Ea_~zn$aj`{%`6aYCh~t>W<7j z#vSHjA+}wAT-+1OEiBGvKkzeW%XuwlQ~l1xi}*X3BWdS)1D9OTnrlI%2bXsn6BfaD zxU1{)+019rk@g7jRGNO~nJbT-&{CLYnvXs{O(@#Py>^Qzm7zzl4cMAL=e+J)gl4pI zP7HMp3{Ni^snUFjcl{{Ek)(%hr@LENBRKpN6;6lMVCUPmZz@IByO_mMpKA}g^lrh@9u)0v z{wfj&Ujk%^`QevN#w>pv*8RC@RV51TV&cli>p+OPyFVMr#Hy`E7iZHz+KmAV48lb3PHYZBO=5fqTc zacpU-kjPx@vIv&6(M%tB2TmW8aTD753>?i<_~^%)>mpNQgbdV*=}+6VYwfc2KYA+b z|9<<->CVItZ-xxn{77N?bvp2rOJT`RUI}e?+gPOfto$omm3*H0!cE%%`bpClb@lP( zo5~8Ga$c<-&qjI1jAcYhEg%ESW{M^|($MOBc@PR=_rT0KYywfeR|p;z1~11x+HUk3SKEr!)E7c809gw)A#><= zmZ0sczgnv&_-ee)+-xR=ECc#!(w&nFG>c%{`o(qYgD#-@9B{0rX|r=+EHW!T=rwik z#jUkt+6L9mhaXon;6=lWGHT8F(}^QasiQ~-zY`5UOs=L{d`}}^ECML!HQAKUz7+HX z#Z!eeJFL*8J*@yjDC3s2n<^lisL%!NN@WF}$O$5B8}UP$D(EWmW)|BUasOFIF@qW0w*DSRgChSQqIiLs`sg<8#`*b10Xay% z$XxU+gSlR5cQWqBay_@9;PEyxSYKSs2*GElXq)!~qqn}r&8iZss}UdaK?YoiN1bPY zHAHf@xR)5U*`MtFN(%pG6W9`OGc8IKbV<<(iYgb^DEg>Au;@ITV>folS6(^mLuanu zynJoUF05>Yw_*#HU~FSiMM%_ZkNR1#2!pCFDp^dYxAD+nc_ry+ti{7??pe8t?+vd3$3Beqxk!{aJsxd-*x9=NRZHH z+E>nH*8~Q$o6`CkLf1=FE6n>GPW1)pvoy=~qeR{2Cva|}p(82*p0HFDg4T7?EzbISK@APA8=<(V6c`C(=}`Sew)!7Yk^jTX z|IGL1SMeW@SrT6hPtmq%SM`_5BvhJ6^Ci!r1htI0OefI1@y#$#h2qIKbKdml z+%QRh-7W5p|KZ8@3OKP?%g-JfzM$?r@Ohp_1vOU|(bLn@3$-k$cyJ{(b>uMrPDGTD zclWaZ__WGLgs=~{55r9YY0{Hq&mhks{?y06;r{}_@ef1IlecH|?aUhsZty?XCMjXRfYw|CS* zy8{BORBp}?P*eTHeZ>}*x?|qdypC%HHf_Fyz+3|8UHJd0!2cQYFZCJ8|LaHjpYdjh zxw45&Q8A_}nvn&iV7S56T_J)IdDBT8u+Rh_mk>Q<(*5XJH=$Mc4!DC)W-U*zjtBWg zAG+_22(Pe9tiRNF>iyI4K%=)PBGzf@7B>?njb&vKJP?}qaeUP9k%`BWb7X8K!Y9^c zs6=Y<(?{7<1dTxoJz=yi46K{`D8Rf|a53c}YYM}IINwj}q>oit$~OiqYr_M#tA1T^ zY<<^x_ORjG3Qy^jr)b2TM4mSKChGdDJSZBbzI+!98@E;BGu-Ru-jmOx=aj|Lc<><57c|Une;XpS2XReZc1H1Xw}9eii72{JFLu({u`o*;?7?9JM96a)ayqGx8C2?RA zo1G|^#TfCr(k+6Uh)|(?GN@*L7swcC@~D_j1BNNcRHE)LWtsiWAn0dv+y3>k)1S9D zzt72)UjlwJt*R0W{sg9yhD*q8i5RZlSw5FTGy!#@J$s5EgHks4ff|yMgYzMFSlySn z5f~!5yFrhkY&|(Fz&g_SR~F?tVfDtA@~}(NlRSL!I8QEXSeIS#>};pYdb&F@jzVNu z-E0Ur&1MLdZ-b%t#W@epR35rKT&Ew4=)tr( z@imzLfI zA92mN)z|pqdA+5D^{-6174MK$D#L?i(W%a}pv6-bnS#&dzKZ_(U@C-&Qc<)vo&zZ(s(plMG_o*Jsn#q-3Y%ht+tP3}E-^H@N;?(h>^ zgU0xWafW9(Q6mEb%`Qy3fAgZhdsn0s`GB7|5b0D29%hy3hZ{C%HKP4BG1!@+du{v( zL4PH}3h_~DZ@`P}9?eLdnMkOQkpjWHJ*I5_Jc;bH6eWf1^|4PgQ$Jl>L z?Wcg=Udm>4{gGE>{)+csu5&%J<+`!P@oGV{k-Dyv?fLgss<(Ba&oXC&iRvg8%~;lb z_zTj}&uyvy=0mP4UjAsHC?$23s7V&t)7I(QbYKr{E}iNHNwR)XS3_207&dK;AhUv9T%}fHtT@?3@8FKqu#w7ouX}7lzwp+`w5=@T zX0eDGldA(+i55{iX#Oe;VwF{sxrQWwDkR(s(|vw?E9g7UveeR_K7%#%tzDH5{! zl}NGT_*^Tmo_!vTn#NScdu%Y$`{*gnB;C@w4s-1QvM08arWNInzii0`UJ|aIrc(F( zc3$okdm00~k{uK8;^g%6sDk;@K3q608d&wpBDV>ElQjSf(N{Zra9ZMNpUK&lRVPc> z=g96g*gc?McA(kOy$yG^c`?q&d=8|N@$4vp2o!()ZQUGiGO(v_@2~6IU%SE8GEN$= zHmEH!ROnO6cWls`tQvH4&}#Z~ zXsF20uh>fHw}#%S3Gn)i>x8$(H_yXAf_@>>!snt-WeGlNpzM~s=-ukT1tM z5U{XFVjWX_{BI0D_x{$%D~pYh2~tEC8B@Y=iAzRNThK^>JZn4<&L+{$B(cZg2~gH0 zwUQkx%?-?x!D?BVmEX;8F4A@NpF~EG^vd7Y(t<+OLZ=WS2s0GN8}*prS>`Dd01ycE z<%|mZP4VYq+d7<<{JnQ-P_UPHmnoznlH+Qq357TR`L~I1fk|$`a2yHplp1=&SsDa^ z-`4Pw7#^7yPL&2qjYe;NQk zDx?xePV>0*eCx$IJuaxU?docLXRPgn#*HESZ`%9ZCBzIq8@!}aRlCoE1OD7u>Z**N z5{Q!XFv_Bi)K*FbYGPG!1lh#GgbKWy-MOq^37Vd&|0@x-%03gU{+HJjl`DbQAE}c| z8wlU)3iN#Bj0?<7Q-cWV+nPr{eAXonjK4w&SdDA)0gthZbG?qrqqQIWfXfaCFgHOdDAcg-by!)w zevUv{G&;5qZF037*er76`tXTR{jF$d#qQ`@Eoz;jh_4}Q23)a# z#S0~~NJ`S9MBo0xlFUaU&3Iva(QM0}Tk^$ix02afKBGlAK4yc@Z=Or+%@JI;x_+n= zHw*JBcfeWHV`H<)+g7T%ONwe-svoEpB}SMJ8e`|!_(Vl0alIIz_}~*a^8i zqcxoS0F>qV^3z)837B$Pf+6OsfgEbuk{g_u8T32ycwzIiHz)b{$@k+EoMP(_3Aj=U zpRyv#JZ>xx=sJA7b@sUYQS;&(&g%cy_bGczJO6Fxv<0^EiD)lL@F{A#|7Xb4RDjn| zk{Snx-RsvAAkC%PXGwqmN2)!D=jiLI``7K6Lo061GU1*f>7xYc!^hn^$tTPXMw~K_ ziyryMl=2!m)(^deW(sjWO+yD@XRjy=w&qFkDRkU&iDX-$DXm@=)by?lbsfu{4tWHO zf$*zY<{G*n{B9Z{$w#{?cgT%`el|Z?eEi;iW)MOojY7+ZO4T37ttE!iCvz zLn3UqetZA=glqs+^A6}!C6k^0uv9Ugbninin<{=b2Y?n;ryXh%ymp31n^X3x@0vB@ULiYF-y=%SsZaVglsxPG- z;U%0k?8WEia;f0U!+**H_q)X8b;EfM40s@BNkouRgdvviQ#0b3&TiYW;O1W7$Itkc z$V1(!)uX=!4inQSG}`XnGnxsR*YKFBp=Yyo@K#;u_WIBwQN`g#)?=ARVc~Tk!c!@w zes^)+hS04pPGI$yYsxhJDI?ir7YT4WUQ8g(PoP$>2Rxi*mj{vDj_T6t>}iwXNcw*1 zCrdrQ!oJ>R98~0~-gBF|>uoOVFQnYvLYc>LgtowYGqTZ^)atuPacmehku$y{NQ7Uh zc65`edpxtVMW&Wq5AI$Feq2i3yecDT_-s|OSWb*C+#N@rRBr16f&~fN0{FPqm7q@c zSf?=%YAav8fuor29Fdxi&FO-73NIr#rUdh#&xlZQ*2utbn~GVdEbtbzmUVy9_cp8L zD9h*+pQVBnt3pqrptWHgV~3FLtaE8!um)BeoNt%+5GeGfXuVI)&aF7Q%q7W(q*GPy zzgVS*H*rZ>hY-RHM~A4|k@I?Q=0weI-qju-a`-~j*bF(|>*Yc&Tk%y+%VcJ32e~|FqJR#A{hosa2?q8R1i1!tH`VS83=-Nop@Em5&ehW%PX^Mi1wx(ib+WzNKodr>S{o_5DQI z+MDgWmXG(Puhz`qoJK!-hh)$gzC=WaKPCnXI2{83Pv@p6~E&%b7hXvAq{MX=XX=EVG$-lMh_be7nUlU;LAtPx02j z06fcA`DP0G%J+##X-%X>HE0cyhVi$D`Bl;nfC!-?1sXKNpxB@r4e`}ta(HS4!U(1Ypw)4d)G9yMmMJWMQt5o@}sX}IAce$%fH zj7PpJUS5op2@bt?QL22x_e%G+2x7B4Shq45;;rWJKHOPY*?!nlcH}$PncZ6Zx|E$e z#WL^eD}wHp&vl_JmJ=~X-E(1HBH!;N*=>(qpd=Lt)Xx}}j3Zl1I;mB(a+aSdvd^QN zdacfNF&*>7ypmJ{ORX}lD~+s3eXZVZf+;1Y8$jx4QvAo2%vEj!=74~({ktu#k5m6S z6I>|j!`B?)x?f7sC%br&z;u&X3Pvu!{)AC2#vL#VWz{XjA`5%_7-WbSCgT5%$^T-A zXR7>VIqJ)WkIvPFyJ=+_MA>vS`wX1-tVJ;VKNfrSpB0}OWCsK@zk4P4 z8!Tz5B;SDWrOv9P8IHNAL16_AOF{kIPx6-v^PN&SKbNjBer!o>r{!A6KyIENyfzlM z=2pLFWmu~R(oO9N$ELtH>f(hvd*V4RZ~Y`9o-@+TS)jj5bTcmym>n@?jl9SM`Fc6t zI8w$)A-%S#t6g5pY(FL>J$eJuR( ze!gLlIcM0|p^3R(=X{_K%|=Q@dA_|qIA>+?VE9652#dw$L9x{ceR{gZhC2nZ&;Ytf zrkg&%n=2sE(og3h@LI@}s@Bg$)@^c&p4&(rvBG?f1BxF=iIsskSCX$v>R#rfr#jnV zrD&vNTt|<@2flIq7v2>`0}5oxaNip-b!T=*td z@_uwfNRiJzZ{bImB@c~jjH&v8@fas->W-FDIm)dw7 ze+D8ohmVc#P%cId+f_-MS2r5l^4pX=79J9+rciodfuaj!=Id7 z?pKRJk{Ek?WSfd@=}9%oPsa^Nh76jYYUilD8qTBE4}CG4FBKRFzn&u-^=lUz$00Z&>QQZAb4GDbIP+ocn)3vA)K`?cou>WSpIO&j zd}TJ~m?FrF=v)gv0H7 zTz2-$BGr(O4i!9}kdIt3AL!J#nzY8AaMVkFzMpQ9%D7_D`?g$5+}1cZy@p&K2G(~~ zYfo*B?@CDE?bh_fD>f_yr#`wJPAedCjaLv+WNyB9UkMwkT_j3Q;>yAJ1N?z7X?-u4 zKGnAI+>2@df>7NtYAlHRn>z*G^|N(3`JY>=FRM3<2%d;>F}7WfLrPrDQ4mPZaKa{R z=*-s6GHd3+(esY8Tf^u_k6Cq=LcH8jH1;6HSko>;sOTfp+-5`+4b*86qFK|3Vu8V& zO{5@Vb?8}5O@EyA&qB|gcks%wmP-l1Ak%mEg@mMTw$p3q&LFkgi`p$#-VYzNm>nhIw`A*g@a_dXt_-(<2 z=Voy-wWo>4FP^k*`JbP&OVffwi>y@ebE=G*s9CuY0bZ`=z)36Yihjq)5^_?m?+m~| zd^Kv$k1q@w85IZ^h-nE*4{x@cjn@g?$2}P8qi{*VIx6F;Nh10F&A5;c;$hvuif9E)=s!jxL$6`qeFi z==(3xpi&3i{ao=Du}JLK5~^e80fWlBg1lzg1m)*hd+$CD56+}PvQ+xNeWKfm7|F4j z8aA*O2P`xctuz<)X+>@*`2_2^ktgMN1-UWEs*5TYsl)__Nko<>)qth);^Vwe^fgz5 zvZJzaL^Zg z`i7<(YOBu3fV}B5ThX_4H%AZ>Q^^Nl5u^#?iobh;|4=Nym>F|Csq^*6^D)NE^?j9H zCEJ0FIYTqoUZtq@7Ot%8$blrkj)-C#Os%-lYmAy!Pj|Qp3Ve3RVHd z3k{16o+cZYTqTD#d}s6J_|y%a4p0R+?hQ&3IUhMgglka_4tI1qnm3v_2dj+q!P7Oc z_WArtR1;uwxGUzpq|2iR#wif&jVk*9ZckhD^z`|>dAoD=r;N~^u!$mB# z>Ni&{qG`{HW-!?6-RkzHqs}#@7NZ`C%G9^h1rtn#hHGYVE6g*0fwNa?lr0k9z#iUr zaz>}{)1&GXPf~R+qm+j(ReZt~bmu?bPecTy=p=0AOkfHLIL_Mm&9B+9q_3BITi5;t zc#EauyiOC+QTv&RNPi8A-L?9P(WIqW@Y!X?3i_5TEm}KfuAd2DN#f)NBpc%09On-g zeQSyv46?y{5$TwHm*3{Lh&(=9E(EI!J9U%9(Myc4^R}3UzZdqRDgx)f*Qchnt)- z4{_Lu&KYA)6vY58+Bf5j@LYH7d`fz$4T^WDe;NTNP{C@sy_>=JBmB6H01Wm(DO%+Q zk58J_f<=<1R_EW)#$O1&ogQmr>D~6vnJ~0QLCV(Q0IHja{`Otd$ag}DP)WT=m!+Zo ziMdj)b_vc9S=9afE z{GDMXi^aKpx6@cAQt+C0EU)CJPD>lx*2!d05;cH*g>Y2HpuTXdg% z{VIZy$okZth~I4#NkpFIGE4;eta{d9fNo+*S(Vl!mxhspLbr~Bcn}qjTpl>(pPb1f zhl%2e8o{^aG7(9olyQpkYjur**Z$*wAB5JcWF=aEgTL_kaY{qi|BXS{R3*ti8ebge z%{Kly6TgbTy=6taK`)?|M10Fltkrf)0C?uy8LAUDNKcp3&J@V*ti8$8s}k+cT`%I7 z!-wq)n@h-*9vBU$B>qL5_{rHY?*&wd`RS5y>@LD(;IAsCzRQiZ({0m(X_eE2!3SghIKdsRK zy@~X(K+mfd8xS<(W_2SxEY0!=(br0A_K{gUbto55i_hr@mVb0I%aY+aBN97*LUymS zczXipeEOQcZ0?k(>d+S~*6!rv&%p>*sM>5y*6*PNt|hq_aO6(kwC8=LQ(%%6$|)wB z;rkm*Fj@qo?h5BmjY@+dp9)J>QP;Jkn$ZWUMmnsLEHW(Shn8Z(FT zfQ31&bU|?r2@~pX(~uO)4p_)?FD((N_NXM)mUZ4>ZM}oo`g%~Bb}{ugX6I`}0d*`t z&E^gp+a*|Ldt$#Y+h3}$5yh~;jV39 z8jmbL`$1u-b9D+#DVN5i7U83gXx_RicSU7Q(E$lOUV%!u542RQq{f(HJDdvkvm~334 z0-<>7DI(fIYv6E?ZuBf7vJiSm+U=#LuA>*#3q>!77}7@HZCKU zlz6vN@US-FBs29q`P42m*S~*X+FAFNV4f)F2SJ-k3SD}v0RIKTk=aHIQoZ4-6cveF z*9Hn;~>umIeiSr&AOEZPcSv z8O26(`PmQ%NsFxmhlB7zIHM*J^-L+aX}{|OQz5B*o4=zC9$K&!;%-?cx@0#kbV>?#ds@xsMQQQnVuNC;K__Vwv-LRove zWH>fXt2)h8x^Az*mV0m|vChy}%EPjmhwU;UW?Ec`n;-qw8R1Ka>JzlHe>-(X>sOm5 zcbLq`%7M70_d*+Xv%V&rfxBoc4l}W7NNkB~t*PFg!1&kNRdaC2QNtl$w8J_hIAXx& zv(x>zx)ZNz8Wg}i*kmi`daaYWT~e0-DdBoObA3)6DE+V-P!qD`6-8z zkCnci)0ktA5I-{DrqT(c%lI2Q|k)BMN&8tihXhVaxpW+R4Ihgf}_UT5CTj&iHZ)3%{S2TL$vM4te2jf!V zRPVg>D{LV)MM7w1e<^$yEjBWvc15o|AKMQc?3+!xSKo(FSHtGI%eJj8d2EXkt4Y zFr@#fzQA+&`Q>%6we6U?Y+!>y{U(f2htr6Ye|WLW(l6WDJ|xc7tT%jEYC^#A&uDK3o12Nzi3O0Z9 zwjV3VfGHT;$hTvtT1o=c=1uAxLP&Oq(`?$A0EEeQiPy~GPqM%o33kRZY1x*)Tkr3> z7E#|6u>cdUwb(C-jA*aIa~y)7#ndJybwiR7pkv~Ie$g$)LmOnM_iS$}or6r|C0=W; z@2o8DepZlfRQx#tM+*};kVIG-swcXsi<-w8jJ0(|C)%3;cM2)Lr@bw;voHY_YiGd2 z&xtYi*XL`fUG}BkU*%QPA)0?i!{AvTqh4ShRVS>Y`pIRk-O|EKYE?zxAy>==x)G}c zvw47gO`l%8*a4=JUyBc37#7u^{bQU{eP4b%5TVQ1liitY7}9}J(vLSPR!d5fM+=4H z8Pp=&PN>u>A%p{PlQwME9z91itn7OgO-gv88tKVeuVab>R@`#o_v-e%hNT{9&wc`N zrMXCY^>ol|0k>tTnyLhs&1g|Y2*ts;*gG1^mS6m521>wbz4OV0J+L5LZ@*}M?2@9I zTbC#wM6~ew(kWa90}H1F|BP0dx}~|$mh_5Rl&A%Kl>PQ7Q6AwdF$r{d2`d8v>f;h- zkl%d$GJk~pPAu2oX}q-Er25a9)W2N@{?|?Yzx(~a>G=Sz+GlHt)V$R5{L?cFN$F3a zM4lnqDD~|^Bi&%HP`E@_UH&?7{w*beN1O$Dzu-n95J@~KX05|>Y%K*kOpUa?FLayC zkjkACt|-64OBYFe`mg|?M}n@`2|mOoR$e|1vD51O<}vPV?H_AzeRx7HI3=|5V)r?p z&6<$N&@95;#b79{phss}Uo-VsUP1sM0=YlD4q_yiiNc>1fjWC*(cJmY1(yd)i`w#Z zDhAp_J|9}XC?A(F*2Ns|SYdlt#9%)Mt%{slh z(CN7elOHPI4j|wDl$)x_FOhRJ5*Puc*;qaxP=IBh9IEb<*7F|A4?v!JKSg?ZA#ZlCaW;1C!R>j_V-J*35F{_qIg zR7!k4_s^MfudMvrr*%7S;PuYk`s*b<7<5&))MeMe z&7hSFAPL(8MFD3Fly9P(wKpu<$_N#xrK>SKeU~EP^112UutH!qMRzBdHwVbblK(|z zlJ%u01#t58Ib3~lp-n(jU0toe{9i-9KRpB9*N>kuu-p13LQAXMyNnPux9fxqSB)ST zj&g~wWy{#L7(mmv&(LtiJz7v+xVUbu2Qu>HnO&(#ymqz1KvJ8YISX*9B0f!$h88FE zMs@C6wOd~I;Jf?c?JrQ|zWO2k-uIxXY?_Rsx5pgq;x`iWpn3X~>fOdNeROJa1Y|#S zlk)Vd7ytH+AA?>q!AP2oeVTeDXSi0O(X7dQJIXC1qfk@UuxByPGnvoO!LY0W1d%co zrsf%+`7ioZJ~e~0D}iP`WLFB{;%3pXzh6xyNrb4qk*@EV9?~GxXjq7StGzPEw6Oq+ zEsU9u;)wEST@AF_$yVM#V1p@FiRbbJvt*LSHq(UW?$bg}IOG4MI?t5R_IQ1N38P)B z@X(5d#_y%zL{-f73ADreT!rXE|FIy

~@a9F<$KRlkj)trfmG4#~EHbki}$-45AX4}YW5)!rJ z(Pf|CMAqqPNdqQ4Y<#IDm?i_Vel5E{Ayl#c{Nh~sJL7zE@&1&JReC%|a2(Ynffv%P z`}l{wLC;_HfeDL=o6fS|_EsuT{%7{JjVVDHCp+=e-a7Ckk7o8BtWthp#4pk*{ z>a}Iav%I>>N7yfEO8cM#-situ+pbw@D0g1pX zx}QY2D_DaEPzxi2UP_==w9ZY|MA&=B+9}|1^1{j5h7pY`m-9gn$U24!+i~xMBsM26 z#|6sq^MT%+iZ@RVYWGiCPsILc8VX9e4l6Ym9Is3vwUM2JuNAc+EL~ju9l19gpik+6 z{XAL}06vR(0&v1&w5(9#9`0rVxoQc1m)}$HN75&GI*invz^P1+O5iC-NATxigb$@5 z`qo0Kv=8pTaz!E|_LYOVai4LMd9HzfDzaaOjkCC^DsnUY$`dkk6E07{jRq>Pi@zE9 zmWIcF%{e{U(>OdIG*CSeTw2`Luo>;Z!ghZsD}$*R&DI;zo7P63Ku8d5YZnstRrh_`-HZkyLaSOZuj*i%BCwqr1PoH8ojon* zzl6=bi$vXmQQ#1X%}Gb+l}uuL0>^$A^1;xMvl)BBG6ByKAHORpVe#0{<^A|jp^>@l zUx<)uO>eH>6|D*(ksP5)lN>QStIoM9$5%j&!4+P&Zk`TP|HZK{IpZCZo*QiMklDxfw?Sm%c?UH@WA#|@)>^9Nl-I;+!Xwh% zq*e7ksD;y>bhWuOVy=4CG_g$?=v`Gw;&RO_%gVl>B;y-nmp&Bp^a-tcQF zH~77aJu99Nm~WiWR3XR^CRCo3%IjY5ydLXc898y%7*J|s8i)Q))U{N2r4#XVRucs) zG7#Ha)+1>ye%H76pf?N84M>#6y3Q@4?JvHd!c4;$4Vdnj)3m2i+?jqqrm2>_J` zFYG&^q0F4?>;Hu?uEn8YP2S2)C%IseV8di%BEY#o#iX1nV*eX10ow2zG_bWgKv$#d zgjfsjUJ+h1Xit;Nb%xYAH;o%YPdMtYzrR0YEAvXqd4@@&CmerRG$r&oK34j4VEr!# z1P$|cV^D`h26_y+=%`N`$RIm_mbeYv4Y*B9(bO66MJPOTsUz8vLdy=H^n21`Y~*)s zP_^35-(3e*s+uNSq2M}*M<+_=n;UG24UIX}2&9SMIO(v;$A3%c*J#K#MrEQk!k=o? zI~hVFPbvdYGWtOziwwl(MY=v)uB82g*~b8(oPE2Do`Qtzb$D<^ssuqyInC8oGZSsZ znK6ZZpcZ?V+4NXknR?hb$#!xLqVb;K=EJYl%1gW~sMT_ROceGPqH!6Uk)?wi<@@lL zL9!k$#DZ3BHytr|Qrqcfo=tT=^qwi)`7aype?@XOx_Tw}?p$|>aBS>H!QmpP;fnN! z!C@^g;UR}rR@cR$&VdBLUC2qMBU!08z-iLG)l1QMq3Twy5n!n7ko3wFm1A9~>!IUC zbcWfj^^@9%AZR5< zNhJZ_i8rkZuxms*&H1|kvTO%z;me;PmQlu+_fMMCK@qq-8ITJcf6@yI5!Kt<+mZVG z)Dh}bK>bsRmGmhcZ9=fvm9M_(kNra8t1uOGVKzm7EmQ-lb)gxVC*Z6Ovg^?Tn$i38 z-u}qgH_8(2Ms+?)O9Em?PH(@O^PFx%fs;rj}9oL2o^?jo>WaL7|2vAo5y*;(tqy> z=l0YJ`r()MBY^VbX6VJ@2+7@O<@r8kcF6?5ii}^PX0)*gj(4tDE75ebIvZOM-kvT< zw-%^+f4)RmJ#ckCOCX` z!a{X^6r)F^crEda^LZA#g6l3(Q2Y0gEPaUKpNarC01-&0BiLU7LFEaq#w#;1OBJ^d z{!gcbK5Z`jKUW{8#l<(_V`-u==f4{JP**hpIS76>azO;9i?zaqS@sTMW8?Qj-UrtK z)H5296wqq%r5o0l{FKi1w^Mip-?&iCN*H1yAJy{fzL+nd3A|a574VtT!2n#$aMk-j zgmz@ecWsd9|ItFbnZ0n+KAeTY`3shZD0LIik!AN;3-sDOivpc>elCfm9=lJuJnR;YIpK^qlavv!-%X$Wu`Myv)U7X4aJQe6Gd8;`*f5AmTQh6Pt&) zztyJhNa37nkvC_VxTQ&9AJdqycvH+)pYcwU&>hR8Y2>hw7R-TQr)iDX0RXMkO!WlG zvpM38S*jhEm-(ik%@bAo16_3|gUXxp0-2r2HjbpWX30ZJS-_n0d;r|% zvA(%ixYu&;qcyN0J`gdl$eke^BV@K@6s*w1=8sw8h3r#hz!^C4 zuhkP}e$C!`x;f1B0^zGd>I7BMQ3)_er0x58d! zXy>%Qrb7KA;J2On9lQ4A79IjS*tG_}-NM_gceu}8kv5Z#0C|5Zr=uQ37%>L3NeXtu zfPe>|m`6hfCa*x|Yf6D&2Ji?$GCxxzi^)ULPOFATr%sojTQpGTqrwO!~{b&Y5LR>|Ig2J%z7|X&;Xk_ePb3 zJGkG4%)0PHw(7k2S2jy^=3K$Sz7`Z_mq8L4(8fqBehbG|s%>ADAX1scG1AziiNbxr zv*HPnaZ0!q(+(H@{B6ewJubY&w?OtP^-{C0l6ShQd;-lpZVI7>E1I6iwIh@v9^B{TYl9H_N;(u7)#^WK*_+6Eg^YkU0n(XwN$8rqxKMUg2TTVkdjzD|C}(&FYtv z7F*Z!m^l)3aoYWx>c~w+5B`k5T@5bUbJQqy+$pROJXjfJ+A3dovr~=Ovr|m zVo<+FBA;JgX*Fp?q2@sWYckH^l^Mdp&Ow9x-9h`^1m8+{p|`WN1BCX0t?w$QUI`U3rY2f=mXUy=fqo5`0Xx2piVgRn&HCp3! zd5rBrCJ6*kECkcrSux7(f;HJ8!p z3YPtDbhtCyRrTOv+lLS4Htyp%03u2a>bK(t95iZ0Q{&5rD;El4R}MY4@K-;Q31ili z0^W;~x!#gDEV!{RRn3Lcg~HWc0Ki-bZx5}pS>~o%`^dySREck(R*q^SCwBu;I{!ml z%M5~fA}wS^f#89@B9lWrkrCC|*~)m0m|3cr%rsw|I&OJjNi^L-rj@eRRXp}3N%DlP z3KUSxb?YI_1A>!LA`BYd?FDxkP_JgcPe+k6Qek zR)L@@BH5qS+aZ~QZ_%Mfq3ne;(GhOkrzl93VB`DHu*sE_NRR2WNzg~O=e5V-NRsSp zF*#R|55l6Nx*Y5Rn44mqK1hym7uQ6N7GP$J+oNGM#R;VF)HdP#cw%U(9o|5~(oc2X z^J$+tP4gv$V|zl-QRs~r>}7c7cGI2#;clvZZ`<1uNk^B-#5=j|zT!d=hOQ8RtGJiO z+oPmeP)x<%2CUew#MXnBd_m!r=M)=PZie@ut4{kdYqFVFUOagPYCmfV610oC_&O_k z&h4C!(~_ddaY;U%@?@%4&$ob`mI#wAJtvRW`yo}yPo8*wwTN6gxZT`?BWzBoh{5q=!GxX~^ViOB3KHbVx0{mdHo7Qoc zF2&dGf5K{9)+IUDX_~zc$yrDXh}!2vG=}&`xU=#G>Z$nv7B*xpq`>vXZ^xu$8X_X< zF%+l)@$gnDuIgzIGHEB>U&}BfEG!&&rriGbEyHR_&F3}Z&;U`N+apE2f7EajD(8$I zvld)qrU$`)a4_C?>y-9(z!Ac^h~}9?keeZvee&$<*|QeWoIQD_xbBmFV_ptIbq0kW zBBz{T?JHRqZ*-6I3m%sAwcVB+57XFufXNUh>p_P%@?z3RgInK9Ehp`%n8$r;`F|AO zCwA*3vF661B;A!Ef&-PNoC-4eGw~=m=Kr2yYhOZhmrK) zsS9_V=HEy2$?v#hu}-E>m4?psz4HYe*MxxrVjsPvU%@>4ZGL&#&u`!dpQ*Epoe^n*5V!dFpzy z*xJ>9&J0I;)QAihbzq9?m5x6R_U1M8g|EDtgF&&D2oFExpHBqum?&n8QSRa9Y-8xg0mg+EyF^P@JrtgorA20r_PLhx`RvU1)7%r7B!Y5x*BP$tmyEg5{|W z4LJ#$?e=QOe0CQAS_>f1W1o6LEw8RB;W}X&$}nYUJ{=ih-8g96;U(%qy2xh6>g!b> ztt7ha5;tpZ&ae@M%OA}H$ThPu#lP6Nhsw$BY)j<&wwsJG;-k8|zT~+#XI{0`<-p}> zx#^v5BPEK)s;T4FtCQL-^vfUGsC6;)7;m7`!iq4kpgNA<6EFzIE9oF}pN9!0XaeX7n2OPMuN8535V|W*c1SW^FzmmpARw*5T zqP~f`^E*bO!Xvi#z6ThrQZ14ViNmYL!-n2@6b)S?!KWjfs`@o%sc1LZB^Or!GtR!X zGt@TNt*4Fs`};p*&%-Dd`9LAzKz+Q=G}sMY~18HcR`{QeRy9h7A5WV=o*<&I`cpgxR}pJes%@Za>En z$G9akva>1pGCgJ5nrN8jvG|v6u%qCVeag-pES2s(cX!8(;G^&GsT?mJDj?b_kPP`y zROa_Rxj^SHjM<3RN{x#p)5?v7H+FiGpOBRa%`GB^4TTD1tK|4?FdodgBYRwsQn@lv zX2$pDaEj!tCoUO4)PrFZ54#~OPRc+~A5_sFF&a1+zq=D)nv`*8Vaye$Wvlkuy?UZ_ zfywO^+C|{zc4}C&HX|UBq-ea+AWXLFQQn~dEP7S=rW36QKB8<%z`Aq zCYF`>1~<;{W-Hm&UiBLt-Xr3MO&7fcT_8`tm%qUCq(NYs!A}i9UtmzEZ%NP7q3Vr? zgT-U78?44U4r)Aj6si}R6q+uk50NSy$(3rQrBDp`3sTdL!aR{(n-x7^#15s{)aYP5rvH+7X z*L}dBn@(FMVA)OWV70QLxUVcd@fRpKN+#x|66Faaz`?v>AZmeq8r6<{iE=@ zgVJ~C4|y_Ezh`+%iEttBRl!9g2C)jy9VEI zkztC5VnZt1WLwPa<=)63LA%_O#!jG~pli?JWFF@6T)GYd)t#P}lwEJh9@2IW#%A^! z2Y@|2p|~|eJi^_D8N@tw!i3lVjd~vK>m9zqNiNG@@9aXi~;fwe-GFYdu|-&)`{%H%`wJ>;e)zKCN{-+{dH7f3TEt9Ler2eDAxAX46f2k1Cu*Yr{z>vIUn6 z-eYYbs=KcD8?nCJkYa zLvD_0cbCsmW;<+eS<5+kNzRAfL=C3~*7oI1aYbTAdy-qUAtV=CuFg{dN2plwIa=qa z2HwYtx<(?XoK3x;#P}eI8e@^Uk?wqr3B$iw`6UvSFY8p@ z>wa4erbZiMB!v;;IIt5`Q)={hSZi^mpS2g~Y=SszGvBAxofRfL!NS=S?>=mAsZH7R zD>cIwSl6Ve#ZZ7tb0}wk?2ePu3A3!e3ruN9t#Q~vy`h}sQv!{iVLzxT^qkY6lwbY~ z=a31Um`1=VCz2t_uuzvlW>$w>npaBxvVvc)bh?Rl-k1daYNL}pn1nGdsVuwOUbMT^ zHKOH4cu*$3kE)$KlD~*GC2PJVnA7~c-k{P@+s&I_?;mYp+~{TRjKD*ig`4{bPPJe` zbgty+`>XzGc1}pGX8SHnoeP_iNlhvrKHu)%WBB39S#1yUd!F%8C2{rU@#uNu7ys)~ z-hcP|_u`YrqPkK6xiv=;Wg!};IP?GbzlS=1iWvW|(su2)|D55l{A=4;ZjW?E=Kg=A zU4MZ7P*`&9{!+uqhe(wxqvsAY zuuWF_W0x5@h8Z@|C7Ss)-07K#a-V% ze$Mz)JbXfQWd8fp^{wa|PX4?TBgLz8@0~P6{<^Rl)h1;`0@?Lw%ajadF0cAC?eY+A z+iq#fT!t^TzyF;JVW!rH9~Ds#FjTj%^U<2W$M#)(;_}cQ=R)b!Zm-Wtm+k*qikuqr zP)jxL!-`xVa5ho65pmK~yLL0+=aW4j6@AtT-yK=){Y6RMVEjoPxJ_j5k7;BwYjsW= zf4wiWVLqJ?p49FHzZv(pX5+tu@cyee=B-OX(Z@Xk% zfA-;OvE{8a>5mM}wG*K213^t!Cdh1Om-oEr1N zzoO2lpTh3{2iSRv^RO*jwR^l6@xO*;^B8@c{r7rN4PZNI+nB)IyumBtjWo~NzH;-F z=UUF7?XXUj+9haEf1hQ-}21jLfX-bIq(vvLy=&D{w-vAEZ=uiv^z&J*H` zQNVd~JWB0TyjSA7-)z``-AwH&;Qne1DNKS^I5OXbt1iHH<=?`f>e`eHogrB5lR|?# zw`YE;pU}1qQGf0zTY`N7=qiU9I7dXou(*cb`Tt_>y~CPZ+I4Z31w}yxqzf#n1PDq; znoD{@551}oN`TOdfZ$R<>5z~Bp-Kr5sw@T*SK*Z7&nS>_^rJLW@~k}hBaf2#NzxN~`%YagDhL_r}P zyMCrj!4q+~bLRU0rQevY1ra;Sib_got?<%Oq3xkD$kkey`&f~1d@moiO$FVLs-WzV z98KcMN2^L#|2Z4}|1SJDr1(inRETigHoMbbY1TckU=+%TiXO}MES7Q&DIdVks;iu% z6ZX0ioHlTp%?s|!3#N`g{r*Mv`?1IOJ6GeEM+*d++(Bka11d#Cu8e(%z8Hm%!el_1zC zHVMv7jE}Ss8ZV0yw4pA@voIZK^(3>H@M6ecw6Uvu!h?q&L>jCghrgk`CdCQOk1%8= zg7`>2)?^s0);8|Nv+b*zY<%)-7^e|GczvaqYqHc$0oTW1fXc2kNH9)NU>M^z0+3J z>&(p&@tdN77iBUO{~UN{TaXLFkMI`r<7fR8$H9Ed8&(3XjJ%tpWLY5z`n? zgEeMy%LmG9m&;!MxL{8v0N>}B=sgptj}^M(39?`akOao|zjY+V7Z2R0aok{E)zi(J z?YBQ3T{d(l#hIj*cgbWt=zsouaz3Eivo32Un{l#HDymk7+~|3_5MD^h)6RTSVX={K zZBW9*wHonzJepU9x$PE+{)t?Vm$n*mVc6FlxN=JIhBK z0sMOq*n%V4s1e!sI^DieMX94CW_&%{x*->=Ugm1bc(LK2U~+lA(ED*G2>OZ*RG0_m z1M6x_0LRO=u6)3FqTl(n`i;4@1?kjxQ{v2Ns2U?|KPZ2c=PSTBPjPt-v}fh$2-OJ2 z&_`YLVK7gjJJRVvUxDJc!P-Kx{i}WeL*4Nk^BJmla#9#xkpysHetGn5ALUG)3*2{S zm||hcl^v(NpO6FT=Ar6252F_&0{E`?@OocpdysvhC<{6%jq#`nPd=5A7Yns+7EbNG z*{}sUh&nGfvCd>-!UI_$UL(~Eci{Ot-6h=tg^O>J2d?m^FoFC=*I)3BY>a;34rXW# zDE-UnA8X4xN{xnI6~HD(4$|t)klz{8c-WmGr`{l!e9$Oh?E_6^GQx-Ea6x1q}0pf;tj>_ zOHKRW60$_rb2xF0v%MVyw*37~gQ%0)TU02oam%n1o>W8(wdvq=G^uh2=fK=aJ|Z(x zc(D`9da+f^wcMJ4qMVnX%D7)D^=B-XD^)atnOB(j2fgwtIAuP?94^{S`AlCy7$)|K z7vR!Rbpyt1uHVzWDSN*J0F7993bKk+nB>jb(fYEow$%Um5WFhp=n}Pw%-m0^+Lo62 zxZl%nBNjwY^wdT}tQQ@+DA|&AkP7n&;3$qg3t(!|^3lR{DMAfZlvqv!)JeI!*blo_ zFN!9)JFCRCfur<<(iR=HCQW=?8&dnE`_ujGivllhyqIWqxhdi^O)Ad55=K)emIJV} zQJNU>rfc6OFwfKWXX>Bl<(+fWsM;zDh&}lsEgKP3cuq;oxMiwsi}wwIc|?xAj)h5a zZ5za=Y@^d1;|wGf(B2NVVf0`hD*+Z`jjDx{Q0v6?V83e@)RGd3PKl&WH8ra;K}R(; zM~9({{*8`XeU|YpWkEmmnzyDo&yfg@1qmMG6EuKK{sQlZE_3l}S?xz)W01wJH1aEg z>G3(B575weM)^mJd%(JDlb9tf?z8Zq5jo^8skmx%WfH)jG9aFq<)U1Xb z+EjxZMP&Q0csN*9bVf1ciQv6#8V!SO-zm~*gzs+6tfLUwVg

!!GgJmC}0MVF}!L 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 literal 0 HcmV?d00001 diff --git a/packages/swing-store/docs/images/data-export-4.jpg b/packages/swing-store/docs/images/data-export-4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d9e269527ebabda1966f87a37dfe0c78f8947d18 GIT binary patch literal 131220 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 z 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 z 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 JjgS7G{x9FN(l-DA literal 0 HcmV?d00001 diff --git a/packages/swing-store/package.json b/packages/swing-store/package.json index 4bfe5a8c943..b2ae9bad608 100644 --- a/packages/swing-store/package.json +++ b/packages/swing-store/package.json @@ -21,6 +21,7 @@ "@agoric/assert": "^0.5.1", "@agoric/internal": "^0.2.1", "better-sqlite3": "^7.5.0", + "readline-transform": "^1.0.0", "tmp": "^0.2.1" }, "devDependencies": { diff --git a/packages/swing-store/src/hasher.js b/packages/swing-store/src/hasher.js index 700154d2663..17153494b35 100644 --- a/packages/swing-store/src/hasher.js +++ b/packages/swing-store/src/hasher.js @@ -1,25 +1,30 @@ -import { assert } from '@agoric/assert'; +import { Fail } from '@agoric/assert'; import { createHash } from 'crypto'; /** - * @typedef { (initial?: string) => { - * add: (more: string) => void, - * finish: () => string, - * } - * } CreateSHA256 + * @typedef {{ + * add: (more: string | Buffer) => Hasher, + * finish: () => string, + * }} Hasher */ -/** @type { CreateSHA256 } */ +/** + * @param {string | Buffer} [initial] + * @returns {Hasher} + */ function createSHA256(initial = undefined) { const hash = createHash('sha256'); let done = false; + // eslint-disable-next-line no-use-before-define + const self = harden({ add, finish, sample }); function add(more) { - assert(!done); + !done || Fail`hash already finished`; hash.update(more); + return self; } function finish() { - assert(!done); + !done || Fail`hash already finished`; done = true; return hash.digest('hex'); } @@ -29,7 +34,7 @@ function createSHA256(initial = undefined) { if (initial) { add(initial); } - return harden({ add, finish, sample }); + return self; } harden(createSHA256); export { createSHA256 }; diff --git a/packages/swing-store/src/snapStore.js b/packages/swing-store/src/snapStore.js index 801cbd2c557..2f34cf8ad26 100644 --- a/packages/swing-store/src/snapStore.js +++ b/packages/swing-store/src/snapStore.js @@ -4,7 +4,7 @@ import { createHash } from 'crypto'; import { finished as finishedCallback, Readable } from 'stream'; import { promisify } from 'util'; import { createGzip, createGunzip } from 'zlib'; -import { assert, details as d } from '@agoric/assert'; +import { Fail, q } from '@agoric/assert'; import { aggregateTryFinally, PromiseAllOrErrors } from '@agoric/internal'; import { fsStreamReady } from '@agoric/internal/src/fs-stream.js'; @@ -26,18 +26,28 @@ import { fsStreamReady } from '@agoric/internal/src/fs-stream.js'; */ /** + * @typedef { import('./swingStore').SwingStoreExporter } SwingStoreExporter + * * @typedef {{ - * hasHash: (vatID: string, hash: string) => boolean, * loadSnapshot: (vatID: string, loadRaw: (filePath: string) => Promise) => Promise, * saveSnapshot: (vatID: string, endPos: number, saveRaw: (filePath: string) => Promise) => Promise, * deleteAllUnusedSnapshots: () => void, * deleteVatSnapshots: (vatID: string) => void, - * deleteSnapshotByHash: (vatID: string, hash: string) => void, + * stopUsingLastSnapshot: (vatID: string) => void, * getSnapshotInfo: (vatID: string) => SnapshotInfo, * }} SnapStore * * @typedef {{ - * dumpActiveSnapshots: () => {}, + * exportSnapshot: (name: string, includeHistorical: boolean) => AsyncIterable, + * importSnapshot: (artifactName: string, exporter: SwingStoreExporter, artifactMetadata: Map) => void, + * getExportRecords: (includeHistorical: boolean) => Iterable<[key: string, value: string]>, + * getArtifactNames: (includeHistorical: boolean) => AsyncIterable, + * }} SnapStoreInternal + * + * @typedef {{ + * hasHash: (vatID: string, hash: string) => boolean, + * dumpSnapshots: (includeHistorical?: boolean) => {}, + * deleteSnapshotByHash: (vatID: string, hash: string) => void, * }} SnapStoreDebug * */ @@ -65,6 +75,7 @@ const noPath = /** @type {import('fs').PathLike} */ ( /** * @param {*} db + * @param {() => void} ensureTxn * @param {{ * createReadStream: typeof import('fs').createReadStream, * createWriteStream: typeof import('fs').createWriteStream, @@ -75,12 +86,14 @@ const noPath = /** @type {import('fs').PathLike} */ ( * tmpName: typeof import('tmp').tmpName, * unlink: typeof import('fs').promises.unlink, * }} io + * @param {(key: string, value: string | undefined) => void} noteExport * @param {object} [options] * @param {boolean | undefined} [options.keepSnapshots] - * @returns {SnapStore & SnapStoreDebug} + * @returns {SnapStore & SnapStoreInternal & SnapStoreDebug} */ export function makeSnapStore( db, + ensureTxn, { createReadStream, createWriteStream, @@ -90,6 +103,7 @@ export function makeSnapStore( tmpName, unlink, }, + noteExport = () => {}, { keepSnapshots = false } = {}, ) { db.exec(` @@ -131,19 +145,68 @@ export function makeSnapStore( * use by some vat. */ function deleteAllUnusedSnapshots() { + ensureTxn(); sqlDeleteAllUnusedSnapshots.run(); } + function snapshotArtifactName(rec) { + return `snapshot.${rec.vatID}.${rec.endPos}`; + } + + function snapshotMetadataKey(rec) { + return `snapshot.${rec.vatID}.${rec.endPos}`; + } + + function currentSnapshotMetadataKey(rec) { + return `snapshot.${rec.vatID}.current`; + } + + /** + * @param {string} vatID + * @param {number} endPos + * @param {string} [hash] + * @param {number} [inUse] + */ + function snapshotRec(vatID, endPos, hash, inUse) { + return { vatID, endPos, hash, inUse }; + } + + const sqlGetPriorSnapshotInfo = db.prepare(` + SELECT endPos, hash + FROM snapshots + WHERE vatID = ? AND inUse = 1 + `); + + const sqlClearLastSnapshot = db.prepare(` + UPDATE snapshots + SET inUse = 0, compressedSnapshot = null + WHERE inUse = 1 AND vatID = ? + `); + const sqlStopUsingLastSnapshot = db.prepare(` UPDATE snapshots SET inUse = 0 WHERE inUse = 1 AND vatID = ? `); + function stopUsingLastSnapshot(vatID) { + ensureTxn(); + const oldInfo = sqlGetPriorSnapshotInfo.get(vatID); + if (oldInfo) { + const rec = snapshotRec(vatID, oldInfo.endPos, oldInfo.hash, 0); + noteExport(snapshotMetadataKey(rec), JSON.stringify(rec)); + if (keepSnapshots) { + sqlStopUsingLastSnapshot.run(vatID); + } else { + sqlClearLastSnapshot.run(vatID); + } + } + } + const sqlSaveSnapshot = db.prepare(` INSERT OR REPLACE INTO snapshots (vatID, endPos, inUse, hash, uncompressedSize, compressedSize, compressedSnapshot) - VALUES (?, ?, 1, ?, ?, ?, ?) + VALUES (?, ?, ?, ?, ?, ?, ?) `); /** @@ -190,20 +253,25 @@ export function makeSnapStore( await finished(snapReader); const h = hashStream.digest('hex'); - sqlStopUsingLastSnapshot.run(vatID); - if (!keepSnapshots) { - deleteAllUnusedSnapshots(); - } + ensureTxn(); + stopUsingLastSnapshot(vatID); compressedSize = compressedSnapshot.length; sqlSaveSnapshot.run( vatID, endPos, + 1, h, uncompressedSize, compressedSize, compressedSnapshot, ); - + const rec = snapshotRec(vatID, endPos, h, 1); + const exportKey = snapshotMetadataKey(rec); + noteExport(exportKey, JSON.stringify(rec)); + noteExport( + currentSnapshotMetadataKey(rec), + snapshotArtifactName(rec), + ); return h; }); @@ -223,12 +291,50 @@ export function makeSnapStore( ); } + const sqlGetSnapshot = db.prepare(` + SELECT compressedSnapshot, inUse + FROM snapshots + WHERE vatID = ? AND endPos = ? + `); + + /** + * Read a snapshot and return it as a stream of data suitable for export to + * another store. + * + * Snapshot artifact names should be strings of the form: + * `snapshot.${vatID}.${startPos}` + * + * @param {string} name + * @param {boolean} includeHistorical + * @returns {AsyncIterable} + */ + function exportSnapshot(name, includeHistorical) { + typeof name === 'string' || Fail`artifact name must be a string`; + const parts = name.split('.'); + const [type, vatID, pos] = parts; + // prettier-ignore + (parts.length === 3 && type === 'snapshot') || + Fail`expected artifact name of the form 'snapshot.{vatID}.{endPos}', saw ${q(name)}`; + const endPos = Number(pos); + const snapshotInfo = sqlGetSnapshot.get(vatID, endPos); + snapshotInfo || Fail`snapshot ${q(name)} not available`; + const { inUse, compressedSnapshot } = snapshotInfo; + compressedSnapshot || Fail`artifact ${q(name)} is not available`; + inUse || includeHistorical || Fail`artifact ${q(name)} is not available`; + // weird construct here is because we need to be able to throw before the generator starts + async function* exporter() { + const gzReader = Readable.from(compressedSnapshot); + const unzipper = createGunzip(); + const snapshotReader = gzReader.pipe(unzipper); + yield* snapshotReader; + } + return exporter(); + } + const sqlLoadSnapshot = db.prepare(` SELECT hash, compressedSnapshot FROM snapshots - WHERE vatID = ? - ORDER BY endPos DESC - LIMIT 1 + WHERE vatID = ? AND inUse = 1 `); /** @@ -243,8 +349,9 @@ export function makeSnapStore( return aggregateTryFinally( async () => { const loadInfo = sqlLoadSnapshot.get(vatID); - assert(loadInfo, `no snapshot available for vat ${vatID}`); + loadInfo || Fail`no snapshot available for vat ${q(vatID)}`; const { hash, compressedSnapshot } = loadInfo; + compressedSnapshot || Fail`no snapshot available for vat ${q(vatID)}`; const gzReader = Readable.from(compressedSnapshot); cleanup.push(() => gzReader.destroy()); const snapReader = gzReader.pipe(createGunzip()); @@ -268,7 +375,7 @@ export function makeSnapStore( await Promise.all([finished(gzReader), finished(snapWriter)]); const h = hashStream.digest('hex'); - h === hash || assert.fail(d`actual hash ${h} !== expected ${hash}`); + h === hash || Fail`actual hash ${q(h)} !== expected ${q(hash)}`; const snapWriterClose = cleanup.pop(); snapWriterClose(); @@ -287,21 +394,34 @@ export function makeSnapStore( WHERE vatID = ? `); + const sqlGetSnapshotList = db.prepare(` + SELECT endPos + FROM snapshots + WHERE vatID = ? + ORDER BY endPos + `); + sqlGetSnapshotList.pluck(true); + /** * Delete all snapshots for a given vat (for use when, e.g., a vat is terminated) * * @param {string} vatID */ function deleteVatSnapshots(vatID) { + ensureTxn(); + const deletions = sqlGetSnapshotList.all(vatID); + for (const endPos of deletions) { + const exportRec = snapshotRec(vatID, endPos, undefined); + noteExport(snapshotMetadataKey(exportRec), undefined); + } + noteExport(currentSnapshotMetadataKey({ vatID }), undefined); sqlDeleteVatSnapshots.run(vatID); } const sqlGetSnapshotInfo = db.prepare(` SELECT endPos, hash, uncompressedSize, compressedSize FROM snapshots - WHERE vatID = ? - ORDER BY endPos DESC - LIMIT 1 + WHERE vatID = ? AND inUse = 1 `); /** @@ -353,24 +473,138 @@ export function makeSnapStore( * @param {string} hash */ function deleteSnapshotByHash(vatID, hash) { + ensureTxn(); sqlDeleteSnapshotByHash.run(vatID, hash); } - const sqlDumpActiveSnapshots = db.prepare(` - SELECT vatID, endPos, hash, compressedSnapshot + const sqlGetSnapshotMetadata = db.prepare(` + SELECT vatID, endPos, hash, uncompressedSize, compressedSize, inUse + FROM snapshots + WHERE inUse = ? + ORDER BY vatID, endPos + `); + + /** + * Obtain artifact metadata records for spanshots contained in this store. + * + * @param {boolean} includeHistorical If true, include all metadata that is + * present in the store regardless of its currency; if false, only include + * the metadata that is part of the swingset's active operational state. + * + * Note: in the currently anticipated operational mode, this flag should + * always be set to `true`, because *all* snapshot metadata is, for now, + * considered part of the consensus set. This metadata is being retained for + * diagnostic purposes and as a hedge against possible future need. While + * such a need seems highly unlikely, the future is uncertain and it will be + * easier to purge this data later than to recover it if it is lost. However, + * the flag itself is present in case future operational policy allows for + * pruning historical metadata, for example after further analysis and + * practical experience tells us that it will not be needed. + * + * @yields {[key: string, value: string]} + * @returns {Iterable<[key: string, value: string]>} + */ + function* getExportRecords(includeHistorical = true) { + for (const rec of sqlGetSnapshotMetadata.iterate(1)) { + const exportRec = snapshotRec(rec.vatID, rec.endPos, rec.hash, 1); + const exportKey = snapshotMetadataKey(rec); + yield [exportKey, JSON.stringify(exportRec)]; + yield [currentSnapshotMetadataKey(rec), snapshotArtifactName(rec)]; + } + if (includeHistorical) { + for (const rec of sqlGetSnapshotMetadata.iterate(0)) { + const exportRec = snapshotRec(rec.vatID, rec.endPos, rec.hash, 0); + yield [snapshotMetadataKey(rec), JSON.stringify(exportRec)]; + } + } + } + + async function* getArtifactNames(includeHistorical) { + for (const rec of sqlGetSnapshotMetadata.iterate(1)) { + yield snapshotArtifactName(rec); + } + if (includeHistorical) { + for (const rec of sqlGetSnapshotMetadata.iterate(0)) { + yield snapshotArtifactName(rec); + } + } + } + + /** + * @param {string} name Artifact name of the snapshot + * @param {SwingStoreExporter} exporter Whence to get the bits + * @param {object} info Metadata describing the artifact + * @returns {Promise} + */ + async function importSnapshot(name, exporter, info) { + const parts = name.split('.'); + const [type, vatID, rawEndPos] = parts; + // prettier-ignore + parts.length === 3 && type === 'snapshot' || + Fail`expected snapshot name of the form 'snapshot.{vatID}.{endPos}', saw '${q(name)}'`; + // prettier-ignore + info.vatID === vatID || + Fail`snapshot name says vatID ${q(vatID)}, metadata says ${q(info.vatID)}`; + const endPos = Number(rawEndPos); + // prettier-ignore + info.endPos === endPos || + Fail`snapshot name says endPos ${q(endPos)}, metadata says ${q(info.endPos)}`; + + const artifactChunks = exporter.getArtifact(name); + const inStream = Readable.from(artifactChunks); + let size = 0; + inStream.on('data', chunk => (size += chunk.length)); + const hashStream = createHash('sha256'); + const gzip = createGzip(); + inStream.pipe(hashStream); + inStream.pipe(gzip); + const compressedArtifact = await buffer(gzip); + await finished(inStream); + const hash = hashStream.digest('hex'); + // prettier-ignore + info.hash === hash || + Fail`snapshot ${q(name)} hash is ${q(hash)}, metadata says ${q(info.hash)}`; + ensureTxn(); + sqlSaveSnapshot.run( + vatID, + endPos, + info.inUse, + info.hash, + size, + compressedArtifact.length, + compressedArtifact, + ); + } + + const sqlDumpCurrentSnapshots = db.prepare(` + SELECT vatID, endPos, hash, compressedSnapshot, inUse FROM snapshots WHERE inUse = 1 ORDER BY vatID, endPos `); + const sqlDumpAllSnapshots = db.prepare(` + SELECT vatID, endPos, hash, compressedSnapshot, inUse + FROM snapshots + ORDER BY vatID, endPos + `); + /** * debug function to dump active snapshots + * + * @param {boolean} [includeHistorical] */ - function dumpActiveSnapshots() { + function dumpSnapshots(includeHistorical = true) { + const sql = includeHistorical + ? sqlDumpAllSnapshots + : sqlDumpCurrentSnapshots; const dump = {}; - for (const row of sqlDumpActiveSnapshots.iterate()) { - const { vatID, endPos, hash, compressedSnapshot } = row; - dump[vatID] = { endPos, hash, compressedSnapshot }; + for (const row of sql.iterate()) { + const { vatID, endPos, hash, compressedSnapshot, inUse } = row; + if (!dump[vatID]) { + dump[vatID] = []; + } + dump[vatID].push({ endPos, hash, compressedSnapshot, inUse }); } return dump; } @@ -380,11 +614,15 @@ export function makeSnapStore( loadSnapshot, deleteAllUnusedSnapshots, deleteVatSnapshots, + stopUsingLastSnapshot, getSnapshotInfo, + getExportRecords, + getArtifactNames, + exportSnapshot, + importSnapshot, hasHash, + dumpSnapshots, deleteSnapshotByHash, - - dumpActiveSnapshots, }); } diff --git a/packages/swing-store/src/streamStore.js b/packages/swing-store/src/streamStore.js deleted file mode 100644 index 1c978d4eb78..00000000000 --- a/packages/swing-store/src/streamStore.js +++ /dev/null @@ -1,162 +0,0 @@ -// @ts-check -import { assert, Fail, q } from '@agoric/assert'; - -const STREAM_START = 0; -/** - * @typedef { number } StreamPosition - * - * @typedef {{ - * writeStreamItem: (streamName: string, item: string, position: StreamPosition) => StreamPosition, - * readStream: (streamName: string, startPosition: StreamPosition, endPosition: StreamPosition) => IterableIterator, - * closeStream: (streamName: string) => void, - * STREAM_START: StreamPosition, - * }} StreamStore - * - * @typedef {{ - * dumpStreams: () => any, - * }} StreamStoreDebug - * - */ - -function* empty() { - // Yield nothing -} - -/** - * @param {unknown} streamName - * @returns {asserts streamName is string} - */ - -function insistStreamName(streamName) { - assert.typeof(streamName, 'string'); - streamName.match(/^[-\w]+$/) || Fail`invalid stream name ${q(streamName)}`; -} - -/** - * @param {unknown} position - * @returns {asserts position is StreamPosition} - */ - -function insistStreamPosition(position) { - assert.typeof(position, 'number'); - assert(position >= 0); -} - -/** - * @param {*} db - * @param {() => void} ensureTxn - * @returns { StreamStore & StreamStoreDebug } - */ -export function makeStreamStore(db, ensureTxn) { - db.exec(` - CREATE TABLE IF NOT EXISTS streamItem ( - streamName TEXT, - position INTEGER, - item TEXT, - PRIMARY KEY (streamName, position) - ) - `); - - const streamStatus = new Map(); - - const sqlDumpStreamsQuery = db.prepare(` - SELECT streamName, position, item - FROM streamItem - ORDER BY streamName, position - `); - - function dumpStreams() { - // debug function to return: dump[streamName][position] = item - const streams = {}; - for (const row of sqlDumpStreamsQuery.iterate()) { - const { streamName, position, item } = row; - if (!streams[streamName]) { - streams[streamName] = []; - } - streams[streamName][position] = item; - } - return streams; - } - - const sqlReadStreamQuery = db.prepare(` - SELECT item - FROM streamItem - WHERE streamName = ? AND position >= ? AND position < ? - ORDER BY position - `); - - /** - * @param {string} streamName - * @param {StreamPosition} startPosition - * @param {StreamPosition} endPosition - */ - function readStream(streamName, startPosition, endPosition) { - insistStreamName(streamName); - !streamStatus.get(streamName) || - Fail`can't read stream ${q(streamName)} because it's already in use`; - insistStreamPosition(startPosition); - insistStreamPosition(endPosition); - startPosition <= endPosition || - Fail`${q(startPosition)} <= ${q(endPosition)}}`; - - function* reader() { - ensureTxn(); - for (const { item } of sqlReadStreamQuery.iterate( - streamName, - startPosition, - endPosition, - )) { - streamStatus.get(streamName) === 'reading' || - Fail`can't read stream ${q(streamName)}, it's been closed`; - yield item; - } - streamStatus.delete(streamName); - } - !streamStatus.has(streamName) || - Fail`can't read stream ${q(streamName)} because it's already in use`; - - if (startPosition === endPosition) { - return empty(); - } - - streamStatus.set(streamName, 'reading'); - - return reader(); - } - - const sqlStreamWrite = db.prepare(` - INSERT INTO streamItem (streamName, item, position) - VALUES (?, ?, ?) - ON CONFLICT(streamName, position) DO UPDATE SET item = ? - `); - - /** - * @param {string} streamName - * @param {string} item - * @param {StreamPosition} position - */ - const writeStreamItem = (streamName, item, position) => { - insistStreamName(streamName); - insistStreamPosition(position); - !streamStatus.get(streamName) || - Fail`can't write stream ${q(streamName)} because it's already in use`; - - ensureTxn(); - sqlStreamWrite.run(streamName, item, position, item); - return position + 1; - }; - - /** @param {string} streamName */ - const closeStream = streamName => { - insistStreamName(streamName); - streamStatus.delete(streamName); - }; - - return harden({ - writeStreamItem, - readStream, - closeStream, - STREAM_START, - dumpStreams, - }); -} diff --git a/packages/swing-store/src/swingStore.js b/packages/swing-store/src/swingStore.js index 56ec40ce430..43e663ef280 100644 --- a/packages/swing-store/src/swingStore.js +++ b/packages/swing-store/src/swingStore.js @@ -7,10 +7,10 @@ import { file as tmpFile, tmpName } from 'tmp'; import sqlite3 from 'better-sqlite3'; -import { assert, Fail } from '@agoric/assert'; +import { assert, Fail, q } from '@agoric/assert'; import { makeMeasureSeconds } from '@agoric/internal'; -import { makeStreamStore } from './streamStore.js'; +import { makeTranscriptStore } from './transcriptStore.js'; import { makeSnapStore } from './snapStore.js'; import { createSHA256 } from './hasher.js'; @@ -29,6 +29,18 @@ export function makeSnapStoreIO() { }; } +/** + * @param {string} key + */ +function getKeyType(key) { + if (key.startsWith('local.')) { + return 'local'; + } else if (key.startsWith('host.')) { + return 'host'; + } + return 'consensus'; +} + /** * @typedef {{ * has: (key: string) => boolean, @@ -39,16 +51,17 @@ export function makeSnapStoreIO() { * }} KVStore * * @typedef { import('./snapStore').SnapStore } SnapStore + * @typedef { import('./snapStore').SnapStoreInternal } SnapStoreInternal * @typedef { import('./snapStore').SnapshotResult } SnapshotResult * - * @typedef { import('./streamStore').StreamPosition } StreamPosition - * @typedef { import('./streamStore').StreamStore } StreamStore - * @typedef { import('./streamStore').StreamStoreDebug } StreamStoreDebug + * @typedef { import('./transcriptStore').TranscriptStore } TranscriptStore + * @typedef { import('./transcriptStore').TranscriptStoreInternal } TranscriptStoreInternal + * @typedef { import('./transcriptStore').TranscriptStoreDebug } TranscriptStoreDebug * * @typedef {{ - * kvStore: KVStore, // a key-value StorageAPI object to load and store data on behalf of the kernel - * streamStore: StreamStore, // a stream-oriented API object to append and read streams of data - * snapStore?: SnapStore, + * kvStore: KVStore, // a key-value API object to load and store data on behalf of the kernel + * transcriptStore: TranscriptStore, // a stream-oriented API object to append and read transcript entries + * snapStore: SnapStore, * startCrank: () => void, * establishCrankSavepoint: (savepoint: string) => void, * rollbackCrank: (savepoint: string) => void, @@ -58,30 +71,190 @@ export function makeSnapStoreIO() { * }} SwingStoreKernelStorage * * @typedef {{ - * kvStore: KVStore, // a key-value StorageAPI object to load and store data on behalf of the host + * kvStore: KVStore, // a key-value API object to load and store data on behalf of the host * commit: () => Promise, // commit changes made since the last commit * close: () => Promise, // shutdown the store, abandoning any uncommitted changes * diskUsage?: () => number, // optional stats method + * setExportCallback: (cb: (updates: KVPair[]) => void) => void, // Set a callback invoked by swingStore when new serializable data is available for export * }} SwingStoreHostStorage - * + */ + +/** * @typedef {{ * kvEntries: {}, - * streams: {}, + * transcripts: {}, * snapshots: {}, * }} SwingStoreDebugDump * * @typedef {{ - * dump: () => SwingStoreDebugDump, + * dump: (includeHistorical?: boolean) => SwingStoreDebugDump, * serialize: () => Buffer, * }} SwingStoreDebugTools * * @typedef {{ + * transcriptStore: TranscriptStoreInternal, + * snapStore: SnapStoreInternal, + * }} SwingStoreInternal + * + * @typedef {{ * kernelStorage: SwingStoreKernelStorage, * hostStorage: SwingStoreHostStorage, * debug: SwingStoreDebugTools, + * internal: SwingStoreInternal, * }} SwingStore */ +/** + * @typedef {[ + * key: string, + * value: string|undefined, + * ]} KVPair + * + * @typedef {object} SwingStoreExporter + * + * Allows export of data from a swingStore as a fixed view onto the content as + * of the most recent commit point at the time the exporter was created. The + * exporter may be used while another SwingStore instance is active for the same + * DB, possibly in another thread or process. It guarantees that regardless of + * the concurrent activity of other swingStore instances, the data representing + * the commit point will stay consistent and available. + * + * @property {() => AsyncIterable} getExportData + * + * Get a full copy of the first-stage export data (key-value pairs) from the + * swingStore. This represents both the contents of the KVStore (excluding host + * and local prefixes), as well as any data needed to validate all artifacts, + * both current and historical. As such it represents the root of trust for the + * application. + * + * Content of validation data (with supporting entries for indexing): + * - kv.${key} = ${value} // ordinary kvStore data entry + * - snapshot.${vatID}.${endPos} = ${{ vatID, endPos, hash }); + * - snapshot.${vatID}.current = `snapshot.${vatID}.${endPos}` + * - transcript.${vatID}.${startPos} = ${{ vatID, startPos, endPos, hash }} + * - transcript.${vatID}.current = ${{ vatID, startPos, endPos, hash }} + * + * @property {() => AsyncIterable} getArtifactNames + * + * Get a list of name of artifacts available from the swingStore. A name returned + * by this method guarantees that a call to `getArtifact` on the same exporter + * instance will succeed. Options control the filtering of the artifact names + * yielded. + * + * Artifact names: + * - transcript.${vatID}.${startPos}.${endPos} + * - snapshot.${vatID}.${endPos} + * + * @property {(name: string) => AsyncIterable} getArtifact + * + * Retrieve an artifact by name. May throw if the artifact is not available, + * which can occur if the artifact is historical and wasn't been preserved. + * + * @property {() => Promise} close + * + * Dispose of all resources held by this exporter. Any further operation on this + * exporter or its outstanding iterators will fail. + */ + +/** + * @param {string} dirPath + * @param {string} exportMode + * @returns {SwingStoreExporter} + */ +export function makeSwingStoreExporter(dirPath, exportMode = 'current') { + typeof dirPath === 'string' || Fail`dirPath must be a string`; + exportMode === 'current' || + exportMode === 'archival' || + exportMode === 'debug' || + Fail`invalid exportMode ${q(exportMode)}`; + const exportHistoricalSnapshots = exportMode === 'debug'; + const exportHistoricalTranscripts = exportMode !== 'current'; + const filePath = path.join(dirPath, 'swingstore.sqlite'); + const db = sqlite3(filePath); + + // Execute the data export in a (read) transaction, to ensure that we are + // capturing the state of the database at a single point in time. + const sqlBeginTransaction = db.prepare('BEGIN TRANSACTION'); + sqlBeginTransaction.run(); + + // ensureTxn can be a dummy, we just started one + const ensureTxn = () => {}; + const snapStore = makeSnapStore(db, ensureTxn, makeSnapStoreIO()); + const transcriptStore = makeTranscriptStore(db, ensureTxn, () => {}); + + const sqlGetAllKVData = db.prepare(` + SELECT key, value + FROM kvStore + ORDER BY key + `); + + /** + * @returns {AsyncIterable} + * @yields {KVPair} + */ + async function* getExportData() { + const kvPairs = sqlGetAllKVData.iterate(); + for (const kv of kvPairs) { + if (getKeyType(kv.key) === 'consensus') { + yield [`kv.${kv.key}`, kv.value]; + } + } + yield* snapStore.getExportRecords(true); + yield* transcriptStore.getExportRecords(true); + } + + /** + * @returns {AsyncIterable} + * @yields {string} + */ + async function* getArtifactNames() { + yield* snapStore.getArtifactNames(exportHistoricalSnapshots); + yield* transcriptStore.getArtifactNames(exportHistoricalTranscripts); + } + + /** + * @param {string} name + * @returns {AsyncIterable} + */ + function getArtifact(name) { + typeof name === 'string' || Fail`artifact name must be a string`; + const [type] = name.split('.', 1); + + if (type === 'snapshot') { + return snapStore.exportSnapshot(name, exportHistoricalSnapshots); + } else if (type === 'transcript') { + return transcriptStore.exportSpan(name, exportHistoricalTranscripts); + } else { + assert.fail(`invalid artifact type ${q(type)}`); + } + } + + const sqlAbort = db.prepare('ROLLBACK'); + + async function close() { + // After all the data has been extracted, always abort the export + // transaction to ensure that the export was read-only (i.e., that no bugs + // inadvertantly modified the database). + sqlAbort.run(); + db.close(); + } + + return harden({ + getExportData, + getArtifactNames, + getArtifact, + close, + }); +} + +/** + * Function used to create a new swingStore from an object implementing the + * exporter API. The exporter API may be provided by a swingStore instance, or + * implemented by a host to restore data that was previously exported. + * + * @typedef {(exporter: SwingStoreExporter) => Promise} ImportSwingStore + */ + /** * A swing store holds the state of a swingset instance. This "store" is * actually several different stores of different types that travel as a flock @@ -95,7 +268,7 @@ export function makeSnapStoreIO() { * and values are both strings. Provides random access to a large number of * mostly small data items. Persistently stored in a sqlite table. * - * streamStore - a streaming store used to hold kernel transcripts. Transcripts + * transcriptStore - a streaming store used to hold kernel transcripts. Transcripts * are both written and read (if they are read at all) sequentially, according * to metadata kept in the kvStore. Persistently stored in a sqllite table. * @@ -141,8 +314,8 @@ export function makeSnapStoreIO() { function makeSwingStore(dirPath, forceReset, options = {}) { const { serialized } = options; if (serialized) { - assert(Buffer.isBuffer(serialized), `options.serialized must be Buffer`); - assert.equal(dirPath, null, `options.serialized makes :memory: DB`); + Buffer.isBuffer(serialized) || Fail`options.serialized must be Buffer`; + dirPath === null || Fail`options.serialized makes :memory: DB`; } let crankhasher; function resetCrankhash() { @@ -175,7 +348,7 @@ function makeSwingStore(dirPath, forceReset, options = {}) { filePath = ':memory:'; } - const { traceFile, keepSnapshots } = options; + const { traceFile, keepSnapshots, keepTranscripts } = options; let traceOutput = traceFile ? fs.createWriteStream(path.resolve(traceFile), { @@ -219,6 +392,22 @@ function makeSwingStore(dirPath, forceReset, options = {}) { ) `); + db.exec(` + CREATE TABLE IF NOT EXISTS pendingExports ( + key TEXT, + value TEXT, + PRIMARY KEY (key) + ) + `); + let exportCallback; + function setExportCallback(cb) { + typeof cb === 'function' || Fail`callback must be a function`; + exportCallback = cb; + } + if (options.exportCallback) { + setExportCallback(options.exportCallback); + } + const sqlBeginTransaction = db.prepare('BEGIN IMMEDIATE TRANSACTION'); let inCrank = false; @@ -241,26 +430,14 @@ function makeSwingStore(dirPath, forceReset, options = {}) { // happens, it would wake up with inconsistent state. The only commit point // must be the hostStorage.commit(). function ensureTxn() { - assert(db); + db || Fail`db not initialized`; if (!db.inTransaction) { sqlBeginTransaction.run(); - assert(db.inTransaction); + db.inTransaction || Fail`must be in a transaction`; } return db; } - /** - * @param {string} key - */ - function getKeyType(key) { - if (key.startsWith('local.')) { - return 'local'; - } else if (key.startsWith('host.')) { - return 'host'; - } - return 'consensus'; - } - function diskUsage() { if (dirPath) { const dataFilePath = `${dirPath}/swingstore.sqlite`; @@ -289,7 +466,7 @@ function makeSwingStore(dirPath, forceReset, options = {}) { * @throws if key is not a string. */ function get(key) { - assert.typeof(key, 'string'); + typeof key === 'string' || Fail`key must be a string`; return sqlKVGet.get(key); } @@ -329,7 +506,7 @@ function makeSwingStore(dirPath, forceReset, options = {}) { */ function getNextKey(previousKey) { - assert.typeof(previousKey, 'string'); + typeof previousKey === 'string' || Fail`previousKey must be a string`; return sqlKVGetNextKey.get(previousKey); } @@ -343,7 +520,7 @@ function makeSwingStore(dirPath, forceReset, options = {}) { * @throws if key is not a string. */ function has(key) { - assert.typeof(key, 'string'); + typeof key === 'string' || Fail`key must be a string`; return get(key) !== undefined; } @@ -363,8 +540,8 @@ function makeSwingStore(dirPath, forceReset, options = {}) { * @throws if either parameter is not a string. */ function set(key, value) { - assert.typeof(key, 'string'); - assert.typeof(value, 'string'); + typeof key === 'string' || Fail`key must be a string`; + typeof value === 'string' || Fail`value must be a string`; // synchronous read after write within a transaction is safe // The transaction's overall success will be awaited during commit ensureTxn(); @@ -386,7 +563,7 @@ function makeSwingStore(dirPath, forceReset, options = {}) { * @throws if key is not a string. */ function del(key) { - assert.typeof(key, 'string'); + typeof key === 'string' || Fail`key must be a string`; ensureTxn(); sqlKVDel.run(key); trace('del', key); @@ -400,14 +577,27 @@ function makeSwingStore(dirPath, forceReset, options = {}) { delete: del, }; + const sqlAddPendingExport = db.prepare(` + INSERT INTO pendingExports (key, value) + VALUES (?, ?) + ON CONFLICT DO UPDATE SET value = excluded.value + `); + + function noteExport(key, value) { + if (exportCallback) { + sqlAddPendingExport.run(key, value); + } + } + const kernelKVStore = { ...kvStore, - set(key, value, bypassHash) { - assert.typeof(key, 'string'); + set(key, value) { + typeof key === 'string' || Fail`key must be a string`; const keyType = getKeyType(key); - assert(keyType !== 'host'); + keyType !== 'host' || Fail`kernelKVStore refuses host keys`; set(key, value); - if (keyType === 'consensus' && !bypassHash) { + if (keyType === 'consensus') { + noteExport(`kv.${key}`, value); crankhasher.add('add'); crankhasher.add('\n'); crankhasher.add(key); @@ -417,11 +607,12 @@ function makeSwingStore(dirPath, forceReset, options = {}) { } }, delete(key) { - assert.typeof(key, 'string'); + typeof key === 'string' || Fail`key must be a string`; const keyType = getKeyType(key); - assert(keyType !== 'host'); + keyType !== 'host' || Fail`kernelKVStore refuses host keys`; del(key); if (keyType === 'consensus') { + noteExport(`kv.${key}`, undefined); crankhasher.add('delete'); crankhasher.add('\n'); crankhasher.add(key); @@ -434,20 +625,29 @@ function makeSwingStore(dirPath, forceReset, options = {}) { ...kvStore, set(key, value) { const keyType = getKeyType(key); - assert(keyType === 'host'); + keyType === 'host' || Fail`hostKVStore requires host keys`; set(key, value); }, delete(key) { const keyType = getKeyType(key); - assert(keyType === 'host'); + keyType === 'host' || Fail`hostKVStore requires host keys`; del(key); }, }; - const { dumpStreams, ...streamStore } = makeStreamStore(db, ensureTxn); - const { dumpActiveSnapshots, ...snapStore } = makeSnapStore( + const { dumpTranscripts, ...transcriptStore } = makeTranscriptStore( + db, + ensureTxn, + noteExport, + { + keepTranscripts, + }, + ); + const { dumpSnapshots, ...snapStore } = makeSnapStore( db, + ensureTxn, makeSnapStoreIO(), + noteExport, { keepSnapshots, }, @@ -457,13 +657,13 @@ function makeSwingStore(dirPath, forceReset, options = {}) { const sqlReleaseSavepoints = db.prepare('RELEASE SAVEPOINT t0'); function startCrank() { - !inCrank || Fail`already in crank`; + !inCrank || Fail`startCrank while already in a crank`; inCrank = true; resetCrankhash(); } function establishCrankSavepoint(savepoint) { - inCrank || Fail`not in crank`; + inCrank || Fail`establishCrankSavepoint outside of crank`; const savepointOrdinal = savepoints.length; savepoints.push(savepoint); const sql = db.prepare(`SAVEPOINT t${savepointOrdinal}`); @@ -471,7 +671,7 @@ function makeSwingStore(dirPath, forceReset, options = {}) { } function rollbackCrank(savepoint) { - inCrank || Fail`not in crank`; + inCrank || Fail`rollbackCrank outside of crank`; for (const savepointOrdinal of savepoints.keys()) { if (savepoints[savepointOrdinal] === savepoint) { const sql = db.prepare(`ROLLBACK TO SAVEPOINT t${savepointOrdinal}`); @@ -480,7 +680,7 @@ function makeSwingStore(dirPath, forceReset, options = {}) { return; } } - assert.fail(`no such savepoint as "${savepoint}"`); + Fail`no such savepoint as "${q(savepoint)}"`; } function emitCrankHashes() { @@ -506,6 +706,10 @@ function makeSwingStore(dirPath, forceReset, options = {}) { // Store the new activityhash const activityhash = hasher.finish(); set('activityhash', activityhash); + // Need to explicitly call noteExport here because activityhash is written + // directly to the low-level store to avoid recursive hashing, which + // bypasses the normal notification mechanism + noteExport(`kv.activityhash`, activityhash); return { crankhash, activityhash }; } @@ -514,12 +718,35 @@ function makeSwingStore(dirPath, forceReset, options = {}) { return get('activityhash') || ''; } + const sqlExportsGet = db.prepare(` + SELECT * + FROM pendingExports + ORDER BY key + `); + sqlExportsGet.raw(true); + + const sqlExportsClear = db.prepare(` + DELETE + FROM pendingExports + `); + + function flushPendingExports() { + if (exportCallback) { + const exports = sqlExportsGet.all(); + if (exports.length > 0) { + sqlExportsClear.run(); + exportCallback(exports); + } + } + } + function endCrank() { - inCrank || Fail`not in crank`; + inCrank || Fail`endCrank outside of crank`; if (savepoints.length > 0) { sqlReleaseSavepoints.run(); savepoints.length = 0; } + flushPendingExports(); inCrank = false; } @@ -529,8 +756,9 @@ function makeSwingStore(dirPath, forceReset, options = {}) { * Commit unsaved changes. */ async function commit() { - assert(db); + db || Fail`db not initialized`; if (db.inTransaction) { + flushPendingExports(); sqlCommit.run(); } } @@ -540,7 +768,7 @@ function makeSwingStore(dirPath, forceReset, options = {}) { * you want to save them, call commit() first). */ async function close() { - assert(db); + db || Fail`db not initialized`; commit(); db.close(); db = null; @@ -569,19 +797,37 @@ function makeSwingStore(dirPath, forceReset, options = {}) { return Object.fromEntries(s.all()); } - function dump() { + function dump(includeHistorical = true) { // return comparable JS object graph with entire DB state return harden({ kvEntries: dumpKVEntries(), - streams: dumpStreams(), - snapshots: dumpActiveSnapshots(), + transcripts: dumpTranscripts(includeHistorical), + snapshots: dumpSnapshots(includeHistorical), }); } + const transcriptStorePublic = { + initTranscript: transcriptStore.initTranscript, + rolloverSpan: transcriptStore.rolloverSpan, + getCurrentSpanBounds: transcriptStore.getCurrentSpanBounds, + addItem: transcriptStore.addItem, + readSpan: transcriptStore.readSpan, + deleteVatTranscripts: transcriptStore.deleteVatTranscripts, + }; + + const snapStorePublic = { + loadSnapshot: snapStore.loadSnapshot, + saveSnapshot: snapStore.saveSnapshot, + deleteAllUnusedSnapshots: snapStore.deleteAllUnusedSnapshots, + deleteVatSnapshots: snapStore.deleteVatSnapshots, + stopUsingLastSnapshot: snapStore.stopUsingLastSnapshot, + getSnapshotInfo: snapStore.getSnapshotInfo, + }; + const kernelStorage = { kvStore: kernelKVStore, - streamStore, - snapStore, + transcriptStore: transcriptStorePublic, + snapStore: snapStorePublic, startCrank, establishCrankSavepoint, rollbackCrank, @@ -594,16 +840,22 @@ function makeSwingStore(dirPath, forceReset, options = {}) { commit, close, diskUsage, + setExportCallback, }; const debug = { serialize, dump, }; + const internal = { + snapStore, + transcriptStore, + }; return harden({ kernelStorage, hostStorage, debug, + internal, }); } @@ -625,11 +877,179 @@ function makeSwingStore(dirPath, forceReset, options = {}) { */ export function initSwingStore(dirPath = null, options = {}) { if (dirPath) { - assert.typeof(dirPath, 'string'); + typeof dirPath === 'string' || Fail`dirPath must be a string`; } return makeSwingStore(dirPath, true, options); } +function parseVatArtifactExportKey(key) { + const parts = key.split('.'); + const [_type, vatID, rawPos] = parts; + // prettier-ignore + parts.length === 3 || + Fail`expected artifact name of the form '{type}.{vatID}.{pos}', saw ${q(key)}`; + const isCurrent = rawPos === 'current'; + let pos; + if (isCurrent) { + pos = -1; + } else { + pos = Number(rawPos); + } + + return { vatID, isCurrent, pos }; +} + +function artifactKey(type, vatID, pos) { + return `${type}.${vatID}.${pos}`; +} + +/** + * @param {SwingStoreExporter} exporter + * @param {string | null} [dirPath] + * @param {object} options + * @returns {Promise} + */ +export async function importSwingStore(exporter, dirPath = null, options = {}) { + if (dirPath) { + typeof dirPath === 'string' || Fail`dirPath must be a string`; + } + const { includeHistorical = false } = options; + const store = makeSwingStore(dirPath, true, options); + const { kernelStorage, internal } = store; + + // Artifact metadata, keyed as `${type}.${vatID}.${pos}` + // + // Note that this key is almost but not quite the artifact name, since the + // names of transcript span artifacts also include the endPos, but the endPos + // value is in flux until the span is complete. + const artifactMetadata = new Map(); + + // Each vat requires a transcript span and (usually) a snapshot. This table + // tracks which of these we've seen, keyed by vatID. + // vatID -> { snapshotKey: metadataKey, transcriptKey: metatdataKey } + const vatArtifacts = new Map(); + + for await (const [key, value] of exporter.getExportData()) { + const [tag] = key.split('.', 1); + const subKey = key.substring(tag.length + 1); + if (tag === 'kv') { + // 'kv' keys contain individual kvStore entries + if (value == null) { + // Note '==' rather than '===': any nullish value implies deletion + kernelStorage.kvStore.delete(subKey); + } else { + kernelStorage.kvStore.set(subKey, value); + } + } else if (tag === 'transcript' || tag === 'snapshot') { + // 'transcript' and 'snapshot' keys contain artifact description info. + assert(value); // make TypeScript shut up + const { vatID, isCurrent, pos } = parseVatArtifactExportKey(key); + if (isCurrent) { + const vatInfo = vatArtifacts.get(vatID) || {}; + if (tag === 'snapshot') { + // `export.snapshot.{vatID}.current` directly identifies the current snapshot artifact + vatInfo.snapshotKey = value; + } else if (tag === 'transcript') { + // `export.transcript.${vatID}.current` contains a metadata record for the current + // state of the current transcript span as of the time of export + const metadata = JSON.parse(value); + vatInfo.transcriptKey = artifactKey(tag, vatID, metadata.startPos); + artifactMetadata.set(vatInfo.transcriptKey, metadata); + } + vatArtifacts.set(vatID, vatInfo); + } else { + artifactMetadata.set(artifactKey(tag, vatID, pos), JSON.parse(value)); + } + } else { + Fail`unknown artifact type tag ${q(tag)} on import`; + } + } + + // At this point we should have acquired the entire KV store state, plus + // sufficient metadata to identify the complete set of artifacts we'll need to + // fetch along with the information required to validate each of them after + // fetching. + // + // Depending on how the export was parameterized, the metadata may also include + // information about historical artifacts that we might or might not actually + // fetch depending on how this import was parameterized + + // Fetch the set of current artifacts. + + // Keep track of fetched artifacts in this set so we don't fetch them a second + // time if we are trying for historical artifacts also. + const fetchedArtifacts = new Set(); + + for await (const [vatID, vatInfo] of vatArtifacts.entries()) { + // For each vat, we *must* have a transcript span. If this is not the very + // first transcript span in the history of that vat, then we also must have + // a snapshot for the state of the vat immediately prior to when the + // transcript span begins. + vatInfo.transcriptKey || + Fail`missing current transcript key for vat ${q(vatID)}`; + const transcriptInfo = artifactMetadata.get(vatInfo.transcriptKey); + transcriptInfo || Fail`missing transcript metadata for vat ${q(vatID)}`; + let snapshotInfo; + if (vatInfo.snapshotKey) { + snapshotInfo = artifactMetadata.get(vatInfo.snapshotKey); + snapshotInfo || Fail`missing snapshot metadata for vat ${q(vatID)}`; + } + if (!snapshotInfo) { + transcriptInfo.startPos === 0 || + Fail`missing current snapshot for vat ${q(vatID)}`; + } else { + snapshotInfo.endPos === transcriptInfo.startPos || + Fail`current transcript for vat ${q(vatID)} doesn't go with snapshot`; + fetchedArtifacts.add(vatInfo.snapshotKey); + } + await (!snapshotInfo || + internal.snapStore.importSnapshot( + vatInfo.snapshotKey, + exporter, + snapshotInfo, + )); + const transcriptArtifactName = `${vatInfo.transcriptKey}.${transcriptInfo.endPos}`; + await internal.transcriptStore.importSpan( + transcriptArtifactName, + exporter, + transcriptInfo, + ); + fetchedArtifacts.add(transcriptArtifactName); + } + if (!includeHistorical) { + return store; + } + + // If we're also importing historical artifacts, have the exporter enumerate + // the complete set of artifacts it has and fetch all of them except for the + // ones we've already fetched. + for await (const artifactName of exporter.getArtifactNames()) { + if (fetchedArtifacts.has(artifactName)) { + continue; + } + let fetchedP; + if (artifactName.startsWith('snapshot.')) { + fetchedP = internal.snapStore.importSnapshot( + artifactName, + exporter, + artifactMetadata.get(artifactName), + ); + } else if (artifactName.startsWith('transcript.')) { + // strip endPos off artifact name + const metadataKey = artifactName.split('.').slice(0, 3).join('.'); + fetchedP = internal.transcriptStore.importSpan( + artifactName, + exporter, + artifactMetadata.get(metadataKey), + ); + } else { + Fail`unknown artifact type: ${artifactName}`; + } + await fetchedP; + } + return store; +} + /** * Open a persistent swingset store. If there is no existing store at the given * `dirPath`, a new, empty store will be created. @@ -643,7 +1063,7 @@ export function initSwingStore(dirPath = null, options = {}) { * @returns {SwingStore} */ export function openSwingStore(dirPath, options = {}) { - assert.typeof(dirPath, 'string'); + typeof dirPath === 'string' || Fail`dirPath must be a string`; return makeSwingStore(dirPath, false, options); } @@ -658,7 +1078,7 @@ export function openSwingStore(dirPath, options = {}) { * or openSwingStore, returns true. Else returns false. */ export function isSwingStore(dirPath) { - assert.typeof(dirPath, 'string'); + typeof dirPath === 'string' || Fail`dirPath must be a string`; if (fs.existsSync(dirPath)) { const storeFile = path.resolve(dirPath, 'swingstore.sqlite'); if (fs.existsSync(storeFile)) { diff --git a/packages/swing-store/src/transcriptStore.js b/packages/swing-store/src/transcriptStore.js new file mode 100644 index 00000000000..2b4a9969740 --- /dev/null +++ b/packages/swing-store/src/transcriptStore.js @@ -0,0 +1,523 @@ +// @ts-check +import ReadlineTransform from 'readline-transform'; +import { Readable } from 'stream'; +import { Buffer } from 'buffer'; +import { Fail, q } from '@agoric/assert'; +import { createSHA256 } from './hasher.js'; + +/** + * @typedef { import('./swingStore').SwingStoreExporter } SwingStoreExporter + * + * @typedef {{ + * initTranscript: (vatID: string) => void, + * rolloverSpan: (vatID: string) => void, + * getCurrentSpanBounds: (vatID: string) => { startPos: number, endPos: number, hash: string }, + * deleteVatTranscripts: (vatID: string) => void, + * addItem: (vatID: string, item: string) => void, + * readSpan: (vatID: string, startPos?: number) => Iterable, + * }} TranscriptStore + * + * @typedef {{ + * exportSpan: (name: string, includeHistorical: boolean) => AsyncIterable + * importSpan: (artifactName: string, exporter: SwingStoreExporter, artifactMetadata: Map) => Promise, + * getExportRecords: (includeHistorical: boolean) => Iterable<[key: string, value: string]>, + * getArtifactNames: (includeHistorical: boolean) => AsyncIterable, + * }} TranscriptStoreInternal + * + * @typedef {{ + * dumpTranscripts: (includeHistorical?: boolean) => any, + * }} TranscriptStoreDebug + * + */ + +function* empty() { + // Yield nothing +} + +/** + * @param {number} position + * @returns {asserts position is number} + */ + +function insistTranscriptPosition(position) { + typeof position === 'number' || Fail`position must be a number`; + position >= 0 || Fail`position must not be negative`; +} + +/** + * @param {*} db + * @param {() => void} ensureTxn + * @param {(key: string, value: string | undefined ) => void} noteExport + * @param {object} [options] + * @param {boolean | undefined} [options.keepTranscripts] + * @returns { TranscriptStore & TranscriptStoreInternal & TranscriptStoreDebug } + */ +export function makeTranscriptStore( + db, + ensureTxn, + noteExport = () => {}, + { keepTranscripts = true } = {}, +) { + db.exec(` + CREATE TABLE IF NOT EXISTS transcriptItems ( + vatID TEXT, + position INTEGER, + item TEXT, + PRIMARY KEY (vatID, position) + ) + `); + + // Transcripts are broken up into "spans", delimited by heap snapshots. If we + // take heap snapshots after deliveries 100 and 200, and have not yet + // performed delivery 201, we'll have two non-current (i.e., isCurrent=null) + // spans (one with startPos=0, endPos=100, the second with startPos=100, + // endPos=200), and a single empty isCurrent==1 span with startPos=200 and + // endPos=200. After we perform delivery 201, the single isCurrent=1 span + // will will still have startPos=200 but will now have endPos=201. For every + // vatID, there will be exactly one isCurrent=1 span, and zero or more + // non-current (historical) spans. + // + // The transcriptItems associated with historical spans may or may not exist, + // depending on pruning. However, the items associated with the current span + // must always be present + + db.exec(` + CREATE TABLE IF NOT EXISTS transcriptSpans ( + vatID TEXT, + startPos INTEGER, -- inclusive + endPos INTEGER, -- exclusive + hash TEXT, -- cumulative hash of this item and previous cumulative hash + isCurrent INTEGER, + PRIMARY KEY (vatID, startPos), + UNIQUE (vatID, isCurrent) + ) + `); + db.exec(` + CREATE INDEX IF NOT EXISTS currentTranscriptIndex + ON transcriptSpans (vatID, isCurrent) + `); + + const sqlDumpItemsQuery = db.prepare(` + SELECT vatID, position, item + FROM transcriptItems + WHERE vatID = ? AND ? <= position AND position < ? + ORDER BY vatID, position + `); + + const sqlDumpSpansQuery = db.prepare(` + SELECT vatID, startPos, endPos, isCurrent + FROM transcriptSpans + ORDER BY vatID, startPos + `); + + function dumpTranscripts(includeHistorical = true) { + // debug function to return: dump[vatID][position] = item + const transcripts = {}; + for (const spanRow of sqlDumpSpansQuery.iterate()) { + if (includeHistorical || spanRow.isCurrent) { + for (const row of sqlDumpItemsQuery.iterate( + spanRow.vatID, + spanRow.startPos, + spanRow.endPos, + )) { + const { vatID, position, item } = row; + if (!transcripts[vatID]) { + transcripts[vatID] = {}; + } + transcripts[vatID][position] = item; + } + } + } + return transcripts; + } + + /** + * Compute a new cumulative hash for a span that includes a new transcript + * item. This is computed by hashing together the hash from the previous item + * in its span together with the new item's own text. + * + * @param {string} priorHash The previous item's hash + * @param {string} item The item itself + * + * @returns {string} The hash of the combined parameters. + */ + function updateSpanHash(priorHash, item) { + const itemHash = createSHA256(item).finish(); + return createSHA256(priorHash).add(itemHash).finish(); + } + + /** + * @type {string} Seed hash to use as the prior hash when computing the hash + * of the very first item in a span, since it has no prior item to draw upon. + */ + const initialHash = createSHA256('start of transcript span').finish(); + + const sqlWriteSpan = db.prepare(` + INSERT INTO transcriptSpans + (vatID, startPos, endPos, hash, isCurrent) + VALUES (?, ?, ?, ?, ?) + `); + + /** + * Start a new transcript for a given vat + * + * @param {string} vatID The vat whose transcript this shall be + */ + function initTranscript(vatID) { + ensureTxn(); + sqlWriteSpan.run(vatID, 0, 0, initialHash, 1); + } + + const sqlGetCurrentSpanBounds = db.prepare(` + SELECT startPos, endPos, hash + FROM transcriptSpans + WHERE vatID = ? AND isCurrent = 1 + `); + + /** + * Obtain the bounds and other metadata for a vat's current transcript span. + * + * @param {string} vatID The vat in question + * + * @returns {{startPos: number, endPos: number, hash: string}} + */ + function getCurrentSpanBounds(vatID) { + const bounds = sqlGetCurrentSpanBounds.get(vatID); + bounds || Fail`no current transcript for ${q(vatID)}`; + return bounds; + } + + function spanArtifactName(rec) { + return `transcript.${rec.vatID}.${rec.startPos}.${rec.endPos}`; + } + + function spanMetadataKey(rec) { + if (rec.isCurrent) { + return `transcript.${rec.vatID}.current`; + } else { + return `transcript.${rec.vatID}.${rec.startPos}`; + } + } + + function spanRec(vatID, startPos, endPos, hash, isCurrent) { + isCurrent = isCurrent ? 1 : 0; + return { vatID, startPos, endPos, hash, isCurrent }; + } + + const sqlEndCurrentSpan = db.prepare(` + UPDATE transcriptSpans + SET isCurrent = null + WHERE isCurrent = 1 AND vatID = ? + `); + + const sqlDeleteOldItems = db.prepare(` + DELETE FROM transcriptItems + WHERE vatID = ? AND position < ? + `); + + /** + * End the current transcript span for a vat and start a new one. + * + * @param {string} vatID The vat whose transcript is to rollover to a new + * span. + */ + function rolloverSpan(vatID) { + ensureTxn(); + const { hash, startPos, endPos } = getCurrentSpanBounds(vatID); + const rec = spanRec(vatID, startPos, endPos, hash, 0); + noteExport(spanMetadataKey(rec), JSON.stringify(rec)); + sqlEndCurrentSpan.run(vatID); + sqlWriteSpan.run(vatID, endPos, endPos, initialHash, 1); + const newRec = spanRec(vatID, endPos, endPos, initialHash, 1); + noteExport(spanMetadataKey(newRec), JSON.stringify(newRec)); + if (!keepTranscripts) { + sqlDeleteOldItems.run(vatID, endPos); + } + } + + const sqlDeleteVatSpans = db.prepare(` + DELETE FROM transcriptSpans + WHERE vatID = ? + `); + + const sqlDeleteVatItems = db.prepare(` + DELETE FROM transcriptItems + WHERE vatID = ? + `); + + const sqlGetVatSpans = db.prepare(` + SELECT vatID, startPos, isCurrent + FROM transcriptSpans + WHERE vatID = ? + ORDER BY startPos + `); + + /** + * Delete all transcript data for a given vat (for use when, e.g., a vat is terminated) + * + * @param {string} vatID + */ + function deleteVatTranscripts(vatID) { + ensureTxn(); + const deletions = sqlGetVatSpans.all(vatID); + for (const rec of deletions) { + noteExport(spanMetadataKey(rec), undefined); + } + sqlDeleteVatItems.run(vatID); + sqlDeleteVatSpans.run(vatID); + } + + const sqlGetAllSpanMetadata = db.prepare(` + SELECT vatID, startPos, endPos, hash, isCurrent + FROM transcriptSpans + ORDER BY vatID, startPos + `); + + const sqlGetCurrentSpanMetadata = db.prepare(` + SELECT vatID, startPos, endPos, hash, isCurrent + FROM transcriptSpans + WHERE isCurrent = 1 + ORDER BY vatID, startPos + `); + + /** + * Obtain artifact metadata records for spans contained in this store. + * + * @param {boolean} includeHistorical If true, include all metadata that is + * present in the store regardless of its currency; if false, only include + * the metadata that is part of the swingset's active operational state. + * + * Note: in the currently anticipated operational mode, this flag should + * always be set to `true`, because *all* transcript span metadata is, for + * now, considered part of the consensus set. This metadata is being retained + * as a hedge against possible future need, wherein we find it necessary to + * replay a vat's entire history from t0 and therefor need to be able to + * validate historical transcript artifacts that were recovered from external + * archives rather than retained directly. While such a need seems highly + * unlikely, it hypothetically could be forced by some necessary vat upgrade + * that implicates path-dependent ephemeral state despite our best efforts to + * avoid having any such state. However, the flag itself is present in case + * future operational policy allows for pruning historical transcript span + * metadata, for example because we've determined that such full-history + * replay will never be required or because such replay would be prohibitively + * expensive regardless of need and therefor other repair strategies employed. + * + * @yields {[key: string, value: string]} + * @returns {Iterable<[key: string, value: string]>} An iterator over pairs of + * [spanMetadataKey, rec], where `rec` is a JSON-encoded metadata record for the + * span named by `spanMetadataKey`. + */ + function* getExportRecords(includeHistorical = true) { + const sql = includeHistorical + ? sqlGetAllSpanMetadata + : sqlGetCurrentSpanMetadata; + for (const rec of sql.iterate()) { + const { vatID, startPos, endPos, hash, isCurrent } = rec; + const exportRec = spanRec(vatID, startPos, endPos, hash, isCurrent); + yield [spanMetadataKey(rec), JSON.stringify(exportRec)]; + } + } + + /** + * Obtain artifact names for spans contained in this store. + * + * @param {boolean} includeHistorical If true, include all spans that are + * present in the store regardless of their currency; if false, only include + * the current span for each vat. + * + * @yields {string} + * @returns {AsyncIterable} An iterator over the names of all the artifacts requested + */ + async function* getArtifactNames(includeHistorical) { + const sql = includeHistorical + ? sqlGetAllSpanMetadata + : sqlGetCurrentSpanMetadata; + for (const rec of sql.iterate()) { + yield spanArtifactName(rec); + } + } + + const sqlGetSpanEndPos = db.prepare(` + SELECT endPos + FROM transcriptSpans + WHERE vatID = ? AND startPos = ? + `); + sqlGetSpanEndPos.pluck(true); + + const sqlReadSpanItems = db.prepare(` + SELECT item + FROM transcriptItems + WHERE vatID = ? AND ? <= position AND position < ? + ORDER BY position + `); + + /** + * Read the items in a transcript span + * + * @param {string} vatID The vat whose transcript is being read + * @param {number} [startPos] A start position identifying the span to be + * read; defaults to the current span, whatever it is + * + * @returns {Iterable} An iterator over the items in the indicated span + */ + function readSpan(vatID, startPos) { + let endPos; + if (startPos === undefined) { + ({ startPos, endPos } = getCurrentSpanBounds(vatID)); + } else { + insistTranscriptPosition(startPos); + endPos = sqlGetSpanEndPos.get(vatID, startPos); + typeof endPos === 'number' || + Fail`no transcript span for ${q(vatID)} at ${q(startPos)}`; + } + insistTranscriptPosition(startPos); + startPos <= endPos || Fail`${q(startPos)} <= ${q(endPos)}}`; + + function* reader() { + for (const { item } of sqlReadSpanItems.iterate( + vatID, + startPos, + endPos, + )) { + yield item; + } + } + + if (startPos === endPos) { + return empty(); + } + + return reader(); + } + + const sqlGetSpanIsCurrent = db.prepare(` + SELECT isCurrent + FROM transcriptSpans + WHERE vatID = ? AND startPos = ? + `); + sqlGetSpanIsCurrent.pluck(true); + + /** + * Read a transcript span and return it as a stream of data suitable for + * export to another store. Transcript items are terminated by newlines. + * + * Transcript span artifact names should be strings of the form: + * `transcript.${vatID}.${startPos}.${endPos}` + * + * @param {string} name The name of the transcript artifact to be read + * @param {boolean} includeHistorical If true, allow non-current spans to be fetched + * + * @returns {AsyncIterable} + * @yields {Uint8Array} + */ + async function* exportSpan(name, includeHistorical) { + typeof name === 'string' || Fail`artifact name must be a string`; + const parts = name.split('.'); + const [type, vatID, pos] = parts; + // prettier-ignore + (parts.length === 4 && type === 'transcript') || + Fail`expected artifact name of the form 'transcript.{vatID}.{startPos}.{endPos}', saw ${q(name)}`; + const isCurrent = sqlGetSpanIsCurrent.get(vatID, pos); + isCurrent !== undefined || Fail`transcript span ${q(name)} not available`; + isCurrent || + includeHistorical || + Fail`transcript span ${q(name)} not available`; + const startPos = Number(pos); + for (const entry of readSpan(vatID, startPos)) { + yield Buffer.from(`${entry}\n`); + } + } + + const sqlAddItem = db.prepare(` + INSERT INTO transcriptItems (vatID, item, position) + VALUES (?, ?, ?) + `); + + const sqlUpdateSpan = db.prepare(` + UPDATE transcriptSpans + SET endPos = ?, hash = ? + WHERE vatID = ? AND isCurrent = 1 + `); + + /** + * Append an item to the current transcript span for a given vat + * + * @param {string} vatID The whose transcript is being added to + * @param {string} item The item to add + */ + const addItem = (vatID, item) => { + ensureTxn(); + const { startPos, endPos, hash } = getCurrentSpanBounds(vatID); + sqlAddItem.run(vatID, item, endPos); + const newEndPos = endPos + 1; + const newHash = updateSpanHash(hash, item); + sqlUpdateSpan.run(newEndPos, newHash, vatID); + const rec = spanRec(vatID, startPos, newEndPos, newHash, 1); + noteExport(spanMetadataKey(rec), JSON.stringify(rec)); + }; + + /** + * Import a transcript span from another store. + * + * @param {string} name Artifact Name of the transcript span + * @param {SwingStoreExporter} exporter Exporter from which to get the span data + * @param {object} info Metadata describing the span + * + * @returns {Promise} + */ + async function importSpan(name, exporter, info) { + const parts = name.split('.'); + const [type, vatID, rawStartPos, rawEndPos] = parts; + // prettier-ignore + parts.length === 4 && type === 'transcript' || + Fail`expected artifact name of the form 'transcript.{vatID}.{startPos}.{endPos}', saw '${q(name)}'`; + // prettier-ignore + info.vatID === vatID || + Fail`artifact name says vatID ${q(vatID)}, metadata says ${q(info.vatID)}`; + const startPos = Number(rawStartPos); + // prettier-ignore + info.startPos === startPos || + Fail`artifact name says startPos ${q(startPos)}, metadata says ${q(info.startPos)}`; + const endPos = Number(rawEndPos); + // prettier-ignore + info.endPos === endPos || + Fail`artifact name says endPos ${q(endPos)}, metadata says ${q(info.endPos)}`; + const artifactChunks = exporter.getArtifact(name); + const inStream = Readable.from(artifactChunks); + const lineTransform = new ReadlineTransform(); + const lineStream = inStream.pipe(lineTransform); + let hash = initialHash; + let pos = startPos; + for await (const item of lineStream) { + sqlAddItem.run(vatID, item, pos); + hash = updateSpanHash(hash, item); + pos += 1; + } + pos === endPos || Fail`artifact ${name} is not available`; + info.hash === hash || + Fail`artifact ${name} hash is ${q(hash)}, metadata says ${q(info.hash)}`; + sqlWriteSpan.run( + info.vatID, + info.startPos, + info.endPos, + info.hash, + info.isCurrent ? 1 : null, + ); + } + + return harden({ + initTranscript, + rolloverSpan, + getCurrentSpanBounds, + addItem, + readSpan, + deleteVatTranscripts, + + exportSpan, + importSpan, + getExportRecords, + getArtifactNames, + + dumpTranscripts, + }); +} diff --git a/packages/swing-store/test/test-deletion.js b/packages/swing-store/test/test-deletion.js new file mode 100644 index 00000000000..a01727a5c2e --- /dev/null +++ b/packages/swing-store/test/test-deletion.js @@ -0,0 +1,93 @@ +// @ts-check +import test from 'ava'; +import '@endo/init/debug.js'; +import fs from 'fs'; +import { initSwingStore } from '../src/swingStore.js'; + +async function dosnap(filePath) { + fs.writeFileSync(filePath, 'abc'); +} + +test('delete snapshots with export callback', async t => { + const exportLog = []; + const exportCallback = exports => { + for (const [key, value] of exports) { + exportLog.push([key, value]); + } + }; + const store = initSwingStore(null, { exportCallback }); + const { kernelStorage, hostStorage } = store; + const { snapStore } = kernelStorage; + const { commit } = hostStorage; + + await snapStore.saveSnapshot('v1', 10, dosnap); + await snapStore.saveSnapshot('v1', 11, dosnap); + await snapStore.saveSnapshot('v1', 12, dosnap); + // nothing is written to exportCallback until endCrank() or commit() + t.deepEqual(exportLog, []); + + await commit(); + + t.is(exportLog.length, 4); + t.is(exportLog[0][0], 'snapshot.v1.10'); + t.is(exportLog[1][0], 'snapshot.v1.11'); + t.is(exportLog[2][0], 'snapshot.v1.12'); + t.is(exportLog[3][0], 'snapshot.v1.current'); + exportLog.length = 0; + + // in a previous version, deleteVatSnapshots caused overlapping SQL + // queries, and failed + snapStore.deleteVatSnapshots('v1'); + await commit(); + + t.deepEqual(exportLog, [ + ['snapshot.v1.10', null], + ['snapshot.v1.11', null], + ['snapshot.v1.12', null], + ['snapshot.v1.current', null], + ]); + exportLog.length = 0; +}); + +test('delete transcripts with export callback', async t => { + const exportLog = []; + const exportCallback = exports => { + for (const [key, value] of exports) { + exportLog.push([key, value]); + } + }; + const store = initSwingStore(null, { exportCallback }); + const { kernelStorage, hostStorage } = store; + const { transcriptStore } = kernelStorage; + const { commit } = hostStorage; + + transcriptStore.initTranscript('v1'); + transcriptStore.addItem('v1', 'aaa'); + transcriptStore.addItem('v1', 'bbb'); + transcriptStore.addItem('v1', 'ccc'); + transcriptStore.rolloverSpan('v1'); + transcriptStore.addItem('v1', 'ddd'); + transcriptStore.addItem('v1', 'eee'); + transcriptStore.addItem('v1', 'fff'); + // nothing is written to exportCallback until endCrank() or commit() + t.deepEqual(exportLog, []); + + await commit(); + + t.is(exportLog.length, 2); + t.is(exportLog[0][0], 'transcript.v1.0'); + t.is(exportLog[1][0], 'transcript.v1.current'); + exportLog.length = 0; + + // in a previous version, deleteVatTranscripts caused overlapping SQL + // queries, and failed + transcriptStore.deleteVatTranscripts('v1'); + await commit(); + + t.deepEqual(exportLog, [ + ['transcript.v1.0', null], + ['transcript.v1.current', null], + ]); + + exportLog.length = 0; +}); diff --git a/packages/swing-store/test/test-exportImport.js b/packages/swing-store/test/test-exportImport.js new file mode 100644 index 00000000000..f6b38aeccfa --- /dev/null +++ b/packages/swing-store/test/test-exportImport.js @@ -0,0 +1,444 @@ +// @ts-check + +import '@endo/init/debug.js'; +import fs from 'fs'; + +// eslint-disable-next-line import/no-extraneous-dependencies +import test from 'ava'; +// eslint-disable-next-line import/no-extraneous-dependencies +import tmp from 'tmp'; + +import { + initSwingStore, + makeSwingStoreExporter, + importSwingStore, +} from '../src/swingStore.js'; + +function makeExportLog() { + const exportLog = []; + const shadowStore = new Map(); + return { + callback(updates) { + exportLog.push(updates); + for (const [key, value] of updates) { + if (value == null) { + shadowStore.delete(key); + } else { + shadowStore.set(key, value); + } + } + }, + getLog() { + return exportLog; + }, + entries() { + return shadowStore.entries(); + }, + }; +} + +/** + * @param {string} [prefix] + * @returns {Promise<[string, () => void]>} + */ +const tmpDir = prefix => + new Promise((resolve, reject) => { + tmp.dir({ unsafeCleanup: true, prefix }, (err, name, removeCallback) => { + if (err) { + reject(err); + } else { + resolve([name, removeCallback]); + } + }); + }); + +function actLikeAVatRunningACrank(vat, ks, crank, doFail) { + const { kvStore, transcriptStore } = ks; + const { vatID } = vat; + ks.startCrank(); + if (doFail) { + ks.establishCrankSavepoint('a'); + } + kvStore.set('kval', `set in ${crank}`); + kvStore.set(`${vatID}.vval`, `stuff in ${crank}`); + kvStore.set(`${vatID}.monotonic.${crank}`, 'more and more'); + if (crank % 3 === 0) { + kvStore.delete('brigadoon'); + } else { + kvStore.set('brigadoon', `here during ${crank}`); + } + transcriptStore.addItem(vatID, `stuff done during crank #${crank}`); + if (doFail) { + ks.rollbackCrank('a'); + } else { + vat.endPos += 1; + } + ks.endCrank(); +} + +async function fakeAVatSnapshot(vat, ks) { + await ks.snapStore.saveSnapshot(vat.vatID, vat.endPos, async filePath => { + fs.writeFileSync( + filePath, + `snapshot of vat ${vat.vatID} as of ${vat.endPos}`, + ); + }); + ks.transcriptStore.rolloverSpan(vat.vatID); +} + +const compareElems = (a, b) => a[0].localeCompare(b[0]); + +test('crank abort leaves no debris in export log', async t => { + const exportLog = makeExportLog(); + const [dbDir, cleanup] = await tmpDir('testdb'); + t.teardown(cleanup); + + const ssOut = initSwingStore(dbDir, { + exportCallback: exportLog.callback, + }); + const { kernelStorage } = ssOut; + + const vat = { vatID: 'vatA', endPos: 0 }; + kernelStorage.transcriptStore.initTranscript(vat.vatID); + + // Run 4 "blocks", each consisting of 4 "cranks", accumulating stuff, + // aborting every third crank. + let crankNum = 0; + for (let block = 0; block < 4; block += 1) { + for (let crank = 0; crank < 4; crank += 1) { + crankNum += 1; + actLikeAVatRunningACrank( + vat, + kernelStorage, + crankNum, + crankNum % 3 === 0, + ); + } + // eslint-disable-next-line no-await-in-loop + await ssOut.hostStorage.commit(); + } + + const exporter = makeSwingStoreExporter(dbDir, 'current'); + + const exportData = []; + for await (const elem of exporter.getExportData()) { + exportData.push(elem); + } + exportData.sort(compareElems); + + const feedData = []; + for (const elem of exportLog.entries()) { + feedData.push(elem); + } + feedData.sort(compareElems); + + t.deepEqual(exportData, feedData); + // Commented data entries would have been produced by the aborted cranks + t.deepEqual(exportData, [ + ['kv.brigadoon', 'here during 16'], + ['kv.kval', 'set in 16'], + ['kv.vatA.monotonic.1', 'more and more'], + ['kv.vatA.monotonic.10', 'more and more'], + ['kv.vatA.monotonic.11', 'more and more'], + // ['kv.vatA.monotonic.12', 'more and more'], + ['kv.vatA.monotonic.13', 'more and more'], + ['kv.vatA.monotonic.14', 'more and more'], + // ['kv.vatA.monotonic.15', 'more and more'], + ['kv.vatA.monotonic.16', 'more and more'], + ['kv.vatA.monotonic.2', 'more and more'], + // ['kv.vatA.monotonic.3', 'more and more'], + ['kv.vatA.monotonic.4', 'more and more'], + ['kv.vatA.monotonic.5', 'more and more'], + // ['kv.vatA.monotonic.6', 'more and more'], + ['kv.vatA.monotonic.7', 'more and more'], + ['kv.vatA.monotonic.8', 'more and more'], + // ['kv.vatA.monotonic.9', 'more and more'], + ['kv.vatA.vval', 'stuff in 16'], + [ + 'transcript.vatA.current', + // '{"vatID":"vatA","startPos":0,"endPos":16,"hash":"83e7ed8d3ee339a8b0989512973396d3e9db4b4c3d76570862d99e3cdebaf8c6","isCurrent":1}', + '{"vatID":"vatA","startPos":0,"endPos":11,"hash":"ff988824e0fb02bfd0a5ecf466513fd4ef2ac6e488ab9070e640683faa8ddb11","isCurrent":1}', + ], + ]); +}); + +async function testExportImport( + t, + runMode, + exportMode, + importMode, + failureMode, + expectedArtifactNames, +) { + const exportLog = makeExportLog(); + const [dbDir, cleanup] = await tmpDir('testdb'); + t.teardown(cleanup); + + const keepTranscripts = runMode !== 'current'; + const keepSnapshots = runMode === 'debug'; + const ssOut = initSwingStore(dbDir, { + exportCallback: exportLog.callback, + keepSnapshots, + keepTranscripts, + }); + const { kernelStorage, debug } = ssOut; + + const vats = [ + { vatID: 'vatA', endPos: 0 }, + { vatID: 'vatB', endPos: 0 }, + ]; + for (const vat of vats) { + kernelStorage.transcriptStore.initTranscript(vat.vatID); + } + + // Run 4 "blocks", each consisting of 4 "cranks", across 2 "vats" + // Snapshot 'vatA' after the first and third blocks and 'vatB' after the second + // This will leave 2 current snapshots and 1 historical snapshot + let crankNum = 0; + for (let block = 0; block < 4; block += 1) { + for (let crank = 0; crank < 4; crank += 1) { + crankNum += 1; + const vat = vats[crankNum % vats.length]; + actLikeAVatRunningACrank(vat, kernelStorage, crankNum); + } + if (block < 3) { + // eslint-disable-next-line no-await-in-loop + await fakeAVatSnapshot(vats[block % 2], kernelStorage); + } + // eslint-disable-next-line no-await-in-loop + await ssOut.hostStorage.commit(); + } + + const exporter = makeSwingStoreExporter(dbDir, exportMode); + + const exportData = []; + for await (const elem of exporter.getExportData()) { + exportData.push(elem); + } + exportData.sort(compareElems); + + const feedData = []; + for (const elem of exportLog.entries()) { + feedData.push(elem); + } + feedData.sort(compareElems); + + t.deepEqual(exportData, feedData); + t.deepEqual(exportData, [ + ['kv.brigadoon', 'here during 16'], + ['kv.kval', 'set in 16'], + ['kv.vatA.monotonic.10', 'more and more'], + ['kv.vatA.monotonic.12', 'more and more'], + ['kv.vatA.monotonic.14', 'more and more'], + ['kv.vatA.monotonic.16', 'more and more'], + ['kv.vatA.monotonic.2', 'more and more'], + ['kv.vatA.monotonic.4', 'more and more'], + ['kv.vatA.monotonic.6', 'more and more'], + ['kv.vatA.monotonic.8', 'more and more'], + ['kv.vatA.vval', 'stuff in 16'], + ['kv.vatB.monotonic.1', 'more and more'], + ['kv.vatB.monotonic.11', 'more and more'], + ['kv.vatB.monotonic.13', 'more and more'], + ['kv.vatB.monotonic.15', 'more and more'], + ['kv.vatB.monotonic.3', 'more and more'], + ['kv.vatB.monotonic.5', 'more and more'], + ['kv.vatB.monotonic.7', 'more and more'], + ['kv.vatB.monotonic.9', 'more and more'], + ['kv.vatB.vval', 'stuff in 15'], + [ + 'snapshot.vatA.2', + '{"vatID":"vatA","endPos":2,"hash":"6c7e452ee3eaec849c93234d933af4300012e4ff161c328d3c088ec3deef76a6","inUse":0}', + ], + [ + 'snapshot.vatA.6', + '{"vatID":"vatA","endPos":6,"hash":"36afc9e2717c395759e308c4a877d491f967e9768d73520bde758ff4fac5d8b9","inUse":1}', + ], + ['snapshot.vatA.current', 'snapshot.vatA.6'], + [ + 'snapshot.vatB.4', + '{"vatID":"vatB","endPos":4,"hash":"afd477014db678fbc1aa58beab50f444deb653b8cc8e8583214a363fd12ed57a","inUse":1}', + ], + ['snapshot.vatB.current', 'snapshot.vatB.4'], + [ + 'transcript.vatA.0', + '{"vatID":"vatA","startPos":0,"endPos":2,"hash":"ea8ac1a751712ad66e4a9182adc65afe9bb0f4cd0ee0b828c895c63fbd2e3157","isCurrent":0}', + ], + [ + 'transcript.vatA.2', + '{"vatID":"vatA","startPos":2,"endPos":6,"hash":"88f299ca67b8acdf6023a83bb8e899af5adcf3271c7a1a2a495dcd6f1fbaac9f","isCurrent":0}', + ], + [ + 'transcript.vatA.current', + '{"vatID":"vatA","startPos":6,"endPos":8,"hash":"fe5d692b24a32d53bf617ba9ed3391b60c36a402c70a07a6aa984fc316e4efcc","isCurrent":1}', + ], + [ + 'transcript.vatB.0', + '{"vatID":"vatB","startPos":0,"endPos":4,"hash":"41dbf60cdec066106c7030517cb9f9f34a50fe2259705cf5fdbdd0b39ae12e46","isCurrent":0}', + ], + [ + 'transcript.vatB.current', + '{"vatID":"vatB","startPos":4,"endPos":8,"hash":"34fa09207bfb7af5fc3e65acb07f13b60834d0fbd2c6b9708f794c4397bd865d","isCurrent":1}', + ], + ]); + + const artifactNames = []; + for await (const name of exporter.getArtifactNames()) { + artifactNames.push(name); + } + t.deepEqual(artifactNames, expectedArtifactNames); + + const includeHistorical = importMode !== 'current'; + + const beforeDump = debug.dump(keepSnapshots); + let ssIn; + try { + ssIn = await importSwingStore(exporter, null, { + includeHistorical, + }); + } catch (e) { + if (failureMode === 'transcript') { + t.is(e.message, 'artifact "transcript.vatA.0.2" is not available'); + return; + } else if (failureMode === 'snapshot') { + t.is(e.message, 'artifact "snapshot.vatA.2" is not available'); + return; + } + throw e; + } + t.is(failureMode, 'none'); + await ssIn.hostStorage.commit(); + const dumpsShouldMatch = + runMode !== 'debug' || (exportMode === 'debug' && importMode !== 'current'); + if (dumpsShouldMatch) { + const afterDump = ssIn.debug.dump(keepSnapshots); + t.deepEqual(beforeDump, afterDump); + } + + exporter.close(); +} + +const expectedCurrentArtifacts = [ + 'snapshot.vatA.6', + 'snapshot.vatB.4', + 'transcript.vatA.6.8', + 'transcript.vatB.4.8', +]; + +const expectedArchivalArtifacts = [ + 'snapshot.vatA.6', + 'snapshot.vatB.4', + 'transcript.vatA.0.2', + 'transcript.vatA.2.6', + 'transcript.vatA.6.8', + 'transcript.vatB.0.4', + 'transcript.vatB.4.8', +]; + +const expectedDebugArtifacts = [ + 'snapshot.vatA.6', + 'snapshot.vatB.4', + 'snapshot.vatA.2', + 'transcript.vatA.0.2', + 'transcript.vatA.2.6', + 'transcript.vatA.6.8', + 'transcript.vatB.0.4', + 'transcript.vatB.4.8', +]; + +const C = 'current'; +const A = 'archival'; +const D = 'debug'; + +test('export and import data for state sync - current->current->current', async t => { + await testExportImport(t, C, C, C, 'none', expectedCurrentArtifacts); +}); +test('export and import data for state sync - current->current->archival', async t => { + await testExportImport(t, C, C, A, 'none', expectedCurrentArtifacts); +}); +test('export and import data for state sync - current->current->debug', async t => { + await testExportImport(t, C, C, D, 'none', expectedCurrentArtifacts); +}); + +test('export and import data for state sync - current->archival->current', async t => { + await testExportImport(t, C, A, C, 'none', expectedArchivalArtifacts); +}); +test('export and import data for state sync - current->archival->archival', async t => { + await testExportImport(t, C, A, A, 'transcript', expectedArchivalArtifacts); +}); +test('export and import data for state sync - current->archival->debug', async t => { + await testExportImport(t, C, A, D, 'transcript', expectedArchivalArtifacts); +}); + +test('export and import data for state sync - current->debug->current', async t => { + await testExportImport(t, C, D, C, 'none', expectedDebugArtifacts); +}); +test('export and import data for state sync - current->debug->archival', async t => { + await testExportImport(t, C, D, A, 'snapshot', expectedDebugArtifacts); +}); +test('export and import data for state sync - current->debug->debug', async t => { + await testExportImport(t, C, D, D, 'snapshot', expectedDebugArtifacts); +}); + +// ------------------------------------------------------------ + +test('export and import data for state sync - archival->current->current', async t => { + await testExportImport(t, A, C, C, 'none', expectedCurrentArtifacts); +}); +test('export and import data for state sync - archival->current->archival', async t => { + await testExportImport(t, A, C, A, 'none', expectedCurrentArtifacts); +}); +test('export and import data for state sync - archival->current->debug', async t => { + await testExportImport(t, A, C, D, 'none', expectedCurrentArtifacts); +}); + +test('export and import data for state sync - archival->archival->current', async t => { + await testExportImport(t, A, A, C, 'none', expectedArchivalArtifacts); +}); +test('export and import data for state sync - archival->archival->archival', async t => { + await testExportImport(t, A, A, A, 'none', expectedArchivalArtifacts); +}); +test('export and import data for state sync - archival->archival->debug', async t => { + await testExportImport(t, A, A, D, 'none', expectedArchivalArtifacts); +}); + +test('export and import data for state sync - archival->debug->current', async t => { + await testExportImport(t, A, D, C, 'none', expectedDebugArtifacts); +}); +test('export and import data for state sync - archival->debug->archival', async t => { + await testExportImport(t, A, D, A, 'snapshot', expectedDebugArtifacts); +}); +test('export and import data for state sync - archival->debug->debug', async t => { + await testExportImport(t, A, D, D, 'snapshot', expectedDebugArtifacts); +}); + +// ------------------------------------------------------------ + +test('export and import data for state sync - debug->current->current', async t => { + await testExportImport(t, D, C, C, 'none', expectedCurrentArtifacts); +}); +test('export and import data for state sync - debug->current->archival', async t => { + await testExportImport(t, D, C, A, 'none', expectedCurrentArtifacts); +}); +test('export and import data for state sync - debug->current->debug', async t => { + await testExportImport(t, D, C, D, 'none', expectedCurrentArtifacts); +}); + +test('export and import data for state sync - debug->archival->current', async t => { + await testExportImport(t, D, A, C, 'none', expectedArchivalArtifacts); +}); +test('export and import data for state sync - debug->archival->archival', async t => { + await testExportImport(t, D, A, A, 'none', expectedArchivalArtifacts); +}); +test('export and import data for state sync - debug->archival->debug', async t => { + await testExportImport(t, D, A, D, 'none', expectedArchivalArtifacts); +}); + +test('export and import data for state sync - debug->debug->current', async t => { + await testExportImport(t, D, D, C, 'none', expectedDebugArtifacts); +}); +test('export and import data for state sync - debug->debug->archival', async t => { + await testExportImport(t, D, D, A, 'none', expectedDebugArtifacts); +}); +test('export and import data for state sync - debug->debug->debug', async t => { + await testExportImport(t, D, D, D, 'none', expectedDebugArtifacts); +}); diff --git a/packages/swing-store/test/test-snapstore.js b/packages/swing-store/test/test-snapstore.js index 4dc0eae7c1b..2eb167c9cfa 100644 --- a/packages/swing-store/test/test-snapstore.js +++ b/packages/swing-store/test/test-snapstore.js @@ -13,16 +13,36 @@ import tmp from 'tmp'; import { makeMeasureSeconds } from '@agoric/internal'; import { makeSnapStore } from '../src/snapStore.js'; +function makeExportLog() { + const exportLog = []; + return { + noteExport(key, value) { + exportLog.push([key, value]); + }, + getLog() { + return exportLog; + }, + }; +} + +function ensureTxn() {} + test('build temp file; compress to cache file', async t => { const db = sqlite3(':memory:'); - const store = makeSnapStore(db, { - ...tmp, - tmpFile: tmp.file, - ...path, - ...fs, - ...fs.promises, - measureSeconds: makeMeasureSeconds(() => 0), - }); + const exportLog = makeExportLog(); + const store = makeSnapStore( + db, + ensureTxn, + { + ...tmp, + tmpFile: tmp.file, + ...path, + ...fs, + ...fs.promises, + measureSeconds: makeMeasureSeconds(() => 0), + }, + exportLog.noteExport, + ); let keepTmp = ''; const result = await store.saveSnapshot('fakeVatID', 47, async filePath => { t.falsy(fs.existsSync(filePath)); @@ -32,7 +52,7 @@ test('build temp file; compress to cache file', async t => { const { hash } = result; const expectedHash = 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'; - t.like(result, { + t.deepEqual(result, { hash: expectedHash, uncompressedSize: 3, compressedSize: 23, @@ -40,12 +60,18 @@ test('build temp file; compress to cache file', async t => { compressSeconds: 0, }); const snapshotInfo = store.getSnapshotInfo('fakeVatID'); - t.deepEqual(snapshotInfo, { + const dbInfo = { endPos: 47, hash: expectedHash, uncompressedSize: 3, compressedSize: 23, - }); + }; + const exportInfo = { + endPos: 47, + hash: expectedHash, + inUse: 1, + }; + t.deepEqual(snapshotInfo, dbInfo); t.is(store.hasHash('fakeVatID', hash), true); const zero = '0000000000000000000000000000000000000000000000000000000000000000'; @@ -66,6 +92,11 @@ test('build temp file; compress to cache file', async t => { t.truthy(snapshotGZ); const contents = zlib.gunzipSync(snapshotGZ); t.is(contents.toString(), 'abc', 'gunzip(contents) matches original'); + const logInfo = { vatID: 'fakeVatID', ...exportInfo }; + t.deepEqual(exportLog.getLog(), [ + ['snapshot.fakeVatID.47', JSON.stringify(logInfo)], + ['snapshot.fakeVatID.current', `snapshot.fakeVatID.47`], + ]); }); test('snapStore prepare / commit delete is robust', async t => { @@ -78,7 +109,9 @@ test('snapStore prepare / commit delete is robust', async t => { measureSeconds: makeMeasureSeconds(() => 0), }; const db = sqlite3(':memory:'); - const store = makeSnapStore(db, io, { keepSnapshots: true }); + const store = makeSnapStore(db, ensureTxn, io, () => {}, { + keepSnapshots: true, + }); const hashes = []; for (let i = 0; i < 5; i += 1) { diff --git a/packages/swing-store/test/test-state.js b/packages/swing-store/test/test-state.js index 7e2aef3e4bb..c2629428aff 100644 --- a/packages/swing-store/test/test-state.js +++ b/packages/swing-store/test/test-state.js @@ -41,13 +41,26 @@ function* iterate(kvStore, start, end) { } } +function makeExportLog() { + const exportLog = []; + return { + callback(updates) { + exportLog.push(updates); + }, + getLog() { + return exportLog; + }, + }; +} + function checkKVState(t, swingstore) { const kv = swingstore.debug.dump().kvEntries; t.deepEqual(kv, { foo: 'f', foo1: 'f1', foo3: 'f3' }); } -function testKVStore(t, storage) { - const { kvStore } = storage.kernelStorage; +function testKVStore(t, storage, exportLog) { + const { kvStore, startCrank, endCrank } = storage.kernelStorage; + startCrank(); t.falsy(kvStore.has('missing')); t.is(kvStore.get('missing'), undefined); @@ -69,18 +82,31 @@ function testKVStore(t, storage) { 'foo2', 'foo3', ]); + endCrank(); + startCrank(); kvStore.delete('foo2'); t.falsy(kvStore.has('foo2')); t.is(kvStore.get('foo2'), undefined); t.is(kvStore.getNextKey('foo1'), 'foo3'); t.is(kvStore.getNextKey('foo2'), 'foo3'); + endCrank(); checkKVState(t, storage); + t.deepEqual(exportLog.getLog(), [ + [ + ['kv.foo', 'f'], + ['kv.foo1', 'f1'], + ['kv.foo2', 'f2'], + ['kv.foo3', 'f3'], + ], + [['kv.foo2', null]], + ]); } test('in-memory kvStore read/write', t => { - const ss1 = initSwingStore(null); - testKVStore(t, ss1); + const exportLog = makeExportLog(); + const ss1 = initSwingStore(null, { exportCallback: exportLog.callback }); + testKVStore(t, ss1, exportLog); const serialized = ss1.debug.serialize(); const ss2 = initSwingStore(null, { serialized }); checkKVState(t, ss2); @@ -88,10 +114,11 @@ test('in-memory kvStore read/write', t => { test('persistent kvStore read/write/re-open', async t => { const [dbDir, cleanup] = await tmpDir('testdb'); + const exportLog = makeExportLog(); t.teardown(cleanup); t.is(isSwingStore(dbDir), false); - const ss1 = initSwingStore(dbDir); - testKVStore(t, ss1); + const ss1 = initSwingStore(dbDir, { exportCallback: exportLog.callback }); + testKVStore(t, ss1, exportLog); await ss1.hostStorage.commit(); await ss1.hostStorage.close(); t.is(isSwingStore(dbDir), true); @@ -120,114 +147,96 @@ test('persistent kvStore maxKeySize write', async t => { await hostStorage.close(); }); -async function testStreamStore(t, dbDir) { - const { kernelStorage, hostStorage } = initSwingStore(dbDir); - const { streamStore } = kernelStorage; +async function testTranscriptStore(t, dbDir) { + const exportLog = makeExportLog(); + const { kernelStorage, hostStorage } = initSwingStore(dbDir, { + exportCallback: exportLog.callback, + keepTranscripts: true, // XXX need to vary + }); + const { transcriptStore } = kernelStorage; const { commit, close } = hostStorage; - const start = streamStore.STREAM_START; - let s1pos = start; - s1pos = streamStore.writeStreamItem('st1', 'first', s1pos); - s1pos = streamStore.writeStreamItem('st1', 'second', s1pos); - const s1posAlt = s1pos; - s1pos = streamStore.writeStreamItem('st1', 'third', s1pos); - let s2pos = streamStore.STREAM_START; - s2pos = streamStore.writeStreamItem('st2', 'oneth', s2pos); - s1pos = streamStore.writeStreamItem('st1', 'fourth', s1pos); - s2pos = streamStore.writeStreamItem('st2', 'twoth', s2pos); - const s2posAlt = s2pos; - s2pos = streamStore.writeStreamItem('st2', 'threeth', s2pos); - s2pos = streamStore.writeStreamItem('st2', 'fourst', s2pos); - streamStore.closeStream('st1'); - streamStore.closeStream('st2'); - const reader1 = streamStore.readStream('st1', start, s1pos); - t.deepEqual(Array.from(reader1), ['first', 'second', 'third', 'fourth']); - s2pos = streamStore.writeStreamItem('st2', 're3', s2posAlt); - streamStore.closeStream('st2'); - const reader2 = streamStore.readStream('st2', start, s2pos); - t.deepEqual(Array.from(reader2), ['oneth', 'twoth', 're3']); - - const reader1alt = streamStore.readStream('st1', s1posAlt, s1pos); + transcriptStore.initTranscript('st1'); + transcriptStore.initTranscript('st2'); + transcriptStore.addItem('st1', 'first'); + transcriptStore.addItem('st1', 'second'); + transcriptStore.rolloverSpan('st1'); + transcriptStore.addItem('st1', 'third'); + transcriptStore.addItem('st2', 'oneth'); + transcriptStore.addItem('st1', 'fourth'); + transcriptStore.addItem('st2', 'twoth'); + transcriptStore.addItem('st2', 'threeth'); + transcriptStore.addItem('st2', 'fourst'); + const reader1 = transcriptStore.readSpan('st1', 0); + t.deepEqual(Array.from(reader1), ['first', 'second']); + const reader2 = transcriptStore.readSpan('st2', 0); + t.deepEqual(Array.from(reader2), ['oneth', 'twoth', 'threeth', 'fourst']); + + t.throws(() => transcriptStore.readSpan('st2', 3), { + message: 'no transcript span for "st2" at 3', + }); + + const reader1alt = transcriptStore.readSpan('st1'); t.deepEqual(Array.from(reader1alt), ['third', 'fourth']); + const reader1alt2 = transcriptStore.readSpan('st1', 2); + t.deepEqual(Array.from(reader1alt2), ['third', 'fourth']); - const emptyPos = streamStore.writeStreamItem('empty', 'filler', start); - streamStore.closeStream('empty'); - const readerEmpty = streamStore.readStream('empty', emptyPos, emptyPos); + transcriptStore.initTranscript('empty'); + const readerEmpty = transcriptStore.readSpan('empty'); t.deepEqual(Array.from(readerEmpty), []); - const readerEmpty2 = streamStore.readStream('empty', start, start); - t.deepEqual(Array.from(readerEmpty2), []); - - await commit(); - await close(); -} - -test('in-memory streamStore read/write', async t => { - await testStreamStore(t, null); -}); -test('persistent streamStore read/write', async t => { - const [dbDir, cleanup] = await tmpDir('testdb'); - t.teardown(cleanup); - t.is(isSwingStore(dbDir), false); - await testStreamStore(t, dbDir); -}); - -async function testStreamStoreModeInterlock(t, dbDir) { - const { kernelStorage, hostStorage } = initSwingStore(dbDir); - const { streamStore } = kernelStorage; - const { commit, close } = hostStorage; - const start = streamStore.STREAM_START; - - const s1pos = streamStore.writeStreamItem('st1', 'first', start); - streamStore.closeStream('st1'); - - const reader = streamStore.readStream('st1', start, s1pos); - t.throws(() => streamStore.readStream('st1', start, s1pos), { - message: `can't read stream "st1" because it's already in use`, - }); - t.throws(() => streamStore.writeStreamItem('st1', 'second', s1pos), { - message: `can't write stream "st1" because it's already in use`, + t.throws(() => transcriptStore.readSpan('nonexistent'), { + message: 'no current transcript for "nonexistent"', }); - streamStore.closeStream('st1'); - t.throws(() => reader.next(), { - message: `can't read stream "st1", it's been closed`, - }); - - streamStore.closeStream('nonexistent'); await commit(); + t.deepEqual(exportLog.getLog(), [ + [ + [ + 'transcript.st1.0', + '{"vatID":"st1","startPos":0,"endPos":2,"hash":"d385c43882cfb5611d255e362a9a98626ba4e55dfc308fc346c144c696ae734e","isCurrent":0}', + ], + [ + 'transcript.st1.current', + '{"vatID":"st1","startPos":2,"endPos":4,"hash":"789342fab468506c624c713c46953992f53a7eaae390d634790d791636b96cab","isCurrent":1}', + ], + [ + 'transcript.st2.current', + '{"vatID":"st2","startPos":0,"endPos":4,"hash":"45de7ae9d2be34148f9cf3000052e5d1374932d663442fe9f39a342d221cebf1","isCurrent":1}', + ], + ], + ]); await close(); } -test('in-memory streamStore mode interlock', async t => { - await testStreamStoreModeInterlock(t, null); +test('in-memory transcriptStore read/write', async t => { + await testTranscriptStore(t, null); }); -test('persistent streamStore mode interlock', async t => { +test('persistent transcriptStore read/write', async t => { const [dbDir, cleanup] = await tmpDir('testdb'); t.teardown(cleanup); t.is(isSwingStore(dbDir), false); - await testStreamStoreModeInterlock(t, dbDir); + await testTranscriptStore(t, dbDir); }); -test('streamStore abort', async t => { +test('transcriptStore abort', async t => { const [dbDir, cleanup] = await tmpDir('testdb'); t.teardown(cleanup); const { kernelStorage, hostStorage } = initSwingStore(dbDir); - const { streamStore } = kernelStorage; + const { transcriptStore } = kernelStorage; const { commit, close } = hostStorage; - const start = streamStore.STREAM_START; - const s1pos = streamStore.writeStreamItem('st1', 'first', start); - streamStore.closeStream('st1'); + transcriptStore.initTranscript('st1'); + transcriptStore.addItem('st1', 'first'); await commit(); // really write 'first' - streamStore.writeStreamItem('st2', 'second', s1pos); - streamStore.closeStream('st1'); + transcriptStore.initTranscript('st2'); + transcriptStore.addItem('st2', 'second'); // abort is close without commit await close(); - const { streamStore: ss2 } = openSwingStore(dbDir).kernelStorage; - const reader = ss2.readStream('st1', start, s1pos); + const { transcriptStore: ss2 } = openSwingStore(dbDir).kernelStorage; + const reader = ss2.readSpan('st1', 0); t.deepEqual(Array.from(reader), ['first']); // and not 'second' }); diff --git a/packages/swingset-runner/src/dumpstore.js b/packages/swingset-runner/src/dumpstore.js index 14ed012bdb5..74833e48ad7 100644 --- a/packages/swingset-runner/src/dumpstore.js +++ b/packages/swingset-runner/src/dumpstore.js @@ -3,7 +3,7 @@ import process from 'process'; /* eslint-disable no-use-before-define */ export function dumpStore(kernelStorage, outfile, rawMode, truncate = true) { - const streamStore = kernelStorage.streamStore; + const transcriptStore = kernelStorage.transcriptStore; let out; if (outfile) { out = fs.createWriteStream(outfile); @@ -178,11 +178,7 @@ export function dumpStore(kernelStorage, outfile, rawMode, truncate = true) { p(`// transcript of vat ${v} (${vn})`); if (endPos) { let idx = 1; - for (const item of streamStore.readStream( - `transcript-${v}`, - streamStore.STREAM_START, - endPos, - )) { + for (const item of transcriptStore.readTranscript(v, 0, endPos)) { pkvBig('transcript', `${v}.${idx}`, item, 500); idx += 1; } From c02253cf94fb5f087e81ac0bb5c1bc5a1bf53587 Mon Sep 17 00:00:00 2001 From: Brian Warner Date: Wed, 15 Feb 2023 12:38:28 -0600 Subject: [PATCH 02/26] fix(swingset): add placeholders for upgrade/stopvat work This makes room inside processUpgradeVat() for the new cleanup steps that we want to add. refs #6650 refs #7001 refs #6694 refs #6696 --- packages/SwingSet/src/kernel/kernel.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/SwingSet/src/kernel/kernel.js b/packages/SwingSet/src/kernel/kernel.js index 1884af60894..3c18f803653 100644 --- a/packages/SwingSet/src/kernel/kernel.js +++ b/packages/SwingSet/src/kernel/kernel.js @@ -823,6 +823,11 @@ export default function buildKernel( const vd1 = vatWarehouse.kernelDeliveryToVatDelivery(vatID, kd1); const status1 = await deliverAndLogToVat(vatID, kd1, vd1); + // TODO: send BOYD to the vat, to give it one last chance to clean + // up, drop imports, and delete durable data. If we ever have a + // vat that is so broken it can't do BOYD, we can make that + // optional. #7001 + // make arguments for vat-vat-admin.js vatUpgradeCallback() /** * @param {SwingSetCapData} _errorCD @@ -873,8 +878,17 @@ export default function buildKernel( return results; } - // stopVat succeeded, so now we stop the worker, delete the - // transcript and any snapshot + // stopVat succeeded. finish cleanup on behalf of the worker. + + // TODO: walk c-list for all decided promises, reject them all #6694 + + // TODO: getNonDurableObjectExports, synthesize abandonVSO, + // execute it as if it were a syscall. (maybe distinguish between + // reachable/recognizable exports, abandon the reachable, retire + // the recognizable) #6696 + + // cleanup done, now we stop the worker, delete the transcript and + // any snapshot await vatWarehouse.resetWorker(vatID); const source = { bundleID }; From 3efce4e7c2502cb3f5a2342bd032658eb56c8c1f Mon Sep 17 00:00:00 2001 From: Brian Warner Date: Wed, 15 Feb 2023 12:46:31 -0600 Subject: [PATCH 03/26] fix(swingset): factor out getDecidedPromises() cleanupAfterTerminatedVat() had a loop which identified all the promises (kpids) which were decided by a vat, so it could reject all of them as the vat was being terminated. We will have a need for this list of kpids during vat upgrade too, so refactor it out into a separate kernelKeeper method, and change terminateVat() to fetch the list before calling cleanupAfterTerminatedVat(). --- packages/SwingSet/src/kernel/kernel.js | 6 ++- .../SwingSet/src/kernel/state/kernelKeeper.js | 44 ++++++++++--------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/packages/SwingSet/src/kernel/kernel.js b/packages/SwingSet/src/kernel/kernel.js index 3c18f803653..28447a6a412 100644 --- a/packages/SwingSet/src/kernel/kernel.js +++ b/packages/SwingSet/src/kernel/kernel.js @@ -257,7 +257,8 @@ export default function buildKernel( // check will report 'false'. That's fine, there's no state to // clean up. if (kernelKeeper.vatIsAlive(vatID)) { - const promisesToReject = kernelKeeper.cleanupAfterTerminatedVat(vatID); + const promisesToReject = kernelKeeper.getDecidedPromises(vatID); + kernelKeeper.cleanupAfterTerminatedVat(vatID); for (const kpid of promisesToReject) { resolveToError(kpid, makeError('vat terminated'), vatID); } @@ -818,8 +819,9 @@ export default function buildKernel( upgradeMessage, incarnationNumber: vatKeeper.getIncarnationNumber(), }; + const disconnectObjectCD = kser(disconnectObject); /** @type { import('../types-external.js').KernelDeliveryStopVat } */ - const kd1 = harden(['stopVat', kser(disconnectObject)]); + const kd1 = harden(['stopVat', disconnectObjectCD]); const vd1 = vatWarehouse.kernelDeliveryToVatDelivery(vatID, kd1); const status1 = await deliverAndLogToVat(vatID, kd1, vd1); diff --git a/packages/SwingSet/src/kernel/state/kernelKeeper.js b/packages/SwingSet/src/kernel/state/kernelKeeper.js index 4cdc9d84664..2a77c76643c 100644 --- a/packages/SwingSet/src/kernel/state/kernelKeeper.js +++ b/packages/SwingSet/src/kernel/state/kernelKeeper.js @@ -775,14 +775,32 @@ export default function makeKernelKeeper(kernelStorage, kernelSlog) { kvStore.set(`${kernelSlot}.data.slots`, capdata.slots.join(',')); } + function* getDecidedPromises(vatID) { + const promisePrefix = `${vatID}.c.p`; + for (const k of enumeratePrefixedKeys(kvStore, promisePrefix)) { + // The vpid for a promise imported or exported by a vat (and thus + // potentially a promise for which the vat *might* be the decider) will + // always be of the form `p+NN` or `p-NN`. The corresponding vpid->kpid + // c-list entry will thus always begin with `vMM.c.p`. Decider-ship is + // independent of whether the promise was imported or exported, so we + // have to look up the corresponding kernel promise table entry to see + // whether the vat is the decider or not. If it is, we add the promise + // to the list of promises that must be rejected because the dead vat + // will never be able to act upon them. + const kpid = kvStore.get(k); + const p = getKernelPromise(kpid); + if (p.state === 'unresolved' && p.decider === vatID) { + yield kpid; + } + } + } + function cleanupAfterTerminatedVat(vatID) { insistVatID(vatID); // eslint-disable-next-line no-use-before-define const vatKeeper = provideVatKeeper(vatID); const exportPrefix = `${vatID}.c.o+`; const importPrefix = `${vatID}.c.o-`; - const promisePrefix = `${vatID}.c.p`; - const kernelPromisesToReject = []; vatKeeper.deleteSnapshotsAndTranscript(); @@ -822,23 +840,8 @@ export default function makeKernelKeeper(kernelStorage, kernelSlog) { // that will also delete both db keys } - // now find all orphaned promises, which must be rejected - for (const k of enumeratePrefixedKeys(kvStore, promisePrefix)) { - // The vpid for a promise imported or exported by a vat (and thus - // potentially a promise for which the vat *might* be the decider) will - // always be of the form `p+NN` or `p-NN`. The corresponding vpid->kpid - // c-list entry will thus always begin with `vMM.c.p`. Decider-ship is - // independent of whether the promise was imported or exported, so we - // have to look up the corresponding kernel promise table entry to see - // whether the vat is the decider or not. If it is, we add the promise - // to the list of promises that must be rejected because the dead vat - // will never be able to act upon them. - const kpid = kvStore.get(k); - const p = getKernelPromise(kpid); - if (p.state === 'unresolved' && p.decider === vatID) { - kernelPromisesToReject.push(kpid); - } - } + // the caller used getDecidedPromises() before calling us, so they + // already known the orphaned promises, so it can reject them // now loop back through everything and delete it all for (const k of enumeratePrefixedKeys(kvStore, `${vatID}.`)) { @@ -870,8 +873,6 @@ export default function makeKernelKeeper(kernelStorage, kernelSlog) { } decStat('vats'); } - - return kernelPromisesToReject; } function addMessageToPromiseQueue(kernelSlot, msg) { @@ -1597,6 +1598,7 @@ export default function makeKernelKeeper(kernelStorage, kernelSlog) { provideVatKeeper, vatIsAlive, evictVatKeeper, + getDecidedPromises, cleanupAfterTerminatedVat, addDynamicVatID, getDynamicVats, From d79623f3fb3b87653dba1c71eb1153711c9d962c Mon Sep 17 00:00:00 2001 From: Brian Warner Date: Wed, 15 Feb 2023 12:50:05 -0600 Subject: [PATCH 04/26] fix: move rejectAllPromises from stopVat to kernels-side upgradeVat When upgrading a vat, we must reject all promises that were decided by the old incarnation, because none of them are durable (the new incarnation will be unable to resolve them). Previously, the vat's stopVat() delivery would do the rejection. This moves the responsibility to the kernel, to happen in the pause between the old version being shut down and the new version being launched. closes #6694 --- packages/SwingSet/src/kernel/kernel.js | 5 ++++- packages/swingset-liveslots/src/stop-vat.js | 24 --------------------- 2 files changed, 4 insertions(+), 25 deletions(-) diff --git a/packages/SwingSet/src/kernel/kernel.js b/packages/SwingSet/src/kernel/kernel.js index 28447a6a412..91ddf41a1a8 100644 --- a/packages/SwingSet/src/kernel/kernel.js +++ b/packages/SwingSet/src/kernel/kernel.js @@ -882,7 +882,10 @@ export default function buildKernel( // stopVat succeeded. finish cleanup on behalf of the worker. - // TODO: walk c-list for all decided promises, reject them all #6694 + // walk c-list for all decided promises, reject them all + for (const kpid of vatKeeper.getDecidedPromises()) { + doResolve(vatID, [[kpid, true, disconnectObjectCD]]); + } // TODO: getNonDurableObjectExports, synthesize abandonVSO, // execute it as if it were a syscall. (maybe distinguish between diff --git a/packages/swingset-liveslots/src/stop-vat.js b/packages/swingset-liveslots/src/stop-vat.js index 488fe2af920..a522b5db99e 100644 --- a/packages/swingset-liveslots/src/stop-vat.js +++ b/packages/swingset-liveslots/src/stop-vat.js @@ -33,25 +33,6 @@ import { enumerateKeysWithPrefix } from './vatstore-iterators.js'; const rootSlot = makeVatSlot('object', true, 0n); -function rejectAllPromises({ deciderVPIDs, syscall, disconnectObjectCapData }) { - // Pretend that userspace rejected all non-durable promises. We - // basically do the same thing that `thenReject(p, vpid)(rejection)` - // would have done, but we skip ahead to the syscall.resolve - // part. The real `thenReject` also does pRec.reject(), which would - // give control to userspace (who might have re-imported the promise - // and attached a .then to it), and stopVat() must not allow - // userspace to gain agency. - - const rejections = deciderVPIDs.map(vpid => [ - vpid, - true, - disconnectObjectCapData, - ]); - if (rejections.length) { - syscall.resolve(rejections); - } -} - function identifyExportedRemotables( vrefSet, { exportedRemotables, valToSlot }, @@ -298,11 +279,6 @@ function deleteCollectionsWithDecref({ syscall, vrm }) { // END: the preceding functions aren't ready for use yet export async function releaseOldState(tools) { - // First, pretend that userspace has rejected all non-durable - // promises, so we'll resolve them into the kernel (and retire their - // IDs). - - rejectAllPromises(tools); // The next step is to pretend that the kernel has dropped all // non-durable exports: both the in-RAM Remotables and the on-disk From 24016f039898b4149105cc6b1dfe916cbb99e745 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Fri, 3 Mar 2023 21:02:33 -0500 Subject: [PATCH 05/26] fix(SwingSet): Access getDecidedPromises on the correct object --- packages/SwingSet/src/kernel/kernel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/SwingSet/src/kernel/kernel.js b/packages/SwingSet/src/kernel/kernel.js index 91ddf41a1a8..754db43fc83 100644 --- a/packages/SwingSet/src/kernel/kernel.js +++ b/packages/SwingSet/src/kernel/kernel.js @@ -883,7 +883,7 @@ export default function buildKernel( // stopVat succeeded. finish cleanup on behalf of the worker. // walk c-list for all decided promises, reject them all - for (const kpid of vatKeeper.getDecidedPromises()) { + for (const kpid of kernelKeeper.getDecidedPromises(vatID)) { doResolve(vatID, [[kpid, true, disconnectObjectCD]]); } From 517ab2802eff1992a25ec027b111a01b0625da39 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Tue, 7 Mar 2023 17:23:54 -0500 Subject: [PATCH 06/26] fix(SwingSet): Iterate kpids decided by a vat before removing its data --- packages/SwingSet/src/kernel/kernel.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/SwingSet/src/kernel/kernel.js b/packages/SwingSet/src/kernel/kernel.js index 754db43fc83..a93a809bd4a 100644 --- a/packages/SwingSet/src/kernel/kernel.js +++ b/packages/SwingSet/src/kernel/kernel.js @@ -257,7 +257,9 @@ export default function buildKernel( // check will report 'false'. That's fine, there's no state to // clean up. if (kernelKeeper.vatIsAlive(vatID)) { - const promisesToReject = kernelKeeper.getDecidedPromises(vatID); + // Reject all promises decided by the vat, making sure to capture the list + // of kpids before that data is deleted. + const promisesToReject = [...kernelKeeper.getDecidedPromises(vatID)]; kernelKeeper.cleanupAfterTerminatedVat(vatID); for (const kpid of promisesToReject) { resolveToError(kpid, makeError('vat terminated'), vatID); From 4189e9af57d99830ad1aa34a714c33f115343ff1 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Tue, 7 Mar 2023 17:30:46 -0500 Subject: [PATCH 07/26] style(SwingSet): Colocate getDecidedPromises with related functions --- .../SwingSet/src/kernel/state/kernelKeeper.js | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/packages/SwingSet/src/kernel/state/kernelKeeper.js b/packages/SwingSet/src/kernel/state/kernelKeeper.js index 2a77c76643c..499840cb2ef 100644 --- a/packages/SwingSet/src/kernel/state/kernelKeeper.js +++ b/packages/SwingSet/src/kernel/state/kernelKeeper.js @@ -775,26 +775,6 @@ export default function makeKernelKeeper(kernelStorage, kernelSlog) { kvStore.set(`${kernelSlot}.data.slots`, capdata.slots.join(',')); } - function* getDecidedPromises(vatID) { - const promisePrefix = `${vatID}.c.p`; - for (const k of enumeratePrefixedKeys(kvStore, promisePrefix)) { - // The vpid for a promise imported or exported by a vat (and thus - // potentially a promise for which the vat *might* be the decider) will - // always be of the form `p+NN` or `p-NN`. The corresponding vpid->kpid - // c-list entry will thus always begin with `vMM.c.p`. Decider-ship is - // independent of whether the promise was imported or exported, so we - // have to look up the corresponding kernel promise table entry to see - // whether the vat is the decider or not. If it is, we add the promise - // to the list of promises that must be rejected because the dead vat - // will never be able to act upon them. - const kpid = kvStore.get(k); - const p = getKernelPromise(kpid); - if (p.state === 'unresolved' && p.decider === vatID) { - yield kpid; - } - } - } - function cleanupAfterTerminatedVat(vatID) { insistVatID(vatID); // eslint-disable-next-line no-use-before-define @@ -926,6 +906,26 @@ export default function makeKernelKeeper(kernelStorage, kernelSlog) { kvStore.set(`${kpid}.decider`, ''); } + function* getDecidedPromises(vatID) { + const promisePrefix = `${vatID}.c.p`; + for (const k of enumeratePrefixedKeys(kvStore, promisePrefix)) { + // The vpid for a promise imported or exported by a vat (and thus + // potentially a promise for which the vat *might* be the decider) will + // always be of the form `p+NN` or `p-NN`. The corresponding vpid->kpid + // c-list entry will thus always begin with `vMM.c.p`. Decider-ship is + // independent of whether the promise was imported or exported, so we + // have to look up the corresponding kernel promise table entry to see + // whether the vat is the decider or not. If it is, we add the promise + // to the list of promises that must be rejected because the dead vat + // will never be able to act upon them. + const kpid = kvStore.get(k); + const p = getKernelPromise(kpid); + if (p.state === 'unresolved' && p.decider === vatID) { + yield kpid; + } + } + } + function addSubscriberToPromise(kernelSlot, vatID) { insistKernelType('promise', kernelSlot); insistVatID(vatID); @@ -1569,6 +1569,7 @@ export default function makeKernelKeeper(kernelStorage, kernelSlog) { addSubscriberToPromise, setDecider, clearDecider, + getDecidedPromises, incrementRefCount, decrementRefCount, getObjectRefCount, @@ -1598,7 +1599,6 @@ export default function makeKernelKeeper(kernelStorage, kernelSlog) { provideVatKeeper, vatIsAlive, evictVatKeeper, - getDecidedPromises, cleanupAfterTerminatedVat, addDynamicVatID, getDynamicVats, From f0ee093e84e824954371e2f677d0786be205e9c4 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Tue, 7 Mar 2023 17:58:40 -0500 Subject: [PATCH 08/26] style(SwingSet): Align promise-by-decider generator with related functions --- packages/SwingSet/src/kernel/kernel.js | 6 +++--- packages/SwingSet/src/kernel/state/kernelKeeper.js | 9 +++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/SwingSet/src/kernel/kernel.js b/packages/SwingSet/src/kernel/kernel.js index a93a809bd4a..f91463d2f0e 100644 --- a/packages/SwingSet/src/kernel/kernel.js +++ b/packages/SwingSet/src/kernel/kernel.js @@ -259,9 +259,9 @@ export default function buildKernel( if (kernelKeeper.vatIsAlive(vatID)) { // Reject all promises decided by the vat, making sure to capture the list // of kpids before that data is deleted. - const promisesToReject = [...kernelKeeper.getDecidedPromises(vatID)]; + const deadPromises = [...kernelKeeper.enumeratePromisesByDecider(vatID)]; kernelKeeper.cleanupAfterTerminatedVat(vatID); - for (const kpid of promisesToReject) { + for (const kpid of deadPromises) { resolveToError(kpid, makeError('vat terminated'), vatID); } } @@ -885,7 +885,7 @@ export default function buildKernel( // stopVat succeeded. finish cleanup on behalf of the worker. // walk c-list for all decided promises, reject them all - for (const kpid of kernelKeeper.getDecidedPromises(vatID)) { + for (const kpid of kernelKeeper.enumeratePromisesByDecider(vatID)) { doResolve(vatID, [[kpid, true, disconnectObjectCD]]); } diff --git a/packages/SwingSet/src/kernel/state/kernelKeeper.js b/packages/SwingSet/src/kernel/state/kernelKeeper.js index 499840cb2ef..e3afc63d10d 100644 --- a/packages/SwingSet/src/kernel/state/kernelKeeper.js +++ b/packages/SwingSet/src/kernel/state/kernelKeeper.js @@ -820,8 +820,8 @@ export default function makeKernelKeeper(kernelStorage, kernelSlog) { // that will also delete both db keys } - // the caller used getDecidedPromises() before calling us, so they - // already known the orphaned promises, so it can reject them + // the caller used enumeratePromisesByDecider() before calling us, + // so they already know the orphaned promises to reject // now loop back through everything and delete it all for (const k of enumeratePrefixedKeys(kvStore, `${vatID}.`)) { @@ -906,7 +906,8 @@ export default function makeKernelKeeper(kernelStorage, kernelSlog) { kvStore.set(`${kpid}.decider`, ''); } - function* getDecidedPromises(vatID) { + function* enumeratePromisesByDecider(vatID) { + insistVatID(vatID); const promisePrefix = `${vatID}.c.p`; for (const k of enumeratePrefixedKeys(kvStore, promisePrefix)) { // The vpid for a promise imported or exported by a vat (and thus @@ -1569,7 +1570,7 @@ export default function makeKernelKeeper(kernelStorage, kernelSlog) { addSubscriberToPromise, setDecider, clearDecider, - getDecidedPromises, + enumeratePromisesByDecider, incrementRefCount, decrementRefCount, getObjectRefCount, From f4653983cc51e04adc165d28b5fe21d9453736aa Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Tue, 7 Mar 2023 17:59:24 -0500 Subject: [PATCH 09/26] test(SwingSet): Minor improvements --- packages/SwingSet/test/bootstrap-syscall-failure.js | 2 +- packages/SwingSet/test/test-marshal.js | 2 +- packages/SwingSet/test/vat-syscall-failure.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/SwingSet/test/bootstrap-syscall-failure.js b/packages/SwingSet/test/bootstrap-syscall-failure.js index e22cc98d98d..123e6b54fbc 100644 --- a/packages/SwingSet/test/bootstrap-syscall-failure.js +++ b/packages/SwingSet/test/bootstrap-syscall-failure.js @@ -34,7 +34,7 @@ export function buildRootObject(vatPowers, vatParameters) { () => testLog('p2 resolve (bad!)'), e => testLog(`p2 reject ${e}`), ); - const p3 = E(badvat).begood(ourThing); + const p3 = E(badvat).begoodagain(ourThing); p3.then( () => testLog('p3 resolve (bad!)'), e => testLog(`p3 reject ${e}`), diff --git a/packages/SwingSet/test/test-marshal.js b/packages/SwingSet/test/test-marshal.js index ccc6b6c7aad..16029f47390 100644 --- a/packages/SwingSet/test/test-marshal.js +++ b/packages/SwingSet/test/test-marshal.js @@ -144,7 +144,7 @@ test('unserialize promise', async t => { t.truthy(p instanceof Promise); }); -test('kernel serialzation of errors', async t => { +test('kernel serialization of errors', async t => { // The kernel synthesizes e.g. `Error('vat-upgrade failure')`, so we // need kmarshal to serialize those errors in a deterministic // way. This test checks that we don't get surprising things like diff --git a/packages/SwingSet/test/vat-syscall-failure.js b/packages/SwingSet/test/vat-syscall-failure.js index 7442ac1d163..861c73e399e 100644 --- a/packages/SwingSet/test/vat-syscall-failure.js +++ b/packages/SwingSet/test/vat-syscall-failure.js @@ -8,7 +8,7 @@ export default function setup(syscall, _state, _helpers, vatPowers) { } const { method, args } = extractMessage(vatDeliverObject); vatPowers.testLog(`${method}`); - const thing = method === 'begood' ? args.slots[0] : 'o-3414159'; + const thing = method.startsWith('begood') ? args.slots[0] : 'o-3414159'; syscall.send(thing, kser(['pretendToBeAThing', [method]])); } return dispatch; From 82b37a7fabaa25e9156ed3d8ca6ac477bf706c05 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Tue, 7 Mar 2023 18:39:02 -0500 Subject: [PATCH 10/26] style(SwingSet): Improve variable names and step ordering --- packages/SwingSet/src/kernel/kernel.js | 84 +++++++++++++++----------- 1 file changed, 49 insertions(+), 35 deletions(-) diff --git a/packages/SwingSet/src/kernel/kernel.js b/packages/SwingSet/src/kernel/kernel.js index f91463d2f0e..248f2bfc617 100644 --- a/packages/SwingSet/src/kernel/kernel.js +++ b/packages/SwingSet/src/kernel/kernel.js @@ -821,39 +821,37 @@ export default function buildKernel( upgradeMessage, incarnationNumber: vatKeeper.getIncarnationNumber(), }; - const disconnectObjectCD = kser(disconnectObject); + const disconnectionCapData = kser(disconnectObject); /** @type { import('../types-external.js').KernelDeliveryStopVat } */ - const kd1 = harden(['stopVat', disconnectObjectCD]); - const vd1 = vatWarehouse.kernelDeliveryToVatDelivery(vatID, kd1); - const status1 = await deliverAndLogToVat(vatID, kd1, vd1); + const stopVatKD = harden(['stopVat', disconnectionCapData]); + const stopVatVD = vatWarehouse.kernelDeliveryToVatDelivery( + vatID, + stopVatKD, + ); + const stopVatStatus = await deliverAndLogToVat(vatID, stopVatKD, stopVatVD); + const stopVatResults = deliveryCrankResults(vatID, stopVatStatus, false); - // TODO: send BOYD to the vat, to give it one last chance to clean - // up, drop imports, and delete durable data. If we ever have a - // vat that is so broken it can't do BOYD, we can make that - // optional. #7001 + // We don't meter stopVat, since no user code is running, but we + // still report computrons to the runPolicy + let { computrons } = stopVatResults; // BigInt or undefined + if (computrons !== undefined) { + assert.typeof(computrons, 'bigint'); + } - // make arguments for vat-vat-admin.js vatUpgradeCallback() /** - * @param {SwingSetCapData} _errorCD + * Make a method-arguments structure representing failure + * for vat-vat-admin.js vatUpgradeCallback(). + * + * @param {SwingSetCapData} _errorCapData * @returns {RawMethargs} */ - function makeFailure(_errorCD) { - insistCapData(_errorCD); // kser(Error) + const makeFailureMethargs = _errorCapData => { + insistCapData(_errorCapData); // kser(Error) // const error = kunser(_errorCD) // actually we shouldn't reveal the details, so instead we do: const error = Error('vat-upgrade failure'); return ['vatUpgradeCallback', [upgradeID, false, error]]; - } - - // We use deliveryCrankResults to parse the stopVat status. - const results1 = deliveryCrankResults(vatID, status1, false); - - // We don't meter stopVat, since no user code is running, but we - // still report computrons to the runPolicy - let { computrons } = results1; // BigInt or undefined - if (computrons !== undefined) { - assert.typeof(computrons, 'bigint'); - } + }; // TODO: if/when we implement vat pause/suspend, and if // deliveryCrankResults changes to not use .terminate to indicate @@ -861,18 +859,20 @@ export default function buildKernel( // pause/suspend a vat for a delivery error, here we want to // unwind the upgrade. - if (results1.terminate) { + if (stopVatResults.terminate) { // get rid of the worker, so the next delivery to this vat will // re-create one from the previous state // eslint-disable-next-line @jessie.js/no-nested-await await vatWarehouse.stopWorker(vatID); // notify vat-admin of the failed upgrade - const vatAdminMethargs = makeFailure(results1.terminate.info); + const vatAdminMethargs = makeFailureMethargs( + stopVatResults.terminate.info, + ); // we still report computrons to the runPolicy const results = harden({ - ...results1, + ...stopVatResults, computrons, abort: true, // always unwind consumeMessage: true, // don't repeat the upgrade @@ -884,9 +884,14 @@ export default function buildKernel( // stopVat succeeded. finish cleanup on behalf of the worker. + // TODO: send BOYD to the vat, to give it one last chance to clean + // up, drop imports, and delete durable data. If we ever have a + // vat that is so broken it can't do BOYD, we can make that + // optional. #7001 + // walk c-list for all decided promises, reject them all for (const kpid of kernelKeeper.enumeratePromisesByDecider(vatID)) { - doResolve(vatID, [[kpid, true, disconnectObjectCD]]); + resolveToError(kpid, disconnectionCapData, vatID); } // TODO: getNonDurableObjectExports, synthesize abandonVSO, @@ -909,23 +914,32 @@ export default function buildKernel( // deliver a startVat with the new vatParameters /** @type { import('../types-external.js').KernelDeliveryStartVat } */ - const kd2 = harden(['startVat', vatParameters]); - const vd2 = vatWarehouse.kernelDeliveryToVatDelivery(vatID, kd2); + const startVatKD = harden(['startVat', vatParameters]); + const startVatVD = vatWarehouse.kernelDeliveryToVatDelivery( + vatID, + startVatKD, + ); // decref vatParameters now that translation did incref for (const kref of vatParameters.slots) { kernelKeeper.decrementRefCount(kref, 'upgrade-vat-event'); } - const status2 = await deliverAndLogToVat(vatID, kd2, vd2); - const results2 = deliveryCrankResults(vatID, status2, false); - computrons = addComputrons(computrons, results2.computrons); + const startVatStatus = await deliverAndLogToVat( + vatID, + startVatKD, + startVatVD, + ); + const startVatResults = deliveryCrankResults(vatID, startVatStatus, false); + computrons = addComputrons(computrons, startVatResults.computrons); - if (results2.terminate) { + if (startVatResults.terminate) { // unwind just like above // eslint-disable-next-line @jessie.js/no-nested-await await vatWarehouse.stopWorker(vatID); - const vatAdminMethargs = makeFailure(results2.terminate.info); + const vatAdminMethargs = makeFailureMethargs( + startVatResults.terminate.info, + ); const results = harden({ - ...results2, + ...startVatResults, computrons, abort: true, // always unwind consumeMessage: true, // don't repeat the upgrade From 9ce63bc491c276577f4a28e0fc4ba5ced1b54c08 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Wed, 8 Mar 2023 13:55:10 -0500 Subject: [PATCH 11/26] test(swingset-liveslots): Verify that vat upgrade rejects local promises --- packages/swingset-liveslots/package.json | 4 +- .../test/test-vat-upgrade.js | 73 +++++++++++++++++++ .../test/vat-durable-promise-watcher.js | 40 ++++++++++ 3 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 packages/swingset-liveslots/test/test-vat-upgrade.js create mode 100644 packages/swingset-liveslots/test/vat-durable-promise-watcher.js diff --git a/packages/swingset-liveslots/package.json b/packages/swingset-liveslots/package.json index 9efed053c92..0fa13f591e0 100644 --- a/packages/swingset-liveslots/package.json +++ b/packages/swingset-liveslots/package.json @@ -16,7 +16,9 @@ "lint:types": "tsc -p jsconfig.json", "lint:eslint": "eslint ." }, - "devDependencies": {}, + "devDependencies": { + "@agoric/swingset-vat": "^0.30.2" + }, "dependencies": { "@agoric/assert": "^0.5.1", "@agoric/internal": "^0.2.1", diff --git a/packages/swingset-liveslots/test/test-vat-upgrade.js b/packages/swingset-liveslots/test/test-vat-upgrade.js new file mode 100644 index 00000000000..d03a2ca3411 --- /dev/null +++ b/packages/swingset-liveslots/test/test-vat-upgrade.js @@ -0,0 +1,73 @@ +import '@agoric/swingset-vat/tools/prepare-test-env.js'; +import test from 'ava'; +import { buildVatController } from '@agoric/swingset-vat'; +import { kunser } from '@agoric/swingset-vat/src/lib/kmarshal.js'; + +const bfile = name => new URL(name, import.meta.url).pathname; + +test('local promises are rejected by vat upgrade', async t => { + // TODO: Generalize packages/SwingSet/test/upgrade/test-upgrade.js + /** @type {SwingSetConfig} */ + const config = { + includeDevDependencies: true, // for vat-data + defaultManagerType: 'xs-worker', + bootstrap: 'bootstrap', + defaultReapInterval: 'never', + vats: { + bootstrap: { + sourceSpec: bfile('../../SwingSet/test/bootstrap-relay.js'), + }, + }, + bundles: { + watcher: { sourceSpec: bfile('./vat-durable-promise-watcher.js') }, + }, + }; + const c = await buildVatController(config); + t.teardown(c.shutdown); + c.pinVatRoot('bootstrap'); + await c.run(); + + const run = async (method, args = []) => { + assert(Array.isArray(args)); + const kpid = c.queueToVatRoot('bootstrap', method, args); + await c.run(); + const status = c.kpStatus(kpid); + if (status === 'fulfilled') { + const result = c.kpResolution(kpid); + return kunser(result); + } + assert(status === 'rejected'); + const err = c.kpResolution(kpid); + throw kunser(err); + }; + const messageVat = (name, methodName, args) => + run('messageVat', [{ name, methodName, args }]); + // eslint-disable-next-line no-underscore-dangle + const _messageObject = (presence, methodName, args) => + run('messageVatObject', [{ presence, methodName, args }]); + + const S = Symbol.for('passable'); + await run('createVat', [{ name: 'watcher', bundleCapName: 'watcher' }]); + await messageVat('watcher', 'watchLocalPromise', ['orphaned']); + await messageVat('watcher', 'watchLocalPromise', ['fulfilled', S]); + await messageVat('watcher', 'watchLocalPromise', ['rejected', undefined, S]); + const v1Settlements = await messageVat('watcher', 'getSettlements'); + t.deepEqual(v1Settlements, { + fulfilled: { status: 'fulfilled', value: S }, + rejected: { status: 'rejected', reason: S }, + }); + await run('upgradeVat', [{ name: 'watcher', bundleCapName: 'watcher' }]); + const v2Settlements = await messageVat('watcher', 'getSettlements'); + t.deepEqual(v2Settlements, { + fulfilled: { status: 'fulfilled', value: S }, + rejected: { status: 'rejected', reason: S }, + orphaned: { + status: 'rejected', + reason: { + name: 'vatUpgraded', + upgradeMessage: 'vat upgraded', + incarnationNumber: 1, + }, + }, + }); +}); diff --git a/packages/swingset-liveslots/test/vat-durable-promise-watcher.js b/packages/swingset-liveslots/test/vat-durable-promise-watcher.js new file mode 100644 index 00000000000..aad122941dc --- /dev/null +++ b/packages/swingset-liveslots/test/vat-durable-promise-watcher.js @@ -0,0 +1,40 @@ +import { Far } from '@endo/marshal'; +import { getCopyMapEntries, M } from '@agoric/store'; +import { makePromiseKit } from '@endo/promise-kit'; +import { + prepareExo, + provideDurableMapStore, + watchPromise, +} from '@agoric/vat-data'; + +export function buildRootObject(_vatPowers, vatParameters, baggage) { + const settlements = provideDurableMapStore(baggage, 'settlements'); + const PromiseWatcherI = M.interface('PromiseWatcher', { + onFulfilled: M.call(M.any(), M.string()).returns(), + onRejected: M.call(M.any(), M.string()).returns(), + }); + const watcher = prepareExo(baggage, 'PromiseWatcher', PromiseWatcherI, { + onFulfilled(value, name) { + settlements.init(name, harden({ status: 'fulfilled', value })); + }, + onRejected(reason, name) { + settlements.init(name, harden({ status: 'rejected', reason })); + }, + }); + + return Far('root', { + watchLocalPromise: (name, fulfillment, rejection) => { + const { promise, resolve, reject } = makePromiseKit(); + if (fulfillment !== undefined) { + resolve(fulfillment); + } else if (rejection !== undefined) { + reject(rejection); + } + watchPromise(promise, watcher, name); + }, + getSettlements: () => { + const settlementsCopyMap = settlements.snapshot(); + return Object.fromEntries(getCopyMapEntries(settlementsCopyMap)); + }, + }); +} From a602f2cc4f682d1f29d3d0807d931184ae4858b7 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Wed, 8 Mar 2023 13:59:57 -0500 Subject: [PATCH 12/26] docs(swingset-liveslots): Clean up VPID managment documentation --- .../swingset-liveslots/src/vpid-tracking.md | 75 ++++++++++--------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/packages/swingset-liveslots/src/vpid-tracking.md b/packages/swingset-liveslots/src/vpid-tracking.md index 7c32976a186..e8725c5360d 100644 --- a/packages/swingset-liveslots/src/vpid-tracking.md +++ b/packages/swingset-liveslots/src/vpid-tracking.md @@ -2,85 +2,88 @@ Kernels and vats communicate about promises by referring to their VPIDs: vat(-centric) promise IDs. These are strings like `p+12` and `p-23`. Like VOIDs (object IDs), the plus/minus sign indicates which side of the boundary allocated the number (`p+12` and `o+12` are allocated by the vat, `p-13` and `o-13` are allocated by the kernel). But where the object ID sign also indicates which side "owns" the object (i.e. where the behavior lives), the promise ID sign is generally irrelevant. -Instead, we care about which side holds the resolution authority. This is not indicated by the VPID sign, and in fact is not necessarily static. Liveslots does not currently have any mechanism to allow one promise to be forwarded to another, but if it acquires this some day, then the decider of a promise could shift from kernel to vat to kernel again before it finally gets resolved. And there *is* a sequence that allows a vat to receive a reference to a promise in method arguments first, then receive a message whose result promise uses that VPID second (`p1 = p2~.foo(); x~.bar(p1)`, then someone resolves `p2` to `x`). In this case, the decider is initially the kernel, then the authority is transferred to the vat later. +Instead, we care about which side holds the resolution authority for a promise (referred to as being its **decider**). This is not indicated by the VPID sign, and in fact is not necessarily static. Liveslots does not currently have any mechanism to allow one promise to be forwarded to another, but if it acquires this some day, then the decider of a promise could shift from kernel to vat to kernel again before it finally gets resolved. And there *are* sequences that allow a vat to receive a reference to a promise in method arguments before receiving a message for which that same VPID identifies the result promise (e.g., `pk = makePromiseKit(); p2 = E(pk.promise).push('queued'); await E(observer).push(p2); pk.resolve(observer)` with an observer whose `push` returns a prompt response). In such cases, the decider is initially the kernel but later becomes the receiving vat. -Each `Promise` starts out in the "unresolved" state, then later transitions irrevocably to the "resolved" state. Liveslots frequently (but not always) pays attention to this transition by calling `.then`, to attach a callback. To handle resolution cycles, liveslots remembers the resolution of old promises in a `WeakMap` for as long as the `Promise` exists. Consequently, for liveslots' purposes, every `Promise` is either resolved (the callback has fired and liveslots remembers the resolution), or unresolved (liveslots has not yet seen a resolution). +Each Promise starts out in the "unresolved" state, then later transitions irrevocably to the "resolved" state. Liveslots frequently (but not always) pays attention to this transition by calling `then` to attach fulfillment/rejection callbacks. To handle resolution cycles, liveslots remembers the resolution of old promises in a `WeakMap` for as long as the Promise exists. Consequently, for liveslots' purposes, every Promise is either resolved (a callback has fired and liveslots remembers the settlement), or unresolved (liveslots has not yet seen a resolution). There are roughly four ways that liveslots might become aware of a promise: -* serialization: a `Promise` instance is serialized, either for the arguments of an outbound `syscall.send` or `syscall.resolve`, the argument of `watchPromise()`, or to be stored into virtualized data (e.g. `bigMapStore.set(key, promise)`, or assignment to a property of a virtual object) -* creation for outbound result: liveslots allocates a VPID for the `.result` of an outbound `syscall.send`, and creates a new `Promise` instance to give back to userspace -* deserialization: the arguments of an inbound `dispatch.deliver` or `dispatch.notify` are deserialized, and a new `Promise` instance is created -* inbound result: the kernel-allocated `.result` VPID of an inbound `dispatch.deliver` is associated with the `Promise` we get back from `HandledPromise.applyMethod` +* serialization: a Promise instance is serialized, either for the arguments of an outbound `syscall.send` or `syscall.resolve`, the argument of `watchPromise()`, or to be stored into virtualized data (e.g. `bigMapStore.set(key, promise)`, or assignment to a property of a virtual object) +* creation for outbound result: liveslots allocates a VPID for the `result` of an outbound `syscall.send`, and creates a new Promise instance to give back to userspace +* deserialization: the arguments of an inbound `dispatch.deliver` or `dispatch.notify` are deserialized, and a new Promise instance is created +* inbound result: the kernel-allocated `result` VPID of an inbound `dispatch.deliver` is associated with the Promise we get back from `HandledPromise.applyMethod` -A `Promise` may be associated with a VPID even though the kernel does not know about it (i.e. the VPID is not in the c-list): this can occur when a Promise is merely stored into virtual data without also being sent to (or received from) the kernel. The kernel's knowledge is temporary: once the promise is resolved (either `syscall.resolve` or `dispatch.notify`), the VPID is retired from the vat's c-list. So a VPID might start out stored only in vdata, then get sent to the kernel, then get resolved, leaving it solely in vdata once more. +A Promise may be associated with a VPID even though the kernel does not know about it (i.e. the VPID is not in the kernel's c-list for that vat). This can occur when a Promise is stored into virtual data without also being sent to (or received from) the kernel. It can also occur when a Promise is resolved but still referenced in vdata (the kernel's knowledge is temporary; it retires VPIDs from c-lists upon `syscall.resolve` or `dispatch.notify` as relevant). So a VPID might start out stored only in vdata, then get sent to the kernel, then get resolved, leaving it solely in vdata once more. -Each unresolved VPID has a decider: either the vat or the kernel. The VPID is resolved by the first of the following events: +Each unresolved VPID has a decider: either the kernel or a vat. It can remain unresolved for arbitrarily long, but becomes resolved by the first of the following events: -* if/when userspace resolves the corresponding `Promise` and liveslots learns of the resolution, then liveslots will perform a `syscall.resolve()` -* if/when the vat is upgraded, liveslots will perform a `syscall.resolve()` of all remaining VPIDs during the delivery of `dispatch.stopVat()` (after which all `Promise`s evaporate along with the rest of the JS heap) -* if/when the vat is terminated, the kernel internally rejects all remaining vat-decided KPIDs, without involving the vat -* otherwise, the VPID remains unresolved until the heat death of the universe +* if userspace resolves the corresponding Promise and liveslots learns of the resolution, then liveslots will perform a `syscall.resolve()` +* if the vat is upgraded, liveslots will perform a `syscall.resolve()` of all remaining VPIDs during the delivery of `dispatch.stopVat()` (after which all Promises evaporate along with the rest of the JS heap) +* if the vat is terminated, the kernel internally rejects all remaining vat-decided KPIDs without involving the vat Liveslots tracks promises in the following data structures: -* `slotToVal` / `valToSlot` : these manage *registration*, the mapping from VPID to `Promise` and vice versa. These also register objects (Presences, Remotables, and Representatives) to/from VOIDs, and device nodes. +* `slotToVal` / `valToSlot` : these manage *registration*, the mapping from VPID to Promise and vice versa. These also register objects (Presences, Remotables, and Representatives) to/from VOIDs, and device nodes. * to support GC of objects, `slotToVal.get(vref)` is a WeakRef, and `valToSlot` is a WeakMap * liveslots uses independent strong references to maintain object/promise lifetimes * `exportedVPIDs`: a `Map`: all Promises currently known to the kernel and decided by the vat * `importedVPIDs`: a `Map`: all Promises currently known to the kernel and decided by the kernel * `remotableRefCounts`: a `Map`: all Promises (and Remotables) referenced by virtual data -The vat-kernel c-list contains all VPIDs in `exportedVPIDs` and `importedVPIDs`. The vat is the decider for `exportedVPIDs`, while the kernel is the decider for `importedVPIDs`. For every VPID in `exportedVPIDs`, we've used `.then` on the `Promise` instance to arrange for a `syscall.resolve` when the promise resolves or rejects. For every VPID key of the `importedVPIDs` Map, the corresponding value is a `[resolve, reject]` "`pRec`", so one of them can be called during `dispatch.notify`. Every VPID in `slotToVal` is either in `exportedVPIDs`, `importedVPIDs`, or neither. +The kernel's c-list for a vat contains all VPIDs in `exportedVPIDs` and `importedVPIDs`. The vat is the decider for `exportedVPIDs`, while the kernel is the decider for `importedVPIDs`. For every VPID in `exportedVPIDs`, we've used `then` on the Promise instance to arrange for a `syscall.resolve` when it settles (becomes fulfilled or rejected). For every VPID key of the `importedVPIDs` Map, the corresponding value is a `[resolve, reject]` "**pRec**", so one of the functions can be called during `dispatch.notify`. Every VPID in `slotToVal` is either in `exportedVPIDs` but not `importedVPIDs`, `importedVPIDs` but not `exportedVPIDs`, or neither. -If a VPID in `importedVPIDs` is resolved (by the kernel, via `dispatch.notify`), the VPID is removed from `importedVPIDs`. If a VPID in `exportedVPIDs` is resolved (by the vat, i.e. liveslots observes the previously-added `.then` callback be executed), liveslots invokes `syscall.resolve` and removes the VPID from `exportedVPIDs`. The c-list will not contain VPIDs for any resolved promise. +If a VPID in `importedVPIDs` is resolved (by the kernel, via `dispatch.notify`), the VPID is removed from `importedVPIDs`. If a VPID in `exportedVPIDs` is resolved (by the vat, i.e. liveslots observes invocation of a previously-added settlement callback), liveslots invokes `syscall.resolve` and removes the VPID from `exportedVPIDs`. The c-list for a vat will not contain a VPID for any resolved promise. -The `slotToVal`/`valToSlot` registration must remain until 1: the kernel is no longer aware of the VPID, 2: the Promise is not present in any virtual data, and 3: the promise is not being watched by a `promiseWatcher`. If the registration were to be lost while one of those three conditions were still true, a replacement `Promise` might be created while the original was still around, causing confusion. +The `slotToVal`/`valToSlot` registration must remain until all of the following are true: + +* the kernel is no longer aware of the VPID +* the Promise is not present in any virtual data +* the promise is not being watched by a `promiseWatcher`. + +If the registration were to be lost while any of the above conditions were still true, a replacement Promise might be created while the original was still around, causing confusion. ## Maintaining Strong References -Remember that the `slotToVal` registration uses a WeakRef, so being registered there does not keep the `Promise` object alive. +Remember that the `slotToVal` registration uses a WeakRef, so being registered there does not keep the Promise object alive. -`exportedVPIDs` and `importedVPIDs` keep their `Promise` alive in their value. vdata keeps it alive through the key of `remotableRefCounts`. `promiseWatcher` uses an internal `ScalarBigMapStore` to keep the `Promise` alive. +`exportedVPIDs` and `importedVPIDs` keep their Promise alive in their value. vdata keeps it alive through the key of `remotableRefCounts`. `promiseWatcher` uses an internal `ScalarBigMapStore` to keep the Promise alive. ## Promise/VPID Management Algorithm -* When a `Promise` is first serialized (it appears in `convertValToSlot`), a VPID is assigned and the VPID/`Promise` mapping is registered in `valToSlot`/`slotToVal` +* When a Promise is first serialized (it appears in `convertValToSlot`), a VPID is assigned and the VPID/Promise mapping is registered in `valToSlot`/`slotToVal` * at this point, there is not yet a strong reference to the Promise * When a VPID appears in the serialized arguments of `syscall.send` or `syscall.resolve`: * if the VPID already exists in `exportedVPIDs` or `importedVPIDs`: do nothing - * else: use `followForKernel` to add to `exportedVPIDs` and use `.then()` to attach a `handle` callback -* When `followForKernel`'s `handle` callback is executed: + * else: use `followForKernel` to add the VPID to `exportedVPIDs` and attach settlement callbacks +* When a `followForKernel` settlement callback is executed: * do `syscall.resolve()` * remove from `exportedVPIDs` - * check `remotableRefCounts`. If 0: unregister from `valToSlot`/`slotToVal` + * if `remotableRefCounts` reports 0 references: unregister from `valToSlot`/`slotToVal` * When the kernel delivers a `dispatch.notify`: - * retrieve the `resolve`/`reject` "`pRec`" from `importedVPIDs` + * retrieve the `[resolve, reject]` pRec from `importedVPIDs` * invoke the appropriate function with the deserialized argument - * check `remotableRefCounts`. If 0: unregister from `valToSlot`/`slotToVal` + * if `remotableRefCounts` reports 0 references: unregister from `valToSlot`/`slotToVal` * When the vdata refcount for a VPID drops to zero: * if the VPID still exists in `exportedVPIDs` or `importedVPIDs`: do nothing * else: unregister from `valToSlot`/`slotToVal` * When a new VPID is deserialized (it appears in `convertSlotToVal`), this must be the arguments of a delivery (not vdata) * use `makePipelinablePromise` to create a HandledPromise for the VPID - * add the Promise and it's `resolve`/`reject` pair to `importedVPIDs` - * register the Promise in `valToSlot`/`slotToVal'` + * add the Promise and its `resolve`/`reject` pair to `importedVPIDs` + * register the Promise in `valToSlot`/`slotToVal` * use `syscall.subscribe` to request a `dispatch.notify` delivery when the kernel resolves this promise -* When a VPID appears as the `.result` of an outbound `syscall.send`: +* When a VPID appears as the `result` of an outbound `syscall.send`: (_note overlap with the preceding_) * use `allocateVPID` to allocate a new VPID * use `makePipelinablePromise` to create a HandledPromise for the VPID - * add the Promise and it's `resolve`/`reject` pair to `importedVPIDs` - * register the Promise in `valToSlot`/`slotToVal'` + * add the Promise and its `resolve`/`reject` pair to `importedVPIDs` + * register the Promise in `valToSlot`/`slotToVal` * use `syscall.subscribe` to request a `dispatch.notify` delivery when the kernel resolves this promise -* When a VPID appears as the `.result` of an inbound `dispatch.deliver`: - * check to see if the VPID is present in `importedVPIDs`: - * if yes: extract `pRec`, use `pRec.resolve(res)` to forward the invocation result promise to the previously-imported promise, then remove the VPID from `importedVPIDs` - * if no: register `res` the invocation result promise under the VPID - * in either case, next we add the VPID to `exportedVPIDs` - * then we call `followForKernel` to attach a callback to the `res` promise +* When a VPID appears as the `result` of an inbound `dispatch.deliver`: + * if the VPID is present in `importedVPIDs`: retrieve the `[resolve, reject]` pRec and use `resolve(res)` to forward the invocation result promise to the previously-imported promise, then remove the VPID from `importedVPIDs` + * else: register `res` the invocation result promise under the VPID + * in either case, use `followForKernel` to add the VPID to `exportedVPIDs` and attach settlement callbacks -If the serialization is for storage in virtual data, the act of storing the `VPID` will add the `Promise` to `remotableRefCounts`, which maintains a strong reference for as long as the VPID is held. When it is removed from virtual data (or the object/collection is deleted), the refcount will be decremented. When the refcount drops to zero, we perform the `exportedVPIDs`/`importedVPIDs` check and then maybe unregister the promise. +If the serialization is for storage in virtual data, the act of storing the VPID will add the Promise to `remotableRefCounts`, which maintains a strong reference for as long as the VPID is held. When it is removed from virtual data (or the object/collection is deleted), the refcount will be decremented. When the refcount drops to zero, we perform the `exportedVPIDs`/`importedVPIDs` check and then maybe unregister the promise. If the serialization is for the arguments of an outbound `syscall.send` or `syscall.resolve` (or `syscall.callNow`, or `syscall.exit`), the VPID will be added to `exportedVPIDs`. From 5d841578aa2fbe92fe99a5f376b6a8d12475dfc0 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Wed, 8 Mar 2023 21:07:26 -0500 Subject: [PATCH 13/26] refactor(swingset-liveslots): Update some function signatures Increases clarity and convenience and sets up for future changes. --- packages/swingset-liveslots/src/liveslots.js | 26 +++++++++----- packages/swingset-liveslots/src/stop-vat.js | 1 - .../swingset-liveslots/src/watchedPromises.js | 35 ++++++++++--------- .../tools/fakeVirtualSupport.js | 19 ++++++---- 4 files changed, 49 insertions(+), 32 deletions(-) diff --git a/packages/swingset-liveslots/src/liveslots.js b/packages/swingset-liveslots/src/liveslots.js index 02e3711a249..e903a3f228a 100644 --- a/packages/swingset-liveslots/src/liveslots.js +++ b/packages/swingset-liveslots/src/liveslots.js @@ -551,7 +551,14 @@ function build( const knownResolutions = new WeakMap(); - // this is called with all outbound argument vrefs + /** + * Determines if a vref from an outbound argument + * identifies a promise that should be exported, and if so then + * adds it to exportedVPIDs and sets up handlers. + * + * @param {any} vref + * @returns {boolean} + */ function maybeExportPromise(vref) { // we only care about new vpids if ( @@ -570,7 +577,9 @@ function build( // if (!knownResolutions.has(p)) { // TODO really? // eslint-disable-next-line no-use-before-define followForKernel(vpid, p); + return true; } + return false; } function exportPassByPresence() { @@ -657,18 +666,15 @@ function build( assertAcceptableSyscallCapdataSize, ); - const watchedPromiseManager = makeWatchedPromiseManager( + const watchedPromiseManager = makeWatchedPromiseManager({ syscall, vrm, vom, collectionManager, // eslint-disable-next-line no-use-before-define convertValToSlot, - unmeteredConvertSlotToVal, - // eslint-disable-next-line no-use-before-define - meterControl.unmetered(revivePromise), - unmeteredUnserialize, - ); + convertSlotToVal: unmeteredConvertSlotToVal, + }); function convertValToSlot(val) { // lsdebug(`serializeToSlot`, val, Object.isFrozen(val)); @@ -816,6 +822,7 @@ function build( registerValue(slot, p); return p; } + const unmeteredRevivePromise = meterControl.unmetered(revivePromise); function resolutionCollector() { const resolutions = []; @@ -1424,7 +1431,10 @@ function build( Fail`buildRootObject() for vat ${forVatID} returned ${rootObject} with no interface`; // Need to load watched promises *after* buildRootObject() so that handler kindIDs // have a chance to be reassociated with their handlers. - watchedPromiseManager.loadWatchedPromiseTable(); + watchedPromiseManager.loadWatchedPromiseTable( + unmeteredUnserialize, + unmeteredRevivePromise, + ); const rootSlot = makeVatSlot('object', true, BigInt(0)); valToSlot.set(rootObject, rootSlot); diff --git a/packages/swingset-liveslots/src/stop-vat.js b/packages/swingset-liveslots/src/stop-vat.js index a522b5db99e..4a5ab226ff5 100644 --- a/packages/swingset-liveslots/src/stop-vat.js +++ b/packages/swingset-liveslots/src/stop-vat.js @@ -279,7 +279,6 @@ function deleteCollectionsWithDecref({ syscall, vrm }) { // END: the preceding functions aren't ready for use yet export async function releaseOldState(tools) { - // The next step is to pretend that the kernel has dropped all // non-durable exports: both the in-RAM Remotables and the on-disk // virtual objects (but not the root object). This will trigger diff --git a/packages/swingset-liveslots/src/watchedPromises.js b/packages/swingset-liveslots/src/watchedPromises.js index 8a7e6cabbc7..2edc26ac540 100644 --- a/packages/swingset-liveslots/src/watchedPromises.js +++ b/packages/swingset-liveslots/src/watchedPromises.js @@ -7,27 +7,23 @@ import { E } from '@endo/eventual-send'; import { parseVatSlot } from './parseVatSlots.js'; /** - * - * @param {*} syscall - * @param {*} vrm - * @param {import('./virtualObjectManager.js').VirtualObjectManager} vom - * @param {*} cm - * @param {*} convertValToSlot - * @param {*} convertSlotToVal - * @param {*} [revivePromise] - * @param {*} [unserialize] + * @param {object} options + * @param {*} options.syscall + * @param {*} options.vrm + * @param {import('./virtualObjectManager.js').VirtualObjectManager} options.vom + * @param {*} options.collectionManager + * @param {import('@endo/marshal').ConvertValToSlot} options.convertValToSlot + * @param {import('@endo/marshal').ConvertSlotToVal} options.convertSlotToVal */ -export function makeWatchedPromiseManager( +export function makeWatchedPromiseManager({ syscall, vrm, vom, - cm, + collectionManager, convertValToSlot, convertSlotToVal, - revivePromise, - unserialize, -) { - const { makeScalarBigMapStore } = cm; +}) { + const { makeScalarBigMapStore } = collectionManager; const { defineDurableKind } = vom; // virtual Store (not durable) mapping vpid to Promise objects, to @@ -104,7 +100,14 @@ export function makeWatchedPromiseManager( ); } - function loadWatchedPromiseTable() { + /** + * Revives watched promises. + * + * @param {import('@endo/marshal').Unserialize} unserialize + * @param {(vref: any) => Promise} revivePromise + * @returns {void} + */ + function loadWatchedPromiseTable(unserialize, revivePromise) { const deadPromisesRaw = syscall.vatstoreGet('deadPromises'); if (!deadPromisesRaw) { return; diff --git a/packages/swingset-liveslots/tools/fakeVirtualSupport.js b/packages/swingset-liveslots/tools/fakeVirtualSupport.js index b8639f998d1..6e90a9e073e 100644 --- a/packages/swingset-liveslots/tools/fakeVirtualSupport.js +++ b/packages/swingset-liveslots/tools/fakeVirtualSupport.js @@ -268,15 +268,20 @@ export function makeFakeVirtualReferenceManager( ); } -export function makeFakeWatchedPromiseManager(vrm, vom, cm, fakeStuff) { - return makeWatchedPromiseManager( - fakeStuff.syscall, +export function makeFakeWatchedPromiseManager( + vrm, + vom, + collectionManager, + fakeStuff, +) { + return makeWatchedPromiseManager({ + syscall: fakeStuff.syscall, vrm, vom, - cm, - fakeStuff.convertValToSlot, - fakeStuff.convertSlotToVal, - ); + collectionManager, + convertValToSlot: fakeStuff.convertValToSlot, + convertSlotToVal: fakeStuff.convertSlotToVal, + }); } /** * Configure virtual stuff with relaxed durability rules and fake liveslots From dd29ff35c5dc72efbbf7087849182aa7f04b2bb1 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Wed, 8 Mar 2023 21:11:52 -0500 Subject: [PATCH 14/26] fix(swingset-liveslots): Move promise rejection responsibility into the kernel Fixes #6694 --- packages/SwingSet/src/kernel/kernelQueue.js | 4 +- packages/swingset-liveslots/src/liveslots.js | 24 +------ .../swingset-liveslots/src/watchedPromises.js | 65 ++++--------------- .../tools/fakeVirtualSupport.js | 4 ++ 4 files changed, 21 insertions(+), 76 deletions(-) diff --git a/packages/SwingSet/src/kernel/kernelQueue.js b/packages/SwingSet/src/kernel/kernelQueue.js index 7f3fc29b808..3a8672b74d8 100644 --- a/packages/SwingSet/src/kernel/kernelQueue.js +++ b/packages/SwingSet/src/kernel/kernelQueue.js @@ -45,9 +45,7 @@ export function makeKernelQueueHandler(tools) { const p = kernelKeeper.getResolveablePromise(kpid, vatID); const { subscribers } = p; for (const subscriber of subscribers) { - if (subscriber !== vatID) { - notify(subscriber, kpid); - } + notify(subscriber, kpid); } kernelKeeper.resolveKernelPromise(kpid, rejected, data); const tag = rejected ? 'rejected' : 'fulfilled'; diff --git a/packages/swingset-liveslots/src/liveslots.js b/packages/swingset-liveslots/src/liveslots.js index e903a3f228a..82cf235a2dd 100644 --- a/packages/swingset-liveslots/src/liveslots.js +++ b/packages/swingset-liveslots/src/liveslots.js @@ -552,7 +552,7 @@ function build( const knownResolutions = new WeakMap(); /** - * Determines if a vref from an outbound argument + * Determines if a vref from a watched promise or outbound argument * identifies a promise that should be exported, and if so then * adds it to exportedVPIDs and sets up handlers. * @@ -674,6 +674,7 @@ function build( // eslint-disable-next-line no-use-before-define convertValToSlot, convertSlotToVal: unmeteredConvertSlotToVal, + maybeExportPromise, }); function convertValToSlot(val) { @@ -1190,7 +1191,6 @@ function build( // upgrade, or if we acquire decider authority for a // previously-imported promise if (pRec) { - // TODO: insist that we do not have decider authority for promiseID meterControl.assertNotMetered(); const val = m.unserialize(data); if (rejected) { @@ -1431,10 +1431,7 @@ function build( Fail`buildRootObject() for vat ${forVatID} returned ${rootObject} with no interface`; // Need to load watched promises *after* buildRootObject() so that handler kindIDs // have a chance to be reassociated with their handlers. - watchedPromiseManager.loadWatchedPromiseTable( - unmeteredUnserialize, - unmeteredRevivePromise, - ); + watchedPromiseManager.loadWatchedPromiseTable(unmeteredRevivePromise); const rootSlot = makeVatSlot('object', true, BigInt(0)); valToSlot.set(rootObject, rootSlot); @@ -1526,26 +1523,11 @@ function build( assert(!didStopVat); didStopVat = true; - // all vpids are either "imported" (kernel knows about it and - // kernel decides), "exported" (kernel knows about it but we - // decide), or neither (local, we decide, kernel is unaware). TODO - // this could be cheaper if we tracked all three states (make a - // Set for "neither") instead of doing enumeration and set math. - try { - // mark "imported" plus "neither" for rejection at next startup - const importedVPIDsSet = new Set(importedVPIDs.keys()); - watchedPromiseManager.prepareShutdownRejections( - importedVPIDsSet, - disconnectObjectCapData, - ); - // reject all "exported" vpids now - const deciderVPIDs = Array.from(exportedVPIDs.keys()).sort(); // eslint-disable-next-line @jessie.js/no-nested-await await releaseOldState({ m, disconnectObjectCapData, - deciderVPIDs, syscall, exportedRemotables, addToPossiblyDeadSet, diff --git a/packages/swingset-liveslots/src/watchedPromises.js b/packages/swingset-liveslots/src/watchedPromises.js index 2edc26ac540..2f3ffc1851a 100644 --- a/packages/swingset-liveslots/src/watchedPromises.js +++ b/packages/swingset-liveslots/src/watchedPromises.js @@ -14,6 +14,7 @@ import { parseVatSlot } from './parseVatSlots.js'; * @param {*} options.collectionManager * @param {import('@endo/marshal').ConvertValToSlot} options.convertValToSlot * @param {import('@endo/marshal').ConvertSlotToVal} options.convertSlotToVal + * @param {(vref: any) => boolean} options.maybeExportPromise */ export function makeWatchedPromiseManager({ syscall, @@ -22,6 +23,7 @@ export function makeWatchedPromiseManager({ collectionManager, convertValToSlot, convertSlotToVal, + maybeExportPromise, }) { const { makeScalarBigMapStore } = collectionManager; const { defineDurableKind } = vom; @@ -103,41 +105,14 @@ export function makeWatchedPromiseManager({ /** * Revives watched promises. * - * @param {import('@endo/marshal').Unserialize} unserialize * @param {(vref: any) => Promise} revivePromise * @returns {void} */ - function loadWatchedPromiseTable(unserialize, revivePromise) { - const deadPromisesRaw = syscall.vatstoreGet('deadPromises'); - if (!deadPromisesRaw) { - return; - } - const disconnectObjectCapData = JSON.parse( - syscall.vatstoreGet('deadPromiseDO'), - ); - const disconnectObject = unserialize(disconnectObjectCapData); - syscall.vatstoreDelete('deadPromises'); - syscall.vatstoreDelete('deadPromiseDO'); - const deadPromises = new Set(deadPromisesRaw.split(',')); - - for (const [vpid, watches] of watchedPromiseTable.entries()) { - if (deadPromises.has(vpid)) { - watchedPromiseTable.delete(vpid); - for (const watch of watches) { - const [watcher, ...args] = watch; - void Promise.resolve().then(() => { - if (watcher.onRejected) { - watcher.onRejected(disconnectObject, ...args); - } else { - throw disconnectObject; - } - }); - } - } else { - const p = revivePromise(vpid); - promiseRegistrations.init(vpid, p); - pseudoThen(p, vpid); - } + function loadWatchedPromiseTable(revivePromise) { + for (const vpid of watchedPromiseTable.keys()) { + const p = revivePromise(vpid); + promiseRegistrations.init(vpid, p); + pseudoThen(p, vpid); } } @@ -178,7 +153,6 @@ export function makeWatchedPromiseManager({ // TODO: add vpid->p virtual table mapping, to keep registration alive // TODO: remove mapping upon resolution - // TODO: track watched but non-exported promises, add during prepareShutdownRejections // maybe check importedVPIDs here and add to table if !has void Promise.resolve().then(() => { const watcherVref = convertValToSlot(watcher); @@ -205,35 +179,22 @@ export function makeWatchedPromiseManager({ watchedPromiseTable.set(vpid, harden([...watches, [watcher, ...args]])); } else { watchedPromiseTable.init(vpid, harden([[watcher, ...args]])); + + // Ensure that this vat's promises are rejected at termination. + if (maybeExportPromise(vpid)) { + syscall.subscribe(vpid); + } + promiseRegistrations.init(vpid, p); pseudoThen(p, vpid); } }); } - function prepareShutdownRejections( - importedVPIDsSet, - disconnectObjectCapData, - ) { - const deadPromises = []; - for (const vpid of watchedPromiseTable.keys()) { - if (!importedVPIDsSet.has(vpid)) { - deadPromises.push(vpid); // "exported" plus "neither" vpids - } - } - deadPromises.sort(); // just in case - syscall.vatstoreSet('deadPromises', deadPromises.join(',')); - syscall.vatstoreSet( - 'deadPromiseDO', - JSON.stringify(disconnectObjectCapData), - ); - } - return harden({ preparePromiseWatcherTables, loadWatchedPromiseTable, providePromiseWatcher, watchPromise, - prepareShutdownRejections, }); } diff --git a/packages/swingset-liveslots/tools/fakeVirtualSupport.js b/packages/swingset-liveslots/tools/fakeVirtualSupport.js index 6e90a9e073e..89c91d0b541 100644 --- a/packages/swingset-liveslots/tools/fakeVirtualSupport.js +++ b/packages/swingset-liveslots/tools/fakeVirtualSupport.js @@ -230,6 +230,8 @@ export function makeFakeLiveSlotsStuff(options = {}) { function assertAcceptableSyscallCapdataSize(_capdatas) {} + const maybeExportPromise = _vref => false; + return { syscall, allocateExportID, @@ -250,6 +252,7 @@ export function makeFakeLiveSlotsStuff(options = {}) { dumpStore, setVrm, assertAcceptableSyscallCapdataSize, + maybeExportPromise, }; } @@ -281,6 +284,7 @@ export function makeFakeWatchedPromiseManager( collectionManager, convertValToSlot: fakeStuff.convertValToSlot, convertSlotToVal: fakeStuff.convertSlotToVal, + maybeExportPromise: fakeStuff.maybeExportPromise, }); } /** From cf2c34df306c47500b4abcccc5d6f7dfff5f47b2 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Wed, 8 Mar 2023 21:21:20 -0500 Subject: [PATCH 15/26] docs(swingset-liveslots): Update VPID management documentation for code changes --- packages/swingset-liveslots/src/vpid-tracking.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/swingset-liveslots/src/vpid-tracking.md b/packages/swingset-liveslots/src/vpid-tracking.md index e8725c5360d..dec609b7af6 100644 --- a/packages/swingset-liveslots/src/vpid-tracking.md +++ b/packages/swingset-liveslots/src/vpid-tracking.md @@ -13,7 +13,7 @@ There are roughly four ways that liveslots might become aware of a promise: * deserialization: the arguments of an inbound `dispatch.deliver` or `dispatch.notify` are deserialized, and a new Promise instance is created * inbound result: the kernel-allocated `result` VPID of an inbound `dispatch.deliver` is associated with the Promise we get back from `HandledPromise.applyMethod` -A Promise may be associated with a VPID even though the kernel does not know about it (i.e. the VPID is not in the kernel's c-list for that vat). This can occur when a Promise is stored into virtual data without also being sent to (or received from) the kernel. It can also occur when a Promise is resolved but still referenced in vdata (the kernel's knowledge is temporary; it retires VPIDs from c-lists upon `syscall.resolve` or `dispatch.notify` as relevant). So a VPID might start out stored only in vdata, then get sent to the kernel, then get resolved, leaving it solely in vdata once more. +A Promise may be associated with a VPID even though the kernel does not know about it (i.e. the VPID is not in the kernel's c-list for that vat). This can occur when a Promise is stored into virtual data without also being sent to (or received from) the kernel, although note that every Promise associated with a durable promise watcher _is_ sent to the kernel so it can be rejected during vat upgrade. A Promise can also be resolved but still referenced in vdata and forgotten by the kernel (the kernel's knowledge is temporary; it retires VPIDs from c-lists upon `syscall.resolve` or `dispatch.notify` as relevant). So a VPID might start out stored only in vdata, then get sent to the kernel, then get resolved, leaving it solely in vdata once more. Each unresolved VPID has a decider: either the kernel or a vat. It can remain unresolved for arbitrarily long, but becomes resolved by the first of the following events: From 01729ab55648fc0a8b4bd42cb444ec42aa054121 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Wed, 8 Mar 2023 21:21:20 -0500 Subject: [PATCH 16/26] docs(swingset-liveslots): Clarify VPID managment documentation --- .../swingset-liveslots/src/vpid-tracking.md | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/packages/swingset-liveslots/src/vpid-tracking.md b/packages/swingset-liveslots/src/vpid-tracking.md index dec609b7af6..80ada85849f 100644 --- a/packages/swingset-liveslots/src/vpid-tracking.md +++ b/packages/swingset-liveslots/src/vpid-tracking.md @@ -2,9 +2,9 @@ Kernels and vats communicate about promises by referring to their VPIDs: vat(-centric) promise IDs. These are strings like `p+12` and `p-23`. Like VOIDs (object IDs), the plus/minus sign indicates which side of the boundary allocated the number (`p+12` and `o+12` are allocated by the vat, `p-13` and `o-13` are allocated by the kernel). But where the object ID sign also indicates which side "owns" the object (i.e. where the behavior lives), the promise ID sign is generally irrelevant. -Instead, we care about which side holds the resolution authority for a promise (referred to as being its **decider**). This is not indicated by the VPID sign, and in fact is not necessarily static. Liveslots does not currently have any mechanism to allow one promise to be forwarded to another, but if it acquires this some day, then the decider of a promise could shift from kernel to vat to kernel again before it finally gets resolved. And there *are* sequences that allow a vat to receive a reference to a promise in method arguments before receiving a message for which that same VPID identifies the result promise (e.g., `pk = makePromiseKit(); p2 = E(pk.promise).push('queued'); await E(observer).push(p2); pk.resolve(observer)` with an observer whose `push` returns a prompt response). In such cases, the decider is initially the kernel but later becomes the receiving vat. +Instead, we care about which side holds the resolution authority for a promise (referred to as being its **decider**). This is not indicated by the VPID sign, and in fact is not necessarily static. Liveslots does not currently have any mechanism to allow one promise to be forwarded to another, but if it acquires this some day, then the decider of a promise could shift from kernel to vat to kernel again before it finally gets resolved. And there *are* sequences that allow a vat to receive a reference to a promise in method arguments before receiving a message for which that same VPID identifies the result promise (e.g., `{ promise: p1, resolve: resolveP1 } = makePromiseKit(); p2 = E(p1).push('queued'); await E(observer).push(p2); resolveP1(observer);` with an observer whose `push` returns a prompt response). In such cases, the decider is initially the kernel but later becomes the receiving vat. -Each Promise starts out in the "unresolved" state, then later transitions irrevocably to the "resolved" state. Liveslots frequently (but not always) pays attention to this transition by calling `then` to attach fulfillment/rejection callbacks. To handle resolution cycles, liveslots remembers the resolution of old promises in a `WeakMap` for as long as the Promise exists. Consequently, for liveslots' purposes, every Promise is either resolved (a callback has fired and liveslots remembers the settlement), or unresolved (liveslots has not yet seen a resolution). +Each Promise starts out in the "unresolved" state, then later transitions irrevocably to the "resolved" state. Liveslots frequently (but not always) pays attention to this transition by calling `then` to attach fulfillment/rejection settlement callbacks. To handle resolution cycles, liveslots remembers the resolution of old promises in a `WeakMap` for as long as the Promise exists. Consequently, for liveslots' purposes, every Promise is either resolved (a callback has fired and liveslots remembers the settlement), or unresolved (liveslots has not yet seen a resolution that settles it). There are roughly four ways that liveslots might become aware of a promise: @@ -13,13 +13,14 @@ There are roughly four ways that liveslots might become aware of a promise: * deserialization: the arguments of an inbound `dispatch.deliver` or `dispatch.notify` are deserialized, and a new Promise instance is created * inbound result: the kernel-allocated `result` VPID of an inbound `dispatch.deliver` is associated with the Promise we get back from `HandledPromise.applyMethod` -A Promise may be associated with a VPID even though the kernel does not know about it (i.e. the VPID is not in the kernel's c-list for that vat). This can occur when a Promise is stored into virtual data without also being sent to (or received from) the kernel, although note that every Promise associated with a durable promise watcher _is_ sent to the kernel so it can be rejected during vat upgrade. A Promise can also be resolved but still referenced in vdata and forgotten by the kernel (the kernel's knowledge is temporary; it retires VPIDs from c-lists upon `syscall.resolve` or `dispatch.notify` as relevant). So a VPID might start out stored only in vdata, then get sent to the kernel, then get resolved, leaving it solely in vdata once more. +A Promise may be associated with a VPID even though the kernel does not know about it (i.e. the VPID is not in the kernel's c-list for that vat). This can occur when a Promise is stored into virtual data without also being sent to (or received from) the kernel, although note that every Promise associated with a durable promise watcher _is_ sent to the kernel so it can be rejected during vat upgrade. A Promise can also be resolved but still referenced in vdata and forgotten by the kernel (the kernel's knowledge is temporary; it retires VPIDs from c-lists upon `syscall.resolve` or `dispatch.notify` as appropriate). So a VPID might start out stored only in vdata, then get sent to the kernel, then get resolved, leaving it solely in vdata once more. Each unresolved VPID has a decider: either the kernel or a vat. It can remain unresolved for arbitrarily long, but becomes resolved by the first of the following events: -* if userspace resolves the corresponding Promise and liveslots learns of the resolution, then liveslots will perform a `syscall.resolve()` -* if the vat is upgraded, liveslots will perform a `syscall.resolve()` of all remaining VPIDs during the delivery of `dispatch.stopVat()` (after which all Promises evaporate along with the rest of the JS heap) +* if liveslots learns about local resolution of the corresponding Promise by userspace, then liveslots will perform a `syscall.resolve()` (prompting 'notify' deliveries to other subscribed vats) +* if liveslots learns about resolution by inbound notify, then liveslots will unregister it as necessary and inform userspace of the resolution * if the vat is terminated, the kernel internally rejects all remaining vat-decided KPIDs without involving the vat +* if the vat is upgraded, each of those terminate-associated rejections is followed by a 'notify' delivery to the new incarnation Liveslots tracks promises in the following data structures: @@ -54,7 +55,7 @@ Remember that the `slotToVal` registration uses a WeakRef, so being registered t * at this point, there is not yet a strong reference to the Promise * When a VPID appears in the serialized arguments of `syscall.send` or `syscall.resolve`: * if the VPID already exists in `exportedVPIDs` or `importedVPIDs`: do nothing - * else: use `followForKernel` to add the VPID to `exportedVPIDs` and attach settlement callbacks + * else: use `followForKernel` to add the VPID to `exportedVPIDs` and attach `.then(onFulfill, onReject)` callbacks that will map fulfillment/rejection to `syscall.resolve()` * When a `followForKernel` settlement callback is executed: * do `syscall.resolve()` * remove from `exportedVPIDs` @@ -77,10 +78,11 @@ Remember that the `slotToVal` registration uses a WeakRef, so being registered t * add the Promise and its `resolve`/`reject` pair to `importedVPIDs` * register the Promise in `valToSlot`/`slotToVal` * use `syscall.subscribe` to request a `dispatch.notify` delivery when the kernel resolves this promise -* When a VPID appears as the `result` of an inbound `dispatch.deliver`: - * if the VPID is present in `importedVPIDs`: retrieve the `[resolve, reject]` pRec and use `resolve(res)` to forward the invocation result promise to the previously-imported promise, then remove the VPID from `importedVPIDs` - * else: register `res` the invocation result promise under the VPID - * in either case, use `followForKernel` to add the VPID to `exportedVPIDs` and attach settlement callbacks +* When a VPID appears as the `result` of an inbound `dispatch.deliver`, the vat is responsible for deciding it: + * construct a promise `res` to capture the userspace-provided result + * if the VPID is present in `importedVPIDs`: retrieve the `[resolve, reject]` pRec and use `resolve(res)` to forward eventual settlement of `res` to settlement of the previously-imported promise, then remove the VPID from `importedVPIDs` + * else: register marshaller association between the VPID and `res` + * in either case, use `followForKernel` to add the VPID to `exportedVPIDs` and attach `.then(onFulfill, onReject)` callbacks that will map fulfillment/rejection to `syscall.resolve() If the serialization is for storage in virtual data, the act of storing the VPID will add the Promise to `remotableRefCounts`, which maintains a strong reference for as long as the VPID is held. When it is removed from virtual data (or the object/collection is deleted), the refcount will be decremented. When the refcount drops to zero, we perform the `exportedVPIDs`/`importedVPIDs` check and then maybe unregister the promise. From be8adc3d92b8fd8177ac150fb69dc4d6206fbfd6 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Mon, 13 Mar 2023 00:23:20 -0400 Subject: [PATCH 17/26] test: Move full-environment test from liveslots to SwingSet --- packages/SwingSet/test/test-promises.js | 71 +++++++++++++++++- .../test/vat-durable-promise-watcher.js | 0 packages/swingset-liveslots/package.json | 4 +- .../test/test-vat-upgrade.js | 73 ------------------- 4 files changed, 71 insertions(+), 77 deletions(-) rename packages/{swingset-liveslots => SwingSet}/test/vat-durable-promise-watcher.js (100%) delete mode 100644 packages/swingset-liveslots/test/test-vat-upgrade.js diff --git a/packages/SwingSet/test/test-promises.js b/packages/SwingSet/test/test-promises.js index 272aeea929b..8ed2724f390 100644 --- a/packages/SwingSet/test/test-promises.js +++ b/packages/SwingSet/test/test-promises.js @@ -6,7 +6,9 @@ import { loadBasedir, buildKernelBundles, } from '../src/index.js'; -import { kser, kslot } from '../src/lib/kmarshal.js'; +import { kser, kslot, kunser } from '../src/lib/kmarshal.js'; + +const bfile = name => new URL(name, import.meta.url).pathname; test.before(async t => { const kernelBundles = await buildKernelBundles(); @@ -212,3 +214,70 @@ test('refcount while queued', async t => { await c.run(); t.deepEqual(c.kpResolution(kpid4), kser([true, 3])); }); + +test('local promises are rejected by vat upgrade', async t => { + // TODO: Generalize packages/SwingSet/test/upgrade/test-upgrade.js + /** @type {SwingSetConfig} */ + const config = { + includeDevDependencies: true, // for vat-data + defaultManagerType: 'xs-worker', + bootstrap: 'bootstrap', + defaultReapInterval: 'never', + vats: { + bootstrap: { + sourceSpec: bfile('./bootstrap-relay.js'), + }, + }, + bundles: { + watcher: { sourceSpec: bfile('./vat-durable-promise-watcher.js') }, + }, + }; + const c = await buildVatController(config); + t.teardown(c.shutdown); + c.pinVatRoot('bootstrap'); + await c.run(); + + const run = async (method, args = []) => { + assert(Array.isArray(args)); + const kpid = c.queueToVatRoot('bootstrap', method, args); + await c.run(); + const status = c.kpStatus(kpid); + if (status === 'fulfilled') { + const result = c.kpResolution(kpid); + return kunser(result); + } + assert(status === 'rejected'); + const err = c.kpResolution(kpid); + throw kunser(err); + }; + const messageVat = (name, methodName, args) => + run('messageVat', [{ name, methodName, args }]); + // eslint-disable-next-line no-underscore-dangle + const _messageObject = (presence, methodName, args) => + run('messageVatObject', [{ presence, methodName, args }]); + + const S = Symbol.for('passable'); + await run('createVat', [{ name: 'watcher', bundleCapName: 'watcher' }]); + await messageVat('watcher', 'watchLocalPromise', ['orphaned']); + await messageVat('watcher', 'watchLocalPromise', ['fulfilled', S]); + await messageVat('watcher', 'watchLocalPromise', ['rejected', undefined, S]); + const v1Settlements = await messageVat('watcher', 'getSettlements'); + t.deepEqual(v1Settlements, { + fulfilled: { status: 'fulfilled', value: S }, + rejected: { status: 'rejected', reason: S }, + }); + await run('upgradeVat', [{ name: 'watcher', bundleCapName: 'watcher' }]); + const v2Settlements = await messageVat('watcher', 'getSettlements'); + t.deepEqual(v2Settlements, { + fulfilled: { status: 'fulfilled', value: S }, + rejected: { status: 'rejected', reason: S }, + orphaned: { + status: 'rejected', + reason: { + name: 'vatUpgraded', + upgradeMessage: 'vat upgraded', + incarnationNumber: 1, + }, + }, + }); +}); diff --git a/packages/swingset-liveslots/test/vat-durable-promise-watcher.js b/packages/SwingSet/test/vat-durable-promise-watcher.js similarity index 100% rename from packages/swingset-liveslots/test/vat-durable-promise-watcher.js rename to packages/SwingSet/test/vat-durable-promise-watcher.js diff --git a/packages/swingset-liveslots/package.json b/packages/swingset-liveslots/package.json index 0fa13f591e0..9efed053c92 100644 --- a/packages/swingset-liveslots/package.json +++ b/packages/swingset-liveslots/package.json @@ -16,9 +16,7 @@ "lint:types": "tsc -p jsconfig.json", "lint:eslint": "eslint ." }, - "devDependencies": { - "@agoric/swingset-vat": "^0.30.2" - }, + "devDependencies": {}, "dependencies": { "@agoric/assert": "^0.5.1", "@agoric/internal": "^0.2.1", diff --git a/packages/swingset-liveslots/test/test-vat-upgrade.js b/packages/swingset-liveslots/test/test-vat-upgrade.js deleted file mode 100644 index d03a2ca3411..00000000000 --- a/packages/swingset-liveslots/test/test-vat-upgrade.js +++ /dev/null @@ -1,73 +0,0 @@ -import '@agoric/swingset-vat/tools/prepare-test-env.js'; -import test from 'ava'; -import { buildVatController } from '@agoric/swingset-vat'; -import { kunser } from '@agoric/swingset-vat/src/lib/kmarshal.js'; - -const bfile = name => new URL(name, import.meta.url).pathname; - -test('local promises are rejected by vat upgrade', async t => { - // TODO: Generalize packages/SwingSet/test/upgrade/test-upgrade.js - /** @type {SwingSetConfig} */ - const config = { - includeDevDependencies: true, // for vat-data - defaultManagerType: 'xs-worker', - bootstrap: 'bootstrap', - defaultReapInterval: 'never', - vats: { - bootstrap: { - sourceSpec: bfile('../../SwingSet/test/bootstrap-relay.js'), - }, - }, - bundles: { - watcher: { sourceSpec: bfile('./vat-durable-promise-watcher.js') }, - }, - }; - const c = await buildVatController(config); - t.teardown(c.shutdown); - c.pinVatRoot('bootstrap'); - await c.run(); - - const run = async (method, args = []) => { - assert(Array.isArray(args)); - const kpid = c.queueToVatRoot('bootstrap', method, args); - await c.run(); - const status = c.kpStatus(kpid); - if (status === 'fulfilled') { - const result = c.kpResolution(kpid); - return kunser(result); - } - assert(status === 'rejected'); - const err = c.kpResolution(kpid); - throw kunser(err); - }; - const messageVat = (name, methodName, args) => - run('messageVat', [{ name, methodName, args }]); - // eslint-disable-next-line no-underscore-dangle - const _messageObject = (presence, methodName, args) => - run('messageVatObject', [{ presence, methodName, args }]); - - const S = Symbol.for('passable'); - await run('createVat', [{ name: 'watcher', bundleCapName: 'watcher' }]); - await messageVat('watcher', 'watchLocalPromise', ['orphaned']); - await messageVat('watcher', 'watchLocalPromise', ['fulfilled', S]); - await messageVat('watcher', 'watchLocalPromise', ['rejected', undefined, S]); - const v1Settlements = await messageVat('watcher', 'getSettlements'); - t.deepEqual(v1Settlements, { - fulfilled: { status: 'fulfilled', value: S }, - rejected: { status: 'rejected', reason: S }, - }); - await run('upgradeVat', [{ name: 'watcher', bundleCapName: 'watcher' }]); - const v2Settlements = await messageVat('watcher', 'getSettlements'); - t.deepEqual(v2Settlements, { - fulfilled: { status: 'fulfilled', value: S }, - rejected: { status: 'rejected', reason: S }, - orphaned: { - status: 'rejected', - reason: { - name: 'vatUpgraded', - upgradeMessage: 'vat upgraded', - incarnationNumber: 1, - }, - }, - }); -}); From abbf2a87f60cee3c239b0da5163f9a301179dc9b Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Mon, 13 Mar 2023 11:31:17 -0400 Subject: [PATCH 18/26] refactor(vat-data): Merge kind-utils.js into exo-utils.js --- packages/vat-data/src/exo-utils.js | 61 ++++++++++++++++++- packages/vat-data/src/index.js | 8 ++- packages/vat-data/src/kind-utils.js | 68 ---------------------- packages/vat-data/src/vat-data-bindings.js | 2 +- 4 files changed, 66 insertions(+), 73 deletions(-) delete mode 100644 packages/vat-data/src/kind-utils.js diff --git a/packages/vat-data/src/exo-utils.js b/packages/vat-data/src/exo-utils.js index e84cb504e48..7a792fad623 100644 --- a/packages/vat-data/src/exo-utils.js +++ b/packages/vat-data/src/exo-utils.js @@ -1,11 +1,11 @@ import { initEmpty } from '@agoric/store'; -import { provideKindHandle } from './kind-utils.js'; import { defineKind, defineKindMulti, defineDurableKind, defineDurableKindMulti, + makeKindHandle, provide, } from './vat-data-bindings.js'; @@ -17,6 +17,65 @@ import { /** @template T @typedef {import('./types.js').KindFacets} KindFacets */ /** @typedef {import('./types.js').DurableKindHandle} DurableKindHandle */ +/** + * Make a version of the argument function that takes a kind context but + * ignores it. + * + * @type {(fn: T) => import('./types.js').PlusContext} + */ +export const ignoreContext = + fn => + (_context, ...args) => + fn(...args); +harden(ignoreContext); + +/** + * @param {Baggage} baggage + * @param {string} kindName + * @returns {DurableKindHandle} + */ +export const provideKindHandle = (baggage, kindName) => + provide(baggage, `${kindName}_kindHandle`, () => makeKindHandle(kindName)); +harden(provideKindHandle); + +/** + * @deprecated Use prepareExoClass instead + * @type {import('./types.js').PrepareKind} + */ +export const prepareKind = ( + baggage, + kindName, + init, + behavior, + options = undefined, +) => + defineDurableKind( + provideKindHandle(baggage, kindName), + init, + behavior, + options, + ); +harden(prepareKind); + +/** + * @deprecated Use prepareExoClassKit instead + * @type {import('./types.js').PrepareKindMulti} + */ +export const prepareKindMulti = ( + baggage, + kindName, + init, + behavior, + options = undefined, +) => + defineDurableKindMulti( + provideKindHandle(baggage, kindName), + init, + behavior, + options, + ); +harden(prepareKindMulti); + // TODO interfaceGuard type https://github.com/Agoric/agoric-sdk/issues/6206 /** * @template {(...args: any) => any} I init state function diff --git a/packages/vat-data/src/index.js b/packages/vat-data/src/index.js index 4bff2886698..cb0e4076ed7 100644 --- a/packages/vat-data/src/index.js +++ b/packages/vat-data/src/index.js @@ -35,7 +35,7 @@ export { prepareExoClass, prepareExoClassKit, prepareExo, - // deorecated + // deprecated prepareSingleton, } from './exo-utils.js'; @@ -45,10 +45,12 @@ export { // //////////////////////////// deprecated ///////////////////////////////////// +/** + * @deprecated Use Exos/ExoClasses instead of Kinds + */ export { - // deprecated ignoreContext, provideKindHandle, prepareKind, prepareKindMulti, -} from './kind-utils.js'; +} from './exo-utils.js'; diff --git a/packages/vat-data/src/kind-utils.js b/packages/vat-data/src/kind-utils.js deleted file mode 100644 index 1084f4dfdf0..00000000000 --- a/packages/vat-data/src/kind-utils.js +++ /dev/null @@ -1,68 +0,0 @@ -import { - provide, - defineDurableKind, - defineDurableKindMulti, - makeKindHandle, -} from './vat-data-bindings.js'; - -/** @typedef {import('./types.js').Baggage} Baggage */ -/** @typedef {import('./types.js').DurableKindHandle} DurableKindHandle */ - -/** - * Make a version of the argument function that takes a kind context but - * ignores it. - * - * @type {(fn: T) => import('./types.js').PlusContext} - */ -export const ignoreContext = - fn => - (_context, ...args) => - fn(...args); -harden(ignoreContext); - -/** - * @param {Baggage} baggage - * @param {string} kindName - * @returns {DurableKindHandle} - */ -export const provideKindHandle = (baggage, kindName) => - provide(baggage, `${kindName}_kindHandle`, () => makeKindHandle(kindName)); -harden(provideKindHandle); - -/** - * @deprecated Use prepareExoClass instead - * @type {import('./types.js').PrepareKind} - */ -export const prepareKind = ( - baggage, - kindName, - init, - behavior, - options = undefined, -) => - defineDurableKind( - provideKindHandle(baggage, kindName), - init, - behavior, - options, - ); -harden(prepareKind); - -/** - * @deprecated Use prepareExoClassKit instead - * @type {import('./types.js').PrepareKindMulti} - */ -export const prepareKindMulti = ( - baggage, - kindName, - init, - behavior, - options = undefined, -) => - defineDurableKindMulti( - provideKindHandle(baggage, kindName), - init, - behavior, - options, - ); -harden(prepareKindMulti); diff --git a/packages/vat-data/src/vat-data-bindings.js b/packages/vat-data/src/vat-data-bindings.js index a20c005dda0..7cacca40144 100644 --- a/packages/vat-data/src/vat-data-bindings.js +++ b/packages/vat-data/src/vat-data-bindings.js @@ -30,7 +30,7 @@ if ('VatData' in globalThis) { } /** - * @deprecated Use Exos/ExoClasses instead of kinds + * @deprecated Use Exos/ExoClasses instead of Kinds */ export const { defineKind, From 835b5e5eadf6db060b2edc202cc237f2c5d70b64 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Mon, 13 Mar 2023 20:51:30 -0400 Subject: [PATCH 19/26] refactor(vat-data): Generalize store/kind/exo maker factories to VatData scope --- packages/vat-data/src/exo-utils.js | 500 +++++++++++---------- packages/vat-data/src/vat-data-bindings.js | 88 ++-- 2 files changed, 318 insertions(+), 270 deletions(-) diff --git a/packages/vat-data/src/exo-utils.js b/packages/vat-data/src/exo-utils.js index 7a792fad623..cec5ca1473a 100644 --- a/packages/vat-data/src/exo-utils.js +++ b/packages/vat-data/src/exo-utils.js @@ -1,13 +1,6 @@ import { initEmpty } from '@agoric/store'; -import { - defineKind, - defineKindMulti, - defineDurableKind, - defineDurableKindMulti, - makeKindHandle, - provide, -} from './vat-data-bindings.js'; +import { provide, VatData as globalVatData } from './vat-data-bindings.js'; /** @template L,R @typedef {import('@endo/eventual-send').RemotableBrand} RemotableBrand */ /** @template T @typedef {import('@endo/far').ERef} ERef */ @@ -29,264 +22,291 @@ export const ignoreContext = fn(...args); harden(ignoreContext); -/** - * @param {Baggage} baggage - * @param {string} kindName - * @returns {DurableKindHandle} - */ -export const provideKindHandle = (baggage, kindName) => - provide(baggage, `${kindName}_kindHandle`, () => makeKindHandle(kindName)); -harden(provideKindHandle); +// TODO: Find a good home for this function used by @agoric/vat-data and testing code +export const makeExoUtils = VatData => { + const { + defineKind, + defineKindMulti, + defineDurableKind, + defineDurableKindMulti, + makeKindHandle, + } = VatData; -/** - * @deprecated Use prepareExoClass instead - * @type {import('./types.js').PrepareKind} - */ -export const prepareKind = ( - baggage, - kindName, - init, - behavior, - options = undefined, -) => - defineDurableKind( - provideKindHandle(baggage, kindName), + /** + * @param {Baggage} baggage + * @param {string} kindName + * @returns {DurableKindHandle} + */ + const provideKindHandle = (baggage, kindName) => + provide(baggage, `${kindName}_kindHandle`, () => makeKindHandle(kindName)); + harden(provideKindHandle); + + /** + * @deprecated Use prepareExoClass instead + * @type {import('./types.js').PrepareKind} + */ + const prepareKind = ( + baggage, + kindName, init, behavior, - options, - ); -harden(prepareKind); + options = undefined, + ) => + defineDurableKind( + provideKindHandle(baggage, kindName), + init, + behavior, + options, + ); + harden(prepareKind); -/** - * @deprecated Use prepareExoClassKit instead - * @type {import('./types.js').PrepareKindMulti} - */ -export const prepareKindMulti = ( - baggage, - kindName, - init, - behavior, - options = undefined, -) => - defineDurableKindMulti( - provideKindHandle(baggage, kindName), + /** + * @deprecated Use prepareExoClassKit instead + * @type {import('./types.js').PrepareKindMulti} + */ + const prepareKindMulti = ( + baggage, + kindName, init, behavior, - options, - ); -harden(prepareKindMulti); + options = undefined, + ) => + defineDurableKindMulti( + provideKindHandle(baggage, kindName), + init, + behavior, + options, + ); + harden(prepareKindMulti); -// TODO interfaceGuard type https://github.com/Agoric/agoric-sdk/issues/6206 -/** - * @template {(...args: any) => any} I init state function - * @template T behavior - * @param {string} tag - * @param {any} interfaceGuard - * @param {I} init - * @param {T & ThisType<{ self: T, state: ReturnType }>} methods - * @param {DefineKindOptions<{ self: T, state: ReturnType }>} [options] - * @returns {(...args: Parameters) => (T & RemotableBrand<{}, T>)} - */ -export const defineVirtualExoClass = ( - tag, - interfaceGuard, - init, - methods, - options, -) => - // @ts-expect-error The use of `thisfulMethods` to change - // the appropriate static type is the whole point of this method. - defineKind(tag, init, methods, { - ...options, - thisfulMethods: true, - interfaceGuard, - }); -harden(defineVirtualExoClass); + // TODO interfaceGuard type https://github.com/Agoric/agoric-sdk/issues/6206 + /** + * @template {(...args: any) => any} I init state function + * @template T behavior + * @param {string} tag + * @param {any} interfaceGuard + * @param {I} init + * @param {T & ThisType<{ self: T, state: ReturnType }>} methods + * @param {DefineKindOptions<{ self: T, state: ReturnType }>} [options] + * @returns {(...args: Parameters) => (T & RemotableBrand<{}, T>)} + */ + const defineVirtualExoClass = (tag, interfaceGuard, init, methods, options) => + defineKind(tag, init, methods, { + ...options, + thisfulMethods: true, + interfaceGuard, + }); + harden(defineVirtualExoClass); -// TODO interfaceGuard type https://github.com/Agoric/agoric-sdk/issues/6206 -/** - * @template {(...args: any) => any} I init state function - * @template {Record>} T facets - * @param {string} tag - * @param {any} interfaceGuardKit - * @param {I} init - * @param {T & ThisType<{ facets: T, state: ReturnType }> } facets - * @param {DefineKindOptions<{ facets: T, state: ReturnType }>} [options] - * @returns {(...args: Parameters) => (T & RemotableBrand<{}, T>)} - */ -export const defineVirtualExoClassKit = ( - tag, - interfaceGuardKit, - init, - facets, - options, -) => - // @ts-expect-error The use of `thisfulMethods` to change - // the appropriate static type is the whole point of this method. - defineKindMulti(tag, init, facets, { - ...options, - thisfulMethods: true, - interfaceGuard: interfaceGuardKit, - }); -harden(defineVirtualExoClassKit); + // TODO interfaceGuard type https://github.com/Agoric/agoric-sdk/issues/6206 + /** + * @template {(...args: any) => any} I init state function + * @template {Record>} T facets + * @param {string} tag + * @param {any} interfaceGuardKit + * @param {I} init + * @param {T & ThisType<{ facets: T, state: ReturnType }> } facets + * @param {DefineKindOptions<{ facets: T, state: ReturnType }>} [options] + * @returns {(...args: Parameters) => (T & RemotableBrand<{}, T>)} + */ + const defineVirtualExoClassKit = ( + tag, + interfaceGuardKit, + init, + facets, + options, + ) => + defineKindMulti(tag, init, facets, { + ...options, + thisfulMethods: true, + interfaceGuard: interfaceGuardKit, + }); + harden(defineVirtualExoClassKit); -// TODO interfaceGuard type https://github.com/Agoric/agoric-sdk/issues/6206 -/** - * @template {(...args: any) => any} I init state function - * @template {Record} T methods - * @param {DurableKindHandle} kindHandle - * @param {any} interfaceGuard - * @param {I} init - * @param {T & ThisType<{ self: T, state: ReturnType }>} methods - * @param {DefineKindOptions<{ self: T, state: ReturnType }>} [options] - * @returns {(...args: Parameters) => (T & RemotableBrand<{}, T>)} - */ -export const defineDurableExoClass = ( - kindHandle, - interfaceGuard, - init, - methods, - options, -) => - // @ts-expect-error The use of `thisfulMethods` to change - // the appropriate static type is the whole point of this method. - defineDurableKind(kindHandle, init, methods, { - ...options, - thisfulMethods: true, + // TODO interfaceGuard type https://github.com/Agoric/agoric-sdk/issues/6206 + /** + * @template {(...args: any) => any} I init state function + * @template {Record} T methods + * @param {DurableKindHandle} kindHandle + * @param {any} interfaceGuard + * @param {I} init + * @param {T & ThisType<{ self: T, state: ReturnType }>} methods + * @param {DefineKindOptions<{ self: T, state: ReturnType }>} [options] + * @returns {(...args: Parameters) => (T & RemotableBrand<{}, T>)} + */ + const defineDurableExoClass = ( + kindHandle, interfaceGuard, - }); -harden(defineDurableExoClass); + init, + methods, + options, + ) => + defineDurableKind(kindHandle, init, methods, { + ...options, + thisfulMethods: true, + interfaceGuard, + }); + harden(defineDurableExoClass); -// TODO interfaceGuard type https://github.com/Agoric/agoric-sdk/issues/6206 -/** - * @template {(...args: any) => any} I init state function - * @template {Record>} T facets - * @param {DurableKindHandle} kindHandle - * @param {any} interfaceGuardKit - * @param {I} init - * @param {T & ThisType<{ facets: T, state: ReturnType}> } facets - * @param {DefineKindOptions<{ facets: T, state: ReturnType}>} [options] - * @returns {(...args: Parameters) => (T & RemotableBrand<{}, T>)} - */ -export const defineDurableExoClassKit = ( - kindHandle, - interfaceGuardKit, - init, - facets, - options, -) => - // @ts-expect-error The use of `thisfulMethods` to change - // the appropriate static type is the whole point of this method. - defineDurableKindMulti(kindHandle, init, facets, { - ...options, - thisfulMethods: true, - interfaceGuard: interfaceGuardKit, - }); -harden(defineDurableExoClassKit); + // TODO interfaceGuard type https://github.com/Agoric/agoric-sdk/issues/6206 + /** + * @template {(...args: any) => any} I init state function + * @template {Record>} T facets + * @param {DurableKindHandle} kindHandle + * @param {any} interfaceGuardKit + * @param {I} init + * @param {T & ThisType<{ facets: T, state: ReturnType}> } facets + * @param {DefineKindOptions<{ facets: T, state: ReturnType}>} [options] + * @returns {(...args: Parameters) => (T & RemotableBrand<{}, T>)} + */ + const defineDurableExoClassKit = ( + kindHandle, + interfaceGuardKit, + init, + facets, + options, + ) => + defineDurableKindMulti(kindHandle, init, facets, { + ...options, + thisfulMethods: true, + interfaceGuard: interfaceGuardKit, + }); + harden(defineDurableExoClassKit); -// TODO interfaceGuard type https://github.com/Agoric/agoric-sdk/issues/6206 -/** - * @template {(...args: any) => any} I init state function - * @template {Record} T methods - * @param {Baggage} baggage - * @param {string} kindName - * @param {any} interfaceGuard - * @param {I} init - * @param {T & ThisType<{ self: T, state: ReturnType }>} methods - * @param {DefineKindOptions<{ self: T, state: ReturnType }>} [options] - * @returns {(...args: Parameters) => (T & RemotableBrand<{}, T>)} - */ -export const prepareExoClass = ( - baggage, - kindName, - interfaceGuard, - init, - methods, - options = undefined, -) => - defineDurableExoClass( - provideKindHandle(baggage, kindName), + // TODO interfaceGuard type https://github.com/Agoric/agoric-sdk/issues/6206 + /** + * @template {(...args: any) => any} I init state function + * @template {Record} T methods + * @param {Baggage} baggage + * @param {string} kindName + * @param {any} interfaceGuard + * @param {I} init + * @param {T & ThisType<{ self: T, state: ReturnType }>} methods + * @param {DefineKindOptions<{ self: T, state: ReturnType }>} [options] + * @returns {(...args: Parameters) => (T & RemotableBrand<{}, T>)} + */ + const prepareExoClass = ( + baggage, + kindName, interfaceGuard, init, methods, - options, - ); -harden(prepareExoClass); + options = undefined, + ) => + defineDurableExoClass( + provideKindHandle(baggage, kindName), + interfaceGuard, + init, + methods, + options, + ); + harden(prepareExoClass); -// TODO interfaceGuard type https://github.com/Agoric/agoric-sdk/issues/6206 -/** - * @template {(...args: any) => any} I init state function - * @template {Record>} T facets - * @param {Baggage} baggage - * @param {string} kindName - * @param {any} interfaceGuardKit - * @param {I} init - * @param {T & ThisType<{ facets: T, state: ReturnType }> } facets - * @param {DefineKindOptions<{ facets: T, state: ReturnType }>} [options] - * @returns {(...args: Parameters) => (T & RemotableBrand<{}, T>)} - */ -export const prepareExoClassKit = ( - baggage, - kindName, - interfaceGuardKit, - init, - facets, - options = undefined, -) => - defineDurableExoClassKit( - provideKindHandle(baggage, kindName), + // TODO interfaceGuard type https://github.com/Agoric/agoric-sdk/issues/6206 + /** + * @template {(...args: any) => any} I init state function + * @template {Record>} T facets + * @param {Baggage} baggage + * @param {string} kindName + * @param {any} interfaceGuardKit + * @param {I} init + * @param {T & ThisType<{ facets: T, state: ReturnType }> } facets + * @param {DefineKindOptions<{ facets: T, state: ReturnType }>} [options] + * @returns {(...args: Parameters) => (T & RemotableBrand<{}, T>)} + */ + const prepareExoClassKit = ( + baggage, + kindName, interfaceGuardKit, init, facets, - options, - ); -harden(prepareExoClassKit); + options = undefined, + ) => + defineDurableExoClassKit( + provideKindHandle(baggage, kindName), + interfaceGuardKit, + init, + facets, + options, + ); + harden(prepareExoClassKit); -// TODO interfaceGuard type https://github.com/Agoric/agoric-sdk/issues/6206 -/** - * @template {Record} M methods - * @param {Baggage} baggage - * @param {string} kindName - * @param {any} interfaceGuard - * @param {M} methods - * @param {DefineKindOptions<{ self: M }>} [options] - * @returns {M & RemotableBrand<{}, M>} - */ -export const prepareExo = ( - baggage, - kindName, - interfaceGuard, - methods, - options = undefined, -) => { - const makeSingleton = prepareExoClass( + // TODO interfaceGuard type https://github.com/Agoric/agoric-sdk/issues/6206 + /** + * @template {Record} M methods + * @param {Baggage} baggage + * @param {string} kindName + * @param {any} interfaceGuard + * @param {M} methods + * @param {DefineKindOptions<{ self: M }>} [options] + * @returns {M & RemotableBrand<{}, M>} + */ + const prepareExo = ( baggage, kindName, interfaceGuard, - initEmpty, methods, - options, - ); + options = undefined, + ) => { + const makeSingleton = prepareExoClass( + baggage, + kindName, + interfaceGuard, + initEmpty, + methods, + options, + ); + + // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error -- https://github.com/Agoric/agoric-sdk/issues/4620 + // @ts-ignore could be instantiated with an arbitrary type + return provide(baggage, `the_${kindName}`, () => makeSingleton()); + }; + harden(prepareExo); + + /** + * @template {Record} M methods + * @deprecated Use prepareExo instead. + * @param {Baggage} baggage + * @param {string} kindName + * @param {M} methods + * @param {DefineKindOptions<{ self: M }>} [options] + * @returns {M & RemotableBrand<{}, M>} + */ + const prepareSingleton = (baggage, kindName, methods, options = undefined) => + prepareExo(baggage, kindName, undefined, methods, options); + harden(prepareSingleton); + + return harden({ + defineVirtualExoClass, + defineVirtualExoClassKit, + defineDurableExoClass, + defineDurableExoClassKit, + prepareExoClass, + prepareExoClassKit, + prepareExo, + prepareSingleton, - // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error -- https://github.com/Agoric/agoric-sdk/issues/4620 - // @ts-ignore could be instantiated with an arbitrary type - return provide(baggage, `the_${kindName}`, () => makeSingleton()); + provideKindHandle, + prepareKind, + prepareKindMulti, + }); }; -harden(prepareExo); + +const globalExoUtils = makeExoUtils(globalVatData); + +export const { + defineVirtualExoClass, + defineVirtualExoClassKit, + defineDurableExoClass, + defineDurableExoClassKit, + prepareExoClass, + prepareExoClassKit, + prepareExo, + prepareSingleton, +} = globalExoUtils; /** - * @template {Record} M methods - * @deprecated Use prepareExo instead. - * @param {Baggage} baggage - * @param {string} kindName - * @param {M} methods - * @param {DefineKindOptions<{ self: M }>} [options] - * @returns {M & RemotableBrand<{}, M>} + * @deprecated Use Exos/ExoClasses instead of Kinds */ -export const prepareSingleton = ( - baggage, - kindName, - methods, - options = undefined, -) => prepareExo(baggage, kindName, undefined, methods, options); -harden(prepareSingleton); +export const { provideKindHandle, prepareKind, prepareKindMulti } = + globalExoUtils; diff --git a/packages/vat-data/src/vat-data-bindings.js b/packages/vat-data/src/vat-data-bindings.js index 7cacca40144..8a7fd78bc41 100644 --- a/packages/vat-data/src/vat-data-bindings.js +++ b/packages/vat-data/src/vat-data-bindings.js @@ -29,6 +29,9 @@ if ('VatData' in globalThis) { }; } +const VatDataExport = VatDataGlobal; +export { VatDataExport as VatData }; + /** * @deprecated Use Exos/ExoClasses instead of Kinds */ @@ -140,35 +143,60 @@ harden(partialAssign); */ export const provide = provideLazy; -/** - * @param {import('./types').Baggage} baggage - * @param {string} name - * @param {Omit} options - */ -export const provideDurableMapStore = (baggage, name, options = {}) => - provide(baggage, name, () => - makeScalarBigMapStore(name, { durable: true, ...options }), - ); -harden(provideDurableMapStore); +// TODO: Find a good home for this function used by @agoric/vat-data and testing code +export const makeStoreUtils = VatData => { + const { + // eslint-disable-next-line no-shadow -- these literally do shadow the globals + makeScalarBigMapStore, + // eslint-disable-next-line no-shadow -- these literally do shadow the globals + makeScalarBigWeakMapStore, + // eslint-disable-next-line no-shadow -- these literally do shadow the globals + makeScalarBigSetStore, + } = VatData; -/** - * @param {import('./types').Baggage} baggage - * @param {string} name - * @param {Omit} options - */ -export const provideDurableWeakMapStore = (baggage, name, options = {}) => - provide(baggage, name, () => - makeScalarBigWeakMapStore(name, { durable: true, ...options }), - ); -harden(provideDurableWeakMapStore); + /** + * @param {import('./types').Baggage} baggage + * @param {string} name + * @param {Omit} options + */ + const provideDurableMapStore = (baggage, name, options = {}) => + provide(baggage, name, () => + makeScalarBigMapStore(name, { durable: true, ...options }), + ); + harden(provideDurableMapStore); -/** - * @param {import('./types').Baggage} baggage - * @param {string} name - * @param {Omit} options - */ -export const provideDurableSetStore = (baggage, name, options = {}) => - provide(baggage, name, () => - makeScalarBigSetStore(name, { durable: true, ...options }), - ); -harden(provideDurableSetStore); + /** + * @param {import('./types').Baggage} baggage + * @param {string} name + * @param {Omit} options + */ + const provideDurableWeakMapStore = (baggage, name, options = {}) => + provide(baggage, name, () => + makeScalarBigWeakMapStore(name, { durable: true, ...options }), + ); + harden(provideDurableWeakMapStore); + + /** + * @param {import('./types').Baggage} baggage + * @param {string} name + * @param {Omit} options + */ + const provideDurableSetStore = (baggage, name, options = {}) => + provide(baggage, name, () => + makeScalarBigSetStore(name, { durable: true, ...options }), + ); + harden(provideDurableSetStore); + + return harden({ + provideDurableMapStore, + provideDurableWeakMapStore, + provideDurableSetStore, + }); +}; + +const globalStoreUtils = makeStoreUtils(VatDataGlobal); +export const { + provideDurableMapStore, + provideDurableWeakMapStore, + provideDurableSetStore, +} = globalStoreUtils; From 261e0701f5e81fb96bb79aa4e65d7b9c86cc9c5b Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Mon, 13 Mar 2023 21:21:56 -0400 Subject: [PATCH 20/26] test(swingset-liveslots): Expand the signature of setupTestLiveslots Ref #6523 --- .../test/liveslots-helpers.js | 38 +++++++++++---- .../test/storeGC/test-lifecycle.js | 16 +++---- .../test/storeGC/test-refcount-management.js | 14 +++--- .../test/storeGC/test-scalar-store-kind.js | 2 +- .../test/storeGC/test-weak-key.js | 6 +-- .../swingset-liveslots/test/test-baggage.js | 2 +- .../test/test-initial-vrefs.js | 6 ++- .../virtual-objects/test-virtualObjectGC.js | 48 +++++++++---------- .../tools/vo-test-harness.js | 3 +- 9 files changed, 77 insertions(+), 58 deletions(-) diff --git a/packages/swingset-liveslots/test/liveslots-helpers.js b/packages/swingset-liveslots/test/liveslots-helpers.js index 40904d9c83a..626f10d4200 100644 --- a/packages/swingset-liveslots/test/liveslots-helpers.js +++ b/packages/swingset-liveslots/test/liveslots-helpers.js @@ -15,11 +15,13 @@ import { import { kser } from './kmarshal.js'; /** - * @param {boolean} [skipLogging = false] + * @param {object} [options] + * @param {boolean} [options.skipLogging = false] + * @param {Map} [options.kvStore = new Map()] */ -export function buildSyscall(skipLogging) { +export function buildSyscall(options = {}) { + const { skipLogging = false, kvStore: fakestore = new Map() } = options; const log = []; - const fakestore = new Map(); let sortedKeys; let priorKeyReturned; let priorKeyIndex; @@ -152,23 +154,38 @@ export async function makeDispatch( return { dispatch, testHooks }; } -function makeRPMaker() { - let idx = 0; +function makeRPMaker(nextNumber = 1) { + let idx = nextNumber - 1; return () => { idx += 1; return `p-${idx}`; }; } +/** + * @param {import('ava').ExecutionContext} t + * @param {Function} buildRootObject + * @param {string} vatName + * @param {object} [options] + * @param {boolean} [options.forceGC] + * @param {Map} [options.kvStore = new Map()] + * @param {number} [options.nextPromiseImportNumber] + * @param {boolean} [options.skipLogging = false] + */ export async function setupTestLiveslots( t, buildRootObject, vatName, - forceGC, - skipLogging, + options = {}, ) { - const { log, syscall, fakestore } = buildSyscall(skipLogging); - const nextRP = makeRPMaker(); + const { + forceGC, + kvStore = new Map(), + nextPromiseImportNumber, + skipLogging = false, + } = options; + const { log, syscall, fakestore } = buildSyscall({ skipLogging, kvStore }); + const nextRP = makeRPMaker(nextPromiseImportNumber); const { dispatch, testHooks } = await makeDispatch( syscall, buildRootObject, @@ -215,7 +232,7 @@ export async function setupTestLiveslots( for (const [vpid, rejected, value] of l.resolutions) { if (vpid === rp) { if (rejected) { - throw Error(`vpid ${vpid} rejected with ${value}`); + throw Error(`vpid ${rp} rejected with ${value}`); } else { return value; // resolved successfully } @@ -249,6 +266,7 @@ export async function setupTestLiveslots( return { v, + dispatch, dispatchMessage, dispatchMessageSuccessfully, dispatchDropExports, diff --git a/packages/swingset-liveslots/test/storeGC/test-lifecycle.js b/packages/swingset-liveslots/test/storeGC/test-lifecycle.js index e7de7cef5da..72691cbf75d 100644 --- a/packages/swingset-liveslots/test/storeGC/test-lifecycle.js +++ b/packages/swingset-liveslots/test/storeGC/test-lifecycle.js @@ -71,7 +71,7 @@ test.serial('store lifecycle 1', async t => { t, buildRootObject, 'bob', - true, + { forceGC: true }, ); // lerv -> Lerv Create store @@ -100,7 +100,7 @@ test.serial('store lifecycle 2', async t => { dispatchMessageSuccessfully, dispatchDropExports, dispatchRetireExports, - } = await setupTestLiveslots(t, buildRootObject, 'bob', true); + } = await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); // lerv -> Lerv Create store await dispatchMessageSuccessfully('makeAndHold'); @@ -176,7 +176,7 @@ test.serial('store lifecycle 3', async t => { dispatchMessageSuccessfully, dispatchDropExports, dispatchRetireExports, - } = await setupTestLiveslots(t, buildRootObject, 'bob', true); + } = await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); // lerv -> Lerv Create store await dispatchMessageSuccessfully('makeAndHold'); @@ -213,7 +213,7 @@ test.serial('store lifecycle 3', async t => { // test 4: lerv -> Lerv -> LERv -> LeRv -> lerv test.serial('store lifecycle 4', async t => { const { v, dispatchMessageSuccessfully, dispatchDropExports } = - await setupTestLiveslots(t, buildRootObject, 'bob', true); + await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); // lerv -> Lerv Create store await dispatchMessageSuccessfully('makeAndHold'); @@ -245,7 +245,7 @@ test.serial('store lifecycle 5', async t => { dispatchMessageSuccessfully, dispatchDropExports, dispatchRetireExports, - } = await setupTestLiveslots(t, buildRootObject, 'bob', true); + } = await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); // lerv -> Lerv Create store await dispatchMessageSuccessfully('makeAndHold'); @@ -279,7 +279,7 @@ test.serial('store lifecycle 5', async t => { // test 6: lerv -> Lerv -> LERv -> LeRv -> LeRV -> LeRv -> LeRV -> leRV -> lerv test.serial('store lifecycle 6', async t => { const { v, dispatchMessageSuccessfully, dispatchDropExports } = - await setupTestLiveslots(t, buildRootObject, 'bob', true); + await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); // lerv -> Lerv Create store await dispatchMessageSuccessfully('makeAndHold'); @@ -324,7 +324,7 @@ test.serial('store lifecycle 6', async t => { // test 7: lerv -> Lerv -> LERv -> lERv -> LERv -> lERv -> lerv test.serial('store lifecycle 7', async t => { const { v, dispatchMessageSuccessfully, dispatchDropExports } = - await setupTestLiveslots(t, buildRootObject, 'bob', true); + await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); // lerv -> Lerv Create store await dispatchMessageSuccessfully('makeAndHold'); @@ -363,7 +363,7 @@ test.serial('store lifecycle 7', async t => { // test 8: lerv -> Lerv -> LERv -> LERV -> LERv -> LERV -> lERV -> lERv -> lerv test.serial('store lifecycle 8', async t => { const { v, dispatchMessageSuccessfully, dispatchDropExports } = - await setupTestLiveslots(t, buildRootObject, 'bob', true); + await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); // lerv -> Lerv Create store await dispatchMessageSuccessfully('makeAndHold'); diff --git a/packages/swingset-liveslots/test/storeGC/test-refcount-management.js b/packages/swingset-liveslots/test/storeGC/test-refcount-management.js index 6bf4950ac8b..c9a3772aef6 100644 --- a/packages/swingset-liveslots/test/storeGC/test-refcount-management.js +++ b/packages/swingset-liveslots/test/storeGC/test-refcount-management.js @@ -28,7 +28,7 @@ test.serial('store refcount management 1', async t => { t, buildRootObject, 'bob', - true, + { forceGC: true }, ); const { fakestore } = v; @@ -100,7 +100,7 @@ test.serial('store refcount management 2', async t => { t, buildRootObject, 'bob', - true, + { forceGC: true }, ); const { fakestore } = v; @@ -136,7 +136,7 @@ test.serial('store refcount management 3', async t => { t, buildRootObject, 'bob', - true, + { forceGC: true }, ); const { fakestore } = v; @@ -176,7 +176,7 @@ test.serial('presence refcount management 1', async t => { t, buildRootObject, 'bob', - true, + { forceGC: true }, ); const { fakestore } = v; @@ -224,7 +224,7 @@ test.serial('presence refcount management 2', async t => { t, buildRootObject, 'bob', - true, + { forceGC: true }, ); const { fakestore } = v; @@ -280,7 +280,7 @@ test.serial('remotable refcount management 1', async t => { t, buildRootObject, 'bob', - true, + { forceGC: true }, ); const { fakestore } = v; @@ -316,7 +316,7 @@ test.serial('remotable refcount management 2', async t => { t, buildRootObject, 'bob', - true, + { forceGC: true }, ); const { fakestore } = v; diff --git a/packages/swingset-liveslots/test/storeGC/test-scalar-store-kind.js b/packages/swingset-liveslots/test/storeGC/test-scalar-store-kind.js index a34025913e3..e6b427e15db 100644 --- a/packages/swingset-liveslots/test/storeGC/test-scalar-store-kind.js +++ b/packages/swingset-liveslots/test/storeGC/test-scalar-store-kind.js @@ -18,7 +18,7 @@ test.serial('assert known scalarMapStore ID', async t => { // registered. Check it explicity here. If this test fails, consider // updating `mapRef()` to use the new value. - const { testHooks } = await setupTestLiveslots(t, buildRootObject, 'bob', true); + const { testHooks } = await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const id = testHooks.obtainStoreKindID('scalarMapStore'); t.is(id, 2); t.is(mapRef('INDEX'), 'o+v2/INDEX'); diff --git a/packages/swingset-liveslots/test/storeGC/test-weak-key.js b/packages/swingset-liveslots/test/storeGC/test-weak-key.js index a816a897954..c53dcd22785 100644 --- a/packages/swingset-liveslots/test/storeGC/test-weak-key.js +++ b/packages/swingset-liveslots/test/storeGC/test-weak-key.js @@ -23,7 +23,7 @@ test.serial('verify store weak key GC', async t => { t, buildRootObject, 'bob', - true, + { forceGC: true }, ); const { fakestore } = v; @@ -108,7 +108,7 @@ test.serial('verify weakly held value GC', async t => { t, buildRootObject, 'bob', - true, + { forceGC: true }, ); const { fakestore } = v; @@ -147,7 +147,7 @@ test.serial('verify weakly held value GC', async t => { // prettier-ignore test.serial('verify presence weak key GC', async t => { const { v, dispatchMessage, dispatchRetireImports, testHooks } = - await setupTestLiveslots(t, buildRootObject, 'bob', true); + await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const { fakestore } = v; const presenceRef = 'o-5'; // Presence5 diff --git a/packages/swingset-liveslots/test/test-baggage.js b/packages/swingset-liveslots/test/test-baggage.js index 61f44028fc7..2f3647e0912 100644 --- a/packages/swingset-liveslots/test/test-baggage.js +++ b/packages/swingset-liveslots/test/test-baggage.js @@ -22,7 +22,7 @@ test.serial('exercise baggage', async t => { t, buildRootObject, 'bob', - true, + { forceGC: true }, ); const { fakestore } = v; diff --git a/packages/swingset-liveslots/test/test-initial-vrefs.js b/packages/swingset-liveslots/test/test-initial-vrefs.js index 2b5371f4c7a..04ce20281a6 100644 --- a/packages/swingset-liveslots/test/test-initial-vrefs.js +++ b/packages/swingset-liveslots/test/test-initial-vrefs.js @@ -51,7 +51,9 @@ function buildRootObject(vatPowers, vatParameters, baggage) { } test('initial vatstore contents', async t => { - const { v } = await setupTestLiveslots(t, buildRootObject, 'bob', true); + const { v } = await setupTestLiveslots(t, buildRootObject, 'bob', { + forceGC: true, + }); const { fakestore } = v; const get = key => fakestore.get(key); @@ -100,7 +102,7 @@ test('vrefs', async t => { t, buildRootObject, 'bob', - true, + { forceGC: true }, ); // const { fakestore, dumpFakestore } = v; const { fakestore } = v; diff --git a/packages/swingset-liveslots/test/virtual-objects/test-virtualObjectGC.js b/packages/swingset-liveslots/test/virtual-objects/test-virtualObjectGC.js index 49435cdbd6a..e07ef98bc8d 100644 --- a/packages/swingset-liveslots/test/virtual-objects/test-virtualObjectGC.js +++ b/packages/swingset-liveslots/test/virtual-objects/test-virtualObjectGC.js @@ -417,7 +417,7 @@ async function voLifeCycleTest1(t, isf) { t, buildRootObject, 'bob', - true, + { forceGC: true }, ); const vref = facetRef(isf, thingVref(isf, 2), '1'); @@ -452,7 +452,7 @@ async function voLifeCycleTest2(t, isf) { dispatchMessageSuccessfully, dispatchDropExports, dispatchRetireExports, - } = await setupTestLiveslots(t, buildRootObject, 'bob', true); + } = await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const vref = facetRef(isf, thingVref(isf, 2), '1'); const thing = kslot(vref, isf ? 'thing facetB' : 'thing'); @@ -533,7 +533,7 @@ async function voLifeCycleTest3(t, isf) { dispatchMessageSuccessfully, dispatchDropExports, dispatchRetireExports, - } = await setupTestLiveslots(t, buildRootObject, 'bob', true); + } = await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const vref = facetRef(isf, thingVref(isf, 2), '1'); const thing = kslot(vref, isf ? 'thing facetB' : 'thing'); @@ -577,7 +577,7 @@ test.serial('VO lifecycle 3 faceted', async t => { // test 4: lerv -> Lerv -> LERv -> LeRv -> lerv async function voLifeCycleTest4(t, isf) { const { v, dispatchMessageSuccessfully, dispatchDropExports } = - await setupTestLiveslots(t, buildRootObject, 'bob', true); + await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const vref = facetRef(isf, thingVref(isf, 2), '1'); const thing = kslot(vref, isf ? 'thing facetB' : 'thing'); @@ -614,7 +614,7 @@ async function voLifeCycleTest5(t, isf) { dispatchMessageSuccessfully, dispatchDropExports, dispatchRetireExports, - } = await setupTestLiveslots(t, buildRootObject, 'bob', true); + } = await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const vref = facetRef(isf, thingVref(isf, 2), '1'); const thing = kslot(vref, isf ? 'thing facetB' : 'thing'); @@ -650,7 +650,7 @@ test.serial('VO lifecycle 5 faceted', async t => { // test 6: lerv -> Lerv -> LERv -> LeRv -> LeRV -> LeRv -> LeRV -> leRV -> lerv async function voLifeCycleTest6(t, isf) { const { v, dispatchMessageSuccessfully, dispatchDropExports } = - await setupTestLiveslots(t, buildRootObject, 'bob', true); + await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const vref = facetRef(isf, thingVref(isf, 2), '1'); const thing = kslot(vref, isf ? 'thing facetB' : 'thing'); @@ -699,7 +699,7 @@ test.serial('VO lifecycle 6 faceted', async t => { // test 7: lerv -> Lerv -> LERv -> lERv -> LERv -> lERv -> lerv async function voLifeCycleTest7(t, isf) { const { v, dispatchMessageSuccessfully, dispatchDropExports } = - await setupTestLiveslots(t, buildRootObject, 'bob', true); + await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const vref = facetRef(isf, thingVref(isf, 2), '1'); const thing = kslot(vref, isf ? 'thing facetB' : 'thing'); @@ -740,7 +740,7 @@ test.serial('VO lifecycle 7 faceted', async t => { // test 8: lerv -> Lerv -> LERv -> LERV -> LERv -> LERV -> lERV -> lERv -> lerv async function voLifeCycleTest8(t, isf) { const { v, dispatchMessageSuccessfully, dispatchDropExports } = - await setupTestLiveslots(t, buildRootObject, 'bob', true); + await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const vref = facetRef(isf, thingVref(isf, 2), '1'); const thing = kslot(vref, isf ? 'thing facetB' : 'thing'); @@ -792,7 +792,7 @@ test.serial('VO multifacet export 1', async t => { t, buildRootObject, 'bob', - true, + { forceGC: true }, ); const vref = facetRef(true, thingVref(true, 2), '1'); @@ -810,7 +810,7 @@ test.serial('VO multifacet export 1', async t => { // multifacet export test 2a: export A, drop A, retire A test.serial('VO multifacet export 2a', async t => { const { v, dispatchMessageSuccessfully, dispatchDropExports } = - await setupTestLiveslots(t, buildRootObject, 'bob', true); + await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const vref = facetRef(true, thingVref(true, 2), '0'); const thingA = kslot(vref, 'thing facetA'); @@ -838,7 +838,7 @@ test.serial('VO multifacet export 2a', async t => { // multifacet export test 2b: export B, drop B, retire B test.serial('VO multifacet export 2b', async t => { const { v, dispatchMessageSuccessfully, dispatchDropExports } = - await setupTestLiveslots(t, buildRootObject, 'bob', true); + await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const vref = facetRef(true, thingVref(true, 2), '1'); const thingB = kslot(vref, 'thing facetB'); @@ -865,7 +865,7 @@ test.serial('VO multifacet export 2b', async t => { // multifacet export test 3abba: export A, export B, drop B, drop A, retire test.serial('VO multifacet export 3abba', async t => { const { v, dispatchMessageSuccessfully, dispatchDropExports } = - await setupTestLiveslots(t, buildRootObject, 'bob', true); + await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const vrefA = facetRef(true, thingVref(true, 2), '0'); const thingA = kslot(vrefA, 'thing facetA'); const vrefB = facetRef(true, thingVref(true, 2), '1'); @@ -903,7 +903,7 @@ test.serial('VO multifacet export 3abba', async t => { // multifacet export test 3abab: export A, export B, drop A, drop B, retire test.serial('VO multifacet export 3abab', async t => { const { v, dispatchMessageSuccessfully, dispatchDropExports } = - await setupTestLiveslots(t, buildRootObject, 'bob', true); + await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const vrefA = facetRef(true, thingVref(true, 2), '0'); const thingA = kslot(vrefA, 'thing facetA'); const vrefB = facetRef(true, thingVref(true, 2), '1'); @@ -943,7 +943,7 @@ test.serial('VO multifacet markers only', async t => { t, buildRootObject, 'bob', - true, + { forceGC: true }, ); const vrefA = facetRef(true, `${markerBaseRef}/1`, '0'); const { baseRef } = parseVatSlot(vrefA); @@ -961,7 +961,7 @@ test.serial('VO multifacet markers only', async t => { // prettier-ignore async function voRefcountManagementTest1(t, isf) { - const { v, dispatchMessageSuccessfully } = await setupTestLiveslots(t, buildRootObject, 'bob', true); + const { v, dispatchMessageSuccessfully } = await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const vref = facetRef(isf, thingVref(isf, 2), '1'); const { baseRef } = parseVatSlot(vref); const thing = kslot(vref, isf ? 'thing facetB' : 'thing'); @@ -1002,7 +1002,7 @@ test.serial('VO refcount management 1 faceted', async t => { // prettier-ignore async function voRefcountManagementTest2(t, isf) { - const { v, dispatchMessageSuccessfully } = await setupTestLiveslots(t, buildRootObject, 'bob', true); + const { v, dispatchMessageSuccessfully } = await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const vref = facetRef(isf, thingVref(isf, 2), '1'); const { baseRef } = parseVatSlot(vref); const thing = kslot(vref, isf ? 'thing facetB' : 'thing'); @@ -1043,7 +1043,7 @@ test.serial('VO refcount management 2 faceted', async t => { // prettier-ignore async function voRefcountManagementTest3(t, isf) { - const { v, dispatchMessageSuccessfully } = await setupTestLiveslots(t, buildRootObject, 'bob', true); + const { v, dispatchMessageSuccessfully } = await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const vref = facetRef(isf, thingVref(isf, 2), '1'); const { baseRef } = parseVatSlot(vref); const thing = kslot(vref, isf ? 'thing facetB' : 'thing'); @@ -1093,7 +1093,7 @@ test.serial('VO refcount management 3 faceted', async t => { // prettier-ignore test.serial('presence refcount management 1', async t => { - const { v, dispatchMessageSuccessfully } = await setupTestLiveslots(t, buildRootObject, 'bob', true); + const { v, dispatchMessageSuccessfully } = await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const { fakestore } = v; const vref = 'o-5'; @@ -1132,7 +1132,7 @@ test.serial('presence refcount management 1', async t => { // prettier-ignore test.serial('presence refcount management 2', async t => { - const { v, dispatchMessageSuccessfully } = await setupTestLiveslots(t, buildRootObject, 'bob', true); + const { v, dispatchMessageSuccessfully } = await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const { fakestore } = v; const vref = 'o-5'; @@ -1170,7 +1170,7 @@ test.serial('presence refcount management 2', async t => { // prettier-ignore test.serial('remotable refcount management 1', async t => { - const { v, dispatchMessageSuccessfully } = await setupTestLiveslots(t, buildRootObject, 'bob', true); + const { v, dispatchMessageSuccessfully } = await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const { fakestore } = v; // holder Kind is the next-to-last created kind, which gets idCounters.exportID-2 @@ -1213,7 +1213,7 @@ test.serial('remotable refcount management 1', async t => { // prettier-ignore test.serial('remotable refcount management 2', async t => { - const { v, dispatchMessageSuccessfully } = await setupTestLiveslots(t, buildRootObject, 'bob', true); + const { v, dispatchMessageSuccessfully } = await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const { fakestore } = v; const holderKindID = JSON.parse(fakestore.get(`idCounters`)).exportID - 2; @@ -1234,7 +1234,7 @@ test.serial('remotable refcount management 2', async t => { // prettier-ignore async function voWeakKeyGCTest(t, isf) { - const { v, dispatchMessageSuccessfully, testHooks } = await setupTestLiveslots(t, buildRootObject, 'bob', true); + const { v, dispatchMessageSuccessfully, testHooks } = await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const vref = facetRef(isf, thingVref(isf, 2), '1'); const thing = kslot(vref, isf ? 'thing facetB' : 'thing'); const { baseRef } = parseVatSlot(vref); @@ -1265,7 +1265,7 @@ test.serial('verify VO weak key GC faceted', async t => { // prettier-ignore test.serial('verify presence weak key GC', async t => { const { v, dispatchMessageSuccessfully, dispatchRetireImports, testHooks } = - await setupTestLiveslots(t, buildRootObject, 'bob', true); + await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const vref = 'o-5'; const presence = kslot(vref, 'thing'); // hold a Presence weakly by a VOAwareWeak(Map/Set), also by RAM @@ -1316,7 +1316,7 @@ test.serial('verify presence weak key GC', async t => { // prettier-ignore test.serial('VO holding non-VO', async t => { const { v, dispatchMessageSuccessfully, dispatchDropExports, dispatchRetireExports } = - await setupTestLiveslots(t, buildRootObject, 'bob', true); + await setupTestLiveslots(t, buildRootObject, 'bob', { forceGC: true }); const { fakestore } = v; // lerv -> Lerv Create non-VO diff --git a/packages/swingset-liveslots/tools/vo-test-harness.js b/packages/swingset-liveslots/tools/vo-test-harness.js index cb13aee62e4..4885246d7d9 100644 --- a/packages/swingset-liveslots/tools/vo-test-harness.js +++ b/packages/swingset-liveslots/tools/vo-test-harness.js @@ -131,8 +131,7 @@ export async function runVOTest(t, prepare, makeTestObject, testTestObject) { t, buildRootObject, 'bob', - true, - true, + { forceGC: true, skipLogging: true }, ); await dispatchMessage('makeAndHold'); From 60a8375c7b6f69cb019adf08c6c51be14a9d2da9 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Mon, 13 Mar 2023 21:22:40 -0400 Subject: [PATCH 21/26] test(swingset-liveslots): Add a default cache size to makeFakeVirtualStuff --- .../tools/fakeVirtualSupport.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/swingset-liveslots/tools/fakeVirtualSupport.js b/packages/swingset-liveslots/tools/fakeVirtualSupport.js index 89c91d0b541..6db39bd5cfd 100644 --- a/packages/swingset-liveslots/tools/fakeVirtualSupport.js +++ b/packages/swingset-liveslots/tools/fakeVirtualSupport.js @@ -291,17 +291,22 @@ export function makeFakeWatchedPromiseManager( * Configure virtual stuff with relaxed durability rules and fake liveslots * * @param {object} [options] + * @param {number} [options.cacheSize=3] * @param {boolean} [options.relaxDurabilityRules=true] - * @param {number} [options.cacheSize] */ export function makeFakeVirtualStuff(options = {}) { - const fakeStuff = makeFakeLiveSlotsStuff(options); - const { relaxDurabilityRules = true } = options; + const actualOptions = { + cacheSize: 3, + relaxDurabilityRules: true, + ...options, + }; + const { relaxDurabilityRules } = actualOptions; + const fakeStuff = makeFakeLiveSlotsStuff(actualOptions); const vrm = makeFakeVirtualReferenceManager(fakeStuff, relaxDurabilityRules); - const vom = makeFakeVirtualObjectManager(vrm, fakeStuff, options); + const vom = makeFakeVirtualObjectManager(vrm, fakeStuff, actualOptions); vom.initializeKindHandleKind(); fakeStuff.setVrm(vrm); - const cm = makeFakeCollectionManager(vrm, fakeStuff, options); + const cm = makeFakeCollectionManager(vrm, fakeStuff, actualOptions); const wpm = makeFakeWatchedPromiseManager(vrm, vom, cm, fakeStuff); return { fakeStuff, vrm, vom, cm, wpm }; } From 9207f4495f7f9c4457b4f1fa45a87087b5d680e2 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Wed, 15 Mar 2023 22:31:30 -0400 Subject: [PATCH 22/26] test(swingset-liveslots): Add liveslots-level handled promises tests --- .../test/test-handled-promises.js | 294 ++++++++++++++++++ 1 file changed, 294 insertions(+) create mode 100644 packages/swingset-liveslots/test/test-handled-promises.js diff --git a/packages/swingset-liveslots/test/test-handled-promises.js b/packages/swingset-liveslots/test/test-handled-promises.js new file mode 100644 index 00000000000..fefb3b17e12 --- /dev/null +++ b/packages/swingset-liveslots/test/test-handled-promises.js @@ -0,0 +1,294 @@ +/* eslint-disable no-await-in-loop, @jessie.js/no-nested-await */ +import test from 'ava'; +import '@endo/init/debug.js'; + +import { Far } from '@endo/marshal'; +import { Fail } from '@agoric/assert'; +import { M } from '@agoric/store'; +import { makePromiseKit } from '@endo/promise-kit'; +// import { makeStoreUtils } from '../../vat-data/src/vat-data-bindings.js'; +import { makeExoUtils } from '../../vat-data/src/exo-utils.js'; +import { kslot, kser } from './kmarshal.js'; +import { setupTestLiveslots } from './liveslots-helpers.js'; +import { makeResolve, makeReject } from './util.js'; + +// eslint-disable-next-line no-underscore-dangle, no-nested-ternary +const _compareByKey = (a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0); + +// cf. packages/SwingSet/test/vat-durable-promise-watcher.js +const buildPromiseWatcherRootObject = (vatPowers, _vatParameters, baggage) => { + const { VatData } = vatPowers; + const { watchPromise } = VatData; + const { prepareExo } = makeExoUtils(VatData); + // const { makeScalarBigMapStore } = makeStoreUtils(VatData); + const PromiseWatcherI = M.interface('ExtraArgPromiseWatcher', { + onFulfilled: M.call(M.any(), M.string()).returns(), + onRejected: M.call(M.any(), M.string()).returns(), + }); + const watcher = prepareExo( + baggage, + 'DurablePromiseIgnorer', + PromiseWatcherI, + { + onFulfilled(_value, _name) {}, + onRejected(_reason, _name) {}, + }, + ); + + const localPromises = new Map(); + + return Far('root', { + exportPromise: () => [Promise.resolve()], + createLocalPromise: (name, fulfillment, rejection) => { + !localPromises.has(name) || Fail`local promise already exists: ${name}`; + const { promise, resolve, reject } = makePromiseKit(); + if (fulfillment !== undefined) { + resolve(fulfillment); + } else if (rejection !== undefined) { + reject(rejection); + } + localPromises.set(name, promise); + return `created local promise: ${name}`; + }, + watchLocalPromise: name => { + localPromises.has(name) || Fail`local promise not found: ${name}`; + watchPromise(localPromises.get(name), watcher, name); + return `watched local promise: ${name}`; + }, + }); +}; +const kvStoreDataV1 = Object.entries({ + baggageID: 'o+d6/1', + idCounters: '{"exportID":11,"collectionID":5,"promiseID":9}', + kindIDID: '1', + storeKindIDTable: + '{"scalarMapStore":2,"scalarWeakMapStore":3,"scalarSetStore":4,"scalarWeakSetStore":5,"scalarDurableMapStore":6,"scalarDurableWeakMapStore":7,"scalarDurableSetStore":8,"scalarDurableWeakSetStore":9}', + 'vc.1.sDurablePromiseIgnorer_kindHandle': + '{"body":"#\\"$0.Alleged: kind\\"","slots":["o+d1/10"]}', + 'vc.1.sthe_DurablePromiseIgnorer': + '{"body":"#\\"$0.Alleged: DurablePromiseIgnorer\\"","slots":["o+d10/1"]}', + 'vc.1.|entryCount': '2', + 'vc.1.|label': 'baggage', + 'vc.1.|nextOrdinal': '1', + 'vc.1.|schemata': + '{"body":"#[{\\"#tag\\":\\"match:string\\",\\"payload\\":[]}]","slots":[]}', + // non-durable + // 'vc.2.sp+6': '{"body":"#\\"&0\\"","slots":["p+6"]}', + // 'vc.2.|entryCount': '1', + // 'vc.2.|label': 'promiseRegistrations', + // 'vc.2.|nextOrdinal': '1', + // 'vc.2.|schemata': '{"body":"#[{\\"#tag\\":\\"match:scalar\\",\\"payload\\":\\"#undefined\\"}]","slots":[]}', + 'vc.3.|entryCount': '0', + 'vc.3.|label': 'promiseWatcherByKind', + 'vc.3.|nextOrdinal': '1', + 'vc.3.|schemata': + '{"body":"#[{\\"#tag\\":\\"match:scalar\\",\\"payload\\":\\"#undefined\\"}]","slots":[]}', + 'vc.4.sp+6': + '{"body":"#[[\\"$0.Alleged: DurablePromiseIgnorer\\",\\"orphaned\\"]]","slots":["o+d10/1"]}', + 'vc.4.sp-8': + '{"body":"#[[\\"$0.Alleged: DurablePromiseIgnorer\\",\\"unresolved\\"]]","slots":["o+d10/1"]}', + 'vc.4.sp-9': + '{"body":"#[[\\"$0.Alleged: DurablePromiseIgnorer\\",\\"late-rejected\\"]]","slots":["o+d10/1"]}', + 'vc.4.|entryCount': '3', + 'vc.4.|label': 'watchedPromises', + 'vc.4.|nextOrdinal': '1', + 'vc.4.|schemata': + '{"body":"#[{\\"#tag\\":\\"match:and\\",\\"payload\\":[{\\"#tag\\":\\"match:scalar\\",\\"payload\\":\\"#undefined\\"},{\\"#tag\\":\\"match:string\\",\\"payload\\":[]}]}]","slots":[]}', + 'vom.dkind.10': + '{"kindID":"10","tag":"DurablePromiseIgnorer","nextInstanceID":2,"unfaceted":true}', + 'vom.o+d10/1': '{}', + 'vom.rc.o+d1/10': '1', + 'vom.rc.o+d10/1': '3', + 'vom.rc.o+d6/1': '1', + 'vom.rc.o+d6/3': '1', + 'vom.rc.o+d6/4': '1', + watchedPromiseTableID: 'o+d6/4', + watcherTableID: 'o+d6/3', +}); +const kvStoreDataV1VpidsToReject = ['p+6', 'p-9']; +const kvStoreDataV1KeysToDelete = ['vc.4.sp+6', 'vc.4.sp-9']; +const kvStoreDataV1VpidsToKeep = ['p-8']; +const kvStoreDataV1KeysToKeep = ['vc.4.sp-8']; + +test('past-incarnation watched promises', async t => { + const kvStore = new Map(); + let { v, dispatch, dispatchMessage } = await setupTestLiveslots( + t, + buildPromiseWatcherRootObject, + 'durable-promise-watcher', + { kvStore }, + ); + let vatLogs = v.log; + + // Anchor promise counters upon which the other assertions depend. + const firstPImport = 1; + // cf. src/liveslots.js:initialIDCounters + const firstPExport = 5; + let lastPImport = firstPImport - 1; + let lastPExport = firstPExport - 1; + const nextPImport = () => (lastPImport += 1); + const nextPExport = () => (lastPExport += 1); + // Ignore vatstore syscalls. + const getDispatchLogs = () => + vatLogs.splice(0).filter(m => !m.type.startsWith('vatstore')); + const settlementMessage = (vpid, rejected, value) => ({ + type: 'resolve', + resolutions: [[vpid, rejected, kser(value)]], + }); + const fulfillmentMessage = (vpid, value) => + settlementMessage(vpid, false, value); + const rejectionMessage = (vpid, value) => + settlementMessage(vpid, true, value); + const subscribeMessage = vpid => ({ + type: 'subscribe', + target: vpid, + }); + vatLogs.length = 0; + await dispatchMessage('exportPromise'); + t.deepEqual(getDispatchLogs(), [ + fulfillmentMessage(`p-${nextPImport()}`, [kslot(`p+${nextPExport()}`)]), + fulfillmentMessage(`p+${lastPExport}`, undefined), + ]); + + const S = 'settlement'; + await dispatchMessage('createLocalPromise', 'orphaned'); + t.deepEqual(getDispatchLogs(), [ + fulfillmentMessage(`p-${nextPImport()}`, 'created local promise: orphaned'), + ]); + await dispatchMessage('createLocalPromise', 'fulfilled', S); + t.deepEqual(getDispatchLogs(), [ + fulfillmentMessage( + `p-${nextPImport()}`, + 'created local promise: fulfilled', + ), + ]); + await dispatchMessage('createLocalPromise', 'rejected', undefined, S); + t.deepEqual(getDispatchLogs(), [ + fulfillmentMessage(`p-${nextPImport()}`, 'created local promise: rejected'), + ]); + t.deepEqual( + lastPImport - firstPImport + 1, + 4, + 'imported 4 promises (1 per dispatch)', + ); + t.deepEqual(lastPExport - firstPExport + 1, 1, 'exported 1 promise: first'); + + await dispatchMessage('watchLocalPromise', 'orphaned'); + t.deepEqual(getDispatchLogs(), [ + subscribeMessage(`p+${nextPExport()}`), + fulfillmentMessage(`p-${nextPImport()}`, 'watched local promise: orphaned'), + ]); + await dispatchMessage('watchLocalPromise', 'fulfilled'); + t.deepEqual(getDispatchLogs(), [ + subscribeMessage(`p+${nextPExport()}`), + fulfillmentMessage( + `p-${nextPImport()}`, + 'watched local promise: fulfilled', + ), + fulfillmentMessage(`p+${lastPExport}`, S), + ]); + await dispatchMessage('watchLocalPromise', 'rejected'); + t.deepEqual(getDispatchLogs(), [ + subscribeMessage(`p+${nextPExport()}`), + fulfillmentMessage(`p-${nextPImport()}`, 'watched local promise: rejected'), + rejectionMessage(`p+${lastPExport}`, S), + ]); + t.deepEqual( + lastPImport - firstPImport + 1, + 7, + 'imported 7 promises (1 per dispatch)', + ); + t.deepEqual( + lastPExport - firstPExport + 1, + 4, + 'exported 4 promises: first, orphaned, fulfilled, rejected', + ); + + // Simulate upgrade by starting from the non-empty kvStore. + // t.log(Object.fromEntries([...kvStore.entries()].sort(_compareByKey))); + const clonedStore = new Map(kvStore); + ({ v, dispatch, dispatchMessage } = await setupTestLiveslots( + t, + buildPromiseWatcherRootObject, + 'durable-promise-watcher-v2', + { kvStore: clonedStore, nextPromiseImportNumber: lastPImport + 1 }, + )); + vatLogs = v.log; + + // Simulate kernel rejection of promises orphaned by termination/upgrade of their decider vat. + const expectedDeletions = [...clonedStore.entries()].filter(entry => + entry[1].includes('orphaned'), + ); + t.true(expectedDeletions.length >= 1); + await dispatch( + makeReject(`p+${firstPExport + 1}`, kser('tomorrow never came')), + ); + for (const [key, value] of expectedDeletions) { + t.false(clonedStore.has(key), `entry should be removed: ${key}: ${value}`); + } + + // Verify that the data is still in loadable condition. + const finalClonedStore = new Map(clonedStore); + ({ v, dispatch, dispatchMessage } = await setupTestLiveslots( + t, + buildPromiseWatcherRootObject, + 'durable-promise-watcher-final', + { kvStore: finalClonedStore, nextPromiseImportNumber: lastPImport + 1 }, + )); + vatLogs = v.log; + vatLogs.length = 0; + await dispatchMessage('createLocalPromise', 'final', S); + await dispatchMessage('watchLocalPromise', 'final'); + t.deepEqual(getDispatchLogs(), [ + fulfillmentMessage(`p-${nextPImport()}`, 'created local promise: final'), + subscribeMessage(`p+${nextPExport()}`), + fulfillmentMessage(`p-${nextPImport()}`, 'watched local promise: final'), + fulfillmentMessage(`p+${lastPExport}`, S), + ]); +}); + +test('past-incarnation watched promises from original-format kvStore', async t => { + const kvStore = new Map(kvStoreDataV1); + for (const key of [ + ...kvStoreDataV1KeysToDelete, + ...kvStoreDataV1KeysToKeep, + ]) { + t.true(kvStore.has(key), `key must be initially present: ${key}`); + } + + let { v, dispatch, dispatchMessage } = await setupTestLiveslots( + t, + buildPromiseWatcherRootObject, + 'durable-promise-watcher', + { kvStore, nextPromiseImportNumber: 100 }, + ); + let vatLogs = v.log; + for (const vpid of kvStoreDataV1VpidsToReject) { + await dispatch(makeReject(vpid, kser('tomorrow never came'))); + } + for (const key of kvStoreDataV1KeysToDelete) { + t.false(kvStore.has(key), `key should be removed: ${key}`); + } + for (const key of kvStoreDataV1KeysToKeep) { + t.true(kvStore.has(key), `key should remain: ${key}`); + } + + // Verify that the data is still in loadable condition. + const finalClonedStore = new Map(kvStore); + // eslint-disable-next-line no-unused-vars + ({ v, dispatch, dispatchMessage } = await setupTestLiveslots( + t, + buildPromiseWatcherRootObject, + 'durable-promise-watcher-final', + { kvStore: finalClonedStore, nextPromiseImportNumber: 200 }, + )); + vatLogs = v.log; + console.log(...vatLogs); + vatLogs.length = 0; + for (const vpid of kvStoreDataV1VpidsToKeep) { + await dispatch(makeResolve(vpid, kser('finally'))); + } + for (const key of kvStoreDataV1KeysToKeep) { + t.false(finalClonedStore.has(key), `key should be removed: ${key}`); + } +}); From 8327856c524a75076ac300b0a63ec7cde0f642f6 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Thu, 16 Mar 2023 00:51:44 -0400 Subject: [PATCH 23/26] chore: Minor jsdoc/eslint improvements --- packages/SwingSet/test/test-promises.js | 4 ++-- packages/swingset-liveslots/src/liveslots.js | 2 +- packages/swingset-liveslots/test/test-handled-promises.js | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/SwingSet/test/test-promises.js b/packages/SwingSet/test/test-promises.js index 8ed2724f390..89cc8e12c23 100644 --- a/packages/SwingSet/test/test-promises.js +++ b/packages/SwingSet/test/test-promises.js @@ -252,8 +252,8 @@ test('local promises are rejected by vat upgrade', async t => { }; const messageVat = (name, methodName, args) => run('messageVat', [{ name, methodName, args }]); - // eslint-disable-next-line no-underscore-dangle - const _messageObject = (presence, methodName, args) => + // eslint-disable-next-line no-unused-vars + const messageObject = (presence, methodName, args) => run('messageVatObject', [{ presence, methodName, args }]); const S = Symbol.for('passable'); diff --git a/packages/swingset-liveslots/src/liveslots.js b/packages/swingset-liveslots/src/liveslots.js index 82cf235a2dd..2699c8dee1e 100644 --- a/packages/swingset-liveslots/src/liveslots.js +++ b/packages/swingset-liveslots/src/liveslots.js @@ -557,7 +557,7 @@ function build( * adds it to exportedVPIDs and sets up handlers. * * @param {any} vref - * @returns {boolean} + * @returns {boolean} whether the vref was added to exportedVPIDs */ function maybeExportPromise(vref) { // we only care about new vpids diff --git a/packages/swingset-liveslots/test/test-handled-promises.js b/packages/swingset-liveslots/test/test-handled-promises.js index fefb3b17e12..07c101d23dd 100644 --- a/packages/swingset-liveslots/test/test-handled-promises.js +++ b/packages/swingset-liveslots/test/test-handled-promises.js @@ -12,8 +12,8 @@ import { kslot, kser } from './kmarshal.js'; import { setupTestLiveslots } from './liveslots-helpers.js'; import { makeResolve, makeReject } from './util.js'; -// eslint-disable-next-line no-underscore-dangle, no-nested-ternary -const _compareByKey = (a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0); +// eslint-disable-next-line no-unused-vars +const compareEntriesByKey = ([ka], [kb]) => (ka < kb ? -1 : 1); // cf. packages/SwingSet/test/vat-durable-promise-watcher.js const buildPromiseWatcherRootObject = (vatPowers, _vatParameters, baggage) => { @@ -205,7 +205,7 @@ test('past-incarnation watched promises', async t => { ); // Simulate upgrade by starting from the non-empty kvStore. - // t.log(Object.fromEntries([...kvStore.entries()].sort(_compareByKey))); + // t.log(Object.fromEntries([...kvStore.entries()].sort(compareEntriesByKey))); const clonedStore = new Map(kvStore); ({ v, dispatch, dispatchMessage } = await setupTestLiveslots( t, From 5a723d4761af8e034724d410a057814f352168fb Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Thu, 16 Mar 2023 16:06:12 -0400 Subject: [PATCH 24/26] fixup! docs(swingset-liveslots): Clarify VPID managment documentation --- packages/swingset-liveslots/src/vpid-tracking.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/swingset-liveslots/src/vpid-tracking.md b/packages/swingset-liveslots/src/vpid-tracking.md index 80ada85849f..05a2714a0e0 100644 --- a/packages/swingset-liveslots/src/vpid-tracking.md +++ b/packages/swingset-liveslots/src/vpid-tracking.md @@ -82,7 +82,7 @@ Remember that the `slotToVal` registration uses a WeakRef, so being registered t * construct a promise `res` to capture the userspace-provided result * if the VPID is present in `importedVPIDs`: retrieve the `[resolve, reject]` pRec and use `resolve(res)` to forward eventual settlement of `res` to settlement of the previously-imported promise, then remove the VPID from `importedVPIDs` * else: register marshaller association between the VPID and `res` - * in either case, use `followForKernel` to add the VPID to `exportedVPIDs` and attach `.then(onFulfill, onReject)` callbacks that will map fulfillment/rejection to `syscall.resolve() + * in either case, use `followForKernel` to add the VPID to `exportedVPIDs` and attach `.then(onFulfill, onReject)` callbacks that will map fulfillment/rejection to `syscall.resolve()` If the serialization is for storage in virtual data, the act of storing the VPID will add the Promise to `remotableRefCounts`, which maintains a strong reference for as long as the VPID is held. When it is removed from virtual data (or the object/collection is deleted), the refcount will be decremented. When the refcount drops to zero, we perform the `exportedVPIDs`/`importedVPIDs` check and then maybe unregister the promise. From 3777b89832bfdd68dff5fa350e51e31a97411b9a Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Thu, 16 Mar 2023 16:16:26 -0400 Subject: [PATCH 25/26] test(swingset-liveslots): Remove the dependency on vat-data --- .../test/test-handled-promises.js | 79 +++++++++++++++++-- 1 file changed, 74 insertions(+), 5 deletions(-) diff --git a/packages/swingset-liveslots/test/test-handled-promises.js b/packages/swingset-liveslots/test/test-handled-promises.js index 07c101d23dd..db1aafbaed8 100644 --- a/packages/swingset-liveslots/test/test-handled-promises.js +++ b/packages/swingset-liveslots/test/test-handled-promises.js @@ -1,13 +1,14 @@ -/* eslint-disable no-await-in-loop, @jessie.js/no-nested-await */ +/* eslint-disable no-await-in-loop, @jessie.js/no-nested-await, no-shadow */ import test from 'ava'; import '@endo/init/debug.js'; import { Far } from '@endo/marshal'; import { Fail } from '@agoric/assert'; -import { M } from '@agoric/store'; +import { M, provideLazy as provide } from '@agoric/store'; import { makePromiseKit } from '@endo/promise-kit'; -// import { makeStoreUtils } from '../../vat-data/src/vat-data-bindings.js'; -import { makeExoUtils } from '../../vat-data/src/exo-utils.js'; +// Disabled to avoid circular dependencies. +// import { makeStoreUtils } from '@agoric/vat-data/src/vat-data-bindings.js'; +// import { makeExoUtils } from '@agoric/vat-data/src/exo-utils.js'; import { kslot, kser } from './kmarshal.js'; import { setupTestLiveslots } from './liveslots-helpers.js'; import { makeResolve, makeReject } from './util.js'; @@ -15,6 +16,75 @@ import { makeResolve, makeReject } from './util.js'; // eslint-disable-next-line no-unused-vars const compareEntriesByKey = ([ka], [kb]) => (ka < kb ? -1 : 1); +// Paritally duplicates @agoric/vat-data to avoid circular dependencies. +const makeExoUtils = VatData => { + const { defineDurableKind, makeKindHandle, watchPromise } = VatData; + + const provideKindHandle = (baggage, kindName) => + provide(baggage, `${kindName}_kindHandle`, () => makeKindHandle(kindName)); + + const emptyRecord = harden({}); + const initEmpty = () => emptyRecord; + + const defineDurableExoClass = ( + kindHandle, + interfaceGuard, + init, + methods, + options, + ) => + defineDurableKind(kindHandle, init, methods, { + ...options, + thisfulMethods: true, + interfaceGuard, + }); + + const prepareExoClass = ( + baggage, + kindName, + interfaceGuard, + init, + methods, + options = undefined, + ) => + defineDurableExoClass( + provideKindHandle(baggage, kindName), + interfaceGuard, + init, + methods, + options, + ); + + const prepareExo = ( + baggage, + kindName, + interfaceGuard, + methods, + options = undefined, + ) => { + const makeSingleton = prepareExoClass( + baggage, + kindName, + interfaceGuard, + initEmpty, + methods, + options, + ); + return provide(baggage, `the_${kindName}`, () => makeSingleton()); + }; + + return { + defineDurableKind, + makeKindHandle, + watchPromise, + + provideKindHandle, + defineDurableExoClass, + prepareExoClass, + prepareExo, + }; +}; + // cf. packages/SwingSet/test/vat-durable-promise-watcher.js const buildPromiseWatcherRootObject = (vatPowers, _vatParameters, baggage) => { const { VatData } = vatPowers; @@ -283,7 +353,6 @@ test('past-incarnation watched promises from original-format kvStore', async t = { kvStore: finalClonedStore, nextPromiseImportNumber: 200 }, )); vatLogs = v.log; - console.log(...vatLogs); vatLogs.length = 0; for (const vpid of kvStoreDataV1VpidsToKeep) { await dispatch(makeResolve(vpid, kser('finally'))); From 8dab80ff5ec39902791897d22d2aa0d42596db6d Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Thu, 16 Mar 2023 18:58:46 -0400 Subject: [PATCH 26/26] docs(swingset-liveslots): Restore tildot example that might be important --- packages/swingset-liveslots/src/vpid-tracking.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/swingset-liveslots/src/vpid-tracking.md b/packages/swingset-liveslots/src/vpid-tracking.md index 05a2714a0e0..208acc7a6cf 100644 --- a/packages/swingset-liveslots/src/vpid-tracking.md +++ b/packages/swingset-liveslots/src/vpid-tracking.md @@ -2,7 +2,7 @@ Kernels and vats communicate about promises by referring to their VPIDs: vat(-centric) promise IDs. These are strings like `p+12` and `p-23`. Like VOIDs (object IDs), the plus/minus sign indicates which side of the boundary allocated the number (`p+12` and `o+12` are allocated by the vat, `p-13` and `o-13` are allocated by the kernel). But where the object ID sign also indicates which side "owns" the object (i.e. where the behavior lives), the promise ID sign is generally irrelevant. -Instead, we care about which side holds the resolution authority for a promise (referred to as being its **decider**). This is not indicated by the VPID sign, and in fact is not necessarily static. Liveslots does not currently have any mechanism to allow one promise to be forwarded to another, but if it acquires this some day, then the decider of a promise could shift from kernel to vat to kernel again before it finally gets resolved. And there *are* sequences that allow a vat to receive a reference to a promise in method arguments before receiving a message for which that same VPID identifies the result promise (e.g., `{ promise: p1, resolve: resolveP1 } = makePromiseKit(); p2 = E(p1).push('queued'); await E(observer).push(p2); resolveP1(observer);` with an observer whose `push` returns a prompt response). In such cases, the decider is initially the kernel but later becomes the receiving vat. +Instead, we care about which side holds the resolution authority for a promise (referred to as being its **decider**). This is not indicated by the VPID sign, and in fact is not necessarily static. Liveslots does not currently have any mechanism to allow one promise to be forwarded to another, but if it acquires this some day, then the decider of a promise could shift from kernel to vat to kernel again before it finally gets resolved. And there *are* sequences that allow a vat to receive a reference to a promise in method arguments before receiving a message whose result promise uses that same VPID (e.g., `p1 = p2~.foo(); x~.bar(p1)`, then someone resolves `p2` to `x`. Consider also tildot-free code like `{ promise: p1, resolve: resolveP1 } = makePromiseKit(); p2 = E(p1).push('queued'); await E(observer).push(p2); resolveP1(observer);` with an observer whose `push` returns a prompt response). In such cases, the decider is initially the kernel but that authority is transferred to a vat later. Each Promise starts out in the "unresolved" state, then later transitions irrevocably to the "resolved" state. Liveslots frequently (but not always) pays attention to this transition by calling `then` to attach fulfillment/rejection settlement callbacks. To handle resolution cycles, liveslots remembers the resolution of old promises in a `WeakMap` for as long as the Promise exists. Consequently, for liveslots' purposes, every Promise is either resolved (a callback has fired and liveslots remembers the settlement), or unresolved (liveslots has not yet seen a resolution that settles it).