@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
package/app/app.go
CHANGED
|
@@ -44,7 +44,6 @@ import (
|
|
|
44
44
|
"github.com/cosmos/cosmos-sdk/x/capability"
|
|
45
45
|
capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper"
|
|
46
46
|
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
|
|
47
|
-
crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types"
|
|
48
47
|
distr "github.com/cosmos/cosmos-sdk/x/distribution"
|
|
49
48
|
distrclient "github.com/cosmos/cosmos-sdk/x/distribution/client"
|
|
50
49
|
distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
|
|
@@ -87,14 +86,14 @@ import (
|
|
|
87
86
|
icahostkeeper "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/host/keeper"
|
|
88
87
|
icahosttypes "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/host/types"
|
|
89
88
|
icatypes "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/types"
|
|
90
|
-
"github.com/cosmos/ibc-go/v6/modules/apps/transfer"
|
|
89
|
+
ibctransfer "github.com/cosmos/ibc-go/v6/modules/apps/transfer"
|
|
91
90
|
ibctransferkeeper "github.com/cosmos/ibc-go/v6/modules/apps/transfer/keeper"
|
|
92
91
|
ibctransfertypes "github.com/cosmos/ibc-go/v6/modules/apps/transfer/types"
|
|
93
92
|
ibc "github.com/cosmos/ibc-go/v6/modules/core"
|
|
94
93
|
ibcclient "github.com/cosmos/ibc-go/v6/modules/core/02-client"
|
|
95
94
|
ibcclientclient "github.com/cosmos/ibc-go/v6/modules/core/02-client/client"
|
|
96
95
|
ibcclienttypes "github.com/cosmos/ibc-go/v6/modules/core/02-client/types"
|
|
97
|
-
|
|
96
|
+
ibcporttypes "github.com/cosmos/ibc-go/v6/modules/core/05-port/types"
|
|
98
97
|
ibchost "github.com/cosmos/ibc-go/v6/modules/core/24-host"
|
|
99
98
|
ibckeeper "github.com/cosmos/ibc-go/v6/modules/core/keeper"
|
|
100
99
|
"github.com/gorilla/mux"
|
|
@@ -111,6 +110,8 @@ import (
|
|
|
111
110
|
|
|
112
111
|
appante "github.com/Agoric/agoric-sdk/golang/cosmos/ante"
|
|
113
112
|
agorictypes "github.com/Agoric/agoric-sdk/golang/cosmos/types"
|
|
113
|
+
|
|
114
|
+
// conv "github.com/Agoric/agoric-sdk/golang/cosmos/types/conv"
|
|
114
115
|
"github.com/Agoric/agoric-sdk/golang/cosmos/vm"
|
|
115
116
|
"github.com/Agoric/agoric-sdk/golang/cosmos/x/swingset"
|
|
116
117
|
swingsetclient "github.com/Agoric/agoric-sdk/golang/cosmos/x/swingset/client"
|
|
@@ -121,11 +122,14 @@ import (
|
|
|
121
122
|
"github.com/Agoric/agoric-sdk/golang/cosmos/x/vibc"
|
|
122
123
|
"github.com/Agoric/agoric-sdk/golang/cosmos/x/vlocalchain"
|
|
123
124
|
"github.com/Agoric/agoric-sdk/golang/cosmos/x/vstorage"
|
|
125
|
+
"github.com/Agoric/agoric-sdk/golang/cosmos/x/vtransfer"
|
|
126
|
+
vtransferkeeper "github.com/Agoric/agoric-sdk/golang/cosmos/x/vtransfer/keeper"
|
|
127
|
+
testtypes "github.com/cosmos/ibc-go/v6/testing/types"
|
|
124
128
|
|
|
125
129
|
// Import the packet forward middleware
|
|
126
|
-
packetforward "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v6/
|
|
127
|
-
packetforwardkeeper "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v6/
|
|
128
|
-
packetforwardtypes "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v6/
|
|
130
|
+
packetforward "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v6/packetforward"
|
|
131
|
+
packetforwardkeeper "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v6/packetforward/keeper"
|
|
132
|
+
packetforwardtypes "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v6/packetforward/types"
|
|
129
133
|
|
|
130
134
|
// unnamed import of statik for swagger UI support
|
|
131
135
|
_ "github.com/cosmos/cosmos-sdk/client/docs/statik"
|
|
@@ -133,13 +137,22 @@ import (
|
|
|
133
137
|
|
|
134
138
|
const appName = "agoric"
|
|
135
139
|
|
|
136
|
-
|
|
137
|
-
//
|
|
138
|
-
//
|
|
139
|
-
// value is
|
|
140
|
-
//
|
|
141
|
-
//
|
|
142
|
-
|
|
140
|
+
const (
|
|
141
|
+
// FlagSwingStoreExportDir defines the config flag used to specify where a
|
|
142
|
+
// genesis swing-store export is expected. For start from genesis, the default
|
|
143
|
+
// value is config/swing-store in the home directory. For genesis export, the
|
|
144
|
+
// value is always a "swing-store" directory sibling to the exported
|
|
145
|
+
// genesis.json file.
|
|
146
|
+
// TODO: document this flag in config, likely alongside the genesis path
|
|
147
|
+
FlagSwingStoreExportDir = "swing-store-export-dir"
|
|
148
|
+
// FlagSwingStoreExportMode defines the export mode for the swing store
|
|
149
|
+
// Alongside the default mode `operational`, there are two other modes
|
|
150
|
+
//
|
|
151
|
+
// 1- `skip` mode will skip the swing store export altogether
|
|
152
|
+
//
|
|
153
|
+
// 2- `debug` mode will export all the available store
|
|
154
|
+
FlagSwingStoreExportMode = "swing-store-export-mode"
|
|
155
|
+
)
|
|
143
156
|
|
|
144
157
|
var (
|
|
145
158
|
// DefaultNodeHome default home directories for the application daemon
|
|
@@ -172,7 +185,7 @@ var (
|
|
|
172
185
|
ibc.AppModuleBasic{},
|
|
173
186
|
upgrade.AppModuleBasic{},
|
|
174
187
|
evidence.AppModuleBasic{},
|
|
175
|
-
|
|
188
|
+
ibctransfer.AppModuleBasic{},
|
|
176
189
|
vesting.AppModuleBasic{},
|
|
177
190
|
ica.AppModuleBasic{},
|
|
178
191
|
packetforward.AppModuleBasic{},
|
|
@@ -180,6 +193,7 @@ var (
|
|
|
180
193
|
vstorage.AppModuleBasic{},
|
|
181
194
|
vibc.AppModuleBasic{},
|
|
182
195
|
vbank.AppModuleBasic{},
|
|
196
|
+
vtransfer.AppModuleBasic{},
|
|
183
197
|
)
|
|
184
198
|
|
|
185
199
|
// module account permissions
|
|
@@ -209,6 +223,7 @@ var (
|
|
|
209
223
|
// capabilities aren't needed for testing.
|
|
210
224
|
type GaiaApp struct { // nolint: golint
|
|
211
225
|
*baseapp.BaseApp
|
|
226
|
+
resolvedConfig servertypes.AppOptions
|
|
212
227
|
legacyAmino *codec.LegacyAmino
|
|
213
228
|
appCodec codec.Codec
|
|
214
229
|
interfaceRegistry types.InterfaceRegistry
|
|
@@ -220,6 +235,7 @@ type GaiaApp struct { // nolint: golint
|
|
|
220
235
|
vibcPort int
|
|
221
236
|
vstoragePort int
|
|
222
237
|
vlocalchainPort int
|
|
238
|
+
vtransferPort int
|
|
223
239
|
|
|
224
240
|
upgradeDetails *upgradeDetails
|
|
225
241
|
|
|
@@ -230,6 +246,9 @@ type GaiaApp struct { // nolint: golint
|
|
|
230
246
|
tkeys map[string]*storetypes.TransientStoreKey
|
|
231
247
|
memKeys map[string]*storetypes.MemoryStoreKey
|
|
232
248
|
|
|
249
|
+
// manage communication from the VM to the ABCI app
|
|
250
|
+
AgdServer *vm.AgdServer
|
|
251
|
+
|
|
233
252
|
// keepers
|
|
234
253
|
AccountKeeper authkeeper.AccountKeeper
|
|
235
254
|
BankKeeper bankkeeper.Keeper
|
|
@@ -257,6 +276,7 @@ type GaiaApp struct { // nolint: golint
|
|
|
257
276
|
VibcKeeper vibc.Keeper
|
|
258
277
|
VbankKeeper vbank.Keeper
|
|
259
278
|
VlocalchainKeeper vlocalchain.Keeper
|
|
279
|
+
VtransferKeeper vtransferkeeper.Keeper
|
|
260
280
|
|
|
261
281
|
// make scoped keepers public for test purposes
|
|
262
282
|
ScopedIBCKeeper capabilitykeeper.ScopedKeeper
|
|
@@ -293,21 +313,29 @@ func NewGaiaApp(
|
|
|
293
313
|
appOpts servertypes.AppOptions,
|
|
294
314
|
baseAppOptions ...func(*baseapp.BaseApp),
|
|
295
315
|
) *GaiaApp {
|
|
296
|
-
defaultController
|
|
297
|
-
fmt.
|
|
298
|
-
return "", nil
|
|
316
|
+
var defaultController vm.Sender = func(ctx context.Context, needReply bool, jsonRequest string) (jsonReply string, err error) {
|
|
317
|
+
return "", fmt.Errorf("unexpected VM upcall with no controller: %s", jsonRequest)
|
|
299
318
|
}
|
|
300
319
|
return NewAgoricApp(
|
|
301
|
-
defaultController,
|
|
320
|
+
defaultController, vm.NewAgdServer(),
|
|
302
321
|
logger, db, traceStore, loadLatest, skipUpgradeHeights,
|
|
303
322
|
homePath, invCheckPeriod, encodingConfig, appOpts, baseAppOptions...,
|
|
304
323
|
)
|
|
305
324
|
}
|
|
306
325
|
|
|
307
326
|
func NewAgoricApp(
|
|
308
|
-
sendToController
|
|
309
|
-
|
|
310
|
-
|
|
327
|
+
sendToController vm.Sender,
|
|
328
|
+
agdServer *vm.AgdServer,
|
|
329
|
+
logger log.Logger,
|
|
330
|
+
db dbm.DB,
|
|
331
|
+
traceStore io.Writer,
|
|
332
|
+
loadLatest bool,
|
|
333
|
+
skipUpgradeHeights map[int64]bool,
|
|
334
|
+
homePath string,
|
|
335
|
+
invCheckPeriod uint,
|
|
336
|
+
encodingConfig gaiaappparams.EncodingConfig,
|
|
337
|
+
appOpts servertypes.AppOptions,
|
|
338
|
+
baseAppOptions ...func(*baseapp.BaseApp),
|
|
311
339
|
) *GaiaApp {
|
|
312
340
|
appCodec := encodingConfig.Marshaler
|
|
313
341
|
legacyAmino := encodingConfig.Amino
|
|
@@ -324,13 +352,16 @@ func NewAgoricApp(
|
|
|
324
352
|
govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey,
|
|
325
353
|
evidencetypes.StoreKey, ibctransfertypes.StoreKey, packetforwardtypes.StoreKey,
|
|
326
354
|
capabilitytypes.StoreKey, feegrant.StoreKey, authzkeeper.StoreKey, icahosttypes.StoreKey,
|
|
327
|
-
swingset.StoreKey, vstorage.StoreKey, vibc.StoreKey,
|
|
355
|
+
swingset.StoreKey, vstorage.StoreKey, vibc.StoreKey,
|
|
356
|
+
vlocalchain.StoreKey, vtransfer.StoreKey, vbank.StoreKey,
|
|
328
357
|
)
|
|
329
358
|
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey)
|
|
330
359
|
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
|
|
331
360
|
|
|
332
361
|
app := &GaiaApp{
|
|
333
362
|
BaseApp: bApp,
|
|
363
|
+
AgdServer: agdServer,
|
|
364
|
+
resolvedConfig: appOpts,
|
|
334
365
|
legacyAmino: legacyAmino,
|
|
335
366
|
appCodec: appCodec,
|
|
336
367
|
interfaceRegistry: interfaceRegistry,
|
|
@@ -446,11 +477,11 @@ func NewAgoricApp(
|
|
|
446
477
|
)
|
|
447
478
|
|
|
448
479
|
// This function is tricky to get right, so we build it ourselves.
|
|
449
|
-
callToController := func(ctx sdk.Context,
|
|
480
|
+
callToController := func(ctx sdk.Context, jsonRequest string) (jsonReply string, err error) {
|
|
450
481
|
app.CheckControllerInited(true)
|
|
451
482
|
// We use SwingSet-level metering to charge the user for the call.
|
|
452
|
-
defer
|
|
453
|
-
return sendToController(sdk.WrapSDKContext(ctx), true,
|
|
483
|
+
defer app.AgdServer.SetControllerContext(ctx)()
|
|
484
|
+
return sendToController(sdk.WrapSDKContext(ctx), true, jsonRequest)
|
|
454
485
|
}
|
|
455
486
|
|
|
456
487
|
setBootstrapNeeded := func() {
|
|
@@ -460,7 +491,7 @@ func NewAgoricApp(
|
|
|
460
491
|
app.VstorageKeeper = vstorage.NewKeeper(
|
|
461
492
|
keys[vstorage.StoreKey],
|
|
462
493
|
)
|
|
463
|
-
app.vstoragePort =
|
|
494
|
+
app.vstoragePort = app.AgdServer.MustRegisterPortHandler("vstorage", vstorage.NewStorageHandler(app.VstorageKeeper))
|
|
464
495
|
|
|
465
496
|
// The SwingSetKeeper is the Keeper from the SwingSet module
|
|
466
497
|
app.SwingSetKeeper = swingset.NewKeeper(
|
|
@@ -469,7 +500,7 @@ func NewAgoricApp(
|
|
|
469
500
|
app.VstorageKeeper, vbanktypes.ReservePoolName,
|
|
470
501
|
callToController,
|
|
471
502
|
)
|
|
472
|
-
app.swingsetPort =
|
|
503
|
+
app.swingsetPort = app.AgdServer.MustRegisterPortHandler("swingset", swingset.NewPortHandler(app.SwingSetKeeper))
|
|
473
504
|
|
|
474
505
|
app.SwingStoreExportsHandler = *swingsetkeeper.NewSwingStoreExportsHandler(
|
|
475
506
|
app.Logger(),
|
|
@@ -508,7 +539,20 @@ func NewAgoricApp(
|
|
|
508
539
|
|
|
509
540
|
vibcModule := vibc.NewAppModule(app.VibcKeeper, app.BankKeeper)
|
|
510
541
|
vibcIBCModule := vibc.NewIBCModule(app.VibcKeeper)
|
|
511
|
-
app.vibcPort =
|
|
542
|
+
app.vibcPort = app.AgdServer.MustRegisterPortHandler("vibc", vibc.NewReceiver(app.VibcKeeper))
|
|
543
|
+
|
|
544
|
+
app.VtransferKeeper = vtransferkeeper.NewKeeper(
|
|
545
|
+
appCodec,
|
|
546
|
+
keys[vtransfer.StoreKey],
|
|
547
|
+
app.VibcKeeper,
|
|
548
|
+
scopedTransferKeeper,
|
|
549
|
+
app.SwingSetKeeper.PushAction,
|
|
550
|
+
)
|
|
551
|
+
|
|
552
|
+
vtransferModule := vtransfer.NewAppModule(app.VtransferKeeper)
|
|
553
|
+
app.vtransferPort = app.AgdServer.MustRegisterPortHandler("vtransfer",
|
|
554
|
+
vibc.NewReceiver(app.VtransferKeeper),
|
|
555
|
+
)
|
|
512
556
|
|
|
513
557
|
app.VbankKeeper = vbank.NewKeeper(
|
|
514
558
|
appCodec, keys[vbank.StoreKey], app.GetSubspace(vbank.ModuleName),
|
|
@@ -516,7 +560,7 @@ func NewAgoricApp(
|
|
|
516
560
|
app.SwingSetKeeper.PushAction,
|
|
517
561
|
)
|
|
518
562
|
vbankModule := vbank.NewAppModule(app.VbankKeeper)
|
|
519
|
-
app.vbankPort =
|
|
563
|
+
app.vbankPort = app.AgdServer.MustRegisterPortHandler("bank", vbank.NewPortHandler(vbankModule, app.VbankKeeper))
|
|
520
564
|
|
|
521
565
|
// register the proposal types
|
|
522
566
|
govRouter := govv1beta1.NewRouter()
|
|
@@ -551,56 +595,64 @@ func NewAgoricApp(
|
|
|
551
595
|
app.IBCKeeper.ChannelKeeper,
|
|
552
596
|
app.DistrKeeper,
|
|
553
597
|
app.BankKeeper,
|
|
554
|
-
|
|
598
|
+
// Make vtransfer the middleware wrapper for the IBCKeeper.
|
|
599
|
+
app.VtransferKeeper.GetICS4Wrapper(),
|
|
555
600
|
)
|
|
556
601
|
|
|
557
602
|
app.TransferKeeper = ibctransferkeeper.NewKeeper(
|
|
558
603
|
appCodec,
|
|
559
604
|
keys[ibctransfertypes.StoreKey],
|
|
560
605
|
app.GetSubspace(ibctransfertypes.ModuleName),
|
|
561
|
-
app.PacketForwardKeeper,
|
|
606
|
+
app.PacketForwardKeeper, // Wire in the middleware ICS4Wrapper.
|
|
562
607
|
app.IBCKeeper.ChannelKeeper,
|
|
563
608
|
&app.IBCKeeper.PortKeeper,
|
|
564
609
|
app.AccountKeeper,
|
|
565
610
|
app.BankKeeper,
|
|
566
611
|
scopedTransferKeeper,
|
|
567
612
|
)
|
|
568
|
-
|
|
569
|
-
transferIBCModule := transfer.NewIBCModule(app.TransferKeeper)
|
|
613
|
+
|
|
570
614
|
app.PacketForwardKeeper.SetTransferKeeper(app.TransferKeeper)
|
|
571
|
-
transferPFMModule := packetforward.NewIBCMiddleware(
|
|
572
|
-
transferIBCModule,
|
|
573
|
-
app.PacketForwardKeeper,
|
|
574
|
-
0, // retries on timeout
|
|
575
|
-
packetforwardkeeper.DefaultForwardTransferPacketTimeoutTimestamp, // forward timeout
|
|
576
|
-
packetforwardkeeper.DefaultRefundTransferPacketTimeoutTimestamp, // refund timeout
|
|
577
|
-
)
|
|
578
615
|
|
|
616
|
+
// NewAppModule uses a pointer to the host keeper in case there's a need to
|
|
617
|
+
// tie a circular knot with IBC middleware before icahostkeeper.NewKeeper
|
|
618
|
+
// can be called.
|
|
579
619
|
app.ICAHostKeeper = icahostkeeper.NewKeeper(
|
|
580
620
|
appCodec, keys[icahosttypes.StoreKey],
|
|
581
621
|
app.GetSubspace(icahosttypes.SubModuleName),
|
|
582
|
-
app.
|
|
622
|
+
app.IBCKeeper.ChannelKeeper, // This is where middleware binding would happen.
|
|
583
623
|
app.IBCKeeper.ChannelKeeper,
|
|
584
624
|
&app.IBCKeeper.PortKeeper,
|
|
585
625
|
app.AccountKeeper,
|
|
586
626
|
scopedICAHostKeeper,
|
|
587
627
|
app.MsgServiceRouter(),
|
|
588
628
|
)
|
|
589
|
-
icaModule := ica.NewAppModule(nil, &app.ICAHostKeeper)
|
|
590
629
|
icaHostIBCModule := icahost.NewIBCModule(app.ICAHostKeeper)
|
|
630
|
+
icaModule := ica.NewAppModule(nil, &app.ICAHostKeeper)
|
|
631
|
+
|
|
632
|
+
ics20TransferModule := ibctransfer.NewAppModule(app.TransferKeeper)
|
|
633
|
+
|
|
634
|
+
// Create the IBC router, which maps *module names* (not PortIDs) to modules.
|
|
635
|
+
ibcRouter := ibcporttypes.NewRouter()
|
|
636
|
+
|
|
637
|
+
// Add an IBC route for the ICA Host.
|
|
638
|
+
ibcRouter.AddRoute(icahosttypes.SubModuleName, icaHostIBCModule)
|
|
591
639
|
|
|
592
|
-
//
|
|
593
|
-
|
|
594
|
-
// PortIDs) to modules.
|
|
595
|
-
ibcRouter := porttypes.NewRouter()
|
|
640
|
+
// Add an IBC route for vIBC.
|
|
641
|
+
ibcRouter.AddRoute(vibc.ModuleName, vibcIBCModule)
|
|
596
642
|
|
|
597
|
-
//
|
|
598
|
-
//
|
|
599
|
-
// -
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
643
|
+
// Add an IBC route for ICS-20 fungible token transfers, wrapping base
|
|
644
|
+
// Cosmos functionality with middleware (from the inside out, Cosmos
|
|
645
|
+
// packet-forwarding and then our own "vtransfer").
|
|
646
|
+
var ics20TransferIBCModule ibcporttypes.IBCModule = ibctransfer.NewIBCModule(app.TransferKeeper)
|
|
647
|
+
ics20TransferIBCModule = packetforward.NewIBCMiddleware(
|
|
648
|
+
ics20TransferIBCModule,
|
|
649
|
+
app.PacketForwardKeeper,
|
|
650
|
+
0, // retries on timeout
|
|
651
|
+
packetforwardkeeper.DefaultForwardTransferPacketTimeoutTimestamp, // forward timeout
|
|
652
|
+
packetforwardkeeper.DefaultRefundTransferPacketTimeoutTimestamp, // refund timeout
|
|
653
|
+
)
|
|
654
|
+
ics20TransferIBCModule = vtransfer.NewIBCMiddleware(ics20TransferIBCModule, app.VtransferKeeper)
|
|
655
|
+
ibcRouter.AddRoute(ibctransfertypes.ModuleName, ics20TransferIBCModule)
|
|
604
656
|
|
|
605
657
|
// Seal the router
|
|
606
658
|
app.IBCKeeper.SetRouter(ibcRouter)
|
|
@@ -612,8 +664,9 @@ func NewAgoricApp(
|
|
|
612
664
|
keys[vlocalchain.StoreKey],
|
|
613
665
|
app.BaseApp.MsgServiceRouter(),
|
|
614
666
|
app.BaseApp.GRPCQueryRouter(),
|
|
667
|
+
app.AccountKeeper,
|
|
615
668
|
)
|
|
616
|
-
app.vlocalchainPort =
|
|
669
|
+
app.vlocalchainPort = app.AgdServer.MustRegisterPortHandler(
|
|
617
670
|
"vlocalchain",
|
|
618
671
|
vlocalchain.NewReceiver(app.VlocalchainKeeper),
|
|
619
672
|
)
|
|
@@ -629,6 +682,7 @@ func NewAgoricApp(
|
|
|
629
682
|
app.EvidenceKeeper = *evidenceKeeper
|
|
630
683
|
|
|
631
684
|
swingStoreExportDir := cast.ToString(appOpts.Get(FlagSwingStoreExportDir))
|
|
685
|
+
swingStoreExportMode := cast.ToString(appOpts.Get(FlagSwingStoreExportMode))
|
|
632
686
|
|
|
633
687
|
// NOTE: Any module instantiated in the module manager that is later modified
|
|
634
688
|
// must be passed by reference here.
|
|
@@ -654,13 +708,21 @@ func NewAgoricApp(
|
|
|
654
708
|
authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
|
|
655
709
|
ibc.NewAppModule(app.IBCKeeper),
|
|
656
710
|
params.NewAppModule(app.ParamsKeeper),
|
|
657
|
-
|
|
711
|
+
ics20TransferModule,
|
|
658
712
|
icaModule,
|
|
659
713
|
packetforward.NewAppModule(app.PacketForwardKeeper),
|
|
660
714
|
vstorage.NewAppModule(app.VstorageKeeper),
|
|
661
|
-
swingset.NewAppModule(
|
|
715
|
+
swingset.NewAppModule(
|
|
716
|
+
app.SwingSetKeeper,
|
|
717
|
+
&app.SwingStoreExportsHandler,
|
|
718
|
+
setBootstrapNeeded,
|
|
719
|
+
app.ensureControllerInited,
|
|
720
|
+
swingStoreExportDir,
|
|
721
|
+
swingStoreExportMode,
|
|
722
|
+
),
|
|
662
723
|
vibcModule,
|
|
663
724
|
vbankModule,
|
|
725
|
+
vtransferModule,
|
|
664
726
|
)
|
|
665
727
|
|
|
666
728
|
// During begin block slashing happens after distr.BeginBlocker so that
|
|
@@ -669,11 +731,15 @@ func NewAgoricApp(
|
|
|
669
731
|
// NOTE: staking module is required if HistoricalEntries param > 0
|
|
670
732
|
// NOTE: capability module's beginblocker must come before any modules using capabilities (e.g. IBC)
|
|
671
733
|
app.mm.SetOrderBeginBlockers(
|
|
734
|
+
// Cosmos-SDK modules appear roughly in the order used by simapp and gaiad.
|
|
672
735
|
// upgrades should be run first
|
|
673
736
|
upgradetypes.ModuleName,
|
|
674
737
|
capabilitytypes.ModuleName,
|
|
738
|
+
// params influence many other modules, so it should be near the top.
|
|
739
|
+
paramstypes.ModuleName,
|
|
675
740
|
govtypes.ModuleName,
|
|
676
741
|
stakingtypes.ModuleName,
|
|
742
|
+
// ibc apps are grouped together
|
|
677
743
|
ibctransfertypes.ModuleName,
|
|
678
744
|
ibchost.ModuleName,
|
|
679
745
|
icatypes.ModuleName,
|
|
@@ -687,7 +753,6 @@ func NewAgoricApp(
|
|
|
687
753
|
evidencetypes.ModuleName,
|
|
688
754
|
authz.ModuleName,
|
|
689
755
|
feegrant.ModuleName,
|
|
690
|
-
paramstypes.ModuleName,
|
|
691
756
|
vestingtypes.ModuleName,
|
|
692
757
|
vstorage.ModuleName,
|
|
693
758
|
// This will cause the swingset controller to init if it hadn't yet, passing
|
|
@@ -695,12 +760,15 @@ func NewAgoricApp(
|
|
|
695
760
|
swingset.ModuleName,
|
|
696
761
|
vibc.ModuleName,
|
|
697
762
|
vbank.ModuleName,
|
|
763
|
+
vtransfer.ModuleName,
|
|
698
764
|
)
|
|
699
765
|
app.mm.SetOrderEndBlockers(
|
|
700
|
-
|
|
701
|
-
vbank.ModuleName,
|
|
766
|
+
// Cosmos-SDK modules appear roughly in the order used by simapp and gaiad.
|
|
702
767
|
govtypes.ModuleName,
|
|
703
768
|
stakingtypes.ModuleName,
|
|
769
|
+
// vibc is an Agoric-specific IBC app, so group it here with other IBC apps.
|
|
770
|
+
vibc.ModuleName,
|
|
771
|
+
vtransfer.ModuleName,
|
|
704
772
|
ibctransfertypes.ModuleName,
|
|
705
773
|
ibchost.ModuleName,
|
|
706
774
|
icatypes.ModuleName,
|
|
@@ -718,7 +786,11 @@ func NewAgoricApp(
|
|
|
718
786
|
paramstypes.ModuleName,
|
|
719
787
|
upgradetypes.ModuleName,
|
|
720
788
|
vestingtypes.ModuleName,
|
|
721
|
-
//
|
|
789
|
+
// Putting vbank before SwingSet VM will enable vbank to capture all event
|
|
790
|
+
// history that was produced all the other modules, and push those balance
|
|
791
|
+
// changes on the VM's actionQueue.
|
|
792
|
+
vbank.ModuleName,
|
|
793
|
+
// SwingSet VM needs to be last, for it to capture all the pushed actions.
|
|
722
794
|
swingset.ModuleName,
|
|
723
795
|
// And then vstorage, to produce SwingSet-induced events.
|
|
724
796
|
vstorage.ModuleName,
|
|
@@ -735,26 +807,28 @@ func NewAgoricApp(
|
|
|
735
807
|
capabilitytypes.ModuleName,
|
|
736
808
|
authtypes.ModuleName,
|
|
737
809
|
banktypes.ModuleName,
|
|
810
|
+
paramstypes.ModuleName,
|
|
738
811
|
distrtypes.ModuleName,
|
|
739
812
|
stakingtypes.ModuleName,
|
|
740
813
|
slashingtypes.ModuleName,
|
|
741
814
|
govtypes.ModuleName,
|
|
742
815
|
minttypes.ModuleName,
|
|
743
816
|
ibctransfertypes.ModuleName,
|
|
817
|
+
packetforwardtypes.ModuleName,
|
|
744
818
|
ibchost.ModuleName,
|
|
745
819
|
icatypes.ModuleName,
|
|
746
820
|
evidencetypes.ModuleName,
|
|
747
821
|
feegrant.ModuleName,
|
|
748
822
|
authz.ModuleName,
|
|
749
823
|
genutiltypes.ModuleName,
|
|
750
|
-
paramstypes.ModuleName,
|
|
751
824
|
upgradetypes.ModuleName,
|
|
752
825
|
vestingtypes.ModuleName,
|
|
826
|
+
// Agoric-specific modules go last since they may rely on other SDK modules.
|
|
753
827
|
vstorage.ModuleName,
|
|
754
828
|
vbank.ModuleName,
|
|
755
829
|
vibc.ModuleName,
|
|
830
|
+
vtransfer.ModuleName,
|
|
756
831
|
swingset.ModuleName,
|
|
757
|
-
packetforwardtypes.ModuleName,
|
|
758
832
|
}
|
|
759
833
|
|
|
760
834
|
app.mm.SetOrderInitGenesis(moduleOrderForGenesisAndUpgrade...)
|
|
@@ -783,7 +857,7 @@ func NewAgoricApp(
|
|
|
783
857
|
params.NewAppModule(app.ParamsKeeper),
|
|
784
858
|
evidence.NewAppModule(app.EvidenceKeeper),
|
|
785
859
|
ibc.NewAppModule(app.IBCKeeper),
|
|
786
|
-
|
|
860
|
+
ics20TransferModule,
|
|
787
861
|
)
|
|
788
862
|
|
|
789
863
|
app.sm.RegisterStoreDecoders()
|
|
@@ -817,34 +891,26 @@ func NewAgoricApp(
|
|
|
817
891
|
app.SetBeginBlocker(app.BeginBlocker)
|
|
818
892
|
app.SetEndBlocker(app.EndBlocker)
|
|
819
893
|
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
upgradeName,
|
|
827
|
-
unreleasedUpgradeHandler(app, upgradeName),
|
|
828
|
-
)
|
|
829
|
-
app.UpgradeKeeper.SetUpgradeHandler(
|
|
830
|
-
upgradeNameTest,
|
|
831
|
-
unreleasedUpgradeHandler(app, upgradeNameTest),
|
|
832
|
-
)
|
|
894
|
+
for _, name := range upgradeNamesOfThisVersion {
|
|
895
|
+
app.UpgradeKeeper.SetUpgradeHandler(
|
|
896
|
+
name,
|
|
897
|
+
unreleasedUpgradeHandler(app, name),
|
|
898
|
+
)
|
|
899
|
+
}
|
|
833
900
|
|
|
901
|
+
// At this point we don't have a way to read from the store, so we have to
|
|
902
|
+
// rely on data saved by the x/upgrade module in the previous software.
|
|
834
903
|
upgradeInfo, err := app.UpgradeKeeper.ReadUpgradeInfoFromDisk()
|
|
835
904
|
if err != nil {
|
|
836
905
|
panic(err)
|
|
837
906
|
}
|
|
838
|
-
|
|
907
|
+
// Store migrations can only run once, so we use a notion of "primary upgrade
|
|
908
|
+
// name" to trigger them. Testnets may end up upgrading from one rc to
|
|
909
|
+
// another, which shouldn't re-run store upgrades.
|
|
910
|
+
if isPrimaryUpgradeName(upgradeInfo.Name) && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) {
|
|
839
911
|
storeUpgrades := storetypes.StoreUpgrades{
|
|
840
|
-
Added:
|
|
841
|
-
|
|
842
|
-
vlocalchain.ModuleName, // Agoric added vlocalchain
|
|
843
|
-
},
|
|
844
|
-
Deleted: []string{
|
|
845
|
-
crisistypes.ModuleName, // The SDK discontinued the crisis module in v0.51.0
|
|
846
|
-
"lien", // Agoric removed the lien module
|
|
847
|
-
},
|
|
912
|
+
Added: []string{},
|
|
913
|
+
Deleted: []string{},
|
|
848
914
|
}
|
|
849
915
|
|
|
850
916
|
// configure store loader that checks if version == upgradeHeight and applies store upgrades
|
|
@@ -871,52 +937,6 @@ func NewAgoricApp(
|
|
|
871
937
|
return app
|
|
872
938
|
}
|
|
873
939
|
|
|
874
|
-
// unreleasedUpgradeHandler performs standard upgrade actions plus custom actions for the unreleased upgrade.
|
|
875
|
-
func unreleasedUpgradeHandler(app *GaiaApp, targetUpgrade string) func(sdk.Context, upgradetypes.Plan, module.VersionMap) (module.VersionMap, error) {
|
|
876
|
-
return func(ctx sdk.Context, plan upgradetypes.Plan, fromVm module.VersionMap) (module.VersionMap, error) {
|
|
877
|
-
app.CheckControllerInited(false)
|
|
878
|
-
|
|
879
|
-
// Each CoreProposalStep runs sequentially, and can be constructed from
|
|
880
|
-
// one or more modules executing in parallel within the step.
|
|
881
|
-
CoreProposalSteps := []vm.CoreProposalStep{
|
|
882
|
-
// First, upgrade wallet factory
|
|
883
|
-
vm.CoreProposalStepForModules("@agoric/builders/scripts/smart-wallet/build-wallet-factory2-upgrade.js"),
|
|
884
|
-
// Then, upgrade Zoe and ZCF
|
|
885
|
-
vm.CoreProposalStepForModules("@agoric/builders/scripts/vats/replace-zoe.js"),
|
|
886
|
-
// Then, upgrade the provisioning vat
|
|
887
|
-
vm.CoreProposalStepForModules("@agoric/builders/scripts/vats/replace-provisioning.js"),
|
|
888
|
-
// Enable low-level Orchestration.
|
|
889
|
-
vm.CoreProposalStepForModules(
|
|
890
|
-
"@agoric/builders/scripts/vats/init-network.js",
|
|
891
|
-
"@agoric/builders/scripts/vats/init-localchain.js",
|
|
892
|
-
),
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
app.upgradeDetails = &upgradeDetails{
|
|
896
|
-
// Record the plan to send to SwingSet
|
|
897
|
-
Plan: plan,
|
|
898
|
-
// Core proposals that should run during the upgrade block
|
|
899
|
-
// These will be merged with any coreProposals specified in the
|
|
900
|
-
// upgradeInfo field of the upgrade plan ran as subsequent steps
|
|
901
|
-
CoreProposals: vm.CoreProposalsFromSteps(CoreProposalSteps...),
|
|
902
|
-
}
|
|
903
|
-
|
|
904
|
-
// Always run module migrations
|
|
905
|
-
mvm, err := app.mm.RunMigrations(ctx, app.configurator, fromVm)
|
|
906
|
-
if err != nil {
|
|
907
|
-
return mvm, err
|
|
908
|
-
}
|
|
909
|
-
|
|
910
|
-
m := swingsetkeeper.NewMigrator(app.SwingSetKeeper)
|
|
911
|
-
err = m.MigrateParams(ctx)
|
|
912
|
-
if err != nil {
|
|
913
|
-
return mvm, err
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
return mvm, nil
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
|
|
920
940
|
// normalizeModuleAccount ensures that the given account is a module account,
|
|
921
941
|
// initializing or updating it if necessary. The account name must be listed in maccPerms.
|
|
922
942
|
func normalizeModuleAccount(ctx sdk.Context, ak authkeeper.AccountKeeper, name string) {
|
|
@@ -941,11 +961,12 @@ type upgradeDetails struct {
|
|
|
941
961
|
|
|
942
962
|
type cosmosInitAction struct {
|
|
943
963
|
vm.ActionHeader `actionType:"AG_COSMOS_INIT"`
|
|
944
|
-
ChainID string
|
|
945
|
-
IsBootstrap bool
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
SupplyCoins sdk.Coins
|
|
964
|
+
ChainID string `json:"chainID"`
|
|
965
|
+
IsBootstrap bool `json:"isBootstrap"`
|
|
966
|
+
Params swingset.Params `json:"params"`
|
|
967
|
+
ResolvedConfig *swingset.SwingsetConfig `json:"resolvedConfig"`
|
|
968
|
+
SupplyCoins sdk.Coins `json:"supplyCoins"`
|
|
969
|
+
UpgradeDetails *upgradeDetails `json:"upgradeDetails,omitempty"`
|
|
949
970
|
// CAVEAT: Every property ending in "Port" is saved in chain-main.js/portNums
|
|
950
971
|
// with a key consisting of this name with the "Port" stripped.
|
|
951
972
|
StoragePort int `json:"storagePort"`
|
|
@@ -953,6 +974,7 @@ type cosmosInitAction struct {
|
|
|
953
974
|
VbankPort int `json:"vbankPort"`
|
|
954
975
|
VibcPort int `json:"vibcPort"`
|
|
955
976
|
VlocalchainPort int `json:"vlocalchainPort"`
|
|
977
|
+
VtransferPort int `json:"vtransferPort"`
|
|
956
978
|
}
|
|
957
979
|
|
|
958
980
|
// Name returns the name of the App
|
|
@@ -976,10 +998,15 @@ func (app *GaiaApp) initController(ctx sdk.Context, bootstrap bool) {
|
|
|
976
998
|
app.controllerInited = true
|
|
977
999
|
|
|
978
1000
|
// Begin initializing the controller here.
|
|
1001
|
+
swingsetConfig, err := swingset.SwingsetConfigFromViper(app.resolvedConfig)
|
|
1002
|
+
if err != nil {
|
|
1003
|
+
panic(err)
|
|
1004
|
+
}
|
|
979
1005
|
action := &cosmosInitAction{
|
|
980
1006
|
ChainID: ctx.ChainID(),
|
|
981
1007
|
IsBootstrap: bootstrap,
|
|
982
1008
|
Params: app.SwingSetKeeper.GetParams(ctx),
|
|
1009
|
+
ResolvedConfig: swingsetConfig,
|
|
983
1010
|
SupplyCoins: sdk.NewCoins(app.BankKeeper.GetSupply(ctx, "uist")),
|
|
984
1011
|
UpgradeDetails: app.upgradeDetails,
|
|
985
1012
|
// See CAVEAT in cosmosInitAction.
|
|
@@ -988,6 +1015,7 @@ func (app *GaiaApp) initController(ctx sdk.Context, bootstrap bool) {
|
|
|
988
1015
|
VbankPort: app.vbankPort,
|
|
989
1016
|
VibcPort: app.vibcPort,
|
|
990
1017
|
VlocalchainPort: app.vlocalchainPort,
|
|
1018
|
+
VtransferPort: app.vtransferPort,
|
|
991
1019
|
}
|
|
992
1020
|
// This uses `BlockingSend` as a friendly wrapper for `sendToController`
|
|
993
1021
|
//
|
|
@@ -1252,11 +1280,44 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino
|
|
|
1252
1280
|
paramsKeeper.Subspace(slashingtypes.ModuleName)
|
|
1253
1281
|
paramsKeeper.Subspace(govtypes.ModuleName).WithKeyTable(govtypesv1.ParamKeyTable())
|
|
1254
1282
|
paramsKeeper.Subspace(ibctransfertypes.ModuleName)
|
|
1283
|
+
paramsKeeper.Subspace(packetforwardtypes.ModuleName).WithKeyTable(packetforwardtypes.ParamKeyTable())
|
|
1255
1284
|
paramsKeeper.Subspace(ibchost.ModuleName)
|
|
1256
1285
|
paramsKeeper.Subspace(icahosttypes.SubModuleName)
|
|
1257
|
-
paramsKeeper.Subspace(packetforwardtypes.ModuleName).WithKeyTable(packetforwardtypes.ParamKeyTable())
|
|
1258
1286
|
paramsKeeper.Subspace(swingset.ModuleName)
|
|
1259
1287
|
paramsKeeper.Subspace(vbank.ModuleName)
|
|
1260
1288
|
|
|
1261
1289
|
return paramsKeeper
|
|
1262
1290
|
}
|
|
1291
|
+
|
|
1292
|
+
// TestingApp functions
|
|
1293
|
+
|
|
1294
|
+
// GetBaseApp implements the TestingApp interface.
|
|
1295
|
+
func (app *GaiaApp) GetBaseApp() *baseapp.BaseApp {
|
|
1296
|
+
return app.BaseApp
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
// GetStakingKeeper implements the TestingApp interface.
|
|
1300
|
+
func (app *GaiaApp) GetStakingKeeper() testtypes.StakingKeeper {
|
|
1301
|
+
return app.StakingKeeper
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
// GetIBCKeeper implements the TestingApp interface.
|
|
1305
|
+
func (app *GaiaApp) GetIBCKeeper() *ibckeeper.Keeper {
|
|
1306
|
+
return app.IBCKeeper
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
// GetScopedIBCKeeper implements the TestingApp interface.
|
|
1310
|
+
func (app *GaiaApp) GetScopedIBCKeeper() capabilitykeeper.ScopedKeeper {
|
|
1311
|
+
return app.ScopedIBCKeeper
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
// GetTxConfig implements the TestingApp interface.
|
|
1315
|
+
func (app *GaiaApp) GetTxConfig() client.TxConfig {
|
|
1316
|
+
return MakeEncodingConfig().TxConfig
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
// For testing purposes
|
|
1320
|
+
func (app *GaiaApp) SetSwingStoreExportDir(dir string) {
|
|
1321
|
+
module := app.mm.Modules[swingset.ModuleName].(swingset.AppModule)
|
|
1322
|
+
module.SetSwingStoreExportDir(dir)
|
|
1323
|
+
}
|