-
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
fix: fix bug when updating allowance inside AllowedMsgAllowance #10564
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.
I have reviewed all of my changes, and added some comments.
x/feegrant/filtered_fee.go
Outdated
return allowance.Accept(ctx, fee, msgs) | ||
remove, reserr := allowance.Accept(ctx, fee, msgs) | ||
if !remove { | ||
a.Allowance, err = types.NewAnyWithValue(allowance.(proto.Message)) |
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.
Assign the changed allowance to the old one, so the change could be applied.
There is no need to do this job if remove
is true
apparently.
@@ -0,0 +1,208 @@ | |||
package feegrant_test |
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 test has been copied from basic_fee_test.go.
x/feegrant/filtered_fee_test.go
Outdated
"msg contained": { | ||
allowance: &feegrant.BasicAllowance{}, | ||
msgs: []string{"/cosmos.feegrant.v1beta1.MsgRevokeAllowance"}, | ||
accept: true, | ||
}, |
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.
It is the simplest case. In the test, the called message would be /cosmos.feegrant.v1beta1.MsgRevokeAllowance
, so it must be accepted.
x/feegrant/filtered_fee_test.go
Outdated
"msg not contained": { | ||
allowance: &feegrant.BasicAllowance{}, | ||
msgs: []string{"/cosmos.feegrant.v1beta1.MsgGrantAllowance"}, | ||
accept: false, | ||
}, |
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 added this case to confirm that Accept()
rejects the message if it is not in its list.
Other than this case, these are just borrowed cases from basic_fee_test.go.
x/feegrant/filtered_fee_test.go
Outdated
updatedGrant := func(granter, grantee sdk.AccAddress, | ||
allowance feegrant.FeeAllowanceI) feegrant.Grant { | ||
newGrant, err := feegrant.NewGrant( | ||
granter, | ||
grantee, | ||
allowance) | ||
require.NoError(t, err) | ||
|
||
cdc := simapp.MakeTestEncodingConfig().Codec | ||
bz, err := cdc.Marshal(&newGrant) | ||
require.NoError(t, err) | ||
|
||
var loaded feegrant.Grant | ||
err = cdc.Unmarshal(bz, &loaded) | ||
require.NoError(t, err) | ||
return loaded | ||
} |
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.
Mimic the logic as best as I can.
After Accept()
has been called, the updated grant should be saved, so I added Marshal()
.
To check the values are all correct, we must load the grant again, so I added Unmarshal()
.
require.NoError(t, err) | ||
feeAllowance, err := newAllowance.(*feegrant.AllowedMsgAllowance).GetAllowance() | ||
require.NoError(t, err) | ||
assert.Equal(t, tc.remains, feeAllowance.(*feegrant.BasicAllowance).SpendLimit) |
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.
Finally, the assert against SpendLimit
has been made.
Is |
According to the documents and implementation, yes, it has to be mutated. cosmos-sdk/proto/cosmos/feegrant/v1beta1/feegrant.proto Lines 19 to 22 in 0a3660d
cosmos-sdk/x/feegrant/basic_fee.go Lines 20 to 36 in 3582cce
The modification I'm adding is just saving the change into the state correctly. |
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.
Changes LGTM, but I just don't have enough context about this module to give it an ACK. @AmauryM who designed or implemented the feegrant 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.
Thanks @0Tech! the fix in x/feegrant/filtered_fee.go LGTM
Could you clean up the tests a little bit? they are really hard to follow
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.
actually, let's make the test simpler before merging.
x/feegrant/filtered_fee_test.go
Outdated
if !removed { | ||
// save the new grant | ||
newGrant, err := feegrant.NewGrant( | ||
sdk.AccAddress(grant.Granter), | ||
sdk.AccAddress(grant.Grantee), | ||
allowance) | ||
require.NoError(t, err) | ||
|
||
cdc := simapp.MakeTestEncodingConfig().Codec | ||
bz, err := cdc.Marshal(&newGrant) | ||
require.NoError(t, err) | ||
|
||
// load the grant | ||
var loadedGrant feegrant.Grant | ||
err = cdc.Unmarshal(bz, &loadedGrant) | ||
require.NoError(t, err) | ||
|
||
newAllowance, err := newGrant.GetGrant() | ||
require.NoError(t, err) | ||
feeAllowance, err := newAllowance.(*feegrant.AllowedMsgAllowance).GetAllowance() | ||
require.NoError(t, err) | ||
assert.Equal(t, tc.remains, feeAllowance.(*feegrant.BasicAllowance).SpendLimit) | ||
} |
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 actually don't understand this block so well, still.
Can we simply do:
if !removed {
assert.Equal(t, tc.remains, allowance.Allowance.GetCachedValue().(*feegrant.BasicAllowance).SpendLimit)
}
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.
This block is the whole point of this fix. With the simplified version, we cannot check whether the allowance has been updated correctly, because the cached value was correct even before the fix.
This patch is forcing the cached value applied to the state. We must marshal & unmarshal it, which simulates the actual process.
That was the last redundant func()
meant for. If you don't mind, I can wrap it with func()
again (or a block with curly brackets suffice?), providing meaningful name and comments.
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, there was a mistake during the modification. I think this has confused you.
newGrant
at line 185 must be loadedGrant
.
I will also apply the fix after your response.
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 Understood. Yes loadedGrant
on L185 sounds already clearer.
Could you add some comments, e.g. around marshaling to simulate the actual process of putting in block?
If you don't mind, I can wrap it with func() again (or a block with curly brackets suffice?), providing meaningful name and comments.
I don't think that's idiomatic go. Using newlines and comments should be enough to describe what you're achieving.
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 !removed {
assert.Equal(t, tc.remains, allowance.GetAllowance().(*feegrant.BasicAllowance).SpendLimit)
}
I align with @AmauryM here, this thing works I guess, can you verify that this assert should be fail with the earlier code and passes with the changes in this PR. if that works no need of creating the Grant and marshals.
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 verified that the simplified version does not fail with both of the earlier code and the new code. And I also verified that the longer version with marshaling fails with the earlier 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.
looks good, few nits!
}{ | ||
"msg contained": { | ||
allowance: &feegrant.BasicAllowance{}, | ||
msgs: []string{sdk.MsgTypeURL(&call)}, |
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.
msgs: []string{sdk.MsgTypeURL(&call)}, | |
msgs: []string{sdk.MsgTypeURL(&banktypes.MsgSend{})}, |
we can remove call
if this works.
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 think it could be more straight-forward to use the variable call
, because we don't need to compare the msgs in the cases with the actual calling msg in the loop. To be more pedantic, I have to make sure that the msg type of "msg not contained" case is not identical to that of call
, but I think it's not necessary.
x/feegrant/filtered_fee.go
Outdated
a.Allowance, err = types.NewAnyWithValue(allowance.(proto.Message)) | ||
if err != nil { | ||
return false, sdkerrors.Wrapf(sdkerrors.ErrPackAny, "cannot proto marshal %T", allowance) | ||
} |
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 separate this into a separate method AllowedMsgAllowance.SetAllowance(allowance)
x/feegrant/filtered_fee_test.go
Outdated
if !removed { | ||
// save the new grant | ||
newGrant, err := feegrant.NewGrant( | ||
sdk.AccAddress(grant.Granter), | ||
sdk.AccAddress(grant.Grantee), | ||
allowance) | ||
require.NoError(t, err) | ||
|
||
cdc := simapp.MakeTestEncodingConfig().Codec | ||
bz, err := cdc.Marshal(&newGrant) | ||
require.NoError(t, err) | ||
|
||
// load the grant | ||
var loadedGrant feegrant.Grant | ||
err = cdc.Unmarshal(bz, &loadedGrant) | ||
require.NoError(t, err) | ||
|
||
newAllowance, err := newGrant.GetGrant() | ||
require.NoError(t, err) | ||
feeAllowance, err := newAllowance.(*feegrant.AllowedMsgAllowance).GetAllowance() | ||
require.NoError(t, err) | ||
assert.Equal(t, tc.remains, feeAllowance.(*feegrant.BasicAllowance).SpendLimit) | ||
} |
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 !removed {
assert.Equal(t, tc.remains, allowance.GetAllowance().(*feegrant.BasicAllowance).SpendLimit)
}
I align with @AmauryM here, this thing works I guess, can you verify that this assert should be fail with the earlier code and passes with the changes in this PR. if that works no need of creating the Grant and marshals.
grant, err := feegrant.NewGrant(granter, grantee, allowance) | ||
require.NoError(t, err) |
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.
grant, err := feegrant.NewGrant(granter, grantee, allowance) | |
require.NoError(t, err) |
Co-authored-by: atheeshp <[email protected]>
Co-authored-by: atheeshp <[email protected]>
Description
Closes: #10563
By the fix, AllowedMsgAllowance updates its allowance after the change in
Accept()
.To catch the corresponding issue, the fix also adds new unit tests.
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