Skip to content

Commit 6786515

Browse files
songgaoyealjo242
andauthored
fix(types/address): correct sort comparator in Compose to satisfy strict weak ordering (#25944)
Co-authored-by: Alex | Cosmos Labs <[email protected]>
1 parent d9bd545 commit 6786515

3 files changed

Lines changed: 25 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ This patch release contains only minor dependency bumps.
155155
* (x/group) [#25917](https://github.com/cosmos/cosmos-sdk/pull/25917) Prevent creation of zero-weight groups.
156156
* (x/group) [#25919](https://github.com/cosmos/cosmos-sdk/pull/25919) add safer type assertions to group `DecisionPolicy` getter calls.
157157
* (x/group) [#25920](https://github.com/cosmos/cosmos-sdk/pull/25920) Expand voting period check to verify period is positive instead of nonzero.
158+
* (types/address) [#25944] (https://github.com/cosmos/cosmos-sdk/pull/25944) correct sort comparator in Compose to satisfy strict weak ordering.
158159
* (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.
159160

160161
### Deprecated

types/address/hash.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func Compose(typ string, subAddresses []Addressable) ([]byte, error) {
5353
totalLen += len(as[i])
5454
}
5555

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

66+
func lessBytes(a, b []byte) bool {
67+
return bytes.Compare(a, b) < 0
68+
}
69+
6670
// Module is a specialized version of a composed address for modules. Each module account
6771
// is constructed from a module name and a sequence of derivation keys (at least one
6872
// derivation key must be provided). The derivation keys must be unique

types/address/hash_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,25 @@ func (suite *AddressSuite) TestComposed() {
6161
_, err = Compose(typ, []Addressable{a1, addrMock{make([]byte, 300)}})
6262
assert.Error(err)
6363
assert.Contains(err.Error(), "should be max 255 bytes, got 300")
64+
65+
// strict weak ordering: irreflexive and asymmetric
66+
la := []byte{1, 2}
67+
lb := []byte{3, 4}
68+
assert.False(lessBytes(la, la), "lessBytes must be irreflexive")
69+
assert.True(lessBytes(la, lb), "lessBytes(a,b) must be true when a < b")
70+
assert.False(lessBytes(lb, la), "lessBytes must be asymmetric")
71+
72+
// Compose must be order-independent even when sub-addresses include duplicates
73+
da := addrMock{[]byte{1, 2, 3}}
74+
db := addrMock{[]byte{4, 5, 6}}
75+
aab, err := Compose("test", []Addressable{da, da, db})
76+
assert.NoError(err)
77+
aba, err := Compose("test", []Addressable{da, db, da})
78+
assert.NoError(err)
79+
baa, err := Compose("test", []Addressable{db, da, da})
80+
assert.NoError(err)
81+
assert.Equal(aab, aba, "Compose must be order-independent with duplicates")
82+
assert.Equal(aab, baa, "Compose must be order-independent with duplicates")
6483
}
6584

6685
func (suite *AddressSuite) TestModule() {

0 commit comments

Comments
 (0)