|
| 1 | +// Copyright (c) 2023 The Dash Core developers |
| 2 | +// Distributed under the MIT/X11 software license, see the accompanying |
| 3 | +// file COPYING or http://www.opensource.org/licenses/mit-license.php. |
| 4 | + |
| 5 | +#include <llmq/ehf_signals.h> |
| 6 | +#include <llmq/utils.h> |
| 7 | +#include <llmq/quorums.h> |
| 8 | +#include <llmq/signing_shares.h> |
| 9 | +#include <llmq/commitment.h> |
| 10 | + |
| 11 | + |
| 12 | +#include <evo/mnhftx.h> |
| 13 | +#include <evo/specialtx.h> |
| 14 | + |
| 15 | +#include <index/txindex.h> // g_txindex |
| 16 | + |
| 17 | +#include <primitives/transaction.h> |
| 18 | +#include <spork.h> |
| 19 | +#include <txmempool.h> |
| 20 | +#include <validation.h> |
| 21 | + |
| 22 | +namespace llmq { |
| 23 | + |
| 24 | + |
| 25 | +CEHFSignalsHandler::CEHFSignalsHandler(CChainState& chainstate, CConnman& connman, |
| 26 | + CSigningManager& sigman, CSigSharesManager& shareman, |
| 27 | + const CSporkManager& sporkman, const CQuorumManager& qman, CTxMemPool& mempool) : |
| 28 | + chainstate(chainstate), |
| 29 | + connman(connman), |
| 30 | + sigman(sigman), |
| 31 | + shareman(shareman), |
| 32 | + sporkman(sporkman), |
| 33 | + qman(qman), |
| 34 | + mempool(mempool) |
| 35 | +{ |
| 36 | + sigman.RegisterRecoveredSigsListener(this); |
| 37 | +} |
| 38 | + |
| 39 | + |
| 40 | +CEHFSignalsHandler::~CEHFSignalsHandler() |
| 41 | +{ |
| 42 | + sigman.UnregisterRecoveredSigsListener(this); |
| 43 | +} |
| 44 | + |
| 45 | +void CEHFSignalsHandler::UpdatedBlockTip(const CBlockIndex* const pindexNew) |
| 46 | +{ |
| 47 | + if (!fMasternodeMode || !llmq::utils::IsV20Active(pindexNew) || !sporkman.IsSporkActive(SPORK_24_EHF)) { |
| 48 | + return; |
| 49 | + } |
| 50 | + |
| 51 | + // TODO: should do this for all not-yet-signied bits |
| 52 | + trySignEHFSignal(Params().GetConsensus().vDeployments[Consensus::DEPLOYMENT_MN_RR].bit, pindexNew); |
| 53 | +} |
| 54 | + |
| 55 | +void CEHFSignalsHandler::trySignEHFSignal(int bit, const CBlockIndex* const pindex) |
| 56 | +{ |
| 57 | + MNHFTxPayload mnhfPayload; |
| 58 | + mnhfPayload.signal.versionBit = bit; |
| 59 | + const uint256 requestId = mnhfPayload.GetRequestId(); |
| 60 | + |
| 61 | + LogPrintf("CEHFSignalsHandler::trySignEHFSignal: bit=%d at height=%d id=%s\n", bit, pindex->nHeight, requestId.ToString()); |
| 62 | + |
| 63 | + const Consensus::LLMQType& llmqType = Params().GetConsensus().llmqTypeMnhf; |
| 64 | + const auto& llmq_params_opt = llmq::GetLLMQParams(llmqType); |
| 65 | + if (!llmq_params_opt.has_value()) { |
| 66 | + return; |
| 67 | + } |
| 68 | + if (sigman.HasRecoveredSigForId(llmqType, requestId)) { |
| 69 | + LOCK(cs); |
| 70 | + ids.insert(requestId); |
| 71 | + |
| 72 | + // no need to sign same message one more time |
| 73 | + return; |
| 74 | + } |
| 75 | + |
| 76 | + const auto quorum = sigman.SelectQuorumForSigning(llmq_params_opt.value(), qman, requestId); |
| 77 | + if (!quorum) { |
| 78 | + LogPrintf("CEHFSignalsHandler::trySignEHFSignal no quorum for id=%s\n", requestId.ToString()); |
| 79 | + return; |
| 80 | + } |
| 81 | + |
| 82 | + mnhfPayload.signal.quorumHash = quorum->qc->quorumHash; |
| 83 | + const uint256 msgHash = mnhfPayload.PrepareTx().GetHash(); |
| 84 | + |
| 85 | + { |
| 86 | + LOCK(cs); |
| 87 | + ids.insert(requestId); |
| 88 | + } |
| 89 | + sigman.AsyncSignIfMember(llmqType, shareman, requestId, msgHash); |
| 90 | +} |
| 91 | + |
| 92 | +void CEHFSignalsHandler::HandleNewRecoveredSig(const CRecoveredSig& recoveredSig) |
| 93 | +{ |
| 94 | + if (g_txindex) { |
| 95 | + g_txindex->BlockUntilSyncedToCurrentChain(); |
| 96 | + } |
| 97 | + |
| 98 | + if (WITH_LOCK(cs, return ids.find(recoveredSig.getId()) == ids.end())) { |
| 99 | + // Do nothing, it's not for this handler |
| 100 | + return; |
| 101 | + } |
| 102 | + |
| 103 | + MNHFTxPayload mnhfPayload; |
| 104 | + // TODO: should do this for all not-yet-signied bits |
| 105 | + mnhfPayload.signal.versionBit = Params().GetConsensus().vDeployments[Consensus::DEPLOYMENT_MN_RR].bit; |
| 106 | + |
| 107 | + const uint256 expectedId = mnhfPayload.GetRequestId(); |
| 108 | + LogPrintf("CEHFSignalsHandler::HandleNewRecoveredSig expecting ID=%s received=%s\n", expectedId.ToString(), recoveredSig.getId().ToString()); |
| 109 | + if (recoveredSig.getId() != mnhfPayload.GetRequestId()) { |
| 110 | + // there's nothing interesting for CEHFSignalsHandler |
| 111 | + LogPrintf("CEHFSignalsHandler::HandleNewRecoveredSig id is known but it's not MN_RR, expected: %s\n", mnhfPayload.GetRequestId().ToString()); |
| 112 | + return; |
| 113 | + } |
| 114 | + |
| 115 | + mnhfPayload.signal.quorumHash = recoveredSig.getQuorumHash(); |
| 116 | + mnhfPayload.signal.sig = recoveredSig.sig.Get(); |
| 117 | + |
| 118 | + CMutableTransaction tx = mnhfPayload.PrepareTx(); |
| 119 | + |
| 120 | + { |
| 121 | + CTransactionRef tx_to_sent = MakeTransactionRef(std::move(tx)); |
| 122 | + LogPrintf("CEHFSignalsHandler::HandleNewRecoveredSig Special EHF TX is created hash=%s\n", tx_to_sent->GetHash().ToString()); |
| 123 | + LOCK(cs_main); |
| 124 | + TxValidationState state; |
| 125 | + if (AcceptToMemoryPool(chainstate, mempool, state, tx_to_sent, /* bypass_limits=*/ false, /* nAbsurdFee=*/ 0)) { |
| 126 | + connman.RelayTransaction(*tx_to_sent); |
| 127 | + } else { |
| 128 | + LogPrintf("CEHFSignalsHandler::HandleNewRecoveredSig -- AcceptToMemoryPool failed: %s\n", state.ToString()); |
| 129 | + } |
| 130 | + } |
| 131 | +} |
| 132 | +} // namespace llmq |
0 commit comments