Merge PR #1086: Bech32Cosmos output/input for the LCD
* refactored bech32ization * updated keys endpoints for bech32 * bech32 for sending and querying * trying to change output of validator addresses * fixed validator output * linted * fixed merge conflict * added bech32 to staking endpoints * removed some logging statements * added GetAccPubKeyBech32Cosmos * fixed cli tests * updated swagger * merged standard bech32 change * renamed bech32cosmos to bech32 * bech32ify json output for key add * readded changelog * fixed changelog merge issue * Update CHANGELOG.md
This commit is contained in:
+4
-7
@@ -102,12 +102,6 @@ func runAddCmd(cmd *cobra.Command, args []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// addOutput lets us json format the data
|
||||
type addOutput struct {
|
||||
Key keys.Info `json:"key"`
|
||||
Seed string `json:"seed"`
|
||||
}
|
||||
|
||||
func printCreate(info keys.Info, seed string) {
|
||||
output := viper.Get(cli.OutputFlag)
|
||||
switch output {
|
||||
@@ -121,7 +115,10 @@ func printCreate(info keys.Info, seed string) {
|
||||
fmt.Println(seed)
|
||||
}
|
||||
case "json":
|
||||
out := addOutput{Key: info}
|
||||
out, err := Bech32KeyOutput(info)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if !viper.GetBool(flagNoBackup) {
|
||||
out.Seed = seed
|
||||
}
|
||||
|
||||
+5
-4
@@ -4,7 +4,6 @@ import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -54,9 +53,11 @@ func QueryKeysRequestHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("[]"))
|
||||
return
|
||||
}
|
||||
keysOutput := make([]KeyOutput, len(infos))
|
||||
for i, info := range infos {
|
||||
keysOutput[i] = KeyOutput{Name: info.Name, Address: sdk.Address(info.PubKey.Address().Bytes())}
|
||||
keysOutput, err := Bech32KeysOutput(infos)
|
||||
if err != nil {
|
||||
w.WriteHeader(500)
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
output, err := json.MarshalIndent(keysOutput, "", " ")
|
||||
if err != nil {
|
||||
|
||||
+6
-2
@@ -4,7 +4,6 @@ import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/gorilla/mux"
|
||||
keys "github.com/tendermint/go-crypto/keys"
|
||||
|
||||
@@ -51,7 +50,12 @@ func GetKeyRequestHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
keyOutput := KeyOutput{Name: info.Name, Address: sdk.Address(info.PubKey.Address())}
|
||||
keyOutput, err := Bech32KeyOutput(info)
|
||||
if err != nil {
|
||||
w.WriteHeader(500)
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
output, err := json.MarshalIndent(keyOutput, "", " ")
|
||||
if err != nil {
|
||||
w.WriteHeader(500)
|
||||
|
||||
+38
-26
@@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/spf13/viper"
|
||||
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
keys "github.com/tendermint/go-crypto/keys"
|
||||
"github.com/tendermint/tmlibs/cli"
|
||||
dbm "github.com/tendermint/tmlibs/db"
|
||||
@@ -47,29 +46,47 @@ func SetKeyBase(kb keys.Keybase) {
|
||||
|
||||
// used for outputting keys.Info over REST
|
||||
type KeyOutput struct {
|
||||
Name string `json:"name"`
|
||||
Address sdk.Address `json:"address"`
|
||||
PubKey crypto.PubKey `json:"pub_key"`
|
||||
Name string `json:"name"`
|
||||
Address string `json:"address"`
|
||||
PubKey string `json:"pub_key"`
|
||||
Seed string `json:"seed,omitempty"`
|
||||
}
|
||||
|
||||
func NewKeyOutput(info keys.Info) KeyOutput {
|
||||
return KeyOutput{
|
||||
Name: info.Name,
|
||||
Address: sdk.Address(info.PubKey.Address().Bytes()),
|
||||
PubKey: info.PubKey,
|
||||
}
|
||||
}
|
||||
|
||||
func NewKeyOutputs(infos []keys.Info) []KeyOutput {
|
||||
// create a list of KeyOutput in bech32 format
|
||||
func Bech32KeysOutput(infos []keys.Info) ([]KeyOutput, error) {
|
||||
kos := make([]KeyOutput, len(infos))
|
||||
for i, info := range infos {
|
||||
kos[i] = NewKeyOutput(info)
|
||||
ko, err := Bech32KeyOutput(info)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kos[i] = ko
|
||||
}
|
||||
return kos
|
||||
return kos, nil
|
||||
}
|
||||
|
||||
// create a KeyOutput in bech32 format
|
||||
func Bech32KeyOutput(info keys.Info) (KeyOutput, error) {
|
||||
bechAccount, err := sdk.Bech32ifyAcc(sdk.Address(info.PubKey.Address().Bytes()))
|
||||
if err != nil {
|
||||
return KeyOutput{}, err
|
||||
}
|
||||
bechPubKey, err := sdk.Bech32ifyAccPub(info.PubKey)
|
||||
if err != nil {
|
||||
return KeyOutput{}, err
|
||||
}
|
||||
return KeyOutput{
|
||||
Name: info.Name,
|
||||
Address: bechAccount,
|
||||
PubKey: bechPubKey,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func printInfo(info keys.Info) {
|
||||
ko := NewKeyOutput(info)
|
||||
ko, err := Bech32KeyOutput(info)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
switch viper.Get(cli.OutputFlag) {
|
||||
case "text":
|
||||
fmt.Printf("NAME:\tADDRESS:\t\t\t\t\t\tPUBKEY:\n")
|
||||
@@ -84,7 +101,10 @@ func printInfo(info keys.Info) {
|
||||
}
|
||||
|
||||
func printInfos(infos []keys.Info) {
|
||||
kos := NewKeyOutputs(infos)
|
||||
kos, err := Bech32KeysOutput(infos)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
switch viper.Get(cli.OutputFlag) {
|
||||
case "text":
|
||||
fmt.Printf("NAME:\tADDRESS:\t\t\t\t\t\tPUBKEY:\n")
|
||||
@@ -101,13 +121,5 @@ func printInfos(infos []keys.Info) {
|
||||
}
|
||||
|
||||
func printKeyOutput(ko KeyOutput) {
|
||||
bechAccount, err := sdk.Bech32ifyAcc(ko.Address)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
bechPubKey, err := sdk.Bech32ifyAccPub(ko.PubKey)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("%s\t%s\t%s\n", ko.Name, bechAccount, bechPubKey)
|
||||
fmt.Printf("%s\t%s\t%s\n", ko.Name, ko.Address, ko.PubKey)
|
||||
}
|
||||
|
||||
+39
-30
@@ -33,6 +33,7 @@ import (
|
||||
|
||||
client "github.com/cosmos/cosmos-sdk/client"
|
||||
keys "github.com/cosmos/cosmos-sdk/client/keys"
|
||||
rpc "github.com/cosmos/cosmos-sdk/client/rpc"
|
||||
gapp "github.com/cosmos/cosmos-sdk/cmd/gaia/app"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
tests "github.com/cosmos/cosmos-sdk/tests"
|
||||
@@ -40,14 +41,17 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/wire"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||
stakerest "github.com/cosmos/cosmos-sdk/x/stake/client/rest"
|
||||
)
|
||||
|
||||
var (
|
||||
coinDenom = "steak"
|
||||
coinAmount = int64(10000000)
|
||||
|
||||
validatorAddr1 = ""
|
||||
validatorAddr2 = ""
|
||||
validatorAddr1Hx = ""
|
||||
validatorAddr2Hx = ""
|
||||
validatorAddr1 = ""
|
||||
validatorAddr2 = ""
|
||||
|
||||
// XXX bad globals
|
||||
name = "test"
|
||||
@@ -99,13 +103,13 @@ func TestKeys(t *testing.T) {
|
||||
err = cdc.UnmarshalJSON([]byte(body), &m)
|
||||
require.Nil(t, err)
|
||||
|
||||
sendAddrAcc, _ := sdk.GetAccAddressHex(sendAddr)
|
||||
addrAcc, _ := sdk.GetAccAddressHex(addr)
|
||||
addrBech32, _ := sdk.Bech32ifyAcc(addrAcc)
|
||||
|
||||
assert.Equal(t, m[0].Name, name, "Did not serve keys name correctly")
|
||||
assert.Equal(t, m[0].Address, sendAddrAcc, "Did not serve keys Address correctly")
|
||||
assert.Equal(t, m[1].Name, newName, "Did not serve keys name correctly")
|
||||
assert.Equal(t, m[1].Address, addrAcc, "Did not serve keys Address correctly")
|
||||
assert.Equal(t, name, m[0].Name, "Did not serve keys name correctly")
|
||||
assert.Equal(t, sendAddr, m[0].Address, "Did not serve keys Address correctly")
|
||||
assert.Equal(t, newName, m[1].Name, "Did not serve keys name correctly")
|
||||
assert.Equal(t, addrBech32, m[1].Address, "Did not serve keys Address correctly")
|
||||
|
||||
// select key
|
||||
keyEndpoint := fmt.Sprintf("/keys/%s", newName)
|
||||
@@ -116,7 +120,7 @@ func TestKeys(t *testing.T) {
|
||||
require.Nil(t, err)
|
||||
|
||||
assert.Equal(t, newName, m2.Name, "Did not serve keys name correctly")
|
||||
assert.Equal(t, addrAcc, m2.Address, "Did not serve keys Address correctly")
|
||||
assert.Equal(t, addrBech32, m2.Address, "Did not serve keys Address correctly")
|
||||
|
||||
// update key
|
||||
jsonStr = []byte(fmt.Sprintf(`{"old_password":"%s", "new_password":"12345678901"}`, newPassword))
|
||||
@@ -198,7 +202,7 @@ func TestBlock(t *testing.T) {
|
||||
|
||||
func TestValidators(t *testing.T) {
|
||||
|
||||
var resultVals ctypes.ResultValidators
|
||||
var resultVals rpc.ResultValidatorsOutput
|
||||
|
||||
res, body := request(t, port, "GET", "/validatorsets/latest", nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
@@ -206,7 +210,10 @@ func TestValidators(t *testing.T) {
|
||||
err := cdc.UnmarshalJSON([]byte(body), &resultVals)
|
||||
require.Nil(t, err, "Couldn't parse validatorset")
|
||||
|
||||
assert.NotEqual(t, ctypes.ResultValidators{}, resultVals)
|
||||
assert.NotEqual(t, rpc.ResultValidatorsOutput{}, resultVals)
|
||||
|
||||
assert.Contains(t, resultVals.Validators[0].Address, "cosmosvaladdr")
|
||||
assert.Contains(t, resultVals.Validators[0].PubKey, "cosmosvalpub")
|
||||
|
||||
// --
|
||||
|
||||
@@ -216,7 +223,7 @@ func TestValidators(t *testing.T) {
|
||||
err = cdc.UnmarshalJSON([]byte(body), &resultVals)
|
||||
require.Nil(t, err, "Couldn't parse validatorset")
|
||||
|
||||
assert.NotEqual(t, ctypes.ResultValidators{}, resultVals)
|
||||
assert.NotEqual(t, rpc.ResultValidatorsOutput{}, resultVals)
|
||||
|
||||
// --
|
||||
|
||||
@@ -225,10 +232,11 @@ func TestValidators(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCoinSend(t *testing.T) {
|
||||
bz, _ := hex.DecodeString("8FA6AB57AD6870F6B5B2E57735F38F2F30E73CB6")
|
||||
someFakeAddr, _ := sdk.Bech32ifyAcc(bz)
|
||||
|
||||
// query empty
|
||||
//res, body := request(t, port, "GET", "/accounts/8FA6AB57AD6870F6B5B2E57735F38F2F30E73CB6", nil)
|
||||
res, body := request(t, port, "GET", "/accounts/8FA6AB57AD6870F6B5B2E57735F38F2F30E73CB6", nil)
|
||||
res, body := request(t, port, "GET", "/accounts/"+someFakeAddr, nil)
|
||||
require.Equal(t, http.StatusNoContent, res.StatusCode, body)
|
||||
|
||||
acc := getAccount(t, sendAddr)
|
||||
@@ -323,15 +331,14 @@ func TestValidatorsQuery(t *testing.T) {
|
||||
|
||||
// make sure all the validators were found (order unknown because sorted by owner addr)
|
||||
foundVal1, foundVal2 := false, false
|
||||
res1, res2 := hex.EncodeToString(validators[0].Owner), hex.EncodeToString(validators[1].Owner)
|
||||
if res1 == validatorAddr1 || res2 == validatorAddr1 {
|
||||
if validators[0].Owner == validatorAddr1 || validators[1].Owner == validatorAddr1 {
|
||||
foundVal1 = true
|
||||
}
|
||||
if res1 == validatorAddr2 || res2 == validatorAddr2 {
|
||||
if validators[0].Owner == validatorAddr2 || validators[1].Owner == validatorAddr2 {
|
||||
foundVal2 = true
|
||||
}
|
||||
assert.True(t, foundVal1, "validatorAddr1 %v, res1 %v, res2 %v", validatorAddr1, res1, res2)
|
||||
assert.True(t, foundVal2, "validatorAddr2 %v, res1 %v, res2 %v", validatorAddr2, res1, res2)
|
||||
assert.True(t, foundVal1, "validatorAddr1 %v, owner1 %v, owner2 %v", validatorAddr1, validators[0].Owner, validators[1].Owner)
|
||||
assert.True(t, foundVal2, "validatorAddr2 %v, owner1 %v, owner2 %v", validatorAddr2, validators[0].Owner, validators[1].Owner)
|
||||
}
|
||||
|
||||
func TestBond(t *testing.T) {
|
||||
@@ -418,8 +425,10 @@ func startTMAndLCD() (*nm.Node, net.Listener, error) {
|
||||
|
||||
pk1 := genDoc.Validators[0].PubKey
|
||||
pk2 := genDoc.Validators[1].PubKey
|
||||
validatorAddr1 = hex.EncodeToString(pk1.Address())
|
||||
validatorAddr2 = hex.EncodeToString(pk2.Address())
|
||||
validatorAddr1Hx = hex.EncodeToString(pk1.Address())
|
||||
validatorAddr2Hx = hex.EncodeToString(pk2.Address())
|
||||
validatorAddr1, _ = sdk.Bech32ifyVal(pk1.Address())
|
||||
validatorAddr2, _ = sdk.Bech32ifyVal(pk2.Address())
|
||||
|
||||
// NOTE it's bad practice to reuse pk address for the owner address but doing in the
|
||||
// test for simplicity
|
||||
@@ -444,7 +453,8 @@ func startTMAndLCD() (*nm.Node, net.Listener, error) {
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
sendAddr = info.PubKey.Address().String() // XXX global
|
||||
sendAddrHex, _ := sdk.GetAccAddressHex(info.PubKey.Address().String())
|
||||
sendAddr, _ = sdk.Bech32ifyAcc(sendAddrHex) // XXX global
|
||||
accAuth := auth.NewBaseAccountWithAddress(info.PubKey.Address())
|
||||
accAuth.Coins = sdk.Coins{{"steak", 100}}
|
||||
acc := gapp.NewGenesisAccount(&accAuth)
|
||||
@@ -548,7 +558,7 @@ func doSend(t *testing.T, port, seed string) (receiveAddr string, resultTx ctype
|
||||
kb := client.MockKeyBase()
|
||||
receiveInfo, _, err := kb.Create("receive_address", "1234567890", cryptoKeys.CryptoAlgo("ed25519"))
|
||||
require.Nil(t, err)
|
||||
receiveAddr = receiveInfo.PubKey.Address().String()
|
||||
receiveAddr, _ = sdk.Bech32ifyAcc(receiveInfo.PubKey.Address())
|
||||
|
||||
acc := getAccount(t, sendAddr)
|
||||
sequence := acc.GetSequence()
|
||||
@@ -565,12 +575,11 @@ func doSend(t *testing.T, port, seed string) (receiveAddr string, resultTx ctype
|
||||
}
|
||||
|
||||
func doIBCTransfer(t *testing.T, port, seed string) (resultTx ctypes.ResultBroadcastTxCommit) {
|
||||
|
||||
// create receive address
|
||||
kb := client.MockKeyBase()
|
||||
receiveInfo, _, err := kb.Create("receive_address", "1234567890", cryptoKeys.CryptoAlgo("ed25519"))
|
||||
require.Nil(t, err)
|
||||
receiveAddr := receiveInfo.PubKey.Address().String()
|
||||
receiveAddr, _ := sdk.Bech32ifyAcc(receiveInfo.PubKey.Address())
|
||||
|
||||
// get the account to get the sequence
|
||||
acc := getAccount(t, sendAddr)
|
||||
@@ -609,13 +618,13 @@ func doBond(t *testing.T, port, seed string) (resultTx ctypes.ResultBroadcastTxC
|
||||
"sequence": %d,
|
||||
"delegate": [
|
||||
{
|
||||
"delegator_addr": "%x",
|
||||
"delegator_addr": "%s",
|
||||
"validator_addr": "%s",
|
||||
"bond": { "denom": "%s", "amount": 10 }
|
||||
}
|
||||
],
|
||||
"unbond": []
|
||||
}`, name, password, sequence, acc.GetAddress(), validatorAddr1, coinDenom))
|
||||
}`, name, password, sequence, sendAddr, validatorAddr1, coinDenom))
|
||||
res, body := request(t, port, "POST", "/stake/delegations", jsonStr)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
@@ -639,12 +648,12 @@ func doUnbond(t *testing.T, port, seed string) (resultTx ctypes.ResultBroadcastT
|
||||
"bond": [],
|
||||
"unbond": [
|
||||
{
|
||||
"delegator_addr": "%x",
|
||||
"delegator_addr": "%s",
|
||||
"validator_addr": "%s",
|
||||
"shares": "1"
|
||||
}
|
||||
]
|
||||
}`, name, password, sequence, acc.GetAddress(), validatorAddr1))
|
||||
}`, name, password, sequence, sendAddr, validatorAddr1))
|
||||
res, body := request(t, port, "POST", "/stake/delegations", jsonStr)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
@@ -655,11 +664,11 @@ func doUnbond(t *testing.T, port, seed string) (resultTx ctypes.ResultBroadcastT
|
||||
return results[0]
|
||||
}
|
||||
|
||||
func getValidators(t *testing.T) []stake.Validator {
|
||||
func getValidators(t *testing.T) []stakerest.StakeValidatorOutput {
|
||||
// get the account to get the sequence
|
||||
res, body := request(t, port, "GET", "/stake/validators", nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
var validators stake.Validators
|
||||
var validators []stakerest.StakeValidatorOutput
|
||||
err := cdc.UnmarshalJSON([]byte(body), &validators)
|
||||
require.Nil(t, err)
|
||||
return validators
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/context"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
// TODO these next two functions feel kinda hacky based on their placement
|
||||
@@ -28,6 +30,38 @@ func ValidatorCommand() *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Validator output in bech32 format
|
||||
type ValidatorOutput struct {
|
||||
Address string `json:"address"` // in bech32
|
||||
PubKey string `json:"pub_key"` // in bech32
|
||||
Accum int64 `json:"accum"`
|
||||
VotingPower int64 `json:"voting_power"`
|
||||
}
|
||||
|
||||
// Validators at a certain height output in bech32 format
|
||||
type ResultValidatorsOutput struct {
|
||||
BlockHeight int64 `json:"block_height"`
|
||||
Validators []ValidatorOutput `json:"validators"`
|
||||
}
|
||||
|
||||
func bech32ValidatorOutput(validator *tmtypes.Validator) (ValidatorOutput, error) {
|
||||
bechAddress, err := sdk.Bech32ifyVal(validator.Address)
|
||||
if err != nil {
|
||||
return ValidatorOutput{}, err
|
||||
}
|
||||
bechValPubkey, err := sdk.Bech32ifyValPub(validator.PubKey)
|
||||
if err != nil {
|
||||
return ValidatorOutput{}, err
|
||||
}
|
||||
|
||||
return ValidatorOutput{
|
||||
Address: bechAddress,
|
||||
PubKey: bechValPubkey,
|
||||
Accum: validator.Accum,
|
||||
VotingPower: validator.VotingPower,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getValidators(ctx context.CoreContext, height *int64) ([]byte, error) {
|
||||
// get the node
|
||||
node, err := ctx.GetNode()
|
||||
@@ -35,12 +69,23 @@ func getValidators(ctx context.CoreContext, height *int64) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := node.Validators(height)
|
||||
validatorsRes, err := node.Validators(height)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
output, err := cdc.MarshalJSON(res)
|
||||
outputValidatorsRes := ResultValidatorsOutput{
|
||||
BlockHeight: validatorsRes.BlockHeight,
|
||||
Validators: make([]ValidatorOutput, len(validatorsRes.Validators)),
|
||||
}
|
||||
for i := 0; i < len(validatorsRes.Validators); i++ {
|
||||
outputValidatorsRes.Validators[i], err = bech32ValidatorOutput(validatorsRes.Validators[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
output, err := cdc.MarshalJSON(outputValidatorsRes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -96,6 +141,7 @@ func ValidatorSetRequestHandlerFn(ctx context.CoreContext) http.HandlerFunc {
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(output)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user