Skip to content

Commit

Permalink
Add Multiple Validators in One Transaction (#677)
Browse files Browse the repository at this point in the history
Co-authored-by: riley-stride <104941670+riley-stride@users.noreply.github.com>
  • Loading branch information
sampocs and riley-stride committed Mar 24, 2023
1 parent 7e7335a commit 4ce1317
Show file tree
Hide file tree
Showing 34 changed files with 794 additions and 1,054 deletions.
2 changes: 1 addition & 1 deletion app/app.go
Expand Up @@ -161,7 +161,7 @@ func getGovProposalHandlers() []govclient.ProposalHandler {
upgradeclient.LegacyCancelProposalHandler,
ibcclientclient.UpdateClientProposalHandler,
ibcclientclient.UpgradeProposalHandler,
stakeibcclient.AddValidatorProposalHandler,
stakeibcclient.AddValidatorsProposalHandler,
ratelimitclient.AddRateLimitProposalHandler,
ratelimitclient.UpdateRateLimitProposalHandler,
ratelimitclient.RemoveRateLimitProposalHandler,
Expand Down
2 changes: 1 addition & 1 deletion dockernet/src/init_chain.sh
Expand Up @@ -65,7 +65,7 @@ MAIN_CONFIG=""
MAIN_GENESIS=""
echo "Initializing $CHAIN chain..."
for (( i=1; i <= $NUM_NODES; i++ )); do
# Node names will be of the form: "stride-node1"
# Node names will be of the form: "stride1"
node_name="${NODE_PREFIX}${i}"
# Moniker is of the form: STRIDE_1
moniker=$(printf "${NODE_PREFIX}_${i}" | awk '{ print toupper($0) }')
Expand Down
25 changes: 21 additions & 4 deletions dockernet/src/register_host.sh
Expand Up @@ -12,6 +12,7 @@ CHANNEL="channel-$HOST_ZONE_NUM"

CHAIN_ID=$(GET_VAR_VALUE ${CHAIN}_CHAIN_ID)
VAL_PREFIX=$(GET_VAR_VALUE ${CHAIN}_VAL_PREFIX)
NODE_PREFIX=$(GET_VAR_VALUE ${CHAIN}_NODE_PREFIX)
IBC_DENOM=$(GET_VAR_VALUE IBC_${CHAIN}_CHANNEL_${HOST_ZONE_NUM}_DENOM)
HOST_DENOM=$(GET_VAR_VALUE ${CHAIN}_DENOM)
ADDRESS_PREFIX=$(GET_VAR_VALUE ${CHAIN}_ADDRESS_PREFIX)
Expand All @@ -24,16 +25,32 @@ $STRIDE_MAIN_CMD tx stakeibc register-host-zone \
sleep 10

echo "$CHAIN - Registering validators..."
# Build array of validators of the form:
# {"name": "...", "address": "...", "weight": "..."}
validators=()
weights=(5 10 5 10 5) # alternate weights across vals
for (( i=1; i <= $NUM_VALS; i++ )); do
delegate_val=$(GET_VAL_ADDR $CHAIN $i)
weight=${weights[$i]}
weight=${weights[$((i-1))]}

$STRIDE_MAIN_CMD tx stakeibc add-validator $CHAIN_ID ${VAL_PREFIX}${i} $delegate_val 10 $weight \
--from $STRIDE_ADMIN_ACCT -y | TRIM_TX
sleep 10
validator="{\"name\":\"${VAL_PREFIX}${i}\",\"address\":\"$delegate_val\",\"weight\":$weight}"
if [[ "$i" != $NUM_VALS ]]; then
validator="${validator},"
fi
validators+=("$validator")
done

# Write validators list to json file of the form:
# {"validators": [{"name": "...", "address": "...", "weight": "..."}, {"name": ... }] }
validator_json=$DOCKERNET_HOME/state/${NODE_PREFIX}1/validators.json
echo "{\"validators\": [${validators[*]}]}" > $validator_json

# Add host zone validators to Stride's host zone struct
$STRIDE_MAIN_CMD tx stakeibc add-validators $CHAIN_ID $validator_json \
--from $STRIDE_ADMIN_ACCT -y | TRIM_TX
sleep 5

# Confirm the ICA accounts have been registered before continuing
timeout=100
while true; do
if ! $STRIDE_MAIN_CMD q stakeibc show-host-zone $CHAIN_ID | grep Account | grep -q null; then
Expand Down
8 changes: 3 additions & 5 deletions proto/stride/stakeibc/gov.proto
@@ -1,19 +1,17 @@
syntax = "proto3";
package stride.stakeibc;
import "cosmos_proto/cosmos.proto";
import "gogoproto/gogo.proto";
import "stride/stakeibc/validator.proto";
option go_package = "github.com/Stride-Labs/stride/v7/x/stakeibc/types";

message AddValidatorProposal {
message AddValidatorsProposal {
option (gogoproto.equal) = true;
option (gogoproto.goproto_getters) = false;
option (gogoproto.goproto_stringer) = false;

string title = 1;
string description = 2;
string host_zone = 3;
string validator_name = 4;
string validator_address = 5
[ (cosmos_proto.scalar) = "cosmos.AddressString" ];
repeated Validator validators = 4;
string deposit = 6 [ (gogoproto.moretags) = "yaml:\"deposit\"" ];
}
13 changes: 5 additions & 8 deletions proto/stride/stakeibc/tx.proto
Expand Up @@ -2,7 +2,7 @@ syntax = "proto3";
package stride.stakeibc;

import "stride/stakeibc/ica_account.proto";
// this line is used by starport scaffolding # proto/tx/import
import "stride/stakeibc/validator.proto";

option go_package = "github.com/Stride-Labs/stride/v7/x/stakeibc/types";
import "gogoproto/gogo.proto";
Expand All @@ -18,7 +18,7 @@ service Msg {
returns (MsgClaimUndelegatedTokensResponse);
rpc RebalanceValidators(MsgRebalanceValidators)
returns (MsgRebalanceValidatorsResponse);
rpc AddValidator(MsgAddValidator) returns (MsgAddValidatorResponse);
rpc AddValidators(MsgAddValidators) returns (MsgAddValidatorsResponse);
rpc ChangeValidatorWeight(MsgChangeValidatorWeight)
returns (MsgChangeValidatorWeightResponse);
rpc DeleteValidator(MsgDeleteValidator) returns (MsgDeleteValidatorResponse);
Expand Down Expand Up @@ -109,15 +109,12 @@ message MsgRebalanceValidators {
}
message MsgRebalanceValidatorsResponse {}

message MsgAddValidator {
message MsgAddValidators {
string creator = 1;
string host_zone = 2;
string name = 3;
string address = 4 [ (cosmos_proto.scalar) = "cosmos.AddressString" ];
uint64 commission = 5;
uint64 weight = 6;
repeated Validator validators = 3;
}
message MsgAddValidatorResponse {}
message MsgAddValidatorsResponse {}

message MsgChangeValidatorWeight {
string creator = 1;
Expand Down
9 changes: 1 addition & 8 deletions proto/stride/stakeibc/validator.proto
Expand Up @@ -16,18 +16,11 @@ message ValidatorExchangeRate {
message Validator {
string name = 1;
string address = 2 [ (cosmos_proto.scalar) = "cosmos.AddressString" ];

enum ValidatorStatus {
ACTIVE = 0;
INACTIVE = 1;
}

ValidatorStatus status = 3;
uint64 commission_rate = 4;
string delegation_amt = 5 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
(gogoproto.nullable) = false
];
uint64 weight = 6;
ValidatorExchangeRate internal_exchange_rate = 7;
reserved 3, 4;
}
4 changes: 2 additions & 2 deletions x/stakeibc/README.md
Expand Up @@ -46,7 +46,7 @@ SafetyNumValidators (default uint64 = 35)
- `RedeemStake()`
- `ClaimUndelegatedTokens()`
- `RebalanceValidators()`
- `AddValidator()`
- `AddValidators()`
- `ChangeValidatorWeight()`
- `DeleteValidator()`
- `RegisterHostZone()`
Expand Down Expand Up @@ -86,7 +86,7 @@ Misc

Governance

- `AddValidatorProposal`
- `AddValidatorsProposal`

## Queries

Expand Down
2 changes: 1 addition & 1 deletion x/stakeibc/client/cli/tx.go
Expand Up @@ -29,7 +29,7 @@ func GetTxCmd() *cobra.Command {
cmd.AddCommand(CmdRedeemStake())
cmd.AddCommand(CmdClaimUndelegatedTokens())
cmd.AddCommand(CmdRebalanceValidators())
cmd.AddCommand(CmdAddValidator())
cmd.AddCommand(CmdAddValidators())
cmd.AddCommand(CmdChangeValidatorWeight())
cmd.AddCommand(CmdDeleteValidator())
cmd.AddCommand(CmdRestoreInterchainAccount())
Expand Down
54 changes: 0 additions & 54 deletions x/stakeibc/client/cli/tx_add_validator.go

This file was deleted.

73 changes: 73 additions & 0 deletions x/stakeibc/client/cli/tx_add_validators.go
@@ -0,0 +1,73 @@
package cli

import (
"encoding/json"
"os"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/tx"
"github.com/spf13/cobra"

"github.com/Stride-Labs/stride/v7/x/stakeibc/types"
)

type ValidatorsList struct {
Validators []*types.Validator `json:"validators,omitempty"`
}

// Parse a JSON with a list of validators in the format
// {
// "validators": [
// {"name": "val1", "address": "cosmosXXX", "weight": 1},
// {"name": "val2", "address": "cosmosXXX", "weight": 2}
// ]
// }
func parseAddValidatorsFile(validatorsFile string) (validators ValidatorsList, err error) {
fileContents, err := os.ReadFile(validatorsFile)
if err != nil {
return validators, err
}

if err = json.Unmarshal(fileContents, &validators); err != nil {
return validators, err
}

return validators, nil
}

func CmdAddValidators() *cobra.Command {
cmd := &cobra.Command{
Use: "add-validators [host-zone] [validator-list-file]",
Short: "Broadcast message add-validators",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) (err error) {
hostZone := args[0]
validatorListProposalFile := args[1]

validators, err := parseAddValidatorsFile(validatorListProposalFile)
if err != nil {
return err
}

clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

msg := types.NewMsgAddValidators(
clientCtx.GetFromAddress().String(),
hostZone,
validators.Validators,
)
if err := msg.ValidateBasic(); err != nil {
return err
}
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

flags.AddTxFlagsToCmd(cmd)

return cmd
}
Expand Up @@ -21,10 +21,7 @@ import (
"github.com/Stride-Labs/stride/v7/x/stakeibc/types"
)

func parseAddValidatorProposalFile(cdc codec.JSONCodec, proposalFile string) (types.AddValidatorProposal, error) {

proposal := types.AddValidatorProposal{}

func parseAddValidatorsProposalFile(cdc codec.JSONCodec, proposalFile string) (proposal types.AddValidatorsProposal, err error) {
contents, err := os.ReadFile(proposalFile)
if err != nil {
return proposal, err
Expand All @@ -34,30 +31,32 @@ func parseAddValidatorProposalFile(cdc codec.JSONCodec, proposalFile string) (ty
return proposal, err
}

proposal.Title = fmt.Sprintf("Add %s validator %s (address: %s)",
proposal.HostZone, proposal.ValidatorName, proposal.ValidatorAddress)
proposal.Title = fmt.Sprintf("Add validators to %s", proposal.HostZone)

return proposal, nil
}

func CmdAddValidatorProposal() *cobra.Command {

func CmdAddValidatorsProposal() *cobra.Command {
cmd := &cobra.Command{
Use: "add-validator [proposal-file]",
Use: "add-validators [proposal-file]",
Short: "Submit an add-validator proposal",
Long: strings.TrimSpace(
fmt.Sprintf(`Submit an add-validator proposal along with an initial deposit.
fmt.Sprintf(`Submit an add-validators proposal along with an initial deposit.
The proposal details must be supplied via a JSON file.
Example:
$ %s tx gov submit-legacy-proposal add-validator <path/to/proposal.json> --from=<key_or_address>
$ %s tx gov submit-legacy-proposal add-validators <path/to/proposal.json> --from=<key_or_address>
Where proposal.json contains:
{
"description": "Proposal to add Imperator because they contribute in XYZ ways!",
"hostZone": "GAIA",
"validatorName": "Imperator",
"validatorAddress": "cosmosvaloper1v5y0tg0jllvxf5c3afml8s3awue0ymju89frut",
"validators": [
{
"name": "Imperator",
"address": "cosmosvaloper1v5y0tg0jllvxf5c3afml8s3awue0ymju89frut",
},
],
"deposit": "64000000ustrd"
}
`, version.AppName),
Expand All @@ -69,7 +68,7 @@ Where proposal.json contains:
return err
}

proposal, err := parseAddValidatorProposalFile(clientCtx.Codec, args[0])
proposal, err := parseAddValidatorsProposalFile(clientCtx.Codec, args[0])
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion x/stakeibc/client/proposal_handler.go
Expand Up @@ -7,5 +7,5 @@ import (
)

var (
AddValidatorProposalHandler = govclient.NewProposalHandler(cli.CmdAddValidatorProposal)
AddValidatorsProposalHandler = govclient.NewProposalHandler(cli.CmdAddValidatorsProposal)
)

0 comments on commit 4ce1317

Please sign in to comment.