LCOV - code coverage report
Current view: top level - src/llmq - quorums_dkgsession.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 73 74 98.6 %
Date: 2025-02-23 09:33:43 Functions: 23 23 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2018-2021 The Dash Core developers
       2             : // Copyright (c) 2022 The PIVX Core developers
       3             : // Distributed under the MIT/X11 software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #ifndef PIVX_LLMQ_QUORUMS_DKGSESSION_H
       7             : #define PIVX_LLMQ_QUORUMS_DKGSESSION_H
       8             : 
       9             : #include "bls/bls_ies.h"
      10             : #include "bls/bls_worker.h"
      11             : #include "consensus/params.h"
      12             : #include "evo/deterministicmns.h"
      13             : #include "net.h"
      14             : #include "llmq/quorums_utils.h"
      15             : #include "logging.h"
      16             : 
      17             : class UniValue;
      18             : 
      19             : namespace llmq
      20             : {
      21             : 
      22             : class CFinalCommitment;
      23             : class CDKGSession;
      24             : class CDKGSessionManager;
      25             : class CDKGPendingMessages;
      26             : 
      27        1501 : class CDKGLogger : public CBatchedLogger
      28             : {
      29             : public:
      30             :     CDKGLogger(const CDKGSession& _quorumDkg, const std::string& _func);
      31             :     CDKGLogger(const std::string& _llmqTypeName, const uint256& _quorumHash, int _height, bool _areWeMember, const std::string& _func);
      32             : };
      33             : 
      34             : class CDKGContribution
      35             : {
      36             : public:
      37             :     uint8_t llmqType;
      38             :     uint256 quorumHash;
      39             :     uint256 proTxHash;
      40             :     BLSVerificationVectorPtr vvec;
      41             :     std::shared_ptr<CBLSIESMultiRecipientObjects<CBLSSecretKey>> contributions;
      42             :     CBLSSignature sig;
      43             : 
      44             : public:
      45             :     template<typename Stream>
      46         629 :     inline void SerializeWithoutSig(Stream& s) const
      47             :     {
      48         629 :         s << llmqType;
      49         629 :         s << quorumHash;
      50         629 :         s << proTxHash;
      51         629 :         s << *vvec;
      52         629 :         s << *contributions;
      53         629 :     }
      54             :     template<typename Stream>
      55         375 :     inline void Serialize(Stream& s) const
      56             :     {
      57         375 :         SerializeWithoutSig(s);
      58         375 :         s << sig;
      59             :     }
      60             :     template<typename Stream>
      61         186 :     inline void Unserialize(Stream& s)
      62             :     {
      63         186 :         BLSVerificationVector tmp1;
      64         186 :         CBLSIESMultiRecipientObjects<CBLSSecretKey> tmp2;
      65             : 
      66         186 :         s >> llmqType;
      67         186 :         s >> quorumHash;
      68         186 :         s >> proTxHash;
      69         186 :         s >> tmp1;
      70         186 :         s >> tmp2;
      71         186 :         s >> sig;
      72             : 
      73         186 :         vvec = std::make_shared<BLSVerificationVector>(std::move(tmp1));
      74         186 :         contributions = std::make_shared<CBLSIESMultiRecipientObjects<CBLSSecretKey>>(std::move(tmp2));
      75         186 :     }
      76             : 
      77         254 :     uint256 GetSignHash() const
      78             :     {
      79         254 :         CHashWriter hw(SER_GETHASH, 0);
      80         254 :         SerializeWithoutSig(hw);
      81         508 :         hw << CBLSSignature();
      82         254 :         return hw.GetHash();
      83             :     }
      84             : };
      85             : 
      86         253 : class CDKGComplaint
      87             : {
      88             : public:
      89             :     uint8_t llmqType;
      90             :     uint256 quorumHash;
      91             :     uint256 proTxHash;
      92             :     std::vector<bool> badMembers;
      93             :     std::vector<bool> complainForMembers;
      94             :     CBLSSignature sig;
      95             : 
      96             : public:
      97         316 :     CDKGComplaint() {}
      98             :     explicit CDKGComplaint(const Consensus::LLMQParams& params);
      99             : 
     100         382 :     SERIALIZE_METHODS(CDKGComplaint, obj)
     101             :     {
     102         204 :         READWRITE(obj.llmqType);
     103         204 :         READWRITE(obj.quorumHash);
     104         204 :         READWRITE(obj.proTxHash);
     105         204 :         READWRITE(DYNBITSET(obj.badMembers));
     106         204 :         READWRITE(DYNBITSET(obj.complainForMembers));
     107         204 :         READWRITE(obj.sig);
     108         204 :     }
     109             : 
     110          66 :     uint256 GetSignHash() const
     111             :     {
     112          66 :         CDKGComplaint tmp(*this);
     113          66 :         tmp.sig = CBLSSignature();
     114         132 :         return ::SerializeHash(tmp);
     115             :     }
     116             : };
     117             : 
     118          53 : class CDKGJustification
     119             : {
     120             : public:
     121             :     uint8_t llmqType;
     122             :     uint256 quorumHash;
     123             :     uint256 proTxHash;
     124             :     std::vector<std::pair<uint32_t, CBLSSecretKey>> contributions;
     125             :     CBLSSignature sig;
     126             : 
     127             : public:
     128             : 
     129          96 :     SERIALIZE_METHODS(CDKGJustification, obj)
     130             :     {
     131          52 :         READWRITE(obj.llmqType);
     132          52 :         READWRITE(obj.quorumHash);
     133          52 :         READWRITE(obj.proTxHash);
     134          52 :         READWRITE(obj.contributions);
     135          52 :         READWRITE(obj.sig);
     136          52 :     }
     137             : 
     138          16 :     uint256 GetSignHash() const
     139             :     {
     140          16 :         CDKGJustification tmp(*this);
     141          16 :         tmp.sig = CBLSSignature();
     142          32 :         return ::SerializeHash(tmp);
     143             :     }
     144             : };
     145             : 
     146             : // each member commits to a single set of valid members with this message
     147             : // then each node aggregate all received premature commitments
     148             : // into a single CFinalCommitment, which is only valid if
     149             : // enough (>=minSize) premature commitments were aggregated
     150         626 : class CDKGPrematureCommitment
     151             : {
     152             : public:
     153             :     uint8_t llmqType;
     154             :     uint256 quorumHash;
     155             :     uint256 proTxHash;
     156             :     std::vector<bool> validMembers;
     157             : 
     158             :     CBLSPublicKey quorumPublicKey;
     159             :     uint256 quorumVvecHash;
     160             : 
     161             :     CBLSSignature quorumSig; // threshold sig share of quorumHash+validMembers+pubKeyHash+vvecHash
     162             :     CBLSSignature sig; // single member sig of quorumHash+validMembers+pubKeyHash+vvecHash
     163             : 
     164             : public:
     165        1848 :     CDKGPrematureCommitment() {}
     166             :     explicit CDKGPrematureCommitment(const Consensus::LLMQParams& params);
     167             : 
     168         535 :     int CountValidMembers() const
     169             :     {
     170         535 :         return (int)std::count(validMembers.begin(), validMembers.end(), true);
     171             :     }
     172             : 
     173             : public:
     174             : 
     175         798 :     SERIALIZE_METHODS(CDKGPrematureCommitment, obj)
     176             :     {
     177         479 :         READWRITE(obj.llmqType);
     178         479 :         READWRITE(obj.quorumHash);
     179         479 :         READWRITE(obj.proTxHash);
     180         479 :         READWRITE(DYNBITSET(obj.validMembers));
     181         479 :         READWRITE(obj.quorumPublicKey);
     182         479 :         READWRITE(obj.quorumVvecHash);
     183         479 :         READWRITE(obj.quorumSig);
     184         479 :         READWRITE(obj.sig);
     185         479 :     }
     186             : 
     187         360 :     uint256 GetSignHash() const
     188             :     {
     189         360 :         return utils::BuildCommitmentHash((Consensus::LLMQType)llmqType, quorumHash, validMembers, quorumPublicKey, quorumVvecHash);
     190             :     }
     191             : };
     192             : 
     193             : class CDKGMember
     194             : {
     195             : public:
     196             :     CDKGMember(CDeterministicMNCPtr _dmn, size_t _idx);
     197             : 
     198             :     CDeterministicMNCPtr dmn;
     199             :     size_t idx;
     200             :     CBLSId id;
     201             : 
     202             :     std::set<uint256> contributions;
     203             :     std::set<uint256> complaints;
     204             :     std::set<uint256> justifications;
     205             :     std::set<uint256> prematureCommitments;
     206             : 
     207             :     std::set<uint256> badMemberVotes;
     208             :     std::set<uint256> complaintsFromOthers;
     209             : 
     210             :     bool bad{false};
     211             :     bool weComplain{false};
     212             :     bool someoneComplain{false};
     213             : };
     214             : 
     215             : /**
     216             :  * The DKG session is a single instance of the DKG process. It is owned and called by CDKGSessionHandler, which passes
     217             :  * received DKG messages to the session. The session is not persistent and will loose it's state (the whole object is
     218             :  * discarded) when it finishes (after the mining phase) or is aborted.
     219             :  *
     220             :  * When incoming contributions are received and the verification vector is valid, it is passed to CDKGSessionManager
     221             :  * which will store it in the evo DB. Secret key contributions which are meant for the local member are also passed
     222             :  * to CDKGSessionManager to store them in the evo DB. If verification of the SK contribution initially fails, it is
     223             :  * not passed to CDKGSessionManager. If the justification phase later gives a valid SK contribution from the same
     224             :  * member, it is then passed to CDKGSessionManager and after this handled the same way.
     225             :  *
     226             :  * The contributions stored by CDKGSessionManager are then later loaded by the quorum instances and used for signing
     227             :  * sessions, but only if the local node is a member of the quorum.
     228             :  */
     229             : class CDKGSession
     230             : {
     231             :     friend class CDKGSessionHandler;
     232             :     friend class CDKGSessionManager;
     233             :     friend class CDKGLogger;
     234             :     template<typename Message> friend class CDKGMessageHandler;
     235             : 
     236             : private:
     237             :     const Consensus::LLMQParams& params;
     238             : 
     239             :     CBLSWorker& blsWorker;
     240             :     CBLSWorkerCache cache;
     241             :     CDKGSessionManager& dkgManager;
     242             : 
     243             :     const CBlockIndex* pindexQuorum;
     244             : 
     245             :     std::vector<std::unique_ptr<CDKGMember>> members;
     246             :     std::map<uint256, size_t> membersMap;
     247             :     std::set<uint256> relayMembers;
     248             :     BLSVerificationVectorPtr vvecContribution;
     249             :     BLSSecretKeyVector skContributions;
     250             : 
     251             :     BLSIdVector memberIds;
     252             :     std::vector<BLSVerificationVectorPtr> receivedVvecs;
     253             :     // these are not necessarily verified yet. Only trust in what was written to the DB
     254             :     BLSSecretKeyVector receivedSkContributions;
     255             : 
     256             :     uint256 myProTxHash;
     257             :     CBLSId myId;
     258             :     size_t myIdx{(size_t)-1};
     259             : 
     260             :     // all indexed by msg hash
     261             :     // we expect to only receive a single vvec and contribution per member, but we must also be able to relay
     262             :     // conflicting messages as otherwise an attacker might be able to broadcast conflicting (valid+invalid) messages
     263             :     // and thus split the quorum. Such members are later removed from the quorum.
     264             :     mutable RecursiveMutex invCs;
     265             :     std::map<uint256, CDKGContribution> contributions;
     266             :     std::map<uint256, CDKGComplaint> complaints;
     267             :     std::map<uint256, CDKGJustification> justifications;
     268             :     std::map<uint256, CDKGPrematureCommitment> prematureCommitments;
     269             : 
     270             :     std::set<uint256> seenMessages;
     271             : 
     272             :     std::vector<size_t> pendingContributionVerifications;
     273             : 
     274             :     // filled by ReceivePrematureCommitment and used by FinalizeCommitments
     275             :     std::set<uint256> validCommitments;
     276             : 
     277             : public:
     278         983 :     CDKGSession(const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker, CDKGSessionManager& _dkgManager) :
     279        1966 :         params(_params), blsWorker(_blsWorker), cache(_blsWorker), dkgManager(_dkgManager) {}
     280             : 
     281             :     bool Init(const CBlockIndex* _pindexQuorum, const std::vector<CDeterministicMNCPtr>& mns, const uint256& _myProTxHash);
     282             : 
     283           0 :     size_t GetMyMemberIndex() const { return myIdx; }
     284             : 
     285             :     /**
     286             :      * The following sets of methods are for the first 4 phases handled in the session. The flow of message calls
     287             :      * is identical for all phases:
     288             :      * 1. Execute local action (e.g. create/send own contributions)
     289             :      * 2. PreVerify incoming messages for this phase. Preverification means that everything from the message is checked
     290             :      *    that does not require too much resources for verification. This specifically excludes all CPU intensive BLS
     291             :      *    operations.
     292             :      * 3. CDKGSessionHandler will collect pre verified messages in batches and perform batched BLS signature verification
     293             :      *    on these.
     294             :      * 4. ReceiveMessage is called for each pre verified message with a valid signature. ReceiveMessage is also
     295             :      *    responsible for further verification of validity (e.g. validate vvecs and SK contributions).
     296             :      */
     297             : 
     298             :     // Phase 1: contribution
     299             :     void Contribute(CDKGPendingMessages& pendingMessages);
     300             :     void SendContributions(CDKGPendingMessages& pendingMessages);
     301             :     bool PreVerifyMessage(const CDKGContribution& qc, bool& retBan) const;
     302             :     void ReceiveMessage(const uint256& hash, const CDKGContribution& qc, bool& retBan);
     303             :     void VerifyPendingContributions();
     304             : 
     305             :     // Phase 2: complaint
     306             :     void VerifyAndComplain(CDKGPendingMessages& pendingMessages);
     307             :     void VerifyConnectionAndMinProtoVersions();
     308             :     void SendComplaint(CDKGPendingMessages& pendingMessages);
     309             :     bool PreVerifyMessage(const CDKGComplaint& qc, bool& retBan) const;
     310             :     void ReceiveMessage(const uint256& hash, const CDKGComplaint& qc, bool& retBan);
     311             : 
     312             :     // Phase 3: justification
     313             :     void VerifyAndJustify(CDKGPendingMessages& pendingMessages);
     314             :     void SendJustification(CDKGPendingMessages& pendingMessages, const std::set<uint256>& forMembers);
     315             :     bool PreVerifyMessage(const CDKGJustification& qj, bool& retBan) const;
     316             :     void ReceiveMessage(const uint256& hash, const CDKGJustification& qj, bool& retBan);
     317             : 
     318             :     // Phase 4: commit
     319             :     void VerifyAndCommit(CDKGPendingMessages& pendingMessages);
     320             :     void SendCommitment(CDKGPendingMessages& pendingMessages);
     321             :     bool PreVerifyMessage(const CDKGPrematureCommitment& qc, bool& retBan) const;
     322             :     void ReceiveMessage(const uint256& hash, const CDKGPrematureCommitment& qc, bool& retBan);
     323             : 
     324             :     // Phase 5: aggregate/finalize
     325             :     std::vector<CFinalCommitment> FinalizeCommitments();
     326             : 
     327       10408 :     bool AreWeMember() const { return !myProTxHash.IsNull(); }
     328             :     void MarkBadMember(CDKGMember* member);
     329             : 
     330             :     void RelayInvToParticipants(const CInv& inv) const;
     331             : 
     332             :     CDKGMember* GetMember(const uint256& proTxHash) const;
     333             : 
     334             : private:
     335             :     bool ShouldSimulateError(const std::string& error_type);
     336             : };
     337             : 
     338             : // Return false if error_type is not found
     339             : bool SetSimulatedDKGErrorRate(const std::string& error_type, double rate);
     340             : 
     341             : }
     342             : 
     343             : #endif // PIVX_LLMQ_QUORUMS_DKGSESSION_H

Generated by: LCOV version 1.14