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:
Fabian
2018-06-06 06:53:04 +02:00
committed by Christopher Goes
parent af15f89531
commit 5f409ce832
15 changed files with 348 additions and 138 deletions
+4 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+48 -2
View File
@@ -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)
}
}