-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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!: IS rebase #13122
feat!: IS rebase #13122
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.
Did a first pass through. I'm gonna need more time to look at the staking changes. The index key stuff I find to be pretty confusing atm.
) (val types.Validator, found bool) { | ||
store := ctx.KVStore(k.storeKey) | ||
|
||
valKey := store.Get(types.GetUnbondingIndexKey(id)) |
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.
So am I correct in reading that the GetUnbondingIndexKey
key can store numerous different things? I.e. validator, redelegation keys, and undelegation keys?
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.
Exactly. The UnbondingIndexKey is a mapping from UnbondingIDs to strings, where each string is the key of an unbonding operation, i.e., validator (that is unbonding), undelegation entry, redelegation entry.
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.
Interesting. This initially seems like a codesmell/poor design choice to me. Is it possible that a value overwrite an existing ID's value unintentionally?
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 it possible that a value overwrite an existing ID's value unintentionally?
Not sure that I follow.
This initially seems like a codesmell/poor design choice to me.
How else can you avoid duplicating logic that is the same regardless of the type of unbonding operation. For example, the CCV module is dealing with the completion of undelegation and redelegation in the same way. By adding different hooks and different IDs (e.g., ubdeID and redeID), CCV will need to duplicate code.
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 use a dedicated key for each stored value type. Having to type check/error check based on the value is a codesmell. I.e. "I'm storing value X at key K. What is X? Idk, let me try these 5 different types..."
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.
Got a second opinion form @ethanfrey and he tends to agree this approach is a code smell. We should refactor this. Would consider this a blocker for the merge. @mpoke any chance you or someone on your team can pick this up. once completed we can merge this work.
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.
@marbar3778 @alexanderbez I will take a look at this right now. I wrote the offending code
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 pattern in question is most clearly demonstrated not here, but in the top level code that calls this function in UnbondingCanComplete
. UnbondingCanComplete
works sort of like an if/else statement.
if (is redelegation) {
} else if (is undelegation) {
} else if (is validator unbonding) {
} else {
}
This didn't seem so bad when I wrote it, but I guess the part that troubles you is just the fact that references to records of different types are being kept in one store? Or is it that we are checking which type it is with failed deserializations?
The simplest way I can think of to avoid the latter issue is to make another index which stores unbondingId->type
. Then we would check this first to find out what to deserialize to without the potential several failed deserializations which are bugging you.
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.
but I guess the part that troubles you is just the fact that references to records of different types are being kept in one store?
Yes, exactly! It's that a key, a dedicated prefix really, can store values of different types yielding the need to have custom business logic of these if/else blocks as you pointed out. To me this is a code smell and no other SDK module does this.
What if we just combined/flattened all the possible value types into one type and have a field/enum that describes what kind of action to take?
something like
type MyValue struct {
Type string // or enum
// all fields that can represent everything you need
}
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.
Seems like maybe this is something a proto oneof could deal with efficiently
b45dd5f
to
83260b0
Compare
if !red.Entries[i].OnHold() && red.Entries[i].IsMature(ctx.BlockHeader().Time) { | ||
// If matured, complete it. | ||
// Remove entry | ||
red.RemoveEntry(int64(i)) |
Check failure
Code scanning / gosec
Potential integer overflow by integer type conversion
} | ||
|
||
// Remove entry | ||
ubd.RemoveEntry(int64(i)) |
Check failure
Code scanning / gosec
Potential integer overflow by integer type conversion
|
||
// Convert into bytes for storage | ||
bz := make([]byte, 8) | ||
binary.BigEndian.PutUint64(bz, uint64(unbondingType)) |
Check failure
Code scanning / gosec
Potential integer overflow by integer type conversion
I have rebased to main here. I'll fix the tests and the build in #13420. |
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## main #13122 +/- ##
==========================================
+ Coverage 54.01% 54.04% +0.03%
==========================================
Files 648 646 -2
Lines 55429 55711 +282
==========================================
+ Hits 29938 30109 +171
- Misses 23093 23188 +95
- Partials 2398 2414 +16
|
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.
LGTM, added a couple of comments
I approved this without fully understanding the code, removing my approval to avoid any confusion
Just reminding that we please don't merge until we test this as a dependency in interchain-security/. Thanks. |
Description
Closes: #XXXX
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