-
Notifications
You must be signed in to change notification settings - Fork 210
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
Codebase migration refactor #464
Conversation
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 is the motivation for these changes?
app/app.go
Outdated
EvidenceKeeper evidence.Keeper | ||
DeploymentKeeper deployment.Keeper | ||
MarketKeeper market.Keeper | ||
ProviderKeeper provider.Keeper |
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.
Why are these public?
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.
making the keepers public leverages the AkashApp
as the source for integration tests (as it should be). See cosmos/cosmos-sdk#4875 for reference
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.
fwiw I think that the reality is that they don't need to be fields in the struct at all
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 need to access all of the keepers?
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.
anyways, please keep them in a separate struct for organization/isolation and only export the keepers that you need to.
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.
fwiw I think that the reality is that they don't need to be fields in the struct at all?
As you prefer, I'd still need to make the keeper
internal struct public tho.
You need to access all of the keepers?
I need access to all the keepers used by the Akash modules
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.
ok please keep them in an isolated struct and export them on an as-needed basis.
app/app.go
Outdated
} | ||
|
||
// GetMaccPerms returns a copy of the module account permissions | ||
func GetMaccPerms() map[string][]string { |
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.
Why not use the previous definition?
app/app.go
Outdated
EvidenceKeeper evidence.Keeper | ||
DeploymentKeeper deployment.Keeper | ||
MarketKeeper market.Keeper | ||
ProviderKeeper provider.Keeper |
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.
fwiw I think that the reality is that they don't need to be fields in the struct at all
app/app.go
Outdated
func NewApp( | ||
logger log.Logger, db dbm.DB, tio io.Writer, options ...func(*bam.BaseApp), | ||
// NewAkashApp creates and returns a new Akash App. | ||
func NewAkashApp( |
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.
Why are you changing the name?
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.
because the constructor name should match the returned value (i.e AkashApp
)
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.
okay. would have preferred to change the struct name to App
.
app/app.go
Outdated
auth.ModuleName, distr.ModuleName, staking.ModuleName, bank.ModuleName, | ||
slashing.ModuleName, gov.ModuleName, mint.ModuleName, supply.ModuleName, | ||
crisis.ModuleName, genutil.ModuleName, evidence.ModuleName, | ||
deployment.ModuleName, provider.ModuleName, market.ModuleName, // akash |
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.
why are you changing the format here?
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.
uses too many lines. I usually break the line at ~80 chars
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.
Please keep the previous format.
app/app.go
Outdated
func (app *AkashApp) beginBlocker( | ||
ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock { | ||
// BeginBlocker application updates every begin block | ||
func (app *AkashApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock { |
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.
why are you making these public?
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.
One reason is, it helps in simapp tests
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.
that's the standard of the SDK framework. It doesn´t make much difference since the function calls a private function. Otherwise, you can call the module manager, mm
, directly so there's no need to have a private function call another private function imho.
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.
Exporting symbols comes with many costs. Please don't export any symbols unless absolutely necessary.
great! @fedekunze please also to make sure to document your findings and reasons, especially for major interface changes (names, etc) since we have other members in the team that need to rebase and we want to make sure practices are documented well to reduce knowledge asymmetry. add a section "refactor considerations" for [DCS-5].(https://github.com/ovrclk/dcs/blob/master/spec/dcs-5/README.md) |
I checked all these updates and are in sync with the standards sdk/gaia follows. There are a plenty of discussions before making all these changes in gaia and simapp. I also feel that, keeping akash code close to gaia will help in reducing redundant work for upgrades (sdk changes). Otherwise, it will be an overhead to upgrade. |
The Gia and cosmos-sdk "standards" are constantly-moving targets. They also tend to diverge from idiomatic go patterns. Refactoring for the sake of refactoring can be necessary at times, but it is not here. |
app/app.go
Outdated
|
||
// akash | ||
deployment.AppModuleBasic{}, | ||
market.AppModuleBasic{}, | ||
provider.AppModuleBasic{}, | ||
) | ||
|
||
// module account permissions | ||
maccPerms = map[string][]string{ |
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.
the reason for having these be functions was to prevent mutation - the functions return a new copy every time. please revert to the previous pattern.
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.
that's what GetMaccPerms
does too 🙂
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.
why did you change it then? before there was no way that it could be unintentionally mutated, and now there is.
Signed-off-by: Federico Kunze <[email protected]>
@@ -12,19 +12,19 @@ import ( | |||
func NewHandler(keeper keeper.Keeper, mkeeper MarketKeeper) sdk.Handler { | |||
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { | |||
switch msg := msg.(type) { | |||
case types.MsgCreate: | |||
case types.MsgCreateDeployment: |
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.
+1
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.
Looking great, thank you!
x/deployment/types/msgs.go
Outdated
const ( | ||
TypeMsgCreateDeployment = "create_deployment" | ||
TypeMsgUpdateDeployment = "update_deployment" | ||
TypeMsgCloseDeployment = "close_deployment" |
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.
Can you make these values be the same as those in the codec registration and use these constants there?
If they don't need to be exported, please make them private.
if id.Owner.Empty() { | ||
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "owner cannot be empty") | ||
} | ||
if id.DSeq == 0 && id.GSeq == 0 && id.OSeq == 0 { |
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 believe you can use return id.GroupID().Validate()
. Same goes for the rest of them, I'll illustrate below.
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 can't bc OSeq
is not defined for GroupID
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.
BidID = OrderID + Provider
;Validate(BidID) = Validate(OrderID) + Validate(Provider)
OrderID = GroupID + OSeq
;Validate(OrderID) = Validate(GroupID) + Validate(OSeq)
GroupID = DeploymentID + GSeq
;Validate(GroupID) = Validate(DeploymentID) + Validate(GSeq)
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.
In other words, re-use the validations from the contained structures. Unrolling at every level will lead to bugs, missed validations, and make refactoring more difficult. There are utilities for converting between the various IDs.
See the Equals()
methods for an example.
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 respectfully disagree, not having any validation or the lack of testing leads to bugs. The same applies for private functions and vars, they don't provide any extra security guarantee if you define the public functions within the scope of the module.
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.
not having any validation or the lack of testing leads to bugs
That's why we have a task to do those things.
Those things are, of course, completely separate from the topic of the benefits of abstraction, unless you count the benefits of re-using already-tested code (when OrderID.Validate()
is tested, BidID.Validate()
would use that tested code).
The same applies for private functions and vars, they don't provide any extra security guarantee if you define the public functions within the scope of the module.
I don't really know what you mean by that last part, but keeping the surface area of a package to a minimum interface is for abstraction (internal implementation can change without affecting users of the package), isolation (prevents and/or minimizes paths to state mutation), and yes, security (vars can be re-assigned). This is software engineering 101 stuff.
) | ||
|
||
// MaccPerms returns the module account permissions | ||
func MaccPerms() map[string][]string { |
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.
Please just revert this to the original. Does it need to be exported?
// ModuleBasics defines the module BasicManager is in charge of setting up basic, | ||
// non-dependant module elements, such as codec registration | ||
// and genesis verification. | ||
ModuleBasics = module.NewBasicManager( |
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.
Please revert this to the original. Exporting it as a function prevents other modules from re-assigning it.
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.
Exporting it as a function prevents other modules from re-assigning it.
modules don't have access to other modules, nor the module manager or other application-level fields unless explicitly given as arguments to the keepers.
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.
sorry, I meant packages as in golang packages.
The fact of the matter is that there was absolutely no reason to change this. The same is true for most of this PR. I won't approve any of these (not necessarily) stylistic changes.
bam.MainStoreKey, auth.StoreKey, staking.StoreKey, | ||
supply.StoreKey, mint.StoreKey, distr.StoreKey, slashing.StoreKey, | ||
gov.StoreKey, params.StoreKey, evidence.StoreKey, | ||
deployment.StoreKey, market.StoreKey, provider.StoreKey, |
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.
revert to original format for all of these, please.
|
||
// ModuleAccountAddrs returns all the app's module account addresses. | ||
func (app *App) ModuleAccountAddrs() map[string]bool { | ||
modAccAddrs := make(map[string]bool) |
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.
general template like was done originally
coll := generator()
vals := make(map[string]bool,len(coll))
for k, v := range coll {
// ...
}
return vals
if id.Owner.Empty() { | ||
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "owner cannot be empty") | ||
} | ||
if id.DSeq == 0 && id.GSeq == 0 { |
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.
return id.DeploymentID().Validate()
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.
ditto, I can't because GSeq
is not defined for DeploymentID
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.
GroupID = DeploymentID + GSeq
; Validate(GroupID) = Validate(DeploymentID) + Validate(GSeq)
TypeMsgCloseDeployment = "close_deployment" | ||
typeMsgCreateDeployment = "create_deployment" | ||
typeMsgUpdateDeployment = "update_deployment" | ||
typeMsgCloseDeployment = "close_deployment" |
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.
Either
// msgs.go
typeMsgCreateDeployment = ModuleName + "/msg-create-deployment"
// codec.go
cdc.RegisterConcrete(MsgCreateDeployment{}, typeMsgCreateDeployment, nil)
or
// msgs.go
typeMsgCreateDeployment = msg-create-deployment"
// codec.go
cdc.RegisterConcrete(MsgCreateDeployment{}, ModuleName + "/" + typeMsgCreateDeployment, nil)
Same goes for the rest of these.
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.
if you check the godoc for the RegisterConcrete
the name must match the type name
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.
great then use
// msgs.go
typeMsgCreateDeployment = `MsgCreateDeployment`
// codec.go
cdc.RegisterConcrete(MsgCreateDeployment{}, ModuleName + "/" + typeMsgCreateDeployment, nil)
I feel like the request was pretty obvious, I don't know why we're still talking about it.
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.
Events have different formats (they use snake case) than amino registration, hence the difference.
I feel like the request was pretty obvious, I don't know why we're still talking about it.
I totally agree, idk why are you still nitpicking on these small things...
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 totally agree, idk why are you still nitpicking on these small things...
because you resolved the conversation without saying why you didn't address it.
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.
Can you explain why you think these two things need to have different formats?
The documentation for Type()
says:
Returns a human-readable string for the message, intended for utilization within tags
It doesn't say anything about snake case.
Also, it doesn't look like RegisterConcrete()
needs to be camel case. In fact, this was working fine before without it. Indeed, the go-amino
examples have "anything can go in here if its unique"
in the main README.md
:
amino.RegisterConcrete(&MyStruct3{}, "anythingcangoinhereifitsunique", nil)
In the future, please provide sources for your arguments. If you say that the documentation says it must be some way or another, provide a link to that documentation. In this case, it'd be the go-amio godoc for RegisterConcrete()
and that Type()
should return snake case. Nobody should need to hunt these sources down for you.
idk why are you still nitpicking on these small things...
This was an incredibly innocuous request - use one constant in two places so that the message type name is standardized.
cdc.RegisterConcrete(MsgCloseBid{}, ModuleName+"/msg-close-bid", nil) | ||
cdc.RegisterConcrete(MsgCloseOrder{}, ModuleName+"/MsgCloseOrder", nil) | ||
cdc.RegisterConcrete(MsgCreateBid{}, ModuleName+"/MsgCreateBid", nil) | ||
cdc.RegisterConcrete(MsgCloseBid{}, ModuleName+"/MsgCloseBid", 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.
- use the constants defined in
msgs.go
. - use the original names.
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.
see above
OrderMatched OrderState = iota | ||
// OrderClosed is used when state of order is closed | ||
OrderClosed OrderState = iota | ||
OrderMatched |
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.
Closed
is not the initial state.- Some linters will complain about this formatting. Why are you changing it to begin with?
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.
the default value for uint8
is 0, that means that all default states would have been open
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.
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.
Some linters will complain about this formatting.
which linters complain about this format?
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.
Yes of course I know the initial value for iota
.
When orders are created they are open
, hence that being the default state. closed
is an end state.
I think it would be reasonable to not use 0
as a value at all to make sure things are always explicit. To do this, replace iota
with iota + 1
.
I don't remember what linter doesn't like it.
BidLost BidState = iota | ||
// BidClosed is used when state of bid is closed | ||
BidClosed BidState = iota | ||
BidLost |
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.
Same as above.
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.
see reply
// LeaseActive is used when state of lease is active | ||
LeaseActive | ||
// LeaseInsufficientFunds is used when lease has insufficient funds | ||
LeaseInsufficientFunds |
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.
Again.
) | ||
|
||
// Setup initializes a new SimApp. A Nop logger is set in SimApp. | ||
func Setup(isCheckTx bool) *App { |
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.
Is this used for anything other than tests? Does it need access to private fields or functions?
Not sure it should be here. If nothing else, call it SetupTest()
and put it in a file that ends in _test.go
so that it's only available during testing.
I think it'd be best to re-start this PR - create a fresh branch and include only the changes necessary for one isolated change - "support using |
closes #457
Description
Motivation and Context
design/approved
labelHow Has This Been Tested?
Types of changes
Checklist:
git commit -s