Skip to content
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: deterministic map iteration #12781

Merged
merged 13 commits into from Aug 17, 2022
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -54,6 +54,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* [#12634](https://github.com/cosmos/cosmos-sdk/pull/12634) Move `sdk.Dec` to math package.
* [#12596](https://github.com/cosmos/cosmos-sdk/pull/12596) Remove all imports of the non-existent gogo/protobuf v1.3.3 to ease downstream use and go workspaces.
* [#12187](https://github.com/cosmos/cosmos-sdk/pull/12187) Add batch operation for x/nft module.
* [#12693](https://github.com/cosmos/cosmos-sdk/pull/12693) Make sure the order of each node is consistent when emitting proto events.

### State Machine Breaking

Expand Down
9 changes: 8 additions & 1 deletion types/events.go
Expand Up @@ -3,6 +3,8 @@ package types
import (
"encoding/json"
"fmt"
"golang.org/x/exp/maps"
"golang.org/x/exp/slices"
"reflect"
"sort"
"strings"
Expand Down Expand Up @@ -87,8 +89,13 @@ func TypedEventToEvent(tev proto.Message) (Event, error) {
return Event{}, err
}

// sort the keys to ensure the order is always the same
tac0turtle marked this conversation as resolved.
Show resolved Hide resolved
keys := maps.Keys(attrMap)
slices.Sort(keys)

attrs := make([]abci.EventAttribute, 0, len(attrMap))
for k, v := range attrMap {
for _, k := range keys {
v := attrMap[k]
attrs = append(attrs, abci.EventAttribute{
Key: k,
Value: string(v),
Expand Down
15 changes: 15 additions & 0 deletions types/events_test.go
Expand Up @@ -67,6 +67,21 @@ func (s *eventsTestSuite) TestEventManager() {
s.Require().Equal(em.Events(), events.AppendEvent(event))
}

func (s *eventsTestSuite) TestEmitTypedEvent() {
s.Run("deterministic key-value order", func() {
for i := 0; i < 10; i++ {
em := sdk.NewEventManager()
coin := sdk.NewCoin("fakedenom", sdk.NewInt(1999999))
s.Require().NoError(em.EmitTypedEvent(&coin))
s.Require().Len(em.Events(), 1)
attrs := em.Events()[0].Attributes
s.Require().Len(attrs, 2)
s.Require().Equal(attrs[0].Key, "amount")
s.Require().Equal(attrs[1].Key, "denom")
}
})
}

func (s *eventsTestSuite) TestEventManagerTypedEvents() {
em := sdk.NewEventManager()

Expand Down