@@ -723,3 +723,124 @@ func TestQuorumCertificateMoreNodes(t *testing.T) {
723
723
assert .Equal (t , cadence .NewBool (true ), result )
724
724
})
725
725
}
726
+
727
+ func TestQuorumCertificateNotSubmittedVote (t * testing.T ) {
728
+ b := newBlockchain ()
729
+
730
+ env := templates.Environment {
731
+ FungibleTokenAddress : emulatorFTAddress ,
732
+ FlowTokenAddress : emulatorFlowTokenAddress ,
733
+ }
734
+
735
+ accountKeys := test .AccountKeyGenerator ()
736
+
737
+ // Create new keys for the QC account and deploy
738
+ QCAccountKey , QCSigner := accountKeys .NewWithSigner ()
739
+ QCCode := contracts .FlowQC ()
740
+
741
+ QCAddress , err := b .CreateAccount ([]* flow.AccountKey {QCAccountKey }, []sdktemplates.Contract {
742
+ {
743
+ Name : "FlowClusterQC" ,
744
+ Source : string (QCCode ),
745
+ },
746
+ })
747
+ if ! assert .NoError (t , err ) {
748
+ t .Log (err .Error ())
749
+ }
750
+
751
+ env .QuorumCertificateAddress = QCAddress .Hex ()
752
+
753
+ collectorVoteHasher := flow_crypto .NewBLSKMAC (encoding .CollectorVoteTag )
754
+
755
+ tx := createTxWithTemplateAndAuthorizer (b , templates .GeneratePublishVoterScript (env ), QCAddress )
756
+
757
+ signAndSubmit (
758
+ t , b , tx ,
759
+ []flow.Address {b .ServiceKey ().Address , QCAddress },
760
+ []crypto.Signer {b .ServiceKey ().Signer (), QCSigner },
761
+ false ,
762
+ )
763
+
764
+ numberOfClusters := 1
765
+ numberOfNodesPerCluster := 4
766
+
767
+ // Create new user accounts
768
+ addresses , _ , signers := registerAndMintManyAccounts (t , b , accountKeys , numberOfClusters * numberOfNodesPerCluster )
769
+
770
+ clusterNodeIDStrings := make ([][]string , numberOfClusters * numberOfNodesPerCluster )
771
+
772
+ stakingPrivateKeys , stakingPublicKeys , _ , _ := generateManyNodeKeys (t , numberOfClusters * numberOfNodesPerCluster )
773
+
774
+ // initializes clusters by filling them all in in order
775
+ // Other tests continue this cluster organization assumption
776
+ startVotingArguments := initClusters (clusterNodeIDStrings , numberOfClusters , numberOfNodesPerCluster )
777
+
778
+ tx = createTxWithTemplateAndAuthorizer (b , templates .GenerateStartVotingScript (env ), QCAddress )
779
+
780
+ err = tx .AddArgument (cadence .NewArray (startVotingArguments [0 ]))
781
+ require .NoError (t , err )
782
+
783
+ err = tx .AddArgument (cadence .NewArray (startVotingArguments [1 ]))
784
+ require .NoError (t , err )
785
+
786
+ err = tx .AddArgument (cadence .NewArray (startVotingArguments [2 ]))
787
+ require .NoError (t , err )
788
+
789
+ signAndSubmit (
790
+ t , b , tx ,
791
+ []flow.Address {b .ServiceKey ().Address , QCAddress },
792
+ []crypto.Signer {b .ServiceKey ().Signer (), QCSigner },
793
+ false ,
794
+ )
795
+
796
+ // Claim voter resources
797
+ for i := 0 ; i < numberOfClusters * numberOfNodesPerCluster ; i ++ {
798
+
799
+ tx := createTxWithTemplateAndAuthorizer (b , templates .GenerateCreateVoterScript (env ), addresses [i ])
800
+
801
+ _ = tx .AddArgument (cadence .NewAddress (QCAddress ))
802
+ _ = tx .AddArgument (cadence .NewString (clusterNodeIDStrings [i / numberOfNodesPerCluster ][i % numberOfNodesPerCluster ]))
803
+ _ = tx .AddArgument (cadence .NewString (stakingPublicKeys [i ]))
804
+
805
+ signAndSubmit (
806
+ t , b , tx ,
807
+ []flow.Address {b .ServiceKey ().Address , addresses [i ]},
808
+ []crypto.Signer {b .ServiceKey ().Signer (), signers [i ]},
809
+ false ,
810
+ )
811
+ }
812
+
813
+ t .Run ("Should generate a valid quorum certificate even if a node hasn't voted" , func (t * testing.T ) {
814
+
815
+ for i := 0 ; i < numberOfNodesPerCluster - 1 ; i ++ {
816
+
817
+ // Construct a valid message and signature
818
+ msg , _ := hex .DecodeString ("deadbeef" )
819
+ validSignature , err := stakingPrivateKeys [i ].Sign (msg , collectorVoteHasher )
820
+ validSignatureString := validSignature .String ()[2 :]
821
+ assert .NoError (t , err )
822
+
823
+ tx := createTxWithTemplateAndAuthorizer (b , templates .GenerateSubmitVoteScript (env ), addresses [i ])
824
+
825
+ _ = tx .AddArgument (cadence .NewString (validSignatureString ))
826
+ _ = tx .AddArgument (cadence .NewString ("deadbeef" ))
827
+
828
+ signAndSubmit (
829
+ t , b , tx ,
830
+ []flow.Address {b .ServiceKey ().Address , addresses [i ]},
831
+ []crypto.Signer {b .ServiceKey ().Signer (), signers [i ]},
832
+ false ,
833
+ )
834
+ }
835
+
836
+ result := executeScriptAndCheck (t , b , templates .GenerateGetVotingCompletedScript (env ), nil )
837
+ assert .Equal (t , cadence .NewBool (true ), result )
838
+
839
+ result = executeScriptAndCheck (t , b , templates .GenerateGetClusterCompleteScript (env ), [][]byte {jsoncdc .MustEncode (cadence .UInt16 (uint16 (0 )))})
840
+ assert .Equal (t , cadence .NewBool (true ), result )
841
+
842
+ executeScriptAndCheck (t , b , templates .GenerateGenerateQuorumCertificateScript (env ), [][]byte {jsoncdc .MustEncode (cadence .UInt16 (uint16 (0 )))})
843
+
844
+ })
845
+
846
+ }
0 commit comments