From 23db0f5700d11f76318b2ac6485e48373b3a7bd9 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Thu, 5 Sep 2024 12:23:20 -0400 Subject: [PATCH] feat: Add consensus-independent vat transcript span retention configuration to AG_COSMOS_INIT Ref #9174 Ref #9386 --- golang/cosmos/util/util.go | 9 +++ golang/cosmos/x/swingset/config.go | 67 +++++++++++++++++--- packages/cosmic-swingset/src/chain-main.js | 7 +- packages/cosmic-swingset/src/launch-chain.js | 2 + 4 files changed, 76 insertions(+), 9 deletions(-) diff --git a/golang/cosmos/util/util.go b/golang/cosmos/util/util.go index c23ad788a186..c2d7533a0784 100644 --- a/golang/cosmos/util/util.go +++ b/golang/cosmos/util/util.go @@ -4,6 +4,15 @@ import ( "github.com/spf13/viper" ) +func IndexOf[T comparable](a []T, x T) int { + for i, s := range a { + if s == x { + return i + } + } + return -1 +} + func NewFileOnlyViper(v1 *viper.Viper) (*viper.Viper, error) { v2 := viper.New() v2.SetConfigFile(v1.ConfigFileUsed()) diff --git a/golang/cosmos/x/swingset/config.go b/golang/cosmos/x/swingset/config.go index 3ed38a376350..3ebe9551cda6 100644 --- a/golang/cosmos/x/swingset/config.go +++ b/golang/cosmos/x/swingset/config.go @@ -7,6 +7,8 @@ import ( "github.com/spf13/viper" "github.com/cosmos/cosmos-sdk/client/flags" + pruningtypes "github.com/cosmos/cosmos-sdk/pruning/types" + serverconfig "github.com/cosmos/cosmos-sdk/server/config" servertypes "github.com/cosmos/cosmos-sdk/server/types" "github.com/Agoric/agoric-sdk/golang/cosmos/util" @@ -15,8 +17,16 @@ import ( const ( ConfigPrefix = "swingset" FlagSlogfile = ConfigPrefix + ".slogfile" + + TranscriptRetentionOptionArchival = "archival" + TranscriptRetentionOptionOperational = "operational" ) +var transcriptRetentionValues []string = []string{ + TranscriptRetentionOptionArchival, + TranscriptRetentionOptionOperational, +} + // DefaultConfigTemplate defines a default TOML configuration section for the SwingSet VM. // Values are pulled from a "Swingset" property, in accord with CustomAppConfig from // ../../daemon/cmd/root.go. @@ -38,6 +48,16 @@ slogfile = "{{ .Swingset.SlogFile }}" # requires less memory but may have a negative performance impact if vats need to # be frequently paged out to remain under this limit. max-vats-online = {{ .Swingset.MaxVatsOnline }} + +# Retention of vat transcript spans, with values analogous to those of export +# ` + "`artifactMode`" + ` (cf. +# https://github.com/Agoric/agoric-sdk/blob/master/packages/swing-store/docs/data-export.md#optional--historical-data +# * "archival": keep all transcript spans +# * "operational": keep only necessary transcript spans (i.e., since the +# last snapshot of their vat) +# * "default": determined by ` + "`pruning`" + ` ("archival" if ` + "`pruning`" + ` is +# "nothing", otherwise "operational") +vat-transcript-retention = "{{ .Swingset.VatTranscriptRetention }}" ` // SwingsetConfig defines configuration for the SwingSet VM. @@ -53,11 +73,21 @@ type SwingsetConfig struct { // MaxVatsOnline is the maximum number of vats that the SwingSet kernel will have online // at any given time. MaxVatsOnline int `mapstructure:"max-vats-online" json:"maxVatsOnline,omitempty"` + // VatTranscriptRetention controls retention of vat transcript spans, + // and has values analogous to those of export `artifactMode` (cf. + // ../../../../packages/swing-store/docs/data-export.md#optional--historical-data ). + // * "archival": keep all transcript spans + // * "operational": keep only necessary transcript spans (i.e., since the + // last snapshot of their vat) + // * "default": determined by `pruning` ("archival" if `pruning` is + // "nothing", otherwise "operational") + VatTranscriptRetention string `mapstructure:"vat-transcript-retention" json:"vatTranscriptRetention,omitempty"` } var DefaultSwingsetConfig = SwingsetConfig{ - SlogFile: "", - MaxVatsOnline: 50, + SlogFile: "", + MaxVatsOnline: 50, + VatTranscriptRetention: "default", } func SwingsetConfigFromViper(resolvedConfig servertypes.AppOptions) (*SwingsetConfig, error) { @@ -73,11 +103,32 @@ func SwingsetConfigFromViper(resolvedConfig servertypes.AppOptions) (*SwingsetCo return nil, nil } v.MustBindEnv(FlagSlogfile, "SLOGFILE") - wrapper := struct{ Swingset SwingsetConfig }{} - if err := v.Unmarshal(&wrapper); err != nil { + // See CustomAppConfig in ../../daemon/cmd/root.go. + type ExtendedConfig struct { + serverconfig.Config `mapstructure:",squash"` + Swingset SwingsetConfig `mapstructure:"swingset"` + } + extendedConfig := ExtendedConfig{} + if err := v.Unmarshal(&extendedConfig); err != nil { + return nil, err + } + ssConfig := &extendedConfig.Swingset + + // Default/validate transcript retention. + if ssConfig.VatTranscriptRetention == "" || ssConfig.VatTranscriptRetention == "default" { + if extendedConfig.Pruning == pruningtypes.PruningOptionNothing { + ssConfig.VatTranscriptRetention = TranscriptRetentionOptionArchival + } else { + ssConfig.VatTranscriptRetention = TranscriptRetentionOptionOperational + } + } + if util.IndexOf(transcriptRetentionValues, ssConfig.VatTranscriptRetention) == -1 { + err := fmt.Errorf( + "value for vat-transcript-retention must be in %q", + transcriptRetentionValues, + ) return nil, err } - config := &wrapper.Swingset // Interpret relative paths from config files against the application home // directory and from other sources (e.g. env vars) against the current @@ -108,11 +159,11 @@ func SwingsetConfigFromViper(resolvedConfig servertypes.AppOptions) (*SwingsetCo return filepath.Abs(path) } - resolvedSlogFile, err := resolvePath(config.SlogFile, FlagSlogfile) + resolvedSlogFile, err := resolvePath(ssConfig.SlogFile, FlagSlogfile) if err != nil { return nil, err } - config.SlogFile = resolvedSlogFile + ssConfig.SlogFile = resolvedSlogFile - return config, nil + return ssConfig, nil } diff --git a/packages/cosmic-swingset/src/chain-main.js b/packages/cosmic-swingset/src/chain-main.js index 523eb67a3d95..bb32233e176d 100644 --- a/packages/cosmic-swingset/src/chain-main.js +++ b/packages/cosmic-swingset/src/chain-main.js @@ -74,12 +74,14 @@ const toNumber = specimen => { * @typedef {object} CosmosSwingsetConfig * @property {string} [slogfile] * @property {number} [maxVatsOnline] + * @property {'archival' | 'operational'} [vatTranscriptRetention] */ const SwingsetConfigShape = M.splitRecord( {}, { slogfile: M.string(), maxVatsOnline: M.number(), + vatTranscriptRetention: M.or('archival', 'operational'), }, M.any(), ); @@ -308,7 +310,8 @@ export default async function main(progname, args, { env, homedir, agcc }) { /** @type {CosmosSwingsetConfig} */ const swingsetConfig = harden(initAction.resolvedConfig || {}); validateSwingsetConfig(swingsetConfig); - const { slogfile } = swingsetConfig; + const { slogfile, vatTranscriptRetention } = swingsetConfig; + const keepTranscripts = vatTranscriptRetention === 'archival'; // As a kludge, back-propagate selected configuration into environment variables. // eslint-disable-next-line dot-notation @@ -461,6 +464,7 @@ export default async function main(progname, args, { env, homedir, agcc }) { trueValue: pathResolve(stateDBDir, 'store-trace.log'), }); + // TODO: Add to SwingsetConfig (#9386) const keepSnapshots = XSNAP_KEEP_SNAPSHOTS === '1' || XSNAP_KEEP_SNAPSHOTS === 'true'; @@ -545,6 +549,7 @@ export default async function main(progname, args, { env, homedir, agcc }) { swingStoreExportCallback, swingStoreTraceFile, keepSnapshots, + keepTranscripts, afterCommitCallback, swingsetConfig, }); diff --git a/packages/cosmic-swingset/src/launch-chain.js b/packages/cosmic-swingset/src/launch-chain.js index 2fbcc1515427..e10cf93285c9 100644 --- a/packages/cosmic-swingset/src/launch-chain.js +++ b/packages/cosmic-swingset/src/launch-chain.js @@ -331,6 +331,7 @@ export async function launch({ swingStoreTraceFile, swingStoreExportCallback, keepSnapshots, + keepTranscripts, afterCommitCallback = async () => ({}), swingsetConfig, }) { @@ -373,6 +374,7 @@ export async function launch({ traceFile: swingStoreTraceFile, exportCallback: swingStoreExportSyncCallback, keepSnapshots, + keepTranscripts, }); const { kvStore, commit } = hostStorage;