@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.
- package/MAINTAINERS.md +3 -0
- package/Makefile +38 -34
- package/ante/ante.go +1 -4
- package/ante/inbound_test.go +2 -2
- package/app/app.go +198 -137
- package/app/upgrade.go +248 -0
- package/cmd/agd/agvm.go +3 -3
- package/cmd/agd/find_binary.go +2 -2
- package/cmd/agd/main.go +9 -10
- package/cmd/libdaemon/main.go +13 -13
- package/daemon/cmd/root.go +235 -92
- package/daemon/cmd/root_test.go +189 -1
- package/daemon/main.go +3 -2
- package/git-revision.txt +1 -1
- package/go.mod +14 -11
- package/go.sum +20 -19
- package/index.cjs +1 -1
- package/package.json +4 -3
- package/proto/agoric/swingset/genesis.proto +4 -0
- package/proto/agoric/swingset/swingset.proto +26 -1
- package/proto/agoric/vbank/vbank.proto +7 -0
- package/proto/agoric/vtransfer/genesis.proto +18 -0
- package/scripts/protocgen.sh +7 -8
- package/types/kv_entry_helpers.go +42 -0
- package/upgradegaia.sh +8 -8
- package/util/util.go +21 -0
- package/vm/action.go +1 -1
- package/vm/client.go +15 -13
- package/vm/client_test.go +34 -36
- package/vm/controller.go +3 -38
- package/vm/core_proposals.go +22 -2
- package/vm/proto_json.go +38 -0
- package/vm/proto_json_test.go +103 -0
- package/vm/server.go +106 -5
- package/x/swingset/alias.go +2 -0
- package/x/swingset/config.go +234 -0
- package/x/swingset/genesis.go +178 -40
- package/x/swingset/keeper/extension_snapshotter.go +2 -2
- package/x/swingset/keeper/keeper.go +24 -27
- package/x/swingset/keeper/swing_store_exports_handler.go +14 -3
- package/x/swingset/keeper/test_utils.go +16 -0
- package/x/swingset/module.go +24 -9
- package/x/swingset/testing/queue.go +17 -0
- package/x/swingset/types/default-params.go +31 -5
- package/x/swingset/types/expected_keepers.go +2 -2
- package/x/swingset/types/genesis.pb.go +78 -25
- package/x/swingset/types/msgs.go +53 -12
- package/x/swingset/types/params.go +53 -43
- package/x/swingset/types/params_test.go +75 -9
- package/x/swingset/types/swingset.pb.go +387 -57
- package/x/vbank/README.md +6 -1
- package/x/vbank/genesis.go +0 -2
- package/x/vbank/keeper/keeper.go +4 -9
- package/x/vbank/keeper/migrations.go +30 -0
- package/x/vbank/module.go +8 -7
- package/x/vbank/types/key.go +3 -3
- package/x/vbank/types/msgs.go +0 -12
- package/x/vbank/types/params.go +43 -2
- package/x/vbank/types/vbank.pb.go +105 -36
- package/x/vbank/vbank.go +8 -13
- package/x/vbank/vbank_test.go +14 -9
- package/x/vibc/alias.go +1 -1
- package/x/vibc/module.go +2 -7
- package/x/vibc/types/ibc_module.go +9 -3
- package/x/vibc/types/receiver.go +17 -7
- package/x/vlocalchain/handler.go +2 -1
- package/x/vlocalchain/keeper/keeper.go +24 -8
- package/x/vlocalchain/keeper/keeper_test.go +65 -1
- package/x/vlocalchain/types/expected_keepers.go +12 -0
- package/x/vlocalchain/vlocalchain.go +27 -22
- package/x/vlocalchain/vlocalchain_test.go +163 -8
- package/x/vstorage/keeper/grpc_query.go +0 -1
- package/x/vstorage/keeper/keeper.go +9 -17
- package/x/vstorage/module.go +0 -5
- package/x/vstorage/testing/queue.go +28 -0
- package/x/vtransfer/alias.go +13 -0
- package/x/vtransfer/genesis.go +39 -0
- package/x/vtransfer/genesis_test.go +12 -0
- package/x/vtransfer/handler.go +20 -0
- package/x/vtransfer/ibc_middleware.go +186 -0
- package/x/vtransfer/ibc_middleware_test.go +449 -0
- package/x/vtransfer/keeper/keeper.go +282 -0
- package/x/vtransfer/module.go +124 -0
- package/x/vtransfer/types/baseaddr.go +156 -0
- package/x/vtransfer/types/baseaddr_test.go +167 -0
- package/x/vtransfer/types/expected_keepers.go +38 -0
- package/x/vtransfer/types/genesis.pb.go +328 -0
- package/x/vtransfer/types/key.go +9 -0
- package/x/vtransfer/types/msgs.go +9 -0
- 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
|
+
}
|
package/x/swingset/genesis.go
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
package swingset
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
|
-
|
|
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
|
|
56
|
-
|
|
57
|
-
|
|
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.
|
|
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(
|
|
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:
|
|
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
|
-
|
|
98
|
-
|
|
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
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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 :=
|
|
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
|
-
|
|
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, ¶ms)
|
|
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(
|
|
320
|
-
|
|
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(
|
|
355
|
-
|
|
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
|
+
}
|