Skip to content

Commit

Permalink
feat(cosmic-swingset): export swingStore kvData to vstorage
Browse files Browse the repository at this point in the history
  • Loading branch information
mhofman committed Apr 19, 2023
1 parent 37858cb commit be68431
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 2 deletions.
1 change: 1 addition & 0 deletions golang/cosmos/x/swingset/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const (
StoragePathMailbox = "mailbox"
StoragePathCustom = "published"
StoragePathBundles = "bundles"
StoragePathSwingStore = "swingStore"
)

// 2 ** 256 - 1
Expand Down
39 changes: 38 additions & 1 deletion packages/cosmic-swingset/src/chain-main.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
exportMailbox,
} from '@agoric/swingset-vat/src/devices/mailbox/mailbox.js';

import { Fail } from '@agoric/assert';
import { Fail, q } from '@agoric/assert';
import { makeSlogSender, tryFlushSlogSender } from '@agoric/telemetry';

import {
Expand Down Expand Up @@ -243,6 +243,42 @@ export default async function main(progname, args, { env, homedir, agcc }) {
commit: actionQueueRawStorage.commit,
abort: actionQueueRawStorage.abort,
});
/**
* Callback invoked during SwingSet execution when new "export data" is
* generated by swingStore to be saved in the host's verified DB. In our
* case, we publish these entries in vstorage under a dedicated prefix.
* This effectively shadows the "export data" of the swingStore so that
* processes like state-sync can generate a verified "root of trust" to
* restore SwingSet state.
*
* @param {ReadonlyArray<[path: string, value?: string | null]>} updates
*/
const swingStoreExportCallback = async updates => {
// Allow I/O to proceed first
await waitUntilQuiescent();

const entries = updates.map(([key, value]) => {
if (typeof key !== 'string') {
throw Fail`Unexpected swingStore exported key ${q(key)}`;
}
const path = `${STORAGE_PATH.SWING_STORE}.${key}`;
if (value == null) {
return [path];
}
if (typeof value !== 'string') {
throw Fail`Unexpected ${typeof value} value for swingStore exported key ${q(
key,
)}`;
}
return [path, value];
});
sendToChain(
stringify({
method: 'setWithoutNotify',
args: entries,
}),
);
};
function setActivityhash(activityhash) {
const entry = [STORAGE_PATH.ACTIVITYHASH, activityhash];
const msg = stringify({
Expand Down Expand Up @@ -399,6 +435,7 @@ export default async function main(progname, args, { env, homedir, agcc }) {
verboseBlocks: true,
metricsProvider,
slogSender,
swingStoreExportCallback,
swingStoreTraceFile,
keepSnapshots,
afterCommitCallback,
Expand Down
19 changes: 18 additions & 1 deletion packages/cosmic-swingset/src/launch-chain.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { waitUntilQuiescent } from '@agoric/swingset-vat/src/lib-nodejs/waitUnti
import { assert, Fail } from '@agoric/assert';
import { openSwingStore } from '@agoric/swing-store';
import { BridgeId as BRIDGE_ID } from '@agoric/internal';
import { makeWithQueue } from '@agoric/internal/src/queue.js';
import * as ActionType from '@agoric/internal/src/action-types.js';

import { extractCoreProposalBundles } from '@agoric/deploy-script-support/src/extract-proposal.js';
Expand Down Expand Up @@ -226,13 +227,28 @@ export async function launch({
metricsProvider = makeDefaultMeterProvider(),
slogSender,
swingStoreTraceFile,
swingStoreExportCallback,
keepSnapshots,
afterCommitCallback = async () => ({}),
}) {
console.info('Launching SwingSet kernel');

// The swingStore's exportCallback is synchronous, however we allow the
// callback provided to launch-chain to be asynchronous. The callbacks are
// invoked sequentially like if they were awaited, and the block manager
// synchronizes before finishing END_BLOCK
let pendingSwingStoreExport = Promise.resolve();
const swingStoreExportCallbackWithQueue =
swingStoreExportCallback && makeWithQueue()(swingStoreExportCallback);
const swingStoreExportSyncCallback =
swingStoreExportCallback &&
(updates => {
pendingSwingStoreExport = swingStoreExportCallbackWithQueue(updates);
});

const { kernelStorage, hostStorage } = openSwingStore(kernelStateDBDir, {
traceFile: swingStoreTraceFile,
exportCallback: swingStoreExportSyncCallback,
keepSnapshots,
});
const { kvStore, commit } = hostStorage;
Expand Down Expand Up @@ -647,6 +663,7 @@ export async function launch({
blockHeight,
runNum,
});
await pendingSwingStoreExport;
controller.writeSlogObject({
type: 'cosmic-swingset-bootstrap-block-finish',
blockTime,
Expand Down Expand Up @@ -758,7 +775,7 @@ export async function launch({

// We write out our on-chain state as a number of chainSends.
const start = Date.now();
await saveChainState();
await Promise.all([saveChainState(), pendingSwingStoreExport]);
chainTime = Date.now() - start;

// Advance our saved state variables.
Expand Down
1 change: 1 addition & 0 deletions packages/internal/src/chain-storage-paths.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export const EGRESS = 'egress';
export const MAILBOX = 'mailbox';
export const BUNDLES = 'bundles';
export const CUSTOM = 'published';
export const SWING_STORE = 'swingStore';

0 comments on commit be68431

Please sign in to comment.