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

View File

@ -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_

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
}

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 {

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)

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)
}

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

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)
}
}

View File

@ -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 {

View File

@ -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

View File

@ -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 {

View File

@ -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())))

View File

@ -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()))

View File

@ -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()))

View File

@ -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)

View File

@ -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++
}