Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/governance/governance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1303,3 +1303,8 @@ void CGovernanceManager::RemoveInvalidVotes()
// store current MN list for the next run so that we can determine which keys changed
lastMNListForVotingKeys = curMNList;
}

bool AreSuperblocksEnabled()
{
return gArgs.GetBoolArg("-enablesuperblocks", DEFAULT_ENABLE_SUPERBLOCKS);
}
4 changes: 4 additions & 0 deletions src/governance/governance.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ typedef std::pair<CGovernanceObject, ExpirationInfo> object_info_pair_t;

static const int RATE_BUFFER_SIZE = 5;

static const bool DEFAULT_ENABLE_SUPERBLOCKS = true;

class CRateCheckBuffer
{
private:
Expand Down Expand Up @@ -432,4 +434,6 @@ class CGovernanceManager

};

bool AreSuperblocksEnabled();

#endif // BITCOIN_GOVERNANCE_GOVERNANCE_H
13 changes: 11 additions & 2 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,10 @@
#include <walletinitinterface.h>

#include <evo/deterministicmns.h>
#include <llmq/quorums_init.h>
#include <llmq/quorums_blockprocessor.h>
#include <llmq/quorums_chainlocks.h>
#include <llmq/quorums_init.h>
#include <llmq/quorums_instantsend.h>

#include <stdint.h>
#include <stdio.h>
Expand Down Expand Up @@ -585,7 +587,6 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-debug=<category>", strprintf(_("Output debugging information (default: %u, supplying <category> is optional)"), 0) + ". " +
_("If <category> is not supplied or if <category> = 1, output all debugging information.") + " " + _("<category> can be:") + " " + ListLogCategories() + ".");
strUsage += HelpMessageOpt("-debugexclude=<category>", strprintf(_("Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.")));
strUsage += HelpMessageOpt("-disablegovernance", strprintf(_("Disable governance validation (0-1, default: %u)"), 0));
strUsage += HelpMessageOpt("-help-debug", _("Show all debugging options (usage: --help -help-debug)"));
strUsage += HelpMessageOpt("-logips", strprintf(_("Include IP addresses in debug output (default: %u)"), DEFAULT_LOGIPS));
if (showDebug)
Expand Down Expand Up @@ -615,9 +616,17 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-masternodeblsprivkey=<hex>", _("Set the masternode BLS private key and enable the client to act as a masternode"));
strUsage += HelpMessageOpt("-platform-user=<user>", _("Set the username for the \"platform user\", a restricted user intended to be used by Dash Platform, to the specified username."));

strUsage += HelpMessageGroup(_("ChainLocks options:"));
strUsage += HelpMessageOpt("-enablechainlocks", strprintf(_("Enable use of ChainLocks (default: %u)"), DEFAULT_ENABLE_CHAINLOCKS));

strUsage += HelpMessageGroup(_("InstantSend options:"));
strUsage += HelpMessageOpt("-instantsendnotify=<cmd>", _("Execute command when a wallet InstantSend transaction is successfully locked (%s in cmd is replaced by TxID)"));
strUsage += HelpMessageOpt("-enableinstantsend", strprintf(_("Enable use of InstantSend (default: %u)"), DEFAULT_ENABLE_INSTANTSEND));
strUsage += HelpMessageOpt("-rejectconflictingblocks", strprintf(_("Reject blocks containing txes that conflict with ones locked via InstantSend (default: %u)"), DEFAULT_REJECT_CONFLICTING_BLOCKS));

strUsage += HelpMessageGroup(_("Goverenance options:"));
strUsage += HelpMessageOpt("-enablesuperblocks", strprintf(_("Allow Superblocks to be produced at predefined intervals (default: %u)"), DEFAULT_ENABLE_SUPERBLOCKS));
strUsage += HelpMessageOpt("-disablegovernance", strprintf(_("Disable governance validation (0-1, default: %u)"), 0));

strUsage += HelpMessageGroup(_("Node relay options:"));
if (showDebug) {
Expand Down
21 changes: 13 additions & 8 deletions src/llmq/quorums_chainlocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ CChainLockSig CChainLocksHandler::GetBestChainLock()

void CChainLocksHandler::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman)
{
if (!sporkManager.IsSporkActive(SPORK_19_CHAINLOCKS_ENABLED)) {
if (!AreChainLocksEnabled()) {
return;
}

Expand Down Expand Up @@ -230,8 +230,8 @@ void CChainLocksHandler::CheckActiveState()

LOCK(cs);
bool oldIsEnforced = isEnforced;
isSporkActive = sporkManager.IsSporkActive(SPORK_19_CHAINLOCKS_ENABLED);
isEnforced = (fDIP0008Active && isSporkActive);
isEnabled = AreChainLocksEnabled();
isEnforced = (fDIP0008Active && isEnabled);

if (!oldIsEnforced && isEnforced) {
// ChainLocks got activated just recently, but it's possible that it was already running before, leaving
Expand Down Expand Up @@ -273,7 +273,7 @@ void CChainLocksHandler::TrySignChainTip()
{
LOCK(cs);

if (!isSporkActive) {
if (!isEnabled) {
return;
}

Expand All @@ -300,7 +300,7 @@ void CChainLocksHandler::TrySignChainTip()
// considered safe when it is islocked or at least known since 10 minutes (from mempool or block). These checks are
// performed for the tip (which we try to sign) and the previous 5 blocks. If a ChainLocked block is found on the
// way down, we consider all TXs to be safe.
if (IsInstantSendEnabled() && sporkManager.IsSporkActive(SPORK_3_INSTANTSEND_BLOCK_FILTERING)) {
if (IsInstantSendEnabled() && RejectConflictingBlocks()) {
auto pindexWalk = pindex;
while (pindexWalk) {
if (pindex->nHeight - pindexWalk->nHeight > 5) {
Expand Down Expand Up @@ -459,7 +459,7 @@ CChainLocksHandler::BlockTxs::mapped_type CChainLocksHandler::GetBlockTxs(const

bool CChainLocksHandler::IsTxSafeForMining(const uint256& txid)
{
if (!sporkManager.IsSporkActive(SPORK_3_INSTANTSEND_BLOCK_FILTERING)) {
if (!RejectConflictingBlocks()) {
return true;
}
if (!IsInstantSendEnabled()) {
Expand All @@ -469,7 +469,7 @@ bool CChainLocksHandler::IsTxSafeForMining(const uint256& txid)
int64_t txAge = 0;
{
LOCK(cs);
if (!isSporkActive || !isEnforced) {
if (!isEnabled || !isEnforced) {
return true;
}
auto it = txFirstSeenTime.find(txid);
Expand Down Expand Up @@ -568,7 +568,7 @@ void CChainLocksHandler::HandleNewRecoveredSig(const llmq::CRecoveredSig& recove
{
LOCK(cs);

if (!isSporkActive) {
if (!isEnabled) {
return;
}

Expand Down Expand Up @@ -727,4 +727,9 @@ void CChainLocksHandler::Cleanup()
lastCleanupTime = GetTimeMillis();
}

bool AreChainLocksEnabled()
{
return gArgs.GetBoolArg("-enablechainlocks", DEFAULT_ENABLE_CHAINLOCKS);
}

} // namespace llmq
5 changes: 4 additions & 1 deletion src/llmq/quorums_chainlocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
class CBlockIndex;
class CScheduler;

static const bool DEFAULT_ENABLE_CHAINLOCKS = true;

namespace llmq
{

Expand Down Expand Up @@ -57,7 +59,7 @@ class CChainLocksHandler : public CRecoveredSigsListener
boost::thread* scheduler_thread;
CCriticalSection cs;
bool tryLockChainTipScheduled{false};
bool isSporkActive{false};
bool isEnabled{false};
bool isEnforced{false};

uint256 bestChainLockHash;
Expand Down Expand Up @@ -122,6 +124,7 @@ class CChainLocksHandler : public CRecoveredSigsListener

extern CChainLocksHandler* chainLocksHandler;

bool AreChainLocksEnabled();

} // namespace llmq

Expand Down
9 changes: 7 additions & 2 deletions src/llmq/quorums_instantsend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1142,7 +1142,7 @@ void CInstantSendManager::UpdatedBlockTip(const CBlockIndex* pindexNew)
// TODO remove this after DIP8 has activated
bool fDIP0008Active = VersionBitsState(pindexNew->pprev, Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0008, versionbitscache) == ThresholdState::ACTIVE;

if (sporkManager.IsSporkActive(SPORK_19_CHAINLOCKS_ENABLED) && fDIP0008Active) {
if (AreChainLocksEnabled() && fDIP0008Active) {
// Nothing to do here. We should keep all islocks and let chainlocks handle them.
return;
}
Expand Down Expand Up @@ -1519,7 +1519,12 @@ void CInstantSendManager::WorkThreadMain()

bool IsInstantSendEnabled()
{
return sporkManager.IsSporkActive(SPORK_2_INSTANTSEND_ENABLED);
return gArgs.GetBoolArg("-enableinstantsend", DEFAULT_ENABLE_INSTANTSEND);
}

bool RejectConflictingBlocks()
{
return gArgs.GetBoolArg("-rejectconflictingblocks", DEFAULT_REJECT_CONFLICTING_BLOCKS);
}

} // namespace llmq
4 changes: 4 additions & 0 deletions src/llmq/quorums_instantsend.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
#include <unordered_map>
#include <unordered_set>

static const bool DEFAULT_ENABLE_INSTANTSEND = true;
static const bool DEFAULT_REJECT_CONFLICTING_BLOCKS = true;

namespace llmq
{

Expand Down Expand Up @@ -174,6 +177,7 @@ class CInstantSendManager : public CRecoveredSigsListener
extern CInstantSendManager* quorumInstantSendManager;

bool IsInstantSendEnabled();
bool RejectConflictingBlocks();

} // namespace llmq

Expand Down
18 changes: 8 additions & 10 deletions src/masternode/masternode-payments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,8 @@ bool IsBlockValueValid(const CBlock& block, int nBlockHeight, CAmount blockRewar

// we are synced and possibly on a superblock now

if (!sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED)) {
// should NOT allow superblocks at all, when superblocks are disabled
// revert to block reward limits in this case
if (!AreSuperblocksEnabled()) {
// should NOT allow superblocks at all, revert to block reward limits in this case
LogPrint(BCLog::GOBJECT, "%s -- Superblocks are disabled, no superblocks allowed\n", __func__);
if(!isBlockRewardValueMet) {
strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, superblocks are disabled",
Expand Down Expand Up @@ -177,7 +176,7 @@ bool IsBlockPayeeValid(const CTransaction& txNew, int nBlockHeight, CAmount bloc
// superblocks started
// SEE IF THIS IS A VALID SUPERBLOCK

if(sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED)) {
if(AreSuperblocksEnabled()) {
if(CSuperblockManager::IsSuperblockTriggered(nBlockHeight)) {
if(CSuperblockManager::IsValid(txNew, nBlockHeight, blockReward)) {
LogPrint(BCLog::GOBJECT, "%s -- Valid superblock at height %d: %s", __func__, nBlockHeight, txNew.ToString()); /* Continued */
Expand All @@ -191,7 +190,7 @@ bool IsBlockPayeeValid(const CTransaction& txNew, int nBlockHeight, CAmount bloc
LogPrint(BCLog::GOBJECT, "%s -- No triggered superblock detected at height %d\n", __func__, nBlockHeight);
}
} else {
// should NOT allow superblocks at all, when superblocks are disabled
// should NOT allow superblocks at all
LogPrint(BCLog::GOBJECT, "%s -- Superblocks are disabled, no superblocks allowed\n", __func__);
}

Expand All @@ -207,12 +206,11 @@ bool IsBlockPayeeValid(const CTransaction& txNew, int nBlockHeight, CAmount bloc

void FillBlockPayments(CMutableTransaction& txNew, int nBlockHeight, CAmount blockReward, std::vector<CTxOut>& voutMasternodePaymentsRet, std::vector<CTxOut>& voutSuperblockPaymentsRet)
{
// only create superblocks if spork is enabled AND if superblock is actually triggered
// only create superblocks if they are allowed AND if superblock is actually triggered
// (height should be validated inside)
if(sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED) &&
CSuperblockManager::IsSuperblockTriggered(nBlockHeight)) {
LogPrint(BCLog::GOBJECT, "%s -- triggered superblock creation at height %d\n", __func__, nBlockHeight);
CSuperblockManager::GetSuperblockPayments(nBlockHeight, voutSuperblockPaymentsRet);
if(AreSuperblocksEnabled() && CSuperblockManager::IsSuperblockTriggered(nBlockHeight)) {
LogPrint(BCLog::GOBJECT, "%s -- triggered superblock creation at height %d\n", __func__, nBlockHeight);
CSuperblockManager::GetSuperblockPayments(nBlockHeight, voutSuperblockPaymentsRet);
}

if (!CMasternodePayments::GetMasternodeTxOuts(nBlockHeight, blockReward, voutMasternodePaymentsRet)) {
Expand Down
4 changes: 2 additions & 2 deletions src/rpc/mining.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
mnpayments.GetBlockTxOuts(chainActive.Height() + 1, 0, voutMasternodePayments);

// next bock is a superblock and we need governance info to correctly construct it
if (sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED)
if (AreSuperblocksEnabled()
&& !masternodeSync.IsSynced()
&& CSuperblock::IsValidBlockHeight(chainActive.Height() + 1))
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Dash Core is syncing with network...");
Expand Down Expand Up @@ -704,7 +704,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
}
result.pushKV("superblock", superblockObjArray);
result.pushKV("superblocks_started", pindexPrev->nHeight + 1 > consensusParams.nSuperblockStartBlock);
result.pushKV("superblocks_enabled", sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED));
result.pushKV("superblocks_enabled", AreSuperblocksEnabled());

result.pushKV("coinbase_payload", HexStr(pblock->vtx[0]->vExtraPayload));

Expand Down
4 changes: 0 additions & 4 deletions src/spork.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,7 @@ const std::string CSporkManager::SERIALIZATION_VERSION_STRING = "CSporkManager-V

#define MAKE_SPORK_DEF(name, defaultValue) CSporkDef{name, defaultValue, #name}
std::vector<CSporkDef> sporkDefs = {
MAKE_SPORK_DEF(SPORK_2_INSTANTSEND_ENABLED, 4070908800ULL), // OFF
MAKE_SPORK_DEF(SPORK_3_INSTANTSEND_BLOCK_FILTERING, 4070908800ULL), // OFF
MAKE_SPORK_DEF(SPORK_9_SUPERBLOCKS_ENABLED, 4070908800ULL), // OFF
MAKE_SPORK_DEF(SPORK_17_QUORUM_DKG_ENABLED, 4070908800ULL), // OFF
MAKE_SPORK_DEF(SPORK_19_CHAINLOCKS_ENABLED, 4070908800ULL), // OFF
MAKE_SPORK_DEF(SPORK_21_QUORUM_ALL_CONNECTED, 4070908800ULL), // OFF
MAKE_SPORK_DEF(SPORK_22_PS_MORE_PARTICIPANTS, 4070908800ULL), // OFF
};
Expand Down
4 changes: 0 additions & 4 deletions src/spork.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,7 @@ class CSporkManager;
- This would result in old clients getting confused about which spork is for what
*/
enum SporkId : int32_t {
SPORK_2_INSTANTSEND_ENABLED = 10001,
SPORK_3_INSTANTSEND_BLOCK_FILTERING = 10002,
SPORK_9_SUPERBLOCKS_ENABLED = 10008,
SPORK_17_QUORUM_DKG_ENABLED = 10016,
SPORK_19_CHAINLOCKS_ENABLED = 10018,
SPORK_21_QUORUM_ALL_CONNECTED = 10020,
SPORK_22_PS_MORE_PARTICIPANTS = 10021,

Expand Down
2 changes: 1 addition & 1 deletion src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2313,7 +2313,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl

// DASH : CHECK TRANSACTIONS FOR INSTANTSEND

if (sporkManager.IsSporkActive(SPORK_3_INSTANTSEND_BLOCK_FILTERING)) {
if (llmq::RejectConflictingBlocks()) {
// Require other nodes to comply, send them some data in case they are missing it.
for (const auto& tx : block.vtx) {
// skip txes that have no inputs
Expand Down
5 changes: 3 additions & 2 deletions test/functional/feature_dip4_coinbasemerkleroots.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ def getmnlistdiff(self, baseBlockHash, blockHash):

class LLMQCoinbaseCommitmentsTest(DashTestFramework):
def set_test_params(self):
self.set_dash_test_params(4, 3, fast_dip3_enforcement=True)
self.set_dash_dip8_activation(200)
# Note: Have to disable ChainLocks because they won't let you to invalidate already locked blocks.
# Do this for the whole test to avoid restarting all nodes twice while running it.
self.set_dash_test_params(4, 3, [["-enablechainlocks=0"]] * 4, fast_dip3_enforcement=True)

def run_test(self):
self.test_node = self.nodes[0].add_p2p_connection(TestP2PConn())
Expand Down
2 changes: 1 addition & 1 deletion test/functional/feature_governance_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def validate_object(prepared, rpc_prepared):

class DashGovernanceTest (DashTestFramework):
def set_test_params(self):
self.set_dash_test_params(2, 1)
self.set_dash_test_params(2, 1, fast_dip3_enforcement=True)

def prepare_object(self, object_type, parent_hash, creation_time, revision, name, amount):
proposal_rev = revision
Expand Down
16 changes: 4 additions & 12 deletions test/functional/feature_llmq_chainlocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
class LLMQChainLocksTest(DashTestFramework):
def set_test_params(self):
self.set_dash_test_params(4, 3, fast_dip3_enforcement=True)
self.set_dash_dip8_activation(10)

def run_test(self):

Expand All @@ -43,9 +42,6 @@ def run_test(self):
for i in range(4):
self.mine_quorum()

self.nodes[0].spork("SPORK_19_CHAINLOCKS_ENABLED", 0)
self.wait_for_sporks_same()

self.log.info("Mine single block, wait for chainlock")
self.nodes[0].generate(1)
self.wait_for_chainlocked_block_all_nodes(self.nodes[0].getbestblockhash())
Expand Down Expand Up @@ -106,11 +102,6 @@ def run_test(self):
self.wait_for_chainlocked_block(self.nodes[0], self.nodes[1].getbestblockhash())
assert(self.nodes[0].getbestblockhash() == self.nodes[1].getbestblockhash())

self.log.info("Enable LLMQ bases InstantSend, which also enables checks for \"safe\" transactions")
self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 0)
self.nodes[0].spork("SPORK_3_INSTANTSEND_BLOCK_FILTERING", 0)
self.wait_for_sporks_same()

self.log.info("Isolate a node and let it create some transactions which won't get IS locked")
isolate_node(self.nodes[0])
txs = []
Expand All @@ -124,17 +115,18 @@ def run_test(self):
assert("confirmations" not in tx)
time.sleep(1)
assert(not self.nodes[0].getblock(self.nodes[0].getbestblockhash())["chainlock"])
self.log.info("Disable LLMQ based InstantSend for a very short time (this never gets propagated to other nodes)")
self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 4070908800)
self.log.info("Restart the node with LLMQ based InstantSend disabled")
self.restart_node(0, self.extra_args[0] + ['-enableinstantsend=0'])
self.log.info("Now the TXs should be included")
self.nodes[0].generate(1)
self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 0)
self.log.info("Assert that TXs got included now")
for txid in txs:
tx = self.nodes[0].getrawtransaction(txid, 1)
assert("confirmations" in tx and tx["confirmations"] > 0)
# Enable network on first node again, which will cause the blocks to propagate and IS locks to happen retroactively
# for the mined TXs, which will then allow the network to create a CLSIG
self.log.info("Restart the node with LLMQ based InstantSend enabled")
self.restart_node(0, self.extra_args[0])
self.log.info("Reenable network on first node and wait for chainlock")
reconnect_isolated_node(self.nodes[0], 1)
self.wait_for_chainlocked_block(self.nodes[0], self.nodes[0].getbestblockhash(), timeout=30)
Expand Down
1 change: 0 additions & 1 deletion test/functional/feature_llmq_dkgerrors.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
class LLMQDKGErrors(DashTestFramework):
def set_test_params(self):
self.set_dash_test_params(4, 3, [["-whitelist=127.0.0.1"]] * 4, fast_dip3_enforcement=True)
self.set_dash_dip8_activation(10)

def run_test(self):

Expand Down
Loading