Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initialization of POS chain #1373

Merged
merged 4 commits into from
Jul 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ BREAKING CHANGES

FEATURES
* [lcd] Can now query governance proposals by ProposalStatus
* [baseapp] Initialize validator set on ResponseInitChain
* Added support for cosmos-sdk-cli tool under cosmos-sdk/cmd
* This allows SDK users to init a new project repository with a single command.

Expand Down
2 changes: 1 addition & 1 deletion baseapp/baseapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitC
if app.initChainer == nil {
return
}
app.initChainer(app.deliverState.ctx, req) // no error
res = app.initChainer(app.deliverState.ctx, req)

// NOTE: we don't commit, but BeginBlock for block 1
// starts from this deliverState
Expand Down
21 changes: 8 additions & 13 deletions client/lcd/lcd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,25 +358,20 @@ func TestTxs(t *testing.T) {
}

func TestValidatorsQuery(t *testing.T) {
cleanup, pks, port := InitializeTestLCD(t, 2, []sdk.AccAddress{})
cleanup, pks, port := InitializeTestLCD(t, 1, []sdk.AccAddress{})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can't we initialize with 2 validators?

defer cleanup()
require.Equal(t, 2, len(pks))
require.Equal(t, 1, len(pks))

validators := getValidators(t, port)
require.Equal(t, len(validators), 2)
require.Equal(t, len(validators), 1)

// make sure all the validators were found (order unknown because sorted by owner addr)
foundVal1, foundVal2 := false, false
pk1Bech := sdk.MustBech32ifyValPub(pks[0])
pk2Bech := sdk.MustBech32ifyValPub(pks[1])
if validators[0].PubKey == pk1Bech || validators[1].PubKey == pk1Bech {
foundVal1 = true
foundVal := false
pkBech := sdk.MustBech32ifyValPub(pks[0])
if validators[0].PubKey == pkBech {
foundVal = true
}
if validators[0].PubKey == pk2Bech || validators[1].PubKey == pk2Bech {
foundVal2 = true
}
require.True(t, foundVal1, "pk1Bech %v, owner1 %v, owner2 %v", pk1Bech, validators[0].Owner, validators[1].Owner)
require.True(t, foundVal2, "pk2Bech %v, owner1 %v, owner2 %v", pk2Bech, validators[0].Owner, validators[1].Owner)
require.True(t, foundVal, "pkBech %v, owner %v", pkBech, validators[0].Owner)
}

func TestBonding(t *testing.T) {
Expand Down
6 changes: 4 additions & 2 deletions cmd/gaia/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,15 +173,17 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
}

// load the initial stake information
err = stake.InitGenesis(ctx, app.stakeKeeper, genesisState.StakeData)
validators, err := stake.InitGenesis(ctx, app.stakeKeeper, genesisState.StakeData)
if err != nil {
panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468
// return sdk.ErrGenesisParse("").TraceCause(err, "")
}

gov.InitGenesis(ctx, app.govKeeper, gov.DefaultGenesisState())

return abci.ResponseInitChain{}
return abci.ResponseInitChain{
Validators: validators,
}
}

// export the state of gaia for a genesis file
Expand Down
6 changes: 4 additions & 2 deletions cmd/gaia/cmd/gaiadebug/hack.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,10 +249,12 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci
}

// load the initial stake information
err = stake.InitGenesis(ctx, app.stakeKeeper, genesisState.StakeData)
validators, err := stake.InitGenesis(ctx, app.stakeKeeper, genesisState.StakeData)
if err != nil {
panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468 // return sdk.ErrGenesisParse("").TraceCause(err, "")
}

return abci.ResponseInitChain{}
return abci.ResponseInitChain{
Validators: validators,
}
}
17 changes: 7 additions & 10 deletions server/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,9 @@ var (

// genesis piece structure for creating combined genesis
type GenesisTx struct {
NodeID string `json:"node_id"`
IP string `json:"ip"`
Validator tmtypes.GenesisValidator `json:"validator"`
AppGenTx json.RawMessage `json:"app_gen_tx"`
NodeID string `json:"node_id"`
IP string `json:"ip"`
AppGenTx json.RawMessage `json:"app_gen_tx"`
}

// Storage for init command input parameters
Expand Down Expand Up @@ -121,16 +120,15 @@ func gentxWithConfig(cdc *wire.Codec, appInit AppInit, config *cfg.Config, genTx
nodeID := string(nodeKey.ID())
pubKey := readOrCreatePrivValidator(config)

appGenTx, cliPrint, validator, err := appInit.AppGenTx(cdc, pubKey, genTxConfig)
appGenTx, cliPrint, _, err := appInit.AppGenTx(cdc, pubKey, genTxConfig)
if err != nil {
return
}

tx := GenesisTx{
NodeID: nodeID,
IP: genTxConfig.IP,
Validator: validator,
AppGenTx: appGenTx,
NodeID: nodeID,
IP: genTxConfig.IP,
AppGenTx: appGenTx,
}
bz, err := wire.MarshalJSONIndent(cdc, tx)
if err != nil {
Expand Down Expand Up @@ -312,7 +310,6 @@ func processGenTxs(genTxsDir string, cdc *wire.Codec) (
genTx := genTxs[nodeID]

// combine some stuff
validators = append(validators, genTx.Validator)
appGenTxs = append(appGenTxs, genTx.AppGenTx)

// Add a persistent peer
Expand Down
6 changes: 4 additions & 2 deletions x/gov/test_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,14 @@ func getInitChainer(mapp *mock.App, keeper Keeper, stakeKeeper stake.Keeper) sdk
stakeGenesis := stake.DefaultGenesisState()
stakeGenesis.Pool.LooseTokens = sdk.NewRat(100000)

err := stake.InitGenesis(ctx, stakeKeeper, stakeGenesis)
validators, err := stake.InitGenesis(ctx, stakeKeeper, stakeGenesis)
if err != nil {
panic(err)
}
InitGenesis(ctx, keeper, DefaultGenesisState())
return abci.ResponseInitChain{}
return abci.ResponseInitChain{
Validators: validators,
}
}
}

Expand Down
7 changes: 5 additions & 2 deletions x/slashing/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,14 @@ func getInitChainer(mapp *mock.App, keeper stake.Keeper) sdk.InitChainer {
mapp.InitChainer(ctx, req)
stakeGenesis := stake.DefaultGenesisState()
stakeGenesis.Pool.LooseTokens = sdk.NewRat(100000)
err := stake.InitGenesis(ctx, keeper, stakeGenesis)
validators, err := stake.InitGenesis(ctx, keeper, stakeGenesis)
if err != nil {
panic(err)
}
return abci.ResponseInitChain{}

return abci.ResponseInitChain{
Validators: validators,
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion x/slashing/test_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, para

genesis.Pool.LooseTokens = sdk.NewRat(initCoins.MulRaw(int64(len(addrs))).Int64())

err = stake.InitGenesis(ctx, sk, genesis)
_, err = stake.InitGenesis(ctx, sk, genesis)
require.Nil(t, err)

for _, addr := range addrs {
Expand Down
6 changes: 4 additions & 2 deletions x/stake/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,14 @@ func getInitChainer(mapp *mock.App, keeper Keeper) sdk.InitChainer {
stakeGenesis := DefaultGenesisState()
stakeGenesis.Pool.LooseTokens = sdk.NewRat(100000)

err := InitGenesis(ctx, keeper, stakeGenesis)
validators, err := InitGenesis(ctx, keeper, stakeGenesis)
if err != nil {
panic(err)
}

return abci.ResponseInitChain{}
return abci.ResponseInitChain{
Validators: validators,
}
}
}

Expand Down
19 changes: 14 additions & 5 deletions x/stake/genesis.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package stake

import (
abci "github.com/tendermint/tendermint/abci/types"
tmtypes "github.com/tendermint/tendermint/types"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/stake/types"
"github.com/pkg/errors"
tmtypes "github.com/tendermint/tendermint/types"
)

// InitGenesis sets the pool and parameters for the provided keeper and
// initializes the IntraTxCounter. For each validator in data, it sets that
// validator in the keeper along with manually setting the indexes. In
// addition, it also sets any delegations found in data. Finally, it updates
// the bonded validators.
func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) error {
// Returns final validator set after applying all declaration and delegations
func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) (res []abci.Validator, err error) {
keeper.SetPool(ctx, data.Pool)
keeper.SetNewParams(ctx, data.Params)
keeper.InitIntraTxCounter(ctx)
Expand All @@ -21,10 +24,10 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) error
keeper.SetValidator(ctx, validator)

if validator.Tokens.IsZero() {
return errors.Errorf("genesis validator cannot have zero pool shares, validator: %v", validator)
return res, errors.Errorf("genesis validator cannot have zero pool shares, validator: %v", validator)
}
if validator.DelegatorShares.IsZero() {
return errors.Errorf("genesis validator cannot have zero delegator shares, validator: %v", validator)
return res, errors.Errorf("genesis validator cannot have zero delegator shares, validator: %v", validator)
}

// Manually set indexes for the first time
Expand All @@ -43,7 +46,13 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) error
}

keeper.UpdateBondedValidatorsFull(ctx)
return nil

vals := keeper.GetValidatorsBonded(ctx)
res = make([]abci.Validator, len(vals))
for i, val := range vals {
res[i] = sdk.ABCIValidator(val)
}
return
}

// WriteGenesis returns a GenesisState for a given context and keeper. The
Expand Down
57 changes: 54 additions & 3 deletions x/stake/genesis_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package stake

import (
"fmt"
"testing"

"github.com/stretchr/testify/require"

abci "github.com/tendermint/tendermint/abci/types"

sdk "github.com/cosmos/cosmos-sdk/types"
keep "github.com/cosmos/cosmos-sdk/x/stake/keeper"
"github.com/cosmos/cosmos-sdk/x/stake/types"
Expand All @@ -14,7 +17,7 @@ func TestInitGenesis(t *testing.T) {
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)

pool := keeper.GetPool(ctx)
pool.LooseTokens = sdk.NewRat(2)
pool.BondedTokens = sdk.NewRat(2)

params := keeper.GetParams(ctx)
var delegations []Delegation
Expand All @@ -24,17 +27,19 @@ func TestInitGenesis(t *testing.T) {
NewValidator(keep.Addrs[1], keep.PKs[1], Description{Moniker: "bloop"}),
}
genesisState := types.NewGenesisState(pool, params, validators, delegations)
err := InitGenesis(ctx, keeper, genesisState)
_, err := InitGenesis(ctx, keeper, genesisState)
require.Error(t, err)

// initialize the validators
validators[0].Status = sdk.Bonded
validators[0].Tokens = sdk.OneRat()
validators[0].DelegatorShares = sdk.OneRat()
validators[1].Status = sdk.Bonded
validators[1].Tokens = sdk.OneRat()
validators[1].DelegatorShares = sdk.OneRat()

genesisState = types.NewGenesisState(pool, params, validators, delegations)
err = InitGenesis(ctx, keeper, genesisState)
vals, err := InitGenesis(ctx, keeper, genesisState)
require.NoError(t, err)

// now make sure the validators are bonded
Expand All @@ -45,4 +50,50 @@ func TestInitGenesis(t *testing.T) {
resVal, found = keeper.GetValidator(ctx, keep.Addrs[1])
require.True(t, found)
require.Equal(t, sdk.Bonded, resVal.Status)

abcivals := make([]abci.Validator, len(vals))
for i, val := range validators {
abcivals[i] = sdk.ABCIValidator(val)
}

require.Equal(t, abcivals, vals)
}

func TestInitGenesisLargeValidatorSet(t *testing.T) {
size := 200
require.True(t, size > 100)

ctx, _, keeper := keep.CreateTestInput(t, false, 1000)

// Assigning 2 to the first 100 vals, 1 to the rest
pool := keeper.GetPool(ctx)
pool.BondedTokens = sdk.NewRat(int64(200 + (size - 100)))

params := keeper.GetParams(ctx)
delegations := []Delegation{}
validators := make([]Validator, size)

for i := range validators {
validators[i] = NewValidator(keep.Addrs[i], keep.PKs[i], Description{Moniker: fmt.Sprintf("#%d", i)})

validators[i].Status = sdk.Bonded
if i < 100 {
validators[i].Tokens = sdk.NewRat(2)
validators[i].DelegatorShares = sdk.NewRat(2)
} else {
validators[i].Tokens = sdk.OneRat()
validators[i].DelegatorShares = sdk.OneRat()
}
}

genesisState := types.NewGenesisState(pool, params, validators, delegations)
vals, err := InitGenesis(ctx, keeper, genesisState)
require.NoError(t, err)

abcivals := make([]abci.Validator, 100)
for i, val := range validators[:100] {
abcivals[i] = sdk.ABCIValidator(val)
}

require.Equal(t, abcivals, vals)
}
4 changes: 2 additions & 2 deletions x/stake/keeper/test_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import (

// dummy addresses used for testing
var (
Addrs = createTestAddrs(100)
PKs = createTestPubKeys(100)
Addrs = createTestAddrs(500)
PKs = createTestPubKeys(500)
emptyAddr sdk.AccAddress
emptyPubkey crypto.PubKey

Expand Down