mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-26 00:05:18 +00:00
commit
3ff2637431
23
Gopkg.lock
generated
23
Gopkg.lock
generated
@ -48,7 +48,7 @@
|
||||
revision = "d4cc87b860166d00d6b5b9e0d3b3d71d6088d4d4"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:7f6e80c9a48014e57211353a9a82d12088f9dc85f564b6a70674bbc1d5abc34e"
|
||||
digest = "1:485c3fd6d387a850672e86b89eabf32d0363890652c1b499898c925a5e8a02ce"
|
||||
name = "github.com/cosmos/cosmos-sdk"
|
||||
packages = [
|
||||
"baseapp",
|
||||
@ -66,21 +66,26 @@
|
||||
"server",
|
||||
"server/config",
|
||||
"store",
|
||||
"tests",
|
||||
"types",
|
||||
"version",
|
||||
"wire",
|
||||
"x/auth",
|
||||
"x/auth/client/cli",
|
||||
"x/auth/client/context",
|
||||
"x/auth/client/rest",
|
||||
"x/bank",
|
||||
"x/bank/client",
|
||||
"x/bank/client/cli",
|
||||
"x/bank/client/rest",
|
||||
"x/mock",
|
||||
"x/params",
|
||||
"x/slashing",
|
||||
"x/slashing/client/cli",
|
||||
"x/slashing/client/rest",
|
||||
"x/stake",
|
||||
"x/stake/client/cli",
|
||||
"x/stake/client/rest",
|
||||
"x/stake/keeper",
|
||||
"x/stake/tags",
|
||||
"x/stake/types",
|
||||
@ -673,34 +678,50 @@
|
||||
"github.com/cosmos/cosmos-sdk/client/rpc",
|
||||
"github.com/cosmos/cosmos-sdk/client/tx",
|
||||
"github.com/cosmos/cosmos-sdk/client/utils",
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys",
|
||||
"github.com/cosmos/cosmos-sdk/server",
|
||||
"github.com/cosmos/cosmos-sdk/server/config",
|
||||
"github.com/cosmos/cosmos-sdk/tests",
|
||||
"github.com/cosmos/cosmos-sdk/types",
|
||||
"github.com/cosmos/cosmos-sdk/version",
|
||||
"github.com/cosmos/cosmos-sdk/wire",
|
||||
"github.com/cosmos/cosmos-sdk/x/auth",
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/client/cli",
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/client/context",
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/client/rest",
|
||||
"github.com/cosmos/cosmos-sdk/x/bank",
|
||||
"github.com/cosmos/cosmos-sdk/x/bank/client/cli",
|
||||
"github.com/cosmos/cosmos-sdk/x/bank/client/rest",
|
||||
"github.com/cosmos/cosmos-sdk/x/mock",
|
||||
"github.com/cosmos/cosmos-sdk/x/params",
|
||||
"github.com/cosmos/cosmos-sdk/x/slashing",
|
||||
"github.com/cosmos/cosmos-sdk/x/slashing/client/cli",
|
||||
"github.com/cosmos/cosmos-sdk/x/slashing/client/rest",
|
||||
"github.com/cosmos/cosmos-sdk/x/stake",
|
||||
"github.com/cosmos/cosmos-sdk/x/stake/client/cli",
|
||||
"github.com/cosmos/cosmos-sdk/x/stake/client/rest",
|
||||
"github.com/gorilla/mux",
|
||||
"github.com/pkg/errors",
|
||||
"github.com/spf13/cobra",
|
||||
"github.com/spf13/pflag",
|
||||
"github.com/spf13/viper",
|
||||
"github.com/stretchr/testify/assert",
|
||||
"github.com/stretchr/testify/require",
|
||||
"github.com/tendermint/go-amino",
|
||||
"github.com/tendermint/tendermint/abci/types",
|
||||
"github.com/tendermint/tendermint/config",
|
||||
"github.com/tendermint/tendermint/crypto",
|
||||
"github.com/tendermint/tendermint/crypto/ed25519",
|
||||
"github.com/tendermint/tendermint/libs/cli",
|
||||
"github.com/tendermint/tendermint/libs/common",
|
||||
"github.com/tendermint/tendermint/libs/db",
|
||||
"github.com/tendermint/tendermint/libs/log",
|
||||
"github.com/tendermint/tendermint/node",
|
||||
"github.com/tendermint/tendermint/p2p",
|
||||
"github.com/tendermint/tendermint/privval",
|
||||
"github.com/tendermint/tendermint/proxy",
|
||||
"github.com/tendermint/tendermint/rpc/core/types",
|
||||
"github.com/tendermint/tendermint/rpc/lib/server",
|
||||
"github.com/tendermint/tendermint/types",
|
||||
]
|
||||
solver-name = "gps-cdcl"
|
||||
|
@ -22,7 +22,7 @@ import (
|
||||
paychancmd "github.com/kava-labs/kava/internal/x/paychan/client/cli"
|
||||
|
||||
"github.com/kava-labs/kava/internal/app"
|
||||
//"github.com/kava-labs/kava/internal/lcd"
|
||||
"github.com/kava-labs/kava/internal/lcd"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -59,8 +59,7 @@ func main() {
|
||||
|
||||
advancedCmd.AddCommand(
|
||||
tendermintCmd,
|
||||
//ibcCmd,
|
||||
//lcd.ServeCommand(cdc),
|
||||
lcd.ServeCommand(cdc),
|
||||
)
|
||||
rootCmd.AddCommand(
|
||||
advancedCmd,
|
||||
|
@ -1,27 +1,24 @@
|
||||
package lcd
|
||||
|
||||
/*
|
||||
import (
|
||||
"net/http"
|
||||
//"encoding/hex"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/context"
|
||||
"github.com/cosmos/cosmos-sdk/wire"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
)
|
||||
*/
|
||||
|
||||
type TxBody struct {
|
||||
type txBody struct {
|
||||
TxBase64 string `json:"txbase64"`
|
||||
}
|
||||
|
||||
// Decode a tx from base64 into json
|
||||
func DecodeTxRequestHandlerFn(ctx context.CoreContext, cdc *wire.Codec) http.HandlerFunc {
|
||||
func DecodeTxRequestHandlerFn(cliCtx context.CLIContext, cdc *wire.Codec) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// get the input base64 string
|
||||
var m TxBody
|
||||
var m txBody
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
err := decoder.Decode(&m)
|
||||
if err != nil {
|
||||
|
695
internal/lcd/lcd_test.go
Normal file
695
internal/lcd/lcd_test.go
Normal file
@ -0,0 +1,695 @@
|
||||
// Copyright 2016 All in Bits, inc
|
||||
// Modifications copyright 2018 Kava Labs
|
||||
package lcd
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
cryptoKeys "github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
p2p "github.com/tendermint/tendermint/p2p"
|
||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
|
||||
client "github.com/cosmos/cosmos-sdk/client"
|
||||
keys "github.com/cosmos/cosmos-sdk/client/keys"
|
||||
rpc "github.com/cosmos/cosmos-sdk/client/rpc"
|
||||
tests "github.com/cosmos/cosmos-sdk/tests"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/wire"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/slashing"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake/client/rest"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cryptoKeys.BcryptSecurityParameter = 1
|
||||
}
|
||||
|
||||
func TestKeys(t *testing.T) {
|
||||
name, password := "test", "1234567890"
|
||||
addr, seed := CreateAddr(t, "test", password, GetKeyBase(t))
|
||||
cleanup, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr})
|
||||
defer cleanup()
|
||||
|
||||
// get seed
|
||||
// TODO Do we really need this endpoint?
|
||||
res, body := Request(t, port, "GET", "/keys/seed", nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
reg, err := regexp.Compile(`([a-z]+ ){12}`)
|
||||
require.Nil(t, err)
|
||||
match := reg.MatchString(seed)
|
||||
require.True(t, match, "Returned seed has wrong format", seed)
|
||||
|
||||
newName := "test_newname"
|
||||
newPassword := "0987654321"
|
||||
|
||||
// add key
|
||||
jsonStr := []byte(fmt.Sprintf(`{"name":"%s", "password":"%s", "seed":"%s"}`, newName, newPassword, seed))
|
||||
res, body = Request(t, port, "POST", "/keys", jsonStr)
|
||||
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
var resp keys.KeyOutput
|
||||
err = wire.Cdc.UnmarshalJSON([]byte(body), &resp)
|
||||
require.Nil(t, err, body)
|
||||
|
||||
addr2Bech32 := resp.Address.String()
|
||||
_, err = sdk.AccAddressFromBech32(addr2Bech32)
|
||||
require.NoError(t, err, "Failed to return a correct bech32 address")
|
||||
|
||||
// test if created account is the correct account
|
||||
expectedInfo, _ := GetKeyBase(t).CreateKey(newName, seed, newPassword)
|
||||
expectedAccount := sdk.AccAddress(expectedInfo.GetPubKey().Address().Bytes())
|
||||
assert.Equal(t, expectedAccount.String(), addr2Bech32)
|
||||
|
||||
// existing keys
|
||||
res, body = Request(t, port, "GET", "/keys", nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
var m [2]keys.KeyOutput
|
||||
err = cdc.UnmarshalJSON([]byte(body), &m)
|
||||
require.Nil(t, err)
|
||||
|
||||
addrBech32 := addr.String()
|
||||
|
||||
require.Equal(t, name, m[0].Name, "Did not serve keys name correctly")
|
||||
require.Equal(t, addrBech32, m[0].Address.String(), "Did not serve keys Address correctly")
|
||||
require.Equal(t, newName, m[1].Name, "Did not serve keys name correctly")
|
||||
require.Equal(t, addr2Bech32, m[1].Address.String(), "Did not serve keys Address correctly")
|
||||
|
||||
// select key
|
||||
keyEndpoint := fmt.Sprintf("/keys/%s", newName)
|
||||
res, body = Request(t, port, "GET", keyEndpoint, nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
var m2 keys.KeyOutput
|
||||
err = cdc.UnmarshalJSON([]byte(body), &m2)
|
||||
require.Nil(t, err)
|
||||
|
||||
require.Equal(t, newName, m2.Name, "Did not serve keys name correctly")
|
||||
require.Equal(t, addr2Bech32, m2.Address.String(), "Did not serve keys Address correctly")
|
||||
|
||||
// update key
|
||||
jsonStr = []byte(fmt.Sprintf(`{
|
||||
"old_password":"%s",
|
||||
"new_password":"12345678901"
|
||||
}`, newPassword))
|
||||
|
||||
res, body = Request(t, port, "PUT", keyEndpoint, jsonStr)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
// here it should say unauthorized as we changed the password before
|
||||
res, body = Request(t, port, "PUT", keyEndpoint, jsonStr)
|
||||
require.Equal(t, http.StatusUnauthorized, res.StatusCode, body)
|
||||
|
||||
// delete key
|
||||
jsonStr = []byte(`{"password":"12345678901"}`)
|
||||
res, body = Request(t, port, "DELETE", keyEndpoint, jsonStr)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
}
|
||||
|
||||
func TestVersion(t *testing.T) {
|
||||
cleanup, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{})
|
||||
defer cleanup()
|
||||
|
||||
// node info
|
||||
res, body := Request(t, port, "GET", "/version", nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
reg, err := regexp.Compile(`\d+\.\d+\.\d+(-dev)?`)
|
||||
require.Nil(t, err)
|
||||
match := reg.MatchString(body)
|
||||
require.True(t, match, body)
|
||||
|
||||
// node info
|
||||
res, body = Request(t, port, "GET", "/node_version", nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
reg, err = regexp.Compile(`\d+\.\d+\.\d+(-dev)?`)
|
||||
require.Nil(t, err)
|
||||
match = reg.MatchString(body)
|
||||
require.True(t, match, body)
|
||||
}
|
||||
|
||||
func TestNodeStatus(t *testing.T) {
|
||||
cleanup, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{})
|
||||
defer cleanup()
|
||||
|
||||
// node info
|
||||
res, body := Request(t, port, "GET", "/node_info", nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
var nodeInfo p2p.NodeInfo
|
||||
err := cdc.UnmarshalJSON([]byte(body), &nodeInfo)
|
||||
require.Nil(t, err, "Couldn't parse node info")
|
||||
|
||||
require.NotEqual(t, p2p.NodeInfo{}, nodeInfo, "res: %v", res)
|
||||
|
||||
// syncing
|
||||
res, body = Request(t, port, "GET", "/syncing", nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
// we expect that there is no other node running so the syncing state is "false"
|
||||
require.Equal(t, "false", body)
|
||||
}
|
||||
|
||||
func TestBlock(t *testing.T) {
|
||||
cleanup, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{})
|
||||
defer cleanup()
|
||||
|
||||
var resultBlock ctypes.ResultBlock
|
||||
|
||||
res, body := Request(t, port, "GET", "/blocks/latest", nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
err := cdc.UnmarshalJSON([]byte(body), &resultBlock)
|
||||
require.Nil(t, err, "Couldn't parse block")
|
||||
|
||||
require.NotEqual(t, ctypes.ResultBlock{}, resultBlock)
|
||||
|
||||
// --
|
||||
|
||||
res, body = Request(t, port, "GET", "/blocks/1", nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
err = wire.Cdc.UnmarshalJSON([]byte(body), &resultBlock)
|
||||
require.Nil(t, err, "Couldn't parse block")
|
||||
|
||||
require.NotEqual(t, ctypes.ResultBlock{}, resultBlock)
|
||||
|
||||
// --
|
||||
|
||||
res, body = Request(t, port, "GET", "/blocks/1000000000", nil)
|
||||
require.Equal(t, http.StatusNotFound, res.StatusCode, body)
|
||||
}
|
||||
|
||||
func TestValidators(t *testing.T) {
|
||||
cleanup, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{})
|
||||
defer cleanup()
|
||||
|
||||
var resultVals rpc.ResultValidatorsOutput
|
||||
|
||||
res, body := Request(t, port, "GET", "/validatorsets/latest", nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
err := cdc.UnmarshalJSON([]byte(body), &resultVals)
|
||||
require.Nil(t, err, "Couldn't parse validatorset")
|
||||
|
||||
require.NotEqual(t, rpc.ResultValidatorsOutput{}, resultVals)
|
||||
|
||||
require.Contains(t, resultVals.Validators[0].Address.String(), "cosmosvaladdr")
|
||||
require.Contains(t, resultVals.Validators[0].PubKey, "cosmosvalpub")
|
||||
|
||||
// --
|
||||
|
||||
res, body = Request(t, port, "GET", "/validatorsets/1", nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
err = cdc.UnmarshalJSON([]byte(body), &resultVals)
|
||||
require.Nil(t, err, "Couldn't parse validatorset")
|
||||
|
||||
require.NotEqual(t, rpc.ResultValidatorsOutput{}, resultVals)
|
||||
|
||||
// --
|
||||
|
||||
res, body = Request(t, port, "GET", "/validatorsets/1000000000", nil)
|
||||
require.Equal(t, http.StatusNotFound, res.StatusCode, body)
|
||||
}
|
||||
|
||||
func TestCoinSend(t *testing.T) {
|
||||
name, password := "test", "1234567890"
|
||||
addr, seed := CreateAddr(t, "test", password, GetKeyBase(t))
|
||||
cleanup, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr})
|
||||
defer cleanup()
|
||||
|
||||
bz, err := hex.DecodeString("8FA6AB57AD6870F6B5B2E57735F38F2F30E73CB6")
|
||||
require.NoError(t, err)
|
||||
someFakeAddr := sdk.AccAddress(bz)
|
||||
|
||||
// query empty
|
||||
res, body := Request(t, port, "GET", fmt.Sprintf("/accounts/%s", someFakeAddr), nil)
|
||||
require.Equal(t, http.StatusNoContent, res.StatusCode, body)
|
||||
|
||||
acc := getAccount(t, port, addr)
|
||||
initialBalance := acc.GetCoins()
|
||||
|
||||
// create TX
|
||||
receiveAddr, resultTx := doSend(t, port, seed, name, password, addr)
|
||||
tests.WaitForHeight(resultTx.Height+1, port)
|
||||
|
||||
// check if tx was committed
|
||||
require.Equal(t, uint32(0), resultTx.CheckTx.Code)
|
||||
require.Equal(t, uint32(0), resultTx.DeliverTx.Code)
|
||||
|
||||
// query sender
|
||||
acc = getAccount(t, port, addr)
|
||||
coins := acc.GetCoins()
|
||||
mycoins := coins[0]
|
||||
|
||||
require.Equal(t, "KVA", mycoins.Denom)
|
||||
require.Equal(t, initialBalance[0].Amount.SubRaw(1), mycoins.Amount)
|
||||
|
||||
// query receiver
|
||||
acc = getAccount(t, port, receiveAddr)
|
||||
coins = acc.GetCoins()
|
||||
mycoins = coins[0]
|
||||
|
||||
require.Equal(t, "KVA", mycoins.Denom)
|
||||
require.Equal(t, int64(1), mycoins.Amount.Int64())
|
||||
}
|
||||
|
||||
func TestTxs(t *testing.T) {
|
||||
name, password := "test", "1234567890"
|
||||
addr, seed := CreateAddr(t, "test", password, GetKeyBase(t))
|
||||
cleanup, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr})
|
||||
defer cleanup()
|
||||
|
||||
// query wrong
|
||||
res, body := Request(t, port, "GET", "/txs", nil)
|
||||
require.Equal(t, http.StatusBadRequest, res.StatusCode, body)
|
||||
|
||||
// query empty
|
||||
res, body = Request(t, port, "GET", fmt.Sprintf("/txs?tag=sender_bech32='%s'", "cosmosaccaddr1jawd35d9aq4u76sr3fjalmcqc8hqygs9gtnmv3"), nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
require.Equal(t, "[]", body)
|
||||
|
||||
// create TX
|
||||
receiveAddr, resultTx := doSend(t, port, seed, name, password, addr)
|
||||
|
||||
tests.WaitForHeight(resultTx.Height+1, port)
|
||||
|
||||
// check if tx is findable
|
||||
res, body = Request(t, port, "GET", fmt.Sprintf("/txs/%s", resultTx.Hash), nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
var indexedTxs []tx.Info
|
||||
|
||||
// check if tx is queryable
|
||||
res, body = Request(t, port, "GET", fmt.Sprintf("/txs?tag=tx.hash='%s'", resultTx.Hash), nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
require.NotEqual(t, "[]", body)
|
||||
|
||||
err := cdc.UnmarshalJSON([]byte(body), &indexedTxs)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(indexedTxs))
|
||||
|
||||
// XXX should this move into some other testfile for txs in general?
|
||||
// test if created TX hash is the correct hash
|
||||
require.Equal(t, resultTx.Hash, indexedTxs[0].Hash)
|
||||
|
||||
// query sender
|
||||
// also tests url decoding
|
||||
res, body = Request(t, port, "GET", fmt.Sprintf("/txs?tag=sender_bech32=%%27%s%%27", addr), nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
err = cdc.UnmarshalJSON([]byte(body), &indexedTxs)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(indexedTxs), "%v", indexedTxs) // there are 2 txs created with doSend
|
||||
require.Equal(t, resultTx.Height, indexedTxs[0].Height)
|
||||
|
||||
// query recipient
|
||||
res, body = Request(t, port, "GET", fmt.Sprintf("/txs?tag=recipient_bech32='%s'", receiveAddr), nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
err = cdc.UnmarshalJSON([]byte(body), &indexedTxs)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(indexedTxs))
|
||||
require.Equal(t, resultTx.Height, indexedTxs[0].Height)
|
||||
}
|
||||
|
||||
func TestValidatorsQuery(t *testing.T) {
|
||||
cleanup, pks, port := InitializeTestLCD(t, 1, []sdk.AccAddress{})
|
||||
defer cleanup()
|
||||
require.Equal(t, 1, len(pks))
|
||||
|
||||
validators := getValidators(t, port)
|
||||
require.Equal(t, len(validators), 1)
|
||||
|
||||
// make sure all the validators were found (order unknown because sorted by owner addr)
|
||||
foundVal := false
|
||||
pkBech := sdk.MustBech32ifyValPub(pks[0])
|
||||
if validators[0].PubKey == pkBech {
|
||||
foundVal = true
|
||||
}
|
||||
require.True(t, foundVal, "pkBech %v, owner %v", pkBech, validators[0].Owner)
|
||||
}
|
||||
|
||||
func TestValidatorQuery(t *testing.T) {
|
||||
cleanup, pks, port := InitializeTestLCD(t, 1, []sdk.AccAddress{})
|
||||
defer cleanup()
|
||||
require.Equal(t, 1, len(pks))
|
||||
|
||||
validator1Owner := sdk.AccAddress(pks[0].Address())
|
||||
|
||||
validator := getValidator(t, port, validator1Owner)
|
||||
bech32ValAddress, err := sdk.Bech32ifyValPub(pks[0])
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, validator.PubKey, bech32ValAddress, "The returned validator does not hold the correct data")
|
||||
}
|
||||
|
||||
func TestBonding(t *testing.T) {
|
||||
name, password, denom := "test", "1234567890", "KVA"
|
||||
addr, seed := CreateAddr(t, "test", password, GetKeyBase(t))
|
||||
cleanup, pks, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr})
|
||||
defer cleanup()
|
||||
|
||||
validator1Owner := sdk.AccAddress(pks[0].Address())
|
||||
|
||||
// create bond TX
|
||||
resultTx := doDelegate(t, port, seed, name, password, addr, validator1Owner)
|
||||
tests.WaitForHeight(resultTx.Height+1, port)
|
||||
|
||||
// check if tx was committed
|
||||
require.Equal(t, uint32(0), resultTx.CheckTx.Code)
|
||||
require.Equal(t, uint32(0), resultTx.DeliverTx.Code)
|
||||
|
||||
// query sender
|
||||
acc := getAccount(t, port, addr)
|
||||
coins := acc.GetCoins()
|
||||
|
||||
require.Equal(t, int64(40), coins.AmountOf(denom).Int64())
|
||||
|
||||
// query validator
|
||||
bond := getDelegation(t, port, addr, validator1Owner)
|
||||
require.Equal(t, "60.0000000000", bond.Shares)
|
||||
|
||||
//////////////////////
|
||||
// testing unbonding
|
||||
|
||||
// create unbond TX
|
||||
resultTx = doBeginUnbonding(t, port, seed, name, password, addr, validator1Owner)
|
||||
tests.WaitForHeight(resultTx.Height+1, port)
|
||||
|
||||
// query validator
|
||||
bond = getDelegation(t, port, addr, validator1Owner)
|
||||
require.Equal(t, "30.0000000000", bond.Shares)
|
||||
|
||||
// check if tx was committed
|
||||
require.Equal(t, uint32(0), resultTx.CheckTx.Code)
|
||||
require.Equal(t, uint32(0), resultTx.DeliverTx.Code)
|
||||
|
||||
// should the sender should have not received any coins as the unbonding has only just begun
|
||||
// query sender
|
||||
acc = getAccount(t, port, addr)
|
||||
coins = acc.GetCoins()
|
||||
require.Equal(t, int64(40), coins.AmountOf("KVA").Int64())
|
||||
|
||||
// query unbonding delegation
|
||||
validatorAddr := sdk.AccAddress(pks[0].Address())
|
||||
unbondings := getUndelegations(t, port, addr, validatorAddr)
|
||||
assert.Len(t, unbondings, 1, "Unbondings holds all unbonding-delegations")
|
||||
assert.Equal(t, "30", unbondings[0].Balance.Amount.String())
|
||||
|
||||
// query summary
|
||||
summary := getDelegationSummary(t, port, addr)
|
||||
|
||||
assert.Len(t, summary.Delegations, 1, "Delegation summary holds all delegations")
|
||||
assert.Equal(t, "30.0000000000", summary.Delegations[0].Shares)
|
||||
assert.Len(t, summary.UnbondingDelegations, 1, "Delegation summary holds all unbonding-delegations")
|
||||
assert.Equal(t, "30", summary.UnbondingDelegations[0].Balance.Amount.String())
|
||||
|
||||
// TODO add redelegation, need more complex capabilities such to mock context and
|
||||
// TODO check summary for redelegation
|
||||
// assert.Len(t, summary.Redelegations, 1, "Delegation summary holds all redelegations")
|
||||
|
||||
// query txs
|
||||
txs := getBondingTxs(t, port, addr, "")
|
||||
assert.Len(t, txs, 2, "All Txs found")
|
||||
|
||||
txs = getBondingTxs(t, port, addr, "bond")
|
||||
assert.Len(t, txs, 1, "All bonding txs found")
|
||||
|
||||
txs = getBondingTxs(t, port, addr, "unbond")
|
||||
assert.Len(t, txs, 1, "All unbonding txs found")
|
||||
}
|
||||
|
||||
func TestUnrevoke(t *testing.T) {
|
||||
_, password := "test", "1234567890"
|
||||
addr, _ := CreateAddr(t, "test", password, GetKeyBase(t))
|
||||
cleanup, pks, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr})
|
||||
defer cleanup()
|
||||
|
||||
// XXX: any less than this and it fails
|
||||
tests.WaitForHeight(3, port)
|
||||
pkString, _ := sdk.Bech32ifyValPub(pks[0])
|
||||
signingInfo := getSigningInfo(t, port, pkString)
|
||||
tests.WaitForHeight(4, port)
|
||||
require.Equal(t, true, signingInfo.IndexOffset > 0)
|
||||
require.Equal(t, time.Unix(0, 0).UTC(), signingInfo.JailedUntil)
|
||||
require.Equal(t, true, signingInfo.SignedBlocksCounter > 0)
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
// get the account to get the sequence
|
||||
func getAccount(t *testing.T, port string, addr sdk.AccAddress) auth.Account {
|
||||
res, body := Request(t, port, "GET", fmt.Sprintf("/accounts/%s", addr), nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
var acc auth.Account
|
||||
err := cdc.UnmarshalJSON([]byte(body), &acc)
|
||||
require.Nil(t, err)
|
||||
return acc
|
||||
}
|
||||
|
||||
func doSend(t *testing.T, port, seed, name, password string, addr sdk.AccAddress) (receiveAddr sdk.AccAddress, resultTx ctypes.ResultBroadcastTxCommit) {
|
||||
|
||||
// create receive address
|
||||
kb := client.MockKeyBase()
|
||||
receiveInfo, _, err := kb.CreateMnemonic("receive_address", cryptoKeys.English, "1234567890", cryptoKeys.SigningAlgo("secp256k1"))
|
||||
require.Nil(t, err)
|
||||
receiveAddr = sdk.AccAddress(receiveInfo.GetPubKey().Address())
|
||||
|
||||
acc := getAccount(t, port, addr)
|
||||
accnum := acc.GetAccountNumber()
|
||||
sequence := acc.GetSequence()
|
||||
chainID := viper.GetString(client.FlagChainID)
|
||||
// send
|
||||
coinbz, err := cdc.MarshalJSON(sdk.NewInt64Coin("KVA", 1))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
jsonStr := []byte(fmt.Sprintf(`{
|
||||
"name":"%s",
|
||||
"password":"%s",
|
||||
"account_number":"%d",
|
||||
"sequence":"%d",
|
||||
"gas": "10000",
|
||||
"amount":[%s],
|
||||
"chain_id":"%s"
|
||||
}`, name, password, accnum, sequence, coinbz, chainID))
|
||||
res, body := Request(t, port, "POST", fmt.Sprintf("/accounts/%s/send", receiveAddr), jsonStr)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
err = cdc.UnmarshalJSON([]byte(body), &resultTx)
|
||||
require.Nil(t, err)
|
||||
|
||||
return receiveAddr, resultTx
|
||||
}
|
||||
|
||||
func getSigningInfo(t *testing.T, port string, validatorPubKey string) slashing.ValidatorSigningInfo {
|
||||
res, body := Request(t, port, "GET", fmt.Sprintf("/slashing/signing_info/%s", validatorPubKey), nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
var signingInfo slashing.ValidatorSigningInfo
|
||||
err := cdc.UnmarshalJSON([]byte(body), &signingInfo)
|
||||
require.Nil(t, err)
|
||||
return signingInfo
|
||||
}
|
||||
|
||||
// ============= Stake Module ================
|
||||
|
||||
func getDelegation(t *testing.T, port string, delegatorAddr, validatorAddr sdk.AccAddress) rest.DelegationWithoutRat {
|
||||
|
||||
// get the account to get the sequence
|
||||
res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/delegations/%s", delegatorAddr, validatorAddr), nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
var bond rest.DelegationWithoutRat
|
||||
err := cdc.UnmarshalJSON([]byte(body), &bond)
|
||||
require.Nil(t, err)
|
||||
return bond
|
||||
}
|
||||
|
||||
func getUndelegations(t *testing.T, port string, delegatorAddr, validatorAddr sdk.AccAddress) []stake.UnbondingDelegation {
|
||||
|
||||
// get the account to get the sequence
|
||||
res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/unbonding_delegations/%s", delegatorAddr, validatorAddr), nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
var unbondings []stake.UnbondingDelegation
|
||||
err := cdc.UnmarshalJSON([]byte(body), &unbondings)
|
||||
require.Nil(t, err)
|
||||
return unbondings
|
||||
}
|
||||
|
||||
func getDelegationSummary(t *testing.T, port string, delegatorAddr sdk.AccAddress) rest.DelegationSummary {
|
||||
|
||||
// get the account to get the sequence
|
||||
res, body := Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s", delegatorAddr), nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
var summary rest.DelegationSummary
|
||||
err := cdc.UnmarshalJSON([]byte(body), &summary)
|
||||
require.Nil(t, err)
|
||||
return summary
|
||||
}
|
||||
|
||||
func getBondingTxs(t *testing.T, port string, delegatorAddr sdk.AccAddress, query string) []tx.Info {
|
||||
|
||||
// get the account to get the sequence
|
||||
var res *http.Response
|
||||
var body string
|
||||
if len(query) > 0 {
|
||||
res, body = Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/txs?type=%s", delegatorAddr, query), nil)
|
||||
} else {
|
||||
res, body = Request(t, port, "GET", fmt.Sprintf("/stake/delegators/%s/txs", delegatorAddr), nil)
|
||||
}
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
var txs []tx.Info
|
||||
err := cdc.UnmarshalJSON([]byte(body), &txs)
|
||||
require.Nil(t, err)
|
||||
return txs
|
||||
}
|
||||
|
||||
func doDelegate(t *testing.T, port, seed, name, password string, delegatorAddr, validatorAddr sdk.AccAddress) (resultTx ctypes.ResultBroadcastTxCommit) {
|
||||
// get the account to get the sequence
|
||||
acc := getAccount(t, port, delegatorAddr)
|
||||
accnum := acc.GetAccountNumber()
|
||||
sequence := acc.GetSequence()
|
||||
|
||||
chainID := viper.GetString(client.FlagChainID)
|
||||
|
||||
// send
|
||||
jsonStr := []byte(fmt.Sprintf(`{
|
||||
"name": "%s",
|
||||
"password": "%s",
|
||||
"account_number": "%d",
|
||||
"sequence": "%d",
|
||||
"gas": "10000",
|
||||
"chain_id": "%s",
|
||||
"delegations": [
|
||||
{
|
||||
"delegator_addr": "%s",
|
||||
"validator_addr": "%s",
|
||||
"delegation": { "denom": "%s", "amount": "60" }
|
||||
}
|
||||
],
|
||||
"begin_unbondings": [],
|
||||
"complete_unbondings": [],
|
||||
"begin_redelegates": [],
|
||||
"complete_redelegates": []
|
||||
}`, name, password, accnum, sequence, chainID, delegatorAddr, validatorAddr, "KVA"))
|
||||
res, body := Request(t, port, "POST", fmt.Sprintf("/stake/delegators/%s/delegations", delegatorAddr), jsonStr)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
var results []ctypes.ResultBroadcastTxCommit
|
||||
err := cdc.UnmarshalJSON([]byte(body), &results)
|
||||
require.Nil(t, err)
|
||||
|
||||
return results[0]
|
||||
}
|
||||
|
||||
func doBeginUnbonding(t *testing.T, port, seed, name, password string,
|
||||
delegatorAddr, validatorAddr sdk.AccAddress) (resultTx ctypes.ResultBroadcastTxCommit) {
|
||||
|
||||
// get the account to get the sequence
|
||||
acc := getAccount(t, port, delegatorAddr)
|
||||
accnum := acc.GetAccountNumber()
|
||||
sequence := acc.GetSequence()
|
||||
|
||||
chainID := viper.GetString(client.FlagChainID)
|
||||
|
||||
// send
|
||||
jsonStr := []byte(fmt.Sprintf(`{
|
||||
"name": "%s",
|
||||
"password": "%s",
|
||||
"account_number": "%d",
|
||||
"sequence": "%d",
|
||||
"gas": "20000",
|
||||
"chain_id": "%s",
|
||||
"delegations": [],
|
||||
"begin_unbondings": [
|
||||
{
|
||||
"delegator_addr": "%s",
|
||||
"validator_addr": "%s",
|
||||
"shares": "30"
|
||||
}
|
||||
],
|
||||
"complete_unbondings": [],
|
||||
"begin_redelegates": [],
|
||||
"complete_redelegates": []
|
||||
}`, name, password, accnum, sequence, chainID, delegatorAddr, validatorAddr))
|
||||
res, body := Request(t, port, "POST", fmt.Sprintf("/stake/delegators/%s/delegations", delegatorAddr), jsonStr)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
var results []ctypes.ResultBroadcastTxCommit
|
||||
err := cdc.UnmarshalJSON([]byte(body), &results)
|
||||
require.Nil(t, err)
|
||||
|
||||
return results[0]
|
||||
}
|
||||
|
||||
func doBeginRedelegation(t *testing.T, port, seed, name, password string,
|
||||
delegatorAddr, validatorSrcAddr, validatorDstAddr sdk.AccAddress) (resultTx ctypes.ResultBroadcastTxCommit) {
|
||||
|
||||
// get the account to get the sequence
|
||||
acc := getAccount(t, port, delegatorAddr)
|
||||
accnum := acc.GetAccountNumber()
|
||||
sequence := acc.GetSequence()
|
||||
|
||||
chainID := viper.GetString(client.FlagChainID)
|
||||
|
||||
// send
|
||||
jsonStr := []byte(fmt.Sprintf(`{
|
||||
"name": "%s",
|
||||
"password": "%s",
|
||||
"account_number": "%d",
|
||||
"sequence": "%d",
|
||||
"gas": "10000",
|
||||
"chain_id": "%s",
|
||||
"delegations": [],
|
||||
"begin_unbondings": [],
|
||||
"complete_unbondings": [],
|
||||
"begin_redelegates": [
|
||||
{
|
||||
"delegator_addr": "%s",
|
||||
"validator_src_addr": "%s",
|
||||
"validator_dst_addr": "%s",
|
||||
"shares": "30"
|
||||
}
|
||||
],
|
||||
"complete_redelegates": []
|
||||
}`, name, password, accnum, sequence, chainID, delegatorAddr, validatorSrcAddr, validatorDstAddr))
|
||||
res, body := Request(t, port, "POST", fmt.Sprintf("/stake/delegators/%s/delegations", delegatorAddr), jsonStr)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
var results []ctypes.ResultBroadcastTxCommit
|
||||
err := cdc.UnmarshalJSON([]byte(body), &results)
|
||||
require.Nil(t, err)
|
||||
|
||||
return results[0]
|
||||
}
|
||||
|
||||
func getValidators(t *testing.T, port string) []stake.BechValidator {
|
||||
// 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.BechValidator
|
||||
err := cdc.UnmarshalJSON([]byte(body), &validators)
|
||||
require.Nil(t, err)
|
||||
return validators
|
||||
}
|
||||
|
||||
func getValidator(t *testing.T, port string, validatorAddr sdk.AccAddress) stake.BechValidator {
|
||||
// get the account to get the sequence
|
||||
res, body := Request(t, port, "GET", fmt.Sprintf("/stake/validators/%s", validatorAddr.String()), nil)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
var validator stake.BechValidator
|
||||
err := cdc.UnmarshalJSON([]byte(body), &validator)
|
||||
require.Nil(t, err)
|
||||
return validator
|
||||
}
|
@ -3,32 +3,27 @@
|
||||
|
||||
package lcd
|
||||
|
||||
/*
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
tmserver "github.com/tendermint/tendermint/rpc/lib/server"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
|
||||
client "github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/context"
|
||||
keys "github.com/cosmos/cosmos-sdk/client/keys"
|
||||
rpc "github.com/cosmos/cosmos-sdk/client/rpc"
|
||||
tx "github.com/cosmos/cosmos-sdk/client/tx"
|
||||
version "github.com/cosmos/cosmos-sdk/version"
|
||||
"github.com/cosmos/cosmos-sdk/wire"
|
||||
auth "github.com/cosmos/cosmos-sdk/x/auth/client/rest"
|
||||
bank "github.com/cosmos/cosmos-sdk/x/bank/client/rest"
|
||||
//ibc "github.com/cosmos/cosmos-sdk/x/ibc/client/rest"
|
||||
//stake "github.com/cosmos/cosmos-sdk/x/stake/client/rest"
|
||||
slashing "github.com/cosmos/cosmos-sdk/x/slashing/client/rest"
|
||||
stake "github.com/cosmos/cosmos-sdk/x/stake/client/rest"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
cmn "github.com/tendermint/tendermint/libs/common"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmserver "github.com/tendermint/tendermint/rpc/lib/server"
|
||||
)
|
||||
*/
|
||||
|
||||
// ServeCommand will generate a long-running rest server
|
||||
// (aka Light Client Daemon) that exposes functionality similar
|
||||
@ -36,6 +31,7 @@ import (
|
||||
func ServeCommand(cdc *wire.Codec) *cobra.Command {
|
||||
flagListenAddr := "laddr"
|
||||
flagCORS := "cors"
|
||||
flagMaxOpenConnections := "max-open"
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "rest-server",
|
||||
@ -43,48 +39,59 @@ func ServeCommand(cdc *wire.Codec) *cobra.Command {
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
listenAddr := viper.GetString(flagListenAddr)
|
||||
handler := createHandler(cdc)
|
||||
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).
|
||||
With("module", "rest-server")
|
||||
listener, err := tmserver.StartHTTPServer(listenAddr, handler, logger)
|
||||
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "rest-server")
|
||||
maxOpen := viper.GetInt(flagMaxOpenConnections)
|
||||
|
||||
listener, err := tmserver.StartHTTPServer(
|
||||
listenAddr, handler, logger,
|
||||
tmserver.Config{MaxOpenConnections: maxOpen},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logger.Info("REST server started")
|
||||
|
||||
// Wait forever and cleanup
|
||||
// wait forever and cleanup
|
||||
cmn.TrapSignal(func() {
|
||||
err := listener.Close()
|
||||
logger.Error("Error closing listener", "err", err)
|
||||
logger.Error("error closing listener", "err", err)
|
||||
})
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
cmd.Flags().StringP(flagListenAddr, "a", "tcp://localhost:1317", "Address for server to listen on")
|
||||
cmd.Flags().String(flagCORS, "", "Set to domains that can make CORS requests (* for all)")
|
||||
cmd.Flags().StringP(client.FlagChainID, "c", "", "ID of chain we connect to")
|
||||
cmd.Flags().StringP(client.FlagNode, "n", "tcp://localhost:46657", "Node to connect to")
|
||||
|
||||
cmd.Flags().String(flagListenAddr, "tcp://localhost:1317", "The address for the server to listen on")
|
||||
cmd.Flags().String(flagCORS, "", "Set the domains that can make CORS requests (* for all)")
|
||||
cmd.Flags().String(client.FlagChainID, "", "The chain ID to connect to")
|
||||
cmd.Flags().String(client.FlagNode, "tcp://localhost:26657", "Address of the node to connect to")
|
||||
cmd.Flags().Int(flagMaxOpenConnections, 1000, "The number of maximum open connections")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func createHandler(cdc *wire.Codec) http.Handler {
|
||||
r := mux.NewRouter()
|
||||
r.HandleFunc("/version", version.RequestHandler).Methods("GET")
|
||||
|
||||
kb, err := keys.GetKeyBase() //XXX
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
ctx := context.NewCoreContextFromViper()
|
||||
cliCtx := context.NewCLIContext().WithCodec(cdc).WithLogger(os.Stdout)
|
||||
|
||||
r.HandleFunc("/version", CLIVersionRequestHandler).Methods("GET")
|
||||
r.HandleFunc("/node_version", NodeVersionRequestHandler(cliCtx)).Methods("GET")
|
||||
r.HandleFunc("/decode_tx", DecodeTxRequestHandlerFn(cliCtx, cdc)).Methods("POST")
|
||||
|
||||
// TODO make more functional? aka r = keys.RegisterRoutes(r)
|
||||
keys.RegisterRoutes(r)
|
||||
rpc.RegisterRoutes(ctx, r)
|
||||
tx.RegisterRoutes(ctx, r, cdc)
|
||||
auth.RegisterRoutes(ctx, r, cdc, "acc")
|
||||
bank.RegisterRoutes(ctx, r, cdc, kb)
|
||||
//ibc.RegisterRoutes(ctx, r, cdc, kb)
|
||||
//stake.RegisterRoutes(ctx, r, cdc, kb)
|
||||
r.HandleFunc("/decode_tx", DecodeTxRequestHandlerFn(ctx, cdc)).Methods("POST")
|
||||
rpc.RegisterRoutes(cliCtx, r)
|
||||
tx.RegisterRoutes(cliCtx, r, cdc)
|
||||
auth.RegisterRoutes(cliCtx, r, cdc, "acc")
|
||||
bank.RegisterRoutes(cliCtx, r, cdc, kb)
|
||||
stake.RegisterRoutes(cliCtx, r, cdc, kb)
|
||||
slashing.RegisterRoutes(cliCtx, r, cdc, kb)
|
||||
|
||||
return r
|
||||
}
|
||||
|
275
internal/lcd/test_helpers.go
Normal file
275
internal/lcd/test_helpers.go
Normal file
@ -0,0 +1,275 @@
|
||||
// Copyright 2016 All in Bits, inc
|
||||
// Modifications copyright 2018 Kava Labs
|
||||
|
||||
package lcd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
keys "github.com/cosmos/cosmos-sdk/client/keys"
|
||||
crkeys "github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
"github.com/cosmos/cosmos-sdk/tests"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/wire"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
kapp "github.com/kava-labs/kava/internal/app"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmcfg "github.com/tendermint/tendermint/config"
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||
"github.com/tendermint/tendermint/libs/cli"
|
||||
dbm "github.com/tendermint/tendermint/libs/db"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
nm "github.com/tendermint/tendermint/node"
|
||||
pvm "github.com/tendermint/tendermint/privval"
|
||||
"github.com/tendermint/tendermint/proxy"
|
||||
tmrpc "github.com/tendermint/tendermint/rpc/lib/server"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
// makePathname creates a unique pathname for each test. It will panic if it
|
||||
// cannot get the current working directory.
|
||||
func makePathname() string {
|
||||
p, err := os.Getwd()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sep := string(filepath.Separator)
|
||||
return strings.Replace(p, sep, "_", -1)
|
||||
}
|
||||
|
||||
// GetConfig returns a Tendermint config for the test cases.
|
||||
func GetConfig() *tmcfg.Config {
|
||||
pathname := makePathname()
|
||||
config := tmcfg.ResetTestRoot(pathname)
|
||||
|
||||
tmAddr, _, err := server.FreeTCPAddr()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
rcpAddr, _, err := server.FreeTCPAddr()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
grpcAddr, _, err := server.FreeTCPAddr()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
config.P2P.ListenAddress = tmAddr
|
||||
config.RPC.ListenAddress = rcpAddr
|
||||
config.RPC.GRPCListenAddress = grpcAddr
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
// GetKeyBase returns the LCD test keybase. It also requires that a directory
|
||||
// could be made and a keybase could be fetched.
|
||||
//
|
||||
// NOTE: memDB cannot be used because the request is expecting to interact with
|
||||
// the default location.
|
||||
func GetKeyBase(t *testing.T) crkeys.Keybase {
|
||||
dir, err := ioutil.TempDir("", "lcd_test")
|
||||
require.NoError(t, err)
|
||||
|
||||
viper.Set(cli.HomeFlag, dir)
|
||||
|
||||
keybase, err := keys.GetKeyBase()
|
||||
require.NoError(t, err)
|
||||
|
||||
return keybase
|
||||
}
|
||||
|
||||
// CreateAddr adds an address to the key store and returns an address and seed.
|
||||
// It also requires that the key could be created.
|
||||
func CreateAddr(t *testing.T, name, password string, kb crkeys.Keybase) (sdk.AccAddress, string) {
|
||||
var (
|
||||
err error
|
||||
info crkeys.Info
|
||||
seed string
|
||||
)
|
||||
|
||||
info, seed, err = kb.CreateMnemonic(name, crkeys.English, password, crkeys.Secp256k1)
|
||||
require.NoError(t, err)
|
||||
|
||||
return sdk.AccAddress(info.GetPubKey().Address()), seed
|
||||
}
|
||||
|
||||
// InitializeTestLCD starts Tendermint and the LCD in process, listening on
|
||||
// their respective sockets where nValidators is the total number of validators
|
||||
// and initAddrs are the accounts to initialize with some KVA tokens. It
|
||||
// returns a cleanup function, a set of validator public keys, and a port.
|
||||
func InitializeTestLCD(t *testing.T, nValidators int, initAddrs []sdk.AccAddress) (func(), []crypto.PubKey, string) {
|
||||
config := GetConfig()
|
||||
config.Consensus.TimeoutCommit = 100
|
||||
config.Consensus.SkipTimeoutCommit = false
|
||||
config.TxIndex.IndexAllTags = true
|
||||
|
||||
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
|
||||
logger = log.NewFilter(logger, log.AllowError())
|
||||
|
||||
privValidatorFile := config.PrivValidatorFile()
|
||||
privVal := pvm.LoadOrGenFilePV(privValidatorFile)
|
||||
privVal.Reset()
|
||||
|
||||
db := dbm.NewMemDB()
|
||||
app := kapp.NewKavaApp(logger, db, nil)
|
||||
cdc = kapp.CreateKavaAppCodec()
|
||||
|
||||
genesisFile := config.GenesisFile()
|
||||
genDoc, err := tmtypes.GenesisDocFromFile(genesisFile)
|
||||
require.NoError(t, err)
|
||||
|
||||
if nValidators < 1 {
|
||||
panic("InitializeTestLCD must use at least one validator")
|
||||
}
|
||||
|
||||
for i := 1; i < nValidators; i++ {
|
||||
genDoc.Validators = append(genDoc.Validators,
|
||||
tmtypes.GenesisValidator{
|
||||
PubKey: ed25519.GenPrivKey().PubKey(),
|
||||
Power: 1,
|
||||
Name: "val",
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
var validatorsPKs []crypto.PubKey
|
||||
|
||||
// NOTE: It's bad practice to reuse public key address for the owner
|
||||
// address but doing in the test for simplicity.
|
||||
var appGenTxs []json.RawMessage
|
||||
for _, gdValidator := range genDoc.Validators {
|
||||
pk := gdValidator.PubKey
|
||||
validatorsPKs = append(validatorsPKs, pk)
|
||||
|
||||
appGenTx, _, _, err := kapp.KavaAppGenTxNF(cdc, pk, sdk.AccAddress(pk.Address()), "test_val1")
|
||||
require.NoError(t, err)
|
||||
|
||||
appGenTxs = append(appGenTxs, appGenTx)
|
||||
}
|
||||
|
||||
genesisState, err := kapp.KavaAppGenState(cdc, appGenTxs[:])
|
||||
require.NoError(t, err)
|
||||
|
||||
// add some tokens to init accounts
|
||||
for _, addr := range initAddrs {
|
||||
accAuth := auth.NewBaseAccountWithAddress(addr)
|
||||
accAuth.Coins = sdk.Coins{sdk.NewInt64Coin("KVA", 100)}
|
||||
acc := kapp.NewGenesisAccount(&accAuth)
|
||||
genesisState.Accounts = append(genesisState.Accounts, acc)
|
||||
genesisState.StakeData.Pool.LooseTokens = genesisState.StakeData.Pool.LooseTokens.Add(sdk.NewRat(100))
|
||||
}
|
||||
|
||||
appState, err := wire.MarshalJSONIndent(cdc, genesisState)
|
||||
require.NoError(t, err)
|
||||
genDoc.AppState = appState
|
||||
|
||||
listenAddr, port, err := server.FreeTCPAddr()
|
||||
require.NoError(t, err)
|
||||
|
||||
// XXX: Need to set this so LCD knows the tendermint node address!
|
||||
viper.Set(client.FlagNode, config.RPC.ListenAddress)
|
||||
viper.Set(client.FlagChainID, genDoc.ChainID)
|
||||
|
||||
node, err := startTM(config, logger, genDoc, privVal, app)
|
||||
require.NoError(t, err)
|
||||
|
||||
lcd, err := startLCD(logger, listenAddr, cdc)
|
||||
require.NoError(t, err)
|
||||
|
||||
tests.WaitForLCDStart(port)
|
||||
tests.WaitForHeight(1, port)
|
||||
|
||||
cleanup := func() {
|
||||
logger.Debug("cleaning up LCD initialization")
|
||||
node.Stop()
|
||||
node.Wait()
|
||||
lcd.Close()
|
||||
}
|
||||
|
||||
return cleanup, validatorsPKs, port
|
||||
}
|
||||
|
||||
// startTM creates and starts an in-process Tendermint node with memDB and
|
||||
// in-process ABCI application. It returns the new node or any error that
|
||||
// occurred.
|
||||
//
|
||||
// TODO: Clean up the WAL dir or enable it to be not persistent!
|
||||
func startTM(
|
||||
tmcfg *tmcfg.Config, logger log.Logger, genDoc *tmtypes.GenesisDoc,
|
||||
privVal tmtypes.PrivValidator, app abci.Application,
|
||||
) (*nm.Node, error) {
|
||||
genDocProvider := func() (*tmtypes.GenesisDoc, error) { return genDoc, nil }
|
||||
dbProvider := func(*nm.DBContext) (dbm.DB, error) { return dbm.NewMemDB(), nil }
|
||||
node, err := nm.NewNode(
|
||||
tmcfg,
|
||||
privVal,
|
||||
proxy.NewLocalClientCreator(app),
|
||||
genDocProvider,
|
||||
dbProvider,
|
||||
nm.DefaultMetricsProvider(tmcfg.Instrumentation),
|
||||
logger.With("module", "node"),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = node.Start()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tests.WaitForRPC(tmcfg.RPC.ListenAddress)
|
||||
logger.Info("Tendermint running!")
|
||||
|
||||
return node, err
|
||||
}
|
||||
|
||||
// startLCD starts the LCD.
|
||||
//
|
||||
// NOTE: This causes the thread to block.
|
||||
func startLCD(logger log.Logger, listenAddr string, cdc *wire.Codec) (net.Listener, error) {
|
||||
return tmrpc.StartHTTPServer(listenAddr, createHandler(cdc), logger, tmrpc.Config{})
|
||||
}
|
||||
|
||||
// Request makes a test LCD test request. It returns a response object and a
|
||||
// stringified response body.
|
||||
func Request(t *testing.T, port, method, path string, payload []byte) (*http.Response, string) {
|
||||
var (
|
||||
err error
|
||||
res *http.Response
|
||||
)
|
||||
url := fmt.Sprintf("http://localhost:%v%v", port, path)
|
||||
fmt.Println("REQUEST " + method + " " + url)
|
||||
|
||||
req, err := http.NewRequest(method, url, bytes.NewBuffer(payload))
|
||||
require.Nil(t, err)
|
||||
|
||||
res, err = http.DefaultClient.Do(req)
|
||||
require.Nil(t, err)
|
||||
|
||||
output, err := ioutil.ReadAll(res.Body)
|
||||
res.Body.Close()
|
||||
require.Nil(t, err)
|
||||
|
||||
return res, string(output)
|
||||
}
|
32
internal/lcd/version.go
Normal file
32
internal/lcd/version.go
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2016 All in Bits, inc
|
||||
// Modifications copyright 2018 Kava Labs
|
||||
|
||||
package lcd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/context"
|
||||
"github.com/cosmos/cosmos-sdk/version"
|
||||
)
|
||||
|
||||
// cli version REST handler endpoint
|
||||
func CLIVersionRequestHandler(w http.ResponseWriter, r *http.Request) {
|
||||
v := version.GetVersion()
|
||||
w.Write([]byte(v))
|
||||
}
|
||||
|
||||
// connected node version REST handler endpoint
|
||||
func NodeVersionRequestHandler(cliCtx context.CLIContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
version, err := cliCtx.Query("/app/version")
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(fmt.Sprintf("Could't query version. Error: %s", err.Error())))
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(version)
|
||||
}
|
||||
}
|
@ -1,11 +1,12 @@
|
||||
// Copyright 2016 All in Bits, inc
|
||||
// Modifications copyright 2018 Kava Labs
|
||||
|
||||
package lcd
|
||||
|
||||
/*
|
||||
import (
|
||||
amino "github.com/tendermint/go-amino"
|
||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
)
|
||||
*/
|
||||
|
||||
var cdc = amino.NewCodec()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user