Skip to content

Commit

Permalink
feat!: Add bech32 prefix to authkeeper (cosmos#9759)
Browse files Browse the repository at this point in the history
<!--
The default pull request template is for types feat, fix, or refactor.
For other templates, add one of the following parameters to the url:
- template=docs.md
- template=other.md
-->

## Description

Closes **Step1** from cosmos#9690

<!-- Add a description of the changes that this PR introduces and the files that
are the most critical to review. -->

- Add auth keeper methods and gRPC queries:
  - the `NewAccountKeeper` should take a `string bech32Prefix` argument
  - ` auth AccountKeeper` implements `Codec` interface that contains 2 methods:  `ConvertAddressStringToBytes` and `ConvertAddressBytesToString` 
  - Add the 3 following gRPC queries:
    - Get bech32 prefix
    - `AddressStringToBytes` (converts `AccountAddr` string to `AccountAddr` bytes)
    - `AddressBytesToString` ( converts `AccountAddr` bytes to `AccountAddr` str)
  - Add the corresponding keeper methods
  - Add tests
---

### Author Checklist

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [x] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [x] added a changelog entry to `CHANGELOG.md`
- [x] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [x] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed 
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
  • Loading branch information
cyberbono3 authored Aug 25, 2021
1 parent 147d798 commit 59640fb
Show file tree
Hide file tree
Showing 16 changed files with 2,070 additions and 347 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### API Breaking Changes

* [\#9759](https://github.com/cosmos/cosmos-sdk/pull/9759) `NewAccountKeeeper` in `x/auth` now takes an additional `bech32Prefix` argument that represents `sdk.Bech32MainPrefix`.
* [\#9628](https://github.com/cosmos/cosmos-sdk/pull/9628) Rename `x/{mod}/legacy` to `x/{mod}/migrations`.
* [\#9571](https://github.com/cosmos/cosmos-sdk/pull/9571) Implemented error handling for staking hooks, which now return an error on failure.
* [\#9427](https://github.com/cosmos/cosmos-sdk/pull/9427) Move simapp `FundAccount` and `FundModuleAccount` to `x/bank/testutil`
Expand Down
6 changes: 2 additions & 4 deletions client/docs/statik/statik.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion client/grpc/tmservice/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/testutil/network"
qtypes "github.com/cosmos/cosmos-sdk/types/query"
"github.com/cosmos/cosmos-sdk/testutil/rest"
qtypes "github.com/cosmos/cosmos-sdk/types/query"
"github.com/cosmos/cosmos-sdk/version"
)

Expand Down
94 changes: 94 additions & 0 deletions docs/core/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
- [PageResponse](#cosmos.base.query.v1beta1.PageResponse)

- [cosmos/auth/v1beta1/query.proto](#cosmos/auth/v1beta1/query.proto)
- [AddressBytesToStringRequest](#cosmos.auth.v1beta1.AddressBytesToStringRequest)
- [AddressBytesToStringResponse](#cosmos.auth.v1beta1.AddressBytesToStringResponse)
- [AddressStringToBytesRequest](#cosmos.auth.v1beta1.AddressStringToBytesRequest)
- [AddressStringToBytesResponse](#cosmos.auth.v1beta1.AddressStringToBytesResponse)
- [Bech32PrefixRequest](#cosmos.auth.v1beta1.Bech32PrefixRequest)
- [Bech32PrefixResponse](#cosmos.auth.v1beta1.Bech32PrefixResponse)
- [QueryAccountRequest](#cosmos.auth.v1beta1.QueryAccountRequest)
- [QueryAccountResponse](#cosmos.auth.v1beta1.QueryAccountResponse)
- [QueryAccountsRequest](#cosmos.auth.v1beta1.QueryAccountsRequest)
Expand Down Expand Up @@ -846,6 +852,91 @@ corresponding request message has used PageRequest.



<a name="cosmos.auth.v1beta1.AddressBytesToStringRequest"></a>

### AddressBytesToStringRequest
AddressBytesToStringRequest is the request type for AddressString rpc method


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `address_bytes` | [bytes](#bytes) | | |






<a name="cosmos.auth.v1beta1.AddressBytesToStringResponse"></a>

### AddressBytesToStringResponse
AddressBytesToStringResponse is the response type for AddressString rpc method


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `address_string` | [string](#string) | | |






<a name="cosmos.auth.v1beta1.AddressStringToBytesRequest"></a>

### AddressStringToBytesRequest
AddressStringToBytesRequest is the request type for AccountBytes rpc method


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `address_string` | [string](#string) | | |






<a name="cosmos.auth.v1beta1.AddressStringToBytesResponse"></a>

### AddressStringToBytesResponse
AddressStringToBytesResponse is the response type for AddressBytes rpc method


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `address_bytes` | [bytes](#bytes) | | |






<a name="cosmos.auth.v1beta1.Bech32PrefixRequest"></a>

### Bech32PrefixRequest
Bech32PrefixRequest is the request type for Bech32Prefix rpc method






<a name="cosmos.auth.v1beta1.Bech32PrefixResponse"></a>

### Bech32PrefixResponse
Bech32PrefixResponse is the response type for Bech32Prefix rpc method


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `bech32_prefix` | [string](#string) | | |






<a name="cosmos.auth.v1beta1.QueryAccountRequest"></a>

### QueryAccountRequest
Expand Down Expand Up @@ -974,6 +1065,9 @@ Query defines the gRPC querier service.
| `Account` | [QueryAccountRequest](#cosmos.auth.v1beta1.QueryAccountRequest) | [QueryAccountResponse](#cosmos.auth.v1beta1.QueryAccountResponse) | Account returns account details based on address. | GET|/cosmos/auth/v1beta1/accounts/{address}|
| `Params` | [QueryParamsRequest](#cosmos.auth.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.auth.v1beta1.QueryParamsResponse) | Params queries all parameters. | GET|/cosmos/auth/v1beta1/params|
| `ModuleAccounts` | [QueryModuleAccountsRequest](#cosmos.auth.v1beta1.QueryModuleAccountsRequest) | [QueryModuleAccountsResponse](#cosmos.auth.v1beta1.QueryModuleAccountsResponse) | ModuleAccounts returns all the existing module accounts. | GET|/cosmos/auth/v1beta1/module_accounts|
| `Bech32Prefix` | [Bech32PrefixRequest](#cosmos.auth.v1beta1.Bech32PrefixRequest) | [Bech32PrefixResponse](#cosmos.auth.v1beta1.Bech32PrefixResponse) | Bech32 queries bech32Prefix | GET|/cosmos/auth/v1beta1/bech32|
| `AddressBytesToString` | [AddressBytesToStringRequest](#cosmos.auth.v1beta1.AddressBytesToStringRequest) | [AddressBytesToStringResponse](#cosmos.auth.v1beta1.AddressBytesToStringResponse) | AddressBytesToString converts Account Address bytes to string | GET|/cosmos/auth/v1beta1/bech32/{address_bytes}|
| `AddressStringToBytes` | [AddressStringToBytesRequest](#cosmos.auth.v1beta1.AddressStringToBytesRequest) | [AddressStringToBytesResponse](#cosmos.auth.v1beta1.AddressStringToBytesResponse) | AddressStringToBytes converts Address string to bytes | GET|/cosmos/auth/v1beta1/bech32/{address_string}|

<!-- end services -->

Expand Down
63 changes: 53 additions & 10 deletions proto/cosmos/auth/v1beta1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,21 @@ service Query {
rpc ModuleAccounts(QueryModuleAccountsRequest) returns (QueryModuleAccountsResponse) {
option (google.api.http).get = "/cosmos/auth/v1beta1/module_accounts";
}

// Bech32 queries bech32Prefix
rpc Bech32Prefix(Bech32PrefixRequest) returns (Bech32PrefixResponse) {
option (google.api.http).get = "/cosmos/auth/v1beta1/bech32";
}

// AddressBytesToString converts Account Address bytes to string
rpc AddressBytesToString(AddressBytesToStringRequest) returns (AddressBytesToStringResponse) {
option (google.api.http).get = "/cosmos/auth/v1beta1/bech32/{address_bytes}";
}

// AddressStringToBytes converts Address string to bytes
rpc AddressStringToBytes(AddressStringToBytesRequest) returns (AddressStringToBytesResponse) {
option (google.api.http).get = "/cosmos/auth/v1beta1/bech32/{address_string}";
}
}

// QueryAccountsRequest is the request type for the Query/Accounts RPC method.
Expand All @@ -57,6 +72,15 @@ message QueryAccountRequest {
string address = 1;
}

// QueryModuleAccountsRequest is the request type for the Query/ModuleAccounts RPC method.
message QueryModuleAccountsRequest {}

// QueryParamsResponse is the response type for the Query/Params RPC method.
message QueryParamsResponse {
// params defines the parameters of the module.
Params params = 1 [(gogoproto.nullable) = false];
}

// QueryAccountResponse is the response type for the Query/Account RPC method.
message QueryAccountResponse {
// account defines the account of the corresponding address.
Expand All @@ -66,16 +90,35 @@ message QueryAccountResponse {
// QueryParamsRequest is the request type for the Query/Params RPC method.
message QueryParamsRequest {}

// QueryParamsResponse is the response type for the Query/Params RPC method.
message QueryParamsResponse {
// params defines the parameters of the module.
Params params = 1 [(gogoproto.nullable) = false];
}

// QueryModuleAccountsRequest is the request type for the Query/ModuleAccounts RPC method.
message QueryModuleAccountsRequest {}

// QueryModuleAccountsResponse is the response type for the Query/ModuleAccounts RPC method.
message QueryModuleAccountsResponse {
repeated google.protobuf.Any accounts = 1 [(cosmos_proto.accepts_interface) = "ModuleAccountI"];
}
}

// Bech32PrefixRequest is the request type for Bech32Prefix rpc method
message Bech32PrefixRequest {}

// Bech32PrefixResponse is the response type for Bech32Prefix rpc method
message Bech32PrefixResponse {
string bech32_prefix = 1;
}

// AddressBytesToStringRequest is the request type for AddressString rpc method
message AddressBytesToStringRequest {
bytes address_bytes = 1;
}

// AddressBytesToStringResponse is the response type for AddressString rpc method
message AddressBytesToStringResponse {
string address_string = 1;
}

// AddressStringToBytesRequest is the request type for AccountBytes rpc method
message AddressStringToBytesRequest {
string address_string = 1;
}

// AddressStringToBytesResponse is the response type for AddressBytes rpc method
message AddressStringToBytesResponse {
bytes address_bytes = 1;
}
2 changes: 1 addition & 1 deletion simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ func NewSimApp(

// add keepers
app.AccountKeeper = authkeeper.NewAccountKeeper(
appCodec, keys[authtypes.StoreKey], app.GetSubspace(authtypes.ModuleName), authtypes.ProtoBaseAccount, maccPerms,
appCodec, keys[authtypes.StoreKey], app.GetSubspace(authtypes.ModuleName), authtypes.ProtoBaseAccount, maccPerms, sdk.Bech32MainPrefix,
)
app.BankKeeper = bankkeeper.NewBaseKeeper(
appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.ModuleAccountAddrs(),
Expand Down
4 changes: 3 additions & 1 deletion types/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ func AccAddressFromHex(address string) (addr AccAddress, err error) {

// VerifyAddressFormat verifies that the provided bytes form a valid address
// according to the default address rules or a custom address verifier set by
// GetConfig().SetAddressVerifier()
// GetConfig().SetAddressVerifier().
// TODO make an issue to get rid of global Config
// ref: https://github.com/cosmos/cosmos-sdk/issues/9690
func VerifyAddressFormat(bz []byte) error {
verifier := GetConfig().GetAddressVerifier()
if verifier != nil {
Expand Down
9 changes: 9 additions & 0 deletions types/address/codec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package address

// Codec defines an interface to convert addresses from and to string/bytes.
type Codec interface {
// StringToBytes decodes text to bytes
StringToBytes(text string) ([]byte, error)
// BytesToString encodes bytes to text
BytesToString(bz []byte) (string, error)
}
46 changes: 46 additions & 0 deletions x/auth/keeper/bech32_codec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package keeper

import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
"github.com/cosmos/cosmos-sdk/types/bech32"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)

type bech32Codec struct {
bech32Prefix string
}

var _ address.Codec = &bech32Codec{}

func newBech32Codec(prefix string) bech32Codec {
return bech32Codec{prefix}
}

// StringToBytes encodes text to bytes
func (bc bech32Codec) StringToBytes(text string) ([]byte, error) {
hrp, bz, err := bech32.DecodeAndConvert(text)
if err != nil {
return nil, err
}

if hrp != bc.bech32Prefix {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "hrp does not match bech32Prefix")
}

if err := sdk.VerifyAddressFormat(bz); err != nil {
return nil, err
}

return bz, nil
}

// BytesToString decodes bytes to text
func (bc bech32Codec) BytesToString(bz []byte) (string, error) {
text, err := bech32.ConvertAndEncode(bc.bech32Prefix, bz)
if err != nil {
return "", err
}

return text, nil
}
45 changes: 45 additions & 0 deletions x/auth/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package keeper

import (
"context"
"errors"
"strings"

"github.com/cosmos/cosmos-sdk/store/prefix"
"github.com/cosmos/cosmos-sdk/types/query"
Expand Down Expand Up @@ -108,3 +110,46 @@ func (ak AccountKeeper) ModuleAccounts(c context.Context, req *types.QueryModule

return &types.QueryModuleAccountsResponse{Accounts: modAccounts}, nil
}

func (ak AccountKeeper) Bech32Prefix(ctx context.Context, req *types.Bech32PrefixRequest) (*types.Bech32PrefixResponse, error) {
bech32Prefix, err := ak.getBech32Prefix()
if err != nil {
return nil, err
}

return &types.Bech32PrefixResponse{Bech32Prefix: bech32Prefix}, nil
}

func (ak AccountKeeper) AddressBytesToString(ctx context.Context, req *types.AddressBytesToStringRequest) (*types.AddressBytesToStringResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}

if len(req.AddressBytes) == 0 {
return nil, errors.New("empty address bytes is not allowed")
}

text, err := ak.addressCdc.BytesToString(req.AddressBytes)
if err != nil {
return nil, err
}

return &types.AddressBytesToStringResponse{AddressString: text}, nil
}

func (ak AccountKeeper) AddressStringToBytes(ctx context.Context, req *types.AddressStringToBytesRequest) (*types.AddressStringToBytesResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}

if len(strings.TrimSpace(req.AddressString)) == 0 {
return nil, errors.New("empty address string is not allowed")
}

bz, err := ak.addressCdc.StringToBytes(req.AddressString)
if err != nil {
return nil, err
}

return &types.AddressStringToBytesResponse{AddressBytes: bz}, nil
}
Loading

0 comments on commit 59640fb

Please sign in to comment.