From a4e6b8a9930f34fe1f5fc5ec759dacb8a486f9c3 Mon Sep 17 00:00:00 2001 From: pasta Date: Sun, 18 Aug 2024 09:27:49 +0700 Subject: [PATCH 01/14] Merge #6208: fix: persist coinjoin denoms options from gui over restarts 3ec0c8ca0a34cf35df4f4431bc282f0b99618d8a fix: persist coinjoin denoms and sessions options from gui over restarts (pasta) Pull request description: ## Issue being fixed or feature implemented Persist coinjoin denoms over restarts, fixes #5975 ## What was done? Soft set the argument into the daemon from GUI settings ## How Has This Been Tested? follow procedure in 5975 ## Breaking Changes ## Checklist: _Go over all the following points, and put an `x` in all the boxes that apply._ - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ACKs for top commit: knst: utACK 3ec0c8ca0a34cf35df4f4431bc282f0b99618d8a UdjinM6: utACK 3ec0c8ca0a34cf35df4f4431bc282f0b99618d8a Tree-SHA512: b7378460b3990713b755f36de506b94e7d0005f19cf1155f2fc12191ba03f2e16c35049ddbd89f578acd89bc8eae5e432913114e1ff5ef7ab2cc30628aeff3f2 --- src/qt/optionsmodel.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 912e8d5dd8..416a122317 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -224,6 +224,8 @@ void OptionsModel::Init(bool resetSettings) // CoinJoin if (!settings.contains("nCoinJoinSessions")) settings.setValue("nCoinJoinSessions", DEFAULT_COINJOIN_SESSIONS); + if (!gArgs.SoftSetArg("-coinjoinsessions", settings.value("nCoinJoinSessions").toString().toStdString())) + addOverriddenOption("-coinjoinsessions"); if (!settings.contains("nCoinJoinRounds")) settings.setValue("nCoinJoinRounds", DEFAULT_COINJOIN_ROUNDS); @@ -247,9 +249,13 @@ void OptionsModel::Init(bool resetSettings) if (!settings.contains("nCoinJoinDenomsGoal")) settings.setValue("nCoinJoinDenomsGoal", DEFAULT_COINJOIN_DENOMS_GOAL); + if (!gArgs.SoftSetArg("-coinjoindenomsgoal", settings.value("nCoinJoinDenomsGoal").toString().toStdString())) + addOverriddenOption("-coinjoindenomsgoal"); if (!settings.contains("nCoinJoinDenomsHardCap")) settings.setValue("nCoinJoinDenomsHardCap", DEFAULT_COINJOIN_DENOMS_HARDCAP); + if (!gArgs.SoftSetArg("-coinjoindenomshardcap", settings.value("nCoinJoinDenomsHardCap").toString().toStdString())) + addOverriddenOption("-coinjoindenomshardcap"); #endif // Network From 87bebfc2468bdf069532d5178cf50dcc5fa06752 Mon Sep 17 00:00:00 2001 From: pasta Date: Sun, 18 Aug 2024 09:10:33 +0700 Subject: [PATCH 02/14] Merge #6219: fix: correct is_snapshot_cs in VerifyDB bf377d47e59d9adaca42d5b6df3505e5d3b24fc7 fix: correct is_snapshot_cs in VerifyDB (James O'Beirne) Pull request description: ## Issue being fixed or feature implemented Flag `is_snapshot_cs` has been inverted in bitcoin#21584 Discovered during investigation of issue: ``` Verifying last 6 blocks at level 3 2024-08-14T14:51:55Z [0%]...*** Found EvoDB inconsistency, you must reindex to continue ``` So far as code below does: ``` if ((fPruneMode || is_snapshot_cs) && !(pindex->nStatus & BLOCK_HAVE_DATA)) { // If pruning or running under an assumeutxo snapshot, only go // back as far as we have data. LogPrintf("VerifyDB(): block verification stopping at height %d (pruning, no data)\n", pindex->nHeight); break; } ``` In case of missing data in evo db we will get instead of "block verification stopping at height" we may get data inconsistency issue. ## What was done? Inverted condition back (same fix in bitcoin/bitcoin#27596) ## How Has This Been Tested? Unit/functional tests doesn't cover it, but they do no fail after fix. ## Breaking Changes N/A ## Checklist: - [x] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone ACKs for top commit: UdjinM6: utACK bf377d47e59d9adaca42d5b6df3505e5d3b24fc7 PastaPastaPasta: utACK bf377d47e59d9adaca42d5b6df3505e5d3b24fc7 Tree-SHA512: ac21e6db6e23c4c7dc150fb16171aef47c9f42c29466b403bca7d56ed6faa2fccc41df92e1fabec4d6e9fd56991e152dea168593a4550fc3583631a63009c27f --- src/validation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/validation.cpp b/src/validation.cpp index 15be0df400..1509b8499f 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -4678,7 +4678,7 @@ bool CVerifyDB::VerifyDB( int reportDone = 0; LogPrintf("[0%%]..."); /* Continued */ - const bool is_snapshot_cs{!chainstate.m_from_snapshot_blockhash}; + const bool is_snapshot_cs{chainstate.m_from_snapshot_blockhash}; for (pindex = chainstate.m_chain.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) { const int percentageDone = std::max(1, std::min(99, (int)(((double)(chainstate.m_chain.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100)))); From 9bf39a93d3bc200ed4ceadb994e3b84e015df56f Mon Sep 17 00:00:00 2001 From: pasta Date: Thu, 22 Aug 2024 08:19:46 -0500 Subject: [PATCH 03/14] Merge #6222: fix: adjust payee predictions after mn_rr activation, add tests 715bc1af66b0584a2a9aa8cced9181ba94c6ca37 test: check `masternode winners` before and after mn_rr (UdjinM6) 9d47cd222657d52d41d5b18e5449e4986c77e3e2 fix: adjust payee predictions after mn_rr activation (UdjinM6) Pull request description: ## Issue being fixed or feature implemented Payment predictions in GUI are wrong when mn_rr is active, `masternode winners` RPC is affected by the same issue too. Actual payments aren't affected. ## What was done? Adjust calculations, add tests for `masternode winners`. ## How Has This Been Tested? Run dash-qt on testnet, check "Next Payment" on "Masternode" tab. Run tests. ## Breaking Changes n/a ## Checklist: - [x] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [ ] I have assigned this pull request to a milestone ACKs for top commit: PastaPastaPasta: utACK 715bc1a Tree-SHA512: 293c77974bcb50c6f9c51449d7bb12f89ad8db5871cad3a6083fe1951fe77e0deba8de7688b2f600fabe977bdc7390a66a984a6a076be19183c23742e00e27bf --- src/evo/deterministicmns.cpp | 7 ++--- test/functional/feature_llmq_evo.py | 42 ++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index b35dab60a9..b75c1403c2 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -215,7 +215,9 @@ std::vector CDeterministicMNList::GetProjectedMNPayees(gsl if (nCount < 0 ) { return {}; } - const auto weighted_count = GetValidWeightedMNsCount(); + const bool isMNRewardReallocation = DeploymentActiveAfter(pindexPrev, Params().GetConsensus(), + Consensus::DEPLOYMENT_MN_RR); + const auto weighted_count = isMNRewardReallocation ? GetValidMNsCount() : GetValidWeightedMNsCount(); nCount = std::min(nCount, int(weighted_count)); std::vector result; @@ -223,7 +225,6 @@ std::vector CDeterministicMNList::GetProjectedMNPayees(gsl int remaining_evo_payments{0}; CDeterministicMNCPtr evo_to_be_skipped{nullptr}; - const bool isMNRewardReallocation{DeploymentActiveAfter(pindexPrev, Params().GetConsensus(), Consensus::DEPLOYMENT_MN_RR)}; if (!isMNRewardReallocation) { ForEachMNShared(true, [&](const CDeterministicMNCPtr& dmn) { if (dmn->pdmnState->nLastPaidHeight == nHeight) { @@ -242,7 +243,7 @@ std::vector CDeterministicMNList::GetProjectedMNPayees(gsl ForEachMNShared(true, [&](const CDeterministicMNCPtr& dmn) { if (dmn == evo_to_be_skipped) return; - for ([[maybe_unused]] auto _ : irange::range(GetMnType(dmn->nType).voting_weight)) { + for ([[maybe_unused]] auto _ : irange::range(isMNRewardReallocation ? 1 : GetMnType(dmn->nType).voting_weight)) { result.emplace_back(dmn); } }); diff --git a/test/functional/feature_llmq_evo.py b/test/functional/feature_llmq_evo.py index 6543b9fa6a..c847ab8268 100755 --- a/test/functional/feature_llmq_evo.py +++ b/test/functional/feature_llmq_evo.py @@ -17,7 +17,7 @@ from test_framework.messages import CBlock, CBlockHeader, CCbTx, CMerkleBlock, f QuorumId, ser_uint256 from test_framework.test_framework import DashTestFramework from test_framework.util import ( - assert_equal, p2p_port + assert_equal, assert_greater_than_or_equal, p2p_port ) @@ -46,7 +46,7 @@ class TestP2PConn(P2PInterface): class LLMQEvoNodesTest(DashTestFramework): def set_test_params(self): - self.set_dash_test_params(5, 4, fast_dip3_enforcement=True, evo_count=7) + self.set_dash_test_params(5, 4, fast_dip3_enforcement=True, evo_count=5) self.set_dash_llmq_test_params(4, 4) def run_test(self): @@ -92,7 +92,7 @@ class LLMQEvoNodesTest(DashTestFramework): self.mine_cycle_quorum(llmq_type_name='llmq_test_dip0024', llmq_type=103) evo_protxhash_list = list() - for i in range(5): + for i in range(self.evo_count): evo_info = self.dynamically_add_masternode(evo=True) evo_protxhash_list.append(evo_info.proTxHash) self.nodes[0].generate(8) @@ -115,6 +115,7 @@ class LLMQEvoNodesTest(DashTestFramework): self.log.info("Test that EvoNodes are paid 4x blocks in a row") self.test_evo_payments(window_analysis=48) + self.test_masternode_winners() self.activate_v20() self.activate_mn_rr() @@ -127,6 +128,7 @@ class LLMQEvoNodesTest(DashTestFramework): self.log.info("Test that EvoNodes are paid 1 block in a row after MN RewardReallocation activation") self.test_evo_payments(window_analysis=48, v20active=True) + self.test_masternode_winners(mn_rr_active=True) self.log.info(self.nodes[0].masternodelist()) @@ -248,6 +250,40 @@ class LLMQEvoNodesTest(DashTestFramework): assert_equal(detailed_count['regular']['total'], expected_mns_count) assert_equal(detailed_count['evo']['total'], expected_evo_count) + def test_masternode_winners(self, mn_rr_active=False): + # ignore recent winners, test future ones only + # we get up to 21 entries here: tip + up to 20 future payees + winners = self.nodes[0].masternode('winners', '0') + weighted_count = self.mn_count + self.evo_count * (1 if mn_rr_active else 4) + assert_equal(len(winners.keys()) - 1, 20 if weighted_count > 20 else weighted_count) + consecutive_payments = 0 + full_consecutive_payments_found = 0 + payment_cycles = 0 + first_payee = None + prev_winner = None + for height in winners.keys(): + winner = winners[height] + if mn_rr_active: + assert_equal(prev_winner == winner, False) + else: + if prev_winner == winner: + consecutive_payments += 1 + else: + if consecutive_payments == 3: + full_consecutive_payments_found += 1 + consecutive_payments = 0 + assert_greater_than_or_equal(3, consecutive_payments) + if consecutive_payments == 0 and winner == first_payee: + payment_cycles += 1 + if first_payee is None: + first_payee = winner + prev_winner = winner + if mn_rr_active: + assert_equal(full_consecutive_payments_found, 0) + else: + assert_greater_than_or_equal(full_consecutive_payments_found, (len(winners.keys()) - 1 - self.mn_count) // 4 - 1) + assert_equal(payment_cycles, (len(winners.keys()) - 1) // weighted_count) + def test_getmnlistdiff(self, baseBlockHash, blockHash, baseMNList, expectedDeleted, expectedUpdated): d = self.test_getmnlistdiff_base(baseBlockHash, blockHash) From bd772fbe8f730ba4710cefa0725d1f252c036f59 Mon Sep 17 00:00:00 2001 From: pasta Date: Thu, 5 Sep 2024 09:36:03 -0500 Subject: [PATCH 04/14] Merge #6229: fix: `creditOutputs` in AssetLock tx json output should be an array of objects, not debug strings 9876c2d78b0df7eee802cf3b90529fdcacdf1c2c docs: add partial release notes (UdjinM6) b330318db788129eab69ed91c755b31cafa03c8f refactor: drop circular dependency (UdjinM6) e54fe42ce85b0ace8291699f3ecce2e52e638d27 refactor: use `key_to_p2pkh_script` in more places (UdjinM6) 3ed62468898eb45c124ac02ce35fac315606fb40 test: check `creditOutputs` format (UdjinM6) ba0e64505b7bc97f9e5da3e457f89db77040e97f fix: `creditOutputs` in AssetLock tx json output should be an array of objects, not debug strings (UdjinM6) Pull request description: ## Issue being fixed or feature implemented Txout-s in `creditOutputs` for AssetLock txes should be shown the way txout-s are shown in other places. We should not be using debug strings there. Example: `getrawtransaction 50757f651f335e22c5a810bd05c1e5aac0d95b132f6454e2a72683f88e3983f3 1` develop: ``` "assetLockTx": { "version": 1, "creditOutputs": [ "CTxOut(nValue=0.01000000, scriptPubKey=76a914cdfca4ae1cf2333056659a2c)" ] }, ``` This PR: ``` "assetLockTx": { "version": 1, "creditOutputs": [ { "value": 0.01000000, "valueSat": 1000000, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 cdfca4ae1cf2333056659a2c8dc656f36d228402 OP_EQUALVERIFY OP_CHECKSIG", "hex": "76a914cdfca4ae1cf2333056659a2c8dc656f36d22840288ac", "address": "yf6c2VSpWGXUgmjQSHRpfEcTPsbqN4oL4c", "type": "pubkeyhash" } } ] }, ``` kudos to @coolaj86 for finding the issue ## What was done? Change `CAssetLockPayload::ToJson()` output to be closer to [`TxToUniv()`](https://github.com/dashpay/dash/blob/develop/src/core_write.cpp#L262-L272) NOTE: `refactor: use key_to_p2pkh_script in more places` commit is a bit unrelated but I decided to add it anyway to make it easier to follow assetlock creation vs getrawtransaction rpc check. ## How Has This Been Tested? Try example above, run tests ## Breaking Changes RPC output is different for AssetLock txes ## Checklist: - [x] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [ ] I have assigned this pull request to a milestone ACKs for top commit: PastaPastaPasta: utACK 9876c2d78b0df7eee802cf3b90529fdcacdf1c2c Tree-SHA512: 158c98ac9e4979bb29c4f54cb1b71806f22aaec92218d92cd2b2e9b9f74df721563e7a6c5f517ea358ac74659fa79f51d1b683002a1cdceb1b8ee80f8fd79375 --- doc/release-notes-6229.md | 4 ++++ src/evo/assetlocktx.h | 22 +++++++++++++++------- test/functional/feature_asset_locks.py | 15 ++++++++------- 3 files changed, 27 insertions(+), 14 deletions(-) create mode 100644 doc/release-notes-6229.md diff --git a/doc/release-notes-6229.md b/doc/release-notes-6229.md new file mode 100644 index 0000000000..9400e96606 --- /dev/null +++ b/doc/release-notes-6229.md @@ -0,0 +1,4 @@ +RPC changes +----------- + +- `creditOutputs` entries in various RPCs that output transaction JSON are shown as objects now instead of being shown as strings. diff --git a/src/evo/assetlocktx.h b/src/evo/assetlocktx.h index ff4853fb35..b55902fea4 100644 --- a/src/evo/assetlocktx.h +++ b/src/evo/assetlocktx.h @@ -22,6 +22,10 @@ namespace llmq { class CQuorumManager; } // namespace llmq +// Forward declaration from core_io to get rid of circular dependency +UniValue ValueFromAmount(const CAmount amount); +void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex, bool include_addresses); + class CAssetLockPayload { public: @@ -51,14 +55,18 @@ public: [[nodiscard]] UniValue ToJson() const { - UniValue obj; - obj.setObject(); - obj.pushKV("version", int(nVersion)); - UniValue outputs; - outputs.setArray(); - for (const CTxOut& out : creditOutputs) { - outputs.push_back(out.ToString()); + UniValue outputs(UniValue::VARR); + for (const CTxOut& credit_output : creditOutputs) { + UniValue out(UniValue::VOBJ); + out.pushKV("value", ValueFromAmount(credit_output.nValue)); + out.pushKV("valueSat", credit_output.nValue); + UniValue spk(UniValue::VOBJ); + ScriptPubKeyToUniv(credit_output.scriptPubKey, spk, /* fIncludeHex = */ true, /* include_addresses = */ false); + out.pushKV("scriptPubKey", spk); + outputs.push_back(out); } + UniValue obj(UniValue::VOBJ); + obj.pushKV("version", int(nVersion)); obj.pushKV("creditOutputs", outputs); return obj; } diff --git a/test/functional/feature_asset_locks.py b/test/functional/feature_asset_locks.py index c4a1b030be..5c27945965 100755 --- a/test/functional/feature_asset_locks.py +++ b/test/functional/feature_asset_locks.py @@ -30,12 +30,9 @@ from test_framework.messages import ( from test_framework.script import ( CScript, OP_CHECKSIG, - OP_DUP, - OP_EQUALVERIFY, - OP_HASH160, OP_RETURN, - hash160, ) +from test_framework.script_util import key_to_p2pkh_script from test_framework.test_framework import DashTestFramework from test_framework.util import ( assert_equal, @@ -66,8 +63,8 @@ class AssetLocksTest(DashTestFramework): tmp_amount = amount if tmp_amount > COIN: tmp_amount -= COIN - credit_outputs.append(CTxOut(COIN, CScript([OP_DUP, OP_HASH160, hash160(pubkey), OP_EQUALVERIFY, OP_CHECKSIG]))) - credit_outputs.append(CTxOut(tmp_amount, CScript([OP_DUP, OP_HASH160, hash160(pubkey), OP_EQUALVERIFY, OP_CHECKSIG]))) + credit_outputs.append(CTxOut(COIN, key_to_p2pkh_script(pubkey))) + credit_outputs.append(CTxOut(tmp_amount, key_to_p2pkh_script(pubkey))) lockTx_payload = CAssetLockTx(1, credit_outputs) @@ -281,7 +278,11 @@ class AssetLocksTest(DashTestFramework): self.check_mempool_result(tx=asset_lock_tx, result_expected={'allowed': True, 'fees': {'base': Decimal(str(tiny_amount / COIN))}}) self.validate_credit_pool_balance(0) txid_in_block = self.send_tx(asset_lock_tx) - assert "assetLockTx" in node.getrawtransaction(txid_in_block, 1) + rpc_tx = node.getrawtransaction(txid_in_block, 1) + assert_equal(len(rpc_tx["assetLockTx"]["creditOutputs"]), 2) + assert_equal(rpc_tx["assetLockTx"]["creditOutputs"][0]["valueSat"] + rpc_tx["assetLockTx"]["creditOutputs"][1]["valueSat"], locked_1) + assert_equal(rpc_tx["assetLockTx"]["creditOutputs"][0]["scriptPubKey"]["hex"], key_to_p2pkh_script(pubkey).hex()) + assert_equal(rpc_tx["assetLockTx"]["creditOutputs"][1]["scriptPubKey"]["hex"], key_to_p2pkh_script(pubkey).hex()) self.validate_credit_pool_balance(0) node.generate(1) assert_equal(self.get_credit_pool_balance(node=node), locked_1) From 80ed27914ed0b71833d498fccd45ea32f0d64e00 Mon Sep 17 00:00:00 2001 From: pasta Date: Wed, 16 Oct 2024 11:34:19 -0500 Subject: [PATCH 05/14] Merge #6328: backport: bitcoin/bitcoin#30131, #23258, #30504 - fix bild for Ubuntu 24.10 + clang e994691e2d5ed53c071218814aac25b5336b490c Merge bitcoin/bitcoin#30504: doc: use proper doxygen formatting for CTxMemPool::cs (merge-script) a3e6378108e2908075edbb8ee13509a415bd7d37 Merge bitcoin/bitcoin#23258: doc: Fix outdated comments referring to ::ChainActive() (fanquake) dcbf67155173bf5b25ed527c613f4727a5295fe4 Merge bitcoin/bitcoin#30131: wallet, tests: Avoid stringop-overflow warning in PollutePubKey (merge-script) Pull request description: ## Issue being fixed or feature implemented It fixes build with clang 19.1.1 (default clang version on Ubuntu 24.10) ## What was done? Backport 30131, 30504 to fix compilation error and warning; 23258 to reduce conflicts. See commit messages for details ## How Has This Been Tested? Build and succeed ``` CC=clang CXX=clang++ ./configure --prefix=$(pwd)/depends/x86_64-pc-linux-gnu --enable-suppress-external-warnings --enable-debug --enable-stacktraces --enable-werror --enable-crash-hooks --enable-maintainer-mode --enable-multiprocess ``` ## Breaking Changes N/A ## Checklist: - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have added or updated relevant unit/integration/functional/e2e tests - [x] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone ACKs for top commit: PastaPastaPasta: utACK e994691e2d5ed53c071218814aac25b5336b490c UdjinM6: utACK e994691e2d5ed53c071218814aac25b5336b490c Tree-SHA512: 82623030c164c0852d87e8497a59157630f87a385050b6c58d79bf5a8f32462fb26cb02e61b1062afdf9f835e10b9baf4590c326c0fb41bbdd79c82e9d105513 --- src/index/base.cpp | 2 +- src/policy/fees.cpp | 2 +- src/txmempool.h | 5 +---- src/validation.h | 2 +- src/wallet/test/wallet_tests.cpp | 6 ++++-- src/wallet/wallet.cpp | 2 +- 6 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/index/base.cpp b/src/index/base.cpp index 7a0afaff8d..920df64f19 100644 --- a/src/index/base.cpp +++ b/src/index/base.cpp @@ -328,7 +328,7 @@ bool BaseIndex::BlockUntilSyncedToCurrentChain() const { // Skip the queue-draining stuff if we know we're caught up with - // ::ChainActive().Tip(). + // m_chain.Tip(). LOCK(cs_main); const CBlockIndex* chain_tip = m_chainstate->m_chain.Tip(); const CBlockIndex* best_block_index = m_best_block_index.load(); diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 3a57c4311a..6852342702 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -554,7 +554,7 @@ void CBlockPolicyEstimator::processTransaction(const CTxMemPoolEntry& entry, boo if (txHeight != nBestSeenHeight) { // Ignore side chains and re-orgs; assuming they are random they don't // affect the estimate. We'll potentially double count transactions in 1-block reorgs. - // Ignore txs if BlockPolicyEstimator is not in sync with ::ChainActive().Tip(). + // Ignore txs if BlockPolicyEstimator is not in sync with ActiveChain().Tip(). // It will be synced next time a block is processed. return; } diff --git a/src/txmempool.h b/src/txmempool.h index 12efa08b51..ad80c24aca 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -524,17 +524,14 @@ public: * that are guarded by it. * * @par Consistency guarantees - * * By design, it is guaranteed that: - * * 1. Locking both `cs_main` and `mempool.cs` will give a view of mempool - * that is consistent with current chain tip (`::ChainActive()` and + * that is consistent with current chain tip (`ActiveChain()` and * `CoinsTip()`) and is fully populated. Fully populated means that if the * current active chain is missing transactions that were present in a * previously active chain, all the missing transactions will have been * re-added to the mempool and should be present if they meet size and * consistency constraints. - * * 2. Locking `mempool.cs` without `cs_main` will give a view of a mempool * consistent with some chain that was active since `cs_main` was last * locked, and that is fully populated as described above. It is ok for diff --git a/src/validation.h b/src/validation.h index 9b2541fd93..b29fcf6df3 100644 --- a/src/validation.h +++ b/src/validation.h @@ -104,7 +104,7 @@ static const bool DEFAULT_SYNC_MEMPOOL = true; /** Default for -stopatheight */ static const int DEFAULT_STOPATHEIGHT = 0; -/** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ::ChainActive().Tip() will not be pruned. */ +/** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ActiveChain().Tip() will not be pruned. */ static const unsigned int MIN_BLOCKS_TO_KEEP = 288; static const signed int DEFAULT_CHECKBLOCKS = 6; static const unsigned int DEFAULT_CHECKLEVEL = 3; diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index c6fc807db1..fd10162ec6 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -526,8 +526,10 @@ static void TestWatchOnlyPubKey(LegacyScriptPubKeyMan* spk_man, const CPubKey& a // Cryptographically invalidate a PubKey whilst keeping length and first byte static void PollutePubKey(CPubKey& pubkey) { - std::vector pubkey_raw(pubkey.begin(), pubkey.end()); - std::fill(pubkey_raw.begin()+1, pubkey_raw.end(), 0); + assert(pubkey.size() >= 1); + std::vector pubkey_raw; + pubkey_raw.push_back(pubkey[0]); + pubkey_raw.insert(pubkey_raw.end(), pubkey.size() - 1, 0); pubkey = CPubKey(pubkey_raw); assert(!pubkey.IsFullyValid()); assert(pubkey.IsValid()); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 36cdf3f171..32e4201bba 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1313,7 +1313,7 @@ void CWallet::updatedBlockTip() void CWallet::BlockUntilSyncedToCurrentChain() const { AssertLockNotHeld(cs_wallet); // Skip the queue-draining stuff if we know we're caught up with - // chainActive.Tip(), otherwise put a callback in the validation interface queue and wait + // chain().Tip(), otherwise put a callback in the validation interface queue and wait // for the queue to drain enough to execute it (indicating we are caught up // at least with the time we entered this function). uint256 last_block_hash = WITH_LOCK(cs_wallet, return m_last_block_processed); From 8e70262db42bc0f583802dd490dcc1f477ff9a02 Mon Sep 17 00:00:00 2001 From: pasta Date: Wed, 7 Aug 2024 08:29:35 +0700 Subject: [PATCH 06/14] Merge #6131: feat: make a support of Qt app to show Platform transfer Tx 21f174aff107f9aec9b758a00bde67b96ad3cd55 feat: improve query categorisation in Qt App (Konstantin Akimov) c863473286e2a34bff6abf2fb58611ad239c65ab test: add spending asset unlock tx in functional tests (Konstantin Akimov) 1fb67ece0e99baf668687538d9d22217bdc70e4f feat: make a support of Qt app to show Platform Transfer transaction as a new type of transaction (Konstantin Akimov) Pull request description: ## Issue being fixed or feature implemented Transfers from platform have incorrectly shown amount in Dash Core wallet app. They also shown in Qt app as self-send that is not completely true. ## What was done? Added new type of transaction to Qt App, added a filter for its type, fixed calculation of output for tx records. As well added a new type of transaction `platform-transfer` in rpc output of `gettransaction` RPC ## How Has This Been Tested? Make a Platform Transfer transaction on RegTest and check it in Dash Core ![image](https://github.com/user-attachments/assets/16c83f09-724f-4b8b-99c8-9bb0df1428da) Helper to see it: export dpath=/tmp/dash_func_test_PATHPATH/ ; src/qt/dash-qt -regtest -conf=$dpath/node0/dash.conf -datadir=$dpath/node0/ -debug=0 -debuglogfile=/dev/stdout ## Breaking Changes There's new type of transaction "platform-transfer" in rpc output of `gettransaction`. **This PR DOES NOT change any consensus rules.** Breaking changes that makes withdrawal transaction immature is moved to https://github.com/dashpay/dash/pull/6128 ## Checklist: - [x] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone Top commit has no ACKs. Tree-SHA512: ec2a54a910f121ad30ff8e94cf17080b5b3c651872e9bc3de9ec0924ca7f7a0e526b74b05cde26aaf860e3809e67f66142112319a69c216527e5bcb1b8a2b8f6 --- src/interfaces/wallet.h | 1 + src/primitives/transaction.h | 5 +++++ src/qt/transactiondesc.cpp | 4 ++++ src/qt/transactionrecord.cpp | 7 ++++++- src/qt/transactionrecord.h | 3 ++- src/qt/transactiontablemodel.cpp | 29 +++++++++++++++++++------- src/qt/transactionview.cpp | 1 + src/wallet/interfaces.cpp | 1 + src/wallet/rpcwallet.cpp | 15 ++++++++++--- src/wallet/wallet.h | 1 + test/functional/feature_asset_locks.py | 23 ++++++++++++++++++-- 11 files changed, 75 insertions(+), 15 deletions(-) diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h index 3b068f16be..e2365c4c89 100644 --- a/src/interfaces/wallet.h +++ b/src/interfaces/wallet.h @@ -408,6 +408,7 @@ struct WalletTx int64_t time; std::map value_map; bool is_coinbase; + bool is_platform_transfer{false}; bool is_denominate; }; diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index dc87c07152..ba56ef366d 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -264,6 +264,11 @@ public: return nVersion >= SPECIAL_VERSION; } + bool IsPlatformTransfer() const noexcept + { + return IsSpecialTxVersion() && nType == TRANSACTION_ASSET_UNLOCK; + } + bool HasExtraPayloadField() const noexcept { return IsSpecialTxVersion() && nType != TRANSACTION_NORMAL; diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 139db97a78..0e89ffe556 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -93,6 +93,10 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall { strHTML += "" + tr("Source") + ": " + tr("Generated") + "
"; } + else if (wtx.is_platform_transfer) + { + strHTML += "" + tr("Source") + ": " + tr("Platform Transfer") + "
"; + } else if (wtx.value_map.count("from") && !wtx.value_map["from"].empty()) { // Online transaction diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 155c368c92..949a4ad19a 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -39,7 +39,7 @@ QList TransactionRecord::decomposeTransaction(interfaces::Wal auto node = interfaces::MakeNode(); auto& coinJoinOptions = node->coinJoinOptions(); - if (nNet > 0 || wtx.is_coinbase) + if (nNet > 0 || wtx.is_coinbase || wtx.is_platform_transfer) { // // Credit @@ -74,6 +74,11 @@ QList TransactionRecord::decomposeTransaction(interfaces::Wal // Generated sub.type = TransactionRecord::Generated; } + if (wtx.is_platform_transfer) + { + // Withdrawal from platform + sub.type = TransactionRecord::PlatformTransfer; + } parts.append(sub); } diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h index 113ff35f21..92a6086d65 100644 --- a/src/qt/transactionrecord.h +++ b/src/qt/transactionrecord.h @@ -96,7 +96,8 @@ public: CoinJoinCollateralPayment, CoinJoinMakeCollaterals, CoinJoinCreateDenominations, - CoinJoinSend + CoinJoinSend, + PlatformTransfer, }; /** Number of confirmation recommended for accepting a transaction */ diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index c08c7db2f9..5ba76de957 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -431,6 +431,8 @@ QString TransactionTableModel::formatTxType(const TransactionRecord *wtx) const return tr("Payment to yourself"); case TransactionRecord::Generated: return tr("Mined"); + case TransactionRecord::PlatformTransfer: + return tr("Platform Transfer"); case TransactionRecord::CoinJoinMixing: return tr("%1 Mixing").arg(QString::fromStdString(gCoinJoinName)); @@ -443,9 +445,10 @@ QString TransactionTableModel::formatTxType(const TransactionRecord *wtx) const case TransactionRecord::CoinJoinSend: return tr("%1 Send").arg(QString::fromStdString(gCoinJoinName)); - default: - return QString(); - } + case TransactionRecord::Other: + break; // use fail-over here + } // no default case, so the compiler can warn about missing cases + return QString(); } QVariant TransactionTableModel::txAddressDecoration(const TransactionRecord *wtx) const @@ -473,14 +476,20 @@ QString TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx, b case TransactionRecord::SendToAddress: case TransactionRecord::Generated: case TransactionRecord::CoinJoinSend: + case TransactionRecord::PlatformTransfer: return formatAddressLabel(wtx->strAddress, wtx->label, tooltip) + watchAddress; case TransactionRecord::SendToOther: return QString::fromStdString(wtx->strAddress) + watchAddress; case TransactionRecord::SendToSelf: return formatAddressLabel(wtx->strAddress, wtx->label, tooltip) + watchAddress; - default: - return tr("(n/a)") + watchAddress; - } + case TransactionRecord::CoinJoinMixing: + case TransactionRecord::CoinJoinCollateralPayment: + case TransactionRecord::CoinJoinMakeCollaterals: + case TransactionRecord::CoinJoinCreateDenominations: + case TransactionRecord::Other: + break; // use fail-over here + } // no default case, so the compiler can warn about missing cases + return tr("(n/a)") + watchAddress; } QVariant TransactionTableModel::addressColor(const TransactionRecord *wtx) const @@ -491,6 +500,7 @@ QVariant TransactionTableModel::addressColor(const TransactionRecord *wtx) const case TransactionRecord::RecvWithAddress: case TransactionRecord::SendToAddress: case TransactionRecord::Generated: + case TransactionRecord::PlatformTransfer: case TransactionRecord::CoinJoinSend: case TransactionRecord::RecvWithCoinJoin: { @@ -504,9 +514,11 @@ QVariant TransactionTableModel::addressColor(const TransactionRecord *wtx) const case TransactionRecord::CoinJoinMakeCollaterals: case TransactionRecord::CoinJoinCollateralPayment: return GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BAREADDRESS); - default: + case TransactionRecord::SendToOther: + case TransactionRecord::RecvFromOther: + case TransactionRecord::Other: break; - } + } // no default case, so the compiler can warn about missing cases return GUIUtil::getThemedQColor(GUIUtil::ThemedColor::DEFAULT); } @@ -530,6 +542,7 @@ QVariant TransactionTableModel::amountColor(const TransactionRecord *rec) const case TransactionRecord::RecvWithCoinJoin: case TransactionRecord::RecvWithAddress: case TransactionRecord::RecvFromOther: + case TransactionRecord::PlatformTransfer: return GUIUtil::getThemedQColor(GUIUtil::ThemedColor::GREEN); case TransactionRecord::CoinJoinSend: case TransactionRecord::SendToAddress: diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index 573d91d64f..a711082dbb 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -90,6 +90,7 @@ TransactionView::TransactionView(QWidget* parent) : typeWidget->addItem(tr("%1 Collateral Payment").arg(strCoinJoinName), TransactionFilterProxy::TYPE(TransactionRecord::CoinJoinCollateralPayment)); typeWidget->addItem(tr("To yourself"), TransactionFilterProxy::TYPE(TransactionRecord::SendToSelf)); typeWidget->addItem(tr("Mined"), TransactionFilterProxy::TYPE(TransactionRecord::Generated)); + typeWidget->addItem(tr("Platform Transfer"), TransactionFilterProxy::TYPE(TransactionRecord::PlatformTransfer)); typeWidget->addItem(tr("Other"), TransactionFilterProxy::TYPE(TransactionRecord::Other)); typeWidget->setCurrentIndex(settings.value("transactionType").toInt()); diff --git a/src/wallet/interfaces.cpp b/src/wallet/interfaces.cpp index 9f1ebb49fd..04afc44e24 100644 --- a/src/wallet/interfaces.cpp +++ b/src/wallet/interfaces.cpp @@ -81,6 +81,7 @@ WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx) result.time = wtx.GetTxTime(); result.value_map = wtx.mapValue; result.is_coinbase = wtx.IsCoinBase(); + result.is_platform_transfer = wtx.IsPlatformTransfer(); // The determination of is_denominate is based on simplified checks here because in this part of the code // we only want to know about mixing transactions belonging to this specific wallet. result.is_denominate = wtx.tx->vin.size() == wtx.tx->vout.size() && // Number of inputs is same as number of outputs diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 2107cec953..984e701da1 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -167,6 +167,8 @@ static void WalletTxToJSON(interfaces::Chain& chain, const CWalletTx& wtx, UniVa entry.pushKV("chainlock", chainlock); if (wtx.IsCoinBase()) entry.pushKV("generated", true); + if (wtx.IsPlatformTransfer()) + entry.pushKV("platform-transfer", true); if (confirms > 0) { entry.pushKV("blockhash", wtx.m_confirm.hashBlock.GetHex()); @@ -1419,6 +1421,10 @@ static void ListTransactions(const CWallet* const pwallet, const CWalletTx& wtx, else entry.pushKV("category", "generate"); } + else if (wtx.IsPlatformTransfer()) + { + entry.pushKV("category", "platform-transfer"); + } else { entry.pushKV("category", "receive"); @@ -1483,7 +1489,8 @@ static RPCHelpMan listtransactions() "\"receive\" Non-coinbase transactions received.\n" "\"generate\" Coinbase transactions received with more than 100 confirmations.\n" "\"immature\" Coinbase transactions received with 100 or fewer confirmations.\n" - "\"orphan\" Orphaned coinbase transactions received.\n"}, + "\"orphan\" Orphaned coinbase transactions received.\n" + "\"platform-transfer\" Platform Transfer transactions received.\n"}, {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and is positive\n" "for all other categories"}, {RPCResult::Type::STR, "label", "A comment for the address/transaction, if any"}, @@ -1599,7 +1606,8 @@ static RPCHelpMan listsinceblock() "\"receive\" Non-coinbase transactions received.\n" "\"generate\" Coinbase transactions received with more than 100 confirmations.\n" "\"immature\" Coinbase transactions received with 100 or fewer confirmations.\n" - "\"orphan\" Orphaned coinbase transactions received.\n"}, + "\"orphan\" Orphaned coinbase transactions received.\n" + "\"platform-transfer\" Platform Transfer transactions received.\n"}, {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT + ". This is negative for the 'send' category, and is positive\n" "for all other categories"}, {RPCResult::Type::NUM, "vout", "the vout value"}, @@ -1740,7 +1748,8 @@ static RPCHelpMan gettransaction() "\"receive\" Non-coinbase transactions received.\n" "\"generate\" Coinbase transactions received with more than 100 confirmations.\n" "\"immature\" Coinbase transactions received with 100 or fewer confirmations.\n" - "\"orphan\" Orphaned coinbase transactions received.\n"}, + "\"orphan\" Orphaned coinbase transactions received.\n" + "\"platform-transfer\" Platform Transfer transactions received.\n"}, {RPCResult::Type::STR_AMOUNT, "amount", "The amount in " + CURRENCY_UNIT}, {RPCResult::Type::STR, "label", "A comment for the address/transaction, if any"}, {RPCResult::Type::NUM, "vout", "the vout value"}, diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 0ac9666989..b29a010dbe 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -591,6 +591,7 @@ public: void setConfirmed() { m_confirm.status = CWalletTx::CONFIRMED; } const uint256& GetHash() const { return tx->GetHash(); } bool IsCoinBase() const { return tx->IsCoinBase(); } + bool IsPlatformTransfer() const { return tx->IsPlatformTransfer(); } bool IsImmatureCoinBase() const; // Disable copying of CWalletTx objects to prevent bugs where instances get diff --git a/test/functional/feature_asset_locks.py b/test/functional/feature_asset_locks.py index 5c27945965..d9d535a06a 100755 --- a/test/functional/feature_asset_locks.py +++ b/test/functional/feature_asset_locks.py @@ -41,6 +41,7 @@ from test_framework.util import ( get_bip9_details, hex_str_to_bytes, ) +from test_framework.wallet_util import bytes_to_wif llmq_type_test = 106 # LLMQType::LLMQ_TEST_PLATFORM tiny_amount = int(Decimal("0.0007") * COIN) @@ -257,6 +258,8 @@ class AssetLocksTest(DashTestFramework): key = ECKey() key.generate() + privkey = bytes_to_wif(key.get_bytes()) + node_wallet.importprivkey(privkey) pubkey = key.get_pubkey().get_bytes() self.test_asset_locks(node_wallet, node, pubkey) @@ -478,15 +481,31 @@ class AssetLocksTest(DashTestFramework): self.check_mempool_result(tx=asset_unlock_tx_full, result_expected={'allowed': True, 'fees': {'base': Decimal(str(tiny_amount / COIN))}}) txid_in_block = self.send_tx(asset_unlock_tx_full) + expected_balance = (Decimal(self.get_credit_pool_balance()) - Decimal(tiny_amount)) node.generate(1) self.sync_all() - self.log.info("Check txid_in_block was mined...") + self.log.info("Check txid_in_block was mined") block = node.getblock(node.getbestblockhash()) assert txid_in_block in block['tx'] self.validate_credit_pool_balance(0) + self.log.info(f"Check status of withdrawal and try to spend it") + withdrawal_status = node_wallet.gettransaction(txid_in_block) + assert_equal(withdrawal_status['amount'] * COIN, expected_balance) + assert_equal(withdrawal_status['details'][0]['category'], 'platform-transfer') + + spend_withdrawal_hex = node_wallet.createrawtransaction([{'txid': txid_in_block, 'vout' : 0}], { node_wallet.getnewaddress() : (expected_balance - Decimal(tiny_amount)) / COIN}) + spend_withdrawal_hex = node_wallet.signrawtransactionwithwallet(spend_withdrawal_hex)['hex'] + spend_withdrawal = tx_from_hex(spend_withdrawal_hex) + self.check_mempool_result(tx=spend_withdrawal, result_expected={'allowed': True, 'fees': {'base': Decimal(str(tiny_amount / COIN))}}) + spend_txid_in_block = self.send_tx(spend_withdrawal) + + node.generate(1) + block = node.getblock(node.getbestblockhash()) + assert spend_txid_in_block in block['tx'] + self.log.info("Fast forward to the next day to reset all current unlock limits...") - self.slowly_generate_batch(blocks_in_one_day + 1) + self.slowly_generate_batch(blocks_in_one_day) self.mine_quorum(llmq_type_name="llmq_test_platform", llmq_type=106) total = self.get_credit_pool_balance() From bb96df428fa376c54db5898f846f952fab999550 Mon Sep 17 00:00:00 2001 From: pasta Date: Tue, 22 Oct 2024 10:08:02 -0500 Subject: [PATCH 07/14] Merge #6336: fix: rpc getblock and getblockstats for blocks with withdrawal transactions (asset unlock) b9a46f6d2c14a07803cc26cf79b3a0d97fe8e486 refactor: use IsPlatformTransfer in core_write and rpc/blockchain (Konstantin Akimov) f6169fade4303284aa97aba7f3869c761e0ab242 fix: make composite rpc 'masternode payments' to work with withdrawals (Konstantin Akimov) e498378eb79332f576931c1ad06d3f42f3dc5c54 feat: add test for fee in getmempoolentry (Konstantin Akimov) b0d06f0b5fc8f23625dcc08aed839b58f4fac559 feat: add regression test for `getblock` and `getblockstats` for withdrawal fee calculation failure (Konstantin Akimov) ab7172bc8f0197d278ab1e4d94aa0dc66ef18f3a fix: getblockstats rpc to work with withdrawal transactions (Konstantin Akimov) 96c9b469cad439f2e2489a2a15d30d7a02e195cd fix: getblock for withdrawal transaction if verbosity level is 2 (Konstantin Akimov) Pull request description: ## Issue being fixed or feature implemented https://github.com/dashpay/dash/issues/6335 ## What was done? Applied fixes for `getblock` rpc and `getblockstats` rpc to make them work with withdrawal transactions (asset unlock). ## How Has This Been Tested? Run updated functional test `feature_asset_locks.py` without the fix causes a failure: ``` 2024-10-22T12:01:35.902000Z TestFramework (ERROR): JSONRPC error Traceback (most recent call last): File "/home/knst/projects/dash-reviews/test/functional/test_framework/test_framework.py", line 160, in main self.run_test() File "/home/knst/projects/dash-reviews/test/functional/feature_asset_locks.py", line 273, in run_test self.test_asset_unlocks(node_wallet, node, pubkey) File "/home/knst/projects/dash-reviews/test/functional/feature_asset_locks.py", line 410, in test_asset_unlocks self.log.info(f"block info: {node.getblock(block_asset_unlock, 2)}") ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/knst/projects/dash-reviews/test/functional/test_framework/coverage.py", line 49, in __call__ return_val = self.auth_service_proxy_instance.__call__(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/knst/projects/dash-reviews/test/functional/test_framework/authproxy.py", line 148, in __call__ raise JSONRPCException(response['error'], status) test_framework.authproxy.JSONRPCException: Internal bug detected: "MoneyRange(fee)" core_write.cpp:338 (TxToUniv) Please report this issue here: https://github.com/dashpay/dash/issues (-1) ``` With patch functional test `feature_asset_locks.py` succeed. ## Breaking Changes N/A ## Checklist: - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have added or updated relevant unit/integration/functional/e2e tests - [x] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone ACKs for top commit: PastaPastaPasta: utACK b9a46f6d2c14a07803cc26cf79b3a0d97fe8e486 kwvg: utACK b9a46f6d2c14a07803cc26cf79b3a0d97fe8e486 UdjinM6: utACK b9a46f6d2c14a07803cc26cf79b3a0d97fe8e486 ogabrielides: utACK https://github.com/dashpay/dash/commit/b9a46f6d2c14a07803cc26cf79b3a0d97fe8e486 Tree-SHA512: e49cf73bff5fabc9463ae538c6c556d02b3f9e396e0353f5ea0661afa015259409cdada406d05b77bf0414761c76a013cd428ffc283cbdefbefe3384c9d6ccc5 --- src/core_write.cpp | 5 ++++- src/rpc/blockchain.cpp | 6 ++++++ src/rpc/masternode.cpp | 6 ++++++ test/functional/feature_asset_locks.py | 4 ++++ 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/core_write.cpp b/src/core_write.cpp index ffad7897ff..2edee784bb 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -334,7 +334,10 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, bool include_add } if (calculate_fee) { - const CAmount fee = amt_total_in - amt_total_out; + CAmount fee = amt_total_in - amt_total_out; + if (tx.IsPlatformTransfer()) { + fee = CHECK_NONFATAL(GetTxPayload(tx))->getFee(); + } CHECK_NONFATAL(MoneyRange(fee)); entry.pushKV("fee", ValueFromAmount(fee)); } diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 524736d560..44221b64d1 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -47,6 +47,7 @@ #include #include +#include #include #include #include @@ -2423,6 +2424,11 @@ static RPCHelpMan getblockstats() } CAmount txfee = tx_total_in - tx_total_out; + + if (tx->IsPlatformTransfer()) { + txfee = CHECK_NONFATAL(GetTxPayload(*tx))->getFee(); + } + CHECK_NONFATAL(MoneyRange(txfee)); if (do_medianfee) { fee_array.push_back(txfee); diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 923cdc0993..92940d4b28 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include +#include #include #include #include @@ -409,6 +410,11 @@ static RPCHelpMan masternode_payments() if (tx->IsCoinBase()) { continue; } + if (tx->IsPlatformTransfer()) { + nBlockFees += CHECK_NONFATAL(GetTxPayload(*tx))->getFee(); + continue; + } + CAmount nValueIn{0}; for (const auto& txin : tx->vin) { uint256 blockHashTmp; diff --git a/test/functional/feature_asset_locks.py b/test/functional/feature_asset_locks.py index d9d535a06a..66b2985a3b 100755 --- a/test/functional/feature_asset_locks.py +++ b/test/functional/feature_asset_locks.py @@ -365,6 +365,7 @@ class AssetLocksTest(DashTestFramework): self.wait_for_sporks_same() txid = self.send_tx(asset_unlock_tx) + assert_equal(node.getmempoolentry(txid)['fee'], Decimal("0.0007")) is_id = node_wallet.sendtoaddress(node_wallet.getnewaddress(), 1) for node in self.nodes: self.wait_for_instantlock(is_id, node) @@ -403,6 +404,9 @@ class AssetLocksTest(DashTestFramework): self.mempool_size -= 2 self.check_mempool_size() block_asset_unlock = node.getrawtransaction(asset_unlock_tx.rehash(), 1)['blockhash'] + self.log.info("Checking rpc `getblock` and `getblockstats` succeeds as they use own fee calculation mechanism") + assert_equal(node.getblockstats(node.getblockcount())['maxfee'], tiny_amount) + node.getblock(block_asset_unlock, 2) self.send_tx(asset_unlock_tx, expected_error = "Transaction already in block chain", From c0ca93cf7aba5371fb8b2880b40fc5252a455c56 Mon Sep 17 00:00:00 2001 From: pasta Date: Tue, 22 Oct 2024 12:21:19 -0500 Subject: [PATCH 08/14] Merge #6340: fix: make 6336 compile in v21.1.x branch, using older CHECK_NONFATAL functionality a7bbcc823d800b293e9ec54dff518fa9929c763c fix: make 6336 compile in v21.1.x branch, using older CHECK_NONFATAL functionality (pasta) Pull request description: ## Issue being fixed or feature implemented Resolve build failures when 6336 is back ported ## What was done? Use older functionality of CHECK_NONFATAL ## How Has This Been Tested? built on both branches ## Breaking Changes ## Checklist: _Go over all the following points, and put an `x` in all the boxes that apply._ - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ACKs for top commit: knst: utACK a7bbcc823d800b293e9ec54dff518fa9929c763c UdjinM6: utACK a7bbcc823d800b293e9ec54dff518fa9929c763c (#6339 compiles with this one applied on top of it) kwvg: utACK a7bbcc823d800b293e9ec54dff518fa9929c763c Tree-SHA512: 17b6d8223f653eaafa6ef9d1a4e8fc14ca1fe1623fbb13d23a9429e87a64c8fae3ddaf6d2d8d5a52138ab712a36949662b38a8a9cbbc5db3618ce24f565f6f2a --- src/core_write.cpp | 4 +++- src/rpc/blockchain.cpp | 4 +++- src/rpc/masternode.cpp | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/core_write.cpp b/src/core_write.cpp index 2edee784bb..a2cdf68aa4 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -336,7 +336,9 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, bool include_add if (calculate_fee) { CAmount fee = amt_total_in - amt_total_out; if (tx.IsPlatformTransfer()) { - fee = CHECK_NONFATAL(GetTxPayload(tx))->getFee(); + auto payload = GetTxPayload(tx); + CHECK_NONFATAL(payload); + fee = payload->getFee(); } CHECK_NONFATAL(MoneyRange(fee)); entry.pushKV("fee", ValueFromAmount(fee)); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 44221b64d1..6535a70f93 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -2426,7 +2426,9 @@ static RPCHelpMan getblockstats() CAmount txfee = tx_total_in - tx_total_out; if (tx->IsPlatformTransfer()) { - txfee = CHECK_NONFATAL(GetTxPayload(*tx))->getFee(); + auto payload = GetTxPayload(*tx); + CHECK_NONFATAL(payload); + txfee = payload->getFee(); } CHECK_NONFATAL(MoneyRange(txfee)); diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 92940d4b28..ad0869c3b7 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -411,7 +411,9 @@ static RPCHelpMan masternode_payments() continue; } if (tx->IsPlatformTransfer()) { - nBlockFees += CHECK_NONFATAL(GetTxPayload(*tx))->getFee(); + auto payload = GetTxPayload(*tx); + CHECK_NONFATAL(payload); + nBlockFees += payload->getFee(); continue; } From 6fb4e49ae55afaaee8ecf9bb235043761aefbd49 Mon Sep 17 00:00:00 2001 From: pasta Date: Mon, 12 Aug 2024 17:25:30 +0700 Subject: [PATCH 09/14] Merge #6197: ci: always build guix, save artifacts 770651aa157c2412b96e38fd8ee56a33e8c292bc set hosts in guix-check (pasta) 580bbe6d1c3d4b6229d20e69978e5eeebac845a5 feat: improve guix building; run always, save artifacts (pasta) 101a31555fbe039113c55ec641ec9f1d4121abf2 refactor: simplify caching setup, add a restore key to actually cache besides 1 run (pasta) 1b139e4837b9bc3167028def245522df75f18ae3 feat: automatically run guix-build on all tags pushed (pasta) Pull request description: ## Issue being fixed or feature implemented Previously, we only ran guix on 1 machine for all hosts; this slowed it down a lot. Let's move to GitHub action runners, but run them all separately. Then upload the artifacts. In the future there is significant caching I can add that should help a lot more. But currently, takes about 1 hour ## What was done? ## How Has This Been Tested? see: https://github.com/PastaPastaPasta/dash/actions/runs/10345024600 ## Breaking Changes None ## Checklist: _Go over all the following points, and put an `x` in all the boxes that apply._ - [x] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ACKs for top commit: UdjinM6: utACK 770651aa157c2412b96e38fd8ee56a33e8c292bc Tree-SHA512: 639b95c3b6a26f205ed00c138a9189f915cfc36a815516035e59ceda82675414b1bd31a361b33449b5e4c58a7655f3a7d616b362c23f7fa75e72b1284be06b9e --- .github/workflows/guix-build.yml | 100 +++++++++++++++++++++---------- 1 file changed, 68 insertions(+), 32 deletions(-) diff --git a/.github/workflows/guix-build.yml b/.github/workflows/guix-build.yml index dbdaddcb37..8d1dd36219 100644 --- a/.github/workflows/guix-build.yml +++ b/.github/workflows/guix-build.yml @@ -1,15 +1,18 @@ name: Guix Build +permissions: + packages: write + on: - pull_request: - types: [ labeled ] - workflow_dispatch: + pull_request_target: + push: jobs: - build: - runs-on: [ "self-hosted", "linux", "x64", "ubuntu-core" ] - if: contains(github.event.pull_request.labels.*.name, 'guix-build') - timeout-minutes: 480 + build-image: + runs-on: ubuntu-latest + outputs: + image-tag: ${{ steps.prepare.outputs.image-tag }} + repo-name: ${{ steps.prepare.outputs.repo-name }} steps: - name: Checkout uses: actions/checkout@v4 @@ -22,37 +25,72 @@ jobs: uses: docker/setup-buildx-action@v3 - name: Commit variables - id: dockerfile + id: prepare run: | echo "hash=$(sha256sum ./dash/contrib/containers/guix/Dockerfile | cut -d ' ' -f1)" >> $GITHUB_OUTPUT echo "host_user_id=$(id -u)" >> $GITHUB_OUTPUT echo "host_group_id=$(id -g)" >> $GITHUB_OUTPUT + BRANCH_NAME=$(echo "${GITHUB_REF##*/}" | tr '[:upper:]' '[:lower:]') + REPO_NAME=$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]') + echo "::set-output name=image-tag::${BRANCH_NAME}" + echo "::set-output name=repo-name::${REPO_NAME}" + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Build Docker image - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: context: ${{ github.workspace }}/dash build-args: | - USER_ID=${{ steps.dockerfile.outputs.host_user_id }} - GROUP_ID=${{ steps.dockerfile.outputs.host_group_id }} + USER_ID=${{ steps.prepare.outputs.host_user_id }} + GROUP_ID=${{ steps.prepare.outputs.host_group_id }} build-contexts: | docker_root=${{ github.workspace }}/dash/contrib/containers/guix file: ./dash/contrib/containers/guix/Dockerfile - load: true - tags: guix_ubuntu:latest - cache-from: type=gha - cache-to: type=gha,mode=max + push: true + tags: | + ghcr.io/${{ steps.prepare.outputs.repo-name }}/dashcore-guix-builder:${{ steps.prepare.outputs.image-tag }} + ghcr.io/${{ steps.prepare.outputs.repo-name }}/dashcore-guix-builder:latest + cache-from: type=registry,ref=ghcr.io/${{ steps.prepare.outputs.repo-name }}/dashcore-guix-builder:latest + cache-to: type=inline,mode=max - - name: Restore Guix cache and depends + build: + needs: build-image + # runs-on: [ "self-hosted", "linux", "x64", "ubuntu-core" ] + runs-on: ubuntu-latest +# if: ${{ contains(github.event.pull_request.labels.*.name, 'guix-build') }} + strategy: + matrix: + build_target: [x86_64-linux-gnu, arm-linux-gnueabihf, aarch64-linux-gnu, riscv64-linux-gnu, x86_64-w64-mingw32, x86_64-apple-darwin, arm64-apple-darwin] + + timeout-minutes: 480 + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + path: dash + fetch-depth: 0 + + - name: Cache Guix and depends id: guix-cache-restore - uses: actions/cache/restore@v3 + uses: actions/cache@v3 with: path: | ${{ github.workspace }}/.cache ${{ github.workspace }}/dash/depends/built ${{ github.workspace }}/dash/depends/sources ${{ github.workspace }}/dash/depends/work - key: ${{ runner.os }}-guix + /gnu/store + key: ${{ runner.os }}-guix-${{ matrix.build_target }}-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-guix-${{ matrix.build_target }} + ${{ runner.os }}-guix- - name: Create .cache folder if missing if: steps.guix-cache-restore.outputs.cache-hit != 'true' @@ -67,8 +105,8 @@ jobs: -v ${{ github.workspace }}/dash:/src/dash \ -v ${{ github.workspace }}/.cache:/home/ubuntu/.cache \ -w /src/dash \ - guix_ubuntu:latest && \ - docker exec guix-daemon bash -c '/usr/local/bin/guix-start' + ghcr.io/${{ needs.build-image.outputs.repo-name }}/dashcore-guix-builder:${{ needs.build-image.outputs.image-tag }} && \ + docker exec guix-daemon bash -c 'HOSTS=${{ matrix.build_target }} /usr/local/bin/guix-start' - name: Ensure build passes run: | @@ -77,17 +115,15 @@ jobs: exit 1 fi - - name: Save Guix cache and depends - id: guix-cache-save - uses: actions/cache/save@v3 - with: - path: | - ${{ github.workspace }}/.cache - ${{ github.workspace }}/dash/depends/built - ${{ github.workspace }}/dash/depends/sources - ${{ github.workspace }}/dash/depends/work - key: ${{ steps.guix-cache-restore.outputs.cache-primary-key }} - - name: Compute SHA256 checksums + continue-on-error: true # It will complain on depending on only some hosts run: | - ./dash/contrib/containers/guix/scripts/guix-check ${{ github.workspace }}/dash + HOSTS=${{ matrix.build_target }} ./dash/contrib/containers/guix/scripts/guix-check ${{ github.workspace }}/dash + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: guix-artifacts-${{ matrix.build_target }} + path: | + ${{ github.workspace }}/dash/guix-build*/output/${{ matrix.build_target }}/ + From 167608c7c7f852e9759a27fcf9eb892bd1704b80 Mon Sep 17 00:00:00 2001 From: pasta Date: Tue, 22 Oct 2024 10:24:37 -0500 Subject: [PATCH 10/14] Merge #6338: ci: attest results of guix builds cd712e86b7ea11fe3c5ce13107beec089514911c ci: attest results of guix builds (pasta) Pull request description: ## Issue being fixed or feature implemented This simply adds attestations to guix results by GitHub. This way, not only can someone verify that all us developers agree, but also that GitHub hosted runners agree :) ## What was done? Add actions/attest-build-provenance to guix-build CI ## How Has This Been Tested? see: https://github.com/PastaPastaPasta/dash/actions/runs/11239755631 ## Breaking Changes None ## Checklist: _Go over all the following points, and put an `x` in all the boxes that apply._ - [x] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ACKs for top commit: UdjinM6: utACK cd712e86b7ea11fe3c5ce13107beec089514911c Tree-SHA512: b590ee2cf29aa57f78cb68c22d5327e8c9272d63d523c3b64fbbdffabb90981a6b6505c5f511bde19310ea1d8c96fc6d181359a7d7a0672612473110cbe079ef --- .github/workflows/guix-build.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/guix-build.yml b/.github/workflows/guix-build.yml index 8d1dd36219..e6435e7efc 100644 --- a/.github/workflows/guix-build.yml +++ b/.github/workflows/guix-build.yml @@ -2,6 +2,8 @@ name: Guix Build permissions: packages: write + id-token: write + attestations: write on: pull_request_target: @@ -127,3 +129,7 @@ jobs: path: | ${{ github.workspace }}/dash/guix-build*/output/${{ matrix.build_target }}/ + - name: Attest build provenance + uses: actions/attest-build-provenance@v1 + with: + subject-path: ${{ github.workspace }}/dash/guix-build*/output/${{ matrix.build_target }}/* From a2bc0f1b1be9f52f3ae53668e2613d34f9913fad Mon Sep 17 00:00:00 2001 From: pasta Date: Thu, 3 Oct 2024 11:44:16 -0500 Subject: [PATCH 11/14] Merge #6290: chore: update pasta gpg key to reflect new subkeys c3f24748985c65bb2c7ca797f73097b763426994 chore: update pasta gpg key to reflect new subkeys (pasta) Pull request description: ## Issue being fixed or feature implemented I've added 2 subkeys to my GPG key `29590362EC878A81FD3C202B52527BEDABE87984` to better follow best practices, which avoids using your primary key whenever possible. All future git commit signing, and potentially releases will be signed by a subkey instead of the primary key. These updated subkeys keys are now included on all the major keyservers hkps://keyserver.ubuntu.com hkps://pgp.mit.edu hkps://keyserver.ubuntu.com keybase has 1 of the 2 subkeys already, will add the other soon. ## What was done? ## How Has This Been Tested? ## Breaking Changes Users who validate my signatures may have to refresh the key from keyservers via `gpg --refresh-keys` or pull down from keybase via `curl https://keybase.io/pasta/pgp_keys.asc | gpg --import` ## Checklist: - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ACKs for top commit: UdjinM6: utACK c3f24748985c65bb2c7ca797f73097b763426994 Tree-SHA512: 87d33caceb1973a54877c5d5a8b85a48e1373b7709698efc793598bf7453608979bfe1c75e4ea0c9ec852c0343b43b06357c58f6c4fbf72915eb910788cc705f --- contrib/builder-keys/pasta.pgp | 188 ++++++++++++++++++++++++--------- 1 file changed, 139 insertions(+), 49 deletions(-) diff --git a/contrib/builder-keys/pasta.pgp b/contrib/builder-keys/pasta.pgp index 018162fd70..934ee1804a 100644 --- a/contrib/builder-keys/pasta.pgp +++ b/contrib/builder-keys/pasta.pgp @@ -24,53 +24,143 @@ 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 -u+HE6D2rqvc0CA1wAreY5+lD96PbmOAjnA== -=lPi0 +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 +t8FIucvlOdt4EqKaSmoBQZk0Aj/N5q4= +=vjZr -----END PGP PUBLIC KEY BLOCK----- From 1c00726acaa51a5f4312ac262c2f2a0cd17d103e Mon Sep 17 00:00:00 2001 From: pasta Date: Wed, 18 Sep 2024 11:26:23 -0500 Subject: [PATCH 12/14] Merge #6277: chore: add builder key for kittywhiskers 315fcea83493266449a96739c7f028cdff00cc75 chore: add builder key for kittywhiskers (Kittywhiskers Van Gogh) Pull request description: ## Additional Information Key ID `30CD 0C06 5E5C 4AAD`. Same key registered with Keybase ([source](https://keybase.io/kittywhiskers/pgp_keys.asc?fingerprint=969187a8e74fe40a8a48067430cd0c065e5c4aad)) and used to sign commits on GitHub. PGP key named after Keybase username. ACKs for top commit: UdjinM6: utACK 315fcea83493266449a96739c7f028cdff00cc75 knst: ACK 315fcea83493266449a96739c7f028cdff00cc75 PastaPastaPasta: utACK 315fcea83493266449a96739c7f028cdff00cc75 Tree-SHA512: f566c514831cfaf0a8bf95ebfb8aa5629474bdf0b88fd8948d4c1d3f1340ccdd3a9c67c817bd08d2f4d2e477b1599bf4fd148ad50fe68357d24feba651d832f7 --- contrib/builder-keys/kittywhiskers.pgp | 32 ++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 contrib/builder-keys/kittywhiskers.pgp diff --git a/contrib/builder-keys/kittywhiskers.pgp b/contrib/builder-keys/kittywhiskers.pgp new file mode 100644 index 0000000000..03feedde46 --- /dev/null +++ b/contrib/builder-keys/kittywhiskers.pgp @@ -0,0 +1,32 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mDMEZZs7ABYJKwYBBAHaRw8BAQdAxvpS5zLLn9agjKg1bpMyHtKROTC8SLTl3AZm +b4DKXJq0P0tpdHR5d2hpc2tlcnMgVmFuIEdvZ2ggPDYzMTg5NTMxK2t3dmdAdXNl +cnMubm9yZXBseS5naXRodWIuY29tPoiaBBMWCABCAhsDBQkDw7iAAheAAhkBFiEE +lpGHqOdP5AqKSAZ0MM0MBl5cSq0FAmbpq2gFCwkIBwIGFQoJCAsCBRYCAwEAAh4F +AAoJEDDNDAZeXEqt6D4BALOgavknWXzg3zyBI4rzqS2Qq1qrDl0AVohpYQYJrUZ6 +AP92LejS8DyeR4NZuUeP4gCxL/0wOydz6LkmEefaTvNiD7RIS2l0dHl3aGlza2Vy +cyBWYW4gR29naCA8NjMxODk1MzEra2l0dHl3aGlza2Vyc0B1c2Vycy5ub3JlcGx5 +LmdpdGh1Yi5jb20+iJcEExYIAD8CGwMFCQPDuIACF4AWIQSWkYeo50/kCopIBnQw +zQwGXlxKrQUCZumraQULCQgHAgYVCgkICwIFFgIDAQACHgUACgkQMM0MBl5cSq3B +zAD/T6dYqUtzIuZjIIBXisBMISNTHQxRv1KH3txuN+lCW/UBAIMV6Y41aIqbGnI2 +ADm+WYFsnABokj+mT5GZBuqfEYQEtEdLaXR0eXdoaXNrZXJzIFZhbiBHb2doIDw2 +MDk4OTc0LWtpdHR5d2hpc2tlcnNAdXNlcnMubm9yZXBseS5naXRsYWIuY29tPoiX +BBMWCAA/AhsDBQkDw7iAAheAFiEElpGHqOdP5AqKSAZ0MM0MBl5cSq0FAmbpq2kF +CwkIBwIGFQoJCAsCBRYCAwEAAh4FAAoJEDDNDAZeXEqt2D0BAIZOVRQgvP6DZeXc +ONNZcFGp3mrbumudjsoCCiDTS/PZAP48LFSFBB8NBcXgjj1edktii9AN3JYyW+yF +60uLMN4NAbQvS2l0dHl3aGlza2VycyBWYW4gR29naCA8a2l0dHl3aGlza2Vyc0Bk +YXNoLm9yZz6IlwQTFgoAPwIbAwUJA8O4gAIXgBYhBJaRh6jnT+QKikgGdDDNDAZe +XEqtBQJm6atpBQsJCAcCBhUKCQgLAgUWAgMBAAIeBQAKCRAwzQwGXlxKrSHfAQCU +Tu3DPWNWj8weotN4NKoShfsMrIEEeKqv1ykLc1K2lwD8CwEBUG69Pl8NFWMElvam +6wu9OWtOKp9xBkFS+CjM8A60NktpdHR5d2hpc2tlcnMgVmFuIEdvZ2ggPGt3dmdA +dXNlcnMubm9yZXBseS5naXRodWIuY29tPoiXBBMWCgA/AhsDBQkDw7iAAheAFiEE +lpGHqOdP5AqKSAZ0MM0MBl5cSq0FAmbpq2kFCwkIBwIGFQoJCAsCBRYCAwEAAh4F +AAoJEDDNDAZeXEqt4YAA/22FrVJGDOeZVYRNLjFL34+YjXEyTO5dACjZ8jV2/uHD +AQDB9osQDYr/lDfuMMSPZhufAryHIWBJp/e8AwHwJ65aALg4BGWbOwASCisGAQQB +l1UBBQEBB0DCbqznf45arlTBDkpS76ineVKFabpOa3vohGKIKJ+5FAMBCAeIfgQY +FggAJhYhBJaRh6jnT+QKikgGdDDNDAZeXEqtBQJlmzsAAhsMBQkDw7iAAAoJEDDN +DAZeXEqtUvEBALBrYJ7jRRCwBMBTG2doiFupibGQh2vN46gKSrXzYSG9AQDIXcCJ +moGvMWiiBz71Wr9JZ7/ZV6rcRE1YXfM06G6gCQ== +=gtD4 +-----END PGP PUBLIC KEY BLOCK----- From 5f9700c69a4313397e4103af26a9123ace84e062 Mon Sep 17 00:00:00 2001 From: pasta Date: Tue, 22 Oct 2024 09:53:17 -0500 Subject: [PATCH 13/14] docs: release notes for v21.1.1 --- doc/release-notes-6229.md | 4 - doc/release-notes.md | 31 ++--- .../dash/release-notes-21.1.0.md | 121 ++++++++++++++++++ 3 files changed, 134 insertions(+), 22 deletions(-) delete mode 100644 doc/release-notes-6229.md create mode 100644 doc/release-notes/dash/release-notes-21.1.0.md diff --git a/doc/release-notes-6229.md b/doc/release-notes-6229.md deleted file mode 100644 index 9400e96606..0000000000 --- a/doc/release-notes-6229.md +++ /dev/null @@ -1,4 +0,0 @@ -RPC changes ------------ - -- `creditOutputs` entries in various RPCs that output transaction JSON are shown as objects now instead of being shown as strings. diff --git a/doc/release-notes.md b/doc/release-notes.md index 7b0ef32142..06f26776e0 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -1,9 +1,8 @@ -# Dash Core version v21.1.0 +# Dash Core version v21.1.1 -This is a new minor version release, bringing important bugfixes. +This is a new patch version release, bringing important bugfixes. -This release is **mandatory** for all masternodes. -This release is optional but recommended for all other nodes. +This release is **optional** but recommended for all nodes. Please report bugs using the issue tracker at GitHub: @@ -34,18 +33,13 @@ reindex or re-sync the whole chain. # Notable changes -Allow EHF Resigning -------------------- - -During implementation, the values for requestID and msgHash for EHF signing were switched. As a result, a masternode -which participated in an earlier failed attempt to form an EHF message is unable to participate in subsequent -attempts. This is because the LLMQ Signing System requires that the requestID be unique, and that a node will not -sign two different msgHash for the same requestID. See the [forum post](https://www.dash.org/forum/index.php?threads/ehf-activation-issues.55146/) -explaining it further. - -As there is no need to restrict double signing for EHF, we now allow signing of multiple msgHash's for a single EHF -requestID. Once a sufficient number of masternodes upgrade to v21.1, the EHF message will be automatically signed and -mined. +- Core now categorizes asset unlock transactions as "Platform Transfers" on the Transactions tab in Dash-Qt and in the output of the `gettransaction` RPC (#6131) +- Persist Coinjoin Denoms options changes made via GUI over restarts (#6208) +- Fix incorrect payment predictions for evonodes in Dash-Qt and in RPC `masternode winners` (#6222) +- `creditOutputs` entries in various RPCs that output transaction JSON are shown as objects now instead of being shown as strings (#6229) +- Updated PGP key for builder 'pasta' to reflect new subkeys. You may need to reimport this key to validate signatures. (#6290) +- Build failures on Ubuntu 24.10 / clang 19.1.1 resolved (#6328) +- RPC errors in `masternode payments`, `getblock`, `getblockstats` related to Asset Unlock parsing have been fixed (#6336) # v21.1.0 Change log @@ -55,10 +49,10 @@ See detailed [set of changes][set-of-changes]. Thanks to everyone who directly contributed to this release: +- Kittywhiskers Van Gogh - Konstantin Akimov - PastaPastaPasta - UdjinM6 -- ogabrielides As well as everyone that submitted issues, reviewed pull requests and helped debug the release candidates. @@ -67,6 +61,7 @@ debug the release candidates. These release are considered obsolete. Old release notes can be found here: +- [v21.1.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-21.1.0.md) released Aug/8/2024 - [v21.0.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-21.0.2.md) released Aug/1/2024 - [v21.0.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-21.0.0.md) released Jul/25/2024 - [v20.1.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-20.1.1.md) released April/3/2024 @@ -118,4 +113,4 @@ These release are considered obsolete. Old release notes can be found here: - [v0.10.x](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.10.0.md) released Sep/25/2014 - [v0.9.x](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.9.0.md) released Mar/13/2014 -[set-of-changes]: https://github.com/dashpay/dash/compare/v21.0.2...dashpay:v21.1.0 +[set-of-changes]: https://github.com/dashpay/dash/compare/v21.1.0...dashpay:v21.1.1 diff --git a/doc/release-notes/dash/release-notes-21.1.0.md b/doc/release-notes/dash/release-notes-21.1.0.md new file mode 100644 index 0000000000..7b0ef32142 --- /dev/null +++ b/doc/release-notes/dash/release-notes-21.1.0.md @@ -0,0 +1,121 @@ +# Dash Core version v21.1.0 + +This is a new minor version release, bringing important bugfixes. + +This release is **mandatory** for all masternodes. +This release is optional but recommended for all other nodes. + +Please report bugs using the issue tracker at GitHub: + + + + +# Upgrading and downgrading + +## How to Upgrade + +If you are running an older version, shut it down. Wait until it has completely +shut down (which might take a few minutes for older versions), then run the +installer (on Windows) or just copy over /Applications/Dash-Qt (on Mac) or +dashd/dash-qt (on Linux). + +## Downgrade warning + +### Downgrade to a version < v21.0.0 + +Downgrading to a version older than v21.0.0 may not be supported due to changes +if you are using descriptor wallets. + +### Downgrade to a version < v19.2.0 + +Downgrading to a version older than v19.2.0 is not supported due to changes +in the evodb database. If you need to use an older version, you must either +reindex or re-sync the whole chain. + +# Notable changes + +Allow EHF Resigning +------------------- + +During implementation, the values for requestID and msgHash for EHF signing were switched. As a result, a masternode +which participated in an earlier failed attempt to form an EHF message is unable to participate in subsequent +attempts. This is because the LLMQ Signing System requires that the requestID be unique, and that a node will not +sign two different msgHash for the same requestID. See the [forum post](https://www.dash.org/forum/index.php?threads/ehf-activation-issues.55146/) +explaining it further. + +As there is no need to restrict double signing for EHF, we now allow signing of multiple msgHash's for a single EHF +requestID. Once a sufficient number of masternodes upgrade to v21.1, the EHF message will be automatically signed and +mined. + +# v21.1.0 Change log + +See detailed [set of changes][set-of-changes]. + +# Credits + +Thanks to everyone who directly contributed to this release: + +- Konstantin Akimov +- PastaPastaPasta +- UdjinM6 +- ogabrielides + +As well as everyone that submitted issues, reviewed pull requests and helped +debug the release candidates. + +# Older releases + +These release are considered obsolete. Old release notes can be found here: + +- [v21.0.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-21.0.2.md) released Aug/1/2024 +- [v21.0.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-21.0.0.md) released Jul/25/2024 +- [v20.1.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-20.1.1.md) released April/3/2024 +- [v20.1.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-20.1.0.md) released March/5/2024 +- [v20.0.4](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-20.0.4.md) released Jan/13/2024 +- [v20.0.3](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-20.0.3.md) released December/26/2023 +- [v20.0.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-20.0.2.md) released December/06/2023 +- [v20.0.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-20.0.1.md) released November/18/2023 +- [v20.0.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-20.0.0.md) released November/15/2023 +- [v19.3.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-19.3.0.md) released July/31/2023 +- [v19.2.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-19.2.0.md) released June/19/2023 +- [v19.1.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-19.1.0.md) released May/22/2023 +- [v19.0.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-19.0.0.md) released Apr/14/2023 +- [v18.2.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-18.2.2.md) released Mar/21/2023 +- [v18.2.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-18.2.1.md) released Jan/17/2023 +- [v18.2.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-18.2.0.md) released Jan/01/2023 +- [v18.1.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-18.1.1.md) released January/08/2023 +- [v18.1.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-18.1.0.md) released October/09/2022 +- [v18.0.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-18.0.2.md) released October/09/2022 +- [v18.0.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-18.0.1.md) released August/17/2022 +- [v0.17.0.3](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.17.0.3.md) released June/07/2021 +- [v0.17.0.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.17.0.2.md) released May/19/2021 +- [v0.16.1.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.16.1.1.md) released November/17/2020 +- [v0.16.1.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.16.1.0.md) released November/14/2020 +- [v0.16.0.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.16.0.1.md) released September/30/2020 +- [v0.15.0.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.15.0.0.md) released Febrary/18/2020 +- [v0.14.0.5](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.14.0.5.md) released December/08/2019 +- [v0.14.0.4](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.14.0.4.md) released November/22/2019 +- [v0.14.0.3](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.14.0.3.md) released August/15/2019 +- [v0.14.0.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.14.0.2.md) released July/4/2019 +- [v0.14.0.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.14.0.1.md) released May/31/2019 +- [v0.14.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.14.0.md) released May/22/2019 +- [v0.13.3](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.13.3.md) released Apr/04/2019 +- [v0.13.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.13.2.md) released Mar/15/2019 +- [v0.13.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.13.1.md) released Feb/9/2019 +- [v0.13.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.13.0.md) released Jan/14/2019 +- [v0.12.3.4](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.12.3.4.md) released Dec/14/2018 +- [v0.12.3.3](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.12.3.3.md) released Sep/19/2018 +- [v0.12.3.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.12.3.2.md) released Jul/09/2018 +- [v0.12.3.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.12.3.1.md) released Jul/03/2018 +- [v0.12.2.3](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.12.2.3.md) released Jan/12/2018 +- [v0.12.2.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.12.2.2.md) released Dec/17/2017 +- [v0.12.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.12.2.md) released Nov/08/2017 +- [v0.12.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.12.1.md) released Feb/06/2017 +- [v0.12.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.12.0.md) released Aug/15/2015 +- [v0.11.2](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.11.2.md) released Mar/04/2015 +- [v0.11.1](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.11.1.md) released Feb/10/2015 +- [v0.11.0](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.11.0.md) released Jan/15/2015 +- [v0.10.x](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.10.0.md) released Sep/25/2014 +- [v0.9.x](https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-0.9.0.md) released Mar/13/2014 + +[set-of-changes]: https://github.com/dashpay/dash/compare/v21.0.2...dashpay:v21.1.0 From d627a6ee526aebaae5a7dbae75bc93b37ac02d26 Mon Sep 17 00:00:00 2001 From: pasta Date: Tue, 22 Oct 2024 10:54:17 -0500 Subject: [PATCH 14/14] chore: bump version to 21.1.1 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 52fe2db6d8..ab071c9f56 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ([2.69]) dnl Don't forget to push a corresponding tag when updating any of _CLIENT_VERSION_* numbers define(_CLIENT_VERSION_MAJOR, 21) define(_CLIENT_VERSION_MINOR, 1) -define(_CLIENT_VERSION_BUILD, 0) +define(_CLIENT_VERSION_BUILD, 1) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2024) define(_COPYRIGHT_HOLDERS,[The %s developers])