feat!: IS rebase#13122
Conversation
alexanderbez
left a comment
There was a problem hiding this comment.
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.
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.
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.
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.
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.
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.
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.
@marbar3778 @alexanderbez I will take a look at this right now. I wrote the offending code
There was a problem hiding this comment.
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.
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.
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
|
facundomedica
left a comment
There was a problem hiding this comment.
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.mdReviewers 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