Merge PR #3803: Validator Creation Updates
This commit is contained in:
parent
57fe79ffbf
commit
51c03aa6fe
@ -19,6 +19,11 @@
|
||||
|
||||
### Gaia
|
||||
|
||||
* [\#3789] Update validator creation flow:
|
||||
* Remove `NewMsgCreateValidatorOnBehalfOf` and corresponding business logic
|
||||
* Ensure the validator address equals the delegator address during
|
||||
`MsgCreateValidator#ValidateBasic`
|
||||
|
||||
### SDK
|
||||
|
||||
* [\#3669] Ensure consistency in message naming, codec registration, and JSON
|
||||
|
||||
@ -53,20 +53,19 @@ __Note__: If unspecified, `consensus_pubkey` will default to the output of `gaia
|
||||
|
||||
## Participate in genesis as a validator
|
||||
|
||||
__Note__: This section only concerns validators that want to be in the genesis file. If the chain you want to validate is already live, skip this section.
|
||||
__Note__: This section only concerns validators that want to be in the genesis
|
||||
file. If the chain you want to validate is already live, skip this section.
|
||||
|
||||
__Note__: `Gaia-9002` and `Game of stakes` will not use this process. They will be bootsrapped using Tendermint seed validators. You will just need to use the [create-validator](#create-your-validator) command in order to join as a validator for these networks.
|
||||
__Note__: `Gaia-9002` and `Game of stakes` will not use this process. They will
|
||||
be bootstrapped using validators operated by Tendermint. You will just need to use the
|
||||
[create-validator](#create-your-validator) command in order to join as a validator
|
||||
for these networks.
|
||||
|
||||
If you want to participate in genesis as a validator, you need to justify that you (or a delegator) have some stake at genesis, create one (or multiple) transaction to bond this stake to your validator address, and include this transaction in the genesis file.
|
||||
If you want to participate in genesis as a validator, you need to justify that
|
||||
you have some stake at genesis, create one (or multiple) transactions to bond this
|
||||
stake to your validator address, and include this transaction in the genesis file.
|
||||
|
||||
We thus need to distinguish two cases:
|
||||
|
||||
- Case 1: You want to bond the initial stake from your validator's address.
|
||||
- Case 2: You want to bond the initial stake from a delegator's address.
|
||||
|
||||
### Case 1: The initial stake comes from your validator's address
|
||||
|
||||
In this case, you will create a `gentx`:
|
||||
You will need create a `gentx`:
|
||||
|
||||
```bash
|
||||
gaiad gentx \
|
||||
@ -78,46 +77,17 @@ gaiad gentx \
|
||||
--name <key_name>
|
||||
```
|
||||
|
||||
__Note__: This command automatically store your `gentx` in `~/.gaiad/config/gentx` for it to be processed at genesis.
|
||||
__Note__: This command automatically store your `gentx` in `~/.gaiad/config/gentx`
|
||||
for it to be processed at genesis.
|
||||
|
||||
::: tip
|
||||
Consult `gaiad gentx --help` for more information on the flags defaults.
|
||||
:::
|
||||
|
||||
A `gentx` is a JSON file carrying a self-delegation. All genesis transactions are collected by a `genesis coordinator` and validated against an initial `genesis.json`. Such initial `genesis.json` contains only a list of accounts and their coins. Once the transactions are processed, they are merged in the `genesis.json`'s `gentxs` field.
|
||||
|
||||
### Case 2: The initial stake comes from a delegator's address
|
||||
|
||||
In this case, you need both the signature of the validator and the delegator. Start by creating an unsigned `create-validator` transaction, and save it in a file called `unsignedValTx`:
|
||||
|
||||
```bash
|
||||
gaiacli tx staking create-validator \
|
||||
--amount=5STAKE \
|
||||
--pubkey=$(gaiad tendermint show-validator) \
|
||||
--moniker="choose a moniker" \
|
||||
--chain-id=<chain_id> \
|
||||
--from=<key_name> \
|
||||
--commission-rate="0.10" \
|
||||
--commission-max-rate="0.20" \
|
||||
--commission-max-change-rate="0.01" \
|
||||
--address-delegator="address of the delegator" \
|
||||
--generate-only \
|
||||
> unsignedValTx.json
|
||||
```
|
||||
|
||||
Then, sign this `unsignedValTx` with your validator's private key, and save the output in a new file `signedValTx.json`:
|
||||
|
||||
```bash
|
||||
gaiacli tx sign unsignedValTx.json --from=<validator_key_name> > signedValTx.json
|
||||
```
|
||||
|
||||
Then, pass this file to the delegator, who needs to run the following command:
|
||||
|
||||
```bash
|
||||
gaiacli tx sign signedValTx.json --from=<delegator_key_name> > gentx.json
|
||||
```
|
||||
|
||||
This `gentx.json` needs to be included in the `~/.gaiad/config/gentx` folder on the validator's machine to be processed at genesis, just like in case 1 (except here it needs to be copied manually into the folder).
|
||||
A `gentx` is a JSON file carrying a self-delegation. All genesis transactions are
|
||||
collected by a `genesis coordinator` and validated against an initial `genesis.json`.
|
||||
Such initial `genesis.json` contains only a list of accounts and their coins.
|
||||
Once the transactions are processed, they are merged in the `genesis.json`'s `gentxs` field.
|
||||
|
||||
### Copy the Initial Genesis File and Process Genesis Transactions
|
||||
|
||||
|
||||
@ -57,13 +57,6 @@ __참고__: 이 문항은 제네시스 파일에 참가하려는 밸리데이터
|
||||
|
||||
밸리데이터로써 제네시스에 참가하고 싶으시다면 우선 본인(또는 위임자)가 stake를 보유하고 있다는 것을 증명해야 합니다. 스테이크를 검증인에게 본딩하는 하나 이상의 트랜잭션을 발생하신 후, 해당 트랜잭션을 제네시스 파일에 추가하시기 바랍니다.
|
||||
|
||||
우선 두가지의 케이스가 존재합니다:
|
||||
|
||||
- 경우 1: 본인 밸리데이터의 stake를 본딩(위임)한다.
|
||||
- 경우 2: 타인(위임자)의 stake를 본딩한다.
|
||||
|
||||
### Case 1: 최초 위임이 밸리데이터 본인 주소에서 발생하는 경우
|
||||
|
||||
이런 경우에는 `gentx`를 생성하셔야 합니다:
|
||||
|
||||
```bash
|
||||
@ -84,40 +77,6 @@ __참고__: 이 명령어는 제네시스에서의 처리를 위해 `gentx`를 `
|
||||
|
||||
`gentx`는 자체위임 정보가 포함된 JSON 파일입니다. 모든 제네시스 트랜잭셕은 `genesis coordinator`에 의하여 모아진 후 최초 `genesis.json`파일과 대치하여 검증합니다. 최초 `genesis.json`에는 계정 리스트와 각 계정이 보유하고 있는 코인 정보가 포함되어있습니다. 트랜잭션이 처리되었다면 해당 정보는 `genesis.json`의 `gentx` 항목에 머지(merge)됩니다.
|
||||
|
||||
### Case 2: 최초 위임이 위임자(delegator) 주소에서 발생하는 경우
|
||||
|
||||
이런 경우에는 위임자와 검증인의 서명이 둘다 필요합니다. 우선 서명이 되지 않은 `create-validator` 트랜잭션을 생성하신 후 `unsignedValTx`라는 파일에 저장하십시오:
|
||||
|
||||
```bash
|
||||
gaiacli tx staking create-validator \
|
||||
--amount=5STAKE \
|
||||
--pubkey=$(gaiad tendermint show-validator) \
|
||||
--moniker="choose a moniker" \
|
||||
--chain-id=<chain_id> \
|
||||
--from=<key_name> \
|
||||
--commission-rate="0.10" \
|
||||
--commission-max-rate="0.20" \
|
||||
--commission-max-change-rate="0.01" \
|
||||
--address-delegator="address of the delegator" \
|
||||
--generate-only \
|
||||
> unsignedValTx.json
|
||||
```
|
||||
|
||||
이제 해당 `unsignedValTx`를 밸리데이터의 프라이빗 키를 이용해 서명합니다. 서명이된 아웃풋을 `signedValTx.json`이라는 파일에 저장합니다:
|
||||
|
||||
```bash
|
||||
gaiacli tx sign unsignedValTx.json --from=<validator_key_name> > signedValTx.json
|
||||
```
|
||||
|
||||
이제 이 파일을 위임자에게 전달하세요. 위임인은 다음 명령어를 실행하면 됩니다:
|
||||
|
||||
```bash
|
||||
gaiacli tx sign signedValTx.json --from=<delegator_key_name> > gentx.json
|
||||
```
|
||||
|
||||
이 파일은 제네시스 절차에서 필요하기 때문에 Case 1과 동일하게 `gentx.json`은 밸리데이터 머신의 `~/.gaiad/config/gentx` 폴더에 포함되어야 합니다 (Case 2 에서는 직접 해당 파을을 이동해야 합니다).
|
||||
|
||||
|
||||
### 제네시스 파일 복사, 제네시스 트랜잭션 처리하기
|
||||
|
||||
우선 `genesis.json`파일을 `gaiad`의 config 디렉토리로 가져옵니다.
|
||||
|
||||
@ -85,12 +85,11 @@ var (
|
||||
DefaultGenesisState = types.DefaultGenesisState
|
||||
RegisterCodec = types.RegisterCodec
|
||||
|
||||
NewMsgCreateValidator = types.NewMsgCreateValidator
|
||||
NewMsgCreateValidatorOnBehalfOf = types.NewMsgCreateValidatorOnBehalfOf
|
||||
NewMsgEditValidator = types.NewMsgEditValidator
|
||||
NewMsgDelegate = types.NewMsgDelegate
|
||||
NewMsgUndelegate = types.NewMsgUndelegate
|
||||
NewMsgBeginRedelegate = types.NewMsgBeginRedelegate
|
||||
NewMsgCreateValidator = types.NewMsgCreateValidator
|
||||
NewMsgEditValidator = types.NewMsgEditValidator
|
||||
NewMsgDelegate = types.NewMsgDelegate
|
||||
NewMsgUndelegate = types.NewMsgUndelegate
|
||||
NewMsgBeginRedelegate = types.NewMsgBeginRedelegate
|
||||
|
||||
NewQuerier = querier.NewQuerier
|
||||
NewQueryDelegatorParams = querier.NewQueryDelegatorParams
|
||||
|
||||
@ -131,28 +131,13 @@ func TestStakingMsgs(t *testing.T) {
|
||||
require.Equal(t, sdk.Bonded, validator.Status)
|
||||
require.True(sdk.IntEq(t, bondTokens, validator.BondedTokens()))
|
||||
|
||||
// addr1 create validator on behalf of addr2
|
||||
createValidatorMsgOnBehalfOf := NewMsgCreateValidatorOnBehalfOf(
|
||||
addr1, sdk.ValAddress(addr2), priv2.PubKey(), bondCoin, description, commissionMsg, sdk.OneInt(),
|
||||
)
|
||||
|
||||
mock.SignCheckDeliver(t, mApp.Cdc, mApp.BaseApp, []sdk.Msg{createValidatorMsgOnBehalfOf}, []uint64{0, 0}, []uint64{1, 0}, true, true, priv1, priv2)
|
||||
mock.CheckBalance(t, mApp, addr1, sdk.Coins{genCoin.Sub(bondCoin).Sub(bondCoin)})
|
||||
mApp.BeginBlock(abci.RequestBeginBlock{})
|
||||
|
||||
validator = checkValidator(t, mApp, keeper, sdk.ValAddress(addr2), true)
|
||||
require.Equal(t, sdk.ValAddress(addr2), validator.OperatorAddress)
|
||||
require.Equal(t, sdk.Bonded, validator.Status)
|
||||
require.True(sdk.IntEq(t, bondTokens, validator.Tokens))
|
||||
|
||||
// check the bond that should have been created as well
|
||||
checkDelegation(t, mApp, keeper, addr1, sdk.ValAddress(addr1), true, bondTokens.ToDec())
|
||||
|
||||
// edit the validator
|
||||
description = NewDescription("bar_moniker", "", "", "")
|
||||
editValidatorMsg := NewMsgEditValidator(sdk.ValAddress(addr1), description, nil, nil)
|
||||
|
||||
mock.SignCheckDeliver(t, mApp.Cdc, mApp.BaseApp, []sdk.Msg{editValidatorMsg}, []uint64{0}, []uint64{2}, true, true, priv1)
|
||||
mock.SignCheckDeliver(t, mApp.Cdc, mApp.BaseApp, []sdk.Msg{editValidatorMsg}, []uint64{0}, []uint64{1}, true, true, priv1)
|
||||
validator = checkValidator(t, mApp, keeper, sdk.ValAddress(addr1), true)
|
||||
require.Equal(t, description, validator.Description)
|
||||
|
||||
@ -160,13 +145,13 @@ func TestStakingMsgs(t *testing.T) {
|
||||
mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin})
|
||||
delegateMsg := NewMsgDelegate(addr2, sdk.ValAddress(addr1), bondCoin)
|
||||
|
||||
mock.SignCheckDeliver(t, mApp.Cdc, mApp.BaseApp, []sdk.Msg{delegateMsg}, []uint64{0}, []uint64{1}, true, true, priv2)
|
||||
mock.SignCheckDeliver(t, mApp.Cdc, mApp.BaseApp, []sdk.Msg{delegateMsg}, []uint64{0}, []uint64{0}, true, true, priv2)
|
||||
mock.CheckBalance(t, mApp, addr2, sdk.Coins{genCoin.Sub(bondCoin)})
|
||||
checkDelegation(t, mApp, keeper, addr2, sdk.ValAddress(addr1), true, bondTokens.ToDec())
|
||||
|
||||
// begin unbonding
|
||||
beginUnbondingMsg := NewMsgUndelegate(addr2, sdk.ValAddress(addr1), bondTokens.ToDec())
|
||||
mock.SignCheckDeliver(t, mApp.Cdc, mApp.BaseApp, []sdk.Msg{beginUnbondingMsg}, []uint64{0}, []uint64{2}, true, true, priv2)
|
||||
mock.SignCheckDeliver(t, mApp.Cdc, mApp.BaseApp, []sdk.Msg{beginUnbondingMsg}, []uint64{0}, []uint64{1}, true, true, priv2)
|
||||
|
||||
// delegation should exist anymore
|
||||
checkDelegation(t, mApp, keeper, addr2, sdk.ValAddress(addr1), false, sdk.Dec{})
|
||||
|
||||
@ -8,7 +8,6 @@ import (
|
||||
|
||||
// nolint
|
||||
const (
|
||||
FlagAddressDelegator = "address-delegator"
|
||||
FlagAddressValidator = "validator"
|
||||
FlagAddressValidatorSrc = "addr-validator-source"
|
||||
FlagAddressValidatorDst = "addr-validator-dest"
|
||||
@ -67,7 +66,6 @@ func init() {
|
||||
fsDescriptionEdit.String(FlagWebsite, types.DoNotModifyDesc, "The validator's (optional) website")
|
||||
fsDescriptionEdit.String(FlagDetails, types.DoNotModifyDesc, "The validator's (optional) details")
|
||||
fsValidator.String(FlagAddressValidator, "", "The Bech32 address of the validator")
|
||||
fsDelegator.String(FlagAddressDelegator, "", "The Bech32 address of the delegator")
|
||||
fsRedelegation.String(FlagAddressValidatorSrc, "", "The Bech32 address of the source validator")
|
||||
fsRedelegation.String(FlagAddressValidatorDst, "", "The Bech32 address of the destination validator")
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@ func GetCmdCreateValidator(cdc *codec.Codec) *cobra.Command {
|
||||
cmd.Flags().AddFlagSet(fsDescriptionCreate)
|
||||
cmd.Flags().AddFlagSet(FsCommissionCreate)
|
||||
cmd.Flags().AddFlagSet(FsMinSelfDelegation)
|
||||
cmd.Flags().AddFlagSet(fsDelegator)
|
||||
|
||||
cmd.Flags().String(FlagIP, "", fmt.Sprintf("The node's public IP. It takes effect only when used in combination with --%s", client.FlagGenerateOnly))
|
||||
cmd.Flags().String(FlagNodeID, "", "The node's ID")
|
||||
|
||||
@ -259,23 +259,9 @@ func BuildCreateValidatorMsg(cliCtx context.CLIContext, txBldr authtxb.TxBuilder
|
||||
return txBldr, nil, fmt.Errorf(staking.ErrMinSelfDelegationInvalid(staking.DefaultCodespace).Error())
|
||||
}
|
||||
|
||||
delAddr := viper.GetString(FlagAddressDelegator)
|
||||
|
||||
var msg sdk.Msg
|
||||
if delAddr != "" {
|
||||
delAddr, err := sdk.AccAddressFromBech32(delAddr)
|
||||
if err != nil {
|
||||
return txBldr, nil, err
|
||||
}
|
||||
|
||||
msg = staking.NewMsgCreateValidatorOnBehalfOf(
|
||||
delAddr, sdk.ValAddress(valAddr), pk, amount, description, commissionMsg, minSelfDelegation,
|
||||
)
|
||||
} else {
|
||||
msg = staking.NewMsgCreateValidator(
|
||||
sdk.ValAddress(valAddr), pk, amount, description, commissionMsg, minSelfDelegation,
|
||||
)
|
||||
}
|
||||
msg := staking.NewMsgCreateValidator(
|
||||
sdk.ValAddress(valAddr), pk, amount, description, commissionMsg, minSelfDelegation,
|
||||
)
|
||||
|
||||
if viper.GetBool(client.FlagGenerateOnly) {
|
||||
ip := viper.GetString(FlagIP)
|
||||
@ -284,5 +270,6 @@ func BuildCreateValidatorMsg(cliCtx context.CLIContext, txBldr authtxb.TxBuilder
|
||||
txBldr = txBldr.WithMemo(fmt.Sprintf("%s@%s:26656", nodeID, ip))
|
||||
}
|
||||
}
|
||||
|
||||
return txBldr, msg, nil
|
||||
}
|
||||
|
||||
@ -178,38 +178,6 @@ func TestInvalidPubKeyTypeMsgCreateValidator(t *testing.T) {
|
||||
require.True(t, got.IsOK(), "%v", got)
|
||||
}
|
||||
|
||||
func TestDuplicatesMsgCreateValidatorOnBehalfOf(t *testing.T) {
|
||||
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
||||
|
||||
validatorAddr := sdk.ValAddress(keep.Addrs[0])
|
||||
delegatorAddr := keep.Addrs[1]
|
||||
pk := keep.PKs[0]
|
||||
valTokens := sdk.TokensFromTendermintPower(10)
|
||||
msgCreateValidatorOnBehalfOf := NewTestMsgCreateValidatorOnBehalfOf(delegatorAddr, validatorAddr, pk, valTokens)
|
||||
got := handleMsgCreateValidator(ctx, msgCreateValidatorOnBehalfOf, keeper)
|
||||
require.True(t, got.IsOK(), "%v", got)
|
||||
|
||||
// must end-block
|
||||
updates := keeper.ApplyAndReturnValidatorSetUpdates(ctx)
|
||||
require.Equal(t, 1, len(updates))
|
||||
|
||||
validator, found := keeper.GetValidator(ctx, validatorAddr)
|
||||
|
||||
require.True(t, found)
|
||||
assert.Equal(t, sdk.Bonded, validator.Status)
|
||||
assert.Equal(t, validatorAddr, validator.OperatorAddress)
|
||||
assert.Equal(t, pk, validator.ConsPubKey)
|
||||
assert.True(sdk.IntEq(t, valTokens, validator.Tokens))
|
||||
assert.True(sdk.DecEq(t, valTokens.ToDec(), validator.DelegatorShares))
|
||||
assert.Equal(t, Description{}, validator.Description)
|
||||
|
||||
// one validator cannot be created twice even from different delegator
|
||||
msgCreateValidatorOnBehalfOf.DelegatorAddress = keep.Addrs[2]
|
||||
msgCreateValidatorOnBehalfOf.PubKey = keep.PKs[1]
|
||||
got = handleMsgCreateValidator(ctx, msgCreateValidatorOnBehalfOf, keeper)
|
||||
require.False(t, got.IsOK(), "%v", got)
|
||||
}
|
||||
|
||||
func TestLegacyValidatorDelegations(t *testing.T) {
|
||||
ctx, _, keeper := keep.CreateTestInput(t, false, int64(1000))
|
||||
setInstantUnbondPeriod(keeper, ctx)
|
||||
@ -555,25 +523,27 @@ func TestMultipleMsgCreateValidator(t *testing.T) {
|
||||
sdk.ValAddress(keep.Addrs[2]),
|
||||
}
|
||||
delegatorAddrs := []sdk.AccAddress{
|
||||
keep.Addrs[3],
|
||||
keep.Addrs[4],
|
||||
keep.Addrs[5],
|
||||
keep.Addrs[0],
|
||||
keep.Addrs[1],
|
||||
keep.Addrs[2],
|
||||
}
|
||||
|
||||
// bond them all
|
||||
for i, validatorAddr := range validatorAddrs {
|
||||
valTokens := sdk.TokensFromTendermintPower(10)
|
||||
msgCreateValidatorOnBehalfOf := NewTestMsgCreateValidatorOnBehalfOf(
|
||||
delegatorAddrs[i], validatorAddr, keep.PKs[i], valTokens)
|
||||
msgCreateValidatorOnBehalfOf := NewTestMsgCreateValidator(validatorAddr, keep.PKs[i], valTokens)
|
||||
|
||||
got := handleMsgCreateValidator(ctx, msgCreateValidatorOnBehalfOf, keeper)
|
||||
require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got)
|
||||
|
||||
//Check that the account is bonded
|
||||
// verify that the account is bonded
|
||||
validators := keeper.GetValidators(ctx, 100)
|
||||
require.Equal(t, (i + 1), len(validators))
|
||||
|
||||
val := validators[i]
|
||||
balanceExpd := initTokens.Sub(valTokens)
|
||||
balanceGot := accMapper.GetAccount(ctx, delegatorAddrs[i]).GetCoins().AmountOf(params.BondDenom)
|
||||
|
||||
require.Equal(t, i+1, len(validators), "expected %d validators got %d, validators: %v", i+1, len(validators), validators)
|
||||
require.Equal(t, valTokens, val.DelegatorShares.RoundInt(), "expected %d shares, got %d", 10, val.DelegatorShares)
|
||||
require.Equal(t, balanceExpd, balanceGot, "expected account to have %d, got %d", balanceExpd, balanceGot)
|
||||
|
||||
@ -54,10 +54,3 @@ func NewTestMsgDelegate(delAddr sdk.AccAddress, valAddr sdk.ValAddress, amt sdk.
|
||||
amount := sdk.NewCoin(sdk.DefaultBondDenom, amt)
|
||||
return NewMsgDelegate(delAddr, valAddr, amount)
|
||||
}
|
||||
|
||||
func NewTestMsgCreateValidatorOnBehalfOf(delAddr sdk.AccAddress, valAddr sdk.ValAddress,
|
||||
valPubKey crypto.PubKey, amt sdk.Int) MsgCreateValidator {
|
||||
|
||||
amount := sdk.NewCoin(sdk.DefaultBondDenom, amt)
|
||||
return NewMsgCreateValidatorOnBehalfOf(delAddr, valAddr, valPubKey, amount, Description{}, commissionMsg, sdk.OneInt())
|
||||
}
|
||||
|
||||
@ -42,23 +42,17 @@ type msgCreateValidatorJSON struct {
|
||||
}
|
||||
|
||||
// Default way to create validator. Delegator address and validator address are the same
|
||||
func NewMsgCreateValidator(valAddr sdk.ValAddress, pubkey crypto.PubKey,
|
||||
selfDelegation sdk.Coin, description Description, commission CommissionMsg, minSelfDelegation sdk.Int) MsgCreateValidator {
|
||||
func NewMsgCreateValidator(
|
||||
valAddr sdk.ValAddress, pubKey crypto.PubKey, selfDelegation sdk.Coin,
|
||||
description Description, commission CommissionMsg, minSelfDelegation sdk.Int,
|
||||
) MsgCreateValidator {
|
||||
|
||||
return NewMsgCreateValidatorOnBehalfOf(
|
||||
sdk.AccAddress(valAddr), valAddr, pubkey, selfDelegation, description, commission, minSelfDelegation,
|
||||
)
|
||||
}
|
||||
|
||||
// Creates validator msg by delegator address on behalf of validator address
|
||||
func NewMsgCreateValidatorOnBehalfOf(delAddr sdk.AccAddress, valAddr sdk.ValAddress,
|
||||
pubkey crypto.PubKey, value sdk.Coin, description Description, commission CommissionMsg, minSelfDelegation sdk.Int) MsgCreateValidator {
|
||||
return MsgCreateValidator{
|
||||
Description: description,
|
||||
DelegatorAddress: delAddr,
|
||||
DelegatorAddress: sdk.AccAddress(valAddr),
|
||||
ValidatorAddress: valAddr,
|
||||
PubKey: pubkey,
|
||||
Value: value,
|
||||
PubKey: pubKey,
|
||||
Value: selfDelegation,
|
||||
Commission: commission,
|
||||
MinSelfDelegation: minSelfDelegation,
|
||||
}
|
||||
@ -133,6 +127,9 @@ func (msg MsgCreateValidator) ValidateBasic() sdk.Error {
|
||||
if msg.ValidatorAddress.Empty() {
|
||||
return ErrNilValidatorAddr(DefaultCodespace)
|
||||
}
|
||||
if !sdk.AccAddress(msg.ValidatorAddress).Equals(msg.DelegatorAddress) {
|
||||
return ErrBadValidatorAddr(DefaultCodespace)
|
||||
}
|
||||
if msg.Value.Amount.LTE(sdk.ZeroInt()) {
|
||||
return ErrBadDelegationAmount(DefaultCodespace)
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
@ -78,55 +77,6 @@ func TestMsgEditValidator(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// test ValidateBasic and GetSigners for MsgCreateValidatorOnBehalfOf
|
||||
func TestMsgCreateValidatorOnBehalfOf(t *testing.T) {
|
||||
commission1 := NewCommissionMsg(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec())
|
||||
commission2 := NewCommissionMsg(sdk.NewDec(5), sdk.NewDec(5), sdk.NewDec(5))
|
||||
|
||||
tests := []struct {
|
||||
name, moniker, identity, website, details string
|
||||
commissionMsg CommissionMsg
|
||||
minSelfDelegation sdk.Int
|
||||
delegatorAddr sdk.AccAddress
|
||||
validatorAddr sdk.ValAddress
|
||||
validatorPubKey crypto.PubKey
|
||||
bond sdk.Coin
|
||||
expectPass bool
|
||||
}{
|
||||
{"basic good", "a", "b", "c", "d", commission2, sdk.OneInt(), sdk.AccAddress(addr1), addr2, pk2, coinPos, true},
|
||||
{"partial description", "", "", "c", "", commission2, sdk.OneInt(), sdk.AccAddress(addr1), addr2, pk2, coinPos, true},
|
||||
{"empty description", "", "", "", "", commission1, sdk.OneInt(), sdk.AccAddress(addr1), addr2, pk2, coinPos, false},
|
||||
{"empty delegator address", "a", "b", "c", "d", commission1, sdk.OneInt(), sdk.AccAddress(emptyAddr), addr2, pk2, coinPos, false},
|
||||
{"empty validator address", "a", "b", "c", "d", commission2, sdk.OneInt(), sdk.AccAddress(addr1), emptyAddr, pk2, coinPos, false},
|
||||
{"empty pubkey", "a", "b", "c", "d", commission1, sdk.OneInt(), sdk.AccAddress(addr1), addr2, emptyPubkey, coinPos, true},
|
||||
{"empty bond", "a", "b", "c", "d", commission2, sdk.OneInt(), sdk.AccAddress(addr1), addr2, pk2, coinZero, false},
|
||||
{"zero min self delegation", "a", "b", "c", "d", commission2, sdk.ZeroInt(), sdk.AccAddress(addr1), addr2, pk2, coinPos, false},
|
||||
{"negative min self delegation", "", "", "c", "", commission2, sdk.NewInt(-1), sdk.AccAddress(addr1), addr2, pk2, coinPos, false},
|
||||
{"delegation less than min self delegation", "a", "b", "c", "d", commission2, coinPos.Amount.Add(sdk.OneInt()), sdk.AccAddress(addr1), addr2, pk2, coinPos, false},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
description := NewDescription(tc.moniker, tc.identity, tc.website, tc.details)
|
||||
msg := NewMsgCreateValidatorOnBehalfOf(
|
||||
tc.delegatorAddr, tc.validatorAddr, tc.validatorPubKey, tc.bond, description, tc.commissionMsg, tc.minSelfDelegation,
|
||||
)
|
||||
|
||||
if tc.expectPass {
|
||||
require.Nil(t, msg.ValidateBasic(), "test: %v", tc.name)
|
||||
} else {
|
||||
require.NotNil(t, msg.ValidateBasic(), "test: %v", tc.name)
|
||||
}
|
||||
}
|
||||
|
||||
msg := NewMsgCreateValidator(addr1, pk1, coinPos, Description{}, CommissionMsg{}, sdk.OneInt())
|
||||
addrs := msg.GetSigners()
|
||||
require.Equal(t, []sdk.AccAddress{sdk.AccAddress(addr1)}, addrs, "Signers on default msg is wrong")
|
||||
|
||||
msg = NewMsgCreateValidatorOnBehalfOf(sdk.AccAddress(addr2), addr1, pk1, coinPos, Description{}, CommissionMsg{}, sdk.OneInt())
|
||||
addrs = msg.GetSigners()
|
||||
require.Equal(t, []sdk.AccAddress{sdk.AccAddress(addr2), sdk.AccAddress(addr1)}, addrs, "Signers for onbehalfof msg is wrong")
|
||||
}
|
||||
|
||||
// test ValidateBasic for MsgDelegate
|
||||
func TestMsgDelegate(t *testing.T) {
|
||||
tests := []struct {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user