Skip to content

Commit

Permalink
merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
nullpointer0x00 committed Jan 25, 2024
2 parents 4949743 + e7615d6 commit ecd81aa
Show file tree
Hide file tree
Showing 11 changed files with 401 additions and 7 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,14 @@ Ref: https://keepachangelog.com/en/1.0.0/

* Add the ibcratelimit module [#1498](https://github.com/provenance-io/provenance/issues/1498).
* Add NAV support for metadata scopes [#1749](https://github.com/provenance-io/provenance/issues/1749).
* Add fix for NAV units to tourmaline upgrade handler [#1815](https://github.com/provenance-io/provenance/issues/1815).

### Improvements

* Add upgrade handler for 1.18 [#1756](https://github.com/provenance-io/provenance/pull/1756).
* Remove the rust upgrade handlers [PR 1774](https://github.com/provenance-io/provenance/pull/1774).
* Allow bypassing the config warning wait using an environment variable [PR 1810](https://github.com/provenance-io/provenance/pull/1810).
* Filter out empty distribution events from begin blocker [#1822](https://github.com/provenance-io/provenance/pull/1822).

### Bug Fixes

Expand All @@ -70,7 +72,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
- Bump `github/codeql-action` from 2 to 3 ([#1784](https://github.com/provenance-io/provenance/pull/1784))
- Bump `actions/download-artifact` from 3 to 4 ([#1785](https://github.com/provenance-io/provenance/pull/1785))
- Bump `actions/upload-artifact` from 3 to 4 ([#1785](https://github.com/provenance-io/provenance/pull/1785))
- Bump `google.golang.org/grpc` from 1.59.0 to 1.60.1 ([#1794](https://github.com/provenance-io/provenance/pull/1794))
- Bump `google.golang.org/grpc` from 1.59.0 to 1.61.0 ([#1794](https://github.com/provenance-io/provenance/pull/1794), [#1820](https://github.com/provenance-io/provenance/pull/1820))
- Bump `golang.org/x/crypto` from 0.14.0 to 0.17.0 ([#1788](https://github.com/provenance-io/provenance/pull/1788))
- Bump `cosmossdk.io/errors` from 1.0.0 to 1.0.1 ([#1806](https://github.com/provenance-io/provenance/pull/1806))
- Bump `actions/cache` from 3 to 4 ([#1817](https://github.com/provenance-io/provenance/pull/1817))
Expand Down
28 changes: 27 additions & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -1124,7 +1124,33 @@ func (app *App) Name() string { return app.BaseApp.Name() }

// BeginBlocker application updates every begin block
func (app *App) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock {
return app.mm.BeginBlock(ctx, req)
responseBeginBlock := app.mm.BeginBlock(ctx, req)
responseBeginBlock.Events = filterBeginBlockerEvents(responseBeginBlock)
return responseBeginBlock
}

// filterBeginBlockerEvents filters out events from a given abci.ResponseBeginBlock according to the criteria defined in shouldFilterEvent.
func filterBeginBlockerEvents(responseBeginBlock abci.ResponseBeginBlock) []abci.Event {
filteredEvents := make([]abci.Event, 0)
for _, e := range responseBeginBlock.Events {
if shouldFilterEvent(e) {
continue
}
filteredEvents = append(filteredEvents, e)
}
return filteredEvents
}

// shouldFilterEvent checks if an abci.Event should be filtered based on its type and attributes.
func shouldFilterEvent(e abci.Event) bool {
if e.Type == distrtypes.EventTypeCommission || e.Type == distrtypes.EventTypeRewards || e.Type == distrtypes.EventTypeProposerReward || e.Type == banktypes.EventTypeTransfer || e.Type == banktypes.EventTypeCoinSpent || e.Type == banktypes.EventTypeCoinReceived {
for _, a := range e.Attributes {
if string(a.Key) == sdk.AttributeKeyAmount && len(a.Value) == 0 {
return true
}
}
}
return false
}

// EndBlocker application updates every end block
Expand Down
102 changes: 102 additions & 0 deletions app/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
sdksim "github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"

abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
Expand Down Expand Up @@ -322,3 +324,103 @@ func assertAddrNotInAccounts(t *testing.T, addr sdk.AccAddress, addrName string,
}
return true
}

func createEvent(eventType string, attributes []abci.EventAttribute) abci.Event {
return abci.Event{
Type: eventType,
Attributes: attributes,
}
}

func TestShouldFilterEvent(t *testing.T) {
tests := []struct {
name string
event abci.Event
expect bool
}{
{"Empty commission event", createEvent(distrtypes.EventTypeCommission, []abci.EventAttribute{{Key: []byte("amount"), Value: []byte("")}}), true},
{"Nil commission event", createEvent(distrtypes.EventTypeCommission, []abci.EventAttribute{{Key: []byte("amount"), Value: nil}}), true},
{"Non-empty commission event", createEvent(distrtypes.EventTypeCommission, []abci.EventAttribute{{Key: []byte("amount"), Value: []byte("100")}}), false},

{"Empty rewards event", createEvent(distrtypes.EventTypeRewards, []abci.EventAttribute{{Key: []byte("amount"), Value: []byte("")}}), true},
{"Nil rewards event", createEvent(distrtypes.EventTypeRewards, []abci.EventAttribute{{Key: []byte("amount"), Value: nil}}), true},
{"Non-empty rewards event", createEvent(distrtypes.EventTypeRewards, []abci.EventAttribute{{Key: []byte("amount"), Value: []byte("100")}}), false},

{"Empty proposer_reward event", createEvent(distrtypes.EventTypeProposerReward, []abci.EventAttribute{{Key: []byte("amount"), Value: []byte("")}}), true},
{"Nil proposer_reward event", createEvent(distrtypes.EventTypeProposerReward, []abci.EventAttribute{{Key: []byte("amount"), Value: nil}}), true},
{"Non-empty proposer_reward event", createEvent(distrtypes.EventTypeProposerReward, []abci.EventAttribute{{Key: []byte("amount"), Value: []byte("100")}}), false},

{"Empty transfer event", createEvent(banktypes.EventTypeTransfer, []abci.EventAttribute{{Key: []byte("amount"), Value: []byte("")}}), true},
{"Nil transfer event", createEvent(banktypes.EventTypeTransfer, []abci.EventAttribute{{Key: []byte("amount"), Value: nil}}), true},
{"Non-empty transfer event", createEvent(banktypes.EventTypeTransfer, []abci.EventAttribute{{Key: []byte("amount"), Value: []byte("100")}}), false},

{"Empty coin_spent event", createEvent(banktypes.EventTypeCoinSpent, []abci.EventAttribute{{Key: []byte("amount"), Value: []byte("")}}), true},
{"Nil coin_spent event", createEvent(banktypes.EventTypeCoinSpent, []abci.EventAttribute{{Key: []byte("amount"), Value: nil}}), true},
{"Non-empty coin_spent event", createEvent(banktypes.EventTypeCoinSpent, []abci.EventAttribute{{Key: []byte("amount"), Value: []byte("100")}}), false},

{"Empty coin_received event", createEvent(banktypes.EventTypeCoinReceived, []abci.EventAttribute{{Key: []byte("amount"), Value: []byte("")}}), true},
{"Nil coin_received event", createEvent(banktypes.EventTypeCoinReceived, []abci.EventAttribute{{Key: []byte("amount"), Value: nil}}), true},
{"Non-empty coin_received event", createEvent(banktypes.EventTypeCoinReceived, []abci.EventAttribute{{Key: []byte("amount"), Value: []byte("100")}}), false},

{"Unhandled event type with empty amount", createEvent("unhandled_type", []abci.EventAttribute{{Key: []byte("amount"), Value: []byte("")}}), false},
{"Unhandled event type with nil amount", createEvent("unhandled_type", []abci.EventAttribute{{Key: []byte("amount"), Value: nil}}), false},
{"Unhandled event type with non-empty amount", createEvent("unhandled_type", []abci.EventAttribute{{Key: []byte("amount"), Value: []byte("100")}}), false},
{"Event with no attributes", createEvent(distrtypes.EventTypeCommission, []abci.EventAttribute{}), false},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
result := shouldFilterEvent(tc.event)
assert.Equal(t, tc.expect, result, "Test %v failed: expected %v, got %v", tc.name, tc.expect, result)
})
}
}

func TestFilterBeginBlockerEvents(t *testing.T) {
tests := []struct {
name string
events []abci.Event
expected []abci.Event
}{
{
name: "Filter out events with empty amounts",
events: []abci.Event{
createEvent(distrtypes.EventTypeCommission, []abci.EventAttribute{{Key: []byte(sdk.AttributeKeyAmount), Value: []byte("")}}),
createEvent(distrtypes.EventTypeRewards, []abci.EventAttribute{{Key: []byte(sdk.AttributeKeyAmount), Value: []byte("100")}}),
},
expected: []abci.Event{
createEvent(distrtypes.EventTypeRewards, []abci.EventAttribute{{Key: []byte(sdk.AttributeKeyAmount), Value: []byte("100")}}),
},
},
{
name: "No filtering when all events are valid",
events: []abci.Event{
createEvent(banktypes.EventTypeTransfer, []abci.EventAttribute{{Key: []byte(sdk.AttributeKeyAmount), Value: []byte("100")}}),
},
expected: []abci.Event{
createEvent(banktypes.EventTypeTransfer, []abci.EventAttribute{{Key: []byte(sdk.AttributeKeyAmount), Value: []byte("100")}}),
},
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
responseBeginBlock := abci.ResponseBeginBlock{Events: tc.events}
actualEvents := filterBeginBlockerEvents(responseBeginBlock)
assert.Equal(t, len(tc.expected), len(actualEvents), "Number of events mismatch")

for i, expectedEvent := range tc.expected {
actualEvent := actualEvents[i]
assert.Equal(t, expectedEvent.Type, actualEvent.Type, "Event types mismatch")

assert.Equal(t, len(expectedEvent.Attributes), len(actualEvent.Attributes), "Number of attributes mismatch in event %v", expectedEvent.Type)

for j, expectedAttribute := range expectedEvent.Attributes {
actualAttribute := actualEvent.Attributes[j]
assert.Equal(t, expectedAttribute.Key, actualAttribute.Key, "Attribute keys mismatch in event %v", expectedEvent.Type)
assert.Equal(t, expectedAttribute.Value, actualAttribute.Value, "Attribute values mismatch in event %v", expectedEvent.Type)
}
}
})
}
}
26 changes: 26 additions & 0 deletions app/upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ var upgrades = map[string]appUpgrade{
}

removeInactiveValidatorDelegations(ctx, app)
convertNavUnits(ctx, app)

return vm, nil
},
Expand All @@ -141,6 +142,7 @@ var upgrades = map[string]appUpgrade{
}

removeInactiveValidatorDelegations(ctx, app)
convertNavUnits(ctx, app)

return vm, nil
},
Expand Down Expand Up @@ -349,3 +351,27 @@ func updateIbcMarkerDenomMetadata(ctx sdk.Context, app *App) {
})
ctx.Logger().Info("Done updating ibc marker denom metadata")
}

// convertNavUnits iterates all the net asset values and updates their units if they are using usd.
func convertNavUnits(ctx sdk.Context, app *App) {
ctx.Logger().Info("Converting NAV units")
err := app.MarkerKeeper.IterateAllNetAssetValues(ctx, func(markerAddr sdk.AccAddress, nav markertypes.NetAssetValue) (stop bool) {
if nav.Price.Denom == markertypes.UsdDenom {
nav.Price.Amount = nav.Price.Amount.Mul(math.NewInt(10))
marker, err := app.MarkerKeeper.GetMarker(ctx, markerAddr)
if err != nil {
ctx.Logger().Error(fmt.Sprintf("Unable to get marker for address: %s, error: %s", markerAddr, err))
return false
}
err = app.MarkerKeeper.SetNetAssetValue(ctx, marker, nav, "upgrade")
if err != nil {
ctx.Logger().Error(fmt.Sprintf("Unable to set net asset value for marker: %s, error: %s", markerAddr, err))
return false
}
}
return false
})
if err != nil {
ctx.Logger().Error(fmt.Sprintf("Unable to iterate all net asset values error: %s", err))
}
}
115 changes: 113 additions & 2 deletions app/upgrades_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -425,13 +425,17 @@ func (s *UpgradeTestSuite) TestSaffron() {
}

func (s *UpgradeTestSuite) TestTourmalineRC1() {
expInLog := []string{}
expInLog := []string{
"INF Converting NAV units",
}

s.AssertUpgradeHandlerLogs("tourmaline-rc1", expInLog, nil)
}

func (s *UpgradeTestSuite) TestTourmaline() {
expInLog := []string{}
expInLog := []string{
"INF Converting NAV units",
}

s.AssertUpgradeHandlerLogs("tourmaline", expInLog, nil)
}
Expand Down Expand Up @@ -780,3 +784,110 @@ func (s *UpgradeTestSuite) TestSetExchangeParams() {
})
}
}

func (s *UpgradeTestSuite) TestConvertNAVUnits() {
tests := []struct {
name string
markerNavs []sdk.Coins
expected []sdk.Coins
}{
{
name: "should work with no markers",
markerNavs: []sdk.Coins{},
expected: []sdk.Coins{},
},
{
name: "should work with one marker no usd denom",
markerNavs: []sdk.Coins{
sdk.NewCoins(sdk.NewInt64Coin("jackthecat", 1)),
},
expected: []sdk.Coins{
sdk.NewCoins(sdk.NewInt64Coin("jackthecat", 1)),
},
},
{
name: "should work with multiple markers no usd denom",
markerNavs: []sdk.Coins{
sdk.NewCoins(sdk.NewInt64Coin("jackthecat", 1)),
sdk.NewCoins(sdk.NewInt64Coin("georgethedog", 2)),
},
expected: []sdk.Coins{
sdk.NewCoins(sdk.NewInt64Coin("jackthecat", 1)),
sdk.NewCoins(sdk.NewInt64Coin("georgethedog", 2)),
},
},
{
name: "should work with one marker with usd denom",
markerNavs: []sdk.Coins{
sdk.NewCoins(sdk.NewInt64Coin("jackthecat", 1), sdk.NewInt64Coin(markertypes.UsdDenom, 2)),
},
expected: []sdk.Coins{
sdk.NewCoins(sdk.NewInt64Coin("jackthecat", 1), sdk.NewInt64Coin(markertypes.UsdDenom, 20)),
},
},
{
name: "should work with multiple markers with usd denom",
markerNavs: []sdk.Coins{
sdk.NewCoins(sdk.NewInt64Coin("jackthecat", 1), sdk.NewInt64Coin(markertypes.UsdDenom, 3)),
sdk.NewCoins(sdk.NewInt64Coin("georgethedog", 2), sdk.NewInt64Coin(markertypes.UsdDenom, 4)),
},
expected: []sdk.Coins{
sdk.NewCoins(sdk.NewInt64Coin("jackthecat", 1), sdk.NewInt64Coin(markertypes.UsdDenom, 30)),
sdk.NewCoins(sdk.NewInt64Coin("georgethedog", 2), sdk.NewInt64Coin(markertypes.UsdDenom, 40)),
},
},
}

for _, tc := range tests {
s.Run(tc.name, func() {
// Create the marker
for i, prices := range tc.markerNavs {
address := sdk.AccAddress(fmt.Sprintf("marker%d", i))
marker := markertypes.NewEmptyMarkerAccount(fmt.Sprintf("coin%d", i), address.String(), []markertypes.AccessGrant{})
marker.Supply = sdk.OneInt()
s.Require().NoError(s.app.MarkerKeeper.AddMarkerAccount(s.ctx, marker), "AddMarkerAccount() error")

var navs []markertypes.NetAssetValue
for _, price := range prices {
navs = append(navs, markertypes.NewNetAssetValue(price, uint64(1)))
navAddr := sdk.AccAddress(price.Denom)
if acc, _ := s.app.MarkerKeeper.GetMarkerByDenom(s.ctx, price.Denom); acc == nil {
navMarker := markertypes.NewEmptyMarkerAccount(price.Denom, navAddr.String(), []markertypes.AccessGrant{})
navMarker.Supply = sdk.OneInt()
s.Require().NoError(s.app.MarkerKeeper.AddMarkerAccount(s.ctx, navMarker), "AddMarkerAccount() error")
}
}
s.Require().NoError(s.app.MarkerKeeper.AddSetNetAssetValues(s.ctx, marker, navs, "AddSetNetAssetValues() error"))
}

// Test Logic
convertNavUnits(s.ctx, s.app)
for i := range tc.markerNavs {
marker, err := s.app.MarkerKeeper.GetMarkerByDenom(s.ctx, fmt.Sprintf("coin%d", i))
s.Require().NoError(err, "GetMarkerByDenom() error")
var prices sdk.Coins

s.app.MarkerKeeper.IterateNetAssetValues(s.ctx, marker.GetAddress(), func(state markertypes.NetAssetValue) (stop bool) {
prices = append(prices, state.Price)
return false
})
s.Require().EqualValues(tc.expected[i], prices, "should update prices correctly for nav")
}

// Destroy the marker
for i, prices := range tc.markerNavs {
coin := fmt.Sprintf("coin%d", i)
marker, err := s.app.MarkerKeeper.GetMarkerByDenom(s.ctx, coin)
s.Require().NoError(err, "GetMarkerByDenom() error")
s.app.MarkerKeeper.RemoveMarker(s.ctx, marker)

// We need to remove the nav markers
for _, price := range prices {
if navMarker, _ := s.app.MarkerKeeper.GetMarkerByDenom(s.ctx, price.Denom); navMarker != nil {
s.app.MarkerKeeper.RemoveMarker(s.ctx, navMarker)
}
}
}
})
}
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ require (
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
golang.org/x/text v0.14.0
google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f
google.golang.org/grpc v1.60.1
google.golang.org/grpc v1.61.0
google.golang.org/protobuf v1.32.0
gopkg.in/yaml.v2 v2.4.0

Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1790,8 +1790,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu
google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU=
google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0=
google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
Expand Down
18 changes: 18 additions & 0 deletions x/marker/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,24 @@ func (k Keeper) IterateNetAssetValues(ctx sdk.Context, markerAddr sdk.AccAddress
return nil
}

// IterateAllNetAssetValues iterates all net asset values
func (k Keeper) IterateAllNetAssetValues(ctx sdk.Context, handler func(sdk.AccAddress, types.NetAssetValue) (stop bool)) error {
store := ctx.KVStore(k.storeKey)
it := sdk.KVStorePrefixIterator(store, types.NetAssetValuePrefix)
defer it.Close()
for ; it.Valid(); it.Next() {
markerAddr := types.GetMarkerFromNetAssetValueKey(it.Key())
var markerNav types.NetAssetValue
err := k.cdc.Unmarshal(it.Value(), &markerNav)
if err != nil {
return err
} else if handler(markerAddr, markerNav) {
break
}
}
return nil
}

// RemoveNetAssetValues removes all net asset values for a marker
func (k Keeper) RemoveNetAssetValues(ctx sdk.Context, markerAddr sdk.AccAddress) {
store := ctx.KVStore(k.storeKey)
Expand Down
Loading

0 comments on commit ecd81aa

Please sign in to comment.