Skip to content

Commit

Permalink
Part 8 - Edit Validator.Delegators via MsgStake
Browse files Browse the repository at this point in the history
  • Loading branch information
kinesis-agent committed Sep 6, 2023
1 parent 463e578 commit f6371ad
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 7 deletions.
14 changes: 14 additions & 0 deletions x/nodes/keeper/valStateChanges.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,15 @@ func (k Keeper) ValidateEditStake(ctx sdk.Ctx, currentValidator, newValidtor typ
return types.ErrUnequalOutputAddr(k.Codespace())
}
}

// Delegators can be set/edited only if 1) the feature has been activated
// AND 2) the message is signed by the operator address.
if k.Cdc.IsAfterDelegatorUpgrade(ctx.BlockHeight()) &&
!types.CompareStringMaps(currentValidator.Delegators, newValidtor.Delegators) &&
!signer.Equals(currentValidator.Address) {
return types.ErrDisallowedOutputAddressEdit(k.Codespace())
}

// prevent waiting vals from modifying anything
if k.IsWaitingValidator(ctx, currentValidator.Address) {
return types.ErrValidatorWaitingToUnstake(types.ModuleName)
Expand Down Expand Up @@ -328,6 +337,11 @@ func (k Keeper) EditStakeValidator(ctx sdk.Ctx, currentValidator, updatedValidat
currentValidator.OutputAddress == nil {
currentValidator.OutputAddress = updatedValidator.OutputAddress
}

// After the upgrade, we allow delegators change
if k.Cdc.IsAfterDelegatorUpgrade(ctx.BlockHeight()) {
currentValidator.Delegators = updatedValidator.Delegators
}
}
// update chains
currentValidator.Chains = updatedValidator.Chains
Expand Down
100 changes: 93 additions & 7 deletions x/nodes/keeper/valStateChanges_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,13 +369,8 @@ func handleStakeForTesting(
msg types.MsgStake,
signer crypto.PublicKey,
) sdk.Error {
validator := types.NewValidator(
sdk.Address(msg.PublicKey.Address()),
msg.PublicKey,
msg.Chains,
msg.ServiceUrl,
sdk.ZeroInt(),
msg.Output)
validator := types.NewValidatorFromMsg(msg)
validator.StakedTokens = sdk.ZeroInt()
if err := k.ValidateValidatorStaking(
ctx, validator, msg.Value, sdk.Address(signer.Address())); err != nil {
return err
Expand Down Expand Up @@ -498,6 +493,97 @@ func TestValidatorStateChange_OutputAddressEdit(t *testing.T) {
assert.Equal(t, validatorCur.OutputAddress, outputAddress)
}

func TestValidatorStateChange_Delegators(t *testing.T) {
ctx, _, k := createTestInput(t, true)

originalUpgradeHeight := codec.UpgradeHeight
originalTestMode := codec.TestMode
originalNCUST := codec.UpgradeFeatureMap[codec.NonCustodialUpdateKey]
originalOEDIT := codec.UpgradeFeatureMap[codec.OutputAddressEditKey]
originalDELE := codec.UpgradeFeatureMap[codec.DelegatorsKey]
t.Cleanup(func() {
codec.UpgradeHeight = originalUpgradeHeight
codec.TestMode = originalTestMode
codec.UpgradeFeatureMap[codec.NonCustodialUpdateKey] = originalNCUST
codec.UpgradeFeatureMap[codec.OutputAddressEditKey] = originalOEDIT
codec.UpgradeFeatureMap[codec.DelegatorsKey] = originalDELE
})

// Enable EditStake, NCUST, and OEDIT
codec.TestMode = 0
codec.UpgradeHeight = -1
codec.UpgradeFeatureMap[codec.NonCustodialUpdateKey] = -1
codec.UpgradeFeatureMap[codec.OutputAddressEditKey] = -1

// Prepare accounts
outputPubKey := getRandomPubKey()
operatorPubKey1 := getRandomPubKey()
operatorPubKey2 := getRandomPubKey()
operatorAddr1 := sdk.Address(operatorPubKey1.Address())
outputAddress := sdk.Address(outputPubKey.Address())
operatorAddr2 := sdk.Address(operatorPubKey2.Address())

// Fund output address for two nodes
stakeAmount := sdk.NewCoin(k.StakeDenom(ctx), sdk.NewInt(k.MinimumStake(ctx)))
assert.Nil(t, fundAccount(ctx, k, outputAddress, stakeAmount))
assert.Nil(t, fundAccount(ctx, k, outputAddress, stakeAmount))

runStake := func(
operatorPubkey crypto.PublicKey,
delegators map[string]uint32,
signer crypto.PublicKey,
) sdk.Error {
msgStake := types.MsgStake{
Chains: []string{"0021", "0040"},
ServiceUrl: "https://www.pokt.network:443",
Value: stakeAmount.Amount,
PublicKey: operatorPubkey,
Output: outputAddress,
Delegators: delegators,
}
return handleStakeForTesting(ctx, k, msgStake, signer)
}

singleDelegator := map[string]uint32{}
singleDelegator[getRandomValidatorAddress().String()] = 1

// Attempt to set a delegators before DELE upgrade --> The field is ignored
assert.Nil(t, runStake(operatorPubKey1, singleDelegator, outputPubKey))
validatorCur, found := k.GetValidator(ctx, operatorAddr1)
assert.True(t, found)
assert.Nil(t, validatorCur.Delegators)

// Enable DELE
codec.UpgradeFeatureMap[codec.DelegatorsKey] = -1

// Attempt to change the delegators with output's signature --> Fail
err := runStake(operatorPubKey1, singleDelegator, outputPubKey)
assert.NotNil(t, err)
assert.Equal(t, k.codespace, err.Codespace())
assert.Equal(t, types.CodeDisallowedOutputAddressEdit, err.Code())

// Attempt to set the delegators with operator's signature --> Success
err = runStake(operatorPubKey1, singleDelegator, operatorPubKey1)
assert.Nil(t, err)
validatorCur, found = k.GetValidator(ctx, operatorAddr1)
assert.True(t, found)
assert.True(t, types.CompareStringMaps(validatorCur.Delegators, singleDelegator))

// Attempt to reset the delegators with operator's signature --> Success
err = runStake(operatorPubKey1, nil, operatorPubKey1)
assert.Nil(t, err)
validatorCur, found = k.GetValidator(ctx, operatorAddr1)
assert.True(t, found)
assert.Nil(t, validatorCur.Delegators)

// New stake with delegators can be signed by the output --> Success
err = runStake(operatorPubKey2, singleDelegator, outputPubKey)
assert.Nil(t, err)
validatorCur, found = k.GetValidator(ctx, operatorAddr2)
assert.True(t, found)
assert.True(t, types.CompareStringMaps(validatorCur.Delegators, singleDelegator))
}

func TestKeeper_JailValidator(t *testing.T) {
type fields struct {
keeper Keeper
Expand Down

0 comments on commit f6371ad

Please sign in to comment.