Merge pull request #4805 from PastaPastaPasta/v18.x-bc-pr2

[18.x] V18.x backport pr2
This commit is contained in:
UdjinM6 2022-04-26 20:32:53 +03:00 committed by GitHub
commit ce0aa5336d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 10019 additions and 4620 deletions

View File

@ -209,7 +209,7 @@ public:
/**
* Execute a callback on all masternodes in the mnList. This will pass a reference
* of each masternode to the callback function. This should be prefered over ForEachMNShared.
* of each masternode to the callback function. This should be preferred over ForEachMNShared.
* @param onlyValid Run on all masternodes, or only "valid" (not banned) masternodes
* @param cb callback to execute
*/

View File

@ -262,7 +262,7 @@ static constexpr std::array<LLMQParams, 10> available_llmqs = {
.dkgPhaseBlocks = 2,
.dkgMiningWindowStart = 10, // dkgPhaseBlocks * 5 = after finalization
.dkgMiningWindowEnd = 18,
.dkgBadVotesThreshold = 40,
.dkgBadVotesThreshold = 48,
.signingActiveQuorumCount = 32,
.keepOldConnections = 33,

View File

@ -65,9 +65,9 @@ std::vector<CDeterministicMNCPtr> CLLMQUtils::GetAllQuorumMembers(Consensus::LLM
}
/*
* Quorums created with rotation are now created in a different way. All signingActiveQuorumCount are created during the period of dkgInterval.
* But they are not created exactly in the same block, they are spreaded overtime: one quorum in each block until all signingActiveQuorumCount are created.
* But they are not created exactly in the same block, they are spread overtime: one quorum in each block until all signingActiveQuorumCount are created.
* The new concept of quorumIndex is introduced in order to identify them.
* In every dkgInterval blocks (also called CycleQuorumBaseBlock), the spreaded quorum creation starts like this:
* In every dkgInterval blocks (also called CycleQuorumBaseBlock), the spread quorum creation starts like this:
* For quorumIndex = 0 : signingActiveQuorumCount
* Quorum Q with quorumIndex is created at height CycleQuorumBaseBlock + quorumIndex
*/
@ -351,69 +351,77 @@ void CLLMQUtils::BuildQuorumSnapshot(const Consensus::LLMQParams& llmqParams, co
std::vector<std::vector<CDeterministicMNCPtr>> CLLMQUtils::GetQuorumQuarterMembersBySnapshot(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pQuorumBaseBlockIndex, const llmq::CQuorumSnapshot& snapshot, int nHeight)
{
auto numQuorums = static_cast<size_t>(llmqParams.signingActiveQuorumCount);
auto quorumSize = static_cast<size_t>(llmqParams.size);
std::vector<CDeterministicMNCPtr> sortedCombinedMns;
{
const CBlockIndex* pWorkBlockIndex = pQuorumBaseBlockIndex->GetAncestor(pQuorumBaseBlockIndex->nHeight - 8);
const auto modifier = ::SerializeHash(std::make_pair(llmqParams.type, pWorkBlockIndex->GetBlockHash()));
const auto [MnsUsedAtH, MnsNotUsedAtH] = CLLMQUtils::GetMNUsageBySnapshot(llmqParams.type, pQuorumBaseBlockIndex, snapshot, nHeight);
// the list begins with all the unused MNs
auto sortedMnsNotUsedAtH = MnsNotUsedAtH.CalculateQuorum(MnsNotUsedAtH.GetAllMNsCount(), modifier);
sortedCombinedMns = std::move(sortedMnsNotUsedAtH);
// Now add the already used MNs to the end of the list
auto sortedMnsUsedAtH = MnsUsedAtH.CalculateQuorum(MnsUsedAtH.GetAllMNsCount(), modifier);
std::move(sortedMnsUsedAtH.begin(), sortedMnsUsedAtH.end(), std::back_inserter(sortedCombinedMns));
}
auto numQuorums = size_t(llmqParams.signingActiveQuorumCount);
auto quorumSize = size_t(llmqParams.size);
auto quarterSize = quorumSize / 4;
std::vector<std::vector<CDeterministicMNCPtr>> quarterQuorumMembers(numQuorums);
const CBlockIndex* pWorkBlockIndex = pQuorumBaseBlockIndex->GetAncestor(pQuorumBaseBlockIndex->nHeight - 8);
auto modifier = ::SerializeHash(std::make_pair(llmqParams.type, pWorkBlockIndex->GetBlockHash()));
if (sortedCombinedMns.empty()) return quarterQuorumMembers;
auto [MnsUsedAtH, MnsNotUsedAtH] = CLLMQUtils::GetMNUsageBySnapshot(llmqParams.type, pQuorumBaseBlockIndex, snapshot, nHeight);
auto sortedMnsUsedAtH = MnsUsedAtH.CalculateQuorum(MnsUsedAtH.GetAllMNsCount(), modifier);
auto sortedMnsNotUsedAtH = MnsNotUsedAtH.CalculateQuorum(MnsNotUsedAtH.GetAllMNsCount(), modifier);
auto sortedCombinedMns = std::move(sortedMnsNotUsedAtH);
for (auto& m : sortedMnsUsedAtH) {
sortedCombinedMns.push_back(std::move(m));
}
//Mode 0: No skipping
if (snapshot.mnSkipListMode == SnapshotSkipMode::MODE_NO_SKIPPING) {
auto itm = sortedCombinedMns.begin();
for (auto i = 0; i < llmqParams.signingActiveQuorumCount; ++i) {
while (quarterQuorumMembers[i].size() < quarterSize) {
quarterQuorumMembers[i].push_back(*itm);
itm++;
if (itm == sortedCombinedMns.end())
itm = sortedCombinedMns.begin();
switch (snapshot.mnSkipListMode) {
case SnapshotSkipMode::MODE_NO_SKIPPING:
{
auto itm = sortedCombinedMns.begin();
for (auto i = 0; i < llmqParams.signingActiveQuorumCount; ++i) {
while (quarterQuorumMembers[i].size() < quarterSize) {
quarterQuorumMembers[i].push_back(*itm);
itm++;
if (itm == sortedCombinedMns.end()) {
itm = sortedCombinedMns.begin();
}
}
}
return quarterQuorumMembers;
}
}
//Mode 1: List holds entries to be skipped
else if (snapshot.mnSkipListMode == SnapshotSkipMode::MODE_SKIPPING_ENTRIES) {
size_t first_entry_index = {};
std::vector<int> processesdSkipList;
for (const auto& s : snapshot.mnSkipList) {
if (first_entry_index == 0) {
first_entry_index = s;
processesdSkipList.push_back(s);
} else
processesdSkipList.push_back(first_entry_index + s);
}
auto idx = 0;
auto itsk = processesdSkipList.begin();
for (auto i = 0; i < llmqParams.signingActiveQuorumCount; ++i) {
while (quarterQuorumMembers[i].size() < quarterSize) {
if (itsk != processesdSkipList.end() && idx == *itsk)
itsk++;
else
quarterQuorumMembers[i].push_back(sortedCombinedMns[idx]);
idx++;
if (idx == sortedCombinedMns.size())
idx = 0;
case SnapshotSkipMode::MODE_SKIPPING_ENTRIES: // List holds entries to be skipped
{
size_t first_entry_index{0};
std::vector<int> processesdSkipList;
for (const auto& s : snapshot.mnSkipList) {
if (first_entry_index == 0) {
first_entry_index = s;
processesdSkipList.push_back(s);
} else {
processesdSkipList.push_back(first_entry_index + s);
}
}
}
}
//Mode 2: List holds entries to be kept
else if (snapshot.mnSkipListMode == SnapshotSkipMode::MODE_NO_SKIPPING_ENTRIES) {
//TODO Mode 2 will be written. Not used now
}
//Mode 3: Every node was skipped. Returning empty quarterQuorumMembers
return quarterQuorumMembers;
auto idx = 0;
auto itsk = processesdSkipList.begin();
for (auto i = 0; i < llmqParams.signingActiveQuorumCount; ++i) {
while (quarterQuorumMembers[i].size() < quarterSize) {
if (itsk != processesdSkipList.end() && idx == *itsk) {
itsk++;
} else {
quarterQuorumMembers[i].push_back(sortedCombinedMns[idx]);
}
idx++;
if (idx == sortedCombinedMns.size()) {
idx = 0;
}
}
}
return quarterQuorumMembers;
}
case SnapshotSkipMode::MODE_NO_SKIPPING_ENTRIES: // List holds entries to be kept
case SnapshotSkipMode::MODE_ALL_SKIPPED: // Every node was skipped. Returning empty quarterQuorumMembers
default:
return quarterQuorumMembers;
}
}
std::pair<CDeterministicMNList, CDeterministicMNList> CLLMQUtils::GetMNUsageBySnapshot(Consensus::LLMQType llmqType, const CBlockIndex* pQuorumBaseBlockIndex, const llmq::CQuorumSnapshot& snapshot, int nHeight)
@ -579,6 +587,12 @@ std::set<uint256> CLLMQUtils::GetQuorumRelayMembers(const Consensus::LLMQParams&
std::set<uint256> result;
auto calcOutbound = [&](size_t i, const uint256& proTxHash) {
if (mns.size() == 1) {
// No outbound connections are needed when there is one MN only.
// Also note that trying to calculate results via the algorithm below
// would result in an endless loop.
return std::set<uint256>();
}
// Relay to nodes at indexes (i+2^k)%n, where
// k: 0..max(1, floor(log2(n-1))-1)
// n: size of the quorum/ring

View File

@ -9,21 +9,23 @@
#define UNUSED
#endif
static const char UNUSED *dash_strings[] = {
QT_TRANSLATE_NOOP("dash-core", "Dash Core"),
QT_TRANSLATE_NOOP("dash-core", "The %s developers"),
QT_TRANSLATE_NOOP("dash-core", ""
"%s corrupt. Try using the wallet tool dash-wallet to salvage or restoring a "
"backup."),
QT_TRANSLATE_NOOP("dash-core", ""
"%s file contains all private keys from this wallet. Do not share it with "
"anyone!"),
QT_TRANSLATE_NOOP("dash-core", ""
"%s uses exact denominated amounts to send funds, you might simply need to "
"mix some more coins."),
QT_TRANSLATE_NOOP("dash-core", ""
"-masternode option is deprecated and ignored, specifying -"
"masternodeblsprivkey is enough to start this node as a masternode."),
QT_TRANSLATE_NOOP("dash-core", ""
"-maxtxfee is set very high! Fees this large could be paid on a single "
"transaction."),
QT_TRANSLATE_NOOP("dash-core", ""
"Can't generate a change-address key. No keys in the internal keypool and "
"can't generate any keys."),
QT_TRANSLATE_NOOP("dash-core", ""
"Cannot obtain a lock on data directory %s. %s is probably already running."),
QT_TRANSLATE_NOOP("dash-core", ""
"Cannot provide specific connections and have addrman find outgoing "
@ -43,6 +45,9 @@ QT_TRANSLATE_NOOP("dash-core", ""
"restarted wallet in less than 60 seconds. You can continue if you are ok "
"with this."),
QT_TRANSLATE_NOOP("dash-core", ""
"Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -"
"fallbackfee."),
QT_TRANSLATE_NOOP("dash-core", ""
"Found unconfirmed denominated outputs, will wait till they confirm to "
"continue."),
QT_TRANSLATE_NOOP("dash-core", ""
@ -78,6 +83,10 @@ QT_TRANSLATE_NOOP("dash-core", ""
QT_TRANSLATE_NOOP("dash-core", ""
"The transaction amount is too small to send after the fee has been deducted"),
QT_TRANSLATE_NOOP("dash-core", ""
"This error could occur if this wallet was not shutdown cleanly and was last "
"loaded using a build with a newer version of Berkeley DB. If so, please use "
"the software that last loaded this wallet"),
QT_TRANSLATE_NOOP("dash-core", ""
"This is a pre-release test build - use at your own risk - do not use for "
"mining or merchant applications"),
QT_TRANSLATE_NOOP("dash-core", ""
@ -100,27 +109,16 @@ QT_TRANSLATE_NOOP("dash-core", ""
"Unable to replay blocks. You will need to rebuild the database using -"
"reindex-chainstate."),
QT_TRANSLATE_NOOP("dash-core", ""
"Unsupported argument -socks found. Setting SOCKS version isn't possible "
"anymore, only SOCKS5 proxies are supported."),
QT_TRANSLATE_NOOP("dash-core", ""
"Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/"
"or -whitelistforcerelay."),
QT_TRANSLATE_NOOP("dash-core", ""
"WARNING! Failed to replenish keypool, please unlock your wallet to do so."),
QT_TRANSLATE_NOOP("dash-core", ""
"Wallet is locked, can't replenish keypool! Automatic backups and mixing are "
"disabled, please unlock your wallet to replenish keypool."),
QT_TRANSLATE_NOOP("dash-core", ""
"Warning: Private keys detected in wallet {%s} with disabled private keys"),
QT_TRANSLATE_NOOP("dash-core", ""
"Warning: The network does not appear to fully agree! Some miners appear to "
"be experiencing issues."),
QT_TRANSLATE_NOOP("dash-core", ""
"Warning: Unknown block versions being mined! It's possible unknown rules are "
"in effect"),
QT_TRANSLATE_NOOP("dash-core", ""
"Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; "
"if your balance or transactions are incorrect you should restore from a "
"backup."),
QT_TRANSLATE_NOOP("dash-core", ""
"Warning: We do not appear to fully agree with our peers! You may need to "
"upgrade, or other nodes may need to upgrade."),
QT_TRANSLATE_NOOP("dash-core", ""
@ -130,17 +128,17 @@ QT_TRANSLATE_NOOP("dash-core", ""
"mode. This will redownload the entire blockchain"),
QT_TRANSLATE_NOOP("dash-core", "%d of last 100 blocks have unexpected version"),
QT_TRANSLATE_NOOP("dash-core", "%s can't be lower than %s"),
QT_TRANSLATE_NOOP("dash-core", "%s corrupt, salvage failed"),
QT_TRANSLATE_NOOP("dash-core", "%s failed"),
QT_TRANSLATE_NOOP("dash-core", "%s is idle."),
QT_TRANSLATE_NOOP("dash-core", "%s is not a valid backup folder!"),
QT_TRANSLATE_NOOP("dash-core", "%s is only allowed with a single wallet file"),
QT_TRANSLATE_NOOP("dash-core", "%s is set very high!"),
QT_TRANSLATE_NOOP("dash-core", "%s request incomplete: %s"),
QT_TRANSLATE_NOOP("dash-core", "%s request incomplete:"),
QT_TRANSLATE_NOOP("dash-core", "-devnet can only be specified once"),
QT_TRANSLATE_NOOP("dash-core", "-litemode is deprecated."),
QT_TRANSLATE_NOOP("dash-core", "-maxmempool must be at least %d MB"),
QT_TRANSLATE_NOOP("dash-core", "-port must be specified when -devnet and -listen are specified"),
QT_TRANSLATE_NOOP("dash-core", "-rpcport must be specified when -devnet and -server are specified"),
QT_TRANSLATE_NOOP("dash-core", "A fatal internal error occurred, see debug.log for details"),
QT_TRANSLATE_NOOP("dash-core", "Already have that input."),
QT_TRANSLATE_NOOP("dash-core", "Automatic backups disabled"),
QT_TRANSLATE_NOOP("dash-core", "Can't find random Masternode."),
@ -148,11 +146,16 @@ QT_TRANSLATE_NOOP("dash-core", "Can't mix while sync in progress."),
QT_TRANSLATE_NOOP("dash-core", "Can't mix: no compatible inputs found!"),
QT_TRANSLATE_NOOP("dash-core", "Cannot downgrade wallet"),
QT_TRANSLATE_NOOP("dash-core", "Cannot resolve -%s address: '%s'"),
QT_TRANSLATE_NOOP("dash-core", "Cannot set -peerblockfilters without -blockfilterindex."),
QT_TRANSLATE_NOOP("dash-core", "Cannot write to data directory '%s'; check permissions."),
QT_TRANSLATE_NOOP("dash-core", "Change index out of range"),
QT_TRANSLATE_NOOP("dash-core", "Collateral not valid."),
QT_TRANSLATE_NOOP("dash-core", "Config setting for %s only applied on %s network when in [%s] section."),
QT_TRANSLATE_NOOP("dash-core", "Copyright (C)"),
QT_TRANSLATE_NOOP("dash-core", "Corrupted block database detected"),
QT_TRANSLATE_NOOP("dash-core", "Could not find asmap file %s"),
QT_TRANSLATE_NOOP("dash-core", "Could not parse asmap file %s"),
QT_TRANSLATE_NOOP("dash-core", "Disk space is too low!"),
QT_TRANSLATE_NOOP("dash-core", "Do you want to rebuild the block database now?"),
QT_TRANSLATE_NOOP("dash-core", "Done loading"),
QT_TRANSLATE_NOOP("dash-core", "ERROR! Failed to create automatic backup"),
@ -161,6 +164,7 @@ QT_TRANSLATE_NOOP("dash-core", "Entry exceeds maximum size."),
QT_TRANSLATE_NOOP("dash-core", "Error initializing block database"),
QT_TRANSLATE_NOOP("dash-core", "Error initializing wallet database environment %s!"),
QT_TRANSLATE_NOOP("dash-core", "Error loading %s"),
QT_TRANSLATE_NOOP("dash-core", "Error loading %s: Private keys can only be disabled during creation"),
QT_TRANSLATE_NOOP("dash-core", "Error loading %s: Wallet corrupted"),
QT_TRANSLATE_NOOP("dash-core", "Error loading %s: Wallet requires newer version of %s"),
QT_TRANSLATE_NOOP("dash-core", "Error loading %s: You can't disable HD on an already existing HD wallet"),
@ -170,25 +174,24 @@ QT_TRANSLATE_NOOP("dash-core", "Error opening block database"),
QT_TRANSLATE_NOOP("dash-core", "Error reading from database, shutting down."),
QT_TRANSLATE_NOOP("dash-core", "Error upgrading chainstate database"),
QT_TRANSLATE_NOOP("dash-core", "Error upgrading evo database"),
QT_TRANSLATE_NOOP("dash-core", "Error"),
QT_TRANSLATE_NOOP("dash-core", "Error: A fatal internal error occurred, see debug.log for details"),
QT_TRANSLATE_NOOP("dash-core", "Error: Disk space is low!"),
QT_TRANSLATE_NOOP("dash-core", "Error: Disk space is low for %s"),
QT_TRANSLATE_NOOP("dash-core", "Error: failed to add socket to epollfd (epoll_ctl returned error %s)"),
QT_TRANSLATE_NOOP("dash-core", "Error: failed to add socket to kqueuefd (kevent returned error %s)"),
QT_TRANSLATE_NOOP("dash-core", "Exceeded max tries."),
QT_TRANSLATE_NOOP("dash-core", "Failed to clear fulfilled requests cache at"),
QT_TRANSLATE_NOOP("dash-core", "Failed to clear governance cache at"),
QT_TRANSLATE_NOOP("dash-core", "Failed to clear masternode cache at"),
QT_TRANSLATE_NOOP("dash-core", "Failed to clear fulfilled requests cache at %s"),
QT_TRANSLATE_NOOP("dash-core", "Failed to clear governance cache at %s"),
QT_TRANSLATE_NOOP("dash-core", "Failed to clear masternode cache at %s"),
QT_TRANSLATE_NOOP("dash-core", "Failed to commit EvoDB"),
QT_TRANSLATE_NOOP("dash-core", "Failed to create backup %s!"),
QT_TRANSLATE_NOOP("dash-core", "Failed to create backup, error: %s"),
QT_TRANSLATE_NOOP("dash-core", "Failed to delete backup, error: %s"),
QT_TRANSLATE_NOOP("dash-core", "Failed to find mixing queue to join"),
QT_TRANSLATE_NOOP("dash-core", "Failed to listen on any port. Use -listen=0 if you want this."),
QT_TRANSLATE_NOOP("dash-core", "Failed to load fulfilled requests cache from"),
QT_TRANSLATE_NOOP("dash-core", "Failed to load governance cache from"),
QT_TRANSLATE_NOOP("dash-core", "Failed to load masternode cache from"),
QT_TRANSLATE_NOOP("dash-core", "Failed to load sporks cache from"),
QT_TRANSLATE_NOOP("dash-core", "Failed to load fulfilled requests cache from %s"),
QT_TRANSLATE_NOOP("dash-core", "Failed to load governance cache from %s"),
QT_TRANSLATE_NOOP("dash-core", "Failed to load masternode cache from %s"),
QT_TRANSLATE_NOOP("dash-core", "Failed to load sporks cache from %s"),
QT_TRANSLATE_NOOP("dash-core", "Failed to rescan the wallet during initialization"),
QT_TRANSLATE_NOOP("dash-core", "Failed to start a new mixing queue"),
QT_TRANSLATE_NOOP("dash-core", "Found enough users, signing ( waiting %s )"),
@ -198,13 +201,13 @@ QT_TRANSLATE_NOOP("dash-core", "Incompatible mode."),
QT_TRANSLATE_NOOP("dash-core", "Incompatible version."),
QT_TRANSLATE_NOOP("dash-core", "Incorrect -rescan mode, falling back to default value"),
QT_TRANSLATE_NOOP("dash-core", "Incorrect or no genesis block found. Wrong datadir for network?"),
QT_TRANSLATE_NOOP("dash-core", "Information"),
QT_TRANSLATE_NOOP("dash-core", "Initialization sanity check failed. %s is shutting down."),
QT_TRANSLATE_NOOP("dash-core", "Input is not valid."),
QT_TRANSLATE_NOOP("dash-core", "Inputs vs outputs size mismatch."),
QT_TRANSLATE_NOOP("dash-core", "Insufficient funds."),
QT_TRANSLATE_NOOP("dash-core", "Invalid -onion address or hostname: '%s'"),
QT_TRANSLATE_NOOP("dash-core", "Invalid -proxy address or hostname: '%s'"),
QT_TRANSLATE_NOOP("dash-core", "Invalid P2P permission: '%s'"),
QT_TRANSLATE_NOOP("dash-core", "Invalid amount for -%s=<amount>: '%s'"),
QT_TRANSLATE_NOOP("dash-core", "Invalid amount for -discardfee=<amount>: '%s'"),
QT_TRANSLATE_NOOP("dash-core", "Invalid amount for -fallbackfee=<amount>: '%s'"),
@ -214,8 +217,6 @@ QT_TRANSLATE_NOOP("dash-core", "Invalid minimum number of spork signers specifie
QT_TRANSLATE_NOOP("dash-core", "Invalid netmask specified in -whitelist: '%s'"),
QT_TRANSLATE_NOOP("dash-core", "Invalid script detected."),
QT_TRANSLATE_NOOP("dash-core", "Invalid spork address specified with -sporkaddr"),
QT_TRANSLATE_NOOP("dash-core", "It has been replaced by -disablegovernance."),
QT_TRANSLATE_NOOP("dash-core", "Its replacement -disablegovernance has been forced instead."),
QT_TRANSLATE_NOOP("dash-core", "Keypool ran out, please call keypoolrefill first"),
QT_TRANSLATE_NOOP("dash-core", "Last queue was created too recently."),
QT_TRANSLATE_NOOP("dash-core", "Last successful action was too recent."),
@ -243,12 +244,14 @@ QT_TRANSLATE_NOOP("dash-core", "Not enough file descriptors available."),
QT_TRANSLATE_NOOP("dash-core", "Not enough funds to mix."),
QT_TRANSLATE_NOOP("dash-core", "Not in the Masternode list."),
QT_TRANSLATE_NOOP("dash-core", "Prune cannot be configured with a negative value."),
QT_TRANSLATE_NOOP("dash-core", "Prune mode is incompatible with -blockfilterindex."),
QT_TRANSLATE_NOOP("dash-core", "Prune mode is incompatible with -disablegovernance=false."),
QT_TRANSLATE_NOOP("dash-core", "Prune mode is incompatible with -txindex."),
QT_TRANSLATE_NOOP("dash-core", "Pruning blockstore..."),
QT_TRANSLATE_NOOP("dash-core", "Reducing -maxconnections from %d to %d, because of system limitations."),
QT_TRANSLATE_NOOP("dash-core", "Replaying blocks..."),
QT_TRANSLATE_NOOP("dash-core", "Rescanning..."),
QT_TRANSLATE_NOOP("dash-core", "Section [%s] is not recognized."),
QT_TRANSLATE_NOOP("dash-core", "Session not complete!"),
QT_TRANSLATE_NOOP("dash-core", "Session timed out."),
QT_TRANSLATE_NOOP("dash-core", "Signing transaction failed"),
@ -262,6 +265,7 @@ QT_TRANSLATE_NOOP("dash-core", "Synchronization finished"),
QT_TRANSLATE_NOOP("dash-core", "Synchronizing blockchain..."),
QT_TRANSLATE_NOOP("dash-core", "Synchronizing governance objects..."),
QT_TRANSLATE_NOOP("dash-core", "The source code is available from %s."),
QT_TRANSLATE_NOOP("dash-core", "The specified config file %s does not exist\n"),
QT_TRANSLATE_NOOP("dash-core", "The transaction amount is too small to pay the fee"),
QT_TRANSLATE_NOOP("dash-core", "The wallet will avoid paying less than the minimum relay fee."),
QT_TRANSLATE_NOOP("dash-core", "This is expected because you are running a pruned node."),
@ -275,33 +279,29 @@ QT_TRANSLATE_NOOP("dash-core", "Transaction fees are too high."),
QT_TRANSLATE_NOOP("dash-core", "Transaction has too long of a mempool chain"),
QT_TRANSLATE_NOOP("dash-core", "Transaction must have at least one recipient"),
QT_TRANSLATE_NOOP("dash-core", "Transaction not valid."),
QT_TRANSLATE_NOOP("dash-core", "Transaction too large for fee policy"),
QT_TRANSLATE_NOOP("dash-core", "Transaction too large"),
QT_TRANSLATE_NOOP("dash-core", "Trying to connect..."),
QT_TRANSLATE_NOOP("dash-core", "Unable to bind to %s on this computer (bind returned error %s)"),
QT_TRANSLATE_NOOP("dash-core", "Unable to bind to %s on this computer. %s is probably already running."),
QT_TRANSLATE_NOOP("dash-core", "Unable to create the PID file '%s': %s"),
QT_TRANSLATE_NOOP("dash-core", "Unable to generate initial keys"),
QT_TRANSLATE_NOOP("dash-core", "Unable to locate enough mixed funds for this transaction."),
QT_TRANSLATE_NOOP("dash-core", "Unable to locate enough non-denominated funds for this transaction."),
QT_TRANSLATE_NOOP("dash-core", "Unable to sign spork message, wrong key?"),
QT_TRANSLATE_NOOP("dash-core", "Unable to start HTTP server. See debug log for details."),
QT_TRANSLATE_NOOP("dash-core", "Unknown -blockfilterindex value %s."),
QT_TRANSLATE_NOOP("dash-core", "Unknown network specified in -onlynet: '%s'"),
QT_TRANSLATE_NOOP("dash-core", "Unknown response."),
QT_TRANSLATE_NOOP("dash-core", "Unknown state: id = %u"),
QT_TRANSLATE_NOOP("dash-core", "Unsupported argument -benchmark ignored, use -debug=bench."),
QT_TRANSLATE_NOOP("dash-core", "Unsupported argument -debugnet ignored, use -debug=net."),
QT_TRANSLATE_NOOP("dash-core", "Unsupported argument -tor found, use -onion."),
QT_TRANSLATE_NOOP("dash-core", "Unsupported logging category %s=%s."),
QT_TRANSLATE_NOOP("dash-core", "Upgrading UTXO database"),
QT_TRANSLATE_NOOP("dash-core", "Upgrading txindex database"),
QT_TRANSLATE_NOOP("dash-core", "User Agent comment (%s) contains unsafe characters."),
QT_TRANSLATE_NOOP("dash-core", "Verifying blocks..."),
QT_TRANSLATE_NOOP("dash-core", "Verifying wallet(s)..."),
QT_TRANSLATE_NOOP("dash-core", "Very low number of keys left: %d"),
QT_TRANSLATE_NOOP("dash-core", "Wallet %s resides outside wallet directory %s"),
QT_TRANSLATE_NOOP("dash-core", "Wallet is locked."),
QT_TRANSLATE_NOOP("dash-core", "Wallet needed to be rewritten: restart %s to complete"),
QT_TRANSLATE_NOOP("dash-core", "Warning"),
QT_TRANSLATE_NOOP("dash-core", "Warning: %s is deprecated, please use %s instead"),
QT_TRANSLATE_NOOP("dash-core", "Warning: can't use %s and %s together, will prefer %s"),
QT_TRANSLATE_NOOP("dash-core", "Warning: incorrect parameter %s, path must exist! Using default path."),
QT_TRANSLATE_NOOP("dash-core", "Warning: unknown new rules activated (versionbit %i)"),
@ -312,7 +312,6 @@ QT_TRANSLATE_NOOP("dash-core", "You can not disable governance validation on a m
QT_TRANSLATE_NOOP("dash-core", "You can not start a masternode with wallet enabled."),
QT_TRANSLATE_NOOP("dash-core", "You need to rebuild the database using -reindex to change -addressindex"),
QT_TRANSLATE_NOOP("dash-core", "You need to rebuild the database using -reindex to change -spentindex"),
QT_TRANSLATE_NOOP("dash-core", "You need to rebuild the database using -reindex to change -txindex"),
QT_TRANSLATE_NOOP("dash-core", "Your entries added successfully."),
QT_TRANSLATE_NOOP("dash-core", "Zapping all transactions from wallet..."),
QT_TRANSLATE_NOOP("dash-core", "no mixing available."),

View File

@ -61,7 +61,7 @@
<item>
<widget class="QLineEdit" name="filterLineEdit">
<property name="toolTip">
<string>Filter propsal list</string>
<string>Filter proposal list</string>
</property>
</widget>
</item>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -153,14 +153,20 @@ void WalletView::setClientModel(ClientModel *_clientModel)
{
this->clientModel = _clientModel;
overviewPage->setClientModel(_clientModel);
sendCoinsPage->setClientModel(_clientModel);
coinJoinCoinsPage->setClientModel(_clientModel);
if (overviewPage != nullptr) {
overviewPage->setClientModel(_clientModel);
}
if (sendCoinsPage != nullptr) {
sendCoinsPage->setClientModel(_clientModel);
}
if (coinJoinCoinsPage != nullptr) {
coinJoinCoinsPage->setClientModel(_clientModel);
}
QSettings settings;
if (settings.value("fShowMasternodesTab").toBool()) {
if (settings.value("fShowMasternodesTab").toBool() && masternodeListPage != nullptr) {
masternodeListPage->setClientModel(_clientModel);
}
if (settings.value("fShowGovernanceTab").toBool()) {
if (settings.value("fShowGovernanceTab").toBool() && governanceListPage != nullptr) {
governanceListPage->setClientModel(_clientModel);
}
}

View File

@ -647,26 +647,27 @@ static UniValue quorum_getdata(const JSONRPCRequest& request)
});
}
static void quorum_getrotationinfo_help()
static void quorum_rotationinfo_help()
{
throw std::runtime_error(
RPCHelpMan{
"quorum rotationinfo",
"Get quorum rotation information\n",
{{"blockRequestHash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The blockHash of the request."},
{"baseBlockHashesNb", RPCArg::Type::NUM, RPCArg::Optional::NO,
"Number of baseBlockHashes"},
{"extraShare", RPCArg::Type::BOOL, RPCArg::Optional::NO, "Extra share"}},
{
{"blockRequestHash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The blockHash of the request"},
{"extraShare", RPCArg::Type::BOOL, /* default */ "false", "Extra share"},
{"baseBlockHash...", RPCArg::Type::STR_HEX, /* default*/ "", "baseBlockHashes"},
},
RPCResults{},
RPCExamples{""},
}
.ToString());
.ToString());
}
static UniValue quorum_getrotationdata(const JSONRPCRequest& request)
static UniValue quorum_rotationinfo(const JSONRPCRequest& request)
{
if (request.fHelp || (request.params.size() < 2)) {
quorum_getrotationinfo_help();
quorum_rotationinfo_help();
}
llmq::CGetQuorumRotationInfo cmd;
@ -674,15 +675,12 @@ static UniValue quorum_getrotationdata(const JSONRPCRequest& request)
std::string strError;
cmd.blockRequestHash = ParseHashV(request.params[1], "blockRequestHash");
size_t baseBlockHashesNb = static_cast<uint32_t>(ParseInt32V(request.params[2], "baseBlockHashesNb"));
cmd.extraShare = ParseBoolV(request.params[3], "extraShare");
cmd.extraShare = request.params[2].isNull() ? false : ParseBoolV(request.params[2], "extraShare");
/*if (request.params.size() - 2 != cmd.baseBlockHashesNb) {
quorum_getrotationinfo_help();
}*/
for (auto i = 0; i < baseBlockHashesNb; i++) {
cmd.baseBlockHashes.push_back(ParseHashV(request.params[3 + i], "quorumHash"));
size_t idx = 3;
while (!request.params[idx].isNull()) {
cmd.baseBlockHashes.emplace_back(ParseHashV(request.params[idx], "baseBlockHash"));
++idx;
}
LOCK(cs_main);
if (!BuildQuorumRotationInfo(cmd, quorumRotationInfoRet, strError)) {
@ -753,7 +751,7 @@ static UniValue _quorum(const JSONRPCRequest& request)
} else if (command == "getdata") {
return quorum_getdata(request);
} else if (command == "rotationinfo") {
return quorum_getrotationdata(request);
return quorum_rotationinfo(request);
} else {
quorum_help();
}

View File

@ -128,7 +128,7 @@ void DoCheck(const std::string& prv, const std::string& pub, int flags, const st
// When the descriptor is hardened, evaluate with access to the private keys inside.
const FlatSigningProvider& key_provider = (flags & HARDENED) ? keys_priv : keys_pub;
// Evaluate the descriptor selected by `t` in poisition `i`.
// Evaluate the descriptor selected by `t` in position `i`.
FlatSigningProvider script_provider, script_provider_cached;
std::vector<CScript> spks, spks_cached;
std::vector<unsigned char> cache;

View File

@ -51,8 +51,8 @@ class TestP2PConn(P2PInterface):
class LLMQ_IS_CL_Conflicts(DashTestFramework):
def set_test_params(self):
self.set_dash_test_params(4, 3, fast_dip3_enforcement=True)
#disable_mocktime()
self.set_dash_test_params(5, 4, fast_dip3_enforcement=True)
self.set_dash_llmq_test_params(4, 4)
def run_test(self):
self.activate_dip8()
@ -72,6 +72,14 @@ class LLMQ_IS_CL_Conflicts(DashTestFramework):
self.test_chainlock_overrides_islock(True, False)
self.test_chainlock_overrides_islock(True, True)
self.test_chainlock_overrides_islock_overrides_nonchainlock(False)
self.activate_dip0024()
self.log.info("Activated DIP0024 at height:" + str(self.nodes[0].getblockcount()))
self.test_chainlock_overrides_islock_overrides_nonchainlock(False)
# At this point, we need to move forward 3 cycles (3 x 24 blocks) so the first 3 quarters can be created (without DKG sessions)
self.move_to_next_cycle()
self.move_to_next_cycle()
self.move_to_next_cycle()
self.mine_cycle_quorum()
self.test_chainlock_overrides_islock_overrides_nonchainlock(True)
def test_chainlock_overrides_islock(self, test_block_conflict, mine_confllicting=False):
@ -320,7 +328,7 @@ class LLMQ_IS_CL_Conflicts(DashTestFramework):
coinbase.calc_sha256()
block = create_block(int(tip_hash, 16), coinbase, ntime=bt['curtime'])
block = create_block(int(tip_hash, 16), coinbase, ntime=bt['curtime'], version=bt['version'])
block.vtx += vtx
# Add quorum commitments from template

View File

@ -6,7 +6,7 @@ import time
from test_framework.messages import CTransaction, FromHex, hash256, ser_compact_size, ser_string
from test_framework.test_framework import DashTestFramework
from test_framework.util import wait_until, connect_nodes, sync_blocks
from test_framework.util import wait_until, connect_nodes
'''
feature_llmq_is_migration.py
@ -91,7 +91,7 @@ class LLMQISMigrationTest(DashTestFramework):
self.move_to_next_cycle()
self.log.info("Cycle H+2C height:" + str(self.nodes[0].getblockcount()))
(quorum_info_0_0, quorum_info_0_1) = self.mine_cycle_quorum("llmq_test_dip0024", 103)
(quorum_info_0_0, quorum_info_0_1) = self.mine_cycle_quorum()
q_list = self.nodes[0].quorum("list")
self.log.info(q_list)
@ -118,20 +118,5 @@ class LLMQISMigrationTest(DashTestFramework):
assert not n.quorum("hasrecsig", 104, request_id2, txid2)
def move_to_next_cycle(self):
cycle_length = 24
mninfos_online = self.mninfo.copy()
nodes = [self.nodes[0]] + [mn.node for mn in mninfos_online]
cur_block = self.nodes[0].getblockcount()
# move forward to next DKG
skip_count = cycle_length - (cur_block % cycle_length)
if skip_count != 0:
self.bump_mocktime(1, nodes=nodes)
self.nodes[0].generate(skip_count)
sync_blocks(nodes)
time.sleep(1)
self.log.info('Moved from block %d to %d' % (cur_block, self.nodes[0].getblockcount()))
if __name__ == '__main__':
LLMQISMigrationTest().main()

View File

@ -9,7 +9,6 @@ feature_llmq_rotation.py
Checks LLMQs Quorum Rotation
'''
import time
from test_framework.test_framework import DashTestFramework
from test_framework.util import (
assert_equal,
@ -128,21 +127,6 @@ class LLMQQuorumRotationTest(DashTestFramework):
wait_until(lambda: self.nodes[0].getbestblockhash() == new_quorum_blockhash, sleep=1)
assert_equal(self.nodes[0].quorum("list", llmq_type), new_quorum_list)
def move_to_next_cycle(self):
cycle_length = 24
mninfos_online = self.mninfo.copy()
nodes = [self.nodes[0]] + [mn.node for mn in mninfos_online]
cur_block = self.nodes[0].getblockcount()
# move forward to next DKG
skip_count = cycle_length - (cur_block % cycle_length)
if skip_count != 0:
self.bump_mocktime(1, nodes=nodes)
self.nodes[0].generate(skip_count)
sync_blocks(nodes)
time.sleep(1)
self.log.info('Moved from block %d to %d' % (cur_block, self.nodes[0].getblockcount()))
if __name__ == '__main__':
LLMQQuorumRotationTest().main()

View File

@ -28,6 +28,7 @@ from test_framework.messages import (
msg_clsig,
msg_inv,
msg_isdlock,
msg_islock,
msg_tx,
ser_string,
uint256_from_str,
@ -52,24 +53,39 @@ class ZMQPublisher(Enum):
raw_recovered_sig = "rawrecoveredsig"
class ZMQSubscriber:
def __init__(self, socket, topic):
self.socket = socket
self.topic = topic
import zmq
self.socket.setsockopt(zmq.SUBSCRIBE, self.topic)
def receive(self, flags=0):
topic, body, seq = self.socket.recv_multipart(flags)
# Topic should match the subscriber topic.
assert_equal(topic, self.topic)
return io.BytesIO(body)
class TestP2PConn(P2PInterface):
def __init__(self):
super().__init__()
self.islocks = {}
self.txes = {}
def send_islock(self, islock):
def send_islock(self, islock, deterministic):
hash = uint256_from_str(hash256(islock.serialize()))
self.islocks[hash] = islock
inv = msg_inv([CInv(30, hash)])
inv = msg_inv([CInv(31 if deterministic else 30, hash)])
self.send_message(inv)
def send_tx(self, tx):
def send_tx(self, tx, deterministic):
hash = uint256_from_str(hash256(tx.serialize()))
self.txes[hash] = tx
inv = msg_inv([CInv(30, hash)])
inv = msg_inv([CInv(31 if deterministic else 30, hash)])
self.send_message(inv)
def on_getdata(self, message):
@ -89,7 +105,10 @@ class DashZMQTest (DashTestFramework):
node0_extra_args.append("-whitelist=127.0.0.1")
node0_extra_args.append("-watchquorums") # have to watch quorums to receive recsigs and trigger zmq
self.set_dash_test_params(4, 3, fast_dip3_enforcement=True, extra_args=[node0_extra_args, [], [], []])
extra_args = [[]] * 5
extra_args[0] = node0_extra_args
self.set_dash_test_params(5, 4, fast_dip3_enforcement=True, extra_args=extra_args)
self.set_dash_llmq_test_params(4, 4)
def skip_test_if_missing_module(self):
self.skip_if_no_py3_zmq()
@ -97,16 +116,15 @@ class DashZMQTest (DashTestFramework):
self.skip_if_no_wallet()
def run_test(self):
self.subscribers = {}
# Check that dashd has been built with ZMQ enabled.
config = configparser.ConfigParser()
config.read_file(open(self.options.configfile))
import zmq
try:
# Setup the ZMQ subscriber socket
# Setup the ZMQ subscriber context
self.zmq_context = zmq.Context()
self.socket = self.zmq_context.socket(zmq.SUB)
self.socket.connect(self.address)
# Initialize the network
self.activate_dip8()
self.nodes[0].spork("SPORK_17_QUORUM_DKG_ENABLED", 0)
@ -122,30 +140,41 @@ class DashZMQTest (DashTestFramework):
# Test all dash related ZMQ publisher
self.test_recovered_signature_publishers()
self.test_chainlock_publishers()
self.test_instantsend_publishers()
self.test_governance_publishers()
self.test_getzmqnotifications()
self.test_instantsend_publishers(False)
self.activate_dip0024()
self.wait_for_chainlocked_block_all_nodes(self.nodes[0].getbestblockhash())
self.log.info("Activated DIP0024 at height:" + str(self.nodes[0].getblockcount()))
self.test_instantsend_publishers(False)
# At this point, we need to move forward 3 cycles (3 x 24 blocks) so the first 3 quarters can be created (without DKG sessions)
self.move_to_next_cycle()
self.test_instantsend_publishers(False)
self.move_to_next_cycle()
self.test_instantsend_publishers(False)
self.move_to_next_cycle()
self.test_instantsend_publishers(False)
self.mine_cycle_quorum()
self.test_instantsend_publishers(True)
finally:
# Destroy the ZMQ context.
self.log.debug("Destroying ZMQ context")
self.zmq_context.destroy(linger=None)
def subscribe(self, publishers):
import zmq
# Setup the ZMQ subscriber socket
socket = self.zmq_context.socket(zmq.SUB)
socket.set(zmq.RCVTIMEO, 60000)
socket.connect(self.address)
# Subscribe to a list of ZMQPublishers
for pub in publishers:
self.socket.subscribe(pub.value)
self.subscribers[pub] = ZMQSubscriber(socket, pub.value.encode())
def unsubscribe(self, publishers):
# Unsubscribe from a list of ZMQPublishers
for pub in publishers:
self.socket.unsubscribe(pub.value)
def receive(self, publisher, flags=0):
# Receive a ZMQ message and validate it's sent from the correct ZMQPublisher
topic, body, seq = self.socket.recv_multipart(flags)
# Topic should match the publisher value
assert_equal(topic.decode(), publisher.value)
return io.BytesIO(body)
del self.subscribers[pub]
def test_recovered_signature_publishers(self):
@ -153,11 +182,11 @@ class DashZMQTest (DashTestFramework):
# Make sure the recovered sig exists by RPC
rpc_recovered_sig = self.get_recovered_sig(request_id, msg_hash)
# Validate hashrecoveredsig
zmq_recovered_sig_hash = self.receive(ZMQPublisher.hash_recovered_sig).read(32).hex()
zmq_recovered_sig_hash = self.subscribers[ZMQPublisher.hash_recovered_sig].receive().read(32).hex()
assert_equal(zmq_recovered_sig_hash, msg_hash)
# Validate rawrecoveredsig
zmq_recovered_sig_raw = CRecoveredSig()
zmq_recovered_sig_raw.deserialize(self.receive(ZMQPublisher.raw_recovered_sig))
zmq_recovered_sig_raw.deserialize(self.subscribers[ZMQPublisher.raw_recovered_sig].receive())
assert_equal(zmq_recovered_sig_raw.llmqType, rpc_recovered_sig['llmqType'])
assert_equal(uint256_to_string(zmq_recovered_sig_raw.quorumHash), rpc_recovered_sig['quorumHash'])
assert_equal(uint256_to_string(zmq_recovered_sig_raw.id), rpc_recovered_sig['id'])
@ -207,15 +236,15 @@ class DashZMQTest (DashTestFramework):
rpc_chain_lock_hash = rpc_chain_locked_block["hash"]
assert_equal(generated_hash, rpc_chain_lock_hash)
# Validate hashchainlock
zmq_chain_lock_hash = self.receive(ZMQPublisher.hash_chain_lock).read(32).hex()
zmq_chain_lock_hash = self.subscribers[ZMQPublisher.hash_chain_lock].receive().read(32).hex()
assert_equal(zmq_chain_lock_hash, rpc_best_chain_lock_hash)
# Validate rawchainlock
zmq_chain_locked_block = CBlock()
zmq_chain_locked_block.deserialize(self.receive(ZMQPublisher.raw_chain_lock))
zmq_chain_locked_block.deserialize(self.subscribers[ZMQPublisher.raw_chain_lock].receive())
assert zmq_chain_locked_block.is_valid()
assert_equal(zmq_chain_locked_block.hash, rpc_chain_lock_hash)
# Validate rawchainlocksig
zmq_chain_lock_sig_stream = self.receive(ZMQPublisher.raw_chain_lock_sig)
zmq_chain_lock_sig_stream = self.subscribers[ZMQPublisher.raw_chain_lock_sig].receive()
zmq_chain_locked_block = CBlock()
zmq_chain_locked_block.deserialize(zmq_chain_lock_sig_stream)
assert zmq_chain_locked_block.is_valid()
@ -228,7 +257,7 @@ class DashZMQTest (DashTestFramework):
# Unsubscribe from ChainLock messages
self.unsubscribe(chain_lock_publishers)
def test_instantsend_publishers(self):
def test_instantsend_publishers(self, deterministic):
import zmq
instantsend_publishers = [
ZMQPublisher.hash_tx_lock,
@ -251,57 +280,57 @@ class DashZMQTest (DashTestFramework):
rpc_raw_tx_1_hash = self.nodes[0].sendrawtransaction(rpc_raw_tx_1['hex'])
self.wait_for_instantlock(rpc_raw_tx_1_hash, self.nodes[0])
# Validate hashtxlock
zmq_tx_lock_hash = self.receive(ZMQPublisher.hash_tx_lock).read(32).hex()
zmq_tx_lock_hash = self.subscribers[ZMQPublisher.hash_tx_lock].receive().read(32).hex()
assert_equal(zmq_tx_lock_hash, rpc_raw_tx_1['txid'])
# Validate rawtxlock
zmq_tx_lock_raw = CTransaction()
zmq_tx_lock_raw.deserialize(self.receive(ZMQPublisher.raw_tx_lock))
zmq_tx_lock_raw.deserialize(self.subscribers[ZMQPublisher.raw_tx_lock].receive())
assert zmq_tx_lock_raw.is_valid()
assert_equal(zmq_tx_lock_raw.hash, rpc_raw_tx_1['txid'])
# Validate rawtxlocksig
zmq_tx_lock_sig_stream = self.receive(ZMQPublisher.raw_tx_lock_sig)
zmq_tx_lock_sig_stream = self.subscribers[ZMQPublisher.raw_tx_lock_sig].receive()
zmq_tx_lock_tx = CTransaction()
zmq_tx_lock_tx.deserialize(zmq_tx_lock_sig_stream)
assert zmq_tx_lock_tx.is_valid()
assert_equal(zmq_tx_lock_tx.hash, rpc_raw_tx_1['txid'])
zmq_tx_lock = msg_isdlock()
zmq_tx_lock = msg_isdlock() if deterministic else msg_islock()
zmq_tx_lock.deserialize(zmq_tx_lock_sig_stream)
assert_equal(uint256_to_string(zmq_tx_lock.txid), rpc_raw_tx_1['txid'])
# Try to send the second transaction. This must throw an RPC error because it conflicts with rpc_raw_tx_1
# which already got the InstantSend lock.
assert_raises_rpc_error(-26, "tx-txlock-conflict", self.nodes[0].sendrawtransaction, rpc_raw_tx_2['hex'])
# Validate hashinstantsenddoublespend
zmq_double_spend_hash2 = self.receive(ZMQPublisher.hash_instantsend_doublespend).read(32).hex()
zmq_double_spend_hash1 = self.receive(ZMQPublisher.hash_instantsend_doublespend).read(32).hex()
zmq_double_spend_hash2 = self.subscribers[ZMQPublisher.hash_instantsend_doublespend].receive().read(32).hex()
zmq_double_spend_hash1 = self.subscribers[ZMQPublisher.hash_instantsend_doublespend].receive().read(32).hex()
assert_equal(zmq_double_spend_hash2, rpc_raw_tx_2['txid'])
assert_equal(zmq_double_spend_hash1, rpc_raw_tx_1['txid'])
# Validate rawinstantsenddoublespend
zmq_double_spend_tx_2 = CTransaction()
zmq_double_spend_tx_2.deserialize(self.receive(ZMQPublisher.raw_instantsend_doublespend))
zmq_double_spend_tx_2.deserialize(self.subscribers[ZMQPublisher.raw_instantsend_doublespend].receive())
assert zmq_double_spend_tx_2.is_valid()
assert_equal(zmq_double_spend_tx_2.hash, rpc_raw_tx_2['txid'])
zmq_double_spend_tx_1 = CTransaction()
zmq_double_spend_tx_1.deserialize(self.receive(ZMQPublisher.raw_instantsend_doublespend))
zmq_double_spend_tx_1.deserialize(self.subscribers[ZMQPublisher.raw_instantsend_doublespend].receive())
assert zmq_double_spend_tx_1.is_valid()
assert_equal(zmq_double_spend_tx_1.hash, rpc_raw_tx_1['txid'])
# No islock notifications when tx is not received yet
self.nodes[0].generate(1)
rpc_raw_tx_3 = self.create_raw_tx(self.nodes[0], self.nodes[0], 1, 1, 100)
islock = self.create_islock(rpc_raw_tx_3['hex'])
self.test_node.send_islock(islock)
islock = self.create_islock(rpc_raw_tx_3['hex'], deterministic)
self.test_node.send_islock(islock, deterministic)
# Validate NO hashtxlock
time.sleep(1)
try:
self.receive(ZMQPublisher.hash_tx_lock, zmq.NOBLOCK)
self.subscribers[ZMQPublisher.hash_tx_lock].receive(zmq.NOBLOCK)
assert False
except zmq.ZMQError:
# this is expected
pass
# Now send the tx itself
self.test_node.send_tx(FromHex(msg_tx(), rpc_raw_tx_3['hex']))
self.test_node.send_tx(FromHex(msg_tx(), rpc_raw_tx_3['hex']), deterministic)
self.wait_for_instantlock(rpc_raw_tx_3['txid'], self.nodes[0])
# Validate hashtxlock
zmq_tx_lock_hash = self.receive(ZMQPublisher.hash_tx_lock).read(32).hex()
zmq_tx_lock_hash = self.subscribers[ZMQPublisher.hash_tx_lock].receive().read(32).hex()
assert_equal(zmq_tx_lock_hash, rpc_raw_tx_3['txid'])
# Drop test node connection
self.nodes[0].disconnect_p2ps()
@ -337,10 +366,11 @@ class DashZMQTest (DashTestFramework):
self.sync_blocks()
rpc_proposal_hash = self.nodes[0].gobject("submit", "0", proposal_rev, proposal_time, proposal_hex, collateral)
# Validate hashgovernanceobject
zmq_governance_object_hash = self.receive(ZMQPublisher.hash_governance_object).read(32).hex()
zmq_governance_object_hash = self.subscribers[ZMQPublisher.hash_governance_object].receive().read(32).hex()
assert_equal(zmq_governance_object_hash, rpc_proposal_hash)
# Validate rawgovernanceobject
zmq_governance_object_raw = CGovernanceObject()
zmq_governance_object_raw.deserialize(self.receive(ZMQPublisher.raw_governance_object))
zmq_governance_object_raw.deserialize(self.subscribers[ZMQPublisher.raw_governance_object].receive())
assert_equal(zmq_governance_object_raw.nHashParent, 0)
assert_equal(zmq_governance_object_raw.nRevision, proposal_rev)
assert_equal(zmq_governance_object_raw.nTime, proposal_time)
@ -365,11 +395,11 @@ class DashZMQTest (DashTestFramework):
self.nodes[0].gobject("vote-many", rpc_proposal_hash, map_vote_signals[1], map_vote_outcomes[1])
rpc_proposal_votes = self.nodes[0].gobject('getcurrentvotes', rpc_proposal_hash)
# Validate hashgovernancevote
zmq_governance_vote_hash = self.receive(ZMQPublisher.hash_governance_vote).read(32).hex()
zmq_governance_vote_hash = self.subscribers[ZMQPublisher.hash_governance_vote].receive().read(32).hex()
assert zmq_governance_vote_hash in rpc_proposal_votes
# Validate rawgovernancevote
zmq_governance_vote_raw = CGovernanceVote()
zmq_governance_vote_raw.deserialize(self.receive(ZMQPublisher.raw_governance_vote))
zmq_governance_vote_raw.deserialize(self.subscribers[ZMQPublisher.raw_governance_vote].receive())
assert_equal(uint256_to_string(zmq_governance_vote_raw.nParentHash), rpc_proposal_hash)
rpc_vote_parts = rpc_proposal_votes[zmq_governance_vote_hash].split(':')
rpc_outpoint_parts = rpc_vote_parts[0].split('-')

View File

@ -82,7 +82,7 @@ class RPCVerifyISLockTest(DashTestFramework):
break
assert selected_hash == oldest_quorum_hash
# Create the ISLOCK, then mine a quorum to move the signing quorum out of the active set
islock = self.create_islock(rawtx, True)
islock = self.create_islock(rawtx, False)
# Mine one block to trigger the "signHeight + dkgInterval" verification for the ISLOCK
self.mine_quorum()
# Verify the ISLOCK for a transaction that is not yet known by the node

View File

@ -1038,13 +1038,14 @@ class DashTestFramework(BitcoinTestFramework):
request_id = hash256(request_id_buf)[::-1].hex()
message_hash = tx.hash
llmq_type = 103 if deterministic else 104
quorum_member = None
for mn in self.mninfo:
res = mn.node.quorum('sign', 104, request_id, message_hash)
res = mn.node.quorum('sign', llmq_type, request_id, message_hash)
if (res and quorum_member is None):
quorum_member = mn
rec_sig = self.get_recovered_sig(request_id, message_hash, node=quorum_member.node, llmq_type=104)
rec_sig = self.get_recovered_sig(request_id, message_hash, node=quorum_member.node, llmq_type=llmq_type)
if deterministic:
block_count = quorum_member.node.getblockcount()
@ -1330,7 +1331,7 @@ class DashTestFramework(BitcoinTestFramework):
return new_quorum
def mine_cycle_quorum(self, llmq_type_name="llmq_test", llmq_type=100, expected_connections=None, expected_members=None, expected_contributions=None, expected_complaints=0, expected_justifications=0, expected_commitments=None, mninfos_online=None, mninfos_valid=None):
def mine_cycle_quorum(self, llmq_type_name="llmq_test_dip0024", llmq_type=103, expected_connections=None, expected_members=None, expected_contributions=None, expected_complaints=0, expected_justifications=0, expected_commitments=None, mninfos_online=None, mninfos_valid=None):
spork21_active = self.nodes[0].spork('show')['SPORK_21_QUORUM_ALL_CONNECTED'] <= 1
spork23_active = self.nodes[0].spork('show')['SPORK_23_QUORUM_POSE'] <= 1
@ -1462,11 +1463,26 @@ class DashTestFramework(BitcoinTestFramework):
best_block_hash = self.nodes[0].getbestblockhash()
block_height = self.nodes[0].getblockcount()
quorum_rotation_info = self.nodes[0].quorum("rotationinfo", best_block_hash, 0, False)
quorum_rotation_info = self.nodes[0].quorum("rotationinfo", best_block_hash)
self.log.info("h("+str(block_height)+"):"+str(quorum_rotation_info))
return (quorum_info_0, quorum_info_1)
def move_to_next_cycle(self):
cycle_length = 24
mninfos_online = self.mninfo.copy()
nodes = [self.nodes[0]] + [mn.node for mn in mninfos_online]
cur_block = self.nodes[0].getblockcount()
# move forward to next DKG
skip_count = cycle_length - (cur_block % cycle_length)
if skip_count != 0:
self.bump_mocktime(1, nodes=nodes)
self.nodes[0].generate(skip_count)
sync_blocks(nodes)
time.sleep(1)
self.log.info('Moved from block %d to %d' % (cur_block, self.nodes[0].getblockcount()))
def get_recovered_sig(self, rec_sig_id, rec_sig_msg_hash, llmq_type=100, node=None):
# Note: recsigs aren't relayed to regular nodes by default,
# make sure to pick a mn as a node to query for recsigs.

View File

@ -640,7 +640,7 @@ class ImportMultiTest(BitcoinTestFramework):
assert_equal(addr2, newaddr2)
# Import a multisig and make sure the keys don't go into the keypool
self.log.info('Imported scripts with pubkeys shoud not have their pubkeys go into the keypool')
self.log.info('Imported scripts with pubkeys should not have their pubkeys go into the keypool')
addr1 = self.nodes[0].getnewaddress()
addr2 = self.nodes[0].getnewaddress()
pub1 = self.nodes[0].getaddressinfo(addr1)['pubkey']

View File

@ -15,6 +15,6 @@ if ! command -v codespell > /dev/null; then
fi
IGNORE_WORDS_FILE=test/lint/lint-spelling.ignore-words.txt
if ! codespell --check-filenames --disable-colors --quiet-level=7 --ignore-words=${IGNORE_WORDS_FILE} $(git ls-files -- ":(exclude)build-aux/m4/" ":(exclude)contrib/seeds/*.txt" ":(exclude)depends/" ":(exclude)doc/release-notes/" ":(exclude)src/crypto/" ":(exclude)src/leveldb/" ":(exclude)src/qt/locale/" ":(exclude)src/qt/*.qrc" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/"); then
if ! codespell --check-filenames --disable-colors --quiet-level=7 --ignore-words=${IGNORE_WORDS_FILE} $(git ls-files -- ":(exclude)build-aux/m4/" ":(exclude)contrib/seeds/*.txt" ":(exclude)depends/" ":(exclude)doc/release-notes/" ":(exclude)src/bip39_english.h" ":(exclude)src/crc32c/" ":(exclude)src/crypto/" ":(exclude)src/ctpl_stl.h" ":(exclude)src/cxxtimer.hpp" ":(exclude)src/leveldb/" ":(exclude)src/qt/locale/" ":(exclude)src/qt/*.qrc" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/"); then
echo "^ Warning: codespell identified likely spelling errors. Any false positives? Add them to the list of ignored words in ${IGNORE_WORDS_FILE}"
fi