Skip to content

Commit f6371ad

Browse files
committed
Part 8 - Edit Validator.Delegators via MsgStake
1 parent 463e578 commit f6371ad

File tree

2 files changed

+107
-7
lines changed

2 files changed

+107
-7
lines changed

x/nodes/keeper/valStateChanges.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,15 @@ func (k Keeper) ValidateEditStake(ctx sdk.Ctx, currentValidator, newValidtor typ
261261
return types.ErrUnequalOutputAddr(k.Codespace())
262262
}
263263
}
264+
265+
// Delegators can be set/edited only if 1) the feature has been activated
266+
// AND 2) the message is signed by the operator address.
267+
if k.Cdc.IsAfterDelegatorUpgrade(ctx.BlockHeight()) &&
268+
!types.CompareStringMaps(currentValidator.Delegators, newValidtor.Delegators) &&
269+
!signer.Equals(currentValidator.Address) {
270+
return types.ErrDisallowedOutputAddressEdit(k.Codespace())
271+
}
272+
264273
// prevent waiting vals from modifying anything
265274
if k.IsWaitingValidator(ctx, currentValidator.Address) {
266275
return types.ErrValidatorWaitingToUnstake(types.ModuleName)
@@ -328,6 +337,11 @@ func (k Keeper) EditStakeValidator(ctx sdk.Ctx, currentValidator, updatedValidat
328337
currentValidator.OutputAddress == nil {
329338
currentValidator.OutputAddress = updatedValidator.OutputAddress
330339
}
340+
341+
// After the upgrade, we allow delegators change
342+
if k.Cdc.IsAfterDelegatorUpgrade(ctx.BlockHeight()) {
343+
currentValidator.Delegators = updatedValidator.Delegators
344+
}
331345
}
332346
// update chains
333347
currentValidator.Chains = updatedValidator.Chains

x/nodes/keeper/valStateChanges_test.go

Lines changed: 93 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -369,13 +369,8 @@ func handleStakeForTesting(
369369
msg types.MsgStake,
370370
signer crypto.PublicKey,
371371
) sdk.Error {
372-
validator := types.NewValidator(
373-
sdk.Address(msg.PublicKey.Address()),
374-
msg.PublicKey,
375-
msg.Chains,
376-
msg.ServiceUrl,
377-
sdk.ZeroInt(),
378-
msg.Output)
372+
validator := types.NewValidatorFromMsg(msg)
373+
validator.StakedTokens = sdk.ZeroInt()
379374
if err := k.ValidateValidatorStaking(
380375
ctx, validator, msg.Value, sdk.Address(signer.Address())); err != nil {
381376
return err
@@ -498,6 +493,97 @@ func TestValidatorStateChange_OutputAddressEdit(t *testing.T) {
498493
assert.Equal(t, validatorCur.OutputAddress, outputAddress)
499494
}
500495

496+
func TestValidatorStateChange_Delegators(t *testing.T) {
497+
ctx, _, k := createTestInput(t, true)
498+
499+
originalUpgradeHeight := codec.UpgradeHeight
500+
originalTestMode := codec.TestMode
501+
originalNCUST := codec.UpgradeFeatureMap[codec.NonCustodialUpdateKey]
502+
originalOEDIT := codec.UpgradeFeatureMap[codec.OutputAddressEditKey]
503+
originalDELE := codec.UpgradeFeatureMap[codec.DelegatorsKey]
504+
t.Cleanup(func() {
505+
codec.UpgradeHeight = originalUpgradeHeight
506+
codec.TestMode = originalTestMode
507+
codec.UpgradeFeatureMap[codec.NonCustodialUpdateKey] = originalNCUST
508+
codec.UpgradeFeatureMap[codec.OutputAddressEditKey] = originalOEDIT
509+
codec.UpgradeFeatureMap[codec.DelegatorsKey] = originalDELE
510+
})
511+
512+
// Enable EditStake, NCUST, and OEDIT
513+
codec.TestMode = 0
514+
codec.UpgradeHeight = -1
515+
codec.UpgradeFeatureMap[codec.NonCustodialUpdateKey] = -1
516+
codec.UpgradeFeatureMap[codec.OutputAddressEditKey] = -1
517+
518+
// Prepare accounts
519+
outputPubKey := getRandomPubKey()
520+
operatorPubKey1 := getRandomPubKey()
521+
operatorPubKey2 := getRandomPubKey()
522+
operatorAddr1 := sdk.Address(operatorPubKey1.Address())
523+
outputAddress := sdk.Address(outputPubKey.Address())
524+
operatorAddr2 := sdk.Address(operatorPubKey2.Address())
525+
526+
// Fund output address for two nodes
527+
stakeAmount := sdk.NewCoin(k.StakeDenom(ctx), sdk.NewInt(k.MinimumStake(ctx)))
528+
assert.Nil(t, fundAccount(ctx, k, outputAddress, stakeAmount))
529+
assert.Nil(t, fundAccount(ctx, k, outputAddress, stakeAmount))
530+
531+
runStake := func(
532+
operatorPubkey crypto.PublicKey,
533+
delegators map[string]uint32,
534+
signer crypto.PublicKey,
535+
) sdk.Error {
536+
msgStake := types.MsgStake{
537+
Chains: []string{"0021", "0040"},
538+
ServiceUrl: "https://www.pokt.network:443",
539+
Value: stakeAmount.Amount,
540+
PublicKey: operatorPubkey,
541+
Output: outputAddress,
542+
Delegators: delegators,
543+
}
544+
return handleStakeForTesting(ctx, k, msgStake, signer)
545+
}
546+
547+
singleDelegator := map[string]uint32{}
548+
singleDelegator[getRandomValidatorAddress().String()] = 1
549+
550+
// Attempt to set a delegators before DELE upgrade --> The field is ignored
551+
assert.Nil(t, runStake(operatorPubKey1, singleDelegator, outputPubKey))
552+
validatorCur, found := k.GetValidator(ctx, operatorAddr1)
553+
assert.True(t, found)
554+
assert.Nil(t, validatorCur.Delegators)
555+
556+
// Enable DELE
557+
codec.UpgradeFeatureMap[codec.DelegatorsKey] = -1
558+
559+
// Attempt to change the delegators with output's signature --> Fail
560+
err := runStake(operatorPubKey1, singleDelegator, outputPubKey)
561+
assert.NotNil(t, err)
562+
assert.Equal(t, k.codespace, err.Codespace())
563+
assert.Equal(t, types.CodeDisallowedOutputAddressEdit, err.Code())
564+
565+
// Attempt to set the delegators with operator's signature --> Success
566+
err = runStake(operatorPubKey1, singleDelegator, operatorPubKey1)
567+
assert.Nil(t, err)
568+
validatorCur, found = k.GetValidator(ctx, operatorAddr1)
569+
assert.True(t, found)
570+
assert.True(t, types.CompareStringMaps(validatorCur.Delegators, singleDelegator))
571+
572+
// Attempt to reset the delegators with operator's signature --> Success
573+
err = runStake(operatorPubKey1, nil, operatorPubKey1)
574+
assert.Nil(t, err)
575+
validatorCur, found = k.GetValidator(ctx, operatorAddr1)
576+
assert.True(t, found)
577+
assert.Nil(t, validatorCur.Delegators)
578+
579+
// New stake with delegators can be signed by the output --> Success
580+
err = runStake(operatorPubKey2, singleDelegator, outputPubKey)
581+
assert.Nil(t, err)
582+
validatorCur, found = k.GetValidator(ctx, operatorAddr2)
583+
assert.True(t, found)
584+
assert.True(t, types.CompareStringMaps(validatorCur.Delegators, singleDelegator))
585+
}
586+
501587
func TestKeeper_JailValidator(t *testing.T) {
502588
type fields struct {
503589
keeper Keeper

0 commit comments

Comments
 (0)