Skip to content
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ This patch release contains only minor dependency bumps.
* (x/group) [#25917](https://github.com/cosmos/cosmos-sdk/pull/25917) Prevent creation of zero-weight groups.
* (x/group) [#25919](https://github.com/cosmos/cosmos-sdk/pull/25919) add safer type assertions to group `DecisionPolicy` getter calls.
* (x/group) [#25920](https://github.com/cosmos/cosmos-sdk/pull/25920) Expand voting period check to verify period is positive instead of nonzero.
* (types/address) [#25944] (https://github.com/cosmos/cosmos-sdk/pull/25944) correct sort comparator in Compose to satisfy strict weak ordering.
* (baseapp) [#26063](https://github.com/cosmos/cosmos-sdk/pull/26063) Fixes an issue where values embedded in context during ante handling were wiped after the handlers returned.

### Deprecated
Expand Down
6 changes: 5 additions & 1 deletion types/address/hash.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func Compose(typ string, subAddresses []Addressable) ([]byte, error) {
totalLen += len(as[i])
}

sort.Slice(as, func(i, j int) bool { return bytes.Compare(as[i], as[j]) <= 0 })
sort.Slice(as, func(i, j int) bool { return lessBytes(as[i], as[j]) })
key := make([]byte, totalLen)
offset := 0
for i := range as {
Expand All @@ -63,6 +63,10 @@ func Compose(typ string, subAddresses []Addressable) ([]byte, error) {
return Hash(typ, key), nil
}

func lessBytes(a, b []byte) bool {
return bytes.Compare(a, b) < 0
}

// Module is a specialized version of a composed address for modules. Each module account
// is constructed from a module name and a sequence of derivation keys (at least one
// derivation key must be provided). The derivation keys must be unique
Expand Down
19 changes: 19 additions & 0 deletions types/address/hash_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,25 @@ func (suite *AddressSuite) TestComposed() {
_, err = Compose(typ, []Addressable{a1, addrMock{make([]byte, 300)}})
assert.Error(err)
assert.Contains(err.Error(), "should be max 255 bytes, got 300")

// strict weak ordering: irreflexive and asymmetric
la := []byte{1, 2}
lb := []byte{3, 4}
assert.False(lessBytes(la, la), "lessBytes must be irreflexive")
assert.True(lessBytes(la, lb), "lessBytes(a,b) must be true when a < b")
assert.False(lessBytes(lb, la), "lessBytes must be asymmetric")

// Compose must be order-independent even when sub-addresses include duplicates
da := addrMock{[]byte{1, 2, 3}}
db := addrMock{[]byte{4, 5, 6}}
aab, err := Compose("test", []Addressable{da, da, db})
assert.NoError(err)
aba, err := Compose("test", []Addressable{da, db, da})
assert.NoError(err)
baa, err := Compose("test", []Addressable{db, da, da})
assert.NoError(err)
assert.Equal(aab, aba, "Compose must be order-independent with duplicates")
assert.Equal(aab, baa, "Compose must be order-independent with duplicates")
}

func (suite *AddressSuite) TestModule() {
Expand Down
Loading