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:
parent
af15f89531
commit
5f409ce832
|
@ -1,5 +1,9 @@
|
|||
# Changelog
|
||||
|
||||
BREAKING CHANGES
|
||||
|
||||
* [lcd] Switch to bech32 for addresses on all human readable inputs and outputs
|
||||
|
||||
## 0.18.0
|
||||
|
||||
_2018-06-05_
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -170,7 +170,13 @@ func executeGetAddrPK(t *testing.T, cmdStr string) (sdk.Address, crypto.PubKey)
|
|||
var ko keys.KeyOutput
|
||||
keys.UnmarshalJSON([]byte(out), &ko)
|
||||
|
||||
return ko.Address, ko.PubKey
|
||||
address, err := sdk.GetAccAddressBech32(ko.Address)
|
||||
require.NoError(t, err)
|
||||
|
||||
pk, err := sdk.GetAccPubKeyBech32(ko.PubKey)
|
||||
require.NoError(t, err)
|
||||
|
||||
return address, pk
|
||||
}
|
||||
|
||||
func executeGetAccount(t *testing.T, cmdStr string) auth.BaseAccount {
|
||||
|
|
|
@ -102,7 +102,7 @@ paths:
|
|||
- application/json
|
||||
responses:
|
||||
200:
|
||||
description: 12 word Seed
|
||||
description: 16 word Seed
|
||||
schema:
|
||||
type: string
|
||||
/keys/{name}:
|
||||
|
@ -204,7 +204,7 @@ paths:
|
|||
parameters:
|
||||
- in: path
|
||||
name: address
|
||||
description: Account address
|
||||
description: Account address in bech32 format
|
||||
required: true
|
||||
type: string
|
||||
get:
|
||||
|
@ -222,7 +222,7 @@ paths:
|
|||
parameters:
|
||||
- in: path
|
||||
name: address
|
||||
description: Account address
|
||||
description: Account address in bech32 format
|
||||
required: true
|
||||
type: string
|
||||
post:
|
||||
|
@ -255,18 +255,6 @@ paths:
|
|||
description: Tx was send and will probably be added to the next block
|
||||
400:
|
||||
description: The Tx was malformated
|
||||
/accounts/{address}/nonce:
|
||||
parameters:
|
||||
- in: path
|
||||
name: address
|
||||
description: Account address
|
||||
required: true
|
||||
type: string
|
||||
get:
|
||||
summary: Get the nonce for a certain account
|
||||
responses:
|
||||
200:
|
||||
description: Plaintext nonce i.e. "4" defaults to "0"
|
||||
/blocks/latest:
|
||||
get:
|
||||
summary: Get the latest block
|
||||
|
@ -304,9 +292,14 @@ paths:
|
|||
200:
|
||||
description: The validator set at the latest block height
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/definitions/Delegate"
|
||||
type: object
|
||||
properties:
|
||||
block_height:
|
||||
type: number
|
||||
validators:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/definitions/Validator"
|
||||
/validatorsets/{height}:
|
||||
parameters:
|
||||
- in: path
|
||||
|
@ -322,9 +315,14 @@ paths:
|
|||
200:
|
||||
description: The validator set at a specific block height
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/definitions/Delegate"
|
||||
type: object
|
||||
properties:
|
||||
block_height:
|
||||
type: number
|
||||
validators:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/definitions/Validator"
|
||||
404:
|
||||
description: Block at height not available
|
||||
# /txs:
|
||||
|
@ -549,7 +547,20 @@ paths:
|
|||
definitions:
|
||||
Address:
|
||||
type: string
|
||||
example: DF096FDE8D380FA5B2AD20DB2962C82DDEA1ED9B
|
||||
description: bech32 encoded addres
|
||||
example: cosmosaccaddr:zgnkwr7eyyv643dllwfpdwensmgdtz89yu73zq
|
||||
ValidatorAddress:
|
||||
type: string
|
||||
description: bech32 encoded addres
|
||||
example: cosmosvaladdr:zgnkwr7eyyv643dllwfpdwensmgdtz89yu73zq
|
||||
PubKey:
|
||||
type: string
|
||||
description: bech32 encoded public key
|
||||
example: cosmosaccpub:zgnkwr7eyyv643dllwfpdwensmgdtz89yu73zq
|
||||
ValidatorPubKey:
|
||||
type: string
|
||||
description: bech32 encoded public key
|
||||
example: cosmosvalpub:zgnkwr7eyyv643dllwfpdwensmgdtz89yu73zq
|
||||
Coins:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -652,16 +663,6 @@ definitions:
|
|||
example: 81B11E717789600CC192B26F452A983DF13B985EE75ABD9DD9E68D7BA007A958
|
||||
Pubkey:
|
||||
$ref: "#/definitions/PubKey"
|
||||
PubKey:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- ed25519
|
||||
data:
|
||||
type: string
|
||||
example: 81B11E717789600CC192B26F452A983DF13B985EE75ABD9DD9E68D7BA007A958
|
||||
Account:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -753,17 +754,19 @@ definitions:
|
|||
type: array
|
||||
items:
|
||||
type: object
|
||||
Delegate:
|
||||
Validator:
|
||||
type: object
|
||||
properties:
|
||||
address:
|
||||
$ref: '#/definitions/ValidatorAddress'
|
||||
pub_key:
|
||||
$ref: "#/definitions/PubKey"
|
||||
$ref: "#/definitions/ValidatorPubKey"
|
||||
power:
|
||||
type: number
|
||||
example: 1000
|
||||
name:
|
||||
type: string
|
||||
example: "159.89.3.34"
|
||||
accum:
|
||||
type: number
|
||||
example: 1000
|
||||
# Added by API Auto Mocking Plugin
|
||||
host: virtserver.swaggerhub.com
|
||||
basePath: /faboweb1/Cosmos-LCD-2/1.0.0
|
||||
|
|
|
@ -32,7 +32,7 @@ func Bech32ifyAccPub(pub crypto.PubKey) (string, error) {
|
|||
}
|
||||
|
||||
// Bech32ifyVal returns the bech32 encoded string for a validator address
|
||||
func bech32ifyVal(addr Address) (string, error) {
|
||||
func Bech32ifyVal(addr Address) (string, error) {
|
||||
return bech32.ConvertAndEncode(Bech32PrefixValAddr, addr.Bytes())
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,21 @@ func GetAccAddressBech32(address string) (addr Address, err error) {
|
|||
return Address(bz), nil
|
||||
}
|
||||
|
||||
// create a Pubkey from a string
|
||||
func GetAccPubKeyBech32(address string) (pk crypto.PubKey, err error) {
|
||||
bz, err := getFromBech32(address, Bech32PrefixAccPub)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pk, err = crypto.PubKeyFromBytes(bz)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return pk, nil
|
||||
}
|
||||
|
||||
// create an Address from a hex string
|
||||
func GetValAddressHex(address string) (addr Address, err error) {
|
||||
if len(address) == 0 {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package rest
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
|
@ -26,17 +25,16 @@ func RegisterRoutes(ctx context.CoreContext, r *mux.Router, cdc *wire.Codec, sto
|
|||
func QueryAccountRequestHandlerFn(storeName string, cdc *wire.Codec, decoder auth.AccountDecoder, ctx context.CoreContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
addr := vars["address"]
|
||||
bech32addr := vars["address"]
|
||||
|
||||
bz, err := hex.DecodeString(addr)
|
||||
addr, err := sdk.GetAccAddressBech32(bech32addr)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
key := sdk.Address(bz)
|
||||
|
||||
res, err := ctx.Query(key, storeName)
|
||||
res, err := ctx.Query(addr, storeName)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(fmt.Sprintf("Could't query account. Error: %s", err.Error())))
|
||||
|
|
|
@ -41,7 +41,14 @@ func SendRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx context.CoreCont
|
|||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// collect data
|
||||
vars := mux.Vars(r)
|
||||
address := vars["address"]
|
||||
bech32addr := vars["address"]
|
||||
|
||||
address, err := sdk.GetAccAddressBech32(bech32addr)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
var m sendBody
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
|
@ -64,7 +71,7 @@ func SendRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx context.CoreCont
|
|||
return
|
||||
}
|
||||
|
||||
to, err := sdk.GetAccAddressHex(address)
|
||||
to, err := sdk.GetAccAddressHex(address.String())
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte(err.Error()))
|
||||
|
|
|
@ -35,7 +35,14 @@ func TransferRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx context.Core
|
|||
// collect data
|
||||
vars := mux.Vars(r)
|
||||
destChainID := vars["destchain"]
|
||||
address := vars["address"]
|
||||
bech32addr := vars["address"]
|
||||
|
||||
address, err := sdk.GetAccAddressBech32(bech32addr)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
var m transferBody
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
|
@ -58,7 +65,7 @@ func TransferRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx context.Core
|
|||
return
|
||||
}
|
||||
|
||||
bz, err := hex.DecodeString(address)
|
||||
bz, err := hex.DecodeString(address.String())
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte(err.Error()))
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package rest
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
|
@ -30,24 +29,22 @@ func bondingStatusHandlerFn(ctx context.CoreContext, storeName string, cdc *wire
|
|||
|
||||
// read parameters
|
||||
vars := mux.Vars(r)
|
||||
delegator := vars["delegator"]
|
||||
validator := vars["validator"]
|
||||
bech32delegator := vars["delegator"]
|
||||
bech32validator := vars["validator"]
|
||||
|
||||
bz, err := hex.DecodeString(delegator)
|
||||
delegatorAddr, err := sdk.GetAccAddressBech32(bech32delegator)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
delegatorAddr := sdk.Address(bz)
|
||||
|
||||
bz, err = hex.DecodeString(validator)
|
||||
validatorAddr, err := sdk.GetValAddressBech32(bech32validator)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
validatorAddr := sdk.Address(bz)
|
||||
|
||||
key := stake.GetDelegationKey(delegatorAddr, validatorAddr, cdc)
|
||||
|
||||
|
@ -83,6 +80,62 @@ func bondingStatusHandlerFn(ctx context.CoreContext, storeName string, cdc *wire
|
|||
}
|
||||
}
|
||||
|
||||
// TODO inherit from Validator
|
||||
type StakeValidatorOutput struct {
|
||||
Owner string `json:"owner"` // in bech32
|
||||
PubKey string `json:"pub_key"` // in bech32
|
||||
Revoked bool `json:"revoked"` // has the validator been revoked from bonded status?
|
||||
|
||||
PoolShares stake.PoolShares `json:"pool_shares"` // total shares for tokens held in the pool
|
||||
DelegatorShares sdk.Rat `json:"delegator_shares"` // total shares issued to a validator's delegators
|
||||
|
||||
Description stake.Description `json:"description"` // description terms for the validator
|
||||
BondHeight int64 `json:"bond_height"` // earliest height as a bonded validator
|
||||
BondIntraTxCounter int16 `json:"bond_intra_tx_counter"` // block-local tx index of validator change
|
||||
ProposerRewardPool sdk.Coins `json:"proposer_reward_pool"` // XXX reward pool collected from being the proposer
|
||||
|
||||
Commission sdk.Rat `json:"commission"` // XXX the commission rate of fees charged to any delegators
|
||||
CommissionMax sdk.Rat `json:"commission_max"` // XXX maximum commission rate which this validator can ever charge
|
||||
CommissionChangeRate sdk.Rat `json:"commission_change_rate"` // XXX maximum daily increase of the validator commission
|
||||
CommissionChangeToday sdk.Rat `json:"commission_change_today"` // XXX commission rate change today, reset each day (UTC time)
|
||||
|
||||
// fee related
|
||||
PrevBondedShares sdk.Rat `json:"prev_bonded_shares"` // total shares of a global hold pools
|
||||
}
|
||||
|
||||
func bech32StakeValidatorOutput(validator stake.Validator) (StakeValidatorOutput, error) {
|
||||
bechOwner, err := sdk.Bech32ifyVal(validator.Owner)
|
||||
if err != nil {
|
||||
return StakeValidatorOutput{}, err
|
||||
}
|
||||
bechValPubkey, err := sdk.Bech32ifyValPub(validator.PubKey)
|
||||
if err != nil {
|
||||
return StakeValidatorOutput{}, err
|
||||
}
|
||||
|
||||
return StakeValidatorOutput{
|
||||
Owner: bechOwner,
|
||||
PubKey: bechValPubkey,
|
||||
Revoked: validator.Revoked,
|
||||
|
||||
PoolShares: validator.PoolShares,
|
||||
DelegatorShares: validator.DelegatorShares,
|
||||
|
||||
Description: validator.Description,
|
||||
BondHeight: validator.BondHeight,
|
||||
BondIntraTxCounter: validator.BondIntraTxCounter,
|
||||
ProposerRewardPool: validator.ProposerRewardPool,
|
||||
|
||||
Commission: validator.Commission,
|
||||
CommissionMax: validator.CommissionMax,
|
||||
CommissionChangeRate: validator.CommissionChangeRate,
|
||||
CommissionChangeToday: validator.CommissionChangeToday,
|
||||
|
||||
PrevBondedShares: validator.PrevBondedShares,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TODO bech32
|
||||
// http request handler to query list of validators
|
||||
func validatorsHandlerFn(ctx context.CoreContext, storeName string, cdc *wire.Codec) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -100,16 +153,20 @@ func validatorsHandlerFn(ctx context.CoreContext, storeName string, cdc *wire.Co
|
|||
}
|
||||
|
||||
// parse out the validators
|
||||
validators := make([]stake.Validator, len(kvs))
|
||||
validators := make([]StakeValidatorOutput, len(kvs))
|
||||
for i, kv := range kvs {
|
||||
var validator stake.Validator
|
||||
var bech32Validator StakeValidatorOutput
|
||||
err = cdc.UnmarshalBinary(kv.Value, &validator)
|
||||
if err == nil {
|
||||
bech32Validator, err = bech32StakeValidatorOutput(validator)
|
||||
}
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error())))
|
||||
return
|
||||
}
|
||||
validators[i] = validator
|
||||
validators[i] = bech32Validator
|
||||
}
|
||||
|
||||
output, err := cdc.MarshalJSON(validators)
|
||||
|
|
|
@ -3,6 +3,7 @@ package rest
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
|
@ -23,13 +24,24 @@ func registerTxRoutes(ctx context.CoreContext, r *mux.Router, cdc *wire.Codec, k
|
|||
).Methods("POST")
|
||||
}
|
||||
|
||||
type msgDelegateInput struct {
|
||||
DelegatorAddr string `json:"delegator_addr"` // in bech32
|
||||
ValidatorAddr string `json:"validator_addr"` // in bech32
|
||||
Bond sdk.Coin `json:"bond"`
|
||||
}
|
||||
type msgUnbondInput struct {
|
||||
DelegatorAddr string `json:"delegator_addr"` // in bech32
|
||||
ValidatorAddr string `json:"validator_addr"` // in bech32
|
||||
Shares string `json:"shares"`
|
||||
}
|
||||
|
||||
type editDelegationsBody struct {
|
||||
LocalAccountName string `json:"name"`
|
||||
Password string `json:"password"`
|
||||
ChainID string `json:"chain_id"`
|
||||
Sequence int64 `json:"sequence"`
|
||||
Delegate []stake.MsgDelegate `json:"delegate"`
|
||||
Unbond []stake.MsgUnbond `json:"unbond"`
|
||||
LocalAccountName string `json:"name"`
|
||||
Password string `json:"password"`
|
||||
ChainID string `json:"chain_id"`
|
||||
Sequence int64 `json:"sequence"`
|
||||
Delegate []msgDelegateInput `json:"delegate"`
|
||||
Unbond []msgUnbondInput `json:"unbond"`
|
||||
}
|
||||
|
||||
func editDelegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx context.CoreContext) http.HandlerFunc {
|
||||
|
@ -59,21 +71,53 @@ func editDelegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx conte
|
|||
messages := make([]sdk.Msg, len(m.Delegate)+len(m.Unbond))
|
||||
i := 0
|
||||
for _, msg := range m.Delegate {
|
||||
if !bytes.Equal(info.Address(), msg.DelegatorAddr) {
|
||||
delegatorAddr, err := sdk.GetAccAddressBech32(msg.DelegatorAddr)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(fmt.Sprintf("Couldn't decode delegator. Error: %s", err.Error())))
|
||||
return
|
||||
}
|
||||
validatorAddr, err := sdk.GetValAddressBech32(msg.ValidatorAddr)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error())))
|
||||
return
|
||||
}
|
||||
if !bytes.Equal(info.Address(), delegatorAddr) {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
w.Write([]byte("Must use own delegator address"))
|
||||
return
|
||||
}
|
||||
messages[i] = msg
|
||||
messages[i] = stake.MsgDelegate{
|
||||
DelegatorAddr: delegatorAddr,
|
||||
ValidatorAddr: validatorAddr,
|
||||
Bond: msg.Bond,
|
||||
}
|
||||
i++
|
||||
}
|
||||
for _, msg := range m.Unbond {
|
||||
if !bytes.Equal(info.Address(), msg.DelegatorAddr) {
|
||||
delegatorAddr, err := sdk.GetAccAddressBech32(msg.DelegatorAddr)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(fmt.Sprintf("Couldn't decode delegator. Error: %s", err.Error())))
|
||||
return
|
||||
}
|
||||
validatorAddr, err := sdk.GetValAddressBech32(msg.ValidatorAddr)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(fmt.Sprintf("Couldn't decode validator. Error: %s", err.Error())))
|
||||
return
|
||||
}
|
||||
if !bytes.Equal(info.Address(), delegatorAddr) {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
w.Write([]byte("Must use own delegator address"))
|
||||
return
|
||||
}
|
||||
messages[i] = msg
|
||||
messages[i] = stake.MsgUnbond{
|
||||
DelegatorAddr: delegatorAddr,
|
||||
ValidatorAddr: validatorAddr,
|
||||
Shares: msg.Shares,
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue