Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: auto generation EHF and spork+EHF activation for MN_RR #5597

Merged
merged 10 commits into from
Oct 18, 2023
Prev Previous commit
Next Next commit
feat: auto signing EHF signals and submitting TX with that signal to …
…Mempool

This commit adds basic implementation for auto-generation of EHF signals.
This implementation is a basement for various EHF (include MN_RR).

Please, notice that some unit and functional tests are broken after this commit
due to unexpected activation of MN_RR (or in opposited expected non-activation)

Next commit is adding a new Spork SPORK_24_MN_RR_READY and fixes all Unit and
Functional tests accordingly new logic of MN_RR activation
knst committed Oct 17, 2023
commit 2ba09c9a78aa74a1c0aa45c8c1bc2213d8b2243f
14 changes: 8 additions & 6 deletions src/Makefile.am
Original file line number Diff line number Diff line change
@@ -213,22 +213,24 @@ BITCOIN_CORE_H = \
key_io.h \
dbwrapper.h \
limitedmap.h \
llmq/quorums.h \
llmq/blockprocessor.h \
llmq/commitment.h \
llmq/chainlocks.h \
llmq/clsig.h \
llmq/commitment.h \
llmq/context.h \
llmq/debug.h \
llmq/dkgsession.h \
llmq/dkgsessionhandler.h \
llmq/dkgsessionmgr.h \
llmq/dkgsession.h \
llmq/context.h \
llmq/ehf_signals.cpp \
llmq/ehf_signals.h \
llmq/instantsend.h \
llmq/snapshot.h \
llmq/params.h \
llmq/quorums.h \
llmq/signing.h \
llmq/signing_shares.h \
llmq/snapshot.h \
llmq/utils.h \
llmq/params.h \
logging.h \
logging/timer.h \
mapport.h \
22 changes: 13 additions & 9 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
@@ -219,10 +219,11 @@ class CMainParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].bit = 10;
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nStartTime = 19999999999; // TODO: To be determined later
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nWindowSize = 4032;
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdStart = 3226; // 80% of 4032
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdMin = 2420; // 60% of 4032
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nWindowSize = 576;
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdStart = 460; // 80% of 576
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdMin = 346; // 60% of 576
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nFalloffCoeff = 5; // this corresponds to 10 periods
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nMNActivationHeight = 0; // requires EHF activation

// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000008677827656704520eb39"); // 1889000
@@ -420,6 +421,7 @@ class CTestNetParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdStart = 80; // 80% of 100
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdMin = 60; // 60% of 100
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nFalloffCoeff = 5; // this corresponds to 10 periods
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nMNActivationHeight = 0; // requires EHF activation

// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000002d68c8cc1b8e54b"); // 851000
@@ -587,10 +589,11 @@ class CDevNetParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].bit = 10;
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nStartTime = 1661990400; // Sep 1st, 2022
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nWindowSize = 120;
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdStart = 80; // 80% of 100
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdMin = 60; // 60% of 100
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nWindowSize = 1;
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdStart = 1; // 80% of 100
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdMin = 1; // 60% of 100
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nFalloffCoeff = 5; // this corresponds to 10 periods
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nMNActivationHeight = 0; // requires EHF activation

// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000000000000000000000000");
@@ -826,10 +829,11 @@ class CRegTestParams : public CChainParams {
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].bit = 10;
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nStartTime = 0;
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nWindowSize = 1030;
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdStart = 800; // 80% of 1000
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdMin = 600; // 60% of 1000
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nWindowSize = 1;
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdStart = 1; // 100% of 1
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdMin = 1; // 100% of 1
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nFalloffCoeff = 5; // this corresponds to 10 periods
consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nMNActivationHeight = 0; // requires EHF activation

// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("0x00");
2 changes: 2 additions & 0 deletions src/dsnotificationinterface.cpp
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@
#include <llmq/chainlocks.h>
#include <llmq/context.h>
#include <llmq/dkgsessionmgr.h>
#include <llmq/ehf_signals.h>
#include <llmq/instantsend.h>
#include <llmq/quorums.h>

@@ -78,6 +79,7 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con

llmq_ctx->qman->UpdatedBlockTip(pindexNew, fInitialDownload);
llmq_ctx->qdkgsman->UpdatedBlockTip(pindexNew, fInitialDownload);
llmq_ctx->ehfSignalsHandler->UpdatedBlockTip(pindexNew);

if (!fDisableGovernance) govman.UpdatedBlockTip(pindexNew, connman);
}
22 changes: 18 additions & 4 deletions src/evo/mnhftx.cpp
Original file line number Diff line number Diff line change
@@ -19,9 +19,24 @@
#include <string>
#include <vector>

extern const std::string MNEHF_REQUESTID_PREFIX = "mnhf";
static const std::string MNEHF_REQUESTID_PREFIX = "mnhf";
static const std::string DB_SIGNALS = "mnhf_s";

uint256 MNHFTxPayload::GetRequestId() const
{
return ::SerializeHash(std::make_pair(MNEHF_REQUESTID_PREFIX, int64_t{signal.versionBit}));
}

CMutableTransaction MNHFTxPayload::PrepareTx() const
{
CMutableTransaction tx;
tx.nVersion = 3;
tx.nType = SPECIALTX_TYPE;
SetTxPayload(tx, *this);

return tx;
}

CMNHFManager::Signals CMNHFManager::GetSignalsStage(const CBlockIndex* const pindexPrev)
{
Signals signals = GetFromCache(pindexPrev);
@@ -53,7 +68,7 @@ CMNHFManager::Signals CMNHFManager::GetSignalsStage(const CBlockIndex* const pin
return signals;
}

bool MNHFTx::Verify(const uint256& quorumHash, const uint256& msgHash, TxValidationState& state) const
bool MNHFTx::Verify(const uint256& quorumHash, const uint256& requestId, const uint256& msgHash, TxValidationState& state) const
{
if (versionBit >= VERSIONBITS_NUM_BITS) {
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-nbit-out-of-bounds");
@@ -62,7 +77,6 @@ bool MNHFTx::Verify(const uint256& quorumHash, const uint256& msgHash, TxValidat
const Consensus::LLMQType& llmqType = Params().GetConsensus().llmqTypeMnhf;
const auto quorum = llmq::quorumManager->GetQuorum(llmqType, quorumHash);

const uint256 requestId = ::SerializeHash(std::make_pair(MNEHF_REQUESTID_PREFIX, int64_t{versionBit}));
const uint256 signHash = llmq::utils::BuildSignHash(llmqType, quorum->qc->quorumHash, requestId, msgHash);
if (!sig.VerifyInsecure(quorum->qc->quorumPublicKey, signHash)) {
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-invalid");
@@ -104,7 +118,7 @@ bool CheckMNHFTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValida
uint256 msgHash = tx_copy.GetHash();


if (!mnhfTx.signal.Verify(mnhfTx.signal.quorumHash, msgHash, state)) {
if (!mnhfTx.signal.Verify(mnhfTx.signal.quorumHash, mnhfTx.GetRequestId(), msgHash, state)) {
// set up inside Verify
return false;
}
15 changes: 13 additions & 2 deletions src/evo/mnhftx.h
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@ class MNHFTx
CBLSSignature sig{};

MNHFTx() = default;
bool Verify(const uint256& quorumHash, const uint256& msgHash, TxValidationState& state) const;
bool Verify(const uint256& quorumHash, const uint256& requestId, const uint256& msgHash, TxValidationState& state) const;

SERIALIZE_METHODS(MNHFTx, obj)
{
@@ -63,6 +63,17 @@ class MNHFTxPayload
uint8_t nVersion{CURRENT_VERSION};
MNHFTx signal;

public:
/**
* helper function to calculare Request ID used for signing
*/
uint256 GetRequestId() const;

/**
* helper function to prepare special transaction for signing
*/
CMutableTransaction PrepareTx() const;

SERIALIZE_METHODS(MNHFTxPayload, obj)
{
READWRITE(obj.nVersion, obj.signal);
@@ -120,6 +131,7 @@ class CMNHFManager
* This member function is not const because it calls non-const GetFromCache()
*/
Signals GetSignalsStage(const CBlockIndex* const pindexPrev);

private:
void AddToCache(const Signals& signals, const CBlockIndex* const pindex);

@@ -129,7 +141,6 @@ class CMNHFManager
* validate them by
*/
Signals GetFromCache(const CBlockIndex* const pindex);

};

std::optional<uint8_t> extractEHFSignal(const CTransaction& tx);
2 changes: 1 addition & 1 deletion src/init.cpp
Original file line number Diff line number Diff line change
@@ -1938,7 +1938,7 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
llmq::quorumSnapshotManager.reset();
llmq::quorumSnapshotManager.reset(new llmq::CQuorumSnapshotManager(*node.evodb));
node.llmq_ctx.reset();
node.llmq_ctx.reset(new LLMQContext(chainman.ActiveChainstate(), *node.connman, *node.evodb, *::sporkManager, *node.mempool, node.peerman, false, fReset || fReindexChainState));
node.llmq_ctx.reset(new LLMQContext(chainman.ActiveChainstate(), *node.connman, *node.evodb, *::sporkManager, *node.mnhf_manager, *node.mempool, node.peerman, false, fReset || fReindexChainState));

if (fReset) {
pblocktree->WriteReindexing(true);
6 changes: 4 additions & 2 deletions src/llmq/context.cpp
Original file line number Diff line number Diff line change
@@ -12,14 +12,15 @@
#include <llmq/commitment.h>
#include <llmq/debug.h>
#include <llmq/dkgsessionmgr.h>
#include <llmq/ehf_signals.h>
#include <llmq/instantsend.h>
#include <llmq/quorums.h>
#include <llmq/signing.h>
#include <llmq/signing_shares.h>
#include <llmq/utils.h>
#include <masternode/sync.h>

LLMQContext::LLMQContext(CChainState& chainstate, CConnman& connman, CEvoDB& evo_db, CSporkManager& sporkman, CTxMemPool& mempool,
LLMQContext::LLMQContext(CChainState& chainstate, CConnman& connman, CEvoDB& evo_db, CSporkManager& sporkman, CMNHFManager& mnhfman, CTxMemPool& mempool,
const std::unique_ptr<PeerManager>& peerman, bool unit_tests, bool wipe) :
bls_worker{std::make_shared<CBLSWorker>()},
dkg_debugman{std::make_unique<llmq::CDKGDebugManager>()},
@@ -45,7 +46,8 @@ LLMQContext::LLMQContext(CChainState& chainstate, CConnman& connman, CEvoDB& evo
assert(llmq::quorumInstantSendManager == nullptr);
llmq::quorumInstantSendManager = std::make_unique<llmq::CInstantSendManager>(*llmq::chainLocksHandler, chainstate, connman, *llmq::quorumManager, *sigman, *shareman, sporkman, mempool, *::masternodeSync, peerman, unit_tests, wipe);
return llmq::quorumInstantSendManager.get();
}()}
}()},
ehfSignalsHandler{std::make_unique<llmq::CEHFSignalsHandler>(chainstate, connman, *sigman, *shareman, *llmq::quorumManager, mempool, mnhfman)}
{
// NOTE: we use this only to wipe the old db, do NOT use it for anything else
// TODO: remove it in some future version
14 changes: 9 additions & 5 deletions src/llmq/context.h
Original file line number Diff line number Diff line change
@@ -12,25 +12,28 @@ class CChainState;
class CConnman;
class CDBWrapper;
class CEvoDB;
class CTxMemPool;
class CMNHFManager;
class CSporkManager;
class CTxMemPool;
class PeerManager;

namespace llmq {
class CChainLocksHandler;
class CDKGDebugManager;
class CQuorumBlockProcessor;
class CDKGSessionManager;
class CEHFSignalsHandler;
class CInstantSendManager;
class CQuorumBlockProcessor;
class CQuorumManager;
class CSigSharesManager;
class CSigningManager;
class CChainLocksHandler;
class CInstantSendManager;
}

struct LLMQContext {
LLMQContext() = delete;
LLMQContext(const LLMQContext&) = delete;
LLMQContext(CChainState& chainstate, CConnman& connman, CEvoDB& evo_db, CSporkManager& sporkman, CTxMemPool& mempool,
LLMQContext(CChainState& chainstate, CConnman& connman, CEvoDB& evo_db, CSporkManager& sporkman,
CMNHFManager& mnhfman, CTxMemPool& mempool,
const std::unique_ptr<PeerManager>& peerman, bool unit_tests, bool wipe);
~LLMQContext();

@@ -57,6 +60,7 @@ struct LLMQContext {
const std::unique_ptr<llmq::CSigSharesManager> shareman;
llmq::CChainLocksHandler* const clhandler;
llmq::CInstantSendManager* const isman;
const std::unique_ptr<llmq::CEHFSignalsHandler> ehfSignalsHandler;
};

#endif // BITCOIN_LLMQ_CONTEXT_H
Loading
Oops, something went wrong.