@@ -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+
501587func TestKeeper_JailValidator (t * testing.T ) {
502588 type fields struct {
503589 keeper Keeper
0 commit comments