Merge branch 'develop' into greg/testnet-command-2
This commit is contained in:
commit
73b0b489cf
32
CHANGELOG.md
32
CHANGELOG.md
@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## 0.20.0
|
||||
|
||||
*TBD*
|
||||
|
||||
## 0.19.0
|
||||
|
||||
*June 13, 2018*
|
||||
|
||||
BREAKING CHANGES
|
||||
* msg.GetSignBytes() now returns bech32-encoded addresses in all cases
|
||||
* [lcd] REST end-points now include gas
|
||||
@ -14,8 +22,11 @@ IMPROVEMENTS
|
||||
* [lcd] refactored to eliminate use of global variables, and interdependent tests
|
||||
* Added testnet command to gaiad
|
||||
* Added localnet targets to Makefile
|
||||
* [x/stake] More stake tests added to test ByPower index
|
||||
|
||||
FIXES
|
||||
* Fixes consensus fault on testnet - see postmortem [here](https://github.com/cosmos/cosmos-sdk/issues/1197#issuecomment-396823021)
|
||||
* [x/stake] bonded inflation removed, non-bonded inflation partially implemented
|
||||
* [lcd] Switch to bech32 for addresses on all human readable inputs and outputs
|
||||
* [lcd] fixed tx indexing/querying
|
||||
* [cli] Added `--gas` flag to specify transaction gas limit
|
||||
@ -24,7 +35,7 @@ FIXES
|
||||
|
||||
## 0.18.0
|
||||
|
||||
_2018-06-05_
|
||||
*June 9, 2018*
|
||||
|
||||
BREAKING CHANGES
|
||||
|
||||
@ -87,8 +98,27 @@ BUG FIXES
|
||||
* query sequence via account store
|
||||
* fixed duplicate pub_key in stake.Validator
|
||||
* Auto-sequencing now works correctly
|
||||
* [gaiacli] Fix error message when account isn't found when running gaiacli account
|
||||
|
||||
|
||||
## 0.17.5
|
||||
|
||||
*June 5, 2018*
|
||||
|
||||
Update to Tendermint v0.19.9 (Fix evidence reactor, mempool deadlock, WAL panic,
|
||||
memory leak)
|
||||
|
||||
## 0.17.4
|
||||
|
||||
*May 31, 2018*
|
||||
|
||||
Update to Tendermint v0.19.7 (WAL fixes and more)
|
||||
|
||||
## 0.17.3
|
||||
|
||||
*May 29, 2018*
|
||||
|
||||
Update to Tendermint v0.19.6 (fix fast-sync halt)
|
||||
|
||||
## 0.17.5
|
||||
|
||||
|
||||
5
Makefile
5
Makefile
@ -46,6 +46,9 @@ install_examples:
|
||||
go install $(BUILD_FLAGS) ./examples/democoin/cmd/democoind
|
||||
go install $(BUILD_FLAGS) ./examples/democoin/cmd/democli
|
||||
|
||||
install_debug:
|
||||
go install $(BUILD_FLAGS) ./cmd/gaia/cmd/gaiadebug
|
||||
|
||||
dist:
|
||||
@bash publish/dist.sh
|
||||
@bash publish/publish.sh
|
||||
@ -172,4 +175,4 @@ remotenet-status:
|
||||
# To avoid unintended conflicts with file names, always add to .PHONY
|
||||
# unless there is a reason not to.
|
||||
# https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html
|
||||
.PHONY: build build_examples install install_examples dist check_tools get_tools get_vendor_deps draw_deps test test_cli test_unit test_cover test_lint benchmark devdoc_init devdoc devdoc_save devdoc_update build-linux build-docker-gaiadnode localnet-start localnet-stop remotenet-start remotenet-stop remotenet-status
|
||||
.PHONY: build build_examples install install_examples install_debug dist check_tools get_tools get_vendor_deps draw_deps test test_cli test_unit test_cover test_lint benchmark devdoc_init devdoc devdoc_save devdoc_update build-linux build-docker-gaiadnode localnet-start localnet-stop remotenet-start remotenet-stop remotenet-status
|
||||
|
||||
@ -18,6 +18,14 @@ master | [
|
||||
|
||||
## Testnet
|
||||
|
||||
For more information on connecting to the testnet, see
|
||||
[cmd/gaia/testnets](/cmd/gaia/testnets)
|
||||
|
||||
For the latest status of the testnet, see the [status
|
||||
file](/cmd/gaia/testnets/STATUS.md).
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
@ -396,9 +396,10 @@ func TestBonding(t *testing.T) {
|
||||
|
||||
// TODO fix shares fn in staking
|
||||
// query sender
|
||||
//acc = getAccount(t, port, addr)
|
||||
//coins = acc.GetCoins()
|
||||
//assert.Equal(t, int64(70), coins.AmountOf(denom))
|
||||
//acc := getAccount(t, sendAddr)
|
||||
//coins := acc.GetCoins()
|
||||
//assert.Equal(t, int64(98), coins.AmountOf(coinDenom))
|
||||
|
||||
}
|
||||
|
||||
//_____________________________________________________________________________
|
||||
|
||||
243
cmd/gaia/cmd/gaiadebug/hack.go
Normal file
243
cmd/gaia/cmd/gaiadebug/hack.go
Normal file
@ -0,0 +1,243 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
abci "github.com/tendermint/abci/types"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
dbm "github.com/tendermint/tmlibs/db"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
bam "github.com/cosmos/cosmos-sdk/baseapp"
|
||||
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/bank"
|
||||
"github.com/cosmos/cosmos-sdk/x/ibc"
|
||||
"github.com/cosmos/cosmos-sdk/x/slashing"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||
|
||||
gaia "github.com/cosmos/cosmos-sdk/cmd/gaia/app"
|
||||
)
|
||||
|
||||
func runHackCmd(cmd *cobra.Command, args []string) error {
|
||||
|
||||
if len(args) != 1 {
|
||||
return fmt.Errorf("Expected 1 arg")
|
||||
}
|
||||
|
||||
// ".gaiad"
|
||||
dataDir := args[0]
|
||||
dataDir = path.Join(dataDir, "data")
|
||||
|
||||
// load the app
|
||||
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
|
||||
db, err := dbm.NewGoLevelDB("gaia", dataDir)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
app := NewGaiaApp(logger, db)
|
||||
|
||||
// print some info
|
||||
id := app.LastCommitID()
|
||||
lastBlockHeight := app.LastBlockHeight()
|
||||
fmt.Println("ID", id)
|
||||
fmt.Println("LastBlockHeight", lastBlockHeight)
|
||||
|
||||
//----------------------------------------------------
|
||||
// XXX: start hacking!
|
||||
//----------------------------------------------------
|
||||
// eg. gaia-6001 testnet bug
|
||||
// We paniced when iterating through the "bypower" keys.
|
||||
// The following powerKey was there, but the corresponding "trouble" validator did not exist.
|
||||
// So here we do a binary search on the past states to find when the powerKey first showed up ...
|
||||
|
||||
// owner of the validator the bonds, gets revoked, later unbonds, and then later is still found in the bypower store
|
||||
trouble := hexToBytes("D3DC0FF59F7C3B548B7AFA365561B87FD0208AF8")
|
||||
// this is his "bypower" key
|
||||
powerKey := hexToBytes("05303030303030303030303033FFFFFFFFFFFF4C0C0000FFFED3DC0FF59F7C3B548B7AFA365561B87FD0208AF8")
|
||||
|
||||
topHeight := lastBlockHeight
|
||||
bottomHeight := int64(0)
|
||||
checkHeight := topHeight
|
||||
for {
|
||||
// load the given version of the state
|
||||
err = app.LoadVersion(checkHeight, app.keyMain)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
ctx := app.NewContext(true, abci.Header{})
|
||||
|
||||
// check for the powerkey and the validator from the store
|
||||
store := ctx.KVStore(app.keyStake)
|
||||
res := store.Get(powerKey)
|
||||
val, _ := app.stakeKeeper.GetValidator(ctx, trouble)
|
||||
fmt.Println("checking height", checkHeight, res, val)
|
||||
if res == nil {
|
||||
bottomHeight = checkHeight
|
||||
} else {
|
||||
topHeight = checkHeight
|
||||
}
|
||||
checkHeight = (topHeight + bottomHeight) / 2
|
||||
}
|
||||
}
|
||||
|
||||
func base64ToPub(b64 string) crypto.PubKeyEd25519 {
|
||||
data, _ := base64.StdEncoding.DecodeString(b64)
|
||||
var pubKey crypto.PubKeyEd25519
|
||||
copy(pubKey[:], data)
|
||||
return pubKey
|
||||
|
||||
}
|
||||
|
||||
func hexToBytes(h string) []byte {
|
||||
trouble, _ := hex.DecodeString(h)
|
||||
return trouble
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// NOTE: This is all copied from gaia/app/app.go
|
||||
// so we can access internal fields!
|
||||
|
||||
const (
|
||||
appName = "GaiaApp"
|
||||
)
|
||||
|
||||
// default home directories for expected binaries
|
||||
var (
|
||||
DefaultCLIHome = os.ExpandEnv("$HOME/.gaiacli")
|
||||
DefaultNodeHome = os.ExpandEnv("$HOME/.gaiad")
|
||||
)
|
||||
|
||||
// Extended ABCI application
|
||||
type GaiaApp struct {
|
||||
*bam.BaseApp
|
||||
cdc *wire.Codec
|
||||
|
||||
// keys to access the substores
|
||||
keyMain *sdk.KVStoreKey
|
||||
keyAccount *sdk.KVStoreKey
|
||||
keyIBC *sdk.KVStoreKey
|
||||
keyStake *sdk.KVStoreKey
|
||||
keySlashing *sdk.KVStoreKey
|
||||
|
||||
// Manage getting and setting accounts
|
||||
accountMapper auth.AccountMapper
|
||||
feeCollectionKeeper auth.FeeCollectionKeeper
|
||||
coinKeeper bank.Keeper
|
||||
ibcMapper ibc.Mapper
|
||||
stakeKeeper stake.Keeper
|
||||
slashingKeeper slashing.Keeper
|
||||
}
|
||||
|
||||
func NewGaiaApp(logger log.Logger, db dbm.DB) *GaiaApp {
|
||||
cdc := MakeCodec()
|
||||
|
||||
// create your application object
|
||||
var app = &GaiaApp{
|
||||
BaseApp: bam.NewBaseApp(appName, cdc, logger, db),
|
||||
cdc: cdc,
|
||||
keyMain: sdk.NewKVStoreKey("main"),
|
||||
keyAccount: sdk.NewKVStoreKey("acc"),
|
||||
keyIBC: sdk.NewKVStoreKey("ibc"),
|
||||
keyStake: sdk.NewKVStoreKey("stake"),
|
||||
keySlashing: sdk.NewKVStoreKey("slashing"),
|
||||
}
|
||||
|
||||
// define the accountMapper
|
||||
app.accountMapper = auth.NewAccountMapper(
|
||||
app.cdc,
|
||||
app.keyAccount, // target store
|
||||
&auth.BaseAccount{}, // prototype
|
||||
)
|
||||
|
||||
// add handlers
|
||||
app.coinKeeper = bank.NewKeeper(app.accountMapper)
|
||||
app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace))
|
||||
app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.coinKeeper, app.RegisterCodespace(stake.DefaultCodespace))
|
||||
app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, app.stakeKeeper, app.RegisterCodespace(slashing.DefaultCodespace))
|
||||
|
||||
// register message routes
|
||||
app.Router().
|
||||
AddRoute("bank", bank.NewHandler(app.coinKeeper)).
|
||||
AddRoute("ibc", ibc.NewHandler(app.ibcMapper, app.coinKeeper)).
|
||||
AddRoute("stake", stake.NewHandler(app.stakeKeeper))
|
||||
|
||||
// initialize BaseApp
|
||||
app.SetInitChainer(app.initChainer)
|
||||
app.SetBeginBlocker(app.BeginBlocker)
|
||||
app.SetEndBlocker(app.EndBlocker)
|
||||
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeCollectionKeeper))
|
||||
app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake, app.keySlashing)
|
||||
err := app.LoadLatestVersion(app.keyMain)
|
||||
if err != nil {
|
||||
cmn.Exit(err.Error())
|
||||
}
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
// custom tx codec
|
||||
func MakeCodec() *wire.Codec {
|
||||
var cdc = wire.NewCodec()
|
||||
ibc.RegisterWire(cdc)
|
||||
bank.RegisterWire(cdc)
|
||||
stake.RegisterWire(cdc)
|
||||
slashing.RegisterWire(cdc)
|
||||
auth.RegisterWire(cdc)
|
||||
sdk.RegisterWire(cdc)
|
||||
wire.RegisterCrypto(cdc)
|
||||
return cdc
|
||||
}
|
||||
|
||||
// application updates every end block
|
||||
func (app *GaiaApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock {
|
||||
tags := slashing.BeginBlocker(ctx, req, app.slashingKeeper)
|
||||
|
||||
return abci.ResponseBeginBlock{
|
||||
Tags: tags.ToKVPairs(),
|
||||
}
|
||||
}
|
||||
|
||||
// application updates every end block
|
||||
func (app *GaiaApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
|
||||
validatorUpdates := stake.EndBlocker(ctx, app.stakeKeeper)
|
||||
|
||||
return abci.ResponseEndBlock{
|
||||
ValidatorUpdates: validatorUpdates,
|
||||
}
|
||||
}
|
||||
|
||||
// custom logic for gaia initialization
|
||||
func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
|
||||
stateJSON := req.AppStateBytes
|
||||
// TODO is this now the whole genesis file?
|
||||
|
||||
var genesisState gaia.GenesisState
|
||||
err := app.cdc.UnmarshalJSON(stateJSON, &genesisState)
|
||||
if err != nil {
|
||||
panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468
|
||||
// return sdk.ErrGenesisParse("").TraceCause(err, "")
|
||||
}
|
||||
|
||||
// load the accounts
|
||||
for _, gacc := range genesisState.Accounts {
|
||||
acc := gacc.ToAccount()
|
||||
app.accountMapper.SetAccount(ctx, acc)
|
||||
}
|
||||
|
||||
// load the initial stake information
|
||||
stake.InitGenesis(ctx, app.stakeKeeper, genesisState.StakeData)
|
||||
return abci.ResponseInitChain{}
|
||||
|
||||
}
|
||||
159
cmd/gaia/cmd/gaiadebug/main.go
Normal file
159
cmd/gaia/cmd/gaiadebug/main.go
Normal file
@ -0,0 +1,159 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
gaia "github.com/cosmos/cosmos-sdk/cmd/gaia/app"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/spf13/cobra"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(txCmd)
|
||||
rootCmd.AddCommand(pubkeyCmd)
|
||||
rootCmd.AddCommand(hackCmd)
|
||||
rootCmd.AddCommand(rawBytesCmd)
|
||||
}
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "gaiadebug",
|
||||
Short: "Gaia debug tool",
|
||||
SilenceUsage: true,
|
||||
}
|
||||
|
||||
var txCmd = &cobra.Command{
|
||||
Use: "tx",
|
||||
Short: "Decode a gaia tx from hex or base64",
|
||||
RunE: runTxCmd,
|
||||
}
|
||||
|
||||
var pubkeyCmd = &cobra.Command{
|
||||
Use: "pubkey",
|
||||
Short: "Decode a pubkey from hex or base64",
|
||||
RunE: runPubKeyCmd,
|
||||
}
|
||||
|
||||
var hackCmd = &cobra.Command{
|
||||
Use: "hack",
|
||||
Short: "Boilerplate to Hack on an existing state by scripting some Go...",
|
||||
RunE: runHackCmd,
|
||||
}
|
||||
|
||||
var rawBytesCmd = &cobra.Command{
|
||||
Use: "raw-bytes",
|
||||
Short: "Convert raw bytes output (eg. [10 21 13 255]) to hex",
|
||||
RunE: runRawBytesCmd,
|
||||
}
|
||||
|
||||
func runRawBytesCmd(cmd *cobra.Command, args []string) error {
|
||||
if len(args) != 1 {
|
||||
return fmt.Errorf("Expected single arg")
|
||||
}
|
||||
stringBytes := args[0]
|
||||
stringBytes = strings.Trim(stringBytes, "[")
|
||||
stringBytes = strings.Trim(stringBytes, "]")
|
||||
spl := strings.Split(stringBytes, " ")
|
||||
|
||||
byteArray := []byte{}
|
||||
for _, s := range spl {
|
||||
b, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
byteArray = append(byteArray, byte(b))
|
||||
}
|
||||
fmt.Printf("%X\n", byteArray)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runPubKeyCmd(cmd *cobra.Command, args []string) error {
|
||||
if len(args) != 1 {
|
||||
return fmt.Errorf("Expected single arg")
|
||||
}
|
||||
|
||||
pubkeyString := args[0]
|
||||
|
||||
// try hex, then base64
|
||||
pubkeyBytes, err := hex.DecodeString(pubkeyString)
|
||||
if err != nil {
|
||||
var err2 error
|
||||
pubkeyBytes, err2 = base64.StdEncoding.DecodeString(pubkeyString)
|
||||
if err2 != nil {
|
||||
return fmt.Errorf(`Expected hex or base64. Got errors:
|
||||
hex: %v,
|
||||
base64: %v
|
||||
`, err, err2)
|
||||
}
|
||||
}
|
||||
|
||||
cdc := gaia.MakeCodec()
|
||||
var pubKey crypto.PubKeyEd25519
|
||||
copy(pubKey[:], pubkeyBytes)
|
||||
pubKeyJSONBytes, err := cdc.MarshalJSON(pubKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("Address:", pubKey.Address())
|
||||
fmt.Printf("Hex: %X\n", pubkeyBytes)
|
||||
fmt.Println("JSON (base64):", string(pubKeyJSONBytes))
|
||||
return nil
|
||||
}
|
||||
|
||||
func runTxCmd(cmd *cobra.Command, args []string) error {
|
||||
if len(args) != 1 {
|
||||
return fmt.Errorf("Expected single arg")
|
||||
}
|
||||
|
||||
txString := args[0]
|
||||
|
||||
// try hex, then base64
|
||||
txBytes, err := hex.DecodeString(txString)
|
||||
if err != nil {
|
||||
var err2 error
|
||||
txBytes, err2 = base64.StdEncoding.DecodeString(txString)
|
||||
if err2 != nil {
|
||||
return fmt.Errorf(`Expected hex or base64. Got errors:
|
||||
hex: %v,
|
||||
base64: %v
|
||||
`, err, err2)
|
||||
}
|
||||
}
|
||||
|
||||
var tx = auth.StdTx{}
|
||||
cdc := gaia.MakeCodec()
|
||||
|
||||
err = cdc.UnmarshalBinary(txBytes, &tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bz, err := cdc.MarshalJSON(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
err = json.Indent(buf, bz, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println(buf.String())
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := rootCmd.Execute()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
258
cmd/gaia/testnets/README.md
Normal file
258
cmd/gaia/testnets/README.md
Normal file
@ -0,0 +1,258 @@
|
||||
# Connect to the `gaia-6001` Testnet
|
||||
|
||||
Note: We are aware this documentation is sub-par. We are working to
|
||||
improve the tooling and the documentation to make this process as painless as
|
||||
possible. In the meantime, join the
|
||||
[Validator Chat](https://riot.im/app/#/room/#cosmos_validators:matrix.org)
|
||||
for technical support. Thanks very much for your patience. :)
|
||||
|
||||
## Setting Up a New Node
|
||||
|
||||
These instructions are for setting up a brand new full node from scratch. If you ran a full node on a previous testnet, please skip to [Upgrading From Previous Testnet](#upgrading-from-previous-testnet).
|
||||
|
||||
### Install Go
|
||||
|
||||
Install `go` by following the [official docs](https://golang.org/doc/install).
|
||||
**Go 1.10+** is required for the Cosmos SDK.
|
||||
|
||||
### Install Cosmos SDK
|
||||
|
||||
Next, let's install the testnet's version of the Cosmos SDK.
|
||||
|
||||
```
|
||||
mkdir -p $GOPATH/src/github.com/cosmos
|
||||
cd $GOPATH/src/github.com/cosmos
|
||||
git clone https://github.com/cosmos/cosmos-sdk
|
||||
cd cosmos-sdk && git checkout v0.18.0
|
||||
make get_tools && make get_vendor_deps && make install
|
||||
```
|
||||
|
||||
That will install the `gaiad` and `gaiacli` binaries. Verify that everything is OK:
|
||||
|
||||
```
|
||||
gaiad version
|
||||
0.18.0-eceb56b7
|
||||
```
|
||||
|
||||
### Node Setup
|
||||
|
||||
Create the required configuration files:
|
||||
|
||||
```
|
||||
gaiad init
|
||||
```
|
||||
|
||||
Name your node by editing the `moniker` in `$HOME/.gaiad/config/config.toml`. Note that only ASCII characters are supported. Using Unicode renders your node unconnectable.
|
||||
|
||||
```
|
||||
# A custom human readable name for this node
|
||||
moniker = "<your_custom_name>"
|
||||
```
|
||||
|
||||
Your full node has been initialized! Please skip to [Genesis & Seeds](#genesis--seeds).
|
||||
|
||||
## Upgrading From Previous Testnet
|
||||
|
||||
These instructions are for full nodes that have ran on previous testnets and would like to upgrade to the latest testnet.
|
||||
|
||||
### Reset Data
|
||||
|
||||
First, remove the outdated files and reset the data.
|
||||
|
||||
```
|
||||
rm $HOME/.gaiad/config/addrbook.json $HOME/.gaiad/config/genesis.json
|
||||
gaiad unsafe_reset_all
|
||||
```
|
||||
|
||||
Your node is now in a pristine state while keeping the original `priv_validator.json` and `config.toml`. If you had any sentry nodes or full nodes setup before,
|
||||
your node will still try to connect to them, but may fail if they haven't also
|
||||
been upgraded.
|
||||
|
||||
**WARNING:** Make sure that every node has a unique `priv_validator.json`. Do not copy the `priv_validator.json` from an old node to multiple new nodes. Running two nodes with the same `priv_validator.json` will cause you to double sign.
|
||||
|
||||
### Software Upgrade
|
||||
|
||||
Now it is time to upgrade the software:
|
||||
|
||||
```
|
||||
cd $GOPATH/src/github.com/cosmos/cosmos-sdk
|
||||
git fetch --all && git checkout v0.18.0
|
||||
make update_tools && make get_vendor_deps && make install
|
||||
```
|
||||
|
||||
Your full node has been cleanly upgraded!
|
||||
|
||||
## Genesis & Seeds
|
||||
|
||||
### Copy the Genesis File
|
||||
|
||||
Copy the testnet's `genesis.json` file and place it in `gaiad`'s config directory.
|
||||
|
||||
```
|
||||
mkdir -p $HOME/.gaiad/config
|
||||
cp -a $GOPATH/src/github.com/cosmos/cosmos-sdk/cmd/gaia/testnets/gaia-6001/genesis.json $HOME/.gaiad/config/genesis.json
|
||||
```
|
||||
|
||||
### Add Seed Nodes
|
||||
|
||||
Your node needs to know how to find peers. You'll need to add healthy seed nodes to `$HOME/.gaiad/config/config.toml`. Here are some seed nodes you can use:
|
||||
|
||||
```
|
||||
# Comma separated list of seed nodes to connect to
|
||||
seeds = "38aa9bec3998f12ae9088b21a2d910d19d565c27@gaia-6001.coinculture.net:46656,80a35a46ce09cfb31ee220c8141a25e73e0b239b@seed.cosmos.cryptium.ch:46656,80a35a46ce09cfb31ee220c8141a25e73e0b239b@35.198.166.171:46656,032fa56301de335d835057fb6ad9f7ce2242a66d@165.227.236.213:46656"
|
||||
```
|
||||
|
||||
You can also [ask other validators](https://riot.im/app/#/room/#cosmos_validators:matrix.org) for a persistent peer and add it under the `persistent_peers` key. For more information on seeds and peers, [read this](https://github.com/tendermint/tendermint/blob/develop/docs/using-tendermint.md#peers).
|
||||
|
||||
## Run a Full Node
|
||||
|
||||
Start the full node with this command:
|
||||
|
||||
```
|
||||
gaiad start
|
||||
```
|
||||
|
||||
Check that everything is running smoothly:
|
||||
|
||||
```
|
||||
gaiacli status
|
||||
```
|
||||
|
||||
View the status of the network with the [Cosmos Explorer](https://explorecosmos.network). Once your full node syncs up to the current block height, you should see it appear on the [list of full nodes](https://explorecosmos.network/validators). If it doesn't show up, that's ok--the Explorer does not connect to every node.
|
||||
|
||||
## Generate Keys
|
||||
|
||||
You'll need a private and public key pair \(a.k.a. `sk, pk` respectively\) to be able to receive funds, send txs, bond tx, etc.
|
||||
|
||||
To generate a new key \(default _ed25519_ elliptic curve\):
|
||||
|
||||
```
|
||||
gaiacli keys add <your_key_name>
|
||||
```
|
||||
|
||||
Next, you will have to create a passphrase. Save the _seed_ _phrase_ in a safe place in case you forget the password.
|
||||
|
||||
If you check your private keys, you'll now see `<your_key_name>`:
|
||||
|
||||
```
|
||||
gaiacli keys show <your_key_name>
|
||||
```
|
||||
|
||||
You can see all your available keys by typing:
|
||||
|
||||
```
|
||||
gaiacli keys list
|
||||
```
|
||||
|
||||
View the validator pubkey for your node by typing:
|
||||
|
||||
```
|
||||
gaiad tendermint show_validator
|
||||
```
|
||||
|
||||
Save your address and pubkey to environment variables for later use:
|
||||
|
||||
```
|
||||
MYADDR=<your_newly_generated_address>
|
||||
MYPUBKEY=<your_newly_generated_public_key>
|
||||
```
|
||||
|
||||
**WARNING:** We strongly recommend NOT using the same passphrase for multiple keys. The Tendermint team and the Interchain Foundation will not be responsible for the loss of funds.
|
||||
|
||||
## Get Tokens
|
||||
|
||||
The best way to get tokens is from the [Cosmos Testnet Faucet](https://faucetcosmos.network). If the faucet is not working for you, try asking [#cosmos-validators](https://riot.im/app/#/room/#cosmos-validators:matrix.org).
|
||||
|
||||
After receiving tokens to your address, you can view your account's balance by typing:
|
||||
|
||||
```
|
||||
gaiacli account <your_newly_generated_address>
|
||||
```
|
||||
|
||||
Note: When you query an account balance with zero tokens, you will get this error: `No account with address <your_newly_generated_address> was found in the state.` This is expected! We're working on improving our error messages.
|
||||
|
||||
## Send Tokens
|
||||
|
||||
```
|
||||
gaiacli send --amount=10faucetToken --chain-id=<name_of_testnet_chain> --name=<key_name> --to=<destination_address>
|
||||
```
|
||||
|
||||
Note: The `--amount` flag accepts the format `--amount=<value|coin_name>`.
|
||||
|
||||
Now, view the updated balances of the origin and destination accounts:
|
||||
|
||||
```
|
||||
gaiacli account <origin_address>
|
||||
gaiacli account <destination_address>
|
||||
```
|
||||
|
||||
You can also check your balance at a given block by using the `--block` flag:
|
||||
|
||||
```
|
||||
gaiacli account <your_address> --block=<block_height>
|
||||
```
|
||||
|
||||
## Run a Validator Node
|
||||
|
||||
[Validators](https://cosmos.network/validators) are responsible for committing new blocks to the blockchain through voting. A validator's stake is slashed if they become unavailable, double sign a transaction, or don't cast their votes. If you only want to run a full node, a VM in the cloud is fine. However, if you are want to become a validator for the Hub's `mainnet`, you should research hardened setups. Please read [Sentry Node Architecture](https://github.com/cosmos/cosmos/blob/master/VALIDATORS_FAQ.md#how-can-validators-protect-themselves-from-denial-of-service-attacks) to protect your node from DDOS and ensure high-availability. Also see the [technical requirements](https://github.com/cosmos/cosmos/blob/master/VALIDATORS_FAQ.md#technical-requirements)). There's also more info on our [website](https://cosmos.network/validators).
|
||||
|
||||
Your `pubkey` can be used to create a new validator by staking tokens. You can find your validator pubkey by running:
|
||||
|
||||
```
|
||||
gaiad tendermint show_validator
|
||||
```
|
||||
|
||||
Next, craft your `gaiacli stake create-validator` command:
|
||||
|
||||
```
|
||||
gaiacli stake create-validator --amount=5steak --pubkey=<your_node_pubkey> --address-validator=<your_address> --moniker=satoshi --chain-id=<name_of_the_testnet_chain> --name=<key_name>
|
||||
```
|
||||
|
||||
You can add more information to the validator, such as`--website`, `--keybase-sig`, or `--details`. Here's how:
|
||||
|
||||
```
|
||||
gaiacli stake edit-validator --details="To the cosmos !" --website="https://cosmos.network"
|
||||
```
|
||||
|
||||
View the validator's information with this command:
|
||||
|
||||
```
|
||||
gaiacli stake validator --address-validator=<your_address> --chain-id=<name_of_the_testnet_chain>
|
||||
```
|
||||
|
||||
To check that the validator is active, look for it here:
|
||||
|
||||
```
|
||||
gaiacli advanced tendermint validator-set
|
||||
```
|
||||
|
||||
**Note:** To be in the validator set, you need to have more total voting power than the 100th validator.
|
||||
|
||||
## Delegating to a Validator
|
||||
|
||||
On the upcoming mainnet, you can delegate `atom` to a validator. These [delegators](https://cosmos.network/resources/delegators) can receive part of the validator's fee revenue. Read more about the [Cosmos Token Model](https://github.com/cosmos/cosmos/raw/master/Cosmos_Token_Model.pdf).
|
||||
|
||||
### Bond Tokens
|
||||
|
||||
On the testnet, we delegate `steak` instead of `atom`. Here's how you can bond tokens to a testnet validator:
|
||||
|
||||
```
|
||||
gaiacli stake delegate --amount=10steak --address-delegator=<your_address> --address-validator=<bonded_validator_address> --name=<key_name> --chain-id=<name_of_testnet_chain>
|
||||
```
|
||||
|
||||
While tokens are bonded, they are pooled with all the other bonded tokens in the network. Validators and delegators obtain a percentage of shares that equal their stake in this pool.
|
||||
|
||||
### Unbond Tokens
|
||||
|
||||
If for any reason the validator misbehaves, or you want to unbond a certain amount of tokens, use this following command. You can unbond a specific amount of`shares`\(eg:`12.1`\) or all of them \(`MAX`\).
|
||||
|
||||
```
|
||||
gaiacli stake unbond --address-delegator=<your_address> --address-validator=<bonded_validator_address> --shares=MAX --name=<key_name> --chain-id=<name_of_testnet_chain>
|
||||
```
|
||||
|
||||
You can check your balance and your stake delegation to see that the unbonding went through successfully.
|
||||
|
||||
```
|
||||
gaiacli account <your_address>
|
||||
gaiacli stake delegation --address-delegator=<your_address> --address-validator=<bonded_validator_address> --chain-id=<name_of_testnet_chain>
|
||||
```
|
||||
80
cmd/gaia/testnets/STATUS.md
Normal file
80
cmd/gaia/testnets/STATUS.md
Normal file
@ -0,0 +1,80 @@
|
||||
# TESTNET STATUS
|
||||
|
||||
## *June 13, 2018, 2:30 EST* - Published Postmortem of Gaia-6001 failure
|
||||
|
||||
- A bug in the design of the staking data model caused a sanity check to fail
|
||||
- Full writeup
|
||||
[here](https://github.com/cosmos/cosmos-sdk/issues/1197#issuecomment-396823021)
|
||||
|
||||
## *June 10, 2018, 8:30 EST* - Gaia-6001 consensus failure
|
||||
|
||||
- Validator unbonding and revocation activity caused a consensus failure
|
||||
- There is a bug in the staking module that must be fixed
|
||||
- The team is taking its time to look into this and release a fix following a
|
||||
proper protocol for hotfix upgrades to the testnet
|
||||
- Please stay tuned!
|
||||
|
||||
## *June 9, 2018, 14:00 EST* - New Release
|
||||
|
||||
- Released gaia
|
||||
[v0.18.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.18.0) with
|
||||
update for Tendermint
|
||||
[v0.20.0](https://github.com/tendermint/tendermint/releases/tag/v0.20.0)
|
||||
- Includes bug fix for declaring candidacy from the command line
|
||||
|
||||
## *June 8, 2018, 23:30 EST* - Gaia-6001 is making blocks
|
||||
|
||||
- +2/3 of the voting power is finally online for Gaia-6001 and it is making
|
||||
blocks!
|
||||
- This is a momentous achievement - a successful asynchronous decentralized
|
||||
testnet launch
|
||||
- Congrats everyone!
|
||||
|
||||
## *June 8, 2018, 12:00 EST* - New Testnet Gaia-6001
|
||||
|
||||
- After some confusion around testnet deployment and a contention testnet
|
||||
hardfork, a new genesis file and network was released for `gaia-6001`
|
||||
|
||||
## *June 7, 2018, 9:00 EST* - New Testnet Gaia-6000
|
||||
|
||||
- Released a new `genesis.json` file for `gaia-6000`
|
||||
- Initial validators include those that were most active in
|
||||
the gaia-5001 testnet
|
||||
- Join the network via gaia `v0.18.0-rc0`
|
||||
|
||||
## *June 5, 2018, 21:00 EST* - New Release
|
||||
|
||||
- Released gaia
|
||||
[v0.17.5](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.17.5)
|
||||
with update for Tendermint
|
||||
[v0.19.9](https://github.com/tendermint/tendermint/releases/tag/v0.19.9)
|
||||
- Fixes many bugs!
|
||||
- evidence gossipping
|
||||
- mempool deadlock
|
||||
- WAL panic
|
||||
- memory leak
|
||||
- Please update to this to put a stop to the rampant invalid evidence gossiping
|
||||
:)
|
||||
|
||||
## *May 31, 2018, 14:00 EST* - New Release
|
||||
|
||||
- Released gaia
|
||||
[v0.17.4](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.17.4) with update for Tendermint v0.19.7
|
||||
- Fixes a WAL bug and some more
|
||||
- Please update to this if you have trouble restarting a node
|
||||
|
||||
## *May 31, 2018, 2:00 EST* - Testnet Halt
|
||||
|
||||
- A validator equivocated last week and Evidence is being rampantly gossipped
|
||||
- Peers that can't process the evidence (either too far behind or too far ahead) are disconnecting from the peers that
|
||||
sent it, causing high peer turn-over
|
||||
- The high peer turn-over may be causing a memory-leak, resulting in some nodes
|
||||
crashing and the testnet halting
|
||||
- We need to fix some issues in the EvidenceReactor to address this and also
|
||||
investigate the possible memory-leak
|
||||
|
||||
## *May 29, 2018* - New Release
|
||||
|
||||
- Released v0.17.3 with update for Tendermint v0.19.6
|
||||
- Fixes fast-sync bug
|
||||
- Please update to this to sync with the testnet
|
||||
20
cmd/gaia/testnets/gaia-5001/adrian.json
Normal file
20
cmd/gaia/testnets/gaia-5001/adrian.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"node_id": "1ebc5ca705b3ae1c06a0888ff1287ada82149dc3",
|
||||
"ip": "138.68.77.24",
|
||||
"validator": {
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "TZTQnfqOsi89SeoXVnIw+tnFJnr4X8qVC0U8AsEmFk4="
|
||||
},
|
||||
"power": 100,
|
||||
"name": "adrian"
|
||||
},
|
||||
"app_gen_tx": {
|
||||
"name": "default",
|
||||
"address": "D9C12CB5186FE0018179742FD3110EE534C63460",
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "TZTQnfqOsi89SeoXVnIw+tnFJnr4X8qVC0U8AsEmFk4="
|
||||
}
|
||||
}
|
||||
}
|
||||
20
cmd/gaia/testnets/gaia-5001/anton.json
Normal file
20
cmd/gaia/testnets/gaia-5001/anton.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"node_id": "c272ae3cff7558db2c6195eea38fd43fd08406dc",
|
||||
"ip": "206.189.31.178",
|
||||
"validator": {
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "tJlZJWjOpYvRitYFTWNPTaUtvQVf+hoNjlfI84VPqvI="
|
||||
},
|
||||
"power": 100,
|
||||
"name": "anton"
|
||||
},
|
||||
"app_gen_tx": {
|
||||
"name": "default",
|
||||
"address": "E766088FD171906289617F60BF0014C46F0F85EC",
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "tJlZJWjOpYvRitYFTWNPTaUtvQVf+hoNjlfI84VPqvI="
|
||||
}
|
||||
}
|
||||
}
|
||||
20
cmd/gaia/testnets/gaia-5001/aurel.json
Normal file
20
cmd/gaia/testnets/gaia-5001/aurel.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"node_id": "aef085c4bfed0c1ffc6705f2e1e3bf85e5164600",
|
||||
"ip": "45.77.53.208",
|
||||
"validator": {
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "RpX+xkwnCNw5DpBelscz4//TiODyC9RDiyIuD6NEwx0="
|
||||
},
|
||||
"power": 100,
|
||||
"name": "aurel"
|
||||
},
|
||||
"app_gen_tx": {
|
||||
"name": "aurel",
|
||||
"address": "10B0899E05A486AE4E5589C39587DF7E9A185872",
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "RpX+xkwnCNw5DpBelscz4//TiODyC9RDiyIuD6NEwx0="
|
||||
}
|
||||
}
|
||||
}
|
||||
20
cmd/gaia/testnets/gaia-5001/bucky.json
Normal file
20
cmd/gaia/testnets/gaia-5001/bucky.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"node_id": "b0dd378c3fbc4c156cd6d302a799f0d2e4227201",
|
||||
"ip": "159.89.121.174",
|
||||
"validator": {
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "0aNTDL49987ZNRi3FtJIi0jk93ybHuYg1FjWrfP9H2o="
|
||||
},
|
||||
"power": 100,
|
||||
"name": "bucky"
|
||||
},
|
||||
"app_gen_tx": {
|
||||
"name": "bucky",
|
||||
"address": "935E48ED79F1006ED135553768E1D9A768747CF6",
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "0aNTDL49987ZNRi3FtJIi0jk93ybHuYg1FjWrfP9H2o="
|
||||
}
|
||||
}
|
||||
}
|
||||
20
cmd/gaia/testnets/gaia-5001/cwgoes.json
Normal file
20
cmd/gaia/testnets/gaia-5001/cwgoes.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"node_id": "e25603602d8cf8542570ad0e311d50f55f497f85",
|
||||
"ip": "158.69.63.13",
|
||||
"validator": {
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "dcmCn+RZTBdwbCa4YqSnw/Va7xQloBw6vF87ItLwdM0="
|
||||
},
|
||||
"power": 100,
|
||||
"name": "cwgoes"
|
||||
},
|
||||
"app_gen_tx": {
|
||||
"name": "cwgoes",
|
||||
"address": "328FBB8EA315D070DF908982A5F91A3618001D20",
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "dcmCn+RZTBdwbCa4YqSnw/Va7xQloBw6vF87ItLwdM0="
|
||||
}
|
||||
}
|
||||
}
|
||||
20
cmd/gaia/testnets/gaia-5001/iris.json
Normal file
20
cmd/gaia/testnets/gaia-5001/iris.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"node_id": "aabf05a67b2f399807dc602d05bf97b0ed283ac2",
|
||||
"ip": "116.62.62.39",
|
||||
"validator": {
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "7SaH/LyM+qdz9ovD/pvqIf2q7LC7tc5v0ZJxsA2CGTw="
|
||||
},
|
||||
"power": 100,
|
||||
"name": "iris"
|
||||
},
|
||||
"app_gen_tx": {
|
||||
"name": "=suyu",
|
||||
"address": "4B5BE759EB23B0D76C6A60636BD0E3111178794E",
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "7SaH/LyM+qdz9ovD/pvqIf2q7LC7tc5v0ZJxsA2CGTw="
|
||||
}
|
||||
}
|
||||
}
|
||||
20
cmd/gaia/testnets/gaia-5001/lino.json
Normal file
20
cmd/gaia/testnets/gaia-5001/lino.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"node_id": "79466a03e9d4b4648a7dd8cead1fa7121ce76ee3",
|
||||
"ip": "34.235.130.1",
|
||||
"validator": {
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "SW12+WpGKUCO9oT2CV0CD5kUclbXjJHV1MjerLWB7Oc="
|
||||
},
|
||||
"power": 100,
|
||||
"name": "lino"
|
||||
},
|
||||
"app_gen_tx": {
|
||||
"name": "lino",
|
||||
"address": "5A007B81A25AF34B829B79DA508A26E12180BCDB",
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "SW12+WpGKUCO9oT2CV0CD5kUclbXjJHV1MjerLWB7Oc="
|
||||
}
|
||||
}
|
||||
}
|
||||
20
cmd/gaia/testnets/gaia-5001/pbostrom.json
Normal file
20
cmd/gaia/testnets/gaia-5001/pbostrom.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"node_id": "adb290585a2753bf1a520c76802b0dab3dffa895",
|
||||
"ip": "34.201.21.179",
|
||||
"validator": {
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "pY7eLF0Ez3yq495kIjag8mD67Q131np/ssagpEvlV2A="
|
||||
},
|
||||
"power": 100,
|
||||
"name": "pbostrom"
|
||||
},
|
||||
"app_gen_tx": {
|
||||
"name": "default",
|
||||
"address": "109720515B4F8C0858DA3521E448262334534FFD",
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "pY7eLF0Ez3yq495kIjag8mD67Q131np/ssagpEvlV2A="
|
||||
}
|
||||
}
|
||||
}
|
||||
20
cmd/gaia/testnets/gaia-5001/poldsam.json
Normal file
20
cmd/gaia/testnets/gaia-5001/poldsam.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"node_id": "678503e6c8f50db7279c7da3cb9b072aac4bc0d5",
|
||||
"ip": "35.193.188.125",
|
||||
"validator": {
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "RMwWTZsVdkq1heicNJb2fosy9Fls4NHxAHReiJvHl+8="
|
||||
},
|
||||
"power": 100,
|
||||
"name": "polsdam"
|
||||
},
|
||||
"app_gen_tx": {
|
||||
"name": "poldsam",
|
||||
"address": "FA929191B04C5DB222AFC6F15C63EF48CCC864C5",
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "RMwWTZsVdkq1heicNJb2fosy9Fls4NHxAHReiJvHl+8="
|
||||
}
|
||||
}
|
||||
}
|
||||
20
cmd/gaia/testnets/gaia-5001/staked.json
Normal file
20
cmd/gaia/testnets/gaia-5001/staked.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"node_id": "3519f05985394107e0b2e285361b7e012adb1113",
|
||||
"ip": "54.209.118.64",
|
||||
"validator": {
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "vq0V0BjpmIh6WyNnFpMaO5LyUK2FamkNt65eJYa5AaQ="
|
||||
},
|
||||
"power": 100,
|
||||
"name": "staked"
|
||||
},
|
||||
"app_gen_tx": {
|
||||
"name": "default",
|
||||
"address": "935E04662697134905706A4CCDB822AC6FC11C2E",
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "vq0V0BjpmIh6WyNnFpMaO5LyUK2FamkNt65eJYa5AaQ="
|
||||
}
|
||||
}
|
||||
}
|
||||
20
cmd/gaia/testnets/gaia-5001/zach.json
Normal file
20
cmd/gaia/testnets/gaia-5001/zach.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"node_id": "8a2802fb25d352f3e7e277559a4f683780c3ef22",
|
||||
"ip": "167.99.191.184",
|
||||
"validator": {
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "NjjEQKUsq8F0gWxl3BoU2Li5n7hEz9H/LX80rfMxVyE="
|
||||
},
|
||||
"power": 100,
|
||||
"name": ""
|
||||
},
|
||||
"app_gen_tx": {
|
||||
"name": "zach",
|
||||
"address": "9D5723057702E2090405AB5D3B48C45B9ABF4377",
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "NjjEQKUsq8F0gWxl3BoU2Li5n7hEz9H/LX80rfMxVyE="
|
||||
}
|
||||
}
|
||||
}
|
||||
20
cmd/gaia/testnets/gaia-5001/zaki.json
Normal file
20
cmd/gaia/testnets/gaia-5001/zaki.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"node_id": "30b45459e4881680c0ef1750fde136fefa6c3b98",
|
||||
"ip": "35.184.182.143",
|
||||
"validator": {
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "CDF/8aD8Lt+ikR3LyCg9c7DwWBA51NH+MUkH7tzxrfY="
|
||||
},
|
||||
"power": 100,
|
||||
"name": "zaki"
|
||||
},
|
||||
"app_gen_tx": {
|
||||
"name": "zaki",
|
||||
"address": "ECE57661F0CDCF28EED257B72F86240E57F4A612",
|
||||
"pub_key": {
|
||||
"type": "AC26791624DE60",
|
||||
"value": "CDF/8aD8Lt+ikR3LyCg9c7DwWBA51NH+MUkH7tzxrfY="
|
||||
}
|
||||
}
|
||||
}
|
||||
1459
cmd/gaia/testnets/gaia-6000/genesis.json
Normal file
1459
cmd/gaia/testnets/gaia-6000/genesis.json
Normal file
File diff suppressed because it is too large
Load Diff
1459
cmd/gaia/testnets/gaia-6001/genesis.json
Normal file
1459
cmd/gaia/testnets/gaia-6001/genesis.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,15 +1,11 @@
|
||||
//nolint
|
||||
package version
|
||||
|
||||
// when updating these,
|
||||
// remember to also update examples/basecoin/tests/cli/rpc.sh
|
||||
// TODO improve
|
||||
|
||||
const Maj = "0"
|
||||
const Min = "18"
|
||||
const Min = "20"
|
||||
const Fix = "0"
|
||||
|
||||
const Version = "0.18.0-dev"
|
||||
const Version = "0.20.0-dev"
|
||||
|
||||
// GitCommit set by build flags
|
||||
var GitCommit = ""
|
||||
|
||||
@ -33,6 +33,78 @@ func newTestMsgDelegate(delegatorAddr, validatorAddr sdk.Address, amt int64) Msg
|
||||
|
||||
//______________________________________________________________________
|
||||
|
||||
func TestValidatorByPowerIndex(t *testing.T) {
|
||||
validatorAddr, validatorAddr3 := addrs[0], addrs[1]
|
||||
|
||||
initBond := int64(1000000)
|
||||
initBondStr := "1000"
|
||||
ctx, _, keeper := createTestInput(t, false, initBond)
|
||||
|
||||
// create validator
|
||||
msgCreateValidator := newTestMsgCreateValidator(validatorAddr, pks[0], initBond)
|
||||
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
assert.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got)
|
||||
|
||||
// verify the self-delegation exists
|
||||
bond, found := keeper.GetDelegation(ctx, validatorAddr, validatorAddr)
|
||||
require.True(t, found)
|
||||
gotBond := bond.Shares.Evaluate()
|
||||
require.Equal(t, initBond, gotBond,
|
||||
"initBond: %v\ngotBond: %v\nbond: %v\n",
|
||||
initBond, gotBond, bond)
|
||||
|
||||
// verify that the by power index exists
|
||||
validator, found := keeper.GetValidator(ctx, validatorAddr)
|
||||
require.True(t, found)
|
||||
pool := keeper.GetPool(ctx)
|
||||
power := GetValidatorsByPowerKey(validator, pool)
|
||||
require.True(t, keeper.validatorByPowerIndexExists(ctx, power))
|
||||
|
||||
// create a second validator keep it bonded
|
||||
msgCreateValidator = newTestMsgCreateValidator(validatorAddr3, pks[2], int64(1000000))
|
||||
got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
assert.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got)
|
||||
|
||||
// slash and revoke the first validator
|
||||
keeper.Slash(ctx, pks[0], 0, sdk.NewRat(1, 2))
|
||||
keeper.Revoke(ctx, pks[0])
|
||||
validator, found = keeper.GetValidator(ctx, validatorAddr)
|
||||
require.True(t, found)
|
||||
require.Equal(t, sdk.Unbonded, validator.PoolShares.Status) // ensure is unbonded
|
||||
require.Equal(t, int64(500000), validator.PoolShares.Amount.Evaluate()) // ensure is unbonded
|
||||
|
||||
// the old power record should have been deleted as the power changed
|
||||
assert.False(t, keeper.validatorByPowerIndexExists(ctx, power))
|
||||
|
||||
// but the new power record should have been created
|
||||
validator, found = keeper.GetValidator(ctx, validatorAddr)
|
||||
require.True(t, found)
|
||||
pool = keeper.GetPool(ctx)
|
||||
power2 := GetValidatorsByPowerKey(validator, pool)
|
||||
require.True(t, keeper.validatorByPowerIndexExists(ctx, power2))
|
||||
|
||||
// inflate a bunch
|
||||
for i := 0; i < 20000; i++ {
|
||||
pool = keeper.processProvisions(ctx)
|
||||
keeper.setPool(ctx, pool)
|
||||
}
|
||||
|
||||
// now the new record power index should be the same as the original record
|
||||
power3 := GetValidatorsByPowerKey(validator, pool)
|
||||
assert.Equal(t, power2, power3)
|
||||
|
||||
// unbond self-delegation
|
||||
msgUnbond := NewMsgUnbond(validatorAddr, validatorAddr, "MAX")
|
||||
got = handleMsgUnbond(ctx, msgUnbond, keeper)
|
||||
assert.True(t, got.IsOK(),
|
||||
"got: %v\nmsgUnbond: %v\ninitBondStr: %v\n", got, msgUnbond, initBondStr)
|
||||
|
||||
// verify that by power key nolonger exists
|
||||
_, found = keeper.GetValidator(ctx, validatorAddr)
|
||||
require.False(t, found)
|
||||
assert.False(t, keeper.validatorByPowerIndexExists(ctx, power3))
|
||||
}
|
||||
|
||||
func TestDuplicatesMsgCreateValidator(t *testing.T) {
|
||||
ctx, _, keeper := createTestInput(t, false, 1000)
|
||||
|
||||
@ -42,6 +114,7 @@ func TestDuplicatesMsgCreateValidator(t *testing.T) {
|
||||
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||
assert.True(t, got.IsOK(), "%v", got)
|
||||
validator, found := keeper.GetValidator(ctx, validatorAddr)
|
||||
|
||||
require.True(t, found)
|
||||
assert.Equal(t, sdk.Bonded, validator.Status())
|
||||
assert.Equal(t, validatorAddr, validator.Owner)
|
||||
|
||||
@ -22,7 +22,9 @@ func (k Keeper) processProvisions(ctx sdk.Context) Pool {
|
||||
// which needs to be updated is the `BondedPool`. So for each previsions cycle:
|
||||
|
||||
provisions := pool.Inflation.Mul(sdk.NewRat(pool.TokenSupply())).Quo(hrsPerYrRat).Evaluate()
|
||||
pool.BondedTokens += provisions
|
||||
|
||||
// TODO add to the fees provisions
|
||||
pool.LooseUnbondedTokens += provisions
|
||||
return pool
|
||||
}
|
||||
|
||||
|
||||
@ -74,8 +74,6 @@ func TestProcessProvisions(t *testing.T) {
|
||||
initialBondedTokens int64 = 250000000
|
||||
initialUnbondedTokens int64 = 300000000
|
||||
cumulativeExpProvs int64
|
||||
initialBondedShares = sdk.NewRat(250000000, 1)
|
||||
initialUnbondedShares = sdk.NewRat(300000000, 1)
|
||||
validatorTokens = []int64{150000000, 100000000, 100000000, 100000000, 100000000}
|
||||
bondedValidators uint16 = 2
|
||||
)
|
||||
@ -93,9 +91,7 @@ func TestProcessProvisions(t *testing.T) {
|
||||
|
||||
//get the pool and do the final value checks from checkFinalPoolValues
|
||||
pool = keeper.GetPool(ctx)
|
||||
checkFinalPoolValues(t, pool, initialTotalTokens,
|
||||
initialUnbondedTokens, cumulativeExpProvs,
|
||||
0, 0, initialBondedShares, initialUnbondedShares)
|
||||
checkFinalPoolValues(t, pool, initialTotalTokens, cumulativeExpProvs)
|
||||
}
|
||||
|
||||
// Tests that the hourly rate of change of inflation will be positive, negative, or zero, depending on bonded ratio and inflation rate
|
||||
@ -109,8 +105,6 @@ func TestHourlyInflationRateOfChange(t *testing.T) {
|
||||
initialBondedTokens int64 = 150000000
|
||||
initialUnbondedTokens int64 = 400000000
|
||||
cumulativeExpProvs int64
|
||||
bondedShares = sdk.NewRat(150000000, 1)
|
||||
unbondedShares = sdk.NewRat(400000000, 1)
|
||||
validatorTokens = []int64{150000000, 100000000, 100000000, 100000000, 100000000}
|
||||
bondedValidators uint16 = 1
|
||||
)
|
||||
@ -131,9 +125,7 @@ func TestHourlyInflationRateOfChange(t *testing.T) {
|
||||
|
||||
// Final check that the pool equals initial values + cumulative provisions and adjustments we recorded
|
||||
pool = keeper.GetPool(ctx)
|
||||
checkFinalPoolValues(t, pool, initialTotalTokens,
|
||||
initialUnbondedTokens, cumulativeExpProvs,
|
||||
0, 0, bondedShares, unbondedShares)
|
||||
checkFinalPoolValues(t, pool, initialTotalTokens, cumulativeExpProvs)
|
||||
}
|
||||
|
||||
//Test that a large unbonding will significantly lower the bonded ratio
|
||||
@ -181,9 +173,7 @@ func TestLargeUnbond(t *testing.T) {
|
||||
|
||||
// Final check that the pool equals initial values + provisions and adjustments we recorded
|
||||
pool = keeper.GetPool(ctx)
|
||||
checkFinalPoolValues(t, pool, initialTotalTokens,
|
||||
initialUnbondedTokens, expProvisionsAfter,
|
||||
-val0UnbondedTokens, val0UnbondedTokens, bondedShares, unbondedShares)
|
||||
checkFinalPoolValues(t, pool, initialTotalTokens, expProvisionsAfter)
|
||||
}
|
||||
|
||||
//Test that a large bonding will significantly increase the bonded ratio
|
||||
@ -192,12 +182,9 @@ func TestLargeBond(t *testing.T) {
|
||||
pool := keeper.GetPool(ctx)
|
||||
|
||||
var (
|
||||
initialTotalTokens int64 = 1600000000
|
||||
initialBondedTokens int64 = 400000000
|
||||
initialUnbondedTokens int64 = 1200000000
|
||||
val9UnbondedTokens int64 = 400000000
|
||||
val9BondedTokens int64
|
||||
bondedShares = sdk.NewRat(400000000, 1)
|
||||
initialTotalTokens int64 = 1600000000
|
||||
initialBondedTokens int64 = 400000000
|
||||
initialUnbondedTokens int64 = 1200000000
|
||||
unbondedShares = sdk.NewRat(1200000000, 1)
|
||||
unbondedSharesVal9 = sdk.NewRat(400000000, 1)
|
||||
validatorTokens = []int64{400000000, 100000000, 100000000, 100000000, 100000000, 100000000, 100000000, 100000000, 100000000, 400000000}
|
||||
@ -225,10 +212,6 @@ func TestLargeBond(t *testing.T) {
|
||||
// process provisions after the bonding, to compare the difference in expProvisions and expInflation
|
||||
_, expProvisionsAfter, pool := updateProvisions(t, keeper, pool, ctx, 0)
|
||||
unbondedShares = unbondedShares.Sub(unbondedSharesVal9)
|
||||
val9BondedTokens = val9UnbondedTokens
|
||||
val9UnbondedTokens = 0
|
||||
bondedTokens := initialBondedTokens + val9BondedTokens + expProvisionsAfter
|
||||
bondedShares = sdk.NewRat(bondedTokens, 1).Quo(pool.bondedShareExRate())
|
||||
|
||||
// unbonded shares should decrease
|
||||
assert.True(t, unbondedShares.LT(sdk.NewRat(1200000000, 1)))
|
||||
@ -237,9 +220,7 @@ func TestLargeBond(t *testing.T) {
|
||||
// Final check that the pool equals initial values + provisions and adjustments we recorded
|
||||
pool = keeper.GetPool(ctx)
|
||||
|
||||
checkFinalPoolValues(t, pool, initialTotalTokens,
|
||||
initialUnbondedTokens, expProvisionsAfter,
|
||||
val9BondedTokens, -val9BondedTokens, bondedShares, unbondedShares)
|
||||
checkFinalPoolValues(t, pool, initialTotalTokens, expProvisionsAfter)
|
||||
}
|
||||
|
||||
// Tests that inflation increases or decreases as expected when we do a random operation on 20 different validators
|
||||
@ -296,30 +277,13 @@ func TestInflationWithRandomOperations(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
//_________________________________________________________________________________________
|
||||
////////////////////////////////HELPER FUNCTIONS BELOW/////////////////////////////////////
|
||||
|
||||
// Final check on the global pool values for what the total tokens accumulated from each hour of provisions and other functions
|
||||
// bondedAdjustment and unbondedAdjustment are the accumulated changes for the operations of the test
|
||||
// (i.e. if three unbond operations happened, their total value would be passed as unbondedAdjustment)
|
||||
func checkFinalPoolValues(t *testing.T, pool Pool, initialTotalTokens, initialUnbondedTokens,
|
||||
cumulativeExpProvs, bondedAdjustment, unbondedAdjustment int64, bondedShares, unbondedShares sdk.Rat) {
|
||||
|
||||
initialBonded := initialTotalTokens - initialUnbondedTokens
|
||||
// Final check on the global pool values for what the total tokens accumulated from each hour of provisions
|
||||
func checkFinalPoolValues(t *testing.T, pool Pool, initialTotalTokens, cumulativeExpProvs int64) {
|
||||
calculatedTotalTokens := initialTotalTokens + cumulativeExpProvs
|
||||
calculatedBondedTokens := initialBonded + cumulativeExpProvs + bondedAdjustment
|
||||
calculatedUnbondedTokens := initialUnbondedTokens + unbondedAdjustment
|
||||
|
||||
// test that the bonded ratio the pool has is equal to what we calculated for tokens
|
||||
assert.True(t, pool.bondedRatio().Equal(sdk.NewRat(calculatedBondedTokens, calculatedTotalTokens)), "%v", pool.bondedRatio())
|
||||
|
||||
// test global supply
|
||||
assert.Equal(t, calculatedTotalTokens, pool.TokenSupply())
|
||||
assert.Equal(t, calculatedBondedTokens, pool.BondedTokens)
|
||||
assert.Equal(t, calculatedUnbondedTokens, pool.UnbondedTokens)
|
||||
|
||||
// test the value of validator shares
|
||||
assert.True(t, pool.bondedShareExRate().Mul(bondedShares).Equal(sdk.NewRat(calculatedBondedTokens)), "%v", pool.bondedShareExRate())
|
||||
assert.True(t, pool.unbondedShareExRate().Mul(unbondedShares).Equal(sdk.NewRat(calculatedUnbondedTokens)), "%v", pool.unbondedShareExRate())
|
||||
}
|
||||
|
||||
// Processes provisions are added to the pool correctly every hour
|
||||
@ -327,13 +291,11 @@ func checkFinalPoolValues(t *testing.T, pool Pool, initialTotalTokens, initialUn
|
||||
func updateProvisions(t *testing.T, keeper Keeper, pool Pool, ctx sdk.Context, hr int) (sdk.Rat, int64, Pool) {
|
||||
expInflation := keeper.nextInflation(ctx)
|
||||
expProvisions := (expInflation.Mul(sdk.NewRat(pool.TokenSupply())).Quo(hrsPerYrRat)).Evaluate()
|
||||
startBondedPool := pool.BondedTokens
|
||||
startTotalSupply := pool.TokenSupply()
|
||||
pool = keeper.processProvisions(ctx)
|
||||
keeper.setPool(ctx, pool)
|
||||
|
||||
//check provisions were added to pool
|
||||
require.Equal(t, startBondedPool+expProvisions, pool.BondedTokens, "hr %v", hr)
|
||||
require.Equal(t, startTotalSupply+expProvisions, pool.TokenSupply())
|
||||
|
||||
return expInflation, expProvisions, pool
|
||||
@ -405,5 +367,4 @@ func checkInflation(t *testing.T, pool Pool, previousInflation, updatedInflation
|
||||
assert.Equal(t, true, inflationChange.LT(sdk.ZeroRat()), msg)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -78,6 +78,12 @@ func (k Keeper) setValidatorByPowerIndex(ctx sdk.Context, validator Validator, p
|
||||
store.Set(GetValidatorsByPowerKey(validator, pool), validator.Owner)
|
||||
}
|
||||
|
||||
// used in testing
|
||||
func (k Keeper) validatorByPowerIndexExists(ctx sdk.Context, power []byte) bool {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
return store.Get(power) != nil
|
||||
}
|
||||
|
||||
// Get the set of all validators with no limits, used during genesis dump
|
||||
func (k Keeper) getAllValidators(ctx sdk.Context) (validators Validators) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
|
||||
@ -24,6 +24,47 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func TestUpdateValidatorByPowerIndex(t *testing.T) {
|
||||
ctx, _, keeper := createTestInput(t, false, 0)
|
||||
pool := keeper.GetPool(ctx)
|
||||
|
||||
// create a random pool
|
||||
pool.BondedTokens = 1234
|
||||
pool.BondedShares = sdk.NewRat(124)
|
||||
pool.UnbondingTokens = 13934
|
||||
pool.UnbondingShares = sdk.NewRat(145)
|
||||
pool.UnbondedTokens = 154
|
||||
pool.UnbondedShares = sdk.NewRat(1333)
|
||||
keeper.setPool(ctx, pool)
|
||||
|
||||
// add a validator
|
||||
validator := NewValidator(addrVals[0], pks[0], Description{})
|
||||
validator, pool, delSharesCreated := validator.addTokensFromDel(pool, 100)
|
||||
require.Equal(t, sdk.Unbonded, validator.Status())
|
||||
assert.Equal(t, int64(100), validator.PoolShares.Tokens(pool).Evaluate())
|
||||
keeper.setPool(ctx, pool)
|
||||
keeper.updateValidator(ctx, validator)
|
||||
validator, found := keeper.GetValidator(ctx, addrVals[0])
|
||||
require.True(t, found)
|
||||
assert.Equal(t, int64(100), validator.PoolShares.Tokens(pool).Evaluate(), "\nvalidator %v\npool %v", validator, pool)
|
||||
|
||||
pool = keeper.GetPool(ctx)
|
||||
power := GetValidatorsByPowerKey(validator, pool)
|
||||
assert.True(t, keeper.validatorByPowerIndexExists(ctx, power))
|
||||
|
||||
// burn half the delegator shares
|
||||
validator, pool, burned := validator.removeDelShares(pool, delSharesCreated.Quo(sdk.NewRat(2)))
|
||||
assert.Equal(t, int64(50), burned)
|
||||
keeper.setPool(ctx, pool) // update the pool
|
||||
keeper.updateValidator(ctx, validator) // update the validator, possibly kicking it out
|
||||
assert.False(t, keeper.validatorByPowerIndexExists(ctx, power))
|
||||
|
||||
pool = keeper.GetPool(ctx)
|
||||
validator, found = keeper.GetValidator(ctx, addrVals[0])
|
||||
power = GetValidatorsByPowerKey(validator, pool)
|
||||
assert.True(t, keeper.validatorByPowerIndexExists(ctx, power))
|
||||
}
|
||||
|
||||
func TestSetValidator(t *testing.T) {
|
||||
ctx, _, keeper := createTestInput(t, false, 0)
|
||||
pool := keeper.GetPool(ctx)
|
||||
|
||||
@ -118,13 +118,14 @@ func (s PoolShares) ToBonded(p Pool) PoolShares {
|
||||
|
||||
//_________________________________________________________________________________________________________
|
||||
|
||||
// TODO better tests
|
||||
// get the equivalent amount of tokens contained by the shares
|
||||
func (s PoolShares) Tokens(p Pool) sdk.Rat {
|
||||
switch s.Status {
|
||||
case sdk.Bonded:
|
||||
return p.unbondedShareExRate().Mul(s.Amount) // (tokens/shares) * shares
|
||||
return p.bondedShareExRate().Mul(s.Amount) // (tokens/shares) * shares
|
||||
case sdk.Unbonding:
|
||||
return p.unbondedShareExRate().Mul(s.Amount)
|
||||
return p.unbondingShareExRate().Mul(s.Amount)
|
||||
case sdk.Unbonded:
|
||||
return p.unbondedShareExRate().Mul(s.Amount)
|
||||
default:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user