Skip to content
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: Add genesis support for new modules and group genesis #270

Merged
merged 31 commits into from
Mar 30, 2021

Conversation

blushi
Copy link
Member

@blushi blushi commented Feb 18, 2021

closes: #214

@codecov
Copy link

codecov bot commented Feb 18, 2021

Codecov Report

Merging #270 (2f24c89) into master (4032eb7) will decrease coverage by 0.40%.
The diff coverage is 59.85%.

@@            Coverage Diff             @@
##           master     #270      +/-   ##
==========================================
- Coverage   62.66%   62.25%   -0.41%     
==========================================
  Files          46       47       +1     
  Lines        2954     2994      +40     
==========================================
+ Hits         1851     1864      +13     
- Misses        892      911      +19     
- Partials      211      219       +8     

@blushi blushi marked this pull request as ready for review March 3, 2021 13:57
Comment on lines 46 to 53
// InitGenesisHandler is a function to get a module InitGenesisHandler.
InitGenesisHandler(moduleName string) module.InitGenesisHandler

// ExportGenesisHandler is a function to get a module ExportGenesisHandler.
ExportGenesisHandler(moduleName string) module.ExportGenesisHandler

// Codec is the app ProtoCodec.
Codec() *codec.ProtoCodec
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need all this here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To use them in tests, see in x/group/server/testsuite/ but happy to discuss any other solutions that would look better to you.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about we simply have InitGenesis() and ExportGenesis() methods? Rather than being able to look up the handler by module. Also consider we want to use these same Fixtures for Network based tests in the future (#246).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thing is that we can register multiple modules as part of FixtureFactory Setup() which is why I added them as look up methods.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that approach will work using a Network fixture. Would InitGenesis and ExportGenesis also work for the tests?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you say InitGenesis() and ExportGenesis() methods, could you elaborate on the params and return values?
Do you see them as being similar to the manager InitGenesis() and ExportGenesis(), ie they would actually execute init or export genesis (instead of simply returning a function)?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think Aaron has a good point - hiding the app details, and only have InitGenesis to initialize genesis for all modules would simplify the usage.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated it so we have InitGenesis and ExportGenesis methods instead.

@aaronc
Copy link
Member

aaronc commented Mar 10, 2021

I'm planning to review this soon. In the meantime can anyone else review?

@blushi
Copy link
Member Author

blushi commented Mar 11, 2021

I'm planning to review this soon. In the meantime can anyone else review?

@AmauryM said he'll have a look.

Copy link
Contributor

@amaury1093 amaury1093 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM overall. Would like to avoid panics, and after that for me we can merge.

I also added a bunch of questions, mostly me getting up to speed with the groups module.

x/group/server/testsuite/genesis.go Outdated Show resolved Hide resolved
x/group/server/testsuite/genesis.go Outdated Show resolved Hide resolved
x/group/server/testsuite/genesis.go Show resolved Hide resolved
proto/regen/group/v1alpha1/genesis.proto Show resolved Hide resolved
x/group/server/genesis.go Outdated Show resolved Hide resolved
@@ -165,4 +165,5 @@ func RegisterServices(configurator servermodule.Configurator, accountKeeper Acco
impl := newServer(configurator.ModuleKey(), configurator.Router(), accountKeeper, configurator.Marshaler())
group.RegisterMsgServer(configurator.MsgServer(), impl)
group.RegisterQueryServer(configurator.QueryServer(), impl)
configurator.RegisterGenesisHandlers(impl.InitGenesis, impl.ExportGenesis)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a big fan of these custom Register* functions.

In the SDK, there's AppModule interface, and it's clear what the module developer needs to implement.

With this impl, we would have RegisterGenesisHandlers, RegisterInvariants, RegisterBeginBlocker etc... right? I feel it's easier to forget one register, whereas in AppModule the skipped ones were clearly marked (with an empty implementation).

One idea could be:

type ModuleConfig interface {
  RegisterMsgServer()
  RegisterQueryServer()
  InitGenesis()
  ExportGenesis()
  BeginBlocker()
}

and then var _ ModuleConfig = impl{}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, I'll try to improve that, thanks!

Copy link
Member Author

@blushi blushi Mar 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though we can't really add RegisterMsgServer and RegisterQueryServer as part of the interface, these are proto-generated standalone functions, serverImpl rather implements MsgServer and QueryServer interfaces, which are module specific. So I'd prefer to have separate interfaces for different concerns, and create a separate interface for genesis which would look like this (not really sure about the naming here):

type GenesisServer interface {
  InitGenesis() ...
  ExportGenesis() ...
}

Copy link
Member Author

@blushi blushi Mar 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or we could also have a single interface as you suggested such as:

type Server interface {
 InitGenesis() 
 ExportGenesis() 
 RegisterInvariants()
 ...
}

And then we could also have one single entry method for the configurator to register genesis handlers, invariants, etc.

func (c *configurator) RegisterServer(s Server) {
 c.initGenesisHandler = s.InitGenesis
 c.exportGenesisHandler = s.ExportGenesis
 c.registerInvariantsHandler = s.RegisterInvariants
 ...
}

But maybe that can be done as part of a separate PR, once we have more functions to register, wdyt?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But maybe that can be done as part of a separate PR, once we have more functions to register, wdyt?

Yes, good idea. #301

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this things at all in a configurator? In comment's above I'm trying to find out if we could reuse module.Manager.

Copy link
Member Author

@blushi blushi Mar 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see my previous comment #270:

This server manager is used for the new modules (ecocredit, data, group) which are not registered with the usual sdk manager (see module wiring in app.go and experimental_appconfig.go). These new modules don't implement AppModule and don't have a direct access to the server implementation which is private (contrary to sdk modules with a reference to a keeper). So we pass relevant methods (init/export genesis in this case) to the configurator on RegisterServices so they can be passed in turn to the server manager on RegisterModules, then the server manager can use them to perform init/export genesis when needed.

This is needed in this context:

serverMod.RegisterServices(cfg)
mm.initGenesisHandlers[name] = cfg.initGenesisHandler
mm.exportGenesisHandlers[name] = cfg.exportGenesisHandler

x/group/server/genesis.go Show resolved Hide resolved
Copy link
Contributor

@amaury1093 amaury1093 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All my questions were addressed, thanks @blushi

app/app.go Outdated Show resolved Hide resolved
app/app.go Outdated Show resolved Hide resolved
app/app.go Outdated Show resolved Hide resolved
app/export.go Show resolved Hide resolved
app/stable_appconfig.go Show resolved Hide resolved
testutil/testdata/model.go Outdated Show resolved Hide resolved
router *router
requiredServices map[reflect.Type]bool
initGenesisHandlers map[string]module.InitGenesisHandler
exportGenesisHandlers map[string]module.ExportGenesisHandler
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need to put this here? Can't types/module.Manager be used? It has InitGenesis method.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the manager InitGenesis and ExportGenesis methods use those handlers.

return abci.ResponseInitChain{
Validators: validatorUpdates,
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is almost a copy of types/module.Manager.InitGenesis - why we do that? Why we can't reuse the modules.Manager?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This server manager is used for the new modules (ecocredit, data, group) which are not registered with the usual sdk manager (see module wiring in app.go and experimental_appconfig.go). These new modules don't implement AppModule and don't have a direct access to the server implementation which is private (contrary to sdk modules with a reference to a keeper). So we pass relevant methods (init/export genesis in this case) to the configurator on RegisterServices so they can be passed in turn to the server manager on RegisterModules, then the server manager can use them to perform init/export genesis when needed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a doc string explaining that (to the Manager.Init/Export Genesis

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, this mechanism looks tricky. Instead of calling interface, we pass a manager and ask the module to register itself. I don't think that extending the Registration pattern is a good approach. Not going to block on that. Let me know wht do you think. If we find that it's good to rethink it then maybe we can continue in a new issue?
@aaronc - do you have any comments on that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should try something like I'm describing here which is a hybrid between the ADR 033 approach and the existing approach: #301 (comment).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's follow up on that as part of this issue #301

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, let's roll this PR and think about better approach in the issue.

@@ -165,4 +165,5 @@ func RegisterServices(configurator servermodule.Configurator, accountKeeper Acco
impl := newServer(configurator.ModuleKey(), configurator.Router(), accountKeeper, configurator.Marshaler())
group.RegisterMsgServer(configurator.MsgServer(), impl)
group.RegisterQueryServer(configurator.QueryServer(), impl)
configurator.RegisterGenesisHandlers(impl.InitGenesis, impl.ExportGenesis)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this things at all in a configurator? In comment's above I'm trying to find out if we could reuse module.Manager.

x/group/server/testsuite/genesis.go Outdated Show resolved Hide resolved
@blushi blushi changed the title Add genesis support for new modules and group genesis feat: Add genesis support for new modules and group genesis Mar 25, 2021
Copy link
Collaborator

@robert-zaremba robert-zaremba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's think what to do with types/module.Manager vs initGenesisHandlers and exportGenesisHandlers
Not going to block on it, but let's see if this is a right approach we want to use towards SDKv1 before merging. (we can expand on this in an issue).

app/stable_appconfig.go Outdated Show resolved Hide resolved
}

// ImportTableData initializes a table and attached indexers from the given json encoded `[]Model`s.
// ImportTableData initializes a table and attaches indexers from the given data interface{}.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think copying indexes (first approach) is not bad. It won't take much more memory since we are only copying pointers.

If you like we can do it (or consider 2nd approach or even something else) later in a new issue?

return abci.ResponseInitChain{
Validators: validatorUpdates,
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a doc string explaining that (to the Manager.Init/Export Genesis

return abci.ResponseInitChain{
Validators: validatorUpdates,
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, this mechanism looks tricky. Instead of calling interface, we pass a manager and ask the module to register itself. I don't think that extending the Registration pattern is a good approach. Not going to block on that. Let me know wht do you think. If we find that it's good to rethink it then maybe we can continue in a new issue?
@aaronc - do you have any comments on that?

Copy link
Collaborator

@robert-zaremba robert-zaremba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please recheck if we have documentation for attributes updated.

@blushi blushi merged commit a38ebdb into master Mar 30, 2021
@blushi blushi deleted the marie/214-group-genesis branch March 30, 2021 08:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[x/group] Genesis state and import/export
4 participants