-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(cli/module)!: separate the app genesis state by module into folders when export/import/validate #13032
Conversation
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## main #13032 +/- ##
==========================================
- Coverage 53.92% 53.80% -0.12%
==========================================
Files 643 653 +10
Lines 55475 57032 +1557
==========================================
+ Hits 29913 30686 +773
- Misses 23159 23877 +718
- Partials 2403 2469 +66
|
cc0606b
to
e8b3c82
Compare
e8b3c82
to
0c3c878
Compare
Prior to continuing potentially wasted work on this PR, have we come to consensus on if we need this or not? I mean we did introduce recently the ability to export named/specific module states. |
abd64fd
to
17d2f06
Compare
forZeroHeight, _ := cmd.Flags().GetBool(FlagForZeroHeight) | ||
jailAllowedAddrs, _ := cmd.Flags().GetStringSlice(FlagJailAllowedAddrs) | ||
modulesToExport, _ := cmd.Flags().GetStringSlice(FlagModulesToExport) | ||
splitModules, _ := cmd.Flags().GetBool(FlagSplitModules) |
Check warning
Code scanning / gosec
Returned error is not propagated up the stack.
@alexanderbez |
d05698e
to
12c9fad
Compare
Thanks for the update. Re-reviewing now!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have left a few comments. Thanks for the PR, I see the use case now!
Can you as well add a CHANGELOG?
return err | ||
} | ||
if splitModules { | ||
wd, err := os.Getwd() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't correct, as it will export it in the current directory. You don't need it as we have homeDir
.
cmd.SetOut(cmd.OutOrStdout()) | ||
cmd.SetErr(cmd.OutOrStderr()) | ||
cmd.Println(string(sdk.MustSortJSON(encoded))) | ||
if err := doc.SaveAs(filepath.Join(wd, "genesis", "genesis.json")); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should use homeDir
instead. Are we sure we want to override the file if it exists? If so let's add an explanation in the command description.
if err != nil { | ||
return servertypes.ExportedApp{}, err | ||
} | ||
app.ModuleManager.GenesisPath = wd |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
app.ModuleManager.GenesisPath = wd | |
app.ModuleManager.GenesisPath = filepath.Join(cast.ToString(app.appOpts.Get(flags.FlagHome)), "config", "genesis") |
@@ -28,11 +34,30 @@ func (app *SimApp) ExportAppStateAndValidators(forZeroHeight bool, jailAllowedAd | |||
app.prepForZeroHeightGenesis(ctx, jailAllowedAddrs) | |||
} | |||
|
|||
genState := app.ModuleManager.ExportGenesisForModules(ctx, app.appCodec, modulesToExport) | |||
appState, err := json.MarshalIndent(genState, "", " ") | |||
wd, err := os.Getwd() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't get the current directory.
@@ -235,6 +239,7 @@ func NewManager(modules ...AppModule) *Manager { | |||
OrderExportGenesis: modulesStr, | |||
OrderBeginBlockers: modulesStr, | |||
OrderEndBlockers: modulesStr, | |||
GenesisPath: "", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GenesisPath: "", |
It is go default.
@@ -320,19 +340,31 @@ func (m *Manager) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, genesisData | |||
} | |||
|
|||
// ExportGenesis performs export genesis functionality for modules | |||
func (m *Manager) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) map[string]json.RawMessage { | |||
return m.ExportGenesisForModules(ctx, cdc, []string{}) | |||
func (m *Manager) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) (map[string]json.RawMessage, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is API breaking. Shouldn't we panic instead?
return nil | ||
}, | ||
} | ||
|
||
cmd.Flags().Bool(FlagValidateSplitModules, false, "validate the modules' genesis state in current working path") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cmd.Flags().Bool(FlagValidateSplitModules, false, "validate the modules' genesis state in current working path") | |
cmd.Flags().Bool(FlagValidateSplitModules, false, "validate the modules' genesis state at the genesis.json directory") |
return fmt.Errorf("error unmarshalling genesis doc %s: %s", genesis, err.Error()) | ||
} | ||
if splitModules { | ||
wd, err := os.Getwd() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think of using genesis
so we support arguments too and keep the same behavior. We can get the directory of that file with filepath.Dir
.
But isn't that at odds with the ORM which allows Genesis streaming (cc @aaronc). I don't think it's ideal to have two completely different ways to do one thing. |
Yes, but to solve the issue (RAM) completely using Genesis steaming, we need to do it within each module when executing the genesis export/import. That's a big API change. Agree, we can do Genesis steaming for the current export/import when we got the rawjson from/to each module export/import. My question:
|
This approach I'm pretty sure is compatible with what I've outlined in #12972 and https://github.com/cosmos/cosmos-sdk/pull/13082/files#diff-e8221a593d36e8d8497d6f3970bf820a8bb3533426f13f6045cd941359483a37. That API tries to be flexible and allow for a few different approaches. This approach wouldn't be needed for modules which use the ORM and have built-in streaming, but sounds like it could be helpful for the current genesis structure. |
@aaronc do you think or recommend that we take this approach then as well? |
Well it seems like it solves an immediate problem that people have. On the other hand, I wonder how often this scenario is needed. The logic for splitting a single module's JSON into multiple files seems a bit complex and renders the JSON more or less unreadable and uneditable. @JayT106 can you describe more the use case you're targeting for this? Is it for dump state/restart upgrades or for some other internal analytics/testing usage? An alternative approach which might be simpler but allow the same benefits and also keep the JSON usable to split a module's genesis based on object fields. For example, if we split the top-level fields in bank's
This is essentially what the ORM does behind the scenes, but with support for actually streaming the data which should make memory requirements very low. Without the streaming memory usage would be higher but probably much better than what we have. Would this alternate approach meet your needs @JayT106 ? |
@aaronc
I think the operator can choose whether they want to split it or not by a flag, we just need to provide the option. Or maybe provides some tooling if they would like to read or edit the files. I can try to rewrite it by implementing #12808 (comment) |
Nobody is doing it currently. What you're trying to do doesn't even need the API change because you're recomposing everything into a single runtime object per module right? Just to confirm, do you think this alternate approach of splitting by top-level field would address the issue? Also just curious, why is cronos doing export/import upgrades instead of using x/upgrade? |
that's correct!
No, but easing it (same as this PR) unless we are able to introduce a new module export/import API with the file streamer, which will require the downstream project to integrate. Or migrate the whole module state using the ORM module?
Yes, currently we are using x/upgrade for the chain upgrade |
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
Description
Closes: #12808
updates:
add extra arguments in ExportAppStateAndValidators (API-breaking). Since #13437 already added this new API, it should be fine if this PR is accepted and released in the same SDK version.
Implementation
Export
add
split-modules
flag in the cliexport
, the app will export the genesis state to the current working path and name itgenesis
. otherwise, the export cli will export the whole app genesis state into agenesis.json
file (the current default export method)Validate
use
validate-split-modules
flag in the clivalidate-genesis
, to validate the exportedgenesis
folderImport (InitChain)
a. clean out the app data directory, i.e.
home/.simapp/data
.b. copy/move the exported
genesis
folder to the app config directory, i.e.home/.simapp/config
.c. copy/move
genesis.json
in thegenesis
folder to the app config directoryd. re-start the app
The structure in the
genesis
folder will be (the gray background meaning it's a folder):genesis
If the module state is more than 100 MB (currently hard cording), it will split into several files
Author Checklist
All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.
I have...
!
to the type prefix if API or client breaking changeCHANGELOG.md
Reviewers Checklist
All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.
I have...
!
in the type prefix if API or client breaking change