diff --git a/golang/cosmos/types/address_hooks.go b/golang/cosmos/types/address_hooks.go index 4c4fcfd0803..b26fe1e85f4 100644 --- a/golang/cosmos/types/address_hooks.go +++ b/golang/cosmos/types/address_hooks.go @@ -33,8 +33,8 @@ func init() { } } -// ExtractBaseAddress extracts the base address from a parameterized address. -// It removes all subpath and query components from addr. +// ExtractBaseAddress extracts the base address from an Address Hook. It +// returns addr verbatim if it is not an Address Hook. func ExtractBaseAddress(addr string) (string, error) { baseAddr, _, err := SplitHookedAddress(addr) if err != nil { @@ -63,13 +63,14 @@ func SplitHookedAddress(addr string) (string, []byte, error) { b := 0 for i := BaseAddressLengthBytes - 1; i >= 0; i -= 1 { - by := bz[len(bz)-1-i] + byteVal := bz[len(bz)-1-i] b <<= 8 - b |= int(by) + b |= int(byteVal) } - if b > len(bz)-BaseAddressLengthBytes { - return "", []byte{}, fmt.Errorf("base address length 0x%x is longer than specimen length 0x%x", b, len(bz)-BaseAddressLengthBytes) + payloadEnd := len(bz) - BaseAddressLengthBytes + if b > payloadEnd { + return "", []byte{}, fmt.Errorf("base address length 0x%x is longer than payload end 0x%x", b, payloadEnd) } baseAddressBuf := bz[0:b] @@ -78,7 +79,7 @@ func SplitHookedAddress(addr string) (string, []byte, error) { return "", []byte{}, err } - return baseAddress, bz[b:], nil + return baseAddress, bz[b:payloadEnd], nil } // JoinHookedAddress joins a base bech32 address with hook data to create a @@ -91,15 +92,21 @@ func JoinHookedAddress(baseAddr string, hookData []byte) (string, error) { } b := len(bz) - if b > 0xffff { - return "", fmt.Errorf("base address length 0x%x is longer than the maximum 0x%x", b, 1<<(8*BaseAddressLengthBytes-1)+1) + maxB := 1<<(8*BaseAddressLengthBytes-1) + 1 + if b > maxB { + return "", fmt.Errorf("base address length 0x%x is longer than the maximum 0x%x", b, maxB) } payload := make([]byte, 0, len(AddressHookMagic)+b+len(hookData)+BaseAddressLengthBytes) payload = append(payload, AddressHookMagic...) payload = append(payload, bz...) payload = append(payload, hookData...) - payload = append(payload, byte(b>>8), byte(b)) + baLen := make([]byte, BaseAddressLengthBytes) + for i := BaseAddressLengthBytes - 1; i >= 0; i -= 1 { + baLen[i] = byte(b) + b >>= 8 + } + payload = append(payload, baLen...) return bech32.ConvertAndEncode(prefix, payload) } diff --git a/golang/cosmos/types/address_hooks_test.go b/golang/cosmos/types/address_hooks_test.go index e20e1540811..8ae9faad1e7 100644 --- a/golang/cosmos/types/address_hooks_test.go +++ b/golang/cosmos/types/address_hooks_test.go @@ -54,6 +54,10 @@ func TestExtractBaseAddress(t *testing.T) { require.NotEqual(t, b.addr, addr) } else { require.Equal(t, b.addr, addr) + addr, hookData, err := types.SplitHookedAddress(addrHook) + require.NoError(t, err) + require.Equal(t, b.addr, addr) + require.Equal(t, s.hookStr, string(hookData)) } } }) @@ -68,10 +72,23 @@ func TestExtractBaseAddressFromPacket(t *testing.T) { channeltypes.RegisterInterfaces(ir) clienttypes.RegisterInterfaces(ir) - cosmosHook, err := types.JoinHookedAddress("cosmos1qqxuevtt", []byte("?foo=bar&baz=bot#fragment")) + cosmosAddr := "cosmos1qqxuevtt" + cosmosHookStr := "?foo=bar&baz=bot#fragment" + cosmosHook, err := types.JoinHookedAddress(cosmosAddr, []byte(cosmosHookStr)) + require.NoError(t, err) + addr, hookData, err := types.SplitHookedAddress(cosmosHook) + require.NoError(t, err) + require.Equal(t, cosmosAddr, addr) + require.Equal(t, cosmosHookStr, string(hookData)) + + agoricAddr := "agoric1qqp0e5ys" + agoricHookStr := "?bingo=again" + agoricHook, err := types.JoinHookedAddress(agoricAddr, []byte(agoricHookStr)) require.NoError(t, err) - agoricHook, err := types.JoinHookedAddress("agoric1qqp0e5ys", []byte("?bingo=again")) + addr, hookData, err = types.SplitHookedAddress(agoricHook) require.NoError(t, err) + require.Equal(t, agoricAddr, addr) + require.Equal(t, agoricHookStr, string(hookData)) cases := []struct { name string