@@ -589,6 +589,157 @@ test_MergeValidatorLicense = do
589589 [(validatorLicenseSv2Cid, _)] <- queryFilter @ValidatorLicense dso (\license -> license.validator == sv2)
590590 submitMultiMustFail [sv1] [dso] $ exerciseCmd rulesCid (DsoRules_MergeValidatorLicense [validatorLicenseCid3, validatorLicenseSv2Cid] (Some sv1))
591591
592+ -- Test weight merging: min weight should be used
593+ v2 <- allocateParty "v2"
594+ validatorLicenseW1 <- submit dso $ createCmd ValidatorLicense with
595+ validator = v2
596+ sponsor = sv1
597+ dso
598+ faucetState = Some FaucetState with
599+ firstReceivedFor = Round 0
600+ lastReceivedFor = Round 1
601+ numCouponsMissed = 0
602+ metadata = None
603+ lastActiveAt = Some now
604+ weight = None
605+ kind = Some OperatorLicense
606+
607+ validatorLicenseW2 <- submit dso $ createCmd ValidatorLicense with
608+ validator = v2
609+ sponsor = sv2
610+ dso
611+ faucetState = Some FaucetState with
612+ firstReceivedFor = Round 0
613+ lastReceivedFor = Round 3
614+ numCouponsMissed = 0
615+ metadata = None
616+ lastActiveAt = Some now
617+ weight = Some 2.0
618+ kind = Some OperatorLicense
619+
620+ validatorLicenseW3 <- submit dso $ createCmd ValidatorLicense with
621+ validator = v2
622+ sponsor = sv1
623+ dso
624+ faucetState = Some FaucetState with
625+ firstReceivedFor = Round 0
626+ lastReceivedFor = Round 2
627+ numCouponsMissed = 0
628+ metadata = None
629+ lastActiveAt = Some now
630+ weight = Some 1.5
631+ kind = Some OperatorLicense
632+
633+ DsoRules_MergeValidatorLicenseResult mergedWeightLicense <- submitMulti [sv1] [dso] $ exerciseCmd rulesCid (DsoRules_MergeValidatorLicense [validatorLicenseW1, validatorLicenseW2, validatorLicenseW3] (Some sv1))
634+ [(_, mergedLicense)] <- queryFilter @ValidatorLicense dso (\license -> license.validator == v2)
635+ -- The merged license should have the minimum weight (0.5) and the highest lastReceivedFor (Round 3)
636+ mergedLicense.weight === Some 1.5
637+ mergedLicense.faucetState === Some FaucetState with
638+ firstReceivedFor = Round 0
639+ lastReceivedFor = Round 3
640+ numCouponsMissed = 0
641+
642+ -- Test kind merging: Some OperatorLicense if any license has None or Some OperatorLicense
643+ v3 <- allocateParty "v3"
644+
645+ -- Test case 1: mixing None and Some NonOperatorLicense -> should result in Some OperatorLicense
646+ validatorLicenseK1 <- submit dso $ createCmd ValidatorLicense with
647+ validator = v3
648+ sponsor = sv1
649+ dso
650+ faucetState = Some FaucetState with
651+ firstReceivedFor = Round 0
652+ lastReceivedFor = Round 1
653+ numCouponsMissed = 0
654+ metadata = None
655+ lastActiveAt = Some now
656+ weight = None
657+ kind = None -- None should be treated as OperatorLicense
658+
659+ validatorLicenseK2 <- submit dso $ createCmd ValidatorLicense with
660+ validator = v3
661+ sponsor = sv2
662+ dso
663+ faucetState = Some FaucetState with
664+ firstReceivedFor = Round 0
665+ lastReceivedFor = Round 2
666+ numCouponsMissed = 0
667+ metadata = None
668+ lastActiveAt = Some now
669+ weight = None
670+ kind = Some NonOperatorLicense
671+
672+ DsoRules_MergeValidatorLicenseResult mergedKind1 <- submitMulti [sv1] [dso] $ exerciseCmd rulesCid (DsoRules_MergeValidatorLicense [validatorLicenseK1, validatorLicenseK2] (Some sv1))
673+ [(_, mergedLicense1)] <- queryFilter @ValidatorLicense dso (\license -> license.validator == v3)
674+ -- Should be OperatorLicense because one license had None
675+ mergedLicense1.kind === Some OperatorLicense
676+
677+ -- Test case 2: mixing Some OperatorLicense and Some NonOperatorLicense -> should result in Some OperatorLicense
678+ v4 <- allocateParty "v4"
679+ validatorLicenseK3 <- submit dso $ createCmd ValidatorLicense with
680+ validator = v4
681+ sponsor = sv1
682+ dso
683+ faucetState = Some FaucetState with
684+ firstReceivedFor = Round 0
685+ lastReceivedFor = Round 1
686+ numCouponsMissed = 0
687+ metadata = None
688+ lastActiveAt = Some now
689+ weight = None
690+ kind = Some OperatorLicense
691+
692+ validatorLicenseK4 <- submit dso $ createCmd ValidatorLicense with
693+ validator = v4
694+ sponsor = sv2
695+ dso
696+ faucetState = Some FaucetState with
697+ firstReceivedFor = Round 0
698+ lastReceivedFor = Round 2
699+ numCouponsMissed = 0
700+ metadata = None
701+ lastActiveAt = Some now
702+ weight = None
703+ kind = Some NonOperatorLicense
704+
705+ DsoRules_MergeValidatorLicenseResult mergedKind2 <- submitMulti [sv1] [dso] $ exerciseCmd rulesCid (DsoRules_MergeValidatorLicense [validatorLicenseK3, validatorLicenseK4] (Some sv1))
706+ [(_, mergedLicense2)] <- queryFilter @ValidatorLicense dso (\license -> license.validator == v4)
707+ -- Should be OperatorLicense to prevent downgrading
708+ mergedLicense2.kind === Some OperatorLicense
709+
710+ -- Test case 3: all licenses are Some NonOperatorLicense -> should result in Some NonOperatorLicense
711+ v5 <- allocateParty "v5"
712+ validatorLicenseK5 <- submit dso $ createCmd ValidatorLicense with
713+ validator = v5
714+ sponsor = sv1
715+ dso
716+ faucetState = Some FaucetState with
717+ firstReceivedFor = Round 0
718+ lastReceivedFor = Round 1
719+ numCouponsMissed = 0
720+ metadata = None
721+ lastActiveAt = Some now
722+ weight = None
723+ kind = Some NonOperatorLicense
724+
725+ validatorLicenseK6 <- submit dso $ createCmd ValidatorLicense with
726+ validator = v5
727+ sponsor = sv2
728+ dso
729+ faucetState = Some FaucetState with
730+ firstReceivedFor = Round 0
731+ lastReceivedFor = Round 2
732+ numCouponsMissed = 0
733+ metadata = None
734+ lastActiveAt = Some now
735+ weight = None
736+ kind = Some NonOperatorLicense
737+
738+ DsoRules_MergeValidatorLicenseResult mergedKind3 <- submitMulti [sv1] [dso] $ exerciseCmd rulesCid (DsoRules_MergeValidatorLicense [validatorLicenseK5, validatorLicenseK6] (Some sv1))
739+ [(_, mergedLicense3)] <- queryFilter @ValidatorLicense dso (\license -> license.validator == v5)
740+ -- Should be NonOperatorLicense since all licenses are NonOperatorLicense
741+ mergedLicense3.kind === Some NonOperatorLicense
742+
592743 pure()
593744
594745testBootstrapDevNetWithNonZeroRound : Script ()
0 commit comments