-
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
Migrate x/params JSON state #6983
Comments
Any thoughts on what to do here @alexanderbez ? |
I wasn't involved in the discussion for use of Amino JSON, but I do recall being frustrated by this because its slow af and Jae wanted it for some reason. That being said, I don't think option (1) is viable. (3) seems like we might run into issues if there are non-go-based SDK clients (correct me if I'm wrong)? So I think (2) is preferable. Nearly all params are primitive types with the exception of |
FYI we decided to go with approach (2) in our dev call. |
@aaronc Does Also, |
We should be preferring |
@alexanderbez Just hit another sticking point with this that we need to making a decision on. The subspace See this test for an example of where we currently expect this as functionality. I don't see why this is necessary as a feature. If a Param value is a struct, I would expect that it can only be get/set/updated wholesale. If there's a desire to update individual subfields of a given value, shouldn't this just be a separate parameter? Maybe there's some context i'm missing.. Seems related to #4403 |
So a few things. One, I personally believe struct-based params are an anti-pattern, and AFAIK is only used by That being said and in this context, it's actually valuable because say you only want to update one field in the struct. You, as a Now for the actual issue with the migration to Proto3, it's unfortunate and I'm not sure what to do, but here are some immediate thoughts/plans that come to mind:
|
I'm not certain that In the current code, it looks like the It's not clear to me that we should be expecting the same behavior when calling
This makes sense to me. I'll keep it in mind as our backup option. |
We would be using With binary encoding, I'm not sure we can support this. |
After spending some more time digging into this I've realized I'm not quite happy with any of the paths I see forward. Here's an articulation of where I've gotten. I'd appreciate feedback from anyone whose spent time with x/params to provide feedback on what makes the most sense. Option 1: All parameter values must be valid protobuf messagesThis is the first strategy I was pursuing, which involves requiring that for each Params message (for a given module), all fields must have values that themselves are protobuf messges. Primitive types must be wrapped accordingly. The main pain point with this, is that modules when interacting with params have to unwrap them with Option 2: All parameter values must be either a whitelisted set of primitive types, or a valid protobuf messageI then started exploring a situation in which we try to keep everything as is, except for the actual serialization of param messages. This strategy involves func (s Subspace) Get(ctx sdk.Context, key []byte, ptr interface{}) {
s.checkType(key, ptr)
store := s.kvStore(ctx)
bz := store.Get(key)
switch v := ptr.(type) {
case uint64:
var wrapper_ptr *pt.UInt64Value
if err := s.cdc.UnmarshalBinaryBare(bz, wrapper_ptr); err != nil {
panic(err)
}
v = wrapper_ptr.Value
case string:
var wrapper_ptr *pt.StringValue
if err := s.cdc.UnmarshalBinaryBare(bz, wrapper_ptr); err != nil {
panic(err)
}
v = wrapper_ptr.Value
...
...
case codec.ProtoMarshaler:
if err := s.cdc.UnmarshalBinaryBare(bz, v); err != nil {
panic(err)
}
default:
panic(fmt.Sprintf("Unsupported ParamSetPair Value type: %T", v))
}
} While I think this option does result in a cleaner UX for end users and chain developers, it still requires knowing & understanding what types can be handled as bare primitives, and which ones can't. For instance, this will break for repeated fields (the wrapper type for repeated fields All to say that this approach also felt hacky and ugly to me. We would need to decide how to treat some existing parameters like Option 3: Store a full module's paramset as one serialized value in the Subspace's KV store.This involves a larger refactor of the params module, which would do away with a lot of the Option 4: Leave as is and punt on this entire issue until we do a larger params refactor in conjunction with other store refactorsJust bringing this up as a possibility. As we're inching closer to Stargate release, I don't want this to the yet another issue that balloons in scope and slows down getting an RC out the door. Please comment with any preferences, upgrades, or other alternatives I should be considering. I'm considering this largely orthogonal to the previous issue above, which is why i haven't gone into details of x/gov's updating of struct fields in this, as I think a solution for that will be found independently of this larger conversation. |
Thanks for the detailed and excellent summary @clevinson! Yeah, option (1) definitely seems like a no-go from what you've laid out, especially since it results in a very poor UX -- no gusta. I really like options (2) and (3). The former seems like something we can tackle before stargate and honestly, having a limited set of types to support for params may not be that bad, but I can foresee it being a limiting factor for app devs, which may also lead to a poor dev-UX. So really, option (3) seems like the best path to take, especially with field-masks as that allows us to keep the current behavior. However, this is unlikely to be completed before stargate. This is something I can take off of your plate though. So tl;dr, I think punting on this for 0.41 is the best path to take. Can you layout any remaining blockers for stargate? |
I agree we should punt this to 0.41, and really simplify this when we do. It should just be primitive types. All the reflection and struct stuff really strikes me as anti patterns. |
Ok great. I'll do a last audit of the existing params tx pathways to make sure there isn't anything breaking or horrid in the current path (e.g. verifying how params update proposals get handled via the GRPC endpoints), and then move this issue to 0.41. @alexanderbez Remaining stargate blockers are being tracked here |
superseded by #10514 |
x/params
uses JSON encoding forParamSetPair.Value
s and it was missed in the protobuf state migrations. It won't easily work with protobuf JSON or binary because some types are primitives likeuint64
and would need to be wrapped inUInt64Value
for protobuf.Does anyone know why this was JSON and not binary btw? @alexanderbez ?
We have a few options:
ParamSetPair.Value
frominterface{}
->proto.Message
and make everything use a proto-compatible type. Then we can use proto binary or JSON. We might run in to trouble, however, trying to make this backwards compatible with amino state encoding. Maybe that's a non-goal now??json.Marshal
methods. This may work, but there might be issues with types likeDec
. I'm not really sure...The text was updated successfully, but these errors were encountered: