|
21 | 21 | #include <util/thread.h> |
22 | 22 | #include <util/time.h> |
23 | 23 | #include <util/underlying.h> |
| 24 | +#include <validation.h> |
24 | 25 |
|
25 | 26 | #include <cxxtimer.hpp> |
26 | 27 |
|
@@ -179,10 +180,11 @@ void CSigSharesNodeState::RemoveSession(const uint256& signHash) |
179 | 180 |
|
180 | 181 | ////////////////////// |
181 | 182 |
|
182 | | -CSigSharesManager::CSigSharesManager(CConnman& connman, CSigningManager& _sigman, PeerManager& peerman, |
183 | | - const CActiveMasternodeManager& mn_activeman, const CQuorumManager& _qman, |
184 | | - const CSporkManager& sporkman) : |
| 183 | +CSigSharesManager::CSigSharesManager(CConnman& connman, CChainState& chainstate, CSigningManager& _sigman, |
| 184 | + PeerManager& peerman, const CActiveMasternodeManager& mn_activeman, |
| 185 | + const CQuorumManager& _qman, const CSporkManager& sporkman) : |
185 | 186 | m_connman{connman}, |
| 187 | + m_chainstate{chainstate}, |
186 | 188 | sigman{_sigman}, |
187 | 189 | m_peerman{peerman}, |
188 | 190 | m_mn_activeman{mn_activeman}, |
@@ -867,6 +869,86 @@ CDeterministicMNCPtr CSigSharesManager::SelectMemberForRecovery(const CQuorumCPt |
867 | 869 | return v[attempt % v.size()].second; |
868 | 870 | } |
869 | 871 |
|
| 872 | +bool CSigSharesManager::AsyncSignIfMember(Consensus::LLMQType llmqType, CSigningManager& sigman, const uint256& id, |
| 873 | + const uint256& msgHash, const uint256& quorumHash, bool allowReSign, |
| 874 | + bool allowDiffMsgHashSigning) |
| 875 | +{ |
| 876 | + AssertLockNotHeld(cs_pendingSigns); |
| 877 | + |
| 878 | + if (m_mn_activeman.GetProTxHash().IsNull()) return false; |
| 879 | + |
| 880 | + const auto quorum = [&]() { |
| 881 | + if (quorumHash.IsNull()) { |
| 882 | + // This might end up giving different results on different members |
| 883 | + // This might happen when we are on the brink of confirming a new quorum |
| 884 | + // This gives a slight risk of not getting enough shares to recover a signature |
| 885 | + // But at least it shouldn't be possible to get conflicting recovered signatures |
| 886 | + // TODO fix this by re-signing when the next block arrives, but only when that block results in a change of |
| 887 | + // the quorum list and no recovered signature has been created in the mean time |
| 888 | + const auto& llmq_params_opt = Params().GetLLMQ(llmqType); |
| 889 | + assert(llmq_params_opt.has_value()); |
| 890 | + return SelectQuorumForSigning(llmq_params_opt.value(), m_chainstate.m_chain, qman, id); |
| 891 | + } else { |
| 892 | + return qman.GetQuorum(llmqType, quorumHash); |
| 893 | + } |
| 894 | + }(); |
| 895 | + |
| 896 | + if (!quorum) { |
| 897 | + LogPrint(BCLog::LLMQ, "CSigningManager::%s -- failed to select quorum. id=%s, msgHash=%s\n", __func__, |
| 898 | + id.ToString(), msgHash.ToString()); |
| 899 | + return false; |
| 900 | + } |
| 901 | + |
| 902 | + if (!quorum->IsValidMember(m_mn_activeman.GetProTxHash())) { |
| 903 | + return false; |
| 904 | + } |
| 905 | + |
| 906 | + { |
| 907 | + auto& db = sigman.GetDb(); |
| 908 | + bool hasVoted = db.HasVotedOnId(llmqType, id); |
| 909 | + if (hasVoted) { |
| 910 | + uint256 prevMsgHash; |
| 911 | + db.GetVoteForId(llmqType, id, prevMsgHash); |
| 912 | + if (msgHash != prevMsgHash) { |
| 913 | + if (allowDiffMsgHashSigning) { |
| 914 | + LogPrintf("%s -- already voted for id=%s and msgHash=%s. Signing for different " /* Continued */ |
| 915 | + "msgHash=%s\n", |
| 916 | + __func__, id.ToString(), prevMsgHash.ToString(), msgHash.ToString()); |
| 917 | + hasVoted = false; |
| 918 | + } else { |
| 919 | + LogPrintf("%s -- already voted for id=%s and msgHash=%s. Not voting on " /* Continued */ |
| 920 | + "conflicting msgHash=%s\n", |
| 921 | + __func__, id.ToString(), prevMsgHash.ToString(), msgHash.ToString()); |
| 922 | + return false; |
| 923 | + } |
| 924 | + } else if (allowReSign) { |
| 925 | + LogPrint(BCLog::LLMQ, "%s -- already voted for id=%s and msgHash=%s. Resigning!\n", __func__, |
| 926 | + id.ToString(), prevMsgHash.ToString()); |
| 927 | + } else { |
| 928 | + LogPrint(BCLog::LLMQ, "%s -- already voted for id=%s and msgHash=%s. Not voting again.\n", __func__, |
| 929 | + id.ToString(), prevMsgHash.ToString()); |
| 930 | + return false; |
| 931 | + } |
| 932 | + } |
| 933 | + |
| 934 | + if (db.HasRecoveredSigForId(llmqType, id)) { |
| 935 | + // no need to sign it if we already have a recovered sig |
| 936 | + return true; |
| 937 | + } |
| 938 | + if (!hasVoted) { |
| 939 | + db.WriteVoteForId(llmqType, id, msgHash); |
| 940 | + } |
| 941 | + } |
| 942 | + |
| 943 | + if (allowReSign) { |
| 944 | + // make us re-announce all known shares (other nodes might have run into a timeout) |
| 945 | + ForceReAnnouncement(quorum, llmqType, id, msgHash); |
| 946 | + } |
| 947 | + AsyncSign(quorum, id, msgHash); |
| 948 | + |
| 949 | + return true; |
| 950 | +} |
| 951 | + |
870 | 952 | void CSigSharesManager::CollectSigSharesToRequest(std::unordered_map<NodeId, Uint256HashMap<CSigSharesInv>>& sigSharesToRequest) |
871 | 953 | { |
872 | 954 | AssertLockHeld(cs); |
|
0 commit comments