Open jtremback opened 1 year ago
Either of the last two options seem solid to me
- Use
iota
, but simply have a rule to only ever append to the list. Might help to have the keys in a separate file to prevent people from being tempted to refactor. Having a separate file might also facilitate an automated tool that would run on CI and error if keys had been rearranged.
I like this solution as it's the simplest to adopt. Basically, we need better testing around keys. Any idea of a test ensures that keys are only appended?
- Write out bytes, e.g.
[]byte{0x04}
Having a single keys.go
file with all the keys can enable also this solution. We could check then that all the keys are unique. However, if somebody adds a key to keys.go
, but not to keys_test.go
, then we have a problem.
What about using a constant map?
func getKeyPrefix() map[string]byte {
return map[string]byte{
"PortByteKey": 0,
"MaturedUnbondingOpsByteKey": 1,
"ValidatorSetUpdateIdByteKey": 2,
}
}
func PortKey() []byte {
return []byte{getKey("PortByteKey")}
}
Like this we can easily test that the map contains only unique values. Also, it's only a refactor.
@mpoke this does make a possible catastrophic key rearrangement impossible. It doesn't solve the problem 100%, since there's still the potential for the numbers to become scrambled and have gaps as refactors happen. But that will just cause compile errors and the worst case scenario is someone having to try again with a different number as they're writing the code and get an error.
To me, either this approach, or the one I tried here would be satisfactory. I'll leave it to you to make the final call.
Reopening issue to deal with consumer changes.
Protocol Change Proposal
EDIT: Use the solution propose in https://github.com/cosmos/interchain-security/issues/939#issuecomment-1549162175.
Summary
We currently use Go's
iota
operator to choose byte prefixes for our database keys. This is clean looking, but it can be brittle. If someone changes the order of the keys in the file, or adds or removes a key, it changes the prefixes of all following keys. This means that simple refactors can require database migrations. There are many alternatives but all of them have tradeoffs. I will discuss them here and we can decide on whether to change what we do.Proposal
Key prefixing techniques:
iota
[]byte{0x04}
KeyChannelEndPrefix = "channelEnds"
iota
, but simply have a rule to only ever append to the list. Might help to have the keys in a separate file to prevent people from being tempted to refactor. Having a separate file might also facilitate an automated tool that would run on CI and error if keys had been rearranged.For Admin Use