@agoric/cosmos 0.34.2-orchestration-dev-096c4e8.0 → 0.34.2-other-dev-3eb1a1d.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/MAINTAINERS.md +3 -0
  2. package/Makefile +38 -34
  3. package/ante/ante.go +1 -4
  4. package/ante/inbound_test.go +2 -2
  5. package/app/app.go +198 -137
  6. package/app/upgrade.go +248 -0
  7. package/cmd/agd/agvm.go +3 -3
  8. package/cmd/agd/find_binary.go +2 -2
  9. package/cmd/agd/main.go +9 -10
  10. package/cmd/libdaemon/main.go +13 -13
  11. package/daemon/cmd/root.go +235 -92
  12. package/daemon/cmd/root_test.go +189 -1
  13. package/daemon/main.go +3 -2
  14. package/git-revision.txt +1 -1
  15. package/go.mod +14 -11
  16. package/go.sum +20 -19
  17. package/index.cjs +1 -1
  18. package/package.json +4 -3
  19. package/proto/agoric/swingset/genesis.proto +4 -0
  20. package/proto/agoric/swingset/swingset.proto +26 -1
  21. package/proto/agoric/vbank/vbank.proto +7 -0
  22. package/proto/agoric/vtransfer/genesis.proto +18 -0
  23. package/scripts/protocgen.sh +7 -8
  24. package/types/kv_entry_helpers.go +42 -0
  25. package/upgradegaia.sh +8 -8
  26. package/util/util.go +21 -0
  27. package/vm/action.go +1 -1
  28. package/vm/client.go +15 -13
  29. package/vm/client_test.go +34 -36
  30. package/vm/controller.go +3 -38
  31. package/vm/core_proposals.go +22 -2
  32. package/vm/proto_json.go +38 -0
  33. package/vm/proto_json_test.go +103 -0
  34. package/vm/server.go +106 -5
  35. package/x/swingset/alias.go +2 -0
  36. package/x/swingset/config.go +234 -0
  37. package/x/swingset/genesis.go +178 -40
  38. package/x/swingset/keeper/extension_snapshotter.go +2 -2
  39. package/x/swingset/keeper/keeper.go +24 -27
  40. package/x/swingset/keeper/swing_store_exports_handler.go +14 -3
  41. package/x/swingset/keeper/test_utils.go +16 -0
  42. package/x/swingset/module.go +24 -9
  43. package/x/swingset/testing/queue.go +17 -0
  44. package/x/swingset/types/default-params.go +31 -5
  45. package/x/swingset/types/expected_keepers.go +2 -2
  46. package/x/swingset/types/genesis.pb.go +78 -25
  47. package/x/swingset/types/msgs.go +53 -12
  48. package/x/swingset/types/params.go +53 -43
  49. package/x/swingset/types/params_test.go +75 -9
  50. package/x/swingset/types/swingset.pb.go +387 -57
  51. package/x/vbank/README.md +6 -1
  52. package/x/vbank/genesis.go +0 -2
  53. package/x/vbank/keeper/keeper.go +4 -9
  54. package/x/vbank/keeper/migrations.go +30 -0
  55. package/x/vbank/module.go +8 -7
  56. package/x/vbank/types/key.go +3 -3
  57. package/x/vbank/types/msgs.go +0 -12
  58. package/x/vbank/types/params.go +43 -2
  59. package/x/vbank/types/vbank.pb.go +105 -36
  60. package/x/vbank/vbank.go +8 -13
  61. package/x/vbank/vbank_test.go +14 -9
  62. package/x/vibc/alias.go +1 -1
  63. package/x/vibc/module.go +2 -7
  64. package/x/vibc/types/ibc_module.go +9 -3
  65. package/x/vibc/types/receiver.go +17 -7
  66. package/x/vlocalchain/handler.go +2 -1
  67. package/x/vlocalchain/keeper/keeper.go +24 -8
  68. package/x/vlocalchain/keeper/keeper_test.go +65 -1
  69. package/x/vlocalchain/types/expected_keepers.go +12 -0
  70. package/x/vlocalchain/vlocalchain.go +27 -22
  71. package/x/vlocalchain/vlocalchain_test.go +163 -8
  72. package/x/vstorage/keeper/grpc_query.go +0 -1
  73. package/x/vstorage/keeper/keeper.go +9 -17
  74. package/x/vstorage/module.go +0 -5
  75. package/x/vstorage/testing/queue.go +28 -0
  76. package/x/vtransfer/alias.go +13 -0
  77. package/x/vtransfer/genesis.go +39 -0
  78. package/x/vtransfer/genesis_test.go +12 -0
  79. package/x/vtransfer/handler.go +20 -0
  80. package/x/vtransfer/ibc_middleware.go +186 -0
  81. package/x/vtransfer/ibc_middleware_test.go +449 -0
  82. package/x/vtransfer/keeper/keeper.go +282 -0
  83. package/x/vtransfer/module.go +124 -0
  84. package/x/vtransfer/types/baseaddr.go +156 -0
  85. package/x/vtransfer/types/baseaddr_test.go +167 -0
  86. package/x/vtransfer/types/expected_keepers.go +38 -0
  87. package/x/vtransfer/types/genesis.pb.go +328 -0
  88. package/x/vtransfer/types/key.go +9 -0
  89. package/x/vtransfer/types/msgs.go +9 -0
  90. package/ante/fee.go +0 -97
@@ -0,0 +1,234 @@
1
+ package swingset
2
+
3
+ import (
4
+ "fmt"
5
+ "path/filepath"
6
+
7
+ "github.com/spf13/viper"
8
+
9
+ "github.com/cosmos/cosmos-sdk/client/flags"
10
+ pruningtypes "github.com/cosmos/cosmos-sdk/pruning/types"
11
+ serverconfig "github.com/cosmos/cosmos-sdk/server/config"
12
+ servertypes "github.com/cosmos/cosmos-sdk/server/types"
13
+
14
+ "github.com/Agoric/agoric-sdk/golang/cosmos/util"
15
+ )
16
+
17
+ const (
18
+ ConfigPrefix = "swingset"
19
+ FlagSlogfile = ConfigPrefix + ".slogfile"
20
+ FlagVatSnapshotArchiveDir = ConfigPrefix + ".vat-snapshot-archive-dir"
21
+ FlagVatTranscriptArchiveDir = ConfigPrefix + ".vat-transcript-archive-dir"
22
+
23
+ SnapshotRetentionOptionDebug = "debug"
24
+ SnapshotRetentionOptionOperational = "operational"
25
+
26
+ TranscriptRetentionOptionArchival = "archival"
27
+ TranscriptRetentionOptionOperational = "operational"
28
+ )
29
+
30
+ var snapshotRetentionValues []string = []string{
31
+ SnapshotRetentionOptionDebug,
32
+ SnapshotRetentionOptionOperational,
33
+ }
34
+
35
+ var transcriptRetentionValues []string = []string{
36
+ TranscriptRetentionOptionArchival,
37
+ TranscriptRetentionOptionOperational,
38
+ }
39
+
40
+ // DefaultConfigTemplate defines a default TOML configuration section for the SwingSet VM.
41
+ // Values are pulled from a "Swingset" property, in accord with CustomAppConfig from
42
+ // ../../daemon/cmd/root.go.
43
+ // See https://github.com/cosmos/cosmos-sdk/issues/20097 for auto-synchronization ideas.
44
+ const DefaultConfigTemplate = `
45
+ ###############################################################################
46
+ ### SwingSet Configuration ###
47
+ ###############################################################################
48
+
49
+ [swingset]
50
+ # The path at which a SwingSet log "slog" file should be written.
51
+ # If relative, it is interpreted against the application home directory
52
+ # (e.g., ~/.agoric).
53
+ # May be overridden by a SLOGFILE environment variable, which if relative is
54
+ # interpreted against the working directory.
55
+ slogfile = "{{ .Swingset.SlogFile }}"
56
+
57
+ # The maximum number of vats that the SwingSet kernel will bring online. A lower number
58
+ # requires less memory but may have a negative performance impact if vats need to
59
+ # be frequently paged out to remain under this limit.
60
+ max-vats-online = {{ .Swingset.MaxVatsOnline }}
61
+
62
+ # Retention of vat snapshots, with values analogous to those of export
63
+ # 'artifactMode' (cf.
64
+ # https://github.com/Agoric/agoric-sdk/blob/master/packages/swing-store/docs/data-export.md#optional--historical-data ).
65
+ # * "debug": keep all snapshots
66
+ # * "operational": keep only the last snapshot
67
+ vat-snapshot-retention = "{{ .Swingset.VatSnapshotRetention }}"
68
+
69
+ # Retention of vat transcript spans, with values analogous to those of export
70
+ # 'artifactMode' (cf.
71
+ # https://github.com/Agoric/agoric-sdk/blob/master/packages/swing-store/docs/data-export.md#optional--historical-data ).
72
+ # * "archival": keep all transcript spans
73
+ # * "operational": keep only necessary transcript spans (i.e., since the
74
+ # last snapshot of their vat)
75
+ # * "default": determined by 'pruning' ("archival" if 'pruning' is "nothing",
76
+ # otherwise "operational")
77
+ vat-transcript-retention = "{{ .Swingset.VatTranscriptRetention }}"
78
+
79
+ # Archival of gzipped vat snapshots.
80
+ vat-snapshot-archive-dir = "{{ .Swingset.VatSnapshotArchiveDir }}"
81
+
82
+ # Archival of historical (i.e., closed) vat transcript spans to gzipped files.
83
+ vat-transcript-archive-dir = "{{ .Swingset.VatTranscriptArchiveDir }}"
84
+ `
85
+
86
+ // SwingsetConfig defines configuration for the SwingSet VM.
87
+ // "mapstructure" tag data is used to direct reads from app.toml;
88
+ // "json" tag data is used to populate init messages for the VM.
89
+ // This should be kept in sync with SwingsetConfigShape in
90
+ // ../../../../packages/cosmic-swingset/src/chain-main.js.
91
+ // TODO: Consider extensions from docs/env.md.
92
+ type SwingsetConfig struct {
93
+ // SlogFile is the path at which a SwingSet log "slog" file should be written.
94
+ // If relative, it is interpreted against the application home directory
95
+ SlogFile string `mapstructure:"slogfile" json:"slogfile,omitempty"`
96
+
97
+ // MaxVatsOnline is the maximum number of vats that the SwingSet kernel will have online
98
+ // at any given time.
99
+ MaxVatsOnline int `mapstructure:"max-vats-online" json:"maxVatsOnline,omitempty"`
100
+
101
+ // VatSnapshotRetention controls retention of vat snapshots,
102
+ // and has values analogous to those of export `artifactMode` (cf.
103
+ // ../../../../packages/swing-store/docs/data-export.md#optional--historical-data ).
104
+ // * "debug": keep all snapshots
105
+ // * "operational": keep only the last snapshot
106
+ VatSnapshotRetention string `mapstructure:"vat-snapshot-retention" json:"vatSnapshotRetention,omitempty"`
107
+
108
+ // VatTranscriptRetention controls retention of vat transcript spans,
109
+ // and has values analogous to those of export `artifactMode` (cf.
110
+ // ../../../../packages/swing-store/docs/data-export.md#optional--historical-data ).
111
+ // * "archival": keep all transcript spans
112
+ // * "operational": keep only necessary transcript spans (i.e., since the
113
+ // last snapshot of their vat)
114
+ // * "default": determined by `pruning` ("archival" if `pruning` is
115
+ // "nothing", otherwise "operational")
116
+ VatTranscriptRetention string `mapstructure:"vat-transcript-retention" json:"vatTranscriptRetention,omitempty"`
117
+
118
+ // VatSnapshotArchiveDir controls archival of gzipped vat snapshots.
119
+ VatSnapshotArchiveDir string `mapstructure:"vat-snapshot-archive-dir" json:"vatSnapshotArchiveDir,omitempty"`
120
+
121
+ // VatTranscriptArchiveDir controls archival of historical (i.e., closed) vat
122
+ // transcript spans to gzipped files.
123
+ VatTranscriptArchiveDir string `mapstructure:"vat-transcript-archive-dir" json:"vatTranscriptArchiveDir,omitempty"`
124
+ }
125
+
126
+ var DefaultSwingsetConfig = SwingsetConfig{
127
+ SlogFile: "",
128
+ MaxVatsOnline: 50,
129
+ VatSnapshotRetention: "operational",
130
+ VatTranscriptRetention: "default",
131
+ }
132
+
133
+ func SwingsetConfigFromViper(resolvedConfig servertypes.AppOptions) (*SwingsetConfig, error) {
134
+ v, ok := resolvedConfig.(*viper.Viper)
135
+ if !ok {
136
+ // Tolerate an apparently empty configuration such as
137
+ // cosmos/cosmos-sdk/simapp EmptyAppOptions, but otherwise require viper.
138
+ if resolvedConfig.Get(flags.FlagHome) != nil {
139
+ return nil, fmt.Errorf("expected an instance of viper!")
140
+ }
141
+ }
142
+ if v == nil {
143
+ return nil, nil
144
+ }
145
+ v.MustBindEnv(FlagSlogfile, "SLOGFILE")
146
+ // See CustomAppConfig in ../../daemon/cmd/root.go.
147
+ type ExtendedConfig struct {
148
+ serverconfig.Config `mapstructure:",squash"`
149
+ Swingset SwingsetConfig `mapstructure:"swingset"`
150
+ }
151
+ extendedConfig := ExtendedConfig{}
152
+ if err := v.Unmarshal(&extendedConfig); err != nil {
153
+ return nil, err
154
+ }
155
+ ssConfig := &extendedConfig.Swingset
156
+
157
+ // Validate vat snapshot retention only if non-empty (because otherwise it
158
+ // it will be omitted, leaving the VM to apply its own defaults).
159
+ if ssConfig.VatSnapshotRetention != "" {
160
+ if util.IndexOf(snapshotRetentionValues, ssConfig.VatSnapshotRetention) == -1 {
161
+ err := fmt.Errorf(
162
+ "value for vat-snapshot-retention must be in %q",
163
+ snapshotRetentionValues,
164
+ )
165
+ return nil, err
166
+ }
167
+ }
168
+
169
+ // Default/validate vat transcript retention.
170
+ if ssConfig.VatTranscriptRetention == "" || ssConfig.VatTranscriptRetention == "default" {
171
+ if extendedConfig.Pruning == pruningtypes.PruningOptionNothing {
172
+ ssConfig.VatTranscriptRetention = TranscriptRetentionOptionArchival
173
+ } else {
174
+ ssConfig.VatTranscriptRetention = TranscriptRetentionOptionOperational
175
+ }
176
+ }
177
+ if util.IndexOf(transcriptRetentionValues, ssConfig.VatTranscriptRetention) == -1 {
178
+ valuesCopy := append([]string{}, transcriptRetentionValues...)
179
+ err := fmt.Errorf(
180
+ "value for vat-transcript-retention must be in %q",
181
+ append(valuesCopy, "default"),
182
+ )
183
+ return nil, err
184
+ }
185
+
186
+ // Interpret relative paths from config files against the application home
187
+ // directory and from other sources (e.g. env vars) against the current
188
+ // working directory.
189
+ var fileOnlyViper *viper.Viper
190
+ resolvePath := func(path, configKey string) (string, error) {
191
+ if path == "" || filepath.IsAbs(path) {
192
+ return path, nil
193
+ }
194
+ if v.InConfig(configKey) {
195
+ if fileOnlyViper == nil {
196
+ var err error
197
+ fileOnlyViper, err = util.NewFileOnlyViper(v)
198
+ if err != nil {
199
+ return "", err
200
+ }
201
+ }
202
+ pathFromFile := fileOnlyViper.GetString(configKey)
203
+ if path == pathFromFile {
204
+ homePath := viper.GetString(flags.FlagHome)
205
+ if homePath == "" {
206
+ return "", fmt.Errorf("cannot resolve path against empty application home")
207
+ }
208
+ absHomePath, err := filepath.Abs(homePath)
209
+ return filepath.Join(absHomePath, path), err
210
+ }
211
+ }
212
+ return filepath.Abs(path)
213
+ }
214
+
215
+ resolvedSlogFile, err := resolvePath(ssConfig.SlogFile, FlagSlogfile)
216
+ if err != nil {
217
+ return nil, err
218
+ }
219
+ ssConfig.SlogFile = resolvedSlogFile
220
+
221
+ resolvedSnapshotDir, err := resolvePath(ssConfig.VatSnapshotArchiveDir, FlagVatSnapshotArchiveDir)
222
+ if err != nil {
223
+ return nil, err
224
+ }
225
+ ssConfig.VatSnapshotArchiveDir = resolvedSnapshotDir
226
+
227
+ resolvedTranscriptDir, err := resolvePath(ssConfig.VatTranscriptArchiveDir, FlagVatTranscriptArchiveDir)
228
+ if err != nil {
229
+ return nil, err
230
+ }
231
+ ssConfig.VatTranscriptArchiveDir = resolvedTranscriptDir
232
+
233
+ return ssConfig, nil
234
+ }
@@ -1,8 +1,14 @@
1
1
  package swingset
2
2
 
3
3
  import (
4
- // "os"
4
+ "bytes"
5
+ "crypto/sha256"
6
+ "encoding/hex"
7
+ "encoding/json"
5
8
  "fmt"
9
+ "hash"
10
+ "io"
11
+ "strings"
6
12
 
7
13
  agoric "github.com/Agoric/agoric-sdk/golang/cosmos/types"
8
14
  "github.com/Agoric/agoric-sdk/golang/cosmos/x/swingset/keeper"
@@ -10,6 +16,20 @@ import (
10
16
  sdk "github.com/cosmos/cosmos-sdk/types"
11
17
  )
12
18
 
19
+ const (
20
+ // SwingStoreExportModeSkip indicates swing store data should be
21
+ // excluded from the export.
22
+ SwingStoreExportModeSkip = "skip"
23
+
24
+ // SwingStoreExportModeOperational (default) indicates export should
25
+ // have the minimal set of artifacts needed to operate a node.
26
+ SwingStoreExportModeOperational = "operational"
27
+
28
+ // SwingStoreExportModeDebug indicates export should have the maximal
29
+ // set of artifacts available in the JS swing-store.
30
+ SwingStoreExportModeDebug = "debug"
31
+ )
32
+
13
33
  func ValidateGenesis(data *types.GenesisState) error {
14
34
  if data == nil {
15
35
  return fmt.Errorf("swingset genesis data cannot be nil")
@@ -35,8 +55,10 @@ func InitGenesis(ctx sdk.Context, k Keeper, swingStoreExportsHandler *SwingStore
35
55
  k.SetState(ctx, data.GetState())
36
56
 
37
57
  swingStoreExportData := data.GetSwingStoreExportData()
38
- if len(swingStoreExportData) == 0 {
58
+ if len(swingStoreExportData) == 0 && data.SwingStoreExportDataHash == "" {
39
59
  return true
60
+ } else if data.SwingStoreExportDataHash != "" && len(swingStoreExportData) > 0 {
61
+ panic("Swingset genesis state cannot have both export data and hash of export data")
40
62
  }
41
63
 
42
64
  artifactProvider, err := keeper.OpenSwingStoreExportDirectory(swingStoreExportDir)
@@ -46,15 +68,62 @@ func InitGenesis(ctx sdk.Context, k Keeper, swingStoreExportsHandler *SwingStore
46
68
 
47
69
  swingStore := k.GetSwingStore(ctx)
48
70
 
49
- for _, entry := range swingStoreExportData {
50
- swingStore.Set([]byte(entry.Key), []byte(entry.Value))
51
- }
52
-
53
71
  snapshotHeight := uint64(ctx.BlockHeight())
54
72
 
55
- getExportDataReader := func() (agoric.KVEntryReader, error) {
56
- exportDataIterator := swingStore.Iterator(nil, nil)
57
- return agoric.NewKVIteratorReader(exportDataIterator), nil
73
+ var getExportDataReader func() (agoric.KVEntryReader, error)
74
+
75
+ if len(swingStoreExportData) > 0 {
76
+ for _, entry := range swingStoreExportData {
77
+ swingStore.Set([]byte(entry.Key), []byte(entry.Value))
78
+ }
79
+ getExportDataReader = func() (agoric.KVEntryReader, error) {
80
+ exportDataIterator := swingStore.Iterator(nil, nil)
81
+ return agoric.NewKVIteratorReader(exportDataIterator), nil
82
+ }
83
+ } else {
84
+ hashParts := strings.SplitN(data.SwingStoreExportDataHash, ":", 2)
85
+ if len(hashParts) != 2 {
86
+ panic(fmt.Errorf("invalid swing-store export data hash %s", data.SwingStoreExportDataHash))
87
+ }
88
+ if hashParts[0] != "sha256" {
89
+ panic(fmt.Errorf("invalid swing-store export data hash algorithm %s, expected sha256", hashParts[0]))
90
+ }
91
+ sha256Hash, err := hex.DecodeString(hashParts[1])
92
+ if err != nil {
93
+ panic(err)
94
+ }
95
+ getExportDataReader = func() (agoric.KVEntryReader, error) {
96
+ kvReader, err := artifactProvider.GetExportDataReader()
97
+ if err != nil {
98
+ return nil, err
99
+ }
100
+
101
+ if kvReader == nil {
102
+ return nil, fmt.Errorf("swing-store export has no export data")
103
+ }
104
+
105
+ hasher := sha256.New()
106
+ encoder := json.NewEncoder(hasher)
107
+ encoder.SetEscapeHTML(false)
108
+
109
+ return agoric.NewKVHookingReader(kvReader, func(entry agoric.KVEntry) error {
110
+ key := []byte(entry.Key())
111
+
112
+ if !entry.HasValue() {
113
+ swingStore.Delete(key)
114
+ } else {
115
+ swingStore.Set(key, []byte(entry.StringValue()))
116
+ }
117
+
118
+ return encoder.Encode(entry)
119
+ }, func() error {
120
+ sum := hasher.Sum(nil)
121
+ if !bytes.Equal(sum, sha256Hash) {
122
+ return fmt.Errorf("swing-store data sha256sum didn't match. expected %x, got %x", sha256Hash, sum)
123
+ }
124
+ return nil
125
+ }), nil
126
+ }
58
127
  }
59
128
 
60
129
  err = swingStoreExportsHandler.RestoreExport(
@@ -64,7 +133,7 @@ func InitGenesis(ctx sdk.Context, k Keeper, swingStoreExportsHandler *SwingStore
64
133
  ReadNextArtifact: artifactProvider.ReadNextArtifact,
65
134
  },
66
135
  keeper.SwingStoreRestoreOptions{
67
- ArtifactMode: keeper.SwingStoreArtifactModeReplay,
136
+ ArtifactMode: keeper.SwingStoreArtifactModeOperational,
68
137
  ExportDataMode: keeper.SwingStoreExportDataModeAll,
69
138
  },
70
139
  )
@@ -75,50 +144,69 @@ func InitGenesis(ctx sdk.Context, k Keeper, swingStoreExportsHandler *SwingStore
75
144
  return false
76
145
  }
77
146
 
78
- func ExportGenesis(ctx sdk.Context, k Keeper, swingStoreExportsHandler *SwingStoreExportsHandler, swingStoreExportDir string) *types.GenesisState {
147
+ func ExportGenesis(
148
+ ctx sdk.Context,
149
+ k Keeper,
150
+ swingStoreExportsHandler *SwingStoreExportsHandler,
151
+ swingStoreExportDir string,
152
+ swingStoreExportMode string,
153
+ ) *types.GenesisState {
79
154
  gs := &types.GenesisState{
80
155
  Params: k.GetParams(ctx),
81
156
  State: k.GetState(ctx),
82
- SwingStoreExportData: []*types.SwingStoreExportDataEntry{},
83
- }
84
-
85
- exportDataIterator := k.GetSwingStore(ctx).Iterator(nil, nil)
86
- defer exportDataIterator.Close()
87
- for ; exportDataIterator.Valid(); exportDataIterator.Next() {
88
- entry := types.SwingStoreExportDataEntry{
89
- Key: string(exportDataIterator.Key()),
90
- Value: string(exportDataIterator.Value()),
91
- }
92
- gs.SwingStoreExportData = append(gs.SwingStoreExportData, &entry)
157
+ SwingStoreExportData: nil,
93
158
  }
94
159
 
160
+ // This will only be used in non skip mode
161
+ artifactMode := swingStoreExportMode
162
+ exportDataMode := keeper.SwingStoreExportDataModeSkip
163
+ hasher := sha256.New()
95
164
  snapshotHeight := uint64(ctx.BlockHeight())
96
165
 
97
- err := swingStoreExportsHandler.InitiateExport(
98
- // The export will fail if the export of a historical height was requested
99
- snapshotHeight,
100
- swingStoreGenesisEventHandler{exportDir: swingStoreExportDir, snapshotHeight: snapshotHeight},
101
- // The export will fail if the swing-store does not contain all replay artifacts
102
- keeper.SwingStoreExportOptions{
103
- ArtifactMode: keeper.SwingStoreArtifactModeReplay,
104
- ExportDataMode: keeper.SwingStoreExportDataModeSkip,
105
- },
106
- )
107
- if err != nil {
108
- panic(err)
166
+ if swingStoreExportMode == SwingStoreExportModeDebug {
167
+ exportDataMode = keeper.SwingStoreExportDataModeAll
168
+ snapshotHeight = 0
109
169
  }
110
170
 
111
- err = keeper.WaitUntilSwingStoreExportDone()
112
- if err != nil {
113
- panic(err)
171
+ if swingStoreExportMode != SwingStoreExportModeSkip {
172
+ eventHandler := swingStoreGenesisEventHandler{
173
+ exportDir: swingStoreExportDir,
174
+ snapshotHeight: snapshotHeight,
175
+ swingStore: k.GetSwingStore(ctx),
176
+ hasher: hasher,
177
+ exportMode: swingStoreExportMode,
178
+ }
179
+
180
+ err := swingStoreExportsHandler.InitiateExport(
181
+ // The export will fail if the export of a historical height was requested outside of debug mode
182
+ snapshotHeight,
183
+ eventHandler,
184
+ keeper.SwingStoreExportOptions{
185
+ ArtifactMode: artifactMode,
186
+ ExportDataMode: exportDataMode,
187
+ },
188
+ )
189
+ if err != nil {
190
+ panic(err)
191
+ }
192
+
193
+ err = keeper.WaitUntilSwingStoreExportDone()
194
+ if err != nil {
195
+ panic(err)
196
+ }
114
197
  }
115
198
 
199
+ gs.SwingStoreExportDataHash = fmt.Sprintf("sha256:%x", hasher.Sum(nil))
200
+
116
201
  return gs
117
202
  }
118
203
 
119
204
  type swingStoreGenesisEventHandler struct {
120
205
  exportDir string
121
206
  snapshotHeight uint64
207
+ swingStore sdk.KVStore
208
+ hasher hash.Hash
209
+ exportMode string
122
210
  }
123
211
 
124
212
  func (eventHandler swingStoreGenesisEventHandler) OnExportStarted(height uint64, retrieveSwingStoreExport func() error) error {
@@ -126,15 +214,65 @@ func (eventHandler swingStoreGenesisEventHandler) OnExportStarted(height uint64,
126
214
  }
127
215
 
128
216
  func (eventHandler swingStoreGenesisEventHandler) OnExportRetrieved(provider keeper.SwingStoreExportProvider) error {
129
- if eventHandler.snapshotHeight != provider.BlockHeight {
217
+ if eventHandler.exportMode != SwingStoreExportModeDebug && eventHandler.snapshotHeight != provider.BlockHeight {
130
218
  return fmt.Errorf("snapshot block height (%d) doesn't match requested height (%d)", provider.BlockHeight, eventHandler.snapshotHeight)
131
219
  }
132
220
 
221
+ artifactsEnded := false
222
+
133
223
  artifactsProvider := keeper.SwingStoreExportProvider{
134
224
  GetExportDataReader: func() (agoric.KVEntryReader, error) {
135
- return nil, nil
225
+ exportDataIterator := eventHandler.swingStore.Iterator(nil, nil)
226
+ kvReader := agoric.NewKVIteratorReader(exportDataIterator)
227
+ eventHandler.hasher.Reset()
228
+ encoder := json.NewEncoder(eventHandler.hasher)
229
+ encoder.SetEscapeHTML(false)
230
+
231
+ return agoric.NewKVHookingReader(kvReader, func(entry agoric.KVEntry) error {
232
+ return encoder.Encode(entry)
233
+ }, func() error {
234
+ return nil
235
+ }), nil
136
236
  },
137
- ReadNextArtifact: provider.ReadNextArtifact,
237
+ ReadNextArtifact: func() (types.SwingStoreArtifact, error) {
238
+ var (
239
+ artifact types.SwingStoreArtifact
240
+ err error
241
+ encodedExportData bytes.Buffer
242
+ )
243
+
244
+ if !artifactsEnded {
245
+ artifact, err = provider.ReadNextArtifact()
246
+ } else {
247
+ return types.SwingStoreArtifact{}, io.EOF
248
+ }
249
+
250
+ if err == io.EOF {
251
+ artifactsEnded = true
252
+ if eventHandler.exportMode == SwingStoreExportModeDebug {
253
+ exportDataReader, _ := provider.GetExportDataReader()
254
+
255
+ defer exportDataReader.Close()
256
+
257
+ err = agoric.EncodeKVEntryReaderToJsonl(
258
+ exportDataReader,
259
+ &encodedExportData,
260
+ )
261
+ if err == nil {
262
+ artifact = types.SwingStoreArtifact{
263
+ Data: encodedExportData.Bytes(),
264
+ Name: keeper.UntrustedExportDataArtifactName,
265
+ }
266
+ }
267
+ }
268
+ }
269
+
270
+ return artifact, err
271
+ },
272
+ }
273
+
274
+ if eventHandler.exportMode == SwingStoreExportModeDebug {
275
+ artifactsProvider.BlockHeight = provider.BlockHeight
138
276
  }
139
277
 
140
278
  return keeper.WriteSwingStoreExportToDirectory(artifactsProvider, eventHandler.exportDir)
@@ -125,7 +125,7 @@ func (snapshotter *ExtensionSnapshotter) InitiateSnapshot(height int64) error {
125
125
  blockHeight := uint64(height)
126
126
 
127
127
  return snapshotter.swingStoreExportsHandler.InitiateExport(blockHeight, snapshotter, SwingStoreExportOptions{
128
- ArtifactMode: SwingStoreArtifactModeReplay,
128
+ ArtifactMode: SwingStoreArtifactModeOperational,
129
129
  ExportDataMode: SwingStoreExportDataModeSkip,
130
130
  })
131
131
  }
@@ -304,6 +304,6 @@ func (snapshotter *ExtensionSnapshotter) RestoreExtension(blockHeight uint64, fo
304
304
 
305
305
  return snapshotter.swingStoreExportsHandler.RestoreExport(
306
306
  SwingStoreExportProvider{BlockHeight: blockHeight, GetExportDataReader: getExportDataReader, ReadNextArtifact: readNextArtifact},
307
- SwingStoreRestoreOptions{ArtifactMode: SwingStoreArtifactModeReplay, ExportDataMode: SwingStoreExportDataModeAll},
307
+ SwingStoreRestoreOptions{ArtifactMode: SwingStoreArtifactModeOperational, ExportDataMode: SwingStoreExportDataModeAll},
308
308
  )
309
309
  }
@@ -51,25 +51,6 @@ const (
51
51
  swingStoreKeyPrefix = "swingStore."
52
52
  )
53
53
 
54
- // Contextual information about the message source of an action on an inbound queue.
55
- // This context should be unique per inboundQueueRecord.
56
- type actionContext struct {
57
- // The block height in which the corresponding action was enqueued
58
- BlockHeight int64 `json:"blockHeight"`
59
- // The hash of the cosmos transaction that included the message
60
- // If the action didn't result from a transaction message, a substitute value
61
- // may be used. For example the VBANK_BALANCE_UPDATE actions use `x/vbank`.
62
- TxHash string `json:"txHash"`
63
- // The index of the message within the transaction. If the action didn't
64
- // result from a cosmos transaction, a number should be chosen to make the
65
- // actionContext unique. (for example a counter per block and source module).
66
- MsgIdx int `json:"msgIdx"`
67
- }
68
- type inboundQueueRecord struct {
69
- Action vm.Jsonable `json:"action"`
70
- Context actionContext `json:"context"`
71
- }
72
-
73
54
  // Keeper maintains the link to data vstorage and exposes getter/setter methods for the various parts of the state machine
74
55
  type Keeper struct {
75
56
  storeKey storetypes.StoreKey
@@ -144,7 +125,14 @@ func (k Keeper) pushAction(ctx sdk.Context, inboundQueuePath string, action vm.A
144
125
  if !txHashOk || !msgIdxOk {
145
126
  stdlog.Printf("error while extracting context for action %q\n", action)
146
127
  }
147
- record := inboundQueueRecord{Action: action, Context: actionContext{BlockHeight: ctx.BlockHeight(), TxHash: txHash, MsgIdx: msgIdx}}
128
+ record := types.InboundQueueRecord{
129
+ Action: action,
130
+ Context: types.ActionContext{
131
+ BlockHeight: ctx.BlockHeight(),
132
+ TxHash: txHash,
133
+ MsgIdx: msgIdx,
134
+ },
135
+ }
148
136
  bz, err := json.Marshal(record)
149
137
  if err != nil {
150
138
  return err
@@ -258,7 +246,10 @@ func (k Keeper) BlockingSend(ctx sdk.Context, action vm.Action) (string, error)
258
246
  }
259
247
 
260
248
  func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
261
- k.paramSpace.GetParamSet(ctx, &params)
249
+ // Note the use of "IfExists"...
250
+ // migration fills in missing data with defaults,
251
+ // so it is the only consumer that should ever see a nil pair.
252
+ k.paramSpace.GetParamSetIfExists(ctx, &params)
262
253
  return params
263
254
  }
264
255
 
@@ -316,9 +307,12 @@ func (k Keeper) SetBeansOwing(ctx sdk.Context, addr sdk.AccAddress, beans sdkmat
316
307
  // ChargeBeans charges the given address the given number of beans. It divides
317
308
  // the beans into the number to debit immediately vs. the number to store in the
318
309
  // beansOwing.
319
- func (k Keeper) ChargeBeans(ctx sdk.Context, addr sdk.AccAddress, beans sdkmath.Uint) error {
320
- beansPerUnit := k.GetBeansPerUnit(ctx)
321
-
310
+ func (k Keeper) ChargeBeans(
311
+ ctx sdk.Context,
312
+ beansPerUnit map[string]sdkmath.Uint,
313
+ addr sdk.AccAddress,
314
+ beans sdkmath.Uint,
315
+ ) error {
322
316
  wasOwing := k.GetBeansOwing(ctx, addr)
323
317
  nowOwing := wasOwing.Add(beans)
324
318
 
@@ -351,10 +345,13 @@ func (k Keeper) ChargeBeans(ctx sdk.Context, addr sdk.AccAddress, beans sdkmath.
351
345
  }
352
346
 
353
347
  // ChargeForSmartWallet charges the fee for provisioning a smart wallet.
354
- func (k Keeper) ChargeForSmartWallet(ctx sdk.Context, addr sdk.AccAddress) error {
355
- beansPerUnit := k.GetBeansPerUnit(ctx)
348
+ func (k Keeper) ChargeForSmartWallet(
349
+ ctx sdk.Context,
350
+ beansPerUnit map[string]sdkmath.Uint,
351
+ addr sdk.AccAddress,
352
+ ) error {
356
353
  beans := beansPerUnit[types.BeansPerSmartWalletProvision]
357
- err := k.ChargeBeans(ctx, addr, beans)
354
+ err := k.ChargeBeans(ctx, beansPerUnit, addr, beans)
358
355
  if err != nil {
359
356
  return err
360
357
  }
@@ -787,7 +787,18 @@ func (exportsHandler SwingStoreExportsHandler) RestoreExport(provider SwingStore
787
787
  // a jsonl-like file, before saving the export manifest linking these together.
788
788
  // The export manifest filename and overall export format is common with the JS
789
789
  // swing-store import/export logic.
790
- func WriteSwingStoreExportToDirectory(provider SwingStoreExportProvider, exportDir string) error {
790
+ func WriteSwingStoreExportToDirectory(provider SwingStoreExportProvider, exportDir string) (err error) {
791
+ handleDeferError := func(fn func() error) {
792
+ deferError := fn()
793
+ if err == nil {
794
+ err = deferError
795
+ } else if deferError != nil {
796
+ // Safe to wrap error and use detailed error info since this error
797
+ // will not go back into swingset layers
798
+ err = sdkioerrors.Wrapf(err, "deferred error %+v", deferError)
799
+ }
800
+ }
801
+
791
802
  manifest := exportManifest{
792
803
  BlockHeight: provider.BlockHeight,
793
804
  }
@@ -798,14 +809,14 @@ func WriteSwingStoreExportToDirectory(provider SwingStoreExportProvider, exportD
798
809
  }
799
810
 
800
811
  if exportDataReader != nil {
801
- defer exportDataReader.Close()
812
+ defer handleDeferError(exportDataReader.Close)
802
813
 
803
814
  manifest.Data = exportDataFilename
804
815
  exportDataFile, err := os.OpenFile(filepath.Join(exportDir, exportDataFilename), os.O_CREATE|os.O_WRONLY, exportedFilesMode)
805
816
  if err != nil {
806
817
  return err
807
818
  }
808
- defer exportDataFile.Close()
819
+ defer handleDeferError(exportDataFile.Close)
809
820
 
810
821
  err = agoric.EncodeKVEntryReaderToJsonl(exportDataReader, exportDataFile)
811
822
  if err != nil {
@@ -0,0 +1,16 @@
1
+ package keeper
2
+
3
+ import (
4
+ "testing"
5
+
6
+ "github.com/Agoric/agoric-sdk/golang/cosmos/x/vstorage"
7
+ )
8
+
9
+ // GetVstorageKeeper returns the vstorage keeper from the swingset keeper
10
+ // for testing purposes.
11
+ func GetVstorageKeeper(t *testing.T, k Keeper) vstorage.Keeper {
12
+ if t == nil {
13
+ panic("this function is reserved for testing")
14
+ }
15
+ return k.vstorageKeeper
16
+ }