1
1
package runtime
2
2
3
3
import (
4
+ "context"
4
5
"encoding/json"
6
+ "errors"
7
+ "fmt"
8
+ "io"
5
9
6
10
runtimev2 "cosmossdk.io/api/cosmos/app/runtime/v2"
7
11
appmodulev2 "cosmossdk.io/core/appmodule/v2"
8
12
"cosmossdk.io/core/registry"
13
+ "cosmossdk.io/core/store"
9
14
"cosmossdk.io/core/transaction"
10
15
"cosmossdk.io/log"
16
+ "cosmossdk.io/runtime/v2/services"
11
17
"cosmossdk.io/schema/decoding"
12
18
"cosmossdk.io/server/v2/appmanager"
13
19
"cosmossdk.io/server/v2/stf"
@@ -23,26 +29,80 @@ import (
23
29
// done declaratively with an app config and the rest of it is done the old way.
24
30
// See simapp/app_v2.go for an example of this setup.
25
31
type App [T transaction.Tx ] struct {
26
- * appmanager.AppManager [T ]
32
+ // app configuration
33
+ logger log.Logger
34
+ config * runtimev2.Module
27
35
28
- // app manager dependencies
36
+ // state
29
37
stf * stf.STF [T ]
30
38
msgRouterBuilder * stf.MsgRouterBuilder
31
39
queryRouterBuilder * stf.MsgRouterBuilder
40
+ appm * appmanager.AppManager [T ]
41
+ branch func (state store.ReaderMap ) store.WriterMap
32
42
db Store
43
+ storeLoader StoreLoader
33
44
34
- // app configuration
35
- logger log.Logger
36
- config * runtimev2.Module
37
-
45
+ // modules
38
46
interfaceRegistrar registry.InterfaceRegistrar
39
47
amino registry.AminoRegistrar
40
48
moduleManager * MM [T ]
49
+ queryHandlers map [string ]appmodulev2.Handler // queryHandlers defines the query handlers
50
+ }
51
+
52
+ // initGenesis initializes the genesis state of the application.
53
+ func (a * App [T ]) initGenesis (ctx context.Context , src io.Reader , txHandler func (json.RawMessage ) error ) (store.WriterMap , error ) {
54
+ // this implementation assumes that the state is a JSON object
55
+ bz , err := io .ReadAll (src )
56
+ if err != nil {
57
+ return nil , fmt .Errorf ("failed to read import state: %w" , err )
58
+ }
59
+ var genesisJSON map [string ]json.RawMessage
60
+ if err = json .Unmarshal (bz , & genesisJSON ); err != nil {
61
+ return nil , err
62
+ }
63
+
64
+ v , zeroState , err := a .db .StateLatest ()
65
+ if err != nil {
66
+ return nil , fmt .Errorf ("unable to get latest state: %w" , err )
67
+ }
68
+ if v != 0 { // TODO: genesis state may be > 0, we need to set version on store
69
+ return nil , errors .New ("cannot init genesis on non-zero state" )
70
+ }
71
+ genesisCtx := services .NewGenesisContext (a .branch (zeroState ))
72
+ genesisState , err := genesisCtx .Mutate (ctx , func (ctx context.Context ) error {
73
+ err = a .moduleManager .InitGenesisJSON (ctx , genesisJSON , txHandler )
74
+ if err != nil {
75
+ return fmt .Errorf ("failed to init genesis: %w" , err )
76
+ }
77
+ return nil
78
+ })
79
+
80
+ return genesisState , err
81
+ }
41
82
42
- // QueryHandlers defines the query handlers
43
- QueryHandlers map [string ]appmodulev2.Handler
83
+ // exportGenesis exports the genesis state of the application.
84
+ func (a * App [T ]) exportGenesis (ctx context.Context , version uint64 ) ([]byte , error ) {
85
+ state , err := a .db .StateAt (version )
86
+ if err != nil {
87
+ return nil , fmt .Errorf ("unable to get state at given version: %w" , err )
88
+ }
89
+
90
+ genesisJson , err := a .moduleManager .ExportGenesisForModules (
91
+ ctx ,
92
+ func () store.WriterMap {
93
+ return a .branch (state )
94
+ },
95
+ )
96
+ if err != nil {
97
+ return nil , fmt .Errorf ("failed to export genesis: %w" , err )
98
+ }
99
+
100
+ bz , err := json .Marshal (genesisJson )
101
+ if err != nil {
102
+ return nil , fmt .Errorf ("failed to marshal genesis: %w" , err )
103
+ }
44
104
45
- storeLoader StoreLoader
105
+ return bz , nil
46
106
}
47
107
48
108
// Name returns the app name.
@@ -85,24 +145,26 @@ func (a *App[T]) LoadLatestHeight() (uint64, error) {
85
145
return a .db .GetLatestVersion ()
86
146
}
87
147
88
- // Close is called in start cmd to gracefully cleanup resources.
89
- func (a * App [T ]) Close () error {
90
- return nil
148
+ // AppManager returns the app's appamanger
149
+ func (a * App [T ]) AppManager () * appmanager. AppManager [ T ] {
150
+ return a . appm
91
151
}
92
152
93
- func (a * App [T ]) GetAppManager () * appmanager.AppManager [T ] {
94
- return a .AppManager
153
+ // GetQueryHandlers returns the query handlers.
154
+ func (a * App [T ]) QueryHandlers () map [string ]appmodulev2.Handler {
155
+ return a .queryHandlers
95
156
}
96
157
97
- func (a * App [T ]) GetQueryHandlers () map [string ]appmodulev2.Handler {
98
- return a .QueryHandlers
99
- }
100
-
101
- // GetSchemaDecoderResolver returns the module schema resolver.
102
- func (a * App [T ]) GetSchemaDecoderResolver () decoding.DecoderResolver {
158
+ // SchemaDecoderResolver returns the module schema resolver.
159
+ func (a * App [T ]) SchemaDecoderResolver () decoding.DecoderResolver {
103
160
moduleSet := map [string ]any {}
104
161
for moduleName , module := range a .moduleManager .Modules () {
105
162
moduleSet [moduleName ] = module
106
163
}
107
164
return decoding .ModuleSetDecoderResolver (moduleSet )
108
165
}
166
+
167
+ // Close is called in start cmd to gracefully cleanup resources.
168
+ func (a * App [T ]) Close () error {
169
+ return nil
170
+ }
0 commit comments